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