xref: /illumos-gate/usr/src/common/smbios/smb_info.c (revision 064d431a)
184ab085aSmws /*
284ab085aSmws  * CDDL HEADER START
384ab085aSmws  *
484ab085aSmws  * The contents of this file are subject to the terms of the
5c7c09f80SEric Schrock  * Common Development and Distribution License (the "License").
6c7c09f80SEric Schrock  * You may not use this file except in compliance with the License.
784ab085aSmws  *
884ab085aSmws  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
984ab085aSmws  * or http://www.opensolaris.org/os/licensing.
1084ab085aSmws  * See the License for the specific language governing permissions
1184ab085aSmws  * and limitations under the License.
1284ab085aSmws  *
1384ab085aSmws  * When distributing Covered Code, include this CDDL HEADER in each
1484ab085aSmws  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1584ab085aSmws  * If applicable, add the following below this CDDL HEADER, with the
1684ab085aSmws  * fields enclosed by brackets "[]" replaced with your own identifying
1784ab085aSmws  * information: Portions Copyright [yyyy] [name of copyright owner]
1884ab085aSmws  *
1984ab085aSmws  * CDDL HEADER END
2084ab085aSmws  */
2184ab085aSmws 
2284ab085aSmws /*
234e901881SDale Ghent  * Copyright 2015 OmniTI Computer Consulting, Inc.  All rights reserved.
2416dde076SJohn Levon  * Copyright 2019 Joyent, Inc.
25*064d431aSRobert Mustacchi  * Copyright 2024 Oxide Computer Company
2603f9f63dSTom Pothier  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2784ab085aSmws  * Use is subject to license terms.
2884ab085aSmws  */
2984ab085aSmws 
3084ab085aSmws /*
3184ab085aSmws  * SMBIOS Information Routines
3284ab085aSmws  *
3384ab085aSmws  * The routines in this file are used to convert from the SMBIOS data format to
3484ab085aSmws  * a more reasonable and stable set of structures offered as part of our ABI.
3584ab085aSmws  * These functions take the general form:
3684ab085aSmws  *
3784ab085aSmws  *	stp = smb_lookup_type(shp, foo);
3884ab085aSmws  *	smb_foo_t foo;
3984ab085aSmws  *
4084ab085aSmws  *	smb_info_bcopy(stp->smbst_hdr, &foo, sizeof (foo));
4184ab085aSmws  *      bzero(caller's struct);
4284ab085aSmws  *
4384ab085aSmws  *	copy/convert foo members into caller's struct
4484ab085aSmws  *
4584ab085aSmws  * We copy the internal structure on to an automatic variable so as to avoid
4684ab085aSmws  * checks everywhere for structures that the BIOS has improperly truncated, and
4784ab085aSmws  * also to automatically handle the case of a structure that has been extended.
4884ab085aSmws  * When necessary, this code can use smb_gteq() to determine whether the SMBIOS
4984ab085aSmws  * data is of a particular revision that is supposed to contain a new field.
506734c4b0SRobert Mustacchi  *
516734c4b0SRobert Mustacchi  * Note, when trying to bzero the caller's struct you have to be careful about
526734c4b0SRobert Mustacchi  * versions. One can only bzero the initial version that existed in illumos. In
536734c4b0SRobert Mustacchi  * other words, if someone passes an older library handle that doesn't support a
546734c4b0SRobert Mustacchi  * version you cannot assume that their structures have those additional members
556734c4b0SRobert Mustacchi  * in them. Instead, a 'base' version is introduced for such types that have
566734c4b0SRobert Mustacchi  * differences and instead we only bzero out the base version and then handle
576734c4b0SRobert Mustacchi  * the additional members. In general, because all additional members will be
586734c4b0SRobert Mustacchi  * assigned, there's no reason to zero them out unless they are arrays that
596734c4b0SRobert Mustacchi  * won't be entirely filled in.
606734c4b0SRobert Mustacchi  *
616734c4b0SRobert Mustacchi  * Due to history, anything added after the update from version 2.4, in other
626734c4b0SRobert Mustacchi  * words additions from or after '5094 Update libsmbios with recent items'
636734c4b0SRobert Mustacchi  * (4e901881) is currently being used for this. While we don't allow software
646734c4b0SRobert Mustacchi  * compiling against this to get an older form, this was the first major update
656734c4b0SRobert Mustacchi  * and a good starting point for us to enforce this behavior which is useful for
666734c4b0SRobert Mustacchi  * moving forward to making this more public.
6784ab085aSmws  */
6884ab085aSmws 
6984ab085aSmws #include <sys/smbios_impl.h>
70e5cce96fSRobert Mustacchi #include <sys/byteorder.h>
711566bc34SRobert Mustacchi #include <sys/debug.h>
7284ab085aSmws 
739c94f155SCheng Sean Ye #ifdef _KERNEL
749c94f155SCheng Sean Ye #include <sys/sunddi.h>
759c94f155SCheng Sean Ye #else
76c7c09f80SEric Schrock #include <fcntl.h>
77c7c09f80SEric Schrock #include <unistd.h>
789c94f155SCheng Sean Ye #include <string.h>
79c7c09f80SEric Schrock #endif
80c7c09f80SEric Schrock 
81d53cdfabSRobert Mustacchi #define	SMB_CONT_WORD	2		/* contained elements are word size */
82d53cdfabSRobert Mustacchi 
8384ab085aSmws /*
8484ab085aSmws  * A large number of SMBIOS structures contain a set of common strings used to
8584ab085aSmws  * describe a h/w component's serial number, manufacturer, etc.  These fields
8684ab085aSmws  * helpfully have different names and offsets and sometimes aren't consistent.
8784ab085aSmws  * To simplify life for our clients, we factor these common things out into
8884ab085aSmws  * smbios_info_t, which can be retrieved for any structure.  The following
8984ab085aSmws  * table describes the mapping from a given structure to the smbios_info_t.
90074bb90dSTom Pothier  * Multiple SMBIOS stuctures' contained objects are also handled here.
9184ab085aSmws  */
9284ab085aSmws static const struct smb_infospec {
9384ab085aSmws 	uint8_t is_type;		/* structure type */
9484ab085aSmws 	uint8_t is_manu;		/* manufacturer offset */
9584ab085aSmws 	uint8_t is_product;		/* product name offset */
9684ab085aSmws 	uint8_t is_version;		/* version offset */
9784ab085aSmws 	uint8_t is_serial;		/* serial number offset */
9884ab085aSmws 	uint8_t is_asset;		/* asset tag offset */
9984ab085aSmws 	uint8_t is_location;		/* location string offset */
10084ab085aSmws 	uint8_t is_part;		/* part number offset */
101074bb90dSTom Pothier 	uint8_t is_contc;		/* contained count */
102074bb90dSTom Pothier 	uint8_t is_contsz;		/* contained size */
103074bb90dSTom Pothier 	uint8_t is_contv;		/* contained objects */
10484ab085aSmws } _smb_infospecs[] = {
10584ab085aSmws 	{ SMB_TYPE_SYSTEM,
10684ab085aSmws 		offsetof(smb_system_t, smbsi_manufacturer),
10784ab085aSmws 		offsetof(smb_system_t, smbsi_product),
10884ab085aSmws 		offsetof(smb_system_t, smbsi_version),
10984ab085aSmws 		offsetof(smb_system_t, smbsi_serial),
11084ab085aSmws 		0,
11184ab085aSmws 		0,
112074bb90dSTom Pothier 		0,
113074bb90dSTom Pothier 		0,
114074bb90dSTom Pothier 		0,
11584ab085aSmws 		0 },
11684ab085aSmws 	{ SMB_TYPE_BASEBOARD,
11784ab085aSmws 		offsetof(smb_bboard_t, smbbb_manufacturer),
11884ab085aSmws 		offsetof(smb_bboard_t, smbbb_product),
11984ab085aSmws 		offsetof(smb_bboard_t, smbbb_version),
12084ab085aSmws 		offsetof(smb_bboard_t, smbbb_serial),
12184ab085aSmws 		offsetof(smb_bboard_t, smbbb_asset),
12284ab085aSmws 		offsetof(smb_bboard_t, smbbb_location),
123074bb90dSTom Pothier 		0,
124074bb90dSTom Pothier 		offsetof(smb_bboard_t, smbbb_cn),
125074bb90dSTom Pothier 		SMB_CONT_WORD,
126074bb90dSTom Pothier 		offsetof(smb_bboard_t, smbbb_cv) },
12784ab085aSmws 	{ SMB_TYPE_CHASSIS,
12884ab085aSmws 		offsetof(smb_chassis_t, smbch_manufacturer),
12984ab085aSmws 		0,
13084ab085aSmws 		offsetof(smb_chassis_t, smbch_version),
13184ab085aSmws 		offsetof(smb_chassis_t, smbch_serial),
13284ab085aSmws 		offsetof(smb_chassis_t, smbch_asset),
13384ab085aSmws 		0,
134074bb90dSTom Pothier 		0,
135d53cdfabSRobert Mustacchi 		0,
136d53cdfabSRobert Mustacchi 		0,
137d53cdfabSRobert Mustacchi 		0 },
13884ab085aSmws 	{ SMB_TYPE_PROCESSOR,
13984ab085aSmws 		offsetof(smb_processor_t, smbpr_manufacturer),
14084ab085aSmws 		0,
14184ab085aSmws 		offsetof(smb_processor_t, smbpr_version),
14284ab085aSmws 		offsetof(smb_processor_t, smbpr_serial),
14384ab085aSmws 		offsetof(smb_processor_t, smbpr_asset),
14484ab085aSmws 		offsetof(smb_processor_t, smbpr_socket),
145074bb90dSTom Pothier 		offsetof(smb_processor_t, smbpr_part),
146074bb90dSTom Pothier 		0,
147074bb90dSTom Pothier 		0,
148074bb90dSTom Pothier 		0 },
14984ab085aSmws 	{ SMB_TYPE_CACHE,
15084ab085aSmws 		0,
15184ab085aSmws 		0,
15284ab085aSmws 		0,
15384ab085aSmws 		0,
15484ab085aSmws 		0,
15584ab085aSmws 		offsetof(smb_cache_t, smbca_socket),
156074bb90dSTom Pothier 		0,
157074bb90dSTom Pothier 		0,
158074bb90dSTom Pothier 		0,
15984ab085aSmws 		0 },
16084ab085aSmws 	{ SMB_TYPE_PORT,
16184ab085aSmws 		0,
16284ab085aSmws 		0,
16384ab085aSmws 		0,
16484ab085aSmws 		0,
16584ab085aSmws 		0,
16684ab085aSmws 		offsetof(smb_port_t, smbpo_iref),
167074bb90dSTom Pothier 		0,
168074bb90dSTom Pothier 		0,
169074bb90dSTom Pothier 		0,
17084ab085aSmws 		0 },
17184ab085aSmws 	{ SMB_TYPE_SLOT,
17284ab085aSmws 		0,
17384ab085aSmws 		0,
17484ab085aSmws 		0,
17584ab085aSmws 		0,
17684ab085aSmws 		0,
17784ab085aSmws 		offsetof(smb_slot_t, smbsl_name),
178074bb90dSTom Pothier 		0,
179074bb90dSTom Pothier 		0,
180074bb90dSTom Pothier 		0,
18184ab085aSmws 		0 },
18284ab085aSmws 	{ SMB_TYPE_MEMDEVICE,
18384ab085aSmws 		offsetof(smb_memdevice_t, smbmdev_manufacturer),
18484ab085aSmws 		0,
18584ab085aSmws 		0,
18684ab085aSmws 		offsetof(smb_memdevice_t, smbmdev_serial),
18784ab085aSmws 		offsetof(smb_memdevice_t, smbmdev_asset),
18884ab085aSmws 		offsetof(smb_memdevice_t, smbmdev_dloc),
189074bb90dSTom Pothier 		offsetof(smb_memdevice_t, smbmdev_part),
190074bb90dSTom Pothier 		0,
191074bb90dSTom Pothier 		0,
192074bb90dSTom Pothier 		0 },
19384ab085aSmws 	{ SMB_TYPE_POWERSUP,
19484ab085aSmws 		offsetof(smb_powersup_t, smbpsup_manufacturer),
19584ab085aSmws 		offsetof(smb_powersup_t, smbpsup_devname),
19684ab085aSmws 		offsetof(smb_powersup_t, smbpsup_rev),
19784ab085aSmws 		offsetof(smb_powersup_t, smbpsup_serial),
19884ab085aSmws 		offsetof(smb_powersup_t, smbpsup_asset),
19984ab085aSmws 		offsetof(smb_powersup_t, smbpsup_loc),
200074bb90dSTom Pothier 		offsetof(smb_powersup_t, smbpsup_part),
201074bb90dSTom Pothier 		0,
202074bb90dSTom Pothier 		0,
203074bb90dSTom Pothier 		0 },
20446782190SRobert Mustacchi 	{ SMB_TYPE_BATTERY,
20546782190SRobert Mustacchi 		offsetof(smb_battery_t, smbbat_manufacturer),
20646782190SRobert Mustacchi 		offsetof(smb_battery_t, smbbat_devname),
20746782190SRobert Mustacchi 		0,
20846782190SRobert Mustacchi 		/*
20946782190SRobert Mustacchi 		 * While the serial number is a part of the device, because of
21046782190SRobert Mustacchi 		 * the fact that the battery has two different serial numbers,
21146782190SRobert Mustacchi 		 * we don't include it here.
21246782190SRobert Mustacchi 		 */
21346782190SRobert Mustacchi 		0,
21446782190SRobert Mustacchi 		0,
21546782190SRobert Mustacchi 		offsetof(smb_battery_t, smbbat_loc),
21646782190SRobert Mustacchi 		0,
21746782190SRobert Mustacchi 		0,
21846782190SRobert Mustacchi 		0,
21946782190SRobert Mustacchi 		0
22046782190SRobert Mustacchi 	},
221d53cdfabSRobert Mustacchi 	{ SMB_TYPE_FWINFO,
222d53cdfabSRobert Mustacchi 		offsetof(smb_fwinfo_t, smbfwii_mfg),
223d53cdfabSRobert Mustacchi 		0,
224d53cdfabSRobert Mustacchi 		offsetof(smb_fwinfo_t, smbfwii_vers),
225d53cdfabSRobert Mustacchi 		0,
226d53cdfabSRobert Mustacchi 		0,
227d53cdfabSRobert Mustacchi 		0,
228d53cdfabSRobert Mustacchi 		0,
229d53cdfabSRobert Mustacchi 		0,
230d53cdfabSRobert Mustacchi 		0,
231d53cdfabSRobert Mustacchi 		0
232d53cdfabSRobert Mustacchi 	},
23384ab085aSmws 	{ SMB_TYPE_EOT }
23484ab085aSmws };
23584ab085aSmws 
23684ab085aSmws static const char *
smb_info_strptr(const smb_struct_t * stp,uint8_t off,int * n)23784ab085aSmws smb_info_strptr(const smb_struct_t *stp, uint8_t off, int *n)
23884ab085aSmws {
23984ab085aSmws 	const uint8_t *sp = (const uint8_t *)(uintptr_t)stp->smbst_hdr;
24084ab085aSmws 
24184ab085aSmws 	if (off != 0 && sp + off < stp->smbst_end) {
24284ab085aSmws 		(*n)++; /* indicate success for caller */
24384ab085aSmws 		return (smb_strptr(stp, sp[off]));
24484ab085aSmws 	}
24584ab085aSmws 
24684ab085aSmws 	return (smb_strptr(stp, 0));
24784ab085aSmws }
24884ab085aSmws 
249c6795799SRobert Mustacchi static void
smb_info_bcopy_offset(const smb_header_t * hp,void * dst,size_t dstlen,size_t offset)250c6795799SRobert Mustacchi smb_info_bcopy_offset(const smb_header_t *hp, void *dst, size_t dstlen,
251c6795799SRobert Mustacchi     size_t offset)
252c6795799SRobert Mustacchi {
253c6795799SRobert Mustacchi 	if (offset >= hp->smbh_len) {
254c6795799SRobert Mustacchi 		bzero(dst, dstlen);
255c6795799SRobert Mustacchi 	} else if (offset + dstlen > hp->smbh_len) {
256c6795799SRobert Mustacchi 		size_t nvalid = MIN(hp->smbh_len - offset, dstlen);
257c6795799SRobert Mustacchi 		bcopy((char *)hp + offset, dst, nvalid);
258c6795799SRobert Mustacchi 		bzero((char *)dst + nvalid, dstlen - nvalid);
259c6795799SRobert Mustacchi 	} else {
260c6795799SRobert Mustacchi 		bcopy((char *)hp + offset, dst, dstlen);
261c6795799SRobert Mustacchi 	}
262c6795799SRobert Mustacchi }
263c6795799SRobert Mustacchi 
26484ab085aSmws static void
smb_info_bcopy(const smb_header_t * hp,void * dst,size_t dstlen)26584ab085aSmws smb_info_bcopy(const smb_header_t *hp, void *dst, size_t dstlen)
26684ab085aSmws {
267c6795799SRobert Mustacchi 	return (smb_info_bcopy_offset(hp, dst, dstlen, 0));
26884ab085aSmws }
26984ab085aSmws 
2701951a933SToomas Soome smbios_entry_point_t
smbios_info_smbios(smbios_hdl_t * shp,smbios_entry_t * ep)27184ab085aSmws smbios_info_smbios(smbios_hdl_t *shp, smbios_entry_t *ep)
27284ab085aSmws {
27384ab085aSmws 	bcopy(&shp->sh_ent, ep, sizeof (smbios_entry_t));
2741951a933SToomas Soome 	return (shp->sh_ent_type);
2751951a933SToomas Soome }
2761951a933SToomas Soome 
2771951a933SToomas Soome void
smbios_info_smbios_version(smbios_hdl_t * shp,smbios_version_t * v)2781951a933SToomas Soome smbios_info_smbios_version(smbios_hdl_t *shp, smbios_version_t *v)
2791951a933SToomas Soome {
2801951a933SToomas Soome 	v->smbv_major = SMB_MAJOR(shp->sh_smbvers);
2811951a933SToomas Soome 	v->smbv_minor = SMB_MINOR(shp->sh_smbvers);
28284ab085aSmws }
28384ab085aSmws 
284c7c09f80SEric Schrock #ifndef _KERNEL
285c7c09f80SEric Schrock static char smbios_product_override[256];
286c7c09f80SEric Schrock static boolean_t smbios_product_checked;
287c7c09f80SEric Schrock #endif
288c7c09f80SEric Schrock 
28984ab085aSmws int
smbios_info_common(smbios_hdl_t * shp,id_t id,smbios_info_t * ip)29084ab085aSmws smbios_info_common(smbios_hdl_t *shp, id_t id, smbios_info_t *ip)
29184ab085aSmws {
29284ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
29384ab085aSmws 	const struct smb_infospec *isp;
29484ab085aSmws 	int n = 0;
29584ab085aSmws 
29684ab085aSmws 	if (stp == NULL)
29784ab085aSmws 		return (-1); /* errno is set for us */
29884ab085aSmws 
29984ab085aSmws 	for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) {
30084ab085aSmws 		if (isp->is_type == stp->smbst_hdr->smbh_type)
30184ab085aSmws 			break;
30284ab085aSmws 	}
30384ab085aSmws 
30484ab085aSmws 	ip->smbi_manufacturer = smb_info_strptr(stp, isp->is_manu, &n);
30584ab085aSmws 	ip->smbi_product = smb_info_strptr(stp, isp->is_product, &n);
30684ab085aSmws 	ip->smbi_version = smb_info_strptr(stp, isp->is_version, &n);
30784ab085aSmws 	ip->smbi_serial = smb_info_strptr(stp, isp->is_serial, &n);
30884ab085aSmws 	ip->smbi_asset = smb_info_strptr(stp, isp->is_asset, &n);
30984ab085aSmws 	ip->smbi_location = smb_info_strptr(stp, isp->is_location, &n);
31084ab085aSmws 	ip->smbi_part = smb_info_strptr(stp, isp->is_part, &n);
31184ab085aSmws 
312c7c09f80SEric Schrock 	/*
313c7c09f80SEric Schrock 	 * This private file allows developers to experiment with reporting
314c7c09f80SEric Schrock 	 * different platform strings from SMBIOS.  It is not a supported
315c7c09f80SEric Schrock 	 * mechanism in the long term, and does not work in the kernel.
316c7c09f80SEric Schrock 	 */
317c7c09f80SEric Schrock #ifndef _KERNEL
318c7c09f80SEric Schrock 	if (isp->is_type == SMB_TYPE_SYSTEM) {
319c7c09f80SEric Schrock 		if (!smbios_product_checked) {
320c7c09f80SEric Schrock 			int fd = open("/etc/smbios_product", O_RDONLY);
321c7c09f80SEric Schrock 			if (fd >= 0) {
322c7c09f80SEric Schrock 				(void) read(fd, smbios_product_override,
323c7c09f80SEric Schrock 				    sizeof (smbios_product_override) - 1);
324c7c09f80SEric Schrock 				(void) close(fd);
325c7c09f80SEric Schrock 			}
326c7c09f80SEric Schrock 			smbios_product_checked = B_TRUE;
327c7c09f80SEric Schrock 		}
328c7c09f80SEric Schrock 
329c7c09f80SEric Schrock 		if (smbios_product_override[0] != '\0')
330c7c09f80SEric Schrock 			ip->smbi_product = smbios_product_override;
331c7c09f80SEric Schrock 	}
332c7c09f80SEric Schrock #endif
333c7c09f80SEric Schrock 
33484ab085aSmws 	/*
33584ab085aSmws 	 * If we have a port with an empty internal reference designator string
33684ab085aSmws 	 * try using the external reference designator string instead.
33784ab085aSmws 	 */
33884ab085aSmws 	if (isp->is_type == SMB_TYPE_PORT && ip->smbi_location[0] == '\0') {
33984ab085aSmws 		ip->smbi_location = smb_info_strptr(stp,
34084ab085aSmws 		    offsetof(smb_port_t, smbpo_eref), &n);
34184ab085aSmws 	}
34284ab085aSmws 
34384ab085aSmws 	return (n ? 0 : smb_set_errno(shp, ESMB_NOINFO));
34484ab085aSmws }
34584ab085aSmws 
346074bb90dSTom Pothier /*
347074bb90dSTom Pothier  * Returns the actual number of contained objects.
348074bb90dSTom Pothier  *
349074bb90dSTom Pothier  * idc - number of contained objects
350074bb90dSTom Pothier  * idv - returned array of contained objects
351074bb90dSTom Pothier  */
352074bb90dSTom Pothier int
smbios_info_contains(smbios_hdl_t * shp,id_t id,uint_t idc,id_t * idv)353074bb90dSTom Pothier smbios_info_contains(smbios_hdl_t *shp, id_t id, uint_t idc, id_t *idv)
354074bb90dSTom Pothier {
355074bb90dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
356074bb90dSTom Pothier 	const struct smb_infospec *isp;
357074bb90dSTom Pothier 	id_t *cp;
358074bb90dSTom Pothier 	uint_t size;
359074bb90dSTom Pothier 	uint8_t cnt;
360074bb90dSTom Pothier 	int i, n;
361074bb90dSTom Pothier 
362074bb90dSTom Pothier 	if (stp == NULL) {
363074bb90dSTom Pothier 		return (-1); /* errno is set for us */
364074bb90dSTom Pothier 	}
365074bb90dSTom Pothier 
366074bb90dSTom Pothier 	for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) {
367074bb90dSTom Pothier 		if (isp->is_type == stp->smbst_hdr->smbh_type)
368074bb90dSTom Pothier 			break;
369074bb90dSTom Pothier 	}
370074bb90dSTom Pothier 	if (isp->is_type == SMB_TYPE_EOT)
371074bb90dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
372074bb90dSTom Pothier 
373074bb90dSTom Pothier 	size = isp->is_contsz;
374074bb90dSTom Pothier 	cnt = *((uint8_t *)(uintptr_t)stp->smbst_hdr + isp->is_contc);
375074bb90dSTom Pothier 	cp = (id_t *)((uintptr_t)stp->smbst_hdr + isp->is_contv);
376074bb90dSTom Pothier 
377074bb90dSTom Pothier 	n = MIN(cnt, idc);
378074bb90dSTom Pothier 	for (i = 0; i < n; i++) {
379074bb90dSTom Pothier 		if (size == SMB_CONT_WORD)
380d53cdfabSRobert Mustacchi 			idv[i] = *((uint16_t *)(uintptr_t)cp + (i * 2));
381074bb90dSTom Pothier 		else
382074bb90dSTom Pothier 			return (smb_set_errno(shp, ESMB_INVAL));
383074bb90dSTom Pothier 	}
384074bb90dSTom Pothier 
385074bb90dSTom Pothier 	return (cnt);
386074bb90dSTom Pothier }
387074bb90dSTom Pothier 
38884ab085aSmws id_t
smbios_info_bios(smbios_hdl_t * shp,smbios_bios_t * bp)38984ab085aSmws smbios_info_bios(smbios_hdl_t *shp, smbios_bios_t *bp)
39084ab085aSmws {
39184ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BIOS);
39284ab085aSmws 	const smb_bios_t *bip;
39384ab085aSmws 
39484ab085aSmws 	if (stp == NULL)
39584ab085aSmws 		return (-1); /* errno is set for us */
39684ab085aSmws 
39784ab085aSmws 	if (stp->smbst_hdr->smbh_len < sizeof (smb_bios_t) - sizeof (uint8_t))
39884ab085aSmws 		return (smb_set_errno(shp, ESMB_CORRUPT));
39984ab085aSmws 
40084ab085aSmws 	bip = (smb_bios_t *)(uintptr_t)stp->smbst_hdr;
401e5cce96fSRobert Mustacchi 	bzero(bp, sizeof (smb_base_bios_t));
402e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_31)) {
403e5cce96fSRobert Mustacchi 		bp->smbb_extromsize = 0;
404e5cce96fSRobert Mustacchi 	}
40584ab085aSmws 
40684ab085aSmws 	bp->smbb_vendor = smb_strptr(stp, bip->smbbi_vendor);
40784ab085aSmws 	bp->smbb_version = smb_strptr(stp, bip->smbbi_version);
40884ab085aSmws 	bp->smbb_segment = bip->smbbi_segment;
40984ab085aSmws 	bp->smbb_reldate = smb_strptr(stp, bip->smbbi_reldate);
41084ab085aSmws 	bp->smbb_romsize = 64 * 1024 * ((uint32_t)bip->smbbi_romsize + 1);
41184ab085aSmws 	bp->smbb_runsize = 16 * (0x10000 - (uint32_t)bip->smbbi_segment);
41284ab085aSmws 	bp->smbb_cflags = bip->smbbi_cflags;
41384ab085aSmws 
41484ab085aSmws 	/*
41584ab085aSmws 	 * If one or more extension bytes are present, reset smbb_xcflags to
41684ab085aSmws 	 * point to them.  Otherwise leave this member set to NULL.
41784ab085aSmws 	 */
41884ab085aSmws 	if (stp->smbst_hdr->smbh_len >= sizeof (smb_bios_t)) {
41984ab085aSmws 		bp->smbb_xcflags = bip->smbbi_xcflags;
42084ab085aSmws 		bp->smbb_nxcflags = stp->smbst_hdr->smbh_len -
42184ab085aSmws 		    sizeof (smb_bios_t) + 1;
42284ab085aSmws 
42384ab085aSmws 		if (bp->smbb_nxcflags > SMB_BIOSXB_ECFW_MIN &&
42484ab085aSmws 		    smb_gteq(shp, SMB_VERSION_24)) {
42584ab085aSmws 			bp->smbb_biosv.smbv_major =
42684ab085aSmws 			    bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MAJ];
42784ab085aSmws 			bp->smbb_biosv.smbv_minor =
42884ab085aSmws 			    bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MIN];
42984ab085aSmws 			bp->smbb_ecfwv.smbv_major =
43084ab085aSmws 			    bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MAJ];
43184ab085aSmws 			bp->smbb_ecfwv.smbv_minor =
43284ab085aSmws 			    bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MIN];
43384ab085aSmws 		}
434e5cce96fSRobert Mustacchi 
435e5cce96fSRobert Mustacchi 		if (bp->smbb_nxcflags > SMB_BIOSXB_EXTROM + 1 &&
436e5cce96fSRobert Mustacchi 		    smb_gteq(shp, SMB_VERSION_31)) {
437e5cce96fSRobert Mustacchi 			uint16_t val;
438e5cce96fSRobert Mustacchi 			uint64_t rs;
439e5cce96fSRobert Mustacchi 
440e5cce96fSRobert Mustacchi 			/*
441e5cce96fSRobert Mustacchi 			 * Because of the fact that the extended size is a
442e5cce96fSRobert Mustacchi 			 * uint16_t and we'd need to define an explicit
443e5cce96fSRobert Mustacchi 			 * endian-aware way to access it, we don't include it in
444e5cce96fSRobert Mustacchi 			 * the number of extended flags below and thus subtract
445e5cce96fSRobert Mustacchi 			 * its size.
446e5cce96fSRobert Mustacchi 			 */
447e5cce96fSRobert Mustacchi 			bp->smbb_nxcflags -= sizeof (uint16_t);
448e5cce96fSRobert Mustacchi 			bcopy(&bip->smbbi_xcflags[SMB_BIOSXB_EXTROM], &val,
449e5cce96fSRobert Mustacchi 			    sizeof (val));
450e5cce96fSRobert Mustacchi 			val = LE_16(val);
451e5cce96fSRobert Mustacchi 
452e5cce96fSRobert Mustacchi 			/*
453e5cce96fSRobert Mustacchi 			 * The upper two bits of the extended rom size are used
454e5cce96fSRobert Mustacchi 			 * to indicate whether the other 14 bits are in MB or
455e5cce96fSRobert Mustacchi 			 * GB.
456e5cce96fSRobert Mustacchi 			 */
457e5cce96fSRobert Mustacchi 			rs = SMB_BIOS_EXTROM_VALUE_MASK(val);
458e5cce96fSRobert Mustacchi 			switch (SMB_BIOS_EXTROM_SHIFT_MASK(val)) {
459e5cce96fSRobert Mustacchi 			case 0:
460e5cce96fSRobert Mustacchi 				rs *= 1024ULL * 1024ULL;
461e5cce96fSRobert Mustacchi 				break;
462e5cce96fSRobert Mustacchi 			case 1:
463e5cce96fSRobert Mustacchi 				rs *= 1024ULL * 1024ULL * 1024ULL;
464e5cce96fSRobert Mustacchi 				break;
465e5cce96fSRobert Mustacchi 			default:
466e5cce96fSRobert Mustacchi 				rs = 0;
467e5cce96fSRobert Mustacchi 				break;
468e5cce96fSRobert Mustacchi 			}
469e5cce96fSRobert Mustacchi 
470e5cce96fSRobert Mustacchi 			if (smb_libgteq(shp, SMB_VERSION_31)) {
471e5cce96fSRobert Mustacchi 				bp->smbb_extromsize = rs;
472e5cce96fSRobert Mustacchi 			}
473e5cce96fSRobert Mustacchi 		}
474e5cce96fSRobert Mustacchi 	}
475e5cce96fSRobert Mustacchi 
476e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_31) && bp->smbb_extromsize == 0) {
477e5cce96fSRobert Mustacchi 		bp->smbb_extromsize = bp->smbb_romsize;
47884ab085aSmws 	}
47984ab085aSmws 
48084ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
48184ab085aSmws }
48284ab085aSmws 
48384ab085aSmws id_t
smbios_info_system(smbios_hdl_t * shp,smbios_system_t * sip)48484ab085aSmws smbios_info_system(smbios_hdl_t *shp, smbios_system_t *sip)
48584ab085aSmws {
48684ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM);
48784ab085aSmws 	smb_system_t si;
48884ab085aSmws 
48984ab085aSmws 	if (stp == NULL)
49084ab085aSmws 		return (-1); /* errno is set for us */
49184ab085aSmws 
49284ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &si, sizeof (si));
49384ab085aSmws 	bzero(sip, sizeof (smbios_system_t));
49484ab085aSmws 
49584ab085aSmws 	sip->smbs_uuid = ((smb_system_t *)stp->smbst_hdr)->smbsi_uuid;
49684ab085aSmws 	sip->smbs_uuidlen = sizeof (si.smbsi_uuid);
49784ab085aSmws 	sip->smbs_wakeup = si.smbsi_wakeup;
49884ab085aSmws 	sip->smbs_sku = smb_strptr(stp, si.smbsi_sku);
49984ab085aSmws 	sip->smbs_family = smb_strptr(stp, si.smbsi_family);
50084ab085aSmws 
50184ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
50284ab085aSmws }
50384ab085aSmws 
50484ab085aSmws int
smbios_info_bboard(smbios_hdl_t * shp,id_t id,smbios_bboard_t * bbp)50584ab085aSmws smbios_info_bboard(smbios_hdl_t *shp, id_t id, smbios_bboard_t *bbp)
50684ab085aSmws {
50784ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
50884ab085aSmws 	smb_bboard_t bb;
50984ab085aSmws 
51084ab085aSmws 	if (stp == NULL)
51184ab085aSmws 		return (-1); /* errno is set for us */
51284ab085aSmws 
51384ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_BASEBOARD)
51484ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
51584ab085aSmws 
51684ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &bb, sizeof (bb));
51784ab085aSmws 	bzero(bbp, sizeof (smbios_bboard_t));
51884ab085aSmws 
51984ab085aSmws 	bbp->smbb_chassis = bb.smbbb_chassis;
52084ab085aSmws 	bbp->smbb_flags = bb.smbbb_flags;
52184ab085aSmws 	bbp->smbb_type = bb.smbbb_type;
522074bb90dSTom Pothier 	bbp->smbb_contn = bb.smbbb_cn;
52384ab085aSmws 
52484ab085aSmws 	return (0);
52584ab085aSmws }
52684ab085aSmws 
52784ab085aSmws int
smbios_info_chassis(smbios_hdl_t * shp,id_t id,smbios_chassis_t * chp)52884ab085aSmws smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp)
52984ab085aSmws {
53084ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
531d53cdfabSRobert Mustacchi 	smb_chassis_t ch;
53284ab085aSmws 
533d53cdfabSRobert Mustacchi 	if (stp == NULL) {
53484ab085aSmws 		return (-1); /* errno is set for us */
535d53cdfabSRobert Mustacchi 	}
53684ab085aSmws 
537d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) {
53884ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
539d53cdfabSRobert Mustacchi 	}
54084ab085aSmws 
541d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (ch)) {
542d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
543d53cdfabSRobert Mustacchi 	}
544d53cdfabSRobert Mustacchi 
545d53cdfabSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
5466734c4b0SRobert Mustacchi 	bzero(chp, sizeof (smb_base_chassis_t));
547d53cdfabSRobert Mustacchi 
548d53cdfabSRobert Mustacchi 	/*
549d53cdfabSRobert Mustacchi 	 * See the comments for the smb_chassis_pre35_t in sys/smbios_impl.h for
550d53cdfabSRobert Mustacchi 	 * an explanation as to why this is here. The use of smb_strptr with
551d53cdfabSRobert Mustacchi 	 * index 0 below ensures that we initialize this to an empty string.
552d53cdfabSRobert Mustacchi 	 */
553d53cdfabSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_35)) {
554d53cdfabSRobert Mustacchi 		chp->smbc_sku = smb_strptr(stp, 0);
555d53cdfabSRobert Mustacchi 	} else if (smb_libgteq(shp, SMB_VERSION_27)) {
556d53cdfabSRobert Mustacchi 		smb_chassis_pre35_t *p35 = (smb_chassis_pre35_t *)chp;
557d53cdfabSRobert Mustacchi 		bzero(p35->smbc_sku, sizeof (p35->smbc_sku));
5586734c4b0SRobert Mustacchi 	}
55984ab085aSmws 
560d53cdfabSRobert Mustacchi 	chp->smbc_oemdata = ch.smbch_oemdata;
561d53cdfabSRobert Mustacchi 	chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0;
562d53cdfabSRobert Mustacchi 	chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK;
563d53cdfabSRobert Mustacchi 	chp->smbc_bustate = ch.smbch_bustate;
564d53cdfabSRobert Mustacchi 	chp->smbc_psstate = ch.smbch_psstate;
565d53cdfabSRobert Mustacchi 	chp->smbc_thstate = ch.smbch_thstate;
566d53cdfabSRobert Mustacchi 	chp->smbc_security = ch.smbch_security;
567d53cdfabSRobert Mustacchi 	chp->smbc_uheight = ch.smbch_uheight;
568d53cdfabSRobert Mustacchi 	chp->smbc_cords = ch.smbch_cords;
569d53cdfabSRobert Mustacchi 	chp->smbc_elems = ch.smbch_cn;
570d53cdfabSRobert Mustacchi 	chp->smbc_elemlen = ch.smbch_cm;
571d53cdfabSRobert Mustacchi 
572d53cdfabSRobert Mustacchi 	/*
573d53cdfabSRobert Mustacchi 	 * If the table is older than version 2.7 which added support for the
574d53cdfabSRobert Mustacchi 	 * chassis SKU, there's no reason to proceed.
575d53cdfabSRobert Mustacchi 	 */
576d53cdfabSRobert Mustacchi 	if (!smb_gteq(shp, SMB_VERSION_27)) {
577d53cdfabSRobert Mustacchi 		return (0);
578d53cdfabSRobert Mustacchi 	}
5794e901881SDale Ghent 
580e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_27)) {
581d53cdfabSRobert Mustacchi 		uint8_t strno;
582d53cdfabSRobert Mustacchi 		const char *str;
583d53cdfabSRobert Mustacchi 		off_t off = sizeof (ch) + ch.smbch_cn * ch.smbch_cm;
584d53cdfabSRobert Mustacchi 		if (stp->smbst_hdr->smbh_len < off + 1) {
585d53cdfabSRobert Mustacchi 			return (smb_set_errno(shp, ESMB_SHORT));
586d53cdfabSRobert Mustacchi 		}
587d53cdfabSRobert Mustacchi 		smb_info_bcopy_offset(stp->smbst_hdr, &strno, sizeof (strno),
588d53cdfabSRobert Mustacchi 		    off);
589d53cdfabSRobert Mustacchi 		str = smb_strptr(stp, strno);
590d53cdfabSRobert Mustacchi 		if (smb_libgteq(shp, SMB_VERSION_35)) {
591d53cdfabSRobert Mustacchi 			chp->smbc_sku = str;
592d53cdfabSRobert Mustacchi 		} else {
593d53cdfabSRobert Mustacchi 			smb_chassis_pre35_t *p35 = (smb_chassis_pre35_t *)chp;
594d53cdfabSRobert Mustacchi 			(void) strlcpy(p35->smbc_sku, str,
595d53cdfabSRobert Mustacchi 			    sizeof (p35->smbc_sku));
596d53cdfabSRobert Mustacchi 		}
5974e901881SDale Ghent 	}
59884ab085aSmws 
59984ab085aSmws 	return (0);
60084ab085aSmws }
60184ab085aSmws 
602d53cdfabSRobert Mustacchi int
smbios_info_chassis_elts(smbios_hdl_t * shp,id_t id,uint_t * nentsp,smbios_chassis_entry_t ** entsp)603d53cdfabSRobert Mustacchi smbios_info_chassis_elts(smbios_hdl_t *shp, id_t id, uint_t *nentsp,
604d53cdfabSRobert Mustacchi     smbios_chassis_entry_t **entsp)
605d53cdfabSRobert Mustacchi {
606d53cdfabSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
607d53cdfabSRobert Mustacchi 	smbios_chassis_entry_t *entry;
608d53cdfabSRobert Mustacchi 	smb_chassis_t ch;
609d53cdfabSRobert Mustacchi 	size_t entlen;
610d53cdfabSRobert Mustacchi 	uint_t i;
611d53cdfabSRobert Mustacchi 
612d53cdfabSRobert Mustacchi 	if (stp == NULL) {
613d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
614d53cdfabSRobert Mustacchi 	}
615d53cdfabSRobert Mustacchi 
616d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) {
617d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
618d53cdfabSRobert Mustacchi 	}
619d53cdfabSRobert Mustacchi 
620d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (ch)) {
621d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
622d53cdfabSRobert Mustacchi 	}
623d53cdfabSRobert Mustacchi 
624d53cdfabSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
625d53cdfabSRobert Mustacchi 	if (ch.smbch_cm != sizeof (smb_chassis_entry_t)) {
626d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_CORRUPT));
627d53cdfabSRobert Mustacchi 	}
628d53cdfabSRobert Mustacchi 
629d53cdfabSRobert Mustacchi 	if (ch.smbch_cn == 0) {
630d53cdfabSRobert Mustacchi 		*nentsp = 0;
631d53cdfabSRobert Mustacchi 		*entsp = NULL;
632d53cdfabSRobert Mustacchi 		return (0);
633d53cdfabSRobert Mustacchi 	}
634d53cdfabSRobert Mustacchi 
635d53cdfabSRobert Mustacchi 	entlen = ch.smbch_cm * ch.smbch_cn;
636d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (ch) + entlen) {
637d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
638d53cdfabSRobert Mustacchi 	}
639d53cdfabSRobert Mustacchi 
640d53cdfabSRobert Mustacchi 	if ((entry = smb_alloc(entlen)) == NULL) {
641d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_NOMEM));
642d53cdfabSRobert Mustacchi 	}
643d53cdfabSRobert Mustacchi 
644d53cdfabSRobert Mustacchi 	for (i = 0; i < ch.smbch_cn; i++) {
645d53cdfabSRobert Mustacchi 		smb_chassis_entry_t e;
646d53cdfabSRobert Mustacchi 		size_t off = sizeof (ch) + i * sizeof (e);
647d53cdfabSRobert Mustacchi 
648d53cdfabSRobert Mustacchi 		smb_info_bcopy_offset(stp->smbst_hdr, &e, sizeof (e), off);
649d53cdfabSRobert Mustacchi 		/*
650d53cdfabSRobert Mustacchi 		 * The top bit is used to indicate what type of record this is,
651d53cdfabSRobert Mustacchi 		 * while the lower 7-bits indicate the actual type.
652d53cdfabSRobert Mustacchi 		 */
653d53cdfabSRobert Mustacchi 		entry[i].smbce_type = e.smbce_type & 0x80 ?
654d53cdfabSRobert Mustacchi 		    SMB_CELT_SMBIOS : SMB_CELT_BBOARD;
655d53cdfabSRobert Mustacchi 		entry[i].smbce_elt = e.smbce_type & 0x7f;
656d53cdfabSRobert Mustacchi 		entry[i].smbce_min = e.smbce_min;
657d53cdfabSRobert Mustacchi 		entry[i].smbce_max = e.smbce_max;
658d53cdfabSRobert Mustacchi 	}
659d53cdfabSRobert Mustacchi 
660d53cdfabSRobert Mustacchi 	*entsp = entry;
661d53cdfabSRobert Mustacchi 	*nentsp = ch.smbch_cn;
662d53cdfabSRobert Mustacchi 
663d53cdfabSRobert Mustacchi 	return (0);
664d53cdfabSRobert Mustacchi }
665d53cdfabSRobert Mustacchi 
666d53cdfabSRobert Mustacchi void
smbios_info_chassis_elts_free(smbios_hdl_t * shp,uint_t nents,smbios_chassis_entry_t * ent)667d53cdfabSRobert Mustacchi smbios_info_chassis_elts_free(smbios_hdl_t *shp, uint_t nents,
668d53cdfabSRobert Mustacchi     smbios_chassis_entry_t *ent)
669d53cdfabSRobert Mustacchi {
670d53cdfabSRobert Mustacchi 	size_t sz = nents * sizeof (smbios_chassis_entry_t);
671d53cdfabSRobert Mustacchi 
672d53cdfabSRobert Mustacchi 	if (nents == 0) {
673d53cdfabSRobert Mustacchi 		ASSERT3P(ent, ==, NULL);
674d53cdfabSRobert Mustacchi 		return;
675d53cdfabSRobert Mustacchi 	}
676d53cdfabSRobert Mustacchi 
677d53cdfabSRobert Mustacchi 	smb_free(ent, sz);
678d53cdfabSRobert Mustacchi }
679d53cdfabSRobert Mustacchi 
68084ab085aSmws int
smbios_info_processor(smbios_hdl_t * shp,id_t id,smbios_processor_t * pp)68184ab085aSmws smbios_info_processor(smbios_hdl_t *shp, id_t id, smbios_processor_t *pp)
68284ab085aSmws {
68384ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
68484ab085aSmws 	smb_processor_t p;
68584ab085aSmws 
68684ab085aSmws 	if (stp == NULL)
68784ab085aSmws 		return (-1); /* errno is set for us */
68884ab085aSmws 
68984ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR)
69084ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
69184ab085aSmws 
69284ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p));
6936734c4b0SRobert Mustacchi 	bzero(pp, sizeof (smb_base_processor_t));
69484ab085aSmws 
69584ab085aSmws 	pp->smbp_cpuid = p.smbpr_cpuid;
69684ab085aSmws 	pp->smbp_type = p.smbpr_type;
69784ab085aSmws 	pp->smbp_family = p.smbpr_family;
69884ab085aSmws 	pp->smbp_voltage = p.smbpr_voltage;
6991d1fc316SRobert Mustacchi 	pp->smbp_clkspeed = p.smbpr_clkspeed;
70084ab085aSmws 	pp->smbp_maxspeed = p.smbpr_maxspeed;
70184ab085aSmws 	pp->smbp_curspeed = p.smbpr_curspeed;
70284ab085aSmws 	pp->smbp_status = p.smbpr_status;
70384ab085aSmws 	pp->smbp_upgrade = p.smbpr_upgrade;
70484ab085aSmws 	pp->smbp_l1cache = p.smbpr_l1cache;
70584ab085aSmws 	pp->smbp_l2cache = p.smbpr_l2cache;
70684ab085aSmws 	pp->smbp_l3cache = p.smbpr_l3cache;
70784ab085aSmws 
708e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_25)) {
7094e901881SDale Ghent 		pp->smbp_corecount = p.smbpr_corecount;
7104e901881SDale Ghent 		pp->smbp_coresenabled = p.smbpr_coresenabled;
7114e901881SDale Ghent 		pp->smbp_threadcount = p.smbpr_threadcount;
7124e901881SDale Ghent 		pp->smbp_cflags = p.smbpr_cflags;
7134e901881SDale Ghent 	}
7144e901881SDale Ghent 
715e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_26)) {
716176a9270SRobert Mustacchi 		if (pp->smbp_family == 0xfe) {
717176a9270SRobert Mustacchi 			pp->smbp_family = p.smbpr_family2;
718176a9270SRobert Mustacchi 		}
719e5cce96fSRobert Mustacchi 	}
7204e901881SDale Ghent 
721e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_30)) {
722176a9270SRobert Mustacchi 		if (pp->smbp_corecount == 0xff) {
723176a9270SRobert Mustacchi 			pp->smbp_corecount = p.smbpr_corecount2;
724176a9270SRobert Mustacchi 		}
725176a9270SRobert Mustacchi 		if (pp->smbp_coresenabled == 0xff) {
726176a9270SRobert Mustacchi 			pp->smbp_coresenabled = p.smbpr_coresenabled2;
727176a9270SRobert Mustacchi 		}
728176a9270SRobert Mustacchi 		if (pp->smbp_threadcount == 0xff) {
729176a9270SRobert Mustacchi 			pp->smbp_threadcount = p.smbpr_threadcount2;
730176a9270SRobert Mustacchi 		}
7316734c4b0SRobert Mustacchi 	}
7326734c4b0SRobert Mustacchi 
7331d1fc316SRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_36)) {
7341d1fc316SRobert Mustacchi 		pp->smbp_threadsenabled = p.smpbr_threaden;
7351d1fc316SRobert Mustacchi 	}
7361d1fc316SRobert Mustacchi 
73784ab085aSmws 	return (0);
73884ab085aSmws }
73984ab085aSmws 
74084ab085aSmws int
smbios_info_cache(smbios_hdl_t * shp,id_t id,smbios_cache_t * cap)74184ab085aSmws smbios_info_cache(smbios_hdl_t *shp, id_t id, smbios_cache_t *cap)
74284ab085aSmws {
74384ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
74484ab085aSmws 	smb_cache_t c;
74584ab085aSmws 
74684ab085aSmws 	if (stp == NULL)
74784ab085aSmws 		return (-1); /* errno is set for us */
74884ab085aSmws 
74984ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_CACHE)
75084ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
75184ab085aSmws 
75284ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &c, sizeof (c));
753e5cce96fSRobert Mustacchi 	bzero(cap, sizeof (smb_base_cache_t));
75484ab085aSmws 
75584ab085aSmws 	cap->smba_maxsize = SMB_CACHE_SIZE(c.smbca_maxsize);
75684ab085aSmws 	cap->smba_size = SMB_CACHE_SIZE(c.smbca_size);
75784ab085aSmws 	cap->smba_stype = c.smbca_stype;
75884ab085aSmws 	cap->smba_ctype = c.smbca_ctype;
75984ab085aSmws 	cap->smba_speed = c.smbca_speed;
76084ab085aSmws 	cap->smba_etype = c.smbca_etype;
76184ab085aSmws 	cap->smba_ltype = c.smbca_ltype;
76284ab085aSmws 	cap->smba_assoc = c.smbca_assoc;
76384ab085aSmws 	cap->smba_level = SMB_CACHE_CFG_LEVEL(c.smbca_config);
76484ab085aSmws 	cap->smba_mode = SMB_CACHE_CFG_MODE(c.smbca_config);
76584ab085aSmws 	cap->smba_location = SMB_CACHE_CFG_LOCATION(c.smbca_config);
76684ab085aSmws 
76784ab085aSmws 	if (SMB_CACHE_CFG_ENABLED(c.smbca_config))
76884ab085aSmws 		cap->smba_flags |= SMB_CAF_ENABLED;
76984ab085aSmws 
77084ab085aSmws 	if (SMB_CACHE_CFG_SOCKETED(c.smbca_config))
77184ab085aSmws 		cap->smba_flags |= SMB_CAF_SOCKETED;
77284ab085aSmws 
773e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_31)) {
7741566bc34SRobert Mustacchi 		cap->smba_maxsize2 = SMB_CACHE_EXT_SIZE(c.smbca_maxsize2);
7751566bc34SRobert Mustacchi 		cap->smba_size2 = SMB_CACHE_EXT_SIZE(c.smbca_size2);
7761566bc34SRobert Mustacchi 
7771566bc34SRobert Mustacchi 		if (cap->smba_maxsize2 == 0) {
778e5cce96fSRobert Mustacchi 			cap->smba_maxsize2 = cap->smba_maxsize;
7791566bc34SRobert Mustacchi 		}
7801566bc34SRobert Mustacchi 
7811566bc34SRobert Mustacchi 		if (cap->smba_size2 == 0) {
782e5cce96fSRobert Mustacchi 			cap->smba_size2 = cap->smba_size;
783e5cce96fSRobert Mustacchi 		}
784e5cce96fSRobert Mustacchi 	}
785e5cce96fSRobert Mustacchi 
78684ab085aSmws 	return (0);
78784ab085aSmws }
78884ab085aSmws 
78984ab085aSmws int
smbios_info_port(smbios_hdl_t * shp,id_t id,smbios_port_t * pop)79084ab085aSmws smbios_info_port(smbios_hdl_t *shp, id_t id, smbios_port_t *pop)
79184ab085aSmws {
79284ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
79384ab085aSmws 	smb_port_t p;
79484ab085aSmws 
79584ab085aSmws 	if (stp == NULL)
79684ab085aSmws 		return (-1); /* errno is set for us */
79784ab085aSmws 
79884ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_PORT)
79984ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
80084ab085aSmws 
80184ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p));
80284ab085aSmws 	bzero(pop, sizeof (smbios_port_t));
80384ab085aSmws 
80484ab085aSmws 	pop->smbo_iref = smb_strptr(stp, p.smbpo_iref);
80584ab085aSmws 	pop->smbo_eref = smb_strptr(stp, p.smbpo_eref);
80684ab085aSmws 
80784ab085aSmws 	pop->smbo_itype = p.smbpo_itype;
80884ab085aSmws 	pop->smbo_etype = p.smbpo_etype;
80984ab085aSmws 	pop->smbo_ptype = p.smbpo_ptype;
81084ab085aSmws 
81184ab085aSmws 	return (0);
81284ab085aSmws }
81384ab085aSmws 
81484ab085aSmws int
smbios_info_slot(smbios_hdl_t * shp,id_t id,smbios_slot_t * sp)81584ab085aSmws smbios_info_slot(smbios_hdl_t *shp, id_t id, smbios_slot_t *sp)
81684ab085aSmws {
81784ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
81884ab085aSmws 	smb_slot_t s;
819c6795799SRobert Mustacchi 	smb_slot_cont_t cont;
820c6795799SRobert Mustacchi 	size_t off;
82184ab085aSmws 
82284ab085aSmws 	if (stp == NULL)
82384ab085aSmws 		return (-1); /* errno is set for us */
82484ab085aSmws 
82584ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT)
82684ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
82784ab085aSmws 
82884ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
8291566bc34SRobert Mustacchi 	bzero(sp, sizeof (smb_base_slot_t));
83084ab085aSmws 
83184ab085aSmws 	sp->smbl_name = smb_strptr(stp, s.smbsl_name);
83284ab085aSmws 	sp->smbl_type = s.smbsl_type;
83384ab085aSmws 	sp->smbl_width = s.smbsl_width;
83484ab085aSmws 	sp->smbl_usage = s.smbsl_usage;
83584ab085aSmws 	sp->smbl_length = s.smbsl_length;
83684ab085aSmws 	sp->smbl_id = s.smbsl_id;
83784ab085aSmws 	sp->smbl_ch1 = s.smbsl_ch1;
83884ab085aSmws 	sp->smbl_ch2 = s.smbsl_ch2;
83903f9f63dSTom Pothier 	sp->smbl_sg = s.smbsl_sg;
84003f9f63dSTom Pothier 	sp->smbl_bus = s.smbsl_bus;
84103f9f63dSTom Pothier 	sp->smbl_df = s.smbsl_df;
84203f9f63dSTom Pothier 
8431566bc34SRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_32)) {
8441566bc34SRobert Mustacchi 		sp->smbl_dbw = s.smbsl_dbw;
8451566bc34SRobert Mustacchi 		sp->smbl_npeers = s.smbsl_npeers;
8461566bc34SRobert Mustacchi 	}
8471566bc34SRobert Mustacchi 
848c6795799SRobert Mustacchi 	if (!smb_libgteq(shp, SMB_VERSION_34)) {
849c6795799SRobert Mustacchi 		return (0);
850c6795799SRobert Mustacchi 	}
851c6795799SRobert Mustacchi 
852c6795799SRobert Mustacchi 	/*
853c6795799SRobert Mustacchi 	 * In SMBIOS 3.4, several members were added to follow the variable
854c6795799SRobert Mustacchi 	 * number of peers. These are defined to start at byte 0x14 + 5 *
855c6795799SRobert Mustacchi 	 * npeers. If the table is from before 3.4, we simple zero things out.
856c6795799SRobert Mustacchi 	 * Otherwise we check if the length covers the peers and this addendum
857c6795799SRobert Mustacchi 	 * to include it as the table length is allowed to be less than this and
858c6795799SRobert Mustacchi 	 * not include it.
859c6795799SRobert Mustacchi 	 */
860c6795799SRobert Mustacchi 	off = SMB_SLOT_CONT_START + 5 * s.smbsl_npeers;
861c6795799SRobert Mustacchi 	smb_info_bcopy_offset(stp->smbst_hdr, &cont, sizeof (cont), off);
862c6795799SRobert Mustacchi 	sp->smbl_info = cont.smbsl_info;
863c6795799SRobert Mustacchi 	sp->smbl_pwidth = cont.smbsl_pwidth;
864c6795799SRobert Mustacchi 	sp->smbl_pitch = cont.smbsl_pitch;
865c6795799SRobert Mustacchi 
866d53cdfabSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_35)) {
867d53cdfabSRobert Mustacchi 		sp->smbl_height = cont.smbsl_height;
868d53cdfabSRobert Mustacchi 	}
869d53cdfabSRobert Mustacchi 
8701566bc34SRobert Mustacchi 	return (0);
8711566bc34SRobert Mustacchi }
8721566bc34SRobert Mustacchi 
8731566bc34SRobert Mustacchi void
smbios_info_slot_peers_free(smbios_hdl_t * shp,uint_t npeers,smbios_slot_peer_t * peer)8741566bc34SRobert Mustacchi smbios_info_slot_peers_free(smbios_hdl_t *shp, uint_t npeers,
8751566bc34SRobert Mustacchi     smbios_slot_peer_t *peer)
8761566bc34SRobert Mustacchi {
8771566bc34SRobert Mustacchi 	size_t sz = npeers * sizeof (smbios_slot_peer_t);
8781566bc34SRobert Mustacchi 
8791566bc34SRobert Mustacchi 	if (npeers == 0) {
8801566bc34SRobert Mustacchi 		ASSERT3P(peer, ==, NULL);
8811566bc34SRobert Mustacchi 		return;
8821566bc34SRobert Mustacchi 	}
8831566bc34SRobert Mustacchi 
8841566bc34SRobert Mustacchi 	smb_free(peer, sz);
8851566bc34SRobert Mustacchi }
8861566bc34SRobert Mustacchi 
8871566bc34SRobert Mustacchi int
smbios_info_slot_peers(smbios_hdl_t * shp,id_t id,uint_t * npeers,smbios_slot_peer_t ** peerp)8881566bc34SRobert Mustacchi smbios_info_slot_peers(smbios_hdl_t *shp, id_t id, uint_t *npeers,
8891566bc34SRobert Mustacchi     smbios_slot_peer_t **peerp)
8901566bc34SRobert Mustacchi {
8911566bc34SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
89216dde076SJohn Levon 	const smb_slot_t *slotp;
8931566bc34SRobert Mustacchi 	smbios_slot_peer_t *peer;
8941566bc34SRobert Mustacchi 	size_t minlen;
8951566bc34SRobert Mustacchi 	uint_t i;
8961566bc34SRobert Mustacchi 
8971566bc34SRobert Mustacchi 	if (stp == NULL)
8981566bc34SRobert Mustacchi 		return (-1); /* errno is set for us */
8991566bc34SRobert Mustacchi 
90016dde076SJohn Levon 	slotp = (const smb_slot_t *)stp->smbst_hdr;
90116dde076SJohn Levon 
9021566bc34SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT)
9031566bc34SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
9041566bc34SRobert Mustacchi 
9051566bc34SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len <= offsetof(smb_slot_t, smbsl_npeers) ||
9061566bc34SRobert Mustacchi 	    slotp->smbsl_npeers == 0) {
9071566bc34SRobert Mustacchi 		*npeers = 0;
9081566bc34SRobert Mustacchi 		*peerp = NULL;
9091566bc34SRobert Mustacchi 		return (0);
9101566bc34SRobert Mustacchi 	}
9111566bc34SRobert Mustacchi 
9121566bc34SRobert Mustacchi 	/*
9131566bc34SRobert Mustacchi 	 * Make sure that the size of the structure makes sense for the number
9141566bc34SRobert Mustacchi 	 * of peers reported.
9151566bc34SRobert Mustacchi 	 */
9161566bc34SRobert Mustacchi 	minlen = slotp->smbsl_npeers * sizeof (smb_slot_peer_t) +
9171566bc34SRobert Mustacchi 	    offsetof(smb_slot_t, smbsl_npeers);
9181566bc34SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < minlen) {
9191566bc34SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
9201566bc34SRobert Mustacchi 	}
9211566bc34SRobert Mustacchi 
9221566bc34SRobert Mustacchi 	if ((peer = smb_alloc(slotp->smbsl_npeers *
9231566bc34SRobert Mustacchi 	    sizeof (smbios_slot_peer_t))) == NULL) {
9241566bc34SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_NOMEM));
9251566bc34SRobert Mustacchi 	}
9261566bc34SRobert Mustacchi 
9271566bc34SRobert Mustacchi 	for (i = 0; i < slotp->smbsl_npeers; i++) {
9281566bc34SRobert Mustacchi 		peer[i].smblp_group = slotp->smbsl_peers[i].smbspb_group_no;
9291566bc34SRobert Mustacchi 		peer[i].smblp_bus = slotp->smbsl_peers[i].smbspb_bus;
9301566bc34SRobert Mustacchi 		peer[i].smblp_device = slotp->smbsl_peers[i].smbspb_df >> 3;
9311566bc34SRobert Mustacchi 		peer[i].smblp_function = slotp->smbsl_peers[i].smbspb_df & 0x7;
9321566bc34SRobert Mustacchi 		peer[i].smblp_data_width = slotp->smbsl_peers[i].smbspb_width;
9331566bc34SRobert Mustacchi 	}
9341566bc34SRobert Mustacchi 
9351566bc34SRobert Mustacchi 	*npeers = slotp->smbsl_npeers;
9361566bc34SRobert Mustacchi 	*peerp = peer;
9371566bc34SRobert Mustacchi 
93803f9f63dSTom Pothier 	return (0);
93903f9f63dSTom Pothier }
94003f9f63dSTom Pothier 
94103f9f63dSTom Pothier int
smbios_info_obdevs_ext(smbios_hdl_t * shp,id_t id,smbios_obdev_ext_t * oep)94203f9f63dSTom Pothier smbios_info_obdevs_ext(smbios_hdl_t *shp, id_t id, smbios_obdev_ext_t *oep)
94303f9f63dSTom Pothier {
94403f9f63dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
94503f9f63dSTom Pothier 	smb_obdev_ext_t obe;
94603f9f63dSTom Pothier 
94703f9f63dSTom Pothier 	if (stp == NULL)
94803f9f63dSTom Pothier 		return (-1); /* errno is set for us */
94903f9f63dSTom Pothier 
95003f9f63dSTom Pothier 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVEXT)
95103f9f63dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
95203f9f63dSTom Pothier 
95303f9f63dSTom Pothier 	smb_info_bcopy(stp->smbst_hdr, &obe, sizeof (obe));
95403f9f63dSTom Pothier 	bzero(oep, sizeof (smbios_obdev_ext_t));
95503f9f63dSTom Pothier 
95603f9f63dSTom Pothier 	oep->smboe_name = smb_strptr(stp, obe.smbobe_name);
95703f9f63dSTom Pothier 	oep->smboe_dtype = obe.smbobe_dtype;
95803f9f63dSTom Pothier 	oep->smboe_dti = obe.smbobe_dti;
95903f9f63dSTom Pothier 	oep->smboe_sg = obe.smbobe_sg;
96003f9f63dSTom Pothier 	oep->smboe_bus = obe.smbobe_bus;
96103f9f63dSTom Pothier 	oep->smboe_df = obe.smbobe_df;
96284ab085aSmws 
96384ab085aSmws 	return (0);
96484ab085aSmws }
96584ab085aSmws 
96684ab085aSmws int
smbios_info_obdevs(smbios_hdl_t * shp,id_t id,int obc,smbios_obdev_t * obp)96784ab085aSmws smbios_info_obdevs(smbios_hdl_t *shp, id_t id, int obc, smbios_obdev_t *obp)
96884ab085aSmws {
96984ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
97084ab085aSmws 	const smb_obdev_t *op;
97184ab085aSmws 	int i, m, n;
97284ab085aSmws 
97384ab085aSmws 	if (stp == NULL)
97484ab085aSmws 		return (-1); /* errno is set for us */
97584ab085aSmws 
97684ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVS)
97784ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
97884ab085aSmws 
97984ab085aSmws 	op = (smb_obdev_t *)((uintptr_t)stp->smbst_hdr + sizeof (smb_header_t));
98084ab085aSmws 	m = (stp->smbst_hdr->smbh_len - sizeof (smb_header_t)) / sizeof (*op);
98184ab085aSmws 	n = MIN(m, obc);
98284ab085aSmws 
98384ab085aSmws 	for (i = 0; i < n; i++, op++, obp++) {
98484ab085aSmws 		obp->smbd_name = smb_strptr(stp, op->smbob_name);
98584ab085aSmws 		obp->smbd_type = op->smbob_type & ~SMB_OBT_ENABLED;
98684ab085aSmws 		obp->smbd_enabled = (op->smbob_type & SMB_OBT_ENABLED) != 0;
98784ab085aSmws 	}
98884ab085aSmws 
98984ab085aSmws 	return (m);
99084ab085aSmws }
99184ab085aSmws 
99284ab085aSmws /*
99384ab085aSmws  * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the
99484ab085aSmws  * first byte to indicate the size of a string table at the end of the record.
99584ab085aSmws  * Therefore, smbios_info_strtab() can be used to retrieve the table size and
99684ab085aSmws  * strings for any of these underlying record types.
99784ab085aSmws  */
99884ab085aSmws int
smbios_info_strtab(smbios_hdl_t * shp,id_t id,int argc,const char * argv[])99984ab085aSmws smbios_info_strtab(smbios_hdl_t *shp, id_t id, int argc, const char *argv[])
100084ab085aSmws {
100184ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
100284ab085aSmws 	smb_strtab_t s;
100384ab085aSmws 	int i, n;
100484ab085aSmws 
100584ab085aSmws 	if (stp == NULL)
100684ab085aSmws 		return (-1); /* errno is set for us */
100784ab085aSmws 
100884ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR &&
100984ab085aSmws 	    stp->smbst_hdr->smbh_type != SMB_TYPE_SYSCONFSTR &&
101084ab085aSmws 	    stp->smbst_hdr->smbh_type != SMB_TYPE_LANG)
101184ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
101284ab085aSmws 
101384ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
101484ab085aSmws 	n = MIN(s.smbtb_count, argc);
101584ab085aSmws 
101684ab085aSmws 	for (i = 0; i < n; i++)
101784ab085aSmws 		argv[i] = smb_strptr(stp, i + 1);
101884ab085aSmws 
101984ab085aSmws 	return (s.smbtb_count);
102084ab085aSmws }
102184ab085aSmws 
102284ab085aSmws id_t
smbios_info_lang(smbios_hdl_t * shp,smbios_lang_t * lp)102384ab085aSmws smbios_info_lang(smbios_hdl_t *shp, smbios_lang_t *lp)
102484ab085aSmws {
102584ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_LANG);
102684ab085aSmws 	smb_lang_t l;
102784ab085aSmws 
102884ab085aSmws 	if (stp == NULL)
102984ab085aSmws 		return (-1); /* errno is set for us */
103084ab085aSmws 
103184ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &l, sizeof (l));
103284ab085aSmws 	bzero(lp, sizeof (smbios_lang_t));
103384ab085aSmws 
103484ab085aSmws 	lp->smbla_cur = smb_strptr(stp, l.smblang_cur);
103584ab085aSmws 	lp->smbla_fmt = l.smblang_flags & 1;
103684ab085aSmws 	lp->smbla_num = l.smblang_num;
103784ab085aSmws 
103884ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
103984ab085aSmws }
104084ab085aSmws 
104184ab085aSmws id_t
smbios_info_eventlog(smbios_hdl_t * shp,smbios_evlog_t * evp)104284ab085aSmws smbios_info_eventlog(smbios_hdl_t *shp, smbios_evlog_t *evp)
104384ab085aSmws {
104484ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_EVENTLOG);
104584ab085aSmws 	const smb_sel_t *sel;
104684ab085aSmws 	size_t len;
104784ab085aSmws 
104884ab085aSmws 	if (stp == NULL)
104984ab085aSmws 		return (-1); /* errno is set for us */
105084ab085aSmws 
105184ab085aSmws 	if (stp->smbst_hdr->smbh_len < sizeof (smb_sel_t) - sizeof (uint8_t))
105284ab085aSmws 		return (smb_set_errno(shp, ESMB_CORRUPT));
105384ab085aSmws 
105484ab085aSmws 	sel = (smb_sel_t *)(uintptr_t)stp->smbst_hdr;
105584ab085aSmws 	len = stp->smbst_hdr->smbh_len - sizeof (smb_sel_t) + sizeof (uint8_t);
105684ab085aSmws 	bzero(evp, sizeof (smbios_evlog_t));
105784ab085aSmws 
105884ab085aSmws 	if (len < sel->smbsel_typec * sel->smbsel_typesz)
105984ab085aSmws 		return (smb_set_errno(shp, ESMB_CORRUPT));
106084ab085aSmws 
106184ab085aSmws 	evp->smbev_size = sel->smbsel_len;
106284ab085aSmws 	evp->smbev_hdr = sel->smbsel_hdroff;
106384ab085aSmws 	evp->smbev_data = sel->smbsel_dataoff;
106484ab085aSmws 	evp->smbev_method = sel->smbsel_method;
106584ab085aSmws 	evp->smbev_flags = sel->smbsel_status;
106684ab085aSmws 	evp->smbev_format = sel->smbsel_format;
106784ab085aSmws 	evp->smbev_token = sel->smbsel_token;
106884ab085aSmws 	evp->smbev_addr.eva_addr = sel->smbsel_addr;
106984ab085aSmws 
107084ab085aSmws 	if (sel->smbsel_typesz == sizeof (smbios_evtype_t)) {
107184ab085aSmws 		evp->smbev_typec = sel->smbsel_typec;
107284ab085aSmws 		evp->smbev_typev = (void *)(uintptr_t)sel->smbsel_typev;
107384ab085aSmws 	}
107484ab085aSmws 
107584ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
107684ab085aSmws }
107784ab085aSmws 
107884ab085aSmws int
smbios_info_memarray(smbios_hdl_t * shp,id_t id,smbios_memarray_t * map)107984ab085aSmws smbios_info_memarray(smbios_hdl_t *shp, id_t id, smbios_memarray_t *map)
108084ab085aSmws {
108184ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
108284ab085aSmws 	smb_memarray_t m;
108384ab085aSmws 
108484ab085aSmws 	if (stp == NULL)
108584ab085aSmws 		return (-1); /* errno is set for us */
108684ab085aSmws 
108784ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAY)
108884ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
108984ab085aSmws 
109084ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
109184ab085aSmws 	bzero(map, sizeof (smbios_memarray_t));
109284ab085aSmws 
109384ab085aSmws 	map->smbma_location = m.smbmarr_loc;
109484ab085aSmws 	map->smbma_use = m.smbmarr_use;
109584ab085aSmws 	map->smbma_ecc = m.smbmarr_ecc;
109684ab085aSmws 	map->smbma_ndevs = m.smbmarr_ndevs;
109784ab085aSmws 	map->smbma_err = m.smbmarr_err;
109884ab085aSmws 
109984ab085aSmws 	if (m.smbmarr_cap != 0x80000000)
110084ab085aSmws 		map->smbma_size = (uint64_t)m.smbmarr_cap * 1024;
11014e901881SDale Ghent 	else if (m.smbmarr_extcap != 0)
11024e901881SDale Ghent 		map->smbma_size = m.smbmarr_extcap;
110384ab085aSmws 	else
110484ab085aSmws 		map->smbma_size = 0; /* unknown */
110584ab085aSmws 
110684ab085aSmws 	return (0);
110784ab085aSmws }
110884ab085aSmws 
110984ab085aSmws int
smbios_info_memarrmap(smbios_hdl_t * shp,id_t id,smbios_memarrmap_t * map)111084ab085aSmws smbios_info_memarrmap(smbios_hdl_t *shp, id_t id, smbios_memarrmap_t *map)
111184ab085aSmws {
111284ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
111384ab085aSmws 	smb_memarrmap_t m;
111484ab085aSmws 
111584ab085aSmws 	if (stp == NULL)
111684ab085aSmws 		return (-1); /* errno is set for us */
111784ab085aSmws 
111884ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAYMAP)
111984ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
112084ab085aSmws 
112184ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
112284ab085aSmws 	bzero(map, sizeof (smbios_memarrmap_t));
112384ab085aSmws 
112484ab085aSmws 	map->smbmam_array = m.smbamap_array;
112584ab085aSmws 	map->smbmam_width = m.smbamap_width;
11264e901881SDale Ghent 
11274e901881SDale Ghent 	if (m.smbamap_start != 0xFFFFFFFF && m.smbamap_end != 0xFFFFFFFF) {
11284e901881SDale Ghent 		map->smbmam_addr = (uint64_t)m.smbamap_start * 1024;
11294e901881SDale Ghent 		map->smbmam_size = (uint64_t)
11304e901881SDale Ghent 		    (m.smbamap_end - m.smbamap_start + 1) * 1024;
11314e901881SDale Ghent 	} else if (m.smbamap_extstart != 0 && m.smbamap_extend != 0) {
11324e901881SDale Ghent 		map->smbmam_addr = m.smbamap_extstart;
11334e901881SDale Ghent 		map->smbmam_size = m.smbamap_extend - m.smbamap_extstart + 1;
11344e901881SDale Ghent 	}
113584ab085aSmws 
113684ab085aSmws 	return (0);
113784ab085aSmws }
113884ab085aSmws 
113984ab085aSmws int
smbios_info_memdevice(smbios_hdl_t * shp,id_t id,smbios_memdevice_t * mdp)114084ab085aSmws smbios_info_memdevice(smbios_hdl_t *shp, id_t id, smbios_memdevice_t *mdp)
114184ab085aSmws {
114284ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
114384ab085aSmws 	smb_memdevice_t m;
114484ab085aSmws 
114584ab085aSmws 	if (stp == NULL)
114684ab085aSmws 		return (-1); /* errno is set for us */
114784ab085aSmws 
114884ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICE)
114984ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
115084ab085aSmws 
115184ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
11526734c4b0SRobert Mustacchi 	bzero(mdp, sizeof (smb_base_memdevice_t));
115384ab085aSmws 
115484ab085aSmws 	mdp->smbmd_array = m.smbmdev_array;
115584ab085aSmws 	mdp->smbmd_error = m.smbmdev_error;
115684ab085aSmws 	mdp->smbmd_twidth = m.smbmdev_twidth == 0xFFFF ? -1U : m.smbmdev_twidth;
115784ab085aSmws 	mdp->smbmd_dwidth = m.smbmdev_dwidth == 0xFFFF ? -1U : m.smbmdev_dwidth;
115884ab085aSmws 
11594e901881SDale Ghent 	if (m.smbmdev_size == 0x7FFF) {
11604e901881SDale Ghent 		mdp->smbmd_size = (uint64_t)m.smbmdev_extsize;
11614e901881SDale Ghent 		mdp->smbmd_size *= 1024 * 1024; /* convert MB to bytes */
11624e901881SDale Ghent 	} else if (m.smbmdev_size != 0xFFFF) {
116384ab085aSmws 		mdp->smbmd_size = (uint64_t)(m.smbmdev_size & ~SMB_MDS_KBYTES);
116484ab085aSmws 		if (m.smbmdev_size & SMB_MDS_KBYTES)
116584ab085aSmws 			mdp->smbmd_size *= 1024;
116684ab085aSmws 		else
116784ab085aSmws 			mdp->smbmd_size *= 1024 * 1024;
116884ab085aSmws 	} else
116984ab085aSmws 		mdp->smbmd_size = -1ULL; /* size unknown */
117084ab085aSmws 
117184ab085aSmws 	mdp->smbmd_form = m.smbmdev_form;
117284ab085aSmws 	mdp->smbmd_set = m.smbmdev_set;
117384ab085aSmws 	mdp->smbmd_type = m.smbmdev_type;
11744e901881SDale Ghent 	mdp->smbmd_speed = m.smbmdev_speed;
117584ab085aSmws 	mdp->smbmd_flags = m.smbmdev_flags;
117684ab085aSmws 	mdp->smbmd_dloc = smb_strptr(stp, m.smbmdev_dloc);
117784ab085aSmws 	mdp->smbmd_bloc = smb_strptr(stp, m.smbmdev_bloc);
117884ab085aSmws 
1179e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_26)) {
11804e901881SDale Ghent 		mdp->smbmd_rank = m.smbmdev_attrs & 0x0F;
1181e5cce96fSRobert Mustacchi 	}
11824e901881SDale Ghent 
1183e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_27)) {
11844e901881SDale Ghent 		mdp->smbmd_clkspeed = m.smbmdev_clkspeed;
1185e5cce96fSRobert Mustacchi 	}
11864e901881SDale Ghent 
1187e5cce96fSRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_28)) {
11884e901881SDale Ghent 		mdp->smbmd_minvolt = m.smbmdev_minvolt;
11894e901881SDale Ghent 		mdp->smbmd_maxvolt = m.smbmdev_maxvolt;
11904e901881SDale Ghent 		mdp->smbmd_confvolt = m.smbmdev_confvolt;
11914e901881SDale Ghent 	}
119284ab085aSmws 
11931566bc34SRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_32)) {
11941566bc34SRobert Mustacchi 		mdp->smbmd_memtech = m.smbmdev_memtech;
11951566bc34SRobert Mustacchi 		mdp->smbmd_opcap_flags = m.smbmdev_opmode;
11961566bc34SRobert Mustacchi 		mdp->smbmd_firmware_rev = smb_strptr(stp,
11971566bc34SRobert Mustacchi 		    m.smbmdev_fwver);
11981566bc34SRobert Mustacchi 		mdp->smbmd_modmfg_id = m.smbmdev_modulemfgid;
11991566bc34SRobert Mustacchi 		mdp->smbmd_modprod_id = m.smbmdev_moduleprodid;
12001566bc34SRobert Mustacchi 		mdp->smbmd_cntrlmfg_id = m.smbmdev_memsysmfgid;
12011566bc34SRobert Mustacchi 		mdp->smbmd_cntrlprod_id = m.smbmdev_memsysprodid;
12021566bc34SRobert Mustacchi 		mdp->smbmd_nvsize = m.smbmdev_nvsize;
12031566bc34SRobert Mustacchi 		mdp->smbmd_volatile_size = m.smbmdev_volsize;
12041566bc34SRobert Mustacchi 		mdp->smbmd_cache_size = m.smbmdev_cachesize;
12051566bc34SRobert Mustacchi 		mdp->smbmd_logical_size = m.smbmdev_logicalsize;
12061566bc34SRobert Mustacchi 	}
12071566bc34SRobert Mustacchi 
1208176a9270SRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_33)) {
1209176a9270SRobert Mustacchi 		if (m.smbmdev_speed == 0xffff) {
1210176a9270SRobert Mustacchi 			mdp->smbmd_extspeed = m.smbmdev_extspeed;
1211176a9270SRobert Mustacchi 		} else {
1212176a9270SRobert Mustacchi 			mdp->smbmd_extspeed = m.smbmdev_speed;
1213176a9270SRobert Mustacchi 		}
1214176a9270SRobert Mustacchi 
1215176a9270SRobert Mustacchi 		if (m.smbmdev_clkspeed == 0xffff) {
1216176a9270SRobert Mustacchi 			mdp->smbmd_extclkspeed = m.smbmdev_extclkspeed;
1217176a9270SRobert Mustacchi 		} else {
1218176a9270SRobert Mustacchi 			mdp->smbmd_extclkspeed = m.smbmdev_clkspeed;
1219176a9270SRobert Mustacchi 		}
1220176a9270SRobert Mustacchi 	}
1221176a9270SRobert Mustacchi 
12226bc074b1SRobert Mustacchi 	/*
12236bc074b1SRobert Mustacchi 	 * The unknown key for missing revision information for the RCD and
12246bc074b1SRobert Mustacchi 	 * PMIC0 is not all zeros. As such, we need to look if the device SMBIOS
12256bc074b1SRobert Mustacchi 	 * table is not 3.7 then we need to fix up the bits that we copied.
12266bc074b1SRobert Mustacchi 	 * After that we need to go back and check the consumer's version to
12276bc074b1SRobert Mustacchi 	 * actually place this data there.
12286bc074b1SRobert Mustacchi 	 */
12296bc074b1SRobert Mustacchi 	if (!smb_gteq(shp, SMB_VERSION_37)) {
12306bc074b1SRobert Mustacchi 		m.smbmdev_pmic0mfgid = SMB_MD_MFG_UNKNOWN;
12316bc074b1SRobert Mustacchi 		m.smbmdev_pmic0rev = SMB_MD_REV_UNKNOWN;
12326bc074b1SRobert Mustacchi 		m.smbmdev_rcdmfgid = SMB_MD_MFG_UNKNOWN;
12336bc074b1SRobert Mustacchi 		m.smbmdev_rcdrev = SMB_MD_REV_UNKNOWN;
12346bc074b1SRobert Mustacchi 	}
12356bc074b1SRobert Mustacchi 
12366bc074b1SRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_37)) {
12376bc074b1SRobert Mustacchi 		mdp->smbmd_pmic0_mfgid = m.smbmdev_pmic0mfgid;
12386bc074b1SRobert Mustacchi 		mdp->smbmd_pmic0_rev = m.smbmdev_pmic0rev;
12396bc074b1SRobert Mustacchi 		mdp->smbmd_rcd_mfgid = m.smbmdev_rcdmfgid;
12406bc074b1SRobert Mustacchi 		mdp->smbmd_rcd_rev = m.smbmdev_rcdrev;
12416bc074b1SRobert Mustacchi 	}
12426bc074b1SRobert Mustacchi 
124384ab085aSmws 	return (0);
124484ab085aSmws }
124584ab085aSmws 
124684ab085aSmws int
smbios_info_memdevmap(smbios_hdl_t * shp,id_t id,smbios_memdevmap_t * mdp)124784ab085aSmws smbios_info_memdevmap(smbios_hdl_t *shp, id_t id, smbios_memdevmap_t *mdp)
124884ab085aSmws {
124984ab085aSmws 	const smb_struct_t *stp = smb_lookup_id(shp, id);
125084ab085aSmws 	smb_memdevmap_t m;
125184ab085aSmws 
125284ab085aSmws 	if (stp == NULL)
125384ab085aSmws 		return (-1); /* errno is set for us */
125484ab085aSmws 
125584ab085aSmws 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICEMAP)
125684ab085aSmws 		return (smb_set_errno(shp, ESMB_TYPE));
125784ab085aSmws 
125884ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
125984ab085aSmws 	bzero(mdp, sizeof (smbios_memdevmap_t));
126084ab085aSmws 
126184ab085aSmws 	mdp->smbmdm_device = m.smbdmap_device;
126284ab085aSmws 	mdp->smbmdm_arrmap = m.smbdmap_array;
126384ab085aSmws 	mdp->smbmdm_rpos = m.smbdmap_rpos;
126484ab085aSmws 	mdp->smbmdm_ipos = m.smbdmap_ipos;
126584ab085aSmws 	mdp->smbmdm_idepth = m.smbdmap_idepth;
126684ab085aSmws 
12674e901881SDale Ghent 	if (m.smbdmap_start != 0xFFFFFFFF && m.smbdmap_end != 0xFFFFFFFF) {
12684e901881SDale Ghent 		mdp->smbmdm_addr = (uint64_t)m.smbdmap_start * 1024;
12694e901881SDale Ghent 		mdp->smbmdm_size = (uint64_t)
12704e901881SDale Ghent 		    (m.smbdmap_end - m.smbdmap_start + 1) * 1024;
12714e901881SDale Ghent 	} else if (m.smbdmap_extstart != 0 && m.smbdmap_extend != 0) {
12724e901881SDale Ghent 		mdp->smbmdm_addr = m.smbdmap_extstart;
12734e901881SDale Ghent 		mdp->smbmdm_size = m.smbdmap_extend - m.smbdmap_extstart + 1;
12744e901881SDale Ghent 	}
12754e901881SDale Ghent 
127684ab085aSmws 	return (0);
127784ab085aSmws }
127884ab085aSmws 
127984ab085aSmws id_t
smbios_info_hwsec(smbios_hdl_t * shp,smbios_hwsec_t * hsp)128084ab085aSmws smbios_info_hwsec(smbios_hdl_t *shp, smbios_hwsec_t *hsp)
128184ab085aSmws {
128284ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SECURITY);
128384ab085aSmws 	smb_hwsec_t hs;
128484ab085aSmws 
128584ab085aSmws 	if (stp == NULL)
128684ab085aSmws 		return (-1); /* errno is set for us */
128784ab085aSmws 
128884ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &hs, sizeof (hs));
128984ab085aSmws 	bzero(hsp, sizeof (smbios_hwsec_t));
129084ab085aSmws 
129184ab085aSmws 	hsp->smbh_pwr_ps = SMB_HWS_PWR_PS(hs.smbhs_settings);
129284ab085aSmws 	hsp->smbh_kbd_ps = SMB_HWS_KBD_PS(hs.smbhs_settings);
129384ab085aSmws 	hsp->smbh_adm_ps = SMB_HWS_ADM_PS(hs.smbhs_settings);
129484ab085aSmws 	hsp->smbh_pan_ps = SMB_HWS_PAN_PS(hs.smbhs_settings);
129584ab085aSmws 
129684ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
129784ab085aSmws }
129884ab085aSmws 
129984ab085aSmws id_t
smbios_info_boot(smbios_hdl_t * shp,smbios_boot_t * bp)130084ab085aSmws smbios_info_boot(smbios_hdl_t *shp, smbios_boot_t *bp)
130184ab085aSmws {
130284ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BOOT);
13030b427924SJohn Levon 	const smb_boot_t *b;
130484ab085aSmws 
130584ab085aSmws 	if (stp == NULL)
130684ab085aSmws 		return (-1); /* errno is set for us */
130784ab085aSmws 
130884ab085aSmws 	bzero(bp, sizeof (smbios_boot_t));
130984ab085aSmws 
13100b427924SJohn Levon 	b = (smb_boot_t *)(uintptr_t)stp->smbst_hdr;
13110b427924SJohn Levon 
131284ab085aSmws 	bp->smbt_status = b->smbbo_status[0];
131384ab085aSmws 	bp->smbt_size = stp->smbst_hdr->smbh_len - sizeof (smb_boot_t);
131484ab085aSmws 	bp->smbt_data = bp->smbt_size ? &b->smbbo_status[1] : NULL;
131584ab085aSmws 
131684ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
131784ab085aSmws }
131884ab085aSmws 
131984ab085aSmws id_t
smbios_info_ipmi(smbios_hdl_t * shp,smbios_ipmi_t * ip)132084ab085aSmws smbios_info_ipmi(smbios_hdl_t *shp, smbios_ipmi_t *ip)
132184ab085aSmws {
132284ab085aSmws 	const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_IPMIDEV);
132384ab085aSmws 	smb_ipmi_t i;
132484ab085aSmws 
132584ab085aSmws 	if (stp == NULL)
132684ab085aSmws 		return (-1); /* errno is set for us */
132784ab085aSmws 
132884ab085aSmws 	smb_info_bcopy(stp->smbst_hdr, &i, sizeof (i));
132984ab085aSmws 	bzero(ip, sizeof (smbios_ipmi_t));
133084ab085aSmws 
133184ab085aSmws 	ip->smbip_type = i.smbipm_type;
133284ab085aSmws 	ip->smbip_vers.smbv_major = SMB_IPM_SPEC_MAJOR(i.smbipm_spec);
133384ab085aSmws 	ip->smbip_vers.smbv_minor = SMB_IPM_SPEC_MINOR(i.smbipm_spec);
133484ab085aSmws 	ip->smbip_i2c = i.smbipm_i2c;
133584ab085aSmws 	ip->smbip_addr = i.smbipm_addr & ~SMB_IPM_ADDR_IO;
133684ab085aSmws 	ip->smbip_intr = i.smbipm_intr;
133784ab085aSmws 
133884ab085aSmws 	if (i.smbipm_bus != (uint8_t)-1)
133984ab085aSmws 		ip->smbip_bus = i.smbipm_bus;
134084ab085aSmws 	else
134184ab085aSmws 		ip->smbip_bus = -1u;
134284ab085aSmws 
134384ab085aSmws 	if (SMB_IPM_INFO_LSB(i.smbipm_info))
134484ab085aSmws 		ip->smbip_addr |= 1; /* turn on least-significant bit of addr */
134584ab085aSmws 
134684ab085aSmws 	if (i.smbipm_addr & SMB_IPM_ADDR_IO) {
134784ab085aSmws 		switch (SMB_IPM_INFO_REGS(i.smbipm_info)) {
134884ab085aSmws 		case SMB_IPM_REGS_1B:
134984ab085aSmws 			ip->smbip_regspacing = 1;
135084ab085aSmws 			break;
135184ab085aSmws 		case SMB_IPM_REGS_4B:
135284ab085aSmws 			ip->smbip_regspacing = 4;
135384ab085aSmws 			break;
135484ab085aSmws 		case SMB_IPM_REGS_16B:
135584ab085aSmws 			ip->smbip_regspacing = 16;
135684ab085aSmws 			break;
135784ab085aSmws 		default:
135884ab085aSmws 			ip->smbip_regspacing = 1;
135984ab085aSmws 		}
136084ab085aSmws 		ip->smbip_flags |= SMB_IPMI_F_IOADDR;
136184ab085aSmws 	}
136284ab085aSmws 
136384ab085aSmws 	if (SMB_IPM_INFO_ISPEC(i.smbipm_info))
136484ab085aSmws 		ip->smbip_flags |= SMB_IPMI_F_INTRSPEC;
136584ab085aSmws 
136684ab085aSmws 	if (SMB_IPM_INFO_IPOL(i.smbipm_info) == SMB_IPM_IPOL_HI)
136784ab085aSmws 		ip->smbip_flags |= SMB_IPMI_F_INTRHIGH;
136884ab085aSmws 
136984ab085aSmws 	if (SMB_IPM_INFO_IMODE(i.smbipm_info) == SMB_IPM_IMODE_EDGE)
137084ab085aSmws 		ip->smbip_flags |= SMB_IPMI_F_INTREDGE;
137184ab085aSmws 
137284ab085aSmws 	return (stp->smbst_hdr->smbh_hdl);
137384ab085aSmws }
13749c94f155SCheng Sean Ye 
13759c94f155SCheng Sean Ye static boolean_t
smbios_has_oemstr(smbios_hdl_t * shp,const char * oemstr)13769c94f155SCheng Sean Ye smbios_has_oemstr(smbios_hdl_t *shp, const char *oemstr)
13779c94f155SCheng Sean Ye {
13789c94f155SCheng Sean Ye 	const smb_struct_t *stp = shp->sh_structs;
13799c94f155SCheng Sean Ye 	smb_strtab_t s;
13809c94f155SCheng Sean Ye 	int i, j;
13819c94f155SCheng Sean Ye 
13829c94f155SCheng Sean Ye 	for (i = 0; i < shp->sh_nstructs; i++, stp++) {
13839c94f155SCheng Sean Ye 		if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR)
13849c94f155SCheng Sean Ye 			continue;
13859c94f155SCheng Sean Ye 
13869c94f155SCheng Sean Ye 		smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
13879c94f155SCheng Sean Ye 		for (j = 0; j < s.smbtb_count; j++)
13889c94f155SCheng Sean Ye 			if (strcmp(smb_strptr(stp, j + 1), oemstr) == 0)
13899c94f155SCheng Sean Ye 				return (B_TRUE);
13909c94f155SCheng Sean Ye 	}
13919c94f155SCheng Sean Ye 
13929c94f155SCheng Sean Ye 	return (B_FALSE);
13939c94f155SCheng Sean Ye }
13949c94f155SCheng Sean Ye 
13959c94f155SCheng Sean Ye static const char *
smb_serial_valid(const char * serial)13969c94f155SCheng Sean Ye smb_serial_valid(const char *serial)
13979c94f155SCheng Sean Ye {
13989c94f155SCheng Sean Ye 	char buf[MAXNAMELEN];
13999c94f155SCheng Sean Ye 	int i = 0;
14009c94f155SCheng Sean Ye 
14019c94f155SCheng Sean Ye 	if (serial == NULL)
14029c94f155SCheng Sean Ye 		return (NULL);
14039c94f155SCheng Sean Ye 
14049c94f155SCheng Sean Ye 	(void) strlcpy(buf, serial, sizeof (buf));
14059c94f155SCheng Sean Ye 
14069c94f155SCheng Sean Ye 	while (buf[i] != '\0' && buf[i] == ' ')
14079c94f155SCheng Sean Ye 		i++;
14089c94f155SCheng Sean Ye 
14099c94f155SCheng Sean Ye 	if (buf[i] == '\0' || strstr(buf, SMB_DEFAULT1) != NULL ||
14109c94f155SCheng Sean Ye 	    strstr(buf, SMB_DEFAULT2) != NULL)
14119c94f155SCheng Sean Ye 		return (NULL);
14129c94f155SCheng Sean Ye 
14139c94f155SCheng Sean Ye 	return (serial);
14149c94f155SCheng Sean Ye }
14159c94f155SCheng Sean Ye 
14169c94f155SCheng Sean Ye /*
14179c94f155SCheng Sean Ye  * Get chassis SN or product SN
14189c94f155SCheng Sean Ye  */
14199c94f155SCheng Sean Ye static int
smb_get_sn(smbios_hdl_t * shp,const char ** psnp,const char ** csnp)14209c94f155SCheng Sean Ye smb_get_sn(smbios_hdl_t *shp, const char **psnp, const char **csnp)
14219c94f155SCheng Sean Ye {
14229c94f155SCheng Sean Ye 	const smb_struct_t *stp;
14239c94f155SCheng Sean Ye 	smbios_info_t s1, s3;
14249c94f155SCheng Sean Ye 
14259c94f155SCheng Sean Ye 	if (psnp == NULL || csnp == NULL)
14269c94f155SCheng Sean Ye 		return (smb_set_errno(shp, ESMB_INVAL));
14279c94f155SCheng Sean Ye 
14289c94f155SCheng Sean Ye 	*psnp = *csnp = NULL;
14299c94f155SCheng Sean Ye 
14309c94f155SCheng Sean Ye 	/*
14319c94f155SCheng Sean Ye 	 * If SMBIOS meets Sun's PRMS requirements, retrieve product SN
14329c94f155SCheng Sean Ye 	 * from type 1 structure, and chassis SN from type 3 structure.
14339c94f155SCheng Sean Ye 	 * Otherwise return SN in type 1 structure as chassis SN.
14349c94f155SCheng Sean Ye 	 */
14359c94f155SCheng Sean Ye 
14369c94f155SCheng Sean Ye 	/* Get type 1 SN */
14379c94f155SCheng Sean Ye 	if ((stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM)) == NULL ||
14389c94f155SCheng Sean Ye 	    smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s1) == SMB_ERR)
14399c94f155SCheng Sean Ye 		s1.smbi_serial = NULL;
14409c94f155SCheng Sean Ye 
14419c94f155SCheng Sean Ye 	/* Get type 3 SN */
14429c94f155SCheng Sean Ye 	if ((stp = smb_lookup_type(shp, SMB_TYPE_CHASSIS)) == NULL ||
14439c94f155SCheng Sean Ye 	    smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s3) == SMB_ERR)
14449c94f155SCheng Sean Ye 		s3.smbi_serial = NULL;
14459c94f155SCheng Sean Ye 
14469c94f155SCheng Sean Ye 	if (smbios_has_oemstr(shp, SMB_PRMS1)) {
14479c94f155SCheng Sean Ye 		*psnp = smb_serial_valid(s1.smbi_serial);
14489c94f155SCheng Sean Ye 		*csnp = smb_serial_valid(s3.smbi_serial);
14499c94f155SCheng Sean Ye 	} else {
14509c94f155SCheng Sean Ye 		*csnp = smb_serial_valid(s1.smbi_serial);
14519c94f155SCheng Sean Ye 	}
14529c94f155SCheng Sean Ye 
14539c94f155SCheng Sean Ye 	return (0);
14549c94f155SCheng Sean Ye }
14559c94f155SCheng Sean Ye 
14569c94f155SCheng Sean Ye const char *
smbios_psn(smbios_hdl_t * shp)14579c94f155SCheng Sean Ye smbios_psn(smbios_hdl_t *shp)
14589c94f155SCheng Sean Ye {
14599c94f155SCheng Sean Ye 	const char *psn, *csn;
14609c94f155SCheng Sean Ye 
14619c94f155SCheng Sean Ye 	return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : psn);
14629c94f155SCheng Sean Ye }
14639c94f155SCheng Sean Ye 
14649c94f155SCheng Sean Ye const char *
smbios_csn(smbios_hdl_t * shp)14659c94f155SCheng Sean Ye smbios_csn(smbios_hdl_t *shp)
14669c94f155SCheng Sean Ye {
14679c94f155SCheng Sean Ye 	const char *psn, *csn;
14689c94f155SCheng Sean Ye 
14699c94f155SCheng Sean Ye 	return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : csn);
14709c94f155SCheng Sean Ye }
1471074bb90dSTom Pothier 
1472074bb90dSTom Pothier int
smbios_info_extprocessor(smbios_hdl_t * shp,id_t id,smbios_processor_ext_t * epp)1473074bb90dSTom Pothier smbios_info_extprocessor(smbios_hdl_t *shp, id_t id,
1474074bb90dSTom Pothier     smbios_processor_ext_t *epp)
1475074bb90dSTom Pothier {
1476074bb90dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1477074bb90dSTom Pothier 	smb_processor_ext_t *exp;
1478074bb90dSTom Pothier 
1479074bb90dSTom Pothier 	if (stp == NULL)
1480074bb90dSTom Pothier 		return (-1); /* errno is set for us */
1481074bb90dSTom Pothier 
1482074bb90dSTom Pothier 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PROCESSOR)
1483074bb90dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
1484074bb90dSTom Pothier 
1485074bb90dSTom Pothier 	exp = (smb_processor_ext_t *)(uintptr_t)stp->smbst_hdr;
1486074bb90dSTom Pothier 	bzero(epp, sizeof (smbios_processor_ext_t));
1487074bb90dSTom Pothier 
1488074bb90dSTom Pothier 	epp->smbpe_processor = exp->smbpre_processor;
1489074bb90dSTom Pothier 	epp->smbpe_fru = exp->smbpre_fru;
1490074bb90dSTom Pothier 	epp->smbpe_n = exp->smbpre_n;
1491074bb90dSTom Pothier 	epp->smbpe_apicid = exp->smbpre_apicid;
1492074bb90dSTom Pothier 
1493074bb90dSTom Pothier 	return (0);
1494074bb90dSTom Pothier }
1495074bb90dSTom Pothier 
149603f9f63dSTom Pothier int
smbios_info_extport(smbios_hdl_t * shp,id_t id,smbios_port_ext_t * eportp)149703f9f63dSTom Pothier smbios_info_extport(smbios_hdl_t *shp, id_t id, smbios_port_ext_t *eportp)
149803f9f63dSTom Pothier {
149903f9f63dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
150003f9f63dSTom Pothier 	smb_port_ext_t *ep;
150103f9f63dSTom Pothier 
150203f9f63dSTom Pothier 	if (stp == NULL)
150303f9f63dSTom Pothier 		return (-1); /* errno is set for us */
150403f9f63dSTom Pothier 
150503f9f63dSTom Pothier 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PORT)
150603f9f63dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
150703f9f63dSTom Pothier 
150803f9f63dSTom Pothier 	ep = (smb_port_ext_t *)(uintptr_t)stp->smbst_hdr;
150903f9f63dSTom Pothier 	bzero(eportp, sizeof (smbios_port_ext_t));
151003f9f63dSTom Pothier 
151103f9f63dSTom Pothier 	eportp->smbporte_chassis = ep->smbpoe_chassis;
151203f9f63dSTom Pothier 	eportp->smbporte_port = ep->smbpoe_port;
151303f9f63dSTom Pothier 	eportp->smbporte_dtype = ep->smbpoe_dtype;
151403f9f63dSTom Pothier 	eportp->smbporte_devhdl = ep->smbpoe_devhdl;
151503f9f63dSTom Pothier 	eportp->smbporte_phy = ep->smbpoe_phy;
151603f9f63dSTom Pothier 
151703f9f63dSTom Pothier 	return (0);
151803f9f63dSTom Pothier }
151903f9f63dSTom Pothier 
1520074bb90dSTom Pothier int
smbios_info_pciexrc(smbios_hdl_t * shp,id_t id,smbios_pciexrc_t * rcp)1521074bb90dSTom Pothier smbios_info_pciexrc(smbios_hdl_t *shp, id_t id,
1522074bb90dSTom Pothier     smbios_pciexrc_t *rcp)
1523074bb90dSTom Pothier {
1524074bb90dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1525074bb90dSTom Pothier 	smb_pciexrc_t rc;
1526074bb90dSTom Pothier 
1527074bb90dSTom Pothier 	if (stp == NULL)
1528074bb90dSTom Pothier 		return (-1); /* errno is set for us */
1529074bb90dSTom Pothier 
1530074bb90dSTom Pothier 	if (stp->smbst_hdr->smbh_type != SUN_OEM_PCIEXRC)
1531074bb90dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
1532074bb90dSTom Pothier 
1533074bb90dSTom Pothier 	smb_info_bcopy(stp->smbst_hdr, &rc, sizeof (rc));
1534074bb90dSTom Pothier 	bzero(rcp, sizeof (smbios_pciexrc_t));
1535074bb90dSTom Pothier 
1536074bb90dSTom Pothier 	rcp->smbpcie_bb = rc.smbpciexrc_bboard;
1537074bb90dSTom Pothier 	rcp->smbpcie_bdf = rc.smbpciexrc_bdf;
1538074bb90dSTom Pothier 
1539074bb90dSTom Pothier 	return (0);
1540074bb90dSTom Pothier }
1541074bb90dSTom Pothier 
1542074bb90dSTom Pothier int
smbios_info_extmemarray(smbios_hdl_t * shp,id_t id,smbios_memarray_ext_t * emap)1543074bb90dSTom Pothier smbios_info_extmemarray(smbios_hdl_t *shp, id_t id, smbios_memarray_ext_t *emap)
1544074bb90dSTom Pothier {
1545074bb90dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1546074bb90dSTom Pothier 	smb_memarray_ext_t exma;
1547074bb90dSTom Pothier 
1548074bb90dSTom Pothier 	if (stp == NULL)
1549074bb90dSTom Pothier 		return (-1); /* errno is set for us */
1550074bb90dSTom Pothier 
1551074bb90dSTom Pothier 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMARRAY)
1552074bb90dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
1553074bb90dSTom Pothier 
1554074bb90dSTom Pothier 	smb_info_bcopy(stp->smbst_hdr, &exma, sizeof (exma));
1555074bb90dSTom Pothier 	bzero(emap, sizeof (smbios_memarray_ext_t));
1556074bb90dSTom Pothier 
1557074bb90dSTom Pothier 	emap->smbmae_ma = exma.smbmarre_ma;
1558074bb90dSTom Pothier 	emap->smbmae_comp = exma.smbmarre_component;
1559074bb90dSTom Pothier 	emap->smbmae_bdf = exma.smbmarre_bdf;
1560074bb90dSTom Pothier 
1561074bb90dSTom Pothier 	return (0);
1562074bb90dSTom Pothier }
1563074bb90dSTom Pothier 
1564074bb90dSTom Pothier int
smbios_info_extmemdevice(smbios_hdl_t * shp,id_t id,smbios_memdevice_ext_t * emdp)1565074bb90dSTom Pothier smbios_info_extmemdevice(smbios_hdl_t *shp, id_t id,
1566074bb90dSTom Pothier     smbios_memdevice_ext_t *emdp)
1567074bb90dSTom Pothier {
1568074bb90dSTom Pothier 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1569074bb90dSTom Pothier 	smb_memdevice_ext_t exmd;
1570074bb90dSTom Pothier 
1571074bb90dSTom Pothier 	if (stp == NULL)
1572074bb90dSTom Pothier 		return (-1); /* errno is set for us */
1573074bb90dSTom Pothier 
1574074bb90dSTom Pothier 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
1575074bb90dSTom Pothier 		return (smb_set_errno(shp, ESMB_TYPE));
1576074bb90dSTom Pothier 
1577074bb90dSTom Pothier 	smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
1578074bb90dSTom Pothier 	bzero(emdp, sizeof (smbios_memdevice_ext_t));
1579074bb90dSTom Pothier 
1580074bb90dSTom Pothier 	emdp->smbmdeve_md = exmd.smbmdeve_mdev;
1581074bb90dSTom Pothier 	emdp->smbmdeve_drch = exmd.smbmdeve_dchan;
1582679a141eSToomas Soome 	emdp->smbmdeve_ncs = exmd.smbmdeve_ncs;
1583074bb90dSTom Pothier 
1584074bb90dSTom Pothier 	return (0);
1585074bb90dSTom Pothier }
158632ece1f9SRobert Mustacchi 
1587679a141eSToomas Soome int
smbios_info_extmemdevice_cs(smbios_hdl_t * shp,id_t id,uint_t * ncsp,uint8_t ** csp)1588679a141eSToomas Soome smbios_info_extmemdevice_cs(smbios_hdl_t *shp, id_t id, uint_t *ncsp,
1589679a141eSToomas Soome     uint8_t **csp)
1590679a141eSToomas Soome {
1591679a141eSToomas Soome 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1592679a141eSToomas Soome 	smb_memdevice_ext_t exmd;
1593679a141eSToomas Soome 	size_t size;
1594679a141eSToomas Soome 	void *buf;
1595679a141eSToomas Soome 
1596679a141eSToomas Soome 	if (stp == NULL)
1597679a141eSToomas Soome 		return (-1); /* errno is set for us */
1598679a141eSToomas Soome 
1599679a141eSToomas Soome 	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
1600679a141eSToomas Soome 		return (smb_set_errno(shp, ESMB_TYPE));
1601679a141eSToomas Soome 
1602679a141eSToomas Soome 	smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
1603679a141eSToomas Soome 	if (exmd.smbmdeve_ncs == 0) {
1604679a141eSToomas Soome 		*ncsp = 0;
1605679a141eSToomas Soome 		*csp = NULL;
1606679a141eSToomas Soome 		return (0);
1607679a141eSToomas Soome 	}
1608679a141eSToomas Soome 
1609679a141eSToomas Soome 	size = exmd.smbmdeve_ncs * sizeof (*exmd.smbmdeve_cs);
1610679a141eSToomas Soome 
1611679a141eSToomas Soome 	if (stp->smbst_hdr->smbh_len < sizeof (exmd) + size)
1612679a141eSToomas Soome 		return (smb_set_errno(shp, ESMB_SHORT));
1613679a141eSToomas Soome 
1614679a141eSToomas Soome 	buf = smb_alloc(size);
1615679a141eSToomas Soome 	if (buf == NULL)
1616679a141eSToomas Soome 		return (smb_set_errno(shp, ESMB_NOMEM));
1617679a141eSToomas Soome 	smb_info_bcopy_offset(stp->smbst_hdr, buf, size, sizeof (exmd));
1618679a141eSToomas Soome 
1619679a141eSToomas Soome 	*ncsp = exmd.smbmdeve_ncs;
1620679a141eSToomas Soome 	*csp = buf;
1621679a141eSToomas Soome 	return (0);
1622679a141eSToomas Soome }
1623679a141eSToomas Soome 
1624679a141eSToomas Soome void
smbios_info_extmemdevice_cs_free(smbios_hdl_t * shp __unused,uint_t ncs,uint8_t * csp)1625679a141eSToomas Soome smbios_info_extmemdevice_cs_free(smbios_hdl_t *shp __unused, uint_t ncs,
1626679a141eSToomas Soome     uint8_t *csp)
1627679a141eSToomas Soome {
1628679a141eSToomas Soome 	size_t size = ncs * sizeof (uint8_t);
1629679a141eSToomas Soome 
1630679a141eSToomas Soome 	if (size == 0) {
1631679a141eSToomas Soome 		ASSERT3P(csp, ==, NULL);
1632679a141eSToomas Soome 		return;
1633679a141eSToomas Soome 	}
1634679a141eSToomas Soome 	smb_free(csp, size);
1635679a141eSToomas Soome }
1636679a141eSToomas Soome 
163732ece1f9SRobert Mustacchi int
smbios_info_powersup(smbios_hdl_t * shp,id_t id,smbios_powersup_t * psup)163832ece1f9SRobert Mustacchi smbios_info_powersup(smbios_hdl_t *shp, id_t id, smbios_powersup_t *psup)
163932ece1f9SRobert Mustacchi {
164032ece1f9SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
164132ece1f9SRobert Mustacchi 	smb_powersup_t psu;
164232ece1f9SRobert Mustacchi 
164332ece1f9SRobert Mustacchi 	if (stp == NULL)
164432ece1f9SRobert Mustacchi 		return (-1); /* errno is set for us */
164532ece1f9SRobert Mustacchi 
164632ece1f9SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_POWERSUP)
164732ece1f9SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
164832ece1f9SRobert Mustacchi 
164932ece1f9SRobert Mustacchi 	/* The minimum length required by the spec is 0x10. */
165032ece1f9SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < 0x10)
165132ece1f9SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
165232ece1f9SRobert Mustacchi 
165332ece1f9SRobert Mustacchi 	bzero(psup, sizeof (*psup));
165432ece1f9SRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &psu, sizeof (psu));
165532ece1f9SRobert Mustacchi 	psup->smbps_group = psu.smbpsup_group;
165632ece1f9SRobert Mustacchi 	psup->smbps_maxout = psu.smbpsup_max;
165732ece1f9SRobert Mustacchi 
165832ece1f9SRobert Mustacchi 	if (SMB_PSU_CHARS_ISHOT(psu.smbpsup_char))
165932ece1f9SRobert Mustacchi 		psup->smbps_flags |= SMB_POWERSUP_F_HOT;
166032ece1f9SRobert Mustacchi 	if (SMB_PSU_CHARS_ISPRES(psu.smbpsup_char))
166132ece1f9SRobert Mustacchi 		psup->smbps_flags |= SMB_POWERSUP_F_PRESENT;
166232ece1f9SRobert Mustacchi 	if (SMB_PSU_CHARS_ISUNPLUG(psu.smbpsup_char))
166332ece1f9SRobert Mustacchi 		psup->smbps_flags |= SMB_POWERSUP_F_UNPLUG;
166432ece1f9SRobert Mustacchi 
166532ece1f9SRobert Mustacchi 	psup->smbps_ivrs = SMB_PSU_CHARS_IVRS(psu.smbpsup_char);
166632ece1f9SRobert Mustacchi 	psup->smbps_status = SMB_PSU_CHARS_STATUS(psu.smbpsup_char);
166732ece1f9SRobert Mustacchi 	psup->smbps_pstype = SMB_PSU_CHARS_TYPE(psu.smbpsup_char);
166832ece1f9SRobert Mustacchi 
166932ece1f9SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len >= 0x12) {
167032ece1f9SRobert Mustacchi 		psup->smbps_vprobe = psu.smbpsup_vprobe;
167132ece1f9SRobert Mustacchi 	} else {
167232ece1f9SRobert Mustacchi 		psup->smbps_vprobe = 0xffff;
167332ece1f9SRobert Mustacchi 	}
167432ece1f9SRobert Mustacchi 
167532ece1f9SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len >= 0x14) {
167632ece1f9SRobert Mustacchi 		psup->smbps_cooldev = psu.smbpsup_cooldev;
167732ece1f9SRobert Mustacchi 	} else {
167832ece1f9SRobert Mustacchi 		psup->smbps_cooldev = 0xffff;
167932ece1f9SRobert Mustacchi 	}
168032ece1f9SRobert Mustacchi 
168132ece1f9SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len >= 0x16) {
168232ece1f9SRobert Mustacchi 		psup->smbps_iprobe = psu.smbpsup_iprobe;
168332ece1f9SRobert Mustacchi 	} else {
168432ece1f9SRobert Mustacchi 		psup->smbps_iprobe = 0xffff;
168532ece1f9SRobert Mustacchi 	}
168632ece1f9SRobert Mustacchi 
168732ece1f9SRobert Mustacchi 	return (0);
168832ece1f9SRobert Mustacchi }
1689f44a1392SRobert Mustacchi 
1690f44a1392SRobert Mustacchi int
smbios_info_vprobe(smbios_hdl_t * shp,id_t id,smbios_vprobe_t * vprobe)1691f44a1392SRobert Mustacchi smbios_info_vprobe(smbios_hdl_t *shp, id_t id, smbios_vprobe_t *vprobe)
1692f44a1392SRobert Mustacchi {
1693f44a1392SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1694f44a1392SRobert Mustacchi 	smb_vprobe_t vp;
1695f44a1392SRobert Mustacchi 
1696f44a1392SRobert Mustacchi 	if (stp == NULL)
1697f44a1392SRobert Mustacchi 		return (-1); /* errno is set for us */
1698f44a1392SRobert Mustacchi 
1699f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_VPROBE)
1700f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1701f44a1392SRobert Mustacchi 
1702f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < SMB_VPROBE_MINLEN)
1703f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1704f44a1392SRobert Mustacchi 
1705f44a1392SRobert Mustacchi 	bzero(vprobe, sizeof (*vprobe));
1706f44a1392SRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &vp, sizeof (vp));
1707f44a1392SRobert Mustacchi 	vprobe->smbvp_description = smb_strptr(stp, vp.smbvpr_descr);
1708f44a1392SRobert Mustacchi 	vprobe->smbvp_location = SMB_VPROBE_LOCATION(vp.smbvpr_locstat);
1709f44a1392SRobert Mustacchi 	vprobe->smbvp_status = SMB_VPROBE_STATUS(vp.smbvpr_locstat);
1710f44a1392SRobert Mustacchi 	vprobe->smbvp_maxval = vp.smbvpr_maxval;
1711f44a1392SRobert Mustacchi 	vprobe->smbvp_minval = vp.smbvpr_minval;
1712f44a1392SRobert Mustacchi 	vprobe->smbvp_resolution = vp.smbvpr_resolution;
1713f44a1392SRobert Mustacchi 	vprobe->smbvp_tolerance	= vp.smbvpr_tolerance;
1714f44a1392SRobert Mustacchi 	vprobe->smbvp_accuracy = vp.smbvpr_accuracy;
1715f44a1392SRobert Mustacchi 
1716f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len >= SMB_VPROBE_NOMINAL_MINLEN) {
1717f44a1392SRobert Mustacchi 		vprobe->smbvp_nominal = vp.smbvpr_nominal;
1718f44a1392SRobert Mustacchi 	} else {
1719f44a1392SRobert Mustacchi 		vprobe->smbvp_nominal = SMB_PROBE_UNKNOWN_VALUE;
1720f44a1392SRobert Mustacchi 	}
1721f44a1392SRobert Mustacchi 
1722f44a1392SRobert Mustacchi 	return (0);
1723f44a1392SRobert Mustacchi }
1724f44a1392SRobert Mustacchi 
1725f44a1392SRobert Mustacchi int
smbios_info_cooldev(smbios_hdl_t * shp,id_t id,smbios_cooldev_t * cooldev)1726f44a1392SRobert Mustacchi smbios_info_cooldev(smbios_hdl_t *shp, id_t id, smbios_cooldev_t *cooldev)
1727f44a1392SRobert Mustacchi {
1728f44a1392SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1729f44a1392SRobert Mustacchi 	smb_cooldev_t cd;
1730f44a1392SRobert Mustacchi 
1731f44a1392SRobert Mustacchi 	if (stp == NULL)
1732f44a1392SRobert Mustacchi 		return (-1); /* errno is set for us */
1733f44a1392SRobert Mustacchi 
1734f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_COOLDEV)
1735f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1736f44a1392SRobert Mustacchi 
1737f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < SMB_COOLDEV_MINLEN)
1738f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1739f44a1392SRobert Mustacchi 
1740f44a1392SRobert Mustacchi 	bzero(cooldev, sizeof (*cooldev));
1741f44a1392SRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &cd, sizeof (cd));
1742f44a1392SRobert Mustacchi 	cooldev->smbcd_tprobe = cd.smbcdev_tprobe;
1743f44a1392SRobert Mustacchi 	cooldev->smbcd_type = SMB_COOLDEV_TYPE(cd.smbcdev_typstat);
1744f44a1392SRobert Mustacchi 	cooldev->smbcd_status = SMB_COOLDEV_STATUS(cd.smbcdev_typstat);
1745f44a1392SRobert Mustacchi 	cooldev->smbcd_group = cd.smbcdev_group;
1746f44a1392SRobert Mustacchi 	cooldev->smbcd_oem = cd.smbcdev_oem;
1747f44a1392SRobert Mustacchi 
1748f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len >= SMB_COOLDEV_NOMINAL_MINLEN) {
1749f44a1392SRobert Mustacchi 		cooldev->smbcd_nominal = cd.smbcdev_nominal;
1750f44a1392SRobert Mustacchi 	} else {
1751f44a1392SRobert Mustacchi 		cooldev->smbcd_nominal = SMB_PROBE_UNKNOWN_VALUE;
1752f44a1392SRobert Mustacchi 	}
1753f44a1392SRobert Mustacchi 
1754f44a1392SRobert Mustacchi 	/*
1755f44a1392SRobert Mustacchi 	 * The description field was added in SMBIOS version 2.7. The
1756f44a1392SRobert Mustacchi 	 * SMB_TYPE_COOLDEV support was only added after all of the 2.7+ fields
1757f44a1392SRobert Mustacchi 	 * were added in the spec. So while a user may request an older version,
1758f44a1392SRobert Mustacchi 	 * we don't have to worry about old structures and just simply skip it
1759f44a1392SRobert Mustacchi 	 * if they're not asking for it.
1760f44a1392SRobert Mustacchi 	 */
1761f44a1392SRobert Mustacchi 	if (smb_libgteq(shp, SMB_VERSION_27) &&
1762f44a1392SRobert Mustacchi 	    smb_gteq(shp, SMB_VERSION_27) &&
1763f44a1392SRobert Mustacchi 	    stp->smbst_hdr->smbh_len >= SMB_COOLDEV_DESCR_MINLEN) {
1764f44a1392SRobert Mustacchi 		cooldev->smbcd_descr = smb_strptr(stp, cd.smbcdev_descr);
1765f44a1392SRobert Mustacchi 	} else {
1766f44a1392SRobert Mustacchi 		cooldev->smbcd_descr = NULL;
1767f44a1392SRobert Mustacchi 	}
1768f44a1392SRobert Mustacchi 
1769f44a1392SRobert Mustacchi 	return (0);
1770f44a1392SRobert Mustacchi }
1771f44a1392SRobert Mustacchi 
1772f44a1392SRobert Mustacchi int
smbios_info_tprobe(smbios_hdl_t * shp,id_t id,smbios_tprobe_t * tprobe)1773f44a1392SRobert Mustacchi smbios_info_tprobe(smbios_hdl_t *shp, id_t id, smbios_tprobe_t *tprobe)
1774f44a1392SRobert Mustacchi {
1775f44a1392SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1776f44a1392SRobert Mustacchi 	smb_tprobe_t tp;
1777f44a1392SRobert Mustacchi 
1778f44a1392SRobert Mustacchi 	if (stp == NULL)
1779f44a1392SRobert Mustacchi 		return (-1); /* errno is set for us */
1780f44a1392SRobert Mustacchi 
1781f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_TPROBE)
1782f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1783f44a1392SRobert Mustacchi 
1784f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < SMB_TPROBE_MINLEN)
1785f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1786f44a1392SRobert Mustacchi 
1787f44a1392SRobert Mustacchi 	bzero(tprobe, sizeof (*tprobe));
1788f44a1392SRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &tp, sizeof (tp));
1789f44a1392SRobert Mustacchi 	tprobe->smbtp_description = smb_strptr(stp, tp.smbtpr_descr);
1790f44a1392SRobert Mustacchi 	tprobe->smbtp_location = SMB_TPROBE_LOCATION(tp.smbtpr_locstat);
1791f44a1392SRobert Mustacchi 	tprobe->smbtp_status = SMB_TPROBE_STATUS(tp.smbtpr_locstat);
1792f44a1392SRobert Mustacchi 	tprobe->smbtp_maxval = tp.smbtpr_maxval;
1793f44a1392SRobert Mustacchi 	tprobe->smbtp_minval = tp.smbtpr_minval;
1794f44a1392SRobert Mustacchi 	tprobe->smbtp_resolution = tp.smbtpr_resolution;
1795f44a1392SRobert Mustacchi 	tprobe->smbtp_tolerance	= tp.smbtpr_tolerance;
1796f44a1392SRobert Mustacchi 	tprobe->smbtp_accuracy = tp.smbtpr_accuracy;
1797f44a1392SRobert Mustacchi 
1798f44a1392SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len >= SMB_TPROBE_NOMINAL_MINLEN) {
1799f44a1392SRobert Mustacchi 		tprobe->smbtp_nominal = tp.smbtpr_nominal;
1800f44a1392SRobert Mustacchi 	} else {
1801f44a1392SRobert Mustacchi 		tprobe->smbtp_nominal = SMB_PROBE_UNKNOWN_VALUE;
1802f44a1392SRobert Mustacchi 	}
1803f44a1392SRobert Mustacchi 
1804f44a1392SRobert Mustacchi 	return (0);
1805f44a1392SRobert Mustacchi }
1806f44a1392SRobert Mustacchi 
1807f44a1392SRobert Mustacchi int
smbios_info_iprobe(smbios_hdl_t * shp,id_t id,smbios_iprobe_t * iprobe)1808f44a1392SRobert Mustacchi smbios_info_iprobe(smbios_hdl_t *shp, id_t id, smbios_iprobe_t *iprobe)
1809f44a1392SRobert Mustacchi {
1810f44a1392SRobert Mustacchi 	const smb_struct_t *sip = smb_lookup_id(shp, id);
1811f44a1392SRobert Mustacchi 	smb_iprobe_t ip;
1812f44a1392SRobert Mustacchi 
1813f44a1392SRobert Mustacchi 	if (sip == NULL)
1814f44a1392SRobert Mustacchi 		return (-1); /* errno is set for us */
1815f44a1392SRobert Mustacchi 
1816f44a1392SRobert Mustacchi 	if (sip->smbst_hdr->smbh_type != SMB_TYPE_IPROBE)
1817f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1818f44a1392SRobert Mustacchi 
1819f44a1392SRobert Mustacchi 	if (sip->smbst_hdr->smbh_len < SMB_IPROBE_MINLEN)
1820f44a1392SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1821f44a1392SRobert Mustacchi 
1822f44a1392SRobert Mustacchi 	bzero(iprobe, sizeof (*iprobe));
1823f44a1392SRobert Mustacchi 	smb_info_bcopy(sip->smbst_hdr, &ip, sizeof (ip));
1824f44a1392SRobert Mustacchi 	iprobe->smbip_description = smb_strptr(sip, ip.smbipr_descr);
1825f44a1392SRobert Mustacchi 	iprobe->smbip_location = SMB_IPROBE_LOCATION(ip.smbipr_locstat);
1826f44a1392SRobert Mustacchi 	iprobe->smbip_status = SMB_IPROBE_STATUS(ip.smbipr_locstat);
1827f44a1392SRobert Mustacchi 	iprobe->smbip_maxval = ip.smbipr_maxval;
1828f44a1392SRobert Mustacchi 	iprobe->smbip_minval = ip.smbipr_minval;
1829f44a1392SRobert Mustacchi 	iprobe->smbip_resolution = ip.smbipr_resolution;
1830f44a1392SRobert Mustacchi 	iprobe->smbip_tolerance	= ip.smbipr_tolerance;
1831f44a1392SRobert Mustacchi 	iprobe->smbip_accuracy = ip.smbipr_accuracy;
1832f44a1392SRobert Mustacchi 
1833f44a1392SRobert Mustacchi 	if (sip->smbst_hdr->smbh_len >= SMB_IPROBE_NOMINAL_MINLEN) {
1834f44a1392SRobert Mustacchi 		iprobe->smbip_nominal = ip.smbipr_nominal;
1835f44a1392SRobert Mustacchi 	} else {
1836f44a1392SRobert Mustacchi 		iprobe->smbip_nominal = SMB_PROBE_UNKNOWN_VALUE;
1837f44a1392SRobert Mustacchi 	}
1838f44a1392SRobert Mustacchi 
1839f44a1392SRobert Mustacchi 	return (0);
1840f44a1392SRobert Mustacchi }
1841176a9270SRobert Mustacchi 
1842176a9270SRobert Mustacchi int
smbios_info_processor_info(smbios_hdl_t * shp,id_t id,smbios_processor_info_t * proc)1843176a9270SRobert Mustacchi smbios_info_processor_info(smbios_hdl_t *shp, id_t id,
1844176a9270SRobert Mustacchi     smbios_processor_info_t *proc)
1845176a9270SRobert Mustacchi {
1846176a9270SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1847176a9270SRobert Mustacchi 	smb_processor_info_t pi;
1848176a9270SRobert Mustacchi 
1849176a9270SRobert Mustacchi 	if (stp == NULL)
1850176a9270SRobert Mustacchi 		return (-1); /* errno is set for us */
1851176a9270SRobert Mustacchi 
1852176a9270SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO)
1853176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1854176a9270SRobert Mustacchi 
1855176a9270SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (pi))
1856176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1857176a9270SRobert Mustacchi 
1858176a9270SRobert Mustacchi 	bzero(proc, sizeof (*proc));
1859176a9270SRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &pi, sizeof (pi));
1860176a9270SRobert Mustacchi 
1861176a9270SRobert Mustacchi 	if (sizeof (pi) + pi.smbpai_len > stp->smbst_hdr->smbh_len)
1862176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_CORRUPT));
1863176a9270SRobert Mustacchi 
1864176a9270SRobert Mustacchi 	proc->smbpi_processor = pi.smbpai_proc;
1865176a9270SRobert Mustacchi 	proc->smbpi_ptype = pi.smbpai_type;
1866176a9270SRobert Mustacchi 
1867176a9270SRobert Mustacchi 	return (0);
1868176a9270SRobert Mustacchi }
1869176a9270SRobert Mustacchi 
1870176a9270SRobert Mustacchi int
smbios_info_processor_riscv(smbios_hdl_t * shp,id_t id,smbios_processor_info_riscv_t * riscv)1871176a9270SRobert Mustacchi smbios_info_processor_riscv(smbios_hdl_t *shp, id_t id,
1872176a9270SRobert Mustacchi     smbios_processor_info_riscv_t *riscv)
1873176a9270SRobert Mustacchi {
1874176a9270SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
1875176a9270SRobert Mustacchi 	const smb_processor_info_t *proc;
1876176a9270SRobert Mustacchi 	const smb_processor_info_riscv_t *rv;
1877176a9270SRobert Mustacchi 
1878d53cdfabSRobert Mustacchi 	if (stp == NULL) {
1879d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
1880d53cdfabSRobert Mustacchi 	}
1881d53cdfabSRobert Mustacchi 
1882176a9270SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO) {
1883176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1884176a9270SRobert Mustacchi 	}
1885176a9270SRobert Mustacchi 
1886176a9270SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (*proc)) {
1887176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1888176a9270SRobert Mustacchi 	}
1889176a9270SRobert Mustacchi 
1890176a9270SRobert Mustacchi 	proc = (const smb_processor_info_t *)stp->smbst_hdr;
1891176a9270SRobert Mustacchi 	if (sizeof (*proc) + proc->smbpai_len > stp->smbst_hdr->smbh_len) {
1892176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_CORRUPT));
1893176a9270SRobert Mustacchi 	}
1894176a9270SRobert Mustacchi 
1895176a9270SRobert Mustacchi 	switch (proc->smbpai_type) {
1896176a9270SRobert Mustacchi 	case SMB_PROCINFO_T_RV32:
1897176a9270SRobert Mustacchi 	case SMB_PROCINFO_T_RV64:
1898176a9270SRobert Mustacchi 	case SMB_PROCINFO_T_RV128:
1899176a9270SRobert Mustacchi 		break;
1900176a9270SRobert Mustacchi 	default:
1901176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
1902176a9270SRobert Mustacchi 	}
1903176a9270SRobert Mustacchi 
1904176a9270SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (*proc) + sizeof (*rv)) {
1905176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
1906176a9270SRobert Mustacchi 	}
1907176a9270SRobert Mustacchi 	rv = (const smb_processor_info_riscv_t *)&proc->smbpai_data[0];
1908176a9270SRobert Mustacchi 	if (rv->smbpairv_len != sizeof (*rv)) {
1909176a9270SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_CORRUPT));
1910176a9270SRobert Mustacchi 	}
1911176a9270SRobert Mustacchi 
1912176a9270SRobert Mustacchi 	bcopy(rv->smbpairv_hartid, riscv->smbpirv_hartid,
1913176a9270SRobert Mustacchi 	    sizeof (riscv->smbpirv_hartid));
1914176a9270SRobert Mustacchi 	bcopy(rv->smbpairv_vendid, riscv->smbpirv_vendid,
1915176a9270SRobert Mustacchi 	    sizeof (riscv->smbpirv_vendid));
1916176a9270SRobert Mustacchi 	bcopy(rv->smbpairv_archid, riscv->smbpirv_archid,
1917176a9270SRobert Mustacchi 	    sizeof (riscv->smbpirv_archid));
1918176a9270SRobert Mustacchi 	bcopy(rv->smbpairv_machid, riscv->smbpirv_machid,
1919176a9270SRobert Mustacchi 	    sizeof (riscv->smbpirv_machid));
1920176a9270SRobert Mustacchi 	bcopy(rv->smbpairv_metdi, riscv->smbpirv_metdi,
1921176a9270SRobert Mustacchi 	    sizeof (riscv->smbpirv_metdi));
1922176a9270SRobert Mustacchi 	bcopy(rv->smbpairv_mitdi, riscv->smbpirv_mitdi,
1923176a9270SRobert Mustacchi 	    sizeof (riscv->smbpirv_mitdi));
1924176a9270SRobert Mustacchi 	riscv->smbpirv_isa = rv->smbpairv_isa;
1925176a9270SRobert Mustacchi 	riscv->smbpirv_privlvl = rv->smbpairv_privlvl;
1926176a9270SRobert Mustacchi 	riscv->smbpirv_boothart = rv->smbpairv_boot;
1927176a9270SRobert Mustacchi 	riscv->smbpirv_xlen = rv->smbpairv_xlen;
1928176a9270SRobert Mustacchi 	riscv->smbpirv_mxlen = rv->smbpairv_mxlen;
1929176a9270SRobert Mustacchi 	riscv->smbpirv_sxlen = rv->smbpairv_sxlen;
1930176a9270SRobert Mustacchi 	riscv->smbpirv_uxlen = rv->smbpairv_uxlen;
1931176a9270SRobert Mustacchi 
1932176a9270SRobert Mustacchi 	return (0);
1933176a9270SRobert Mustacchi }
19341d77dcdaSRobert Mustacchi 
19351d77dcdaSRobert Mustacchi int
smbios_info_pointdev(smbios_hdl_t * shp,id_t id,smbios_pointdev_t * pd)19361d77dcdaSRobert Mustacchi smbios_info_pointdev(smbios_hdl_t *shp, id_t id, smbios_pointdev_t *pd)
19371d77dcdaSRobert Mustacchi {
19381d77dcdaSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
19391d77dcdaSRobert Mustacchi 	smb_pointdev_t point;
19401d77dcdaSRobert Mustacchi 
1941d53cdfabSRobert Mustacchi 	if (stp == NULL) {
1942d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
1943d53cdfabSRobert Mustacchi 	}
1944d53cdfabSRobert Mustacchi 
19451d77dcdaSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_POINTDEV) {
19461d77dcdaSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
19471d77dcdaSRobert Mustacchi 	}
19481d77dcdaSRobert Mustacchi 
19491d77dcdaSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (point)) {
19501d77dcdaSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
19511d77dcdaSRobert Mustacchi 	}
19521d77dcdaSRobert Mustacchi 
19531d77dcdaSRobert Mustacchi 	bzero(pd, sizeof (*pd));
19541d77dcdaSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &point, sizeof (point));
19551d77dcdaSRobert Mustacchi 
19561d77dcdaSRobert Mustacchi 	pd->smbpd_type = point.smbpdev_type;
19571d77dcdaSRobert Mustacchi 	pd->smbpd_iface = point.smbpdev_iface;
19581d77dcdaSRobert Mustacchi 	pd->smbpd_nbuttons = point.smbpdev_nbuttons;
19591d77dcdaSRobert Mustacchi 
19601d77dcdaSRobert Mustacchi 	return (0);
19611d77dcdaSRobert Mustacchi }
196246782190SRobert Mustacchi 
196346782190SRobert Mustacchi int
smbios_info_battery(smbios_hdl_t * shp,id_t id,smbios_battery_t * bp)196446782190SRobert Mustacchi smbios_info_battery(smbios_hdl_t *shp, id_t id, smbios_battery_t *bp)
196546782190SRobert Mustacchi {
196646782190SRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
196746782190SRobert Mustacchi 	smb_battery_t bat;
196846782190SRobert Mustacchi 
1969d53cdfabSRobert Mustacchi 	if (stp == NULL) {
1970d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
1971d53cdfabSRobert Mustacchi 	}
1972d53cdfabSRobert Mustacchi 
197346782190SRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_BATTERY) {
197446782190SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
197546782190SRobert Mustacchi 	}
197646782190SRobert Mustacchi 
197746782190SRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (bat)) {
197846782190SRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
197946782190SRobert Mustacchi 	}
198046782190SRobert Mustacchi 
198146782190SRobert Mustacchi 	bzero(bp, sizeof (*bp));
198246782190SRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &bat, sizeof (bat));
198346782190SRobert Mustacchi 
198446782190SRobert Mustacchi 	/*
198546782190SRobert Mustacchi 	 * This may be superseded by the SBDS data.
198646782190SRobert Mustacchi 	 */
198746782190SRobert Mustacchi 	if (bat.smbbat_date != 0) {
198846782190SRobert Mustacchi 		bp->smbb_date = smb_strptr(stp, bat.smbbat_date);
198946782190SRobert Mustacchi 	} else {
199046782190SRobert Mustacchi 		bp->smbb_date = NULL;
199146782190SRobert Mustacchi 	}
199246782190SRobert Mustacchi 
199346782190SRobert Mustacchi 	/*
199446782190SRobert Mustacchi 	 * This may be superseded by the SBDS data.
199546782190SRobert Mustacchi 	 */
199646782190SRobert Mustacchi 	if (bat.smbbat_serial != 0) {
199746782190SRobert Mustacchi 		bp->smbb_serial = smb_strptr(stp, bat.smbbat_serial);
199846782190SRobert Mustacchi 	} else {
199946782190SRobert Mustacchi 		bp->smbb_serial = NULL;
200046782190SRobert Mustacchi 	}
200146782190SRobert Mustacchi 
200246782190SRobert Mustacchi 	bp->smbb_chem = bat.smbbat_chem;
200346782190SRobert Mustacchi 	bp->smbb_cap = bat.smbbat_cap;
200446782190SRobert Mustacchi 	if (bat.smbbat_mult > 0) {
200546782190SRobert Mustacchi 		bp->smbb_cap *= bat.smbbat_mult;
200646782190SRobert Mustacchi 	}
200746782190SRobert Mustacchi 	bp->smbb_volt = bat.smbbat_volt;
200846782190SRobert Mustacchi 	bp->smbb_version = smb_strptr(stp, bat.smbbat_version);
200946782190SRobert Mustacchi 	bp->smbb_err = bat.smbbat_err;
201046782190SRobert Mustacchi 	bp->smbb_ssn = bat.smbbat_ssn;
201146782190SRobert Mustacchi 	bp->smbb_syear = 1980 + (bat.smbbat_sdate >> 9);
201246782190SRobert Mustacchi 	bp->smbb_smonth = (bat.smbbat_sdate >> 5) & 0xf;
201346782190SRobert Mustacchi 	bp->smbb_sday = bat.smbbat_sdate & 0x1f;
201446782190SRobert Mustacchi 	bp->smbb_schem = smb_strptr(stp, bat.smbbat_schem);
201546782190SRobert Mustacchi 	bp->smbb_oemdata = bat.smbbat_oemdata;
201646782190SRobert Mustacchi 
201746782190SRobert Mustacchi 	return (0);
201846782190SRobert Mustacchi }
2019d53cdfabSRobert Mustacchi 
2020d53cdfabSRobert Mustacchi int
smbios_info_strprop(smbios_hdl_t * shp,id_t id,smbios_strprop_t * str)2021d53cdfabSRobert Mustacchi smbios_info_strprop(smbios_hdl_t *shp, id_t id, smbios_strprop_t *str)
2022d53cdfabSRobert Mustacchi {
2023d53cdfabSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
2024d53cdfabSRobert Mustacchi 	smb_strprop_t prop;
2025d53cdfabSRobert Mustacchi 
2026d53cdfabSRobert Mustacchi 	if (stp == NULL) {
2027d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
2028d53cdfabSRobert Mustacchi 	}
2029d53cdfabSRobert Mustacchi 
2030d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_STRPROP) {
2031d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
2032d53cdfabSRobert Mustacchi 	}
2033d53cdfabSRobert Mustacchi 
2034d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (prop)) {
2035d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
2036d53cdfabSRobert Mustacchi 	}
2037d53cdfabSRobert Mustacchi 
2038d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len > sizeof (prop)) {
2039d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_CORRUPT));
2040d53cdfabSRobert Mustacchi 	}
2041d53cdfabSRobert Mustacchi 
2042d53cdfabSRobert Mustacchi 	bzero(str, sizeof (*str));
2043d53cdfabSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &prop, sizeof (prop));
2044d53cdfabSRobert Mustacchi 
2045d53cdfabSRobert Mustacchi 	str->smbsp_parent = prop.smbstrp_phdl;
2046d53cdfabSRobert Mustacchi 	str->smbsp_prop_id = prop.smbstrp_prop_id;
2047d53cdfabSRobert Mustacchi 	str->smbsp_prop_val = smb_strptr(stp, prop.smbstrp_prop_val);
2048d53cdfabSRobert Mustacchi 
2049d53cdfabSRobert Mustacchi 	return (0);
2050d53cdfabSRobert Mustacchi }
2051d53cdfabSRobert Mustacchi 
2052d53cdfabSRobert Mustacchi int
smbios_info_fwinfo(smbios_hdl_t * shp,id_t id,smbios_fwinfo_t * fwinfo)2053d53cdfabSRobert Mustacchi smbios_info_fwinfo(smbios_hdl_t *shp, id_t id, smbios_fwinfo_t *fwinfo)
2054d53cdfabSRobert Mustacchi {
2055d53cdfabSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
2056d53cdfabSRobert Mustacchi 	smb_fwinfo_t fw;
2057d53cdfabSRobert Mustacchi 
2058d53cdfabSRobert Mustacchi 	if (stp == NULL) {
2059d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
2060d53cdfabSRobert Mustacchi 	}
2061d53cdfabSRobert Mustacchi 
2062d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_FWINFO) {
2063d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
2064d53cdfabSRobert Mustacchi 	}
2065d53cdfabSRobert Mustacchi 
2066d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (fw)) {
2067d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
2068d53cdfabSRobert Mustacchi 	}
2069d53cdfabSRobert Mustacchi 
2070d53cdfabSRobert Mustacchi 	/*
2071d53cdfabSRobert Mustacchi 	 * The verion and manufacturer are part of smbios_info_common().
2072d53cdfabSRobert Mustacchi 	 */
2073d53cdfabSRobert Mustacchi 	bzero(fwinfo, sizeof (*fwinfo));
2074d53cdfabSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &fw, sizeof (fw));
2075d53cdfabSRobert Mustacchi 	fwinfo->smbfw_name = smb_strptr(stp, fw.smbfwii_name);
2076d53cdfabSRobert Mustacchi 	fwinfo->smbfw_id = smb_strptr(stp, fw.smbfwii_id);
2077d53cdfabSRobert Mustacchi 	fwinfo->smbfw_reldate = smb_strptr(stp, fw.smbfwii_reldate);
2078d53cdfabSRobert Mustacchi 	fwinfo->smbfw_lsv = smb_strptr(stp, fw.smbfwii_lsv);
2079d53cdfabSRobert Mustacchi 	fwinfo->smbfw_imgsz = fw.smbfwii_imgsz;
2080d53cdfabSRobert Mustacchi 	fwinfo->smbfw_chars = fw.smbfwii_chars;
2081d53cdfabSRobert Mustacchi 	fwinfo->smbfw_state = fw.smbfwii_state;
2082d53cdfabSRobert Mustacchi 	fwinfo->smbfw_ncomps = fw.smbfwii_ncomps;
2083d53cdfabSRobert Mustacchi 	fwinfo->smbfw_vers_fmt = fw.smbfwii_vers_fmt;
2084d53cdfabSRobert Mustacchi 	fwinfo->smbfw_id_fmt = fw.smbfwii_id_fmt;
2085d53cdfabSRobert Mustacchi 
2086d53cdfabSRobert Mustacchi 	return (0);
2087d53cdfabSRobert Mustacchi }
2088d53cdfabSRobert Mustacchi 
2089d53cdfabSRobert Mustacchi int
smbios_info_fwinfo_comps(smbios_hdl_t * shp,id_t id,uint_t * ncompsp,smbios_fwinfo_comp_t ** compsp)2090d53cdfabSRobert Mustacchi smbios_info_fwinfo_comps(smbios_hdl_t *shp, id_t id, uint_t *ncompsp,
2091d53cdfabSRobert Mustacchi     smbios_fwinfo_comp_t **compsp)
2092d53cdfabSRobert Mustacchi {
2093d53cdfabSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
2094d53cdfabSRobert Mustacchi 	smbios_fwinfo_comp_t *comps;
2095d53cdfabSRobert Mustacchi 	smb_fwinfo_t fw;
2096d53cdfabSRobert Mustacchi 	size_t need;
2097d53cdfabSRobert Mustacchi 	uint_t i;
2098d53cdfabSRobert Mustacchi 
2099d53cdfabSRobert Mustacchi 	if (stp == NULL) {
2100d53cdfabSRobert Mustacchi 		return (-1); /* errno is set for us */
2101d53cdfabSRobert Mustacchi 	}
2102d53cdfabSRobert Mustacchi 
2103d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_FWINFO) {
2104d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
2105d53cdfabSRobert Mustacchi 	}
2106d53cdfabSRobert Mustacchi 
2107d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (fw)) {
2108d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
2109d53cdfabSRobert Mustacchi 	}
2110d53cdfabSRobert Mustacchi 
2111d53cdfabSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &fw, sizeof (fw));
2112d53cdfabSRobert Mustacchi 	if (fw.smbfwii_ncomps == 0) {
2113d53cdfabSRobert Mustacchi 		*ncompsp = 0;
2114d53cdfabSRobert Mustacchi 		*compsp = NULL;
2115d53cdfabSRobert Mustacchi 		return (0);
2116d53cdfabSRobert Mustacchi 	}
2117d53cdfabSRobert Mustacchi 
2118d53cdfabSRobert Mustacchi 	need = fw.smbfwii_ncomps * sizeof (uint16_t) + sizeof (smb_fwinfo_t);
2119d53cdfabSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < need) {
2120d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
2121d53cdfabSRobert Mustacchi 	}
2122d53cdfabSRobert Mustacchi 
2123d53cdfabSRobert Mustacchi 	comps = smb_alloc(fw.smbfwii_ncomps * sizeof (smbios_fwinfo_comp_t));
2124d53cdfabSRobert Mustacchi 	if (comps == NULL) {
2125d53cdfabSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_NOMEM));
2126d53cdfabSRobert Mustacchi 	}
2127d53cdfabSRobert Mustacchi 
2128d53cdfabSRobert Mustacchi 	for (i = 0; i < fw.smbfwii_ncomps; i++) {
2129d53cdfabSRobert Mustacchi 		uint16_t id;
2130d53cdfabSRobert Mustacchi 		size_t off = sizeof (smb_fwinfo_t) + sizeof (uint16_t) * i;
2131d53cdfabSRobert Mustacchi 		smb_info_bcopy_offset(stp->smbst_hdr, &id, sizeof (id), off);
2132d53cdfabSRobert Mustacchi 		comps[i].smbfwe_id = id;
2133d53cdfabSRobert Mustacchi 	}
2134d53cdfabSRobert Mustacchi 
2135d53cdfabSRobert Mustacchi 	*ncompsp = fw.smbfwii_ncomps;
2136d53cdfabSRobert Mustacchi 	*compsp = comps;
2137d53cdfabSRobert Mustacchi 
2138d53cdfabSRobert Mustacchi 	return (0);
2139d53cdfabSRobert Mustacchi }
2140d53cdfabSRobert Mustacchi 
2141d53cdfabSRobert Mustacchi void
smbios_info_fwinfo_comps_free(smbios_hdl_t * shp,uint_t ncomps,smbios_fwinfo_comp_t * comps)2142d53cdfabSRobert Mustacchi smbios_info_fwinfo_comps_free(smbios_hdl_t *shp, uint_t ncomps,
2143d53cdfabSRobert Mustacchi     smbios_fwinfo_comp_t *comps)
2144d53cdfabSRobert Mustacchi {
2145d53cdfabSRobert Mustacchi 	size_t sz = ncomps * sizeof (smbios_fwinfo_comp_t);
2146d53cdfabSRobert Mustacchi 
2147d53cdfabSRobert Mustacchi 	if (ncomps == 0) {
2148d53cdfabSRobert Mustacchi 		ASSERT3P(comps, ==, NULL);
2149d53cdfabSRobert Mustacchi 		return;
2150d53cdfabSRobert Mustacchi 	}
2151d53cdfabSRobert Mustacchi 
2152d53cdfabSRobert Mustacchi 	smb_free(comps, sz);
2153d53cdfabSRobert Mustacchi }
2154*064d431aSRobert Mustacchi 
2155*064d431aSRobert Mustacchi int
smbios_info_addinfo_nents(smbios_hdl_t * shp,id_t id,uint_t * nentsp)2156*064d431aSRobert Mustacchi smbios_info_addinfo_nents(smbios_hdl_t *shp, id_t id, uint_t *nentsp)
2157*064d431aSRobert Mustacchi {
2158*064d431aSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
2159*064d431aSRobert Mustacchi 	smb_addinfo_t add;
2160*064d431aSRobert Mustacchi 
2161*064d431aSRobert Mustacchi 	if (stp == NULL) {
2162*064d431aSRobert Mustacchi 		return (-1); /* errno is set for us */
2163*064d431aSRobert Mustacchi 	}
2164*064d431aSRobert Mustacchi 
2165*064d431aSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_ADDINFO) {
2166*064d431aSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
2167*064d431aSRobert Mustacchi 	}
2168*064d431aSRobert Mustacchi 
2169*064d431aSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (add)) {
2170*064d431aSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
2171*064d431aSRobert Mustacchi 	}
2172*064d431aSRobert Mustacchi 
2173*064d431aSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &add, sizeof (add));
2174*064d431aSRobert Mustacchi 	*nentsp = add.smbai_nents;
2175*064d431aSRobert Mustacchi 
2176*064d431aSRobert Mustacchi 	return (0);
2177*064d431aSRobert Mustacchi }
2178*064d431aSRobert Mustacchi 
2179*064d431aSRobert Mustacchi void
smbios_info_addinfo_ent_free(smbios_hdl_t * hdl,smbios_addinfo_ent_t * ent)2180*064d431aSRobert Mustacchi smbios_info_addinfo_ent_free(smbios_hdl_t *hdl, smbios_addinfo_ent_t *ent)
2181*064d431aSRobert Mustacchi {
2182*064d431aSRobert Mustacchi 	if (ent->smbai_dlen > 0) {
2183*064d431aSRobert Mustacchi 		ASSERT3P(ent->smbai_data, !=, NULL);
2184*064d431aSRobert Mustacchi 		smb_free(ent->smbai_data, ent->smbai_dlen);
2185*064d431aSRobert Mustacchi 	}
2186*064d431aSRobert Mustacchi 
2187*064d431aSRobert Mustacchi 	smb_free(ent, sizeof (smbios_addinfo_ent_t));
2188*064d431aSRobert Mustacchi }
2189*064d431aSRobert Mustacchi 
2190*064d431aSRobert Mustacchi int
smbios_info_addinfo_ent(smbios_hdl_t * shp,id_t id,uint_t entno,smbios_addinfo_ent_t ** entp)2191*064d431aSRobert Mustacchi smbios_info_addinfo_ent(smbios_hdl_t *shp, id_t id, uint_t entno,
2192*064d431aSRobert Mustacchi     smbios_addinfo_ent_t **entp)
2193*064d431aSRobert Mustacchi {
2194*064d431aSRobert Mustacchi 	const smb_struct_t *stp = smb_lookup_id(shp, id);
2195*064d431aSRobert Mustacchi 	size_t off;
2196*064d431aSRobert Mustacchi 	smb_addinfo_t add;
2197*064d431aSRobert Mustacchi 	smb_addinfo_ent_t ent;
2198*064d431aSRobert Mustacchi 	smbios_addinfo_ent_t *entry;
2199*064d431aSRobert Mustacchi 	uint_t i;
2200*064d431aSRobert Mustacchi 
2201*064d431aSRobert Mustacchi 	if (stp == NULL) {
2202*064d431aSRobert Mustacchi 		return (-1); /* errno is set for us */
2203*064d431aSRobert Mustacchi 	}
2204*064d431aSRobert Mustacchi 
2205*064d431aSRobert Mustacchi 	if (stp->smbst_hdr->smbh_type != SMB_TYPE_ADDINFO) {
2206*064d431aSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_TYPE));
2207*064d431aSRobert Mustacchi 	}
2208*064d431aSRobert Mustacchi 
2209*064d431aSRobert Mustacchi 	if (stp->smbst_hdr->smbh_len < sizeof (add)) {
2210*064d431aSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_SHORT));
2211*064d431aSRobert Mustacchi 	}
2212*064d431aSRobert Mustacchi 
2213*064d431aSRobert Mustacchi 	smb_info_bcopy(stp->smbst_hdr, &add, sizeof (add));
2214*064d431aSRobert Mustacchi 	if (entno >= add.smbai_nents) {
2215*064d431aSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_REQVAL));
2216*064d431aSRobert Mustacchi 	}
2217*064d431aSRobert Mustacchi 
2218*064d431aSRobert Mustacchi 	off = sizeof (add);
2219*064d431aSRobert Mustacchi 	for (i = 0; i <= entno; i++) {
2220*064d431aSRobert Mustacchi 		if (off + sizeof (ent) > stp->smbst_hdr->smbh_len) {
2221*064d431aSRobert Mustacchi 			return (smb_set_errno(shp, ESMB_SHORT));
2222*064d431aSRobert Mustacchi 		}
2223*064d431aSRobert Mustacchi 
2224*064d431aSRobert Mustacchi 		smb_info_bcopy_offset(stp->smbst_hdr, &ent, sizeof (ent), off);
2225*064d431aSRobert Mustacchi 		if (ent.smbaie_len < sizeof (ent)) {
2226*064d431aSRobert Mustacchi 			return (smb_set_errno(shp, ESMB_SHORT));
2227*064d431aSRobert Mustacchi 		}
2228*064d431aSRobert Mustacchi 
2229*064d431aSRobert Mustacchi 		if (ent.smbaie_len + off > stp->smbst_hdr->smbh_len) {
2230*064d431aSRobert Mustacchi 			return (smb_set_errno(shp, ESMB_CORRUPT));
2231*064d431aSRobert Mustacchi 		}
2232*064d431aSRobert Mustacchi 
2233*064d431aSRobert Mustacchi 		if (i != entno) {
2234*064d431aSRobert Mustacchi 			off += ent.smbaie_len;
2235*064d431aSRobert Mustacchi 		}
2236*064d431aSRobert Mustacchi 	}
2237*064d431aSRobert Mustacchi 
2238*064d431aSRobert Mustacchi 	entry = smb_alloc(sizeof (smbios_addinfo_ent_t));
2239*064d431aSRobert Mustacchi 	if (entry == NULL) {
2240*064d431aSRobert Mustacchi 		return (smb_set_errno(shp, ESMB_NOMEM));
2241*064d431aSRobert Mustacchi 	}
2242*064d431aSRobert Mustacchi 
2243*064d431aSRobert Mustacchi 	entry->smbai_ref = ent.smbaie_rhdl;
2244*064d431aSRobert Mustacchi 	entry->smbai_ref_off = ent.smbaie_off;
2245*064d431aSRobert Mustacchi 	if (ent.smbaie_str != 0) {
2246*064d431aSRobert Mustacchi 		entry->smbai_str = smb_strptr(stp, ent.smbaie_str);
2247*064d431aSRobert Mustacchi 	} else {
2248*064d431aSRobert Mustacchi 		entry->smbai_str = NULL;
2249*064d431aSRobert Mustacchi 	}
2250*064d431aSRobert Mustacchi 	entry->smbai_dlen = ent.smbaie_len - sizeof (ent);
2251*064d431aSRobert Mustacchi 	if (entry->smbai_dlen > 0) {
2252*064d431aSRobert Mustacchi 		entry->smbai_data = smb_alloc(entry->smbai_dlen);
2253*064d431aSRobert Mustacchi 		if (entry->smbai_data == NULL) {
2254*064d431aSRobert Mustacchi 			smb_free(entry, sizeof (smbios_addinfo_ent_t));
2255*064d431aSRobert Mustacchi 			return (smb_set_errno(shp, ESMB_NOMEM));
2256*064d431aSRobert Mustacchi 		}
2257*064d431aSRobert Mustacchi 		smb_info_bcopy_offset(stp->smbst_hdr, entry->smbai_data,
2258*064d431aSRobert Mustacchi 		    entry->smbai_dlen, off + offsetof(smb_addinfo_ent_t,
2259*064d431aSRobert Mustacchi 		    smbaie_val));
2260*064d431aSRobert Mustacchi 	} else {
2261*064d431aSRobert Mustacchi 		entry->smbai_data = NULL;
2262*064d431aSRobert Mustacchi 	}
2263*064d431aSRobert Mustacchi 
2264*064d431aSRobert Mustacchi 	*entp = entry;
2265*064d431aSRobert Mustacchi 	return (0);
2266*064d431aSRobert Mustacchi }
2267