Skip to content

Commit

Permalink
x86, efi: Add basic error handling
Browse files Browse the repository at this point in the history
It's not perfect, but way better than before. Mark efi_enabled as false in
case of error and at least stop dereferencing pointers that are known to
be invalid.

The only significant missing piece is the lack of undoing the
memblock_reserve of the memory that efi marks as in use. On the other
hand, it's not a large amount of memory, and leaving it unavailable for
system use should be the safer choice anyway.

Signed-off-by: Olof Johansson <olof@lixom.net>
Link: http://lkml.kernel.org/r/1329081869-20779-5-git-send-email-olof@lixom.net
Acked-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
  • Loading branch information
Olof Johansson authored and H. Peter Anvin committed Feb 24, 2012
1 parent a6a46f4 commit 140bf27
Showing 1 changed file with 57 additions and 28 deletions.
85 changes: 57 additions & 28 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,29 +430,35 @@ static void __init efi_free_boot_services(void)
}
}

static void __init efi_systab_init(void *phys)
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)
if (efi.systab == NULL) {
pr_err("Couldn't map the system table!\n");
return -ENOMEM;
}
memcpy(&efi_systab, efi.systab, sizeof(efi_system_table_t));
early_iounmap(efi.systab, sizeof(efi_system_table_t));
efi.systab = &efi_systab;

/*
* Verify the EFI Table
*/
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
pr_err("System table signature incorrect!\n");
return -EINVAL;
}
if ((efi.systab->hdr.revision >> 16) == 0)
pr_err("Warning: System table version "
"%d.%02d, expected 1.00 or greater!\n",
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff);

return 0;
}

static void __init efi_config_init(u64 tables, int nr_tables)
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);
Expand All @@ -462,8 +468,10 @@ static void __init efi_config_init(u64 tables, int nr_tables)
*/
config_tables = early_ioremap(efi.systab->tables,
efi.systab->nr_tables * sz);
if (config_tables == NULL)
if (config_tables == NULL) {
pr_err("Could not map Configuration table!\n");
return -ENOMEM;
}

pr_info("");
for (i = 0; i < efi.systab->nr_tables; i++) {
Expand Down Expand Up @@ -497,9 +505,11 @@ static void __init efi_config_init(u64 tables, int nr_tables)
}
pr_cont("\n");
early_iounmap(config_tables, efi.systab->nr_tables * sz);

return 0;
}

static void __init efi_runtime_init(void)
static int __init efi_runtime_init(void)
{
efi_runtime_services_t *runtime;

Expand All @@ -511,37 +521,44 @@ static void __init efi_runtime_init(void)
*/
runtime = early_ioremap((unsigned long)efi.systab->runtime,
sizeof(efi_runtime_services_t));
if (runtime != NULL) {
/*
* We will only need *early* access to the following
* two EFI runtime services before set_virtual_address_map
* is invoked.
*/
efi_phys.get_time = (efi_get_time_t *)runtime->get_time;
efi_phys.set_virtual_address_map =
(efi_set_virtual_address_map_t *)
runtime->set_virtual_address_map;
/*
* Make efi_get_time can be called before entering
* virtual mode.
*/
efi.get_time = phys_efi_get_time;
} else
if (!runtime) {
pr_err("Could not map the runtime service table!\n");
return -ENOMEM;
}
/*
* We will only need *early* access to the following
* two EFI runtime services before set_virtual_address_map
* is invoked.
*/
efi_phys.get_time = (efi_get_time_t *)runtime->get_time;
efi_phys.set_virtual_address_map =
(efi_set_virtual_address_map_t *)
runtime->set_virtual_address_map;
/*
* Make efi_get_time can be called before entering
* virtual mode.
*/
efi.get_time = phys_efi_get_time;
early_iounmap(runtime, sizeof(efi_runtime_services_t));

return 0;
}

static void __init efi_memmap_init(void)
static int __init efi_memmap_init(void)
{
/* Map the EFI memory map */
memmap.map = early_ioremap((unsigned long)memmap.phys_map,
memmap.nr_map * memmap.desc_size);
if (memmap.map == NULL)
if (memmap.map == NULL) {
pr_err("Could not map the memory map!\n");
return -ENOMEM;
}
memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);

if (add_efi_memmap)
do_add_efi_memmap();

return 0;
}

void __init efi_init(void)
Expand All @@ -559,7 +576,10 @@ void __init efi_init(void)
((__u64)boot_params.efi_info.efi_systab_hi<<32));
#endif

efi_systab_init(efi_phys.systab);
if (efi_systab_init(efi_phys.systab)) {
efi_enabled = 0;
return;
}

/*
* Show what we know for posterity
Expand All @@ -577,11 +597,20 @@ void __init efi_init(void)
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff, vendor);

efi_config_init(efi.systab->tables, efi.systab->nr_tables);
if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) {
efi_enabled = 0;
return;
}

efi_runtime_init();
if (efi_runtime_init()) {
efi_enabled = 0;
return;
}

efi_memmap_init();
if (efi_memmap_init()) {
efi_enabled = 0;
return;
}

#ifdef CONFIG_X86_32
x86_platform.get_wallclock = efi_get_time;
Expand Down

0 comments on commit 140bf27

Please sign in to comment.