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