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