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 2010 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include <sys/sysmacros.h> 30 #include <sys/param.h> 31 32 #include <smbios.h> 33 #include <alloca.h> 34 #include <limits.h> 35 #include <unistd.h> 36 #include <strings.h> 37 #include <stdlib.h> 38 #include <stdarg.h> 39 #include <stdio.h> 40 #include <fcntl.h> 41 #include <errno.h> 42 #include <ctype.h> 43 #include <libjedec.h> 44 45 #define SMBIOS_SUCCESS 0 46 #define SMBIOS_ERROR 1 47 #define SMBIOS_USAGE 2 48 49 static const char *g_pname; 50 static int g_hdr; 51 52 static int opt_e; 53 static int opt_i = -1; 54 static int opt_O; 55 static int opt_s; 56 static int opt_t = -1; 57 static int opt_x; 58 59 static boolean_t 60 smbios_vergteq(smbios_version_t *v, uint_t major, uint_t minor) 61 { 62 if (v->smbv_major > major) 63 return (B_TRUE); 64 if (v->smbv_major == major && 65 v->smbv_minor >= minor) 66 return (B_TRUE); 67 return (B_FALSE); 68 } 69 70 /*PRINTFLIKE2*/ 71 static void 72 smbios_warn(smbios_hdl_t *shp, const char *format, ...) 73 { 74 va_list ap; 75 76 va_start(ap, format); 77 (void) vfprintf(stderr, format, ap); 78 va_end(ap); 79 80 if (shp != NULL) { 81 (void) fprintf(stderr, ": %s", 82 smbios_errmsg(smbios_errno(shp))); 83 } 84 85 (void) fprintf(stderr, "\n"); 86 } 87 88 /*PRINTFLIKE2*/ 89 static void 90 oprintf(FILE *fp, const char *format, ...) 91 { 92 va_list ap; 93 94 va_start(ap, format); 95 (void) vfprintf(fp, format, ap); 96 va_end(ap); 97 } 98 99 /*PRINTFLIKE3*/ 100 static void 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 vendor = id & 0xff; 181 cont = (id >> 8) & 0xff; 182 name = libjedec_vendor_string(cont, vendor); 183 if (name == NULL) { 184 oprintf(fp, " %s: 0x%x\n", desc, id); 185 } else { 186 oprintf(fp, " %s: 0x%x (%s)\n", desc, id, name); 187 } 188 } 189 190 static int 191 check_oem(smbios_hdl_t *shp) 192 { 193 int i; 194 int cnt; 195 int rv; 196 id_t oem_id; 197 smbios_struct_t s; 198 const char **oem_str; 199 200 rv = smbios_lookup_type(shp, SMB_TYPE_OEMSTR, &s); 201 if (rv != 0) { 202 return (-1); 203 } 204 205 oem_id = s.smbstr_id; 206 207 cnt = smbios_info_strtab(shp, oem_id, 0, NULL); 208 if (cnt > 0) { 209 oem_str = alloca(sizeof (char *) * cnt); 210 (void) smbios_info_strtab(shp, oem_id, cnt, oem_str); 211 212 for (i = 0; i < cnt; i++) { 213 if (strncmp(oem_str[i], SMB_PRMS1, 214 strlen(SMB_PRMS1) + 1) == 0) { 215 return (0); 216 } 217 } 218 } 219 220 return (-1); 221 } 222 223 static void 224 print_smbios_21(smbios_21_entry_t *ep, FILE *fp) 225 { 226 int i; 227 228 oprintf(fp, "Entry Point Anchor Tag: %*.*s\n", 229 (int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor), 230 ep->smbe_eanchor); 231 232 oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum); 233 oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen); 234 oprintf(fp, "Entry Point Version: %u.%u\n", 235 ep->smbe_major, ep->smbe_minor); 236 oprintf(fp, "Max Structure Size: %u\n", ep->smbe_maxssize); 237 oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision); 238 239 oprintf(fp, "Entry Point Revision Data:"); 240 for (i = 0; i < sizeof (ep->smbe_format); i++) 241 oprintf(fp, " 0x%02x", ep->smbe_format[i]); 242 oprintf(fp, "\n"); 243 244 oprintf(fp, "Intermediate Anchor Tag: %*.*s\n", 245 (int)sizeof (ep->smbe_ianchor), (int)sizeof (ep->smbe_ianchor), 246 ep->smbe_ianchor); 247 248 oprintf(fp, "Intermediate Checksum: 0x%x\n", ep->smbe_icksum); 249 oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen); 250 oprintf(fp, "Structure Table Address: 0x%x\n", ep->smbe_staddr); 251 oprintf(fp, "Structure Table Entries: %u\n", ep->smbe_stnum); 252 oprintf(fp, "DMI BCD Revision: 0x%x\n", ep->smbe_bcdrev); 253 } 254 255 static void 256 print_smbios_30(smbios_30_entry_t *ep, FILE *fp) 257 { 258 oprintf(fp, "Entry Point Anchor Tag: %*.*s\n", 259 (int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor), 260 ep->smbe_eanchor); 261 262 oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum); 263 oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen); 264 oprintf(fp, "SMBIOS Version: %u.%u\n", 265 ep->smbe_major, ep->smbe_minor); 266 oprintf(fp, "SMBIOS DocRev: 0x%x\n", ep->smbe_docrev); 267 oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision); 268 269 oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen); 270 oprintf(fp, "Structure Table Address: 0x%" PRIx64 "\n", 271 ep->smbe_staddr); 272 } 273 274 static void 275 print_smbios(smbios_hdl_t *shp, FILE *fp) 276 { 277 smbios_entry_t ep; 278 279 switch (smbios_info_smbios(shp, &ep)) { 280 case SMBIOS_ENTRY_POINT_21: 281 print_smbios_21(&ep.ep21, fp); 282 break; 283 case SMBIOS_ENTRY_POINT_30: 284 print_smbios_30(&ep.ep30, fp); 285 break; 286 } 287 } 288 289 static void 290 print_common(const smbios_info_t *ip, FILE *fp) 291 { 292 if (ip->smbi_manufacturer[0] != '\0') 293 oprintf(fp, " Manufacturer: %s\n", ip->smbi_manufacturer); 294 if (ip->smbi_product[0] != '\0') 295 oprintf(fp, " Product: %s\n", ip->smbi_product); 296 if (ip->smbi_version[0] != '\0') 297 oprintf(fp, " Version: %s\n", ip->smbi_version); 298 if (ip->smbi_serial[0] != '\0') 299 oprintf(fp, " Serial Number: %s\n", ip->smbi_serial); 300 if (ip->smbi_asset[0] != '\0') 301 oprintf(fp, " Asset Tag: %s\n", ip->smbi_asset); 302 if (ip->smbi_location[0] != '\0') 303 oprintf(fp, " Location Tag: %s\n", ip->smbi_location); 304 if (ip->smbi_part[0] != '\0') 305 oprintf(fp, " Part Number: %s\n", ip->smbi_part); 306 } 307 308 static void 309 print_bios(smbios_hdl_t *shp, FILE *fp) 310 { 311 smbios_bios_t b; 312 313 (void) smbios_info_bios(shp, &b); 314 315 oprintf(fp, " Vendor: %s\n", b.smbb_vendor); 316 oprintf(fp, " Version String: %s\n", b.smbb_version); 317 oprintf(fp, " Release Date: %s\n", b.smbb_reldate); 318 oprintf(fp, " Address Segment: 0x%x\n", b.smbb_segment); 319 oprintf(fp, " ROM Size: %" PRIu64 " bytes\n", b.smbb_extromsize); 320 oprintf(fp, " Image Size: %u bytes\n", b.smbb_runsize); 321 322 flag64_printf(fp, "Characteristics", 323 b.smbb_cflags, sizeof (b.smbb_cflags) * NBBY, 324 smbios_bios_flag_name, smbios_bios_flag_desc); 325 326 if (b.smbb_nxcflags > SMB_BIOSXB_1) { 327 flag_printf(fp, "Characteristics Extension Byte 1", 328 b.smbb_xcflags[SMB_BIOSXB_1], 329 sizeof (b.smbb_xcflags[SMB_BIOSXB_1]) * NBBY, 330 smbios_bios_xb1_name, smbios_bios_xb1_desc); 331 } 332 333 if (b.smbb_nxcflags > SMB_BIOSXB_2) { 334 flag_printf(fp, "Characteristics Extension Byte 2", 335 b.smbb_xcflags[SMB_BIOSXB_2], 336 sizeof (b.smbb_xcflags[SMB_BIOSXB_2]) * NBBY, 337 smbios_bios_xb2_name, smbios_bios_xb2_desc); 338 } 339 340 if (b.smbb_nxcflags > SMB_BIOSXB_BIOS_MIN) { 341 oprintf(fp, " Version Number: %u.%u\n", 342 b.smbb_biosv.smbv_major, b.smbb_biosv.smbv_minor); 343 } 344 345 /* 346 * If the major and minor versions are 0xff then that indicates that the 347 * embedded controller does not exist. 348 */ 349 if (b.smbb_nxcflags > SMB_BIOSXB_ECFW_MIN && 350 b.smbb_ecfwv.smbv_major != 0xff && 351 b.smbb_ecfwv.smbv_minor != 0xff) { 352 oprintf(fp, " Embedded Ctlr Firmware Version Number: %u.%u\n", 353 b.smbb_ecfwv.smbv_major, b.smbb_ecfwv.smbv_minor); 354 } 355 } 356 357 static void 358 print_system(smbios_hdl_t *shp, FILE *fp) 359 { 360 smbios_system_t s; 361 uint_t i; 362 363 (void) smbios_info_system(shp, &s); 364 365 oprintf(fp, " UUID: "); 366 for (i = 0; i < s.smbs_uuidlen; i++) { 367 oprintf(fp, "%02x", s.smbs_uuid[i]); 368 if (i == 3 || i == 5 || i == 7 || i == 9) 369 oprintf(fp, "-"); 370 } 371 oprintf(fp, "\n"); 372 373 desc_printf(smbios_system_wakeup_desc(s.smbs_wakeup), 374 fp, " Wake-Up Event: 0x%x", s.smbs_wakeup); 375 376 oprintf(fp, " SKU Number: %s\n", s.smbs_sku); 377 oprintf(fp, " Family: %s\n", s.smbs_family); 378 } 379 380 static void 381 print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp) 382 { 383 smbios_bboard_t b; 384 int chdl_cnt; 385 386 (void) smbios_info_bboard(shp, id, &b); 387 388 oprintf(fp, " Chassis: %u\n", (uint_t)b.smbb_chassis); 389 390 flag_printf(fp, "Flags", b.smbb_flags, sizeof (b.smbb_flags) * NBBY, 391 smbios_bboard_flag_name, smbios_bboard_flag_desc); 392 393 desc_printf(smbios_bboard_type_desc(b.smbb_type), 394 fp, " Board Type: 0x%x", b.smbb_type); 395 396 chdl_cnt = b.smbb_contn; 397 if (chdl_cnt != 0) { 398 id_t *chdl; 399 uint16_t hdl; 400 int i, n, cnt; 401 402 chdl = alloca(chdl_cnt * sizeof (id_t)); 403 cnt = smbios_info_contains(shp, id, chdl_cnt, chdl); 404 if (cnt > SMB_CONT_MAX) 405 return; 406 n = MIN(chdl_cnt, cnt); 407 408 oprintf(fp, "\n"); 409 for (i = 0; i < n; i++) { 410 hdl = (uint16_t)chdl[i]; 411 oprintf(fp, " Contained Handle: %u\n", hdl); 412 } 413 } 414 } 415 416 static void 417 print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp) 418 { 419 smbios_chassis_t c; 420 int elem_cnt; 421 422 (void) smbios_info_chassis(shp, id, &c); 423 424 oprintf(fp, " OEM Data: 0x%x\n", c.smbc_oemdata); 425 oprintf(fp, " SKU number: %s\n", 426 c.smbc_sku[0] == '\0' ? "<unknown>" : c.smbc_sku); 427 oprintf(fp, " Lock Present: %s\n", c.smbc_lock ? "Y" : "N"); 428 429 desc_printf(smbios_chassis_type_desc(c.smbc_type), 430 fp, " Chassis Type: 0x%x", c.smbc_type); 431 432 desc_printf(smbios_chassis_state_desc(c.smbc_bustate), 433 fp, " Boot-Up State: 0x%x", c.smbc_bustate); 434 435 desc_printf(smbios_chassis_state_desc(c.smbc_psstate), 436 fp, " Power Supply State: 0x%x", c.smbc_psstate); 437 438 desc_printf(smbios_chassis_state_desc(c.smbc_thstate), 439 fp, " Thermal State: 0x%x", c.smbc_thstate); 440 441 oprintf(fp, " Chassis Height: %uu\n", c.smbc_uheight); 442 oprintf(fp, " Power Cords: %u\n", c.smbc_cords); 443 444 elem_cnt = c.smbc_elems; 445 oprintf(fp, " Element Records: %u\n", elem_cnt); 446 447 if (elem_cnt > 0) { 448 id_t *elems; 449 uint8_t type; 450 int i, n, cnt; 451 452 elems = alloca(c.smbc_elems * sizeof (id_t)); 453 cnt = smbios_info_contains(shp, id, elem_cnt, elems); 454 if (cnt > SMB_CONT_MAX) 455 return; 456 n = MIN(elem_cnt, cnt); 457 458 oprintf(fp, "\n"); 459 for (i = 0; i < n; i++) { 460 type = (uint8_t)elems[i]; 461 if (type & 0x80) { 462 /* SMBIOS structrure Type */ 463 desc_printf(smbios_type_name(type & 0x7f), fp, 464 " Contained SMBIOS structure Type: %u", 465 type & 0x80); 466 } else { 467 /* SMBIOS Base Board Type */ 468 desc_printf(smbios_bboard_type_desc(type), fp, 469 " Contained SMBIOS Base Board Type: 0x%x", 470 type); 471 } 472 } 473 } 474 } 475 476 static void 477 print_processor(smbios_hdl_t *shp, id_t id, FILE *fp) 478 { 479 smbios_processor_t p; 480 uint_t status; 481 482 (void) smbios_info_processor(shp, id, &p); 483 status = SMB_PRSTATUS_STATUS(p.smbp_status); 484 485 desc_printf(smbios_processor_family_desc(p.smbp_family), 486 fp, " Family: %u", p.smbp_family); 487 488 if (p.smbp_family2 != 0) 489 desc_printf(smbios_processor_family_desc(p.smbp_family2), 490 fp, " Family Ext: %u", p.smbp_family2); 491 492 oprintf(fp, " CPUID: 0x%llx\n", (u_longlong_t)p.smbp_cpuid); 493 494 desc_printf(smbios_processor_type_desc(p.smbp_type), 495 fp, " Type: %u", p.smbp_type); 496 497 desc_printf(smbios_processor_upgrade_desc(p.smbp_upgrade), 498 fp, " Socket Upgrade: %u", p.smbp_upgrade); 499 500 oprintf(fp, " Socket Status: %s\n", 501 SMB_PRSTATUS_PRESENT(p.smbp_status) ? 502 "Populated" : "Not Populated"); 503 504 desc_printf(smbios_processor_status_desc(status), 505 fp, " Processor Status: %u", status); 506 507 if (SMB_PRV_LEGACY(p.smbp_voltage)) { 508 oprintf(fp, " Supported Voltages:"); 509 switch (p.smbp_voltage) { 510 case SMB_PRV_5V: 511 oprintf(fp, " 5.0V"); 512 break; 513 case SMB_PRV_33V: 514 oprintf(fp, " 3.3V"); 515 break; 516 case SMB_PRV_29V: 517 oprintf(fp, " 2.9V"); 518 break; 519 } 520 oprintf(fp, "\n"); 521 } else { 522 oprintf(fp, " Supported Voltages: %.1fV\n", 523 (float)SMB_PRV_VOLTAGE(p.smbp_voltage) / 10); 524 } 525 526 if (p.smbp_corecount != 0) { 527 if (p.smbp_corecount != 0xff || p.smbp_corecount2 == 0) 528 oprintf(fp, " Core Count: %u\n", p.smbp_corecount); 529 else 530 oprintf(fp, " Core Count: %u\n", p.smbp_corecount2); 531 } else { 532 oprintf(fp, " Core Count: Unknown\n"); 533 } 534 535 if (p.smbp_coresenabled != 0) { 536 if (p.smbp_coresenabled != 0xff || p.smbp_coresenabled2 == 0) { 537 oprintf(fp, " Cores Enabled: %u\n", 538 p.smbp_coresenabled); 539 } else { 540 oprintf(fp, " Cores Enabled: %u\n", 541 p.smbp_coresenabled2); 542 } 543 } else { 544 oprintf(fp, " Cores Enabled: Unknown\n"); 545 } 546 547 if (p.smbp_threadcount != 0) { 548 if (p.smbp_threadcount != 0xff || p.smbp_threadcount2 == 0) { 549 oprintf(fp, " Thread Count: %u\n", 550 p.smbp_threadcount); 551 } else { 552 oprintf(fp, " Thread Count: %u\n", 553 p.smbp_threadcount2); 554 } 555 } else { 556 oprintf(fp, " Thread Count: Unknown\n"); 557 } 558 559 if (p.smbp_cflags) { 560 flag_printf(fp, "Processor Characteristics", 561 p.smbp_cflags, sizeof (p.smbp_cflags) * NBBY, 562 smbios_processor_core_flag_name, 563 smbios_processor_core_flag_desc); 564 } 565 566 if (p.smbp_clkspeed != 0) 567 oprintf(fp, " External Clock Speed: %uMHz\n", p.smbp_clkspeed); 568 else 569 oprintf(fp, " External Clock Speed: Unknown\n"); 570 571 if (p.smbp_maxspeed != 0) 572 oprintf(fp, " Maximum Speed: %uMHz\n", p.smbp_maxspeed); 573 else 574 oprintf(fp, " Maximum Speed: Unknown\n"); 575 576 if (p.smbp_curspeed != 0) 577 oprintf(fp, " Current Speed: %uMHz\n", p.smbp_curspeed); 578 else 579 oprintf(fp, " Current Speed: Unknown\n"); 580 581 id_printf(fp, " L1 Cache Handle: ", p.smbp_l1cache); 582 id_printf(fp, " L2 Cache Handle: ", p.smbp_l2cache); 583 id_printf(fp, " L3 Cache Handle: ", p.smbp_l3cache); 584 } 585 586 static void 587 print_cache(smbios_hdl_t *shp, id_t id, FILE *fp) 588 { 589 smbios_cache_t c; 590 591 (void) smbios_info_cache(shp, id, &c); 592 593 oprintf(fp, " Level: %u\n", c.smba_level); 594 oprintf(fp, " Maximum Installed Size: %" PRIu64 " bytes\n", 595 c.smba_maxsize2); 596 597 if (c.smba_size2 != 0) { 598 oprintf(fp, " Installed Size: %" PRIu64 " bytes\n", 599 c.smba_size2); 600 } else { 601 oprintf(fp, " Installed Size: Not Installed\n"); 602 } 603 604 if (c.smba_speed != 0) 605 oprintf(fp, " Speed: %uns\n", c.smba_speed); 606 else 607 oprintf(fp, " Speed: Unknown\n"); 608 609 flag_printf(fp, "Supported SRAM Types", 610 c.smba_stype, sizeof (c.smba_stype) * NBBY, 611 smbios_cache_ctype_name, smbios_cache_ctype_desc); 612 613 desc_printf(smbios_cache_ctype_desc(c.smba_ctype), 614 fp, " Current SRAM Type: 0x%x", c.smba_ctype); 615 616 desc_printf(smbios_cache_ecc_desc(c.smba_etype), 617 fp, " Error Correction Type: %u", c.smba_etype); 618 619 desc_printf(smbios_cache_logical_desc(c.smba_ltype), 620 fp, " Logical Cache Type: %u", c.smba_ltype); 621 622 desc_printf(smbios_cache_assoc_desc(c.smba_assoc), 623 fp, " Associativity: %u", c.smba_assoc); 624 625 desc_printf(smbios_cache_mode_desc(c.smba_mode), 626 fp, " Mode: %u", c.smba_mode); 627 628 desc_printf(smbios_cache_loc_desc(c.smba_location), 629 fp, " Location: %u", c.smba_location); 630 631 flag_printf(fp, "Flags", c.smba_flags, sizeof (c.smba_flags) * NBBY, 632 smbios_cache_flag_name, smbios_cache_flag_desc); 633 } 634 635 static void 636 print_port(smbios_hdl_t *shp, id_t id, FILE *fp) 637 { 638 smbios_port_t p; 639 640 (void) smbios_info_port(shp, id, &p); 641 642 oprintf(fp, " Internal Reference Designator: %s\n", p.smbo_iref); 643 oprintf(fp, " External Reference Designator: %s\n", p.smbo_eref); 644 645 desc_printf(smbios_port_conn_desc(p.smbo_itype), 646 fp, " Internal Connector Type: %u", p.smbo_itype); 647 648 desc_printf(smbios_port_conn_desc(p.smbo_etype), 649 fp, " External Connector Type: %u", p.smbo_etype); 650 651 desc_printf(smbios_port_type_desc(p.smbo_ptype), 652 fp, " Port Type: %u", p.smbo_ptype); 653 } 654 655 static void 656 print_slot(smbios_hdl_t *shp, id_t id, FILE *fp) 657 { 658 smbios_slot_t s; 659 smbios_version_t v; 660 661 (void) smbios_info_slot(shp, id, &s); 662 smbios_info_smbios_version(shp, &v); 663 664 oprintf(fp, " Reference Designator: %s\n", s.smbl_name); 665 oprintf(fp, " Slot ID: 0x%x\n", s.smbl_id); 666 667 desc_printf(smbios_slot_type_desc(s.smbl_type), 668 fp, " Type: 0x%x", s.smbl_type); 669 670 desc_printf(smbios_slot_width_desc(s.smbl_width), 671 fp, " Width: 0x%x", s.smbl_width); 672 673 desc_printf(smbios_slot_usage_desc(s.smbl_usage), 674 fp, " Usage: 0x%x", s.smbl_usage); 675 676 desc_printf(smbios_slot_length_desc(s.smbl_length), 677 fp, " Length: 0x%x", s.smbl_length); 678 679 flag_printf(fp, "Slot Characteristics 1", 680 s.smbl_ch1, sizeof (s.smbl_ch1) * NBBY, 681 smbios_slot_ch1_name, smbios_slot_ch1_desc); 682 683 flag_printf(fp, "Slot Characteristics 2", 684 s.smbl_ch2, sizeof (s.smbl_ch2) * NBBY, 685 smbios_slot_ch2_name, smbios_slot_ch2_desc); 686 687 if (check_oem(shp) != 0 && !smbios_vergteq(&v, 2, 6)) 688 return; 689 690 oprintf(fp, " Segment Group: %u\n", s.smbl_sg); 691 oprintf(fp, " Bus Number: %u\n", s.smbl_bus); 692 oprintf(fp, " Device/Function Number: %u/%u\n", s.smbl_df >> 3, 693 s.smbl_df & 0x7); 694 695 if (s.smbl_dbw != 0) { 696 oprintf(fp, " Data Bus Width: %d\n", s.smbl_dbw); 697 } 698 699 if (s.smbl_npeers > 0) { 700 smbios_slot_peer_t *peer; 701 uint_t i, npeers; 702 703 if (smbios_info_slot_peers(shp, id, &npeers, &peer) != 0) { 704 smbios_warn(shp, "failed to read slot peer " 705 "information"); 706 return; 707 } 708 709 for (i = 0; i < npeers; i++) { 710 oprintf(fp, " Slot Peer %u:\n", i); 711 oprintf(fp, " Segment group: %u\n", 712 peer[i].smblp_group); 713 oprintf(fp, " Bus/Device/Function: %u/%u/%u", 714 peer[i].smblp_bus, peer[i].smblp_device, 715 peer[i].smblp_function); 716 oprintf(fp, " Electrical width: %u\n", 717 peer[i].smblp_data_width); 718 } 719 720 smbios_info_slot_peers_free(shp, npeers, peer); 721 } 722 } 723 724 static void 725 print_obdevs_ext(smbios_hdl_t *shp, id_t id, FILE *fp) 726 { 727 boolean_t enabled; 728 smbios_obdev_ext_t oe; 729 const char *type; 730 731 (void) smbios_info_obdevs_ext(shp, id, &oe); 732 733 /* 734 * Bit 7 is always whether or not the device is enabled while bits 0:6 735 * are the actual device type. 736 */ 737 enabled = oe.smboe_dtype >> 7; 738 type = smbios_onboard_type_desc(oe.smboe_dtype & 0x7f); 739 740 oprintf(fp, " Reference Designator: %s\n", oe.smboe_name); 741 oprintf(fp, " Device Enabled: %s\n", enabled == B_TRUE ? "true" : 742 "false"); 743 oprintf(fp, " Device Type: %s\n", type); 744 oprintf(fp, " Device Type Instance: %u\n", oe.smboe_dti); 745 oprintf(fp, " Segment Group Number: %u\n", oe.smboe_sg); 746 oprintf(fp, " Bus Number: %u\n", oe.smboe_bus); 747 oprintf(fp, " Device/Function Number: %u\n", oe.smboe_df); 748 } 749 750 static void 751 print_obdevs(smbios_hdl_t *shp, id_t id, FILE *fp) 752 { 753 smbios_obdev_t *argv; 754 int i, argc; 755 756 if ((argc = smbios_info_obdevs(shp, id, 0, NULL)) > 0) { 757 argv = alloca(sizeof (smbios_obdev_t) * argc); 758 (void) smbios_info_obdevs(shp, id, argc, argv); 759 for (i = 0; i < argc; i++) 760 oprintf(fp, " %s\n", argv[i].smbd_name); 761 } 762 } 763 764 static void 765 print_strtab(smbios_hdl_t *shp, id_t id, FILE *fp) 766 { 767 const char **argv; 768 int i, argc; 769 770 if ((argc = smbios_info_strtab(shp, id, 0, NULL)) > 0) { 771 argv = alloca(sizeof (char *) * argc); 772 (void) smbios_info_strtab(shp, id, argc, argv); 773 for (i = 0; i < argc; i++) 774 oprintf(fp, " %s\n", argv[i]); 775 } 776 } 777 778 static void 779 print_lang(smbios_hdl_t *shp, id_t id, FILE *fp) 780 { 781 smbios_lang_t l; 782 783 (void) smbios_info_lang(shp, &l); 784 785 oprintf(fp, " Current Language: %s\n", l.smbla_cur); 786 oprintf(fp, " Language String Format: %u\n", l.smbla_fmt); 787 oprintf(fp, " Number of Installed Languages: %u\n", l.smbla_num); 788 oprintf(fp, " Installed Languages:\n"); 789 790 print_strtab(shp, id, fp); 791 } 792 793 /*ARGSUSED*/ 794 static void 795 print_evlog(smbios_hdl_t *shp, id_t id, FILE *fp) 796 { 797 smbios_evlog_t ev; 798 uint32_t i; 799 800 (void) smbios_info_eventlog(shp, &ev); 801 802 oprintf(fp, " Log Area Size: %lu bytes\n", (ulong_t)ev.smbev_size); 803 oprintf(fp, " Header Offset: %lu\n", (ulong_t)ev.smbev_hdr); 804 oprintf(fp, " Data Offset: %lu\n", (ulong_t)ev.smbev_data); 805 806 desc_printf(smbios_evlog_method_desc(ev.smbev_method), 807 fp, " Data Access Method: %u", ev.smbev_method); 808 809 flag_printf(fp, "Log Flags", 810 ev.smbev_flags, sizeof (ev.smbev_flags) * NBBY, 811 smbios_evlog_flag_name, smbios_evlog_flag_desc); 812 813 desc_printf(smbios_evlog_format_desc(ev.smbev_format), 814 fp, " Log Header Format: %u", ev.smbev_format); 815 816 oprintf(fp, " Update Token: 0x%x\n", ev.smbev_token); 817 oprintf(fp, " Data Access Address: "); 818 819 switch (ev.smbev_method) { 820 case SMB_EVM_1x1i_1x1d: 821 case SMB_EVM_2x1i_1x1d: 822 case SMB_EVM_1x2i_1x1d: 823 oprintf(fp, "Index Address 0x%x, Data Address 0x%x\n", 824 ev.smbev_addr.eva_io.evi_iaddr, 825 ev.smbev_addr.eva_io.evi_daddr); 826 break; 827 case SMB_EVM_GPNV: 828 oprintf(fp, "0x%x\n", ev.smbev_addr.eva_gpnv); 829 break; 830 default: 831 oprintf(fp, "0x%x\n", ev.smbev_addr.eva_addr); 832 } 833 834 oprintf(fp, " Type Descriptors:\n"); 835 836 for (i = 0; i < ev.smbev_typec; i++) { 837 oprintf(fp, " %u: Log Type 0x%x, Data Type 0x%x\n", i, 838 ev.smbev_typev[i].smbevt_ltype, 839 ev.smbev_typev[i].smbevt_dtype); 840 } 841 } 842 843 static void 844 print_bytes(const uint8_t *data, size_t size, FILE *fp) 845 { 846 size_t row, rows = P2ROUNDUP(size, 16) / 16; 847 size_t col, cols; 848 849 char buf[17]; 850 uint8_t x; 851 852 oprintf(fp, "\n offset: 0 1 2 3 4 5 6 7 8 9 a b c d e f " 853 "0123456789abcdef\n"); 854 855 for (row = 0; row < rows; row++) { 856 oprintf(fp, " %#6lx: ", (ulong_t)row * 16); 857 cols = MIN(size - row * 16, 16); 858 859 for (col = 0; col < cols; col++) { 860 if (col % 4 == 0) 861 oprintf(fp, " "); 862 x = *data++; 863 oprintf(fp, "%02x", x); 864 buf[col] = x <= ' ' || x > '~' ? '.' : x; 865 } 866 867 for (; col < 16; col++) { 868 if (col % 4 == 0) 869 oprintf(fp, " "); 870 oprintf(fp, " "); 871 buf[col] = ' '; 872 } 873 874 buf[col] = '\0'; 875 oprintf(fp, " %s\n", buf); 876 } 877 878 oprintf(fp, "\n"); 879 } 880 881 static void 882 print_memarray(smbios_hdl_t *shp, id_t id, FILE *fp) 883 { 884 smbios_memarray_t ma; 885 886 (void) smbios_info_memarray(shp, id, &ma); 887 888 desc_printf(smbios_memarray_loc_desc(ma.smbma_location), 889 fp, " Location: %u", ma.smbma_location); 890 891 desc_printf(smbios_memarray_use_desc(ma.smbma_use), 892 fp, " Use: %u", ma.smbma_use); 893 894 desc_printf(smbios_memarray_ecc_desc(ma.smbma_ecc), 895 fp, " ECC: %u", ma.smbma_ecc); 896 897 oprintf(fp, " Number of Slots/Sockets: %u\n", ma.smbma_ndevs); 898 id_printf(fp, " Memory Error Data: ", ma.smbma_err); 899 oprintf(fp, " Max Capacity: %llu bytes\n", 900 (u_longlong_t)ma.smbma_size); 901 } 902 903 static void 904 print_memdevice(smbios_hdl_t *shp, id_t id, FILE *fp) 905 { 906 smbios_memdevice_t md; 907 908 (void) smbios_info_memdevice(shp, id, &md); 909 910 id_printf(fp, " Physical Memory Array: ", md.smbmd_array); 911 id_printf(fp, " Memory Error Data: ", md.smbmd_error); 912 913 if (md.smbmd_twidth != -1u) 914 oprintf(fp, " Total Width: %u bits\n", md.smbmd_twidth); 915 else 916 oprintf(fp, " Total Width: Unknown\n"); 917 918 if (md.smbmd_dwidth != -1u) 919 oprintf(fp, " Data Width: %u bits\n", md.smbmd_dwidth); 920 else 921 oprintf(fp, " Data Width: Unknown\n"); 922 923 switch (md.smbmd_size) { 924 case -1ull: 925 oprintf(fp, " Size: Unknown\n"); 926 break; 927 case 0: 928 oprintf(fp, " Size: Not Populated\n"); 929 break; 930 default: 931 oprintf(fp, " Size: %llu bytes\n", 932 (u_longlong_t)md.smbmd_size); 933 } 934 935 desc_printf(smbios_memdevice_form_desc(md.smbmd_form), 936 fp, " Form Factor: %u", md.smbmd_form); 937 938 if (md.smbmd_set == 0) 939 oprintf(fp, " Set: None\n"); 940 else if (md.smbmd_set == (uint8_t)-1u) 941 oprintf(fp, " Set: Unknown\n"); 942 else 943 oprintf(fp, " Set: %u\n", md.smbmd_set); 944 945 if (md.smbmd_rank != 0) { 946 desc_printf(smbios_memdevice_rank_desc(md.smbmd_rank), 947 fp, " Rank: %u", md.smbmd_rank); 948 } else { 949 oprintf(fp, " Rank: Unknown\n"); 950 } 951 952 desc_printf(smbios_memdevice_type_desc(md.smbmd_type), 953 fp, " Memory Type: %u", md.smbmd_type); 954 955 flag_printf(fp, "Flags", md.smbmd_flags, sizeof (md.smbmd_flags) * NBBY, 956 smbios_memdevice_flag_name, smbios_memdevice_flag_desc); 957 958 if (md.smbmd_speed != 0) 959 oprintf(fp, " Speed: %u MT/s\n", md.smbmd_speed); 960 else 961 oprintf(fp, " Speed: Unknown\n"); 962 963 if (md.smbmd_clkspeed != 0) 964 oprintf(fp, " Configured Speed: %u MT/s\n", md.smbmd_clkspeed); 965 else 966 oprintf(fp, " Configured Speed: Unknown\n"); 967 968 oprintf(fp, " Device Locator: %s\n", md.smbmd_dloc); 969 oprintf(fp, " Bank Locator: %s\n", md.smbmd_bloc); 970 971 if (md.smbmd_minvolt != 0) { 972 oprintf(fp, " Minimum Voltage: %.2fV\n", 973 md.smbmd_minvolt / 1000.0); 974 } else { 975 oprintf(fp, " Minimum Voltage: Unknown\n"); 976 } 977 978 if (md.smbmd_maxvolt != 0) { 979 oprintf(fp, " Maximum Voltage: %.2fV\n", 980 md.smbmd_maxvolt / 1000.0); 981 } else { 982 oprintf(fp, " Maximum Voltage: Unknown\n"); 983 } 984 985 if (md.smbmd_confvolt != 0) { 986 oprintf(fp, " Configured Voltage: %.2fV\n", 987 md.smbmd_confvolt / 1000.0); 988 } else { 989 oprintf(fp, " Configured Voltage: Unknown\n"); 990 } 991 992 if (md.smbmd_memtech != 0) { 993 desc_printf(smbios_memdevice_memtech_desc(md.smbmd_memtech), 994 fp, " Memory Technology: %u", md.smbmd_memtech); 995 } 996 997 if (md.smbmd_opcap_flags != 0) { 998 flag_printf(fp, " Operating Mode Capabilities", 999 md.smbmd_opcap_flags, sizeof (md.smbmd_opcap_flags) * NBBY, 1000 smbios_memdevice_op_capab_name, 1001 smbios_memdevice_op_capab_desc); 1002 } 1003 1004 if (md.smbmd_firmware_rev[0] != '\0') { 1005 oprintf(fp, " Firmware Revision: %s\n", md.smbmd_firmware_rev); 1006 } 1007 1008 if (md.smbmd_modmfg_id != 0) { 1009 jedec_print(fp, "Module Manufacturer ID", md.smbmd_modmfg_id); 1010 } 1011 1012 if (md.smbmd_modprod_id != 0) { 1013 jedec_print(fp, "Module Product ID", md.smbmd_modprod_id); 1014 } 1015 1016 if (md.smbmd_cntrlmfg_id != 0) { 1017 jedec_print(fp, "Memory Subsystem Controller Manufacturer ID", 1018 md.smbmd_cntrlmfg_id); 1019 } 1020 1021 if (md.smbmd_cntrlprod_id != 0) { 1022 jedec_print(fp, "Memory Subsystem Controller Product ID", 1023 md.smbmd_cntrlprod_id); 1024 } 1025 1026 if (md.smbmd_nvsize == UINT64_MAX) { 1027 oprintf(fp, " Non-volatile Size: Unknown\n"); 1028 } else if (md.smbmd_nvsize != 0) { 1029 oprintf(fp, " Non-volatile Size: %llu bytes\n", 1030 (u_longlong_t)md.smbmd_nvsize); 1031 } 1032 1033 if (md.smbmd_volatile_size == UINT64_MAX) { 1034 oprintf(fp, " Volatile Size: Unknown\n"); 1035 } else if (md.smbmd_volatile_size != 0) { 1036 oprintf(fp, " Volatile Size: %llu bytes\n", 1037 (u_longlong_t)md.smbmd_volatile_size); 1038 } 1039 1040 if (md.smbmd_cache_size == UINT64_MAX) { 1041 oprintf(fp, " Cache Size: Unknown\n"); 1042 } else if (md.smbmd_cache_size != 0) { 1043 oprintf(fp, " Cache Size: %llu bytes\n", 1044 (u_longlong_t)md.smbmd_cache_size); 1045 } 1046 1047 if (md.smbmd_logical_size == UINT64_MAX) { 1048 oprintf(fp, " Logical Size: Unknown\n"); 1049 } else if (md.smbmd_logical_size != 0) { 1050 oprintf(fp, " Logical Size: %llu bytes\n", 1051 (u_longlong_t)md.smbmd_logical_size); 1052 } 1053 } 1054 1055 static void 1056 print_memarrmap(smbios_hdl_t *shp, id_t id, FILE *fp) 1057 { 1058 smbios_memarrmap_t ma; 1059 1060 (void) smbios_info_memarrmap(shp, id, &ma); 1061 1062 id_printf(fp, " Physical Memory Array: ", ma.smbmam_array); 1063 oprintf(fp, " Devices per Row: %u\n", ma.smbmam_width); 1064 1065 oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n", 1066 (u_longlong_t)ma.smbmam_addr, (u_longlong_t)ma.smbmam_size); 1067 } 1068 1069 static void 1070 print_memdevmap(smbios_hdl_t *shp, id_t id, FILE *fp) 1071 { 1072 smbios_memdevmap_t md; 1073 1074 (void) smbios_info_memdevmap(shp, id, &md); 1075 1076 id_printf(fp, " Memory Device: ", md.smbmdm_device); 1077 id_printf(fp, " Memory Array Mapped Address: ", md.smbmdm_arrmap); 1078 1079 oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n", 1080 (u_longlong_t)md.smbmdm_addr, (u_longlong_t)md.smbmdm_size); 1081 1082 oprintf(fp, " Partition Row Position: %u\n", md.smbmdm_rpos); 1083 oprintf(fp, " Interleave Position: %u\n", md.smbmdm_ipos); 1084 oprintf(fp, " Interleave Data Depth: %u\n", md.smbmdm_idepth); 1085 } 1086 1087 static void 1088 print_hwsec(smbios_hdl_t *shp, FILE *fp) 1089 { 1090 smbios_hwsec_t h; 1091 1092 (void) smbios_info_hwsec(shp, &h); 1093 1094 desc_printf(smbios_hwsec_desc(h.smbh_pwr_ps), 1095 fp, " Power-On Password Status: %u", h.smbh_pwr_ps); 1096 desc_printf(smbios_hwsec_desc(h.smbh_kbd_ps), 1097 fp, " Keyboard Password Status: %u", h.smbh_kbd_ps); 1098 desc_printf(smbios_hwsec_desc(h.smbh_adm_ps), 1099 fp, " Administrator Password Status: %u", h.smbh_adm_ps); 1100 desc_printf(smbios_hwsec_desc(h.smbh_pan_ps), 1101 fp, " Front Panel Reset Status: %u", h.smbh_pan_ps); 1102 } 1103 1104 static void 1105 print_vprobe(smbios_hdl_t *shp, id_t id, FILE *fp) 1106 { 1107 smbios_vprobe_t vp; 1108 1109 if (smbios_info_vprobe(shp, id, &vp) != 0) { 1110 smbios_warn(shp, "failed to read voltage probe information"); 1111 return; 1112 } 1113 1114 oprintf(fp, " Description: %s\n", vp.smbvp_description != NULL ? 1115 vp.smbvp_description : "unknown"); 1116 desc_printf(smbios_vprobe_loc_desc(vp.smbvp_location), 1117 fp, " Location: %u", vp.smbvp_location); 1118 desc_printf(smbios_vprobe_status_desc(vp.smbvp_status), 1119 fp, " Status: %u", vp.smbvp_status); 1120 1121 if (vp.smbvp_maxval != SMB_PROBE_UNKNOWN_VALUE) { 1122 oprintf(fp, " Maximum Possible Voltage: %u mV\n", 1123 vp.smbvp_maxval); 1124 } else { 1125 oprintf(fp, " Maximum Possible Voltage: unknown\n"); 1126 } 1127 1128 if (vp.smbvp_minval != SMB_PROBE_UNKNOWN_VALUE) { 1129 oprintf(fp, " Minimum Possible Voltage: %u mV\n", 1130 vp.smbvp_minval); 1131 } else { 1132 oprintf(fp, " Minimum Possible Voltage: unknown\n"); 1133 } 1134 1135 if (vp.smbvp_resolution != SMB_PROBE_UNKNOWN_VALUE) { 1136 oprintf(fp, " Probe Resolution: %u.%u mV\n", 1137 vp.smbvp_resolution / 10, 1138 vp.smbvp_resolution % 10); 1139 } else { 1140 oprintf(fp, " Probe Resolution: unknown\n"); 1141 } 1142 1143 if (vp.smbvp_tolerance != SMB_PROBE_UNKNOWN_VALUE) { 1144 oprintf(fp, " Probe Tolerance: +/-%u mV\n", 1145 vp.smbvp_tolerance); 1146 } else { 1147 oprintf(fp, " Probe Tolerance: unknown\n"); 1148 } 1149 1150 if (vp.smbvp_accuracy != SMB_PROBE_UNKNOWN_VALUE) { 1151 oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n", 1152 vp.smbvp_accuracy / 100, 1153 vp.smbvp_accuracy % 100); 1154 } else { 1155 oprintf(fp, " Probe Accuracy: unknown\n"); 1156 } 1157 1158 oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", vp.smbvp_oem); 1159 1160 if (vp.smbvp_nominal != SMB_PROBE_UNKNOWN_VALUE) { 1161 oprintf(fp, " Probe Nominal Value: %u mV\n", vp.smbvp_nominal); 1162 } else { 1163 oprintf(fp, " Probe Nominal Value: unknown\n"); 1164 } 1165 } 1166 1167 static void 1168 print_cooldev(smbios_hdl_t *shp, id_t id, FILE *fp) 1169 { 1170 smbios_cooldev_t cd; 1171 1172 if (smbios_info_cooldev(shp, id, &cd) != 0) { 1173 smbios_warn(shp, "failed to read cooling device " 1174 "information"); 1175 return; 1176 } 1177 1178 id_printf(fp, " Temperature Probe Handle: ", cd.smbcd_tprobe); 1179 desc_printf(smbios_cooldev_type_desc(cd.smbcd_type), 1180 fp, " Device Type: %u", cd.smbcd_type); 1181 desc_printf(smbios_cooldev_status_desc(cd.smbcd_status), 1182 fp, " Status: %u", cd.smbcd_status); 1183 oprintf(fp, " Cooling Unit Group: %u\n", cd.smbcd_group); 1184 oprintf(fp, " OEM- or BIOS- defined data: 0x%x\n", cd.smbcd_oem); 1185 if (cd.smbcd_nominal != SMB_PROBE_UNKNOWN_VALUE) { 1186 oprintf(fp, " Nominal Speed: %u RPM\n", cd.smbcd_nominal); 1187 } else { 1188 oprintf(fp, " Nominal Speed: unknown\n"); 1189 } 1190 1191 if (cd.smbcd_descr != NULL && cd.smbcd_descr[0] != '\0') { 1192 oprintf(fp, " Description: %s\n", cd.smbcd_descr); 1193 } 1194 } 1195 1196 static void 1197 print_tprobe(smbios_hdl_t *shp, id_t id, FILE *fp) 1198 { 1199 smbios_tprobe_t tp; 1200 1201 if (smbios_info_tprobe(shp, id, &tp) != 0) { 1202 smbios_warn(shp, "failed to read temperature probe " 1203 "information"); 1204 return; 1205 } 1206 1207 oprintf(fp, " Description: %s\n", tp.smbtp_description != NULL ? 1208 tp.smbtp_description : "unknown"); 1209 desc_printf(smbios_tprobe_loc_desc(tp.smbtp_location), 1210 fp, " Location: %u", tp.smbtp_location); 1211 desc_printf(smbios_tprobe_status_desc(tp.smbtp_status), 1212 fp, " Status: %u", tp.smbtp_status); 1213 1214 if (tp.smbtp_maxval != SMB_PROBE_UNKNOWN_VALUE) { 1215 oprintf(fp, " Maximum Possible Temperature: %u.%u C\n", 1216 tp.smbtp_maxval / 10, tp.smbtp_maxval % 10); 1217 } else { 1218 oprintf(fp, " Maximum Possible Temperature: unknown\n"); 1219 } 1220 1221 if (tp.smbtp_minval != SMB_PROBE_UNKNOWN_VALUE) { 1222 oprintf(fp, " Minimum Possible Temperature: %u.%u C\n", 1223 tp.smbtp_minval / 10, tp.smbtp_minval % 10); 1224 } else { 1225 oprintf(fp, " Minimum Possible Temperature: unknown\n"); 1226 } 1227 1228 if (tp.smbtp_resolution != SMB_PROBE_UNKNOWN_VALUE) { 1229 oprintf(fp, " Probe Resolution: %u.%03u C\n", 1230 tp.smbtp_resolution / 1000, 1231 tp.smbtp_resolution % 1000); 1232 } else { 1233 oprintf(fp, " Probe Resolution: unknown\n"); 1234 } 1235 1236 if (tp.smbtp_tolerance != SMB_PROBE_UNKNOWN_VALUE) { 1237 oprintf(fp, " Probe Tolerance: +/-%u.%u C\n", 1238 tp.smbtp_tolerance / 10, tp.smbtp_tolerance % 10); 1239 } else { 1240 oprintf(fp, " Probe Tolerance: unknown\n"); 1241 } 1242 1243 if (tp.smbtp_accuracy != SMB_PROBE_UNKNOWN_VALUE) { 1244 oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n", 1245 tp.smbtp_accuracy / 100, 1246 tp.smbtp_accuracy % 100); 1247 } else { 1248 oprintf(fp, " Probe Accuracy: unknown\n"); 1249 } 1250 1251 oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", tp.smbtp_oem); 1252 1253 if (tp.smbtp_nominal != SMB_PROBE_UNKNOWN_VALUE) { 1254 oprintf(fp, " Probe Nominal Value: %u.%u C\n", 1255 tp.smbtp_nominal / 10, tp.smbtp_nominal % 10); 1256 } else { 1257 oprintf(fp, " Probe Nominal Value: unknown\n"); 1258 } 1259 } 1260 1261 static void 1262 print_iprobe(smbios_hdl_t *shp, id_t id, FILE *fp) 1263 { 1264 smbios_iprobe_t ip; 1265 1266 if (smbios_info_iprobe(shp, id, &ip) != 0) { 1267 smbios_warn(shp, "failed to read current probe information"); 1268 return; 1269 } 1270 1271 oprintf(fp, " Description: %s\n", ip.smbip_description != NULL ? 1272 ip.smbip_description : "unknown"); 1273 desc_printf(smbios_iprobe_loc_desc(ip.smbip_location), 1274 fp, " Location: %u", ip.smbip_location); 1275 desc_printf(smbios_iprobe_status_desc(ip.smbip_status), 1276 fp, " Status: %u", ip.smbip_status); 1277 1278 if (ip.smbip_maxval != SMB_PROBE_UNKNOWN_VALUE) { 1279 oprintf(fp, " Maximum Possible Current: %u mA\n", 1280 ip.smbip_maxval); 1281 } else { 1282 oprintf(fp, " Maximum Possible Current: unknown\n"); 1283 } 1284 1285 if (ip.smbip_minval != SMB_PROBE_UNKNOWN_VALUE) { 1286 oprintf(fp, " Minimum Possible Current: %u mA\n", 1287 ip.smbip_minval); 1288 } else { 1289 oprintf(fp, " Minimum Possible Current: unknown\n"); 1290 } 1291 1292 if (ip.smbip_resolution != SMB_PROBE_UNKNOWN_VALUE) { 1293 oprintf(fp, " Probe Resolution: %u.%u mA\n", 1294 ip.smbip_resolution / 10, 1295 ip.smbip_resolution % 10); 1296 } else { 1297 oprintf(fp, " Probe Resolution: unknown\n"); 1298 } 1299 1300 if (ip.smbip_tolerance != SMB_PROBE_UNKNOWN_VALUE) { 1301 oprintf(fp, " Probe Tolerance: +/-%u mA\n", 1302 ip.smbip_tolerance); 1303 } else { 1304 oprintf(fp, " Probe Tolerance: unknown\n"); 1305 } 1306 1307 if (ip.smbip_accuracy != SMB_PROBE_UNKNOWN_VALUE) { 1308 oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n", 1309 ip.smbip_accuracy / 100, 1310 ip.smbip_accuracy % 100); 1311 } else { 1312 oprintf(fp, " Probe Accuracy: unknown\n"); 1313 } 1314 1315 oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", ip.smbip_oem); 1316 1317 if (ip.smbip_nominal != SMB_PROBE_UNKNOWN_VALUE) { 1318 oprintf(fp, " Probe Nominal Value: %u mA\n", ip.smbip_nominal); 1319 } else { 1320 oprintf(fp, " Probe Nominal Value: unknown\n"); 1321 } 1322 } 1323 1324 1325 static void 1326 print_boot(smbios_hdl_t *shp, FILE *fp) 1327 { 1328 smbios_boot_t b; 1329 1330 (void) smbios_info_boot(shp, &b); 1331 1332 desc_printf(smbios_boot_desc(b.smbt_status), 1333 fp, " Boot Status Code: 0x%x", b.smbt_status); 1334 1335 if (b.smbt_size != 0) { 1336 oprintf(fp, " Boot Data (%lu bytes):\n", (ulong_t)b.smbt_size); 1337 print_bytes(b.smbt_data, b.smbt_size, fp); 1338 } 1339 } 1340 1341 static void 1342 print_ipmi(smbios_hdl_t *shp, FILE *fp) 1343 { 1344 smbios_ipmi_t i; 1345 1346 (void) smbios_info_ipmi(shp, &i); 1347 1348 desc_printf(smbios_ipmi_type_desc(i.smbip_type), 1349 fp, " Type: %u", i.smbip_type); 1350 1351 oprintf(fp, " BMC IPMI Version: %u.%u\n", 1352 i.smbip_vers.smbv_major, i.smbip_vers.smbv_minor); 1353 1354 oprintf(fp, " i2c Bus Slave Address: 0x%x\n", i.smbip_i2c); 1355 oprintf(fp, " NV Storage Device Bus ID: 0x%x\n", i.smbip_bus); 1356 oprintf(fp, " BMC Base Address: 0x%llx\n", (u_longlong_t)i.smbip_addr); 1357 oprintf(fp, " Interrupt Number: %u\n", i.smbip_intr); 1358 oprintf(fp, " Register Spacing: %u\n", i.smbip_regspacing); 1359 1360 flag_printf(fp, "Flags", i.smbip_flags, sizeof (i.smbip_flags) * NBBY, 1361 smbios_ipmi_flag_name, smbios_ipmi_flag_desc); 1362 } 1363 1364 static void 1365 print_powersup(smbios_hdl_t *shp, id_t id, FILE *fp) 1366 { 1367 smbios_powersup_t p; 1368 1369 if (smbios_info_powersup(shp, id, &p) != 0) { 1370 smbios_warn(shp, "failed to read power supply information"); 1371 return; 1372 } 1373 1374 oprintf(fp, " Power Supply Group: %u\n", p.smbps_group); 1375 if (p.smbps_maxout != 0x8000) { 1376 oprintf(fp, " Maximum Output: %llu mW\n", p.smbps_maxout); 1377 } else { 1378 oprintf(fp, " Maximum Output: unknown\n"); 1379 } 1380 1381 flag_printf(fp, "Characteristics", p.smbps_flags, 1382 sizeof (p.smbps_flags) * NBBY, smbios_powersup_flag_name, 1383 smbios_powersup_flag_desc); 1384 1385 desc_printf(smbios_powersup_input_desc(p.smbps_ivrs), 1386 fp, " Input Voltage Range Switching: %u", p.smbps_ivrs); 1387 desc_printf(smbios_powersup_status_desc(p.smbps_status), 1388 fp, " Status: %u", p.smbps_status); 1389 desc_printf(smbios_powersup_type_desc(p.smbps_pstype), 1390 fp, " Type: %u", p.smbps_pstype); 1391 1392 if (p.smbps_vprobe != 0xffff) { 1393 oprintf(fp, " Voltage Probe Handle: %lu\n", p.smbps_vprobe); 1394 } 1395 1396 if (p.smbps_cooldev != 0xffff) { 1397 oprintf(fp, " Cooling Device Handle: %lu\n", p.smbps_cooldev); 1398 } 1399 1400 if (p.smbps_iprobe != 0xffff) { 1401 oprintf(fp, " Current Probe Handle: %lu\n", p.smbps_iprobe); 1402 } 1403 } 1404 1405 static void 1406 print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp) 1407 { 1408 int i; 1409 smbios_processor_ext_t ep; 1410 1411 if (check_oem(shp) != 0) 1412 return; 1413 1414 (void) smbios_info_extprocessor(shp, id, &ep); 1415 1416 oprintf(fp, " Processor: %u\n", ep.smbpe_processor); 1417 oprintf(fp, " FRU: %u\n", ep.smbpe_fru); 1418 oprintf(fp, " Initial APIC ID count: %u\n\n", ep.smbpe_n); 1419 1420 for (i = 0; i < ep.smbpe_n; i++) { 1421 oprintf(fp, " Logical Strand %u: Initial APIC ID: %u\n", i, 1422 ep.smbpe_apicid[i]); 1423 } 1424 } 1425 1426 static void 1427 print_extport(smbios_hdl_t *shp, id_t id, FILE *fp) 1428 { 1429 smbios_port_ext_t epo; 1430 1431 if (check_oem(shp) != 0) 1432 return; 1433 1434 (void) smbios_info_extport(shp, id, &epo); 1435 1436 oprintf(fp, " Chassis Handle: %u\n", epo.smbporte_chassis); 1437 oprintf(fp, " Port Connector Handle: %u\n", epo.smbporte_port); 1438 oprintf(fp, " Device Type: %u\n", epo.smbporte_dtype); 1439 oprintf(fp, " Device Handle: %u\n", epo.smbporte_devhdl); 1440 oprintf(fp, " PHY: %u\n", epo.smbporte_phy); 1441 } 1442 1443 static void 1444 print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp) 1445 { 1446 smbios_pciexrc_t pcie; 1447 1448 if (check_oem(shp) != 0) 1449 return; 1450 1451 (void) smbios_info_pciexrc(shp, id, &pcie); 1452 1453 oprintf(fp, " Component ID: %u\n", pcie.smbpcie_bb); 1454 oprintf(fp, " BDF: 0x%x\n", pcie.smbpcie_bdf); 1455 } 1456 1457 static void 1458 print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp) 1459 { 1460 smbios_memarray_ext_t em; 1461 1462 if (check_oem(shp) != 0) 1463 return; 1464 1465 (void) smbios_info_extmemarray(shp, id, &em); 1466 1467 oprintf(fp, " Physical Memory Array Handle: %u\n", em.smbmae_ma); 1468 oprintf(fp, " Component Parent Handle: %u\n", em.smbmae_comp); 1469 oprintf(fp, " BDF: 0x%x\n", em.smbmae_bdf); 1470 } 1471 1472 static void 1473 print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp) 1474 { 1475 int i; 1476 smbios_memdevice_ext_t emd; 1477 1478 if (check_oem(shp) != 0) 1479 return; 1480 1481 (void) smbios_info_extmemdevice(shp, id, &emd); 1482 1483 oprintf(fp, " Memory Device Handle: %u\n", emd.smbmdeve_md); 1484 oprintf(fp, " DRAM Channel: %u\n", emd.smbmdeve_drch); 1485 oprintf(fp, " Number of Chip Selects: %u\n", emd.smbmdeve_ncs); 1486 1487 for (i = 0; i < emd.smbmdeve_ncs; i++) { 1488 oprintf(fp, " Chip Select: %u\n", emd.smbmdeve_cs[i]); 1489 } 1490 } 1491 1492 static int 1493 print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) 1494 { 1495 smbios_info_t info; 1496 int hex = opt_x; 1497 const char *s; 1498 1499 if (opt_t != -1 && opt_t != sp->smbstr_type) 1500 return (0); /* skip struct if type doesn't match -t */ 1501 1502 if (!opt_O && (sp->smbstr_type == SMB_TYPE_MEMCTL || 1503 sp->smbstr_type == SMB_TYPE_MEMMOD)) 1504 return (0); /* skip struct if type is obsolete */ 1505 1506 if (g_hdr++ == 0 || !opt_s) 1507 oprintf(fp, "%-5s %-4s %s\n", "ID", "SIZE", "TYPE"); 1508 1509 oprintf(fp, "%-5u %-4lu", 1510 (uint_t)sp->smbstr_id, (ulong_t)sp->smbstr_size); 1511 1512 if ((s = smbios_type_name(sp->smbstr_type)) != NULL) 1513 oprintf(fp, " %s (type %u)", s, sp->smbstr_type); 1514 else if (sp->smbstr_type > SMB_TYPE_OEM_LO && 1515 sp->smbstr_type < SMB_TYPE_OEM_HI) 1516 oprintf(fp, " %s+%u (type %u)", "SMB_TYPE_OEM_LO", 1517 sp->smbstr_type - SMB_TYPE_OEM_LO, sp->smbstr_type); 1518 else 1519 oprintf(fp, " %u", sp->smbstr_type); 1520 1521 if ((s = smbios_type_desc(sp->smbstr_type)) != NULL) 1522 oprintf(fp, " (%s)\n", s); 1523 else 1524 oprintf(fp, "\n"); 1525 1526 if (opt_s) 1527 return (0); /* only print header line if -s specified */ 1528 1529 if (smbios_info_common(shp, sp->smbstr_id, &info) == 0) { 1530 oprintf(fp, "\n"); 1531 print_common(&info, fp); 1532 } 1533 1534 switch (sp->smbstr_type) { 1535 case SMB_TYPE_BIOS: 1536 oprintf(fp, "\n"); 1537 print_bios(shp, fp); 1538 break; 1539 case SMB_TYPE_SYSTEM: 1540 oprintf(fp, "\n"); 1541 print_system(shp, fp); 1542 break; 1543 case SMB_TYPE_BASEBOARD: 1544 oprintf(fp, "\n"); 1545 print_bboard(shp, sp->smbstr_id, fp); 1546 break; 1547 case SMB_TYPE_CHASSIS: 1548 oprintf(fp, "\n"); 1549 print_chassis(shp, sp->smbstr_id, fp); 1550 break; 1551 case SMB_TYPE_PROCESSOR: 1552 oprintf(fp, "\n"); 1553 print_processor(shp, sp->smbstr_id, fp); 1554 break; 1555 case SMB_TYPE_CACHE: 1556 oprintf(fp, "\n"); 1557 print_cache(shp, sp->smbstr_id, fp); 1558 break; 1559 case SMB_TYPE_PORT: 1560 oprintf(fp, "\n"); 1561 print_port(shp, sp->smbstr_id, fp); 1562 break; 1563 case SMB_TYPE_SLOT: 1564 oprintf(fp, "\n"); 1565 print_slot(shp, sp->smbstr_id, fp); 1566 break; 1567 case SMB_TYPE_OBDEVS: 1568 oprintf(fp, "\n"); 1569 print_obdevs(shp, sp->smbstr_id, fp); 1570 break; 1571 case SMB_TYPE_OEMSTR: 1572 case SMB_TYPE_SYSCONFSTR: 1573 oprintf(fp, "\n"); 1574 print_strtab(shp, sp->smbstr_id, fp); 1575 break; 1576 case SMB_TYPE_LANG: 1577 oprintf(fp, "\n"); 1578 print_lang(shp, sp->smbstr_id, fp); 1579 break; 1580 case SMB_TYPE_EVENTLOG: 1581 oprintf(fp, "\n"); 1582 print_evlog(shp, sp->smbstr_id, fp); 1583 break; 1584 case SMB_TYPE_MEMARRAY: 1585 oprintf(fp, "\n"); 1586 print_memarray(shp, sp->smbstr_id, fp); 1587 break; 1588 case SMB_TYPE_MEMDEVICE: 1589 oprintf(fp, "\n"); 1590 print_memdevice(shp, sp->smbstr_id, fp); 1591 break; 1592 case SMB_TYPE_MEMARRAYMAP: 1593 oprintf(fp, "\n"); 1594 print_memarrmap(shp, sp->smbstr_id, fp); 1595 break; 1596 case SMB_TYPE_MEMDEVICEMAP: 1597 oprintf(fp, "\n"); 1598 print_memdevmap(shp, sp->smbstr_id, fp); 1599 break; 1600 case SMB_TYPE_SECURITY: 1601 oprintf(fp, "\n"); 1602 print_hwsec(shp, fp); 1603 break; 1604 case SMB_TYPE_VPROBE: 1605 oprintf(fp, "\n"); 1606 print_vprobe(shp, sp->smbstr_id, fp); 1607 break; 1608 case SMB_TYPE_COOLDEV: 1609 oprintf(fp, "\n"); 1610 print_cooldev(shp, sp->smbstr_id, fp); 1611 break; 1612 case SMB_TYPE_TPROBE: 1613 oprintf(fp, "\n"); 1614 print_tprobe(shp, sp->smbstr_id, fp); 1615 break; 1616 case SMB_TYPE_IPROBE: 1617 oprintf(fp, "\n"); 1618 print_iprobe(shp, sp->smbstr_id, fp); 1619 break; 1620 case SMB_TYPE_BOOT: 1621 oprintf(fp, "\n"); 1622 print_boot(shp, fp); 1623 break; 1624 case SMB_TYPE_IPMIDEV: 1625 oprintf(fp, "\n"); 1626 print_ipmi(shp, fp); 1627 break; 1628 case SMB_TYPE_POWERSUP: 1629 oprintf(fp, "\n"); 1630 print_powersup(shp, sp->smbstr_id, fp); 1631 break; 1632 case SMB_TYPE_OBDEVEXT: 1633 oprintf(fp, "\n"); 1634 print_obdevs_ext(shp, sp->smbstr_id, fp); 1635 break; 1636 case SUN_OEM_EXT_PROCESSOR: 1637 oprintf(fp, "\n"); 1638 print_extprocessor(shp, sp->smbstr_id, fp); 1639 break; 1640 case SUN_OEM_EXT_PORT: 1641 oprintf(fp, "\n"); 1642 print_extport(shp, sp->smbstr_id, fp); 1643 break; 1644 case SUN_OEM_PCIEXRC: 1645 oprintf(fp, "\n"); 1646 print_pciexrc(shp, sp->smbstr_id, fp); 1647 break; 1648 case SUN_OEM_EXT_MEMARRAY: 1649 oprintf(fp, "\n"); 1650 print_extmemarray(shp, sp->smbstr_id, fp); 1651 break; 1652 case SUN_OEM_EXT_MEMDEVICE: 1653 oprintf(fp, "\n"); 1654 print_extmemdevice(shp, sp->smbstr_id, fp); 1655 break; 1656 default: 1657 hex++; 1658 } 1659 1660 if (hex) 1661 print_bytes(sp->smbstr_data, sp->smbstr_size, fp); 1662 else 1663 oprintf(fp, "\n"); 1664 1665 return (0); 1666 } 1667 1668 static uint16_t 1669 getu16(const char *name, const char *s) 1670 { 1671 u_longlong_t val; 1672 char *p; 1673 1674 errno = 0; 1675 val = strtoull(s, &p, 0); 1676 1677 if (errno != 0 || p == s || *p != '\0' || val > UINT16_MAX) { 1678 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 1679 g_pname, name, s); 1680 exit(SMBIOS_USAGE); 1681 } 1682 1683 return ((uint16_t)val); 1684 } 1685 1686 static uint16_t 1687 getstype(const char *name, const char *s) 1688 { 1689 const char *ts; 1690 uint16_t t; 1691 1692 for (t = 0; t < SMB_TYPE_OEM_LO; t++) { 1693 if ((ts = smbios_type_name(t)) != NULL && strcmp(s, ts) == 0) 1694 return (t); 1695 } 1696 1697 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 1698 g_pname, name, s); 1699 1700 exit(SMBIOS_USAGE); 1701 /*NOTREACHED*/ 1702 } 1703 1704 static int 1705 usage(FILE *fp) 1706 { 1707 (void) fprintf(fp, "Usage: %s " 1708 "[-BeOsx] [-i id] [-t type] [-w file] [file]\n\n", g_pname); 1709 1710 (void) fprintf(fp, 1711 "\t-B disable header validation for broken BIOSes\n" 1712 "\t-e display SMBIOS entry point information\n" 1713 "\t-i display only the specified structure\n" 1714 "\t-O display obsolete structure types\n" 1715 "\t-s display only a summary of structure identifiers and types\n" 1716 "\t-t display only the specified structure type\n" 1717 "\t-w write the raw data to the specified file\n" 1718 "\t-x display raw data for structures\n"); 1719 1720 return (SMBIOS_USAGE); 1721 } 1722 1723 int 1724 main(int argc, char *argv[]) 1725 { 1726 const char *ifile = NULL; 1727 const char *ofile = NULL; 1728 int oflags = 0; 1729 1730 smbios_hdl_t *shp; 1731 smbios_struct_t s; 1732 int err, fd, c; 1733 char *p; 1734 1735 if ((p = strrchr(argv[0], '/')) == NULL) 1736 g_pname = argv[0]; 1737 else 1738 g_pname = p + 1; 1739 1740 while (optind < argc) { 1741 while ((c = getopt(argc, argv, "Bei:Ost:w:xZ")) != EOF) { 1742 switch (c) { 1743 case 'B': 1744 oflags |= SMB_O_NOCKSUM | SMB_O_NOVERS; 1745 break; 1746 case 'e': 1747 opt_e++; 1748 break; 1749 case 'i': 1750 opt_i = getu16("struct ID", optarg); 1751 break; 1752 case 'O': 1753 opt_O++; 1754 break; 1755 case 's': 1756 opt_s++; 1757 break; 1758 case 't': 1759 if (isdigit(optarg[0])) 1760 opt_t = getu16("struct type", optarg); 1761 else 1762 opt_t = getstype("struct type", optarg); 1763 break; 1764 case 'w': 1765 ofile = optarg; 1766 break; 1767 case 'x': 1768 opt_x++; 1769 break; 1770 case 'Z': 1771 oflags |= SMB_O_ZIDS; /* undocumented */ 1772 break; 1773 default: 1774 return (usage(stderr)); 1775 } 1776 } 1777 1778 if (optind < argc) { 1779 if (ifile != NULL) { 1780 (void) fprintf(stderr, "%s: illegal " 1781 "argument -- %s\n", g_pname, argv[optind]); 1782 return (SMBIOS_USAGE); 1783 } 1784 ifile = argv[optind++]; 1785 } 1786 } 1787 1788 if ((shp = smbios_open(ifile, SMB_VERSION, oflags, &err)) == NULL) { 1789 (void) fprintf(stderr, "%s: failed to load SMBIOS: %s\n", 1790 g_pname, smbios_errmsg(err)); 1791 return (SMBIOS_ERROR); 1792 } 1793 1794 if (opt_i == -1 && opt_t == -1 && opt_e == 0 && 1795 smbios_truncated(shp)) 1796 (void) fprintf(stderr, "%s: SMBIOS table is truncated\n", 1797 g_pname); 1798 1799 if (ofile != NULL) { 1800 if ((fd = open(ofile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) { 1801 (void) fprintf(stderr, "%s: failed to open %s: %s\n", 1802 g_pname, ofile, strerror(errno)); 1803 err = SMBIOS_ERROR; 1804 } else if (smbios_write(shp, fd) != 0) { 1805 (void) fprintf(stderr, "%s: failed to write %s: %s\n", 1806 g_pname, ofile, smbios_errmsg(smbios_errno(shp))); 1807 err = SMBIOS_ERROR; 1808 } 1809 smbios_close(shp); 1810 return (err); 1811 } 1812 1813 if (opt_e) { 1814 print_smbios(shp, stdout); 1815 smbios_close(shp); 1816 return (SMBIOS_SUCCESS); 1817 } 1818 1819 if (opt_O && (opt_i != -1 || opt_t != -1)) 1820 opt_O++; /* -i or -t imply displaying obsolete records */ 1821 1822 if (opt_i != -1) 1823 err = smbios_lookup_id(shp, opt_i, &s); 1824 else 1825 err = smbios_iter(shp, print_struct, stdout); 1826 1827 if (err != 0) { 1828 (void) fprintf(stderr, "%s: failed to access SMBIOS: %s\n", 1829 g_pname, smbios_errmsg(smbios_errno(shp))); 1830 smbios_close(shp); 1831 return (SMBIOS_ERROR); 1832 } 1833 1834 if (opt_i != -1) 1835 (void) print_struct(shp, &s, stdout); 1836 1837 smbios_close(shp); 1838 return (SMBIOS_SUCCESS); 1839 } 1840