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