summaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2020-01-20 10:49:11 +0100
committerArd Biesheuvel <ardb@kernel.org>2020-02-23 21:59:42 +0100
commit14fb4209094355928d5a742e35afabdf7b404c17 (patch)
tree79792232114882e957fb6d6ae3a1eba906099a3d /drivers/firmware
parentb7846e6be235c4a19337a32168b27ed836a1504e (diff)
downloadlinux-stable-14fb4209094355928d5a742e35afabdf7b404c17.tar.gz
linux-stable-14fb4209094355928d5a742e35afabdf7b404c17.tar.bz2
linux-stable-14fb4209094355928d5a742e35afabdf7b404c17.zip
efi: Merge EFI system table revision and vendor checks
We have three different versions of the code that checks the EFI system table revision and copies the firmware vendor string, and they are mostly equivalent, with the exception of the use of early_memremap_ro vs. __va() and the lowest major revision to warn about. Let's move this into common code and factor out the commonalities. Tested-by: Tony Luck <tony.luck@intel.com> # arch/ia64 Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/efi/arm-init.c32
-rw-r--r--drivers/firmware/efi/efi.c61
2 files changed, 66 insertions, 27 deletions
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index d99f5b0c8a09..a656bfcd7e27 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -85,11 +85,9 @@ static void __init init_screen_info(void)
static int __init uefi_init(void)
{
- efi_char16_t *c16;
void *config_tables;
size_t table_size;
- char vendor[100] = "unknown";
- int i, retval;
+ int retval;
efi.systab = early_memremap_ro(efi_system_table,
sizeof(efi_system_table_t));
@@ -102,34 +100,14 @@ static int __init uefi_init(void)
if (IS_ENABLED(CONFIG_64BIT))
set_bit(EFI_64BIT, &efi.flags);
- /*
- * Verify the EFI Table
- */
- if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
- pr_err("System table signature incorrect\n");
- retval = -EINVAL;
+ retval = efi_systab_check_header(&efi.systab->hdr, 2);
+ if (retval)
goto out;
- }
- if ((efi.systab->hdr.revision >> 16) < 2)
- pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
- efi.systab->hdr.revision >> 16,
- efi.systab->hdr.revision & 0xffff);
efi.runtime_version = efi.systab->hdr.revision;
- /* Show what we know for posterity */
- c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
- sizeof(vendor) * sizeof(efi_char16_t));
- if (c16) {
- for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
- vendor[i] = c16[i];
- vendor[i] = '\0';
- early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
- }
-
- pr_info("EFI v%u.%.02u by %s\n",
- efi.systab->hdr.revision >> 16,
- efi.systab->hdr.revision & 0xffff, vendor);
+ efi_systab_report_header(&efi.systab->hdr,
+ efi_to_phys(efi.systab->fw_vendor));
table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 41bb2c44cea4..80fe0044f2e2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -631,6 +631,67 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
return ret;
}
+
+int __init efi_systab_check_header(const efi_table_hdr_t *systab_hdr,
+ int min_major_version)
+{
+ if (systab_hdr->signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+ pr_err("System table signature incorrect!\n");
+ return -EINVAL;
+ }
+
+ if ((systab_hdr->revision >> 16) < min_major_version)
+ pr_err("Warning: System table version %d.%02d, expected %d.00 or greater!\n",
+ systab_hdr->revision >> 16,
+ systab_hdr->revision & 0xffff,
+ min_major_version);
+
+ return 0;
+}
+
+#ifndef CONFIG_IA64
+static const efi_char16_t *__init map_fw_vendor(unsigned long fw_vendor,
+ size_t size)
+{
+ const efi_char16_t *ret;
+
+ ret = early_memremap_ro(fw_vendor, size);
+ if (!ret)
+ pr_err("Could not map the firmware vendor!\n");
+ return ret;
+}
+
+static void __init unmap_fw_vendor(const void *fw_vendor, size_t size)
+{
+ early_memunmap((void *)fw_vendor, size);
+}
+#else
+#define map_fw_vendor(p, s) __va(p)
+#define unmap_fw_vendor(v, s)
+#endif
+
+void __init efi_systab_report_header(const efi_table_hdr_t *systab_hdr,
+ unsigned long fw_vendor)
+{
+ char vendor[100] = "unknown";
+ const efi_char16_t *c16;
+ size_t i;
+
+ c16 = map_fw_vendor(fw_vendor, sizeof(vendor) * sizeof(efi_char16_t));
+ if (c16) {
+ for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+ vendor[i] = c16[i];
+ vendor[i] = '\0';
+
+ unmap_fw_vendor(c16, sizeof(vendor) * sizeof(efi_char16_t));
+ }
+
+ pr_info("EFI v%u.%.02u by %s\n",
+ systab_hdr->revision >> 16,
+ systab_hdr->revision & 0xffff,
+ vendor);
+}
+
#ifdef CONFIG_EFI_VARS_MODULE
static int __init efi_load_efivars(void)
{