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