diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/dmi_scan.c | 38 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 7 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/fdt.c | 7 |
4 files changed, 31 insertions, 23 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 2eebd28b4c40..6e45a43ffe84 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -17,7 +17,9 @@ */ static const char dmi_empty_string[] = " "; -static u16 __initdata dmi_ver; +static u32 dmi_ver __initdata; +static u32 dmi_len; +static u16 dmi_num; /* * Catch too early calls to dmi_check_system(): */ @@ -78,7 +80,7 @@ static const char * __init dmi_string(const struct dmi_header *dm, u8 s) * We have to be cautious here. We have seen BIOSes with DMI pointers * pointing to completely the wrong place for example */ -static void dmi_table(u8 *buf, u32 len, int num, +static void dmi_table(u8 *buf, void (*decode)(const struct dmi_header *, void *), void *private_data) { @@ -91,8 +93,8 @@ static void dmi_table(u8 *buf, u32 len, int num, * off the end of the table (should never happen but sometimes does * on bogus implementations.) */ - while ((!num || i < num) && - (data - buf + sizeof(struct dmi_header)) <= len) { + while ((!dmi_num || i < dmi_num) && + (data - buf + sizeof(struct dmi_header)) <= dmi_len) { const struct dmi_header *dm = (const struct dmi_header *)data; /* @@ -101,9 +103,9 @@ static void dmi_table(u8 *buf, u32 len, int num, * table in dmi_decode or dmi_string */ data += dm->length; - while ((data - buf < len - 1) && (data[0] || data[1])) + while ((data - buf < dmi_len - 1) && (data[0] || data[1])) data++; - if (data - buf < len - 1) + if (data - buf < dmi_len - 1) decode(dm, private_data); /* @@ -118,8 +120,6 @@ static void dmi_table(u8 *buf, u32 len, int num, } static phys_addr_t dmi_base; -static u32 dmi_len; -static u16 dmi_num; static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, void *)) @@ -130,7 +130,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, if (buf == NULL) return -1; - dmi_table(buf, dmi_len, dmi_num, decode, NULL); + dmi_table(buf, decode, NULL); add_device_randomness(buf, dmi_len); @@ -201,7 +201,7 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, * the UUID are supposed to be little-endian encoded. The specification * says that this is the defacto standard. */ - if (dmi_ver >= 0x0206) + if (dmi_ver >= 0x020600) sprintf(s, "%pUL", d); else sprintf(s, "%pUB", d); @@ -473,7 +473,7 @@ static void __init dmi_format_ids(char *buf, size_t len) */ static int __init dmi_present(const u8 *buf) { - int smbios_ver; + u32 smbios_ver; if (memcmp(buf, "_SM_", 4) == 0 && buf[5] < 32 && dmi_checksum(buf, buf[5])) { @@ -506,14 +506,16 @@ static int __init dmi_present(const u8 *buf) if (dmi_walk_early(dmi_decode) == 0) { if (smbios_ver) { dmi_ver = smbios_ver; - pr_info("SMBIOS %d.%d present.\n", - dmi_ver >> 8, dmi_ver & 0xFF); + pr_info("SMBIOS %d.%d%s present.\n", + dmi_ver >> 8, dmi_ver & 0xFF, + (dmi_ver < 0x0300) ? "" : ".x"); } else { dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F); pr_info("Legacy DMI %d.%d present.\n", dmi_ver >> 8, dmi_ver & 0xFF); } + dmi_ver <<= 8; dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string); return 0; @@ -531,14 +533,16 @@ static int __init dmi_smbios3_present(const u8 *buf) { if (memcmp(buf, "_SM3_", 5) == 0 && buf[6] < 32 && dmi_checksum(buf, buf[6])) { - dmi_ver = get_unaligned_be16(buf + 7); + dmi_ver = get_unaligned_be32(buf + 6); + dmi_ver &= 0xFFFFFF; dmi_num = 0; /* No longer specified */ dmi_len = get_unaligned_le32(buf + 12); dmi_base = get_unaligned_le64(buf + 16); if (dmi_walk_early(dmi_decode) == 0) { - pr_info("SMBIOS %d.%d present.\n", - dmi_ver >> 8, dmi_ver & 0xFF); + pr_info("SMBIOS %d.%d.%d present.\n", + dmi_ver >> 16, (dmi_ver >> 8) & 0xFF, + dmi_ver & 0xFF); dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); pr_debug("DMI: %s\n", dmi_ids_string); return 0; @@ -893,7 +897,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *), if (buf == NULL) return -1; - dmi_table(buf, dmi_len, dmi_num, decode, private_data); + dmi_table(buf, decode, private_data); dmi_unmap(buf); return 0; diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index dcae482a9a17..e29560e6b40b 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -175,7 +175,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, unsigned long initrd_addr; u64 initrd_size = 0; unsigned long fdt_addr = 0; /* Original DTB */ - u64 fdt_size = 0; /* We don't get size from configuration table */ + unsigned long fdt_size = 0; char *cmdline_ptr = NULL; int cmdline_size = 0; unsigned long new_fdt_addr; @@ -239,8 +239,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=", - ~0UL, (unsigned long *)&fdt_addr, - (unsigned long *)&fdt_size); + ~0UL, &fdt_addr, &fdt_size); if (status != EFI_SUCCESS) { pr_efi_err(sys_table, "Failed to load device tree!\n"); @@ -252,7 +251,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, pr_efi(sys_table, "Using DTB from command line\n"); } else { /* Look for a device tree configuration table entry. */ - fdt_addr = (uintptr_t)get_fdt(sys_table); + fdt_addr = (uintptr_t)get_fdt(sys_table, &fdt_size); if (fdt_addr) pr_efi(sys_table, "Using DTB from configuration table\n"); } diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 47437b16b186..e334a01cf92f 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -41,7 +41,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, unsigned long fdt_addr, unsigned long fdt_size); -void *get_fdt(efi_system_table_t *sys_table); +void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size); void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, unsigned long desc_size, efi_memory_desc_t *runtime_map, diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 91da56c4fd54..ef5d764e2a27 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -323,7 +323,7 @@ fail: return EFI_LOAD_ERROR; } -void *get_fdt(efi_system_table_t *sys_table) +void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size) { efi_guid_t fdt_guid = DEVICE_TREE_GUID; efi_config_table_t *tables; @@ -336,6 +336,11 @@ void *get_fdt(efi_system_table_t *sys_table) for (i = 0; i < sys_table->nr_tables; i++) if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) { fdt = (void *) tables[i].table; + if (fdt_check_header(fdt) != 0) { + pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n"); + return NULL; + } + *fdt_size = fdt_totalsize(fdt); break; } |