Codebase list dmidecode / dd7dd9b
Import upstream version 3.4+git20221216.1.3d68350 Debian Janitor 1 year, 4 months ago
6 changed file(s) with 353 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
66 characteristics, new slot characteristics, new on-board device types, new
77 pointing device interface types, and a new record type (type 45 -
88 Firmware Inventory Information).
9 - Decode HPE OEM records 194, 199, 203, 236, 237, 238 ans 240.
9 - Decode HPE OEM records 194, 199, 203, 236, 237, 238 and 240.
1010 - Bug fixes:
1111 Fix OEM vendor name matching
1212 Fix ASCII filtering of strings
11041104 || (type >= 0xB6 && type <= 0xB7) /* AMD */
11051105 || (type >= 0xE4 && type <= 0xEF)) /* AMD */
11061106 return cpuid_x86_amd;
1107 else if (type == 0x01 || type == 0x02)
1108 {
1109 const char *version = dmi_string(h, data[0x10]);
1110 /*
1111 * Some X86-class CPU have family "Other" or "Unknown". In this case,
1112 * we use the version string to determine if they are known to
1113 * support the CPUID instruction.
1114 */
1115 if (strncmp(version, "Pentium III MMX", 15) == 0
1116 || strncmp(version, "Intel(R) Core(TM)2", 18) == 0
1117 || strncmp(version, "Intel(R) Pentium(R)", 19) == 0
1118 || strcmp(version, "Genuine Intel(R) CPU U1400") == 0)
1119 return cpuid_x86_intel;
1120 else if (strncmp(version, "AMD Athlon(TM)", 14) == 0
1121 || strncmp(version, "AMD Opteron(tm)", 15) == 0
1122 || strncmp(version, "Dual-Core AMD Opteron(tm)", 25) == 0)
1123 return cpuid_x86_amd;
1124 }
11251107
11261108 /* neither X86 nor ARM */
11271109 return cpuid_none;
27212703 /*
27222704 * If no memory module is present, width may be 0
27232705 */
2724 if (code == 0xFFFF || code == 0)
2706 if (code == 0xFFFF || (code == 0 && !(opt.flags & FLAG_NO_QUIRKS)))
27252707 pr_attr(attr, "Unknown");
27262708 else
27272709 pr_attr(attr, "%u bits", code);
47194701 dmi_memory_device_type_detail(WORD(data + 0x13));
47204702 if (h->length < 0x17) break;
47214703 /* If no module is present, the remaining fields are irrelevant */
4722 if (WORD(data + 0x0C) == 0)
4704 if (WORD(data + 0x0C) == 0 && !(opt.flags & FLAG_NO_QUIRKS))
47234705 break;
47244706 dmi_memory_device_speed("Speed", WORD(data + 0x15),
47254707 h->length >= 0x5C ?
55435525 }
55445526
55455527 /* Fixup a common mistake */
5546 if (h.type == 34)
5528 if (h.type == 34 && !(opt.flags & FLAG_NO_QUIRKS))
55475529 dmi_fixup_type_34(&h, display);
55485530
55495531 if (display)
56995681 return 0;
57005682 }
57015683
5702 if (!checksum(buf, buf[0x06]))
5684 if (buf[0x06] < 0x18
5685 || !checksum(buf, buf[0x06]))
57035686 return 0;
57045687
57055688 ver = (buf[0x07] << 16) + (buf[0x08] << 8) + buf[0x09];
57335716 return 1;
57345717 }
57355718
5736 static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
5737 {
5738 u16 ver;
5739
5740 /* Don't let checksum run beyond the buffer */
5741 if (buf[0x05] > 0x20)
5742 {
5743 fprintf(stderr,
5744 "Entry point length too large (%u bytes, expected %u).\n",
5745 (unsigned int)buf[0x05], 0x1FU);
5746 return 0;
5747 }
5748
5749 if (!checksum(buf, buf[0x05])
5750 || memcmp(buf + 0x10, "_DMI_", 5) != 0
5751 || !checksum(buf + 0x10, 0x0F))
5752 return 0;
5753
5754 ver = (buf[0x06] << 8) + buf[0x07];
5719 static void dmi_fixup_version(u16 *ver)
5720 {
57555721 /* Some BIOS report weird SMBIOS version, fix that up */
5756 switch (ver)
5722 switch (*ver)
57575723 {
57585724 case 0x021F:
57595725 case 0x0221:
57605726 if (!(opt.flags & FLAG_QUIET))
57615727 fprintf(stderr,
57625728 "SMBIOS version fixup (2.%d -> 2.%d).\n",
5763 ver & 0xFF, 3);
5764 ver = 0x0203;
5729 *ver & 0xFF, 3);
5730 *ver = 0x0203;
57655731 break;
57665732 case 0x0233:
57675733 if (!(opt.flags & FLAG_QUIET))
57685734 fprintf(stderr,
57695735 "SMBIOS version fixup (2.%d -> 2.%d).\n",
57705736 51, 6);
5771 ver = 0x0206;
5772 break;
5773 }
5737 *ver = 0x0206;
5738 break;
5739 }
5740 }
5741
5742 static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
5743 {
5744 u16 ver;
5745
5746 /* Don't let checksum run beyond the buffer */
5747 if (buf[0x05] > 0x20)
5748 {
5749 fprintf(stderr,
5750 "Entry point length too large (%u bytes, expected %u).\n",
5751 (unsigned int)buf[0x05], 0x1FU);
5752 return 0;
5753 }
5754
5755 /*
5756 * The size of this structure is 0x1F bytes, but we also accept value
5757 * 0x1E due to a mistake in SMBIOS specification version 2.1.
5758 */
5759 if (buf[0x05] < 0x1E
5760 || !checksum(buf, buf[0x05])
5761 || memcmp(buf + 0x10, "_DMI_", 5) != 0
5762 || !checksum(buf + 0x10, 0x0F))
5763 return 0;
5764
5765 ver = (buf[0x06] << 8) + buf[0x07];
5766 if (!(opt.flags & FLAG_NO_QUIRKS))
5767 dmi_fixup_version(&ver);
57745768 if (!(opt.flags & FLAG_QUIET))
57755769 pr_info("SMBIOS %u.%u present.",
57765770 ver >> 8, ver & 0xFF);
197197 };
198198 unsigned int i;
199199
200 pr_attr("Attributes Defined/Set", NULL);
200 pr_list_start("Attributes Defined/Set", NULL);
201201 for (i = 0; i < ARRAY_SIZE(attributes); i++)
202202 {
203203 if (!(defined.l & (1UL << i)))
204204 continue;
205 pr_subattr(attributes[i], "%s", set.l & (1UL << i) ? "Yes" : "No");
205 pr_list_item("%s: %s", attributes[i], set.l & (1UL << i) ? "Yes" : "No");
206206 }
207 pr_list_end();
207208 }
208209
209210 static void dmi_hp_203_assoc_hndl(const char *fname, u16 num)
281282 "Rear USB Port",
282283 "Internal USB",
283284 "Internal SD Card",
284 "Internal Virutal USB (Embedded NAND)",
285 "Internal Virtual USB (Embedded NAND)",
285286 "Embedded SATA Port",
286287 "Embedded Smart Array",
287288 "PCI Slot",
298299 pr_attr(fname, "%s", str);
299300 }
300301
302 static int dmi_hp_224_status(u8 code)
303 {
304 static const char * const present[] = {
305 "Not Present", /* 0x00 */
306 "Present/Enabled",
307 "Present/Disabled",
308 "Reserved" /* 0x03 */
309 };
310
311 pr_attr("Status", "%s", present[code & 0x03]);
312 if ((code & 0x03) == 0x00)
313 return 0;
314 pr_attr("Option ROM Measuring", "%s", (code & (1 << 2)) ? "Yes" : "No");
315 pr_attr("Hidden", "%s", (code & (1 << 3)) ? "Yes" : "No");
316 return 1;
317 }
318
319 static void dmi_hp_224_ex_status(u8 status, u8 code)
320 {
321 const char *str = "Reserved";
322 static const char * const disable_reason[] = {
323 "Not Specified", /* 0x00 */
324 "User Disabled",
325 "Error Condition",
326 "Reserved" /* 0x03 */
327 };
328 static const char * const error_condition[] = {
329 "Not Specified", /* 0x00 */
330 "Self-Test", /* 0x01 */
331 };
332 if ((status & 0x03) == 0x02)
333 pr_attr("Disable Reason", "%s", disable_reason[code & 0x03]);
334 if ((code & 0x03) == 0x02) {
335 u8 error = (code >> 2) & 0x0f;
336 if (error < ARRAY_SIZE(error_condition))
337 str = error_condition[error];
338 pr_attr("Error Condition", "%s", str);
339 }
340 }
341
342 static void dmi_hp_224_module_type(u8 code)
343 {
344 const char *str = "Reserved";
345 static const char * const type[] = {
346 "Not Specified", /* 0x00 */
347 "TPM 1.2",
348 "TPM 2.0",
349 "Intel PTT fTPM" /* 0x03 */
350 };
351 if ((code & 0x0f) < ARRAY_SIZE(type))
352 str = type[code & 0x0f];
353 pr_attr("Type", "%s", str);
354 pr_attr("Standard Algorithm Supported", "%s", (code & (1 << 4)) ? "Yes" : "No");
355 pr_attr("Chinese Algorithm Supported", "%s", (code & (1 << 5)) ? "Yes" : "No");
356 }
357
358 static void dmi_hp_224_module_attr(u8 code)
359 {
360 static const char * const phys_attr[] = {
361 "Not Specified", /* 0x00 */
362 "Pluggable and Optional",
363 "Pluggable but Standard",
364 "Soldered Down on System Board" /* 0x03 */
365 };
366 static const char * const fips_attr[] = {
367 "Not Specified", /* 0x00 */
368 "Not FIPS Certified",
369 "FIPS Certified",
370 "Reserved" /* 0x03 */
371 };
372 pr_attr("Trusted Module Attributes", "%s", phys_attr[code & 0x3]);
373 pr_attr("FIPS Certification", "%s", fips_attr[((code >> 2) & 0x03)]);
374 }
375
376 static void dmi_hp_224_chipid(u16 code)
377 {
378 const char *str = "Reserved";
379 static const char * const chipid[] = {
380 "None", /* 0x00 */
381 "STMicroGen10 TPM",
382 "Intel firmware TPM (PTT)",
383 "Nationz TPM",
384 "STMicroGen10 Plus TPM",
385 "STMicroGen11 TPM", /* 0x05 */
386 };
387 if ((code & 0xff) < ARRAY_SIZE(chipid))
388 str = chipid[code & 0xff];
389 pr_attr("Chip Identifier", "%s", str);
390 }
391
392 static void dmi_hp_230_method_bus_seg_addr(u8 code, u8 bus_seg, u8 addr)
393 {
394 const char *str = "Reserved";
395 static const char * const method[] = {
396 "Not Available", /* 0x00 */
397 "IPMI I2C",
398 "iLO",
399 "Chassis Manager", /* 0x03 */
400 };
401 if (code < ARRAY_SIZE(method))
402 str = method[code];
403 pr_attr("Access Method", "%s", str);
404 if (code == 0 || code >= ARRAY_SIZE(method))
405 return;
406 if (bus_seg != 0xFF)
407 {
408 if (code == 2)
409 pr_attr("I2C Segment Number", "%d", bus_seg);
410 else
411 pr_attr("I2C Bus Number", "%d", bus_seg);
412 }
413 if (addr != 0xFF)
414 pr_attr("I2C Address", "0x%02x", addr >> 1);
415 }
416
301417 static void dmi_hp_238_loc(const char *fname, unsigned int code)
302418 {
303419 const char *str = "Reserved";
307423 "Rear of Server",
308424 "Embedded internal SD Card",
309425 "iLO USB",
310 "HP NAND Controller (USX 2065 or other)",
426 "USB Hub for NAND Controller",
311427 "Reserved",
312428 "Debug Port", /* 0x07 */
313429 };
347463 str = speed[code];
348464
349465 pr_attr(fname, "%s", str);
466 }
467
468 static void dmi_hp_242_hdd_type(u8 code)
469 {
470 const char *str = "Reserved";
471 static const char * const type[] = {
472 "Undetermined", /* 0x00 */
473 "NVMe SSD",
474 "SATA",
475 "SAS",
476 "SATA SSD",
477 "NVMe Manged by VROC/VMD", /* 0x05 */
478 };
479 if (code < ARRAY_SIZE(type))
480 str = type[code];
481
482 pr_attr("Hard Drive Type", "%s", str);
483 }
484
485 static void dmi_hp_242_form_factor(u8 code)
486 {
487 const char *str = "Reserved";
488 static const char * const form[] = {
489 "Reserved", /* 0x00 */
490 "Reserved",
491 "3.5\" form factor",
492 "2.5\" form factor",
493 "1.8\" form factor",
494 "Less than 1.8\" form factor",
495 "mSATA",
496 "M.2",
497 "MicroSSD",
498 "CFast", /* 0x09 */
499 };
500 if (code < ARRAY_SIZE(form))
501 str = form[code];
502
503 pr_attr("Form Factor", "%s", str);
504 }
505
506 static void dmi_hp_242_speed(const char *attr, u16 speed)
507 {
508 if (speed)
509 pr_attr(attr, "%hu Gbit/s", speed);
510 else
511 pr_attr(attr, "%s", "Unknown");
350512 }
351513
352514 static int dmi_decode_hp(const struct dmi_header *h)
598760 pr_subattr("UEFI", "%s", feat & 0x1400 ? "Yes" : "No");
599761 break;
600762
763 case 224:
764 /*
765 * Vendor Specific: Trusted Module (TPM or TCM) Status
766 *
767 * Offset | Name | Width | Description
768 * -------------------------------------
769 * 0x00 | Type | BYTE | 0xE0, Trusted Module (TPM or TCM) Status
770 * 0x01 | Length | BYTE | Length of structure
771 * 0x02 | Handle | WORD | Unique handle
772 * 0x04 | Status | BYTE | Status Flag Byte
773 * 0x05 | Ex Stat| BYTE | TPM Extended Status
774 * 0x06 | Type | BYTE | Trusted Module Type
775 * 0x07 | Attrib | BYTE | Trusted Module Attributes
776 * 0x08 | Handle | WORD | Handle to map to Type 216
777 * 0x0A | Chip ID| WORD | Chip Identifier Values
778 */
779 pr_handle_name("%s Trusted Module (TPM or TCM) Status", company);
780 if (h->length < 0x05) break;
781 if (!dmi_hp_224_status(data[0x04]))
782 break;
783 if (h->length < 0x0a) break;
784 dmi_hp_224_ex_status(data[0x04], data[0x05]);
785 dmi_hp_224_module_type(data[0x06]);
786 dmi_hp_224_module_attr(data[0x07]);
787 if (!(opt.flags & FLAG_QUIET))
788 pr_attr("Associated Handle", "0x%04X", WORD(data + 0x8));
789 if (h->length < 0x0c) break;
790 dmi_hp_224_chipid(WORD(data + 0x0a));
791 break;
792
793 case 230:
794 /*
795 * Vendor Specific: Power Supply Information OEM SMBIOS Record
796 *
797 * This record is used to communicate additional Power Supply Information
798 * beyond the Industry Standard System Power Supply (Type 39) Record.
799 *
800 * Offset| Name | Width | Description
801 * -----------------------------------------
802 * 0x00 | Type | BYTE | 0xE6, Power Supply Information Indicator
803 * 0x01 | Length | BYTE | Length of structure
804 * 0x02 | Handle | WORD | Unique handle
805 * 0x04 | Assoc Handle| WORD | Associated Handle (Type 39)
806 * 0x06 | Manufacturer| STRING| Actual third party manufacturer
807 * 0x07 | Revision | STRING| Power Supply Revision Level
808 * 0x08 | FRU Access | BYTE | Power Supply FRU Access Method
809 * 0x09 | I2C Bus Num | BYTE | I2C Bus #. Value based upon context
810 * 0x0A | I2C Address | BYTE | I2C Address
811 */
812 pr_handle_name("%s Power Supply Information", company);
813 if (h->length < 0x0B) break;
814 if (!(opt.flags & FLAG_QUIET))
815 pr_attr("Associated Handle", "0x%04X", WORD(data + 0x4));
816 pr_attr("Manufacturer", "%s", dmi_string(h, data[0x06]));
817 pr_attr("Revision", "%s", dmi_string(h, data[0x07]));
818 dmi_hp_230_method_bus_seg_addr(data[0x08], data[0x09], data[0x0A]);
819 break;
820
601821 case 233:
602822 /*
603823 * Vendor Specific: HPE ProLiant NIC MAC Information
769989 pr_attr("Lowest Supported Version", "Not Available");
770990 break;
771991
992 case 242:
993 /*
994 * Vendor Specific: HPE Hard Drive Inventory Record
995 *
996 * This record provides a mechanism for software to gather information for
997 * NVMe and SATA drives that are directly attached to the system. This
998 * record does not contain drive information for drives attached to a HBA
999 * (i.e. a SmartArray controller). This record will only contain information
1000 * for a hard drive detected by the BIOS during POST and does not
1001 * comprehend a hot plug event after the system has booted.
1002 *
1003 * Offset | Name | Width | Description
1004 * ---------------------------------------
1005 * 0x00 | Type | BYTE | 0xF2, HPE Hard Drive Inventory Record
1006 * 0x01 | Length | BYTE | Length of structure
1007 * 0x02 | Handle | WORD | Unique handle
1008 * 0x04 | Hndl Assoc | WORD | Handle to map to Type 203
1009 * 0x06 | HDD Type | BYTE | Hard drive type
1010 * 0x07 | HDD Uniq ID| QWORD | SATA-> WWID. NVMe -> IEEE Ext Uniq ID.
1011 * 0x0F | Capacity | DWORD | Drive Capacity in Mbytes
1012 * 0x13 | Hours | 16BYTE| Number of poweron hours
1013 * 0x23 | Reserved | BYTE | Reserved
1014 * 0x24 | Power | BTYE | Wattage
1015 * 0x25 | Form Factor| BYTE | HDD Form Factor
1016 * 0x26 | Health | BYTE | Hard Drive Health Status
1017 * 0x27 | Serial Num | STRING| NVMe/SATA Serial Number
1018 * 0x28 | Model Num | STRING| NVMe/SATA Model Number
1019 * 0x29 | FW Rev | STRING| Firmware revision
1020 * 0x2A | Location | STRING| Drive location
1021 * 0x2B | Crypt Stat | BYTE | Drive encryption status from BIOS
1022 * 0x2C | Capacity | QWORD | Hard Drive capacity in bytes
1023 * 0x34 | Block Size | DWORD | Logical Block Size in bytes
1024 * 0x38 | Rot Speed | WORD | Nominal Rotational Speed (RPM)
1025 * 0x3A | Neg Speed | WORD | Current negotiated bus speed
1026 * 0x3C | Cap Speed | WORD | Fastest Capable Bus Speed of drive
1027 */
1028 if (gen < G10) return 0;
1029 pr_handle_name("%s ProLiant Hard Drive Inventory Record", company);
1030 if (h->length < 0x2C) break;
1031 if (!(opt.flags & FLAG_QUIET))
1032 pr_attr("Associated Handle", "0x%04X", WORD(data + 0x4));
1033 dmi_hp_242_hdd_type(data[0x06]);
1034 pr_attr("ID", "%lx", QWORD(data + 0x07));
1035 if (h->length < 0x3E)
1036 pr_attr("Capacity", "%u MB", DWORD(data + 0x0F));
1037 else
1038 dmi_print_memory_size("Capacity", QWORD(data + 0x2C), 0);
1039 /* NB: Poweron low QWORD good for 2,104,351,365,926,255 years */
1040 pr_attr("Poweron", "%ld hours", QWORD(data + 0x13));
1041 if (data[0x24])
1042 pr_attr("Power Wattage", "%hhu W", data[0x24]);
1043 else
1044 pr_attr("Power Wattage", "%s", "Unknown");
1045 dmi_hp_242_form_factor(data[0x25]);
1046 feat = data[0x26];
1047 pr_attr("Health Status", "%s", (feat == 0x00) ? "OK" :
1048 (feat == 0x01) ? "Warning" :
1049 (feat == 0x02) ? "Critical" :
1050 (feat == 0xFF) ? "Unknown" : "Reserved");
1051 pr_attr("Serial Number", dmi_string(h, data[0x27]));
1052 pr_attr("Model Number", dmi_string(h, data[0x28]));
1053 pr_attr("Firmware Revision", dmi_string(h, data[0x29]));
1054 pr_attr("Location", dmi_string(h, data[0x2A]));
1055 feat = data[0x2B];
1056 pr_attr("Encryption Status", "%s", (feat == 0) ? "Not Encrypted" :
1057 (feat == 1) ? "Encrypted" :
1058 (feat == 2) ? "Unknown" :
1059 (feat == 3) ? "Not Supported" : "Reserved");
1060 if (h->length < 0x3E) break;
1061 pr_attr("Block Size", "%u bytes", DWORD(data + 0x34));
1062 /* Rotational Speed: 0 -> Not Reported, 1 -> N/A (SSD) */
1063 if (data[0x38] > 1)
1064 pr_attr("Rotational Speed", "%hhu RPM", data[0x38]);
1065 dmi_hp_242_speed("Negotiated Speed", WORD(data + 0x3A));
1066 dmi_hp_242_speed("Capable Speed", WORD(data + 0x3C));
1067 break;
7721068 default:
7731069 return 0;
7741070 }
269269 { "dev-mem", required_argument, NULL, 'd' },
270270 { "help", no_argument, NULL, 'h' },
271271 { "quiet", no_argument, NULL, 'q' },
272 { "no-quirks", no_argument, NULL, 'Q' },
272273 { "string", required_argument, NULL, 's' },
273274 { "type", required_argument, NULL, 't' },
274275 { "dump", no_argument, NULL, 'u' },
300301 break;
301302 case 'q':
302303 opt.flags |= FLAG_QUIET;
304 break;
305 case 'Q':
306 opt.flags |= FLAG_NO_QUIRKS;
303307 break;
304308 case 's':
305309 if (parse_opt_string(optarg) < 0)
370374 " -d, --dev-mem FILE Read memory from device FILE (default: " DEFAULT_MEM_DEV ")\n"
371375 " -h, --help Display this help text and exit\n"
372376 " -q, --quiet Less verbose output\n"
377 " --no-quirks Decode everything without quirks\n"
373378 " -s, --string KEYWORD Only display the value of the given DMI string\n"
374379 " -t, --type TYPE Only display the entries of given type\n"
375380 " -H, --handle HANDLE Only display the entry of given handle\n"
4545 #define FLAG_DUMP_BIN (1 << 4)
4646 #define FLAG_FROM_DUMP (1 << 5)
4747 #define FLAG_NO_SYSFS (1 << 6)
48 #define FLAG_NO_QUIRKS (1 << 7)
4849
4950 int parse_command_line(int argc, char * const argv[]);
5051 void print_help(void);
6868 .BR "-q" ", " "--quiet"
6969 Be less verbose. Unknown, inactive and \s-1OEM\s0-specific entries are not
7070 displayed. Meta-data and handle references are hidden.
71 .TP
72 .BR " " " " "--no-quirks"
73 Decode everything exactly as it is in the table, without trying to fix up
74 common mistakes or hide irrelevant fields.
75 This mode is primarily aimed at firmware developers.
7176 .TP
7277 .BR "-s" ", " "--string \fIKEYWORD\fP"
7378 Only display the value of the \s-1DMI\s0 string identified by \fIKEYWORD\fP.