Commit 14fb4209 authored by Ard Biesheuvel's avatar Ard Biesheuvel

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: default avatarArd Biesheuvel <ardb@kernel.org>
parent b7846e6b
...@@ -479,10 +479,8 @@ void __init ...@@ -479,10 +479,8 @@ void __init
efi_init (void) efi_init (void)
{ {
void *efi_map_start, *efi_map_end; void *efi_map_start, *efi_map_end;
efi_char16_t *c16;
u64 efi_desc_size; u64 efi_desc_size;
char *cp, vendor[100] = "unknown"; char *cp;
int i;
set_bit(EFI_BOOT, &efi.flags); set_bit(EFI_BOOT, &efi.flags);
set_bit(EFI_64BIT, &efi.flags); set_bit(EFI_64BIT, &efi.flags);
...@@ -519,25 +517,10 @@ efi_init (void) ...@@ -519,25 +517,10 @@ efi_init (void)
*/ */
if (efi.systab == NULL) if (efi.systab == NULL)
panic("Whoa! Can't find EFI system table.\n"); panic("Whoa! Can't find EFI system table.\n");
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) if (efi_systab_check_header(&efi.systab->hdr, 1))
panic("Whoa! EFI system table signature incorrect\n"); panic("Whoa! EFI system table signature incorrect\n");
if ((efi.systab->hdr.revision >> 16) == 0)
printk(KERN_WARNING "Warning: EFI system table version "
"%d.%02d, expected 1.00 or greater\n",
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff);
/* Show what we know for posterity */
c16 = __va(efi.systab->fw_vendor);
if (c16) {
for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i)
vendor[i] = *c16++;
vendor[i] = '\0';
}
printk(KERN_INFO "EFI v%u.%.02u by %s:", efi_systab_report_header(&efi.systab->hdr, efi.systab->fw_vendor);
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff, vendor);
palo_phys = EFI_INVALID_TABLE_ADDR; palo_phys = EFI_INVALID_TABLE_ADDR;
......
...@@ -336,15 +336,23 @@ static int __init efi_systab_init(u64 phys) ...@@ -336,15 +336,23 @@ static int __init efi_systab_init(u64 phys)
{ {
int size = efi_enabled(EFI_64BIT) ? sizeof(efi_system_table_64_t) int size = efi_enabled(EFI_64BIT) ? sizeof(efi_system_table_64_t)
: sizeof(efi_system_table_32_t); : sizeof(efi_system_table_32_t);
const efi_table_hdr_t *hdr;
bool over4g = false; bool over4g = false;
void *p; void *p;
int ret;
p = early_memremap_ro(phys, size); hdr = p = early_memremap_ro(phys, size);
if (p == NULL) { if (p == NULL) {
pr_err("Couldn't map the system table!\n"); pr_err("Couldn't map the system table!\n");
return -ENOMEM; return -ENOMEM;
} }
ret = efi_systab_check_header(hdr, 1);
if (ret) {
early_memunmap(p, size);
return ret;
}
if (efi_enabled(EFI_64BIT)) { if (efi_enabled(EFI_64BIT)) {
const efi_system_table_64_t *systab64 = p; const efi_system_table_64_t *systab64 = p;
...@@ -411,6 +419,7 @@ static int __init efi_systab_init(u64 phys) ...@@ -411,6 +419,7 @@ static int __init efi_systab_init(u64 phys)
efi_systab.tables = systab32->tables; efi_systab.tables = systab32->tables;
} }
efi_systab_report_header(hdr, efi_systab.fw_vendor);
early_memunmap(p, size); early_memunmap(p, size);
if (IS_ENABLED(CONFIG_X86_32) && over4g) { if (IS_ENABLED(CONFIG_X86_32) && over4g) {
...@@ -419,28 +428,11 @@ static int __init efi_systab_init(u64 phys) ...@@ -419,28 +428,11 @@ static int __init efi_systab_init(u64 phys)
} }
efi.systab = &efi_systab; efi.systab = &efi_systab;
/*
* Verify the EFI Table
*/
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; return 0;
} }
void __init efi_init(void) void __init efi_init(void)
{ {
efi_char16_t *c16;
char vendor[100] = "unknown";
int i = 0;
if (IS_ENABLED(CONFIG_X86_32) && if (IS_ENABLED(CONFIG_X86_32) &&
(boot_params.efi_info.efi_systab_hi || (boot_params.efi_info.efi_systab_hi ||
boot_params.efi_info.efi_memmap_hi)) { boot_params.efi_info.efi_memmap_hi)) {
...@@ -458,24 +450,6 @@ void __init efi_init(void) ...@@ -458,24 +450,6 @@ void __init efi_init(void)
efi.fw_vendor = (unsigned long)efi.systab->fw_vendor; efi.fw_vendor = (unsigned long)efi.systab->fw_vendor;
efi.runtime = (unsigned long)efi.systab->runtime; efi.runtime = (unsigned long)efi.systab->runtime;
/*
* Show what we know for posterity
*/
c16 = early_memremap_ro(efi.systab->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';
early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
} else {
pr_err("Could not map the firmware vendor!\n");
}
pr_info("EFI v%u.%.02u by %s\n",
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff, vendor);
if (efi_reuse_config(efi.systab->tables, efi.systab->nr_tables)) if (efi_reuse_config(efi.systab->tables, efi.systab->nr_tables))
return; return;
......
...@@ -85,11 +85,9 @@ static void __init init_screen_info(void) ...@@ -85,11 +85,9 @@ static void __init init_screen_info(void)
static int __init uefi_init(void) static int __init uefi_init(void)
{ {
efi_char16_t *c16;
void *config_tables; void *config_tables;
size_t table_size; size_t table_size;
char vendor[100] = "unknown"; int retval;
int i, retval;
efi.systab = early_memremap_ro(efi_system_table, efi.systab = early_memremap_ro(efi_system_table,
sizeof(efi_system_table_t)); sizeof(efi_system_table_t));
...@@ -102,34 +100,14 @@ static int __init uefi_init(void) ...@@ -102,34 +100,14 @@ static int __init uefi_init(void)
if (IS_ENABLED(CONFIG_64BIT)) if (IS_ENABLED(CONFIG_64BIT))
set_bit(EFI_64BIT, &efi.flags); set_bit(EFI_64BIT, &efi.flags);
/* retval = efi_systab_check_header(&efi.systab->hdr, 2);
* Verify the EFI Table if (retval)
*/
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
pr_err("System table signature incorrect\n");
retval = -EINVAL;
goto out; 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; efi.runtime_version = efi.systab->hdr.revision;
/* Show what we know for posterity */ efi_systab_report_header(&efi.systab->hdr,
c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor), 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);
table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables), config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
......
...@@ -631,6 +631,67 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) ...@@ -631,6 +631,67 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
return ret; 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 #ifdef CONFIG_EFI_VARS_MODULE
static int __init efi_load_efivars(void) static int __init efi_load_efivars(void)
{ {
......
...@@ -616,6 +616,10 @@ static inline void efi_esrt_init(void) { } ...@@ -616,6 +616,10 @@ static inline void efi_esrt_init(void) { }
#endif #endif
extern int efi_config_parse_tables(void *config_tables, int count, int sz, extern int efi_config_parse_tables(void *config_tables, int count, int sz,
efi_config_table_type_t *arch_tables); efi_config_table_type_t *arch_tables);
extern int efi_systab_check_header(const efi_table_hdr_t *systab_hdr,
int min_major_version);
extern void efi_systab_report_header(const efi_table_hdr_t *systab_hdr,
unsigned long fw_vendor);
extern u64 efi_get_iobase (void); extern u64 efi_get_iobase (void);
extern int efi_mem_type(unsigned long phys_addr); extern int efi_mem_type(unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment