* [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>
---
| 21 +-----------
arch/x86/boot/tools/build.c | 35 ++++++++------------
2 files changed, 14 insertions(+), 42 deletions(-)
--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 related [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 +-
| 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) > $@
--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 related [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
* [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 related [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