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