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 | |
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>
-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 | } |