Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 292734
b: refs/heads/master
c: 1adbfa3
h: refs/heads/master
v: v3
  • Loading branch information
Olof Johansson authored and H. Peter Anvin committed Feb 24, 2012
1 parent 7b7081e commit 1ed6180
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 140bf275d3e89e9b36851d5cf498dbbbecdf7ca8
refs/heads/master: 1adbfa3511ee1c1118e16a9a0246870f12fef4e6
2 changes: 1 addition & 1 deletion trunk/arch/x86/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,

extern int add_efi_memmap;
extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
extern void efi_memblock_x86_reserve_range(void);
extern int efi_memblock_x86_reserve_range(void);
extern void efi_call_phys_prelog(void);
extern void efi_call_phys_epilog(void);

Expand Down
10 changes: 8 additions & 2 deletions trunk/arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,10 +749,16 @@ void __init setup_arch(char **cmdline_p)
#endif
#ifdef CONFIG_EFI
if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
EFI_LOADER_SIGNATURE, 4)) {
"EL32", 4)) {
efi_enabled = 1;
efi_memblock_x86_reserve_range();
efi_64bit = false;
} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
"EL64", 4)) {
efi_enabled = 1;
efi_64bit = true;
}
if (efi_enabled && efi_memblock_x86_reserve_range())
efi_enabled = 0;
#endif

x86_init.oem.arch_setup();
Expand Down
164 changes: 142 additions & 22 deletions trunk/arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ EXPORT_SYMBOL(efi);

struct efi_memory_map memmap;

bool efi_64bit;
static bool efi_native;

static struct efi efi_phys __initdata;
static efi_system_table_t efi_systab __initdata;

Expand Down Expand Up @@ -339,11 +342,16 @@ static void __init do_add_efi_memmap(void)
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
}

void __init efi_memblock_x86_reserve_range(void)
int __init efi_memblock_x86_reserve_range(void)
{
unsigned long pmap;

#ifdef CONFIG_X86_32
/* Can't handle data above 4GB at this time */
if (boot_params.efi_info.efi_memmap_hi) {
pr_err("Memory map is above 4GB, disabling EFI.\n");
return -EINVAL;
}
pmap = boot_params.efi_info.efi_memmap;
#else
pmap = (boot_params.efi_info.efi_memmap |
Expand All @@ -355,6 +363,8 @@ void __init efi_memblock_x86_reserve_range(void)
memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);

return 0;
}

#if EFI_DEBUG
Expand Down Expand Up @@ -432,14 +442,75 @@ static void __init efi_free_boot_services(void)

static int __init efi_systab_init(void *phys)
{
efi.systab = early_ioremap((unsigned long)efi_phys.systab,
sizeof(efi_system_table_t));
if (efi.systab == NULL) {
pr_err("Couldn't map the system table!\n");
return -ENOMEM;
if (efi_64bit) {
efi_system_table_64_t *systab64;
u64 tmp = 0;

systab64 = early_ioremap((unsigned long)phys,
sizeof(*systab64));
if (systab64 == NULL) {
pr_err("Couldn't map the system table!\n");
return -ENOMEM;
}

efi_systab.hdr = systab64->hdr;
efi_systab.fw_vendor = systab64->fw_vendor;
tmp |= systab64->fw_vendor;
efi_systab.fw_revision = systab64->fw_revision;
efi_systab.con_in_handle = systab64->con_in_handle;
tmp |= systab64->con_in_handle;
efi_systab.con_in = systab64->con_in;
tmp |= systab64->con_in;
efi_systab.con_out_handle = systab64->con_out_handle;
tmp |= systab64->con_out_handle;
efi_systab.con_out = systab64->con_out;
tmp |= systab64->con_out;
efi_systab.stderr_handle = systab64->stderr_handle;
tmp |= systab64->stderr_handle;
efi_systab.stderr = systab64->stderr;
tmp |= systab64->stderr;
efi_systab.runtime = (void *)(unsigned long)systab64->runtime;
tmp |= systab64->runtime;
efi_systab.boottime = (void *)(unsigned long)systab64->boottime;
tmp |= systab64->boottime;
efi_systab.nr_tables = systab64->nr_tables;
efi_systab.tables = systab64->tables;
tmp |= systab64->tables;

early_iounmap(systab64, sizeof(*systab64));
#ifdef CONFIG_X86_32
if (tmp >> 32) {
pr_err("EFI data located above 4GB, disabling EFI.\n");
return -EINVAL;
}
#endif
} else {
efi_system_table_32_t *systab32;

systab32 = early_ioremap((unsigned long)phys,
sizeof(*systab32));
if (systab32 == NULL) {
pr_err("Couldn't map the system table!\n");
return -ENOMEM;
}

efi_systab.hdr = systab32->hdr;
efi_systab.fw_vendor = systab32->fw_vendor;
efi_systab.fw_revision = systab32->fw_revision;
efi_systab.con_in_handle = systab32->con_in_handle;
efi_systab.con_in = systab32->con_in;
efi_systab.con_out_handle = systab32->con_out_handle;
efi_systab.con_out = systab32->con_out;
efi_systab.stderr_handle = systab32->stderr_handle;
efi_systab.stderr = systab32->stderr;
efi_systab.runtime = (void *)(unsigned long)systab32->runtime;
efi_systab.boottime = (void *)(unsigned long)systab32->boottime;
efi_systab.nr_tables = systab32->nr_tables;
efi_systab.tables = systab32->tables;

early_iounmap(systab32, sizeof(*systab32));
}
memcpy(&efi_systab, efi.systab, sizeof(efi_system_table_t));
early_iounmap(efi.systab, sizeof(efi_system_table_t));

efi.systab = &efi_systab;

/*
Expand All @@ -460,24 +531,47 @@ static int __init efi_systab_init(void *phys)

static int __init efi_config_init(u64 tables, int nr_tables)
{
efi_config_table_t *config_tables;
int i, sz = sizeof(efi_config_table_t);
void *config_tables, *tablep;
int i, sz;

if (efi_64bit)
sz = sizeof(efi_config_table_64_t);
else
sz = sizeof(efi_config_table_32_t);

/*
* Let's see what config tables the firmware passed to us.
*/
config_tables = early_ioremap(efi.systab->tables,
efi.systab->nr_tables * sz);
config_tables = early_ioremap(tables, nr_tables * sz);
if (config_tables == NULL) {
pr_err("Could not map Configuration table!\n");
return -ENOMEM;
}

tablep = config_tables;
pr_info("");
for (i = 0; i < efi.systab->nr_tables; i++) {
efi_guid_t guid = config_tables[i].guid;
unsigned long table = config_tables[i].table;

efi_guid_t guid;
unsigned long table;

if (efi_64bit) {
u64 table64;
guid = ((efi_config_table_64_t *)tablep)->guid;
table64 = ((efi_config_table_64_t *)tablep)->table;
table = table64;
#ifdef CONFIG_X86_32
if (table64 >> 32) {
pr_cont("\n");
pr_err("Table located above 4GB, disabling EFI.\n");
early_iounmap(config_tables,
efi.systab->nr_tables * sz);
return -EINVAL;
}
#endif
} else {
guid = ((efi_config_table_32_t *)tablep)->guid;
table = ((efi_config_table_32_t *)tablep)->table;
}
if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
efi.mps = table;
pr_cont(" MPS=0x%lx ", table);
Expand All @@ -502,10 +596,10 @@ static int __init efi_config_init(u64 tables, int nr_tables)
efi.uga = table;
pr_cont(" UGA=0x%lx ", table);
}
tablep += sz;
}
pr_cont("\n");
early_iounmap(config_tables, efi.systab->nr_tables * sz);

return 0;
}

Expand Down Expand Up @@ -569,11 +663,19 @@ void __init efi_init(void)
void *tmp;

#ifdef CONFIG_X86_32
if (boot_params.efi_info.efi_systab_hi ||
boot_params.efi_info.efi_memmap_hi) {
pr_info("Table located above 4GB, disabling EFI.\n");
efi_enabled = 0;
return;
}
efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
efi_native = !efi_64bit;
#else
efi_phys.systab = (efi_system_table_t *)
(boot_params.efi_info.efi_systab |
((__u64)boot_params.efi_info.efi_systab_hi<<32));
(boot_params.efi_info.efi_systab |
((__u64)boot_params.efi_info.efi_systab_hi<<32));
efi_native = efi_64bit;
#endif

if (efi_systab_init(efi_phys.systab)) {
Expand Down Expand Up @@ -602,7 +704,14 @@ void __init efi_init(void)
return;
}

if (efi_runtime_init()) {
/*
* Note: We currently don't support runtime services on an EFI
* that doesn't match the kernel 32/64-bit mode.
*/

if (!efi_native)
pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
else if (efi_runtime_init()) {
efi_enabled = 0;
return;
}
Expand All @@ -611,10 +720,11 @@ void __init efi_init(void)
efi_enabled = 0;
return;
}

#ifdef CONFIG_X86_32
x86_platform.get_wallclock = efi_get_time;
x86_platform.set_wallclock = efi_set_rtc_mmss;
if (efi_native) {
x86_platform.get_wallclock = efi_get_time;
x86_platform.set_wallclock = efi_set_rtc_mmss;
}
#endif

#if EFI_DEBUG
Expand Down Expand Up @@ -672,6 +782,14 @@ void __init efi_enter_virtual_mode(void)

efi.systab = NULL;

/*
* We don't do virtual mode, since we don't do runtime services, on
* non-native EFI
*/

if (!efi_native)
goto out;

/* Merge contiguous regions of the same type and attribute */
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
u64 prev_size;
Expand Down Expand Up @@ -787,6 +905,8 @@ void __init efi_enter_virtual_mode(void)
efi.query_capsule_caps = virt_efi_query_capsule_caps;
if (__supported_pte_mask & _PAGE_NX)
runtime_code_page_mkexec();

out:
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL;
kfree(new_memmap);
Expand Down
45 changes: 45 additions & 0 deletions trunk/include/linux/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,16 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
#define EFI_FILE_SYSTEM_GUID \
EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )

typedef struct {
efi_guid_t guid;
u64 table;
} efi_config_table_64_t;

typedef struct {
efi_guid_t guid;
u32 table;
} efi_config_table_32_t;

typedef struct {
efi_guid_t guid;
unsigned long table;
Expand All @@ -327,6 +337,40 @@ typedef struct {
#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))

typedef struct {
efi_table_hdr_t hdr;
u64 fw_vendor; /* physical addr of CHAR16 vendor string */
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;
u32 nr_tables;
u32 __pad2;
u64 tables;
} efi_system_table_64_t;

typedef struct {
efi_table_hdr_t hdr;
u32 fw_vendor; /* physical addr of CHAR16 vendor string */
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;
} efi_system_table_32_t;

typedef struct {
efi_table_hdr_t hdr;
unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
Expand Down Expand Up @@ -497,6 +541,7 @@ extern int __init efi_setup_pcdp_console(char *);
#ifdef CONFIG_EFI
# ifdef CONFIG_X86
extern int efi_enabled;
extern bool efi_64bit;
# else
# define efi_enabled 1
# endif
Expand Down

0 comments on commit 1ed6180

Please sign in to comment.