diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2026-03-10 09:31:17 +0100 |
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2026-03-10 09:31:17 +0100 |
| commit | 22f77b46ab555f57523990094a3e40a55f2c492a (patch) | |
| tree | 0b2dad175ecf9514c5c9d8fb9473010c2337a3b3 /dmidecode.c | |
| parent | c9aac994d65f7bcc3659e3219d6729a24c803fcf (diff) | |
New upstream version 3.7upstream/3.7upstream
Diffstat (limited to 'dmidecode.c')
| -rw-r--r-- | dmidecode.c | 377 |
1 files changed, 240 insertions, 137 deletions
diff --git a/dmidecode.c b/dmidecode.c index 45a6c06..463f12b 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -2,7 +2,7 @@ * DMI Decode * * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> - * Copyright (C) 2002-2024 Jean Delvare <jdelvare@suse.de> + * Copyright (C) 2002-2025 Jean Delvare <jdelvare@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -85,12 +85,11 @@ #include "dmioem.h" #include "dmioutput.h" -#define out_of_spec "<OUT OF SPEC>" static const char *bad_index = "<BAD INDEX>"; enum cpuid_type cpuid_type = cpuid_none; -#define SUPPORTED_SMBIOS_VER 0x030700 +#define SUPPORTED_SMBIOS_VER 0x030900 #define FLAG_NO_FILE_OFFSET (1 << 0) #define FLAG_STOP_AT_EOT (1 << 1) @@ -163,7 +162,7 @@ const char *dmi_string(const struct dmi_header *dm, u8 s) static const char *dmi_smbios_structure_type(u8 code) { static const char *type[] = { - "BIOS", /* 0 */ + "Platform Firmware", /* 0 */ "System", "Base Board", "Chassis", @@ -176,7 +175,7 @@ static const char *dmi_smbios_structure_type(u8 code) "On Board Devices", "OEM Strings", "System Configuration Options", - "BIOS Language", + "Firmware Language", "Group Associations", "System Event Log", "Physical Memory Array", @@ -274,28 +273,29 @@ static void dmi_dump(const struct dmi_header *h) } } -/* shift is 0 if the value is in bytes, 1 if it is in kilobytes */ -void dmi_print_memory_size(const char *attr, u64 code, int shift) +/* shift is 0 if the value is in bytes, 1 if it is in kibibytes */ +void dmi_print_memory_size(void (*print_cb)(const char *name, const char *format, ...), + const char *attr, u64 code, int shift) { unsigned long capacity; u16 split[7]; static const char *unit[8] = { - "bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB" + "bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB" }; int i; /* - * We split the overall size in powers of thousand: EB, PB, TB, GB, - * MB, kB and B. In practice, it is expected that only one or two + * We split the overall size in powers of 1024: EiB, PiB, TiB, GiB, + * MiB, KiB and B. In practice, it is expected that only one or two * (consecutive) of these will be non-zero. */ - split[0] = code.l & 0x3FFUL; - split[1] = (code.l >> 10) & 0x3FFUL; - split[2] = (code.l >> 20) & 0x3FFUL; - split[3] = ((code.h << 2) & 0x3FCUL) | (code.l >> 30); - split[4] = (code.h >> 8) & 0x3FFUL; - split[5] = (code.h >> 18) & 0x3FFUL; - split[6] = code.h >> 28; + split[0] = code & 0x3FFULL; + split[1] = (code >> 10) & 0x3FFULL; + split[2] = (code >> 20) & 0x3FFULL; + split[3] = (code >> 30) & 0x3FFULL; + split[4] = (code >> 40) & 0x3FFULL; + split[5] = (code >> 50) & 0x3FFULL; + split[6] = (code >> 60) & 0x3FFULL; /* * Now we find the highest unit with a non-zero value. If the following @@ -315,11 +315,33 @@ void dmi_print_memory_size(const char *attr, u64 code, int shift) else capacity = split[i]; - pr_attr(attr, "%lu %s", capacity, unit[i + shift]); + print_cb(attr, "%lu %s", capacity, unit[i + shift]); +} + +/* shift is 0 if the value is in bytes, 1 if it is in kB, 2 if it is in MB */ +void dmi_print_storage_size(const char *attr, u64 code, unsigned int shift) +{ + u64 divisor; + static const char *unit[8] = { + "bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB" + }; + + /* + * We want to choose the unit which will let us display a number + * between 1.0 and 999.9. + */ + divisor = 1; + while (code / divisor >= 1000 && shift + 1 < ARRAY_SIZE(unit)) + { + shift++; + divisor *= 1000; + } + + pr_attr(attr, "%.1f %s", (float)code / divisor, unit[shift]); } /* - * 7.1 BIOS Information (Type 0) + * 7.1 Platform Firmware Information (Type 0) */ static void dmi_bios_runtime_size(u32 code) @@ -332,7 +354,7 @@ static void dmi_bios_runtime_size(u32 code) } else { - format = "%u kB"; + format = "%u KiB"; code >>= 10; } @@ -342,13 +364,12 @@ static void dmi_bios_runtime_size(u32 code) static void dmi_bios_rom_size(u8 code1, u16 code2) { static const char *unit[4] = { - "MB", "GB", out_of_spec, out_of_spec + "MiB", "GiB", out_of_spec, out_of_spec }; if (code1 != 0xFF) { - u64 s = { .l = (code1 + 1) << 6 }; - dmi_print_memory_size("ROM Size", s, 1); + dmi_print_memory_size(pr_attr, "ROM Size", (u64)(code1 + 1) << 6, 1); } else pr_attr("ROM Size", "%u %s", code2 & 0x3FFF, unit[code2 >> 14]); @@ -358,7 +379,7 @@ static void dmi_bios_characteristics(u64 code) { /* 7.1.1 */ static const char *characteristics[] = { - "BIOS characteristics not supported", /* 3 */ + "Firmware characteristics not supported", /* 3 */ "ISA is supported", "MCA is supported", "EISA is supported", @@ -366,13 +387,13 @@ static void dmi_bios_characteristics(u64 code) "PC Card (PCMCIA) is supported", "PNP is supported", "APM is supported", - "BIOS is upgradeable", - "BIOS shadowing is allowed", + "Firmware is upgradeable", + "Firmware shadowing is allowed", "VLB is supported", "ESCD support is available", "Boot from CD is supported", "Selectable boot is supported", - "BIOS ROM is socketed", + "Firmware ROM is socketed", "Boot from PC Card (PCMCIA) is supported", "EDD is supported", "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)", @@ -393,14 +414,14 @@ static void dmi_bios_characteristics(u64 code) /* * This isn't very clear what this bit is supposed to mean */ - if (code.l & (1 << 3)) + if (code & (1ULL << 3)) { pr_list_item("%s", characteristics[0]); return; } for (i = 4; i <= 31; i++) - if (code.l & (1 << i)) + if (code & (1ULL << i)) pr_list_item("%s", characteristics[i - 3]); } @@ -447,8 +468,8 @@ static void dmi_bios_characteristics_x2(u8 code) * 7.2 System Information (Type 1) */ -static void dmi_system_uuid(void (*print_cb)(const char *name, const char *format, ...), - const char *attr, const u8 *p, u16 ver) +void dmi_system_uuid(void (*print_cb)(const char *name, const char *format, ...), + const char *attr, const u8 *p, u16 ver) { int only0xFF = 1, only0x00 = 1; int i; @@ -626,10 +647,10 @@ static const char *dmi_chassis_type(u8 code) "Rack Mount Chassis", "Sealed-case PC", "Multi-system", - "CompactPCI", - "AdvancedTCA", + "Compact PCI", + "Advanced TCA", "Blade", - "Blade Enclosing", + "Blade Enclosure", "Tablet", "Convertible", "Detachable", @@ -730,6 +751,18 @@ static void dmi_chassis_elements(u8 count, u8 len, const u8 *p) pr_list_end(); } +static const char *dmi_chassis_rack_type(u8 code) +{ + static const char *type[] = { + "Unspecified", /* 0x00 */ + "OU" /* 0x01 */ + }; + + if (code <= 0x01) + return type[code]; + return out_of_spec; +} + /* * 7.5 Processor Information (Type 4) */ @@ -942,6 +975,7 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver) { 0xCD, "Core i5" }, { 0xCE, "Core i3" }, { 0xCF, "Core i9" }, + { 0xD0, "Xeon D" }, { 0xD2, "C7-M" }, { 0xD3, "C7-D" }, @@ -1011,6 +1045,15 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver) { 0x26F, "Multi-Core Loongson 3B 5xxx" }, { 0x270, "Multi-Core Loongson 3C 5xxx" }, { 0x271, "Multi-Core Loongson 3D 5xxx" }, + + { 0x300, "Core 3" }, + { 0x301, "Core 5" }, + { 0x302, "Core 7" }, + { 0x303, "Core 9" }, + { 0x304, "Core Ultra 3" }, + { 0x305, "Core Ultra 5" }, + { 0x306, "Core Ultra 7" }, + { 0x307, "Core Ultra 9" }, }; /* * Note to developers: when adding entries to this list, check if @@ -1140,8 +1183,9 @@ static enum cpuid_type dmi_get_cpuid_type(const struct dmi_header *h) void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...), const char *label, enum cpuid_type sig, const u8 *p) { - u32 eax, midr, jep106, soc_revision; - u16 dx; + u32 eax, midr, soc_revision; + u16 dx, soc_id; + u8 jep106_code, jep106_bank; switch (sig) { @@ -1181,12 +1225,12 @@ void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...) case cpuid_arm_soc_id: /* ARM with SOC ID */ /* - * If Soc ID is supported, the first DWORD is the JEP-106 code; - * the second DWORD is the SoC revision value. - */ - jep106 = DWORD(p); - soc_revision = DWORD(p + 4); - /* + * If SoC ID is supported, the first WORD is a SiP + * defined SoC ID; the next BYTE is the JEP-106 + * identification code of the SiP; the next BYTE is + * its bank index; lastly, the next DWORD is the SoC + * revision value. + * * According to SMC Calling Convention (SMCCC) v1.3 specification * (https://developer.arm.com/documentation/den0028/d/), the format * of the values returned by the SMCCC_ARCH_SOC_ID call is as follows: @@ -1201,9 +1245,14 @@ void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...) * Bit[31] must be zero * Bits[30:0] SoC revision */ + soc_id = WORD(p); + jep106_code = p[2] & 0x7F; + jep106_bank = p[3] & 0x7F; + soc_revision = DWORD(p + 4); + pr_attr("Signature", "JEP-106 Bank 0x%02x Manufacturer 0x%02x, SoC ID 0x%04x, SoC Revision 0x%08x", - (jep106 >> 24) & 0x7F, (jep106 >> 16) & 0x7F, jep106 & 0xFFFF, soc_revision); + jep106_bank, jep106_code, soc_id, soc_revision); return; case cpuid_x86_intel: /* Intel */ @@ -1369,8 +1418,8 @@ static const char *dmi_processor_status(u8 code) static const char *status[] = { "Unknown", /* 0x00 */ "Enabled", - "Disabled By User", - "Disabled By BIOS", + "Disabled by user", + "Disabled by firmware", "Idle", /* 0x04 */ out_of_spec, out_of_spec, @@ -1463,10 +1512,17 @@ static const char *dmi_processor_upgrade(u8 code) "Socket BGA1190", "Socket BGA4129", "Socket LGA4710", - "Socket LGA7529" /* 0x50 */ + "Socket LGA7529", + "Socket BGA1964", + "Socket BGA1792", + "Socket BGA2049", + "Socket BGA2551", + "Socket LGA1851", + "Socket BGA2114", + "Socket BGA2833" /* 0x57 */ }; - if (code >= 0x01 && code <= 0x50) + if (code >= 0x01 && code <= 0x57) return upgrade[code - 0x01]; return out_of_spec; } @@ -1710,7 +1766,7 @@ static void dmi_memory_module_size(const char *attr, u8 code) pr_attr(attr, "Not Installed"); return; default: - pr_attr(attr, "%u MB%s", 1 << (code & 0x7F), + pr_attr(attr, "%u MiB%s", 1 << (code & 0x7F), connection); } } @@ -1765,18 +1821,16 @@ static void dmi_cache_size_2(const char *attr, u32 code) if (code & 0x80000000) { - code &= 0x7FFFFFFFLU; - size.l = code << 6; - size.h = code >> 26; + code &= 0x7FFFFFFFULL; + size = (u64)code << 6; } else { - size.l = code; - size.h = 0; + size = code; } /* Use a more convenient unit for large cache size */ - dmi_print_memory_size(attr, size, 1); + dmi_print_memory_size(pr_attr, attr, size, 1); } static void dmi_cache_size(const char *attr, u16 code) @@ -2009,7 +2063,7 @@ static const char *dmi_port_type(u8 code) * 7.10 System Slots (Type 9) */ -static const char *dmi_slot_type(u8 code) +static void dmi_slot_type(u8 code, u8 length) { /* 7.10.1 */ static const char *type[] = { @@ -2102,14 +2156,35 @@ static const char *dmi_slot_type(u8 code) * Note to developers: when adding entries to these lists, check if * function dmi_slot_id below needs updating too. */ + const char *t, *suffix = ""; if (code >= 0x01 && code <= 0x28) - return type[code - 0x01]; - if (code == 0x30) - return type_0x30[code - 0x30]; - if (code >= 0xA0 && code <= 0xC6) - return type_0xA0[code - 0xA0]; - return out_of_spec; + t = type[code - 0x01]; + else if (code == 0x30) + t = type_0x30[code - 0x30]; + else if (code >= 0xA0 && code <= 0xC6) + t = type_0xA0[code - 0xA0]; + else + t = out_of_spec; + + /* For EDSFF slots, add the length suffix */ + switch (code) + { + case 0xC5: /* EDSFF E1 */ + case 0xC6: /* EDSFF E3 */ + switch (length) + { + case 0x03: /* Short */ + suffix = ".S"; + break; + case 0x04: /* Long */ + suffix = ".L"; + break; + } + break; + } + + pr_attr("Type", "%s%s", t, suffix); } static const char *dmi_slot_bus_width(u8 code) @@ -2188,11 +2263,20 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type) case 0x11: /* AGP */ case 0x12: /* PCI-X */ case 0x13: /* AGP */ - case 0x1F: /* PCI Express 2 */ - case 0x20: /* PCI Express 3 */ + case 0x14: /* M.2 */ + case 0x15: /* M.2 */ + case 0x16: /* M.2 */ + case 0x17: /* M.2 */ + case 0x1F: /* PCI Express 2 (U.2) */ + case 0x20: /* PCI Express 3 (U.2) */ case 0x21: /* PCI Express Mini */ case 0x22: /* PCI Express Mini */ case 0x23: /* PCI Express Mini */ + case 0x24: /* PCI Express 4 (U.2) */ + case 0x25: /* PCI Express 5 (U.2) */ + case 0x26: /* OCP */ + case 0x27: /* OCP */ + case 0x28: /* OCP */ case 0xA5: /* PCI Express */ case 0xA6: /* PCI Express */ case 0xA7: /* PCI Express */ @@ -2224,6 +2308,8 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type) case 0xC2: /* PCI Express 5 */ case 0xC3: /* PCI Express 5 */ case 0xC4: /* PCI Express 6+ */ + case 0xC5: /* EDSFF */ + case 0xC6: /* EDSFF */ pr_attr("ID", "%u", code1); break; case 0x07: /* PCMCIA */ @@ -2461,7 +2547,7 @@ static void dmi_system_configuration_options(const struct dmi_header *h) } /* - * 7.14 BIOS Language Information (Type 13) + * 7.14 Firmware Language Information (Type 13) */ static void dmi_bios_languages(const struct dmi_header *h) @@ -2752,10 +2838,10 @@ static void dmi_memory_device_size(u16 code) pr_attr("Size", "Unknown"); else { - u64 s = { .l = code & 0x7FFF }; + u64 s = (u64)code & 0x7FFFULL; if (!(code & 0x8000)) - s.l <<= 10; - dmi_print_memory_size("Size", s, 1); + s <<= 10; + dmi_print_memory_size(pr_attr, "Size", s, 1); } } @@ -2768,11 +2854,11 @@ static void dmi_memory_device_extended_size(u32 code) * as an integer without rounding */ if (code & 0x3FFUL) - pr_attr("Size", "%lu MB", (unsigned long)code); + pr_attr("Size", "%lu MiB", (unsigned long)code); else if (code & 0xFFC00UL) - pr_attr("Size", "%lu GB", (unsigned long)code >> 10); + pr_attr("Size", "%lu GiB", (unsigned long)code >> 10); else - pr_attr("Size", "%lu TB", (unsigned long)code >> 20); + pr_attr("Size", "%lu TiB", (unsigned long)code >> 20); } static void dmi_memory_voltage_value(const char *attr, u16 code) @@ -2803,10 +2889,13 @@ static const char *dmi_memory_device_form_factor(u8 code) "SODIMM", "SRIMM", "FB-DIMM", - "Die" /* 0x10 */ + "Die", + "CAMM", + "CUDIMM", + "CSODIMM" /* 0x13 */ }; - if (code >= 0x01 && code <= 0x10) + if (code >= 0x01 && code <= 0x13) return form_factor[code - 0x01]; return out_of_spec; } @@ -2860,10 +2949,11 @@ static const char *dmi_memory_device_type(u8 code) "HBM2", "DDR5", "LPDDR5", - "HBM3" /* 0x24 */ + "HBM3", + "MRDIMM" /* 0x25 */ }; - if (code >= 0x01 && code <= 0x24) + if (code >= 0x01 && code <= 0x25) return type[code - 0x01]; return out_of_spec; } @@ -2923,7 +3013,7 @@ static void dmi_memory_device_speed(const char *attr, u16 code1, u32 code2) } } -static void dmi_memory_technology(u8 code) +static const char *dmi_memory_technology(u8 code) { /* 7.18.6 */ static const char * const technology[] = { @@ -2933,12 +3023,12 @@ static void dmi_memory_technology(u8 code) "NVDIMM-N", "NVDIMM-F", "NVDIMM-P", - "Intel Optane DC persistent memory" /* 0x07 */ + "Intel Optane persistent memory", + "MRDIMM" /* 0x08 */ }; - if (code >= 0x01 && code <= 0x07) - pr_attr("Memory Technology", "%s", technology[code - 0x01]); - else - pr_attr("Memory Technology", "%s", out_of_spec); + if (code >= 0x01 && code <= 0x08) + return technology[code - 0x01]; + return out_of_spec; } static void dmi_memory_operating_mode_capability(u16 code) @@ -2967,7 +3057,7 @@ static void dmi_memory_operating_mode_capability(u16 code) } } -static void dmi_memory_manufacturer_id(const char *attr, u16 code) +void dmi_memory_manufacturer_id(const char *attr, u16 code) { /* 7.18.8 */ /* 7.18.10 */ @@ -2981,7 +3071,7 @@ static void dmi_memory_manufacturer_id(const char *attr, u16 code) (code & 0x7F) + 1, code >> 8); } -static void dmi_memory_product_id(const char *attr, u16 code) +void dmi_memory_product_id(const char *attr, u16 code) { /* 7.18.9 */ /* 7.18.11 */ @@ -2995,12 +3085,12 @@ static void dmi_memory_size(const char *attr, u64 code) { /* 7.18.12 */ /* 7.18.13 */ - if (code.h == 0xFFFFFFFF && code.l == 0xFFFFFFFF) + if (code == ~0ULL) pr_attr(attr, "Unknown"); - else if (code.h == 0x0 && code.l == 0x0) + else if (code == 0ULL) pr_attr(attr, "None"); else - dmi_print_memory_size(attr, code, 0); + dmi_print_memory_size(pr_attr, attr, code, 0); } static void dmi_memory_revision(const char *attr_type, u16 code, u8 mem_type) @@ -3127,21 +3217,15 @@ static void dmi_mapped_address_size(u32 code) if (code == 0) pr_attr("Range Size", "Invalid"); else - { - u64 size; - - size.h = 0; - size.l = code; - dmi_print_memory_size("Range Size", size, 1); - } + dmi_print_memory_size(pr_attr, "Range Size", (u64)code, 1); } static void dmi_mapped_address_extended_size(u64 start, u64 end) { - if (start.h == end.h && start.l == end.l) + if (start == end) pr_attr("Range Size", "Invalid"); else - dmi_print_memory_size("Range Size", u64_range(start, end), 0); + dmi_print_memory_size(pr_attr, "Range Size", end - start + 1, 0); } /* @@ -3566,10 +3650,10 @@ static const char *dmi_system_boot_status(u8 code) static void dmi_64bit_memory_error_address(const char *attr, u64 code) { - if (code.h == 0x80000000 && code.l == 0x00000000) + if (code == 0x8000000000000000ULL) pr_attr(attr, "Unknown"); else - pr_attr(attr, "0x%08X%08X", code.h, code.l); + pr_attr(attr, "0x%016llX", code); } /* @@ -3703,9 +3787,9 @@ static void dmi_ipmi_base_address(u8 type, const u8 *p, u8 lsb) else { u64 address = QWORD(p); - pr_attr("Base Address", "0x%08X%08X (%s)", - address.h, (address.l & ~1) | lsb, - address.l & 1 ? "I/O" : "Memory-mapped"); + pr_attr("Base Address", "0x%016llX (%s)", + (address & ~1ULL) | lsb, + (address & 1ULL) ? "I/O" : "Memory-mapped"); } } @@ -4374,14 +4458,14 @@ static void dmi_tpm_characteristics(u64 code) /* * This isn't very clear what this bit is supposed to mean */ - if (code.l & (1 << 2)) + if (code & (1ULL << 2)) { pr_list_item("%s", characteristics[0]); return; } for (i = 3; i <= 5; i++) - if (code.l & (1 << i)) + if (code & (1ULL << i)) pr_list_item("%s", characteristics[i - 2]); } @@ -4445,8 +4529,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) */ switch (h->type) { - case 0: /* 7.1 BIOS Information */ - pr_handle_name("BIOS Information"); + case 0: /* 7.1 Platform Firmware Information */ + pr_handle_name("Platform Firmware Information"); if (h->length < 0x12) break; pr_attr("Vendor", "%s", dmi_string(h, data[0x04])); @@ -4468,17 +4552,17 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) dmi_bios_rom_size(data[0x09], h->length < 0x1A ? 16 : WORD(data + 0x18)); pr_list_start("Characteristics", NULL); dmi_bios_characteristics(QWORD(data + 0x0A)); + if (h->length >= 0x13) + dmi_bios_characteristics_x1(data[0x12]); + if (h->length >= 0x14) + dmi_bios_characteristics_x2(data[0x13]); pr_list_end(); - if (h->length < 0x13) break; - dmi_bios_characteristics_x1(data[0x12]); - if (h->length < 0x14) break; - dmi_bios_characteristics_x2(data[0x13]); if (h->length < 0x18) break; if (data[0x14] != 0xFF && data[0x15] != 0xFF) - pr_attr("BIOS Revision", "%u.%u", + pr_attr("Platform Firmware Revision", "%u.%u", data[0x14], data[0x15]); if (data[0x16] != 0xFF && data[0x17] != 0xFF) - pr_attr("Firmware Revision", "%u.%u", + pr_attr("Embedded Controller Firmware Revision", "%u.%u", data[0x16], data[0x17]); break; @@ -4562,14 +4646,32 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) pr_attr("OEM Information", "0x%08X", DWORD(data + 0x0D)); if (h->length < 0x13) break; - dmi_chassis_height(data[0x11]); + if (data[0x11] != 0xFF) + dmi_chassis_height(data[0x11]); dmi_chassis_power_cords(data[0x12]); if (h->length < 0x15) break; if (h->length < 0x15 + data[0x13] * data[0x14]) break; dmi_chassis_elements(data[0x13], data[0x14], data + 0x15); if (h->length < 0x16 + data[0x13] * data[0x14]) break; - pr_attr("SKU Number", "%s", - dmi_string(h, data[0x15 + data[0x13] * data[0x14]])); + /* + * Many old implementations have stray zero bytes at + * the end of this record, probably due to some + * confusion regarding the preceding variable length + * section. Only decode the following fields if they + * are defined in the SMBIOS specification version + * which is implemented. + */ + if (ver >= 0x0207) + pr_attr("SKU Number", "%s", + dmi_string(h, data[0x15 + data[0x13] * data[0x14]])); + if (h->length < 0x18 + data[0x13] * data[0x14]) break; + if (ver >= 0x0309) + { + pr_attr("Rack Type", "%s", + dmi_chassis_rack_type(data[0x16 + data[0x13] * data[0x14]])); + pr_attr("Rack Height", "%hhu", + data[0x17 + data[0x13] * data[0x14]]); + } break; case 4: /* 7.5 Processor Information */ @@ -4586,7 +4688,12 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) dmi_processor_id(h); pr_attr("Version", "%s", dmi_string(h, data[0x10])); - dmi_processor_voltage("Voltage", data[0x11]); + /* + * Since SMBIOS 3.8.0, the processor voltage field + * is deprecated, so ignore it if no value is set. + */ + if (data[0x11]) + dmi_processor_voltage("Voltage", data[0x11]); dmi_processor_frequency("External Clock", data + 0x12); dmi_processor_frequency("Max Speed", data + 0x14); dmi_processor_frequency("Current Speed", data + 0x16); @@ -4645,9 +4752,9 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) dmi_memory_controller_interleave(data[0x06])); pr_attr("Current Interleave", "%s", dmi_memory_controller_interleave(data[0x07])); - pr_attr("Maximum Memory Module Size", "%u MB", + pr_attr("Maximum Memory Module Size", "%u MiB", 1 << data[0x08]); - pr_attr("Maximum Total Memory Size", "%u MB", + pr_attr("Maximum Total Memory Size", "%u MiB", data[0x0E] * (1 << data[0x08])); dmi_memory_controller_speeds("Supported Speeds", WORD(data + 0x09)); @@ -4727,7 +4834,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) if (h->length < 0x0C) break; pr_attr("Designation", "%s", dmi_string(h, data[0x04])); - pr_attr("Type", "%s", dmi_slot_type(data[0x05])); + dmi_slot_type(data[0x05], data[0x08]); pr_attr("Data Bus Width", "%s", dmi_slot_bus_width(data[0x06])); pr_attr("Current Usage", "%s", dmi_slot_current_usage(data[0x07])); @@ -4770,8 +4877,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) dmi_system_configuration_options(h); break; - case 13: /* 7.14 BIOS Language Information */ - pr_handle_name("BIOS Language Information"); + case 13: /* 7.14 Firmware Language Information */ + pr_handle_name("Firmware Language Information"); if (h->length < 0x16) break; if (ver >= 0x0201) { @@ -4838,17 +4945,15 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) if (h->length < 0x17) pr_attr("Maximum Capacity", "Unknown"); else - dmi_print_memory_size("Maximum Capacity", + dmi_print_memory_size(pr_attr, + "Maximum Capacity", QWORD(data + 0x0F), 0); } else { - u64 capacity; - - capacity.h = 0; - capacity.l = DWORD(data + 0x07); - dmi_print_memory_size("Maximum Capacity", - capacity, 1); + dmi_print_memory_size(pr_attr, + "Maximum Capacity", + DWORD(data + 0x07), 1); } if (!(opt.flags & FLAG_QUIET)) dmi_memory_array_error_handle(WORD(data + 0x0B)); @@ -4915,7 +5020,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) dmi_memory_voltage_value("Configured Voltage", WORD(data + 0x26)); if (h->length < 0x34) break; - dmi_memory_technology(data[0x28]); + pr_attr("Memory Technology", "%s", + dmi_memory_technology(data[0x28])); dmi_memory_operating_mode_capability(WORD(data + 0x29)); pr_attr("Firmware Version", "%s", dmi_string(h, data[0x2B])); @@ -4974,10 +5080,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) start = QWORD(data + 0x0F); end = QWORD(data + 0x17); - pr_attr("Starting Address", "0x%08X%08Xk", - start.h, start.l); - pr_attr("Ending Address", "0x%08X%08Xk", - end.h, end.l); + pr_attr("Starting Address", "0x%016llX", start); + pr_attr("Ending Address", "0x%016llX", end); dmi_mapped_address_extended_size(start, end); } else @@ -5007,10 +5111,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) start = QWORD(data + 0x13); end = QWORD(data + 0x1B); - pr_attr("Starting Address", "0x%08X%08Xk", - start.h, start.l); - pr_attr("Ending Address", "0x%08X%08Xk", - end.h, end.l); + pr_attr("Starting Address", "0x%016llX", start); + pr_attr("Ending Address", "0x%016llX", end); dmi_mapped_address_extended_size(start, end); } else @@ -5529,7 +5631,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver) break; default: - if (dmi_decode_oem(h)) + if (dmi_decode_oem(h, ver)) break; if (opt.flags & FLAG_QUIET) return; @@ -5932,7 +6034,8 @@ static int smbios3_decode(u8 *buf, size_t buf_len, const char *devmem, u32 flags buf[0x07], buf[0x08], buf[0x09]); offset = QWORD(buf + 0x10); - if (!(flags & FLAG_NO_FILE_OFFSET) && offset.h && sizeof(off_t) < 8) + if (!(flags & FLAG_NO_FILE_OFFSET) && (offset & 0xFFFFFFFF00000000ULL) + && sizeof(off_t) < 8) { fprintf(stderr, "64-bit addresses not supported, sorry.\n"); return 0; @@ -5940,7 +6043,7 @@ static int smbios3_decode(u8 *buf, size_t buf_len, const char *devmem, u32 flags /* Maximum length, may get trimmed */ len = DWORD(buf + 0x0C); - table = dmi_table_get(((off_t)offset.h << 32) | offset.l, &len, 0, ver, + table = dmi_table_get(offset, &len, 0, ver, devmem, flags | FLAG_STOP_AT_EOT); if (table == NULL) return 1; |
