|
@@ -22,6 +22,9 @@ static u16 __initdata dmi_ver;
|
|
|
*/
|
|
|
static int dmi_initialized;
|
|
|
|
|
|
+/* DMI system identification string used during boot */
|
|
|
+static char dmi_ids_string[128] __initdata;
|
|
|
+
|
|
|
static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
|
|
|
{
|
|
|
const u8 *bp = ((u8 *) dm) + dm->length;
|
|
@@ -376,99 +379,103 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void __init print_filtered(const char *info)
|
|
|
+static int __init print_filtered(char *buf, size_t len, const char *info)
|
|
|
{
|
|
|
+ int c = 0;
|
|
|
const char *p;
|
|
|
|
|
|
if (!info)
|
|
|
- return;
|
|
|
+ return c;
|
|
|
|
|
|
for (p = info; *p; p++)
|
|
|
if (isprint(*p))
|
|
|
- printk(KERN_CONT "%c", *p);
|
|
|
+ c += scnprintf(buf + c, len - c, "%c", *p);
|
|
|
else
|
|
|
- printk(KERN_CONT "\\x%02x", *p & 0xff);
|
|
|
+ c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff);
|
|
|
+ return c;
|
|
|
}
|
|
|
|
|
|
-static void __init dmi_dump_ids(void)
|
|
|
+static void __init dmi_format_ids(char *buf, size_t len)
|
|
|
{
|
|
|
+ int c = 0;
|
|
|
const char *board; /* Board Name is optional */
|
|
|
|
|
|
- printk(KERN_DEBUG "DMI: ");
|
|
|
- print_filtered(dmi_get_system_info(DMI_SYS_VENDOR));
|
|
|
- printk(KERN_CONT " ");
|
|
|
- print_filtered(dmi_get_system_info(DMI_PRODUCT_NAME));
|
|
|
+ c += print_filtered(buf + c, len - c,
|
|
|
+ dmi_get_system_info(DMI_SYS_VENDOR));
|
|
|
+ c += scnprintf(buf + c, len - c, " ");
|
|
|
+ c += print_filtered(buf + c, len - c,
|
|
|
+ dmi_get_system_info(DMI_PRODUCT_NAME));
|
|
|
+
|
|
|
board = dmi_get_system_info(DMI_BOARD_NAME);
|
|
|
if (board) {
|
|
|
- printk(KERN_CONT "/");
|
|
|
- print_filtered(board);
|
|
|
+ c += scnprintf(buf + c, len - c, "/");
|
|
|
+ c += print_filtered(buf + c, len - c, board);
|
|
|
}
|
|
|
- printk(KERN_CONT ", BIOS ");
|
|
|
- print_filtered(dmi_get_system_info(DMI_BIOS_VERSION));
|
|
|
- printk(KERN_CONT " ");
|
|
|
- print_filtered(dmi_get_system_info(DMI_BIOS_DATE));
|
|
|
- printk(KERN_CONT "\n");
|
|
|
+ c += scnprintf(buf + c, len - c, ", BIOS ");
|
|
|
+ c += print_filtered(buf + c, len - c,
|
|
|
+ dmi_get_system_info(DMI_BIOS_VERSION));
|
|
|
+ c += scnprintf(buf + c, len - c, " ");
|
|
|
+ c += print_filtered(buf + c, len - c,
|
|
|
+ dmi_get_system_info(DMI_BIOS_DATE));
|
|
|
}
|
|
|
|
|
|
-static int __init dmi_present(const char __iomem *p)
|
|
|
+static int __init dmi_present(const u8 *buf)
|
|
|
{
|
|
|
- u8 buf[15];
|
|
|
+ int smbios_ver;
|
|
|
+
|
|
|
+ if (memcmp(buf, "_SM_", 4) == 0 &&
|
|
|
+ buf[5] < 32 && dmi_checksum(buf, buf[5])) {
|
|
|
+ smbios_ver = (buf[6] << 8) + buf[7];
|
|
|
+
|
|
|
+ /* Some BIOS report weird SMBIOS version, fix that up */
|
|
|
+ switch (smbios_ver) {
|
|
|
+ case 0x021F:
|
|
|
+ case 0x0221:
|
|
|
+ pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
|
|
|
+ smbios_ver & 0xFF, 3);
|
|
|
+ smbios_ver = 0x0203;
|
|
|
+ break;
|
|
|
+ case 0x0233:
|
|
|
+ pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
|
|
|
+ smbios_ver = 0x0206;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ smbios_ver = 0;
|
|
|
+ }
|
|
|
|
|
|
- memcpy_fromio(buf, p, 15);
|
|
|
- if (dmi_checksum(buf, 15)) {
|
|
|
+ buf += 16;
|
|
|
+
|
|
|
+ if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
|
|
|
dmi_num = (buf[13] << 8) | buf[12];
|
|
|
dmi_len = (buf[7] << 8) | buf[6];
|
|
|
dmi_base = (buf[11] << 24) | (buf[10] << 16) |
|
|
|
(buf[9] << 8) | buf[8];
|
|
|
|
|
|
if (dmi_walk_early(dmi_decode) == 0) {
|
|
|
- if (dmi_ver)
|
|
|
+ if (smbios_ver) {
|
|
|
+ dmi_ver = smbios_ver;
|
|
|
pr_info("SMBIOS %d.%d present.\n",
|
|
|
dmi_ver >> 8, dmi_ver & 0xFF);
|
|
|
- else {
|
|
|
+ } else {
|
|
|
dmi_ver = (buf[14] & 0xF0) << 4 |
|
|
|
(buf[14] & 0x0F);
|
|
|
pr_info("Legacy DMI %d.%d present.\n",
|
|
|
dmi_ver >> 8, dmi_ver & 0xFF);
|
|
|
}
|
|
|
- dmi_dump_ids();
|
|
|
+ dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
|
|
|
+ printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
- dmi_ver = 0;
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-static int __init smbios_present(const char __iomem *p)
|
|
|
-{
|
|
|
- u8 buf[32];
|
|
|
|
|
|
- memcpy_fromio(buf, p, 32);
|
|
|
- if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
|
|
|
- dmi_ver = (buf[6] << 8) + buf[7];
|
|
|
-
|
|
|
- /* Some BIOS report weird SMBIOS version, fix that up */
|
|
|
- switch (dmi_ver) {
|
|
|
- case 0x021F:
|
|
|
- case 0x0221:
|
|
|
- pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
|
|
|
- dmi_ver & 0xFF, 3);
|
|
|
- dmi_ver = 0x0203;
|
|
|
- break;
|
|
|
- case 0x0233:
|
|
|
- pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
|
|
|
- dmi_ver = 0x0206;
|
|
|
- break;
|
|
|
- }
|
|
|
- return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
|
|
|
- }
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
void __init dmi_scan_machine(void)
|
|
|
{
|
|
|
char __iomem *p, *q;
|
|
|
- int rc;
|
|
|
+ char buf[32];
|
|
|
|
|
|
if (efi_enabled(EFI_CONFIG_TABLES)) {
|
|
|
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
|
|
@@ -481,10 +488,10 @@ void __init dmi_scan_machine(void)
|
|
|
p = dmi_ioremap(efi.smbios, 32);
|
|
|
if (p == NULL)
|
|
|
goto error;
|
|
|
-
|
|
|
- rc = smbios_present(p);
|
|
|
+ memcpy_fromio(buf, p, 32);
|
|
|
dmi_iounmap(p, 32);
|
|
|
- if (!rc) {
|
|
|
+
|
|
|
+ if (!dmi_present(buf)) {
|
|
|
dmi_available = 1;
|
|
|
goto out;
|
|
|
}
|
|
@@ -499,18 +506,15 @@ void __init dmi_scan_machine(void)
|
|
|
if (p == NULL)
|
|
|
goto error;
|
|
|
|
|
|
+ memset(buf, 0, 16);
|
|
|
for (q = p; q < p + 0x10000; q += 16) {
|
|
|
- if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
|
|
|
- rc = smbios_present(q);
|
|
|
- else if (memcmp(q, "_DMI_", 5) == 0)
|
|
|
- rc = dmi_present(q);
|
|
|
- else
|
|
|
- continue;
|
|
|
- if (!rc) {
|
|
|
+ memcpy_fromio(buf + 16, q, 16);
|
|
|
+ if (!dmi_present(buf)) {
|
|
|
dmi_available = 1;
|
|
|
dmi_iounmap(p, 0x10000);
|
|
|
goto out;
|
|
|
}
|
|
|
+ memcpy(buf, buf + 16, 16);
|
|
|
}
|
|
|
dmi_iounmap(p, 0x10000);
|
|
|
}
|
|
@@ -520,6 +524,19 @@ void __init dmi_scan_machine(void)
|
|
|
dmi_initialized = 1;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
|
|
|
+ *
|
|
|
+ * Invoke dump_stack_set_arch_desc() with DMI system information so that
|
|
|
+ * DMI identifiers are printed out on task dumps. Arch boot code should
|
|
|
+ * call this function after dmi_scan_machine() if it wants to print out DMI
|
|
|
+ * identifiers on task dumps.
|
|
|
+ */
|
|
|
+void __init dmi_set_dump_stack_arch_desc(void)
|
|
|
+{
|
|
|
+ dump_stack_set_arch_desc("%s", dmi_ids_string);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* dmi_matches - check if dmi_system_id structure matches system DMI data
|
|
|
* @dmi: pointer to the dmi_system_id structure to check
|