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