diff options
| author | Ben Hutchings <ben@decadent.org.uk> | 2013-04-30 18:27:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 20:04:04 -0400 |
| commit | 79bae42d51a5d498500c890c19ef76df41d2bf59 (patch) | |
| tree | cf36c042e863100e2bc30a2ff8b4f3510bf7367d /drivers/firmware | |
| parent | c1d025e22e0ef167a4589cf5a6b2a32bfef0472c (diff) | |
dmi_scan: refactor dmi_scan_machine(), {smbios,dmi}_present()
Move the calls to memcpy_fromio() up into the loop in
dmi_scan_machine(), and move the signature checks back down into
dmi_decode(). We need to check at 16-byte intervals but keep a 32-byte
buffer for an SMBIOS entry, so shift the buffer after each iteration.
Merge smbios_present() into dmi_present(), so we look for an SMBIOS
signature at the beginning of the given buffer and then for a DMI
signature at an offset of 16 bytes.
[artem.savkov@gmail.com: use proper buf type in dmi_present()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Reported-by: Tim McGrath <tmhikaru@gmail.com>
Tested-by: Tim Mcgrath <tmhikaru@gmail.com>
Cc: Zhenzhong Duan <zhenzhong.duan@oracle.com>
Signed-off-by: Artem Savkov <artem.savkov@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/firmware')
| -rw-r--r-- | drivers/firmware/dmi_scan.c | 80 |
1 files changed, 37 insertions, 43 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 98c62081c034..b95159b33c39 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -419,22 +419,45 @@ static void __init dmi_format_ids(char *buf, size_t len) | |||
| 419 | dmi_get_system_info(DMI_BIOS_DATE)); | 419 | dmi_get_system_info(DMI_BIOS_DATE)); |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | static int __init dmi_present(const char __iomem *p) | 422 | static int __init dmi_present(const u8 *buf) |
| 423 | { | 423 | { |
| 424 | u8 buf[15]; | 424 | int smbios_ver; |
| 425 | 425 | ||
| 426 | memcpy_fromio(buf, p, 15); | 426 | if (memcmp(buf, "_SM_", 4) == 0 && |
| 427 | if (dmi_checksum(buf, 15)) { | 427 | buf[5] < 32 && dmi_checksum(buf, buf[5])) { |
| 428 | smbios_ver = (buf[6] << 8) + buf[7]; | ||
| 429 | |||
| 430 | /* Some BIOS report weird SMBIOS version, fix that up */ | ||
| 431 | switch (smbios_ver) { | ||
| 432 | case 0x021F: | ||
| 433 | case 0x0221: | ||
| 434 | pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", | ||
| 435 | smbios_ver & 0xFF, 3); | ||
| 436 | smbios_ver = 0x0203; | ||
| 437 | break; | ||
| 438 | case 0x0233: | ||
| 439 | pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); | ||
| 440 | smbios_ver = 0x0206; | ||
| 441 | break; | ||
| 442 | } | ||
| 443 | } else { | ||
| 444 | smbios_ver = 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | buf += 16; | ||
| 448 | |||
| 449 | if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) { | ||
| 428 | dmi_num = (buf[13] << 8) | buf[12]; | 450 | dmi_num = (buf[13] << 8) | buf[12]; |
| 429 | dmi_len = (buf[7] << 8) | buf[6]; | 451 | dmi_len = (buf[7] << 8) | buf[6]; |
| 430 | dmi_base = (buf[11] << 24) | (buf[10] << 16) | | 452 | dmi_base = (buf[11] << 24) | (buf[10] << 16) | |
| 431 | (buf[9] << 8) | buf[8]; | 453 | (buf[9] << 8) | buf[8]; |
| 432 | 454 | ||
| 433 | if (dmi_walk_early(dmi_decode) == 0) { | 455 | if (dmi_walk_early(dmi_decode) == 0) { |
| 434 | if (dmi_ver) | 456 | if (smbios_ver) { |
| 457 | dmi_ver = smbios_ver; | ||
| 435 | pr_info("SMBIOS %d.%d present.\n", | 458 | pr_info("SMBIOS %d.%d present.\n", |
| 436 | dmi_ver >> 8, dmi_ver & 0xFF); | 459 | dmi_ver >> 8, dmi_ver & 0xFF); |
| 437 | else { | 460 | } else { |
| 438 | dmi_ver = (buf[14] & 0xF0) << 4 | | 461 | dmi_ver = (buf[14] & 0xF0) << 4 | |
| 439 | (buf[14] & 0x0F); | 462 | (buf[14] & 0x0F); |
| 440 | pr_info("Legacy DMI %d.%d present.\n", | 463 | pr_info("Legacy DMI %d.%d present.\n", |
| @@ -445,40 +468,14 @@ static int __init dmi_present(const char __iomem *p) | |||
| 445 | return 0; | 468 | return 0; |
| 446 | } | 469 | } |
| 447 | } | 470 | } |
| 448 | dmi_ver = 0; | ||
| 449 | return 1; | ||
| 450 | } | ||
| 451 | 471 | ||
| 452 | static int __init smbios_present(const char __iomem *p) | ||
| 453 | { | ||
| 454 | u8 buf[32]; | ||
| 455 | |||
| 456 | memcpy_fromio(buf, p, 32); | ||
| 457 | if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { | ||
| 458 | dmi_ver = (buf[6] << 8) + buf[7]; | ||
| 459 | |||
| 460 | /* Some BIOS report weird SMBIOS version, fix that up */ | ||
| 461 | switch (dmi_ver) { | ||
| 462 | case 0x021F: | ||
| 463 | case 0x0221: | ||
| 464 | pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", | ||
| 465 | dmi_ver & 0xFF, 3); | ||
| 466 | dmi_ver = 0x0203; | ||
| 467 | break; | ||
| 468 | case 0x0233: | ||
| 469 | pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); | ||
| 470 | dmi_ver = 0x0206; | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); | ||
| 474 | } | ||
| 475 | return 1; | 472 | return 1; |
| 476 | } | 473 | } |
| 477 | 474 | ||
| 478 | void __init dmi_scan_machine(void) | 475 | void __init dmi_scan_machine(void) |
| 479 | { | 476 | { |
| 480 | char __iomem *p, *q; | 477 | char __iomem *p, *q; |
| 481 | int rc; | 478 | char buf[32]; |
| 482 | 479 | ||
| 483 | if (efi_enabled(EFI_CONFIG_TABLES)) { | 480 | if (efi_enabled(EFI_CONFIG_TABLES)) { |
| 484 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) | 481 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) |
| @@ -491,10 +488,10 @@ void __init dmi_scan_machine(void) | |||
| 491 | p = dmi_ioremap(efi.smbios, 32); | 488 | p = dmi_ioremap(efi.smbios, 32); |
| 492 | if (p == NULL) | 489 | if (p == NULL) |
| 493 | goto error; | 490 | goto error; |
| 494 | 491 | memcpy_fromio(buf, p, 32); | |
| 495 | rc = smbios_present(p); | ||
| 496 | dmi_iounmap(p, 32); | 492 | dmi_iounmap(p, 32); |
| 497 | if (!rc) { | 493 | |
| 494 | if (!dmi_present(buf)) { | ||
| 498 | dmi_available = 1; | 495 | dmi_available = 1; |
| 499 | goto out; | 496 | goto out; |
| 500 | } | 497 | } |
| @@ -509,18 +506,15 @@ void __init dmi_scan_machine(void) | |||
| 509 | if (p == NULL) | 506 | if (p == NULL) |
| 510 | goto error; | 507 | goto error; |
| 511 | 508 | ||
| 509 | memset(buf, 0, 16); | ||
| 512 | for (q = p; q < p + 0x10000; q += 16) { | 510 | for (q = p; q < p + 0x10000; q += 16) { |
| 513 | if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) | 511 | memcpy_fromio(buf + 16, q, 16); |
| 514 | rc = smbios_present(q); | 512 | if (!dmi_present(buf)) { |
| 515 | else if (memcmp(q, "_DMI_", 5) == 0) | ||
| 516 | rc = dmi_present(q); | ||
| 517 | else | ||
| 518 | continue; | ||
| 519 | if (!rc) { | ||
| 520 | dmi_available = 1; | 513 | dmi_available = 1; |
| 521 | dmi_iounmap(p, 0x10000); | 514 | dmi_iounmap(p, 0x10000); |
| 522 | goto out; | 515 | goto out; |
| 523 | } | 516 | } |
| 517 | memcpy(buf, buf + 16, 16); | ||
| 524 | } | 518 | } |
| 525 | dmi_iounmap(p, 0x10000); | 519 | dmi_iounmap(p, 0x10000); |
| 526 | } | 520 | } |
