i386/x86_64 boot: setup data
PATCH 1/2 i386/x86_64 boot: setup data
This patch add a field of 64-bit physical pointer to NULL terminated single linked list of struct setup_data to real-mode kernel header. This is used as a more extensible boot parameters passing mechanism.
This patch has been tested against 2.6.23-rc6-mm1 kernel on x86_64. It is based on the proposal of Peter Anvin.
Known Issues:
1. Where is safe to place the linked list of setup_data? Because the length of the linked list of setup_data is variable, it can not be copied into BSS segment of kernel as that of "zero page". We must find a safe place for it, where it will not be overwritten by kernel during booting up. The i386 kernel will overwrite some pages after _end. The x86_64 kernel will overwrite some pages from 0x1000 on.
ChangeLog:
-- v2 --
- Increase the boot protocol version number.
- Check version number before parsing setup_data.
---
arch/i386/Kconfig | 3 --- arch/i386/boot/header.S | 8 +++++++- arch/i386/kernel/setup.c | 22 ++++++++++++++++++++++ arch/x86_64/kernel/setup.c | 21 +++++++++++++++++++++ include/asm-i386/bootparam.h | 15 +++++++++++++++ include/asm-i386/io.h | 7 +++++++ 6 files changed, 72 insertions(+), 4 deletions(-)
include/asm-i386/bootparam.h +15 -0
@@ -9,6 +9,17 @@#include <asm/ist.h> #include <video/edid.h> +/* setup data types */ +#define SETUP_NONE 0 + +/* extensible setup data list node */ +struct setup_data { +u64 next; +u32 type; +u32 len; +u8 data[0 ]; +} __attribute__((packed)); +struct setup_header {u8 setup_sects;u16 root_flags;
@@ -41,6 +52,10 @@u32 initrd_addr_max;u32 kernel_alignment;u8 relocatable_kernel; +u8 _pad2[3 ]; +u32 cmdline_size; +u32 _pad3; +u64 setup_data; } __attribute__((packed));struct sys_desc_table {
arch/i386/boot/header.S +7 -1
@@ -119,7 +119,7 @@ # Part 2 of the header, from the old setup.S .ascii "HdrS" # header signature - .word 0x0206 # header version number (>= 0x0105) + .word 0x0207 # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) .globl realmode_swtch realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
@@ -214,6 +214,12 @@ #added with boot protocol #version 2.06 +pad4: .long 0 + +setup_data: .quad 0 # 64-bit physical pointer to + # single linked list of + # struct setup_data + # End of setup header ##################################################### .section ".inittext", "ax"
arch/x86_64/kernel/setup.c +21 -0
@@ -221,6 +221,25 @@ ebda_size =64 *1024 ; } +void __init parse_setup_data (void ) +{ +struct setup_data *setup_data; +unsigned long pa_setup_data; + +if (boot_params.hdr.version <0x0207 ) +return ; + pa_setup_data = boot_params.hdr.setup_data; +while (pa_setup_data) { + setup_data =early_ioremap (pa_setup_data,PAGE_SIZE ); +switch (setup_data->type) { +default : +break ; + } + pa_setup_data = setup_data->next; +early_iounmap (setup_data,PAGE_SIZE ); + } +} +void __init setup_arch (char **cmdline_p) {printk (KERN_INFO "Command line: %s\n" , boot_command_line);
@@ -256,6 +275,8 @@strlcpy (command_line, boot_command_line,COMMAND_LINE_SIZE ); *cmdline_p = command_line; +parse_setup_data (); +parse_early_param ();finish_e820_parsing ();
arch/i386/kernel/setup.c +22 -0
@@ -496,6 +496,25 @@return machine_specific_memory_setup (); } +void __init parse_setup_data (void ) +{ +struct setup_data *setup_data; +unsigned long pa_setup_data, pa_next; + +if (boot_params.hdr.version <0x0207 ) +return ; + pa_setup_data = boot_params.hdr.setup_data; +while (pa_setup_data) { + setup_data =boot_ioremap (pa_setup_data,PAGE_SIZE ); + pa_next = setup_data->next; +switch (setup_data->type) { +default : +break ; + } + pa_setup_data = pa_next; + } +} +/* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures
@@ -544,6 +563,9 @@ rd_prompt = ((boot_params.hdr.ram_size &RAMDISK_PROMPT_FLAG ) !=0 ); rd_doload = ((boot_params.hdr.ram_size &RAMDISK_LOAD_FLAG ) !=0 );#endif + +parse_setup_data (); + ARCH_SETUP if (efi_enabled) efi_init();
include/asm-i386/io.h +7 -0
@@ -126,6 +126,13 @@extern void iounmap (volatile void __iomem *addr);/* +* boot_ioremap is for temporary early boot-time mappings, before +* paging_init(), when the boot-time page tables are still in use. +* The mapping is currently limited to at most 4 pages. +*/ +extern void *boot_ioremap (unsigned long offset,unsigned long size); + +/* * bt_ioremap() and bt_iounmap() are for temporary early boot-time * mappings, before the real ioremap() is functional. * A boot-time mapping is currently limited to at most 16 pages.
arch/i386/Kconfig +0 -3
@@ -773,11 +773,8 @@ The default yes will allow the kernel to do irq load balancing. Saying no will keep the kernel from doing irq load balancing. -# turning this on wastes a bunch of space. -# Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) default y config SECCOMP