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 |
static 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 |
static 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 |
|
149 | 301 |
static int dmi_decode_hp(const struct dmi_header *h)
|
150 | 302 |
{
|
151 | 303 |
u8 *data = h->data;
|
152 | 304 |
int nic, ptr;
|
153 | 305 |
u32 feat;
|
154 | 306 |
const char *company = (dmi_vendor == VENDOR_HP) ? "HP" : "HPE";
|
|
307 |
int gen;
|
|
308 |
|
|
309 |
gen = dmi_hpegen(dmi_product);
|
|
310 |
if (gen < 0)
|
|
311 |
return 0;
|
155 | 312 |
|
156 | 313 |
switch (h->type)
|
157 | 314 |
{
|
|
315 |
case 203:
|
|
316 |
/*
|
|
317 |
* Vendor Specific: HP Device Correlation Record
|
|
318 |
*
|
|
319 |
* Offset | Name | Width | Description
|
|
320 |
* -------------------------------------
|
|
321 |
* 0x00 | Type | BYTE | 0xCB, Correlation Record
|
|
322 |
* 0x01 | Length | BYTE | Length of structure
|
|
323 |
* 0x02 | Handle | WORD | Unique handle
|
|
324 |
* 0x04 | Assoc Device | WORD | Handle of Associated Type 9 or Type 41 Record
|
|
325 |
* 0x06 | Assoc SMBus | WORD | Handle of Associated Type 228 SMBus Segment Record
|
|
326 |
* 0x08 | PCI Vendor ID| WORD | PCI Vendor ID of device 0xFFFF -> not present
|
|
327 |
* 0x0A | PCI Device ID| WORD | PCI Device ID of device 0xFFFF -> not present
|
|
328 |
* 0x0C | PCI SubVendor| WORD | PCI Sub Vendor ID of device 0xFFFF -> not present
|
|
329 |
* 0x0E | PCI SubDevice| WORD | PCI Sub Device ID of device 0xFFFF -> not present
|
|
330 |
* 0x10 | Class Code | BYTE | PCI Class Code of Endpoint. 0xFF if device not present.
|
|
331 |
* 0x11 | Class SubCode| BYTE | PCI Sub Class Code of Endpoint. 0xFF if device not present.
|
|
332 |
* 0x12 | Parent Handle| WORD |
|
|
333 |
* 0x14 | Flags | WORD |
|
|
334 |
* 0x16 | Device Type | BYTE | UEFI only
|
|
335 |
* 0x17 | Device Loc | BYTE | Device Location
|
|
336 |
* 0x18 | Dev Instance | BYTE | Device Instance
|
|
337 |
* 0x19 | Sub Instance | BYTE | NIC Port # or NVMe Drive Bay
|
|
338 |
* 0x1A | Bay | BYTE |
|
|
339 |
* 0x1B | Enclosure | BYTE |
|
|
340 |
* 0x1C | UEFI Dev Path| STRING| String number for UEFI Device Path
|
|
341 |
* 0x1D | Struct Name | STRING| String number for UEFI Device Structured Name
|
|
342 |
* 0x1E | Device Name | STRING| String number for UEFI Device Name
|
|
343 |
* 0x1F | UEFI Location| STRING| String number for UEFI Location
|
|
344 |
* 0x20 | Assoc Handle | WORD | Type 9 Handle. Defined if Flags[0] == 1.
|
|
345 |
* 0x22 | Part Number | STRING| PCI Device Part Number
|
|
346 |
* 0x23 | Serial Number| STRING| PCI Device Serial Number
|
|
347 |
* 0x24 | Seg Number | WORD | Segment Group number. 0 -> Single group topology
|
|
348 |
* 0x26 | Bus Number | BYTE | PCI Device Bus Number
|
|
349 |
* 0x27 | Func Number | BTYE | PCI Device and Function Number
|
|
350 |
*/
|
|
351 |
if (gen < G9) break;
|
|
352 |
if (h->length < 0x1F) break;
|
|
353 |
pr_handle_name("%s HP Device Correlation Record", company);
|
|
354 |
dmi_hp_203_assoc_hndl("Associated Device Record", WORD(data + 0x04));
|
|
355 |
dmi_hp_203_assoc_hndl("Associated SMBus Record", WORD(data + 0x06));
|
|
356 |
if (WORD(data + 0x08) == 0xffff && WORD(data + 0x0A) == 0xffff &&
|
|
357 |
WORD(data + 0x0C) == 0xffff && WORD(data + 0x0E) == 0xffff &&
|
|
358 |
data[0x10] == 0xFF && data[0x11] == 0xFF)
|
|
359 |
{
|
|
360 |
pr_attr("PCI Device Info", "Device Not Present");
|
|
361 |
}
|
|
362 |
else
|
|
363 |
{
|
|
364 |
dmi_hp_203_pciinfo("PCI Vendor ID", WORD(data + 0x08));
|
|
365 |
dmi_hp_203_pciinfo("PCI Device ID", WORD(data + 0x0A));
|
|
366 |
dmi_hp_203_pciinfo("PCI Sub Vendor ID", WORD(data + 0x0C));
|
|
367 |
dmi_hp_203_pciinfo("PCI Sub Device ID", WORD(data + 0x0E));
|
|
368 |
dmi_hp_203_pciinfo("PCI Class Code", (char)data[0x10]);
|
|
369 |
dmi_hp_203_pciinfo("PCI Sub Class Code", (char)data[0x11]);
|
|
370 |
}
|
|
371 |
dmi_hp_203_assoc_hndl("Parent Handle", WORD(data + 0x12));
|
|
372 |
pr_attr("Flags", "0x%04X", WORD(data + 0x14));
|
|
373 |
dmi_hp_203_devtyp("Device Type", data[0x16]);
|
|
374 |
dmi_hp_203_devloc("Device Location", data[0x17]);
|
|
375 |
pr_attr("Device Instance", "%d", data[0x18]);
|
|
376 |
pr_attr("Device Sub-Instance", "%d", data[0x19]);
|
|
377 |
dmi_hp_203_bayenc("Bay", data[0x1A]);
|
|
378 |
dmi_hp_203_bayenc("Enclosure", data[0x1B]);
|
|
379 |
pr_attr("Device Path", "%s", dmi_string(h, data[0x1C]));
|
|
380 |
pr_attr("Structured Name", "%s", dmi_string(h, data[0x1D]));
|
|
381 |
pr_attr("Device Name", "%s", dmi_string(h, data[0x1E]));
|
|
382 |
if (h->length < 0x22) break;
|
|
383 |
pr_attr("UEFI Location", "%s", dmi_string(h, data[0x1F]));
|
|
384 |
if (!(opt.flags & FLAG_QUIET))
|
|
385 |
{
|
|
386 |
if (WORD(data + 0x14) & 1)
|
|
387 |
pr_attr("Associated Real/Phys Handle", "0x%04X",
|
|
388 |
WORD(data + 0x20));
|
|
389 |
else
|
|
390 |
pr_attr("Associated Real/Phys Handle", "N/A");
|
|
391 |
}
|
|
392 |
if (h->length < 0x24) break;
|
|
393 |
pr_attr("PCI Part Number", "%s", dmi_string(h, data[0x22]));
|
|
394 |
pr_attr("Serial Number", "%s", dmi_string(h, data[0x23]));
|
|
395 |
if (h->length < 0x28) break;
|
|
396 |
pr_attr("Segment Group Number", "0x%04x", WORD(data + 0x24));
|
|
397 |
pr_attr("PCI Device", "%02x:%02x.%x",
|
|
398 |
data[0x26], data[0x27] >> 3, data[0x27] & 7);
|
|
399 |
break;
|
|
400 |
|
158 | 401 |
case 204:
|
159 | 402 |
/*
|
160 | 403 |
* Vendor Specific: HPE ProLiant System/Rack Locator
|
|
205 | 448 |
nic++;
|
206 | 449 |
ptr += 8;
|
207 | 450 |
}
|
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 | 451 |
break;
|
238 | 452 |
|
239 | 453 |
case 212:
|
|
281 | 495 |
pr_subattr("UEFI", "%s", feat & 0x1400 ? "Yes" : "No");
|
282 | 496 |
break;
|
283 | 497 |
|
|
498 |
case 233:
|
|
499 |
/*
|
|
500 |
* Vendor Specific: HPE ProLiant NIC MAC Information
|
|
501 |
*
|
|
502 |
* This prints the BIOS NIC number,
|
|
503 |
* PCI bus/device/function, and MAC address
|
|
504 |
*
|
|
505 |
* Offset | Name | Width | Description
|
|
506 |
* -------------------------------------
|
|
507 |
* 0x00 | Type | BYTE | 0xE9, NIC structure
|
|
508 |
* 0x01 | Length | BYTE | Length of structure
|
|
509 |
* 0x02 | Handle | WORD | Unique handle
|
|
510 |
* 0x04 | Grp No | WORD | 0 for single segment
|
|
511 |
* 0x06 | Bus No | BYTE | PCI Bus
|
|
512 |
* 0x07 | Dev No | BYTE | PCI Device/Function No
|
|
513 |
* 0x08 | MAC | 32B | MAC addr padded w/ 0s
|
|
514 |
* 0x28 | Port No| BYTE | Each NIC maps to a Port
|
|
515 |
*/
|
|
516 |
pr_handle_name("%s BIOS PXE NIC PCI and MAC Information",
|
|
517 |
company);
|
|
518 |
if (h->length < 0x0E) break;
|
|
519 |
/* If the record isn't long enough, we don't have an ID
|
|
520 |
* use 0xFF to use the internal counter.
|
|
521 |
* */
|
|
522 |
nic = h->length > 0x28 ? data[0x28] : 0xFF;
|
|
523 |
dmi_print_hp_net_iface_rec(nic, data[0x06], data[0x07],
|
|
524 |
&data[0x08]);
|
|
525 |
break;
|
|
526 |
|
|
527 |
case 236:
|
|
528 |
/*
|
|
529 |
* Vendor Specific: HPE ProLiant HDD Backplane
|
|
530 |
*
|
|
531 |
* Offset | Name | Width | Description
|
|
532 |
* ---------------------------------------
|
|
533 |
* 0x00 | Type | BYTE | 0xEC, HDD Backplane
|
|
534 |
* 0x01 | Length | BYTE | Length of structure
|
|
535 |
* 0x02 | Handle | WORD | Unique handle
|
|
536 |
* 0x04 | I2C Address| BYTE | Backplane FRU I2C Address
|
|
537 |
* 0x05 | Box Number | WORD | Backplane Box Number
|
|
538 |
* 0x07 | NVRAM ID | WORD | Backplane NVRAM ID
|
|
539 |
* 0x09 | WWID | QWORD | SAS Expander WWID
|
|
540 |
* 0x11 | Total Bays | BYTE | Total SAS Bays
|
|
541 |
* 0x12 | A0 Bays | BYTE | (deprecated) Number of SAS drive bays behind port 0xA0
|
|
542 |
* 0x13 | A2 Bays | BYTE | (deprecated) Number of SAS drive bays behind port 0xA2
|
|
543 |
* 0x14 | Name | STRING| (deprecated) Backplane Name
|
|
544 |
*/
|
|
545 |
pr_handle_name("%s HDD Backplane FRU Information", company);
|
|
546 |
if (h->length < 0x08) break;
|
|
547 |
pr_attr("FRU I2C Address", "0x%X raw(0x%X)", data[0x4] >> 1, data[0x4]);
|
|
548 |
pr_attr("Box Number", "%d", WORD(data + 0x5));
|
|
549 |
pr_attr("NVRAM ID", "0x%X", WORD(data + 0x7));
|
|
550 |
if (h->length < 0x11) break;
|
|
551 |
pr_attr("SAS Expander WWID", "0x%X", QWORD(data + 0x9));
|
|
552 |
if (h->length < 0x12) break;
|
|
553 |
pr_attr("Total SAS Bays", "%d", data[0x11]);
|
|
554 |
if (h->length < 0x15) break;
|
|
555 |
if (gen < G10P) {
|
|
556 |
pr_attr("A0 Bay Count", "%d", data[0x12]);
|
|
557 |
pr_attr("A2 Bay Count", "%d", data[0x13]);
|
|
558 |
pr_attr("Backplane Name", "%s", dmi_string(h, data[0x14]));
|
|
559 |
}
|
|
560 |
break;
|
|
561 |
|
|
562 |
case 240:
|
|
563 |
/*
|
|
564 |
* Vendor Specific: HPE Proliant Inventory Record
|
|
565 |
*
|
|
566 |
* Reports firmware version information for devices that report their
|
|
567 |
* firmware using their UEFI drivers. Additionally provides association
|
|
568 |
* with other SMBIOS records, such as Type 203 (which in turn is
|
|
569 |
* associated with Types 9, 41, and 228).
|
|
570 |
*
|
|
571 |
* Offset | Name | Width | Description
|
|
572 |
* ---------------------------------------
|
|
573 |
* 0x00 | Type | BYTE | 0xF0, HP Firmware Inventory Record
|
|
574 |
* 0x01 | Length | BYTE | Length of structure
|
|
575 |
* 0x02 | Handle | WORD | Unique handle
|
|
576 |
* 0x04 | Hndl Assoc | WORD | Handle to map to Type 203
|
|
577 |
* 0x06 | Pkg Vers | DWORD | FW Vers Release of All FW in Device
|
|
578 |
* 0x0A | Ver String | STRING| FW Version String
|
|
579 |
* 0x0B | Image Size | QWORD | FW image size (bytes)
|
|
580 |
* 0x13 | Attributes | QWORD | Bitfield: Is attribute defined?
|
|
581 |
* 0x1B | Attr Set | QWORD | BitField: If defined, is attribute set?
|
|
582 |
* 0x23 | Version | DWORD | Lowest supported version.
|
|
583 |
*/
|
|
584 |
pr_handle_name("%s Proliant Inventory Record", company);
|
|
585 |
if (h->length < 0x27) break;
|
|
586 |
if (!(opt.flags & FLAG_QUIET))
|
|
587 |
pr_attr("Associated Handle", "0x%04X", WORD(data + 0x4));
|
|
588 |
pr_attr("Package Version", "0x%08X", DWORD(data + 0x6));
|
|
589 |
pr_attr("Version String", "%s", dmi_string(h, data[0x0A]));
|
|
590 |
|
|
591 |
if (DWORD(data + 0x0B))
|
|
592 |
dmi_print_memory_size("Image Size", QWORD(data + 0xB), 0);
|
|
593 |
else
|
|
594 |
pr_attr("Image Size", "Not Available");
|
|
595 |
|
|
596 |
dmi_hp_240_attr(QWORD(data + 0x13), QWORD(data + 0x1B));
|
|
597 |
|
|
598 |
if (DWORD(data + 0x23))
|
|
599 |
pr_attr("Lowest Supported Version", "0x%08X", DWORD(data + 0x23));
|
|
600 |
else
|
|
601 |
pr_attr("Lowest Supported Version", "Not Available");
|
|
602 |
break;
|
|
603 |
|
284 | 604 |
default:
|
285 | 605 |
return 0;
|
286 | 606 |
}
|