1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
24 * Copyright (c) 2017, Joyent, Inc.
25 * Copyright 2021 Oxide Computer Company
26 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 #include <sys/sysmacros.h>
31 #include <sys/param.h>
32
33 #include <smbios.h>
34 #include <alloca.h>
35 #include <limits.h>
36 #include <unistd.h>
37 #include <strings.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <ctype.h>
44 #include <libjedec.h>
45
46 #define SMBIOS_SUCCESS 0
47 #define SMBIOS_ERROR 1
48 #define SMBIOS_USAGE 2
49
50 static const char *g_pname;
51 static int g_hdr;
52
53 static int opt_e;
54 static int opt_i = -1;
55 static int opt_O;
56 static int opt_s;
57 static int opt_t = -1;
58 static int opt_x;
59
60 static boolean_t
smbios_vergteq(smbios_version_t * v,uint_t major,uint_t minor)61 smbios_vergteq(smbios_version_t *v, uint_t major, uint_t minor)
62 {
63 if (v->smbv_major > major)
64 return (B_TRUE);
65 if (v->smbv_major == major &&
66 v->smbv_minor >= minor)
67 return (B_TRUE);
68 return (B_FALSE);
69 }
70
71 /*PRINTFLIKE2*/
72 static void
smbios_warn(smbios_hdl_t * shp,const char * format,...)73 smbios_warn(smbios_hdl_t *shp, const char *format, ...)
74 {
75 va_list ap;
76
77 va_start(ap, format);
78 (void) vfprintf(stderr, format, ap);
79 va_end(ap);
80
81 if (shp != NULL) {
82 (void) fprintf(stderr, ": %s",
83 smbios_errmsg(smbios_errno(shp)));
84 }
85
86 (void) fprintf(stderr, "\n");
87 }
88
89 /*PRINTFLIKE2*/
90 static void
oprintf(FILE * fp,const char * format,...)91 oprintf(FILE *fp, const char *format, ...)
92 {
93 va_list ap;
94
95 va_start(ap, format);
96 (void) vfprintf(fp, format, ap);
97 va_end(ap);
98 }
99
100 /*PRINTFLIKE3*/
101 static void
desc_printf(const char * d,FILE * fp,const char * format,...)102 desc_printf(const char *d, FILE *fp, const char *format, ...)
103 {
104 va_list ap;
105
106 va_start(ap, format);
107 (void) vfprintf(fp, format, ap);
108 va_end(ap);
109
110 if (d != NULL)
111 (void) fprintf(fp, " (%s)\n", d);
112 else
113 (void) fprintf(fp, "\n");
114 }
115
116 static void
flag_printf(FILE * fp,const char * s,uint_t flags,size_t bits,const char * (* flag_name)(uint_t),const char * (* flag_desc)(uint_t))117 flag_printf(FILE *fp, const char *s, uint_t flags, size_t bits,
118 const char *(*flag_name)(uint_t), const char *(*flag_desc)(uint_t))
119 {
120 size_t i;
121
122 oprintf(fp, " %s: 0x%x\n", s, flags);
123
124 for (i = 0; i < bits; i++) {
125 uint_t f = 1 << i;
126 const char *n;
127
128 if (!(flags & f))
129 continue;
130
131 if ((n = flag_name(f)) != NULL)
132 desc_printf(flag_desc(f), fp, "\t%s", n);
133 else
134 desc_printf(flag_desc(f), fp, "\t0x%x", f);
135 }
136 }
137
138 static void
flag64_printf(FILE * fp,const char * s,uint64_t flags,size_t bits,const char * (* flag_name)(uint64_t),const char * (* flag_desc)(uint64_t))139 flag64_printf(FILE *fp, const char *s, uint64_t flags, size_t bits,
140 const char *(*flag_name)(uint64_t), const char *(*flag_desc)(uint64_t))
141 {
142 size_t i;
143
144 oprintf(fp, " %s: 0x%llx\n", s, (u_longlong_t)flags);
145
146 for (i = 0; i < bits; i++) {
147 u_longlong_t f = 1ULL << i;
148 const char *n;
149
150 if (!(flags & f))
151 continue;
152
153 if ((n = flag_name(f)) != NULL)
154 desc_printf(flag_desc(f), fp, "\t%s", n);
155 else
156 desc_printf(flag_desc(f), fp, "\t0x%llx", f);
157 }
158 }
159
160 static void
id_printf(FILE * fp,const char * s,id_t id)161 id_printf(FILE *fp, const char *s, id_t id)
162 {
163 switch (id) {
164 case SMB_ID_NONE:
165 oprintf(fp, "%sNone\n", s);
166 break;
167 case SMB_ID_NOTSUP:
168 oprintf(fp, "%sNot Supported\n", s);
169 break;
170 default:
171 oprintf(fp, "%s%u\n", s, (uint_t)id);
172 }
173 }
174
175 static void
jedec_print(FILE * fp,const char * desc,uint_t id)176 jedec_print(FILE *fp, const char *desc, uint_t id)
177 {
178 const char *name;
179 uint_t cont, vendor;
180
181 /*
182 * SMBIOS encodes data in the way that the underlying memory standard
183 * does. In this case, the upper byte indicates the vendor that we care
184 * about while the lower byte indicates the number of continuations that
185 * are needed. libjedec indexes this based on zero (e.g. table 1 is zero
186 * continuations), which is how the spec encodes it. We add one so that
187 * we can match how the spec describes it.
188 */
189 vendor = id >> 8;
190 cont = id & 0x7f;
191 name = libjedec_vendor_string(cont, vendor);
192 if (name == NULL) {
193 oprintf(fp, " %s: Bank: 0x%x Vendor: 0x%x\n", desc, cont + 1,
194 vendor);
195 } else {
196 oprintf(fp, " %s: Bank: 0x%x Vendor: 0x%x (%s)\n", desc,
197 cont + 1, vendor, name);
198 }
199 }
200
201 /*
202 * Print a 128-bit data as a series of 16 hex digits.
203 */
204 static void
u128_print(FILE * fp,const char * desc,const uint8_t * data)205 u128_print(FILE *fp, const char *desc, const uint8_t *data)
206 {
207 uint_t i;
208
209 oprintf(fp, "%s: ", desc);
210 for (i = 0; i < 16; i++) {
211 oprintf(fp, " %02x", data[i]);
212 }
213 oprintf(fp, "\n");
214 }
215
216 /*
217 * Print a string that came from an SMBIOS table. We do this character by
218 * character so we can potentially escape strings.
219 */
220 static void
str_print_label(FILE * fp,const char * header,const char * str,boolean_t label)221 str_print_label(FILE *fp, const char *header, const char *str, boolean_t label)
222 {
223 const char *c;
224
225 oprintf(fp, header);
226 if (label) {
227 oprintf(fp, ": ");
228 }
229
230 for (c = str; *c != '\0'; c++) {
231 if (isprint(*c)) {
232 oprintf(fp, "%c", *c);
233 } else {
234 oprintf(fp, "\\x%02x", *c);
235 }
236 }
237
238 oprintf(fp, "\n");
239 }
240
241 static void
str_print_nolabel(FILE * fp,const char * ws,const char * str)242 str_print_nolabel(FILE *fp, const char *ws, const char *str)
243 {
244 return (str_print_label(fp, ws, str, B_FALSE));
245 }
246
247 static void
str_print(FILE * fp,const char * header,const char * str)248 str_print(FILE *fp, const char *header, const char *str)
249 {
250 return (str_print_label(fp, header, str, B_TRUE));
251 }
252
253 static int
check_oem(smbios_hdl_t * shp)254 check_oem(smbios_hdl_t *shp)
255 {
256 int i;
257 int cnt;
258 int rv;
259 id_t oem_id;
260 smbios_struct_t s;
261 const char **oem_str;
262
263 rv = smbios_lookup_type(shp, SMB_TYPE_OEMSTR, &s);
264 if (rv != 0) {
265 return (-1);
266 }
267
268 oem_id = s.smbstr_id;
269
270 cnt = smbios_info_strtab(shp, oem_id, 0, NULL);
271 if (cnt > 0) {
272 oem_str = alloca(sizeof (char *) * cnt);
273 (void) smbios_info_strtab(shp, oem_id, cnt, oem_str);
274
275 for (i = 0; i < cnt; i++) {
276 if (strncmp(oem_str[i], SMB_PRMS1,
277 strlen(SMB_PRMS1) + 1) == 0) {
278 return (0);
279 }
280 }
281 }
282
283 return (-1);
284 }
285
286 static void
print_smbios_21(smbios_21_entry_t * ep,FILE * fp)287 print_smbios_21(smbios_21_entry_t *ep, FILE *fp)
288 {
289 int i;
290
291 oprintf(fp, "Entry Point Anchor Tag: %*.*s\n",
292 (int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor),
293 ep->smbe_eanchor);
294
295 oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum);
296 oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen);
297 oprintf(fp, "Entry Point Version: %u.%u\n",
298 ep->smbe_major, ep->smbe_minor);
299 oprintf(fp, "Max Structure Size: %u\n", ep->smbe_maxssize);
300 oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision);
301
302 oprintf(fp, "Entry Point Revision Data:");
303 for (i = 0; i < sizeof (ep->smbe_format); i++)
304 oprintf(fp, " 0x%02x", ep->smbe_format[i]);
305 oprintf(fp, "\n");
306
307 oprintf(fp, "Intermediate Anchor Tag: %*.*s\n",
308 (int)sizeof (ep->smbe_ianchor), (int)sizeof (ep->smbe_ianchor),
309 ep->smbe_ianchor);
310
311 oprintf(fp, "Intermediate Checksum: 0x%x\n", ep->smbe_icksum);
312 oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen);
313 oprintf(fp, "Structure Table Address: 0x%x\n", ep->smbe_staddr);
314 oprintf(fp, "Structure Table Entries: %u\n", ep->smbe_stnum);
315 oprintf(fp, "DMI BCD Revision: 0x%x\n", ep->smbe_bcdrev);
316 }
317
318 static void
print_smbios_30(smbios_30_entry_t * ep,FILE * fp)319 print_smbios_30(smbios_30_entry_t *ep, FILE *fp)
320 {
321 oprintf(fp, "Entry Point Anchor Tag: %*.*s\n",
322 (int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor),
323 ep->smbe_eanchor);
324
325 oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum);
326 oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen);
327 oprintf(fp, "SMBIOS Version: %u.%u\n",
328 ep->smbe_major, ep->smbe_minor);
329 oprintf(fp, "SMBIOS DocRev: 0x%x\n", ep->smbe_docrev);
330 oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision);
331
332 oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen);
333 oprintf(fp, "Structure Table Address: 0x%" PRIx64 "\n",
334 ep->smbe_staddr);
335 }
336
337 static void
print_smbios(smbios_hdl_t * shp,FILE * fp)338 print_smbios(smbios_hdl_t *shp, FILE *fp)
339 {
340 smbios_entry_t ep;
341
342 switch (smbios_info_smbios(shp, &ep)) {
343 case SMBIOS_ENTRY_POINT_21:
344 print_smbios_21(&ep.ep21, fp);
345 break;
346 case SMBIOS_ENTRY_POINT_30:
347 print_smbios_30(&ep.ep30, fp);
348 break;
349 }
350 }
351
352 static void
print_common(const smbios_info_t * ip,FILE * fp)353 print_common(const smbios_info_t *ip, FILE *fp)
354 {
355 if (ip->smbi_manufacturer[0] != '\0')
356 str_print(fp, " Manufacturer", ip->smbi_manufacturer);
357 if (ip->smbi_product[0] != '\0')
358 str_print(fp, " Product", ip->smbi_product);
359 if (ip->smbi_version[0] != '\0')
360 str_print(fp, " Version", ip->smbi_version);
361 if (ip->smbi_serial[0] != '\0')
362 str_print(fp, " Serial Number", ip->smbi_serial);
363 if (ip->smbi_asset[0] != '\0')
364 str_print(fp, " Asset Tag", ip->smbi_asset);
365 if (ip->smbi_location[0] != '\0')
366 str_print(fp, " Location Tag", ip->smbi_location);
367 if (ip->smbi_part[0] != '\0')
368 str_print(fp, " Part Number", ip->smbi_part);
369 }
370
371 static void
print_bios(smbios_hdl_t * shp,FILE * fp)372 print_bios(smbios_hdl_t *shp, FILE *fp)
373 {
374 smbios_bios_t b;
375
376 (void) smbios_info_bios(shp, &b);
377
378 str_print(fp, " Vendor", b.smbb_vendor);
379 str_print(fp, " Version String", b.smbb_version);
380 str_print(fp, " Release Date", b.smbb_reldate);
381 oprintf(fp, " Address Segment: 0x%x\n", b.smbb_segment);
382 oprintf(fp, " ROM Size: %" PRIu64 " bytes\n", b.smbb_extromsize);
383 oprintf(fp, " Image Size: %u bytes\n", b.smbb_runsize);
384
385 flag64_printf(fp, "Characteristics",
386 b.smbb_cflags, sizeof (b.smbb_cflags) * NBBY,
387 smbios_bios_flag_name, smbios_bios_flag_desc);
388
389 if (b.smbb_nxcflags > SMB_BIOSXB_1) {
390 flag_printf(fp, "Characteristics Extension Byte 1",
391 b.smbb_xcflags[SMB_BIOSXB_1],
392 sizeof (b.smbb_xcflags[SMB_BIOSXB_1]) * NBBY,
393 smbios_bios_xb1_name, smbios_bios_xb1_desc);
394 }
395
396 if (b.smbb_nxcflags > SMB_BIOSXB_2) {
397 flag_printf(fp, "Characteristics Extension Byte 2",
398 b.smbb_xcflags[SMB_BIOSXB_2],
399 sizeof (b.smbb_xcflags[SMB_BIOSXB_2]) * NBBY,
400 smbios_bios_xb2_name, smbios_bios_xb2_desc);
401 }
402
403 if (b.smbb_nxcflags > SMB_BIOSXB_BIOS_MIN) {
404 oprintf(fp, " Version Number: %u.%u\n",
405 b.smbb_biosv.smbv_major, b.smbb_biosv.smbv_minor);
406 }
407
408 /*
409 * If the major and minor versions are 0xff then that indicates that the
410 * embedded controller does not exist.
411 */
412 if (b.smbb_nxcflags > SMB_BIOSXB_ECFW_MIN &&
413 b.smbb_ecfwv.smbv_major != 0xff &&
414 b.smbb_ecfwv.smbv_minor != 0xff) {
415 oprintf(fp, " Embedded Ctlr Firmware Version Number: %u.%u\n",
416 b.smbb_ecfwv.smbv_major, b.smbb_ecfwv.smbv_minor);
417 }
418 }
419
420 static void
print_system(smbios_hdl_t * shp,FILE * fp)421 print_system(smbios_hdl_t *shp, FILE *fp)
422 {
423 smbios_system_t s;
424 uint_t i;
425
426 (void) smbios_info_system(shp, &s);
427
428 oprintf(fp, " UUID: ");
429 for (i = 0; i < s.smbs_uuidlen; i++) {
430 oprintf(fp, "%02x", s.smbs_uuid[i]);
431 if (i == 3 || i == 5 || i == 7 || i == 9)
432 oprintf(fp, "-");
433 }
434 oprintf(fp, "\n");
435
436 desc_printf(smbios_system_wakeup_desc(s.smbs_wakeup),
437 fp, " Wake-Up Event: 0x%x", s.smbs_wakeup);
438
439 str_print(fp, " SKU Number", s.smbs_sku);
440 str_print(fp, " Family", s.smbs_family);
441 }
442
443 static void
print_bboard(smbios_hdl_t * shp,id_t id,FILE * fp)444 print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp)
445 {
446 smbios_bboard_t b;
447 int chdl_cnt;
448
449 (void) smbios_info_bboard(shp, id, &b);
450
451 oprintf(fp, " Chassis: %u\n", (uint_t)b.smbb_chassis);
452
453 flag_printf(fp, "Flags", b.smbb_flags, sizeof (b.smbb_flags) * NBBY,
454 smbios_bboard_flag_name, smbios_bboard_flag_desc);
455
456 desc_printf(smbios_bboard_type_desc(b.smbb_type),
457 fp, " Board Type: 0x%x", b.smbb_type);
458
459 chdl_cnt = b.smbb_contn;
460 if (chdl_cnt != 0) {
461 id_t *chdl;
462 uint16_t hdl;
463 int i, n, cnt;
464
465 chdl = alloca(chdl_cnt * sizeof (id_t));
466 cnt = smbios_info_contains(shp, id, chdl_cnt, chdl);
467 if (cnt > SMB_CONT_MAX)
468 return;
469 n = MIN(chdl_cnt, cnt);
470
471 oprintf(fp, "\n");
472 for (i = 0; i < n; i++) {
473 hdl = (uint16_t)chdl[i];
474 oprintf(fp, " Contained Handle: %u\n", hdl);
475 }
476 }
477 }
478
479 static void
print_chassis(smbios_hdl_t * shp,id_t id,FILE * fp)480 print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp)
481 {
482 smbios_chassis_t c;
483 smbios_chassis_entry_t *elts;
484 uint_t nelts, i;
485
486 (void) smbios_info_chassis(shp, id, &c);
487
488 oprintf(fp, " OEM Data: 0x%x\n", c.smbc_oemdata);
489 str_print(fp, " SKU Number",
490 c.smbc_sku[0] == '\0' ? "<unknown>" : c.smbc_sku);
491 oprintf(fp, " Lock Present: %s\n", c.smbc_lock ? "Y" : "N");
492
493 desc_printf(smbios_chassis_type_desc(c.smbc_type),
494 fp, " Chassis Type: 0x%x", c.smbc_type);
495
496 desc_printf(smbios_chassis_state_desc(c.smbc_bustate),
497 fp, " Boot-Up State: 0x%x", c.smbc_bustate);
498
499 desc_printf(smbios_chassis_state_desc(c.smbc_psstate),
500 fp, " Power Supply State: 0x%x", c.smbc_psstate);
501
502 desc_printf(smbios_chassis_state_desc(c.smbc_thstate),
503 fp, " Thermal State: 0x%x", c.smbc_thstate);
504
505 oprintf(fp, " Chassis Height: %uu\n", c.smbc_uheight);
506 oprintf(fp, " Power Cords: %u\n", c.smbc_cords);
507
508 oprintf(fp, " Element Records: %u\n", c.smbc_elems);
509
510 if (c.smbc_elems == 0) {
511 return;
512 }
513
514 if (smbios_info_chassis_elts(shp, id, &nelts, &elts) != 0) {
515 smbios_warn(shp, "failed to read chassis elements");
516 return;
517 }
518
519 oprintf(fp, "\n");
520
521 for (i = 0; i < nelts; i++) {
522 switch (elts[i].smbce_type) {
523 case SMB_CELT_BBOARD:
524 desc_printf(smbios_bboard_type_desc(elts[i].smbce_elt),
525 fp, " Contained SMBIOS Base Board Type: 0x%x",
526 elts[i].smbce_elt);
527 break;
528 case SMB_CELT_SMBIOS:
529 desc_printf(smbios_type_name(elts[i].smbce_elt), fp,
530 " Contained SMBIOS structure Type: %u",
531 elts[i].smbce_elt);
532 break;
533 default:
534 oprintf(fp, " Unknown contained Type: %u/%u\n",
535 elts[i].smbce_type, elts[i].smbce_elt);
536 break;
537 }
538 oprintf(fp, " Minimum number: %u\n", elts[i].smbce_min);
539 oprintf(fp, " Maximum number: %u\n", elts[i].smbce_max);
540 }
541 }
542
543 static void
print_processor(smbios_hdl_t * shp,id_t id,FILE * fp)544 print_processor(smbios_hdl_t *shp, id_t id, FILE *fp)
545 {
546 smbios_processor_t p;
547 uint_t status;
548
549 (void) smbios_info_processor(shp, id, &p);
550 status = SMB_PRSTATUS_STATUS(p.smbp_status);
551
552 desc_printf(smbios_processor_family_desc(p.smbp_family),
553 fp, " Family: %u", p.smbp_family);
554
555 oprintf(fp, " CPUID: 0x%llx\n", (u_longlong_t)p.smbp_cpuid);
556
557 desc_printf(smbios_processor_type_desc(p.smbp_type),
558 fp, " Type: %u", p.smbp_type);
559
560 desc_printf(smbios_processor_upgrade_desc(p.smbp_upgrade),
561 fp, " Socket Upgrade: %u", p.smbp_upgrade);
562
563 oprintf(fp, " Socket Status: %s\n",
564 SMB_PRSTATUS_PRESENT(p.smbp_status) ?
565 "Populated" : "Not Populated");
566
567 desc_printf(smbios_processor_status_desc(status),
568 fp, " Processor Status: %u", status);
569
570 if (SMB_PRV_LEGACY(p.smbp_voltage)) {
571 oprintf(fp, " Supported Voltages:");
572 switch (p.smbp_voltage) {
573 case SMB_PRV_5V:
574 oprintf(fp, " 5.0V");
575 break;
576 case SMB_PRV_33V:
577 oprintf(fp, " 3.3V");
578 break;
579 case SMB_PRV_29V:
580 oprintf(fp, " 2.9V");
581 break;
582 }
583 oprintf(fp, "\n");
584 } else {
585 oprintf(fp, " Supported Voltages: %.1fV\n",
586 (float)SMB_PRV_VOLTAGE(p.smbp_voltage) / 10);
587 }
588
589 if (p.smbp_corecount != 0) {
590 oprintf(fp, " Core Count: %u\n", p.smbp_corecount);
591 } else {
592 oprintf(fp, " Core Count: Unknown\n");
593 }
594
595 if (p.smbp_coresenabled != 0) {
596 oprintf(fp, " Cores Enabled: %u\n", p.smbp_coresenabled);
597 } else {
598 oprintf(fp, " Cores Enabled: Unknown\n");
599 }
600
601 if (p.smbp_threadcount != 0) {
602 oprintf(fp, " Thread Count: %u\n", p.smbp_threadcount);
603 } else {
604 oprintf(fp, " Thread Count: Unknown\n");
605 }
606
607 if (p.smbp_cflags) {
608 flag_printf(fp, "Processor Characteristics",
609 p.smbp_cflags, sizeof (p.smbp_cflags) * NBBY,
610 smbios_processor_core_flag_name,
611 smbios_processor_core_flag_desc);
612 }
613
614 if (p.smbp_clkspeed != 0)
615 oprintf(fp, " External Clock Speed: %uMHz\n", p.smbp_clkspeed);
616 else
617 oprintf(fp, " External Clock Speed: Unknown\n");
618
619 if (p.smbp_maxspeed != 0)
620 oprintf(fp, " Maximum Speed: %uMHz\n", p.smbp_maxspeed);
621 else
622 oprintf(fp, " Maximum Speed: Unknown\n");
623
624 if (p.smbp_curspeed != 0)
625 oprintf(fp, " Current Speed: %uMHz\n", p.smbp_curspeed);
626 else
627 oprintf(fp, " Current Speed: Unknown\n");
628
629 id_printf(fp, " L1 Cache Handle: ", p.smbp_l1cache);
630 id_printf(fp, " L2 Cache Handle: ", p.smbp_l2cache);
631 id_printf(fp, " L3 Cache Handle: ", p.smbp_l3cache);
632 }
633
634 static void
print_cache(smbios_hdl_t * shp,id_t id,FILE * fp)635 print_cache(smbios_hdl_t *shp, id_t id, FILE *fp)
636 {
637 smbios_cache_t c;
638
639 (void) smbios_info_cache(shp, id, &c);
640
641 oprintf(fp, " Level: %u\n", c.smba_level);
642 oprintf(fp, " Maximum Installed Size: %" PRIu64 " bytes\n",
643 c.smba_maxsize2);
644
645 if (c.smba_size2 != 0) {
646 oprintf(fp, " Installed Size: %" PRIu64 " bytes\n",
647 c.smba_size2);
648 } else {
649 oprintf(fp, " Installed Size: Not Installed\n");
650 }
651
652 if (c.smba_speed != 0)
653 oprintf(fp, " Speed: %uns\n", c.smba_speed);
654 else
655 oprintf(fp, " Speed: Unknown\n");
656
657 flag_printf(fp, "Supported SRAM Types",
658 c.smba_stype, sizeof (c.smba_stype) * NBBY,
659 smbios_cache_ctype_name, smbios_cache_ctype_desc);
660
661 desc_printf(smbios_cache_ctype_desc(c.smba_ctype),
662 fp, " Current SRAM Type: 0x%x", c.smba_ctype);
663
664 desc_printf(smbios_cache_ecc_desc(c.smba_etype),
665 fp, " Error Correction Type: %u", c.smba_etype);
666
667 desc_printf(smbios_cache_logical_desc(c.smba_ltype),
668 fp, " Logical Cache Type: %u", c.smba_ltype);
669
670 desc_printf(smbios_cache_assoc_desc(c.smba_assoc),
671 fp, " Associativity: %u", c.smba_assoc);
672
673 desc_printf(smbios_cache_mode_desc(c.smba_mode),
674 fp, " Mode: %u", c.smba_mode);
675
676 desc_printf(smbios_cache_loc_desc(c.smba_location),
677 fp, " Location: %u", c.smba_location);
678
679 flag_printf(fp, "Flags", c.smba_flags, sizeof (c.smba_flags) * NBBY,
680 smbios_cache_flag_name, smbios_cache_flag_desc);
681 }
682
683 static void
print_port(smbios_hdl_t * shp,id_t id,FILE * fp)684 print_port(smbios_hdl_t *shp, id_t id, FILE *fp)
685 {
686 smbios_port_t p;
687
688 (void) smbios_info_port(shp, id, &p);
689
690 str_print(fp, " Internal Reference Designator", p.smbo_iref);
691 str_print(fp, " External Reference Designator", p.smbo_eref);
692
693 desc_printf(smbios_port_conn_desc(p.smbo_itype),
694 fp, " Internal Connector Type: %u", p.smbo_itype);
695
696 desc_printf(smbios_port_conn_desc(p.smbo_etype),
697 fp, " External Connector Type: %u", p.smbo_etype);
698
699 desc_printf(smbios_port_type_desc(p.smbo_ptype),
700 fp, " Port Type: %u", p.smbo_ptype);
701 }
702
703 static void
print_slot(smbios_hdl_t * shp,id_t id,FILE * fp)704 print_slot(smbios_hdl_t *shp, id_t id, FILE *fp)
705 {
706 smbios_slot_t s;
707 smbios_version_t v;
708
709 (void) smbios_info_slot(shp, id, &s);
710 smbios_info_smbios_version(shp, &v);
711
712 str_print(fp, " Reference Designator", s.smbl_name);
713 oprintf(fp, " Slot ID: 0x%x\n", s.smbl_id);
714
715 desc_printf(smbios_slot_type_desc(s.smbl_type),
716 fp, " Type: 0x%x", s.smbl_type);
717
718 desc_printf(smbios_slot_width_desc(s.smbl_width),
719 fp, " Width: 0x%x", s.smbl_width);
720
721 desc_printf(smbios_slot_usage_desc(s.smbl_usage),
722 fp, " Usage: 0x%x", s.smbl_usage);
723
724 desc_printf(smbios_slot_length_desc(s.smbl_length),
725 fp, " Length: 0x%x", s.smbl_length);
726
727 flag_printf(fp, "Slot Characteristics 1",
728 s.smbl_ch1, sizeof (s.smbl_ch1) * NBBY,
729 smbios_slot_ch1_name, smbios_slot_ch1_desc);
730
731 flag_printf(fp, "Slot Characteristics 2",
732 s.smbl_ch2, sizeof (s.smbl_ch2) * NBBY,
733 smbios_slot_ch2_name, smbios_slot_ch2_desc);
734
735 if (check_oem(shp) != 0 && !smbios_vergteq(&v, 2, 6))
736 return;
737
738 oprintf(fp, " Segment Group: %u\n", s.smbl_sg);
739 oprintf(fp, " Bus Number: %u\n", s.smbl_bus);
740 oprintf(fp, " Device/Function Number: %u/%u\n", s.smbl_df >> 3,
741 s.smbl_df & 0x7);
742
743 if (s.smbl_dbw != 0) {
744 oprintf(fp, " Data Bus Width: %d\n", s.smbl_dbw);
745 }
746
747 if (s.smbl_npeers > 0) {
748 smbios_slot_peer_t *peer;
749 uint_t i, npeers;
750
751 if (smbios_info_slot_peers(shp, id, &npeers, &peer) != 0) {
752 smbios_warn(shp, "failed to read slot peer "
753 "information");
754 return;
755 }
756
757 for (i = 0; i < npeers; i++) {
758 oprintf(fp, " Slot Peer %u:\n", i);
759 oprintf(fp, " Segment group: %u\n",
760 peer[i].smblp_group);
761 oprintf(fp, " Bus/Device/Function: %u/%u/%u\n",
762 peer[i].smblp_bus, peer[i].smblp_device,
763 peer[i].smblp_function);
764 oprintf(fp, " Electrical width: %u\n",
765 peer[i].smblp_data_width);
766 }
767
768 smbios_info_slot_peers_free(shp, npeers, peer);
769 }
770
771 if (s.smbl_info != 0) {
772 if (s.smbl_type >= SMB_SLT_PCIE &&
773 s.smbl_type <= SMB_SLT_PCIEG6P) {
774 oprintf(fp, " PCIe Generation: %d\n", s.smbl_info);
775 } else {
776 oprintf(fp, " Slot Type: 0x%x\n", s.smbl_info);
777 }
778 }
779
780 if (s.smbl_pwidth != 0) {
781 desc_printf(smbios_slot_width_desc(s.smbl_pwidth),
782 fp, " Physical Width: 0x%x", s.smbl_pwidth);
783 }
784
785 if (s.smbl_pitch != 0) {
786 oprintf(fp, " Slot Pitch: %u.%u mm\n", s.smbl_pitch / 100,
787 s.smbl_pitch % 100);
788 }
789
790 /*
791 * The slot height was introduced in SMBIOS 3.5. However, a value of
792 * zero here does not mean that it is unknown, but rather that the
793 * concept is not applicable. Therefore we cannot use a standard check
794 * against zero for this and instead use the version.
795 */
796 if (smbios_vergteq(&v, 3, 5)) {
797 desc_printf(smbios_slot_height_desc(s.smbl_height), fp,
798 " Height: 0x%x", s.smbl_height);
799 } else {
800 oprintf(fp, " Height: unknown\n");
801 }
802 }
803
804 static void
print_obdevs_ext(smbios_hdl_t * shp,id_t id,FILE * fp)805 print_obdevs_ext(smbios_hdl_t *shp, id_t id, FILE *fp)
806 {
807 boolean_t enabled;
808 smbios_obdev_ext_t oe;
809 const char *type;
810
811 (void) smbios_info_obdevs_ext(shp, id, &oe);
812
813 /*
814 * Bit 7 is always whether or not the device is enabled while bits 0:6
815 * are the actual device type.
816 */
817 enabled = oe.smboe_dtype >> 7;
818 type = smbios_onboard_ext_type_desc(oe.smboe_dtype & 0x7f);
819
820 str_print(fp, " Reference Designator", oe.smboe_name);
821 oprintf(fp, " Device Enabled: %s\n", enabled == B_TRUE ? "true" :
822 "false");
823 oprintf(fp, " Device Type: %s\n", type);
824 oprintf(fp, " Device Type Instance: %u\n", oe.smboe_dti);
825 oprintf(fp, " Segment Group Number: %u\n", oe.smboe_sg);
826 oprintf(fp, " Bus Number: %u\n", oe.smboe_bus);
827 oprintf(fp, " Device/Function Number: %u\n", oe.smboe_df);
828 }
829
830 static void
print_obdevs(smbios_hdl_t * shp,id_t id,FILE * fp)831 print_obdevs(smbios_hdl_t *shp, id_t id, FILE *fp)
832 {
833 smbios_obdev_t *argv;
834 int i, argc;
835
836 if ((argc = smbios_info_obdevs(shp, id, 0, NULL)) > 0) {
837 argv = alloca(sizeof (smbios_obdev_t) * argc);
838 (void) smbios_info_obdevs(shp, id, argc, argv);
839 for (i = 0; i < argc; i++)
840 str_print_nolabel(fp, " ", argv[i].smbd_name);
841 }
842 }
843
844 static void
print_strtab(smbios_hdl_t * shp,id_t id,FILE * fp)845 print_strtab(smbios_hdl_t *shp, id_t id, FILE *fp)
846 {
847 const char **argv;
848 int i, argc;
849
850 if ((argc = smbios_info_strtab(shp, id, 0, NULL)) > 0) {
851 argv = alloca(sizeof (char *) * argc);
852 (void) smbios_info_strtab(shp, id, argc, argv);
853 for (i = 0; i < argc; i++)
854 str_print_nolabel(fp, " ", argv[i]);
855 }
856 }
857
858 static void
print_lang(smbios_hdl_t * shp,id_t id,FILE * fp)859 print_lang(smbios_hdl_t *shp, id_t id, FILE *fp)
860 {
861 smbios_lang_t l;
862
863 (void) smbios_info_lang(shp, &l);
864
865 str_print(fp, " Current Language", l.smbla_cur);
866 oprintf(fp, " Language String Format: %u\n", l.smbla_fmt);
867 oprintf(fp, " Number of Installed Languages: %u\n", l.smbla_num);
868 oprintf(fp, " Installed Languages:\n");
869
870 print_strtab(shp, id, fp);
871 }
872
873 /*ARGSUSED*/
874 static void
print_evlog(smbios_hdl_t * shp,id_t id,FILE * fp)875 print_evlog(smbios_hdl_t *shp, id_t id, FILE *fp)
876 {
877 smbios_evlog_t ev;
878 uint32_t i;
879
880 (void) smbios_info_eventlog(shp, &ev);
881
882 oprintf(fp, " Log Area Size: %lu bytes\n", (ulong_t)ev.smbev_size);
883 oprintf(fp, " Header Offset: %lu\n", (ulong_t)ev.smbev_hdr);
884 oprintf(fp, " Data Offset: %lu\n", (ulong_t)ev.smbev_data);
885
886 desc_printf(smbios_evlog_method_desc(ev.smbev_method),
887 fp, " Data Access Method: %u", ev.smbev_method);
888
889 flag_printf(fp, "Log Flags",
890 ev.smbev_flags, sizeof (ev.smbev_flags) * NBBY,
891 smbios_evlog_flag_name, smbios_evlog_flag_desc);
892
893 desc_printf(smbios_evlog_format_desc(ev.smbev_format),
894 fp, " Log Header Format: %u", ev.smbev_format);
895
896 oprintf(fp, " Update Token: 0x%x\n", ev.smbev_token);
897 oprintf(fp, " Data Access Address: ");
898
899 switch (ev.smbev_method) {
900 case SMB_EVM_1x1i_1x1d:
901 case SMB_EVM_2x1i_1x1d:
902 case SMB_EVM_1x2i_1x1d:
903 oprintf(fp, "Index Address 0x%x, Data Address 0x%x\n",
904 ev.smbev_addr.eva_io.evi_iaddr,
905 ev.smbev_addr.eva_io.evi_daddr);
906 break;
907 case SMB_EVM_GPNV:
908 oprintf(fp, "0x%x\n", ev.smbev_addr.eva_gpnv);
909 break;
910 default:
911 oprintf(fp, "0x%x\n", ev.smbev_addr.eva_addr);
912 }
913
914 oprintf(fp, " Type Descriptors:\n");
915
916 for (i = 0; i < ev.smbev_typec; i++) {
917 oprintf(fp, " %u: Log Type 0x%x, Data Type 0x%x\n", i,
918 ev.smbev_typev[i].smbevt_ltype,
919 ev.smbev_typev[i].smbevt_dtype);
920 }
921 }
922
923 static void
print_bytes(const uint8_t * data,size_t size,FILE * fp)924 print_bytes(const uint8_t *data, size_t size, FILE *fp)
925 {
926 size_t row, rows = P2ROUNDUP(size, 16) / 16;
927 size_t col, cols;
928
929 char buf[17];
930 uint8_t x;
931
932 oprintf(fp, "\n offset: 0 1 2 3 4 5 6 7 8 9 a b c d e f "
933 "0123456789abcdef\n");
934
935 for (row = 0; row < rows; row++) {
936 oprintf(fp, " %#6lx: ", (ulong_t)row * 16);
937 cols = MIN(size - row * 16, 16);
938
939 for (col = 0; col < cols; col++) {
940 if (col % 4 == 0)
941 oprintf(fp, " ");
942 x = *data++;
943 oprintf(fp, "%02x", x);
944 buf[col] = x <= ' ' || x > '~' ? '.' : x;
945 }
946
947 for (; col < 16; col++) {
948 if (col % 4 == 0)
949 oprintf(fp, " ");
950 oprintf(fp, " ");
951 buf[col] = ' ';
952 }
953
954 buf[col] = '\0';
955 oprintf(fp, " %s\n", buf);
956 }
957
958 oprintf(fp, "\n");
959 }
960
961 static void
print_memarray(smbios_hdl_t * shp,id_t id,FILE * fp)962 print_memarray(smbios_hdl_t *shp, id_t id, FILE *fp)
963 {
964 smbios_memarray_t ma;
965
966 (void) smbios_info_memarray(shp, id, &ma);
967
968 desc_printf(smbios_memarray_loc_desc(ma.smbma_location),
969 fp, " Location: %u", ma.smbma_location);
970
971 desc_printf(smbios_memarray_use_desc(ma.smbma_use),
972 fp, " Use: %u", ma.smbma_use);
973
974 desc_printf(smbios_memarray_ecc_desc(ma.smbma_ecc),
975 fp, " ECC: %u", ma.smbma_ecc);
976
977 oprintf(fp, " Number of Slots/Sockets: %u\n", ma.smbma_ndevs);
978 id_printf(fp, " Memory Error Data: ", ma.smbma_err);
979 oprintf(fp, " Max Capacity: %llu bytes\n",
980 (u_longlong_t)ma.smbma_size);
981 }
982
983 static void
print_memdevice(smbios_hdl_t * shp,id_t id,FILE * fp)984 print_memdevice(smbios_hdl_t *shp, id_t id, FILE *fp)
985 {
986 smbios_memdevice_t md;
987
988 (void) smbios_info_memdevice(shp, id, &md);
989
990 id_printf(fp, " Physical Memory Array: ", md.smbmd_array);
991 id_printf(fp, " Memory Error Data: ", md.smbmd_error);
992
993 if (md.smbmd_twidth != -1u)
994 oprintf(fp, " Total Width: %u bits\n", md.smbmd_twidth);
995 else
996 oprintf(fp, " Total Width: Unknown\n");
997
998 if (md.smbmd_dwidth != -1u)
999 oprintf(fp, " Data Width: %u bits\n", md.smbmd_dwidth);
1000 else
1001 oprintf(fp, " Data Width: Unknown\n");
1002
1003 switch (md.smbmd_size) {
1004 case -1ull:
1005 oprintf(fp, " Size: Unknown\n");
1006 break;
1007 case 0:
1008 oprintf(fp, " Size: Not Populated\n");
1009 break;
1010 default:
1011 oprintf(fp, " Size: %llu bytes\n",
1012 (u_longlong_t)md.smbmd_size);
1013 }
1014
1015 desc_printf(smbios_memdevice_form_desc(md.smbmd_form),
1016 fp, " Form Factor: %u", md.smbmd_form);
1017
1018 if (md.smbmd_set == 0)
1019 oprintf(fp, " Set: None\n");
1020 else if (md.smbmd_set == (uint8_t)-1u)
1021 oprintf(fp, " Set: Unknown\n");
1022 else
1023 oprintf(fp, " Set: %u\n", md.smbmd_set);
1024
1025 if (md.smbmd_rank != 0) {
1026 desc_printf(smbios_memdevice_rank_desc(md.smbmd_rank),
1027 fp, " Rank: %u", md.smbmd_rank);
1028 } else {
1029 oprintf(fp, " Rank: Unknown\n");
1030 }
1031
1032 desc_printf(smbios_memdevice_type_desc(md.smbmd_type),
1033 fp, " Memory Type: %u", md.smbmd_type);
1034
1035 flag_printf(fp, "Flags", md.smbmd_flags, sizeof (md.smbmd_flags) * NBBY,
1036 smbios_memdevice_flag_name, smbios_memdevice_flag_desc);
1037
1038 if (md.smbmd_extspeed != 0) {
1039 oprintf(fp, " Speed: %" PRIu64 " MT/s\n", md.smbmd_extspeed);
1040 } else {
1041 oprintf(fp, " Speed: Unknown\n");
1042 }
1043
1044 if (md.smbmd_extclkspeed != 0) {
1045 oprintf(fp, " Configured Speed: %" PRIu64 " MT/s\n",
1046 md.smbmd_extclkspeed);
1047 } else {
1048 oprintf(fp, " Configured Speed: Unknown\n");
1049 }
1050
1051 str_print(fp, " Device Locator", md.smbmd_dloc);
1052 str_print(fp, " Bank Locator", md.smbmd_bloc);
1053
1054 if (md.smbmd_minvolt != 0) {
1055 oprintf(fp, " Minimum Voltage: %.2fV\n",
1056 md.smbmd_minvolt / 1000.0);
1057 } else {
1058 oprintf(fp, " Minimum Voltage: Unknown\n");
1059 }
1060
1061 if (md.smbmd_maxvolt != 0) {
1062 oprintf(fp, " Maximum Voltage: %.2fV\n",
1063 md.smbmd_maxvolt / 1000.0);
1064 } else {
1065 oprintf(fp, " Maximum Voltage: Unknown\n");
1066 }
1067
1068 if (md.smbmd_confvolt != 0) {
1069 oprintf(fp, " Configured Voltage: %.2fV\n",
1070 md.smbmd_confvolt / 1000.0);
1071 } else {
1072 oprintf(fp, " Configured Voltage: Unknown\n");
1073 }
1074
1075 if (md.smbmd_memtech != 0) {
1076 desc_printf(smbios_memdevice_memtech_desc(md.smbmd_memtech),
1077 fp, " Memory Technology: %u", md.smbmd_memtech);
1078 }
1079
1080 if (md.smbmd_opcap_flags != 0) {
1081 flag_printf(fp, "Operating Mode Capabilities",
1082 md.smbmd_opcap_flags, sizeof (md.smbmd_opcap_flags) * NBBY,
1083 smbios_memdevice_op_capab_name,
1084 smbios_memdevice_op_capab_desc);
1085 }
1086
1087 if (md.smbmd_firmware_rev[0] != '\0') {
1088 str_print(fp, " Firmware Revision", md.smbmd_firmware_rev);
1089 }
1090
1091 if (md.smbmd_modmfg_id != 0) {
1092 jedec_print(fp, "Module Manufacturer ID", md.smbmd_modmfg_id);
1093 }
1094
1095 if (md.smbmd_modprod_id != 0) {
1096 jedec_print(fp, "Module Product ID", md.smbmd_modprod_id);
1097 }
1098
1099 if (md.smbmd_cntrlmfg_id != 0) {
1100 jedec_print(fp, "Memory Subsystem Controller Manufacturer ID",
1101 md.smbmd_cntrlmfg_id);
1102 }
1103
1104 if (md.smbmd_cntrlprod_id != 0) {
1105 jedec_print(fp, "Memory Subsystem Controller Product ID",
1106 md.smbmd_cntrlprod_id);
1107 }
1108
1109 if (md.smbmd_nvsize == UINT64_MAX) {
1110 oprintf(fp, " Non-volatile Size: Unknown\n");
1111 } else if (md.smbmd_nvsize != 0) {
1112 oprintf(fp, " Non-volatile Size: %llu bytes\n",
1113 (u_longlong_t)md.smbmd_nvsize);
1114 }
1115
1116 if (md.smbmd_volatile_size == UINT64_MAX) {
1117 oprintf(fp, " Volatile Size: Unknown\n");
1118 } else if (md.smbmd_volatile_size != 0) {
1119 oprintf(fp, " Volatile Size: %llu bytes\n",
1120 (u_longlong_t)md.smbmd_volatile_size);
1121 }
1122
1123 if (md.smbmd_cache_size == UINT64_MAX) {
1124 oprintf(fp, " Cache Size: Unknown\n");
1125 } else if (md.smbmd_cache_size != 0) {
1126 oprintf(fp, " Cache Size: %llu bytes\n",
1127 (u_longlong_t)md.smbmd_cache_size);
1128 }
1129
1130 if (md.smbmd_logical_size == UINT64_MAX) {
1131 oprintf(fp, " Logical Size: Unknown\n");
1132 } else if (md.smbmd_logical_size != 0) {
1133 oprintf(fp, " Logical Size: %llu bytes\n",
1134 (u_longlong_t)md.smbmd_logical_size);
1135 }
1136 }
1137
1138 static void
print_memarrmap(smbios_hdl_t * shp,id_t id,FILE * fp)1139 print_memarrmap(smbios_hdl_t *shp, id_t id, FILE *fp)
1140 {
1141 smbios_memarrmap_t ma;
1142
1143 (void) smbios_info_memarrmap(shp, id, &ma);
1144
1145 id_printf(fp, " Physical Memory Array: ", ma.smbmam_array);
1146 oprintf(fp, " Devices per Row: %u\n", ma.smbmam_width);
1147
1148 oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n",
1149 (u_longlong_t)ma.smbmam_addr, (u_longlong_t)ma.smbmam_size);
1150 }
1151
1152 static void
print_memdevmap(smbios_hdl_t * shp,id_t id,FILE * fp)1153 print_memdevmap(smbios_hdl_t *shp, id_t id, FILE *fp)
1154 {
1155 smbios_memdevmap_t md;
1156
1157 (void) smbios_info_memdevmap(shp, id, &md);
1158
1159 id_printf(fp, " Memory Device: ", md.smbmdm_device);
1160 id_printf(fp, " Memory Array Mapped Address: ", md.smbmdm_arrmap);
1161
1162 oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n",
1163 (u_longlong_t)md.smbmdm_addr, (u_longlong_t)md.smbmdm_size);
1164
1165 oprintf(fp, " Partition Row Position: %u\n", md.smbmdm_rpos);
1166 oprintf(fp, " Interleave Position: %u\n", md.smbmdm_ipos);
1167 oprintf(fp, " Interleave Data Depth: %u\n", md.smbmdm_idepth);
1168 }
1169
1170 static void
print_hwsec(smbios_hdl_t * shp,FILE * fp)1171 print_hwsec(smbios_hdl_t *shp, FILE *fp)
1172 {
1173 smbios_hwsec_t h;
1174
1175 (void) smbios_info_hwsec(shp, &h);
1176
1177 desc_printf(smbios_hwsec_desc(h.smbh_pwr_ps),
1178 fp, " Power-On Password Status: %u", h.smbh_pwr_ps);
1179 desc_printf(smbios_hwsec_desc(h.smbh_kbd_ps),
1180 fp, " Keyboard Password Status: %u", h.smbh_kbd_ps);
1181 desc_printf(smbios_hwsec_desc(h.smbh_adm_ps),
1182 fp, " Administrator Password Status: %u", h.smbh_adm_ps);
1183 desc_printf(smbios_hwsec_desc(h.smbh_pan_ps),
1184 fp, " Front Panel Reset Status: %u", h.smbh_pan_ps);
1185 }
1186
1187 static void
print_vprobe(smbios_hdl_t * shp,id_t id,FILE * fp)1188 print_vprobe(smbios_hdl_t *shp, id_t id, FILE *fp)
1189 {
1190 smbios_vprobe_t vp;
1191
1192 if (smbios_info_vprobe(shp, id, &vp) != 0) {
1193 smbios_warn(shp, "failed to read voltage probe information");
1194 return;
1195 }
1196
1197 str_print(fp, " Description", vp.smbvp_description != NULL ?
1198 vp.smbvp_description : "unknown");
1199 desc_printf(smbios_vprobe_loc_desc(vp.smbvp_location),
1200 fp, " Location: %u", vp.smbvp_location);
1201 desc_printf(smbios_vprobe_status_desc(vp.smbvp_status),
1202 fp, " Status: %u", vp.smbvp_status);
1203
1204 if (vp.smbvp_maxval != SMB_PROBE_UNKNOWN_VALUE) {
1205 oprintf(fp, " Maximum Possible Voltage: %u mV\n",
1206 vp.smbvp_maxval);
1207 } else {
1208 oprintf(fp, " Maximum Possible Voltage: unknown\n");
1209 }
1210
1211 if (vp.smbvp_minval != SMB_PROBE_UNKNOWN_VALUE) {
1212 oprintf(fp, " Minimum Possible Voltage: %u mV\n",
1213 vp.smbvp_minval);
1214 } else {
1215 oprintf(fp, " Minimum Possible Voltage: unknown\n");
1216 }
1217
1218 if (vp.smbvp_resolution != SMB_PROBE_UNKNOWN_VALUE) {
1219 oprintf(fp, " Probe Resolution: %u.%u mV\n",
1220 vp.smbvp_resolution / 10,
1221 vp.smbvp_resolution % 10);
1222 } else {
1223 oprintf(fp, " Probe Resolution: unknown\n");
1224 }
1225
1226 if (vp.smbvp_tolerance != SMB_PROBE_UNKNOWN_VALUE) {
1227 oprintf(fp, " Probe Tolerance: +/-%u mV\n",
1228 vp.smbvp_tolerance);
1229 } else {
1230 oprintf(fp, " Probe Tolerance: unknown\n");
1231 }
1232
1233 if (vp.smbvp_accuracy != SMB_PROBE_UNKNOWN_VALUE) {
1234 oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n",
1235 vp.smbvp_accuracy / 100,
1236 vp.smbvp_accuracy % 100);
1237 } else {
1238 oprintf(fp, " Probe Accuracy: unknown\n");
1239 }
1240
1241 oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", vp.smbvp_oem);
1242
1243 if (vp.smbvp_nominal != SMB_PROBE_UNKNOWN_VALUE) {
1244 oprintf(fp, " Probe Nominal Value: %u mV\n", vp.smbvp_nominal);
1245 } else {
1246 oprintf(fp, " Probe Nominal Value: unknown\n");
1247 }
1248 }
1249
1250 static void
print_cooldev(smbios_hdl_t * shp,id_t id,FILE * fp)1251 print_cooldev(smbios_hdl_t *shp, id_t id, FILE *fp)
1252 {
1253 smbios_cooldev_t cd;
1254
1255 if (smbios_info_cooldev(shp, id, &cd) != 0) {
1256 smbios_warn(shp, "failed to read cooling device "
1257 "information");
1258 return;
1259 }
1260
1261 id_printf(fp, " Temperature Probe Handle: ", cd.smbcd_tprobe);
1262 desc_printf(smbios_cooldev_type_desc(cd.smbcd_type),
1263 fp, " Device Type: %u", cd.smbcd_type);
1264 desc_printf(smbios_cooldev_status_desc(cd.smbcd_status),
1265 fp, " Status: %u", cd.smbcd_status);
1266 oprintf(fp, " Cooling Unit Group: %u\n", cd.smbcd_group);
1267 oprintf(fp, " OEM- or BIOS- defined data: 0x%x\n", cd.smbcd_oem);
1268 if (cd.smbcd_nominal != SMB_PROBE_UNKNOWN_VALUE) {
1269 oprintf(fp, " Nominal Speed: %u RPM\n", cd.smbcd_nominal);
1270 } else {
1271 oprintf(fp, " Nominal Speed: unknown\n");
1272 }
1273
1274 if (cd.smbcd_descr != NULL && cd.smbcd_descr[0] != '\0') {
1275 str_print(fp, " Description", cd.smbcd_descr);
1276 }
1277 }
1278
1279 static void
print_tprobe(smbios_hdl_t * shp,id_t id,FILE * fp)1280 print_tprobe(smbios_hdl_t *shp, id_t id, FILE *fp)
1281 {
1282 smbios_tprobe_t tp;
1283
1284 if (smbios_info_tprobe(shp, id, &tp) != 0) {
1285 smbios_warn(shp, "failed to read temperature probe "
1286 "information");
1287 return;
1288 }
1289
1290 str_print(fp, " Description", tp.smbtp_description != NULL ?
1291 tp.smbtp_description : "unknown");
1292 desc_printf(smbios_tprobe_loc_desc(tp.smbtp_location),
1293 fp, " Location: %u", tp.smbtp_location);
1294 desc_printf(smbios_tprobe_status_desc(tp.smbtp_status),
1295 fp, " Status: %u", tp.smbtp_status);
1296
1297 if (tp.smbtp_maxval != SMB_PROBE_UNKNOWN_VALUE) {
1298 oprintf(fp, " Maximum Possible Temperature: %u.%u C\n",
1299 tp.smbtp_maxval / 10, tp.smbtp_maxval % 10);
1300 } else {
1301 oprintf(fp, " Maximum Possible Temperature: unknown\n");
1302 }
1303
1304 if (tp.smbtp_minval != SMB_PROBE_UNKNOWN_VALUE) {
1305 oprintf(fp, " Minimum Possible Temperature: %u.%u C\n",
1306 tp.smbtp_minval / 10, tp.smbtp_minval % 10);
1307 } else {
1308 oprintf(fp, " Minimum Possible Temperature: unknown\n");
1309 }
1310
1311 if (tp.smbtp_resolution != SMB_PROBE_UNKNOWN_VALUE) {
1312 oprintf(fp, " Probe Resolution: %u.%03u C\n",
1313 tp.smbtp_resolution / 1000,
1314 tp.smbtp_resolution % 1000);
1315 } else {
1316 oprintf(fp, " Probe Resolution: unknown\n");
1317 }
1318
1319 if (tp.smbtp_tolerance != SMB_PROBE_UNKNOWN_VALUE) {
1320 oprintf(fp, " Probe Tolerance: +/-%u.%u C\n",
1321 tp.smbtp_tolerance / 10, tp.smbtp_tolerance % 10);
1322 } else {
1323 oprintf(fp, " Probe Tolerance: unknown\n");
1324 }
1325
1326 if (tp.smbtp_accuracy != SMB_PROBE_UNKNOWN_VALUE) {
1327 oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n",
1328 tp.smbtp_accuracy / 100,
1329 tp.smbtp_accuracy % 100);
1330 } else {
1331 oprintf(fp, " Probe Accuracy: unknown\n");
1332 }
1333
1334 oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", tp.smbtp_oem);
1335
1336 if (tp.smbtp_nominal != SMB_PROBE_UNKNOWN_VALUE) {
1337 oprintf(fp, " Probe Nominal Value: %u.%u C\n",
1338 tp.smbtp_nominal / 10, tp.smbtp_nominal % 10);
1339 } else {
1340 oprintf(fp, " Probe Nominal Value: unknown\n");
1341 }
1342 }
1343
1344 static void
print_iprobe(smbios_hdl_t * shp,id_t id,FILE * fp)1345 print_iprobe(smbios_hdl_t *shp, id_t id, FILE *fp)
1346 {
1347 smbios_iprobe_t ip;
1348
1349 if (smbios_info_iprobe(shp, id, &ip) != 0) {
1350 smbios_warn(shp, "failed to read current probe information");
1351 return;
1352 }
1353
1354 str_print(fp, " Description", ip.smbip_description != NULL ?
1355 ip.smbip_description : "unknown");
1356 desc_printf(smbios_iprobe_loc_desc(ip.smbip_location),
1357 fp, " Location: %u", ip.smbip_location);
1358 desc_printf(smbios_iprobe_status_desc(ip.smbip_status),
1359 fp, " Status: %u", ip.smbip_status);
1360
1361 if (ip.smbip_maxval != SMB_PROBE_UNKNOWN_VALUE) {
1362 oprintf(fp, " Maximum Possible Current: %u mA\n",
1363 ip.smbip_maxval);
1364 } else {
1365 oprintf(fp, " Maximum Possible Current: unknown\n");
1366 }
1367
1368 if (ip.smbip_minval != SMB_PROBE_UNKNOWN_VALUE) {
1369 oprintf(fp, " Minimum Possible Current: %u mA\n",
1370 ip.smbip_minval);
1371 } else {
1372 oprintf(fp, " Minimum Possible Current: unknown\n");
1373 }
1374
1375 if (ip.smbip_resolution != SMB_PROBE_UNKNOWN_VALUE) {
1376 oprintf(fp, " Probe Resolution: %u.%u mA\n",
1377 ip.smbip_resolution / 10,
1378 ip.smbip_resolution % 10);
1379 } else {
1380 oprintf(fp, " Probe Resolution: unknown\n");
1381 }
1382
1383 if (ip.smbip_tolerance != SMB_PROBE_UNKNOWN_VALUE) {
1384 oprintf(fp, " Probe Tolerance: +/-%u mA\n",
1385 ip.smbip_tolerance);
1386 } else {
1387 oprintf(fp, " Probe Tolerance: unknown\n");
1388 }
1389
1390 if (ip.smbip_accuracy != SMB_PROBE_UNKNOWN_VALUE) {
1391 oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n",
1392 ip.smbip_accuracy / 100,
1393 ip.smbip_accuracy % 100);
1394 } else {
1395 oprintf(fp, " Probe Accuracy: unknown\n");
1396 }
1397
1398 oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", ip.smbip_oem);
1399
1400 if (ip.smbip_nominal != SMB_PROBE_UNKNOWN_VALUE) {
1401 oprintf(fp, " Probe Nominal Value: %u mA\n", ip.smbip_nominal);
1402 } else {
1403 oprintf(fp, " Probe Nominal Value: unknown\n");
1404 }
1405 }
1406
1407
1408 static void
print_boot(smbios_hdl_t * shp,FILE * fp)1409 print_boot(smbios_hdl_t *shp, FILE *fp)
1410 {
1411 smbios_boot_t b;
1412
1413 (void) smbios_info_boot(shp, &b);
1414
1415 desc_printf(smbios_boot_desc(b.smbt_status),
1416 fp, " Boot Status Code: 0x%x", b.smbt_status);
1417
1418 if (b.smbt_size != 0) {
1419 oprintf(fp, " Boot Data (%lu bytes):\n", (ulong_t)b.smbt_size);
1420 print_bytes(b.smbt_data, b.smbt_size, fp);
1421 }
1422 }
1423
1424 static void
print_ipmi(smbios_hdl_t * shp,FILE * fp)1425 print_ipmi(smbios_hdl_t *shp, FILE *fp)
1426 {
1427 smbios_ipmi_t i;
1428
1429 (void) smbios_info_ipmi(shp, &i);
1430
1431 desc_printf(smbios_ipmi_type_desc(i.smbip_type),
1432 fp, " Type: %u", i.smbip_type);
1433
1434 oprintf(fp, " BMC IPMI Version: %u.%u\n",
1435 i.smbip_vers.smbv_major, i.smbip_vers.smbv_minor);
1436
1437 oprintf(fp, " i2c Bus Slave Address: 0x%x\n", i.smbip_i2c);
1438 oprintf(fp, " NV Storage Device Bus ID: 0x%x\n", i.smbip_bus);
1439 oprintf(fp, " BMC Base Address: 0x%llx\n", (u_longlong_t)i.smbip_addr);
1440 oprintf(fp, " Interrupt Number: %u\n", i.smbip_intr);
1441 oprintf(fp, " Register Spacing: %u\n", i.smbip_regspacing);
1442
1443 flag_printf(fp, "Flags", i.smbip_flags, sizeof (i.smbip_flags) * NBBY,
1444 smbios_ipmi_flag_name, smbios_ipmi_flag_desc);
1445 }
1446
1447 static void
print_powersup(smbios_hdl_t * shp,id_t id,FILE * fp)1448 print_powersup(smbios_hdl_t *shp, id_t id, FILE *fp)
1449 {
1450 smbios_powersup_t p;
1451
1452 if (smbios_info_powersup(shp, id, &p) != 0) {
1453 smbios_warn(shp, "failed to read power supply information");
1454 return;
1455 }
1456
1457 oprintf(fp, " Power Supply Group: %u\n", p.smbps_group);
1458 if (p.smbps_maxout != 0x8000) {
1459 oprintf(fp, " Maximum Output: %llu mW\n", p.smbps_maxout);
1460 } else {
1461 oprintf(fp, " Maximum Output: unknown\n");
1462 }
1463
1464 flag_printf(fp, "Characteristics", p.smbps_flags,
1465 sizeof (p.smbps_flags) * NBBY, smbios_powersup_flag_name,
1466 smbios_powersup_flag_desc);
1467
1468 desc_printf(smbios_powersup_input_desc(p.smbps_ivrs),
1469 fp, " Input Voltage Range Switching: %u", p.smbps_ivrs);
1470 desc_printf(smbios_powersup_status_desc(p.smbps_status),
1471 fp, " Status: %u", p.smbps_status);
1472 desc_printf(smbios_powersup_type_desc(p.smbps_pstype),
1473 fp, " Type: %u", p.smbps_pstype);
1474
1475 if (p.smbps_vprobe != 0xffff) {
1476 oprintf(fp, " Voltage Probe Handle: %lu\n", p.smbps_vprobe);
1477 }
1478
1479 if (p.smbps_cooldev != 0xffff) {
1480 oprintf(fp, " Cooling Device Handle: %lu\n", p.smbps_cooldev);
1481 }
1482
1483 if (p.smbps_iprobe != 0xffff) {
1484 oprintf(fp, " Current Probe Handle: %lu\n", p.smbps_iprobe);
1485 }
1486 }
1487
1488 static void
print_processor_info_riscv(smbios_hdl_t * shp,id_t id,FILE * fp)1489 print_processor_info_riscv(smbios_hdl_t *shp, id_t id, FILE *fp)
1490 {
1491 smbios_processor_info_riscv_t rv;
1492
1493 if (smbios_info_processor_riscv(shp, id, &rv) != 0) {
1494 smbios_warn(shp, "failed to read RISC-V specific processor "
1495 "information");
1496 return;
1497 }
1498
1499 if (rv.smbpirv_boothart != 0) {
1500 oprintf(fp, " Boot Hart\n");
1501 }
1502 u128_print(fp, " Hart ID", rv.smbpirv_hartid);
1503 u128_print(fp, " Vendor ID", rv.smbpirv_vendid);
1504 u128_print(fp, " Architecture ID", rv.smbpirv_archid);
1505 u128_print(fp, " Implementation ID", rv.smbpirv_machid);
1506 flag64_printf(fp, " ISA", rv.smbpirv_isa,
1507 sizeof (rv.smbpirv_isa) * NBBY, smbios_riscv_isa_name,
1508 smbios_riscv_isa_desc);
1509 flag_printf(fp, " Privilege Levels", rv.smbpirv_privlvl,
1510 sizeof (rv.smbpirv_privlvl) * NBBY, smbios_riscv_priv_name,
1511 smbios_riscv_priv_desc);
1512 u128_print(fp, " Machine Exception Trap Delegation",
1513 rv.smbpirv_metdi);
1514 u128_print(fp, " Machine Interrupt Trap Delegation",
1515 rv.smbpirv_mitdi);
1516 desc_printf(smbios_riscv_width_desc(rv.smbpirv_xlen),
1517 fp, " Register Width: 0x%x", rv.smbpirv_xlen);
1518 desc_printf(smbios_riscv_width_desc(rv.smbpirv_mxlen),
1519 fp, " M-Mode Register Width: 0x%x", rv.smbpirv_mxlen);
1520 desc_printf(smbios_riscv_width_desc(rv.smbpirv_sxlen),
1521 fp, " S-Mode Register Width: 0x%x", rv.smbpirv_sxlen);
1522 desc_printf(smbios_riscv_width_desc(rv.smbpirv_uxlen),
1523 fp, " U-Mode Register Width: 0x%x", rv.smbpirv_uxlen);
1524 }
1525
1526 static void
print_processor_info(smbios_hdl_t * shp,id_t id,FILE * fp)1527 print_processor_info(smbios_hdl_t *shp, id_t id, FILE *fp)
1528 {
1529 smbios_processor_info_t p;
1530
1531 if (smbios_info_processor_info(shp, id, &p) != 0) {
1532 smbios_warn(shp, "failed to read processor additional "
1533 "information");
1534 return;
1535 }
1536
1537 id_printf(fp, " Processor Handle: ", p.smbpi_processor);
1538 desc_printf(smbios_processor_info_type_desc(p.smbpi_ptype),
1539 fp, " Processor Type: %u", p.smbpi_ptype);
1540
1541 switch (p.smbpi_ptype) {
1542 case SMB_PROCINFO_T_RV32:
1543 case SMB_PROCINFO_T_RV64:
1544 case SMB_PROCINFO_T_RV128:
1545 oprintf(fp, " RISC-V Additional Processor Information:\n");
1546 print_processor_info_riscv(shp, id, fp);
1547 break;
1548 default:
1549 break;
1550 }
1551 }
1552
1553 static void
print_battery(smbios_hdl_t * shp,id_t id,FILE * fp)1554 print_battery(smbios_hdl_t *shp, id_t id, FILE *fp)
1555 {
1556 smbios_battery_t bat;
1557
1558 if (smbios_info_battery(shp, id, &bat) != 0) {
1559 smbios_warn(shp, "failed to read battery information");
1560 return;
1561 }
1562
1563 if (bat.smbb_date != NULL) {
1564 str_print(fp, " Manufacture Date", bat.smbb_date);
1565 }
1566
1567 if (bat.smbb_serial != NULL) {
1568 str_print(fp, " Serial Number", bat.smbb_serial);
1569 }
1570
1571 if (bat.smbb_chem != SMB_BDC_UNKNOWN) {
1572 desc_printf(smbios_battery_chem_desc(bat.smbb_chem),
1573 fp, " Battery Chemistry: 0x%x", bat.smbb_chem);
1574 }
1575
1576 if (bat.smbb_cap != 0) {
1577 oprintf(fp, " Design Capacity: %u mWh\n", bat.smbb_cap);
1578 } else {
1579 oprintf(fp, " Design Capacity: unknown\n");
1580 }
1581
1582 if (bat.smbb_volt != 0) {
1583 oprintf(fp, " Design Voltage: %u mV\n", bat.smbb_volt);
1584 } else {
1585 oprintf(fp, " Design Voltage: unknown\n");
1586 }
1587
1588 str_print(fp, " SBDS Version Number", bat.smbb_version);
1589 if (bat.smbb_err != UINT8_MAX) {
1590 oprintf(fp, " Maximum Error: %u\n", bat.smbb_err);
1591 } else {
1592 oprintf(fp, " Maximum Error: unknown\n", bat.smbb_err);
1593 }
1594 oprintf(fp, " SBDS Serial Number: %04x\n", bat.smbb_ssn);
1595 oprintf(fp, " SBDS Manufacture Date: %u-%02u-%02u\n", bat.smbb_syear,
1596 bat.smbb_smonth, bat.smbb_sday);
1597 str_print(fp, " SBDS Device Chemistry", bat.smbb_schem);
1598 oprintf(fp, " OEM-specific Information: 0x%08x\n", bat.smbb_oemdata);
1599 }
1600
1601 static void
print_pointdev(smbios_hdl_t * shp,id_t id,FILE * fp)1602 print_pointdev(smbios_hdl_t *shp, id_t id, FILE *fp)
1603 {
1604 smbios_pointdev_t pd;
1605
1606 if (smbios_info_pointdev(shp, id, &pd) != 0) {
1607 smbios_warn(shp, "failed to read pointer device information");
1608 return;
1609 }
1610
1611 desc_printf(smbios_pointdev_type_desc(pd.smbpd_type),
1612 fp, " Type: %u", pd.smbpd_type);
1613 desc_printf(smbios_pointdev_iface_desc(pd.smbpd_iface),
1614 fp, " Interface: %u", pd.smbpd_iface);
1615 oprintf(fp, " Buttons: %u\n", pd.smbpd_nbuttons);
1616 }
1617
1618 static void
print_extprocessor(smbios_hdl_t * shp,id_t id,FILE * fp)1619 print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp)
1620 {
1621 int i;
1622 smbios_processor_ext_t ep;
1623
1624 if (check_oem(shp) != 0)
1625 return;
1626
1627 (void) smbios_info_extprocessor(shp, id, &ep);
1628
1629 oprintf(fp, " Processor: %u\n", ep.smbpe_processor);
1630 oprintf(fp, " FRU: %u\n", ep.smbpe_fru);
1631 oprintf(fp, " Initial APIC ID count: %u\n\n", ep.smbpe_n);
1632
1633 for (i = 0; i < ep.smbpe_n; i++) {
1634 oprintf(fp, " Logical Strand %u: Initial APIC ID: %u\n", i,
1635 ep.smbpe_apicid[i]);
1636 }
1637 }
1638
1639 static void
print_extport(smbios_hdl_t * shp,id_t id,FILE * fp)1640 print_extport(smbios_hdl_t *shp, id_t id, FILE *fp)
1641 {
1642 smbios_port_ext_t epo;
1643
1644 if (check_oem(shp) != 0)
1645 return;
1646
1647 (void) smbios_info_extport(shp, id, &epo);
1648
1649 oprintf(fp, " Chassis Handle: %u\n", epo.smbporte_chassis);
1650 oprintf(fp, " Port Connector Handle: %u\n", epo.smbporte_port);
1651 oprintf(fp, " Device Type: %u\n", epo.smbporte_dtype);
1652 oprintf(fp, " Device Handle: %u\n", epo.smbporte_devhdl);
1653 oprintf(fp, " PHY: %u\n", epo.smbporte_phy);
1654 }
1655
1656 static void
print_pciexrc(smbios_hdl_t * shp,id_t id,FILE * fp)1657 print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp)
1658 {
1659 smbios_pciexrc_t pcie;
1660
1661 if (check_oem(shp) != 0)
1662 return;
1663
1664 (void) smbios_info_pciexrc(shp, id, &pcie);
1665
1666 oprintf(fp, " Component ID: %u\n", pcie.smbpcie_bb);
1667 oprintf(fp, " BDF: 0x%x\n", pcie.smbpcie_bdf);
1668 }
1669
1670 static void
print_extmemarray(smbios_hdl_t * shp,id_t id,FILE * fp)1671 print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp)
1672 {
1673 smbios_memarray_ext_t em;
1674
1675 if (check_oem(shp) != 0)
1676 return;
1677
1678 (void) smbios_info_extmemarray(shp, id, &em);
1679
1680 oprintf(fp, " Physical Memory Array Handle: %u\n", em.smbmae_ma);
1681 oprintf(fp, " Component Parent Handle: %u\n", em.smbmae_comp);
1682 oprintf(fp, " BDF: 0x%x\n", em.smbmae_bdf);
1683 }
1684
1685 static void
print_extmemdevice(smbios_hdl_t * shp,id_t id,FILE * fp)1686 print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp)
1687 {
1688 int i;
1689 smbios_memdevice_ext_t emd;
1690
1691 if (check_oem(shp) != 0)
1692 return;
1693
1694 (void) smbios_info_extmemdevice(shp, id, &emd);
1695
1696 oprintf(fp, " Memory Device Handle: %u\n", emd.smbmdeve_md);
1697 oprintf(fp, " DRAM Channel: %u\n", emd.smbmdeve_drch);
1698 oprintf(fp, " Number of Chip Selects: %u\n", emd.smbmdeve_ncs);
1699
1700 for (i = 0; i < emd.smbmdeve_ncs; i++) {
1701 oprintf(fp, " Chip Select: %u\n", emd.smbmdeve_cs[i]);
1702 }
1703 }
1704
1705 static void
print_strprop_info(smbios_hdl_t * shp,id_t id,FILE * fp)1706 print_strprop_info(smbios_hdl_t *shp, id_t id, FILE *fp)
1707 {
1708 smbios_strprop_t prop;
1709
1710 if (smbios_info_strprop(shp, id, &prop) != 0) {
1711 smbios_warn(shp, "failed to read string property information");
1712 return;
1713 }
1714
1715 desc_printf(smbios_strprop_id_desc(prop.smbsp_prop_id), fp,
1716 " Property ID: %u", prop.smbsp_prop_id);
1717 if (prop.smbsp_prop_val != NULL) {
1718 str_print(fp, " Property Value", prop.smbsp_prop_val);
1719 }
1720 id_printf(fp, " Parent Handle: ", prop.smbsp_parent);
1721 }
1722
1723 static void
print_fwinfo(smbios_hdl_t * shp,id_t id,FILE * fp)1724 print_fwinfo(smbios_hdl_t *shp, id_t id, FILE *fp)
1725 {
1726 smbios_fwinfo_t fw;
1727 smbios_fwinfo_comp_t *comps;
1728 uint_t ncomps, i;
1729
1730 if (smbios_info_fwinfo(shp, id, &fw) != 0) {
1731 smbios_warn(shp, "failed to read firmware inventory");
1732 return;
1733 }
1734
1735 str_print(fp, " Component Name", fw.smbfw_name);
1736 str_print(fp, " ID", fw.smbfw_id);
1737 str_print(fp, " Release Date", fw.smbfw_reldate);
1738 str_print(fp, " Lowest Supported Version", fw.smbfw_lsv);
1739 desc_printf(smbios_fwinfo_vers_desc(fw.smbfw_vers_fmt), fp,
1740 " Version Format: %u", fw.smbfw_vers_fmt);
1741 desc_printf(smbios_fwinfo_id_desc(fw.smbfw_id_fmt), fp,
1742 " ID Format: %u", fw.smbfw_id_fmt);
1743 if (fw.smbfw_imgsz != UINT64_MAX) {
1744 oprintf(fp, " Image Size: %" PRIu64 "\n", fw.smbfw_imgsz);
1745 } else {
1746 oprintf(fp, " Image Size: unknown\n");
1747 }
1748
1749 flag_printf(fp, "Characteristics", fw.smbfw_chars,
1750 sizeof (fw.smbfw_chars) * NBBY, smbios_fwinfo_ch_name,
1751 smbios_fwinfo_ch_desc);
1752
1753 desc_printf(smbios_fwinfo_state_desc(fw.smbfw_state), fp, " State: %u",
1754 fw.smbfw_state);
1755 oprintf(fp, " Number of Associated Components: %u\n",
1756 fw.smbfw_ncomps);
1757
1758 if (fw.smbfw_ncomps == 0)
1759 return;
1760
1761 if (smbios_info_fwinfo_comps(shp, id, &ncomps, &comps) == -1) {
1762 smbios_warn(shp, "failed to read firmware inventory "
1763 "components");
1764 return;
1765 }
1766
1767 oprintf(fp, "\n Component Handles:\n");
1768 for (i = 0; i < ncomps; i++) {
1769 oprintf(fp, " %ld\n", comps[i]);
1770 }
1771 }
1772
1773 static int
print_struct(smbios_hdl_t * shp,const smbios_struct_t * sp,void * fp)1774 print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp)
1775 {
1776 smbios_info_t info;
1777 int hex = opt_x;
1778 const char *s;
1779
1780 if (opt_t != -1 && opt_t != sp->smbstr_type)
1781 return (0); /* skip struct if type doesn't match -t */
1782
1783 if (!opt_O && (sp->smbstr_type == SMB_TYPE_MEMCTL ||
1784 sp->smbstr_type == SMB_TYPE_MEMMOD))
1785 return (0); /* skip struct if type is obsolete */
1786
1787 if (g_hdr++ == 0 || !opt_s)
1788 oprintf(fp, "%-5s %-4s %s\n", "ID", "SIZE", "TYPE");
1789
1790 oprintf(fp, "%-5u %-4lu",
1791 (uint_t)sp->smbstr_id, (ulong_t)sp->smbstr_size);
1792
1793 if ((s = smbios_type_name(sp->smbstr_type)) != NULL)
1794 oprintf(fp, " %s (type %u)", s, sp->smbstr_type);
1795 else if (sp->smbstr_type > SMB_TYPE_OEM_LO &&
1796 sp->smbstr_type < SMB_TYPE_OEM_HI)
1797 oprintf(fp, " %s+%u (type %u)", "SMB_TYPE_OEM_LO",
1798 sp->smbstr_type - SMB_TYPE_OEM_LO, sp->smbstr_type);
1799 else
1800 oprintf(fp, " %u", sp->smbstr_type);
1801
1802 if ((s = smbios_type_desc(sp->smbstr_type)) != NULL)
1803 oprintf(fp, " (%s)\n", s);
1804 else
1805 oprintf(fp, "\n");
1806
1807 if (opt_s)
1808 return (0); /* only print header line if -s specified */
1809
1810 if (smbios_info_common(shp, sp->smbstr_id, &info) == 0) {
1811 oprintf(fp, "\n");
1812 print_common(&info, fp);
1813 }
1814
1815 switch (sp->smbstr_type) {
1816 case SMB_TYPE_BIOS:
1817 oprintf(fp, "\n");
1818 print_bios(shp, fp);
1819 break;
1820 case SMB_TYPE_SYSTEM:
1821 oprintf(fp, "\n");
1822 print_system(shp, fp);
1823 break;
1824 case SMB_TYPE_BASEBOARD:
1825 oprintf(fp, "\n");
1826 print_bboard(shp, sp->smbstr_id, fp);
1827 break;
1828 case SMB_TYPE_CHASSIS:
1829 oprintf(fp, "\n");
1830 print_chassis(shp, sp->smbstr_id, fp);
1831 break;
1832 case SMB_TYPE_PROCESSOR:
1833 oprintf(fp, "\n");
1834 print_processor(shp, sp->smbstr_id, fp);
1835 break;
1836 case SMB_TYPE_CACHE:
1837 oprintf(fp, "\n");
1838 print_cache(shp, sp->smbstr_id, fp);
1839 break;
1840 case SMB_TYPE_PORT:
1841 oprintf(fp, "\n");
1842 print_port(shp, sp->smbstr_id, fp);
1843 break;
1844 case SMB_TYPE_SLOT:
1845 oprintf(fp, "\n");
1846 print_slot(shp, sp->smbstr_id, fp);
1847 break;
1848 case SMB_TYPE_OBDEVS:
1849 oprintf(fp, "\n");
1850 print_obdevs(shp, sp->smbstr_id, fp);
1851 break;
1852 case SMB_TYPE_OEMSTR:
1853 case SMB_TYPE_SYSCONFSTR:
1854 oprintf(fp, "\n");
1855 print_strtab(shp, sp->smbstr_id, fp);
1856 break;
1857 case SMB_TYPE_LANG:
1858 oprintf(fp, "\n");
1859 print_lang(shp, sp->smbstr_id, fp);
1860 break;
1861 case SMB_TYPE_EVENTLOG:
1862 oprintf(fp, "\n");
1863 print_evlog(shp, sp->smbstr_id, fp);
1864 break;
1865 case SMB_TYPE_MEMARRAY:
1866 oprintf(fp, "\n");
1867 print_memarray(shp, sp->smbstr_id, fp);
1868 break;
1869 case SMB_TYPE_MEMDEVICE:
1870 oprintf(fp, "\n");
1871 print_memdevice(shp, sp->smbstr_id, fp);
1872 break;
1873 case SMB_TYPE_MEMARRAYMAP:
1874 oprintf(fp, "\n");
1875 print_memarrmap(shp, sp->smbstr_id, fp);
1876 break;
1877 case SMB_TYPE_MEMDEVICEMAP:
1878 oprintf(fp, "\n");
1879 print_memdevmap(shp, sp->smbstr_id, fp);
1880 break;
1881 case SMB_TYPE_BATTERY:
1882 oprintf(fp, "\n");
1883 print_battery(shp, sp->smbstr_id, fp);
1884 break;
1885 case SMB_TYPE_POINTDEV:
1886 oprintf(fp, "\n");
1887 print_pointdev(shp, sp->smbstr_id, fp);
1888 break;
1889 case SMB_TYPE_SECURITY:
1890 oprintf(fp, "\n");
1891 print_hwsec(shp, fp);
1892 break;
1893 case SMB_TYPE_VPROBE:
1894 oprintf(fp, "\n");
1895 print_vprobe(shp, sp->smbstr_id, fp);
1896 break;
1897 case SMB_TYPE_COOLDEV:
1898 oprintf(fp, "\n");
1899 print_cooldev(shp, sp->smbstr_id, fp);
1900 break;
1901 case SMB_TYPE_TPROBE:
1902 oprintf(fp, "\n");
1903 print_tprobe(shp, sp->smbstr_id, fp);
1904 break;
1905 case SMB_TYPE_IPROBE:
1906 oprintf(fp, "\n");
1907 print_iprobe(shp, sp->smbstr_id, fp);
1908 break;
1909 case SMB_TYPE_BOOT:
1910 oprintf(fp, "\n");
1911 print_boot(shp, fp);
1912 break;
1913 case SMB_TYPE_IPMIDEV:
1914 oprintf(fp, "\n");
1915 print_ipmi(shp, fp);
1916 break;
1917 case SMB_TYPE_POWERSUP:
1918 oprintf(fp, "\n");
1919 print_powersup(shp, sp->smbstr_id, fp);
1920 break;
1921 case SMB_TYPE_OBDEVEXT:
1922 oprintf(fp, "\n");
1923 print_obdevs_ext(shp, sp->smbstr_id, fp);
1924 break;
1925 case SMB_TYPE_PROCESSOR_INFO:
1926 oprintf(fp, "\n");
1927 print_processor_info(shp, sp->smbstr_id, fp);
1928 break;
1929 case SMB_TYPE_STRPROP:
1930 oprintf(fp, "\n");
1931 print_strprop_info(shp, sp->smbstr_id, fp);
1932 break;
1933 case SMB_TYPE_FWINFO:
1934 oprintf(fp, "\n");
1935 print_fwinfo(shp, sp->smbstr_id, fp);
1936 break;
1937 case SUN_OEM_EXT_PROCESSOR:
1938 oprintf(fp, "\n");
1939 print_extprocessor(shp, sp->smbstr_id, fp);
1940 break;
1941 case SUN_OEM_EXT_PORT:
1942 oprintf(fp, "\n");
1943 print_extport(shp, sp->smbstr_id, fp);
1944 break;
1945 case SUN_OEM_PCIEXRC:
1946 oprintf(fp, "\n");
1947 print_pciexrc(shp, sp->smbstr_id, fp);
1948 break;
1949 case SUN_OEM_EXT_MEMARRAY:
1950 oprintf(fp, "\n");
1951 print_extmemarray(shp, sp->smbstr_id, fp);
1952 break;
1953 case SUN_OEM_EXT_MEMDEVICE:
1954 oprintf(fp, "\n");
1955 print_extmemdevice(shp, sp->smbstr_id, fp);
1956 break;
1957 default:
1958 hex++;
1959 }
1960
1961 if (hex)
1962 print_bytes(sp->smbstr_data, sp->smbstr_size, fp);
1963 else
1964 oprintf(fp, "\n");
1965
1966 return (0);
1967 }
1968
1969 static uint16_t
getu16(const char * name,const char * s)1970 getu16(const char *name, const char *s)
1971 {
1972 u_longlong_t val;
1973 char *p;
1974
1975 errno = 0;
1976 val = strtoull(s, &p, 0);
1977
1978 if (errno != 0 || p == s || *p != '\0' || val > UINT16_MAX) {
1979 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n",
1980 g_pname, name, s);
1981 exit(SMBIOS_USAGE);
1982 }
1983
1984 return ((uint16_t)val);
1985 }
1986
1987 static uint16_t
getstype(const char * name,const char * s)1988 getstype(const char *name, const char *s)
1989 {
1990 const char *ts;
1991 uint16_t t;
1992
1993 for (t = 0; t < SMB_TYPE_OEM_LO; t++) {
1994 if ((ts = smbios_type_name(t)) != NULL && strcmp(s, ts) == 0)
1995 return (t);
1996 }
1997
1998 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n",
1999 g_pname, name, s);
2000
2001 exit(SMBIOS_USAGE);
2002 /*NOTREACHED*/
2003 }
2004
2005 static int
usage(FILE * fp)2006 usage(FILE *fp)
2007 {
2008 (void) fprintf(fp, "Usage: %s "
2009 "[-BeOsx] [-i id] [-t type] [-w file] [file]\n\n", g_pname);
2010
2011 (void) fprintf(fp,
2012 "\t-B disable header validation for broken BIOSes\n"
2013 "\t-e display SMBIOS entry point information\n"
2014 "\t-i display only the specified structure\n"
2015 "\t-O display obsolete structure types\n"
2016 "\t-s display only a summary of structure identifiers and types\n"
2017 "\t-t display only the specified structure type\n"
2018 "\t-w write the raw data to the specified file\n"
2019 "\t-x display raw data for structures\n");
2020
2021 return (SMBIOS_USAGE);
2022 }
2023
2024 int
main(int argc,char * argv[])2025 main(int argc, char *argv[])
2026 {
2027 const char *ifile = NULL;
2028 const char *ofile = NULL;
2029 int oflags = 0;
2030
2031 smbios_hdl_t *shp;
2032 smbios_struct_t s;
2033 int err, fd, c;
2034 char *p;
2035
2036 if ((p = strrchr(argv[0], '/')) == NULL)
2037 g_pname = argv[0];
2038 else
2039 g_pname = p + 1;
2040
2041 while (optind < argc) {
2042 while ((c = getopt(argc, argv, "Bei:Ost:w:xZ")) != EOF) {
2043 switch (c) {
2044 case 'B':
2045 oflags |= SMB_O_NOCKSUM | SMB_O_NOVERS;
2046 break;
2047 case 'e':
2048 opt_e++;
2049 break;
2050 case 'i':
2051 opt_i = getu16("struct ID", optarg);
2052 break;
2053 case 'O':
2054 opt_O++;
2055 break;
2056 case 's':
2057 opt_s++;
2058 break;
2059 case 't':
2060 if (isdigit(optarg[0]))
2061 opt_t = getu16("struct type", optarg);
2062 else
2063 opt_t = getstype("struct type", optarg);
2064 break;
2065 case 'w':
2066 ofile = optarg;
2067 break;
2068 case 'x':
2069 opt_x++;
2070 break;
2071 case 'Z':
2072 oflags |= SMB_O_ZIDS; /* undocumented */
2073 break;
2074 default:
2075 return (usage(stderr));
2076 }
2077 }
2078
2079 if (optind < argc) {
2080 if (ifile != NULL) {
2081 (void) fprintf(stderr, "%s: illegal "
2082 "argument -- %s\n", g_pname, argv[optind]);
2083 return (SMBIOS_USAGE);
2084 }
2085 ifile = argv[optind++];
2086 }
2087 }
2088
2089 if ((shp = smbios_open(ifile, SMB_VERSION, oflags, &err)) == NULL) {
2090 (void) fprintf(stderr, "%s: failed to load SMBIOS: %s\n",
2091 g_pname, smbios_errmsg(err));
2092 return (SMBIOS_ERROR);
2093 }
2094
2095 if (opt_i == -1 && opt_t == -1 && opt_e == 0 &&
2096 smbios_truncated(shp))
2097 (void) fprintf(stderr, "%s: SMBIOS table is truncated\n",
2098 g_pname);
2099
2100 if (ofile != NULL) {
2101 if ((fd = open(ofile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) {
2102 (void) fprintf(stderr, "%s: failed to open %s: %s\n",
2103 g_pname, ofile, strerror(errno));
2104 err = SMBIOS_ERROR;
2105 } else if (smbios_write(shp, fd) != 0) {
2106 (void) fprintf(stderr, "%s: failed to write %s: %s\n",
2107 g_pname, ofile, smbios_errmsg(smbios_errno(shp)));
2108 err = SMBIOS_ERROR;
2109 }
2110 smbios_close(shp);
2111 return (err);
2112 }
2113
2114 if (opt_e) {
2115 print_smbios(shp, stdout);
2116 smbios_close(shp);
2117 return (SMBIOS_SUCCESS);
2118 }
2119
2120 if (opt_O && (opt_i != -1 || opt_t != -1))
2121 opt_O++; /* -i or -t imply displaying obsolete records */
2122
2123 if (opt_i != -1)
2124 err = smbios_lookup_id(shp, opt_i, &s);
2125 else
2126 err = smbios_iter(shp, print_struct, stdout);
2127
2128 if (err != 0) {
2129 (void) fprintf(stderr, "%s: failed to access SMBIOS: %s\n",
2130 g_pname, smbios_errmsg(smbios_errno(shp)));
2131 smbios_close(shp);
2132 return (SMBIOS_ERROR);
2133 }
2134
2135 if (opt_i != -1)
2136 (void) print_struct(shp, &s, stdout);
2137
2138 smbios_close(shp);
2139 return (SMBIOS_SUCCESS);
2140 }
2141