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