Due to limited space left in the setup header it was decided to introduce the setup_header2. Its role is to communicate Linux kernel supported features to the boot loader. Starting from now this is the primary way to communicate things to the boot loader.
Suggested-by: H. Peter Anvin <h...@zytor.com> Signed-off-by: Daniel Kiper <daniel.ki...@oracle.com> Reviewed-by: Ross Philipson <ross.philip...@oracle.com> Reviewed-by: Eric Snowberg <eric.snowb...@oracle.com> --- I know that setup_header2 is not the best name. There were some alternatives proposed like setup_header_extra, setup_header_addendum, setup_header_more, ext_setup_header, extended_setup_header, extended_header and extended_setup. Sadly, I am not happy with any of them. So, leaving setup_header2 as is but still looking for better name. Probably shorter == better... --- Documentation/x86/boot.txt | 49 ++++++++++++++++++++++++++++++++ arch/x86/boot/Makefile | 2 +- arch/x86/boot/compressed/Makefile | 4 +-- arch/x86/boot/compressed/setup_header2.S | 12 ++++++++ arch/x86/boot/header.S | 3 +- arch/x86/boot/tools/build.c | 8 ++++++ arch/x86/include/uapi/asm/bootparam.h | 1 + 7 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 arch/x86/boot/compressed/setup_header2.S diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index f4c2a97bfdbd..ff10c6116662 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -61,6 +61,22 @@ Protocol 2.12: (Kernel 3.8) Added the xloadflags field and extension fields to struct boot_params for loading bzImage and ramdisk above 4G in 64bit. +Protocol 2.14: BURNT BY INCORRECT COMMIT ae7e1238e68f2a472a125673ab506d49158c1889 + (x86/boot: Add ACPI RSDP address to setup_header) + DO NOT USE!!! ASSUME SAME AS 2.13. + +Protocol 2.15: (Kernel 5.2) Added the setup_header2. + +Note: The protocol version number should be changed only if the setup header + is changed. There is no need to update the version number if boot_params + or setup_header2 are changed. Additionally, it is recommended to use + xloadflags (in this case the protocol version number should not be + updated either) or setup_header2 to communicate supported Linux kernel + features to the boot loader. Due to very limited space available in + the original setup header every update to it should be considered + with great care. Starting from the protocol 2.15 the primary way to + communicate things to the boot loader is the setup_header2. + **** MEMORY LAYOUT The traditional memory map for the kernel loader, used for Image or @@ -197,6 +213,7 @@ Offset Proto Name Meaning 0258/8 2.10+ pref_address Preferred loading address 0260/4 2.10+ init_size Linear memory required during initialization 0264/4 2.11+ handover_offset Offset of handover entry point +0268/4 2.15+ setup_header2_offset Offset of the setup_header2 (1) For backwards compatibility, if the setup_sects field contains 0, the real value is 4. @@ -744,6 +761,38 @@ Offset/size: 0x264/4 See EFI HANDOVER PROTOCOL below for more details. +Field name: setup_header2_offset +Type: read +Offset/size: 0x268/4 +Protocol: 2.15+ + + This field is the offset from the beginning of the kernel image to the + setup_header2. It is embedded in the Linux image in the uncompressed + protected mode region. + + +**** THE SETUP_HEADER2 + +Due to limited space left in the setup header it was decided to introduce +the setup_header2. Its role is to communicate Linux kernel supported features +to the boot loader. All fields of the setup_header2 are read only from the +boot loader point of view. The setup_header2 is supported starting from the +boot protocol version 2.15. + + +**** DETAILS OF THE SETUP_HEADER2 FIELDS + +Field name: header +Offset/size: 0x0000/4 + + Contains the magic number "hDR2" (0x68445232). + +Field name: size +Offset/size: 0x0004/4 + + This field contains the size of the setup_header2 including setup_header2.header. + It should be used by the boot loader to detect supported fields in the setup_header2. + **** THE IMAGE CHECKSUM diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index e2839b5c246c..c11b57da90f6 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -87,7 +87,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) -sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p' +sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|setup_header2\|input_data\|_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/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 6b84afdd7538..c12ccc2bd923 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -72,8 +72,8 @@ $(obj)/../voffset.h: vmlinux FORCE $(obj)/misc.o: $(obj)/../voffset.h -vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ - $(obj)/string.o $(obj)/cmdline.o $(obj)/error.o \ +vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/setup_header2.o $(obj)/head_$(BITS).o \ + $(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/error.o \ $(obj)/piggy.o $(obj)/cpuflags.o vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o diff --git a/arch/x86/boot/compressed/setup_header2.S b/arch/x86/boot/compressed/setup_header2.S new file mode 100644 index 000000000000..0b3963296825 --- /dev/null +++ b/arch/x86/boot/compressed/setup_header2.S @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + + .section ".rodata.setup_header2", "a" + + .global setup_header2 + +setup_header2: + /* Header. */ + .ascii "hDR2" + /* Size. */ + .long setup_header2_end - setup_header2 +setup_header2_end: diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 850b8762e889..72387b1e359c 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -300,7 +300,7 @@ _start: # Part 2 of the header, from the old setup.S .ascii "HdrS" # header signature - .word 0x020d # header version number (>= 0x0105) + .word 0x020f # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) .globl realmode_swtch realmode_swtch: .word 0, 0 # default_switch, SETUPSEG @@ -557,6 +557,7 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr init_size: .long INIT_SIZE # kernel initialization size handover_offset: .long 0 # Filled in by build.c +setup_header2_offset: .long 0 # Filled in by build.c # End of setup header ##################################################### diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index a93d44e58f9c..7fc9425a0fc9 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -56,6 +56,7 @@ u8 buf[SETUP_SECT_MAX*512]; unsigned long efi32_stub_entry; unsigned long efi64_stub_entry; unsigned long efi_pe_entry; +unsigned long setup_header2; unsigned long startup_64; /*----------------------------------------------------------------------*/ @@ -289,6 +290,10 @@ static inline int reserve_pecoff_reloc_section(int c) } #endif /* CONFIG_EFI_STUB */ +static void setup_header2_offset_update(void) +{ + put_unaligned_le32(setup_header2, &buf[0x268]); +} /* * Parse zoffset.h and find the entry points. We could just #include zoffset.h @@ -321,6 +326,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, setup_header2); PARSE_ZOFS(p, startup_64); p = strchr(p, '\n'); @@ -410,6 +416,8 @@ int main(int argc, char ** argv) efi_stub_entry_update(); + setup_header2_offset_update(); + crc = partial_crc32(buf, i, crc); if (fwrite(buf, 1, i, dest) != i) die("Writing setup failed"); diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index 60733f137e9a..77b48c7a23b4 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -86,6 +86,7 @@ struct setup_header { __u64 pref_address; __u32 init_size; __u32 handover_offset; + __u32 setup_header2_offset; } __attribute__((packed)); struct sys_desc_table { -- 2.11.0