Skip to content

RFC i386/x86_64 boot: 32-bit boot protocol

Huang, Ying lkml 1 version In review

Get series with b4
b4 am [email protected]

Versions newest first

  1. v1 RFC Latest2 patches 9 repliesIn review

Patches in v1 No applies recorded yet

#Subject and filesSizeRepliesApplied
1/2i386/x86_64 boot: setup dataarch/i386/Kconfig arch/i386/boot/header.S arch/i386/kernel/setup.c +3 more+67 -32 replies
2/2i386/x86_64 boot: document for 32 bit boot protocolDocumentation/i386/boot.txt+104 -14 replies

Reviews trailers per patch

No Reviewed-by, Acked-by or Tested-by trailers for v1 yet.

Read the v1 thread

Cover letter [RFC -mm 0/2] i386/x86_64 boot: 32-bit boot protocol

For machine with some new BIOS other than legacy BIOS, such as EFI, LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel based on legacy BIOS can not be used, so a 32-bit boot protocol need to be defined.

This patchset defines a 32-bit boot protocol for i386 and x86_64. A linked list based boot parameters pass mechanism is also added to improve the extensibility.

The patchset has been tested against 2.6.23-rc4-mm1 kernel on x86_64.

This patchset 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.

EFI64 runtime service is the first user of 32-bit boot protocol and boot parameters passing mechanism. To demonstrate their usage, the EFI64 runtime service patch is also appended with the mail.

Best Regards,
Huang Ying

---

 Documentation/i386/boot.txt            |   15 
 Documentation/x86_64/boot-options.txt  |   12 
 arch/x86_64/Kconfig                    |   11 
 arch/x86_64/kernel/Makefile            |    1 
 arch/x86_64/kernel/efi.c               |  597 +++++++++++++++++++++++++++++++++
 arch/x86_64/kernel/efi_callwrap.S      |   69 +++
 arch/x86_64/kernel/reboot.c            |   20 -
 arch/x86_64/kernel/setup.c             |   14 
 arch/x86_64/kernel/time.c              |   48 +-
 include/asm-i386/bootparam.h           |   10 
 include/asm-x86_64/efi.h               |   18 
 include/asm-x86_64/eficallwrap.h       |   33 +
 include/asm-x86_64/emergency-restart.h |    9 
 include/asm-x86_64/fixmap.h            |    3 
 include/asm-x86_64/time.h              |    7 
 15 files changed, 842 insertions(+), 25 deletions(-)
include/asm-x86_64/eficallwrap.h new file +33 -0
Index: linux-2.6.23-rc4/include/asm-x86_64/eficallwrap.h
===================================================================
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2007 Intel Corp
+ *	Bibo Mao <[email protected]>
+ *	Huang Ying <[email protected]>
+ *
+ *  Function calling ABI conversion from SYSV to Windows for x86_64
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_X86_64_EFICALLWRAP_H
+#define __ASM_X86_64_EFICALLWRAP_H
+
+extern efi_status_t lin2win0(void *fp);
+extern efi_status_t lin2win1(void *fp, u64 arg1);
+extern efi_status_t lin2win2(void *fp, u64 arg1, u64 arg2);
+extern efi_status_t lin2win3(void *fp, u64 arg1, u64 arg2, u64 arg3);
+extern efi_status_t lin2win4(void *fp, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+extern efi_status_t lin2win5(void *fp, u64 arg1, u64 arg2, u64 arg3,
+			     u64 arg4, u64 arg5);
+extern efi_status_t lin2win6(void *fp, u64 arg1, u64 arg2, u64 arg3,
+			     u64 arg4, u64 arg5, u64 arg6);
+
+#endif
arch/x86_64/kernel/efi.c new file +597 -0

597 lines not on this page · raw message

arch/x86_64/kernel/efi_callwrap.S new file +69 -0

69 lines not on this page · raw message

arch/x86_64/kernel/setup.c +13 -1
Index: linux-2.6.23-rc4/arch/x86_64/kernel/setup.c
===================================================================
@@ -44,6 +44,7 @@
 #include <linux/dmi.h>
 #include <linux/dma-mapping.h>
 #include <linux/ctype.h>
+#include <linux/efi.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -63,6 +64,7 @@
 #include <asm/numa.h>
 #include <asm/sections.h>
 #include <asm/dmi.h>
+#include <asm/efi.h>
 
 /*
  * Machine setup..
@@ -230,6 +232,9 @@
 	while (pa_setup_data) {
 		setup_data = early_ioremap(pa_setup_data, PAGE_SIZE);
 		switch (setup_data->type) {
+		case SETUP_EFI64_INFO:
+			parse_efi64_info(setup_data, pa_setup_data);
+			break;
 		default:
 			break;
 		}
@@ -292,6 +297,8 @@
 	discover_ebda();
 
 	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
+	if (efi_enabled)
+		efi_init();
 
 	dmi_scan_machine();
 
@@ -384,6 +391,10 @@
         */
        acpi_reserve_bootmem();
 #endif
+
+	if (efi_enabled)
+		efi_reserve_bootmem();
+
 	/*
 	 * Find and reserve possible boot-time SMP configuration:
 	 */
@@ -459,7 +470,8 @@
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-	conswitchp = &vga_con;
+	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+		conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
include/asm-x86_64/fixmap.h +3 -0
Index: linux-2.6.23-rc4/include/asm-x86_64/fixmap.h
===================================================================
@@ -15,6 +15,7 @@
 #include <asm/apicdef.h>
 #include <asm/page.h>
 #include <asm/vsyscall.h>
+#include <asm/efi.h>
 
 /*
  * Here we define all the compile-time 'special' virtual
@@ -41,6 +42,8 @@
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 	FIX_IO_APIC_BASE_0,
 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
+	FIX_EFI_IO_MAP_LAST_PAGE,
+	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE+MAX_EFI_IO_PAGES-1,
 	__end_of_fixed_addresses
 };
 
arch/x86_64/Kconfig +11 -0
Index: linux-2.6.23-rc4/arch/x86_64/Kconfig
===================================================================
@@ -280,6 +280,17 @@
 	depends on SMP && !MK8
 	default y
 
+config EFI
+	bool "EFI runtime service support (EXPERIMENTAL)"
+	---help---
+	  This enables the kernel to use any EFI runtime services that are
+	  available (such as the EFI variable services).
+	  This option is only useful on systems that have EFI firmware
+	  and will result in a kernel image that is ~8k larger. However,
+	  even with this option, the resultant kernel should continue to
+	  boot on existing non-EFI platforms. For more information on
+	  how to set up [U]EFI64 system, see Documentation/x86_64/uefi.txt.
+
 config MATH_EMULATION
 	bool
 
arch/x86_64/kernel/Makefile +1 -0
Index: linux-2.6.23-rc4/arch/x86_64/kernel/Makefile
===================================================================
@@ -39,6 +39,7 @@
 obj-$(CONFIG_K8_NB)		+= k8.o
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj-$(CONFIG_STACK_UNWIND)	+= unwind.o
+obj-$(CONFIG_EFI)		+= efi.o efi_callwrap.o
 
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_PCI)		+= early-quirks.o
include/asm-i386/bootparam.h +10 -0
Index: linux-2.6.23-rc4/include/asm-i386/bootparam.h
===================================================================
@@ -11,6 +11,7 @@
 
 /* setup data types */
 #define SETUP_NONE			0
+#define SETUP_EFI64_INFO		1
 
 /* extensible setup data list node */
 struct setup_data {
@@ -101,4 +102,13 @@
 	u8  _pad9[276];					/* 0xeec */
 } __attribute__((packed));
 
+struct efi64_info {
+	u64 efi_systab;
+	u32 efi_memmap_size;
+	u32 efi_memdesc_size;
+	u32 efi_memdesc_version;
+	u32 _pad1;
+	u8  efi_memmap[0];
+} __attribute__((packed));
+
 #endif /* _ASM_BOOTPARAM_H */
include/asm-x86_64/efi.h new file +18 -0
Index: linux-2.6.23-rc4/include/asm-x86_64/efi.h
===================================================================
@@ -0,0 +1,18 @@
+#ifndef __ASM_X86_64_EFI_H
+#define __ASM_X86_64_EFI_H
+
+#include <asm/bootparam.h>
+
+#define MAX_EFI_IO_PAGES	100
+
+extern void efi_reserve_bootmem(void);
+#ifdef CONFIG_EFI
+extern void parse_efi64_info(struct setup_data *setup_data,
+			     unsigned long pa_setup_data);
+#else
+static inline void parse_efi64_info(struct setup_data *setup_data,
+				    unsigned long pa_setup_data)
+{ }
+#endif
+
+#endif
arch/x86_64/kernel/reboot.c +13 -7
Index: linux-2.6.23-rc4/arch/x86_64/kernel/reboot.c
===================================================================
@@ -9,6 +9,7 @@
 #include <linux/pm.h>
 #include <linux/kdebug.h>
 #include <linux/sched.h>
+#include <linux/efi.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/delay.h>
@@ -27,20 +28,17 @@
 EXPORT_SYMBOL(pm_power_off);
 
 static long no_idt[3];
-static enum { 
-	BOOT_TRIPLE = 't',
-	BOOT_KBD = 'k',
-	BOOT_ACPI = 'a'
-} reboot_type = BOOT_KBD;
+enum reboot_type reboot_type = BOOT_KBD;
 static int reboot_mode = 0;
 int reboot_force;
 
-/* reboot=t[riple] | k[bd] [, [w]arm | [c]old]
+/* reboot=t[riple] | k[bd] | e[fi] [, [w]arm | [c]old]
    warm   Don't set the cold reboot flag
    cold   Set the cold reboot flag
    triple Force a triple fault (init)
    kbd    Use the keyboard controller. cold reset (default)
    acpi   Use the RESET_REG in the FADT
+   efi    Use efi reset_system runtime service
    force  Avoid anything that could hang.
  */ 
 static int __init reboot_setup(char *str)
@@ -59,6 +57,7 @@
 		case 'a':
 		case 'b':
 		case 'k':
+		case 'e':
 			reboot_type = *str;
 			break;
 		case 'f':
@@ -151,7 +150,14 @@
 			acpi_reboot();
 			reboot_type = BOOT_KBD;
 			break;
-		}      
+
+		case BOOT_EFI:
+			if (efi_enabled)
+				efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD,
+						 EFI_SUCCESS, 0, NULL);
+			reboot_type = BOOT_KBD;
+			break;
+		}
 	}      
 }
 
arch/x86_64/kernel/time.c +32 -16

105 lines not on this page · raw message

include/asm-x86_64/emergency-restart.h +9 -0
Index: linux-2.6.23-rc4/include/asm-x86_64/emergency-restart.h
===================================================================
@@ -1,6 +1,15 @@
 #ifndef _ASM_EMERGENCY_RESTART_H
 #define _ASM_EMERGENCY_RESTART_H
 
+enum reboot_type {
+	BOOT_TRIPLE = 't',
+	BOOT_KBD = 'k',
+	BOOT_ACPI = 'a',
+	BOOT_EFI = 'e'
+};
+
+extern enum reboot_type reboot_type;
+
 extern void machine_emergency_restart(void);
 
 #endif /* _ASM_EMERGENCY_RESTART_H */
include/asm-x86_64/time.h new file +7 -0
Index: linux-2.6.23-rc4/include/asm-x86_64/time.h
===================================================================
@@ -0,0 +1,7 @@
+#ifndef __ASM_X86_64_TIME_H
+#define __ASM_X86_64_TIME_H
+
+extern unsigned long (*get_wallclock)(void);
+extern int (*set_wallclock)(unsigned long nowtime);
+
+#endif
Documentation/x86_64/boot-options.txt +11 -1
Index: linux-2.6.23-rc4/Documentation/x86_64/boot-options.txt
===================================================================
@@ -110,7 +110,7 @@
 
 Rebooting
 
-   reboot=b[ios] | t[riple] | k[bd] | a[cpi] [, [w]arm | [c]old]
+   reboot=b[ios] | t[riple] | k[bd] | a[cpi] | e[fi] [, [w]arm | [c]old]
    bios	  Use the CPU reboot vector for warm reset
    warm   Don't set the cold reboot flag
    cold   Set the cold reboot flag
@@ -119,6 +119,9 @@
    acpi   Use the ACPI RESET_REG in the FADT. If ACPI is not configured or the
           ACPI reset does not work, the reboot path attempts the reset using
           the keyboard controller.
+   efi    Use efi reset_system runtime service. If EFI is not configured or the
+          EFI reset does not work, the reboot path attempts the reset using
+          the keyboard controller.
 
    Using warm reset will be much faster especially on big memory
    systems because the BIOS will not go through the memory check.
@@ -303,4 +306,11 @@
 		newfallback: use new unwinder but fall back to old if it gets
 			stuck (default)
 
+EFI
+
+  noefi		Disable EFI support
+
+  noefi_time	Disable EFI time runtime service, programming CMOS
+  		hardware directly
+
 Miscellaneous
Documentation/i386/boot.txt +15 -0
Index: linux-2.6.23-rc4/Documentation/i386/boot.txt
===================================================================
@@ -793,6 +793,21 @@
 
 **** SETUP DATA TYPES
 
+Type name:	UEFI 64 information
+Protocol:	2.07+
+
+  The UEFI 64 firmware information, including UEFI system table and memory map
+  information. The definition is as follow:
+
+  struct efi64_info {
+          u64 efi_systab;		/* EFI system table pointer */
+          u32 efi_memmap_size;		/* EFI memory descriptor map size */
+          u32 efi_memdesc_size;		/* EFI memory descriptor size */
+          u32 efi_memdesc_version;	/* EFI memory descriptor version */
+          u32 _pad1;
+          u8  efi_memmap[0];		/* EFI memory descriptor map */
+  } __attribute__((packed));
+
 
 **** 32-bit BOOT PROTOCOL