diff options
Diffstat (limited to 'drivers/firmware/dmi_scan.c')
-rw-r--r-- | drivers/firmware/dmi_scan.c | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 17afc51f3054..c5f7b4e9eb6c 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num, | |||
93 | const struct dmi_header *dm = (const struct dmi_header *)data; | 93 | const struct dmi_header *dm = (const struct dmi_header *)data; |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0] | ||
97 | */ | ||
98 | if (dm->type == DMI_ENTRY_END_OF_TABLE) | ||
99 | break; | ||
100 | |||
101 | /* | ||
96 | * We want to know the total length (formatted area and | 102 | * We want to know the total length (formatted area and |
97 | * strings) before decoding to make sure we won't run off the | 103 | * strings) before decoding to make sure we won't run off the |
98 | * table in dmi_decode or dmi_string | 104 | * table in dmi_decode or dmi_string |
@@ -107,7 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, | |||
107 | } | 113 | } |
108 | } | 114 | } |
109 | 115 | ||
110 | static u32 dmi_base; | 116 | static phys_addr_t dmi_base; |
111 | static u16 dmi_len; | 117 | static u16 dmi_len; |
112 | static u16 dmi_num; | 118 | static u16 dmi_num; |
113 | 119 | ||
@@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf) | |||
467 | 473 | ||
468 | if (memcmp(buf, "_SM_", 4) == 0 && | 474 | if (memcmp(buf, "_SM_", 4) == 0 && |
469 | buf[5] < 32 && dmi_checksum(buf, buf[5])) { | 475 | buf[5] < 32 && dmi_checksum(buf, buf[5])) { |
470 | smbios_ver = (buf[6] << 8) + buf[7]; | 476 | smbios_ver = get_unaligned_be16(buf + 6); |
471 | 477 | ||
472 | /* Some BIOS report weird SMBIOS version, fix that up */ | 478 | /* Some BIOS report weird SMBIOS version, fix that up */ |
473 | switch (smbios_ver) { | 479 | switch (smbios_ver) { |
@@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf) | |||
489 | buf += 16; | 495 | buf += 16; |
490 | 496 | ||
491 | if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) { | 497 | if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) { |
492 | dmi_num = (buf[13] << 8) | buf[12]; | 498 | dmi_num = get_unaligned_le16(buf + 12); |
493 | dmi_len = (buf[7] << 8) | buf[6]; | 499 | dmi_len = get_unaligned_le16(buf + 6); |
494 | dmi_base = (buf[11] << 24) | (buf[10] << 16) | | 500 | dmi_base = get_unaligned_le32(buf + 8); |
495 | (buf[9] << 8) | buf[8]; | ||
496 | 501 | ||
497 | if (dmi_walk_early(dmi_decode) == 0) { | 502 | if (dmi_walk_early(dmi_decode) == 0) { |
498 | if (smbios_ver) { | 503 | if (smbios_ver) { |
@@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf) | |||
514 | return 1; | 519 | return 1; |
515 | } | 520 | } |
516 | 521 | ||
522 | /* | ||
523 | * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy | ||
524 | * 32-bit entry point, there is no embedded DMI header (_DMI_) in here. | ||
525 | */ | ||
526 | static int __init dmi_smbios3_present(const u8 *buf) | ||
527 | { | ||
528 | if (memcmp(buf, "_SM3_", 5) == 0 && | ||
529 | buf[6] < 32 && dmi_checksum(buf, buf[6])) { | ||
530 | dmi_ver = get_unaligned_be16(buf + 7); | ||
531 | dmi_len = get_unaligned_le32(buf + 12); | ||
532 | dmi_base = get_unaligned_le64(buf + 16); | ||
533 | |||
534 | /* | ||
535 | * The 64-bit SMBIOS 3.0 entry point no longer has a field | ||
536 | * containing the number of structures present in the table. | ||
537 | * Instead, it defines the table size as a maximum size, and | ||
538 | * relies on the end-of-table structure type (#127) to be used | ||
539 | * to signal the end of the table. | ||
540 | * So let's define dmi_num as an upper bound as well: each | ||
541 | * structure has a 4 byte header, so dmi_len / 4 is an upper | ||
542 | * bound for the number of structures in the table. | ||
543 | */ | ||
544 | dmi_num = dmi_len / 4; | ||
545 | |||
546 | if (dmi_walk_early(dmi_decode) == 0) { | ||
547 | pr_info("SMBIOS %d.%d present.\n", | ||
548 | dmi_ver >> 8, dmi_ver & 0xFF); | ||
549 | dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); | ||
550 | pr_debug("DMI: %s\n", dmi_ids_string); | ||
551 | return 0; | ||
552 | } | ||
553 | } | ||
554 | return 1; | ||
555 | } | ||
556 | |||
517 | void __init dmi_scan_machine(void) | 557 | void __init dmi_scan_machine(void) |
518 | { | 558 | { |
519 | char __iomem *p, *q; | 559 | char __iomem *p, *q; |
520 | char buf[32]; | 560 | char buf[32]; |
521 | 561 | ||
522 | if (efi_enabled(EFI_CONFIG_TABLES)) { | 562 | if (efi_enabled(EFI_CONFIG_TABLES)) { |
563 | /* | ||
564 | * According to the DMTF SMBIOS reference spec v3.0.0, it is | ||
565 | * allowed to define both the 64-bit entry point (smbios3) and | ||
566 | * the 32-bit entry point (smbios), in which case they should | ||
567 | * either both point to the same SMBIOS structure table, or the | ||
568 | * table pointed to by the 64-bit entry point should contain a | ||
569 | * superset of the table contents pointed to by the 32-bit entry | ||
570 | * point (section 5.2) | ||
571 | * This implies that the 64-bit entry point should have | ||
572 | * precedence if it is defined and supported by the OS. If we | ||
573 | * have the 64-bit entry point, but fail to decode it, fall | ||
574 | * back to the legacy one (if available) | ||
575 | */ | ||
576 | if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) { | ||
577 | p = dmi_early_remap(efi.smbios3, 32); | ||
578 | if (p == NULL) | ||
579 | goto error; | ||
580 | memcpy_fromio(buf, p, 32); | ||
581 | dmi_early_unmap(p, 32); | ||
582 | |||
583 | if (!dmi_smbios3_present(buf)) { | ||
584 | dmi_available = 1; | ||
585 | goto out; | ||
586 | } | ||
587 | } | ||
523 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) | 588 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) |
524 | goto error; | 589 | goto error; |
525 | 590 | ||
@@ -552,7 +617,7 @@ void __init dmi_scan_machine(void) | |||
552 | memset(buf, 0, 16); | 617 | memset(buf, 0, 16); |
553 | for (q = p; q < p + 0x10000; q += 16) { | 618 | for (q = p; q < p + 0x10000; q += 16) { |
554 | memcpy_fromio(buf + 16, q, 16); | 619 | memcpy_fromio(buf + 16, q, 16); |
555 | if (!dmi_present(buf)) { | 620 | if (!dmi_smbios3_present(buf) || !dmi_present(buf)) { |
556 | dmi_available = 1; | 621 | dmi_available = 1; |
557 | dmi_early_unmap(p, 0x10000); | 622 | dmi_early_unmap(p, 0x10000); |
558 | goto out; | 623 | goto out; |