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