Skip to contentSkip to conversation

EFI : Split EFI tables parsing code from EFI runtime service support code

PATCH New Huang, Ying 1 participant 1 message Jan 4, 2008

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 EFI : Split EFI tables parsing code from EFI runtime service support code

This patch split EFI tables parsing code from EFI runtime service support code. This makes ACPI support and DMI support on EFI platform not depend on EFI runtime service support. Both EFI32 and EFI64 tables parsing functions are provided on i386 and x86_64. This makes it possible to use EFI information in i386 kernel on x86_64 with EFI64 firmware or in x86_64 kernel on x86_64 with EFI32 firmware.

This patch is based on 2.6.24-rc5-mm1 and has been tested for following combinations:

i386 kernel on EFI 32
i386 kernel on EFI 64
x86_64 kernel on EFI 32
x86_64 kernel on EFI 64
ia64 kernel on EFI 64

ChangeLog

v2:

- Change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL.

---
 arch/ia64/kernel/acpi.c      |    6 -
 arch/ia64/kernel/efi.c       |   30 ++++----
 arch/ia64/kernel/setup.c     |    2 
 arch/ia64/sn/kernel/setup.c  |    4 -
 arch/x86/Kconfig             |    4 -
 arch/x86/kernel/Makefile_32  |    3 
 arch/x86/kernel/Makefile_64  |    2 
 arch/x86/kernel/efi.c        |  115 ++++++++--------------------------
 arch/x86/kernel/efi_tables.c |  144 +++++++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/setup_32.c   |    9 ++
 arch/x86/kernel/setup_64.c   |    9 ++
 drivers/acpi/osl.c           |   11 +--
 drivers/firmware/dmi_scan.c  |    7 +-
 drivers/firmware/efivars.c   |   53 ++++++++-------
 drivers/firmware/pcdp.c      |    6 -
 include/asm-ia64/setup.h     |    5 +
 include/asm-ia64/sn/sn_sal.h |    2 
 include/asm-x86/efi.h        |    7 ++
 include/asm-x86/setup.h      |    9 ++
 include/linux/efi.h          |   64 ++++++++++++++++---
 20 files changed, 333 insertions(+), 159 deletions(-)
include/linux/efi.h +56 -8
@@ -212,6 +212,16 @@ typedef struct {
 	unsigned long table;
 } efi_config_table_t;
 
+struct efi_config_table64 {
+	efi_guid_t guid;
+	u64 table;
+};
+
+struct efi_config_table32 {
+	efi_guid_t guid;
+	u32 table;
+};
+
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
 
 typedef struct {
@@ -230,6 +240,39 @@ typedef struct {
 	unsigned long tables;
 } efi_system_table_t;
 
+struct efi_system_table64 {
+	efi_table_hdr_t hdr;
+	u64 fw_vendor;
+	u32 fw_revision;
+	u32 _pad1;
+	u64 con_in_handle;
+	u64 con_in;
+	u64 con_out_handle;
+	u64 con_out;
+	u64 stderr_handle;
+	u64 stderr;
+	u64 runtime;
+	u64 boottime;
+	u64 nr_tables;
+	u64 tables;
+};
+
+struct efi_system_table32 {
+	efi_table_hdr_t hdr;
+	u32 fw_vendor;
+	u32 fw_revision;
+	u32 con_in_handle;
+	u32 con_in;
+	u32 con_out_handle;
+	u32 con_out;
+	u32 stderr_handle;
+	u32 stderr;
+	u32 runtime;
+	u32 boottime;
+	u32 nr_tables;
+	u32 tables;
+};
+
 struct efi_memory_map {
 	void *phys_map;
 	void *map;
@@ -246,14 +289,6 @@ struct efi_memory_map {
  */
 extern struct efi {
 	efi_system_table_t *systab;	/* EFI system table */
-	unsigned long mps;		/* MPS table */
-	unsigned long acpi;		/* ACPI table  (IA64 ext 0.71) */
-	unsigned long acpi20;		/* ACPI table  (ACPI 2.0) */
-	unsigned long smbios;		/* SM BIOS table */
-	unsigned long sal_systab;	/* SAL system table */
-	unsigned long boot_info;	/* boot info table */
-	unsigned long hcdp;		/* HCDP table */
-	unsigned long uga;		/* UGA table */
 	efi_get_time_t *get_time;
 	efi_set_time_t *set_time;
 	efi_get_wakeup_time_t *get_wakeup_time;
@@ -266,6 +301,19 @@ extern struct efi {
 	efi_set_virtual_address_map_t *set_virtual_address_map;
 } efi;
 
+struct efi_tables {
+	unsigned long mps;		/* MPS table */
+	unsigned long acpi;		/* ACPI table  (IA64 ext 0.71) */
+	unsigned long acpi20;		/* ACPI table  (ACPI 2.0) */
+	unsigned long smbios;		/* SM BIOS table */
+	unsigned long sal_systab;	/* SAL system table */
+	unsigned long boot_info;	/* boot info table */
+	unsigned long hcdp;		/* HCDP table */
+	unsigned long uga;		/* UGA table */
+};
+
+extern struct efi_tables efi_tables;
+
 static inline int
 efi_guidcmp (efi_guid_t left, efi_guid_t right)
 {
arch/x86/kernel/efi_tables.c new file +144 -0

144 lines not on this page · raw message

arch/x86/kernel/Makefile_64 +1 -1
@@ -10,7 +10,7 @@ obj-y	:= process_64.o signal_64.o entry_
 		x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \
 		setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \
 		pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \
-		i8253.o rtc.o
+		i8253.o rtc.o efi_tables.o
 
 obj-y				+= ptrace.o
 obj-y				+= ds.o
arch/x86/kernel/setup_32.c +7 -2
@@ -62,6 +62,7 @@
 #include <setup_arch.h>
 #include <bios_ebda.h>
 #include <asm/cacheflush.h>
+#include <asm/efi.h>
 
 /* This value is set up by the early boot code to point to the value
    immediately after the boot time page tables.  It contains a *physical*
@@ -196,6 +197,9 @@ static char __initdata command_line[COMM
 
 struct boot_params __initdata boot_params;
 
+enum bios_type bios_type = BIOS_LEGACY;
+EXPORT_SYMBOL_GPL(bios_type);
+
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
 #ifdef CONFIG_EDD_MODULE
@@ -621,9 +625,9 @@ void __init setup_arch(char **cmdline_p)
 	pre_setup_arch_hook();
 	early_cpu_init();
 
+	efi_check_bios_type();
 #ifdef CONFIG_EFI
-	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
-		     "EL32", 4))
+	if (bios_type == BIOS_EFI32)
 		efi_enabled = 1;
 #endif
 
@@ -677,6 +681,7 @@ void __init setup_arch(char **cmdline_p)
 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
+	efi_tables_parse();
 	if (efi_enabled)
 		efi_init();
 
include/asm-x86/efi.h +7 -0
@@ -44,6 +44,8 @@ extern void *boot_ioremap(unsigned long,
 
 #define end_pfn_map				max_low_pfn
 
+#define EFI_CHECK_ADDR(addr)	((addr) <= -1UL)
+
 #else /* !CONFIG_X86_32 */
 
 #define MAX_EFI_IO_PAGES	100
@@ -102,6 +104,8 @@ extern void *efi_ioremap(unsigned long o
 
 extern int efi_time;
 
+#define EFI_CHECK_ADDR(addr)	1
+
 #endif /* CONFIG_X86_32 */
 
 extern void efi_reserve_bootmem(void);
@@ -109,4 +113,7 @@ extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
 extern void runtime_code_page_mkexec(void);
 
+extern void efi_tables_parse(void);
+extern void efi_check_bios_type(void);
+
 #endif
arch/x86/kernel/setup_64.c +7 -2
@@ -143,6 +143,9 @@ static struct resource bss_resource = {
 	.flags = IORESOURCE_RAM,
 };
 
+enum bios_type bios_type = BIOS_LEGACY;
+EXPORT_SYMBOL_GPL(bios_type);
+
 static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
 
 #ifdef CONFIG_PROC_VMCORE
@@ -283,9 +286,9 @@ void __init setup_arch(char **cmdline_p)
 	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
 #endif
+	efi_check_bios_type();
 #ifdef CONFIG_EFI
-	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
-		     "EL64", 4))
+	if (bios_type == BIOS_EFI64)
 		efi_enabled = 1;
 #endif
 	setup_memory_region();
@@ -327,6 +330,8 @@ void __init setup_arch(char **cmdline_p)
 	discover_ebda();
 
 	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
+
+	efi_tables_parse();
 	if (efi_enabled)
 		efi_init();
 
include/asm-x86/setup.h +9 -0
@@ -56,6 +56,15 @@ extern unsigned long init_pg_tables_end;
 #endif
 
 #endif /* __i386__ */
+
+enum bios_type {
+	BIOS_LEGACY,
+	BIOS_EFI32,
+	BIOS_EFI64,
+};
+
+extern enum bios_type bios_type;
+
 #endif /* _SETUP */
 #endif /* __ASSEMBLY__ */
 #endif  /*  __KERNEL__  */
arch/x86/kernel/Makefile_32 +2 -1
@@ -8,7 +8,8 @@ CPPFLAGS_vmlinux.lds += -Ui386
 obj-y	:= process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \
 		time_32.o ioport_32.o ldt.o setup_32.o i8259_32.o sys_i386_32.o \
 		pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\
-		quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o rtc.o
+		quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o \
+		rtc.o efi_tables.o
 
 obj-y				+= ptrace.o
 obj-y				+= ds.o
drivers/acpi/osl.c +6 -5
@@ -42,6 +42,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/processor.h>
 #include <asm/uaccess.h>
+#include <asm/setup.h>
 
 #include <linux/efi.h>
 #include <linux/ioport.h>
@@ -211,11 +212,11 @@ void acpi_os_vprintf(const char *fmt, va
 
 acpi_physical_address __init acpi_os_get_root_pointer(void)
 {
-	if (efi_enabled) {
-		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
-			return efi.acpi20;
-		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
-			return efi.acpi;
+	if (bios_type == BIOS_EFI64 || bios_type == BIOS_EFI32) {
+		if (efi_tables.acpi20 != EFI_INVALID_TABLE_ADDR)
+			return efi_tables.acpi20;
+		else if (efi_tables.acpi != EFI_INVALID_TABLE_ADDR)
+			return efi_tables.acpi;
 		else {
 			printk(KERN_ERR PREFIX
 			       "System description tables not found\n");
drivers/firmware/dmi_scan.c +4 -3
@@ -7,6 +7,7 @@
 #include <linux/bootmem.h>
 #include <linux/slab.h>
 #include <asm/dmi.h>
+#include <asm/setup.h>
 
 static char * __init dmi_string(const struct dmi_header *dm, u8 s)
 {
@@ -298,15 +299,15 @@ void __init dmi_scan_machine(void)
 	char __iomem *p, *q;
 	int rc;
 
-	if (efi_enabled) {
-		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
+	if (bios_type == BIOS_EFI64 || bios_type == BIOS_EFI32) {
+		if (efi_tables.smbios == EFI_INVALID_TABLE_ADDR)
 			goto out;
 
 		/* This is called as a core_initcall() because it isn't
 		 * needed during early boot.  This also means we can
 		 * iounmap the space when we're done with it.
 		 */
-		p = dmi_ioremap(efi.smbios, 32);
+		p = dmi_ioremap(efi_tables.smbios, 32);
 		if (p == NULL)
 			goto out;
 
arch/x86/kernel/efi.c +28 -87

165 lines not on this page · raw message

drivers/firmware/efivars.c +30 -23

89 lines not on this page · raw message

arch/ia64/kernel/efi.c +16 -14
@@ -43,6 +43,8 @@ extern efi_status_t efi_call_phys (void 
 
 struct efi efi;
 EXPORT_SYMBOL(efi);
+struct efi_tables efi_tables;
+EXPORT_SYMBOL_GPL(efi_tables);
 static efi_runtime_services_t *runtime;
 static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
 
@@ -466,33 +468,33 @@ efi_init (void)
 	printk(KERN_INFO "EFI v%u.%.02u by %s:",
 	       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
 
-	efi.mps        = EFI_INVALID_TABLE_ADDR;
-	efi.acpi       = EFI_INVALID_TABLE_ADDR;
-	efi.acpi20     = EFI_INVALID_TABLE_ADDR;
-	efi.smbios     = EFI_INVALID_TABLE_ADDR;
-	efi.sal_systab = EFI_INVALID_TABLE_ADDR;
-	efi.boot_info  = EFI_INVALID_TABLE_ADDR;
-	efi.hcdp       = EFI_INVALID_TABLE_ADDR;
-	efi.uga        = EFI_INVALID_TABLE_ADDR;
+	efi_tables.mps        = EFI_INVALID_TABLE_ADDR;
+	efi_tables.acpi       = EFI_INVALID_TABLE_ADDR;
+	efi_tables.acpi20     = EFI_INVALID_TABLE_ADDR;
+	efi_tables.smbios     = EFI_INVALID_TABLE_ADDR;
+	efi_tables.sal_systab = EFI_INVALID_TABLE_ADDR;
+	efi_tables.boot_info  = EFI_INVALID_TABLE_ADDR;
+	efi_tables.hcdp       = EFI_INVALID_TABLE_ADDR;
+	efi_tables.uga        = EFI_INVALID_TABLE_ADDR;
 
 	for (i = 0; i < (int) efi.systab->nr_tables; i++) {
 		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
-			efi.mps = config_tables[i].table;
+			efi_tables.mps = config_tables[i].table;
 			printk(" MPS=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
-			efi.acpi20 = config_tables[i].table;
+			efi_tables.acpi20 = config_tables[i].table;
 			printk(" ACPI 2.0=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
-			efi.acpi = config_tables[i].table;
+			efi_tables.acpi = config_tables[i].table;
 			printk(" ACPI=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
-			efi.smbios = config_tables[i].table;
+			efi_tables.smbios = config_tables[i].table;
 			printk(" SMBIOS=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
-			efi.sal_systab = config_tables[i].table;
+			efi_tables.sal_systab = config_tables[i].table;
 			printk(" SALsystab=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
-			efi.hcdp = config_tables[i].table;
+			efi_tables.hcdp = config_tables[i].table;
 			printk(" HCDP=0x%lx", config_tables[i].table);
 		}
 	}
include/asm-ia64/setup.h +5 -0
@@ -3,4 +3,9 @@
 
 #define COMMAND_LINE_SIZE	2048
 
+#define BIOS_EFI64		1
+#define BIOS_EFI32		2
+
+#define bios_type		BIOS_EFI64
+
 #endif
arch/x86/Kconfig +1 -3
@@ -1022,11 +1022,9 @@ config IRQBALANCE
 	  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
 	def_bool y
-	depends on X86_32 && (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
+	depends on X86_32
 
 config SECCOMP
 	def_bool y
arch/ia64/kernel/acpi.c +3 -3
@@ -73,9 +73,9 @@ unsigned long __init acpi_find_rsdp(void
 {
 	unsigned long rsdp_phys = 0;
 
-	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
-		rsdp_phys = efi.acpi20;
-	else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+	if (efi_tables.acpi20 != EFI_INVALID_TABLE_ADDR)
+		rsdp_phys = efi_tables.acpi20;
+	else if (efi_tables.acpi != EFI_INVALID_TABLE_ADDR)
 		printk(KERN_WARNING PREFIX
 		       "v1.0/r0.71 tables no longer supported\n");
 	return rsdp_phys;
arch/ia64/kernel/setup.c +1 -1
@@ -505,7 +505,7 @@ setup_arch (char **cmdline_p)
 	find_memory();
 
 	/* process SAL system table: */
-	ia64_sal_init(__va(efi.sal_systab));
+	ia64_sal_init(__va(efi_tables.sal_systab));
 
 	ia64_setup_printk_clock();
 
include/asm-ia64/sn/sn_sal.h +1 -1
@@ -165,7 +165,7 @@
 static inline u32
 sn_sal_rev(void)
 {
-	struct ia64_sal_systab *systab = __va(efi.sal_systab);
+	struct ia64_sal_systab *systab = __va(efi_tables.sal_systab);
 
 	return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
 }
arch/ia64/sn/kernel/setup.c +2 -2
@@ -324,10 +324,10 @@ sn_scan_pcdp(void)
 	struct pcdp_interface_pci if_pci;
 	extern struct efi efi;
 
-	if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
+	if (efi_tables.hcdp == EFI_INVALID_TABLE_ADDR)
 		return;		/* no hcdp/pcdp table */
 
-	pcdp = __va(efi.hcdp);
+	pcdp = __va(efi_tables.hcdp);
 
 	if (pcdp->rev < 3)
 		return;		/* only support PCDP (rev >= 3) */
drivers/firmware/pcdp.c +3 -3
@@ -92,11 +92,11 @@ efi_setup_pcdp_console(char *cmdline)
 	int i, serial = 0;
 	int rc = -ENODEV;
 
-	if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
+	if (efi_tables.hcdp == EFI_INVALID_TABLE_ADDR)
 		return -ENODEV;
 
-	pcdp = ioremap(efi.hcdp, 4096);
-	printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp);
+	pcdp = ioremap(efi_tables.hcdp, 4096);
+	printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi_tables.hcdp);
 
 	if (strstr(cmdline, "console=hcdp")) {
 		if (pcdp->rev < 3)