xref: /onnv-gate/usr/src/common/smbios/smb_info.c (revision 11859:f06d538b0f01)
1437Smws /*
2437Smws  * CDDL HEADER START
3437Smws  *
4437Smws  * The contents of this file are subject to the terms of the
58467SEric.Schrock@Sun.COM  * Common Development and Distribution License (the "License").
68467SEric.Schrock@Sun.COM  * You may not use this file except in compliance with the License.
7437Smws  *
8437Smws  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9437Smws  * or http://www.opensolaris.org/os/licensing.
10437Smws  * See the License for the specific language governing permissions
11437Smws  * and limitations under the License.
12437Smws  *
13437Smws  * When distributing Covered Code, include this CDDL HEADER in each
14437Smws  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15437Smws  * If applicable, add the following below this CDDL HEADER, with the
16437Smws  * fields enclosed by brackets "[]" replaced with your own identifying
17437Smws  * information: Portions Copyright [yyyy] [name of copyright owner]
18437Smws  *
19437Smws  * CDDL HEADER END
20437Smws  */
21437Smws 
22437Smws /*
23*11859STom.Pothier@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24437Smws  * Use is subject to license terms.
25437Smws  */
26437Smws 
27437Smws /*
28437Smws  * SMBIOS Information Routines
29437Smws  *
30437Smws  * The routines in this file are used to convert from the SMBIOS data format to
31437Smws  * a more reasonable and stable set of structures offered as part of our ABI.
32437Smws  * These functions take the general form:
33437Smws  *
34437Smws  *	stp = smb_lookup_type(shp, foo);
35437Smws  *	smb_foo_t foo;
36437Smws  *
37437Smws  *	smb_info_bcopy(stp->smbst_hdr, &foo, sizeof (foo));
38437Smws  *      bzero(caller's struct);
39437Smws  *
40437Smws  *	copy/convert foo members into caller's struct
41437Smws  *
42437Smws  * We copy the internal structure on to an automatic variable so as to avoid
43437Smws  * checks everywhere for structures that the BIOS has improperly truncated, and
44437Smws  * also to automatically handle the case of a structure that has been extended.
45437Smws  * When necessary, this code can use smb_gteq() to determine whether the SMBIOS
46437Smws  * data is of a particular revision that is supposed to contain a new field.
47437Smws  */
48437Smws 
49437Smws #include <sys/smbios_impl.h>
50437Smws 
5110462SSean.Ye@Sun.COM #ifdef _KERNEL
5210462SSean.Ye@Sun.COM #include <sys/sunddi.h>
5310462SSean.Ye@Sun.COM #else
548467SEric.Schrock@Sun.COM #include <fcntl.h>
558467SEric.Schrock@Sun.COM #include <unistd.h>
5610462SSean.Ye@Sun.COM #include <string.h>
578467SEric.Schrock@Sun.COM #endif
588467SEric.Schrock@Sun.COM 
59437Smws /*
60437Smws  * A large number of SMBIOS structures contain a set of common strings used to
61437Smws  * describe a h/w component's serial number, manufacturer, etc.  These fields
62437Smws  * helpfully have different names and offsets and sometimes aren't consistent.
63437Smws  * To simplify life for our clients, we factor these common things out into
64437Smws  * smbios_info_t, which can be retrieved for any structure.  The following
65437Smws  * table describes the mapping from a given structure to the smbios_info_t.
6610942STom.Pothier@Sun.COM  * Multiple SMBIOS stuctures' contained objects are also handled here.
67437Smws  */
68437Smws static const struct smb_infospec {
69437Smws 	uint8_t is_type;		/* structure type */
70437Smws 	uint8_t is_manu;		/* manufacturer offset */
71437Smws 	uint8_t is_product;		/* product name offset */
72437Smws 	uint8_t is_version;		/* version offset */
73437Smws 	uint8_t is_serial;		/* serial number offset */
74437Smws 	uint8_t is_asset;		/* asset tag offset */
75437Smws 	uint8_t is_location;		/* location string offset */
76437Smws 	uint8_t is_part;		/* part number offset */
7710942STom.Pothier@Sun.COM 	uint8_t is_contc;		/* contained count */
7810942STom.Pothier@Sun.COM 	uint8_t is_contsz;		/* contained size */
7910942STom.Pothier@Sun.COM 	uint8_t is_contv;		/* contained objects */
80437Smws } _smb_infospecs[] = {
81437Smws 	{ SMB_TYPE_SYSTEM,
82437Smws 		offsetof(smb_system_t, smbsi_manufacturer),
83437Smws 		offsetof(smb_system_t, smbsi_product),
84437Smws 		offsetof(smb_system_t, smbsi_version),
85437Smws 		offsetof(smb_system_t, smbsi_serial),
86437Smws 		0,
87437Smws 		0,
8810942STom.Pothier@Sun.COM 		0,
8910942STom.Pothier@Sun.COM 		0,
9010942STom.Pothier@Sun.COM 		0,
91437Smws 		0 },
92437Smws 	{ SMB_TYPE_BASEBOARD,
93437Smws 		offsetof(smb_bboard_t, smbbb_manufacturer),
94437Smws 		offsetof(smb_bboard_t, smbbb_product),
95437Smws 		offsetof(smb_bboard_t, smbbb_version),
96437Smws 		offsetof(smb_bboard_t, smbbb_serial),
97437Smws 		offsetof(smb_bboard_t, smbbb_asset),
98437Smws 		offsetof(smb_bboard_t, smbbb_location),
9910942STom.Pothier@Sun.COM 		0,
10010942STom.Pothier@Sun.COM 		offsetof(smb_bboard_t, smbbb_cn),
10110942STom.Pothier@Sun.COM 		SMB_CONT_WORD,
10210942STom.Pothier@Sun.COM 		offsetof(smb_bboard_t, smbbb_cv) },
103437Smws 	{ SMB_TYPE_CHASSIS,
104437Smws 		offsetof(smb_chassis_t, smbch_manufacturer),
105437Smws 		0,
106437Smws 		offsetof(smb_chassis_t, smbch_version),
107437Smws 		offsetof(smb_chassis_t, smbch_serial),
108437Smws 		offsetof(smb_chassis_t, smbch_asset),
109437Smws 		0,
11010942STom.Pothier@Sun.COM 		0,
11110942STom.Pothier@Sun.COM 		offsetof(smb_chassis_t, smbch_cn),
11210942STom.Pothier@Sun.COM 		SMB_CONT_BYTE,
11310942STom.Pothier@Sun.COM 		offsetof(smb_chassis_t, smbch_cv) },
114437Smws 	{ SMB_TYPE_PROCESSOR,
115437Smws 		offsetof(smb_processor_t, smbpr_manufacturer),
116437Smws 		0,
117437Smws 		offsetof(smb_processor_t, smbpr_version),
118437Smws 		offsetof(smb_processor_t, smbpr_serial),
119437Smws 		offsetof(smb_processor_t, smbpr_asset),
120437Smws 		offsetof(smb_processor_t, smbpr_socket),
12110942STom.Pothier@Sun.COM 		offsetof(smb_processor_t, smbpr_part),
12210942STom.Pothier@Sun.COM 		0,
12310942STom.Pothier@Sun.COM 		0,
12410942STom.Pothier@Sun.COM 		0 },
125437Smws 	{ SMB_TYPE_CACHE,
126437Smws 		0,
127437Smws 		0,
128437Smws 		0,
129437Smws 		0,
130437Smws 		0,
131437Smws 		offsetof(smb_cache_t, smbca_socket),
13210942STom.Pothier@Sun.COM 		0,
13310942STom.Pothier@Sun.COM 		0,
13410942STom.Pothier@Sun.COM 		0,
135437Smws 		0 },
136437Smws 	{ SMB_TYPE_PORT,
137437Smws 		0,
138437Smws 		0,
139437Smws 		0,
140437Smws 		0,
141437Smws 		0,
142437Smws 		offsetof(smb_port_t, smbpo_iref),
14310942STom.Pothier@Sun.COM 		0,
14410942STom.Pothier@Sun.COM 		0,
14510942STom.Pothier@Sun.COM 		0,
146437Smws 		0 },
147437Smws 	{ SMB_TYPE_SLOT,
148437Smws 		0,
149437Smws 		0,
150437Smws 		0,
151437Smws 		0,
152437Smws 		0,
153437Smws 		offsetof(smb_slot_t, smbsl_name),
15410942STom.Pothier@Sun.COM 		0,
15510942STom.Pothier@Sun.COM 		0,
15610942STom.Pothier@Sun.COM 		0,
157437Smws 		0 },
158437Smws 	{ SMB_TYPE_MEMDEVICE,
159437Smws 		offsetof(smb_memdevice_t, smbmdev_manufacturer),
160437Smws 		0,
161437Smws 		0,
162437Smws 		offsetof(smb_memdevice_t, smbmdev_serial),
163437Smws 		offsetof(smb_memdevice_t, smbmdev_asset),
164437Smws 		offsetof(smb_memdevice_t, smbmdev_dloc),
16510942STom.Pothier@Sun.COM 		offsetof(smb_memdevice_t, smbmdev_part),
16610942STom.Pothier@Sun.COM 		0,
16710942STom.Pothier@Sun.COM 		0,
16810942STom.Pothier@Sun.COM 		0 },
169437Smws 	{ SMB_TYPE_POWERSUP,
170437Smws 		offsetof(smb_powersup_t, smbpsup_manufacturer),
171437Smws 		offsetof(smb_powersup_t, smbpsup_devname),
172437Smws 		offsetof(smb_powersup_t, smbpsup_rev),
173437Smws 		offsetof(smb_powersup_t, smbpsup_serial),
174437Smws 		offsetof(smb_powersup_t, smbpsup_asset),
175437Smws 		offsetof(smb_powersup_t, smbpsup_loc),
17610942STom.Pothier@Sun.COM 		offsetof(smb_powersup_t, smbpsup_part),
17710942STom.Pothier@Sun.COM 		0,
17810942STom.Pothier@Sun.COM 		0,
17910942STom.Pothier@Sun.COM 		0 },
180437Smws 	{ SMB_TYPE_EOT }
181437Smws };
182437Smws 
183437Smws static const char *
smb_info_strptr(const smb_struct_t * stp,uint8_t off,int * n)184437Smws smb_info_strptr(const smb_struct_t *stp, uint8_t off, int *n)
185437Smws {
186437Smws 	const uint8_t *sp = (const uint8_t *)(uintptr_t)stp->smbst_hdr;
187437Smws 
188437Smws 	if (off != 0 && sp + off < stp->smbst_end) {
189437Smws 		(*n)++; /* indicate success for caller */
190437Smws 		return (smb_strptr(stp, sp[off]));
191437Smws 	}
192437Smws 
193437Smws 	return (smb_strptr(stp, 0));
194437Smws }
195437Smws 
196437Smws static void
smb_info_bcopy(const smb_header_t * hp,void * dst,size_t dstlen)197437Smws smb_info_bcopy(const smb_header_t *hp, void *dst, size_t dstlen)
198437Smws {
199437Smws 	if (dstlen > hp->smbh_len) {
200437Smws 		bcopy(hp, dst, hp->smbh_len);
201437Smws 		bzero((char *)dst + hp->smbh_len, dstlen - hp->smbh_len);
202437Smws 	} else
203437Smws 		bcopy(hp, dst, dstlen);
204437Smws }
205437Smws 
206437Smws void
smbios_info_smbios(smbios_hdl_t * shp,smbios_entry_t * ep)207437Smws smbios_info_smbios(smbios_hdl_t *shp, smbios_entry_t *ep)
208437Smws {
209437Smws 	bcopy(&shp->sh_ent, ep, sizeof (smbios_entry_t));
210437Smws }
211437Smws 
2128467SEric.Schrock@Sun.COM #ifndef _KERNEL
2138467SEric.Schrock@Sun.COM static char smbios_product_override[256];
2148467SEric.Schrock@Sun.COM static boolean_t smbios_product_checked;
2158467SEric.Schrock@Sun.COM #endif
2168467SEric.Schrock@Sun.COM 
217437Smws int
smbios_info_common(smbios_hdl_t * shp,id_t id,smbios_info_t * ip)218437Smws smbios_info_common(smbios_hdl_t *shp, id_t id, smbios_info_t *ip)
219437Smws {
220437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
221437Smws 	const struct smb_infospec *isp;
222437Smws 	int n = 0;
223437Smws 
224437Smws 	if (stp == NULL)
225437Smws 		return (-1); /* errno is set for us */
226437Smws 
227437Smws 	for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) {
228437Smws 		if (isp->is_type == stp->smbst_hdr->smbh_type)
229437Smws 			break;
230437Smws 	}
231437Smws 
232437Smws 	ip->smbi_manufacturer = smb_info_strptr(stp, isp->is_manu, &n);
233437Smws 	ip->smbi_product = smb_info_strptr(stp, isp->is_product, &n);
234437Smws 	ip->smbi_version = smb_info_strptr(stp, isp->is_version, &n);
235437Smws 	ip->smbi_serial = smb_info_strptr(stp, isp->is_serial, &n);
236437Smws 	ip->smbi_asset = smb_info_strptr(stp, isp->is_asset, &n);
237437Smws 	ip->smbi_location = smb_info_strptr(stp, isp->is_location, &n);
238437Smws 	ip->smbi_part = smb_info_strptr(stp, isp->is_part, &n);
239437Smws 
240437Smws 	/*
2418467SEric.Schrock@Sun.COM 	 * This private file allows developers to experiment with reporting
2428467SEric.Schrock@Sun.COM 	 * different platform strings from SMBIOS.  It is not a supported
2438467SEric.Schrock@Sun.COM 	 * mechanism in the long term, and does not work in the kernel.
2448467SEric.Schrock@Sun.COM 	 */
2458467SEric.Schrock@Sun.COM #ifndef _KERNEL
2468467SEric.Schrock@Sun.COM 	if (isp->is_type == SMB_TYPE_SYSTEM) {
2478467SEric.Schrock@Sun.COM 		if (!smbios_product_checked) {
2488467SEric.Schrock@Sun.COM 			int fd = open("/etc/smbios_product", O_RDONLY);
2498467SEric.Schrock@Sun.COM 			if (fd >= 0) {
2508467SEric.Schrock@Sun.COM 				(void) read(fd, smbios_product_override,
2518467SEric.Schrock@Sun.COM 				    sizeof (smbios_product_override) - 1);
2528467SEric.Schrock@Sun.COM 				(void) close(fd);
2538467SEric.Schrock@Sun.COM 			}
2548467SEric.Schrock@Sun.COM 			smbios_product_checked = B_TRUE;
2558467SEric.Schrock@Sun.COM 		}
2568467SEric.Schrock@Sun.COM 
2578467SEric.Schrock@Sun.COM 		if (smbios_product_override[0] != '\0')
2588467SEric.Schrock@Sun.COM 			ip->smbi_product = smbios_product_override;
2598467SEric.Schrock@Sun.COM 	}
2608467SEric.Schrock@Sun.COM #endif
2618467SEric.Schrock@Sun.COM 
2628467SEric.Schrock@Sun.COM 	/*
263437Smws 	 * If we have a port with an empty internal reference designator string
264437Smws 	 * try using the external reference designator string instead.
265437Smws 	 */
266437Smws 	if (isp->is_type == SMB_TYPE_PORT && ip->smbi_location[0] == '\0') {
267437Smws 		ip->smbi_location = smb_info_strptr(stp,
268437Smws 		    offsetof(smb_port_t, smbpo_eref), &n);
269437Smws 	}
270437Smws 
271437Smws 	return (n ? 0 : smb_set_errno(shp, ESMB_NOINFO));
272437Smws }
273437Smws 
27410942STom.Pothier@Sun.COM /*
27510942STom.Pothier@Sun.COM  * Returns the actual number of contained objects.
27610942STom.Pothier@Sun.COM  *
27710942STom.Pothier@Sun.COM  * idc - number of contained objects
27810942STom.Pothier@Sun.COM  * idv - returned array of contained objects
27910942STom.Pothier@Sun.COM  */
28010942STom.Pothier@Sun.COM int
smbios_info_contains(smbios_hdl_t * shp,id_t id,uint_t idc,id_t * idv)28110942STom.Pothier@Sun.COM smbios_info_contains(smbios_hdl_t *shp, id_t id, uint_t idc, id_t *idv)
28210942STom.Pothier@Sun.COM {
28310942STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
28410942STom.Pothier@Sun.COM 	const struct smb_infospec *isp;
28510942STom.Pothier@Sun.COM 	id_t *cp;
28610942STom.Pothier@Sun.COM 	uint_t size;
28710942STom.Pothier@Sun.COM 	uint8_t cnt;
28810942STom.Pothier@Sun.COM 	int i, n;
28910942STom.Pothier@Sun.COM 
29010942STom.Pothier@Sun.COM 	if (stp == NULL) {
29110942STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
29210942STom.Pothier@Sun.COM 	}
29310942STom.Pothier@Sun.COM 
29410942STom.Pothier@Sun.COM 	for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) {
29510942STom.Pothier@Sun.COM 		if (isp->is_type == stp->smbst_hdr->smbh_type)
29610942STom.Pothier@Sun.COM 			break;
29710942STom.Pothier@Sun.COM 	}
29810942STom.Pothier@Sun.COM 	if (isp->is_type == SMB_TYPE_EOT)
29910942STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
30010942STom.Pothier@Sun.COM 
30110942STom.Pothier@Sun.COM 	size = isp->is_contsz;
30210942STom.Pothier@Sun.COM 	cnt = *((uint8_t *)(uintptr_t)stp->smbst_hdr + isp->is_contc);
30310942STom.Pothier@Sun.COM 	cp = (id_t *)((uintptr_t)stp->smbst_hdr + isp->is_contv);
30410942STom.Pothier@Sun.COM 
30510942STom.Pothier@Sun.COM 	n = MIN(cnt, idc);
30610942STom.Pothier@Sun.COM 	for (i = 0; i < n; i++) {
30710942STom.Pothier@Sun.COM 		if (size == SMB_CONT_WORD)
30810942STom.Pothier@Sun.COM 			idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 2));
30910942STom.Pothier@Sun.COM 		else if (size == SMB_CONT_BYTE)
31010942STom.Pothier@Sun.COM 			idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 3));
31110942STom.Pothier@Sun.COM 		else
31210942STom.Pothier@Sun.COM 			return (smb_set_errno(shp, ESMB_INVAL));
31310942STom.Pothier@Sun.COM 	}
31410942STom.Pothier@Sun.COM 
31510942STom.Pothier@Sun.COM 	return (cnt);
31610942STom.Pothier@Sun.COM }
31710942STom.Pothier@Sun.COM 
318437Smws id_t
smbios_info_bios(smbios_hdl_t * shp,smbios_bios_t * bp)319437Smws smbios_info_bios(smbios_hdl_t *shp, smbios_bios_t *bp)
320437Smws {
321437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BIOS);
322437Smws 	const smb_bios_t *bip;
323437Smws 
324437Smws 	if (stp == NULL)
325437Smws 		return (-1); /* errno is set for us */
326437Smws 
327437Smws 	if (stp->smbst_hdr->smbh_len < sizeof (smb_bios_t) - sizeof (uint8_t))
328437Smws 		return (smb_set_errno(shp, ESMB_CORRUPT));
329437Smws 
330437Smws 	bip = (smb_bios_t *)(uintptr_t)stp->smbst_hdr;
331437Smws 	bzero(bp, sizeof (smbios_bios_t));
332437Smws 
333437Smws 	bp->smbb_vendor = smb_strptr(stp, bip->smbbi_vendor);
334437Smws 	bp->smbb_version = smb_strptr(stp, bip->smbbi_version);
335437Smws 	bp->smbb_segment = bip->smbbi_segment;
336437Smws 	bp->smbb_reldate = smb_strptr(stp, bip->smbbi_reldate);
337437Smws 	bp->smbb_romsize = 64 * 1024 * ((uint32_t)bip->smbbi_romsize + 1);
338437Smws 	bp->smbb_runsize = 16 * (0x10000 - (uint32_t)bip->smbbi_segment);
339437Smws 	bp->smbb_cflags = bip->smbbi_cflags;
340437Smws 
341437Smws 	/*
342437Smws 	 * If one or more extension bytes are present, reset smbb_xcflags to
343437Smws 	 * point to them.  Otherwise leave this member set to NULL.
344437Smws 	 */
345437Smws 	if (stp->smbst_hdr->smbh_len >= sizeof (smb_bios_t)) {
346437Smws 		bp->smbb_xcflags = bip->smbbi_xcflags;
347437Smws 		bp->smbb_nxcflags = stp->smbst_hdr->smbh_len -
348437Smws 		    sizeof (smb_bios_t) + 1;
349437Smws 
350437Smws 		if (bp->smbb_nxcflags > SMB_BIOSXB_ECFW_MIN &&
351437Smws 		    smb_gteq(shp, SMB_VERSION_24)) {
352437Smws 			bp->smbb_biosv.smbv_major =
353437Smws 			    bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MAJ];
354437Smws 			bp->smbb_biosv.smbv_minor =
355437Smws 			    bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MIN];
356437Smws 			bp->smbb_ecfwv.smbv_major =
357437Smws 			    bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MAJ];
358437Smws 			bp->smbb_ecfwv.smbv_minor =
359437Smws 			    bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MIN];
360437Smws 		}
361437Smws 	}
362437Smws 
363437Smws 	return (stp->smbst_hdr->smbh_hdl);
364437Smws }
365437Smws 
366437Smws id_t
smbios_info_system(smbios_hdl_t * shp,smbios_system_t * sip)367437Smws smbios_info_system(smbios_hdl_t *shp, smbios_system_t *sip)
368437Smws {
369437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM);
370437Smws 	smb_system_t si;
371437Smws 
372437Smws 	if (stp == NULL)
373437Smws 		return (-1); /* errno is set for us */
374437Smws 
375437Smws 	smb_info_bcopy(stp->smbst_hdr, &si, sizeof (si));
376437Smws 	bzero(sip, sizeof (smbios_system_t));
377437Smws 
378437Smws 	sip->smbs_uuid = ((smb_system_t *)stp->smbst_hdr)->smbsi_uuid;
379437Smws 	sip->smbs_uuidlen = sizeof (si.smbsi_uuid);
380437Smws 	sip->smbs_wakeup = si.smbsi_wakeup;
381437Smws 	sip->smbs_sku = smb_strptr(stp, si.smbsi_sku);
382437Smws 	sip->smbs_family = smb_strptr(stp, si.smbsi_family);
383437Smws 
384437Smws 	return (stp->smbst_hdr->smbh_hdl);
385437Smws }
386437Smws 
387437Smws int
smbios_info_bboard(smbios_hdl_t * shp,id_t id,smbios_bboard_t * bbp)388437Smws smbios_info_bboard(smbios_hdl_t *shp, id_t id, smbios_bboard_t *bbp)
389437Smws {
390437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
391437Smws 	smb_bboard_t bb;
392437Smws 
393437Smws 	if (stp == NULL)
394437Smws 		return (-1); /* errno is set for us */
395437Smws 
396437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_BASEBOARD)
397437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
398437Smws 
399437Smws 	smb_info_bcopy(stp->smbst_hdr, &bb, sizeof (bb));
400437Smws 	bzero(bbp, sizeof (smbios_bboard_t));
401437Smws 
402437Smws 	bbp->smbb_chassis = bb.smbbb_chassis;
403437Smws 	bbp->smbb_flags = bb.smbbb_flags;
404437Smws 	bbp->smbb_type = bb.smbbb_type;
40510942STom.Pothier@Sun.COM 	bbp->smbb_contn = bb.smbbb_cn;
406437Smws 
407437Smws 	return (0);
408437Smws }
409437Smws 
410437Smws int
smbios_info_chassis(smbios_hdl_t * shp,id_t id,smbios_chassis_t * chp)411437Smws smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp)
412437Smws {
413437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
414437Smws 	smb_chassis_t ch;
415437Smws 
416437Smws 	if (stp == NULL)
417437Smws 		return (-1); /* errno is set for us */
418437Smws 
419437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS)
420437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
421437Smws 
422437Smws 	smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
423437Smws 	bzero(chp, sizeof (smbios_chassis_t));
424437Smws 
425437Smws 	chp->smbc_oemdata = ch.smbch_oemdata;
426437Smws 	chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0;
427437Smws 	chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK;
428437Smws 	chp->smbc_bustate = ch.smbch_bustate;
429437Smws 	chp->smbc_psstate = ch.smbch_psstate;
430437Smws 	chp->smbc_thstate = ch.smbch_thstate;
431437Smws 	chp->smbc_security = ch.smbch_security;
432437Smws 	chp->smbc_uheight = ch.smbch_uheight;
433437Smws 	chp->smbc_cords = ch.smbch_cords;
434437Smws 	chp->smbc_elems = ch.smbch_cn;
43510942STom.Pothier@Sun.COM 	chp->smbc_elemlen = ch.smbch_cm;
436437Smws 
437437Smws 	return (0);
438437Smws }
439437Smws 
440437Smws int
smbios_info_processor(smbios_hdl_t * shp,id_t id,smbios_processor_t * pp)441437Smws smbios_info_processor(smbios_hdl_t *shp, id_t id, smbios_processor_t *pp)
442437Smws {
443437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
444437Smws 	smb_processor_t p;
445437Smws 
446437Smws 	if (stp == NULL)
447437Smws 		return (-1); /* errno is set for us */
448437Smws 
449437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR)
450437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
451437Smws 
452437Smws 	smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p));
453437Smws 	bzero(pp, sizeof (smbios_processor_t));
454437Smws 
455437Smws 	pp->smbp_cpuid = p.smbpr_cpuid;
456437Smws 	pp->smbp_type = p.smbpr_type;
457437Smws 	pp->smbp_family = p.smbpr_family;
458437Smws 	pp->smbp_voltage = p.smbpr_voltage;
459437Smws 	pp->smbp_maxspeed = p.smbpr_maxspeed;
460437Smws 	pp->smbp_curspeed = p.smbpr_curspeed;
461437Smws 	pp->smbp_status = p.smbpr_status;
462437Smws 	pp->smbp_upgrade = p.smbpr_upgrade;
463437Smws 	pp->smbp_l1cache = p.smbpr_l1cache;
464437Smws 	pp->smbp_l2cache = p.smbpr_l2cache;
465437Smws 	pp->smbp_l3cache = p.smbpr_l3cache;
466437Smws 
467437Smws 	return (0);
468437Smws }
469437Smws 
470437Smws int
smbios_info_cache(smbios_hdl_t * shp,id_t id,smbios_cache_t * cap)471437Smws smbios_info_cache(smbios_hdl_t *shp, id_t id, smbios_cache_t *cap)
472437Smws {
473437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
474437Smws 	smb_cache_t c;
475437Smws 
476437Smws 	if (stp == NULL)
477437Smws 		return (-1); /* errno is set for us */
478437Smws 
479437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_CACHE)
480437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
481437Smws 
482437Smws 	smb_info_bcopy(stp->smbst_hdr, &c, sizeof (c));
483437Smws 	bzero(cap, sizeof (smbios_cache_t));
484437Smws 
485437Smws 	cap->smba_maxsize = SMB_CACHE_SIZE(c.smbca_maxsize);
486437Smws 	cap->smba_size = SMB_CACHE_SIZE(c.smbca_size);
487437Smws 	cap->smba_stype = c.smbca_stype;
488437Smws 	cap->smba_ctype = c.smbca_ctype;
489437Smws 	cap->smba_speed = c.smbca_speed;
490437Smws 	cap->smba_etype = c.smbca_etype;
491437Smws 	cap->smba_ltype = c.smbca_ltype;
492437Smws 	cap->smba_assoc = c.smbca_assoc;
493437Smws 	cap->smba_level = SMB_CACHE_CFG_LEVEL(c.smbca_config);
494437Smws 	cap->smba_mode = SMB_CACHE_CFG_MODE(c.smbca_config);
495437Smws 	cap->smba_location = SMB_CACHE_CFG_LOCATION(c.smbca_config);
496437Smws 
497437Smws 	if (SMB_CACHE_CFG_ENABLED(c.smbca_config))
498437Smws 		cap->smba_flags |= SMB_CAF_ENABLED;
499437Smws 
500437Smws 	if (SMB_CACHE_CFG_SOCKETED(c.smbca_config))
501437Smws 		cap->smba_flags |= SMB_CAF_SOCKETED;
502437Smws 
503437Smws 	return (0);
504437Smws }
505437Smws 
506437Smws int
smbios_info_port(smbios_hdl_t * shp,id_t id,smbios_port_t * pop)507437Smws smbios_info_port(smbios_hdl_t *shp, id_t id, smbios_port_t *pop)
508437Smws {
509437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
510437Smws 	smb_port_t p;
511437Smws 
512437Smws 	if (stp == NULL)
513437Smws 		return (-1); /* errno is set for us */
514437Smws 
515437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_PORT)
516437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
517437Smws 
518437Smws 	smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p));
519437Smws 	bzero(pop, sizeof (smbios_port_t));
520437Smws 
521437Smws 	pop->smbo_iref = smb_strptr(stp, p.smbpo_iref);
522437Smws 	pop->smbo_eref = smb_strptr(stp, p.smbpo_eref);
523437Smws 
524437Smws 	pop->smbo_itype = p.smbpo_itype;
525437Smws 	pop->smbo_etype = p.smbpo_etype;
526437Smws 	pop->smbo_ptype = p.smbpo_ptype;
527437Smws 
528437Smws 	return (0);
529437Smws }
530437Smws 
531437Smws int
smbios_info_slot(smbios_hdl_t * shp,id_t id,smbios_slot_t * sp)532437Smws smbios_info_slot(smbios_hdl_t *shp, id_t id, smbios_slot_t *sp)
533437Smws {
534437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
535437Smws 	smb_slot_t s;
536437Smws 
537437Smws 	if (stp == NULL)
538437Smws 		return (-1); /* errno is set for us */
539437Smws 
540437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT)
541437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
542437Smws 
543437Smws 	smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
544437Smws 	bzero(sp, sizeof (smbios_slot_t));
545437Smws 
546437Smws 	sp->smbl_name = smb_strptr(stp, s.smbsl_name);
547437Smws 	sp->smbl_type = s.smbsl_type;
548437Smws 	sp->smbl_width = s.smbsl_width;
549437Smws 	sp->smbl_usage = s.smbsl_usage;
550437Smws 	sp->smbl_length = s.smbsl_length;
551437Smws 	sp->smbl_id = s.smbsl_id;
552437Smws 	sp->smbl_ch1 = s.smbsl_ch1;
553437Smws 	sp->smbl_ch2 = s.smbsl_ch2;
554*11859STom.Pothier@Sun.COM 	sp->smbl_sg = s.smbsl_sg;
555*11859STom.Pothier@Sun.COM 	sp->smbl_bus = s.smbsl_bus;
556*11859STom.Pothier@Sun.COM 	sp->smbl_df = s.smbsl_df;
557*11859STom.Pothier@Sun.COM 
558*11859STom.Pothier@Sun.COM 	return (0);
559*11859STom.Pothier@Sun.COM }
560*11859STom.Pothier@Sun.COM 
561*11859STom.Pothier@Sun.COM int
smbios_info_obdevs_ext(smbios_hdl_t * shp,id_t id,smbios_obdev_ext_t * oep)562*11859STom.Pothier@Sun.COM smbios_info_obdevs_ext(smbios_hdl_t *shp, id_t id, smbios_obdev_ext_t *oep)
563*11859STom.Pothier@Sun.COM {
564*11859STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
565*11859STom.Pothier@Sun.COM 	smb_obdev_ext_t obe;
566*11859STom.Pothier@Sun.COM 
567*11859STom.Pothier@Sun.COM 	if (stp == NULL)
568*11859STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
569*11859STom.Pothier@Sun.COM 
570*11859STom.Pothier@Sun.COM 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVEXT)
571*11859STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
572*11859STom.Pothier@Sun.COM 
573*11859STom.Pothier@Sun.COM 	smb_info_bcopy(stp->smbst_hdr, &obe, sizeof (obe));
574*11859STom.Pothier@Sun.COM 	bzero(oep, sizeof (smbios_obdev_ext_t));
575*11859STom.Pothier@Sun.COM 
576*11859STom.Pothier@Sun.COM 	oep->smboe_name = smb_strptr(stp, obe.smbobe_name);
577*11859STom.Pothier@Sun.COM 	oep->smboe_dtype = obe.smbobe_dtype;
578*11859STom.Pothier@Sun.COM 	oep->smboe_dti = obe.smbobe_dti;
579*11859STom.Pothier@Sun.COM 	oep->smboe_sg = obe.smbobe_sg;
580*11859STom.Pothier@Sun.COM 	oep->smboe_bus = obe.smbobe_bus;
581*11859STom.Pothier@Sun.COM 	oep->smboe_df = obe.smbobe_df;
582437Smws 
583437Smws 	return (0);
584437Smws }
585437Smws 
586437Smws int
smbios_info_obdevs(smbios_hdl_t * shp,id_t id,int obc,smbios_obdev_t * obp)587437Smws smbios_info_obdevs(smbios_hdl_t *shp, id_t id, int obc, smbios_obdev_t *obp)
588437Smws {
589437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
590437Smws 	const smb_obdev_t *op;
591437Smws 	int i, m, n;
592437Smws 
593437Smws 	if (stp == NULL)
594437Smws 		return (-1); /* errno is set for us */
595437Smws 
596437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVS)
597437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
598437Smws 
599437Smws 	op = (smb_obdev_t *)((uintptr_t)stp->smbst_hdr + sizeof (smb_header_t));
600437Smws 	m = (stp->smbst_hdr->smbh_len - sizeof (smb_header_t)) / sizeof (*op);
601437Smws 	n = MIN(m, obc);
602437Smws 
603437Smws 	for (i = 0; i < n; i++, op++, obp++) {
604437Smws 		obp->smbd_name = smb_strptr(stp, op->smbob_name);
605437Smws 		obp->smbd_type = op->smbob_type & ~SMB_OBT_ENABLED;
606437Smws 		obp->smbd_enabled = (op->smbob_type & SMB_OBT_ENABLED) != 0;
607437Smws 	}
608437Smws 
609437Smws 	return (m);
610437Smws }
611437Smws 
612437Smws /*
613437Smws  * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the
614437Smws  * first byte to indicate the size of a string table at the end of the record.
615437Smws  * Therefore, smbios_info_strtab() can be used to retrieve the table size and
616437Smws  * strings for any of these underlying record types.
617437Smws  */
618437Smws int
smbios_info_strtab(smbios_hdl_t * shp,id_t id,int argc,const char * argv[])619437Smws smbios_info_strtab(smbios_hdl_t *shp, id_t id, int argc, const char *argv[])
620437Smws {
621437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
622437Smws 	smb_strtab_t s;
623437Smws 	int i, n;
624437Smws 
625437Smws 	if (stp == NULL)
626437Smws 		return (-1); /* errno is set for us */
627437Smws 
628437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR &&
629437Smws 	    stp->smbst_hdr->smbh_type != SMB_TYPE_SYSCONFSTR &&
630437Smws 	    stp->smbst_hdr->smbh_type != SMB_TYPE_LANG)
631437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
632437Smws 
633437Smws 	smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
634437Smws 	n = MIN(s.smbtb_count, argc);
635437Smws 
636437Smws 	for (i = 0; i < n; i++)
637437Smws 		argv[i] = smb_strptr(stp, i + 1);
638437Smws 
639437Smws 	return (s.smbtb_count);
640437Smws }
641437Smws 
642437Smws id_t
smbios_info_lang(smbios_hdl_t * shp,smbios_lang_t * lp)643437Smws smbios_info_lang(smbios_hdl_t *shp, smbios_lang_t *lp)
644437Smws {
645437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_LANG);
646437Smws 	smb_lang_t l;
647437Smws 
648437Smws 	if (stp == NULL)
649437Smws 		return (-1); /* errno is set for us */
650437Smws 
651437Smws 	smb_info_bcopy(stp->smbst_hdr, &l, sizeof (l));
652437Smws 	bzero(lp, sizeof (smbios_lang_t));
653437Smws 
654437Smws 	lp->smbla_cur = smb_strptr(stp, l.smblang_cur);
655437Smws 	lp->smbla_fmt = l.smblang_flags & 1;
656437Smws 	lp->smbla_num = l.smblang_num;
657437Smws 
658437Smws 	return (stp->smbst_hdr->smbh_hdl);
659437Smws }
660437Smws 
661437Smws id_t
smbios_info_eventlog(smbios_hdl_t * shp,smbios_evlog_t * evp)662437Smws smbios_info_eventlog(smbios_hdl_t *shp, smbios_evlog_t *evp)
663437Smws {
664437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_EVENTLOG);
665437Smws 	const smb_sel_t *sel;
666437Smws 	size_t len;
667437Smws 
668437Smws 	if (stp == NULL)
669437Smws 		return (-1); /* errno is set for us */
670437Smws 
671437Smws 	if (stp->smbst_hdr->smbh_len < sizeof (smb_sel_t) - sizeof (uint8_t))
672437Smws 		return (smb_set_errno(shp, ESMB_CORRUPT));
673437Smws 
674437Smws 	sel = (smb_sel_t *)(uintptr_t)stp->smbst_hdr;
675437Smws 	len = stp->smbst_hdr->smbh_len - sizeof (smb_sel_t) + sizeof (uint8_t);
676437Smws 	bzero(evp, sizeof (smbios_evlog_t));
677437Smws 
678437Smws 	if (len < sel->smbsel_typec * sel->smbsel_typesz)
679437Smws 		return (smb_set_errno(shp, ESMB_CORRUPT));
680437Smws 
681437Smws 	evp->smbev_size = sel->smbsel_len;
682437Smws 	evp->smbev_hdr = sel->smbsel_hdroff;
683437Smws 	evp->smbev_data = sel->smbsel_dataoff;
684437Smws 	evp->smbev_method = sel->smbsel_method;
685437Smws 	evp->smbev_flags = sel->smbsel_status;
686437Smws 	evp->smbev_format = sel->smbsel_format;
687437Smws 	evp->smbev_token = sel->smbsel_token;
688437Smws 	evp->smbev_addr.eva_addr = sel->smbsel_addr;
689437Smws 
690437Smws 	if (sel->smbsel_typesz == sizeof (smbios_evtype_t)) {
691437Smws 		evp->smbev_typec = sel->smbsel_typec;
692437Smws 		evp->smbev_typev = (void *)(uintptr_t)sel->smbsel_typev;
693437Smws 	}
694437Smws 
695437Smws 	return (stp->smbst_hdr->smbh_hdl);
696437Smws }
697437Smws 
698437Smws int
smbios_info_memarray(smbios_hdl_t * shp,id_t id,smbios_memarray_t * map)699437Smws smbios_info_memarray(smbios_hdl_t *shp, id_t id, smbios_memarray_t *map)
700437Smws {
701437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
702437Smws 	smb_memarray_t m;
703437Smws 
704437Smws 	if (stp == NULL)
705437Smws 		return (-1); /* errno is set for us */
706437Smws 
707437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAY)
708437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
709437Smws 
710437Smws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
711437Smws 	bzero(map, sizeof (smbios_memarray_t));
712437Smws 
713437Smws 	map->smbma_location = m.smbmarr_loc;
714437Smws 	map->smbma_use = m.smbmarr_use;
715437Smws 	map->smbma_ecc = m.smbmarr_ecc;
716437Smws 	map->smbma_ndevs = m.smbmarr_ndevs;
717437Smws 	map->smbma_err = m.smbmarr_err;
718437Smws 
719437Smws 	if (m.smbmarr_cap != 0x80000000)
720437Smws 		map->smbma_size = (uint64_t)m.smbmarr_cap * 1024;
721437Smws 	else
722437Smws 		map->smbma_size = 0; /* unknown */
723437Smws 
724437Smws 	return (0);
725437Smws }
726437Smws 
727437Smws int
smbios_info_memarrmap(smbios_hdl_t * shp,id_t id,smbios_memarrmap_t * map)728437Smws smbios_info_memarrmap(smbios_hdl_t *shp, id_t id, smbios_memarrmap_t *map)
729437Smws {
730437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
731437Smws 	smb_memarrmap_t m;
732437Smws 
733437Smws 	if (stp == NULL)
734437Smws 		return (-1); /* errno is set for us */
735437Smws 
736437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAYMAP)
737437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
738437Smws 
739437Smws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
740437Smws 	bzero(map, sizeof (smbios_memarrmap_t));
741437Smws 
742437Smws 	map->smbmam_array = m.smbamap_array;
743437Smws 	map->smbmam_width = m.smbamap_width;
744437Smws 	map->smbmam_addr = (uint64_t)m.smbamap_start * 1024;
745437Smws 	map->smbmam_size = (uint64_t)
746437Smws 	    (m.smbamap_end - m.smbamap_start + 1) * 1024;
747437Smws 
748437Smws 	return (0);
749437Smws }
750437Smws 
751437Smws int
smbios_info_memdevice(smbios_hdl_t * shp,id_t id,smbios_memdevice_t * mdp)752437Smws smbios_info_memdevice(smbios_hdl_t *shp, id_t id, smbios_memdevice_t *mdp)
753437Smws {
754437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
755437Smws 	smb_memdevice_t m;
756437Smws 
757437Smws 	if (stp == NULL)
758437Smws 		return (-1); /* errno is set for us */
759437Smws 
760437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICE)
761437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
762437Smws 
763437Smws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
764437Smws 	bzero(mdp, sizeof (smbios_memdevice_t));
765437Smws 
766437Smws 	mdp->smbmd_array = m.smbmdev_array;
767437Smws 	mdp->smbmd_error = m.smbmdev_error;
768437Smws 	mdp->smbmd_twidth = m.smbmdev_twidth == 0xFFFF ? -1U : m.smbmdev_twidth;
769437Smws 	mdp->smbmd_dwidth = m.smbmdev_dwidth == 0xFFFF ? -1U : m.smbmdev_dwidth;
770437Smws 
771437Smws 	if (mdp->smbmd_size != 0xFFFF) {
772437Smws 		mdp->smbmd_size = (uint64_t)(m.smbmdev_size & ~SMB_MDS_KBYTES);
773437Smws 		if (m.smbmdev_size & SMB_MDS_KBYTES)
774437Smws 			mdp->smbmd_size *= 1024;
775437Smws 		else
776437Smws 			mdp->smbmd_size *= 1024 * 1024;
777437Smws 	} else
778437Smws 		mdp->smbmd_size = -1ULL; /* size unknown */
779437Smws 
780437Smws 	mdp->smbmd_form = m.smbmdev_form;
781437Smws 	mdp->smbmd_set = m.smbmdev_set;
782437Smws 	mdp->smbmd_type = m.smbmdev_type;
783437Smws 	mdp->smbmd_flags = m.smbmdev_flags;
784437Smws 	mdp->smbmd_dloc = smb_strptr(stp, m.smbmdev_dloc);
785437Smws 	mdp->smbmd_bloc = smb_strptr(stp, m.smbmdev_bloc);
786437Smws 
787437Smws 	if (m.smbmdev_speed != 0)
788437Smws 		mdp->smbmd_speed = 1000 / m.smbmdev_speed; /* MHz -> nsec */
789437Smws 
790437Smws 	return (0);
791437Smws }
792437Smws 
793437Smws int
smbios_info_memdevmap(smbios_hdl_t * shp,id_t id,smbios_memdevmap_t * mdp)794437Smws smbios_info_memdevmap(smbios_hdl_t *shp, id_t id, smbios_memdevmap_t *mdp)
795437Smws {
796437Smws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
797437Smws 	smb_memdevmap_t m;
798437Smws 
799437Smws 	if (stp == NULL)
800437Smws 		return (-1); /* errno is set for us */
801437Smws 
802437Smws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICEMAP)
803437Smws 		return (smb_set_errno(shp, ESMB_TYPE));
804437Smws 
805437Smws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
806437Smws 	bzero(mdp, sizeof (smbios_memdevmap_t));
807437Smws 
808437Smws 	mdp->smbmdm_device = m.smbdmap_device;
809437Smws 	mdp->smbmdm_arrmap = m.smbdmap_array;
810437Smws 	mdp->smbmdm_addr = (uint64_t)m.smbdmap_start * 1024;
811437Smws 	mdp->smbmdm_size = (uint64_t)
812437Smws 	    (m.smbdmap_end - m.smbdmap_start + 1) * 1024;
813437Smws 	mdp->smbmdm_rpos = m.smbdmap_rpos;
814437Smws 	mdp->smbmdm_ipos = m.smbdmap_ipos;
815437Smws 	mdp->smbmdm_idepth = m.smbdmap_idepth;
816437Smws 
817437Smws 	return (0);
818437Smws }
819437Smws 
820437Smws id_t
smbios_info_hwsec(smbios_hdl_t * shp,smbios_hwsec_t * hsp)821437Smws smbios_info_hwsec(smbios_hdl_t *shp, smbios_hwsec_t *hsp)
822437Smws {
823437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SECURITY);
824437Smws 	smb_hwsec_t hs;
825437Smws 
826437Smws 	if (stp == NULL)
827437Smws 		return (-1); /* errno is set for us */
828437Smws 
829437Smws 	smb_info_bcopy(stp->smbst_hdr, &hs, sizeof (hs));
830437Smws 	bzero(hsp, sizeof (smbios_hwsec_t));
831437Smws 
832437Smws 	hsp->smbh_pwr_ps = SMB_HWS_PWR_PS(hs.smbhs_settings);
833437Smws 	hsp->smbh_kbd_ps = SMB_HWS_KBD_PS(hs.smbhs_settings);
834437Smws 	hsp->smbh_adm_ps = SMB_HWS_ADM_PS(hs.smbhs_settings);
835437Smws 	hsp->smbh_pan_ps = SMB_HWS_PAN_PS(hs.smbhs_settings);
836437Smws 
837437Smws 	return (stp->smbst_hdr->smbh_hdl);
838437Smws }
839437Smws 
840437Smws id_t
smbios_info_boot(smbios_hdl_t * shp,smbios_boot_t * bp)841437Smws smbios_info_boot(smbios_hdl_t *shp, smbios_boot_t *bp)
842437Smws {
843437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BOOT);
844437Smws 	const smb_boot_t *b = (smb_boot_t *)(uintptr_t)stp->smbst_hdr;
845437Smws 
846437Smws 	if (stp == NULL)
847437Smws 		return (-1); /* errno is set for us */
848437Smws 
849437Smws 	bzero(bp, sizeof (smbios_boot_t));
850437Smws 
851437Smws 	bp->smbt_status = b->smbbo_status[0];
852437Smws 	bp->smbt_size = stp->smbst_hdr->smbh_len - sizeof (smb_boot_t);
853437Smws 	bp->smbt_data = bp->smbt_size ? &b->smbbo_status[1] : NULL;
854437Smws 
855437Smws 	return (stp->smbst_hdr->smbh_hdl);
856437Smws }
857437Smws 
858437Smws id_t
smbios_info_ipmi(smbios_hdl_t * shp,smbios_ipmi_t * ip)859437Smws smbios_info_ipmi(smbios_hdl_t *shp, smbios_ipmi_t *ip)
860437Smws {
861437Smws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_IPMIDEV);
862437Smws 	smb_ipmi_t i;
863437Smws 
864437Smws 	if (stp == NULL)
865437Smws 		return (-1); /* errno is set for us */
866437Smws 
867437Smws 	smb_info_bcopy(stp->smbst_hdr, &i, sizeof (i));
868437Smws 	bzero(ip, sizeof (smbios_ipmi_t));
869437Smws 
870437Smws 	ip->smbip_type = i.smbipm_type;
871437Smws 	ip->smbip_vers.smbv_major = SMB_IPM_SPEC_MAJOR(i.smbipm_spec);
872437Smws 	ip->smbip_vers.smbv_minor = SMB_IPM_SPEC_MINOR(i.smbipm_spec);
873437Smws 	ip->smbip_i2c = i.smbipm_i2c;
874437Smws 	ip->smbip_addr = i.smbipm_addr & ~SMB_IPM_ADDR_IO;
875437Smws 	ip->smbip_intr = i.smbipm_intr;
876437Smws 
877437Smws 	if (i.smbipm_bus != (uint8_t)-1)
878437Smws 		ip->smbip_bus = i.smbipm_bus;
879437Smws 	else
880437Smws 		ip->smbip_bus = -1u;
881437Smws 
882437Smws 	if (SMB_IPM_INFO_LSB(i.smbipm_info))
883437Smws 		ip->smbip_addr |= 1; /* turn on least-significant bit of addr */
884437Smws 
885437Smws 	if (i.smbipm_addr & SMB_IPM_ADDR_IO) {
886437Smws 		switch (SMB_IPM_INFO_REGS(i.smbipm_info)) {
887437Smws 		case SMB_IPM_REGS_1B:
888437Smws 			ip->smbip_regspacing = 1;
889437Smws 			break;
890437Smws 		case SMB_IPM_REGS_4B:
891437Smws 			ip->smbip_regspacing = 4;
892437Smws 			break;
893437Smws 		case SMB_IPM_REGS_16B:
894437Smws 			ip->smbip_regspacing = 16;
895437Smws 			break;
896437Smws 		default:
897437Smws 			ip->smbip_regspacing = 1;
898437Smws 		}
899437Smws 		ip->smbip_flags |= SMB_IPMI_F_IOADDR;
900437Smws 	}
901437Smws 
902437Smws 	if (SMB_IPM_INFO_ISPEC(i.smbipm_info))
903437Smws 		ip->smbip_flags |= SMB_IPMI_F_INTRSPEC;
904437Smws 
905437Smws 	if (SMB_IPM_INFO_IPOL(i.smbipm_info) == SMB_IPM_IPOL_HI)
906437Smws 		ip->smbip_flags |= SMB_IPMI_F_INTRHIGH;
907437Smws 
908437Smws 	if (SMB_IPM_INFO_IMODE(i.smbipm_info) == SMB_IPM_IMODE_EDGE)
909437Smws 		ip->smbip_flags |= SMB_IPMI_F_INTREDGE;
910437Smws 
911437Smws 	return (stp->smbst_hdr->smbh_hdl);
912437Smws }
91310462SSean.Ye@Sun.COM 
91410462SSean.Ye@Sun.COM static boolean_t
smbios_has_oemstr(smbios_hdl_t * shp,const char * oemstr)91510462SSean.Ye@Sun.COM smbios_has_oemstr(smbios_hdl_t *shp, const char *oemstr)
91610462SSean.Ye@Sun.COM {
91710462SSean.Ye@Sun.COM 	const smb_struct_t *stp = shp->sh_structs;
91810462SSean.Ye@Sun.COM 	smb_strtab_t s;
91910462SSean.Ye@Sun.COM 	int i, j;
92010462SSean.Ye@Sun.COM 
92110462SSean.Ye@Sun.COM 	for (i = 0; i < shp->sh_nstructs; i++, stp++) {
92210462SSean.Ye@Sun.COM 		if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR)
92310462SSean.Ye@Sun.COM 			continue;
92410462SSean.Ye@Sun.COM 
92510462SSean.Ye@Sun.COM 		smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
92610462SSean.Ye@Sun.COM 		for (j = 0; j < s.smbtb_count; j++)
92710462SSean.Ye@Sun.COM 			if (strcmp(smb_strptr(stp, j + 1), oemstr) == 0)
92810462SSean.Ye@Sun.COM 				return (B_TRUE);
92910462SSean.Ye@Sun.COM 	}
93010462SSean.Ye@Sun.COM 
93110462SSean.Ye@Sun.COM 	return (B_FALSE);
93210462SSean.Ye@Sun.COM }
93310462SSean.Ye@Sun.COM 
93410462SSean.Ye@Sun.COM static const char *
smb_serial_valid(const char * serial)93510462SSean.Ye@Sun.COM smb_serial_valid(const char *serial)
93610462SSean.Ye@Sun.COM {
93710462SSean.Ye@Sun.COM 	char buf[MAXNAMELEN];
93810462SSean.Ye@Sun.COM 	int i = 0;
93910462SSean.Ye@Sun.COM 
94010462SSean.Ye@Sun.COM 	if (serial == NULL)
94110462SSean.Ye@Sun.COM 		return (NULL);
94210462SSean.Ye@Sun.COM 
94310462SSean.Ye@Sun.COM 	(void) strlcpy(buf, serial, sizeof (buf));
94410462SSean.Ye@Sun.COM 
94510462SSean.Ye@Sun.COM 	while (buf[i] != '\0' && buf[i] == ' ')
94610462SSean.Ye@Sun.COM 		i++;
94710462SSean.Ye@Sun.COM 
94810462SSean.Ye@Sun.COM 	if (buf[i] == '\0' || strstr(buf, SMB_DEFAULT1) != NULL ||
94910462SSean.Ye@Sun.COM 	    strstr(buf, SMB_DEFAULT2) != NULL)
95010462SSean.Ye@Sun.COM 		return (NULL);
95110462SSean.Ye@Sun.COM 
95210462SSean.Ye@Sun.COM 	return (serial);
95310462SSean.Ye@Sun.COM }
95410462SSean.Ye@Sun.COM 
95510462SSean.Ye@Sun.COM /*
95610462SSean.Ye@Sun.COM  * Get chassis SN or product SN
95710462SSean.Ye@Sun.COM  */
95810462SSean.Ye@Sun.COM static int
smb_get_sn(smbios_hdl_t * shp,const char ** psnp,const char ** csnp)95910462SSean.Ye@Sun.COM smb_get_sn(smbios_hdl_t *shp, const char **psnp, const char **csnp)
96010462SSean.Ye@Sun.COM {
96110462SSean.Ye@Sun.COM 	const smb_struct_t *stp;
96210462SSean.Ye@Sun.COM 	smbios_info_t s1, s3;
96310462SSean.Ye@Sun.COM 
96410462SSean.Ye@Sun.COM 	if (psnp == NULL || csnp == NULL)
96510462SSean.Ye@Sun.COM 		return (smb_set_errno(shp, ESMB_INVAL));
96610462SSean.Ye@Sun.COM 
96710462SSean.Ye@Sun.COM 	*psnp = *csnp = NULL;
96810462SSean.Ye@Sun.COM 
96910462SSean.Ye@Sun.COM 	/*
97010462SSean.Ye@Sun.COM 	 * If SMBIOS meets Sun's PRMS requirements, retrieve product SN
97110462SSean.Ye@Sun.COM 	 * from type 1 structure, and chassis SN from type 3 structure.
97210462SSean.Ye@Sun.COM 	 * Otherwise return SN in type 1 structure as chassis SN.
97310462SSean.Ye@Sun.COM 	 */
97410462SSean.Ye@Sun.COM 
97510462SSean.Ye@Sun.COM 	/* Get type 1 SN */
97610462SSean.Ye@Sun.COM 	if ((stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM)) == NULL ||
97710462SSean.Ye@Sun.COM 	    smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s1) == SMB_ERR)
97810462SSean.Ye@Sun.COM 		s1.smbi_serial = NULL;
97910462SSean.Ye@Sun.COM 
98010462SSean.Ye@Sun.COM 	/* Get type 3 SN */
98110462SSean.Ye@Sun.COM 	if ((stp = smb_lookup_type(shp, SMB_TYPE_CHASSIS)) == NULL ||
98210462SSean.Ye@Sun.COM 	    smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s3) == SMB_ERR)
98310462SSean.Ye@Sun.COM 		s3.smbi_serial = NULL;
98410462SSean.Ye@Sun.COM 
98510462SSean.Ye@Sun.COM 	if (smbios_has_oemstr(shp, SMB_PRMS1)) {
98610462SSean.Ye@Sun.COM 		*psnp = smb_serial_valid(s1.smbi_serial);
98710462SSean.Ye@Sun.COM 		*csnp = smb_serial_valid(s3.smbi_serial);
98810462SSean.Ye@Sun.COM 	} else {
98910462SSean.Ye@Sun.COM 		*csnp = smb_serial_valid(s1.smbi_serial);
99010462SSean.Ye@Sun.COM 	}
99110462SSean.Ye@Sun.COM 
99210462SSean.Ye@Sun.COM 	return (0);
99310462SSean.Ye@Sun.COM }
99410462SSean.Ye@Sun.COM 
99510462SSean.Ye@Sun.COM const char *
smbios_psn(smbios_hdl_t * shp)99610462SSean.Ye@Sun.COM smbios_psn(smbios_hdl_t *shp)
99710462SSean.Ye@Sun.COM {
99810462SSean.Ye@Sun.COM 	const char *psn, *csn;
99910462SSean.Ye@Sun.COM 
100010462SSean.Ye@Sun.COM 	return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : psn);
100110462SSean.Ye@Sun.COM }
100210462SSean.Ye@Sun.COM 
100310462SSean.Ye@Sun.COM const char *
smbios_csn(smbios_hdl_t * shp)100410462SSean.Ye@Sun.COM smbios_csn(smbios_hdl_t *shp)
100510462SSean.Ye@Sun.COM {
100610462SSean.Ye@Sun.COM 	const char *psn, *csn;
100710462SSean.Ye@Sun.COM 
100810462SSean.Ye@Sun.COM 	return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : csn);
100910462SSean.Ye@Sun.COM }
101010942STom.Pothier@Sun.COM 
101110942STom.Pothier@Sun.COM int
smbios_info_extprocessor(smbios_hdl_t * shp,id_t id,smbios_processor_ext_t * epp)101210942STom.Pothier@Sun.COM smbios_info_extprocessor(smbios_hdl_t *shp, id_t id,
101310942STom.Pothier@Sun.COM     smbios_processor_ext_t *epp)
101410942STom.Pothier@Sun.COM {
101510942STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
101610942STom.Pothier@Sun.COM 	smb_processor_ext_t *exp;
101710942STom.Pothier@Sun.COM 
101810942STom.Pothier@Sun.COM 	if (stp == NULL)
101910942STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
102010942STom.Pothier@Sun.COM 
102110942STom.Pothier@Sun.COM 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PROCESSOR)
102210942STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
102310942STom.Pothier@Sun.COM 
102410942STom.Pothier@Sun.COM 	exp = (smb_processor_ext_t *)(uintptr_t)stp->smbst_hdr;
102510942STom.Pothier@Sun.COM 	bzero(epp, sizeof (smbios_processor_ext_t));
102610942STom.Pothier@Sun.COM 
102710942STom.Pothier@Sun.COM 	epp->smbpe_processor = exp->smbpre_processor;
102810942STom.Pothier@Sun.COM 	epp->smbpe_fru = exp->smbpre_fru;
102910942STom.Pothier@Sun.COM 	epp->smbpe_n = exp->smbpre_n;
103010942STom.Pothier@Sun.COM 	epp->smbpe_apicid = exp->smbpre_apicid;
103110942STom.Pothier@Sun.COM 
103210942STom.Pothier@Sun.COM 	return (0);
103310942STom.Pothier@Sun.COM }
103410942STom.Pothier@Sun.COM 
103510942STom.Pothier@Sun.COM int
smbios_info_extport(smbios_hdl_t * shp,id_t id,smbios_port_ext_t * eportp)1036*11859STom.Pothier@Sun.COM smbios_info_extport(smbios_hdl_t *shp, id_t id, smbios_port_ext_t *eportp)
1037*11859STom.Pothier@Sun.COM {
1038*11859STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1039*11859STom.Pothier@Sun.COM 	smb_port_ext_t *ep;
1040*11859STom.Pothier@Sun.COM 
1041*11859STom.Pothier@Sun.COM 	if (stp == NULL)
1042*11859STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
1043*11859STom.Pothier@Sun.COM 
1044*11859STom.Pothier@Sun.COM 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PORT)
1045*11859STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
1046*11859STom.Pothier@Sun.COM 
1047*11859STom.Pothier@Sun.COM 	ep = (smb_port_ext_t *)(uintptr_t)stp->smbst_hdr;
1048*11859STom.Pothier@Sun.COM 	bzero(eportp, sizeof (smbios_port_ext_t));
1049*11859STom.Pothier@Sun.COM 
1050*11859STom.Pothier@Sun.COM 	eportp->smbporte_chassis = ep->smbpoe_chassis;
1051*11859STom.Pothier@Sun.COM 	eportp->smbporte_port = ep->smbpoe_port;
1052*11859STom.Pothier@Sun.COM 	eportp->smbporte_dtype = ep->smbpoe_dtype;
1053*11859STom.Pothier@Sun.COM 	eportp->smbporte_devhdl = ep->smbpoe_devhdl;
1054*11859STom.Pothier@Sun.COM 	eportp->smbporte_phy = ep->smbpoe_phy;
1055*11859STom.Pothier@Sun.COM 
1056*11859STom.Pothier@Sun.COM 	return (0);
1057*11859STom.Pothier@Sun.COM }
1058*11859STom.Pothier@Sun.COM 
1059*11859STom.Pothier@Sun.COM int
smbios_info_pciexrc(smbios_hdl_t * shp,id_t id,smbios_pciexrc_t * rcp)106010942STom.Pothier@Sun.COM smbios_info_pciexrc(smbios_hdl_t *shp, id_t id,
106110942STom.Pothier@Sun.COM     smbios_pciexrc_t *rcp)
106210942STom.Pothier@Sun.COM {
106310942STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
106410942STom.Pothier@Sun.COM 	smb_pciexrc_t rc;
106510942STom.Pothier@Sun.COM 
106610942STom.Pothier@Sun.COM 	if (stp == NULL)
106710942STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
106810942STom.Pothier@Sun.COM 
106910942STom.Pothier@Sun.COM 	if (stp->smbst_hdr->smbh_type != SUN_OEM_PCIEXRC)
107010942STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
107110942STom.Pothier@Sun.COM 
107210942STom.Pothier@Sun.COM 	smb_info_bcopy(stp->smbst_hdr, &rc, sizeof (rc));
107310942STom.Pothier@Sun.COM 	bzero(rcp, sizeof (smbios_pciexrc_t));
107410942STom.Pothier@Sun.COM 
107510942STom.Pothier@Sun.COM 	rcp->smbpcie_bb = rc.smbpciexrc_bboard;
107610942STom.Pothier@Sun.COM 	rcp->smbpcie_bdf = rc.smbpciexrc_bdf;
107710942STom.Pothier@Sun.COM 
107810942STom.Pothier@Sun.COM 	return (0);
107910942STom.Pothier@Sun.COM }
108010942STom.Pothier@Sun.COM 
108110942STom.Pothier@Sun.COM int
smbios_info_extmemarray(smbios_hdl_t * shp,id_t id,smbios_memarray_ext_t * emap)108210942STom.Pothier@Sun.COM smbios_info_extmemarray(smbios_hdl_t *shp, id_t id, smbios_memarray_ext_t *emap)
108310942STom.Pothier@Sun.COM {
108410942STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
108510942STom.Pothier@Sun.COM 	smb_memarray_ext_t exma;
108610942STom.Pothier@Sun.COM 
108710942STom.Pothier@Sun.COM 	if (stp == NULL)
108810942STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
108910942STom.Pothier@Sun.COM 
109010942STom.Pothier@Sun.COM 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMARRAY)
109110942STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
109210942STom.Pothier@Sun.COM 
109310942STom.Pothier@Sun.COM 	smb_info_bcopy(stp->smbst_hdr, &exma, sizeof (exma));
109410942STom.Pothier@Sun.COM 	bzero(emap, sizeof (smbios_memarray_ext_t));
109510942STom.Pothier@Sun.COM 
109610942STom.Pothier@Sun.COM 	emap->smbmae_ma = exma.smbmarre_ma;
109710942STom.Pothier@Sun.COM 	emap->smbmae_comp = exma.smbmarre_component;
109810942STom.Pothier@Sun.COM 	emap->smbmae_bdf = exma.smbmarre_bdf;
109910942STom.Pothier@Sun.COM 
110010942STom.Pothier@Sun.COM 	return (0);
110110942STom.Pothier@Sun.COM }
110210942STom.Pothier@Sun.COM 
110310942STom.Pothier@Sun.COM int
smbios_info_extmemdevice(smbios_hdl_t * shp,id_t id,smbios_memdevice_ext_t * emdp)110410942STom.Pothier@Sun.COM smbios_info_extmemdevice(smbios_hdl_t *shp, id_t id,
110510942STom.Pothier@Sun.COM     smbios_memdevice_ext_t *emdp)
110610942STom.Pothier@Sun.COM {
110710942STom.Pothier@Sun.COM 	const smb_struct_t *stp = smb_lookup_id(shp, id);
110810942STom.Pothier@Sun.COM 	smb_memdevice_ext_t exmd;
110910942STom.Pothier@Sun.COM 
111010942STom.Pothier@Sun.COM 	if (stp == NULL)
111110942STom.Pothier@Sun.COM 		return (-1); /* errno is set for us */
111210942STom.Pothier@Sun.COM 
111310942STom.Pothier@Sun.COM 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
111410942STom.Pothier@Sun.COM 		return (smb_set_errno(shp, ESMB_TYPE));
111510942STom.Pothier@Sun.COM 
111610942STom.Pothier@Sun.COM 	smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
111710942STom.Pothier@Sun.COM 	bzero(emdp, sizeof (smbios_memdevice_ext_t));
111810942STom.Pothier@Sun.COM 
111910942STom.Pothier@Sun.COM 	emdp->smbmdeve_md = exmd.smbmdeve_mdev;
112010942STom.Pothier@Sun.COM 	emdp->smbmdeve_drch = exmd.smbmdeve_dchan;
112110942STom.Pothier@Sun.COM 	emdp->smbmdeve_ncs  = exmd.smbmdeve_ncs;
112210942STom.Pothier@Sun.COM 	emdp->smbmdeve_cs = exmd.smbmdeve_cs;
112310942STom.Pothier@Sun.COM 
112410942STom.Pothier@Sun.COM 	return (0);
112510942STom.Pothier@Sun.COM }
1126