aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2013-04-30 18:27:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 20:04:04 -0400
commit79bae42d51a5d498500c890c19ef76df41d2bf59 (patch)
treecf36c042e863100e2bc30a2ff8b4f3510bf7367d
parentc1d025e22e0ef167a4589cf5a6b2a32bfef0472c (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.c80
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
422static int __init dmi_present(const char __iomem *p) 422static 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
452static 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
478void __init dmi_scan_machine(void) 475void __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 }