diff options
Diffstat (limited to 'drivers/firmware')
| -rw-r--r-- | drivers/firmware/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/firmware/dmi_scan.c | 26 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 11 | ||||
| -rw-r--r-- | drivers/firmware/efi/efivars.c | 3 |
4 files changed, 34 insertions, 7 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 93876302fb2e..074787281c94 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -64,6 +64,7 @@ config DELL_RBU tristate "BIOS update support for DELL systems via sysfs" depends on X86 select FW_LOADER + select FW_LOADER_USER_HELPER help Say m if you want to have the option of updating the BIOS for your DELL system. Note you need a Dell OpenManage or Dell Update package (DUP) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b95159b33c39..232fa8fce26a 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -419,6 +419,13 @@ static void __init dmi_format_ids(char *buf, size_t len) dmi_get_system_info(DMI_BIOS_DATE)); } +/* + * Check for DMI/SMBIOS headers in the system firmware image. Any + * SMBIOS header must start 16 bytes before the DMI header, so take a + * 32 byte buffer and check for DMI at offset 16 and SMBIOS at offset + * 0. If the DMI header is present, set dmi_ver accordingly (SMBIOS + * takes precedence) and return 0. Otherwise return 1. + */ static int __init dmi_present(const u8 *buf) { int smbios_ver; @@ -506,6 +513,13 @@ void __init dmi_scan_machine(void) if (p == NULL) goto error; + /* + * Iterate over all possible DMI header addresses q. + * Maintain the 32 bytes around q in buf. On the + * first iteration, substitute zero for the + * out-of-range bytes so there is no chance of falsely + * detecting an SMBIOS header. + */ memset(buf, 0, 16); for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); @@ -551,9 +565,15 @@ static bool dmi_matches(const struct dmi_system_id *dmi) int s = dmi->matches[i].slot; if (s == DMI_NONE) break; - if (dmi_ident[s] - && strstr(dmi_ident[s], dmi->matches[i].substr)) - continue; + if (dmi_ident[s]) { + if (!dmi->matches[i].exact_match && + strstr(dmi_ident[s], dmi->matches[i].substr)) + continue; + else if (dmi->matches[i].exact_match && + !strcmp(dmi_ident[s], dmi->matches[i].substr)) + continue; + } + /* No match */ return false; } diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 202d2c85ba2e..73de5a9c2247 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -79,10 +79,9 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) &entry->var.DataSize, entry->var.Data); size = entry->var.DataSize; - *cb_data->buf = kmalloc(size, GFP_KERNEL); + *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL); if (*cb_data->buf == NULL) return -ENOMEM; - memcpy(*cb_data->buf, entry->var.Data, size); return size; } @@ -104,7 +103,7 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, static int efi_pstore_write(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, - unsigned int part, int count, size_t size, + unsigned int part, int count, size_t hsize, size_t size, struct pstore_info *psi) { char name[DUMP_NAME_LEN]; @@ -236,7 +235,11 @@ static __init int efivars_pstore_init(void) efi_pstore_info.bufsize = 1024; spin_lock_init(&efi_pstore_info.buf_lock); - pstore_register(&efi_pstore_info); + if (pstore_register(&efi_pstore_info)) { + kfree(efi_pstore_info.buf); + efi_pstore_info.buf = NULL; + efi_pstore_info.bufsize = 0; + } return 0; } diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 8bd1bb6dbe47..8a7432a4b413 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -583,6 +583,9 @@ int efivars_sysfs_init(void) struct kobject *parent_kobj = efivars_kobject(); int error = 0; + if (!efi_enabled(EFI_RUNTIME_SERVICES)) + return -ENODEV; + /* No efivars has been registered yet */ if (!parent_kobj) return 0; |
