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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/sysmacros.h> 28 #include <sys/param.h> 29 30 #include <smbios.h> 31 #include <alloca.h> 32 #include <limits.h> 33 #include <unistd.h> 34 #include <strings.h> 35 #include <stdlib.h> 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <fcntl.h> 39 #include <errno.h> 40 #include <ctype.h> 41 42 #define SMBIOS_SUCCESS 0 43 #define SMBIOS_ERROR 1 44 #define SMBIOS_USAGE 2 45 46 static const char *g_pname; 47 static int g_hdr; 48 49 static int opt_e; 50 static int opt_i = -1; 51 static int opt_O; 52 static int opt_s; 53 static int opt_t = -1; 54 static int opt_x; 55 56 /*PRINTFLIKE2*/ 57 static void 58 oprintf(FILE *fp, const char *format, ...) 59 { 60 va_list ap; 61 62 va_start(ap, format); 63 (void) vfprintf(fp, format, ap); 64 va_end(ap); 65 } 66 67 /*PRINTFLIKE3*/ 68 static void 69 desc_printf(const char *d, FILE *fp, const char *format, ...) 70 { 71 va_list ap; 72 73 va_start(ap, format); 74 (void) vfprintf(fp, format, ap); 75 va_end(ap); 76 77 if (d != NULL) 78 (void) fprintf(fp, " (%s)\n", d); 79 else 80 (void) fprintf(fp, "\n"); 81 } 82 83 static void 84 flag_printf(FILE *fp, const char *s, uint_t flags, size_t bits, 85 const char *(*flag_name)(uint_t), const char *(*flag_desc)(uint_t)) 86 { 87 size_t i; 88 89 oprintf(fp, " %s: 0x%x\n", s, flags); 90 91 for (i = 0; i < bits; i++) { 92 uint_t f = 1 << i; 93 const char *n; 94 95 if (!(flags & f)) 96 continue; 97 98 if ((n = flag_name(f)) != NULL) 99 desc_printf(flag_desc(f), fp, "\t%s", n); 100 else 101 desc_printf(flag_desc(f), fp, "\t0x%x", f); 102 } 103 } 104 105 static void 106 flag64_printf(FILE *fp, const char *s, uint64_t flags, size_t bits, 107 const char *(*flag_name)(uint64_t), const char *(*flag_desc)(uint64_t)) 108 { 109 size_t i; 110 111 oprintf(fp, " %s: 0x%llx\n", s, (u_longlong_t)flags); 112 113 for (i = 0; i < bits; i++) { 114 u_longlong_t f = 1ULL << i; 115 const char *n; 116 117 if (!(flags & f)) 118 continue; 119 120 if ((n = flag_name(f)) != NULL) 121 desc_printf(flag_desc(f), fp, "\t%s", n); 122 else 123 desc_printf(flag_desc(f), fp, "\t0x%llx", f); 124 } 125 } 126 127 static void 128 id_printf(FILE *fp, const char *s, id_t id) 129 { 130 switch (id) { 131 case SMB_ID_NONE: 132 oprintf(fp, "%sNone\n", s); 133 break; 134 case SMB_ID_NOTSUP: 135 oprintf(fp, "%sNot Supported\n", s); 136 break; 137 default: 138 oprintf(fp, "%s%u\n", s, (uint_t)id); 139 } 140 } 141 142 static int 143 check_oem(smbios_hdl_t *shp) 144 { 145 int i; 146 int cnt; 147 int rv; 148 id_t oem_id; 149 smbios_struct_t s; 150 const char **oem_str; 151 152 rv = smbios_lookup_type(shp, SMB_TYPE_OEMSTR, &s); 153 if (rv != 0) { 154 return (-1); 155 } 156 157 oem_id = s.smbstr_id; 158 159 cnt = smbios_info_strtab(shp, oem_id, 0, NULL); 160 if (cnt > 0) { 161 oem_str = alloca(sizeof (char *) * cnt); 162 (void) smbios_info_strtab(shp, oem_id, cnt, oem_str); 163 164 for (i = 0; i < cnt; i++) { 165 if (strncmp(oem_str[i], SMB_PRMS1, 166 strlen(SMB_PRMS1) + 1) == 0) { 167 return (0); 168 } 169 } 170 } 171 172 return (-1); 173 } 174 175 static void 176 print_smbios(smbios_hdl_t *shp, FILE *fp) 177 { 178 smbios_entry_t ep; 179 int i; 180 181 smbios_info_smbios(shp, &ep); 182 183 oprintf(fp, "Entry Point Anchor Tag: %*.*s\n", 184 (int)sizeof (ep.smbe_eanchor), (int)sizeof (ep.smbe_eanchor), 185 ep.smbe_eanchor); 186 187 oprintf(fp, "Entry Point Checksum: 0x%x\n", ep.smbe_ecksum); 188 oprintf(fp, "Entry Point Length: %u\n", ep.smbe_elen); 189 oprintf(fp, "Entry Point Version: %u.%u\n", 190 ep.smbe_major, ep.smbe_minor); 191 oprintf(fp, "Max Structure Size: %u\n", ep.smbe_maxssize); 192 oprintf(fp, "Entry Point Revision: 0x%x\n", ep.smbe_revision); 193 194 oprintf(fp, "Entry Point Revision Data:"); 195 for (i = 0; i < sizeof (ep.smbe_format); i++) 196 oprintf(fp, " 0x%02x", ep.smbe_format[i]); 197 oprintf(fp, "\n"); 198 199 oprintf(fp, "Intermediate Anchor Tag: %*.*s\n", 200 (int)sizeof (ep.smbe_ianchor), (int)sizeof (ep.smbe_ianchor), 201 ep.smbe_ianchor); 202 203 oprintf(fp, "Intermediate Checksum: 0x%x\n", ep.smbe_icksum); 204 oprintf(fp, "Structure Table Length: %u\n", ep.smbe_stlen); 205 oprintf(fp, "Structure Table Address: 0x%x\n", ep.smbe_staddr); 206 oprintf(fp, "Structure Table Entries: %u\n", ep.smbe_stnum); 207 oprintf(fp, "DMI BCD Revision: 0x%x\n", ep.smbe_bcdrev); 208 } 209 210 static void 211 print_common(const smbios_info_t *ip, FILE *fp) 212 { 213 if (ip->smbi_manufacturer[0] != '\0') 214 oprintf(fp, " Manufacturer: %s\n", ip->smbi_manufacturer); 215 if (ip->smbi_product[0] != '\0') 216 oprintf(fp, " Product: %s\n", ip->smbi_product); 217 if (ip->smbi_version[0] != '\0') 218 oprintf(fp, " Version: %s\n", ip->smbi_version); 219 if (ip->smbi_serial[0] != '\0') 220 oprintf(fp, " Serial Number: %s\n", ip->smbi_serial); 221 if (ip->smbi_asset[0] != '\0') 222 oprintf(fp, " Asset Tag: %s\n", ip->smbi_asset); 223 if (ip->smbi_location[0] != '\0') 224 oprintf(fp, " Location Tag: %s\n", ip->smbi_location); 225 if (ip->smbi_part[0] != '\0') 226 oprintf(fp, " Part Number: %s\n", ip->smbi_part); 227 } 228 229 static void 230 print_bios(smbios_hdl_t *shp, FILE *fp) 231 { 232 smbios_bios_t b; 233 234 (void) smbios_info_bios(shp, &b); 235 236 oprintf(fp, " Vendor: %s\n", b.smbb_vendor); 237 oprintf(fp, " Version String: %s\n", b.smbb_version); 238 oprintf(fp, " Release Date: %s\n", b.smbb_reldate); 239 oprintf(fp, " Address Segment: 0x%x\n", b.smbb_segment); 240 oprintf(fp, " ROM Size: %u bytes\n", b.smbb_romsize); 241 oprintf(fp, " Image Size: %u bytes\n", b.smbb_runsize); 242 243 flag64_printf(fp, "Characteristics", 244 b.smbb_cflags, sizeof (b.smbb_cflags) * NBBY, 245 smbios_bios_flag_name, smbios_bios_flag_desc); 246 247 if (b.smbb_nxcflags > SMB_BIOSXB_1) { 248 flag_printf(fp, "Characteristics Extension Byte 1", 249 b.smbb_xcflags[SMB_BIOSXB_1], 250 sizeof (b.smbb_xcflags[SMB_BIOSXB_1]) * NBBY, 251 smbios_bios_xb1_name, smbios_bios_xb1_desc); 252 } 253 254 if (b.smbb_nxcflags > SMB_BIOSXB_2) { 255 flag_printf(fp, "Characteristics Extension Byte 2", 256 b.smbb_xcflags[SMB_BIOSXB_2], 257 sizeof (b.smbb_xcflags[SMB_BIOSXB_2]) * NBBY, 258 smbios_bios_xb2_name, smbios_bios_xb2_desc); 259 } 260 261 if (b.smbb_nxcflags > SMB_BIOSXB_BIOS_MIN) { 262 oprintf(fp, " Version Number: %u.%u\n", 263 b.smbb_biosv.smbv_major, b.smbb_biosv.smbv_minor); 264 } 265 266 if (b.smbb_nxcflags > SMB_BIOSXB_ECFW_MIN) { 267 oprintf(fp, " Embedded Ctlr Firmware Version Number: %u.%u\n", 268 b.smbb_ecfwv.smbv_major, b.smbb_ecfwv.smbv_minor); 269 } 270 } 271 272 static void 273 print_system(smbios_hdl_t *shp, FILE *fp) 274 { 275 smbios_system_t s; 276 uint_t i; 277 278 (void) smbios_info_system(shp, &s); 279 280 oprintf(fp, " UUID: "); 281 for (i = 0; i < s.smbs_uuidlen; i++) { 282 oprintf(fp, "%02x", s.smbs_uuid[i]); 283 if (i == 3 || i == 5 || i == 7 || i == 9) 284 oprintf(fp, "-"); 285 } 286 oprintf(fp, "\n"); 287 288 desc_printf(smbios_system_wakeup_desc(s.smbs_wakeup), 289 fp, " Wake-Up Event: 0x%x", s.smbs_wakeup); 290 291 oprintf(fp, " SKU Number: %s\n", s.smbs_sku); 292 oprintf(fp, " Family: %s\n", s.smbs_family); 293 } 294 295 static void 296 print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp) 297 { 298 smbios_bboard_t b; 299 int chdl_cnt; 300 301 (void) smbios_info_bboard(shp, id, &b); 302 303 oprintf(fp, " Chassis: %u\n", (uint_t)b.smbb_chassis); 304 305 flag_printf(fp, "Flags", b.smbb_flags, sizeof (b.smbb_flags) * NBBY, 306 smbios_bboard_flag_name, smbios_bboard_flag_desc); 307 308 desc_printf(smbios_bboard_type_desc(b.smbb_type), 309 fp, " Board Type: 0x%x", b.smbb_type); 310 311 chdl_cnt = b.smbb_contn; 312 if (chdl_cnt != 0) { 313 id_t *chdl; 314 uint16_t hdl; 315 int i, n, cnt; 316 317 chdl = alloca(chdl_cnt * sizeof (id_t)); 318 cnt = smbios_info_contains(shp, id, chdl_cnt, chdl); 319 if (cnt > SMB_CONT_MAX) 320 return; 321 n = MIN(chdl_cnt, cnt); 322 323 oprintf(fp, "\n"); 324 for (i = 0; i < n; i++) { 325 hdl = (uint16_t)chdl[i]; 326 oprintf(fp, " Contained Handle: %u\n", hdl); 327 } 328 } 329 } 330 331 static void 332 print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp) 333 { 334 smbios_chassis_t c; 335 int elem_cnt; 336 337 (void) smbios_info_chassis(shp, id, &c); 338 339 oprintf(fp, " OEM Data: 0x%x\n", c.smbc_oemdata); 340 oprintf(fp, " Lock Present: %s\n", c.smbc_lock ? "Y" : "N"); 341 342 desc_printf(smbios_chassis_type_desc(c.smbc_type), 343 fp, " Chassis Type: 0x%x", c.smbc_type); 344 345 desc_printf(smbios_chassis_state_desc(c.smbc_bustate), 346 fp, " Boot-Up State: 0x%x", c.smbc_bustate); 347 348 desc_printf(smbios_chassis_state_desc(c.smbc_psstate), 349 fp, " Power Supply State: 0x%x", c.smbc_psstate); 350 351 desc_printf(smbios_chassis_state_desc(c.smbc_thstate), 352 fp, " Thermal State: 0x%x", c.smbc_thstate); 353 354 oprintf(fp, " Chassis Height: %uu\n", c.smbc_uheight); 355 oprintf(fp, " Power Cords: %u\n", c.smbc_cords); 356 357 elem_cnt = c.smbc_elems; 358 oprintf(fp, " Element Records: %u\n", elem_cnt); 359 360 if (elem_cnt > 0) { 361 id_t *elems; 362 uint8_t type; 363 int i, n, cnt; 364 365 elems = alloca(c.smbc_elems * sizeof (id_t)); 366 cnt = smbios_info_contains(shp, id, elem_cnt, elems); 367 if (cnt > SMB_CONT_MAX) 368 return; 369 n = MIN(elem_cnt, cnt); 370 371 oprintf(fp, "\n"); 372 for (i = 0; i < n; i++) { 373 type = (uint8_t)elems[i]; 374 if (type & 0x80) { 375 /* SMBIOS structrure Type */ 376 desc_printf(smbios_type_name(type & 0x7f), fp, 377 " Contained SMBIOS structure Type: %u", 378 type & 0x80); 379 } else { 380 /* SMBIOS Base Board Type */ 381 desc_printf(smbios_bboard_type_desc(type), fp, 382 " Contained SMBIOS Base Board Type: 0x%x", 383 type); 384 } 385 } 386 } 387 } 388 389 static void 390 print_processor(smbios_hdl_t *shp, id_t id, FILE *fp) 391 { 392 smbios_processor_t p; 393 uint_t status; 394 395 (void) smbios_info_processor(shp, id, &p); 396 status = SMB_PRSTATUS_STATUS(p.smbp_status); 397 398 desc_printf(smbios_processor_family_desc(p.smbp_family), 399 fp, " Family: %u", p.smbp_family); 400 401 oprintf(fp, " CPUID: 0x%llx\n", (u_longlong_t)p.smbp_cpuid); 402 403 desc_printf(smbios_processor_type_desc(p.smbp_type), 404 fp, " Type: %u", p.smbp_type); 405 406 desc_printf(smbios_processor_upgrade_desc(p.smbp_upgrade), 407 fp, " Socket Upgrade: %u", p.smbp_upgrade); 408 409 oprintf(fp, " Socket Status: %s\n", 410 SMB_PRSTATUS_PRESENT(p.smbp_status) ? 411 "Populated" : "Not Populated"); 412 413 desc_printf(smbios_processor_status_desc(status), 414 fp, " Processor Status: %u", status); 415 416 if (SMB_PRV_LEGACY(p.smbp_voltage)) { 417 oprintf(fp, " Supported Voltages:"); 418 switch (p.smbp_voltage) { 419 case SMB_PRV_5V: 420 oprintf(fp, " 5.0V"); 421 break; 422 case SMB_PRV_33V: 423 oprintf(fp, " 3.3V"); 424 break; 425 case SMB_PRV_29V: 426 oprintf(fp, " 2.9V"); 427 break; 428 } 429 oprintf(fp, "\n"); 430 } else { 431 oprintf(fp, " Supported Voltages: %.1fV\n", 432 (float)SMB_PRV_VOLTAGE(p.smbp_voltage) / 10); 433 } 434 435 if (p.smbp_clkspeed != 0) 436 oprintf(fp, " External Clock Speed: %uMHz\n", p.smbp_clkspeed); 437 else 438 oprintf(fp, " External Clock Speed: Unknown\n"); 439 440 if (p.smbp_maxspeed != 0) 441 oprintf(fp, " Maximum Speed: %uMHz\n", p.smbp_maxspeed); 442 else 443 oprintf(fp, " Maximum Speed: Unknown\n"); 444 445 if (p.smbp_curspeed != 0) 446 oprintf(fp, " Current Speed: %uMHz\n", p.smbp_curspeed); 447 else 448 oprintf(fp, " Current Speed: Unknown\n"); 449 450 id_printf(fp, " L1 Cache: ", p.smbp_l1cache); 451 id_printf(fp, " L2 Cache: ", p.smbp_l2cache); 452 id_printf(fp, " L3 Cache: ", p.smbp_l3cache); 453 } 454 455 static void 456 print_cache(smbios_hdl_t *shp, id_t id, FILE *fp) 457 { 458 smbios_cache_t c; 459 460 (void) smbios_info_cache(shp, id, &c); 461 462 oprintf(fp, " Level: %u\n", c.smba_level); 463 oprintf(fp, " Maximum Installed Size: %u bytes\n", c.smba_maxsize); 464 465 if (c.smba_size != 0) 466 oprintf(fp, " Installed Size: %u bytes\n", c.smba_size); 467 else 468 oprintf(fp, " Installed Size: Not Installed\n"); 469 470 if (c.smba_speed != 0) 471 oprintf(fp, " Speed: %uns\n", c.smba_speed); 472 else 473 oprintf(fp, " Speed: Unknown\n"); 474 475 flag_printf(fp, "Supported SRAM Types", 476 c.smba_stype, sizeof (c.smba_stype) * NBBY, 477 smbios_cache_ctype_name, smbios_cache_ctype_desc); 478 479 desc_printf(smbios_cache_ctype_desc(c.smba_ctype), 480 fp, " Current SRAM Type: 0x%x", c.smba_ctype); 481 482 desc_printf(smbios_cache_ecc_desc(c.smba_etype), 483 fp, " Error Correction Type: %u", c.smba_etype); 484 485 desc_printf(smbios_cache_logical_desc(c.smba_ltype), 486 fp, " Logical Cache Type: %u", c.smba_ltype); 487 488 desc_printf(smbios_cache_assoc_desc(c.smba_assoc), 489 fp, " Associativity: %u", c.smba_assoc); 490 491 desc_printf(smbios_cache_mode_desc(c.smba_mode), 492 fp, " Mode: %u", c.smba_mode); 493 494 desc_printf(smbios_cache_loc_desc(c.smba_location), 495 fp, " Location: %u", c.smba_location); 496 497 flag_printf(fp, "Flags", c.smba_flags, sizeof (c.smba_flags) * NBBY, 498 smbios_cache_flag_name, smbios_cache_flag_desc); 499 } 500 501 static void 502 print_port(smbios_hdl_t *shp, id_t id, FILE *fp) 503 { 504 smbios_port_t p; 505 506 (void) smbios_info_port(shp, id, &p); 507 508 oprintf(fp, " Internal Reference Designator: %s\n", p.smbo_iref); 509 oprintf(fp, " External Reference Designator: %s\n", p.smbo_eref); 510 511 desc_printf(smbios_port_conn_desc(p.smbo_itype), 512 fp, " Internal Connector Type: %u", p.smbo_itype); 513 514 desc_printf(smbios_port_conn_desc(p.smbo_etype), 515 fp, " External Connector Type: %u", p.smbo_etype); 516 517 desc_printf(smbios_port_type_desc(p.smbo_ptype), 518 fp, " Port Type: %u", p.smbo_ptype); 519 } 520 521 static void 522 print_slot(smbios_hdl_t *shp, id_t id, FILE *fp) 523 { 524 smbios_slot_t s; 525 smbios_entry_t e; 526 527 (void) smbios_info_slot(shp, id, &s); 528 (void) smbios_info_smbios(shp, &e); 529 530 oprintf(fp, " Reference Designator: %s\n", s.smbl_name); 531 oprintf(fp, " Slot ID: 0x%x\n", s.smbl_id); 532 533 desc_printf(smbios_slot_type_desc(s.smbl_type), 534 fp, " Type: 0x%x", s.smbl_type); 535 536 desc_printf(smbios_slot_width_desc(s.smbl_width), 537 fp, " Width: 0x%x", s.smbl_width); 538 539 desc_printf(smbios_slot_usage_desc(s.smbl_usage), 540 fp, " Usage: 0x%x", s.smbl_usage); 541 542 desc_printf(smbios_slot_length_desc(s.smbl_length), 543 fp, " Length: 0x%x", s.smbl_length); 544 545 flag_printf(fp, "Slot Characteristics 1", 546 s.smbl_ch1, sizeof (s.smbl_ch1) * NBBY, 547 smbios_slot_ch1_name, smbios_slot_ch1_desc); 548 549 flag_printf(fp, "Slot Characteristics 2", 550 s.smbl_ch2, sizeof (s.smbl_ch2) * NBBY, 551 smbios_slot_ch2_name, smbios_slot_ch2_desc); 552 553 if (check_oem(shp) != 0 && (e.smbe_major < 2 || e.smbe_minor < 6)) 554 return; 555 556 oprintf(fp, " Segment Group: %u\n", s.smbl_sg); 557 oprintf(fp, " Bus Number: %u\n", s.smbl_bus); 558 oprintf(fp, " Device/Function Number: %u\n", s.smbl_df); 559 } 560 561 static void 562 print_obdevs_ext(smbios_hdl_t *shp, id_t id, FILE *fp) 563 { 564 smbios_obdev_ext_t oe; 565 566 (void) smbios_info_obdevs_ext(shp, id, &oe); 567 568 oprintf(fp, " Reference Designator: %s\n", oe.smboe_name); 569 oprintf(fp, " Device Type: %u\n", oe.smboe_dtype); 570 oprintf(fp, " Device Type Instance: %u\n", oe.smboe_dti); 571 oprintf(fp, " Segment Group Number: %u\n", oe.smboe_sg); 572 oprintf(fp, " Bus Number: %u\n", oe.smboe_bus); 573 oprintf(fp, " Device/Function Number: %u\n", oe.smboe_df); 574 } 575 576 static void 577 print_obdevs(smbios_hdl_t *shp, id_t id, FILE *fp) 578 { 579 smbios_obdev_t *argv; 580 int i, argc; 581 582 if ((argc = smbios_info_obdevs(shp, id, 0, NULL)) > 0) { 583 argv = alloca(sizeof (smbios_obdev_t) * argc); 584 (void) smbios_info_obdevs(shp, id, argc, argv); 585 for (i = 0; i < argc; i++) 586 oprintf(fp, " %s\n", argv[i].smbd_name); 587 } 588 } 589 590 static void 591 print_strtab(smbios_hdl_t *shp, id_t id, FILE *fp) 592 { 593 const char **argv; 594 int i, argc; 595 596 if ((argc = smbios_info_strtab(shp, id, 0, NULL)) > 0) { 597 argv = alloca(sizeof (char *) * argc); 598 (void) smbios_info_strtab(shp, id, argc, argv); 599 for (i = 0; i < argc; i++) 600 oprintf(fp, " %s\n", argv[i]); 601 } 602 } 603 604 static void 605 print_lang(smbios_hdl_t *shp, id_t id, FILE *fp) 606 { 607 smbios_lang_t l; 608 609 (void) smbios_info_lang(shp, &l); 610 611 oprintf(fp, " Current Language: %s\n", l.smbla_cur); 612 oprintf(fp, " Language String Format: %u\n", l.smbla_fmt); 613 oprintf(fp, " Number of Installed Languages: %u\n", l.smbla_num); 614 oprintf(fp, " Installed Languages:\n"); 615 616 print_strtab(shp, id, fp); 617 } 618 619 /*ARGSUSED*/ 620 static void 621 print_evlog(smbios_hdl_t *shp, id_t id, FILE *fp) 622 { 623 smbios_evlog_t ev; 624 uint32_t i; 625 626 (void) smbios_info_eventlog(shp, &ev); 627 628 oprintf(fp, " Log Area Size: %lu bytes\n", (ulong_t)ev.smbev_size); 629 oprintf(fp, " Header Offset: %lu\n", (ulong_t)ev.smbev_hdr); 630 oprintf(fp, " Data Offset: %lu\n", (ulong_t)ev.smbev_data); 631 632 desc_printf(smbios_evlog_method_desc(ev.smbev_method), 633 fp, " Data Access Method: %u", ev.smbev_method); 634 635 flag_printf(fp, "Log Flags", 636 ev.smbev_flags, sizeof (ev.smbev_flags) * NBBY, 637 smbios_evlog_flag_name, smbios_evlog_flag_desc); 638 639 desc_printf(smbios_evlog_format_desc(ev.smbev_format), 640 fp, " Log Header Format: %u", ev.smbev_format); 641 642 oprintf(fp, " Update Token: 0x%x\n", ev.smbev_token); 643 oprintf(fp, " Data Access Address: "); 644 645 switch (ev.smbev_method) { 646 case SMB_EVM_1x1i_1x1d: 647 case SMB_EVM_2x1i_1x1d: 648 case SMB_EVM_1x2i_1x1d: 649 oprintf(fp, "Index Address 0x%x, Data Address 0x%x\n", 650 ev.smbev_addr.eva_io.evi_iaddr, 651 ev.smbev_addr.eva_io.evi_daddr); 652 break; 653 case SMB_EVM_GPNV: 654 oprintf(fp, "0x%x\n", ev.smbev_addr.eva_gpnv); 655 break; 656 default: 657 oprintf(fp, "0x%x\n", ev.smbev_addr.eva_addr); 658 } 659 660 oprintf(fp, " Type Descriptors:\n"); 661 662 for (i = 0; i < ev.smbev_typec; i++) { 663 oprintf(fp, " %u: Log Type 0x%x, Data Type 0x%x\n", i, 664 ev.smbev_typev[i].smbevt_ltype, 665 ev.smbev_typev[i].smbevt_dtype); 666 } 667 } 668 669 static void 670 print_bytes(const uint8_t *data, size_t size, FILE *fp) 671 { 672 size_t row, rows = P2ROUNDUP(size, 16) / 16; 673 size_t col, cols; 674 675 char buf[17]; 676 uint8_t x; 677 678 oprintf(fp, "\n offset: 0 1 2 3 4 5 6 7 8 9 a b c d e f " 679 "0123456789abcdef\n"); 680 681 for (row = 0; row < rows; row++) { 682 oprintf(fp, " %#4lx: ", (ulong_t)row * 16); 683 cols = MIN(size - row * 16, 16); 684 685 for (col = 0; col < cols; col++) { 686 if (col % 4 == 0) 687 oprintf(fp, " "); 688 x = *data++; 689 oprintf(fp, "%02x", x); 690 buf[col] = x <= ' ' || x > '~' ? '.' : x; 691 } 692 693 for (; col < 16; col++) { 694 if (col % 4 == 0) 695 oprintf(fp, " "); 696 oprintf(fp, " "); 697 buf[col] = ' '; 698 } 699 700 buf[col] = '\0'; 701 oprintf(fp, " %s\n", buf); 702 } 703 704 oprintf(fp, "\n"); 705 } 706 707 static void 708 print_memarray(smbios_hdl_t *shp, id_t id, FILE *fp) 709 { 710 smbios_memarray_t ma; 711 712 (void) smbios_info_memarray(shp, id, &ma); 713 714 desc_printf(smbios_memarray_loc_desc(ma.smbma_location), 715 fp, " Location: %u", ma.smbma_location); 716 717 desc_printf(smbios_memarray_use_desc(ma.smbma_use), 718 fp, " Use: %u", ma.smbma_use); 719 720 desc_printf(smbios_memarray_ecc_desc(ma.smbma_ecc), 721 fp, " ECC: %u", ma.smbma_ecc); 722 723 oprintf(fp, " Number of Slots/Sockets: %u\n", ma.smbma_ndevs); 724 id_printf(fp, " Memory Error Data: ", ma.smbma_err); 725 oprintf(fp, " Max Capacity: %llu bytes\n", 726 (u_longlong_t)ma.smbma_size); 727 } 728 729 static void 730 print_memdevice(smbios_hdl_t *shp, id_t id, FILE *fp) 731 { 732 smbios_memdevice_t md; 733 734 (void) smbios_info_memdevice(shp, id, &md); 735 736 id_printf(fp, " Physical Memory Array: ", md.smbmd_array); 737 id_printf(fp, " Memory Error Data: ", md.smbmd_error); 738 739 if (md.smbmd_twidth != -1u) 740 oprintf(fp, " Total Width: %u bits\n", md.smbmd_twidth); 741 else 742 oprintf(fp, " Total Width: Unknown\n"); 743 744 if (md.smbmd_dwidth != -1u) 745 oprintf(fp, " Data Width: %u bits\n", md.smbmd_dwidth); 746 else 747 oprintf(fp, " Data Width: Unknown\n"); 748 749 switch (md.smbmd_size) { 750 case -1ull: 751 oprintf(fp, " Size: Unknown\n"); 752 break; 753 case 0: 754 oprintf(fp, " Size: Not Populated\n"); 755 break; 756 default: 757 oprintf(fp, " Size: %llu bytes\n", 758 (u_longlong_t)md.smbmd_size); 759 } 760 761 desc_printf(smbios_memdevice_form_desc(md.smbmd_form), 762 fp, " Form Factor: %u", md.smbmd_form); 763 764 if (md.smbmd_set == 0) 765 oprintf(fp, " Set: None\n"); 766 else if (md.smbmd_set == (uint8_t)-1u) 767 oprintf(fp, " Set: Unknown\n"); 768 else 769 oprintf(fp, " Set: %u\n", md.smbmd_set); 770 771 desc_printf(smbios_memdevice_type_desc(md.smbmd_type), 772 fp, " Memory Type: %u", md.smbmd_type); 773 774 flag_printf(fp, "Flags", md.smbmd_flags, sizeof (md.smbmd_flags) * NBBY, 775 smbios_memdevice_flag_name, smbios_memdevice_flag_desc); 776 777 if (md.smbmd_speed != 0) 778 oprintf(fp, " Speed: %uns\n", md.smbmd_speed); 779 else 780 oprintf(fp, " Speed: Unknown\n"); 781 782 oprintf(fp, " Device Locator: %s\n", md.smbmd_dloc); 783 oprintf(fp, " Bank Locator: %s\n", md.smbmd_bloc); 784 } 785 786 static void 787 print_memarrmap(smbios_hdl_t *shp, id_t id, FILE *fp) 788 { 789 smbios_memarrmap_t ma; 790 791 (void) smbios_info_memarrmap(shp, id, &ma); 792 793 id_printf(fp, " Physical Memory Array: ", ma.smbmam_array); 794 oprintf(fp, " Devices per Row: %u\n", ma.smbmam_width); 795 796 oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n", 797 (u_longlong_t)ma.smbmam_addr, (u_longlong_t)ma.smbmam_size); 798 } 799 800 static void 801 print_memdevmap(smbios_hdl_t *shp, id_t id, FILE *fp) 802 { 803 smbios_memdevmap_t md; 804 805 (void) smbios_info_memdevmap(shp, id, &md); 806 807 id_printf(fp, " Memory Device: ", md.smbmdm_device); 808 id_printf(fp, " Memory Array Mapped Address: ", md.smbmdm_arrmap); 809 810 oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n", 811 (u_longlong_t)md.smbmdm_addr, (u_longlong_t)md.smbmdm_size); 812 813 oprintf(fp, " Partition Row Position: %u\n", md.smbmdm_rpos); 814 oprintf(fp, " Interleave Position: %u\n", md.smbmdm_ipos); 815 oprintf(fp, " Interleave Data Depth: %u\n", md.smbmdm_idepth); 816 } 817 818 static void 819 print_hwsec(smbios_hdl_t *shp, FILE *fp) 820 { 821 smbios_hwsec_t h; 822 823 (void) smbios_info_hwsec(shp, &h); 824 825 desc_printf(smbios_hwsec_desc(h.smbh_pwr_ps), 826 fp, " Power-On Password Status: %u", h.smbh_pwr_ps); 827 desc_printf(smbios_hwsec_desc(h.smbh_kbd_ps), 828 fp, " Keyboard Password Status: %u", h.smbh_kbd_ps); 829 desc_printf(smbios_hwsec_desc(h.smbh_adm_ps), 830 fp, " Administrator Password Status: %u", h.smbh_adm_ps); 831 desc_printf(smbios_hwsec_desc(h.smbh_pan_ps), 832 fp, " Front Panel Reset Status: %u", h.smbh_pan_ps); 833 } 834 835 static void 836 print_boot(smbios_hdl_t *shp, FILE *fp) 837 { 838 smbios_boot_t b; 839 840 (void) smbios_info_boot(shp, &b); 841 842 desc_printf(smbios_boot_desc(b.smbt_status), 843 fp, " Boot Status Code: 0x%x", b.smbt_status); 844 845 if (b.smbt_size != 0) { 846 oprintf(fp, " Boot Data (%lu bytes):\n", (ulong_t)b.smbt_size); 847 print_bytes(b.smbt_data, b.smbt_size, fp); 848 } 849 } 850 851 static void 852 print_ipmi(smbios_hdl_t *shp, FILE *fp) 853 { 854 smbios_ipmi_t i; 855 856 (void) smbios_info_ipmi(shp, &i); 857 858 desc_printf(smbios_ipmi_type_desc(i.smbip_type), 859 fp, " Type: %u", i.smbip_type); 860 861 oprintf(fp, " BMC IPMI Version: %u.%u\n", 862 i.smbip_vers.smbv_major, i.smbip_vers.smbv_minor); 863 864 oprintf(fp, " i2c Bus Slave Address: 0x%x\n", i.smbip_i2c); 865 oprintf(fp, " NV Storage Device Bus ID: 0x%x\n", i.smbip_bus); 866 oprintf(fp, " BMC Base Address: 0x%llx\n", (u_longlong_t)i.smbip_addr); 867 oprintf(fp, " Interrupt Number: %u\n", i.smbip_intr); 868 oprintf(fp, " Register Spacing: %u\n", i.smbip_regspacing); 869 870 flag_printf(fp, "Flags", i.smbip_flags, sizeof (i.smbip_flags) * NBBY, 871 smbios_ipmi_flag_name, smbios_ipmi_flag_desc); 872 } 873 874 static void 875 print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp) 876 { 877 int i; 878 smbios_processor_ext_t ep; 879 880 if (check_oem(shp) != 0) 881 return; 882 883 (void) smbios_info_extprocessor(shp, id, &ep); 884 885 oprintf(fp, " Processor: %u\n", ep.smbpe_processor); 886 oprintf(fp, " FRU: %u\n", ep.smbpe_fru); 887 oprintf(fp, " Initial APIC ID count: %u\n\n", ep.smbpe_n); 888 889 for (i = 0; i < ep.smbpe_n; i++) { 890 oprintf(fp, " Logical Strand %u: Initial APIC ID: %u\n", i, 891 ep.smbpe_apicid[i]); 892 } 893 } 894 895 static void 896 print_extport(smbios_hdl_t *shp, id_t id, FILE *fp) 897 { 898 smbios_port_ext_t epo; 899 900 if (check_oem(shp) != 0) 901 return; 902 903 (void) smbios_info_extport(shp, id, &epo); 904 905 oprintf(fp, " Chassis Handle: %u\n", epo.smbporte_chassis); 906 oprintf(fp, " Port Connector Handle: %u\n", epo.smbporte_port); 907 oprintf(fp, " Device Type: %u\n", epo.smbporte_dtype); 908 oprintf(fp, " Device Handle: %u\n", epo.smbporte_devhdl); 909 oprintf(fp, " PHY: %u\n", epo.smbporte_phy); 910 } 911 912 static void 913 print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp) 914 { 915 smbios_pciexrc_t pcie; 916 917 if (check_oem(shp) != 0) 918 return; 919 920 (void) smbios_info_pciexrc(shp, id, &pcie); 921 922 oprintf(fp, " Component ID: %u\n", pcie.smbpcie_bb); 923 oprintf(fp, " BDF: 0x%x\n", pcie.smbpcie_bdf); 924 } 925 926 static void 927 print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp) 928 { 929 smbios_memarray_ext_t em; 930 931 if (check_oem(shp) != 0) 932 return; 933 934 (void) smbios_info_extmemarray(shp, id, &em); 935 936 oprintf(fp, " Physical Memory Array Handle: %u\n", em.smbmae_ma); 937 oprintf(fp, " Component Parent Handle: %u\n", em.smbmae_comp); 938 oprintf(fp, " BDF: 0x%x\n", em.smbmae_bdf); 939 } 940 941 static void 942 print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp) 943 { 944 int i; 945 smbios_memdevice_ext_t emd; 946 947 if (check_oem(shp) != 0) 948 return; 949 950 (void) smbios_info_extmemdevice(shp, id, &emd); 951 952 oprintf(fp, " Memory Device Handle: %u\n", emd.smbmdeve_md); 953 oprintf(fp, " DRAM Channel: %u\n", emd.smbmdeve_drch); 954 oprintf(fp, " Number of Chip Selects: %u\n", emd.smbmdeve_ncs); 955 956 for (i = 0; i < emd.smbmdeve_ncs; i++) { 957 oprintf(fp, " Chip Select: %u\n", emd.smbmdeve_cs[i]); 958 } 959 } 960 961 static int 962 print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) 963 { 964 smbios_info_t info; 965 int hex = opt_x; 966 const char *s; 967 968 if (opt_t != -1 && opt_t != sp->smbstr_type) 969 return (0); /* skip struct if type doesn't match -t */ 970 971 if (!opt_O && (sp->smbstr_type == SMB_TYPE_MEMCTL || 972 sp->smbstr_type == SMB_TYPE_MEMMOD)) 973 return (0); /* skip struct if type is obsolete */ 974 975 if (g_hdr++ == 0 || !opt_s) 976 oprintf(fp, "%-5s %-4s %s\n", "ID", "SIZE", "TYPE"); 977 978 oprintf(fp, "%-5u %-4lu", 979 (uint_t)sp->smbstr_id, (ulong_t)sp->smbstr_size); 980 981 if ((s = smbios_type_name(sp->smbstr_type)) != NULL) 982 oprintf(fp, " %s", s); 983 else if (sp->smbstr_type > SMB_TYPE_OEM_LO && 984 sp->smbstr_type < SMB_TYPE_OEM_HI) 985 oprintf(fp, " %s+%u", "SMB_TYPE_OEM_LO", 986 sp->smbstr_type - SMB_TYPE_OEM_LO); 987 else 988 oprintf(fp, " %u", sp->smbstr_type); 989 990 if ((s = smbios_type_desc(sp->smbstr_type)) != NULL) 991 oprintf(fp, " (%s)\n", s); 992 else 993 oprintf(fp, "\n"); 994 995 if (opt_s) 996 return (0); /* only print header line if -s specified */ 997 998 if (smbios_info_common(shp, sp->smbstr_id, &info) == 0) { 999 oprintf(fp, "\n"); 1000 print_common(&info, fp); 1001 } 1002 1003 switch (sp->smbstr_type) { 1004 case SMB_TYPE_BIOS: 1005 oprintf(fp, "\n"); 1006 print_bios(shp, fp); 1007 break; 1008 case SMB_TYPE_SYSTEM: 1009 oprintf(fp, "\n"); 1010 print_system(shp, fp); 1011 break; 1012 case SMB_TYPE_BASEBOARD: 1013 oprintf(fp, "\n"); 1014 print_bboard(shp, sp->smbstr_id, fp); 1015 break; 1016 case SMB_TYPE_CHASSIS: 1017 oprintf(fp, "\n"); 1018 print_chassis(shp, sp->smbstr_id, fp); 1019 break; 1020 case SMB_TYPE_PROCESSOR: 1021 oprintf(fp, "\n"); 1022 print_processor(shp, sp->smbstr_id, fp); 1023 break; 1024 case SMB_TYPE_CACHE: 1025 oprintf(fp, "\n"); 1026 print_cache(shp, sp->smbstr_id, fp); 1027 break; 1028 case SMB_TYPE_PORT: 1029 oprintf(fp, "\n"); 1030 print_port(shp, sp->smbstr_id, fp); 1031 break; 1032 case SMB_TYPE_SLOT: 1033 oprintf(fp, "\n"); 1034 print_slot(shp, sp->smbstr_id, fp); 1035 break; 1036 case SMB_TYPE_OBDEVS: 1037 oprintf(fp, "\n"); 1038 print_obdevs(shp, sp->smbstr_id, fp); 1039 break; 1040 case SMB_TYPE_OEMSTR: 1041 case SMB_TYPE_SYSCONFSTR: 1042 oprintf(fp, "\n"); 1043 print_strtab(shp, sp->smbstr_id, fp); 1044 break; 1045 case SMB_TYPE_LANG: 1046 oprintf(fp, "\n"); 1047 print_lang(shp, sp->smbstr_id, fp); 1048 break; 1049 case SMB_TYPE_EVENTLOG: 1050 oprintf(fp, "\n"); 1051 print_evlog(shp, sp->smbstr_id, fp); 1052 break; 1053 case SMB_TYPE_MEMARRAY: 1054 oprintf(fp, "\n"); 1055 print_memarray(shp, sp->smbstr_id, fp); 1056 break; 1057 case SMB_TYPE_MEMDEVICE: 1058 oprintf(fp, "\n"); 1059 print_memdevice(shp, sp->smbstr_id, fp); 1060 break; 1061 case SMB_TYPE_MEMARRAYMAP: 1062 oprintf(fp, "\n"); 1063 print_memarrmap(shp, sp->smbstr_id, fp); 1064 break; 1065 case SMB_TYPE_MEMDEVICEMAP: 1066 oprintf(fp, "\n"); 1067 print_memdevmap(shp, sp->smbstr_id, fp); 1068 break; 1069 case SMB_TYPE_SECURITY: 1070 oprintf(fp, "\n"); 1071 print_hwsec(shp, fp); 1072 break; 1073 case SMB_TYPE_BOOT: 1074 oprintf(fp, "\n"); 1075 print_boot(shp, fp); 1076 break; 1077 case SMB_TYPE_IPMIDEV: 1078 oprintf(fp, "\n"); 1079 print_ipmi(shp, fp); 1080 break; 1081 case SMB_TYPE_OBDEVEXT: 1082 oprintf(fp, "\n"); 1083 print_obdevs_ext(shp, sp->smbstr_id, fp); 1084 break; 1085 case SUN_OEM_EXT_PROCESSOR: 1086 oprintf(fp, "\n"); 1087 print_extprocessor(shp, sp->smbstr_id, fp); 1088 break; 1089 case SUN_OEM_EXT_PORT: 1090 oprintf(fp, "\n"); 1091 print_extport(shp, sp->smbstr_id, fp); 1092 break; 1093 case SUN_OEM_PCIEXRC: 1094 oprintf(fp, "\n"); 1095 print_pciexrc(shp, sp->smbstr_id, fp); 1096 break; 1097 case SUN_OEM_EXT_MEMARRAY: 1098 oprintf(fp, "\n"); 1099 print_extmemarray(shp, sp->smbstr_id, fp); 1100 break; 1101 case SUN_OEM_EXT_MEMDEVICE: 1102 oprintf(fp, "\n"); 1103 print_extmemdevice(shp, sp->smbstr_id, fp); 1104 break; 1105 default: 1106 hex++; 1107 } 1108 1109 if (hex) 1110 print_bytes(sp->smbstr_data, sp->smbstr_size, fp); 1111 else 1112 oprintf(fp, "\n"); 1113 1114 return (0); 1115 } 1116 1117 static uint16_t 1118 getu16(const char *name, const char *s) 1119 { 1120 u_longlong_t val; 1121 char *p; 1122 1123 errno = 0; 1124 val = strtoull(s, &p, 0); 1125 1126 if (errno != 0 || p == s || *p != '\0' || val > UINT16_MAX) { 1127 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 1128 g_pname, name, s); 1129 exit(SMBIOS_USAGE); 1130 } 1131 1132 return ((uint16_t)val); 1133 } 1134 1135 static uint16_t 1136 getstype(const char *name, const char *s) 1137 { 1138 const char *ts; 1139 uint16_t t; 1140 1141 for (t = 0; t < SMB_TYPE_OEM_LO; t++) { 1142 if ((ts = smbios_type_name(t)) != NULL && strcmp(s, ts) == 0) 1143 return (t); 1144 } 1145 1146 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 1147 g_pname, name, s); 1148 1149 exit(SMBIOS_USAGE); 1150 /*NOTREACHED*/ 1151 } 1152 1153 static int 1154 usage(FILE *fp) 1155 { 1156 (void) fprintf(fp, "Usage: %s " 1157 "[-BeOsx] [-i id] [-t type] [-w file] [file]\n\n", g_pname); 1158 1159 (void) fprintf(fp, 1160 "\t-B disable header validation for broken BIOSes\n" 1161 "\t-e display SMBIOS entry point information\n" 1162 "\t-i display only the specified structure\n" 1163 "\t-O display obsolete structure types\n" 1164 "\t-s display only a summary of structure identifiers and types\n" 1165 "\t-t display only the specified structure type\n" 1166 "\t-w write the raw data to the specified file\n" 1167 "\t-x display raw data for structures\n"); 1168 1169 return (SMBIOS_USAGE); 1170 } 1171 1172 int 1173 main(int argc, char *argv[]) 1174 { 1175 const char *ifile = NULL; 1176 const char *ofile = NULL; 1177 int oflags = 0; 1178 1179 smbios_hdl_t *shp; 1180 smbios_struct_t s; 1181 int err, fd, c; 1182 char *p; 1183 1184 if ((p = strrchr(argv[0], '/')) == NULL) 1185 g_pname = argv[0]; 1186 else 1187 g_pname = p + 1; 1188 1189 while (optind < argc) { 1190 while ((c = getopt(argc, argv, "Bei:Ost:w:xZ")) != EOF) { 1191 switch (c) { 1192 case 'B': 1193 oflags |= SMB_O_NOCKSUM | SMB_O_NOVERS; 1194 break; 1195 case 'e': 1196 opt_e++; 1197 break; 1198 case 'i': 1199 opt_i = getu16("struct ID", optarg); 1200 break; 1201 case 'O': 1202 opt_O++; 1203 break; 1204 case 's': 1205 opt_s++; 1206 break; 1207 case 't': 1208 if (isdigit(optarg[0])) 1209 opt_t = getu16("struct type", optarg); 1210 else 1211 opt_t = getstype("struct type", optarg); 1212 break; 1213 case 'w': 1214 ofile = optarg; 1215 break; 1216 case 'x': 1217 opt_x++; 1218 break; 1219 case 'Z': 1220 oflags |= SMB_O_ZIDS; /* undocumented */ 1221 break; 1222 default: 1223 return (usage(stderr)); 1224 } 1225 } 1226 1227 if (optind < argc) { 1228 if (ifile != NULL) { 1229 (void) fprintf(stderr, "%s: illegal " 1230 "argument -- %s\n", g_pname, argv[optind]); 1231 return (SMBIOS_USAGE); 1232 } 1233 ifile = argv[optind++]; 1234 } 1235 } 1236 1237 if ((shp = smbios_open(ifile, SMB_VERSION, oflags, &err)) == NULL) { 1238 (void) fprintf(stderr, "%s: failed to load SMBIOS: %s\n", 1239 g_pname, smbios_errmsg(err)); 1240 return (SMBIOS_ERROR); 1241 } 1242 1243 if (ofile != NULL) { 1244 if ((fd = open(ofile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) { 1245 (void) fprintf(stderr, "%s: failed to open %s: %s\n", 1246 g_pname, ofile, strerror(errno)); 1247 err = SMBIOS_ERROR; 1248 } else if (smbios_write(shp, fd) != 0) { 1249 (void) fprintf(stderr, "%s: failed to write %s: %s\n", 1250 g_pname, ofile, smbios_errmsg(smbios_errno(shp))); 1251 err = SMBIOS_ERROR; 1252 } 1253 smbios_close(shp); 1254 return (err); 1255 } 1256 1257 if (opt_e) { 1258 print_smbios(shp, stdout); 1259 smbios_close(shp); 1260 return (SMBIOS_SUCCESS); 1261 } 1262 1263 if (opt_O && (opt_i != -1 || opt_t != -1)) 1264 opt_O++; /* -i or -t imply displaying obsolete records */ 1265 1266 if (opt_i != -1) 1267 err = smbios_lookup_id(shp, opt_i, &s); 1268 else 1269 err = smbios_iter(shp, print_struct, stdout); 1270 1271 if (err != 0) { 1272 (void) fprintf(stderr, "%s: failed to access SMBIOS: %s\n", 1273 g_pname, smbios_errmsg(smbios_errno(shp))); 1274 smbios_close(shp); 1275 return (SMBIOS_ERROR); 1276 } 1277 1278 if (opt_i != -1) 1279 (void) print_struct(shp, &s, stdout); 1280 1281 smbios_close(shp); 1282 return (SMBIOS_SUCCESS); 1283 } 1284