1ae115bc7Smrj /*
2ae115bc7Smrj * CDDL HEADER START
3ae115bc7Smrj *
4ae115bc7Smrj * The contents of this file are subject to the terms of the
542a58d9dSsethg * Common Development and Distribution License (the "License").
642a58d9dSsethg * You may not use this file except in compliance with the License.
7ae115bc7Smrj *
8ae115bc7Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj * See the License for the specific language governing permissions
11ae115bc7Smrj * and limitations under the License.
12ae115bc7Smrj *
13ae115bc7Smrj * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj *
19ae115bc7Smrj * CDDL HEADER END
20ae115bc7Smrj */
21ae115bc7Smrj
22ae115bc7Smrj /*
2342a58d9dSsethg * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24ae115bc7Smrj * Use is subject to license terms.
25ae115bc7Smrj */
26*caf590b5SRobert Mustacchi /*
27*caf590b5SRobert Mustacchi * Copyright 2015 Joyent, Inc.
28*caf590b5SRobert Mustacchi */
29ae115bc7Smrj
30ae115bc7Smrj /*
31ae115bc7Smrj * x86 System Management BIOS prtdiag
32ae115bc7Smrj *
33ae115bc7Smrj * Most modern x86 systems support a System Management BIOS, which is a memory
34ae115bc7Smrj * buffer filled in by the BIOS at boot time that describes the hardware. This
35ae115bc7Smrj * data format is described by DMTF specification DSP0134 (see http://dmtf.org)
36ae115bc7Smrj * This file implements a rudimentary prtdiag(1M) display using the SMBIOS.
37ae115bc7Smrj * Access to the data is provided by libsmbios: see <sys/smbios.h> for info.
38ae115bc7Smrj *
39ae115bc7Smrj * NOTE: It is important to understand that x86 hardware varies extremely
40ae115bc7Smrj * widely and that the DMTF SMBIOS specification leaves way too much latitude
41ae115bc7Smrj * for implementors, and provides no standardized validation mechanism. As
42ae115bc7Smrj * such, it is not uncommon to find out-of-spec SMBIOSes or fields that
43ae115bc7Smrj * contain strange and possibly even incorrect information. As such, this
44ae115bc7Smrj * file should not be extended to report every SMBIOS tidbit or structure in
45ae115bc7Smrj * the spec unless we have good reason to believe it tends to be reliable.
46ae115bc7Smrj *
47ae115bc7Smrj * Similarly, the prtdiag(1M) utility itself should not be used to spit out
48ae115bc7Smrj * every possible bit of x86 configuration data from every possible source;
49ae115bc7Smrj * otherwise this code will become an unmaintainable and untestable disaster.
50ae115bc7Smrj * Extensions to prtdiag should prefer to use more stable kernel mechanisms
51ae115bc7Smrj * that actually discover the true hardware when such subsystems are available,
52ae115bc7Smrj * and should generally limit themselves to commonly needed h/w data. As such,
53ae115bc7Smrj * extensions to x86 prtdiag should focus on integration with the device tree.
54ae115bc7Smrj *
55ae115bc7Smrj * The prtdiag(1M) utility is for service personnel and system administrators:
56ae115bc7Smrj * it is not your personal ACPI disassembler or CPUID decoder ring. The
57ae115bc7Smrj * complete SMBIOS data is available from smbdump(1), and other specialized
58ae115bc7Smrj * tools can be created to display the state of other x86 features, especially
59ae115bc7Smrj * when that information is more for kernel developers than box administrators.
60ae115bc7Smrj */
61ae115bc7Smrj
62ae115bc7Smrj #include <smbios.h>
63ae115bc7Smrj #include <alloca.h>
64ae115bc7Smrj #include <locale.h>
65ae115bc7Smrj #include <strings.h>
66ae115bc7Smrj #include <stdlib.h>
67ae115bc7Smrj #include <stdio.h>
68ae115bc7Smrj #include <ctype.h>
69*caf590b5SRobert Mustacchi #include <pcidb.h>
70*caf590b5SRobert Mustacchi #include <fm/libtopo.h>
71*caf590b5SRobert Mustacchi #include <fm/topo_hc.h>
72*caf590b5SRobert Mustacchi #include <sys/fm/protocol.h>
73*caf590b5SRobert Mustacchi
74*caf590b5SRobert Mustacchi static pcidb_hdl_t *prt_php;
75ae115bc7Smrj
76ae115bc7Smrj /*ARGSUSED*/
77ae115bc7Smrj static int
do_procs(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)78ae115bc7Smrj do_procs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
79ae115bc7Smrj {
80ae115bc7Smrj smbios_processor_t p;
81ae115bc7Smrj smbios_info_t info;
82ae115bc7Smrj const char *v;
83ae115bc7Smrj char *s;
84ae115bc7Smrj size_t n;
85ae115bc7Smrj
86ae115bc7Smrj if (sp->smbstr_type == SMB_TYPE_PROCESSOR &&
87ae115bc7Smrj smbios_info_processor(shp, sp->smbstr_id, &p) != SMB_ERR &&
88ae115bc7Smrj smbios_info_common(shp, sp->smbstr_id, &info) != SMB_ERR &&
89ae115bc7Smrj SMB_PRSTATUS_PRESENT(p.smbp_status)) {
90ae115bc7Smrj
91ae115bc7Smrj /*
92ae115bc7Smrj * Obtaining a decent string for the type of processor is
93ae115bc7Smrj * messy: the BIOS has hopefully filled in the SMBIOS record.
94ae115bc7Smrj * If so, strip trailing spaces and \r (seen in some BIOSes).
95ae115bc7Smrj * If not, fall back to the family name for p.smbp_family.
96ae115bc7Smrj */
97ae115bc7Smrj if (info.smbi_version != NULL && *info.smbi_version != '\0') {
98ae115bc7Smrj n = strlen(info.smbi_version);
99ae115bc7Smrj v = s = alloca(n + 1);
100ae115bc7Smrj (void) strcpy(s, info.smbi_version);
101ae115bc7Smrj
102ae115bc7Smrj if (s[n - 1] == '\r')
103ae115bc7Smrj s[--n] = '\0';
104ae115bc7Smrj
105ae115bc7Smrj while (n != 0 && isspace(s[n - 1]))
106ae115bc7Smrj s[--n] = '\0';
107ae115bc7Smrj
108ae115bc7Smrj } else if ((v = smbios_processor_family_desc(
109ae115bc7Smrj p.smbp_family)) == NULL) {
110ae115bc7Smrj v = gettext("Unknown");
111ae115bc7Smrj }
112ae115bc7Smrj
113ae115bc7Smrj (void) printf(gettext("%-32s %s\n"), v, info.smbi_location);
114ae115bc7Smrj }
115ae115bc7Smrj
116ae115bc7Smrj return (0);
117ae115bc7Smrj }
118ae115bc7Smrj
119ae115bc7Smrj /*
120ae115bc7Smrj * NOTE: It would be very convenient to print the DIMM size in do_memdevs.
121ae115bc7Smrj * Unfortunately, SMBIOS can only be relied upon to tell us whether a DIMM is
122ae115bc7Smrj * present or not (smbmd_size == 0). Some BIOSes do fill in an accurate size
123ae115bc7Smrj * for DIMMs, whereas others fill in the maximum size, and still others insert
124ae115bc7Smrj * a wrong value. Sizes will need to wait for x86 memory controller interfaces
125ae115bc7Smrj * or integration with IPMI, which can actually read the true DIMM SPD data.
126ae115bc7Smrj */
127ae115bc7Smrj /*ARGSUSED*/
128ae115bc7Smrj static int
do_memdevs(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)129ae115bc7Smrj do_memdevs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
130ae115bc7Smrj {
131ae115bc7Smrj smbios_memdevice_t md;
132ae115bc7Smrj
133ae115bc7Smrj if (sp->smbstr_type == SMB_TYPE_MEMDEVICE &&
134ae115bc7Smrj smbios_info_memdevice(shp, sp->smbstr_id, &md) != SMB_ERR) {
135ae115bc7Smrj
136ae115bc7Smrj const char *t = smbios_memdevice_type_desc(md.smbmd_type);
137ae115bc7Smrj char buf[8];
138ae115bc7Smrj
139ae115bc7Smrj if (md.smbmd_set != (uint8_t)-1)
140ae115bc7Smrj (void) snprintf(buf, sizeof (buf), "%u", md.smbmd_set);
141ae115bc7Smrj else
142ae115bc7Smrj (void) strcpy(buf, "-");
143ae115bc7Smrj
14442a58d9dSsethg (void) printf(gettext("%-11s %-6s %-3s %-19s %s\n"),
145ae115bc7Smrj t ? t : gettext("Unknown"),
146ae115bc7Smrj md.smbmd_size ? gettext("in use") : gettext("empty"),
147ae115bc7Smrj buf, md.smbmd_dloc, md.smbmd_bloc);
148ae115bc7Smrj }
149ae115bc7Smrj
150ae115bc7Smrj return (0);
151ae115bc7Smrj }
152ae115bc7Smrj
153ae115bc7Smrj /*ARGSUSED*/
154ae115bc7Smrj static int
do_obdevs(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)155ae115bc7Smrj do_obdevs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
156ae115bc7Smrj {
157ae115bc7Smrj smbios_obdev_t *argv;
158ae115bc7Smrj int i, argc;
159ae115bc7Smrj
160ae115bc7Smrj if (sp->smbstr_type == SMB_TYPE_OBDEVS &&
161ae115bc7Smrj (argc = smbios_info_obdevs(shp, sp->smbstr_id, 0, NULL)) > 0) {
162ae115bc7Smrj argv = alloca(sizeof (smbios_obdev_t) * argc);
163ae115bc7Smrj (void) smbios_info_obdevs(shp, sp->smbstr_id, argc, argv);
164ae115bc7Smrj for (i = 0; i < argc; i++)
165ae115bc7Smrj (void) printf(gettext("%s\n"), argv[i].smbd_name);
166ae115bc7Smrj }
167ae115bc7Smrj
168ae115bc7Smrj return (0);
169ae115bc7Smrj }
170ae115bc7Smrj
171ae115bc7Smrj /*ARGSUSED*/
172ae115bc7Smrj static int
do_slot_mapping_cb(topo_hdl_t * thp,tnode_t * node,void * arg)173*caf590b5SRobert Mustacchi do_slot_mapping_cb(topo_hdl_t *thp, tnode_t *node, void *arg)
174*caf590b5SRobert Mustacchi {
175*caf590b5SRobert Mustacchi int err, ret;
176*caf590b5SRobert Mustacchi nvlist_t *rsrc = NULL;
177*caf590b5SRobert Mustacchi const char *match = arg;
178*caf590b5SRobert Mustacchi char *s, *fmri = NULL;
179*caf590b5SRobert Mustacchi char *didstr = NULL, *driver = NULL, *vidstr = NULL;
180*caf590b5SRobert Mustacchi boolean_t printed = B_FALSE;
181*caf590b5SRobert Mustacchi
182*caf590b5SRobert Mustacchi ret = TOPO_WALK_NEXT;
183*caf590b5SRobert Mustacchi if (topo_node_resource(node, &rsrc, &err) < 0)
184*caf590b5SRobert Mustacchi goto next;
185*caf590b5SRobert Mustacchi if (topo_fmri_nvl2str(thp, rsrc, &fmri, &err) < 0)
186*caf590b5SRobert Mustacchi goto next;
187*caf590b5SRobert Mustacchi
188*caf590b5SRobert Mustacchi if ((s = strstr(fmri, match)) == NULL)
189*caf590b5SRobert Mustacchi goto next;
190*caf590b5SRobert Mustacchi if (s[strlen(match)] != '\0')
191*caf590b5SRobert Mustacchi goto next;
192*caf590b5SRobert Mustacchi
193*caf590b5SRobert Mustacchi /* At this point we think we've found a match */
194*caf590b5SRobert Mustacchi ret = TOPO_WALK_TERMINATE;
195*caf590b5SRobert Mustacchi if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DRIVER, &driver,
196*caf590b5SRobert Mustacchi &err) != 0)
197*caf590b5SRobert Mustacchi driver = NULL;
198*caf590b5SRobert Mustacchi
199*caf590b5SRobert Mustacchi if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_VENDID,
200*caf590b5SRobert Mustacchi &vidstr, &err) != 0)
201*caf590b5SRobert Mustacchi goto next;
202*caf590b5SRobert Mustacchi
203*caf590b5SRobert Mustacchi if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_DEVID,
204*caf590b5SRobert Mustacchi &didstr, &err) != 0)
205*caf590b5SRobert Mustacchi goto next;
206*caf590b5SRobert Mustacchi
207*caf590b5SRobert Mustacchi if (prt_php != NULL) {
208*caf590b5SRobert Mustacchi long vid, did;
209*caf590b5SRobert Mustacchi
210*caf590b5SRobert Mustacchi vid = strtol(vidstr, NULL, 16);
211*caf590b5SRobert Mustacchi did = strtol(didstr, NULL, 16);
212*caf590b5SRobert Mustacchi if (vid >= 0 && vid <= UINT16_MAX &&
213*caf590b5SRobert Mustacchi did >= 0 && did <= UINT16_MAX) {
214*caf590b5SRobert Mustacchi pcidb_device_t *pdev;
215*caf590b5SRobert Mustacchi
216*caf590b5SRobert Mustacchi pdev = pcidb_lookup_device(prt_php, vid, did);
217*caf590b5SRobert Mustacchi if (pdev != NULL) {
218*caf590b5SRobert Mustacchi pcidb_vendor_t *pvend;
219*caf590b5SRobert Mustacchi pvend = pcidb_device_vendor(pdev);
220*caf590b5SRobert Mustacchi (void) printf(gettext(", %s %s (%s)"),
221*caf590b5SRobert Mustacchi pcidb_vendor_name(pvend),
222*caf590b5SRobert Mustacchi pcidb_device_name(pdev),
223*caf590b5SRobert Mustacchi driver != NULL ? driver : "<unknown>");
224*caf590b5SRobert Mustacchi printed = B_TRUE;
225*caf590b5SRobert Mustacchi }
226*caf590b5SRobert Mustacchi }
227*caf590b5SRobert Mustacchi }
228*caf590b5SRobert Mustacchi
229*caf590b5SRobert Mustacchi if (printed == B_FALSE) {
230*caf590b5SRobert Mustacchi (void) printf(gettext(", pci%s,%s (%s)"), vidstr, didstr,
231*caf590b5SRobert Mustacchi driver != NULL ? driver : "<unknown>");
232*caf590b5SRobert Mustacchi }
233*caf590b5SRobert Mustacchi next:
234*caf590b5SRobert Mustacchi topo_hdl_strfree(thp, didstr);
235*caf590b5SRobert Mustacchi topo_hdl_strfree(thp, driver);
236*caf590b5SRobert Mustacchi topo_hdl_strfree(thp, vidstr);
237*caf590b5SRobert Mustacchi topo_hdl_strfree(thp, fmri);
238*caf590b5SRobert Mustacchi nvlist_free(rsrc);
239*caf590b5SRobert Mustacchi return (ret);
240*caf590b5SRobert Mustacchi }
241*caf590b5SRobert Mustacchi
242*caf590b5SRobert Mustacchi static void
do_slot_mapping(smbios_slot_t * s,topo_hdl_t * thp)243*caf590b5SRobert Mustacchi do_slot_mapping(smbios_slot_t *s, topo_hdl_t *thp)
244*caf590b5SRobert Mustacchi {
245*caf590b5SRobert Mustacchi int err;
246*caf590b5SRobert Mustacchi uint_t dev, func;
247*caf590b5SRobert Mustacchi topo_walk_t *twp;
248*caf590b5SRobert Mustacchi char pciex[256];
249*caf590b5SRobert Mustacchi
250*caf590b5SRobert Mustacchi /*
251*caf590b5SRobert Mustacchi * Bits 7:3 are the device number and bits 2:0 are the function.
252*caf590b5SRobert Mustacchi */
253*caf590b5SRobert Mustacchi dev = s->smbl_df >> 3;
254*caf590b5SRobert Mustacchi func = s->smbl_df & 0x7;
255*caf590b5SRobert Mustacchi
256*caf590b5SRobert Mustacchi (void) snprintf(pciex, sizeof (pciex), "%s=%u/%s=%u/%s=%d",
257*caf590b5SRobert Mustacchi PCIEX_BUS, s->smbl_bus, PCIEX_DEVICE, dev, PCIEX_FUNCTION, func);
258*caf590b5SRobert Mustacchi
259*caf590b5SRobert Mustacchi twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, do_slot_mapping_cb, pciex,
260*caf590b5SRobert Mustacchi &err);
261*caf590b5SRobert Mustacchi if (twp == NULL)
262*caf590b5SRobert Mustacchi return;
263*caf590b5SRobert Mustacchi
264*caf590b5SRobert Mustacchi (void) topo_walk_step(twp, TOPO_WALK_CHILD);
265*caf590b5SRobert Mustacchi topo_walk_fini(twp);
266*caf590b5SRobert Mustacchi }
267*caf590b5SRobert Mustacchi
268*caf590b5SRobert Mustacchi /*ARGSUSED*/
269*caf590b5SRobert Mustacchi static int
do_slots(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)270ae115bc7Smrj do_slots(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
271ae115bc7Smrj {
272ae115bc7Smrj smbios_slot_t s;
273ae115bc7Smrj
274ae115bc7Smrj if (sp->smbstr_type == SMB_TYPE_SLOT &&
275ae115bc7Smrj smbios_info_slot(shp, sp->smbstr_id, &s) != SMB_ERR) {
276ae115bc7Smrj
277ae115bc7Smrj const char *t = smbios_slot_type_desc(s.smbl_type);
278ae115bc7Smrj const char *u = smbios_slot_usage_desc(s.smbl_usage);
279ae115bc7Smrj
280*caf590b5SRobert Mustacchi (void) printf(gettext("%-3u %-9s %-16s %s"),
281ae115bc7Smrj s.smbl_id, u ? u : gettext("Unknown"),
282ae115bc7Smrj t ? t : gettext("Unknown"), s.smbl_name);
283*caf590b5SRobert Mustacchi
284*caf590b5SRobert Mustacchi /*
285*caf590b5SRobert Mustacchi * If the slot isn't of a type where this makes sense, then
286*caf590b5SRobert Mustacchi * SMBIOS will populate any of these members with the value
287*caf590b5SRobert Mustacchi * 0xff. Therefore if we find any of them set there, we just
288*caf590b5SRobert Mustacchi * ignore it for now.
289*caf590b5SRobert Mustacchi */
290*caf590b5SRobert Mustacchi if (s.smbl_sg != 0xff && s.smbl_bus != 0xff &&
291*caf590b5SRobert Mustacchi s.smbl_df != 0xff && arg != NULL)
292*caf590b5SRobert Mustacchi do_slot_mapping(&s, arg);
293*caf590b5SRobert Mustacchi
294*caf590b5SRobert Mustacchi (void) printf(gettext("\n"));
295ae115bc7Smrj }
296ae115bc7Smrj
297ae115bc7Smrj return (0);
298ae115bc7Smrj }
299ae115bc7Smrj
300ae115bc7Smrj /*ARGSUSED*/
301ae115bc7Smrj int
do_prominfo(int opt_v,char * progname,int opt_l,int opt_p)302ae115bc7Smrj do_prominfo(int opt_v, char *progname, int opt_l, int opt_p)
303ae115bc7Smrj {
304ae115bc7Smrj smbios_hdl_t *shp;
305ae115bc7Smrj smbios_system_t sys;
306ae115bc7Smrj smbios_bios_t bios;
307ae115bc7Smrj smbios_ipmi_t ipmi;
308ae115bc7Smrj smbios_info_t info;
309*caf590b5SRobert Mustacchi topo_hdl_t *thp;
310*caf590b5SRobert Mustacchi char *uuid;
311ae115bc7Smrj
312ae115bc7Smrj const char *s;
313ae115bc7Smrj id_t id;
314ae115bc7Smrj int err;
315ae115bc7Smrj
316ae115bc7Smrj if ((shp = smbios_open(NULL, SMB_VERSION, 0, &err)) == NULL) {
317ae115bc7Smrj (void) fprintf(stderr,
318ae115bc7Smrj gettext("%s: failed to open SMBIOS: %s\n"),
319ae115bc7Smrj progname, smbios_errmsg(err));
320ae115bc7Smrj return (1);
321ae115bc7Smrj }
322ae115bc7Smrj
323ae115bc7Smrj if ((id = smbios_info_system(shp, &sys)) != SMB_ERR &&
324ae115bc7Smrj smbios_info_common(shp, id, &info) != SMB_ERR) {
325ae115bc7Smrj (void) printf(gettext("System Configuration: %s %s\n"),
326ae115bc7Smrj info.smbi_manufacturer, info.smbi_product);
327ae115bc7Smrj } else {
328ae115bc7Smrj (void) fprintf(stderr,
329ae115bc7Smrj gettext("%s: failed to get system info: %s\n"),
330ae115bc7Smrj progname, smbios_errmsg(smbios_errno(shp)));
331ae115bc7Smrj }
332ae115bc7Smrj
333ae115bc7Smrj if (smbios_info_bios(shp, &bios) != SMB_ERR) {
334ae115bc7Smrj (void) printf(gettext("BIOS Configuration: %s %s %s\n"),
335ae115bc7Smrj bios.smbb_vendor, bios.smbb_version, bios.smbb_reldate);
336ae115bc7Smrj } else {
337ae115bc7Smrj (void) fprintf(stderr,
338ae115bc7Smrj gettext("%s: failed to get bios info: %s\n"),
339ae115bc7Smrj progname, smbios_errmsg(smbios_errno(shp)));
340ae115bc7Smrj }
341ae115bc7Smrj
342ae115bc7Smrj if (smbios_info_ipmi(shp, &ipmi) != SMB_ERR) {
343ae115bc7Smrj if ((s = smbios_ipmi_type_desc(ipmi.smbip_type)) == NULL)
344ae115bc7Smrj s = gettext("Unknown");
345ae115bc7Smrj
346ae115bc7Smrj (void) printf(gettext("BMC Configuration: IPMI %u.%u (%s)\n"),
347ae115bc7Smrj ipmi.smbip_vers.smbv_major, ipmi.smbip_vers.smbv_minor, s);
348ae115bc7Smrj }
349ae115bc7Smrj
350*caf590b5SRobert Mustacchi /*
351*caf590b5SRobert Mustacchi * Silently swallow all libtopo and libpcidb related errors.
352*caf590b5SRobert Mustacchi */
353*caf590b5SRobert Mustacchi uuid = NULL;
354*caf590b5SRobert Mustacchi if ((thp = topo_open(TOPO_VERSION, NULL, &err)) != NULL) {
355*caf590b5SRobert Mustacchi if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
356*caf590b5SRobert Mustacchi topo_close(thp);
357*caf590b5SRobert Mustacchi thp = NULL;
358*caf590b5SRobert Mustacchi }
359*caf590b5SRobert Mustacchi }
360*caf590b5SRobert Mustacchi
361*caf590b5SRobert Mustacchi prt_php = pcidb_open(PCIDB_VERSION);
362*caf590b5SRobert Mustacchi
363ae115bc7Smrj (void) printf(gettext(
364ae115bc7Smrj "\n==== Processor Sockets ====================================\n"));
365ae115bc7Smrj
366ae115bc7Smrj (void) printf(gettext("\n%-32s %s"), "Version", "Location Tag");
367ae115bc7Smrj
368ae115bc7Smrj (void) printf(gettext(
369ae115bc7Smrj "\n-------------------------------- --------------------------\n"));
370ae115bc7Smrj (void) smbios_iter(shp, do_procs, NULL);
371ae115bc7Smrj
372ae115bc7Smrj (void) printf(gettext(
373ae115bc7Smrj "\n==== Memory Device Sockets ================================\n"));
374ae115bc7Smrj
37542a58d9dSsethg (void) printf(gettext("\n%-11s %-6s %-3s %-19s %s"),
376ae115bc7Smrj "Type", "Status", "Set", "Device Locator", "Bank Locator");
377ae115bc7Smrj
378ae115bc7Smrj (void) printf(gettext(
379ae115bc7Smrj "\n----------- ------ --- ------------------- ----------------\n"));
380ae115bc7Smrj (void) smbios_iter(shp, do_memdevs, NULL);
381ae115bc7Smrj
382ae115bc7Smrj (void) printf(gettext(
383ae115bc7Smrj "\n==== On-Board Devices =====================================\n"));
384ae115bc7Smrj (void) smbios_iter(shp, do_obdevs, NULL);
385ae115bc7Smrj
386ae115bc7Smrj (void) printf(gettext(
387ae115bc7Smrj "\n==== Upgradeable Slots ====================================\n"));
388ae115bc7Smrj
389ae115bc7Smrj (void) printf(gettext("\n%-3s %-9s %-16s %s"),
390ae115bc7Smrj "ID", "Status", "Type", "Description");
391ae115bc7Smrj
392ae115bc7Smrj (void) printf(gettext(
393ae115bc7Smrj "\n--- --------- ---------------- ----------------------------\n"));
394*caf590b5SRobert Mustacchi (void) smbios_iter(shp, do_slots, thp);
395ae115bc7Smrj
396ae115bc7Smrj smbios_close(shp);
397*caf590b5SRobert Mustacchi
398*caf590b5SRobert Mustacchi topo_hdl_strfree(thp, uuid);
399*caf590b5SRobert Mustacchi if (thp != NULL) {
400*caf590b5SRobert Mustacchi topo_snap_release(thp);
401*caf590b5SRobert Mustacchi topo_close(thp);
402*caf590b5SRobert Mustacchi }
403*caf590b5SRobert Mustacchi pcidb_close(prt_php);
404*caf590b5SRobert Mustacchi
405ae115bc7Smrj return (0);
406ae115bc7Smrj }
407