Linux-EFI Archive on lore.kernel.org
 help / color / Atom feed
* [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
@ 2020-02-13 14:59 Ard Biesheuvel
  2020-02-13 14:59 ` [RFC PATCH 1/3] efi/x86: drop redundant .bss section Ard Biesheuvel
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 14:59 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, Ard Biesheuvel, lersek, leif, pjones, mjg59,
	agraf, daniel.kiper, hdegoede, nivedita, mbrown, mingo

This series is another part of my effort to reduce the level of knowledge
on the part of the bootloader or firmware of internal per-architecture
details regarding where/how the kernel is loaded and where its initrd and
other context data are passed.

The x86 architecture has a so-called 'EFI handover protocol', which defines
how the bootparams struct should be populated, and how it should be
interpreted to figure out where to load the kernel, and at which offset in
the binary the entrypoint is located. This scheme allows the initrd to be
loaded beforehand, and allows 32-bit firmware to invoke a 64-bit kernel
via a special entrypoint that manages the state transitions between the
two execution modes.

Due to this, x86 loaders currently do not rely on LoadImage and StartImage,
and therefore, are forced to re-implement things like image authentication
for secure boot and taking the measurements for measured boot in their open
coded clones of these routines.

My previous series on this topic [0] implements a generic way to load the
initrd from any source supported by the loader without relying on something
like device trees or bootparams structures, and so native boot should not
need the EFI handover protocol anymore after those change are merged.

What remains is mixed mode boot, which also needs the EFI handover protocol
regardless of whether an initrd is loaded or not. So let's get rid of that
requirement, and take advantage of the fact that EDK2 based firmware does
support LoadImage() for X64 binaries on IA32 firmware, which means we can
rely on the secure boot and measured boot checks being performed by the
firmware. The only thing we need to put on top is a way to discover the
non-native entrypoint into the binary in a way that does not rely on x86
specific headers and data structures.

So let's introduce a new .compat header in the PE/COFF metadata of the
bzImage, and populate it with a <machine type, entrypoint> tuple, allowing
a generic EFI loader to decide whether the entrypoint supports its native
machine type, and invoke it as an ordinary EFI application entrypoint.
Since we will not be passing a bootparams structure, we need to discover
the base of the image (which contains the setup header) via the loaded
image protocol before we can enter the kernel in 32-bit mode at startup_32()

A loader implementation for OVMF can be found at [1]. Note that this loader
code is fully generic, and could be used without modifications if other
architectures ever emerge that support kernels that can be invoked from a
non-native (but cross-type supported) loader.

[0] https://lore.kernel.org/linux-arm-kernel/20200206140352.6300-1-ardb@kernel.org/
[1] https://github.com/ardbiesheuvel/edk2/commits/linux-efi-generic

Cc: lersek@redhat.com
Cc: leif@nuviainc.com
Cc: pjones@redhat.com
Cc: mjg59@google.com
Cc: agraf@csgraf.de
Cc: daniel.kiper@oracle.com
Cc: hdegoede@redhat.com
Cc: nivedita@alum.mit.edu
Cc: mbrown@fensystems.co.uk
Cc: mingo@kernel.org

Ard Biesheuvel (3):
  efi/x86: drop redundant .bss section
  efi/x86: add true mixed mode entry point into .compat section
  efi/x86: implement mixed mode boot without the handover protocol

 arch/x86/boot/Makefile             |  2 +-
 arch/x86/boot/compressed/head_64.S | 61 +++++++++++++++++-
 arch/x86/boot/header.S             | 23 ++++---
 arch/x86/boot/tools/build.c        | 67 +++++++++++++-------
 4 files changed, 115 insertions(+), 38 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC PATCH 1/3] efi/x86: drop redundant .bss section
  2020-02-13 14:59 [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
@ 2020-02-13 14:59 ` Ard Biesheuvel
  2020-02-13 14:59 ` [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section Ard Biesheuvel
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 14:59 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, Ard Biesheuvel, lersek, leif, pjones, mjg59,
	agraf, daniel.kiper, hdegoede, nivedita, mbrown, mingo

In commit c7fb93ec51d462ec ("x86/efi: Include a .bss section within
the PE/COFF headers"), we added a separate .bss section to the PE/COFF
header of the compressed kernel describing the static memory footprint
of the decompressor, to ensure that it has enough headroom to decompress
itself.

We can achieve the exact same result by increasing the virtual size of
the .text section, without changing the raw size, which, as per the
PE/COFF specification, requires the loader to zero initialize the delta.

Doing so frees up a slot in the section table, which we will use later
to describe the mixed mode entrypoint.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/header.S      | 21 +-----------
 arch/x86/boot/tools/build.c | 35 ++++++++------------
 2 files changed, 14 insertions(+), 42 deletions(-)

diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 97d9b6d6c1af..d59f6604bb42 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -106,7 +106,7 @@ coff_header:
 #else
 	.word	0x8664				# x86-64
 #endif
-	.word	4				# nr_sections
+	.word	3				# nr_sections
 	.long	0 				# TimeDateStamp
 	.long	0				# PointerToSymbolTable
 	.long	1				# NumberOfSymbols
@@ -248,25 +248,6 @@ section_table:
 	.word	0				# NumberOfLineNumbers
 	.long	0x60500020			# Characteristics (section flags)
 
-	#
-	# The offset & size fields are filled in by build.c.
-	#
-	.ascii	".bss"
-	.byte	0
-	.byte	0
-	.byte	0
-	.byte	0
-	.long	0
-	.long	0x0
-	.long	0				# Size of initialized data
-						# on disk
-	.long	0x0
-	.long	0				# PointerToRelocations
-	.long	0				# PointerToLineNumbers
-	.word	0				# NumberOfRelocations
-	.word	0				# NumberOfLineNumbers
-	.long	0xc8000080			# Characteristics (section flags)
-
 #endif /* CONFIG_EFI_STUB */
 
 	# Kernel attributes; used by setup.  This is part 1 of the
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 55e669d29e54..0c8c5a52f1f0 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -203,10 +203,12 @@ static void update_pecoff_setup_and_reloc(unsigned int size)
 	put_unaligned_le32(10, &buf[reloc_offset + 4]);
 }
 
-static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
+static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
+			       unsigned int init_sz)
 {
 	unsigned int pe_header;
 	unsigned int text_sz = file_sz - text_start;
+	unsigned int bss_sz = init_sz - file_sz;
 
 	pe_header = get_unaligned_le32(&buf[0x3c]);
 
@@ -216,28 +218,19 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
 	 */
 	put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
 
-	/*
-	 * Address of entry point for PE/COFF executable
-	 */
-	put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
-
-	update_pecoff_section_header(".text", text_start, text_sz);
-}
-
-static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz)
-{
-	unsigned int pe_header;
-	unsigned int bss_sz = init_sz - file_sz;
-
-	pe_header = get_unaligned_le32(&buf[0x3c]);
-
 	/* Size of uninitialized data */
 	put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]);
 
 	/* Size of image */
 	put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
 
-	update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0);
+	/*
+	 * Address of entry point for PE/COFF executable
+	 */
+	put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
+
+	update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz,
+					    text_sz, text_start);
 }
 
 static int reserve_pecoff_reloc_section(int c)
@@ -278,9 +271,8 @@ static void efi_stub_entry_update(void)
 
 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
 static inline void update_pecoff_text(unsigned int text_start,
-				      unsigned int file_sz) {}
-static inline void update_pecoff_bss(unsigned int file_sz,
-				     unsigned int init_sz) {}
+				      unsigned int file_sz,
+				      unsigned int init_sz) {}
 static inline void efi_stub_defaults(void) {}
 static inline void efi_stub_entry_update(void) {}
 
@@ -406,9 +398,8 @@ int main(int argc, char ** argv)
 	buf[0x1f1] = setup_sectors-1;
 	put_unaligned_le32(sys_size, &buf[0x1f4]);
 
-	update_pecoff_text(setup_sectors * 512, i + (sys_size * 16));
 	init_sz = get_unaligned_le32(&buf[0x260]);
-	update_pecoff_bss(i + (sys_size * 16), init_sz);
+	update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
 
 	efi_stub_entry_update();
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section
  2020-02-13 14:59 [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
  2020-02-13 14:59 ` [RFC PATCH 1/3] efi/x86: drop redundant .bss section Ard Biesheuvel
@ 2020-02-13 14:59 ` Ard Biesheuvel
  2020-02-13 16:59   ` Arvind Sankar
  2020-02-13 14:59 ` [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol Ard Biesheuvel
  2020-02-13 17:53 ` [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Arvind Sankar
  3 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 14:59 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, Ard Biesheuvel, lersek, leif, pjones, mjg59,
	agraf, daniel.kiper, hdegoede, nivedita, mbrown, mingo

Currently, mixed mode is closely tied to the EFI handover protocol
and relies on intimate knowledge of the bootparams structure, setup
header etc, all of which are rather byzantine and entirely specific
to x86.

Even though no other EFI supported architectures are currently known
that could support something like mixed mode, it makes sense to
abstract a bit from this, and make it part of a generic Linux on EFI
boot protocol.

To that end, add a .compat section to the mixed mode binary, and populate
it with the PE machine type and entry point address, allowing firmware
implementations to match it to their native machine type, and invoke
non-native binaries using a secondary entry point.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/Makefile      |  2 +-
 arch/x86/boot/header.S      | 20 +++++++++++-
 arch/x86/boot/tools/build.c | 32 +++++++++++++++++++-
 3 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 012b82fc8617..ef9e1f2c836c 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -88,7 +88,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
 
 SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|efi32_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index d59f6604bb42..76a485013771 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -106,7 +106,7 @@ coff_header:
 #else
 	.word	0x8664				# x86-64
 #endif
-	.word	3				# nr_sections
+	.word	section_count			# nr_sections
 	.long	0 				# TimeDateStamp
 	.long	0				# PointerToSymbolTable
 	.long	1				# NumberOfSymbols
@@ -230,6 +230,23 @@ section_table:
 	.word	0				# NumberOfLineNumbers
 	.long	0x42100040			# Characteristics (section flags)
 
+#ifdef CONFIG_EFI_MIXED
+	#
+	# The offset & size fields are filled in by build.c.
+	#
+	.asciz	".compat"
+	.long	0
+	.long	0x0
+	.long	0				# Size of initialized data
+						# on disk
+	.long	0x0
+	.long	0				# PointerToRelocations
+	.long	0				# PointerToLineNumbers
+	.word	0				# NumberOfRelocations
+	.word	0				# NumberOfLineNumbers
+	.long	0x60500020			# Characteristics (section flags)
+#endif
+
 	#
 	# The offset & size fields are filled in by build.c.
 	#
@@ -248,6 +265,7 @@ section_table:
 	.word	0				# NumberOfLineNumbers
 	.long	0x60500020			# Characteristics (section flags)
 
+	.set	section_count, (. - section_table) / 40
 #endif /* CONFIG_EFI_STUB */
 
 	# Kernel attributes; used by setup.  This is part 1 of the
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 0c8c5a52f1f0..707b979566ca 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -53,9 +53,16 @@ u8 buf[SETUP_SECT_MAX*512];
 
 #define PECOFF_RELOC_RESERVE 0x20
 
+#ifdef CONFIG_EFI_MIXED
+#define PECOFF_COMPAT_RESERVE 0x20
+#else
+#define PECOFF_COMPAT_RESERVE 0x0
+#endif
+
 unsigned long efi32_stub_entry;
 unsigned long efi64_stub_entry;
 unsigned long efi_pe_entry;
+unsigned long efi32_pe_entry;
 unsigned long kernel_info;
 unsigned long startup_64;
 
@@ -189,7 +196,8 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz
 static void update_pecoff_setup_and_reloc(unsigned int size)
 {
 	u32 setup_offset = 0x200;
-	u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
+	u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
+	u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
 	u32 setup_size = reloc_offset - setup_offset;
 
 	update_pecoff_section_header(".setup", setup_offset, setup_size);
@@ -201,6 +209,20 @@ static void update_pecoff_setup_and_reloc(unsigned int size)
 	 */
 	put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
 	put_unaligned_le32(10, &buf[reloc_offset + 4]);
+
+#ifdef CONFIG_EFI_MIXED
+	update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE);
+
+	/*
+	 * Put the IA-32 machine type (0x14c) and the associated entry point
+	 * address in the .compat section, so loaders can figure out which other
+	 * execution modes this image supports.
+	 */
+	buf[compat_offset] = 0x1;
+	buf[compat_offset + 1] = 0x8;
+	put_unaligned_le16(0x14c, &buf[compat_offset + 2]);
+	put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]);
+#endif
 }
 
 static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
@@ -282,6 +304,12 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
+static int reserve_pecoff_compat_section(int c)
+{
+	/* Reserve 0x20 bytes for .compat section */
+	memset(buf+c, 0, PECOFF_COMPAT_RESERVE);
+	return PECOFF_COMPAT_RESERVE;
+}
 
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
@@ -314,6 +342,7 @@ static void parse_zoffset(char *fname)
 		PARSE_ZOFS(p, efi32_stub_entry);
 		PARSE_ZOFS(p, efi64_stub_entry);
 		PARSE_ZOFS(p, efi_pe_entry);
+		PARSE_ZOFS(p, efi32_pe_entry);
 		PARSE_ZOFS(p, kernel_info);
 		PARSE_ZOFS(p, startup_64);
 
@@ -357,6 +386,7 @@ int main(int argc, char ** argv)
 		die("Boot block hasn't got boot flag (0xAA55)");
 	fclose(file);
 
+	c += reserve_pecoff_compat_section(c);
 	c += reserve_pecoff_reloc_section(c);
 
 	/* Pad unused space with zeros */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol
  2020-02-13 14:59 [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
  2020-02-13 14:59 ` [RFC PATCH 1/3] efi/x86: drop redundant .bss section Ard Biesheuvel
  2020-02-13 14:59 ` [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section Ard Biesheuvel
@ 2020-02-13 14:59 ` Ard Biesheuvel
  2020-02-13 17:23   ` Arvind Sankar
  2020-02-13 17:53 ` [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Arvind Sankar
  3 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 14:59 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, Ard Biesheuvel, lersek, leif, pjones, mjg59,
	agraf, daniel.kiper, hdegoede, nivedita, mbrown, mingo

Add support for booting 64-bit x86 kernels from 32-bit firmware running
on 64-bit capable CPUs without requiring the bootloader to implement
the EFI handover protocol, allocate the setup block etc etc, all of
which can be done by the stub using code we have already implemented.

Instead, create an ordinary EFI application entrypoint but implemented
in 32-bit code, so that it can be invoked by 32-bit firmware, and stash
the address of this 32-bit entrypoint in the .compat section where the
bootloader can find it.

Note that we use the setup block embedded in the binary to go through
startup_32(), but it gets reallocated and copied in efi_pe_entry(),
using the same code that runs when the x86 kernel is booted in EFI
mode from native firmware. This requires the loaded image protocol to
be installed on the kernel image's EFI handle, and point to the kernel
image itself and not to its loader. This, in turn, requires the
bootloader to use the LoadImage() boot services to load the 64-bit
image from 32-bit firmware, which is in fact supported by firmware
based on EDK2. (Only StartImage() will fail, and instead, the newly
added entrypoint needs to be invoked)

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/head_64.S | 61 +++++++++++++++++++-
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index a4f5561c1c0e..7baaf9c97f5a 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -207,8 +207,8 @@ SYM_FUNC_START(startup_32)
 	cmp	$0, %edi
 	jz	1f
 	leal	efi64_stub_entry(%ebp), %eax
-	movl	%esi, %edx
 	movl	efi32_boot_args+4(%ebp), %esi
+	movl	efi32_boot_args+8(%ebp), %edx	// saved bootparams pointer
 1:
 #endif
 	pushl	%eax
@@ -233,6 +233,8 @@ SYM_FUNC_START(efi32_stub_entry)
 1:	pop	%ebp
 	subl	$1b, %ebp
 
+	movl	%esi, efi32_boot_args+8(%ebp)
+2:
 	movl	%ecx, efi32_boot_args(%ebp)
 	movl	%edx, efi32_boot_args+4(%ebp)
 	movb	$0, efi_is64(%ebp)
@@ -249,6 +251,49 @@ SYM_FUNC_START(efi32_stub_entry)
 
 	jmp	startup_32
 SYM_FUNC_END(efi32_stub_entry)
+
+#define ST32_boottime		60 // offsetof(efi_system_table_32_t, boottime)
+#define BS32_handle_protocol	88 // offsetof(efi_boot_services_32_t, handle_protocol)
+#define LI32_image_base		32 // offsetof(efi_loaded_image_32_t, image_base)
+
+	.subsection 1
+	.code32
+SYM_FUNC_START(efi32_pe_entry)
+	pushl	%ebp
+
+	call	3f
+3:	pop	%ebp
+	subl	$3b, %ebp
+
+	/* Get the loaded image protocol pointer from the image handle */
+	subl	$12, %esp			// space for the loaded image pointer
+	pushl	%esp				// pass its address
+	leal	5f(%ebp), %eax
+	pushl	%eax				// pass the GUID address
+	pushl	28(%esp)			// pass the image handle
+
+	movl	36(%esp), %eax			// sys_table
+	movl	ST32_boottime(%eax), %eax	// sys_table->boottime
+	call	*BS32_handle_protocol(%eax)	// sys_table->boottime->handle_protocol
+	cmp	$0, %eax
+	jnz	4f
+
+	movl	32(%esp), %ecx			// image_handle
+	movl	36(%esp), %edx			// sys_table
+	movl	12(%esp), %esi			// loaded_image
+	movl	LI32_image_base(%esi), %esi	// loaded_image->image_base
+	jmp	2b
+
+4:	addl	$24, %esp
+	popl	%ebp
+	ret
+SYM_FUNC_END(efi32_pe_entry)
+
+	/* EFI loaded image protocol GUID */
+5:	.long	0x5B1B31A1
+	.word	0x9562, 0x11d2
+	.byte	0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B
+	.previous
 #endif
 
 	.code64
@@ -465,11 +510,23 @@ SYM_CODE_END(startup_64)
 SYM_FUNC_START(efi64_stub_entry)
 SYM_FUNC_START_ALIAS(efi_stub_entry)
 	and	$~0xf, %rsp			/* realign the stack */
+#ifdef CONFIG_EFI_MIXED
+	cmpl	$0, %edx
+	jz	0f
+#endif
 	call	efi_main
 	movq	%rax,%rsi
 	movl	BP_code32_start(%esi), %eax
 	leaq	startup_64(%rax), %rax
 	jmp	*%rax
+
+#ifdef CONFIG_EFI_MIXED
+0:	movl	%edi, %ecx		// MS calling convention
+	movl	%esi, %edx
+	call	efi_pe_entry
+1:	hlt
+	jmp	1b
+#endif
 SYM_FUNC_END(efi64_stub_entry)
 SYM_FUNC_END_ALIAS(efi_stub_entry)
 #endif
@@ -641,7 +698,7 @@ SYM_DATA_START_LOCAL(gdt)
 SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
 
 #ifdef CONFIG_EFI_MIXED
-SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0)
+SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
 SYM_DATA(efi_is64, .byte 1)
 #endif
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section
  2020-02-13 14:59 ` [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section Ard Biesheuvel
@ 2020-02-13 16:59   ` Arvind Sankar
  2020-02-13 17:13     ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Arvind Sankar @ 2020-02-13 16:59 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, linux-arm-kernel, lersek, leif, pjones, mjg59, agraf,
	daniel.kiper, hdegoede, nivedita, mbrown, mingo

On Thu, Feb 13, 2020 at 03:59:27PM +0100, Ard Biesheuvel wrote:
> Currently, mixed mode is closely tied to the EFI handover protocol
> and relies on intimate knowledge of the bootparams structure, setup
> header etc, all of which are rather byzantine and entirely specific
> to x86.
> 
> Even though no other EFI supported architectures are currently known
> that could support something like mixed mode, it makes sense to
> abstract a bit from this, and make it part of a generic Linux on EFI
> boot protocol.
> 
> To that end, add a .compat section to the mixed mode binary, and populate
> it with the PE machine type and entry point address, allowing firmware
> implementations to match it to their native machine type, and invoke
> non-native binaries using a secondary entry point.

This patch refers to efi32_pe_entry which is only defined in the next
one.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section
  2020-02-13 16:59   ` Arvind Sankar
@ 2020-02-13 17:13     ` Ard Biesheuvel
  0 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 17:13 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: linux-efi, linux-arm-kernel, Laszlo Ersek, Leif Lindholm,
	Peter Jones, Matthew Garrett, Alexander Graf, Daniel Kiper,
	Hans de Goede, Michael Brown, Ingo Molnar

On Thu, 13 Feb 2020 at 17:59, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Feb 13, 2020 at 03:59:27PM +0100, Ard Biesheuvel wrote:
> > Currently, mixed mode is closely tied to the EFI handover protocol
> > and relies on intimate knowledge of the bootparams structure, setup
> > header etc, all of which are rather byzantine and entirely specific
> > to x86.
> >
> > Even though no other EFI supported architectures are currently known
> > that could support something like mixed mode, it makes sense to
> > abstract a bit from this, and make it part of a generic Linux on EFI
> > boot protocol.
> >
> > To that end, add a .compat section to the mixed mode binary, and populate
> > it with the PE machine type and entry point address, allowing firmware
> > implementations to match it to their native machine type, and invoke
> > non-native binaries using a secondary entry point.
>
> This patch refers to efi32_pe_entry which is only defined in the next
> one.

Indeed. So the .compat section will be emitted with a bogus entry
point when applying this patch but not the next one, so perhaps I
should simply reorder them .

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol
  2020-02-13 14:59 ` [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol Ard Biesheuvel
@ 2020-02-13 17:23   ` Arvind Sankar
  2020-02-13 17:42     ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Arvind Sankar @ 2020-02-13 17:23 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, linux-arm-kernel, lersek, leif, pjones, mjg59, agraf,
	daniel.kiper, hdegoede, nivedita, mbrown, mingo

On Thu, Feb 13, 2020 at 03:59:28PM +0100, Ard Biesheuvel wrote:
> Add support for booting 64-bit x86 kernels from 32-bit firmware running
> on 64-bit capable CPUs without requiring the bootloader to implement
> the EFI handover protocol, allocate the setup block etc etc, all of
> which can be done by the stub using code we have already implemented.
> 
> Instead, create an ordinary EFI application entrypoint but implemented
> in 32-bit code, so that it can be invoked by 32-bit firmware, and stash
> the address of this 32-bit entrypoint in the .compat section where the
> bootloader can find it.
> 
> Note that we use the setup block embedded in the binary to go through
> startup_32(), but it gets reallocated and copied in efi_pe_entry(),
> using the same code that runs when the x86 kernel is booted in EFI
> mode from native firmware. This requires the loaded image protocol to
> be installed on the kernel image's EFI handle, and point to the kernel
> image itself and not to its loader. This, in turn, requires the
> bootloader to use the LoadImage() boot services to load the 64-bit
> image from 32-bit firmware, which is in fact supported by firmware
> based on EDK2. (Only StartImage() will fail, and instead, the newly
> added entrypoint needs to be invoked)
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/x86/boot/compressed/head_64.S | 61 +++++++++++++++++++-
>  1 file changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index a4f5561c1c0e..7baaf9c97f5a 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -207,8 +207,8 @@ SYM_FUNC_START(startup_32)
>  	cmp	$0, %edi
>  	jz	1f
>  	leal	efi64_stub_entry(%ebp), %eax
> -	movl	%esi, %edx
>  	movl	efi32_boot_args+4(%ebp), %esi
> +	movl	efi32_boot_args+8(%ebp), %edx	// saved bootparams pointer
>  1:
>  #endif
>  	pushl	%eax
> @@ -233,6 +233,8 @@ SYM_FUNC_START(efi32_stub_entry)
>  1:	pop	%ebp
>  	subl	$1b, %ebp
>  
> +	movl	%esi, efi32_boot_args+8(%ebp)
> +2:

I think it would be easier to read if this were turned into a proper
SYM_INNER_LABEL. You could then also just put efi32_pe_entry into the
.text section instead of moving it to the end of .head.text with
.subsection. Another option is to use a separate flag in .data to
indicate that we entered via efi32_pe_entry, then you could just jump
to efi32_stub_entry.

>  	movl	%ecx, efi32_boot_args(%ebp)
>  	movl	%edx, efi32_boot_args+4(%ebp)
>  	movb	$0, efi_is64(%ebp)
> @@ -249,6 +251,49 @@ SYM_FUNC_START(efi32_stub_entry)
>  
>  	jmp	startup_32
>  SYM_FUNC_END(efi32_stub_entry)
> +
> +#define ST32_boottime		60 // offsetof(efi_system_table_32_t, boottime)
> +#define BS32_handle_protocol	88 // offsetof(efi_boot_services_32_t, handle_protocol)
> +#define LI32_image_base		32 // offsetof(efi_loaded_image_32_t, image_base)
> +
> +	.subsection 1
> +	.code32
> +SYM_FUNC_START(efi32_pe_entry)
> +	pushl	%ebp
> +
> +	call	3f
> +3:	pop	%ebp
> +	subl	$3b, %ebp
> +
> +	/* Get the loaded image protocol pointer from the image handle */
> +	subl	$12, %esp			// space for the loaded image pointer
> +	pushl	%esp				// pass its address
> +	leal	5f(%ebp), %eax
> +	pushl	%eax				// pass the GUID address
> +	pushl	28(%esp)			// pass the image handle
> +
> +	movl	36(%esp), %eax			// sys_table
> +	movl	ST32_boottime(%eax), %eax	// sys_table->boottime
> +	call	*BS32_handle_protocol(%eax)	// sys_table->boottime->handle_protocol
> +	cmp	$0, %eax
> +	jnz	4f
> +
> +	movl	32(%esp), %ecx			// image_handle
> +	movl	36(%esp), %edx			// sys_table
> +	movl	12(%esp), %esi			// loaded_image
> +	movl	LI32_image_base(%esi), %esi	// loaded_image->image_base
> +	jmp	2b
> +
> +4:	addl	$24, %esp
> +	popl	%ebp
> +	ret
> +SYM_FUNC_END(efi32_pe_entry)
> +
> +	/* EFI loaded image protocol GUID */
> +5:	.long	0x5B1B31A1
> +	.word	0x9562, 0x11d2
> +	.byte	0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B
> +	.previous

Any reason for this not to live in .data (or .rodata)?
>  #endif
>  
>  	.code64
> @@ -465,11 +510,23 @@ SYM_CODE_END(startup_64)
>  SYM_FUNC_START(efi64_stub_entry)
>  SYM_FUNC_START_ALIAS(efi_stub_entry)
>  	and	$~0xf, %rsp			/* realign the stack */
> +#ifdef CONFIG_EFI_MIXED
> +	cmpl	$0, %edx
> +	jz	0f
> +#endif
>  	call	efi_main
>  	movq	%rax,%rsi
>  	movl	BP_code32_start(%esi), %eax
>  	leaq	startup_64(%rax), %rax
>  	jmp	*%rax
> +
> +#ifdef CONFIG_EFI_MIXED
> +0:	movl	%edi, %ecx		// MS calling convention
> +	movl	%esi, %edx
> +	call	efi_pe_entry
> +1:	hlt
> +	jmp	1b
> +#endif
>  SYM_FUNC_END(efi64_stub_entry)
>  SYM_FUNC_END_ALIAS(efi_stub_entry)
>  #endif
> @@ -641,7 +698,7 @@ SYM_DATA_START_LOCAL(gdt)
>  SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
>  
>  #ifdef CONFIG_EFI_MIXED
> -SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0)
> +SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
>  SYM_DATA(efi_is64, .byte 1)
>  #endif
>  
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol
  2020-02-13 17:23   ` Arvind Sankar
@ 2020-02-13 17:42     ` Ard Biesheuvel
  0 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 17:42 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: linux-efi, linux-arm-kernel, Laszlo Ersek, Leif Lindholm,
	Peter Jones, Matthew Garrett, Alexander Graf, Daniel Kiper,
	Hans de Goede, Michael Brown, Ingo Molnar

On Thu, 13 Feb 2020 at 18:23, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Feb 13, 2020 at 03:59:28PM +0100, Ard Biesheuvel wrote:
> > Add support for booting 64-bit x86 kernels from 32-bit firmware running
> > on 64-bit capable CPUs without requiring the bootloader to implement
> > the EFI handover protocol, allocate the setup block etc etc, all of
> > which can be done by the stub using code we have already implemented.
> >
> > Instead, create an ordinary EFI application entrypoint but implemented
> > in 32-bit code, so that it can be invoked by 32-bit firmware, and stash
> > the address of this 32-bit entrypoint in the .compat section where the
> > bootloader can find it.
> >
> > Note that we use the setup block embedded in the binary to go through
> > startup_32(), but it gets reallocated and copied in efi_pe_entry(),
> > using the same code that runs when the x86 kernel is booted in EFI
> > mode from native firmware. This requires the loaded image protocol to
> > be installed on the kernel image's EFI handle, and point to the kernel
> > image itself and not to its loader. This, in turn, requires the
> > bootloader to use the LoadImage() boot services to load the 64-bit
> > image from 32-bit firmware, which is in fact supported by firmware
> > based on EDK2. (Only StartImage() will fail, and instead, the newly
> > added entrypoint needs to be invoked)
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > ---
> >  arch/x86/boot/compressed/head_64.S | 61 +++++++++++++++++++-
> >  1 file changed, 59 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> > index a4f5561c1c0e..7baaf9c97f5a 100644
> > --- a/arch/x86/boot/compressed/head_64.S
> > +++ b/arch/x86/boot/compressed/head_64.S
> > @@ -207,8 +207,8 @@ SYM_FUNC_START(startup_32)
> >       cmp     $0, %edi
> >       jz      1f
> >       leal    efi64_stub_entry(%ebp), %eax
> > -     movl    %esi, %edx
> >       movl    efi32_boot_args+4(%ebp), %esi
> > +     movl    efi32_boot_args+8(%ebp), %edx   // saved bootparams pointer
> >  1:
> >  #endif
> >       pushl   %eax
> > @@ -233,6 +233,8 @@ SYM_FUNC_START(efi32_stub_entry)
> >  1:   pop     %ebp
> >       subl    $1b, %ebp
> >
> > +     movl    %esi, efi32_boot_args+8(%ebp)
> > +2:
>
> I think it would be easier to read if this were turned into a proper
> SYM_INNER_LABEL. You could then also just put efi32_pe_entry into the
> .text section instead of moving it to the end of .head.text with
> .subsection. Another option is to use a separate flag in .data to
> indicate that we entered via efi32_pe_entry, then you could just jump
> to efi32_stub_entry.
>

Indeed.

> >       movl    %ecx, efi32_boot_args(%ebp)
> >       movl    %edx, efi32_boot_args+4(%ebp)
> >       movb    $0, efi_is64(%ebp)
> > @@ -249,6 +251,49 @@ SYM_FUNC_START(efi32_stub_entry)
> >
> >       jmp     startup_32
> >  SYM_FUNC_END(efi32_stub_entry)
> > +
> > +#define ST32_boottime                60 // offsetof(efi_system_table_32_t, boottime)
> > +#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol)
> > +#define LI32_image_base              32 // offsetof(efi_loaded_image_32_t, image_base)
> > +
> > +     .subsection 1
> > +     .code32
> > +SYM_FUNC_START(efi32_pe_entry)
> > +     pushl   %ebp
> > +
> > +     call    3f
> > +3:   pop     %ebp
> > +     subl    $3b, %ebp
> > +
> > +     /* Get the loaded image protocol pointer from the image handle */
> > +     subl    $12, %esp                       // space for the loaded image pointer
> > +     pushl   %esp                            // pass its address
> > +     leal    5f(%ebp), %eax
> > +     pushl   %eax                            // pass the GUID address
> > +     pushl   28(%esp)                        // pass the image handle
> > +
> > +     movl    36(%esp), %eax                  // sys_table
> > +     movl    ST32_boottime(%eax), %eax       // sys_table->boottime
> > +     call    *BS32_handle_protocol(%eax)     // sys_table->boottime->handle_protocol
> > +     cmp     $0, %eax
> > +     jnz     4f
> > +
> > +     movl    32(%esp), %ecx                  // image_handle
> > +     movl    36(%esp), %edx                  // sys_table
> > +     movl    12(%esp), %esi                  // loaded_image
> > +     movl    LI32_image_base(%esi), %esi     // loaded_image->image_base
> > +     jmp     2b
> > +
> > +4:   addl    $24, %esp
> > +     popl    %ebp
> > +     ret
> > +SYM_FUNC_END(efi32_pe_entry)
> > +
> > +     /* EFI loaded image protocol GUID */
> > +5:   .long   0x5B1B31A1
> > +     .word   0x9562, 0x11d2
> > +     .byte   0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B
> > +     .previous
>
> Any reason for this not to live in .data (or .rodata)?

None other than laziness ...



> >  #endif
> >
> >       .code64
> > @@ -465,11 +510,23 @@ SYM_CODE_END(startup_64)
> >  SYM_FUNC_START(efi64_stub_entry)
> >  SYM_FUNC_START_ALIAS(efi_stub_entry)
> >       and     $~0xf, %rsp                     /* realign the stack */
> > +#ifdef CONFIG_EFI_MIXED
> > +     cmpl    $0, %edx
> > +     jz      0f
> > +#endif
> >       call    efi_main
> >       movq    %rax,%rsi
> >       movl    BP_code32_start(%esi), %eax
> >       leaq    startup_64(%rax), %rax
> >       jmp     *%rax
> > +
> > +#ifdef CONFIG_EFI_MIXED
> > +0:   movl    %edi, %ecx              // MS calling convention
> > +     movl    %esi, %edx
> > +     call    efi_pe_entry
> > +1:   hlt
> > +     jmp     1b
> > +#endif
> >  SYM_FUNC_END(efi64_stub_entry)
> >  SYM_FUNC_END_ALIAS(efi_stub_entry)
> >  #endif
> > @@ -641,7 +698,7 @@ SYM_DATA_START_LOCAL(gdt)
> >  SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
> >
> >  #ifdef CONFIG_EFI_MIXED
> > -SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0)
> > +SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
> >  SYM_DATA(efi_is64, .byte 1)
> >  #endif
> >
> > --
> > 2.17.1
> >

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-13 14:59 [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2020-02-13 14:59 ` [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol Ard Biesheuvel
@ 2020-02-13 17:53 ` Arvind Sankar
  2020-02-13 17:55   ` Ard Biesheuvel
  3 siblings, 1 reply; 16+ messages in thread
From: Arvind Sankar @ 2020-02-13 17:53 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, linux-arm-kernel, lersek, leif, pjones, mjg59, agraf,
	daniel.kiper, hdegoede, nivedita, mbrown, mingo

On Thu, Feb 13, 2020 at 03:59:25PM +0100, Ard Biesheuvel wrote:
> This series is another part of my effort to reduce the level of knowledge
> on the part of the bootloader or firmware of internal per-architecture
> details regarding where/how the kernel is loaded and where its initrd and
> other context data are passed.
> 
> The x86 architecture has a so-called 'EFI handover protocol', which defines
> how the bootparams struct should be populated, and how it should be
> interpreted to figure out where to load the kernel, and at which offset in
> the binary the entrypoint is located. This scheme allows the initrd to be
> loaded beforehand, and allows 32-bit firmware to invoke a 64-bit kernel
> via a special entrypoint that manages the state transitions between the
> two execution modes.
> 
> Due to this, x86 loaders currently do not rely on LoadImage and StartImage,
> and therefore, are forced to re-implement things like image authentication
> for secure boot and taking the measurements for measured boot in their open
> coded clones of these routines.
> 
> My previous series on this topic [0] implements a generic way to load the
> initrd from any source supported by the loader without relying on something
> like device trees or bootparams structures, and so native boot should not
> need the EFI handover protocol anymore after those change are merged.
> 
> What remains is mixed mode boot, which also needs the EFI handover protocol
> regardless of whether an initrd is loaded or not. So let's get rid of that
> requirement, and take advantage of the fact that EDK2 based firmware does
> support LoadImage() for X64 binaries on IA32 firmware, which means we can
> rely on the secure boot and measured boot checks being performed by the
> firmware. The only thing we need to put on top is a way to discover the
> non-native entrypoint into the binary in a way that does not rely on x86
> specific headers and data structures.
> 
> So let's introduce a new .compat header in the PE/COFF metadata of the
> bzImage, and populate it with a <machine type, entrypoint> tuple, allowing
> a generic EFI loader to decide whether the entrypoint supports its native
> machine type, and invoke it as an ordinary EFI application entrypoint.
> Since we will not be passing a bootparams structure, we need to discover
> the base of the image (which contains the setup header) via the loaded
> image protocol before we can enter the kernel in 32-bit mode at startup_32()
> 
> A loader implementation for OVMF can be found at [1]. Note that this loader
> code is fully generic, and could be used without modifications if other
> architectures ever emerge that support kernels that can be invoked from a
> non-native (but cross-type supported) loader.
> 
> [0] https://lore.kernel.org/linux-arm-kernel/20200206140352.6300-1-ardb@kernel.org/
> [1] https://github.com/ardbiesheuvel/edk2/commits/linux-efi-generic
> 

As an alternative to the new section, how about having a CONFIG option
to emit the 64-bit kernel with a 32-bit PE header instead, which would
point to efi32_pe_entry? In that case it could be directly loaded by
existing firmware already. You could even have a tool that can mangle an
existing bzImage's header from 64-bit to 32-bit, say using the newly
added kernel_info structure to record the existence and location of
efi32_pe_entry.

Also, the PE header can live anywhere inside the image, right? Is there
any reason to struggle to shoehorn it into the "boot sector"?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-13 17:53 ` [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Arvind Sankar
@ 2020-02-13 17:55   ` Ard Biesheuvel
  2020-02-13 18:47     ` Arvind Sankar
  0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 17:55 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: linux-efi, linux-arm-kernel, Laszlo Ersek, Leif Lindholm,
	Peter Jones, Matthew Garrett, Alexander Graf, Daniel Kiper,
	Hans de Goede, Michael Brown, Ingo Molnar

On Thu, 13 Feb 2020 at 18:53, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Feb 13, 2020 at 03:59:25PM +0100, Ard Biesheuvel wrote:
> > This series is another part of my effort to reduce the level of knowledge
> > on the part of the bootloader or firmware of internal per-architecture
> > details regarding where/how the kernel is loaded and where its initrd and
> > other context data are passed.
> >
> > The x86 architecture has a so-called 'EFI handover protocol', which defines
> > how the bootparams struct should be populated, and how it should be
> > interpreted to figure out where to load the kernel, and at which offset in
> > the binary the entrypoint is located. This scheme allows the initrd to be
> > loaded beforehand, and allows 32-bit firmware to invoke a 64-bit kernel
> > via a special entrypoint that manages the state transitions between the
> > two execution modes.
> >
> > Due to this, x86 loaders currently do not rely on LoadImage and StartImage,
> > and therefore, are forced to re-implement things like image authentication
> > for secure boot and taking the measurements for measured boot in their open
> > coded clones of these routines.
> >
> > My previous series on this topic [0] implements a generic way to load the
> > initrd from any source supported by the loader without relying on something
> > like device trees or bootparams structures, and so native boot should not
> > need the EFI handover protocol anymore after those change are merged.
> >
> > What remains is mixed mode boot, which also needs the EFI handover protocol
> > regardless of whether an initrd is loaded or not. So let's get rid of that
> > requirement, and take advantage of the fact that EDK2 based firmware does
> > support LoadImage() for X64 binaries on IA32 firmware, which means we can
> > rely on the secure boot and measured boot checks being performed by the
> > firmware. The only thing we need to put on top is a way to discover the
> > non-native entrypoint into the binary in a way that does not rely on x86
> > specific headers and data structures.
> >
> > So let's introduce a new .compat header in the PE/COFF metadata of the
> > bzImage, and populate it with a <machine type, entrypoint> tuple, allowing
> > a generic EFI loader to decide whether the entrypoint supports its native
> > machine type, and invoke it as an ordinary EFI application entrypoint.
> > Since we will not be passing a bootparams structure, we need to discover
> > the base of the image (which contains the setup header) via the loaded
> > image protocol before we can enter the kernel in 32-bit mode at startup_32()
> >
> > A loader implementation for OVMF can be found at [1]. Note that this loader
> > code is fully generic, and could be used without modifications if other
> > architectures ever emerge that support kernels that can be invoked from a
> > non-native (but cross-type supported) loader.
> >
> > [0] https://lore.kernel.org/linux-arm-kernel/20200206140352.6300-1-ardb@kernel.org/
> > [1] https://github.com/ardbiesheuvel/edk2/commits/linux-efi-generic
> >
>
> As an alternative to the new section, how about having a CONFIG option
> to emit the 64-bit kernel with a 32-bit PE header instead, which would
> point to efi32_pe_entry? In that case it could be directly loaded by
> existing firmware already. You could even have a tool that can mangle an
> existing bzImage's header from 64-bit to 32-bit, say using the newly
> added kernel_info structure to record the existence and location of
> efi32_pe_entry.
>

That wouldn't work with, say, signed distro kernels.

> Also, the PE header can live anywhere inside the image, right? Is there
> any reason to struggle to shoehorn it into the "boot sector"?

It cannot. It must live outside a region described by the section headers.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-13 17:55   ` Ard Biesheuvel
@ 2020-02-13 18:47     ` Arvind Sankar
  2020-02-13 22:36       ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Arvind Sankar @ 2020-02-13 18:47 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, linux-efi, linux-arm-kernel, Laszlo Ersek,
	Leif Lindholm, Peter Jones, Matthew Garrett, Alexander Graf,
	Daniel Kiper, Hans de Goede, Michael Brown, Ingo Molnar

On Thu, Feb 13, 2020 at 05:55:44PM +0000, Ard Biesheuvel wrote:
> On Thu, 13 Feb 2020 at 18:53, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > As an alternative to the new section, how about having a CONFIG option
> > to emit the 64-bit kernel with a 32-bit PE header instead, which would
> > point to efi32_pe_entry? In that case it could be directly loaded by
> > existing firmware already. You could even have a tool that can mangle an
> > existing bzImage's header from 64-bit to 32-bit, say using the newly
> > added kernel_info structure to record the existence and location of
> > efi32_pe_entry.
> >
> 
> That wouldn't work with, say, signed distro kernels.

No, the idea would be that the distro would distribute two signed
images, one 32-bit and one 64-bit, which are identical except for the
header. At install time, the installer chooses based on the system's
firmware bit-ness.

> 
> > Also, the PE header can live anywhere inside the image, right? Is there
> > any reason to struggle to shoehorn it into the "boot sector"?
> 
> It cannot. It must live outside a region described by the section headers.

It could still be inserted after .setup, or at the very end of the file, no?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-13 18:47     ` Arvind Sankar
@ 2020-02-13 22:36       ` Ard Biesheuvel
  2020-02-14  0:10         ` Arvind Sankar
  0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-13 22:36 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: linux-efi, linux-arm-kernel, Laszlo Ersek, Leif Lindholm,
	Peter Jones, Matthew Garrett, Alexander Graf, Daniel Kiper,
	Hans de Goede, Michael Brown, Ingo Molnar

On Thu, 13 Feb 2020 at 19:47, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Feb 13, 2020 at 05:55:44PM +0000, Ard Biesheuvel wrote:
> > On Thu, 13 Feb 2020 at 18:53, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > As an alternative to the new section, how about having a CONFIG option
> > > to emit the 64-bit kernel with a 32-bit PE header instead, which would
> > > point to efi32_pe_entry? In that case it could be directly loaded by
> > > existing firmware already. You could even have a tool that can mangle an
> > > existing bzImage's header from 64-bit to 32-bit, say using the newly
> > > added kernel_info structure to record the existence and location of
> > > efi32_pe_entry.
> > >
> >
> > That wouldn't work with, say, signed distro kernels.
>
> No, the idea would be that the distro would distribute two signed
> images, one 32-bit and one 64-bit, which are identical except for the
> header. At install time, the installer chooses based on the system's
> firmware bit-ness.
>

I guess it would be possible, but then we'd need two different images
while today, we can run the same image on both kinds of firmwares. The
only thing I am trying to do is remove all the quirky bootparams stuff
from the loader so that we can switch to LoadImage

> >
> > > Also, the PE header can live anywhere inside the image, right? Is there
> > > any reason to struggle to shoehorn it into the "boot sector"?
> >
> > It cannot. It must live outside a region described by the section headers.
>
> It could still be inserted after .setup, or at the very end of the file, no?

The PE/COFF spec mentions that the COFF header needs to follow the
signature. Also, the SizeOfHeaders field would become somewhat
ambiguous if the header is split up like that.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-13 22:36       ` Ard Biesheuvel
@ 2020-02-14  0:10         ` Arvind Sankar
  2020-02-14  0:12           ` Arvind Sankar
  0 siblings, 1 reply; 16+ messages in thread
From: Arvind Sankar @ 2020-02-14  0:10 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, linux-efi, linux-arm-kernel, Laszlo Ersek,
	Leif Lindholm, Peter Jones, Matthew Garrett, Alexander Graf,
	Daniel Kiper, Hans de Goede, Michael Brown, Ingo Molnar

On Thu, Feb 13, 2020 at 10:36:14PM +0000, Ard Biesheuvel wrote:
> On Thu, 13 Feb 2020 at 19:47, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Thu, Feb 13, 2020 at 05:55:44PM +0000, Ard Biesheuvel wrote:
> > > On Thu, 13 Feb 2020 at 18:53, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > As an alternative to the new section, how about having a CONFIG option
> > > > to emit the 64-bit kernel with a 32-bit PE header instead, which would
> > > > point to efi32_pe_entry? In that case it could be directly loaded by
> > > > existing firmware already. You could even have a tool that can mangle an
> > > > existing bzImage's header from 64-bit to 32-bit, say using the newly
> > > > added kernel_info structure to record the existence and location of
> > > > efi32_pe_entry.
> > > >
> > >
> > > That wouldn't work with, say, signed distro kernels.
> >
> > No, the idea would be that the distro would distribute two signed
> > images, one 32-bit and one 64-bit, which are identical except for the
> > header. At install time, the installer chooses based on the system's
> > firmware bit-ness.
> >
> 
> I guess it would be possible, but then we'd need two different images
> while today, we can run the same image on both kinds of firmwares. The
> only thing I am trying to do is remove all the quirky bootparams stuff
> from the loader so that we can switch to LoadImage

Yeah, but doing that will allow you to boot directly from firmware on
existing machines, and only one image needs to be chosen at install
time, so it just adds a few MiB to the package. I guess most people will
still use a boot manager or loader that can be easily enhanced to use
LoadImage and the new section, but it would be nice to have the option
to avoid that.

> 
> > >
> > > > Also, the PE header can live anywhere inside the image, right? Is there
> > > > any reason to struggle to shoehorn it into the "boot sector"?
> > >
> > > It cannot. It must live outside a region described by the section headers.
> >
> > It could still be inserted after .setup, or at the very end of the file, no?
> 
> The PE/COFF spec mentions that the COFF header needs to follow the
> signature. Also, the SizeOfHeaders field would become somewhat
> ambiguous if the header is split up like that.


Ah, the definition of SizeOfHeaders doesn't make much sense if the
headers weren't contiguous with the MS-DOS stub. I guess they just
wanted the MS-DOS stub to potentially vary in size, but still want the
header to immediately follow it, drat.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-14  0:10         ` Arvind Sankar
@ 2020-02-14  0:12           ` Arvind Sankar
  2020-02-14  0:21             ` Ard Biesheuvel
  0 siblings, 1 reply; 16+ messages in thread
From: Arvind Sankar @ 2020-02-14  0:12 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, linux-arm-kernel, Laszlo Ersek,
	Leif Lindholm, Peter Jones, Matthew Garrett, Alexander Graf,
	Daniel Kiper, Hans de Goede, Michael Brown, Ingo Molnar

On Thu, Feb 13, 2020 at 07:10:49PM -0500, Arvind Sankar wrote:
> On Thu, Feb 13, 2020 at 10:36:14PM +0000, Ard Biesheuvel wrote:
> > On Thu, 13 Feb 2020 at 19:47, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > >
> > > On Thu, Feb 13, 2020 at 05:55:44PM +0000, Ard Biesheuvel wrote:
> > > > On Thu, 13 Feb 2020 at 18:53, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > > As an alternative to the new section, how about having a CONFIG option
> > > > > to emit the 64-bit kernel with a 32-bit PE header instead, which would
> > > > > point to efi32_pe_entry? In that case it could be directly loaded by
> > > > > existing firmware already. You could even have a tool that can mangle an
> > > > > existing bzImage's header from 64-bit to 32-bit, say using the newly
> > > > > added kernel_info structure to record the existence and location of
> > > > > efi32_pe_entry.
> > > > >
> > > >
> > > > That wouldn't work with, say, signed distro kernels.
> > >
> > > No, the idea would be that the distro would distribute two signed
> > > images, one 32-bit and one 64-bit, which are identical except for the
> > > header. At install time, the installer chooses based on the system's
> > > firmware bit-ness.
> > >
> > 
> > I guess it would be possible, but then we'd need two different images
> > while today, we can run the same image on both kinds of firmwares. The
> > only thing I am trying to do is remove all the quirky bootparams stuff
> > from the loader so that we can switch to LoadImage
> 
> Yeah, but doing that will allow you to boot directly from firmware on
> existing machines, and only one image needs to be chosen at install
> time, so it just adds a few MiB to the package. I guess most people will
> still use a boot manager or loader that can be easily enhanced to use
> LoadImage and the new section, but it would be nice to have the option
> to avoid that.

Also not quite today, right? You still need this patchset and the
modifications to bootloaders to get away with one image.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-14  0:12           ` Arvind Sankar
@ 2020-02-14  0:21             ` Ard Biesheuvel
  2020-02-14  0:38               ` Arvind Sankar
  0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-14  0:21 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: linux-efi, linux-arm-kernel, Laszlo Ersek, Leif Lindholm,
	Peter Jones, Matthew Garrett, Alexander Graf, Daniel Kiper,
	Hans de Goede, Michael Brown, Ingo Molnar

On Fri, 14 Feb 2020 at 01:13, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Feb 13, 2020 at 07:10:49PM -0500, Arvind Sankar wrote:
> > On Thu, Feb 13, 2020 at 10:36:14PM +0000, Ard Biesheuvel wrote:
> > > On Thu, 13 Feb 2020 at 19:47, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > >
> > > > On Thu, Feb 13, 2020 at 05:55:44PM +0000, Ard Biesheuvel wrote:
> > > > > On Thu, 13 Feb 2020 at 18:53, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > > > As an alternative to the new section, how about having a CONFIG option
> > > > > > to emit the 64-bit kernel with a 32-bit PE header instead, which would
> > > > > > point to efi32_pe_entry? In that case it could be directly loaded by
> > > > > > existing firmware already. You could even have a tool that can mangle an
> > > > > > existing bzImage's header from 64-bit to 32-bit, say using the newly
> > > > > > added kernel_info structure to record the existence and location of
> > > > > > efi32_pe_entry.
> > > > > >
> > > > >
> > > > > That wouldn't work with, say, signed distro kernels.
> > > >
> > > > No, the idea would be that the distro would distribute two signed
> > > > images, one 32-bit and one 64-bit, which are identical except for the
> > > > header. At install time, the installer chooses based on the system's
> > > > firmware bit-ness.
> > > >
> > >
> > > I guess it would be possible, but then we'd need two different images
> > > while today, we can run the same image on both kinds of firmwares. The
> > > only thing I am trying to do is remove all the quirky bootparams stuff
> > > from the loader so that we can switch to LoadImage
> >
> > Yeah, but doing that will allow you to boot directly from firmware on
> > existing machines, and only one image needs to be chosen at install
> > time, so it just adds a few MiB to the package. I guess most people will
> > still use a boot manager or loader that can be easily enhanced to use
> > LoadImage and the new section, but it would be nice to have the option
> > to avoid that.


I see the value of having a 64-bit image that can boot natively on
32-bit firmware, but I am not expecting any buy in from the distros
for this scheme.


>
> Also not quite today, right? You still need this patchset and the
> modifications to bootloaders to get away with one image.

Sure. But we already have mixed mode support today that doesn't
require this, so it's going to be a difficult sell to switch to a new
scheme that requires infrastructure to distribute different kernels,
and logic to choose between the two.

A generic EFI bootloader/firmware will need to implement the initrd
loadfile2 protocol as well, so some Linux specific features will need
to be implemented anyway. This series is intended to ensure that mixed
mode doesn't get left behind, even though very few people use it
today.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot
  2020-02-14  0:21             ` Ard Biesheuvel
@ 2020-02-14  0:38               ` Arvind Sankar
  0 siblings, 0 replies; 16+ messages in thread
From: Arvind Sankar @ 2020-02-14  0:38 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, linux-efi, linux-arm-kernel, Laszlo Ersek,
	Leif Lindholm, Peter Jones, Matthew Garrett, Alexander Graf,
	Daniel Kiper, Hans de Goede, Michael Brown, Ingo Molnar

On Fri, Feb 14, 2020 at 12:21:30AM +0000, Ard Biesheuvel wrote:
> 
> 
> I see the value of having a 64-bit image that can boot natively on
> 32-bit firmware, but I am not expecting any buy in from the distros
> for this scheme.
> 

Ok.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, back to index

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-13 14:59 [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
2020-02-13 14:59 ` [RFC PATCH 1/3] efi/x86: drop redundant .bss section Ard Biesheuvel
2020-02-13 14:59 ` [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section Ard Biesheuvel
2020-02-13 16:59   ` Arvind Sankar
2020-02-13 17:13     ` Ard Biesheuvel
2020-02-13 14:59 ` [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol Ard Biesheuvel
2020-02-13 17:23   ` Arvind Sankar
2020-02-13 17:42     ` Ard Biesheuvel
2020-02-13 17:53 ` [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Arvind Sankar
2020-02-13 17:55   ` Ard Biesheuvel
2020-02-13 18:47     ` Arvind Sankar
2020-02-13 22:36       ` Ard Biesheuvel
2020-02-14  0:10         ` Arvind Sankar
2020-02-14  0:12           ` Arvind Sankar
2020-02-14  0:21             ` Ard Biesheuvel
2020-02-14  0:38               ` Arvind Sankar

Linux-EFI Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-efi/0 linux-efi/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-efi linux-efi/ https://lore.kernel.org/linux-efi \
		linux-efi@vger.kernel.org
	public-inbox-index linux-efi

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-efi


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git