[coreboot] r1145 - in coreboot-v3: arch/x86 arch/x86/intel/core2 device include lib mainboard/kontron/986lcd-m

svn at coreboot.org svn at coreboot.org
Wed Mar 11 17:17:37 CET 2009


Author: rminnich
Date: 2009-03-11 17:17:37 +0100 (Wed, 11 Mar 2009)
New Revision: 1145

Modified:
   coreboot-v3/arch/x86/intel/core2/init_cpus.c
   coreboot-v3/arch/x86/secondary.S
   coreboot-v3/device/pci_device.c
   coreboot-v3/device/pci_rom.c
   coreboot-v3/include/lib.h
   coreboot-v3/lib/stage2.c
   coreboot-v3/mainboard/kontron/986lcd-m/Makefile
   coreboot-v3/mainboard/kontron/986lcd-m/dts
   coreboot-v3/mainboard/kontron/986lcd-m/initram.c
Log:
last kontron commit. 

This is a potentially good pointer to where someone can take this. 

While startup was working, BSP now explodes once the AP stops, while
BSP is doing startup IPI loop send #2. The code needs to be hardened; I 
think use of the shared variables would really make it much more solid. 
This would be a good undergrad student project if someone is looking for one.

Signed-off-by: Ronald G. Minnich <rminnich at gmail.com>
Acked-by: Stefan Reinauer <stepan at coresystems.de>


Modified: coreboot-v3/arch/x86/intel/core2/init_cpus.c
===================================================================
--- coreboot-v3/arch/x86/intel/core2/init_cpus.c	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/arch/x86/intel/core2/init_cpus.c	2009-03-11 16:17:37 UTC (rev 1145)
@@ -21,7 +21,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
-#include <mainboard.h>
 #include <types.h>
 #include <lib.h>
 #include <console.h>
@@ -73,6 +72,7 @@
 	int nodes, siblings;
 	result = cpuid(1);
 	/* See how many sibling cpus we have */
+	printk(BIOS_DEBUG, "cpuid(1) ebx is %08x\n", result.ebx);
 	siblings = (result.ebx >> 16) & 0xff;
 	if (siblings < 1) {
 		siblings = 1;
@@ -204,6 +204,9 @@
 	 * Starting actual IPI sequence...
 	 */
 
+	printk(BIOS_SPEW, "Before Startup.apicid %ld\n",  apicid);
+	printk(BIOS_SPEW, "Before Startup.sb[0] %p @0 %08x\n",
+			(void *) secondary_base[0], *(u32 *) 0);
 	printk(BIOS_SPEW, "Asserting INIT.\n");
 
 	/*
@@ -321,7 +324,11 @@
 		if (send_status || accept_status)
 			break;
 	}
+	printk(BIOS_SPEW, "udelay(1000000)\n");
+	udelay(1000000);
 	printk(BIOS_SPEW, "After Startup.sb[-1] %p\n", (void *) secondary_base[-1]);
+	printk(BIOS_SPEW, "After Startup.sb[0] %p @0 %08x\n", 
+			 (void *) secondary_base[0],  *(u32 *) 0);
 	if (send_status)
 		printk(BIOS_WARNING, "APIC never delivered???\n");
 	if (accept_status)
@@ -335,13 +342,13 @@
 /* we compile the secondary start code such that this looks like a stack frame
  */
 struct stack {
+	u32 data[16384/sizeof(u32) - 7];
+	struct spinlock *start_cpu_lock;
+	struct atomic *active_cpus;
+	u32 apicid;
+	u32 index;
 	u32 post;
-	u32 index;
-	u32 apicid;
-	struct atomic *active_cpus;
-	struct spinlock *start_cpu_lock;
 	u32  callerpc;
-	u32 data[16384/sizeof(u32) - 7];
 };
 
 struct stackmem {
@@ -377,18 +384,25 @@
 	stackmem->stacks[index].post   = 0;
 	stackmem->stacks[index].active_cpus  = active_cpus;
 	stackmem->stacks[index].start_cpu_lock = start_cpu_lock;
+	printk(BIOS_SPEW, "stack[index, apicid, post, active_cpus, start_cpu_lock] = [%lx, %x, %d, %p, %p]\n", index, apicid, 0, active_cpus, start_cpu_lock);
 	/* Advertise the new stack to start_cpu */
 	printk(BIOS_SPEW, "Set stack @ %p to %p\n", &secondary_base[-1], (void *)stack_end);
 	secondary_base[-1] = stack_end;
 
 	/* Start the cpu */
 	result = lapic_start_cpu(apicid, secondary_base);
+	printk(BIOS_SPEW, "we think we started it. The stack value is 0x%p (should be 0)\n", (void *)secondary_base[-1]);
 
 	if (result) {
+		printk(BIOS_SPEW, "Spinning on post which is now 0x%x\n", 
+				stackmem->stacks[index].post);
 		result = 0;
 		/* Wait 1s or until the new the new cpu calls in */
-		for(count = 0; count < 100000 ; count++) {
-			if (stackmem->stacks[index].post) {
+		for(count = 0; count < 1000000 ; count++) {
+			printk(BIOS_SPEW, 
+				"BSP post 0x%x\n", 
+				stackmem->stacks[index].post);
+			if (stackmem->stacks[index].post >= AP_STOP_OK) {
 				result = 1;
 				break;
 			}
@@ -476,9 +490,13 @@
 	struct atomic *active_cpus,
 	struct spinlock *start_cpu_lock)
 {
+//printk(BIOS_SPEW, "secondary start\n");
+//printk(BIOS_SPEW, "[post, index, apicid,active_cpus, start_cpu_lock] = [%x, %x, %d, %p, %p]\n", post, index, apicid, active_cpus, start_cpu_lock);
 	post = AP_START;
+//printk(BIOS_SPEW, "secondary post %d\n", post);
 	atomic_inc(active_cpus);
 	post = AP_ACTIVEUP;
+//printk(BIOS_SPEW, "secondary post %d\n", post);
 	if (SERIAL_CPU_INIT && (CONFIG_MAX_PHYSICAL_CPUS > 2))
 		spin_lock(start_cpu_lock);
 	post = AP_LOCKED;
@@ -531,6 +549,104 @@
 	printk(BIOS_DEBUG, "All AP CPUs stopped\n");
 }
 
+/* this should be a library call. */
+static void fill_processor_name(char *processor_name, int len)
+{
+	struct cpuid_result regs;
+	char temp_processor_name[49];
+	char *processor_name_start;
+	unsigned int *name_as_ints = (unsigned int *)temp_processor_name;
+	int i;
+
+	if (len > sizeof(temp_processor_name))
+		len = sizeof(temp_processor_name);
+
+	for (i=0; i<3; i++) {
+		regs = cpuid(0x80000002 + i);
+		name_as_ints[i*4 + 0] = regs.eax;
+		name_as_ints[i*4 + 1] = regs.ebx;
+		name_as_ints[i*4 + 2] = regs.ecx;
+		name_as_ints[i*4 + 3] = regs.edx;
+	}
+
+	temp_processor_name[48] = 0;
+
+	/* Skip leading spaces */
+	processor_name_start = temp_processor_name;
+	while (*processor_name_start == ' ') 
+		processor_name_start++;
+
+	memset(processor_name, 0, 49);
+	memcpy(processor_name, processor_name_start, len);
+}
+
+#define IA32_FEATURE_CONTROL 0x003a
+
+#define CPUID_VMX (1 << 5)
+#define CPUID_SMX (1 << 6)
+static void enable_vmx(void)
+{
+	struct cpuid_result regs;
+	struct msr msr;
+
+	msr = rdmsr(IA32_FEATURE_CONTROL);
+
+	if (msr.lo & (1 << 0)) {
+		/* VMX locked. If we set it again we get an illegal
+		 * instruction
+		 */
+		return;
+	}
+
+	regs = cpuid(1);
+	if (regs.ecx & CPUID_VMX) {
+		msr.lo |= (1 << 2);
+		if (regs.ecx & CPUID_SMX)
+			msr.lo |= (1 << 1);
+	}
+
+	wrmsr(IA32_FEATURE_CONTROL, msr);
+
+	msr.lo |= (1 << 0); /* Set lock bit */
+
+	wrmsr(IA32_FEATURE_CONTROL, msr);
+}
+
+#define PMG_CST_CONFIG_CONTROL	0xe2
+static void configure_c_states(void)
+{
+	struct msr msr;
+
+	msr = rdmsr(PMG_CST_CONFIG_CONTROL);
+	msr.lo &= ~(1 << 9); // Issue a  single stop grant cycle upon stpclk
+
+	// TODO Do we want Deep C4 and  Dynamic L2 shrinking?
+	wrmsr(PMG_CST_CONFIG_CONTROL, msr);
+}
+
+#define IA32_MISC_ENABLE	0x1a0
+static void configure_misc(void)
+{
+	struct msr msr;
+
+	msr = rdmsr(IA32_MISC_ENABLE);
+	msr.lo |= (1 << 3); 	/* TM1 enable */
+	msr.lo |= (1 << 13);	/* TM2 enable */
+	msr.lo |= (1 << 17);	/* Bidirectional PROCHOT# */
+
+	msr.lo |= (1 << 10);	/* FERR# multiplexing */
+
+	// TODO: Only if  IA32_PLATFORM_ID[17] = 0 and IA32_PLATFORM_ID[50] = 1
+	msr.lo |= (1 << 16);	/* Enhanced SpeedStep Enable */
+
+	// TODO Do we want Deep C4 and  Dynamic L2 shrinking?
+	wrmsr(IA32_MISC_ENABLE, msr);
+
+	msr.lo |= (1 << 20);	/* Lock Enhanced SpeedStep Enable */
+	wrmsr(IA32_MISC_ENABLE, msr);
+}
+
+
 /**
  * Init all the CPUs. 
  * this was unnecessarily tricky in v2 (surprise!)
@@ -559,12 +675,13 @@
  * @param sysinfo The sys_info pointer
  * @returns the BSP APIC ID
  */
-unsigned int init_cpus(unsigned cpu_init_detectedx,
+unsigned int cpu_phase1(unsigned cpu_init_detectedx,
 			struct sys_info *sysinfo)
 {
 	/* Number of cpus that are currently running in coreboot */
 	struct atomic active_cpus;
 	u32 *secondary_base;
+	char processor_name[49];
 
 	/* every AP gets a stack. The stacks are linear and start at 0x100000 */
 	struct spinlock start_cpu_lock;
@@ -579,10 +696,55 @@
 	// why here? In case some day we can start core1 in amd_sibling_init
 	secondary_base = copy_secondary_start_to_1m_below(); 
 
+	/* Turn on caching if we haven't already */
+	enable_cache();
+
+	/* Update the microcode *
+	intel_update_microcode(microcode_updates);
+	 * needs to be rewritten to use LAR, not code include hacks
+	 */
+
+	/* Print processor name */
+	fill_processor_name(processor_name, sizeof(processor_name));
+	printk(BIOS_INFO, "CPU: %s.\n", processor_name);
+
+#ifdef CONFIG_USBDEBUG_DIRECT
+	// Is this caution really needed?
+	if(!ehci_debug_addr) 
+		ehci_debug_addr = get_ehci_debug();
+	set_ehci_debug(0);
+#endif
+
+	/* Setup MTRRs */
+	x86_setup_mtrrs(36);
+	x86_mtrr_check();
+
+#ifdef CONFIG_USBDEBUG_DIRECT
+	set_ehci_debug(ehci_debug_addr);
+#endif
+
+	/* Enable the local cpu apics */
+	/* do we need this in v3? not sure
+	setup_lapic();
+	 */
+
+	/* Enable virtualization */
+	enable_vmx();
+
+	/* Configure C States */
+	configure_c_states();
+
+	/* Configure Enhanced SpeedStep and Thermal Sensors */
+	configure_misc();
+
+	/* TODO: PIC thermal sensor control */
+
+
 #ifdef CONFIG_SMM
 	smm_init();
 #endif
 
+	/* Start up my cpu siblings */
 	if (! SERIAL_CPU_INIT)
 	/* start all aps at first, so we can init ECC all together */
     	    start_other_cpus(get_nodes(), &active_cpus, &start_cpu_lock, &last_cpu_index, secondary_base);

Modified: coreboot-v3/arch/x86/secondary.S
===================================================================
--- coreboot-v3/arch/x86/secondary.S	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/arch/x86/secondary.S	2009-03-11 16:17:37 UTC (rev 1145)
@@ -21,6 +21,17 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  */
+
+/* POST_ZERO writes a POST_CODE at zero. Note that once we load %ds from %cs, "0" is at the start of this function!
+ * This is debug only; you can't use it on systems with more than one core. It should be left off by default. 
+ */
+#define NO_POST_ZERO
+
+#ifdef NO_POST_ZERO
+#define POST_ZERO(x)
+#else
+#define POST_ZERO(x) movw	x, 0
+#endif
 	.text
 	.globl _secondary_start, _secondary_start_end
 _secondary_start:
@@ -28,58 +39,57 @@
 	.code16
 	.balign 4096
 	cli
-	movw	$0xdead, 0
-	movw	$0xbeef, 2
+	POST_ZERO($0xdead)
 	xorl	%eax, %eax
 	movl	%eax, %cr3    /* Invalidate TLB*/
 	/* On hyper threaded cpus, invalidating the cache here is
 	 * very very bad.  Don't.
 	 */
-	movw	$0, 0
+	POST_ZERO($0)
 	movl	$1b, %ebx
-	movw	$1, 0
-	movw	$2, 0
+	POST_ZERO($1)
+	POST_ZERO($2)
 
 	/* setup the data segment */
 	movw	%cs, %ax
 	movw	%ax, 2
-	movw	$3, 0
+	POST_ZERO($3)
 	movw	%ax, %ds
-	movw	$4, 0
+	POST_ZERO($4)
 	/* past this point, "0" means ds:0, i.e. cs:0, or the 
 	 * segment part of the address. 
 	 */
 
 	data32	lgdt	gdtaddr  - _secondary_start
 //	data32 lgdt %cs:gdtptr
-	movw	$5, 0
+	POST_ZERO($5)
 
 	movl	%cr0, %eax
-	movw	$6, 0
+	POST_ZERO($6)
 	andl	$0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
-	movw	$7, 0
+	POST_ZERO($7)
 	orl	$0x60000001, %eax /* CD, NW, PE = 1 */
-	movw	$8, 0
+	POST_ZERO($8)
 	movl	%eax, %cr0
-	movw	$9, 0
-	hlt
-	/* tested to this point but not past it */
+	POST_ZERO($9)
 
-	/* I am pretty sure this just jumps back into 
-	 * ROM; it's an abs jump
-	 */
-	data32 ljmp	$0x10, $secondary32
-	movw	$0xa, 0
+	/* This jump pops us into 32-bit protected mode */
+	data32 ljmp	$0x8, $secondary32
+	POST_ZERO($0xa)
 1:	
 	.code32
 secondary32:
-	hlt
-	movw	$0x18, %ax
+	POST_ZERO($0x11)
+	movw	$0x10, %ax
 	movw	%ax, %ds
+	/* having a post here for testing is useful. 
+	 *If ds is bad for some reason, we'll reboot */
+	POST_ZERO($0x13)
 	movw	%ax, %es
 	movw	%ax, %ss
 	movw	%ax, %fs
 	movw	%ax, %gs
+	POST_ZERO($0x17)
 
 	/* Load the Interrupt descriptor table */
 	lidt	idtarg
@@ -87,6 +97,8 @@
 	/* Set the stack pointer */
 	movl	-4(%ebx),%esp
 	movl	$0, -4(%ebx)
+	/* tested to this point but not past it */
+	/* AP sees the stack value set to 0 */
 
 	call	secondary_cpu_init
 1:	hlt
@@ -108,14 +120,6 @@
 	/* selgdt 0x10, flat data segment */
 	.word	0xffff, 0x0000
 	.byte	0x00, 0x93, 0xcf, 0x00
-
-	/* selgdt 0x18, flat code segment for CAR */
-	.word	0xffff, 0x0000
-	.byte	0x00, 0x9b, 0xcf, 0x00
-
-	/* selgdt 0x20, flat data segment for CAR */
-	.word	0xffff, 0x0000
-	.byte	0x00, 0x93, 0xcf, 0x00
 gdt_end:
 
 

Modified: coreboot-v3/device/pci_device.c
===================================================================
--- coreboot-v3/device/pci_device.c	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/device/pci_device.c	2009-03-11 16:17:37 UTC (rev 1145)
@@ -1304,7 +1304,8 @@
 	pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
 	pci_write_config16(dev, PCI_COMMAND, cr);
 
-	printk(BIOS_DEBUG, "%s DONE\n", __func__);
+	printk(BIOS_DEBUG, "%s DONE: [%x, %x, %x]\n", __func__, 
+		dev->bus->secondary, bus->secondary, bus->subordinate);
 	printk(BIOS_SPEW, "%s returns max %d\n", __func__, max);
 	return max;
 }

Modified: coreboot-v3/device/pci_rom.c
===================================================================
--- coreboot-v3/device/pci_rom.c	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/device/pci_rom.c	2009-03-11 16:17:37 UTC (rev 1145)
@@ -47,7 +47,7 @@
 		init_archive(&archive);
 		sprintf(pcifile, "pci%04x,%04x.rom", dev->id.pci.vendor,
 			dev->id.pci.device);
-
+		printk(BIOS_DEBUG, "pci_rom_probe: search for %s\n", pcifile);
 		ret = find_file(&archive, pcifile, &result);
 		if (ret) {
 			printk(BIOS_INFO, "No option rom for onboard device.\n");

Modified: coreboot-v3/include/lib.h
===================================================================
--- coreboot-v3/include/lib.h	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/include/lib.h	2009-03-11 16:17:37 UTC (rev 1145)
@@ -52,4 +52,10 @@
 /* Optional ramtest. */
 int ram_check(unsigned long start, unsigned long stop);
 
+/* required: a way to tell if this is a:
+ * power-on/reset (coldboot) OR 
+ * coreboot has initiated a reset (warmboot). 
+ */
+int is_coldboot(void);
+
 #endif /* LIB_H */

Modified: coreboot-v3/lib/stage2.c
===================================================================
--- coreboot-v3/lib/stage2.c	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/lib/stage2.c	2009-03-11 16:17:37 UTC (rev 1145)
@@ -27,8 +27,40 @@
 #include <console.h>
 #include <device/device.h>
 #include <tables.h>
+#include <globalvars.h>
+#include <lib.h>
 
 /**
+ * CPU init code which runs BEFORE any stage2 dev_phase1 is run. 
+ * This code might, for example, init ECC on all cores. 
+ *
+ * @param coldboot Is this a power-on coldboot 
+ * @param sysinfo sysinfo pointer
+ * @returns 0 on success; error number otherwise
+ */
+unsigned int __attribute__((weak)) cpu_phase1(unsigned int coldboot,
+			struct sys_info *sysinfo)
+{
+	printk(BIOS_SPEW, "cpu_phase1: %s: nothing to do.\n", coldboot? "Coldboot" : "Warmboot");
+	return 0;
+}
+
+/**
+ * CPU init code which runs AFTER ALL stage2 dev_phases are run. 
+ * This code might, for example, install an SMI handler
+ *
+ * @param coldboot Is this a power-on coldboot 
+ * @param sysinfo sysinfo pointer
+ * @returns 0 on success; error number otherwise
+ */
+unsigned int __attribute__((weak)) cpu_phase2(unsigned int coldboot,
+			struct sys_info *sysinfo)
+{
+	printk(BIOS_SPEW, "cpu_phase2: %s: nothing to do.\n", coldboot? "Coldboot" : "Warmboot");
+	return 0;
+}
+
+/**
  * Main function of the DRAM part of coreboot.
  *
  * Coreboot is divided into pre-DRAM part and DRAM part. The stages before
@@ -44,8 +76,11 @@
 void *stage2(void)
 {
 	void *mbi;
-
+	struct sys_info *sysinfo;
+	struct global_vars *global_vars(void);
 	post_code(POST_STAGE2_BEGIN);
+	sysinfo = &(global_vars()->sys_info);
+	cpu_phase1(is_coldboot(), sysinfo);
 	dev_init();
 
 	/* Phase 1 was console init and making printk work. Both functions are
@@ -85,6 +120,8 @@
 	dev_phase6();
 	show_all_devs(BIOS_DEBUG, "After phase 6.");
 
+	cpu_phase2(is_coldboot(), sysinfo);
+
 	/* Write tables to pass information to the payloads. */
 	post_code(POST_STAGE2_WRITE_TABLES);
 	mbi = write_tables();

Modified: coreboot-v3/mainboard/kontron/986lcd-m/Makefile
===================================================================
--- coreboot-v3/mainboard/kontron/986lcd-m/Makefile	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/mainboard/kontron/986lcd-m/Makefile	2009-03-11 16:17:37 UTC (rev 1145)
@@ -23,18 +23,17 @@
 STAGE0_MAINBOARD_SRC := $(src)/lib/clog2.c \
 			$(src)/mainboard/$(MAINBOARDDIR)/stage1.c \
 			$(src)/mainboard/$(MAINBOARDDIR)/stage1_debug.c \
+			$(src)/northbridge/intel/i945//reset_test.c \
 
 INITRAM_SRC= $(src)/mainboard/$(MAINBOARDDIR)/initram.c \
-			$(src)/northbridge/intel/i945//reset_test.c \
-			$(src)/arch/x86/intel/core2/init_cpus.c \
 
 INITRAM_OBJ = \
-			$(obj)/arch/x86/secondary.o \
 
-STAGE2_CHIPSET_SRC=
+STAGE2_CHIPSET_SRC= \
+			$(src)/northbridge/intel/i945//reset_test.c \
+			$(src)/arch/x86/intel/core2/init_cpus.c \
+			$(src)/arch/x86/secondary.o \
 
-STAGE2_MAINBOARD_SRC = 
-
 $(obj)/coreboot.vpd:
 	$(Q)printf "  BUILD   DUMMY VPD\n"
 	$(Q)dd if=/dev/zero of=$(obj)/coreboot.vpd bs=256 count=1 $(SILENT)

Modified: coreboot-v3/mainboard/kontron/986lcd-m/dts
===================================================================
--- coreboot-v3/mainboard/kontron/986lcd-m/dts	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/mainboard/kontron/986lcd-m/dts	2009-03-11 16:17:37 UTC (rev 1145)
@@ -152,7 +152,6 @@
 			disabled;
 		};
 		pci at 2,0 { /* Onboard VGA. */
-			rom_address = "0xfff00000"; /* Shouldn't this be a lar path? */
 		};
 		pci at 2,1 { /* Display controller. */
 		};
@@ -169,8 +168,8 @@
 			/config/("southbridge/intel/i82801gx/pcie3.dts");
 		};
 		pci at 1c,3{ disabled; }; /* PCIe port 4 */
-		pci at 1c,4{ disabled; }; /* PCIe port 5 */
-		pci at 1c,5{ disabled; }; /* PCIe port 6 */
+		pci at 1c,4{ /config/("southbridge/intel/i82801gx/pcie5.dts"); }; /* PCIe port 5 */
+		pci at 1c,5{ /config/("southbridge/intel/i82801gx/pcie6.dts"); }; /* PCIe port 6 */
 		pci at 1d,0{
 			/config/("southbridge/intel/i82801gx/usb1.dts");
 		};

Modified: coreboot-v3/mainboard/kontron/986lcd-m/initram.c
===================================================================
--- coreboot-v3/mainboard/kontron/986lcd-m/initram.c	2009-03-05 21:28:56 UTC (rev 1144)
+++ coreboot-v3/mainboard/kontron/986lcd-m/initram.c	2009-03-11 16:17:37 UTC (rev 1145)
@@ -226,8 +226,5 @@
 	}
 #endif
 	MCHBAR16(SSKPD) = 0xCAFE;
-
-	init_cpus(boot_mode, sysinfo);
-	
 	return 0;
 }





More information about the coreboot mailing list