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.
Signed-off-by: Huang Ying <[EMAIL PROTECTED]> --- arch/x86/boot/header.S | 8 +++++++- arch/x86/kernel/e820_64.c | 6 +++--- arch/x86/kernel/head64.c | 26 ++++++++++++++++++++++++++ arch/x86/kernel/head_32.S | 37 ++++++++++++++++++++++++++++++++++++- arch/x86/kernel/setup_32.c | 25 +++++++++++++++++++++++-- arch/x86/kernel/setup_64.c | 22 ++++++++++++++++++++-- arch/x86/mm/discontig_32.c | 3 ++- include/asm-x86/bootparam.h | 15 +++++++++++++++ include/asm-x86/e820_64.h | 1 + include/asm-x86/setup_32.h | 7 +++++++ include/asm-x86/setup_64.h | 2 ++ 11 files changed, 142 insertions(+), 10 deletions(-) Index: linux-2.6/include/asm-x86/bootparam.h =================================================================== --- linux-2.6.orig/include/asm-x86/bootparam.h 2007-10-18 17:11:13.000000000 +0800 +++ linux-2.6/include/asm-x86/bootparam.h 2007-10-22 14:09:25.000000000 +0800 @@ -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 { Index: linux-2.6/arch/x86/boot/header.S =================================================================== --- linux-2.6.orig/arch/x86/boot/header.S 2007-10-15 09:49:15.000000000 +0800 +++ linux-2.6/arch/x86/boot/header.S 2007-10-22 14:09:25.000000000 +0800 @@ -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" Index: linux-2.6/arch/x86/kernel/setup_64.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/setup_64.c 2007-10-22 09:18:08.000000000 +0800 +++ linux-2.6/arch/x86/kernel/setup_64.c 2007-10-22 14:09:25.000000000 +0800 @@ -247,6 +247,22 @@ ebda_size = 64*1024; } +static void __init parse_setup_data(void) +{ + struct setup_data *data; + + if (boot_params.hdr.version < 0x0207) + return; + for (data = __va(boot_params.hdr.setup_data); + data != __va(0); + data = __va(data->next)) { + switch (data->type) { + default: + break; + } + } +} + void __init setup_arch(char **cmdline_p) { printk(KERN_INFO "Command line: %s\n", boot_command_line); @@ -282,6 +298,8 @@ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; + parse_setup_data(); + parse_early_param(); finish_e820_parsing(); @@ -340,9 +358,9 @@ reserve_bootmem_generic(table_start << PAGE_SHIFT, (table_end - table_start) << PAGE_SHIFT); - /* reserve kernel */ + /* reserve kernel and setup data */ reserve_bootmem_generic(__pa_symbol(&_text), - __pa_symbol(&_end) - __pa_symbol(&_text)); + setup_data_end - __pa_symbol(&_text)); /* * reserve physical page 0 - it's a special BIOS page on many boxes, Index: linux-2.6/arch/x86/kernel/setup_32.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/setup_32.c 2007-10-22 09:18:08.000000000 +0800 +++ linux-2.6/arch/x86/kernel/setup_32.c 2007-10-22 14:09:25.000000000 +0800 @@ -66,6 +66,8 @@ address, and must not be in the .bss segment! */ unsigned long init_pg_tables_end __initdata = ~0UL; +unsigned long setup_data_len __initdata; + int disable_pse __devinitdata = 0; /* @@ -327,7 +329,7 @@ * partially used pages are not usable - thus * we are rounding upwards: */ - min_low_pfn = PFN_UP(init_pg_tables_end); + min_low_pfn = PFN_UP(init_pg_tables_end+setup_data_len); find_max_pfn(); @@ -532,6 +534,22 @@ return machine_specific_memory_setup(); } +static void __init parse_setup_data(void) +{ + struct setup_data *data; + + if (boot_params.hdr.version < 0x0207) + return; + for (data = __va(boot_params.hdr.setup_data); + data != __va(0); + data = __va(data->next)) { + switch (data->type) { + default: + break; + } + } +} + /* * 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 @@ -579,6 +597,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(); @@ -594,7 +615,7 @@ init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; - init_mm.brk = init_pg_tables_end + PAGE_OFFSET; + init_mm.brk = init_pg_tables_end + setup_data_len + PAGE_OFFSET; code_resource.start = virt_to_phys(_text); code_resource.end = virt_to_phys(_etext)-1; Index: linux-2.6/arch/x86/kernel/e820_64.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/e820_64.c 2007-10-22 09:18:08.000000000 +0800 +++ linux-2.6/arch/x86/kernel/e820_64.c 2007-10-22 14:09:25.000000000 +0800 @@ -79,9 +79,9 @@ } } #endif - /* kernel code */ - if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) { - *addrp = PAGE_ALIGN(__pa_symbol(&_end)); + /* kernel code and setup data */ + if (last >= __pa_symbol(&_text) && addr < setup_data_end) { + *addrp = PAGE_ALIGN(setup_data_end); return 1; } Index: linux-2.6/arch/x86/kernel/head64.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/head64.c 2007-10-22 09:18:08.000000000 +0800 +++ linux-2.6/arch/x86/kernel/head64.c 2007-10-22 14:09:25.000000000 +0800 @@ -19,6 +19,9 @@ #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/sections.h> +#include <asm/io.h> + +unsigned long __initdata setup_data_end; static void __init zap_identity_mappings(void) { @@ -38,12 +41,35 @@ static void __init copy_bootdata(char *real_mode_data) { char * command_line; + void *sdata_dst; + struct setup_data *sdata; + u64 *ppa_next; + unsigned long sdata_len; memcpy(&boot_params, real_mode_data, sizeof boot_params); if (boot_params.hdr.cmd_line_ptr) { command_line = __va(boot_params.hdr.cmd_line_ptr); memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); } + +#define SETUP_DATA_ALIGN(addr) \ + (((unsigned long)(addr)+(SETUP_DATA_ALIGN_SIZE-1))& \ + ~(SETUP_DATA_ALIGN_SIZE-1)) + + sdata_dst = __va(SETUP_DATA_ALIGN(__pa_symbol(&_end))); + ppa_next = &boot_params.hdr.setup_data; + while (*ppa_next) { + sdata = early_ioremap(*ppa_next, sizeof(*sdata)); + sdata_len = sizeof(*sdata) + sdata->len; + early_iounmap(sdata, sizeof(*sdata)); + sdata = early_ioremap(*ppa_next, sdata_len); + memcpy(sdata_dst, sdata, sdata_len); + early_iounmap(sdata, sdata_len); + *ppa_next = __pa(sdata_dst); + ppa_next = &((struct setup_data *)sdata_dst)->next; + sdata_dst = (void *)SETUP_DATA_ALIGN(sdata_dst+sdata_len); + } + setup_data_end = __pa(sdata_dst); } void __init x86_64_start_kernel(char * real_mode_data) Index: linux-2.6/include/asm-x86/e820_64.h =================================================================== --- linux-2.6.orig/include/asm-x86/e820_64.h 2007-10-15 09:49:20.000000000 +0800 +++ linux-2.6/include/asm-x86/e820_64.h 2007-10-22 14:09:25.000000000 +0800 @@ -56,6 +56,7 @@ extern unsigned ebda_addr, ebda_size; extern unsigned long nodemap_addr, nodemap_size; +extern unsigned long setup_data_end; #endif/*!__ASSEMBLY__*/ #endif/*__E820_HEADER*/ Index: linux-2.6/arch/x86/kernel/head_32.S =================================================================== --- linux-2.6.orig/arch/x86/kernel/head_32.S 2007-10-18 17:11:11.000000000 +0800 +++ linux-2.6/arch/x86/kernel/head_32.S 2007-10-22 14:09:25.000000000 +0800 @@ -127,6 +127,21 @@ rep movsl 1: + movl boot_params - __PAGE_OFFSET + SETUP_DATA_POINTER,%ebp + xorl %ecx,%ecx +2: + andl %ebp,%ebp + jz 1f + movl $(SETUP_DATA_HEADER_LEN+SETUP_DATA_ALIGN_SIZE-1),%eax + addl (SETUP_DATA_LEN)(%ebp),%eax + andl $~(SETUP_DATA_ALIGN_SIZE-1),%eax + addl %eax, %ecx + movl SETUP_DATA_NEXT(%ebp),%ebp + jmp 2b +1: + addl $(PAGE_SIZE_asm-1),%ecx + andl $~(PAGE_SIZE_asm-1),%ecx + movl %ecx,(setup_data_len - __PAGE_OFFSET) /* * Initialize page tables. This creates a PDE and a set of page @@ -153,13 +168,33 @@ stosl addl $0x1000,%eax loop 11b - /* End condition: we must map up to and including INIT_MAP_BEYOND_END */ + /* End condition: we must map up to and including INIT_MAP_BEYOND_END + setup_data_len */ /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */ leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp + addl (setup_data_len - __PAGE_OFFSET),%ebp cmpl %ebp,%eax jb 10b movl %edi,(init_pg_tables_end - __PAGE_OFFSET) + /* Copy setup data */ + leal (boot_params - __PAGE_OFFSET + SETUP_DATA_POINTER),%ebx +2: + movl (%ebx),%ebp + andl %ebp,%ebp + jz 1f + movl $SETUP_DATA_HEADER_LEN,%ecx + addl SETUP_DATA_LEN(%ebp),%ecx + addl $(SETUP_DATA_ALIGN_SIZE-1),%edi + andl $~(SETUP_DATA_ALIGN_SIZE-1),%edi + movl %edi,(%ebx) + movl %ebp,%esi + rep + movsb + movl (%ebx),%ebx + leal SETUP_DATA_NEXT(%ebx),%ebx + jmp 2b +1: + xorl %ebx,%ebx /* This is the boot CPU (BSP) */ jmp 3f /* Index: linux-2.6/arch/x86/mm/discontig_32.c =================================================================== --- linux-2.6.orig/arch/x86/mm/discontig_32.c 2007-10-22 09:18:09.000000000 +0800 +++ linux-2.6/arch/x86/mm/discontig_32.c 2007-10-22 14:09:25.000000000 +0800 @@ -282,7 +282,8 @@ kva_pages = calculate_numa_remap_pages(); /* partially used pages are not usable - thus round upwards */ - system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end); + system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end + + setup_data_len); kva_start_pfn = find_max_low_pfn() - kva_pages; Index: linux-2.6/include/asm-x86/setup_32.h =================================================================== --- linux-2.6.orig/include/asm-x86/setup_32.h 2007-10-18 17:11:13.000000000 +0800 +++ linux-2.6/include/asm-x86/setup_32.h 2007-10-22 14:09:25.000000000 +0800 @@ -25,6 +25,13 @@ #define OLD_CL_OFFSET 0x90022 #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ +#define SETUP_DATA_POINTER 0x240 /* Relative to real mode data */ + +#define SETUP_DATA_NEXT 0x0 +#define SETUP_DATA_LEN 0xc +#define SETUP_DATA_HEADER_LEN 0x10 +#define SETUP_DATA_ALIGN_SIZE 0x8 + #ifndef __ASSEMBLY__ #include <asm/bootparam.h> Index: linux-2.6/include/asm-x86/setup_64.h =================================================================== --- linux-2.6.orig/include/asm-x86/setup_64.h 2007-10-18 17:11:13.000000000 +0800 +++ linux-2.6/include/asm-x86/setup_64.h 2007-10-22 14:09:25.000000000 +0800 @@ -4,7 +4,9 @@ #define COMMAND_LINE_SIZE 2048 #ifdef __KERNEL__ +#include <linux/const.h> +#define SETUP_DATA_ALIGN_SIZE __AC(0x8,UL) #ifndef __ASSEMBLY__ #include <asm/bootparam.h> - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/