[PATCH RFC 1/2] x86/boot: Introduce the setup_header2

From: Daniel Kiper
Date: Fri May 24 2019 - 05:59:30 EST


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 <hpa@xxxxxxxxx>
Signed-off-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx>
Reviewed-by: Ross Philipson <ross.philipson@xxxxxxxxxx>
Reviewed-by: Eric Snowberg <eric.snowberg@xxxxxxxxxx>
---
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