Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ben Hutchings and committed by
Linus Torvalds
79bae42d c1d025e2

+37 -43
+37 -43
drivers/firmware/dmi_scan.c
··· 419 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); 427 - if (dmi_checksum(buf, 15)) { 426 + if (memcmp(buf, "_SM_", 4) == 0 && 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 450 dmi_num = (buf[13] << 8) | buf[12]; 429 451 dmi_len = (buf[7] << 8) | buf[6]; 430 452 dmi_base = (buf[11] << 24) | (buf[10] << 16) | 431 453 (buf[9] << 8) | buf[8]; 432 454 433 455 if (dmi_walk_early(dmi_decode) == 0) { 434 - if (dmi_ver) 456 + if (smbios_ver) { 457 + dmi_ver = smbios_ver; 435 458 pr_info("SMBIOS %d.%d present.\n", 436 459 dmi_ver >> 8, dmi_ver & 0xFF); 437 - else { 460 + } else { 438 461 dmi_ver = (buf[14] & 0xF0) << 4 | 439 462 (buf[14] & 0x0F); 440 463 pr_info("Legacy DMI %d.%d present.\n", ··· 468 445 return 0; 469 446 } 470 447 } 471 - dmi_ver = 0; 472 - return 1; 473 - } 474 448 475 - static int __init smbios_present(const char __iomem *p) 476 - { 477 - u8 buf[32]; 478 - 479 - memcpy_fromio(buf, p, 32); 480 - if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { 481 - dmi_ver = (buf[6] << 8) + buf[7]; 482 - 483 - /* Some BIOS report weird SMBIOS version, fix that up */ 484 - switch (dmi_ver) { 485 - case 0x021F: 486 - case 0x0221: 487 - pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 488 - dmi_ver & 0xFF, 3); 489 - dmi_ver = 0x0203; 490 - break; 491 - case 0x0233: 492 - pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); 493 - dmi_ver = 0x0206; 494 - break; 495 - } 496 - return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); 497 - } 498 449 return 1; 499 450 } 500 451 501 452 void __init dmi_scan_machine(void) 502 453 { 503 454 char __iomem *p, *q; 504 - int rc; 455 + char buf[32]; 505 456 506 457 if (efi_enabled(EFI_CONFIG_TABLES)) { 507 458 if (efi.smbios == EFI_INVALID_TABLE_ADDR) ··· 488 491 p = dmi_ioremap(efi.smbios, 32); 489 492 if (p == NULL) 490 493 goto error; 491 - 492 - rc = smbios_present(p); 494 + memcpy_fromio(buf, p, 32); 493 495 dmi_iounmap(p, 32); 494 - if (!rc) { 496 + 497 + if (!dmi_present(buf)) { 495 498 dmi_available = 1; 496 499 goto out; 497 500 } ··· 506 509 if (p == NULL) 507 510 goto error; 508 511 512 + memset(buf, 0, 16); 509 513 for (q = p; q < p + 0x10000; q += 16) { 510 - if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) 511 - rc = smbios_present(q); 512 - else if (memcmp(q, "_DMI_", 5) == 0) 513 - rc = dmi_present(q); 514 - else 515 - continue; 516 - if (!rc) { 514 + memcpy_fromio(buf + 16, q, 16); 515 + if (!dmi_present(buf)) { 517 516 dmi_available = 1; 518 517 dmi_iounmap(p, 0x10000); 519 518 goto out; 520 519 } 520 + memcpy(buf, buf + 16, 16); 521 521 } 522 522 dmi_iounmap(p, 0x10000); 523 523 }