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