]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/hwinfo/src/hd/smbios.c
Kleiner netter neuer Versuch.
[people/teissler/ipfire-2.x.git] / src / hwinfo / src / hd / smbios.c
CommitLineData
a6316ce4
MT
1#include <stdio.h>
2#include <string.h>
3
4#include "hd.h"
5#include "hd_int.h"
6#include "smbios.h"
7
8
9/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10
11enum sm_map_type { sm_map_str, sm_map_num2str };
12
13typedef struct { unsigned num; char *str; } sm_num2str_t;
14
15typedef struct {
16 enum sm_map_type type;
17 unsigned len;
18 union {
19 char **str;
20 sm_num2str_t *num2str;
21 } list;
22} sm_str_map_t;
23
24
25/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
26
27static char *get_string(str_list_t *sl, int index);
28static void smbios_bitmap_print(FILE *f, hd_bitmap_t *hbm, char *label, int style);
29static void smbios_id_print(FILE *f, hd_id_t *hid, char *label);
30static void smbios_str_print(FILE *f, char *str, char *label);
31static void smbios_id2str(hd_id_t *hid, sm_str_map_t *map, unsigned def);
32static void smbios_bitmap2str(hd_bitmap_t *hbm, sm_str_map_t *map);
33
34
35/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#define SMBIOS_PRINT_ID(a, b) smbios_id_print(f, &sm->a, b)
38#define SMBIOS_PRINT_STR(a, b) smbios_str_print(f, sm->a, b)
39#define SMBIOS_PRINT_BITMAP_SHORT(a, b) smbios_bitmap_print(f, &sm->a, b, 0)
40#define SMBIOS_PRINT_BITMAP_LONG(a, b) smbios_bitmap_print(f, &sm->a, b, 1)
41
42#define SMBIOS_DEF_MAP(a) \
43 static sm_str_map_t a = { \
44 sizeof *a ## _ == sizeof (sm_num2str_t) ? sm_map_num2str : sm_map_str, \
45 sizeof a ## _ / sizeof *a ## _, \
46 { (void *) a ## _ } \
47 };
48
49/* ptr is (unsigned char *) */
50#define READ_MEM16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
51#define READ_MEM32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
52#define READ_MEM64(ptr) (READ_MEM32(ptr) + ((uint64_t) READ_MEM32(ptr + 4) << 32))
53
54
55/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
56
57static sm_num2str_t smbios_bios_feature_[] = {
58 { 4, "ISA supported" },
59 { 5, "MCA supported" },
60 { 6, "EISA supported" },
61 { 7, "PCI supported" },
62 { 8, "PCMCIA supported" },
63 { 9, "PnP supported" },
64 { 10, "APM supported" },
65 { 11, "BIOS flashable" },
66 { 12, "BIOS shadowing allowed" },
67 { 13, "VL-VESA supported" },
68 { 14, "ESCD supported" },
69 { 15, "CD boot supported" },
70 { 16, "Selectable boot supported" },
71 { 17, "BIOS ROM socketed" },
72 { 18, "PCMCIA boot supported" },
73 { 19, "EDD spec supported" },
74 { 20, "1.2MB NEC 9800 Japanese Floppy supported" },
75 { 21, "1.2MB Toshiba Japanese Floppy supported" },
76 { 22, "360kB Floppy supported" },
77 { 23, "1.2MB Floppy supported" },
78 { 24, "720kB Floppy supported" },
79 { 25, "2.88MB Floppy supported" },
80 { 26, "Print Screen supported" },
81 { 27, "8042 Keyboard Services supported" },
82 { 28, "Serial Services supported" },
83 { 29, "Printer Services supported" },
84 { 30, "CGA/Mono Video supported" },
85 { 31, "NEC PC-98" },
86 { 64 + 0, "ACPI supported" },
87 { 64 + 1, "USB Legacy supported" },
88 { 64 + 2, "AGP supported" },
89 { 64 + 3, "I2O boot supported" },
90 { 64 + 4, "LS-120 boot supported" },
91 { 64 + 5, "ATAPI ZIP boot supported" },
92 { 64 + 6, "IEEE1394 boot supported" },
93 { 64 + 7, "Smart Battery supported" },
94 { 64 + 8, "BIOS Boot Spec supported" },
95 { 64 + 9, "F12 Network boot supported" }
96};
97SMBIOS_DEF_MAP(smbios_bios_feature);
98
99
100static char *smbios_system_wakeups_[] = {
101 "Reserved", "Other", "Unknown", "APM Timer",
102 "Modem Ring", "LAN Remote", "Power Switch", "PCI PME#",
103 "AC Power Restored"
104};
105SMBIOS_DEF_MAP(smbios_system_wakeups);
106
107
108static char *smbios_board_feature_[] = {
109 "Hosting Board", "Needs One Daughter Board", "Removable", "Replaceable",
110 "Hot Swappable"
111};
112SMBIOS_DEF_MAP(smbios_board_feature);
113
114
115static char *smbios_board_types_[] = {
116 NULL, "Other", "Unknown", "Server Blade",
117 "Connectivity Switch", "System Management Module", "Processor Module", "I/O Module",
118 "Memory Module", "Daughter Board", "Motherboard", "Processor/Memory Module",
119 "Processor/IO Module", "Interconnect Board"
120};
121SMBIOS_DEF_MAP(smbios_board_types);
122
123
124static char *smbios_chassis_types_[] = {
125 NULL, "Other", "Unknown", "Desktop",
126 "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower",
127 "Portable", "LapTop", "Notebook", "Hand Held",
128 "Docking Station", "All in One", "Sub Notebook", "Space Saving",
129 "Lunch Box", "Main Server Chassis", "Expansion Chassis", "SubChassis",
130 "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", "Rack Mount Chassis",
131 "Sealed-case PC", "Multi-System Chassis"
132};
133SMBIOS_DEF_MAP(smbios_chassis_types);
134
135
136static char *smbios_chassis_states_[] = {
137 NULL, "Other", "Unknown", "Safe",
138 "Warning", "Critical", "Non-recoverable"
139};
140SMBIOS_DEF_MAP(smbios_chassis_states);
141
142
143static char *smbios_chassis_sec_states_[] = {
144 NULL, "Other", "Unknown", "None",
145 "External interface locked out", "External interface enabled"
146};
147SMBIOS_DEF_MAP(smbios_chassis_sec_states);
148
149
150static char *smbios_proc_upgrades_[] = {
151 NULL, "Other", "Unknown", "Daughter Board",
152 "ZIF Socket", "Replaceable Piggy Back", "None", "LIF Socket",
153 "Slot 1", "Slot 2", "370-Pin Socket", "Slot A",
154 "Slot M", "Socket 423", "Socket A (Socket 462)", "Socket 478",
155 "Socket 754", "Socket 940"
156};
157SMBIOS_DEF_MAP(smbios_proc_upgrades);
158
159
160static char *smbios_proc_cpu_status_[8] = {
161 "Unknown", "Enabled", "Disabled by User", "Disabled by BIOS",
162 "Idle", "Reserved", "Reserved", "Other"
163};
164SMBIOS_DEF_MAP(smbios_proc_cpu_status);
165
166
167static char *smbios_proc_types_[] = {
168 NULL, "Other", "Unknown", "CPU",
169 "Math", "DSP", "Video"
170};
171SMBIOS_DEF_MAP(smbios_proc_types);
172
173
174static sm_num2str_t smbios_proc_families_[] = {
175 { 0x00, NULL },
176 { 0x01, "Other" },
177 { 0x02, "Unknown" },
178 { 0x03, "8086" },
179 { 0x04, "80286" },
180 { 0x05, "Intel386" },
181 { 0x06, "Intel486" },
182 { 0x07, "8087" },
183 { 0x08, "80287" },
184 { 0x09, "80387" },
185 { 0x0a, "80487" },
186 { 0x0b, "Pentium" },
187 { 0x0c, "Pentium Pro" },
188 { 0x0d, "Pentium II" },
189 { 0x0e, "Pentium MMX" },
190 { 0x0f, "Celeron" },
191 { 0x10, "Pentium II Xeon" },
192 { 0x11, "Pentium III" },
193 { 0x12, "M1" },
194 { 0x13, "M2" },
195 { 0x18, "Duron" },
196 { 0x19, "K5" },
197 { 0x1a, "K6" },
198 { 0x1b, "K6-2" },
199 { 0x1c, "K6-3" },
200 { 0x1d, "Athlon" },
201 { 0x1e, "AMD2900" },
202 { 0x1f, "K6-2+" },
203 { 0x78, "Crusoe TM5000" },
204 { 0x79, "Crusoe TM3000" },
205 { 0x82, "Itanium" },
206 { 0x83, "Athlon 64" },
207 { 0x84, "Opteron Processor" },
208 { 0xb0, "Pentium III Xeon" },
209 { 0xb1, "Pentium III with SpeedStep" },
210 { 0xb2, "Pentium 4" },
211 { 0xb3, "Xeon" },
212 { 0xb4, "AS400" },
213 { 0xb5, "Xeon MP" },
214 { 0xb6, "Athlon XP" },
215 { 0xb7, "Athlon MP" },
216 { 0xb8, "Itanium 2" }
217};
218SMBIOS_DEF_MAP(smbios_proc_families);
219
220
221static char *smbios_cache_mode_[] = {
222 "Write Through", "Write Back", "Varies with Memory Address", "Unknown"
223};
224SMBIOS_DEF_MAP(smbios_cache_mode);
225
226
227static char *smbios_cache_location_[] = {
228 "Internal", "External", "Reserved", "Unknown"
229};
230SMBIOS_DEF_MAP(smbios_cache_location);
231
232
233static char *smbios_cache_ecc_[] = {
234 NULL, "Other", "Unknown", "None",
235 "Parity", "Single-bit", "Multi-bit", "CRC"
236};
237SMBIOS_DEF_MAP(smbios_cache_ecc);
238#define smbios_memarray_ecc smbios_cache_ecc
239
240
241static char *smbios_cache_type_[] = {
242 NULL, "Other", "Unknown", "Instruction",
243 "Data", "Unified"
244};
245SMBIOS_DEF_MAP(smbios_cache_type);
246
247
248static char *smbios_cache_assoc_[] = {
249 NULL, "Other", "Unknown", "Direct Mapped",
250 "2-way Set-Associative", "4-way Set-Associative", "Fully Associative", "8-way Set-Associative",
251 "16-way Set-Associative"
252};
253SMBIOS_DEF_MAP(smbios_cache_assoc);
254
255
256static char *smbios_cache_sram_[] = {
257 "Other", "Unknown", "Non-Burst", "Burst",
258 "Pipeline Burst", "Synchronous", "Asynchronous"
259};
260SMBIOS_DEF_MAP(smbios_cache_sram);
261
262
263static sm_num2str_t smbios_connect_conn_type_[] = {
264 { 0x00, NULL },
265 { 0x01, "Centronics" },
266 { 0x02, "Mini Centronics" },
267 { 0x03, "Proprietary" },
268 { 0x04, "DB-25 pin male" },
269 { 0x05, "DB-25 pin female" },
270 { 0x06, "DB-15 pin male" },
271 { 0x07, "DB-15 pin female" },
272 { 0x08, "DB-9 pin male" },
273 { 0x09, "DB-9 pin female" },
274 { 0x0a, "RJ-11" },
275 { 0x0b, "RJ-45" },
276 { 0x0c, "50 Pin MiniSCSI" },
277 { 0x0d, "Mini-DIN" },
278 { 0x0e, "Micro-DIN" },
279 { 0x0f, "PS/2" },
280 { 0x10, "Infrared" },
281 { 0x11, "HP-HIL" },
282 { 0x12, "Access Bus [USB]" },
283 { 0x13, "SSA SCSI" },
284 { 0x14, "Circular DIN-8 male" },
285 { 0x15, "Circular DIN-8 female" },
286 { 0x16, "On Board IDE" },
287 { 0x17, "On Board Floppy" },
288 { 0x18, "9 Pin Dual Inline [pin 10 cut]" },
289 { 0x19, "25 Pin Dual Inline [pin 26 cut]" },
290 { 0x1a, "50 Pin Dual Inline" },
291 { 0x1b, "68 Pin Dual Inline" },
292 { 0x1c, "On Board Sound Input from CD-ROM" },
293 { 0x1d, "Mini-Centronics Type-14" },
294 { 0x1e, "Mini-Centronics Type-26" },
295 { 0x1f, "Mini-jack [headphones]" },
296 { 0x20, "BNC" },
297 { 0x21, "1394" },
298 { 0xa0, "PC-98" },
299 { 0xa1, "PC-98Hireso" },
300 { 0xa2, "PC-H98" },
301 { 0xa3, "PC-98Note" },
302 { 0xa4, "PC-98Full" },
303 { 0xff, "Other" }
304};
305SMBIOS_DEF_MAP(smbios_connect_conn_type);
306
307
308static sm_num2str_t smbios_connect_port_type_[] = {
309 { 0x00, NULL },
310 { 0x01, "Parallel Port XT/AT Compatible" },
311 { 0x02, "Parallel Port PS/2" },
312 { 0x03, "Parallel Port ECP" },
313 { 0x04, "Parallel Port EPP" },
314 { 0x05, "Parallel Port ECP/EPP" },
315 { 0x06, "Serial Port XT/AT Compatible" },
316 { 0x07, "Serial Port 16450 Compatible" },
317 { 0x08, "Serial Port 16550 Compatible" },
318 { 0x09, "Serial Port 16550A Compatible" },
319 { 0x0a, "SCSI Port" },
320 { 0x0b, "MIDI Port" },
321 { 0x0c, "Joy Stick Port" },
322 { 0x0d, "Keyboard Port" },
323 { 0x0e, "Mouse Port" },
324 { 0x0f, "SSA SCSI" },
325 { 0x10, "USB" },
326 { 0x11, "FireWire [IEEE P1394]" },
327 { 0x12, "PCMCIA Type I" },
328 { 0x13, "PCMCIA Type II" },
329 { 0x14, "PCMCIA Type III" },
330 { 0x15, "Cardbus" },
331 { 0x16, "Access Bus Port" },
332 { 0x17, "SCSI II" },
333 { 0x18, "SCSI Wide" },
334 { 0x19, "PC-98" },
335 { 0x1a, "PC-98-Hireso" },
336 { 0x1b, "PC-H98" },
337 { 0x1c, "Video Port" },
338 { 0x1d, "Audio Port" },
339 { 0x1e, "Modem Port" },
340 { 0x1f, "Network Port" },
341 { 0xa0, "8251 Compatible" },
342 { 0xa1, "8251 FIFO Compatible" },
343 { 0xff, "Other" }
344};
345SMBIOS_DEF_MAP(smbios_connect_port_type);
346
347
348static sm_num2str_t smbios_slot_type_[] = {
349 { 0x00, NULL },
350 { 0x01, "Other" },
351 { 0x02, "Unknown" },
352 { 0x03, "ISA" },
353 { 0x04, "MCA" },
354 { 0x05, "EISA" },
355 { 0x06, "PCI" },
356 { 0x07, "PC Card [PCMCIA]" },
357 { 0x08, "VL-VESA" },
358 { 0x09, "Proprietary" },
359 { 0x0a, "Processor Card" },
360 { 0x0b, "Proprietary Memory Card" },
361 { 0x0c, "I/O Riser Card" },
362 { 0x0d, "NuBus" },
363 { 0x0e, "PCI - 66MHz Capable" },
364 { 0x0f, "AGP" },
365 { 0x10, "AGP 2X" },
366 { 0x11, "AGP 4X" },
367 { 0x12, "PCI-X" },
368 { 0x13, "AGP 8X" },
369 { 0xa0, "PC-98/C20" },
370 { 0xa1, "PC-98/C24" },
371 { 0xa2, "PC-98/E" },
372 { 0xa3, "PC-98/Local Bus" },
373 { 0xa4, "PC-98/Card" }
374};
375SMBIOS_DEF_MAP(smbios_slot_type);
376
377
378static char *smbios_slot_bus_width_[] = {
379 NULL, "Other", "Unknown", "8 bit",
380 "16 bit", "32 bit", "64 bit", "128 bit"
381};
382SMBIOS_DEF_MAP(smbios_slot_bus_width);
383
384
385static char *smbios_slot_usage_[] = {
386 NULL, "Other", "Unknown", "Available",
387 "In Use"
388};
389SMBIOS_DEF_MAP(smbios_slot_usage);
390
391
392static char *smbios_slot_length_[] = {
393 NULL, "Other", "Unknown", "Short",
394 "Long"
395};
396SMBIOS_DEF_MAP(smbios_slot_length);
397
398
399static char *smbios_slot_feature_[] = {
400 "Unknown", "5.0 V", "3.3 V", "Shared",
401 "PC Card-16", "CardBus", "Zoom Video", "Modem Ring Resume",
402 "PME#", "Hot-Plug"
403};
404SMBIOS_DEF_MAP(smbios_slot_feature);
405
406
407static char *smbios_onboard_type_[] = {
408 "Other", "Other", "Unknown", "Video",
409 "SCSI Controller", "Ethernet", "Token Ring", "Sound"
410};
411SMBIOS_DEF_MAP(smbios_onboard_type);
412
413
414static sm_num2str_t smbios_memarray_location_[] = {
415 { 0x00, NULL },
416 { 0x01, "Other" },
417 { 0x02, "Unknown" },
418 { 0x03, "Motherboard" },
419 { 0x04, "ISA add-on card" },
420 { 0x05, "EISA add-on card" },
421 { 0x06, "PCI add-on card" },
422 { 0x07, "MCA add-on card" },
423 { 0x08, "PCMCIA add-on card" },
424 { 0x09, "Proprietary add-on card" },
425 { 0x0a, "NuBus" },
426 { 0xa0, "PC-98/C20 add-on card" },
427 { 0xa1, "PC-98/C24 add-on card" },
428 { 0xa2, "PC-98/E add-on card" },
429 { 0xa3, "PC-98/Local bus add-on card" }
430};
431SMBIOS_DEF_MAP(smbios_memarray_location);
432
433
434static char *smbios_memarray_use_[] = {
435 NULL, "Other", "Unknown", "System memory",
436 "Video memory", "Flash memory", "Non-volatile RAM", "Cache memory"
437};
438SMBIOS_DEF_MAP(smbios_memarray_use);
439
440
441static char *smbios_mouse_type_[] = {
442 NULL, "Other", "Unknown", "Mouse",
443 "Track Ball", "Track Point", "Glide Point", "Touch Pad",
444 "Touch Screen", "Optical Sensor"
445};
446SMBIOS_DEF_MAP(smbios_mouse_type);
447
448
449static sm_num2str_t smbios_mouse_interface_[] = {
450 { 0x00, NULL },
451 { 0x01, "Other" },
452 { 0x02, "Unknown" },
453 { 0x03, "Serial" },
454 { 0x04, "PS/2" },
455 { 0x05, "Infrared" },
456 { 0x06, "HP-HIL" },
457 { 0x07, "Bus Mouse" },
458 { 0x08, "ADB" },
459 { 0xa0, "Bus mouse DB-9" },
460 { 0xa1, "Bus mouse micro-DIN" },
461 { 0xa2, "USB" }
462};
463SMBIOS_DEF_MAP(smbios_mouse_interface);
464
465
466static char *smbios_memdevice_form_[] = {
467 NULL, "Other", "Unknown", "SIMM",
468 "SIP", "Chip", "DIP", "ZIP",
469 "Proprietary Card", "DIMM", "TSOP", "Row of Chips",
470 "RIMM", "SODIMM", "SRIMM"
471};
472SMBIOS_DEF_MAP(smbios_memdevice_form);
473
474
475static char *smbios_memdevice_type_[] = {
476 NULL, "Other", "Unknown", "DRAM",
477 "EDRAM", "VRAM", "SRAM", "RAM",
478 "ROM", "FLASH", "EEPROM", "FEPROM",
479 "EPROM", "CDRAM", "3DRAM", "SDRAM",
480 "SGRAM", "RDRAM", "DDR"
481};
482SMBIOS_DEF_MAP(smbios_memdevice_type);
483
484
485static char *smbios_memdevice_detail_[] = {
486 NULL, "Other", "Unknown", "Fast-paged",
487 "Static column", "Pseudo-static", "RAMBUS", "Synchronous",
488 "CMOS", "EDO", "Window DRAM", "Cache DRAM",
489 "Non-volatile"
490};
491SMBIOS_DEF_MAP(smbios_memdevice_detail);
492
493
494static char *smbios_memerror_type_[] = {
495 NULL, "Other", "Unknown", "OK",
496 "Bad read", "Parity error", "Single-bit error", "Double-bit error",
497 "Multi-bit error", "Nibble error", "Checksum error", "CRC error",
498 "Corrected single-bit error", "Corrected error", "Uncorrectable error"
499};
500SMBIOS_DEF_MAP(smbios_memerror_type);
501
502
503static char *smbios_memerror_granularity_[] = {
504 NULL, "Other", "Unknown", "Device level",
505 "Memory partition level"
506};
507SMBIOS_DEF_MAP(smbios_memerror_granularity);
508
509
510static char *smbios_memerror_operation_[] = {
511 NULL, "Other", "Unknown", "Read",
512 "Write", "Partial write"
513};
514SMBIOS_DEF_MAP(smbios_memerror_operation);
515
516
517static char *smbios_secure_state_[] = {
518 "Disabled", "Enabled", "Not Implemented", "Unknown"
519};
520SMBIOS_DEF_MAP(smbios_secure_state);
521
522
523/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
524
525/*
526 * return the index'th string from sl
527 */
528char *get_string(str_list_t *sl, int index)
529{
530 if(!sl || !index) return NULL;
531
532 for(; sl; sl = sl->next, index--) {
533 if(index == 1) return new_str(sl->str && *sl->str ? sl->str : NULL);
534 }
535
536 return NULL;
537}
538
539
540/*
541 * Print a bitmap.
542 * Style: 0: short, 1: long.
543 */
544void smbios_bitmap_print(FILE *f, hd_bitmap_t *hbm, char *label, int style)
545{
546 unsigned u;
547 str_list_t *sl;
548
549 if(hbm->not_empty) {
550 fprintf(f, " %s: 0x", label);
551 for(u = (hbm->bits + 7) >> 3; u; u--) {
552 fprintf(f, "%02x", hbm->bitmap[u - 1]);
553 }
554 fprintf(f, style ? "\n" : " (");
555 for(sl = hbm->str; sl; sl = sl->next) {
556 if(style) {
557 fprintf(f, " %s\n", sl->str);
558 }
559 else {
560 fprintf(f, "%s%s", sl->str, sl->next ? ", " : "");
561 }
562 }
563 if(!style) fprintf(f, ")\n");
564 }
565}
566
567
568/*
569 * Print id/name pair.
570 */
571void smbios_id_print(FILE *f, hd_id_t *hid, char *label)
572{
573 if(hid->name) fprintf(f, " %s: 0x%02x (%s)\n", label, hid->id, hid->name);
574}
575
576
577/*
578 * Print a string.
579 */
580void smbios_str_print(FILE *f, char *str, char *label)
581{
582 if(str) fprintf(f, " %s: \"%s\"\n", label, str);
583}
584
585
586/*
587 * Look up the name that corresponds to the id (if any).
588 */
589void smbios_id2str(hd_id_t *hid, sm_str_map_t *map, unsigned def)
590{
591 unsigned u;
592 char *str, *def_str;
593
594 if(map->type == sm_map_str) {
595 str = map->list.str[hid->id < map->len ? hid->id : def];
596 if(hid->id && !str) str = map->list.str[def];
597 }
598 else {
599 for(str = def_str = NULL, u = 0; u < map->len; u++) {
600 if(map->list.num2str[u].num == hid->id) str = map->list.num2str[u].str;
601 if(str) break;
602 if(map->list.num2str[u].num == def) def_str = map->list.num2str[u].str;
603 }
604 if(hid->id && !str) str = def_str;
605 }
606 hid->name = new_str(str);
607}
608
609
610/*
611 * Convert a bitmap into a list of strings. (That is, interpret the
612 * bitmap.)
613 */
614void smbios_bitmap2str(hd_bitmap_t *hbm, sm_str_map_t *map)
615{
616 unsigned u, bit;
617 char *str;
618
619 for(u = 0; u < (hbm->bits + 7) >> 3; u++) {
620 if(hbm->bitmap[u]) {
621 hbm->not_empty = 1;
622 break;
623 }
624 }
625
626 if(map->type == sm_map_str) {
627 for(u = 0; u < map->len; u++) {
628 if(u < hbm->bits && hbm->bitmap[u >> 3] & (1 << (u & 7))) {
629 str = map->list.str[u];
630 if(str) add_str_list(&hbm->str, str);
631 }
632 }
633 }
634 else {
635 for(u = 0; u < map->len; u++) {
636 bit = map->list.num2str[u].num;
637 if(bit < hbm->bits && hbm->bitmap[bit >> 3] & (1 << (bit & 7))) {
638 str = map->list.num2str[u].str;
639 if(str) add_str_list(&hbm->str, str);
640 }
641 }
642 }
643}
644
645
646/*
647 * Interpret raw smbios data.
648 */
649void smbios_parse(hd_data_t *hd_data)
650{
651 hd_smbios_t *sm;
652 str_list_t *sl_any, *sl;
653 int cnt, data_len;
654 unsigned char *sm_data;
655 unsigned u, v;
656
657 if(!hd_data->smbios) return;
658
659 for(cnt = 0, sm = hd_data->smbios; sm; sm = sm->next, cnt++) {
660 sm_data = sm->any.data;
661 data_len = sm->any.data_len;
662 sl_any = sm->any.strings;
663 switch(sm->any.type) {
664 case sm_biosinfo:
665 if(data_len >= 0x12) {
666 sm->biosinfo.start = READ_MEM16(sm_data + 6) << 4;
667 sm->biosinfo.rom_size = (sm_data[9] + 1) << 16;
668 sm->biosinfo.vendor = get_string(sl_any, sm_data[4]);
669 sm->biosinfo.version = get_string(sl_any, sm_data[5]);
670 sm->biosinfo.date = get_string(sl_any, sm_data[8]);
671 memcpy(sm->biosinfo.feature.bitmap, sm_data + 0xa, 8);
672 }
673 if(data_len >= 0x13) {
674 sm->biosinfo.feature.bitmap[8] = sm_data[0x12];
675 }
676 if(data_len >= 0x14) {
677 sm->biosinfo.feature.bitmap[9] = sm_data[0x13];
678 }
679 sm->biosinfo.feature.bits = 80;
680 smbios_bitmap2str(&sm->biosinfo.feature, &smbios_bios_feature);
681 break;
682
683 case sm_sysinfo:
684 if(data_len >= 8) {
685 sm->sysinfo.manuf = get_string(sl_any, sm_data[4]);
686 sm->sysinfo.product = get_string(sl_any, sm_data[5]);
687 sm->sysinfo.version = get_string(sl_any, sm_data[6]);
688 sm->sysinfo.serial = get_string(sl_any, sm_data[7]);
689 }
690 if(data_len >= 0x19) {
691 memcpy(sm->sysinfo.uuid, sm_data + 8, 16);
692 sm->sysinfo.wake_up.id = sm_data[0x18];
693 smbios_id2str(&sm->sysinfo.wake_up, &smbios_system_wakeups, 1);
694 }
695 break;
696
697 case sm_boardinfo:
698 if(data_len >= 8) {
699 sm->boardinfo.manuf = get_string(sl_any, sm_data[4]);
700 sm->boardinfo.product = get_string(sl_any, sm_data[5]);
701 sm->boardinfo.version = get_string(sl_any, sm_data[6]);
702 sm->boardinfo.serial = get_string(sl_any, sm_data[7]);
703 }
704 if(data_len >= 9) {
705 sm->boardinfo.asset = get_string(sl_any, sm_data[8]);
706 }
707 if(data_len >= 0x0e) {
708 sm->boardinfo.feature.bitmap[0] = sm_data[9];
709 sm->boardinfo.feature.bits = 8;
710 smbios_bitmap2str(&sm->boardinfo.feature, &smbios_board_feature);
711 sm->boardinfo.location = get_string(sl_any, sm_data[0x0a]);
712 sm->boardinfo.chassis = READ_MEM16(sm_data + 0x0b);
713 sm->boardinfo.board_type.id = sm_data[0x0d];
714 smbios_id2str(&sm->boardinfo.board_type, &smbios_board_types, 1);
715 }
716 if(data_len >= 0x0f) {
717 u = sm_data[0x0e];
718 if(u && data_len >= 0x0f + 2 * u) {
719 sm->boardinfo.objects_len = u;
720 sm->boardinfo.objects = new_mem(u * sizeof *sm->boardinfo.objects);
721 for(u = 0; u < sm->boardinfo.objects_len; u++) {
722 sm->boardinfo.objects[u] = READ_MEM16(sm_data + 0x0f + 2 * u);
723 }
724 }
725 }
726 break;
727
728 case sm_chassis:
729 if(data_len >= 6) {
730 sm->chassis.manuf = get_string(sl_any, sm_data[4]);
731 sm->chassis.lock = sm_data[5] >> 7;
732 sm->chassis.ch_type.id = sm_data[5] & 0x7f;
733 smbios_id2str(&sm->chassis.ch_type, &smbios_chassis_types, 1);
734 }
735 if(data_len >= 9) {
736 sm->chassis.version = get_string(sl_any, sm_data[6]);
737 sm->chassis.serial = get_string(sl_any, sm_data[7]);
738 sm->chassis.asset = get_string(sl_any, sm_data[8]);
739 }
740 if(data_len >= 0x0d) {
741 sm->chassis.bootup.id = sm_data[9];
742 sm->chassis.power.id = sm_data[0x0a];
743 sm->chassis.thermal.id = sm_data[0x0b];
744 sm->chassis.security.id = sm_data[0x0c];
745 smbios_id2str(&sm->chassis.bootup, &smbios_chassis_states, 1);
746 smbios_id2str(&sm->chassis.power, &smbios_chassis_states, 1);
747 smbios_id2str(&sm->chassis.thermal, &smbios_chassis_states, 1);
748 smbios_id2str(&sm->chassis.security, &smbios_chassis_sec_states, 1);
749 }
750 if(data_len >= 0x11) {
751 sm->chassis.oem = READ_MEM32(sm_data + 0x0d);
752 }
753 break;
754
755 case sm_processor:
756 if(data_len >= 0x1a) {
757 sm->processor.socket = get_string(sl_any, sm_data[4]);
758 sm->processor.manuf = get_string(sl_any, sm_data[7]);
759 sm->processor.version = get_string(sl_any, sm_data[0x10]);
760 sm->processor.voltage = sm_data[0x11];
761 if(sm->processor.voltage & 0x80) {
762 sm->processor.voltage &= 0x7f;
763 }
764 else {
765 switch(sm->processor.voltage) {
766 case 0x01:
767 sm->processor.voltage = 50;
768 break;
769 case 0x02:
770 sm->processor.voltage = 33;
771 break;
772 case 0x04:
773 sm->processor.voltage = 29;
774 break;
775 default:
776 sm->processor.voltage = 0;
777 }
778 }
779 sm->processor.pr_type.id = sm_data[5];
780 sm->processor.family.id = sm_data[6];
781 sm->processor.cpu_id = READ_MEM64(sm_data + 8);
782 sm->processor.ext_clock = READ_MEM16(sm_data + 0x12);
783 sm->processor.max_speed = READ_MEM16(sm_data + 0x14);
784 sm->processor.current_speed = READ_MEM16(sm_data + 0x16);
785 sm->processor.sock_status = (sm_data[0x18] >> 6) & 1;
786 sm->processor.cpu_status.id = sm_data[0x18] & 7;
787 sm->processor.upgrade.id = sm_data[0x19];
788 smbios_id2str(&sm->processor.pr_type, &smbios_proc_types, 1);
789 smbios_id2str(&sm->processor.family, &smbios_proc_families, 1);
790 smbios_id2str(&sm->processor.cpu_status, &smbios_proc_cpu_status, 0);
791 smbios_id2str(&sm->processor.upgrade, &smbios_proc_upgrades, 1);
792 }
793 if(data_len >= 0x20) {
794 sm->processor.l1_cache = READ_MEM16(sm_data + 0x1a);
795 sm->processor.l2_cache = READ_MEM16(sm_data + 0x1c);
796 sm->processor.l3_cache = READ_MEM16(sm_data + 0x1e);
797 if(sm->processor.l1_cache == 0xffff) sm->processor.l1_cache = 0;
798 if(sm->processor.l2_cache == 0xffff) sm->processor.l2_cache = 0;
799 if(sm->processor.l3_cache == 0xffff) sm->processor.l3_cache = 0;
800 }
801 if(data_len >= 0x21) {
802 sm->processor.serial = get_string(sl_any, sm_data[0x20]);
803 }
804 if(data_len >= 0x22) {
805 sm->processor.asset = get_string(sl_any, sm_data[0x21]);
806 sm->processor.part = get_string(sl_any, sm_data[0x22]);
807 }
808 break;
809
810 case sm_cache:
811 if(data_len >= 0x0f) {
812 sm->cache.socket = get_string(sl_any, sm_data[4]);
813 u = READ_MEM16(sm_data + 7);
814 if((u & 0x8000)) u = (u & 0x7fff) << 6;
815 sm->cache.max_size = u;
816 u = READ_MEM16(sm_data + 9);
817 if((u & 0x8000)) u = (u & 0x7fff) << 6;
818 sm->cache.current_size = u;
819 u = READ_MEM16(sm_data + 5);
820 sm->cache.mode.id = (u >> 8) & 3;
821 sm->cache.state = (u >> 7) & 1;
822 sm->cache.location.id = (u >> 5) & 3;
823 sm->cache.socketed = (u >> 3) & 1;
824 sm->cache.level = u & 7;
825 smbios_id2str(&sm->cache.mode, &smbios_cache_mode, 0);
826 smbios_id2str(&sm->cache.location, &smbios_cache_location, 0);
827 sm->cache.supp_sram.bitmap[0] = sm_data[0x0b];
828 sm->cache.supp_sram.bitmap[1] = sm_data[0x0c];
829 sm->cache.supp_sram.bits = 16;
830 sm->cache.sram.bitmap[0] = sm_data[0x0d];
831 sm->cache.sram.bitmap[1] = sm_data[0x0e];
832 sm->cache.sram.bits = 16;
833 smbios_bitmap2str(&sm->cache.supp_sram, &smbios_cache_sram);
834 smbios_bitmap2str(&sm->cache.sram, &smbios_cache_sram);
835 }
836 if(data_len >= 0x13) {
837 sm->cache.speed = sm_data[0x0f];
838 sm->cache.ecc.id = sm_data[0x10];
839 sm->cache.cache_type.id = sm_data[0x11];
840 sm->cache.assoc.id = sm_data[0x12];
841 smbios_id2str(&sm->cache.ecc, &smbios_cache_ecc, 1);
842 smbios_id2str(&sm->cache.cache_type, &smbios_cache_type, 1);
843 smbios_id2str(&sm->cache.assoc, &smbios_cache_assoc, 1);
844 }
845 break;
846
847 case sm_connect:
848 if(data_len >= 9) {
849 sm->connect.i_des = get_string(sl_any, sm_data[4]);
850 sm->connect.x_des = get_string(sl_any, sm_data[6]);
851 sm->connect.i_type.id = sm_data[5];
852 sm->connect.x_type.id = sm_data[7];
853 sm->connect.port_type.id = sm_data[8];
854 smbios_id2str(&sm->connect.port_type, &smbios_connect_conn_type, 0xff);
855 smbios_id2str(&sm->connect.x_type, &smbios_connect_conn_type, 0xff);
856 smbios_id2str(&sm->connect.port_type, &smbios_connect_port_type, 0xff);
857 }
858 break;
859
860 case sm_slot:
861 if(data_len >= 0x0c) {
862 sm->slot.desig = get_string(sl_any, sm_data[4]);
863 sm->slot.slot_type.id = sm_data[5];
864 sm->slot.bus_width.id = sm_data[6];
865 sm->slot.usage.id = sm_data[7];
866 sm->slot.length.id = sm_data[8];
867 sm->slot.id = READ_MEM16(sm_data + 9);
868 sm->slot.feature.bitmap[0] = sm_data[0x0b];
869 }
870 if(data_len >= 0x0d) {
871 sm->slot.feature.bitmap[1] = sm_data[0x0c];
872 }
873 sm->slot.feature.bits = 16;
874 smbios_id2str(&sm->slot.slot_type, &smbios_slot_type, 1);
875 smbios_id2str(&sm->slot.bus_width, &smbios_slot_bus_width, 1);
876 smbios_id2str(&sm->slot.usage, &smbios_slot_usage, 1);
877 smbios_id2str(&sm->slot.length, &smbios_slot_length, 1);
878 smbios_bitmap2str(&sm->slot.feature, &smbios_slot_feature);
879 break;
880
881 case sm_onboard:
882 if(data_len >= 4) {
883 u = data_len - 4;
884 if(!(u & 1)) {
885 u >>= 1;
886 if(u) {
887 sm->onboard.dev_len = u;
888 sm->onboard.dev = new_mem(u * sizeof *sm->onboard.dev);
889 }
890 for(u = 0; u < sm->onboard.dev_len; u++) {
891 sm->onboard.dev[u].name = get_string(sl_any, sm_data[4 + (u << 1) + 1]);
892 v = sm_data[4 + (u << 1)];
893 sm->onboard.dev[u].status = v >> 7;
894 sm->onboard.dev[u].type.id = v & 0x7f;
895 smbios_id2str(&sm->onboard.dev[u].type, &smbios_onboard_type, 1);
896 }
897 }
898 }
899 break;
900
901 case sm_oem:
902 for(sl = sl_any; sl; sl = sl->next) {
903 if(sl->str && *sl->str) add_str_list(&sm->oem.oem_strings, sl->str);
904 }
905 break;
906
907 case sm_config:
908 for(sl = sl_any; sl; sl = sl->next) {
909 if(sl->str && *sl->str) add_str_list(&sm->config.options, sl->str);
910 }
911 break;
912
913 case sm_lang:
914 if(data_len >= 0x16) {
915 sm->lang.current = get_string(sl_any, sm_data[0x15]);
916 }
917 break;
918
919 case sm_group:
920 if(data_len >= 5) {
921 sm->group.name = get_string(sl_any, sm_data[4]);
922 u = (data_len - 5) / 3;
923 if(u) {
924 sm->group.items_len = u;
925 sm->group.item_handles = new_mem(u * sizeof *sm->group.item_handles);
926 for(u = 0; u < sm->group.items_len; u++) {
927 sm->group.item_handles[u] = READ_MEM16(sm_data + 6 + 3 * u);
928 }
929 }
930 }
931 break;
932
933 case sm_memarray:
934 if(data_len >= 0x0f) {
935 sm->memarray.location.id = sm_data[4];
936 sm->memarray.use.id = sm_data[5];
937 sm->memarray.ecc.id = sm_data[6];
938 sm->memarray.max_size = READ_MEM32(sm_data + 7);
939 if(sm->memarray.max_size == 0x80000000) sm->memarray.max_size = 0;
940 sm->memarray.error_handle = READ_MEM16(sm_data + 0x0b);
941 sm->memarray.slots = READ_MEM16(sm_data + 0x0d);
942 smbios_id2str(&sm->memarray.location, &smbios_memarray_location, 1);
943 smbios_id2str(&sm->memarray.use, &smbios_memarray_use, 1);
944 smbios_id2str(&sm->memarray.ecc, &smbios_memarray_ecc, 1);
945 }
946 break;
947
948 case sm_memdevice:
949 if(data_len >= 0x15) {
950 sm->memdevice.array_handle = READ_MEM16(sm_data + 0x04);
951 sm->memdevice.error_handle = READ_MEM16(sm_data + 0x06);
952 sm->memdevice.eccbits = READ_MEM16(sm_data + 8);
953 sm->memdevice.width = READ_MEM16(sm_data + 0xa);
954 if(sm->memdevice.width == 0xffff) sm->memdevice.width = 0;
955 if(sm->memdevice.eccbits == 0xffff) sm->memdevice.eccbits = 0;
956 if(sm->memdevice.eccbits >= sm->memdevice.width) {
957 sm->memdevice.eccbits -= sm->memdevice.width;
958 }
959 else {
960 sm->memdevice.eccbits = 0;
961 }
962 sm->memdevice.size = READ_MEM16(sm_data + 0xc);
963 if(sm->memdevice.size == 0xffff) sm->memdevice.size = 0;
964 if((sm->memdevice.size & 0x8000)) {
965 sm->memdevice.size &= 0x7fff;
966 }
967 else {
968 sm->memdevice.size <<= 10;
969 }
970 sm->memdevice.form.id = sm_data[0xe];
971 sm->memdevice.set = sm_data[0xf];
972 sm->memdevice.location = get_string(sl_any, sm_data[0x10]);
973 sm->memdevice.bank = get_string(sl_any, sm_data[0x11]);
974 sm->memdevice.mem_type.id = sm_data[0x12];
975 smbios_id2str(&sm->memdevice.form, &smbios_memdevice_form, 1);
976 smbios_id2str(&sm->memdevice.mem_type, &smbios_memdevice_type, 1);
977 sm->memdevice.type_detail.bitmap[0] = sm_data[0x13];
978 sm->memdevice.type_detail.bitmap[1] = sm_data[0x14];
979 sm->memdevice.type_detail.bits = 16;
980 smbios_bitmap2str(&sm->memdevice.type_detail, &smbios_memdevice_detail);
981 }
982 if(data_len >= 0x17) {
983 sm->memdevice.speed = READ_MEM16(sm_data + 0x15);
984 }
985 if(data_len >= 0x1b) {
986 sm->memdevice.manuf = get_string(sl_any, sm_data[0x17]);
987 sm->memdevice.serial = get_string(sl_any, sm_data[0x18]);
988 sm->memdevice.asset = get_string(sl_any, sm_data[0x19]);
989 sm->memdevice.part = get_string(sl_any, sm_data[0x1a]);
990 }
991 break;
992
993 case sm_memerror:
994 if(data_len >= 0x17) {
995 sm->memerror.err_type.id = sm_data[4];
996 sm->memerror.granularity.id = sm_data[5];
997 sm->memerror.operation.id = sm_data[6];
998 sm->memerror.syndrome = READ_MEM32(sm_data + 7);
999 sm->memerror.array_addr = READ_MEM32(sm_data + 0xb);
1000 sm->memerror.device_addr = READ_MEM32(sm_data + 0xf);
1001 sm->memerror.range = READ_MEM32(sm_data + 0x13);
1002 smbios_id2str(&sm->memerror.err_type, &smbios_memerror_type, 1);
1003 smbios_id2str(&sm->memerror.granularity, &smbios_memerror_granularity, 1);
1004 smbios_id2str(&sm->memerror.operation, &smbios_memerror_operation, 1);
1005 }
1006 break;
1007
1008 case sm_memarraymap:
1009 if(data_len >= 0x0f) {
1010 sm->memarraymap.start_addr = READ_MEM32(sm_data + 4);
1011 sm->memarraymap.start_addr <<= 10;
1012 sm->memarraymap.end_addr = 1 + READ_MEM32(sm_data + 8);
1013 sm->memarraymap.end_addr <<= 10;
1014 sm->memarraymap.array_handle = READ_MEM16(sm_data + 0xc);
1015 sm->memarraymap.part_width = sm_data[0x0e];
1016 }
1017 break;
1018
1019 case sm_memdevicemap:
1020 if(data_len >= 0x13) {
1021 sm->memdevicemap.start_addr = READ_MEM32(sm_data + 4);
1022 sm->memdevicemap.start_addr <<= 10;
1023 sm->memdevicemap.end_addr = 1 + READ_MEM32(sm_data + 8);
1024 sm->memdevicemap.end_addr <<= 10;
1025 sm->memdevicemap.memdevice_handle = READ_MEM16(sm_data + 0xc);
1026 sm->memdevicemap.arraymap_handle = READ_MEM16(sm_data + 0xe);
1027 sm->memdevicemap.row_pos = sm_data[0x10];
1028 sm->memdevicemap.interleave_pos = sm_data[0x11];
1029 sm->memdevicemap.interleave_depth = sm_data[0x12];
1030 }
1031 break;
1032
1033 case sm_mouse:
1034 if(data_len >= 7) {
1035 sm->mouse.mtype.id = sm_data[4];
1036 sm->mouse.interface.id = sm_data[5];
1037 sm->mouse.buttons = sm_data[6];
1038 smbios_id2str(&sm->mouse.mtype, &smbios_mouse_type, 1);
1039 smbios_id2str(&sm->mouse.interface, &smbios_mouse_interface, 1);
1040 }
1041 break;
1042
1043 case sm_secure:
1044 if(data_len >= 5) {
1045 u = sm_data[4];
1046 sm->secure.power.id = u >> 6;
1047 sm->secure.keyboard.id = (u >> 4) & 3;
1048 sm->secure.admin.id = (u >> 2) & 3;
1049 sm->secure.reset.id = u & 3;
1050 smbios_id2str(&sm->secure.power, &smbios_secure_state, 3);
1051 smbios_id2str(&sm->secure.keyboard, &smbios_secure_state, 3);
1052 smbios_id2str(&sm->secure.admin, &smbios_secure_state, 3);
1053 smbios_id2str(&sm->secure.reset, &smbios_secure_state, 3);
1054 }
1055 break;
1056
1057 case sm_power:
1058 if(data_len >= 9) {
1059 sm->power.month = sm_data[4];
1060 sm->power.day = sm_data[5];
1061 sm->power.hour = sm_data[6];
1062 sm->power.minute = sm_data[7];
1063 sm->power.second = sm_data[8];
1064 }
1065 break;
1066
1067 case sm_mem64error:
1068 if(data_len >= 0x1f) {
1069 sm->mem64error.err_type.id = sm_data[4];
1070 sm->mem64error.granularity.id = sm_data[5];
1071 sm->mem64error.operation.id = sm_data[6];
1072 sm->mem64error.syndrome = READ_MEM32(sm_data + 7);
1073 sm->mem64error.array_addr = READ_MEM64(sm_data + 0xb);
1074 sm->mem64error.device_addr = READ_MEM64(sm_data + 0x13);
1075 sm->mem64error.range = READ_MEM32(sm_data + 0x1b);
1076 smbios_id2str(&sm->mem64error.err_type, &smbios_memerror_type, 1);
1077 smbios_id2str(&sm->mem64error.granularity, &smbios_memerror_granularity, 1);
1078 smbios_id2str(&sm->mem64error.operation, &smbios_memerror_operation, 1);
1079 }
1080 break;
1081
1082 default:
1083 break;
1084 }
1085 }
1086}
1087
1088
1089/*
1090 * Note: new_sm is directly inserted into the list, so you *must* make sure
1091 * that new_sm points to a malloc'ed pice of memory.
1092 */
1093hd_smbios_t *smbios_add_entry(hd_smbios_t **sm, hd_smbios_t *new_sm)
1094{
1095 while(*sm) sm = &(*sm)->next;
1096
1097 return *sm = new_sm;
1098}
1099
1100
1101/*
1102 * Free the memory allocated by a smbios list.
1103 */
1104hd_smbios_t *smbios_free(hd_smbios_t *sm)
1105{
1106 hd_smbios_t *next;
1107 unsigned u;
1108
1109 for(; sm; sm = next) {
1110 next = sm->next;
1111
1112 free_mem(sm->any.data);
1113 free_str_list(sm->any.strings);
1114
1115 switch(sm->any.type) {
1116 case sm_biosinfo:
1117 free_mem(sm->biosinfo.vendor);
1118 free_mem(sm->biosinfo.version);
1119 free_mem(sm->biosinfo.date);
1120 free_str_list(sm->biosinfo.feature.str);
1121 break;
1122
1123 case sm_sysinfo:
1124 free_mem(sm->sysinfo.manuf);
1125 free_mem(sm->sysinfo.product);
1126 free_mem(sm->sysinfo.version);
1127 free_mem(sm->sysinfo.serial);
1128 free_mem(sm->sysinfo.wake_up.name);
1129 break;
1130
1131 case sm_boardinfo:
1132 free_mem(sm->boardinfo.manuf);
1133 free_mem(sm->boardinfo.product);
1134 free_mem(sm->boardinfo.version);
1135 free_mem(sm->boardinfo.serial);
1136 free_mem(sm->boardinfo.asset);
1137 free_mem(sm->boardinfo.location);
1138 free_mem(sm->boardinfo.board_type.name);
1139 free_str_list(sm->boardinfo.feature.str);
1140 free_mem(sm->boardinfo.objects);
1141 break;
1142
1143 case sm_chassis:
1144 free_mem(sm->chassis.manuf);
1145 free_mem(sm->chassis.version);
1146 free_mem(sm->chassis.serial);
1147 free_mem(sm->chassis.asset);
1148 free_mem(sm->chassis.ch_type.name);
1149 free_mem(sm->chassis.bootup.name);
1150 free_mem(sm->chassis.power.name);
1151 free_mem(sm->chassis.thermal.name);
1152 free_mem(sm->chassis.security.name);
1153 break;
1154
1155 case sm_processor:
1156 free_mem(sm->processor.socket);
1157 free_mem(sm->processor.manuf);
1158 free_mem(sm->processor.version);
1159 free_mem(sm->processor.serial);
1160 free_mem(sm->processor.asset);
1161 free_mem(sm->processor.part);
1162 free_mem(sm->processor.upgrade.name);
1163 free_mem(sm->processor.pr_type.name);
1164 free_mem(sm->processor.family.name);
1165 free_mem(sm->processor.cpu_status.name);
1166 break;
1167
1168 case sm_cache:
1169 free_mem(sm->cache.socket);
1170 free_mem(sm->cache.mode.name);
1171 free_mem(sm->cache.location.name);
1172 free_mem(sm->cache.ecc.name);
1173 free_mem(sm->cache.cache_type.name);
1174 free_mem(sm->cache.assoc.name);
1175 free_str_list(sm->cache.supp_sram.str);
1176 free_str_list(sm->cache.sram.str);
1177 break;
1178
1179 case sm_connect:
1180 free_mem(sm->connect.port_type.name);
1181 free_mem(sm->connect.i_des);
1182 free_mem(sm->connect.x_des);
1183 free_mem(sm->connect.i_type.name);
1184 free_mem(sm->connect.x_type.name);
1185 break;
1186
1187 case sm_slot:
1188 free_mem(sm->slot.desig);
1189 free_mem(sm->slot.slot_type.name);
1190 free_mem(sm->slot.bus_width.name);
1191 free_mem(sm->slot.usage.name);
1192 free_mem(sm->slot.length.name);
1193 free_str_list(sm->slot.feature.str);
1194 break;
1195
1196 case sm_onboard:
1197 for(u = 0; u < sm->onboard.dev_len; u++) {
1198 free_mem(sm->onboard.dev[u].name);
1199 free_mem(sm->onboard.dev[u].type.name);
1200 }
1201 free_mem(sm->onboard.dev);
1202 break;
1203
1204 case sm_oem:
1205 free_str_list(sm->oem.oem_strings);
1206 break;
1207
1208 case sm_config:
1209 free_str_list(sm->config.options);
1210 break;
1211
1212 case sm_lang:
1213 free_mem(sm->lang.current);
1214 break;
1215
1216 case sm_group:
1217 free_mem(sm->group.name);
1218 free_mem(sm->group.item_handles);
1219 break;
1220
1221 case sm_memarray:
1222 free_mem(sm->memarray.location.name);
1223 free_mem(sm->memarray.use.name);
1224 free_mem(sm->memarray.ecc.name);
1225 break;
1226
1227 case sm_memdevice:
1228 free_mem(sm->memdevice.location);
1229 free_mem(sm->memdevice.bank);
1230 free_mem(sm->memdevice.manuf);
1231 free_mem(sm->memdevice.serial);
1232 free_mem(sm->memdevice.asset);
1233 free_mem(sm->memdevice.part);
1234 free_mem(sm->memdevice.form.name);
1235 free_mem(sm->memdevice.mem_type.name);
1236 free_str_list(sm->memdevice.type_detail.str);
1237 break;
1238
1239 case sm_memerror:
1240 free_mem(sm->memerror.err_type.name);
1241 free_mem(sm->memerror.granularity.name);
1242 free_mem(sm->memerror.operation.name);
1243 break;
1244
1245 case sm_mouse:
1246 free_mem(sm->mouse.mtype.name);
1247 free_mem(sm->mouse.interface.name);
1248 break;
1249
1250 case sm_secure:
1251 free_mem(sm->secure.power.name);
1252 free_mem(sm->secure.keyboard.name);
1253 free_mem(sm->secure.admin.name);
1254 free_mem(sm->secure.reset.name);
1255 break;
1256
1257 case sm_mem64error:
1258 free_mem(sm->mem64error.err_type.name);
1259 free_mem(sm->mem64error.granularity.name);
1260 free_mem(sm->mem64error.operation.name);
1261 break;
1262
1263 default:
1264 break;
1265 }
1266
1267 free_mem(sm);
1268 }
1269
1270 return NULL;
1271}
1272
1273
1274/*
1275 * print SMBIOS entries
1276 */
1277void smbios_dump(hd_data_t *hd_data, FILE *f)
1278{
1279 hd_smbios_t *sm;
1280 str_list_t *sl;
1281 char c, *s;
1282 unsigned u;
1283 int i;
1284
1285 if(!hd_data->smbios) return;
1286
1287 for(sm = hd_data->smbios; sm; sm = sm->next) {
1288 switch(sm->any.type) {
1289 case sm_biosinfo:
1290 fprintf(f, " BIOS Info: #%d\n", sm->any.handle);
1291 if(sm->biosinfo.vendor) fprintf(f, " Vendor: \"%s\"\n", sm->biosinfo.vendor);
1292 if(sm->biosinfo.version) fprintf(f, " Version: \"%s\"\n", sm->biosinfo.version);
1293 if(sm->biosinfo.date) fprintf(f, " Date: \"%s\"\n", sm->biosinfo.date);
1294 fprintf(f, " Start Address: 0x%05x\n", sm->biosinfo.start);
1295 fprintf(f, " ROM Size: %d kB\n", sm->biosinfo.rom_size >> 10);
1296 SMBIOS_PRINT_BITMAP_LONG(biosinfo.feature, "Features");
1297 break;
1298
1299 case sm_sysinfo:
1300 fprintf(f, " System Info: #%d\n", sm->any.handle);
1301 if(sm->sysinfo.manuf) fprintf(f, " Manufacturer: \"%s\"\n", sm->sysinfo.manuf);
1302 if(sm->sysinfo.product) fprintf(f, " Product: \"%s\"\n", sm->sysinfo.product);
1303 if(sm->sysinfo.version) fprintf(f, " Version: \"%s\"\n", sm->sysinfo.version);
1304 if(sm->sysinfo.serial) fprintf(f, " Serial: \"%s\"\n", sm->sysinfo.serial);
1305 for(i = u = 0; (unsigned) i < sizeof sm->sysinfo.uuid / sizeof *sm->sysinfo.uuid; i++) {
1306 u |= sm->sysinfo.uuid[i];
1307 }
1308 fprintf(f, " UUID: ");
1309 if(u == 0 || u == 0xff) {
1310 fprintf(f, "undefined");
1311 if(u == 0xff) fprintf(f, ", but settable");
1312 }
1313 else {
1314 for(i = sizeof sm->sysinfo.uuid / sizeof *sm->sysinfo.uuid - 1; i >= 0; i--) {
1315 fprintf(f, "%02x", sm->sysinfo.uuid[i]);
1316 }
1317 }
1318 fprintf(f, "\n");
1319 SMBIOS_PRINT_ID(sysinfo.wake_up, "Wake-up");
1320 break;
1321
1322 case sm_boardinfo:
1323 fprintf(f, " Board Info: #%d\n", sm->any.handle);
1324 if(sm->boardinfo.manuf) fprintf(f, " Manufacturer: \"%s\"\n", sm->boardinfo.manuf);
1325 if(sm->boardinfo.product) fprintf(f, " Product: \"%s\"\n", sm->boardinfo.product);
1326 if(sm->boardinfo.version) fprintf(f, " Version: \"%s\"\n", sm->boardinfo.version);
1327 if(sm->boardinfo.serial) fprintf(f, " Serial: \"%s\"\n", sm->boardinfo.serial);
1328 if(sm->boardinfo.asset) fprintf(f, " Asset Tag: \"%s\"\n", sm->boardinfo.asset);
1329 SMBIOS_PRINT_ID(boardinfo.board_type, "Type");
1330 SMBIOS_PRINT_BITMAP_LONG(boardinfo.feature, "Features");
1331 if(sm->boardinfo.location) fprintf(f, " Location: \"%s\"\n", sm->boardinfo.location);
1332 if(sm->boardinfo.chassis) fprintf(f, " Chassis: #%d\n", sm->boardinfo.chassis);
1333 if(sm->boardinfo.objects_len) {
1334 fprintf(f, " Contained Objects: ");
1335 for(i = 0; i < sm->boardinfo.objects_len; i++) {
1336 fprintf(f, "%s#%d", i ? ", " : "", sm->boardinfo.objects[i]);
1337 }
1338 fprintf(f, "\n");
1339 }
1340 break;
1341
1342 case sm_chassis:
1343 fprintf(f, " Chassis Info: #%d\n", sm->any.handle);
1344 if(sm->chassis.manuf) fprintf(f, " Manufacturer: \"%s\"\n", sm->chassis.manuf);
1345 if(sm->chassis.version) fprintf(f, " Version: \"%s\"\n", sm->chassis.version);
1346 if(sm->chassis.serial) fprintf(f, " Serial: \"%s\"\n", sm->chassis.serial);
1347 if(sm->chassis.asset) fprintf(f, " Asset Tag: \"%s\"\n", sm->chassis.asset);
1348 SMBIOS_PRINT_ID(chassis.ch_type, "Type");
1349 if(sm->chassis.lock) fprintf(f, " Lock: present\n");
1350 SMBIOS_PRINT_ID(chassis.bootup, "Bootup State");
1351 SMBIOS_PRINT_ID(chassis.power, "Power Supply State");
1352 SMBIOS_PRINT_ID(chassis.thermal, "Thermal State");
1353 SMBIOS_PRINT_ID(chassis.security, "Security Status");
1354 if(sm->chassis.oem) fprintf(f, " OEM Info: 0x%08x\n", sm->chassis.oem);
1355 break;
1356
1357 case sm_processor:
1358 fprintf(f, " Processor Info: #%d\n", sm->any.handle);
1359 SMBIOS_PRINT_STR(processor.socket, "Socket");
1360 SMBIOS_PRINT_ID(processor.upgrade, "Socket Type");
1361 fprintf(f, " Socket Status: %s\n", sm->processor.sock_status ? "Populated" : "Empty");
1362 SMBIOS_PRINT_ID(processor.pr_type, "Type");
1363 SMBIOS_PRINT_ID(processor.family, "Family");
1364 SMBIOS_PRINT_STR(processor.manuf, "Manufacturer");
1365 SMBIOS_PRINT_STR(processor.version, "Version");
1366 SMBIOS_PRINT_STR(processor.serial, "Serial");
1367 SMBIOS_PRINT_STR(processor.asset, "Asset Tag");
1368 SMBIOS_PRINT_STR(processor.part, "Part Number");
1369 if(sm->processor.cpu_id) {
1370 fprintf(f, " Processor ID: 0x%016"PRIx64"\n", sm->processor.cpu_id);
1371 }
1372 SMBIOS_PRINT_ID(processor.cpu_status, "Status");
1373 if(sm->processor.voltage) {
1374 fprintf(f, " Voltage: %u.%u V\n", sm->processor.voltage / 10, sm->processor.voltage % 10);
1375 }
1376 if(sm->processor.ext_clock) fprintf(f, " External Clock: %u MHz\n", sm->processor.ext_clock);
1377 if(sm->processor.max_speed) fprintf(f, " Max. Speed: %u MHz\n", sm->processor.max_speed);
1378 if(sm->processor.current_speed) fprintf(f, " Current Speed: %u MHz\n", sm->processor.current_speed);
1379
1380 if(sm->processor.l1_cache) fprintf(f, " L1 Cache: #%d\n", sm->processor.l1_cache);
1381 if(sm->processor.l2_cache) fprintf(f, " L2 Cache: #%d\n", sm->processor.l2_cache);
1382 if(sm->processor.l3_cache) fprintf(f, " L3 Cache: #%d\n", sm->processor.l3_cache);
1383 break;
1384
1385 case sm_cache:
1386 fprintf(f, " Cache Info: #%d\n", sm->any.handle);
1387 SMBIOS_PRINT_STR(cache.socket, "Designation");
1388 fprintf(f, " Level: L%u\n", sm->cache.level + 1);
1389 fprintf(f, " State: %s\n", sm->cache.state ? "Enabled" : "Disabled");
1390 SMBIOS_PRINT_ID(cache.mode, "Mode");
1391 if(sm->cache.location.name) {
1392 fprintf(f, " Location: 0x%02x (%s, %sSocketed)\n",
1393 sm->cache.location.id,
1394 sm->cache.location.name,
1395 sm->cache.socketed ? "" : "Not "
1396 );
1397 }
1398 SMBIOS_PRINT_ID(cache.ecc, "ECC");
1399 SMBIOS_PRINT_ID(cache.cache_type, "Type");
1400 SMBIOS_PRINT_ID(cache.assoc, "Associativity");
1401 if(sm->cache.max_size) fprintf(f, " Max. Size: %u kB\n", sm->cache.max_size);
1402 if(sm->cache.current_size) fprintf(f, " Current Size: %u kB\n", sm->cache.current_size);
1403 if(sm->cache.speed) fprintf(f, " Speed: %u ns\n", sm->cache.speed);
1404 SMBIOS_PRINT_BITMAP_SHORT(cache.supp_sram, "Supported SRAM Types");
1405 SMBIOS_PRINT_BITMAP_SHORT(cache.sram, "Current SRAM Type");
1406 break;
1407
1408 case sm_connect:
1409 fprintf(f, " Port Connector: #%d\n", sm->any.handle);
1410 SMBIOS_PRINT_ID(connect.port_type, "Type");
1411 SMBIOS_PRINT_STR(connect.i_des, "Internal Designator");
1412 SMBIOS_PRINT_ID(connect.i_type, "Internal Connector");
1413 SMBIOS_PRINT_STR(connect.x_des, "External Designator");
1414 SMBIOS_PRINT_ID(connect.x_type, "External Connector");
1415 break;
1416
1417 case sm_slot:
1418 fprintf(f, " System Slot: #%d\n", sm->any.handle);
1419 SMBIOS_PRINT_STR(slot.desig, "Designation");
1420 SMBIOS_PRINT_ID(slot.slot_type, "Type");
1421 SMBIOS_PRINT_ID(slot.bus_width, "Bus Width");
1422 SMBIOS_PRINT_ID(slot.usage, "Status");
1423 SMBIOS_PRINT_ID(slot.length, "Length");
1424 fprintf(f, " Slot ID: %u\n", sm->slot.id);
1425 SMBIOS_PRINT_BITMAP_SHORT(slot.feature, "Characteristics");
1426 break;
1427
1428 case sm_onboard:
1429 fprintf(f, " On Board Devices: #%d\n", sm->any.handle);
1430 for(u = 0; u < sm->onboard.dev_len; u++) {
1431 fprintf(f, " %s: \"%s\"%s\n",
1432 sm->onboard.dev[u].type.name,
1433 sm->onboard.dev[u].name,
1434 sm->onboard.dev[u].status ? "" : " (disabled)"
1435 );
1436 }
1437 break;
1438
1439 case sm_oem:
1440 fprintf(f, " OEM Strings: #%d\n", sm->any.handle);
1441 for(sl = sm->oem.oem_strings; sl; sl = sl->next) {
1442 fprintf(f, " %s\n", sl->str);
1443 }
1444 break;
1445
1446 case sm_config:
1447 fprintf(f, " System Config Options (Jumpers & Switches) #%d:\n", sm->any.handle);
1448 for(sl = sm->config.options; sl; sl = sl->next) {
1449 fprintf(f, " %s\n", sl->str);
1450 }
1451 break;
1452
1453 case sm_lang:
1454 fprintf(f, " Language Info: #%d\n", sm->any.handle);
1455 if((sl = sm->lang.strings)) {
1456 fprintf(f, " Languages: ");
1457 for(; sl; sl = sl->next) {
1458 fprintf(f, "%s%s", sl->str, sl->next ? ", " : "");
1459 }
1460 fprintf(f, "\n");
1461 }
1462 if(sm->lang.current) fprintf(f, " Current: %s\n", sm->lang.current);
1463 break;
1464
1465 case sm_group:
1466 fprintf(f, " Group Associations: #%d\n", sm->any.handle);
1467 if(sm->group.name) fprintf(f, " Group Name: \"%s\"\n", sm->group.name);
1468 if(sm->group.items_len) {
1469 fprintf(f, " Items: ");
1470 for(i = 0; i < sm->group.items_len; i++) {
1471 fprintf(f, "%s#%d", i ? ", " : "", sm->group.item_handles[i]);
1472 }
1473 fprintf(f, "\n");
1474 }
1475 break;
1476
1477 case sm_memarray:
1478 fprintf(f, " Physical Memory Array: #%d\n", sm->any.handle);
1479 SMBIOS_PRINT_ID(memarray.use, "Use");
1480 SMBIOS_PRINT_ID(memarray.location, "Location");
1481 fprintf(f, " Slots: %u\n", sm->memarray.slots);
1482 if(sm->memarray.max_size) {
1483 u = sm->memarray.max_size;
1484 c = 'k';
1485 if(!(u & 0x3ff)) { u >>= 10; c = 'M'; }
1486 if(!(u & 0x3ff)) { u >>= 10; c = 'G'; }
1487 fprintf(f, " Max. Size: %u %cB\n", u, c);
1488 }
1489 SMBIOS_PRINT_ID(memarray.ecc, "ECC");
1490 if(sm->memarray.error_handle != 0xfffe) {
1491 fprintf(f, " Error Info: ");
1492 if(sm->memarray.error_handle != 0xffff) {
1493 fprintf(f, "#%d\n", sm->memarray.error_handle);
1494 }
1495 else {
1496 fprintf(f, "No Error\n");
1497 }
1498 }
1499 break;
1500
1501 case sm_memdevice:
1502 fprintf(f, " Memory Device: #%d\n", sm->any.handle);
1503 SMBIOS_PRINT_STR(memdevice.location, "Location");
1504 SMBIOS_PRINT_STR(memdevice.bank, "Bank");
1505 SMBIOS_PRINT_STR(memdevice.manuf, "Manufacturer");
1506 SMBIOS_PRINT_STR(memdevice.serial, "Serial");
1507 SMBIOS_PRINT_STR(memdevice.asset, "Asset Tag");
1508 SMBIOS_PRINT_STR(memdevice.part, "Part Number");
1509 fprintf(f, " Memory Array: #%d\n", sm->memdevice.array_handle);
1510 if(sm->memdevice.error_handle != 0xfffe) {
1511 fprintf(f, " Error Info: ");
1512 if(sm->memdevice.error_handle != 0xffff) {
1513 fprintf(f, "#%d\n", sm->memdevice.error_handle);
1514 }
1515 else {
1516 fprintf(f, "No Error\n");
1517 }
1518 }
1519 SMBIOS_PRINT_ID(memdevice.form, "Form Factor");
1520 SMBIOS_PRINT_ID(memdevice.mem_type, "Type");
1521 SMBIOS_PRINT_BITMAP_SHORT(memdevice.type_detail, "Type Detail");
1522 fprintf(f, " Data Width: %u bits", sm->memdevice.width);
1523 if(sm->memdevice.eccbits) fprintf(f, " (+%u ECC bits)", sm->memdevice.eccbits);
1524 fprintf(f, "\n");
1525 if(sm->memdevice.size) {
1526 u = sm->memdevice.size;
1527 c = 'k';
1528 if(!(u & 0x3ff)) { u >>= 10; c = 'M'; }
1529 if(!(u & 0x3ff)) { u >>= 10; c = 'G'; }
1530 fprintf(f, " Size: %u %cB\n", u, c);
1531 }
1532 else {
1533 fprintf(f, " Size: No Memory Installed\n");
1534 }
1535 if(sm->memdevice.speed) fprintf(f, " Speed: %u MHz\n", sm->memdevice.speed);
1536 break;
1537
1538 case sm_memerror:
1539 fprintf(f, " 32bit-Memory Error Info: #%d\n", sm->any.handle);
1540 SMBIOS_PRINT_ID(memerror.err_type, "Type");
1541 SMBIOS_PRINT_ID(memerror.granularity, "Granularity");
1542 SMBIOS_PRINT_ID(memerror.operation, "Operation");
1543 if(sm->memerror.syndrome) fprintf(f, " Syndrome: 0x%08x\n", sm->memerror.syndrome);
1544 if(sm->memerror.array_addr != (1 << 31)) fprintf(f, " Mem Array Addr: 0x%08x\n", sm->memerror.array_addr);
1545 if(sm->memerror.device_addr != (1 << 31)) fprintf(f, " Mem Device Addr: 0x%08x\n", sm->memerror.device_addr);
1546 if(sm->memerror.range != (1 << 31)) fprintf(f, " Range: 0x%08x\n", sm->memerror.range);
1547 break;
1548
1549 case sm_memarraymap:
1550 fprintf(f, " Memory Array Mapping: #%d\n", sm->any.handle);
1551 fprintf(f, " Memory Array: #%d\n", sm->memarraymap.array_handle);
1552 fprintf(f, " Partition Width: %u\n", sm->memarraymap.part_width);
1553 if((sm->memarraymap.start_addr | sm->memarraymap.end_addr) >> 32) {
1554 fprintf(f, " Start Address: 0x%016"PRIx64"\n", sm->memarraymap.start_addr);
1555 fprintf(f, " End Address: 0x%016"PRIx64"\n", sm->memarraymap.end_addr);
1556 }
1557 else {
1558 fprintf(f, " Start Address: 0x%08x\n", (unsigned) sm->memarraymap.start_addr);
1559 fprintf(f, " End Address: 0x%08x\n", (unsigned) sm->memarraymap.end_addr);
1560 }
1561 break;
1562
1563 case sm_memdevicemap:
1564 fprintf(f, " Memory Device Mapping: #%d\n", sm->any.handle);
1565 fprintf(f, " Memory Device: #%d\n", sm->memdevicemap.memdevice_handle);
1566 fprintf(f, " Array Mapping: #%d\n", sm->memdevicemap.arraymap_handle);
1567 if(sm->memdevicemap.row_pos != 0xff) fprintf(f, " Row: %u\n", sm->memdevicemap.row_pos);
1568 if(
1569 !sm->memdevicemap.interleave_pos ||
1570 sm->memdevicemap.interleave_pos != 0xff
1571 ) {
1572 fprintf(f, " Interleave Pos: %u\n", sm->memdevicemap.interleave_pos);
1573 }
1574 if(
1575 !sm->memdevicemap.interleave_depth ||
1576 sm->memdevicemap.interleave_depth != 0xff
1577 ) {
1578 fprintf(f, " Interleaved Depth: %u\n", sm->memdevicemap.interleave_depth);
1579 }
1580 if((sm->memdevicemap.start_addr | sm->memdevicemap.end_addr) >> 32) {
1581 fprintf(f, " Start Address: 0x%016"PRIx64"\n", sm->memdevicemap.start_addr);
1582 fprintf(f, " End Address: 0x%016"PRIx64"\n", sm->memdevicemap.end_addr);
1583 }
1584 else {
1585 fprintf(f, " Start Address: 0x%08x\n", (unsigned) sm->memdevicemap.start_addr);
1586 fprintf(f, " End Address: 0x%08x\n", (unsigned) sm->memdevicemap.end_addr);
1587 }
1588 break;
1589
1590 case sm_mouse:
1591 fprintf(f, " Pointing Device: #%d\n", sm->any.handle);
1592 SMBIOS_PRINT_ID(mouse.mtype, "Type");
1593 SMBIOS_PRINT_ID(mouse.interface, "Interface");
1594 if(sm->mouse.buttons) fprintf(f, " Buttons: %u\n", sm->mouse.buttons);
1595 break;
1596
1597 case sm_secure:
1598 fprintf(f, " Hardware Security: #%d\n", sm->any.handle);
1599 SMBIOS_PRINT_ID(secure.power, "Power-on Password");
1600 SMBIOS_PRINT_ID(secure.keyboard, "Keyboard Password");
1601 SMBIOS_PRINT_ID(secure.admin, "Admin Password");
1602 SMBIOS_PRINT_ID(secure.reset, "Front Panel Reset");
1603 break;
1604
1605 case sm_power:
1606 fprintf(f, " System Power Controls: #%d\n", sm->any.handle);
1607 fprintf(f,
1608 " Next Power-on: %02x:%02x:%02x %02x/%02x\n",
1609 sm->power.hour, sm->power.minute, sm->power.second,
1610 sm->power.day, sm->power.month
1611 );
1612 break;
1613
1614 case sm_mem64error:
1615 fprintf(f, " 64bit-Memory Error Info: #%d\n", sm->any.handle);
1616 SMBIOS_PRINT_ID(mem64error.err_type, "Type");
1617 SMBIOS_PRINT_ID(mem64error.granularity, "Granularity");
1618 SMBIOS_PRINT_ID(mem64error.operation, "Operation");
1619 if(sm->mem64error.syndrome) fprintf(f, " Syndrome: 0x%08x\n", sm->mem64error.syndrome);
1620 if(
1621 sm->mem64error.array_addr != (1ll << 63) &&
1622 sm->mem64error.array_addr != (1ll << 31)
1623 ) {
1624 fprintf(f, " Mem Array Addr: 0x%016"PRIx64"\n", sm->mem64error.array_addr);
1625 }
1626 if(
1627 sm->mem64error.device_addr != (1ll << 63) &&
1628 sm->mem64error.device_addr != (1ll << 31)
1629 ) {
1630 fprintf(f, " Mem Device Addr: 0x%016"PRIx64"\n", sm->mem64error.device_addr);
1631 }
1632 if(sm->mem64error.range != (1 << 31)) fprintf(f, " Range: 0x%08x\n", sm->mem64error.range);
1633 break;
1634
1635 case sm_end:
1636 break;
1637
1638 default:
1639 if(sm->any.type == sm_inactive) {
1640 fprintf(f, " Inactive Record: #%d\n", sm->any.handle);
1641 }
1642 else {
1643 fprintf(f, " Type %d Record: #%d\n", sm->any.type, sm->any.handle);
1644 }
1645 if(sm->any.data_len) {
1646 for(i = 0; i < sm->any.data_len; i += 0x10) {
1647 u = sm->any.data_len - i;
1648 if(u > 0x10) u = 0x10;
1649 s = NULL;
1650 hexdump(&s, 0, u, sm->any.data + i);
1651 fprintf(f, " Data %02x: %s\n", i, s);
1652 s = free_mem(s);
1653 }
1654 }
1655 for(u = 1, sl = sm->any.strings; sl; sl = sl->next, u++) {
1656 if(sl->str && *sl->str) fprintf(f, " String %u: \"%s\"\n", u, sl->str);
1657 }
1658 break;
1659 }
1660 }
1661}
1662