[PATCH -v7 1/3] x86 boot: setup data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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      |    6 +++++-
 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 |   12 ++++++++++++
 include/asm-x86/e820_64.h   |    1 +
 include/asm-x86/setup_32.h  |    7 +++++++
 include/asm-x86/setup_64.h  |    2 ++
 11 files changed, 137 insertions(+), 10 deletions(-)

Index: linux-2.6/include/asm-x86/bootparam.h
===================================================================
--- linux-2.6.orig/include/asm-x86/bootparam.h	2007-10-23 10:01:35.000000000 +0800
+++ linux-2.6/include/asm-x86/bootparam.h	2007-10-23 10:48:48.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];
+};
+
 struct setup_header {
 	u8	setup_sects;
 	u16	root_flags;
@@ -46,6 +57,7 @@
 	u32	cmdline_size;
 	u32	hardware_subarch;
 	u64	hardware_subarch_data;
+	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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/boot/header.S	2007-10-23 13:51:29.000000000 +0800
@@ -119,7 +119,7 @@
 	# Part 2 of the header, from the old setup.S
 
 		.ascii	"HdrS"		# header signature
-		.word	0x0207		# header version number (>= 0x0105)
+		.word	0x0208		# header version number (>= 0x0105)
 					# or else old loadlin-1.5 will fail)
 		.globl realmode_swtch
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
@@ -219,6 +219,10 @@
 
 hardware_subarch_data:	.quad 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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/kernel/setup_64.c	2007-10-23 10:48:48.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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/kernel/setup_32.c	2007-10-23 13:51:05.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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/kernel/e820_64.c	2007-10-23 10:01:39.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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/kernel/head64.c	2007-10-23 10:01:39.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-23 10:01:35.000000000 +0800
+++ linux-2.6/include/asm-x86/e820_64.h	2007-10-23 10:01:39.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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/kernel/head_32.S	2007-10-23 10:01:39.000000000 +0800
@@ -135,6 +135,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)
 
 #ifdef CONFIG_PARAVIRT
 	cmpw $0x207, (boot_params + BP_version - __PAGE_OFFSET)
@@ -191,13 +206,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-23 10:01:35.000000000 +0800
+++ linux-2.6/arch/x86/mm/discontig_32.c	2007-10-23 10:01:39.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-23 10:01:35.000000000 +0800
+++ linux-2.6/include/asm-x86/setup_32.h	2007-10-23 10:01:39.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	0x248	/* 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-23 10:01:35.000000000 +0800
+++ linux-2.6/include/asm-x86/setup_64.h	2007-10-23 10:03: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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux