From patchwork Fri Feb 1 22:45:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brad Figg X-Patchwork-Id: 217611 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 758592C0082 for ; Sat, 2 Feb 2013 09:46:30 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U1PNG-0000TV-0o; Fri, 01 Feb 2013 22:46:22 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U1PN8-0000PJ-7s for kernel-team@lists.ubuntu.com; Fri, 01 Feb 2013 22:46:14 +0000 Received: from static-50-53-107-235.bvtn.or.frontiernet.net ([50.53.107.235] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1U1PN7-0000FQ-N2 for kernel-team@lists.ubuntu.com; Fri, 01 Feb 2013 22:46:14 +0000 From: Brad Figg To: kernel-team@lists.ubuntu.com Subject: [Precise] [PATCH 07/12] x86, efi: Add basic error handling Date: Fri, 1 Feb 2013 14:45:47 -0800 Message-Id: <1359758752-21643-8-git-send-email-brad.figg@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1359758752-21643-1-git-send-email-brad.figg@canonical.com> References: <1359758752-21643-1-git-send-email-brad.figg@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Olof Johansson BugLink: http://bugs.launchpad.net/bugs/1111689 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 Link: http://lkml.kernel.org/r/1329081869-20779-5-git-send-email-olof@lixom.net Acked-by: Matt Fleming Signed-off-by: H. Peter Anvin (cherry picked from commit 140bf275d3e89e9b36851d5cf498dbbbecdf7ca8) Signed-off-by: Brad Figg --- arch/x86/platform/efi/efi.c | 85 +++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 7108a76..0e16afc 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -435,12 +435,14 @@ 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; @@ -448,16 +450,20 @@ static void __init efi_systab_init(void *phys) /* * 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); @@ -467,8 +473,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++) { @@ -502,9 +510,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; @@ -516,37 +526,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) @@ -564,7 +581,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 @@ -582,11 +602,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;