Merge branch 'release/debian/3.4-1'
Jörg Frings-Fürst
1 year, 9 months ago
20 | 20 | Tyler Bell <tyler.bell@hp.com> |
21 | 21 | Xie XiuQi <xiexiuqi@huawei.com> |
22 | 22 | Petr Oros <poros@redhat.com> |
23 | Prabhakar Pujeri <prabhakar.pujeri@dell.com> | |
24 | Erwan Velu <e.velu@criteo.com> | |
25 | Jerry Hoemann <jerry.hoemann@hpe.com> | |
23 | 26 | |
24 | 27 | MANY THANKS TO (IN CHRONOLOGICAL ORDER) |
25 | 28 | Werner Heuser |
89 | 92 | Stefan Tauner |
90 | 93 | Naga Chumbalkar |
91 | 94 | Jens Rosenboom |
95 | Lianbo Jiang | |
96 | Tianjia Zhang | |
97 | Ivan Tkachenko |
0 | Version 3.4 (Mon Jun 27 2022) | |
1 | - Support for SMBIOS 3.4.0. This includes new memory device types, new | |
2 | processor upgrades, new slot types and characteristics, decoding of memory | |
3 | module extended speed, new system slot types, new processor characteristics | |
4 | and new format of Processor ID. | |
5 | - Support for SMBIOS 3.5.0. This includes new processor upgrades, BIOS | |
6 | characteristics, new slot characteristics, new on-board device types, new | |
7 | pointing device interface types, and a new record type (type 45 - | |
8 | Firmware Inventory Information). | |
9 | - Decode HPE OEM records 194, 199, 203, 236, 237, 238 ans 240. | |
10 | - Bug fixes: | |
11 | Fix OEM vendor name matching | |
12 | Fix ASCII filtering of strings | |
13 | Fix crash with option -u | |
14 | - Minor improvements: | |
15 | Skip details of uninstalled memory modules | |
16 | Don't display the raw CPU ID in quiet mode | |
17 | Improve the formatting of the manual pages | |
18 | ||
0 | 19 | Version 3.3 (Wed Oct 14 2020) |
1 | 20 | - [BUILD] Allow overriding build settings from the environment. |
2 | 21 | - [COMPATIBILITY] Document how the UUID fields are interpreted. |
0 | dmidecode (3.4-1) unstable; urgency=medium | |
1 | ||
2 | * New upstream release. | |
3 | - Remove upstream applied patches: | |
4 | + debian/patches/0145-Fix_condition_error_in_ascii_filter.patch | |
5 | + debian/patches/0150-Fix_crash.patch | |
6 | - Refresh upstream signing key. | |
7 | * Declare compliance with Debian Policy 4.6.1.0 (No changes needed). | |
8 | * debian/copyright: | |
9 | - Add year 2022 to myself. | |
10 | ||
11 | -- Jörg Frings-Fürst <debian@jff.email> Thu, 30 Jun 2022 20:37:08 +0200 | |
12 | ||
0 | 13 | dmidecode (3.3-3) unstable; urgency=medium |
1 | 14 | |
2 | 15 | * Add Architecture riscv64 (Closes: #991854). |
2 | 2 | Priority: optional |
3 | 3 | Maintainer: Jörg Frings-Fürst <debian@jff.email> |
4 | 4 | Build-Depends: debhelper-compat (= 13) |
5 | Standards-Version: 4.6.0.0 | |
5 | Standards-Version: 4.6.1.0 | |
6 | 6 | Rules-Requires-Root: no |
7 | 7 | Vcs-Git: git://jff.email/opt/git/dmidecode.git |
8 | 8 | Vcs-Browser: https://jff.email/cgit/dmidecode.git/ |
12 | 12 | Files: debian/* |
13 | 13 | Copyright: 2003-2007 Petter Reinholdtsen <pere@debian.org> |
14 | 14 | 2011-2012 Daniel Baumann <daniel.baumann@progress-technologies.net> |
15 | 2014-2021 Jörg Frings-Fürst <debian@jff.email> | |
15 | 2014-2022 Jörg Frings-Fürst <debian@jff.email> | |
16 | 16 | License: GPL-2+ |
17 | 17 | |
18 | 18 | License: GPL-2+ |
0 | 0145-Fix_condition_error_in_ascii_filter.patch | |
1 | 0150-Fix_crash.patch | |
0 | #0145-Fix_condition_error_in_ascii_filter.patch | |
1 | #0150-Fix_crash.patch | |
2 | 2 | 0100-ansi-c.patch |
3 | 3 | 0001-hurd.patch |
4 | 4 | #0005-build.patch |
0 | -----BEGIN PGP ARMORED FILE----- | |
1 | Comment: Use "gpg --dearmor" for unpacking | |
0 | -----BEGIN PGP PUBLIC KEY BLOCK----- | |
2 | 1 | |
3 | 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 | |
66 | =9biY | |
67 | -----END PGP ARMORED FILE----- | |
2 | mQINBE6ewEABEACYt7MVRJJeyFsd4dMlP0bRE1U0A76al9te+XoalkAnjwltJPgy | |
3 | xnw2eP1m+klK+HJc9gVMIkg66LutN+c0x+qFf08UT6dk22/jULYnodkt1sUgAxIB | |
4 | cm6vdFif1mXY1WKRRdDrKsZqTZ5dw93Nd8T5w493Ll84ECl4cI9m5ZDDf33JHnph | |
5 | aR7JDCQwT2mxWrZTQzmGawhcFu3tLqQ93SuPBFx6DZWxyU4HT3UCQN89SUMdkiaE | |
6 | p5IYMvHnfdeP+oN7FlfCumqZGIl6Zm3KE31jfm2KiOwIXZdRliDHHGEXD7onnHIb | |
7 | /4WaP02LSvQFDAZ7+KQtnChR6tzfsdnWSKjSJmDeIf/qYzieOxEz5AmdroW6VLdS | |
8 | yBH9UZ11Is9Y6/vJdMJXvFYMGjTw64SDJKsKaeVNFBA4p/JBgFnGkl1Mt7JBlaYZ | |
9 | JwbE//42vC1HvHF0PHV5YOrhl8DDntWPw44PSH3qjyLgnuQ5WGgAWCO9foDSCUdo | |
10 | sk+J+lhtkmL/N4p99sYd3QSw3zNRmJf4snclcH1IBOUnEaOE+JP7wwclhVmeJeSw | |
11 | tMmQlNCx6QN/zzj1MoxVpwoAAkFIV8dmNi2yvIHDHvaqOkCAJI5Y3WzwIENlUl65 | |
12 | vaG0zMKOeyPeLd/EDdwILlssLslf2kCsulj6fjCCFN7Gvh6k9hIwCd0IbQARAQAB | |
13 | tC5KZWFuIERlbHZhcmUgKGtlcm5lbC5vcmcpIDxraGFsaUBsaW51eC1mci5vcmc+ | |
14 | iQIfBDABAgAJBQJUEWgOAh0gAAoJEKVSa5uzzU5q628P/igh/sU9og+quy7QVASy | |
15 | U+r+GcPllzzkOXu0dl5WYOCA/8PGQYNj2gMzH2livYVWtQpndUbZ2zIXxQ8wnvNF | |
16 | gz3n2YdLtJdxInOnmTiY6dXnvf0abIMWYDn9OduvHTrMG+xtwyWAgxHipKZ3LUWv | |
17 | zyE4AfWBhx6waevqGnmkcLZkje1L1OgbeRT5x0x6mu2MUX2hCVX5twqXtF6EK0za | |
18 | Od5XfiG4FYBbbY4e+7Ifd41XgnGmscnSQ7ti+Lo/5j+pREyvKXYRBxRoezSfJ4GW | |
19 | PiYtQLoJ1zmsPFgfH8is1WOweY2P3NjJVKby7RAYq1G4QSiv4X16FbpYIIOWsgdJ | |
20 | GHDB1/u2KTZwLrNsdW5U8rsbZrvzeMfcq7ssWYTP37UoqJFsImXRsyX87//YnB8l | |
21 | HhBZ6ojbMJFB63iD95c6LPqJUkyEXhzOsepjj+JpA3ODSArNDqOMxCMvwkitxDLo | |
22 | fY2KgJk9uR6U/ZYNVfEAQDma8LkxlXkX90gdjmy1f3BSlusFtr0aUKxhtCig//zM | |
23 | FoxkoOQMRQmAk98MQFqHGt11t7aG9g6saLBWkS+1rGNNQF27pDraUz745fdqh42W | |
24 | XPX6iSuTY0iIOeriG7B1g8CwR8qIJp1OKub1nqDxbjctAdtZK3Oa5bVoiIhIw28w | |
25 | Jw1VX84si4r3e6Sv56mtlDdRtCxKZWFuIERlbHZhcmUgKGtlcm5lbC5vcmcpIDxq | |
26 | ZGVsdmFyZUBzdXNlLmRlPokCOAQTAQIAIgUCTp7AQAIbAwYLCQgHAwIGFQgCCQoL | |
27 | BBYCAwECHgECF4AACgkQpVJrm7PNTmr+rhAAi1ek57JZ6zt7PfEbiTa2n5f+jpWm | |
28 | yCDFxLhY50Bt3haP3knek+AkbXHgw+rdA5SEVMax6K56LXppSk0cwLPF9YNS3LYQ | |
29 | 4jKsDF59vD/58Y8AyWY/hy/nUFm7VLz8hr9Nm0pGebw255RYSBNPQWythk40zAgx | |
30 | hX+z9sTtxCEp7qMXKBRHPtwgrtZRCbz93NwICY/y9PzcUnCWPuIvSkHCiSqeJI0p | |
31 | n/XsOpIWjNCWUU6+McB/uh5IRrNimusaDJJujtJRN+2qiQeYMaqOUuKrgWJ9+KmP | |
32 | gJqxOu8KohV/FPF9PkGMakV2AUwcvQvSdkTf+XQ/pk0t0O406sd4RHotxUg1dlQN | |
33 | Taqmvrh79vShgtJH592rEh5gw/U3YLGD89bnjdyXthVTcb9CYXeGv0pTX+5WmLuo | |
34 | 5BMKStUMttQaO03D5IBVRIU0ZuZv1A1TLAHi7qx7onC+126GDODdCUpu5+PdJwum | |
35 | xWdN3qXrdZnSf6ZauLBhy+aG9oe2/ycRNtMp6xuGymzoH0C2nuj3YEnUzRALw4lz | |
36 | X7pk2opWx9HbRzUUmHJwxBLgbeM+TdpqCVJbEpA0vYu/8YaSqWXIFCKQKPIQRRSQ | |
37 | Tt2locKtD1HiJOtD/nM7WO5MXWMSx83iCG0c6DAXkaNMqVWiu9JIYlHV98o0Q/Eb | |
38 | VRy7BAyxoiwoUZu5Ag0ETp7AQAEQAMkhZDUy6k8d4pfORjqIknTfq/d6IbUc4E3h | |
39 | DTKDm87inmjVxZ7FjexpXdtJOYoWWKT/0if9IFUpqFYb8vy2iy3gXc7HfecqJb+P | |
40 | TPAPvLojXs8hGpkLBhkEJuDqRXfQkQsTSKj2hUcjXwwC5k97dnkq6yjpyfW35zTP | |
41 | Scop3oorqKwukGg6FbBy6U3GmsqmbtQzQW3UbKSR05qjoc91ILYT/4RL46BYj7q9 | |
42 | hIkbYcsasFnH7wfeLzrHt3TU+CIDk/P/+TGMRPU9dSSkPqD6yTdbpIBDfJMPqEae | |
43 | GIGHnVIEZZhcmLnQIIYN3zMxEk40fICMcHTLB6HHgC2DKwpQSx/TZvRoEblPmQSa | |
44 | Q6kpc/nWc87MKGTsY6fDRkapwB8Tf1h8ao6+VG1SX/3tAP8MFh4xHmYamO9LyZ3s | |
45 | ulhWbau3jMvB8nu7bR87EWzGu9C+3YcetRoyXTVSPUwaZVloyEMXAWbo7jw1kUhA | |
46 | NBsIZ2Z0W7buaO+ONuQ6GfWwooOGMZSM2zHY8yrSU6ofpaXfmXOFQlRIFCZhXo9B | |
47 | 7oGf42pNzFZjhb6JQM3mAxNwSVrQtA7LtGCKuPBPXawNUEJoZkKIuyhqRI6iIZgz | |
48 | a9fe1LKGpvAPYW5AF3qMp8t49EiGgZ4xpHwz7oNRTaZRQwsgC3VdAb3ViJC/TQe5 | |
49 | svWvD+bPABEBAAGJAh8EGAECAAkFAk6ewEACGwwACgkQpVJrm7PNTmrU3g/+JXwj | |
50 | LsW8H0WY2ZOyZbYJx74jSEOCi+AuZpd1v6f2p1oiz9ec9Q/TQdV4tTPBgyoflwOn | |
51 | /HZC+6C03Zyj0hCyxViekXHP54ZtC8+zSuN/jhy3P3I+pqDedzGZiV72aM+MXr1r | |
52 | v+KMKF6HOlz+NFMmHP5mwYGo3Tgg7S8XxLwz48SbglCc2hX56z9oveZG1e5tAved | |
53 | 05FlAy+7ZOeBYfDN+e9Tdw2V0SLGM0On2rDDpTs/28MwX6YbTAPuQN6qZJzCq2u8 | |
54 | Tv5HsWM3Xe7GnD3gpqGCCARTqCIJ4D9l+Qe/n8VQQbo3eTFTf0UbTi6Z0DIT96Bv | |
55 | FM6VH+jfQl757U99/7xmyw2ugnCKLA06ouaGIPWdGmBQKozHEo8IsGq8itqgjcH2 | |
56 | 3cJWfscKlqZOQtqb75cUMGmfloha3rnSpDc3n4PlKGNG5NaCN9yfjkl5QJ+m4e8/ | |
57 | RFrr9Yj44Bt2cspN32BOztFsbGUahmfLz8OE2mAKs6EnicHm/NBBmoqJ6ZwiQz89 | |
58 | bi5nHZ2Etx744C2nessg/y9RgDIbkSIaTsLwl54KrvqFHiYouIRYki/EpVku87dd | |
59 | Jf9aLHitaRW/c7l/a0iBXEMsEBNyytXvlCZ5OimKnxzZK8K9CdcoUyK75WcRwN8e | |
60 | Qu7m8XPTuUj0t1Fvq0Xleoa74ot+e+pKWAaR40U= | |
61 | =3wf6 | |
62 | -----END PGP PUBLIC KEY BLOCK----- |
84 | 84 | #define out_of_spec "<OUT OF SPEC>" |
85 | 85 | static const char *bad_index = "<BAD INDEX>"; |
86 | 86 | |
87 | #define SUPPORTED_SMBIOS_VER 0x030300 | |
87 | enum cpuid_type cpuid_type = cpuid_none; | |
88 | ||
89 | #define SUPPORTED_SMBIOS_VER 0x030500 | |
88 | 90 | |
89 | 91 | #define FLAG_NO_FILE_OFFSET (1 << 0) |
90 | 92 | #define FLAG_STOP_AT_EOT (1 << 1) |
115 | 117 | size_t i; |
116 | 118 | |
117 | 119 | for (i = 0; i < len; i++) |
118 | if (bp[i] < 32 || bp[i] == 127) | |
120 | if (bp[i] < 32 || bp[i] >= 127) | |
119 | 121 | bp[i] = '.'; |
120 | 122 | } |
121 | 123 | |
200 | 202 | "Additional Information", |
201 | 203 | "Onboard Device", |
202 | 204 | "Management Controller Host Interface", |
203 | "TPM Device", /* 43 */ | |
205 | "TPM Device", | |
206 | "Processor", | |
207 | "Firmware", | |
208 | "String Property" /* 46 */ | |
204 | 209 | }; |
205 | 210 | |
206 | 211 | if (code >= 128) |
207 | 212 | return "OEM-specific"; |
208 | if (code <= 43) | |
213 | if (code <= 46) | |
209 | 214 | return type[code]; |
210 | 215 | return out_of_spec; |
211 | 216 | } |
247 | 252 | { |
248 | 253 | int j, l = strlen(s) + 1; |
249 | 254 | |
250 | off = 0; | |
251 | 255 | for (row = 0; row < ((l - 1) >> 4) + 1; row++) |
252 | 256 | { |
257 | off = 0; | |
253 | 258 | for (j = 0; j < 16 && j < l - (row << 4); j++) |
254 | 259 | off += sprintf(raw_data + off, |
255 | 260 | j ? " %02X" : "%02X", |
266 | 271 | } |
267 | 272 | |
268 | 273 | /* shift is 0 if the value is in bytes, 1 if it is in kilobytes */ |
269 | static void dmi_print_memory_size(const char *attr, u64 code, int shift) | |
274 | void dmi_print_memory_size(const char *attr, u64 code, int shift) | |
270 | 275 | { |
271 | 276 | unsigned long capacity; |
272 | 277 | u16 split[7]; |
423 | 428 | "Function key-initiated network boot is supported", |
424 | 429 | "Targeted content distribution is supported", |
425 | 430 | "UEFI is supported", |
426 | "System is a virtual machine" /* 4 */ | |
431 | "System is a virtual machine", | |
432 | "Manufacturing mode is supported", | |
433 | "Manufacturing mode is enabled" /* 6 */ | |
427 | 434 | }; |
428 | 435 | int i; |
429 | 436 | |
430 | for (i = 0; i <= 4; i++) | |
437 | for (i = 0; i <= 6; i++) | |
431 | 438 | if (code & (1 << i)) |
432 | 439 | pr_list_item("%s", characteristics[i]); |
433 | 440 | } |
1036 | 1043 | } |
1037 | 1044 | } |
1038 | 1045 | |
1046 | static enum cpuid_type dmi_get_cpuid_type(const struct dmi_header *h) | |
1047 | { | |
1048 | const u8 *data = h->data; | |
1049 | const u8 *p = data + 0x08; | |
1050 | u16 type; | |
1051 | ||
1052 | type = (data[0x06] == 0xFE && h->length >= 0x2A) ? | |
1053 | WORD(data + 0x28) : data[0x06]; | |
1054 | ||
1055 | if (type == 0x05) /* 80386 */ | |
1056 | { | |
1057 | return cpuid_80386; | |
1058 | } | |
1059 | else if (type == 0x06) /* 80486 */ | |
1060 | { | |
1061 | u16 dx = WORD(p); | |
1062 | /* | |
1063 | * Not all 80486 CPU support the CPUID instruction, we have to find | |
1064 | * whether the one we have here does or not. Note that this trick | |
1065 | * works only because we know that 80486 must be little-endian. | |
1066 | */ | |
1067 | if ((dx & 0x0F00) == 0x0400 | |
1068 | && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070) | |
1069 | && ((dx & 0x000F) >= 0x0003)) | |
1070 | return cpuid_x86_intel; | |
1071 | else | |
1072 | return cpuid_80486; | |
1073 | } | |
1074 | else if ((type >= 0x100 && type <= 0x101) /* ARM */ | |
1075 | || (type >= 0x118 && type <= 0x119)) /* ARM */ | |
1076 | { | |
1077 | /* | |
1078 | * The field's format depends on the processor's support of | |
1079 | * the SMCCC_ARCH_SOC_ID architectural call. Software can determine | |
1080 | * the support for SoC ID by examining the Processor Characteristics field | |
1081 | * for "Arm64 SoC ID" bit. | |
1082 | */ | |
1083 | if (h->length >= 0x28 | |
1084 | && (WORD(data + 0x26) & (1 << 9))) | |
1085 | return cpuid_arm_soc_id; | |
1086 | else | |
1087 | return cpuid_arm_legacy; | |
1088 | } | |
1089 | else if ((type >= 0x0B && type <= 0x15) /* Intel, Cyrix */ | |
1090 | || (type >= 0x28 && type <= 0x2F) /* Intel */ | |
1091 | || (type >= 0xA1 && type <= 0xB3) /* Intel */ | |
1092 | || type == 0xB5 /* Intel */ | |
1093 | || (type >= 0xB9 && type <= 0xC7) /* Intel */ | |
1094 | || (type >= 0xCD && type <= 0xCF) /* Intel */ | |
1095 | || (type >= 0xD2 && type <= 0xDB) /* VIA, Intel */ | |
1096 | || (type >= 0xDD && type <= 0xE0)) /* Intel */ | |
1097 | return cpuid_x86_intel; | |
1098 | else if ((type >= 0x18 && type <= 0x1D) /* AMD */ | |
1099 | || type == 0x1F /* AMD */ | |
1100 | || (type >= 0x38 && type <= 0x3F) /* AMD */ | |
1101 | || (type >= 0x46 && type <= 0x4F) /* AMD */ | |
1102 | || (type >= 0x66 && type <= 0x6B) /* AMD */ | |
1103 | || (type >= 0x83 && type <= 0x8F) /* AMD */ | |
1104 | || (type >= 0xB6 && type <= 0xB7) /* AMD */ | |
1105 | || (type >= 0xE4 && type <= 0xEF)) /* AMD */ | |
1106 | 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 | } | |
1125 | ||
1126 | /* neither X86 nor ARM */ | |
1127 | return cpuid_none; | |
1128 | } | |
1129 | ||
1130 | void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...), | |
1131 | const char *label, enum cpuid_type sig, const u8 *p) | |
1132 | { | |
1133 | u32 eax, midr, jep106, soc_revision; | |
1134 | u16 dx; | |
1135 | ||
1136 | switch (sig) | |
1137 | { | |
1138 | case cpuid_80386: | |
1139 | dx = WORD(p); | |
1140 | /* | |
1141 | * 80386 have a different signature. | |
1142 | */ | |
1143 | print_cb(label, | |
1144 | "Type %u, Family %u, Major Stepping %u, Minor Stepping %u", | |
1145 | dx >> 12, (dx >> 8) & 0xF, | |
1146 | (dx >> 4) & 0xF, dx & 0xF); | |
1147 | return; | |
1148 | ||
1149 | case cpuid_80486: | |
1150 | dx = WORD(p); | |
1151 | print_cb(label, | |
1152 | "Type %u, Family %u, Model %u, Stepping %u", | |
1153 | (dx >> 12) & 0x3, (dx >> 8) & 0xF, | |
1154 | (dx >> 4) & 0xF, dx & 0xF); | |
1155 | return; | |
1156 | ||
1157 | case cpuid_arm_legacy: /* ARM before SOC ID */ | |
1158 | midr = DWORD(p); | |
1159 | /* | |
1160 | * The format of this field was not defined for ARM processors | |
1161 | * before version 3.1.0 of the SMBIOS specification, so we | |
1162 | * silently skip it if it reads all zeroes. | |
1163 | */ | |
1164 | if (midr == 0) | |
1165 | return; | |
1166 | print_cb(label, | |
1167 | "Implementor 0x%02x, Variant 0x%x, Architecture %u, Part 0x%03x, Revision %u", | |
1168 | midr >> 24, (midr >> 20) & 0xF, | |
1169 | (midr >> 16) & 0xF, (midr >> 4) & 0xFFF, midr & 0xF); | |
1170 | return; | |
1171 | ||
1172 | case cpuid_arm_soc_id: /* ARM with SOC ID */ | |
1173 | /* | |
1174 | * If Soc ID is supported, the first DWORD is the JEP-106 code; | |
1175 | * the second DWORD is the SoC revision value. | |
1176 | */ | |
1177 | jep106 = DWORD(p); | |
1178 | soc_revision = DWORD(p + 4); | |
1179 | /* | |
1180 | * According to SMC Calling Convention (SMCCC) v1.3 specification | |
1181 | * (https://developer.arm.com/documentation/den0028/d/), the format | |
1182 | * of the values returned by the SMCCC_ARCH_SOC_ID call is as follows: | |
1183 | * | |
1184 | * JEP-106 code for the SiP (SoC_ID_type == 0) | |
1185 | * Bit[31] must be zero | |
1186 | * Bits[30:24] JEP-106 bank index for the SiP | |
1187 | * Bits[23:16] JEP-106 identification code with parity bit for the SiP | |
1188 | * Bits[15:0] Implementation defined SoC ID | |
1189 | * | |
1190 | * SoC revision (SoC_ID_type == 1) | |
1191 | * Bit[31] must be zero | |
1192 | * Bits[30:0] SoC revision | |
1193 | */ | |
1194 | pr_attr("Signature", | |
1195 | "JEP-106 Bank 0x%02x Manufacturer 0x%02x, SoC ID 0x%04x, SoC Revision 0x%08x", | |
1196 | (jep106 >> 24) & 0x7F, (jep106 >> 16) & 0x7F, jep106 & 0xFFFF, soc_revision); | |
1197 | return; | |
1198 | ||
1199 | case cpuid_x86_intel: /* Intel */ | |
1200 | eax = DWORD(p); | |
1201 | /* | |
1202 | * Extra flags are now returned in the ECX register when | |
1203 | * one calls the CPUID instruction. Their meaning is | |
1204 | * explained in table 3-5, but DMI doesn't support this | |
1205 | * yet. | |
1206 | */ | |
1207 | print_cb(label, | |
1208 | "Type %u, Family %u, Model %u, Stepping %u", | |
1209 | (eax >> 12) & 0x3, | |
1210 | ((eax >> 20) & 0xFF) + ((eax >> 8) & 0x0F), | |
1211 | ((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F), | |
1212 | eax & 0xF); | |
1213 | break; | |
1214 | ||
1215 | case cpuid_x86_amd: /* AMD, publication #25481 revision 2.28 */ | |
1216 | eax = DWORD(p); | |
1217 | print_cb(label, "Family %u, Model %u, Stepping %u", | |
1218 | ((eax >> 8) & 0xF) + (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : 0), | |
1219 | ((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF ? (eax >> 12) & 0xF0 : 0), | |
1220 | eax & 0xF); | |
1221 | break; | |
1222 | default: | |
1223 | return; | |
1224 | } | |
1225 | } | |
1226 | ||
1039 | 1227 | static void dmi_processor_id(const struct dmi_header *h) |
1040 | 1228 | { |
1041 | 1229 | /* Intel AP-485 revision 36, table 2-4 */ |
1075 | 1263 | }; |
1076 | 1264 | const u8 *data = h->data; |
1077 | 1265 | const u8 *p = data + 0x08; |
1078 | u32 eax, edx; | |
1079 | int sig = 0; | |
1080 | u16 type; | |
1081 | ||
1082 | type = (data[0x06] == 0xFE && h->length >= 0x2A) ? | |
1083 | WORD(data + 0x28) : data[0x06]; | |
1266 | enum cpuid_type sig = dmi_get_cpuid_type(h); | |
1267 | u32 edx; | |
1084 | 1268 | |
1085 | 1269 | /* |
1086 | 1270 | * This might help learn about new processors supporting the |
1087 | 1271 | * CPUID instruction or another form of identification. |
1088 | 1272 | */ |
1089 | pr_attr("ID", "%02X %02X %02X %02X %02X %02X %02X %02X", | |
1090 | p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); | |
1091 | ||
1092 | if (type == 0x05) /* 80386 */ | |
1093 | { | |
1094 | u16 dx = WORD(p); | |
1095 | /* | |
1096 | * 80386 have a different signature. | |
1097 | */ | |
1098 | pr_attr("Signature", | |
1099 | "Type %u, Family %u, Major Stepping %u, Minor Stepping %u", | |
1100 | dx >> 12, (dx >> 8) & 0xF, | |
1101 | (dx >> 4) & 0xF, dx & 0xF); | |
1273 | if (!(opt.flags & FLAG_QUIET)) | |
1274 | pr_attr("ID", "%02X %02X %02X %02X %02X %02X %02X %02X", | |
1275 | p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); | |
1276 | ||
1277 | dmi_print_cpuid(pr_attr, "Signature", sig, p); | |
1278 | ||
1279 | if (sig != cpuid_x86_intel && sig != cpuid_x86_amd) | |
1102 | 1280 | return; |
1103 | } | |
1104 | if (type == 0x06) /* 80486 */ | |
1105 | { | |
1106 | u16 dx = WORD(p); | |
1107 | /* | |
1108 | * Not all 80486 CPU support the CPUID instruction, we have to find | |
1109 | * wether the one we have here does or not. Note that this trick | |
1110 | * works only because we know that 80486 must be little-endian. | |
1111 | */ | |
1112 | if ((dx & 0x0F00) == 0x0400 | |
1113 | && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070) | |
1114 | && ((dx & 0x000F) >= 0x0003)) | |
1115 | sig = 1; | |
1116 | else | |
1117 | { | |
1118 | pr_attr("Signature", | |
1119 | "Type %u, Family %u, Model %u, Stepping %u", | |
1120 | (dx >> 12) & 0x3, (dx >> 8) & 0xF, | |
1121 | (dx >> 4) & 0xF, dx & 0xF); | |
1122 | return; | |
1123 | } | |
1124 | } | |
1125 | else if ((type >= 0x100 && type <= 0x101) /* ARM */ | |
1126 | || (type >= 0x118 && type <= 0x119)) /* ARM */ | |
1127 | { | |
1128 | u32 midr = DWORD(p); | |
1129 | /* | |
1130 | * The format of this field was not defined for ARM processors | |
1131 | * before version 3.1.0 of the SMBIOS specification, so we | |
1132 | * silently skip it if it reads all zeroes. | |
1133 | */ | |
1134 | if (midr == 0) | |
1135 | return; | |
1136 | pr_attr("Signature", | |
1137 | "Implementor 0x%02x, Variant 0x%x, Architecture %u, Part 0x%03x, Revision %u", | |
1138 | midr >> 24, (midr >> 20) & 0xF, | |
1139 | (midr >> 16) & 0xF, (midr >> 4) & 0xFFF, midr & 0xF); | |
1140 | return; | |
1141 | } | |
1142 | else if ((type >= 0x0B && type <= 0x15) /* Intel, Cyrix */ | |
1143 | || (type >= 0x28 && type <= 0x2F) /* Intel */ | |
1144 | || (type >= 0xA1 && type <= 0xB3) /* Intel */ | |
1145 | || type == 0xB5 /* Intel */ | |
1146 | || (type >= 0xB9 && type <= 0xC7) /* Intel */ | |
1147 | || (type >= 0xCD && type <= 0xCF) /* Intel */ | |
1148 | || (type >= 0xD2 && type <= 0xDB) /* VIA, Intel */ | |
1149 | || (type >= 0xDD && type <= 0xE0)) /* Intel */ | |
1150 | sig = 1; | |
1151 | else if ((type >= 0x18 && type <= 0x1D) /* AMD */ | |
1152 | || type == 0x1F /* AMD */ | |
1153 | || (type >= 0x38 && type <= 0x3F) /* AMD */ | |
1154 | || (type >= 0x46 && type <= 0x4F) /* AMD */ | |
1155 | || (type >= 0x66 && type <= 0x6B) /* AMD */ | |
1156 | || (type >= 0x83 && type <= 0x8F) /* AMD */ | |
1157 | || (type >= 0xB6 && type <= 0xB7) /* AMD */ | |
1158 | || (type >= 0xE4 && type <= 0xEF)) /* AMD */ | |
1159 | sig = 2; | |
1160 | else if (type == 0x01 || type == 0x02) | |
1161 | { | |
1162 | const char *version = dmi_string(h, data[0x10]); | |
1163 | /* | |
1164 | * Some X86-class CPU have family "Other" or "Unknown". In this case, | |
1165 | * we use the version string to determine if they are known to | |
1166 | * support the CPUID instruction. | |
1167 | */ | |
1168 | if (strncmp(version, "Pentium III MMX", 15) == 0 | |
1169 | || strncmp(version, "Intel(R) Core(TM)2", 18) == 0 | |
1170 | || strncmp(version, "Intel(R) Pentium(R)", 19) == 0 | |
1171 | || strcmp(version, "Genuine Intel(R) CPU U1400") == 0) | |
1172 | sig = 1; | |
1173 | else if (strncmp(version, "AMD Athlon(TM)", 14) == 0 | |
1174 | || strncmp(version, "AMD Opteron(tm)", 15) == 0 | |
1175 | || strncmp(version, "Dual-Core AMD Opteron(tm)", 25) == 0) | |
1176 | sig = 2; | |
1177 | else | |
1178 | return; | |
1179 | } | |
1180 | else /* neither X86 nor ARM */ | |
1181 | return; | |
1182 | ||
1183 | /* | |
1184 | * Extra flags are now returned in the ECX register when one calls | |
1185 | * the CPUID instruction. Their meaning is explained in table 3-5, but | |
1186 | * DMI doesn't support this yet. | |
1187 | */ | |
1188 | eax = DWORD(p); | |
1189 | edx = DWORD(p + 4); | |
1190 | switch (sig) | |
1191 | { | |
1192 | case 1: /* Intel */ | |
1193 | pr_attr("Signature", | |
1194 | "Type %u, Family %u, Model %u, Stepping %u", | |
1195 | (eax >> 12) & 0x3, | |
1196 | ((eax >> 20) & 0xFF) + ((eax >> 8) & 0x0F), | |
1197 | ((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F), | |
1198 | eax & 0xF); | |
1199 | break; | |
1200 | case 2: /* AMD, publication #25481 revision 2.28 */ | |
1201 | pr_attr("Signature", "Family %u, Model %u, Stepping %u", | |
1202 | ((eax >> 8) & 0xF) + (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : 0), | |
1203 | ((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF ? (eax >> 12) & 0xF0 : 0), | |
1204 | eax & 0xF); | |
1205 | break; | |
1206 | } | |
1207 | 1281 | |
1208 | 1282 | edx = DWORD(p + 4); |
1209 | 1283 | if ((edx & 0xBFEFFBFF) == 0) |
1354 | 1428 | "Socket LGA2066", |
1355 | 1429 | "Socket BGA1392", |
1356 | 1430 | "Socket BGA1510", |
1357 | "Socket BGA1528" /* 0x3C */ | |
1358 | }; | |
1359 | ||
1360 | if (code >= 0x01 && code <= 0x3C) | |
1431 | "Socket BGA1528", | |
1432 | "Socket LGA4189", | |
1433 | "Socket LGA1200", | |
1434 | "Socket LGA4677" /* 0x3F */ | |
1435 | }; | |
1436 | ||
1437 | if (code >= 0x01 && code <= 0x3F) | |
1361 | 1438 | return upgrade[code - 0x01]; |
1362 | 1439 | return out_of_spec; |
1363 | 1440 | } |
1385 | 1462 | "Hardware Thread", |
1386 | 1463 | "Execute Protection", |
1387 | 1464 | "Enhanced Virtualization", |
1388 | "Power/Performance Control" /* 7 */ | |
1465 | "Power/Performance Control", | |
1466 | "128-bit Capable", | |
1467 | "Arm64 SoC ID" /* 9 */ | |
1389 | 1468 | }; |
1390 | 1469 | |
1391 | 1470 | if ((code & 0x00FC) == 0) |
1395 | 1474 | int i; |
1396 | 1475 | |
1397 | 1476 | pr_list_start(attr, NULL); |
1398 | for (i = 2; i <= 7; i++) | |
1477 | for (i = 2; i <= 9; i++) | |
1399 | 1478 | if (code & (1 << i)) |
1400 | 1479 | pr_list_item("%s", characteristics[i - 2]); |
1401 | 1480 | pr_list_end(); |
1930 | 2009 | "MXM Type IV", |
1931 | 2010 | "MXM 3.0 Type A", |
1932 | 2011 | "MXM 3.0 Type B", |
1933 | "PCI Express 2 SFF-8639", | |
1934 | "PCI Express 3 SFF-8639", | |
2012 | "PCI Express 2 SFF-8639 (U.2)", | |
2013 | "PCI Express 3 SFF-8639 (U.2)", | |
1935 | 2014 | "PCI Express Mini 52-pin with bottom-side keep-outs", |
1936 | 2015 | "PCI Express Mini 52-pin without bottom-side keep-outs", |
1937 | "PCI Express Mini 76-pin" /* 0x23 */ | |
2016 | "PCI Express Mini 76-pin", | |
2017 | "PCI Express 4 SFF-8639 (U.2)", | |
2018 | "PCI Express 5 SFF-8639 (U.2)", | |
2019 | "OCP NIC 3.0 Small Form Factor (SFF)", | |
2020 | "OCP NIC 3.0 Large Form Factor (LFF)", | |
2021 | "OCP NIC Prior to 3.0" /* 0x28 */ | |
1938 | 2022 | }; |
1939 | 2023 | static const char *type_0x30[] = { |
1940 | 2024 | "CXL FLexbus 1.0" /* 0x30 */ |
1969 | 2053 | "PCI Express 4 x2", |
1970 | 2054 | "PCI Express 4 x4", |
1971 | 2055 | "PCI Express 4 x8", |
1972 | "PCI Express 4 x16" /* 0xBD */ | |
2056 | "PCI Express 4 x16", | |
2057 | "PCI Express 5", | |
2058 | "PCI Express 5 x1", | |
2059 | "PCI Express 5 x2", | |
2060 | "PCI Express 5 x4", | |
2061 | "PCI Express 5 x8", | |
2062 | "PCI Express 5 x16", | |
2063 | "PCI Express 6+", | |
2064 | "EDSFF E1", | |
2065 | "EDSFF E3" /* 0xC6 */ | |
1973 | 2066 | }; |
1974 | 2067 | /* |
1975 | 2068 | * Note to developers: when adding entries to these lists, check if |
1976 | 2069 | * function dmi_slot_id below needs updating too. |
1977 | 2070 | */ |
1978 | 2071 | |
1979 | if (code >= 0x01 && code <= 0x23) | |
2072 | if (code >= 0x01 && code <= 0x28) | |
1980 | 2073 | return type[code - 0x01]; |
1981 | 2074 | if (code == 0x30) |
1982 | 2075 | return type_0x30[code - 0x30]; |
1983 | if (code >= 0xA0 && code <= 0xBD) | |
2076 | if (code >= 0xA0 && code <= 0xC6) | |
1984 | 2077 | return type_0xA0[code - 0xA0]; |
1985 | 2078 | return out_of_spec; |
1986 | 2079 | } |
1987 | 2080 | |
1988 | static const char *dmi_slot_bus_width(u8 code) | |
2081 | /* If hide_unknown is set, return NULL instead of "Other" or "Unknown" */ | |
2082 | static const char *dmi_slot_bus_width(u8 code, int hide_unknown) | |
1989 | 2083 | { |
1990 | 2084 | /* 7.10.2 */ |
1991 | 2085 | static const char *width[] = { |
1992 | "", /* 0x01, "Other" */ | |
1993 | "", /* "Unknown" */ | |
1994 | "8-bit ", | |
1995 | "16-bit ", | |
1996 | "32-bit ", | |
1997 | "64-bit ", | |
1998 | "128-bit ", | |
1999 | "x1 ", | |
2000 | "x2 ", | |
2001 | "x4 ", | |
2002 | "x8 ", | |
2003 | "x12 ", | |
2004 | "x16 ", | |
2005 | "x32 " /* 0x0E */ | |
2086 | "Other", /* 0x01 */ | |
2087 | "Unknown", | |
2088 | "8-bit", | |
2089 | "16-bit", | |
2090 | "32-bit", | |
2091 | "64-bit", | |
2092 | "128-bit", | |
2093 | "x1", | |
2094 | "x2", | |
2095 | "x4", | |
2096 | "x8", | |
2097 | "x12", | |
2098 | "x16", | |
2099 | "x32" /* 0x0E */ | |
2006 | 2100 | }; |
2007 | 2101 | |
2008 | 2102 | if (code >= 0x01 && code <= 0x0E) |
2103 | { | |
2104 | if (code <= 0x02 && hide_unknown) | |
2105 | return NULL; | |
2009 | 2106 | return width[code - 0x01]; |
2107 | } | |
2010 | 2108 | return out_of_spec; |
2109 | } | |
2110 | ||
2111 | static void dmi_slot_type_with_width(u8 type, u8 width) | |
2112 | { | |
2113 | const char *type_str, *width_str; | |
2114 | ||
2115 | type_str = dmi_slot_type(type); | |
2116 | width_str = dmi_slot_bus_width(width, 1); | |
2117 | ||
2118 | if (width_str) | |
2119 | pr_attr("Type", "%s %s", width_str, type_str); | |
2120 | else | |
2121 | pr_attr("Type", "%s", type_str); | |
2011 | 2122 | } |
2012 | 2123 | |
2013 | 2124 | static const char *dmi_slot_current_usage(u8 code) |
2090 | 2201 | case 0xBB: /* PCI Express 4 */ |
2091 | 2202 | case 0xBC: /* PCI Express 4 */ |
2092 | 2203 | case 0xBD: /* PCI Express 4 */ |
2204 | case 0xBE: /* PCI Express 5 */ | |
2205 | case 0xBF: /* PCI Express 5 */ | |
2206 | case 0xC0: /* PCI Express 5 */ | |
2207 | case 0xC1: /* PCI Express 5 */ | |
2208 | case 0xC2: /* PCI Express 5 */ | |
2209 | case 0xC3: /* PCI Express 5 */ | |
2210 | case 0xC4: /* PCI Express 6+ */ | |
2093 | 2211 | pr_attr("ID", "%u", code1); |
2094 | 2212 | break; |
2095 | 2213 | case 0x07: /* PCMCIA */ |
2115 | 2233 | "PME signal is supported", /* 0 */ |
2116 | 2234 | "Hot-plug devices are supported", |
2117 | 2235 | "SMBus signal is supported", |
2118 | "PCIe slot bifurcation is supported" /* 3 */ | |
2236 | "PCIe slot bifurcation is supported", | |
2237 | "Async/surprise removal is supported", | |
2238 | "Flexbus slot, CXL 1.0 capable", | |
2239 | "Flexbus slot, CXL 2.0 capable" /* 6 */ | |
2119 | 2240 | }; |
2120 | 2241 | |
2121 | 2242 | if (code1 & (1 << 0)) |
2130 | 2251 | for (i = 1; i <= 7; i++) |
2131 | 2252 | if (code1 & (1 << i)) |
2132 | 2253 | pr_list_item("%s", characteristics1[i - 1]); |
2133 | for (i = 0; i <= 3; i++) | |
2254 | for (i = 0; i <= 6; i++) | |
2134 | 2255 | if (code2 & (1 << i)) |
2135 | 2256 | pr_list_item("%s", characteristics2[i]); |
2136 | 2257 | pr_list_end(); |
2152 | 2273 | |
2153 | 2274 | for (i = 1; i <= n; i++, data += 5) |
2154 | 2275 | { |
2155 | sprintf(attr, "Peer Device %hu", i); | |
2276 | sprintf(attr, "Peer Device %hhu", (u8)i); | |
2156 | 2277 | pr_attr(attr, "%04x:%02x:%02x.%x (Width %u)", |
2157 | 2278 | WORD(data), data[2], data[3] >> 3, data[3] & 0x07, |
2158 | 2279 | data[4]); |
2159 | 2280 | } |
2281 | } | |
2282 | ||
2283 | static void dmi_slot_information(u8 type, u8 code) | |
2284 | { | |
2285 | switch (type) | |
2286 | { | |
2287 | case 0x1F: /* PCI Express 2 */ | |
2288 | case 0x20: /* PCI Express 3 */ | |
2289 | case 0x21: /* PCI Express Mini */ | |
2290 | case 0x22: /* PCI Express Mini */ | |
2291 | case 0x23: /* PCI Express Mini */ | |
2292 | case 0xA5: /* PCI Express */ | |
2293 | case 0xA6: /* PCI Express */ | |
2294 | case 0xA7: /* PCI Express */ | |
2295 | case 0xA8: /* PCI Express */ | |
2296 | case 0xA9: /* PCI Express */ | |
2297 | case 0xAA: /* PCI Express */ | |
2298 | case 0xAB: /* PCI Express 2 */ | |
2299 | case 0xAC: /* PCI Express 2 */ | |
2300 | case 0xAD: /* PCI Express 2 */ | |
2301 | case 0xAE: /* PCI Express 2 */ | |
2302 | case 0xAF: /* PCI Express 2 */ | |
2303 | case 0xB0: /* PCI Express 2 */ | |
2304 | case 0xB1: /* PCI Express 3 */ | |
2305 | case 0xB2: /* PCI Express 3 */ | |
2306 | case 0xB3: /* PCI Express 3 */ | |
2307 | case 0xB4: /* PCI Express 3 */ | |
2308 | case 0xB5: /* PCI Express 3 */ | |
2309 | case 0xB6: /* PCI Express 3 */ | |
2310 | case 0xB8: /* PCI Express 4 */ | |
2311 | case 0xB9: /* PCI Express 4 */ | |
2312 | case 0xBA: /* PCI Express 4 */ | |
2313 | case 0xBB: /* PCI Express 4 */ | |
2314 | case 0xBC: /* PCI Express 4 */ | |
2315 | case 0xBD: /* PCI Express 4 */ | |
2316 | case 0xBE: /* PCI Express 5 */ | |
2317 | case 0xBF: /* PCI Express 5 */ | |
2318 | case 0xC0: /* PCI Express 5 */ | |
2319 | case 0xC1: /* PCI Express 5 */ | |
2320 | case 0xC2: /* PCI Express 5 */ | |
2321 | case 0xC3: /* PCI Express 5 */ | |
2322 | case 0xC4: /* PCI Express 6+ */ | |
2323 | if (code) | |
2324 | pr_attr("PCI Express Generation", "%u", code); | |
2325 | break; | |
2326 | } | |
2327 | } | |
2328 | ||
2329 | static void dmi_slot_physical_width(u8 code) | |
2330 | { | |
2331 | if (code) | |
2332 | pr_attr("Slot Physical Width", "%s", | |
2333 | dmi_slot_bus_width(code, 0)); | |
2334 | } | |
2335 | ||
2336 | static void dmi_slot_pitch(u16 code) | |
2337 | { | |
2338 | if (code) | |
2339 | pr_attr("Pitch", "%u.%02u mm", code / 100, code % 100); | |
2340 | } | |
2341 | ||
2342 | static const char *dmi_slot_height(u8 code) | |
2343 | { | |
2344 | /* 7.10.3 */ | |
2345 | static const char *height[] = { | |
2346 | "Not applicable", /* 0x00 */ | |
2347 | "Other", | |
2348 | "Unknown", | |
2349 | "Full height", | |
2350 | "Low-profile" /* 0x04 */ | |
2351 | }; | |
2352 | ||
2353 | if (code <= 0x04) | |
2354 | return height[code]; | |
2355 | return out_of_spec; | |
2160 | 2356 | } |
2161 | 2357 | |
2162 | 2358 | /* |
2176 | 2372 | "Sound", |
2177 | 2373 | "PATA Controller", |
2178 | 2374 | "SATA Controller", |
2179 | "SAS Controller" /* 0x0A */ | |
2180 | }; | |
2181 | ||
2182 | if (code >= 0x01 && code <= 0x0A) | |
2375 | "SAS Controller", | |
2376 | "Wireless LAN", | |
2377 | "Bluetooth", | |
2378 | "WWAN", | |
2379 | "eMMC", | |
2380 | "NVMe Controller", | |
2381 | "UFS Controller" /* 0x10 */ | |
2382 | }; | |
2383 | ||
2384 | if (code >= 0x01 && code <= 0x10) | |
2183 | 2385 | return type[code - 0x01]; |
2184 | 2386 | return out_of_spec; |
2185 | 2387 | } |
2218 | 2420 | |
2219 | 2421 | for (i = 1; i <= count; i++) |
2220 | 2422 | { |
2221 | sprintf(attr, "String %hu", i); | |
2423 | sprintf(attr, "String %hhu", (u8)i); | |
2222 | 2424 | pr_attr(attr, "%s",dmi_string(h, i)); |
2223 | 2425 | } |
2224 | 2426 | } |
2236 | 2438 | |
2237 | 2439 | for (i = 1; i <= count; i++) |
2238 | 2440 | { |
2239 | sprintf(attr, "Option %hu", i); | |
2441 | sprintf(attr, "Option %hhu", (u8)i); | |
2240 | 2442 | pr_attr(attr, "%s",dmi_string(h, i)); |
2241 | 2443 | } |
2242 | 2444 | } |
2420 | 2622 | { |
2421 | 2623 | if (len >= 0x02) |
2422 | 2624 | { |
2423 | sprintf(attr, "Descriptor %hu", i + 1); | |
2625 | sprintf(attr, "Descriptor %d", i + 1); | |
2424 | 2626 | pr_attr(attr, "%s", |
2425 | 2627 | dmi_event_log_descriptor_type(p[i * len])); |
2426 | sprintf(attr, "Data Format %hu", i + 1); | |
2628 | sprintf(attr, "Data Format %d", i + 1); | |
2427 | 2629 | pr_attr(attr, "%s", |
2428 | 2630 | dmi_event_log_descriptor_format(p[i * len + 1])); |
2429 | 2631 | } |
2638 | 2840 | "LPDDR4", |
2639 | 2841 | "Logical non-volatile device", |
2640 | 2842 | "HBM", |
2641 | "HBM2" /* 0x21 */ | |
2642 | }; | |
2643 | ||
2644 | if (code >= 0x01 && code <= 0x21) | |
2843 | "HBM2", | |
2844 | "DDR5", | |
2845 | "LPDDR5" /* 0x23 */ | |
2846 | }; | |
2847 | ||
2848 | if (code >= 0x01 && code <= 0x23) | |
2645 | 2849 | return type[code - 0x01]; |
2646 | 2850 | return out_of_spec; |
2647 | 2851 | } |
2683 | 2887 | } |
2684 | 2888 | } |
2685 | 2889 | |
2686 | static void dmi_memory_device_speed(const char *attr, u16 code) | |
2687 | { | |
2688 | if (code == 0) | |
2689 | pr_attr(attr, "Unknown"); | |
2690 | else | |
2691 | pr_attr(attr, "%u MT/s", code); | |
2890 | static void dmi_memory_device_speed(const char *attr, u16 code1, u32 code2) | |
2891 | { | |
2892 | if (code1 == 0xFFFF) | |
2893 | { | |
2894 | if (code2 == 0) | |
2895 | pr_attr(attr, "Unknown"); | |
2896 | else | |
2897 | pr_attr(attr, "%lu MT/s", code2); | |
2898 | } | |
2899 | else | |
2900 | { | |
2901 | if (code1 == 0) | |
2902 | pr_attr(attr, "Unknown"); | |
2903 | else | |
2904 | pr_attr(attr, "%u MT/s", code1); | |
2905 | } | |
2692 | 2906 | } |
2693 | 2907 | |
2694 | 2908 | static void dmi_memory_technology(u8 code) |
2947 | 3161 | static const char *interface_0xA0[] = { |
2948 | 3162 | "Bus Mouse DB-9", /* 0xA0 */ |
2949 | 3163 | "Bus Mouse Micro DIN", |
2950 | "USB" /* 0xA2 */ | |
3164 | "USB", | |
3165 | "I2C", | |
3166 | "SPI" /* 0xA4 */ | |
2951 | 3167 | }; |
2952 | 3168 | |
2953 | 3169 | if (code >= 0x01 && code <= 0x08) |
2954 | 3170 | return interface[code - 0x01]; |
2955 | if (code >= 0xA0 && code <= 0xA2) | |
3171 | if (code >= 0xA0 && code <= 0xA4) | |
2956 | 3172 | return interface_0xA0[code - 0xA0]; |
2957 | 3173 | return out_of_spec; |
2958 | 3174 | } |
3389 | 3605 | |
3390 | 3606 | for (i = 1; i <= count; i++) |
3391 | 3607 | { |
3392 | sprintf(attr, "Device %hu Load", i); | |
3608 | sprintf(attr, "Device %hhu Load", (u8)i); | |
3393 | 3609 | pr_attr(attr, "%u", p[3 * i]); |
3394 | 3610 | if (!(opt.flags & FLAG_QUIET)) |
3395 | 3611 | { |
3396 | sprintf(attr, "Device %hu Handle", i); | |
3612 | sprintf(attr, "Device %hhu Handle", (u8)i); | |
3397 | 3613 | pr_attr(attr, "0x%04X", WORD(p + 3 * i + 1)); |
3398 | 3614 | } |
3399 | 3615 | } |
3706 | 3922 | * convenience. It could get passed from the SMBIOS |
3707 | 3923 | * header, but that's a lot of passing of pointers just |
3708 | 3924 | * to get that info, and the only thing it is used for is |
3709 | * to determine the endianess of the field. Since we only | |
3925 | * to determine the endianness of the field. Since we only | |
3710 | 3926 | * do this parsing on versions of SMBIOS after 3.1.1, and the |
3711 | * endianess of the field is always little after version 2.6.0 | |
3927 | * endianness of the field is always little after version 2.6.0 | |
3712 | 3928 | * we can just pick a sufficiently recent version here. |
3713 | 3929 | */ |
3714 | 3930 | dmi_system_uuid(pr_subattr, "Service UUID", &rdata[0], 0x311); |
3715 | 3931 | |
3716 | 3932 | /* |
3717 | 3933 | * DSP0270: 8.6: Redfish Over IP Host IP Assignment Type |
3718 | * Note, using decimal indicies here, as the DSP0270 | |
3934 | * Note, using decimal indices here, as the DSP0270 | |
3719 | 3935 | * uses decimal, so as to make it more comparable |
3720 | 3936 | */ |
3721 | 3937 | assign_val = rdata[16]; |
4010 | 4226 | } |
4011 | 4227 | |
4012 | 4228 | /* |
4229 | * 7.46 Firmware Inventory Information (Type 45) | |
4230 | */ | |
4231 | ||
4232 | static void dmi_firmware_characteristics(u16 code) | |
4233 | { | |
4234 | /* 7.46.3 */ | |
4235 | static const char *characteristics[] = { | |
4236 | "Updatable", /* 0 */ | |
4237 | "Write-Protect" /* 1 */ | |
4238 | }; | |
4239 | int i; | |
4240 | ||
4241 | for (i = 0; i <= 1; i++) | |
4242 | pr_list_item("%s: %s", characteristics[i], | |
4243 | (code & (1 << i)) ? "Yes" : "No"); | |
4244 | } | |
4245 | ||
4246 | static const char *dmi_firmware_state(u8 code) | |
4247 | { | |
4248 | /* 7.46.4 */ | |
4249 | static const char *state[] = { | |
4250 | "Other", /* 0x01 */ | |
4251 | "Unknown", | |
4252 | "Disabled", | |
4253 | "Enabled", | |
4254 | "Absent", | |
4255 | "Stand-by Offline", | |
4256 | "Stand-by Spare", | |
4257 | "Unavailable Offline" /* 0x08 */ | |
4258 | }; | |
4259 | ||
4260 | if (code >= 0x01 && code <= 0x08) | |
4261 | return state[code - 0x01]; | |
4262 | return out_of_spec; | |
4263 | } | |
4264 | ||
4265 | static void dmi_firmware_components(u8 count, const u8 *p) | |
4266 | { | |
4267 | int i; | |
4268 | ||
4269 | pr_list_start("Associated Components", "%u", count); | |
4270 | for (i = 0; i < count; i++) | |
4271 | pr_list_item("0x%04X", WORD(p + sizeof(u16) * i)); | |
4272 | pr_list_end(); | |
4273 | } | |
4274 | ||
4275 | /* | |
4013 | 4276 | * Main |
4014 | 4277 | */ |
4015 | 4278 | |
4032 | 4295 | pr_attr("Release Date", "%s", |
4033 | 4296 | dmi_string(h, data[0x08])); |
4034 | 4297 | /* |
4035 | * On IA-64, the BIOS base address will read 0 because | |
4036 | * there is no BIOS. Skip the base address and the | |
4037 | * runtime size in this case. | |
4298 | * On IA-64 and UEFI-based systems, the BIOS base | |
4299 | * address will read 0 because there is no BIOS. Skip | |
4300 | * the base address and the runtime size in this case. | |
4038 | 4301 | */ |
4039 | 4302 | if (WORD(data + 0x06) != 0) |
4040 | 4303 | { |
4301 | 4564 | if (h->length < 0x0C) break; |
4302 | 4565 | pr_attr("Designation", "%s", |
4303 | 4566 | dmi_string(h, data[0x04])); |
4304 | pr_attr("Type", "%s%s", | |
4305 | dmi_slot_bus_width(data[0x06]), | |
4306 | dmi_slot_type(data[0x05])); | |
4567 | dmi_slot_type_with_width(data[0x05], data[0x06]); | |
4307 | 4568 | pr_attr("Current Usage", "%s", |
4308 | 4569 | dmi_slot_current_usage(data[0x07])); |
4309 | 4570 | pr_attr("Length", "%s", |
4318 | 4579 | if (h->length < 0x13) break; |
4319 | 4580 | pr_attr("Data Bus Width", "%u", data[0x11]); |
4320 | 4581 | pr_attr("Peer Devices", "%u", data[0x12]); |
4321 | if (h->length - 0x13 >= data[0x12] * 5) | |
4322 | dmi_slot_peers(data[0x12], data + 0x13); | |
4582 | if (h->length < 0x13 + data[0x12] * 5) break; | |
4583 | dmi_slot_peers(data[0x12], data + 0x13); | |
4584 | if (h->length < 0x17 + data[0x12] * 5) break; | |
4585 | dmi_slot_information(data[0x05], data[0x13 + data[0x12] * 5]); | |
4586 | dmi_slot_physical_width(data[0x14 + data[0x12] * 5]); | |
4587 | dmi_slot_pitch(WORD(data + 0x15 + data[0x12] * 5)); | |
4588 | if (h->length < 0x18 + data[0x12] * 5) break; | |
4589 | pr_attr("Height", "%s", | |
4590 | dmi_slot_height(data[0x17 + data[0x12] * 5])); | |
4323 | 4591 | break; |
4324 | 4592 | |
4325 | 4593 | case 10: /* 7.11 On Board Devices Information */ |
4450 | 4718 | dmi_memory_device_type(data[0x12])); |
4451 | 4719 | dmi_memory_device_type_detail(WORD(data + 0x13)); |
4452 | 4720 | if (h->length < 0x17) break; |
4453 | dmi_memory_device_speed("Speed", WORD(data + 0x15)); | |
4721 | /* If no module is present, the remaining fields are irrelevant */ | |
4722 | if (WORD(data + 0x0C) == 0) | |
4723 | break; | |
4724 | dmi_memory_device_speed("Speed", WORD(data + 0x15), | |
4725 | h->length >= 0x5C ? | |
4726 | DWORD(data + 0x54) : 0); | |
4454 | 4727 | if (h->length < 0x1B) break; |
4455 | 4728 | pr_attr("Manufacturer", "%s", |
4456 | 4729 | dmi_string(h, data[0x17])); |
4467 | 4740 | pr_attr("Rank", "%u", data[0x1B] & 0x0F); |
4468 | 4741 | if (h->length < 0x22) break; |
4469 | 4742 | dmi_memory_device_speed("Configured Memory Speed", |
4470 | WORD(data + 0x20)); | |
4743 | WORD(data + 0x20), | |
4744 | h->length >= 0x5C ? | |
4745 | DWORD(data + 0x58) : 0); | |
4471 | 4746 | if (h->length < 0x28) break; |
4472 | 4747 | dmi_memory_voltage_value("Minimum Voltage", |
4473 | 4748 | WORD(data + 0x22)); |
5050 | 5325 | DWORD(data + 0x1B)); |
5051 | 5326 | break; |
5052 | 5327 | |
5053 | case 126: /* 7.44 Inactive */ | |
5328 | case 45: /* 7.46 Firmware Inventory Information */ | |
5329 | pr_handle_name("Firmware Inventory Information"); | |
5330 | if (h->length < 0x18) break; | |
5331 | pr_attr("Firmware Component Name", "%s", | |
5332 | dmi_string(h, data[0x04])); | |
5333 | pr_attr("Firmware Version", "%s", | |
5334 | dmi_string(h, data[0x05])); | |
5335 | pr_attr("Firmware ID", "%s", dmi_string(h, data[0x07])); | |
5336 | pr_attr("Release Date", "%s", dmi_string(h, data[0x09])); | |
5337 | pr_attr("Manufacturer", "%s", dmi_string(h, data[0x0A])); | |
5338 | pr_attr("Lowest Supported Firmware Version", "%s", | |
5339 | dmi_string(h, data[0x0B])); | |
5340 | dmi_memory_size("Image Size", QWORD(data + 0x0C)); | |
5341 | pr_list_start("Characteristics", NULL); | |
5342 | dmi_firmware_characteristics(WORD(data + 0x14)); | |
5343 | pr_list_end(); | |
5344 | pr_attr("State", "%s", dmi_firmware_state(data[0x16])); | |
5345 | if (h->length < 0x18 + data[0x17] * 2) break; | |
5346 | if (!(opt.flags & FLAG_QUIET)) | |
5347 | dmi_firmware_components(data[0x17], data + 0x18); | |
5348 | break; | |
5349 | ||
5350 | case 126: | |
5054 | 5351 | pr_handle_name("Inactive"); |
5055 | 5352 | break; |
5056 | 5353 | |
5057 | case 127: /* 7.45 End Of Table */ | |
5354 | case 127: | |
5058 | 5355 | pr_handle_name("End Of Table"); |
5059 | 5356 | break; |
5060 | 5357 | |
5141 | 5438 | u8 *data; |
5142 | 5439 | int i = 0; |
5143 | 5440 | |
5441 | /* First pass: Save specific values needed to decode OEM types */ | |
5442 | data = buf; | |
5443 | while ((i < num || !num) | |
5444 | && data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */ | |
5445 | { | |
5446 | u8 *next; | |
5447 | struct dmi_header h; | |
5448 | ||
5449 | to_dmi_header(&h, data); | |
5450 | ||
5451 | /* | |
5452 | * If a short entry is found (less than 4 bytes), not only it | |
5453 | * is invalid, but we cannot reliably locate the next entry. | |
5454 | * Also stop at end-of-table marker if so instructed. | |
5455 | */ | |
5456 | if (h.length < 4 || | |
5457 | (h.type == 127 && | |
5458 | (opt.flags & (FLAG_QUIET | FLAG_STOP_AT_EOT)))) | |
5459 | break; | |
5460 | i++; | |
5461 | ||
5462 | /* Look for the next handle */ | |
5463 | next = data + h.length; | |
5464 | while ((unsigned long)(next - buf + 1) < len | |
5465 | && (next[0] != 0 || next[1] != 0)) | |
5466 | next++; | |
5467 | next += 2; | |
5468 | ||
5469 | /* Make sure the whole structure fits in the table */ | |
5470 | if ((unsigned long)(next - buf) > len) | |
5471 | break; | |
5472 | ||
5473 | /* Assign vendor for vendor-specific decodes later */ | |
5474 | if (h.type == 1 && h.length >= 6) | |
5475 | dmi_set_vendor(_dmi_string(&h, data[0x04], 0), | |
5476 | _dmi_string(&h, data[0x05], 0)); | |
5477 | ||
5478 | /* Remember CPUID type for HPE type 199 */ | |
5479 | if (h.type == 4 && h.length >= 0x1A && cpuid_type == cpuid_none) | |
5480 | cpuid_type = dmi_get_cpuid_type(&h); | |
5481 | data = next; | |
5482 | } | |
5483 | ||
5484 | /* Second pass: Actually decode the data */ | |
5485 | i = 0; | |
5144 | 5486 | data = buf; |
5145 | 5487 | while ((i < num || !num) |
5146 | 5488 | && data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */ |
5199 | 5541 | data = next; |
5200 | 5542 | break; |
5201 | 5543 | } |
5202 | ||
5203 | /* assign vendor for vendor-specific decodes later */ | |
5204 | if (h.type == 1 && h.length >= 5) | |
5205 | dmi_set_vendor(dmi_string(&h, data[0x04])); | |
5206 | 5544 | |
5207 | 5545 | /* Fixup a common mistake */ |
5208 | 5546 | if (h.type == 34) |
30 | 30 | u8 *data; |
31 | 31 | }; |
32 | 32 | |
33 | enum cpuid_type | |
34 | { | |
35 | cpuid_none, | |
36 | cpuid_80386, | |
37 | cpuid_80486, | |
38 | cpuid_arm_legacy, | |
39 | cpuid_arm_soc_id, | |
40 | cpuid_x86_intel, | |
41 | cpuid_x86_amd, | |
42 | }; | |
43 | ||
44 | extern enum cpuid_type cpuid_type; | |
45 | ||
33 | 46 | int is_printable(const u8 *data, int len); |
34 | 47 | const char *dmi_string(const struct dmi_header *dm, u8 s); |
48 | void dmi_print_memory_size(const char *addr, u64 code, int shift); | |
49 | void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...), | |
50 | const char *label, enum cpuid_type sig, const u8 *p); | |
35 | 51 | |
36 | 52 | #endif |
22 | 22 | #include <string.h> |
23 | 23 | |
24 | 24 | #include "types.h" |
25 | #include "util.h" | |
25 | 26 | #include "dmidecode.h" |
26 | 27 | #include "dmioem.h" |
28 | #include "dmiopt.h" | |
27 | 29 | #include "dmioutput.h" |
28 | 30 | |
29 | 31 | /* |
41 | 43 | }; |
42 | 44 | |
43 | 45 | static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN; |
46 | static const char *dmi_product = NULL; | |
44 | 47 | |
45 | 48 | /* |
46 | 49 | * Remember the system vendor for later use. We only actually store the |
47 | 50 | * value if we know how to decode at least one specific entry type for |
48 | 51 | * that vendor. |
49 | 52 | */ |
50 | void dmi_set_vendor(const char *s) | |
51 | { | |
52 | int len; | |
53 | void dmi_set_vendor(const char *v, const char *p) | |
54 | { | |
55 | const struct { const char *str; enum DMI_VENDORS id; } vendor[] = { | |
56 | { "Acer", VENDOR_ACER }, | |
57 | { "HP", VENDOR_HP }, | |
58 | { "Hewlett-Packard", VENDOR_HP }, | |
59 | { "HPE", VENDOR_HPE }, | |
60 | { "Hewlett Packard Enterprise", VENDOR_HPE }, | |
61 | { "IBM", VENDOR_IBM }, | |
62 | { "LENOVO", VENDOR_LENOVO }, | |
63 | }; | |
64 | unsigned int i; | |
65 | size_t len; | |
53 | 66 | |
54 | 67 | /* |
55 | 68 | * Often DMI strings have trailing spaces. Ignore these |
56 | 69 | * when checking for known vendor names. |
57 | 70 | */ |
58 | len = strlen(s); | |
59 | while (len && s[len - 1] == ' ') | |
71 | len = v ? strlen(v) : 0; | |
72 | while (len && v[len - 1] == ' ') | |
60 | 73 | len--; |
61 | 74 | |
62 | if (strncmp(s, "Acer", len) == 0) | |
63 | dmi_vendor = VENDOR_ACER; | |
64 | else if (strncmp(s, "HP", len) == 0 || strncmp(s, "Hewlett-Packard", len) == 0) | |
65 | dmi_vendor = VENDOR_HP; | |
66 | else if (strncmp(s, "HPE", len) == 0 || strncmp(s, "Hewlett Packard Enterprise", len) == 0) | |
67 | dmi_vendor = VENDOR_HPE; | |
68 | else if (strncmp(s, "IBM", len) == 0) | |
69 | dmi_vendor = VENDOR_IBM; | |
70 | else if (strncmp(s, "LENOVO", len) == 0) | |
71 | dmi_vendor = VENDOR_LENOVO; | |
75 | for (i = 0; i < ARRAY_SIZE(vendor); i++) | |
76 | { | |
77 | if (strlen(vendor[i].str) == len && | |
78 | strncmp(v, vendor[i].str, len) == 0) | |
79 | { | |
80 | dmi_vendor = vendor[i].id; | |
81 | break; | |
82 | } | |
83 | } | |
84 | ||
85 | dmi_product = p; | |
72 | 86 | } |
73 | 87 | |
74 | 88 | /* |
132 | 146 | if (id == 0xFF) |
133 | 147 | id = ++nic_ctr; |
134 | 148 | |
135 | sprintf(attr, "NIC %hu", id); | |
149 | sprintf(attr, "NIC %hhu", id); | |
136 | 150 | if (dev == 0x00 && bus == 0x00) |
137 | 151 | pr_attr(attr, "Disabled"); |
138 | 152 | else if (dev == 0xFF && bus == 0xFF) |
146 | 160 | } |
147 | 161 | } |
148 | 162 | |
163 | typedef enum { G6 = 6, G7, G8, G9, G10, G10P } dmi_hpegen_t; | |
164 | ||
165 | static int dmi_hpegen(const char *s) | |
166 | { | |
167 | struct { const char *name; dmi_hpegen_t gen; } table[] = { | |
168 | { "Gen10 Plus", G10P }, | |
169 | { "Gen10", G10 }, | |
170 | { "Gen9", G9 }, | |
171 | { "Gen8", G8 }, | |
172 | { "G7", G7 }, | |
173 | { "G6", G6 }, | |
174 | }; | |
175 | unsigned int i; | |
176 | ||
177 | if (!strstr(s, "ProLiant") && !strstr(s, "Apollo") && | |
178 | !strstr(s, "Synergy") && !strstr(s, "Edgeline")) | |
179 | return -1; | |
180 | ||
181 | for (i = 0; i < ARRAY_SIZE(table); i++) { | |
182 | if (strstr(s, table[i].name)) | |
183 | return(table[i].gen); | |
184 | } | |
185 | ||
186 | return (dmi_vendor == VENDOR_HPE) ? G10P : G6; | |
187 | } | |
188 | ||
189 | static void dmi_hp_240_attr(u64 defined, u64 set) | |
190 | { | |
191 | static const char *attributes[] = { | |
192 | "Updatable", | |
193 | "Reset Required", | |
194 | "Authentication Required", | |
195 | "In Use", | |
196 | "UEFI Image", | |
197 | }; | |
198 | unsigned int i; | |
199 | ||
200 | pr_attr("Attributes Defined/Set", NULL); | |
201 | for (i = 0; i < ARRAY_SIZE(attributes); i++) | |
202 | { | |
203 | if (!(defined.l & (1UL << i))) | |
204 | continue; | |
205 | pr_subattr(attributes[i], "%s", set.l & (1UL << i) ? "Yes" : "No"); | |
206 | } | |
207 | } | |
208 | ||
209 | static void dmi_hp_203_assoc_hndl(const char *fname, u16 num) | |
210 | { | |
211 | if (opt.flags & FLAG_QUIET) | |
212 | return; | |
213 | ||
214 | if (num == 0xFFFE) | |
215 | pr_attr(fname, "N/A"); | |
216 | else | |
217 | pr_attr(fname, "0x%04X", num); | |
218 | } | |
219 | ||
220 | static void dmi_hp_203_pciinfo(const char *fname, u16 num) | |
221 | { | |
222 | if (num == 0xFFFF) | |
223 | pr_attr(fname, "Device Not Present"); | |
224 | else | |
225 | pr_attr(fname, "0x%04x", num); | |
226 | } | |
227 | ||
228 | static void dmi_hp_203_bayenc(const char *fname, u8 num) | |
229 | { | |
230 | switch (num) | |
231 | { | |
232 | case 0x00: | |
233 | pr_attr(fname, "Unknown"); | |
234 | break; | |
235 | case 0xff: | |
236 | pr_attr(fname, "Do Not Display"); | |
237 | break; | |
238 | default: | |
239 | pr_attr(fname, "%d", num); | |
240 | } | |
241 | } | |
242 | ||
243 | static void dmi_hp_203_devtyp(const char *fname, unsigned int code) | |
244 | { | |
245 | const char *str = "Reserved"; | |
246 | static const char *type[] = { | |
247 | "Unknown", /* 0x00 */ | |
248 | "Reserved", | |
249 | "Reserved", | |
250 | "Flexible LOM", | |
251 | "Embedded LOM", | |
252 | "NIC in a Slot", | |
253 | "Storage Controller", | |
254 | "Smart Array Storage Controller", | |
255 | "USB Hard Disk", | |
256 | "Other PCI Device", | |
257 | "RAM Disk", | |
258 | "Firmware Volume", | |
259 | "UEFI Shell", | |
260 | "Generic UEFI USB Boot Entry", | |
261 | "Dynamic Smart Array Controller", | |
262 | "File", | |
263 | "NVME Hard Drive", | |
264 | "NVDIMM" /* 0x11 */ | |
265 | }; | |
266 | ||
267 | if (code < ARRAY_SIZE(type)) | |
268 | str = type[code]; | |
269 | ||
270 | pr_attr(fname, "%s", str); | |
271 | } | |
272 | ||
273 | static void dmi_hp_203_devloc(const char *fname, unsigned int code) | |
274 | { | |
275 | const char *str = "Reserved"; | |
276 | static const char *location[] = { | |
277 | "Unknown", /* 0x00 */ | |
278 | "Embedded", | |
279 | "iLO Virtual Media", | |
280 | "Front USB Port", | |
281 | "Rear USB Port", | |
282 | "Internal USB", | |
283 | "Internal SD Card", | |
284 | "Internal Virutal USB (Embedded NAND)", | |
285 | "Embedded SATA Port", | |
286 | "Embedded Smart Array", | |
287 | "PCI Slot", | |
288 | "RAM Memory", | |
289 | "USB", | |
290 | "Dynamic Smart Array Controller", | |
291 | "URL", | |
292 | "NVMe Drive Bay" /* 0x0F */ | |
293 | }; | |
294 | ||
295 | if (code < ARRAY_SIZE(location)) | |
296 | str = location[code]; | |
297 | ||
298 | pr_attr(fname, "%s", str); | |
299 | } | |
300 | ||
301 | static void dmi_hp_238_loc(const char *fname, unsigned int code) | |
302 | { | |
303 | const char *str = "Reserved"; | |
304 | static const char *location[] = { | |
305 | "Internal", /* 0x00 */ | |
306 | "Front of Server", | |
307 | "Rear of Server", | |
308 | "Embedded internal SD Card", | |
309 | "iLO USB", | |
310 | "HP NAND Controller (USX 2065 or other)", | |
311 | "Reserved", | |
312 | "Debug Port", /* 0x07 */ | |
313 | }; | |
314 | ||
315 | if (code < ARRAY_SIZE(location)) | |
316 | str = location[code]; | |
317 | ||
318 | pr_attr(fname, "%s", str); | |
319 | } | |
320 | ||
321 | static void dmi_hp_238_flags(const char *fname, unsigned int code) | |
322 | { | |
323 | const char *str = "Reserved"; | |
324 | static const char *flags[] = { | |
325 | "Not Shared", /* 0x00 */ | |
326 | "Shared with physical switch", | |
327 | "Shared with automatic control", /* 0x02 */ | |
328 | }; | |
329 | ||
330 | if (code < ARRAY_SIZE(flags)) | |
331 | str = flags[code]; | |
332 | ||
333 | pr_attr(fname, "%s", str); | |
334 | } | |
335 | ||
336 | static void dmi_hp_238_speed(const char *fname, unsigned int code) | |
337 | { | |
338 | const char *str = "Reserved"; | |
339 | static const char *speed[] = { | |
340 | "Reserved", /* 0x00 */ | |
341 | "USB 1.1 Full Speed", | |
342 | "USB 2.0 High Speed", | |
343 | "USB 3.0 Super Speed" /* 0x03 */ | |
344 | }; | |
345 | ||
346 | if (code < ARRAY_SIZE(speed)) | |
347 | str = speed[code]; | |
348 | ||
349 | pr_attr(fname, "%s", str); | |
350 | } | |
351 | ||
149 | 352 | static int dmi_decode_hp(const struct dmi_header *h) |
150 | 353 | { |
151 | 354 | u8 *data = h->data; |
152 | 355 | int nic, ptr; |
153 | 356 | u32 feat; |
154 | 357 | const char *company = (dmi_vendor == VENDOR_HP) ? "HP" : "HPE"; |
358 | int gen; | |
359 | ||
360 | gen = dmi_hpegen(dmi_product); | |
361 | if (gen < 0) | |
362 | return 0; | |
155 | 363 | |
156 | 364 | switch (h->type) |
157 | 365 | { |
366 | case 194: | |
367 | /* | |
368 | * Vendor Specific: Super IO Enable/Disable Features | |
369 | * | |
370 | * Offset | Name | Width | Description | |
371 | * ------------------------------------- | |
372 | * 0x00 | Type | BYTE | 0xC2, Super IO Enable/Disable Indicator | |
373 | * 0x01 | Length | BYTE | Length of structure | |
374 | * 0x02 | Handle | WORD | Unique handle | |
375 | * 0x04 | Dev Status | BYTE | Device Status | |
376 | */ | |
377 | pr_handle_name("%s ProLiant Super IO Enable/Disable Indicator", company); | |
378 | if (h->length < 0x05) break; | |
379 | feat = data[0x04]; | |
380 | pr_attr("Serial Port A", "%s", feat & (1 << 0) ? "Enabled" : "Disabled"); | |
381 | pr_attr("Serial Port B", "%s", feat & (1 << 1) ? "Enabled" : "Disabled"); | |
382 | pr_attr("Parallel Port", "%s", feat & (1 << 2) ? "Enabled" : "Disabled"); | |
383 | pr_attr("Floppy Disk Port", "%s", feat & (1 << 3) ? "Enabled" : "Disabled"); | |
384 | pr_attr("Virtual Serial Port", "%s", feat & (1 << 4) ? "Enabled" : "Disabled"); | |
385 | break; | |
386 | ||
387 | case 199: | |
388 | /* | |
389 | * Vendor Specific: CPU Microcode Patch | |
390 | * | |
391 | * Offset | Name | Width | Description | |
392 | * ------------------------------------- | |
393 | * 0x00 | Type | BYTE | 0xC7, CPU Microcode Patch | |
394 | * 0x01 | Length | BYTE | Length of structure | |
395 | * 0x02 | Handle | WORD | Unique handle | |
396 | * 0x04 | Patch Info | Varies| { <DWORD: ID, DWORD Date, DWORD CPUID> ...} | |
397 | */ | |
398 | if (gen < G9) return 0; | |
399 | pr_handle_name("%s ProLiant CPU Microcode Patch Support Info", company); | |
400 | ||
401 | for (ptr = 0x4; ptr + 12 <= h->length; ptr += 12) { | |
402 | u32 cpuid = DWORD(data + ptr + 2 * 4); | |
403 | u32 date; | |
404 | ||
405 | /* AMD omits BaseFamily. Reconstruction valid on family >= 15. */ | |
406 | if (cpuid_type == cpuid_x86_amd) | |
407 | cpuid = ((cpuid & 0xfff00) << 8) | 0x0f00 | (cpuid & 0xff); | |
408 | ||
409 | dmi_print_cpuid(pr_attr, "CPU ID", cpuid_type, (u8 *) &cpuid); | |
410 | ||
411 | date = DWORD(data + ptr + 4); | |
412 | pr_subattr("Date", "%04x-%02x-%02x", | |
413 | date & 0xffff, (date >> 24) & 0xff, (date >> 16) & 0xff); | |
414 | pr_subattr("Patch", "0x%X", DWORD(data + ptr)); | |
415 | } | |
416 | break; | |
417 | ||
418 | case 203: | |
419 | /* | |
420 | * Vendor Specific: HP Device Correlation Record | |
421 | * | |
422 | * Offset | Name | Width | Description | |
423 | * ------------------------------------- | |
424 | * 0x00 | Type | BYTE | 0xCB, Correlation Record | |
425 | * 0x01 | Length | BYTE | Length of structure | |
426 | * 0x02 | Handle | WORD | Unique handle | |
427 | * 0x04 | Assoc Device | WORD | Handle of Associated Type 9 or Type 41 Record | |
428 | * 0x06 | Assoc SMBus | WORD | Handle of Associated Type 228 SMBus Segment Record | |
429 | * 0x08 | PCI Vendor ID| WORD | PCI Vendor ID of device 0xFFFF -> not present | |
430 | * 0x0A | PCI Device ID| WORD | PCI Device ID of device 0xFFFF -> not present | |
431 | * 0x0C | PCI SubVendor| WORD | PCI Sub Vendor ID of device 0xFFFF -> not present | |
432 | * 0x0E | PCI SubDevice| WORD | PCI Sub Device ID of device 0xFFFF -> not present | |
433 | * 0x10 | Class Code | BYTE | PCI Class Code of Endpoint. 0xFF if device not present. | |
434 | * 0x11 | Class SubCode| BYTE | PCI Sub Class Code of Endpoint. 0xFF if device not present. | |
435 | * 0x12 | Parent Handle| WORD | | |
436 | * 0x14 | Flags | WORD | | |
437 | * 0x16 | Device Type | BYTE | UEFI only | |
438 | * 0x17 | Device Loc | BYTE | Device Location | |
439 | * 0x18 | Dev Instance | BYTE | Device Instance | |
440 | * 0x19 | Sub Instance | BYTE | NIC Port # or NVMe Drive Bay | |
441 | * 0x1A | Bay | BYTE | | |
442 | * 0x1B | Enclosure | BYTE | | |
443 | * 0x1C | UEFI Dev Path| STRING| String number for UEFI Device Path | |
444 | * 0x1D | Struct Name | STRING| String number for UEFI Device Structured Name | |
445 | * 0x1E | Device Name | STRING| String number for UEFI Device Name | |
446 | * 0x1F | UEFI Location| STRING| String number for UEFI Location | |
447 | * 0x20 | Assoc Handle | WORD | Type 9 Handle. Defined if Flags[0] == 1. | |
448 | * 0x22 | Part Number | STRING| PCI Device Part Number | |
449 | * 0x23 | Serial Number| STRING| PCI Device Serial Number | |
450 | * 0x24 | Seg Number | WORD | Segment Group number. 0 -> Single group topology | |
451 | * 0x26 | Bus Number | BYTE | PCI Device Bus Number | |
452 | * 0x27 | Func Number | BTYE | PCI Device and Function Number | |
453 | */ | |
454 | if (gen < G9) return 0; | |
455 | pr_handle_name("%s Device Correlation Record", company); | |
456 | if (h->length < 0x1F) break; | |
457 | dmi_hp_203_assoc_hndl("Associated Device Record", WORD(data + 0x04)); | |
458 | dmi_hp_203_assoc_hndl("Associated SMBus Record", WORD(data + 0x06)); | |
459 | if (WORD(data + 0x08) == 0xffff && WORD(data + 0x0A) == 0xffff && | |
460 | WORD(data + 0x0C) == 0xffff && WORD(data + 0x0E) == 0xffff && | |
461 | data[0x10] == 0xFF && data[0x11] == 0xFF) | |
462 | { | |
463 | pr_attr("PCI Device Info", "Device Not Present"); | |
464 | } | |
465 | else | |
466 | { | |
467 | dmi_hp_203_pciinfo("PCI Vendor ID", WORD(data + 0x08)); | |
468 | dmi_hp_203_pciinfo("PCI Device ID", WORD(data + 0x0A)); | |
469 | dmi_hp_203_pciinfo("PCI Sub Vendor ID", WORD(data + 0x0C)); | |
470 | dmi_hp_203_pciinfo("PCI Sub Device ID", WORD(data + 0x0E)); | |
471 | dmi_hp_203_pciinfo("PCI Class Code", (char)data[0x10]); | |
472 | dmi_hp_203_pciinfo("PCI Sub Class Code", (char)data[0x11]); | |
473 | } | |
474 | dmi_hp_203_assoc_hndl("Parent Handle", WORD(data + 0x12)); | |
475 | pr_attr("Flags", "0x%04X", WORD(data + 0x14)); | |
476 | dmi_hp_203_devtyp("Device Type", data[0x16]); | |
477 | dmi_hp_203_devloc("Device Location", data[0x17]); | |
478 | pr_attr("Device Instance", "%d", data[0x18]); | |
479 | pr_attr("Device Sub-Instance", "%d", data[0x19]); | |
480 | dmi_hp_203_bayenc("Bay", data[0x1A]); | |
481 | dmi_hp_203_bayenc("Enclosure", data[0x1B]); | |
482 | pr_attr("Device Path", "%s", dmi_string(h, data[0x1C])); | |
483 | pr_attr("Structured Name", "%s", dmi_string(h, data[0x1D])); | |
484 | pr_attr("Device Name", "%s", dmi_string(h, data[0x1E])); | |
485 | if (h->length < 0x22) break; | |
486 | pr_attr("UEFI Location", "%s", dmi_string(h, data[0x1F])); | |
487 | if (!(opt.flags & FLAG_QUIET)) | |
488 | { | |
489 | if (WORD(data + 0x14) & 1) | |
490 | pr_attr("Associated Real/Phys Handle", "0x%04X", | |
491 | WORD(data + 0x20)); | |
492 | else | |
493 | pr_attr("Associated Real/Phys Handle", "N/A"); | |
494 | } | |
495 | if (h->length < 0x24) break; | |
496 | pr_attr("PCI Part Number", "%s", dmi_string(h, data[0x22])); | |
497 | pr_attr("Serial Number", "%s", dmi_string(h, data[0x23])); | |
498 | if (h->length < 0x28) break; | |
499 | pr_attr("Segment Group Number", "0x%04x", WORD(data + 0x24)); | |
500 | pr_attr("PCI Device", "%02x:%02x.%x", | |
501 | data[0x26], data[0x27] >> 3, data[0x27] & 7); | |
502 | break; | |
503 | ||
158 | 504 | case 204: |
159 | 505 | /* |
160 | 506 | * Vendor Specific: HPE ProLiant System/Rack Locator |
205 | 551 | nic++; |
206 | 552 | ptr += 8; |
207 | 553 | } |
208 | break; | |
209 | ||
210 | case 233: | |
211 | /* | |
212 | * Vendor Specific: HPE ProLiant NIC MAC Information | |
213 | * | |
214 | * This prints the BIOS NIC number, | |
215 | * PCI bus/device/function, and MAC address | |
216 | * | |
217 | * Offset | Name | Width | Description | |
218 | * ------------------------------------- | |
219 | * 0x00 | Type | BYTE | 0xE9, NIC structure | |
220 | * 0x01 | Length | BYTE | Length of structure | |
221 | * 0x02 | Handle | WORD | Unique handle | |
222 | * 0x04 | Grp No | WORD | 0 for single segment | |
223 | * 0x06 | Bus No | BYTE | PCI Bus | |
224 | * 0x07 | Dev No | BYTE | PCI Device/Function No | |
225 | * 0x08 | MAC | 32B | MAC addr padded w/ 0s | |
226 | * 0x28 | Port No| BYTE | Each NIC maps to a Port | |
227 | */ | |
228 | pr_handle_name("%s BIOS PXE NIC PCI and MAC Information", | |
229 | company); | |
230 | if (h->length < 0x0E) break; | |
231 | /* If the record isn't long enough, we don't have an ID | |
232 | * use 0xFF to use the internal counter. | |
233 | * */ | |
234 | nic = h->length > 0x28 ? data[0x28] : 0xFF; | |
235 | dmi_print_hp_net_iface_rec(nic, data[0x06], data[0x07], | |
236 | &data[0x08]); | |
237 | 554 | break; |
238 | 555 | |
239 | 556 | case 212: |
281 | 598 | pr_subattr("UEFI", "%s", feat & 0x1400 ? "Yes" : "No"); |
282 | 599 | break; |
283 | 600 | |
601 | case 233: | |
602 | /* | |
603 | * Vendor Specific: HPE ProLiant NIC MAC Information | |
604 | * | |
605 | * This prints the BIOS NIC number, | |
606 | * PCI bus/device/function, and MAC address | |
607 | * | |
608 | * Offset | Name | Width | Description | |
609 | * ------------------------------------- | |
610 | * 0x00 | Type | BYTE | 0xE9, NIC structure | |
611 | * 0x01 | Length | BYTE | Length of structure | |
612 | * 0x02 | Handle | WORD | Unique handle | |
613 | * 0x04 | Grp No | WORD | 0 for single segment | |
614 | * 0x06 | Bus No | BYTE | PCI Bus | |
615 | * 0x07 | Dev No | BYTE | PCI Device/Function No | |
616 | * 0x08 | MAC | 32B | MAC addr padded w/ 0s | |
617 | * 0x28 | Port No| BYTE | Each NIC maps to a Port | |
618 | */ | |
619 | pr_handle_name("%s BIOS PXE NIC PCI and MAC Information", | |
620 | company); | |
621 | if (h->length < 0x0E) break; | |
622 | /* If the record isn't long enough, we don't have an ID | |
623 | * use 0xFF to use the internal counter. | |
624 | * */ | |
625 | nic = h->length > 0x28 ? data[0x28] : 0xFF; | |
626 | dmi_print_hp_net_iface_rec(nic, data[0x06], data[0x07], | |
627 | &data[0x08]); | |
628 | break; | |
629 | ||
630 | case 236: | |
631 | /* | |
632 | * Vendor Specific: HPE ProLiant HDD Backplane | |
633 | * | |
634 | * Offset | Name | Width | Description | |
635 | * --------------------------------------- | |
636 | * 0x00 | Type | BYTE | 0xEC, HDD Backplane | |
637 | * 0x01 | Length | BYTE | Length of structure | |
638 | * 0x02 | Handle | WORD | Unique handle | |
639 | * 0x04 | I2C Address| BYTE | Backplane FRU I2C Address | |
640 | * 0x05 | Box Number | WORD | Backplane Box Number | |
641 | * 0x07 | NVRAM ID | WORD | Backplane NVRAM ID | |
642 | * 0x09 | WWID | QWORD | SAS Expander WWID | |
643 | * 0x11 | Total Bays | BYTE | Total SAS Bays | |
644 | * 0x12 | A0 Bays | BYTE | (deprecated) Number of SAS drive bays behind port 0xA0 | |
645 | * 0x13 | A2 Bays | BYTE | (deprecated) Number of SAS drive bays behind port 0xA2 | |
646 | * 0x14 | Name | STRING| (deprecated) Backplane Name | |
647 | */ | |
648 | pr_handle_name("%s HDD Backplane FRU Information", company); | |
649 | if (h->length < 0x08) break; | |
650 | pr_attr("FRU I2C Address", "0x%X raw(0x%X)", data[0x4] >> 1, data[0x4]); | |
651 | pr_attr("Box Number", "%d", WORD(data + 0x5)); | |
652 | pr_attr("NVRAM ID", "0x%X", WORD(data + 0x7)); | |
653 | if (h->length < 0x11) break; | |
654 | pr_attr("SAS Expander WWID", "0x%X", QWORD(data + 0x9)); | |
655 | if (h->length < 0x12) break; | |
656 | pr_attr("Total SAS Bays", "%d", data[0x11]); | |
657 | if (h->length < 0x15) break; | |
658 | if (gen < G10P) { | |
659 | pr_attr("A0 Bay Count", "%d", data[0x12]); | |
660 | pr_attr("A2 Bay Count", "%d", data[0x13]); | |
661 | pr_attr("Backplane Name", "%s", dmi_string(h, data[0x14])); | |
662 | } | |
663 | break; | |
664 | ||
665 | case 237: | |
666 | /* | |
667 | * Vendor Specific: HPE DIMM Vendor Part Number Information | |
668 | * | |
669 | * Offset | Name | Width | Description | |
670 | * --------------------------------------- | |
671 | * 0x00 | Type | BYTE | 0xED, DIMM Vendor Part Number information record | |
672 | * 0x01 | Length | BYTE | Length of structure | |
673 | * 0x02 | Handle | WORD | Unique handle | |
674 | * 0x04 | Hand Assoc | WORD | Handle to map to Type 17 | |
675 | * 0x06 | Manufacture|STRING | DIMM Manufacturer | |
676 | * 0x07 | Part Number|STRING | DIMM Manufacturer's Part Number | |
677 | * 0x08 | Serial Num |STRING | DIMM Vendor Serial Number | |
678 | * 0x09 | Spare Part |STRING | DIMM Spare Part Number | |
679 | */ | |
680 | if (gen < G9) return 0; | |
681 | pr_handle_name("%s DIMM Vendor Information", company); | |
682 | if (h->length < 0x08) break; | |
683 | if (!(opt.flags & FLAG_QUIET)) | |
684 | pr_attr("Associated Handle", "0x%04X", WORD(data + 0x4)); | |
685 | pr_attr("DIMM Manufacturer", "%s", dmi_string(h, data[0x06])); | |
686 | pr_attr("DIMM Manufacturer Part Number", "%s", dmi_string(h, data[0x07])); | |
687 | if (h->length < 0x09) break; | |
688 | pr_attr("DIMM Vendor Serial Number", "%s", dmi_string(h, data[0x08])); | |
689 | if (h->length < 0x0A) break; | |
690 | pr_attr("DIMM Spare Part Number", "%s", dmi_string(h, data[0x09])); | |
691 | break; | |
692 | ||
693 | case 238: | |
694 | /* | |
695 | * Vendor Specific: HPE USB Port Connector Correlation Record | |
696 | * | |
697 | * Offset | Name | Width | Description | |
698 | * --------------------------------------- | |
699 | * 0x00 | Type | BYTE | 0xEE, HP Device Correlation Record | |
700 | * 0x01 | Length | BYTE | Length of structure | |
701 | * 0x02 | Handle | WORD | Unique handle | |
702 | * 0x04 | Hand Assoc | WORD | Handle to map to Type 8 | |
703 | * 0x06 | Parent Bus | BYTE | PCI Bus number of USB controller of this port | |
704 | * 0x07 | Par Dev/Fun| BYTE | PCI Dev/Fun of USB Controller of this port | |
705 | * 0x08 | Location | BYTE | Enumerated value of location of USB port | |
706 | * 0x09 | Flags | WORD | USB Shared Management Port | |
707 | * 0x0B | Port Inst | BYTE | Instance number for this type of USB port | |
708 | * 0x0C | Parent Hub | BYTE | Instance number of internal Hub | |
709 | * 0x0D | Port Speed | BYTE | Enumerated value of speed configured by BIOS | |
710 | * 0x0E | Device Path| STRING| UEFI Device Path of USB endpoint | |
711 | */ | |
712 | if (gen < G9) return 0; | |
713 | pr_handle_name("%s Proliant USB Port Connector Correlation Record", company); | |
714 | if (h->length < 0x0F) break; | |
715 | if (!(opt.flags & FLAG_QUIET)) | |
716 | pr_attr("Associated Handle", "0x%04X", WORD(data + 0x4)); | |
717 | pr_attr("PCI Device", "%02x:%02x.%x", data[0x6], | |
718 | data[0x7] >> 3, data[0x7] & 0x7); | |
719 | dmi_hp_238_loc("Location", data[0x8]); | |
720 | dmi_hp_238_flags("Management Port", WORD(data + 0x9)); | |
721 | pr_attr("Port Instance", "%d", data[0xB]); | |
722 | if (data[0xC] != 0xFE) | |
723 | pr_attr("Parent Hub Port Instance", "%d", data[0xC]); | |
724 | else | |
725 | pr_attr("Parent Hub Port Instance", "N/A"); | |
726 | dmi_hp_238_speed("Port Speed Capability", data[0xD]); | |
727 | pr_attr("Device Path", "%s", dmi_string(h, data[0xE])); | |
728 | break; | |
729 | ||
730 | case 240: | |
731 | /* | |
732 | * Vendor Specific: HPE Proliant Inventory Record | |
733 | * | |
734 | * Reports firmware version information for devices that report their | |
735 | * firmware using their UEFI drivers. Additionally provides association | |
736 | * with other SMBIOS records, such as Type 203 (which in turn is | |
737 | * associated with Types 9, 41, and 228). | |
738 | * | |
739 | * Offset | Name | Width | Description | |
740 | * --------------------------------------- | |
741 | * 0x00 | Type | BYTE | 0xF0, HP Firmware Inventory Record | |
742 | * 0x01 | Length | BYTE | Length of structure | |
743 | * 0x02 | Handle | WORD | Unique handle | |
744 | * 0x04 | Hndl Assoc | WORD | Handle to map to Type 203 | |
745 | * 0x06 | Pkg Vers | DWORD | FW Vers Release of All FW in Device | |
746 | * 0x0A | Ver String | STRING| FW Version String | |
747 | * 0x0B | Image Size | QWORD | FW image size (bytes) | |
748 | * 0x13 | Attributes | QWORD | Bitfield: Is attribute defined? | |
749 | * 0x1B | Attr Set | QWORD | BitField: If defined, is attribute set? | |
750 | * 0x23 | Version | DWORD | Lowest supported version. | |
751 | */ | |
752 | pr_handle_name("%s Proliant Inventory Record", company); | |
753 | if (h->length < 0x27) break; | |
754 | if (!(opt.flags & FLAG_QUIET)) | |
755 | pr_attr("Associated Handle", "0x%04X", WORD(data + 0x4)); | |
756 | pr_attr("Package Version", "0x%08X", DWORD(data + 0x6)); | |
757 | pr_attr("Version String", "%s", dmi_string(h, data[0x0A])); | |
758 | ||
759 | if (DWORD(data + 0x0B)) | |
760 | dmi_print_memory_size("Image Size", QWORD(data + 0xB), 0); | |
761 | else | |
762 | pr_attr("Image Size", "Not Available"); | |
763 | ||
764 | dmi_hp_240_attr(QWORD(data + 0x13), QWORD(data + 0x1B)); | |
765 | ||
766 | if (DWORD(data + 0x23)) | |
767 | pr_attr("Lowest Supported Version", "0x%08X", DWORD(data + 0x23)); | |
768 | else | |
769 | pr_attr("Lowest Supported Version", "Not Available"); | |
770 | break; | |
771 | ||
284 | 772 | default: |
285 | 773 | return 0; |
286 | 774 | } |
20 | 20 | |
21 | 21 | struct dmi_header; |
22 | 22 | |
23 | void dmi_set_vendor(const char *s); | |
23 | void dmi_set_vendor(const char *s, const char *p); | |
24 | 24 | int dmi_decode_oem(const struct dmi_header *h); |
4 | 4 | .\" |
5 | 5 | .SH SYNOPSIS |
6 | 6 | .B biosdecode |
7 | .RB [ OPTIONS ] | |
7 | .RI [ OPTIONS ] | |
8 | 8 | .\" |
9 | 9 | .SH DESCRIPTION |
10 | 10 | .B biosdecode |
58 | 58 | .\" |
59 | 59 | .SH OPTIONS |
60 | 60 | .TP |
61 | .BR "-d" ", " "--dev-mem FILE" | |
62 | Read memory from device \fBFILE\fR (default: \fB/dev/mem\fR) | |
61 | .BR "-d" ", " "--dev-mem \fIFILE\fP" | |
62 | Read memory from device \fIFILE\fP (default: \fI/dev/mem\fP) | |
63 | 63 | .TP |
64 | .BR " " " " "--pir full" | |
65 | Decode the details of the PCI IRQ routing table | |
64 | .BR " " " " "--pir \fBfull\fP" | |
65 | Decode the details of the PCI IRQ routing table. | |
66 | Only \fBfull\fP mode is supported. | |
66 | 67 | .TP |
67 | 68 | .BR "-h" ", " "--help" |
68 | 69 | Display usage information and exit |
4 | 4 | .\" |
5 | 5 | .SH SYNOPSIS |
6 | 6 | .B dmidecode |
7 | .RB [ OPTIONS ] | |
7 | .RI [ OPTIONS ] | |
8 | 8 | .\" |
9 | 9 | .SH DESCRIPTION |
10 | 10 | .B dmidecode |
62 | 62 | .\" |
63 | 63 | .SH OPTIONS |
64 | 64 | .TP |
65 | .BR "-d" ", " "--dev-mem FILE" | |
66 | Read memory from device \fBFILE\fR (default: \fB/dev/mem\fR) | |
65 | .BR "-d" ", " "--dev-mem \fIFILE\fP" | |
66 | Read memory from device \fIFILE\fP (default: \fI/dev/mem\fP) | |
67 | 67 | .TP |
68 | 68 | .BR "-q" ", " "--quiet" |
69 | 69 | Be less verbose. Unknown, inactive and \s-1OEM\s0-specific entries are not |
70 | 70 | displayed. Meta-data and handle references are hidden. |
71 | 71 | .TP |
72 | .BR "-s" ", " "--string KEYWORD" | |
73 | Only display the value of the \s-1DMI\s0 string identified by \fBKEYWORD\fR. | |
74 | \fBKEYWORD\fR must be a keyword from the following list: \fBbios-vendor\fR, | |
75 | \fBbios-version\fR, \fBbios-release-date\fR, | |
76 | \fBbios-revision\fR, \fBfirmware-revision\fR, | |
77 | \fBsystem-manufacturer\fR, \fBsystem-product-name\fR, | |
78 | \fBsystem-version\fR, \fBsystem-serial-number\fR, | |
79 | \fBsystem-uuid\fR, \fBsystem-sku-number\fR, \fBsystem-family\fR, | |
80 | \fBbaseboard-manufacturer\fR, \fBbaseboard-product-name\fR, | |
81 | \fBbaseboard-version\fR, \fBbaseboard-serial-number\fR, | |
82 | \fBbaseboard-asset-tag\fR, \fBchassis-manufacturer\fR, | |
83 | \fBchassis-type\fR, | |
84 | \fBchassis-version\fR, \fBchassis-serial-number\fR, | |
85 | \fBchassis-asset-tag\fR, \fBprocessor-family\fR, | |
86 | \fBprocessor-manufacturer\fR, | |
87 | \fBprocessor-version\fR, \fBprocessor-frequency\fR. | |
72 | .BR "-s" ", " "--string \fIKEYWORD\fP" | |
73 | Only display the value of the \s-1DMI\s0 string identified by \fIKEYWORD\fP. | |
74 | It must be a keyword from the following list: | |
75 | .nh | |
76 | .BR bios\-vendor , | |
77 | .BR bios\-version , | |
78 | .BR bios\-release\-date , | |
79 | .BR bios\-revision , | |
80 | .BR firmware\-revision , | |
81 | .BR system\-manufacturer , | |
82 | .BR system\-product\-name , | |
83 | .BR system\-version , | |
84 | .BR system\-serial\-number , | |
85 | .BR system\-uuid , | |
86 | .BR system\-sku\-number , | |
87 | .BR system\-family , | |
88 | .BR baseboard\-manufacturer , | |
89 | .BR baseboard\-product\-name , | |
90 | .BR baseboard\-version , | |
91 | .BR baseboard\-serial\-number , | |
92 | .BR baseboard\-asset\-tag , | |
93 | .BR chassis\-manufacturer , | |
94 | .BR chassis\-type , | |
95 | .BR chassis\-version , | |
96 | .BR chassis\-serial\-number , | |
97 | .BR chassis\-asset\-tag , | |
98 | .BR processor\-family , | |
99 | .BR processor\-manufacturer , | |
100 | .BR processor\-version , | |
101 | .BR processor\-frequency . | |
102 | .hy | |
88 | 103 | Each keyword corresponds to a given \s-1DMI\s0 type and a given offset |
89 | 104 | within this entry type. |
90 | 105 | Not all strings may be meaningful or even defined on all systems. Some |
91 | 106 | keywords may return more than one result on some systems (e.g. |
92 | \fBprocessor-version\fR on a multi-processor system). | |
93 | If \fBKEYWORD\fR is not provided or not valid, a list of all valid | |
107 | .nh | |
108 | .B processor\-version | |
109 | .hy | |
110 | on a multi-processor system). | |
111 | If \fIKEYWORD\fP is not provided or not valid, a list of all valid | |
94 | 112 | keywords is printed and |
95 | 113 | .B dmidecode |
96 | 114 | exits with an error. |
103 | 121 | .IR /sys/devices/virtual/dmi/id . |
104 | 122 | Most of these files are even readable by regular users. |
105 | 123 | .TP |
106 | .BR "-t" ", " "--type TYPE" | |
107 | Only display the entries of type \fBTYPE\fR. \fBTYPE\fR can be either a | |
124 | .BR "-t" ", " "--type \fITYPE\fP" | |
125 | Only display the entries of type \fITYPE\fP. It can be either a | |
108 | 126 | \s-1DMI\s0 type number, or a comma-separated list of type numbers, or a |
109 | keyword from the following list: \fBbios\fR, \fBsystem\fR, | |
110 | \fBbaseboard\fR, \fBchassis\fR, \fBprocessor\fR, \fBmemory\fR, | |
111 | \fBcache\fR, \fBconnector\fR, \fBslot\fR. Refer to the DMI TYPES section | |
112 | below for details. | |
127 | keyword from the following list: | |
128 | .nh | |
129 | .BR bios , | |
130 | .BR system , | |
131 | .BR baseboard , | |
132 | .BR chassis , | |
133 | .BR processor , | |
134 | .BR memory , | |
135 | .BR cache , | |
136 | .BR connector , | |
137 | .BR slot . | |
138 | .hy | |
139 | Refer to the DMI TYPES section below for details. | |
113 | 140 | If this option is used more than once, the set of displayed entries will be |
114 | 141 | the union of all the given types. |
115 | If \fBTYPE\fR is not provided or not valid, a list of all valid keywords | |
142 | If \fITYPE\fP is not provided or not valid, a list of all valid keywords | |
116 | 143 | is printed and |
117 | 144 | .B dmidecode |
118 | 145 | exits with an error. |
119 | 146 | .TP |
120 | .BR "-H" ", " "--handle HANDLE" | |
121 | Only display the entry whose handle matches \fBHANDLE\fR. \fBHANDLE\fR | |
122 | is a 16-bit integer. | |
147 | .BR "-H" ", " "--handle \fIHANDLE\fP" | |
148 | Only display the entry whose handle matches \fIHANDLE\fP. | |
149 | \fIHANDLE\fP is a 16-bit integer. | |
123 | 150 | .TP |
124 | 151 | .BR "-u" ", " "--dump" |
125 | 152 | Do not decode the entries, dump their contents as hexadecimal instead. |
127 | 154 | you. The strings attached to each entry are displayed as both |
128 | 155 | hexadecimal and \s-1ASCII\s0. This option is mainly useful for debugging. |
129 | 156 | .TP |
130 | .BR " " " " "--dump-bin FILE" | |
157 | .BR " " " " "--dump-bin \fIFILE\fP" | |
131 | 158 | Do not decode the entries, instead dump the DMI data to a file in binary |
132 | form. The generated file is suitable to pass to \fB--from-dump\fR | |
159 | form. The generated file is suitable to pass to \fB--from-dump\fP | |
133 | 160 | later. |
134 | 161 | .TP |
135 | .BR " " " " "--from-dump FILE" | |
136 | Read the DMI data from a binary file previously generated using | |
137 | \fB--dump-bin\fR. | |
162 | .BR " " " " "--from-dump \fIFILE\fP" | |
163 | Read the DMI data from a binary file previously generated using | |
164 | \fB--dump-bin\fP. | |
138 | 165 | .TP |
139 | 166 | .BR " " " " "--no-sysfs" |
140 | 167 | Do not attempt to read DMI data from sysfs files. This is mainly useful for |
141 | 168 | debugging. |
142 | 169 | .TP |
143 | .BR " " " " "--oem-string N" | |
144 | Only display the value of the \s-1OEM\s0 string number \fBN\fR. The first | |
145 | \s-1OEM\s0 string has number 1. With special value "count", return the | |
170 | .BR " " " " "--oem-string \fIN\fP" | |
171 | Only display the value of the \s-1OEM\s0 string number \fIN\fP. The first | |
172 | \s-1OEM\s0 string has number \fB1\fP. With special value \fBcount\fP, return the | |
146 | 173 | number of OEM strings instead. |
147 | 174 | .TP |
148 | 175 | .BR "-h" ", " "--help" |
151 | 178 | .BR "-V" ", " "--version" |
152 | 179 | Display the version and exit |
153 | 180 | .P |
154 | Options --string, --type, --dump-bin and --oem-string | |
181 | Options | |
182 | .BR --string , | |
183 | .BR --type, | |
184 | .BR --dump-bin " and " --oem-string | |
155 | 185 | determine the output format and are mutually exclusive. |
156 | 186 | .P |
157 | 187 | Please note in case of |
219 | 249 | will display these entries by default, but it can only decode them |
220 | 250 | when the vendors have contributed documentation or code for them. |
221 | 251 | |
222 | Keywords can be used instead of type numbers with \fB--type\fR. | |
252 | Keywords can be used instead of type numbers with \fB--type\fP. | |
223 | 253 | Each keyword is equivalent to a list of type numbers: |
224 | 254 | |
225 | 255 | .TS |
249 | 279 | dmidecode --type BIOS |
250 | 280 | .\" |
251 | 281 | .SH BINARY DUMP FILE FORMAT |
252 | The binary dump files generated by --dump-bin and read using --from-dump | |
282 | The binary dump files generated by \fB--dump-bin\fP and read using \fB--from-dump\fP | |
253 | 283 | are formatted as follows: |
254 | 284 | .IP \(bu "\w'\(bu'u+1n" |
255 | 285 | The SMBIOS or DMI entry point is located at offset 0x00. |
4 | 4 | .\" |
5 | 5 | .SH SYNOPSIS |
6 | 6 | .B ownership |
7 | .RB [ OPTIONS ] | |
7 | .RI [ OPTIONS ] | |
8 | 8 | .\" |
9 | 9 | .SH DESCRIPTION |
10 | 10 | .B ownership |
18 | 18 | .\" |
19 | 19 | .SH OPTIONS |
20 | 20 | .TP |
21 | .BR "-d" ", " "--dev-mem FILE" | |
22 | Read memory from device \fBFILE\fR (default: \fB/dev/mem\fR) | |
21 | .BR "-d" ", " "--dev-mem \fIFILE\fP" | |
22 | Read memory from device \fIFILE\fP (default: \fI/dev/mem\fP) | |
23 | 23 | .TP |
24 | 24 | .BR "-h" ", " "--help" |
25 | 25 | Display usage information and exit |
4 | 4 | .\" |
5 | 5 | .SH SYNOPSIS |
6 | 6 | .B vpddecode |
7 | .RB [ OPTIONS ] | |
7 | .RI [ OPTIONS ] | |
8 | 8 | .\" |
9 | 9 | .SH DESCRIPTION |
10 | 10 | .B vpddecode |
31 | 31 | .\" |
32 | 32 | .SH OPTIONS |
33 | 33 | .TP |
34 | .BR "-d" ", " "--dev-mem FILE" | |
35 | Read memory from device \fBFILE\fR (default: \fB/dev/mem\fR) | |
34 | .BR "-d" ", " "--dev-mem \fIFILE\fP" | |
35 | Read memory from device \fIFILE\fP (default: \fI/dev/mem\fP) | |
36 | 36 | .TP |
37 | .BR "-s" ", " "--string KEYWORD" | |
38 | Only display the value of the \s-1VPD\s0 string identified by \fBKEYWORD\fR. | |
39 | \fBKEYWORD\fR must be a keyword from the following list: \fBbios-build-id\fR, | |
40 | \fBbox-serial-number\fR, \fBmotherboard-serial-number\fR, | |
41 | \fBmachine-type-model\fR, \fBbios-release-date\fR. | |
37 | .BR "-s" ", " "--string \fIKEYWORD\fP" | |
38 | Only display the value of the \s-1VPD\s0 string identified by \fIKEYWORD\fP. | |
39 | It must be a keyword from the following list: | |
40 | .nh | |
41 | .BR bios-build-id , | |
42 | .BR box-serial-number , | |
43 | .BR motherboard-serial-number , | |
44 | .BR machine-type-model , | |
45 | .BR bios-release-date . | |
46 | .hy | |
42 | 47 | Each keyword corresponds to an offset and a length within the \s-1VPD\s0 |
43 | 48 | record. |
44 | 49 | Not all strings may be defined on all \s-1VPD\s0-enabled systems. |
45 | If \fBKEYWORD\fR is not provided or not valid, a list of all valid | |
50 | If \fIKEYWORD\fP is not provided or not valid, a list of all valid | |
46 | 51 | keywords is printed and |
47 | 52 | .B vpddecode |
48 | 53 | exits with an error. |
49 | 54 | This option cannot be used more than once. |
50 | Mutually exclusive with \fB--dump\fR. | |
55 | Mutually exclusive with \fB--dump\fP. | |
51 | 56 | .TP |
52 | 57 | .BR "-u" ", " "--dump" |
53 | 58 | Do not decode the VPD records, dump their contents as hexadecimal instead. |
54 | 59 | Note that this is still a text output, no binary data will be thrown upon |
55 | 60 | you. ASCII equivalent is displayed when possible. This option is mainly |
56 | 61 | useful for debugging. |
57 | Mutually exclusive with \fB--string\fR. | |
62 | Mutually exclusive with \fB--string\fP. | |
58 | 63 | .TP |
59 | 64 | .BR "-h" ", " "--help" |
60 | 65 | Display usage information and exit |