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_ipmi(smbios_hdl_t *shp, FILE *fp) 1538 { 1539 smbios_ipmi_t i; 1540 1541 if (smbios_info_ipmi(shp, &i) == -1) { 1542 smbios_warn(shp, "failed to read ipmi information"); 1543 return; 1544 } 1545 1546 desc_printf(smbios_ipmi_type_desc(i.smbip_type), 1547 fp, " Type: %u", i.smbip_type); 1548 1549 oprintf(fp, " BMC IPMI Version: %u.%u\n", 1550 i.smbip_vers.smbv_major, i.smbip_vers.smbv_minor); 1551 1552 oprintf(fp, " i2c Bus Slave Address: 0x%x\n", i.smbip_i2c); 1553 oprintf(fp, " NV Storage Device Bus ID: 0x%x\n", i.smbip_bus); 1554 oprintf(fp, " BMC Base Address: 0x%llx\n", (u_longlong_t)i.smbip_addr); 1555 oprintf(fp, " Interrupt Number: %u\n", i.smbip_intr); 1556 oprintf(fp, " Register Spacing: %u\n", i.smbip_regspacing); 1557 1558 flag_printf(fp, "Flags", i.smbip_flags, sizeof (i.smbip_flags) * NBBY, 1559 smbios_ipmi_flag_name, smbios_ipmi_flag_desc); 1560 } 1561 1562 static void 1563 print_powersup(smbios_hdl_t *shp, id_t id, FILE *fp) 1564 { 1565 smbios_powersup_t p; 1566 1567 if (smbios_info_powersup(shp, id, &p) != 0) { 1568 smbios_warn(shp, "failed to read power supply information"); 1569 return; 1570 } 1571 1572 oprintf(fp, " Power Supply Group: %u\n", p.smbps_group); 1573 if (p.smbps_maxout != 0x8000) { 1574 oprintf(fp, " Maximum Output: %" PRIu64 " mW\n", 1575 p.smbps_maxout); 1576 } else { 1577 oprintf(fp, " Maximum Output: unknown\n"); 1578 } 1579 1580 flag_printf(fp, "Characteristics", p.smbps_flags, 1581 sizeof (p.smbps_flags) * NBBY, smbios_powersup_flag_name, 1582 smbios_powersup_flag_desc); 1583 1584 desc_printf(smbios_powersup_input_desc(p.smbps_ivrs), 1585 fp, " Input Voltage Range Switching: %u", p.smbps_ivrs); 1586 desc_printf(smbios_powersup_status_desc(p.smbps_status), 1587 fp, " Status: %u", p.smbps_status); 1588 desc_printf(smbios_powersup_type_desc(p.smbps_pstype), 1589 fp, " Type: %u", p.smbps_pstype); 1590 1591 if (p.smbps_vprobe != 0xffff) { 1592 oprintf(fp, " Voltage Probe Handle: %" _PRIuID "\n", 1593 p.smbps_vprobe); 1594 } 1595 1596 if (p.smbps_cooldev != 0xffff) { 1597 oprintf(fp, " Cooling Device Handle: %" _PRIuID "\n", 1598 p.smbps_cooldev); 1599 } 1600 1601 if (p.smbps_iprobe != 0xffff) { 1602 oprintf(fp, " Current Probe Handle: %" _PRIuID "\n", 1603 p.smbps_iprobe); 1604 } 1605 } 1606 1607 static void 1608 print_addinfo(smbios_hdl_t *shp, id_t id, FILE *fp) 1609 { 1610 uint_t nents, i; 1611 1612 if (smbios_info_addinfo_nents(shp, id, &nents) != 0) { 1613 smbios_warn(shp, "failed to read additional information"); 1614 return; 1615 } 1616 1617 oprintf(fp, " Number of Additional Information Entries: %u\n", nents); 1618 for (i = 0; i < nents; i++) { 1619 smbios_addinfo_ent_t *ent; 1620 1621 oprintf(fp, " Additional Information Entry %u\n", i); 1622 if (smbios_info_addinfo_ent(shp, id, i, &ent) != 0) { 1623 smbios_warn(shp, "failed to read additional " 1624 "information entry %u", i); 1625 continue; 1626 } 1627 1628 oprintf(fp, " Referenced handle: %" _PRIuID "\n", 1629 ent->smbai_ref); 1630 oprintf(fp, " Handle offset: %u\n", ent->smbai_ref_off); 1631 if (ent->smbai_str != NULL) { 1632 str_print(fp, " Information String", ent->smbai_str); 1633 } 1634 1635 /* 1636 * As of SMBIOS 3.7, there are no extra data entries strictly 1637 * defined in the spec, but there may be something. If we find 1638 * something that's a standard integer size, then we'll 1639 * interpret it and print it as a hex value. In theory this is 1640 * supposed to refer back to some field, but hard to say how 1641 * this'll actually be used. The first time we encountered it 1642 * was just an additional string entry. 1643 */ 1644 if (ent->smbai_dlen > 0) { 1645 oprintf(fp, " Data Length: %u\n", ent->smbai_dlen); 1646 switch (ent->smbai_dlen) { 1647 case 1: 1648 oprintf(fp, " Data: 0x%x\n", 1649 *(uint8_t *)ent->smbai_data); 1650 break; 1651 case 2: 1652 oprintf(fp, " Data: 0x%x\n", 1653 *(uint16_t *)ent->smbai_data); 1654 break; 1655 case 4: 1656 oprintf(fp, " Data: 0x%x\n", 1657 *(uint32_t *)ent->smbai_data); 1658 break; 1659 case 8: 1660 oprintf(fp, " Data: 0x%" PRIx64 "\n", 1661 *(uint64_t *)ent->smbai_data); 1662 break; 1663 default: 1664 break; 1665 } 1666 } 1667 1668 smbios_info_addinfo_ent_free(shp, ent); 1669 } 1670 } 1671 1672 1673 static void 1674 print_processor_info_riscv(smbios_hdl_t *shp, id_t id, FILE *fp) 1675 { 1676 smbios_processor_info_riscv_t rv; 1677 1678 if (smbios_info_processor_riscv(shp, id, &rv) != 0) { 1679 smbios_warn(shp, "failed to read RISC-V specific processor " 1680 "information"); 1681 return; 1682 } 1683 1684 if (rv.smbpirv_boothart != 0) { 1685 oprintf(fp, " Boot Hart\n"); 1686 } 1687 u128_print(fp, " Hart ID", rv.smbpirv_hartid); 1688 u128_print(fp, " Vendor ID", rv.smbpirv_vendid); 1689 u128_print(fp, " Architecture ID", rv.smbpirv_archid); 1690 u128_print(fp, " Implementation ID", rv.smbpirv_machid); 1691 flag64_printf(fp, " ISA", rv.smbpirv_isa, 1692 sizeof (rv.smbpirv_isa) * NBBY, smbios_riscv_isa_name, 1693 smbios_riscv_isa_desc); 1694 flag_printf(fp, " Privilege Levels", rv.smbpirv_privlvl, 1695 sizeof (rv.smbpirv_privlvl) * NBBY, smbios_riscv_priv_name, 1696 smbios_riscv_priv_desc); 1697 u128_print(fp, " Machine Exception Trap Delegation", 1698 rv.smbpirv_metdi); 1699 u128_print(fp, " Machine Interrupt Trap Delegation", 1700 rv.smbpirv_mitdi); 1701 desc_printf(smbios_riscv_width_desc(rv.smbpirv_xlen), 1702 fp, " Register Width: 0x%x", rv.smbpirv_xlen); 1703 desc_printf(smbios_riscv_width_desc(rv.smbpirv_mxlen), 1704 fp, " M-Mode Register Width: 0x%x", rv.smbpirv_mxlen); 1705 desc_printf(smbios_riscv_width_desc(rv.smbpirv_sxlen), 1706 fp, " S-Mode Register Width: 0x%x", rv.smbpirv_sxlen); 1707 desc_printf(smbios_riscv_width_desc(rv.smbpirv_uxlen), 1708 fp, " U-Mode Register Width: 0x%x", rv.smbpirv_uxlen); 1709 } 1710 1711 static void 1712 print_processor_info(smbios_hdl_t *shp, id_t id, FILE *fp) 1713 { 1714 smbios_processor_info_t p; 1715 1716 if (smbios_info_processor_info(shp, id, &p) != 0) { 1717 smbios_warn(shp, "failed to read processor additional " 1718 "information"); 1719 return; 1720 } 1721 1722 id_printf(fp, " Processor Handle: ", p.smbpi_processor); 1723 desc_printf(smbios_processor_info_type_desc(p.smbpi_ptype), 1724 fp, " Processor Type: %u", p.smbpi_ptype); 1725 1726 switch (p.smbpi_ptype) { 1727 case SMB_PROCINFO_T_RV32: 1728 case SMB_PROCINFO_T_RV64: 1729 case SMB_PROCINFO_T_RV128: 1730 oprintf(fp, " RISC-V Additional Processor Information:\n"); 1731 print_processor_info_riscv(shp, id, fp); 1732 break; 1733 default: 1734 break; 1735 } 1736 } 1737 1738 static void 1739 print_battery(smbios_hdl_t *shp, id_t id, FILE *fp) 1740 { 1741 smbios_battery_t bat; 1742 1743 if (smbios_info_battery(shp, id, &bat) != 0) { 1744 smbios_warn(shp, "failed to read battery information"); 1745 return; 1746 } 1747 1748 if (bat.smbb_date != NULL) { 1749 str_print(fp, " Manufacture Date", bat.smbb_date); 1750 } 1751 1752 if (bat.smbb_serial != NULL) { 1753 str_print(fp, " Serial Number", bat.smbb_serial); 1754 } 1755 1756 if (bat.smbb_chem != SMB_BDC_UNKNOWN) { 1757 desc_printf(smbios_battery_chem_desc(bat.smbb_chem), 1758 fp, " Battery Chemistry: 0x%x", bat.smbb_chem); 1759 } 1760 1761 if (bat.smbb_cap != 0) { 1762 oprintf(fp, " Design Capacity: %u mWh\n", bat.smbb_cap); 1763 } else { 1764 oprintf(fp, " Design Capacity: unknown\n"); 1765 } 1766 1767 if (bat.smbb_volt != 0) { 1768 oprintf(fp, " Design Voltage: %u mV\n", bat.smbb_volt); 1769 } else { 1770 oprintf(fp, " Design Voltage: unknown\n"); 1771 } 1772 1773 str_print(fp, " SBDS Version Number", bat.smbb_version); 1774 if (bat.smbb_err != UINT8_MAX) { 1775 oprintf(fp, " Maximum Error: %u\n", bat.smbb_err); 1776 } else { 1777 oprintf(fp, " Maximum Error: unknown\n"); 1778 } 1779 oprintf(fp, " SBDS Serial Number: %04x\n", bat.smbb_ssn); 1780 oprintf(fp, " SBDS Manufacture Date: %u-%02u-%02u\n", bat.smbb_syear, 1781 bat.smbb_smonth, bat.smbb_sday); 1782 str_print(fp, " SBDS Device Chemistry", bat.smbb_schem); 1783 oprintf(fp, " OEM-specific Information: 0x%08x\n", bat.smbb_oemdata); 1784 } 1785 1786 static void 1787 print_pointdev(smbios_hdl_t *shp, id_t id, FILE *fp) 1788 { 1789 smbios_pointdev_t pd; 1790 1791 if (smbios_info_pointdev(shp, id, &pd) != 0) { 1792 smbios_warn(shp, "failed to read pointer device information"); 1793 return; 1794 } 1795 1796 desc_printf(smbios_pointdev_type_desc(pd.smbpd_type), 1797 fp, " Type: %u", pd.smbpd_type); 1798 desc_printf(smbios_pointdev_iface_desc(pd.smbpd_iface), 1799 fp, " Interface: %u", pd.smbpd_iface); 1800 oprintf(fp, " Buttons: %u\n", pd.smbpd_nbuttons); 1801 } 1802 1803 static void 1804 print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp) 1805 { 1806 int i; 1807 smbios_processor_ext_t ep; 1808 1809 if (check_oem(shp) != 0) 1810 return; 1811 1812 if (smbios_info_extprocessor(shp, id, &ep) != 0) { 1813 smbios_warn(shp, "failed to read extended processor " 1814 "information"); 1815 return; 1816 } 1817 1818 oprintf(fp, " Processor: %u\n", ep.smbpe_processor); 1819 oprintf(fp, " FRU: %u\n", ep.smbpe_fru); 1820 oprintf(fp, " Initial APIC ID count: %u\n\n", ep.smbpe_n); 1821 1822 for (i = 0; i < ep.smbpe_n; i++) { 1823 oprintf(fp, " Logical Strand %u: Initial APIC ID: %u\n", i, 1824 ep.smbpe_apicid[i]); 1825 } 1826 } 1827 1828 static void 1829 print_extport(smbios_hdl_t *shp, id_t id, FILE *fp) 1830 { 1831 smbios_port_ext_t epo; 1832 1833 if (check_oem(shp) != 0) 1834 return; 1835 1836 if (smbios_info_extport(shp, id, &epo) != 0) { 1837 smbios_warn(shp, "failed to read extended port information"); 1838 return; 1839 } 1840 1841 oprintf(fp, " Chassis Handle: %u\n", epo.smbporte_chassis); 1842 oprintf(fp, " Port Connector Handle: %u\n", epo.smbporte_port); 1843 oprintf(fp, " Device Type: %u\n", epo.smbporte_dtype); 1844 oprintf(fp, " Device Handle: %u\n", epo.smbporte_devhdl); 1845 oprintf(fp, " PHY: %u\n", epo.smbporte_phy); 1846 } 1847 1848 static void 1849 print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp) 1850 { 1851 smbios_pciexrc_t pcie; 1852 1853 if (check_oem(shp) != 0) 1854 return; 1855 1856 if (smbios_info_pciexrc(shp, id, &pcie) != 0) { 1857 smbios_warn(shp, "failed to read pciexrc information"); 1858 return; 1859 } 1860 1861 oprintf(fp, " Component ID: %u\n", pcie.smbpcie_bb); 1862 oprintf(fp, " BDF: 0x%x\n", pcie.smbpcie_bdf); 1863 } 1864 1865 static void 1866 print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp) 1867 { 1868 smbios_memarray_ext_t em; 1869 1870 if (check_oem(shp) != 0) 1871 return; 1872 1873 if (smbios_info_extmemarray(shp, id, &em) != 0) { 1874 smbios_warn(shp, "failed to read extmemarray information"); 1875 return; 1876 } 1877 1878 oprintf(fp, " Physical Memory Array Handle: %u\n", em.smbmae_ma); 1879 oprintf(fp, " Component Parent Handle: %u\n", em.smbmae_comp); 1880 oprintf(fp, " BDF: 0x%x\n", em.smbmae_bdf); 1881 } 1882 1883 static void 1884 print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp) 1885 { 1886 uint_t i, ncs; 1887 uint8_t *cs; 1888 smbios_memdevice_ext_t emd; 1889 1890 if (check_oem(shp) != 0) 1891 return; 1892 1893 if (smbios_info_extmemdevice(shp, id, &emd) != 0) { 1894 smbios_warn(shp, "failed to read extmemdevice information"); 1895 return; 1896 } 1897 1898 oprintf(fp, " Memory Device Handle: %u\n", emd.smbmdeve_md); 1899 oprintf(fp, " DRAM Channel: %u\n", emd.smbmdeve_drch); 1900 oprintf(fp, " Number of Chip Selects: %u\n", emd.smbmdeve_ncs); 1901 1902 if (emd.smbmdeve_ncs == 0) 1903 return; 1904 1905 if (smbios_info_extmemdevice_cs(shp, id, &ncs, &cs) != 0) { 1906 smbios_warn(shp, "failed to read extmemdevice cs information"); 1907 return; 1908 } 1909 1910 for (i = 0; i < ncs; i++) { 1911 oprintf(fp, " Chip Select: %u\n", cs[i]); 1912 } 1913 smbios_info_extmemdevice_cs_free(shp, ncs, cs); 1914 } 1915 1916 static void 1917 print_strprop_info(smbios_hdl_t *shp, id_t id, FILE *fp) 1918 { 1919 smbios_strprop_t prop; 1920 1921 if (smbios_info_strprop(shp, id, &prop) != 0) { 1922 smbios_warn(shp, "failed to read string property information"); 1923 return; 1924 } 1925 1926 desc_printf(smbios_strprop_id_desc(prop.smbsp_prop_id), fp, 1927 " Property ID: %u", prop.smbsp_prop_id); 1928 if (prop.smbsp_prop_val != NULL) { 1929 str_print(fp, " Property Value", prop.smbsp_prop_val); 1930 } 1931 id_printf(fp, " Parent Handle: ", prop.smbsp_parent); 1932 } 1933 1934 static void 1935 print_fwinfo(smbios_hdl_t *shp, id_t id, FILE *fp) 1936 { 1937 smbios_fwinfo_t fw; 1938 smbios_fwinfo_comp_t *comps; 1939 uint_t ncomps, i; 1940 1941 if (smbios_info_fwinfo(shp, id, &fw) != 0) { 1942 smbios_warn(shp, "failed to read firmware inventory"); 1943 return; 1944 } 1945 1946 str_print(fp, " Component Name", fw.smbfw_name); 1947 str_print(fp, " ID", fw.smbfw_id); 1948 str_print(fp, " Release Date", fw.smbfw_reldate); 1949 str_print(fp, " Lowest Supported Version", fw.smbfw_lsv); 1950 desc_printf(smbios_fwinfo_vers_desc(fw.smbfw_vers_fmt), fp, 1951 " Version Format: %u", fw.smbfw_vers_fmt); 1952 desc_printf(smbios_fwinfo_id_desc(fw.smbfw_id_fmt), fp, 1953 " ID Format: %u", fw.smbfw_id_fmt); 1954 if (fw.smbfw_imgsz != UINT64_MAX) { 1955 oprintf(fp, " Image Size: %" PRIu64 "\n", fw.smbfw_imgsz); 1956 } else { 1957 oprintf(fp, " Image Size: unknown\n"); 1958 } 1959 1960 flag_printf(fp, "Characteristics", fw.smbfw_chars, 1961 sizeof (fw.smbfw_chars) * NBBY, smbios_fwinfo_ch_name, 1962 smbios_fwinfo_ch_desc); 1963 1964 desc_printf(smbios_fwinfo_state_desc(fw.smbfw_state), fp, " State: %u", 1965 fw.smbfw_state); 1966 oprintf(fp, " Number of Associated Components: %u\n", 1967 fw.smbfw_ncomps); 1968 1969 if (fw.smbfw_ncomps == 0) 1970 return; 1971 1972 if (smbios_info_fwinfo_comps(shp, id, &ncomps, &comps) == -1) { 1973 smbios_warn(shp, "failed to read firmware inventory " 1974 "components"); 1975 return; 1976 } 1977 1978 oprintf(fp, "\n Component Handles:\n"); 1979 for (i = 0; i < ncomps; i++) { 1980 oprintf(fp, " %" _PRIdID "\n", comps[i].smbfwe_id); 1981 } 1982 } 1983 1984 static int 1985 print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) 1986 { 1987 smbios_info_t info; 1988 int hex = opt_x; 1989 const char *s; 1990 1991 if (opt_t != -1 && opt_t != sp->smbstr_type) 1992 return (0); /* skip struct if type doesn't match -t */ 1993 1994 if (!opt_O && (sp->smbstr_type == SMB_TYPE_MEMCTL || 1995 sp->smbstr_type == SMB_TYPE_MEMMOD)) 1996 return (0); /* skip struct if type is obsolete */ 1997 1998 if (g_hdr++ == 0 || !opt_s) 1999 oprintf(fp, "%-5s %-4s %s\n", "ID", "SIZE", "TYPE"); 2000 2001 oprintf(fp, "%-5u %-4lu", 2002 (uint_t)sp->smbstr_id, (ulong_t)sp->smbstr_size); 2003 2004 if ((s = smbios_type_name(sp->smbstr_type)) != NULL) 2005 oprintf(fp, " %s (type %u)", s, sp->smbstr_type); 2006 else if (sp->smbstr_type > SMB_TYPE_OEM_LO && 2007 sp->smbstr_type < SMB_TYPE_OEM_HI) 2008 oprintf(fp, " %s+%u (type %u)", "SMB_TYPE_OEM_LO", 2009 sp->smbstr_type - SMB_TYPE_OEM_LO, sp->smbstr_type); 2010 else 2011 oprintf(fp, " %u", sp->smbstr_type); 2012 2013 if ((s = smbios_type_desc(sp->smbstr_type)) != NULL) 2014 oprintf(fp, " (%s)\n", s); 2015 else 2016 oprintf(fp, "\n"); 2017 2018 if (opt_s) 2019 return (0); /* only print header line if -s specified */ 2020 2021 if (smbios_info_common(shp, sp->smbstr_id, &info) == 0) { 2022 oprintf(fp, "\n"); 2023 print_common(&info, fp); 2024 } 2025 2026 switch (sp->smbstr_type) { 2027 case SMB_TYPE_BIOS: 2028 oprintf(fp, "\n"); 2029 print_bios(shp, fp); 2030 break; 2031 case SMB_TYPE_SYSTEM: 2032 oprintf(fp, "\n"); 2033 print_system(shp, fp); 2034 break; 2035 case SMB_TYPE_BASEBOARD: 2036 oprintf(fp, "\n"); 2037 print_bboard(shp, sp->smbstr_id, fp); 2038 break; 2039 case SMB_TYPE_CHASSIS: 2040 oprintf(fp, "\n"); 2041 print_chassis(shp, sp->smbstr_id, fp); 2042 break; 2043 case SMB_TYPE_PROCESSOR: 2044 oprintf(fp, "\n"); 2045 print_processor(shp, sp->smbstr_id, fp); 2046 break; 2047 case SMB_TYPE_CACHE: 2048 oprintf(fp, "\n"); 2049 print_cache(shp, sp->smbstr_id, fp); 2050 break; 2051 case SMB_TYPE_PORT: 2052 oprintf(fp, "\n"); 2053 print_port(shp, sp->smbstr_id, fp); 2054 break; 2055 case SMB_TYPE_SLOT: 2056 oprintf(fp, "\n"); 2057 print_slot(shp, sp->smbstr_id, fp); 2058 break; 2059 case SMB_TYPE_OBDEVS: 2060 oprintf(fp, "\n"); 2061 print_obdevs(shp, sp->smbstr_id, fp); 2062 break; 2063 case SMB_TYPE_OEMSTR: 2064 case SMB_TYPE_SYSCONFSTR: 2065 oprintf(fp, "\n"); 2066 print_strtab(shp, sp->smbstr_id, fp); 2067 break; 2068 case SMB_TYPE_LANG: 2069 oprintf(fp, "\n"); 2070 print_lang(shp, sp->smbstr_id, fp); 2071 break; 2072 case SMB_TYPE_EVENTLOG: 2073 oprintf(fp, "\n"); 2074 print_evlog(shp, sp->smbstr_id, fp); 2075 break; 2076 case SMB_TYPE_MEMARRAY: 2077 oprintf(fp, "\n"); 2078 print_memarray(shp, sp->smbstr_id, fp); 2079 break; 2080 case SMB_TYPE_MEMDEVICE: 2081 oprintf(fp, "\n"); 2082 print_memdevice(shp, sp->smbstr_id, fp); 2083 break; 2084 case SMB_TYPE_MEMARRAYMAP: 2085 oprintf(fp, "\n"); 2086 print_memarrmap(shp, sp->smbstr_id, fp); 2087 break; 2088 case SMB_TYPE_MEMDEVICEMAP: 2089 oprintf(fp, "\n"); 2090 print_memdevmap(shp, sp->smbstr_id, fp); 2091 break; 2092 case SMB_TYPE_BATTERY: 2093 oprintf(fp, "\n"); 2094 print_battery(shp, sp->smbstr_id, fp); 2095 break; 2096 case SMB_TYPE_POINTDEV: 2097 oprintf(fp, "\n"); 2098 print_pointdev(shp, sp->smbstr_id, fp); 2099 break; 2100 case SMB_TYPE_SECURITY: 2101 oprintf(fp, "\n"); 2102 print_hwsec(shp, fp); 2103 break; 2104 case SMB_TYPE_VPROBE: 2105 oprintf(fp, "\n"); 2106 print_vprobe(shp, sp->smbstr_id, fp); 2107 break; 2108 case SMB_TYPE_COOLDEV: 2109 oprintf(fp, "\n"); 2110 print_cooldev(shp, sp->smbstr_id, fp); 2111 break; 2112 case SMB_TYPE_TPROBE: 2113 oprintf(fp, "\n"); 2114 print_tprobe(shp, sp->smbstr_id, fp); 2115 break; 2116 case SMB_TYPE_IPROBE: 2117 oprintf(fp, "\n"); 2118 print_iprobe(shp, sp->smbstr_id, fp); 2119 break; 2120 case SMB_TYPE_BOOT: 2121 oprintf(fp, "\n"); 2122 print_boot(shp, fp); 2123 break; 2124 case SMB_TYPE_IPMIDEV: 2125 oprintf(fp, "\n"); 2126 print_ipmi(shp, fp); 2127 break; 2128 case SMB_TYPE_POWERSUP: 2129 oprintf(fp, "\n"); 2130 print_powersup(shp, sp->smbstr_id, fp); 2131 break; 2132 case SMB_TYPE_ADDINFO: 2133 oprintf(fp, "\n"); 2134 print_addinfo(shp, sp->smbstr_id, fp); 2135 break; 2136 case SMB_TYPE_OBDEVEXT: 2137 oprintf(fp, "\n"); 2138 print_obdevs_ext(shp, sp->smbstr_id, fp); 2139 break; 2140 case SMB_TYPE_PROCESSOR_INFO: 2141 oprintf(fp, "\n"); 2142 print_processor_info(shp, sp->smbstr_id, fp); 2143 break; 2144 case SMB_TYPE_STRPROP: 2145 oprintf(fp, "\n"); 2146 print_strprop_info(shp, sp->smbstr_id, fp); 2147 break; 2148 case SMB_TYPE_FWINFO: 2149 oprintf(fp, "\n"); 2150 print_fwinfo(shp, sp->smbstr_id, fp); 2151 break; 2152 case SUN_OEM_EXT_PROCESSOR: 2153 oprintf(fp, "\n"); 2154 print_extprocessor(shp, sp->smbstr_id, fp); 2155 break; 2156 case SUN_OEM_EXT_PORT: 2157 oprintf(fp, "\n"); 2158 print_extport(shp, sp->smbstr_id, fp); 2159 break; 2160 case SUN_OEM_PCIEXRC: 2161 oprintf(fp, "\n"); 2162 print_pciexrc(shp, sp->smbstr_id, fp); 2163 break; 2164 case SUN_OEM_EXT_MEMARRAY: 2165 oprintf(fp, "\n"); 2166 print_extmemarray(shp, sp->smbstr_id, fp); 2167 break; 2168 case SUN_OEM_EXT_MEMDEVICE: 2169 oprintf(fp, "\n"); 2170 print_extmemdevice(shp, sp->smbstr_id, fp); 2171 break; 2172 default: 2173 hex++; 2174 } 2175 2176 if (hex) 2177 print_bytes(sp->smbstr_data, sp->smbstr_size, fp); 2178 else 2179 oprintf(fp, "\n"); 2180 2181 return (0); 2182 } 2183 2184 static uint16_t 2185 getu16(const char *name, const char *s) 2186 { 2187 u_longlong_t val; 2188 char *p; 2189 2190 errno = 0; 2191 val = strtoull(s, &p, 0); 2192 2193 if (errno != 0 || p == s || *p != '\0' || val > UINT16_MAX) { 2194 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 2195 g_pname, name, s); 2196 exit(SMBIOS_USAGE); 2197 } 2198 2199 return ((uint16_t)val); 2200 } 2201 2202 static uint16_t 2203 getstype(const char *name, const char *s) 2204 { 2205 const char *ts; 2206 uint16_t t; 2207 2208 for (t = 0; t < SMB_TYPE_OEM_LO; t++) { 2209 if ((ts = smbios_type_name(t)) != NULL && strcmp(s, ts) == 0) 2210 return (t); 2211 } 2212 2213 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 2214 g_pname, name, s); 2215 2216 exit(SMBIOS_USAGE); 2217 /*NOTREACHED*/ 2218 } 2219 2220 static int 2221 usage(FILE *fp) 2222 { 2223 (void) fprintf(fp, "Usage: %s " 2224 "[-BeOsx] [-i id] [-t type] [-w file] [file]\n\n", g_pname); 2225 2226 (void) fprintf(fp, 2227 "\t-B disable header validation for broken BIOSes\n" 2228 "\t-e display SMBIOS entry point information\n" 2229 "\t-i display only the specified structure\n" 2230 "\t-O display obsolete structure types\n" 2231 "\t-s display only a summary of structure identifiers and types\n" 2232 "\t-t display only the specified structure type\n" 2233 "\t-w write the raw data to the specified file\n" 2234 "\t-x display raw data for structures\n"); 2235 2236 return (SMBIOS_USAGE); 2237 } 2238 2239 int 2240 main(int argc, char *argv[]) 2241 { 2242 const char *ifile = NULL; 2243 const char *ofile = NULL; 2244 int oflags = 0; 2245 2246 smbios_hdl_t *shp; 2247 smbios_struct_t s; 2248 int err, fd, c; 2249 char *p; 2250 2251 if ((p = strrchr(argv[0], '/')) == NULL) 2252 g_pname = argv[0]; 2253 else 2254 g_pname = p + 1; 2255 2256 while (optind < argc) { 2257 while ((c = getopt(argc, argv, "Bei:Ost:w:xZ")) != EOF) { 2258 switch (c) { 2259 case 'B': 2260 oflags |= SMB_O_NOCKSUM | SMB_O_NOVERS; 2261 break; 2262 case 'e': 2263 opt_e++; 2264 break; 2265 case 'i': 2266 opt_i = getu16("struct ID", optarg); 2267 break; 2268 case 'O': 2269 opt_O++; 2270 break; 2271 case 's': 2272 opt_s++; 2273 break; 2274 case 't': 2275 if (isdigit(optarg[0])) 2276 opt_t = getu16("struct type", optarg); 2277 else 2278 opt_t = getstype("struct type", optarg); 2279 break; 2280 case 'w': 2281 ofile = optarg; 2282 break; 2283 case 'x': 2284 opt_x++; 2285 break; 2286 case 'Z': 2287 oflags |= SMB_O_ZIDS; /* undocumented */ 2288 break; 2289 default: 2290 return (usage(stderr)); 2291 } 2292 } 2293 2294 if (optind < argc) { 2295 if (ifile != NULL) { 2296 (void) fprintf(stderr, "%s: illegal " 2297 "argument -- %s\n", g_pname, argv[optind]); 2298 return (SMBIOS_USAGE); 2299 } 2300 ifile = argv[optind++]; 2301 } 2302 } 2303 2304 if ((shp = smbios_open(ifile, SMB_VERSION, oflags, &err)) == NULL) { 2305 (void) fprintf(stderr, "%s: failed to load SMBIOS: %s\n", 2306 g_pname, smbios_errmsg(err)); 2307 return (SMBIOS_ERROR); 2308 } 2309 2310 if (opt_i == -1 && opt_t == -1 && opt_e == 0 && 2311 smbios_truncated(shp)) 2312 (void) fprintf(stderr, "%s: SMBIOS table is truncated\n", 2313 g_pname); 2314 2315 if (ofile != NULL) { 2316 if ((fd = open(ofile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) { 2317 (void) fprintf(stderr, "%s: failed to open %s: %s\n", 2318 g_pname, ofile, strerror(errno)); 2319 err = SMBIOS_ERROR; 2320 } else if (smbios_write(shp, fd) != 0) { 2321 (void) fprintf(stderr, "%s: failed to write %s: %s\n", 2322 g_pname, ofile, smbios_errmsg(smbios_errno(shp))); 2323 err = SMBIOS_ERROR; 2324 } 2325 smbios_close(shp); 2326 return (err); 2327 } 2328 2329 if (opt_e) { 2330 print_smbios(shp, stdout); 2331 smbios_close(shp); 2332 return (SMBIOS_SUCCESS); 2333 } 2334 2335 if (opt_O && (opt_i != -1 || opt_t != -1)) 2336 opt_O++; /* -i or -t imply displaying obsolete records */ 2337 2338 if (opt_i != -1) 2339 err = smbios_lookup_id(shp, opt_i, &s); 2340 else 2341 err = smbios_iter(shp, print_struct, stdout); 2342 2343 if (err != 0) { 2344 (void) fprintf(stderr, "%s: failed to access SMBIOS: %s\n", 2345 g_pname, smbios_errmsg(smbios_errno(shp))); 2346 smbios_close(shp); 2347 return (SMBIOS_ERROR); 2348 } 2349 2350 if (opt_i != -1) 2351 (void) print_struct(shp, &s, stdout); 2352 2353 smbios_close(shp); 2354 return (SMBIOS_SUCCESS); 2355 } 2356