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.
25064d431aSRobert 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
24984ab085aSmws 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
264c6795799SRobert Mustacchi 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
31284ab085aSmws /*
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
334c7c09f80SEric Schrock /*
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);
531851677fbSRobert Mustacchi off_t skuoff;
532d53cdfabSRobert Mustacchi smb_chassis_t ch;
53384ab085aSmws
534d53cdfabSRobert Mustacchi if (stp == NULL) {
53584ab085aSmws return (-1); /* errno is set for us */
5366734c4b0SRobert Mustacchi }
53784ab085aSmws
538d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) {
539d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
540d53cdfabSRobert Mustacchi }
541d53cdfabSRobert Mustacchi
542851677fbSRobert Mustacchi /*
543851677fbSRobert Mustacchi * The minimum table length for the chassis is 0xd, which is the
544851677fbSRobert Mustacchi * starting point of the OEM data. This was set in SMBIOS 2.1. We don't
545851677fbSRobert Mustacchi * consider SMBIOS 2.0 tables right now.
546851677fbSRobert Mustacchi */
547851677fbSRobert Mustacchi if (stp->smbst_hdr->smbh_len < offsetof(smb_chassis_t, smbch_oemdata)) {
548d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
549d53cdfabSRobert Mustacchi }
550d53cdfabSRobert Mustacchi
551d53cdfabSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
552d53cdfabSRobert Mustacchi bzero(chp, sizeof (smb_base_chassis_t));
553d53cdfabSRobert Mustacchi
554d53cdfabSRobert Mustacchi /*
555d53cdfabSRobert Mustacchi * See the comments for the smb_chassis_pre35_t in sys/smbios_impl.h for
556d53cdfabSRobert Mustacchi * an explanation as to why this is here. The use of smb_strptr with
557d53cdfabSRobert Mustacchi * index 0 below ensures that we initialize this to an empty string.
558d53cdfabSRobert Mustacchi */
559d53cdfabSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_35)) {
560d53cdfabSRobert Mustacchi chp->smbc_sku = smb_strptr(stp, 0);
561d53cdfabSRobert Mustacchi } else if (smb_libgteq(shp, SMB_VERSION_27)) {
562d53cdfabSRobert Mustacchi smb_chassis_pre35_t *p35 = (smb_chassis_pre35_t *)chp;
563d53cdfabSRobert Mustacchi bzero(p35->smbc_sku, sizeof (p35->smbc_sku));
564d53cdfabSRobert Mustacchi }
565d53cdfabSRobert Mustacchi
566d53cdfabSRobert Mustacchi chp->smbc_oemdata = ch.smbch_oemdata;
567d53cdfabSRobert Mustacchi chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0;
568d53cdfabSRobert Mustacchi chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK;
569d53cdfabSRobert Mustacchi chp->smbc_bustate = ch.smbch_bustate;
570d53cdfabSRobert Mustacchi chp->smbc_psstate = ch.smbch_psstate;
571d53cdfabSRobert Mustacchi chp->smbc_thstate = ch.smbch_thstate;
572d53cdfabSRobert Mustacchi chp->smbc_security = ch.smbch_security;
573d53cdfabSRobert Mustacchi chp->smbc_uheight = ch.smbch_uheight;
574d53cdfabSRobert Mustacchi chp->smbc_cords = ch.smbch_cords;
575d53cdfabSRobert Mustacchi chp->smbc_elems = ch.smbch_cn;
576d53cdfabSRobert Mustacchi chp->smbc_elemlen = ch.smbch_cm;
577d53cdfabSRobert Mustacchi
578d53cdfabSRobert Mustacchi /*
579d53cdfabSRobert Mustacchi * If the table is older than version 2.7 which added support for the
580851677fbSRobert Mustacchi * chassis SKU, there's no reason to proceed. A 2.7 table is not
581851677fbSRobert Mustacchi * required to have support for a chassis SKU so we don't proceed either
582851677fbSRobert Mustacchi * if there isn't space for the SKU byte. This is very common of
583851677fbSRobert Mustacchi * hypervisors.
584d53cdfabSRobert Mustacchi */
585851677fbSRobert Mustacchi skuoff = sizeof (ch) + ch.smbch_cn * ch.smbch_cm;
586851677fbSRobert Mustacchi if (!smb_gteq(shp, SMB_VERSION_27) ||
587851677fbSRobert Mustacchi stp->smbst_hdr->smbh_len < skuoff + 1) {
588d53cdfabSRobert Mustacchi return (0);
589d53cdfabSRobert Mustacchi }
5904e901881SDale Ghent
591e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_27)) {
592d53cdfabSRobert Mustacchi uint8_t strno;
593d53cdfabSRobert Mustacchi const char *str;
594851677fbSRobert Mustacchi
595d53cdfabSRobert Mustacchi smb_info_bcopy_offset(stp->smbst_hdr, &strno, sizeof (strno),
596851677fbSRobert Mustacchi skuoff);
597d53cdfabSRobert Mustacchi str = smb_strptr(stp, strno);
598d53cdfabSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_35)) {
599d53cdfabSRobert Mustacchi chp->smbc_sku = str;
600d53cdfabSRobert Mustacchi } else {
601d53cdfabSRobert Mustacchi smb_chassis_pre35_t *p35 = (smb_chassis_pre35_t *)chp;
602d53cdfabSRobert Mustacchi (void) strlcpy(p35->smbc_sku, str,
603d53cdfabSRobert Mustacchi sizeof (p35->smbc_sku));
604d53cdfabSRobert Mustacchi }
6054e901881SDale Ghent }
60684ab085aSmws
60784ab085aSmws return (0);
60884ab085aSmws }
60984ab085aSmws
61084ab085aSmws int
smbios_info_chassis_elts(smbios_hdl_t * shp,id_t id,uint_t * nentsp,smbios_chassis_entry_t ** entsp)611d53cdfabSRobert Mustacchi smbios_info_chassis_elts(smbios_hdl_t *shp, id_t id, uint_t *nentsp,
612d53cdfabSRobert Mustacchi smbios_chassis_entry_t **entsp)
613d53cdfabSRobert Mustacchi {
614d53cdfabSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
615d53cdfabSRobert Mustacchi smbios_chassis_entry_t *entry;
616d53cdfabSRobert Mustacchi smb_chassis_t ch;
617d53cdfabSRobert Mustacchi size_t entlen;
618d53cdfabSRobert Mustacchi uint_t i;
619d53cdfabSRobert Mustacchi
620d53cdfabSRobert Mustacchi if (stp == NULL) {
621d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
622d53cdfabSRobert Mustacchi }
623d53cdfabSRobert Mustacchi
624d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) {
625d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
626d53cdfabSRobert Mustacchi }
627d53cdfabSRobert Mustacchi
628851677fbSRobert Mustacchi /*
629851677fbSRobert Mustacchi * We don't explicitly check the length of the table as it is legal for
630851677fbSRobert Mustacchi * the chassis table to be shorter than something that contains the
631851677fbSRobert Mustacchi * number of elements.
632851677fbSRobert Mustacchi */
633d53cdfabSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
634d53cdfabSRobert Mustacchi if (ch.smbch_cn == 0) {
635d53cdfabSRobert Mustacchi *nentsp = 0;
636d53cdfabSRobert Mustacchi *entsp = NULL;
637d53cdfabSRobert Mustacchi return (0);
638d53cdfabSRobert Mustacchi }
639d53cdfabSRobert Mustacchi
640851677fbSRobert Mustacchi if (ch.smbch_cm != sizeof (smb_chassis_entry_t)) {
641851677fbSRobert Mustacchi return (smb_set_errno(shp, ESMB_CORRUPT));
642851677fbSRobert Mustacchi }
643851677fbSRobert Mustacchi
644d53cdfabSRobert Mustacchi entlen = ch.smbch_cm * ch.smbch_cn;
645d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (ch) + entlen) {
646d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
647d53cdfabSRobert Mustacchi }
648d53cdfabSRobert Mustacchi
649d53cdfabSRobert Mustacchi if ((entry = smb_alloc(entlen)) == NULL) {
650d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_NOMEM));
651d53cdfabSRobert Mustacchi }
652d53cdfabSRobert Mustacchi
653d53cdfabSRobert Mustacchi for (i = 0; i < ch.smbch_cn; i++) {
654d53cdfabSRobert Mustacchi smb_chassis_entry_t e;
655d53cdfabSRobert Mustacchi size_t off = sizeof (ch) + i * sizeof (e);
656d53cdfabSRobert Mustacchi
657d53cdfabSRobert Mustacchi smb_info_bcopy_offset(stp->smbst_hdr, &e, sizeof (e), off);
658d53cdfabSRobert Mustacchi /*
659d53cdfabSRobert Mustacchi * The top bit is used to indicate what type of record this is,
660d53cdfabSRobert Mustacchi * while the lower 7-bits indicate the actual type.
661d53cdfabSRobert Mustacchi */
662d53cdfabSRobert Mustacchi entry[i].smbce_type = e.smbce_type & 0x80 ?
663d53cdfabSRobert Mustacchi SMB_CELT_SMBIOS : SMB_CELT_BBOARD;
664d53cdfabSRobert Mustacchi entry[i].smbce_elt = e.smbce_type & 0x7f;
665d53cdfabSRobert Mustacchi entry[i].smbce_min = e.smbce_min;
666d53cdfabSRobert Mustacchi entry[i].smbce_max = e.smbce_max;
667d53cdfabSRobert Mustacchi }
668d53cdfabSRobert Mustacchi
669d53cdfabSRobert Mustacchi *entsp = entry;
670d53cdfabSRobert Mustacchi *nentsp = ch.smbch_cn;
671d53cdfabSRobert Mustacchi
672d53cdfabSRobert Mustacchi return (0);
673d53cdfabSRobert Mustacchi }
674d53cdfabSRobert Mustacchi
675d53cdfabSRobert Mustacchi void
smbios_info_chassis_elts_free(smbios_hdl_t * shp,uint_t nents,smbios_chassis_entry_t * ent)676d53cdfabSRobert Mustacchi smbios_info_chassis_elts_free(smbios_hdl_t *shp, uint_t nents,
677d53cdfabSRobert Mustacchi smbios_chassis_entry_t *ent)
678d53cdfabSRobert Mustacchi {
679d53cdfabSRobert Mustacchi size_t sz = nents * sizeof (smbios_chassis_entry_t);
680d53cdfabSRobert Mustacchi
681d53cdfabSRobert Mustacchi if (nents == 0) {
682d53cdfabSRobert Mustacchi ASSERT3P(ent, ==, NULL);
683d53cdfabSRobert Mustacchi return;
684d53cdfabSRobert Mustacchi }
685d53cdfabSRobert Mustacchi
686d53cdfabSRobert Mustacchi smb_free(ent, sz);
687d53cdfabSRobert Mustacchi }
688d53cdfabSRobert Mustacchi
689d53cdfabSRobert Mustacchi int
smbios_info_processor(smbios_hdl_t * shp,id_t id,smbios_processor_t * pp)69084ab085aSmws smbios_info_processor(smbios_hdl_t *shp, id_t id, smbios_processor_t *pp)
69184ab085aSmws {
69284ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
69384ab085aSmws smb_processor_t p;
69484ab085aSmws
69584ab085aSmws if (stp == NULL)
69684ab085aSmws return (-1); /* errno is set for us */
69784ab085aSmws
69884ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR)
69984ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
70084ab085aSmws
70184ab085aSmws smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p));
7026734c4b0SRobert Mustacchi bzero(pp, sizeof (smb_base_processor_t));
70384ab085aSmws
70484ab085aSmws pp->smbp_cpuid = p.smbpr_cpuid;
70584ab085aSmws pp->smbp_type = p.smbpr_type;
70684ab085aSmws pp->smbp_family = p.smbpr_family;
70784ab085aSmws pp->smbp_voltage = p.smbpr_voltage;
7081d1fc316SRobert Mustacchi pp->smbp_clkspeed = p.smbpr_clkspeed;
70984ab085aSmws pp->smbp_maxspeed = p.smbpr_maxspeed;
71084ab085aSmws pp->smbp_curspeed = p.smbpr_curspeed;
71184ab085aSmws pp->smbp_status = p.smbpr_status;
71284ab085aSmws pp->smbp_upgrade = p.smbpr_upgrade;
71384ab085aSmws pp->smbp_l1cache = p.smbpr_l1cache;
71484ab085aSmws pp->smbp_l2cache = p.smbpr_l2cache;
71584ab085aSmws pp->smbp_l3cache = p.smbpr_l3cache;
71684ab085aSmws
717e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_25)) {
7184e901881SDale Ghent pp->smbp_corecount = p.smbpr_corecount;
7194e901881SDale Ghent pp->smbp_coresenabled = p.smbpr_coresenabled;
7204e901881SDale Ghent pp->smbp_threadcount = p.smbpr_threadcount;
7214e901881SDale Ghent pp->smbp_cflags = p.smbpr_cflags;
7224e901881SDale Ghent }
7234e901881SDale Ghent
724e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_26)) {
725176a9270SRobert Mustacchi if (pp->smbp_family == 0xfe) {
726176a9270SRobert Mustacchi pp->smbp_family = p.smbpr_family2;
727176a9270SRobert Mustacchi }
728e5cce96fSRobert Mustacchi }
7294e901881SDale Ghent
730e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_30)) {
731176a9270SRobert Mustacchi if (pp->smbp_corecount == 0xff) {
732176a9270SRobert Mustacchi pp->smbp_corecount = p.smbpr_corecount2;
733176a9270SRobert Mustacchi }
734176a9270SRobert Mustacchi if (pp->smbp_coresenabled == 0xff) {
735176a9270SRobert Mustacchi pp->smbp_coresenabled = p.smbpr_coresenabled2;
736176a9270SRobert Mustacchi }
737176a9270SRobert Mustacchi if (pp->smbp_threadcount == 0xff) {
738176a9270SRobert Mustacchi pp->smbp_threadcount = p.smbpr_threadcount2;
739176a9270SRobert Mustacchi }
7406734c4b0SRobert Mustacchi }
7416734c4b0SRobert Mustacchi
7421d1fc316SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_36)) {
743*49f72993SRobert Mustacchi pp->smbp_threadsenabled = p.smbpr_threaden;
744*49f72993SRobert Mustacchi }
745*49f72993SRobert Mustacchi
746*49f72993SRobert Mustacchi /*
747*49f72993SRobert Mustacchi * SMBIOS 3.8 added a socket string which is only required if the
748*49f72993SRobert Mustacchi * processor upgrade constant is not present. We don't try to munge
749*49f72993SRobert Mustacchi * these two together here and leave it to clients to figure out
750*49f72993SRobert Mustacchi * (especially as what'll happen in practice is unknown).
751*49f72993SRobert Mustacchi */
752*49f72993SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_38)) {
753*49f72993SRobert Mustacchi pp->smbp_socktype = smb_strptr(stp, p.smbpr_socktype);
7541d1fc316SRobert Mustacchi }
7551d1fc316SRobert Mustacchi
75684ab085aSmws return (0);
75784ab085aSmws }
75884ab085aSmws
75984ab085aSmws int
smbios_info_cache(smbios_hdl_t * shp,id_t id,smbios_cache_t * cap)76084ab085aSmws smbios_info_cache(smbios_hdl_t *shp, id_t id, smbios_cache_t *cap)
76184ab085aSmws {
76284ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
76384ab085aSmws smb_cache_t c;
76484ab085aSmws
76584ab085aSmws if (stp == NULL)
76684ab085aSmws return (-1); /* errno is set for us */
76784ab085aSmws
76884ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_CACHE)
76984ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
77084ab085aSmws
77184ab085aSmws smb_info_bcopy(stp->smbst_hdr, &c, sizeof (c));
772e5cce96fSRobert Mustacchi bzero(cap, sizeof (smb_base_cache_t));
77384ab085aSmws
77484ab085aSmws cap->smba_maxsize = SMB_CACHE_SIZE(c.smbca_maxsize);
77584ab085aSmws cap->smba_size = SMB_CACHE_SIZE(c.smbca_size);
77684ab085aSmws cap->smba_stype = c.smbca_stype;
77784ab085aSmws cap->smba_ctype = c.smbca_ctype;
77884ab085aSmws cap->smba_speed = c.smbca_speed;
77984ab085aSmws cap->smba_etype = c.smbca_etype;
78084ab085aSmws cap->smba_ltype = c.smbca_ltype;
78184ab085aSmws cap->smba_assoc = c.smbca_assoc;
78284ab085aSmws cap->smba_level = SMB_CACHE_CFG_LEVEL(c.smbca_config);
78384ab085aSmws cap->smba_mode = SMB_CACHE_CFG_MODE(c.smbca_config);
78484ab085aSmws cap->smba_location = SMB_CACHE_CFG_LOCATION(c.smbca_config);
78584ab085aSmws
78684ab085aSmws if (SMB_CACHE_CFG_ENABLED(c.smbca_config))
78784ab085aSmws cap->smba_flags |= SMB_CAF_ENABLED;
78884ab085aSmws
78984ab085aSmws if (SMB_CACHE_CFG_SOCKETED(c.smbca_config))
79084ab085aSmws cap->smba_flags |= SMB_CAF_SOCKETED;
79184ab085aSmws
792e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_31)) {
7931566bc34SRobert Mustacchi cap->smba_maxsize2 = SMB_CACHE_EXT_SIZE(c.smbca_maxsize2);
794e5cce96fSRobert Mustacchi cap->smba_size2 = SMB_CACHE_EXT_SIZE(c.smbca_size2);
7951566bc34SRobert Mustacchi
7961566bc34SRobert Mustacchi if (cap->smba_maxsize2 == 0) {
797e5cce96fSRobert Mustacchi cap->smba_maxsize2 = cap->smba_maxsize;
7981566bc34SRobert Mustacchi }
7991566bc34SRobert Mustacchi
8001566bc34SRobert Mustacchi if (cap->smba_size2 == 0) {
801e5cce96fSRobert Mustacchi cap->smba_size2 = cap->smba_size;
802e5cce96fSRobert Mustacchi }
803e5cce96fSRobert Mustacchi }
804e5cce96fSRobert Mustacchi
80584ab085aSmws return (0);
80684ab085aSmws }
80784ab085aSmws
80884ab085aSmws int
smbios_info_port(smbios_hdl_t * shp,id_t id,smbios_port_t * pop)80984ab085aSmws smbios_info_port(smbios_hdl_t *shp, id_t id, smbios_port_t *pop)
81084ab085aSmws {
81184ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
81284ab085aSmws smb_port_t p;
81384ab085aSmws
81484ab085aSmws if (stp == NULL)
81584ab085aSmws return (-1); /* errno is set for us */
81684ab085aSmws
81784ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_PORT)
81884ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
81984ab085aSmws
82084ab085aSmws smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p));
82184ab085aSmws bzero(pop, sizeof (smbios_port_t));
82284ab085aSmws
82384ab085aSmws pop->smbo_iref = smb_strptr(stp, p.smbpo_iref);
82484ab085aSmws pop->smbo_eref = smb_strptr(stp, p.smbpo_eref);
82584ab085aSmws
82684ab085aSmws pop->smbo_itype = p.smbpo_itype;
82784ab085aSmws pop->smbo_etype = p.smbpo_etype;
82884ab085aSmws pop->smbo_ptype = p.smbpo_ptype;
82984ab085aSmws
83084ab085aSmws return (0);
83184ab085aSmws }
83284ab085aSmws
83384ab085aSmws int
smbios_info_slot(smbios_hdl_t * shp,id_t id,smbios_slot_t * sp)83484ab085aSmws smbios_info_slot(smbios_hdl_t *shp, id_t id, smbios_slot_t *sp)
83584ab085aSmws {
83684ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
83784ab085aSmws smb_slot_t s;
838c6795799SRobert Mustacchi smb_slot_cont_t cont;
839c6795799SRobert Mustacchi size_t off;
84084ab085aSmws
84184ab085aSmws if (stp == NULL)
84284ab085aSmws return (-1); /* errno is set for us */
84384ab085aSmws
84484ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT)
84584ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
84684ab085aSmws
84784ab085aSmws smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
8481566bc34SRobert Mustacchi bzero(sp, sizeof (smb_base_slot_t));
84984ab085aSmws
85084ab085aSmws sp->smbl_name = smb_strptr(stp, s.smbsl_name);
85184ab085aSmws sp->smbl_type = s.smbsl_type;
85284ab085aSmws sp->smbl_width = s.smbsl_width;
85384ab085aSmws sp->smbl_usage = s.smbsl_usage;
85484ab085aSmws sp->smbl_length = s.smbsl_length;
85584ab085aSmws sp->smbl_id = s.smbsl_id;
85684ab085aSmws sp->smbl_ch1 = s.smbsl_ch1;
85784ab085aSmws sp->smbl_ch2 = s.smbsl_ch2;
85803f9f63dSTom Pothier sp->smbl_sg = s.smbsl_sg;
85903f9f63dSTom Pothier sp->smbl_bus = s.smbsl_bus;
86003f9f63dSTom Pothier sp->smbl_df = s.smbsl_df;
86103f9f63dSTom Pothier
8621566bc34SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_32)) {
8631566bc34SRobert Mustacchi sp->smbl_dbw = s.smbsl_dbw;
8641566bc34SRobert Mustacchi sp->smbl_npeers = s.smbsl_npeers;
8651566bc34SRobert Mustacchi }
8661566bc34SRobert Mustacchi
867c6795799SRobert Mustacchi if (!smb_libgteq(shp, SMB_VERSION_34)) {
868c6795799SRobert Mustacchi return (0);
869c6795799SRobert Mustacchi }
870c6795799SRobert Mustacchi
871c6795799SRobert Mustacchi /*
872c6795799SRobert Mustacchi * In SMBIOS 3.4, several members were added to follow the variable
873c6795799SRobert Mustacchi * number of peers. These are defined to start at byte 0x14 + 5 *
874c6795799SRobert Mustacchi * npeers. If the table is from before 3.4, we simple zero things out.
875c6795799SRobert Mustacchi * Otherwise we check if the length covers the peers and this addendum
876c6795799SRobert Mustacchi * to include it as the table length is allowed to be less than this and
877c6795799SRobert Mustacchi * not include it.
878c6795799SRobert Mustacchi */
879c6795799SRobert Mustacchi off = SMB_SLOT_CONT_START + 5 * s.smbsl_npeers;
880c6795799SRobert Mustacchi smb_info_bcopy_offset(stp->smbst_hdr, &cont, sizeof (cont), off);
881c6795799SRobert Mustacchi sp->smbl_info = cont.smbsl_info;
882c6795799SRobert Mustacchi sp->smbl_pwidth = cont.smbsl_pwidth;
883c6795799SRobert Mustacchi sp->smbl_pitch = cont.smbsl_pitch;
884c6795799SRobert Mustacchi
885d53cdfabSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_35)) {
886d53cdfabSRobert Mustacchi sp->smbl_height = cont.smbsl_height;
887d53cdfabSRobert Mustacchi }
888d53cdfabSRobert Mustacchi
8891566bc34SRobert Mustacchi return (0);
8901566bc34SRobert Mustacchi }
8911566bc34SRobert Mustacchi
8921566bc34SRobert Mustacchi void
smbios_info_slot_peers_free(smbios_hdl_t * shp,uint_t npeers,smbios_slot_peer_t * peer)8931566bc34SRobert Mustacchi smbios_info_slot_peers_free(smbios_hdl_t *shp, uint_t npeers,
8941566bc34SRobert Mustacchi smbios_slot_peer_t *peer)
8951566bc34SRobert Mustacchi {
8961566bc34SRobert Mustacchi size_t sz = npeers * sizeof (smbios_slot_peer_t);
8971566bc34SRobert Mustacchi
8981566bc34SRobert Mustacchi if (npeers == 0) {
8991566bc34SRobert Mustacchi ASSERT3P(peer, ==, NULL);
9001566bc34SRobert Mustacchi return;
9011566bc34SRobert Mustacchi }
9021566bc34SRobert Mustacchi
9031566bc34SRobert Mustacchi smb_free(peer, sz);
9041566bc34SRobert Mustacchi }
9051566bc34SRobert Mustacchi
9061566bc34SRobert Mustacchi int
smbios_info_slot_peers(smbios_hdl_t * shp,id_t id,uint_t * npeers,smbios_slot_peer_t ** peerp)9071566bc34SRobert Mustacchi smbios_info_slot_peers(smbios_hdl_t *shp, id_t id, uint_t *npeers,
9081566bc34SRobert Mustacchi smbios_slot_peer_t **peerp)
9091566bc34SRobert Mustacchi {
9101566bc34SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
91116dde076SJohn Levon const smb_slot_t *slotp;
9121566bc34SRobert Mustacchi smbios_slot_peer_t *peer;
9131566bc34SRobert Mustacchi size_t minlen;
9141566bc34SRobert Mustacchi uint_t i;
9151566bc34SRobert Mustacchi
9161566bc34SRobert Mustacchi if (stp == NULL)
9171566bc34SRobert Mustacchi return (-1); /* errno is set for us */
9181566bc34SRobert Mustacchi
91916dde076SJohn Levon slotp = (const smb_slot_t *)stp->smbst_hdr;
92016dde076SJohn Levon
9211566bc34SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT)
9221566bc34SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
9231566bc34SRobert Mustacchi
9241566bc34SRobert Mustacchi if (stp->smbst_hdr->smbh_len <= offsetof(smb_slot_t, smbsl_npeers) ||
9251566bc34SRobert Mustacchi slotp->smbsl_npeers == 0) {
9261566bc34SRobert Mustacchi *npeers = 0;
9271566bc34SRobert Mustacchi *peerp = NULL;
9281566bc34SRobert Mustacchi return (0);
9291566bc34SRobert Mustacchi }
9301566bc34SRobert Mustacchi
9311566bc34SRobert Mustacchi /*
9321566bc34SRobert Mustacchi * Make sure that the size of the structure makes sense for the number
9331566bc34SRobert Mustacchi * of peers reported.
9341566bc34SRobert Mustacchi */
9351566bc34SRobert Mustacchi minlen = slotp->smbsl_npeers * sizeof (smb_slot_peer_t) +
9361566bc34SRobert Mustacchi offsetof(smb_slot_t, smbsl_npeers);
9371566bc34SRobert Mustacchi if (stp->smbst_hdr->smbh_len < minlen) {
9381566bc34SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
9391566bc34SRobert Mustacchi }
9401566bc34SRobert Mustacchi
9411566bc34SRobert Mustacchi if ((peer = smb_alloc(slotp->smbsl_npeers *
9421566bc34SRobert Mustacchi sizeof (smbios_slot_peer_t))) == NULL) {
9431566bc34SRobert Mustacchi return (smb_set_errno(shp, ESMB_NOMEM));
9441566bc34SRobert Mustacchi }
9451566bc34SRobert Mustacchi
9461566bc34SRobert Mustacchi for (i = 0; i < slotp->smbsl_npeers; i++) {
9471566bc34SRobert Mustacchi peer[i].smblp_group = slotp->smbsl_peers[i].smbspb_group_no;
9481566bc34SRobert Mustacchi peer[i].smblp_bus = slotp->smbsl_peers[i].smbspb_bus;
9491566bc34SRobert Mustacchi peer[i].smblp_device = slotp->smbsl_peers[i].smbspb_df >> 3;
9501566bc34SRobert Mustacchi peer[i].smblp_function = slotp->smbsl_peers[i].smbspb_df & 0x7;
9511566bc34SRobert Mustacchi peer[i].smblp_data_width = slotp->smbsl_peers[i].smbspb_width;
9521566bc34SRobert Mustacchi }
9531566bc34SRobert Mustacchi
9541566bc34SRobert Mustacchi *npeers = slotp->smbsl_npeers;
9551566bc34SRobert Mustacchi *peerp = peer;
9561566bc34SRobert Mustacchi
95703f9f63dSTom Pothier return (0);
95803f9f63dSTom Pothier }
95903f9f63dSTom Pothier
96003f9f63dSTom Pothier int
smbios_info_obdevs_ext(smbios_hdl_t * shp,id_t id,smbios_obdev_ext_t * oep)96103f9f63dSTom Pothier smbios_info_obdevs_ext(smbios_hdl_t *shp, id_t id, smbios_obdev_ext_t *oep)
96203f9f63dSTom Pothier {
96303f9f63dSTom Pothier const smb_struct_t *stp = smb_lookup_id(shp, id);
96403f9f63dSTom Pothier smb_obdev_ext_t obe;
96503f9f63dSTom Pothier
96603f9f63dSTom Pothier if (stp == NULL)
96703f9f63dSTom Pothier return (-1); /* errno is set for us */
96803f9f63dSTom Pothier
96903f9f63dSTom Pothier if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVEXT)
97003f9f63dSTom Pothier return (smb_set_errno(shp, ESMB_TYPE));
97103f9f63dSTom Pothier
97203f9f63dSTom Pothier smb_info_bcopy(stp->smbst_hdr, &obe, sizeof (obe));
97303f9f63dSTom Pothier bzero(oep, sizeof (smbios_obdev_ext_t));
97403f9f63dSTom Pothier
97503f9f63dSTom Pothier oep->smboe_name = smb_strptr(stp, obe.smbobe_name);
97603f9f63dSTom Pothier oep->smboe_dtype = obe.smbobe_dtype;
97703f9f63dSTom Pothier oep->smboe_dti = obe.smbobe_dti;
97803f9f63dSTom Pothier oep->smboe_sg = obe.smbobe_sg;
97903f9f63dSTom Pothier oep->smboe_bus = obe.smbobe_bus;
98003f9f63dSTom Pothier oep->smboe_df = obe.smbobe_df;
98184ab085aSmws
98284ab085aSmws return (0);
98384ab085aSmws }
98484ab085aSmws
98584ab085aSmws int
smbios_info_obdevs(smbios_hdl_t * shp,id_t id,int obc,smbios_obdev_t * obp)98684ab085aSmws smbios_info_obdevs(smbios_hdl_t *shp, id_t id, int obc, smbios_obdev_t *obp)
98784ab085aSmws {
98884ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
98984ab085aSmws const smb_obdev_t *op;
99084ab085aSmws int i, m, n;
99184ab085aSmws
99284ab085aSmws if (stp == NULL)
99384ab085aSmws return (-1); /* errno is set for us */
99484ab085aSmws
99584ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVS)
99684ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
99784ab085aSmws
99884ab085aSmws op = (smb_obdev_t *)((uintptr_t)stp->smbst_hdr + sizeof (smb_header_t));
99984ab085aSmws m = (stp->smbst_hdr->smbh_len - sizeof (smb_header_t)) / sizeof (*op);
100084ab085aSmws n = MIN(m, obc);
100184ab085aSmws
100284ab085aSmws for (i = 0; i < n; i++, op++, obp++) {
100384ab085aSmws obp->smbd_name = smb_strptr(stp, op->smbob_name);
100484ab085aSmws obp->smbd_type = op->smbob_type & ~SMB_OBT_ENABLED;
100584ab085aSmws obp->smbd_enabled = (op->smbob_type & SMB_OBT_ENABLED) != 0;
100684ab085aSmws }
100784ab085aSmws
100884ab085aSmws return (m);
100984ab085aSmws }
101084ab085aSmws
101184ab085aSmws /*
101284ab085aSmws * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the
101384ab085aSmws * first byte to indicate the size of a string table at the end of the record.
101484ab085aSmws * Therefore, smbios_info_strtab() can be used to retrieve the table size and
101584ab085aSmws * strings for any of these underlying record types.
101684ab085aSmws */
101784ab085aSmws int
smbios_info_strtab(smbios_hdl_t * shp,id_t id,int argc,const char * argv[])101884ab085aSmws smbios_info_strtab(smbios_hdl_t *shp, id_t id, int argc, const char *argv[])
101984ab085aSmws {
102084ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
102184ab085aSmws smb_strtab_t s;
102284ab085aSmws int i, n;
102384ab085aSmws
102484ab085aSmws if (stp == NULL)
102584ab085aSmws return (-1); /* errno is set for us */
102684ab085aSmws
102784ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR &&
102884ab085aSmws stp->smbst_hdr->smbh_type != SMB_TYPE_SYSCONFSTR &&
102984ab085aSmws stp->smbst_hdr->smbh_type != SMB_TYPE_LANG)
103084ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
103184ab085aSmws
103284ab085aSmws smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
103384ab085aSmws n = MIN(s.smbtb_count, argc);
103484ab085aSmws
103584ab085aSmws for (i = 0; i < n; i++)
103684ab085aSmws argv[i] = smb_strptr(stp, i + 1);
103784ab085aSmws
103884ab085aSmws return (s.smbtb_count);
103984ab085aSmws }
104084ab085aSmws
104184ab085aSmws id_t
smbios_info_lang(smbios_hdl_t * shp,smbios_lang_t * lp)104284ab085aSmws smbios_info_lang(smbios_hdl_t *shp, smbios_lang_t *lp)
104384ab085aSmws {
104484ab085aSmws const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_LANG);
104584ab085aSmws smb_lang_t l;
104684ab085aSmws
104784ab085aSmws if (stp == NULL)
104884ab085aSmws return (-1); /* errno is set for us */
104984ab085aSmws
105084ab085aSmws smb_info_bcopy(stp->smbst_hdr, &l, sizeof (l));
105184ab085aSmws bzero(lp, sizeof (smbios_lang_t));
105284ab085aSmws
105384ab085aSmws lp->smbla_cur = smb_strptr(stp, l.smblang_cur);
105484ab085aSmws lp->smbla_fmt = l.smblang_flags & 1;
105584ab085aSmws lp->smbla_num = l.smblang_num;
105684ab085aSmws
105784ab085aSmws return (stp->smbst_hdr->smbh_hdl);
105884ab085aSmws }
105984ab085aSmws
106084ab085aSmws id_t
smbios_info_eventlog(smbios_hdl_t * shp,smbios_evlog_t * evp)106184ab085aSmws smbios_info_eventlog(smbios_hdl_t *shp, smbios_evlog_t *evp)
106284ab085aSmws {
106384ab085aSmws const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_EVENTLOG);
106484ab085aSmws const smb_sel_t *sel;
106584ab085aSmws size_t len;
106684ab085aSmws
106784ab085aSmws if (stp == NULL)
106884ab085aSmws return (-1); /* errno is set for us */
106984ab085aSmws
107084ab085aSmws if (stp->smbst_hdr->smbh_len < sizeof (smb_sel_t) - sizeof (uint8_t))
107184ab085aSmws return (smb_set_errno(shp, ESMB_CORRUPT));
107284ab085aSmws
107384ab085aSmws sel = (smb_sel_t *)(uintptr_t)stp->smbst_hdr;
107484ab085aSmws len = stp->smbst_hdr->smbh_len - sizeof (smb_sel_t) + sizeof (uint8_t);
107584ab085aSmws bzero(evp, sizeof (smbios_evlog_t));
107684ab085aSmws
107784ab085aSmws if (len < sel->smbsel_typec * sel->smbsel_typesz)
107884ab085aSmws return (smb_set_errno(shp, ESMB_CORRUPT));
107984ab085aSmws
108084ab085aSmws evp->smbev_size = sel->smbsel_len;
108184ab085aSmws evp->smbev_hdr = sel->smbsel_hdroff;
108284ab085aSmws evp->smbev_data = sel->smbsel_dataoff;
108384ab085aSmws evp->smbev_method = sel->smbsel_method;
108484ab085aSmws evp->smbev_flags = sel->smbsel_status;
108584ab085aSmws evp->smbev_format = sel->smbsel_format;
108684ab085aSmws evp->smbev_token = sel->smbsel_token;
108784ab085aSmws evp->smbev_addr.eva_addr = sel->smbsel_addr;
108884ab085aSmws
108984ab085aSmws if (sel->smbsel_typesz == sizeof (smbios_evtype_t)) {
109084ab085aSmws evp->smbev_typec = sel->smbsel_typec;
109184ab085aSmws evp->smbev_typev = (void *)(uintptr_t)sel->smbsel_typev;
109284ab085aSmws }
109384ab085aSmws
109484ab085aSmws return (stp->smbst_hdr->smbh_hdl);
109584ab085aSmws }
109684ab085aSmws
109784ab085aSmws int
smbios_info_memarray(smbios_hdl_t * shp,id_t id,smbios_memarray_t * map)109884ab085aSmws smbios_info_memarray(smbios_hdl_t *shp, id_t id, smbios_memarray_t *map)
109984ab085aSmws {
110084ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
110184ab085aSmws smb_memarray_t m;
110284ab085aSmws
110384ab085aSmws if (stp == NULL)
110484ab085aSmws return (-1); /* errno is set for us */
110584ab085aSmws
110684ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAY)
110784ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
110884ab085aSmws
110984ab085aSmws smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
111084ab085aSmws bzero(map, sizeof (smbios_memarray_t));
111184ab085aSmws
111284ab085aSmws map->smbma_location = m.smbmarr_loc;
111384ab085aSmws map->smbma_use = m.smbmarr_use;
111484ab085aSmws map->smbma_ecc = m.smbmarr_ecc;
111584ab085aSmws map->smbma_ndevs = m.smbmarr_ndevs;
111684ab085aSmws map->smbma_err = m.smbmarr_err;
111784ab085aSmws
111884ab085aSmws if (m.smbmarr_cap != 0x80000000)
111984ab085aSmws map->smbma_size = (uint64_t)m.smbmarr_cap * 1024;
11204e901881SDale Ghent else if (m.smbmarr_extcap != 0)
11214e901881SDale Ghent map->smbma_size = m.smbmarr_extcap;
112284ab085aSmws else
112384ab085aSmws map->smbma_size = 0; /* unknown */
112484ab085aSmws
112584ab085aSmws return (0);
112684ab085aSmws }
112784ab085aSmws
112884ab085aSmws int
smbios_info_memarrmap(smbios_hdl_t * shp,id_t id,smbios_memarrmap_t * map)112984ab085aSmws smbios_info_memarrmap(smbios_hdl_t *shp, id_t id, smbios_memarrmap_t *map)
113084ab085aSmws {
113184ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
113284ab085aSmws smb_memarrmap_t m;
113384ab085aSmws
113484ab085aSmws if (stp == NULL)
113584ab085aSmws return (-1); /* errno is set for us */
113684ab085aSmws
113784ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAYMAP)
113884ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
113984ab085aSmws
114084ab085aSmws smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
114184ab085aSmws bzero(map, sizeof (smbios_memarrmap_t));
114284ab085aSmws
114384ab085aSmws map->smbmam_array = m.smbamap_array;
114484ab085aSmws map->smbmam_width = m.smbamap_width;
11454e901881SDale Ghent
11464e901881SDale Ghent if (m.smbamap_start != 0xFFFFFFFF && m.smbamap_end != 0xFFFFFFFF) {
114784ab085aSmws map->smbmam_addr = (uint64_t)m.smbamap_start * 1024;
114884ab085aSmws map->smbmam_size = (uint64_t)
114984ab085aSmws (m.smbamap_end - m.smbamap_start + 1) * 1024;
11504e901881SDale Ghent } else if (m.smbamap_extstart != 0 && m.smbamap_extend != 0) {
11514e901881SDale Ghent map->smbmam_addr = m.smbamap_extstart;
11524e901881SDale Ghent map->smbmam_size = m.smbamap_extend - m.smbamap_extstart + 1;
11534e901881SDale Ghent }
115484ab085aSmws
115584ab085aSmws return (0);
115684ab085aSmws }
115784ab085aSmws
115884ab085aSmws int
smbios_info_memdevice(smbios_hdl_t * shp,id_t id,smbios_memdevice_t * mdp)115984ab085aSmws smbios_info_memdevice(smbios_hdl_t *shp, id_t id, smbios_memdevice_t *mdp)
116084ab085aSmws {
116184ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
116284ab085aSmws smb_memdevice_t m;
116384ab085aSmws
116484ab085aSmws if (stp == NULL)
116584ab085aSmws return (-1); /* errno is set for us */
116684ab085aSmws
116784ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICE)
116884ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
116984ab085aSmws
117084ab085aSmws smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
11716734c4b0SRobert Mustacchi bzero(mdp, sizeof (smb_base_memdevice_t));
117284ab085aSmws
117384ab085aSmws mdp->smbmd_array = m.smbmdev_array;
117484ab085aSmws mdp->smbmd_error = m.smbmdev_error;
117584ab085aSmws mdp->smbmd_twidth = m.smbmdev_twidth == 0xFFFF ? -1U : m.smbmdev_twidth;
117684ab085aSmws mdp->smbmd_dwidth = m.smbmdev_dwidth == 0xFFFF ? -1U : m.smbmdev_dwidth;
117784ab085aSmws
11784e901881SDale Ghent if (m.smbmdev_size == 0x7FFF) {
11794e901881SDale Ghent mdp->smbmd_size = (uint64_t)m.smbmdev_extsize;
11804e901881SDale Ghent mdp->smbmd_size *= 1024 * 1024; /* convert MB to bytes */
11814e901881SDale Ghent } else if (m.smbmdev_size != 0xFFFF) {
118284ab085aSmws mdp->smbmd_size = (uint64_t)(m.smbmdev_size & ~SMB_MDS_KBYTES);
118384ab085aSmws if (m.smbmdev_size & SMB_MDS_KBYTES)
118484ab085aSmws mdp->smbmd_size *= 1024;
118584ab085aSmws else
118684ab085aSmws mdp->smbmd_size *= 1024 * 1024;
118784ab085aSmws } else
118884ab085aSmws mdp->smbmd_size = -1ULL; /* size unknown */
118984ab085aSmws
119084ab085aSmws mdp->smbmd_form = m.smbmdev_form;
119184ab085aSmws mdp->smbmd_set = m.smbmdev_set;
119284ab085aSmws mdp->smbmd_type = m.smbmdev_type;
11934e901881SDale Ghent mdp->smbmd_speed = m.smbmdev_speed;
119484ab085aSmws mdp->smbmd_flags = m.smbmdev_flags;
119584ab085aSmws mdp->smbmd_dloc = smb_strptr(stp, m.smbmdev_dloc);
119684ab085aSmws mdp->smbmd_bloc = smb_strptr(stp, m.smbmdev_bloc);
119784ab085aSmws
1198e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_26)) {
11994e901881SDale Ghent mdp->smbmd_rank = m.smbmdev_attrs & 0x0F;
1200e5cce96fSRobert Mustacchi }
12014e901881SDale Ghent
1202e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_27)) {
12034e901881SDale Ghent mdp->smbmd_clkspeed = m.smbmdev_clkspeed;
1204e5cce96fSRobert Mustacchi }
12054e901881SDale Ghent
1206e5cce96fSRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_28)) {
12074e901881SDale Ghent mdp->smbmd_minvolt = m.smbmdev_minvolt;
12084e901881SDale Ghent mdp->smbmd_maxvolt = m.smbmdev_maxvolt;
12094e901881SDale Ghent mdp->smbmd_confvolt = m.smbmdev_confvolt;
12104e901881SDale Ghent }
121184ab085aSmws
12121566bc34SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_32)) {
12131566bc34SRobert Mustacchi mdp->smbmd_memtech = m.smbmdev_memtech;
12141566bc34SRobert Mustacchi mdp->smbmd_opcap_flags = m.smbmdev_opmode;
12151566bc34SRobert Mustacchi mdp->smbmd_firmware_rev = smb_strptr(stp,
12161566bc34SRobert Mustacchi m.smbmdev_fwver);
12171566bc34SRobert Mustacchi mdp->smbmd_modmfg_id = m.smbmdev_modulemfgid;
12181566bc34SRobert Mustacchi mdp->smbmd_modprod_id = m.smbmdev_moduleprodid;
12191566bc34SRobert Mustacchi mdp->smbmd_cntrlmfg_id = m.smbmdev_memsysmfgid;
12201566bc34SRobert Mustacchi mdp->smbmd_cntrlprod_id = m.smbmdev_memsysprodid;
12211566bc34SRobert Mustacchi mdp->smbmd_nvsize = m.smbmdev_nvsize;
12221566bc34SRobert Mustacchi mdp->smbmd_volatile_size = m.smbmdev_volsize;
12231566bc34SRobert Mustacchi mdp->smbmd_cache_size = m.smbmdev_cachesize;
12241566bc34SRobert Mustacchi mdp->smbmd_logical_size = m.smbmdev_logicalsize;
12251566bc34SRobert Mustacchi }
12261566bc34SRobert Mustacchi
1227176a9270SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_33)) {
1228176a9270SRobert Mustacchi if (m.smbmdev_speed == 0xffff) {
1229176a9270SRobert Mustacchi mdp->smbmd_extspeed = m.smbmdev_extspeed;
1230176a9270SRobert Mustacchi } else {
1231176a9270SRobert Mustacchi mdp->smbmd_extspeed = m.smbmdev_speed;
1232176a9270SRobert Mustacchi }
1233176a9270SRobert Mustacchi
1234176a9270SRobert Mustacchi if (m.smbmdev_clkspeed == 0xffff) {
1235176a9270SRobert Mustacchi mdp->smbmd_extclkspeed = m.smbmdev_extclkspeed;
1236176a9270SRobert Mustacchi } else {
1237176a9270SRobert Mustacchi mdp->smbmd_extclkspeed = m.smbmdev_clkspeed;
1238176a9270SRobert Mustacchi }
1239176a9270SRobert Mustacchi }
1240176a9270SRobert Mustacchi
12416bc074b1SRobert Mustacchi /*
12426bc074b1SRobert Mustacchi * The unknown key for missing revision information for the RCD and
12436bc074b1SRobert Mustacchi * PMIC0 is not all zeros. As such, we need to look if the device SMBIOS
12446bc074b1SRobert Mustacchi * table is not 3.7 then we need to fix up the bits that we copied.
12456bc074b1SRobert Mustacchi * After that we need to go back and check the consumer's version to
12466bc074b1SRobert Mustacchi * actually place this data there.
12476bc074b1SRobert Mustacchi */
12486bc074b1SRobert Mustacchi if (!smb_gteq(shp, SMB_VERSION_37)) {
12496bc074b1SRobert Mustacchi m.smbmdev_pmic0mfgid = SMB_MD_MFG_UNKNOWN;
12506bc074b1SRobert Mustacchi m.smbmdev_pmic0rev = SMB_MD_REV_UNKNOWN;
12516bc074b1SRobert Mustacchi m.smbmdev_rcdmfgid = SMB_MD_MFG_UNKNOWN;
12526bc074b1SRobert Mustacchi m.smbmdev_rcdrev = SMB_MD_REV_UNKNOWN;
12536bc074b1SRobert Mustacchi }
12546bc074b1SRobert Mustacchi
12556bc074b1SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_37)) {
12566bc074b1SRobert Mustacchi mdp->smbmd_pmic0_mfgid = m.smbmdev_pmic0mfgid;
12576bc074b1SRobert Mustacchi mdp->smbmd_pmic0_rev = m.smbmdev_pmic0rev;
12586bc074b1SRobert Mustacchi mdp->smbmd_rcd_mfgid = m.smbmdev_rcdmfgid;
12596bc074b1SRobert Mustacchi mdp->smbmd_rcd_rev = m.smbmdev_rcdrev;
12606bc074b1SRobert Mustacchi }
12616bc074b1SRobert Mustacchi
126284ab085aSmws return (0);
126384ab085aSmws }
126484ab085aSmws
126584ab085aSmws int
smbios_info_memdevmap(smbios_hdl_t * shp,id_t id,smbios_memdevmap_t * mdp)126684ab085aSmws smbios_info_memdevmap(smbios_hdl_t *shp, id_t id, smbios_memdevmap_t *mdp)
126784ab085aSmws {
126884ab085aSmws const smb_struct_t *stp = smb_lookup_id(shp, id);
126984ab085aSmws smb_memdevmap_t m;
127084ab085aSmws
127184ab085aSmws if (stp == NULL)
127284ab085aSmws return (-1); /* errno is set for us */
127384ab085aSmws
127484ab085aSmws if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICEMAP)
127584ab085aSmws return (smb_set_errno(shp, ESMB_TYPE));
127684ab085aSmws
127784ab085aSmws smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m));
127884ab085aSmws bzero(mdp, sizeof (smbios_memdevmap_t));
127984ab085aSmws
128084ab085aSmws mdp->smbmdm_device = m.smbdmap_device;
128184ab085aSmws mdp->smbmdm_arrmap = m.smbdmap_array;
128284ab085aSmws mdp->smbmdm_rpos = m.smbdmap_rpos;
128384ab085aSmws mdp->smbmdm_ipos = m.smbdmap_ipos;
128484ab085aSmws mdp->smbmdm_idepth = m.smbdmap_idepth;
128584ab085aSmws
12864e901881SDale Ghent if (m.smbdmap_start != 0xFFFFFFFF && m.smbdmap_end != 0xFFFFFFFF) {
12874e901881SDale Ghent mdp->smbmdm_addr = (uint64_t)m.smbdmap_start * 1024;
12884e901881SDale Ghent mdp->smbmdm_size = (uint64_t)
12894e901881SDale Ghent (m.smbdmap_end - m.smbdmap_start + 1) * 1024;
12904e901881SDale Ghent } else if (m.smbdmap_extstart != 0 && m.smbdmap_extend != 0) {
12914e901881SDale Ghent mdp->smbmdm_addr = m.smbdmap_extstart;
12924e901881SDale Ghent mdp->smbmdm_size = m.smbdmap_extend - m.smbdmap_extstart + 1;
12934e901881SDale Ghent }
12944e901881SDale Ghent
129584ab085aSmws return (0);
129684ab085aSmws }
129784ab085aSmws
129884ab085aSmws id_t
smbios_info_hwsec(smbios_hdl_t * shp,smbios_hwsec_t * hsp)129984ab085aSmws smbios_info_hwsec(smbios_hdl_t *shp, smbios_hwsec_t *hsp)
130084ab085aSmws {
130184ab085aSmws const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SECURITY);
130284ab085aSmws smb_hwsec_t hs;
130384ab085aSmws
130484ab085aSmws if (stp == NULL)
130584ab085aSmws return (-1); /* errno is set for us */
130684ab085aSmws
130784ab085aSmws smb_info_bcopy(stp->smbst_hdr, &hs, sizeof (hs));
130884ab085aSmws bzero(hsp, sizeof (smbios_hwsec_t));
130984ab085aSmws
131084ab085aSmws hsp->smbh_pwr_ps = SMB_HWS_PWR_PS(hs.smbhs_settings);
131184ab085aSmws hsp->smbh_kbd_ps = SMB_HWS_KBD_PS(hs.smbhs_settings);
131284ab085aSmws hsp->smbh_adm_ps = SMB_HWS_ADM_PS(hs.smbhs_settings);
131384ab085aSmws hsp->smbh_pan_ps = SMB_HWS_PAN_PS(hs.smbhs_settings);
131484ab085aSmws
131584ab085aSmws return (stp->smbst_hdr->smbh_hdl);
131684ab085aSmws }
131784ab085aSmws
131884ab085aSmws id_t
smbios_info_boot(smbios_hdl_t * shp,smbios_boot_t * bp)131984ab085aSmws smbios_info_boot(smbios_hdl_t *shp, smbios_boot_t *bp)
132084ab085aSmws {
132184ab085aSmws const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BOOT);
13220b427924SJohn Levon const smb_boot_t *b;
132384ab085aSmws
132484ab085aSmws if (stp == NULL)
132584ab085aSmws return (-1); /* errno is set for us */
132684ab085aSmws
132784ab085aSmws bzero(bp, sizeof (smbios_boot_t));
132884ab085aSmws
13290b427924SJohn Levon b = (smb_boot_t *)(uintptr_t)stp->smbst_hdr;
13300b427924SJohn Levon
133184ab085aSmws bp->smbt_status = b->smbbo_status[0];
133284ab085aSmws bp->smbt_size = stp->smbst_hdr->smbh_len - sizeof (smb_boot_t);
133384ab085aSmws bp->smbt_data = bp->smbt_size ? &b->smbbo_status[1] : NULL;
133484ab085aSmws
133584ab085aSmws return (stp->smbst_hdr->smbh_hdl);
133684ab085aSmws }
133784ab085aSmws
133884ab085aSmws id_t
smbios_info_ipmi(smbios_hdl_t * shp,smbios_ipmi_t * ip)133984ab085aSmws smbios_info_ipmi(smbios_hdl_t *shp, smbios_ipmi_t *ip)
134084ab085aSmws {
134184ab085aSmws const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_IPMIDEV);
134284ab085aSmws smb_ipmi_t i;
134384ab085aSmws
134484ab085aSmws if (stp == NULL)
134584ab085aSmws return (-1); /* errno is set for us */
134684ab085aSmws
134784ab085aSmws smb_info_bcopy(stp->smbst_hdr, &i, sizeof (i));
134884ab085aSmws bzero(ip, sizeof (smbios_ipmi_t));
134984ab085aSmws
135084ab085aSmws ip->smbip_type = i.smbipm_type;
135184ab085aSmws ip->smbip_vers.smbv_major = SMB_IPM_SPEC_MAJOR(i.smbipm_spec);
135284ab085aSmws ip->smbip_vers.smbv_minor = SMB_IPM_SPEC_MINOR(i.smbipm_spec);
135384ab085aSmws ip->smbip_i2c = i.smbipm_i2c;
135484ab085aSmws ip->smbip_addr = i.smbipm_addr & ~SMB_IPM_ADDR_IO;
135584ab085aSmws ip->smbip_intr = i.smbipm_intr;
135684ab085aSmws
135784ab085aSmws if (i.smbipm_bus != (uint8_t)-1)
135884ab085aSmws ip->smbip_bus = i.smbipm_bus;
135984ab085aSmws else
136084ab085aSmws ip->smbip_bus = -1u;
136184ab085aSmws
136284ab085aSmws if (SMB_IPM_INFO_LSB(i.smbipm_info))
136384ab085aSmws ip->smbip_addr |= 1; /* turn on least-significant bit of addr */
136484ab085aSmws
136584ab085aSmws if (i.smbipm_addr & SMB_IPM_ADDR_IO) {
136684ab085aSmws switch (SMB_IPM_INFO_REGS(i.smbipm_info)) {
136784ab085aSmws case SMB_IPM_REGS_1B:
136884ab085aSmws ip->smbip_regspacing = 1;
136984ab085aSmws break;
137084ab085aSmws case SMB_IPM_REGS_4B:
137184ab085aSmws ip->smbip_regspacing = 4;
137284ab085aSmws break;
137384ab085aSmws case SMB_IPM_REGS_16B:
137484ab085aSmws ip->smbip_regspacing = 16;
137584ab085aSmws break;
137684ab085aSmws default:
137784ab085aSmws ip->smbip_regspacing = 1;
137884ab085aSmws }
137984ab085aSmws ip->smbip_flags |= SMB_IPMI_F_IOADDR;
138084ab085aSmws }
138184ab085aSmws
138284ab085aSmws if (SMB_IPM_INFO_ISPEC(i.smbipm_info))
138384ab085aSmws ip->smbip_flags |= SMB_IPMI_F_INTRSPEC;
138484ab085aSmws
138584ab085aSmws if (SMB_IPM_INFO_IPOL(i.smbipm_info) == SMB_IPM_IPOL_HI)
138684ab085aSmws ip->smbip_flags |= SMB_IPMI_F_INTRHIGH;
138784ab085aSmws
138884ab085aSmws if (SMB_IPM_INFO_IMODE(i.smbipm_info) == SMB_IPM_IMODE_EDGE)
138984ab085aSmws ip->smbip_flags |= SMB_IPMI_F_INTREDGE;
139084ab085aSmws
139184ab085aSmws return (stp->smbst_hdr->smbh_hdl);
139284ab085aSmws }
13939c94f155SCheng Sean Ye
13949c94f155SCheng Sean Ye static boolean_t
smbios_has_oemstr(smbios_hdl_t * shp,const char * oemstr)13959c94f155SCheng Sean Ye smbios_has_oemstr(smbios_hdl_t *shp, const char *oemstr)
13969c94f155SCheng Sean Ye {
13979c94f155SCheng Sean Ye const smb_struct_t *stp = shp->sh_structs;
13989c94f155SCheng Sean Ye smb_strtab_t s;
13999c94f155SCheng Sean Ye int i, j;
14009c94f155SCheng Sean Ye
14019c94f155SCheng Sean Ye for (i = 0; i < shp->sh_nstructs; i++, stp++) {
14029c94f155SCheng Sean Ye if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR)
14039c94f155SCheng Sean Ye continue;
14049c94f155SCheng Sean Ye
14059c94f155SCheng Sean Ye smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s));
14069c94f155SCheng Sean Ye for (j = 0; j < s.smbtb_count; j++)
14079c94f155SCheng Sean Ye if (strcmp(smb_strptr(stp, j + 1), oemstr) == 0)
14089c94f155SCheng Sean Ye return (B_TRUE);
14099c94f155SCheng Sean Ye }
14109c94f155SCheng Sean Ye
14119c94f155SCheng Sean Ye return (B_FALSE);
14129c94f155SCheng Sean Ye }
14139c94f155SCheng Sean Ye
14149c94f155SCheng Sean Ye static const char *
smb_serial_valid(const char * serial)14159c94f155SCheng Sean Ye smb_serial_valid(const char *serial)
14169c94f155SCheng Sean Ye {
14179c94f155SCheng Sean Ye char buf[MAXNAMELEN];
14189c94f155SCheng Sean Ye int i = 0;
14199c94f155SCheng Sean Ye
14209c94f155SCheng Sean Ye if (serial == NULL)
14219c94f155SCheng Sean Ye return (NULL);
14229c94f155SCheng Sean Ye
14239c94f155SCheng Sean Ye (void) strlcpy(buf, serial, sizeof (buf));
14249c94f155SCheng Sean Ye
14259c94f155SCheng Sean Ye while (buf[i] != '\0' && buf[i] == ' ')
14269c94f155SCheng Sean Ye i++;
14279c94f155SCheng Sean Ye
14289c94f155SCheng Sean Ye if (buf[i] == '\0' || strstr(buf, SMB_DEFAULT1) != NULL ||
14299c94f155SCheng Sean Ye strstr(buf, SMB_DEFAULT2) != NULL)
14309c94f155SCheng Sean Ye return (NULL);
14319c94f155SCheng Sean Ye
14329c94f155SCheng Sean Ye return (serial);
14339c94f155SCheng Sean Ye }
14349c94f155SCheng Sean Ye
14359c94f155SCheng Sean Ye /*
14369c94f155SCheng Sean Ye * Get chassis SN or product SN
14379c94f155SCheng Sean Ye */
14389c94f155SCheng Sean Ye static int
smb_get_sn(smbios_hdl_t * shp,const char ** psnp,const char ** csnp)14399c94f155SCheng Sean Ye smb_get_sn(smbios_hdl_t *shp, const char **psnp, const char **csnp)
14409c94f155SCheng Sean Ye {
14419c94f155SCheng Sean Ye const smb_struct_t *stp;
14429c94f155SCheng Sean Ye smbios_info_t s1, s3;
14439c94f155SCheng Sean Ye
14449c94f155SCheng Sean Ye if (psnp == NULL || csnp == NULL)
14459c94f155SCheng Sean Ye return (smb_set_errno(shp, ESMB_INVAL));
14469c94f155SCheng Sean Ye
14479c94f155SCheng Sean Ye *psnp = *csnp = NULL;
14489c94f155SCheng Sean Ye
14499c94f155SCheng Sean Ye /*
14509c94f155SCheng Sean Ye * If SMBIOS meets Sun's PRMS requirements, retrieve product SN
14519c94f155SCheng Sean Ye * from type 1 structure, and chassis SN from type 3 structure.
14529c94f155SCheng Sean Ye * Otherwise return SN in type 1 structure as chassis SN.
14539c94f155SCheng Sean Ye */
14549c94f155SCheng Sean Ye
14559c94f155SCheng Sean Ye /* Get type 1 SN */
14569c94f155SCheng Sean Ye if ((stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM)) == NULL ||
14579c94f155SCheng Sean Ye smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s1) == SMB_ERR)
14589c94f155SCheng Sean Ye s1.smbi_serial = NULL;
14599c94f155SCheng Sean Ye
14609c94f155SCheng Sean Ye /* Get type 3 SN */
14619c94f155SCheng Sean Ye if ((stp = smb_lookup_type(shp, SMB_TYPE_CHASSIS)) == NULL ||
14629c94f155SCheng Sean Ye smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s3) == SMB_ERR)
14639c94f155SCheng Sean Ye s3.smbi_serial = NULL;
14649c94f155SCheng Sean Ye
14659c94f155SCheng Sean Ye if (smbios_has_oemstr(shp, SMB_PRMS1)) {
14669c94f155SCheng Sean Ye *psnp = smb_serial_valid(s1.smbi_serial);
14679c94f155SCheng Sean Ye *csnp = smb_serial_valid(s3.smbi_serial);
14689c94f155SCheng Sean Ye } else {
14699c94f155SCheng Sean Ye *csnp = smb_serial_valid(s1.smbi_serial);
14709c94f155SCheng Sean Ye }
14719c94f155SCheng Sean Ye
14729c94f155SCheng Sean Ye return (0);
14739c94f155SCheng Sean Ye }
14749c94f155SCheng Sean Ye
14759c94f155SCheng Sean Ye const char *
smbios_psn(smbios_hdl_t * shp)14769c94f155SCheng Sean Ye smbios_psn(smbios_hdl_t *shp)
14779c94f155SCheng Sean Ye {
14789c94f155SCheng Sean Ye const char *psn, *csn;
14799c94f155SCheng Sean Ye
14809c94f155SCheng Sean Ye return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : psn);
14819c94f155SCheng Sean Ye }
14829c94f155SCheng Sean Ye
14839c94f155SCheng Sean Ye const char *
smbios_csn(smbios_hdl_t * shp)14849c94f155SCheng Sean Ye smbios_csn(smbios_hdl_t *shp)
14859c94f155SCheng Sean Ye {
14869c94f155SCheng Sean Ye const char *psn, *csn;
14879c94f155SCheng Sean Ye
14889c94f155SCheng Sean Ye return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : csn);
14899c94f155SCheng Sean Ye }
1490074bb90dSTom Pothier
1491074bb90dSTom Pothier int
smbios_info_extprocessor(smbios_hdl_t * shp,id_t id,smbios_processor_ext_t * epp)1492074bb90dSTom Pothier smbios_info_extprocessor(smbios_hdl_t *shp, id_t id,
1493074bb90dSTom Pothier smbios_processor_ext_t *epp)
1494074bb90dSTom Pothier {
1495074bb90dSTom Pothier const smb_struct_t *stp = smb_lookup_id(shp, id);
1496074bb90dSTom Pothier smb_processor_ext_t *exp;
1497074bb90dSTom Pothier
1498074bb90dSTom Pothier if (stp == NULL)
1499074bb90dSTom Pothier return (-1); /* errno is set for us */
1500074bb90dSTom Pothier
1501074bb90dSTom Pothier if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PROCESSOR)
1502074bb90dSTom Pothier return (smb_set_errno(shp, ESMB_TYPE));
1503074bb90dSTom Pothier
1504074bb90dSTom Pothier exp = (smb_processor_ext_t *)(uintptr_t)stp->smbst_hdr;
1505074bb90dSTom Pothier bzero(epp, sizeof (smbios_processor_ext_t));
1506074bb90dSTom Pothier
1507074bb90dSTom Pothier epp->smbpe_processor = exp->smbpre_processor;
1508074bb90dSTom Pothier epp->smbpe_fru = exp->smbpre_fru;
1509074bb90dSTom Pothier epp->smbpe_n = exp->smbpre_n;
1510074bb90dSTom Pothier epp->smbpe_apicid = exp->smbpre_apicid;
1511074bb90dSTom Pothier
1512074bb90dSTom Pothier return (0);
1513074bb90dSTom Pothier }
1514074bb90dSTom Pothier
1515074bb90dSTom Pothier int
smbios_info_extport(smbios_hdl_t * shp,id_t id,smbios_port_ext_t * eportp)151603f9f63dSTom Pothier smbios_info_extport(smbios_hdl_t *shp, id_t id, smbios_port_ext_t *eportp)
151703f9f63dSTom Pothier {
151803f9f63dSTom Pothier const smb_struct_t *stp = smb_lookup_id(shp, id);
151903f9f63dSTom Pothier smb_port_ext_t *ep;
152003f9f63dSTom Pothier
152103f9f63dSTom Pothier if (stp == NULL)
152203f9f63dSTom Pothier return (-1); /* errno is set for us */
152303f9f63dSTom Pothier
152403f9f63dSTom Pothier if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PORT)
152503f9f63dSTom Pothier return (smb_set_errno(shp, ESMB_TYPE));
152603f9f63dSTom Pothier
152703f9f63dSTom Pothier ep = (smb_port_ext_t *)(uintptr_t)stp->smbst_hdr;
152803f9f63dSTom Pothier bzero(eportp, sizeof (smbios_port_ext_t));
152903f9f63dSTom Pothier
153003f9f63dSTom Pothier eportp->smbporte_chassis = ep->smbpoe_chassis;
153103f9f63dSTom Pothier eportp->smbporte_port = ep->smbpoe_port;
153203f9f63dSTom Pothier eportp->smbporte_dtype = ep->smbpoe_dtype;
153303f9f63dSTom Pothier eportp->smbporte_devhdl = ep->smbpoe_devhdl;
153403f9f63dSTom Pothier eportp->smbporte_phy = ep->smbpoe_phy;
153503f9f63dSTom Pothier
153603f9f63dSTom Pothier return (0);
153703f9f63dSTom Pothier }
153803f9f63dSTom Pothier
153903f9f63dSTom Pothier int
smbios_info_pciexrc(smbios_hdl_t * shp,id_t id,smbios_pciexrc_t * rcp)1540074bb90dSTom Pothier smbios_info_pciexrc(smbios_hdl_t *shp, id_t id,
1541074bb90dSTom Pothier smbios_pciexrc_t *rcp)
1542074bb90dSTom Pothier {
1543074bb90dSTom Pothier const smb_struct_t *stp = smb_lookup_id(shp, id);
1544074bb90dSTom Pothier smb_pciexrc_t rc;
1545074bb90dSTom Pothier
1546074bb90dSTom Pothier if (stp == NULL)
1547074bb90dSTom Pothier return (-1); /* errno is set for us */
1548074bb90dSTom Pothier
1549074bb90dSTom Pothier if (stp->smbst_hdr->smbh_type != SUN_OEM_PCIEXRC)
1550074bb90dSTom Pothier return (smb_set_errno(shp, ESMB_TYPE));
1551074bb90dSTom Pothier
1552074bb90dSTom Pothier smb_info_bcopy(stp->smbst_hdr, &rc, sizeof (rc));
1553074bb90dSTom Pothier bzero(rcp, sizeof (smbios_pciexrc_t));
1554074bb90dSTom Pothier
1555074bb90dSTom Pothier rcp->smbpcie_bb = rc.smbpciexrc_bboard;
1556074bb90dSTom Pothier rcp->smbpcie_bdf = rc.smbpciexrc_bdf;
1557074bb90dSTom Pothier
1558074bb90dSTom Pothier return (0);
1559074bb90dSTom Pothier }
1560074bb90dSTom Pothier
1561074bb90dSTom Pothier int
smbios_info_extmemarray(smbios_hdl_t * shp,id_t id,smbios_memarray_ext_t * emap)1562074bb90dSTom Pothier smbios_info_extmemarray(smbios_hdl_t *shp, id_t id, smbios_memarray_ext_t *emap)
1563074bb90dSTom Pothier {
1564074bb90dSTom Pothier const smb_struct_t *stp = smb_lookup_id(shp, id);
1565074bb90dSTom Pothier smb_memarray_ext_t exma;
1566074bb90dSTom Pothier
1567074bb90dSTom Pothier if (stp == NULL)
1568074bb90dSTom Pothier return (-1); /* errno is set for us */
1569074bb90dSTom Pothier
1570074bb90dSTom Pothier if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMARRAY)
1571074bb90dSTom Pothier return (smb_set_errno(shp, ESMB_TYPE));
1572074bb90dSTom Pothier
1573074bb90dSTom Pothier smb_info_bcopy(stp->smbst_hdr, &exma, sizeof (exma));
1574074bb90dSTom Pothier bzero(emap, sizeof (smbios_memarray_ext_t));
1575074bb90dSTom Pothier
1576074bb90dSTom Pothier emap->smbmae_ma = exma.smbmarre_ma;
1577074bb90dSTom Pothier emap->smbmae_comp = exma.smbmarre_component;
1578074bb90dSTom Pothier emap->smbmae_bdf = exma.smbmarre_bdf;
1579074bb90dSTom Pothier
1580074bb90dSTom Pothier return (0);
1581074bb90dSTom Pothier }
1582074bb90dSTom Pothier
1583074bb90dSTom Pothier int
smbios_info_extmemdevice(smbios_hdl_t * shp,id_t id,smbios_memdevice_ext_t * emdp)1584074bb90dSTom Pothier smbios_info_extmemdevice(smbios_hdl_t *shp, id_t id,
1585074bb90dSTom Pothier smbios_memdevice_ext_t *emdp)
1586074bb90dSTom Pothier {
1587074bb90dSTom Pothier const smb_struct_t *stp = smb_lookup_id(shp, id);
1588074bb90dSTom Pothier smb_memdevice_ext_t exmd;
1589074bb90dSTom Pothier
1590074bb90dSTom Pothier if (stp == NULL)
1591074bb90dSTom Pothier return (-1); /* errno is set for us */
1592074bb90dSTom Pothier
1593074bb90dSTom Pothier if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
1594074bb90dSTom Pothier return (smb_set_errno(shp, ESMB_TYPE));
1595074bb90dSTom Pothier
1596074bb90dSTom Pothier smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
1597074bb90dSTom Pothier bzero(emdp, sizeof (smbios_memdevice_ext_t));
1598074bb90dSTom Pothier
1599074bb90dSTom Pothier emdp->smbmdeve_md = exmd.smbmdeve_mdev;
1600074bb90dSTom Pothier emdp->smbmdeve_drch = exmd.smbmdeve_dchan;
1601074bb90dSTom Pothier emdp->smbmdeve_ncs = exmd.smbmdeve_ncs;
1602074bb90dSTom Pothier
1603074bb90dSTom Pothier return (0);
1604074bb90dSTom Pothier }
160532ece1f9SRobert Mustacchi
160632ece1f9SRobert Mustacchi int
smbios_info_extmemdevice_cs(smbios_hdl_t * shp,id_t id,uint_t * ncsp,uint8_t ** csp)1607679a141eSToomas Soome smbios_info_extmemdevice_cs(smbios_hdl_t *shp, id_t id, uint_t *ncsp,
1608679a141eSToomas Soome uint8_t **csp)
1609679a141eSToomas Soome {
1610679a141eSToomas Soome const smb_struct_t *stp = smb_lookup_id(shp, id);
1611679a141eSToomas Soome smb_memdevice_ext_t exmd;
1612679a141eSToomas Soome size_t size;
1613679a141eSToomas Soome void *buf;
1614679a141eSToomas Soome
1615679a141eSToomas Soome if (stp == NULL)
1616679a141eSToomas Soome return (-1); /* errno is set for us */
1617679a141eSToomas Soome
1618679a141eSToomas Soome if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
1619679a141eSToomas Soome return (smb_set_errno(shp, ESMB_TYPE));
1620679a141eSToomas Soome
1621679a141eSToomas Soome smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
1622679a141eSToomas Soome if (exmd.smbmdeve_ncs == 0) {
1623679a141eSToomas Soome *ncsp = 0;
1624679a141eSToomas Soome *csp = NULL;
1625679a141eSToomas Soome return (0);
1626679a141eSToomas Soome }
1627679a141eSToomas Soome
1628679a141eSToomas Soome size = exmd.smbmdeve_ncs * sizeof (*exmd.smbmdeve_cs);
1629679a141eSToomas Soome
1630679a141eSToomas Soome if (stp->smbst_hdr->smbh_len < sizeof (exmd) + size)
1631679a141eSToomas Soome return (smb_set_errno(shp, ESMB_SHORT));
1632679a141eSToomas Soome
1633679a141eSToomas Soome buf = smb_alloc(size);
1634679a141eSToomas Soome if (buf == NULL)
1635679a141eSToomas Soome return (smb_set_errno(shp, ESMB_NOMEM));
1636679a141eSToomas Soome smb_info_bcopy_offset(stp->smbst_hdr, buf, size, sizeof (exmd));
1637679a141eSToomas Soome
1638679a141eSToomas Soome *ncsp = exmd.smbmdeve_ncs;
1639679a141eSToomas Soome *csp = buf;
1640679a141eSToomas Soome return (0);
1641679a141eSToomas Soome }
1642679a141eSToomas Soome
1643679a141eSToomas Soome void
smbios_info_extmemdevice_cs_free(smbios_hdl_t * shp __unused,uint_t ncs,uint8_t * csp)1644679a141eSToomas Soome smbios_info_extmemdevice_cs_free(smbios_hdl_t *shp __unused, uint_t ncs,
1645679a141eSToomas Soome uint8_t *csp)
1646679a141eSToomas Soome {
1647679a141eSToomas Soome size_t size = ncs * sizeof (uint8_t);
1648679a141eSToomas Soome
1649679a141eSToomas Soome if (size == 0) {
1650679a141eSToomas Soome ASSERT3P(csp, ==, NULL);
1651679a141eSToomas Soome return;
1652679a141eSToomas Soome }
1653679a141eSToomas Soome smb_free(csp, size);
1654679a141eSToomas Soome }
1655679a141eSToomas Soome
1656679a141eSToomas Soome int
smbios_info_powersup(smbios_hdl_t * shp,id_t id,smbios_powersup_t * psup)165732ece1f9SRobert Mustacchi smbios_info_powersup(smbios_hdl_t *shp, id_t id, smbios_powersup_t *psup)
165832ece1f9SRobert Mustacchi {
165932ece1f9SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
166032ece1f9SRobert Mustacchi smb_powersup_t psu;
166132ece1f9SRobert Mustacchi
166232ece1f9SRobert Mustacchi if (stp == NULL)
166332ece1f9SRobert Mustacchi return (-1); /* errno is set for us */
166432ece1f9SRobert Mustacchi
166532ece1f9SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_POWERSUP)
166632ece1f9SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
166732ece1f9SRobert Mustacchi
166832ece1f9SRobert Mustacchi /* The minimum length required by the spec is 0x10. */
166932ece1f9SRobert Mustacchi if (stp->smbst_hdr->smbh_len < 0x10)
167032ece1f9SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
167132ece1f9SRobert Mustacchi
167232ece1f9SRobert Mustacchi bzero(psup, sizeof (*psup));
167332ece1f9SRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &psu, sizeof (psu));
167432ece1f9SRobert Mustacchi psup->smbps_group = psu.smbpsup_group;
167532ece1f9SRobert Mustacchi psup->smbps_maxout = psu.smbpsup_max;
167632ece1f9SRobert Mustacchi
167732ece1f9SRobert Mustacchi if (SMB_PSU_CHARS_ISHOT(psu.smbpsup_char))
167832ece1f9SRobert Mustacchi psup->smbps_flags |= SMB_POWERSUP_F_HOT;
167932ece1f9SRobert Mustacchi if (SMB_PSU_CHARS_ISPRES(psu.smbpsup_char))
168032ece1f9SRobert Mustacchi psup->smbps_flags |= SMB_POWERSUP_F_PRESENT;
168132ece1f9SRobert Mustacchi if (SMB_PSU_CHARS_ISUNPLUG(psu.smbpsup_char))
168232ece1f9SRobert Mustacchi psup->smbps_flags |= SMB_POWERSUP_F_UNPLUG;
168332ece1f9SRobert Mustacchi
168432ece1f9SRobert Mustacchi psup->smbps_ivrs = SMB_PSU_CHARS_IVRS(psu.smbpsup_char);
168532ece1f9SRobert Mustacchi psup->smbps_status = SMB_PSU_CHARS_STATUS(psu.smbpsup_char);
168632ece1f9SRobert Mustacchi psup->smbps_pstype = SMB_PSU_CHARS_TYPE(psu.smbpsup_char);
168732ece1f9SRobert Mustacchi
168832ece1f9SRobert Mustacchi if (stp->smbst_hdr->smbh_len >= 0x12) {
168932ece1f9SRobert Mustacchi psup->smbps_vprobe = psu.smbpsup_vprobe;
169032ece1f9SRobert Mustacchi } else {
169132ece1f9SRobert Mustacchi psup->smbps_vprobe = 0xffff;
169232ece1f9SRobert Mustacchi }
169332ece1f9SRobert Mustacchi
169432ece1f9SRobert Mustacchi if (stp->smbst_hdr->smbh_len >= 0x14) {
169532ece1f9SRobert Mustacchi psup->smbps_cooldev = psu.smbpsup_cooldev;
169632ece1f9SRobert Mustacchi } else {
169732ece1f9SRobert Mustacchi psup->smbps_cooldev = 0xffff;
169832ece1f9SRobert Mustacchi }
169932ece1f9SRobert Mustacchi
170032ece1f9SRobert Mustacchi if (stp->smbst_hdr->smbh_len >= 0x16) {
170132ece1f9SRobert Mustacchi psup->smbps_iprobe = psu.smbpsup_iprobe;
170232ece1f9SRobert Mustacchi } else {
170332ece1f9SRobert Mustacchi psup->smbps_iprobe = 0xffff;
170432ece1f9SRobert Mustacchi }
170532ece1f9SRobert Mustacchi
170632ece1f9SRobert Mustacchi return (0);
170732ece1f9SRobert Mustacchi }
1708f44a1392SRobert Mustacchi
1709f44a1392SRobert Mustacchi int
smbios_info_vprobe(smbios_hdl_t * shp,id_t id,smbios_vprobe_t * vprobe)1710f44a1392SRobert Mustacchi smbios_info_vprobe(smbios_hdl_t *shp, id_t id, smbios_vprobe_t *vprobe)
1711f44a1392SRobert Mustacchi {
1712f44a1392SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
1713f44a1392SRobert Mustacchi smb_vprobe_t vp;
1714f44a1392SRobert Mustacchi
1715f44a1392SRobert Mustacchi if (stp == NULL)
1716f44a1392SRobert Mustacchi return (-1); /* errno is set for us */
1717f44a1392SRobert Mustacchi
1718f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_VPROBE)
1719f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1720f44a1392SRobert Mustacchi
1721f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_len < SMB_VPROBE_MINLEN)
1722f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1723f44a1392SRobert Mustacchi
1724f44a1392SRobert Mustacchi bzero(vprobe, sizeof (*vprobe));
1725f44a1392SRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &vp, sizeof (vp));
1726f44a1392SRobert Mustacchi vprobe->smbvp_description = smb_strptr(stp, vp.smbvpr_descr);
1727f44a1392SRobert Mustacchi vprobe->smbvp_location = SMB_VPROBE_LOCATION(vp.smbvpr_locstat);
1728f44a1392SRobert Mustacchi vprobe->smbvp_status = SMB_VPROBE_STATUS(vp.smbvpr_locstat);
1729f44a1392SRobert Mustacchi vprobe->smbvp_maxval = vp.smbvpr_maxval;
1730f44a1392SRobert Mustacchi vprobe->smbvp_minval = vp.smbvpr_minval;
1731f44a1392SRobert Mustacchi vprobe->smbvp_resolution = vp.smbvpr_resolution;
1732f44a1392SRobert Mustacchi vprobe->smbvp_tolerance = vp.smbvpr_tolerance;
1733f44a1392SRobert Mustacchi vprobe->smbvp_accuracy = vp.smbvpr_accuracy;
1734f44a1392SRobert Mustacchi
1735f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_len >= SMB_VPROBE_NOMINAL_MINLEN) {
1736f44a1392SRobert Mustacchi vprobe->smbvp_nominal = vp.smbvpr_nominal;
1737f44a1392SRobert Mustacchi } else {
1738f44a1392SRobert Mustacchi vprobe->smbvp_nominal = SMB_PROBE_UNKNOWN_VALUE;
1739f44a1392SRobert Mustacchi }
1740f44a1392SRobert Mustacchi
1741f44a1392SRobert Mustacchi return (0);
1742f44a1392SRobert Mustacchi }
1743f44a1392SRobert Mustacchi
1744f44a1392SRobert Mustacchi int
smbios_info_cooldev(smbios_hdl_t * shp,id_t id,smbios_cooldev_t * cooldev)1745f44a1392SRobert Mustacchi smbios_info_cooldev(smbios_hdl_t *shp, id_t id, smbios_cooldev_t *cooldev)
1746f44a1392SRobert Mustacchi {
1747f44a1392SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
1748f44a1392SRobert Mustacchi smb_cooldev_t cd;
1749f44a1392SRobert Mustacchi
1750f44a1392SRobert Mustacchi if (stp == NULL)
1751f44a1392SRobert Mustacchi return (-1); /* errno is set for us */
1752f44a1392SRobert Mustacchi
1753f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_COOLDEV)
1754f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1755f44a1392SRobert Mustacchi
1756f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_len < SMB_COOLDEV_MINLEN)
1757f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1758f44a1392SRobert Mustacchi
1759f44a1392SRobert Mustacchi bzero(cooldev, sizeof (*cooldev));
1760f44a1392SRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &cd, sizeof (cd));
1761f44a1392SRobert Mustacchi cooldev->smbcd_tprobe = cd.smbcdev_tprobe;
1762f44a1392SRobert Mustacchi cooldev->smbcd_type = SMB_COOLDEV_TYPE(cd.smbcdev_typstat);
1763f44a1392SRobert Mustacchi cooldev->smbcd_status = SMB_COOLDEV_STATUS(cd.smbcdev_typstat);
1764f44a1392SRobert Mustacchi cooldev->smbcd_group = cd.smbcdev_group;
1765f44a1392SRobert Mustacchi cooldev->smbcd_oem = cd.smbcdev_oem;
1766f44a1392SRobert Mustacchi
1767f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_len >= SMB_COOLDEV_NOMINAL_MINLEN) {
1768f44a1392SRobert Mustacchi cooldev->smbcd_nominal = cd.smbcdev_nominal;
1769f44a1392SRobert Mustacchi } else {
1770f44a1392SRobert Mustacchi cooldev->smbcd_nominal = SMB_PROBE_UNKNOWN_VALUE;
1771f44a1392SRobert Mustacchi }
1772f44a1392SRobert Mustacchi
1773f44a1392SRobert Mustacchi /*
1774f44a1392SRobert Mustacchi * The description field was added in SMBIOS version 2.7. The
1775f44a1392SRobert Mustacchi * SMB_TYPE_COOLDEV support was only added after all of the 2.7+ fields
1776f44a1392SRobert Mustacchi * were added in the spec. So while a user may request an older version,
1777f44a1392SRobert Mustacchi * we don't have to worry about old structures and just simply skip it
1778f44a1392SRobert Mustacchi * if they're not asking for it.
1779f44a1392SRobert Mustacchi */
1780f44a1392SRobert Mustacchi if (smb_libgteq(shp, SMB_VERSION_27) &&
1781f44a1392SRobert Mustacchi smb_gteq(shp, SMB_VERSION_27) &&
1782f44a1392SRobert Mustacchi stp->smbst_hdr->smbh_len >= SMB_COOLDEV_DESCR_MINLEN) {
1783f44a1392SRobert Mustacchi cooldev->smbcd_descr = smb_strptr(stp, cd.smbcdev_descr);
1784f44a1392SRobert Mustacchi } else {
1785f44a1392SRobert Mustacchi cooldev->smbcd_descr = NULL;
1786f44a1392SRobert Mustacchi }
1787f44a1392SRobert Mustacchi
1788f44a1392SRobert Mustacchi return (0);
1789f44a1392SRobert Mustacchi }
1790f44a1392SRobert Mustacchi
1791f44a1392SRobert Mustacchi int
smbios_info_tprobe(smbios_hdl_t * shp,id_t id,smbios_tprobe_t * tprobe)1792f44a1392SRobert Mustacchi smbios_info_tprobe(smbios_hdl_t *shp, id_t id, smbios_tprobe_t *tprobe)
1793f44a1392SRobert Mustacchi {
1794f44a1392SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
1795f44a1392SRobert Mustacchi smb_tprobe_t tp;
1796f44a1392SRobert Mustacchi
1797f44a1392SRobert Mustacchi if (stp == NULL)
1798f44a1392SRobert Mustacchi return (-1); /* errno is set for us */
1799f44a1392SRobert Mustacchi
1800f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_TPROBE)
1801f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1802f44a1392SRobert Mustacchi
1803f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_len < SMB_TPROBE_MINLEN)
1804f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1805f44a1392SRobert Mustacchi
1806f44a1392SRobert Mustacchi bzero(tprobe, sizeof (*tprobe));
1807f44a1392SRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &tp, sizeof (tp));
1808f44a1392SRobert Mustacchi tprobe->smbtp_description = smb_strptr(stp, tp.smbtpr_descr);
1809f44a1392SRobert Mustacchi tprobe->smbtp_location = SMB_TPROBE_LOCATION(tp.smbtpr_locstat);
1810f44a1392SRobert Mustacchi tprobe->smbtp_status = SMB_TPROBE_STATUS(tp.smbtpr_locstat);
1811f44a1392SRobert Mustacchi tprobe->smbtp_maxval = tp.smbtpr_maxval;
1812f44a1392SRobert Mustacchi tprobe->smbtp_minval = tp.smbtpr_minval;
1813f44a1392SRobert Mustacchi tprobe->smbtp_resolution = tp.smbtpr_resolution;
1814f44a1392SRobert Mustacchi tprobe->smbtp_tolerance = tp.smbtpr_tolerance;
1815f44a1392SRobert Mustacchi tprobe->smbtp_accuracy = tp.smbtpr_accuracy;
1816f44a1392SRobert Mustacchi
1817f44a1392SRobert Mustacchi if (stp->smbst_hdr->smbh_len >= SMB_TPROBE_NOMINAL_MINLEN) {
1818f44a1392SRobert Mustacchi tprobe->smbtp_nominal = tp.smbtpr_nominal;
1819f44a1392SRobert Mustacchi } else {
1820f44a1392SRobert Mustacchi tprobe->smbtp_nominal = SMB_PROBE_UNKNOWN_VALUE;
1821f44a1392SRobert Mustacchi }
1822f44a1392SRobert Mustacchi
1823f44a1392SRobert Mustacchi return (0);
1824f44a1392SRobert Mustacchi }
1825f44a1392SRobert Mustacchi
1826f44a1392SRobert Mustacchi int
smbios_info_iprobe(smbios_hdl_t * shp,id_t id,smbios_iprobe_t * iprobe)1827f44a1392SRobert Mustacchi smbios_info_iprobe(smbios_hdl_t *shp, id_t id, smbios_iprobe_t *iprobe)
1828f44a1392SRobert Mustacchi {
1829f44a1392SRobert Mustacchi const smb_struct_t *sip = smb_lookup_id(shp, id);
1830f44a1392SRobert Mustacchi smb_iprobe_t ip;
1831f44a1392SRobert Mustacchi
1832f44a1392SRobert Mustacchi if (sip == NULL)
1833f44a1392SRobert Mustacchi return (-1); /* errno is set for us */
1834f44a1392SRobert Mustacchi
1835f44a1392SRobert Mustacchi if (sip->smbst_hdr->smbh_type != SMB_TYPE_IPROBE)
1836f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1837f44a1392SRobert Mustacchi
1838f44a1392SRobert Mustacchi if (sip->smbst_hdr->smbh_len < SMB_IPROBE_MINLEN)
1839f44a1392SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1840f44a1392SRobert Mustacchi
1841f44a1392SRobert Mustacchi bzero(iprobe, sizeof (*iprobe));
1842f44a1392SRobert Mustacchi smb_info_bcopy(sip->smbst_hdr, &ip, sizeof (ip));
1843f44a1392SRobert Mustacchi iprobe->smbip_description = smb_strptr(sip, ip.smbipr_descr);
1844f44a1392SRobert Mustacchi iprobe->smbip_location = SMB_IPROBE_LOCATION(ip.smbipr_locstat);
1845f44a1392SRobert Mustacchi iprobe->smbip_status = SMB_IPROBE_STATUS(ip.smbipr_locstat);
1846f44a1392SRobert Mustacchi iprobe->smbip_maxval = ip.smbipr_maxval;
1847f44a1392SRobert Mustacchi iprobe->smbip_minval = ip.smbipr_minval;
1848f44a1392SRobert Mustacchi iprobe->smbip_resolution = ip.smbipr_resolution;
1849f44a1392SRobert Mustacchi iprobe->smbip_tolerance = ip.smbipr_tolerance;
1850f44a1392SRobert Mustacchi iprobe->smbip_accuracy = ip.smbipr_accuracy;
1851f44a1392SRobert Mustacchi
1852f44a1392SRobert Mustacchi if (sip->smbst_hdr->smbh_len >= SMB_IPROBE_NOMINAL_MINLEN) {
1853f44a1392SRobert Mustacchi iprobe->smbip_nominal = ip.smbipr_nominal;
1854f44a1392SRobert Mustacchi } else {
1855f44a1392SRobert Mustacchi iprobe->smbip_nominal = SMB_PROBE_UNKNOWN_VALUE;
1856f44a1392SRobert Mustacchi }
1857f44a1392SRobert Mustacchi
1858f44a1392SRobert Mustacchi return (0);
1859f44a1392SRobert Mustacchi }
1860176a9270SRobert Mustacchi
1861176a9270SRobert Mustacchi int
smbios_info_processor_info(smbios_hdl_t * shp,id_t id,smbios_processor_info_t * proc)1862176a9270SRobert Mustacchi smbios_info_processor_info(smbios_hdl_t *shp, id_t id,
1863176a9270SRobert Mustacchi smbios_processor_info_t *proc)
1864176a9270SRobert Mustacchi {
1865176a9270SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
1866176a9270SRobert Mustacchi smb_processor_info_t pi;
1867176a9270SRobert Mustacchi
1868176a9270SRobert Mustacchi if (stp == NULL)
1869176a9270SRobert Mustacchi return (-1); /* errno is set for us */
1870176a9270SRobert Mustacchi
1871176a9270SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO)
1872176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1873176a9270SRobert Mustacchi
1874176a9270SRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (pi))
1875176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1876176a9270SRobert Mustacchi
1877176a9270SRobert Mustacchi bzero(proc, sizeof (*proc));
1878176a9270SRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &pi, sizeof (pi));
1879176a9270SRobert Mustacchi
1880176a9270SRobert Mustacchi if (sizeof (pi) + pi.smbpai_len > stp->smbst_hdr->smbh_len)
1881176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_CORRUPT));
1882176a9270SRobert Mustacchi
1883176a9270SRobert Mustacchi proc->smbpi_processor = pi.smbpai_proc;
1884176a9270SRobert Mustacchi proc->smbpi_ptype = pi.smbpai_type;
1885176a9270SRobert Mustacchi
1886176a9270SRobert Mustacchi return (0);
1887176a9270SRobert Mustacchi }
1888176a9270SRobert Mustacchi
1889176a9270SRobert Mustacchi int
smbios_info_processor_riscv(smbios_hdl_t * shp,id_t id,smbios_processor_info_riscv_t * riscv)1890176a9270SRobert Mustacchi smbios_info_processor_riscv(smbios_hdl_t *shp, id_t id,
1891176a9270SRobert Mustacchi smbios_processor_info_riscv_t *riscv)
1892176a9270SRobert Mustacchi {
1893176a9270SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
1894176a9270SRobert Mustacchi const smb_processor_info_t *proc;
1895176a9270SRobert Mustacchi const smb_processor_info_riscv_t *rv;
1896176a9270SRobert Mustacchi
1897d53cdfabSRobert Mustacchi if (stp == NULL) {
1898d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
1899d53cdfabSRobert Mustacchi }
1900d53cdfabSRobert Mustacchi
1901176a9270SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO) {
1902176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1903176a9270SRobert Mustacchi }
1904176a9270SRobert Mustacchi
1905176a9270SRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (*proc)) {
1906176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1907176a9270SRobert Mustacchi }
1908176a9270SRobert Mustacchi
1909176a9270SRobert Mustacchi proc = (const smb_processor_info_t *)stp->smbst_hdr;
1910176a9270SRobert Mustacchi if (sizeof (*proc) + proc->smbpai_len > stp->smbst_hdr->smbh_len) {
1911176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_CORRUPT));
1912176a9270SRobert Mustacchi }
1913176a9270SRobert Mustacchi
1914176a9270SRobert Mustacchi switch (proc->smbpai_type) {
1915176a9270SRobert Mustacchi case SMB_PROCINFO_T_RV32:
1916176a9270SRobert Mustacchi case SMB_PROCINFO_T_RV64:
1917176a9270SRobert Mustacchi case SMB_PROCINFO_T_RV128:
1918176a9270SRobert Mustacchi break;
1919176a9270SRobert Mustacchi default:
1920176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
1921176a9270SRobert Mustacchi }
1922176a9270SRobert Mustacchi
1923176a9270SRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (*proc) + sizeof (*rv)) {
1924176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
1925176a9270SRobert Mustacchi }
1926176a9270SRobert Mustacchi rv = (const smb_processor_info_riscv_t *)&proc->smbpai_data[0];
1927176a9270SRobert Mustacchi if (rv->smbpairv_len != sizeof (*rv)) {
1928176a9270SRobert Mustacchi return (smb_set_errno(shp, ESMB_CORRUPT));
1929176a9270SRobert Mustacchi }
1930176a9270SRobert Mustacchi
1931176a9270SRobert Mustacchi bcopy(rv->smbpairv_hartid, riscv->smbpirv_hartid,
1932176a9270SRobert Mustacchi sizeof (riscv->smbpirv_hartid));
1933176a9270SRobert Mustacchi bcopy(rv->smbpairv_vendid, riscv->smbpirv_vendid,
1934176a9270SRobert Mustacchi sizeof (riscv->smbpirv_vendid));
1935176a9270SRobert Mustacchi bcopy(rv->smbpairv_archid, riscv->smbpirv_archid,
1936176a9270SRobert Mustacchi sizeof (riscv->smbpirv_archid));
1937176a9270SRobert Mustacchi bcopy(rv->smbpairv_machid, riscv->smbpirv_machid,
1938176a9270SRobert Mustacchi sizeof (riscv->smbpirv_machid));
1939176a9270SRobert Mustacchi bcopy(rv->smbpairv_metdi, riscv->smbpirv_metdi,
1940176a9270SRobert Mustacchi sizeof (riscv->smbpirv_metdi));
1941176a9270SRobert Mustacchi bcopy(rv->smbpairv_mitdi, riscv->smbpirv_mitdi,
1942176a9270SRobert Mustacchi sizeof (riscv->smbpirv_mitdi));
1943176a9270SRobert Mustacchi riscv->smbpirv_isa = rv->smbpairv_isa;
1944176a9270SRobert Mustacchi riscv->smbpirv_privlvl = rv->smbpairv_privlvl;
1945176a9270SRobert Mustacchi riscv->smbpirv_boothart = rv->smbpairv_boot;
1946176a9270SRobert Mustacchi riscv->smbpirv_xlen = rv->smbpairv_xlen;
1947176a9270SRobert Mustacchi riscv->smbpirv_mxlen = rv->smbpairv_mxlen;
1948176a9270SRobert Mustacchi riscv->smbpirv_sxlen = rv->smbpairv_sxlen;
1949176a9270SRobert Mustacchi riscv->smbpirv_uxlen = rv->smbpairv_uxlen;
1950176a9270SRobert Mustacchi
1951176a9270SRobert Mustacchi return (0);
1952176a9270SRobert Mustacchi }
19531d77dcdaSRobert Mustacchi
19541d77dcdaSRobert Mustacchi int
smbios_info_pointdev(smbios_hdl_t * shp,id_t id,smbios_pointdev_t * pd)19551d77dcdaSRobert Mustacchi smbios_info_pointdev(smbios_hdl_t *shp, id_t id, smbios_pointdev_t *pd)
19561d77dcdaSRobert Mustacchi {
19571d77dcdaSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
19581d77dcdaSRobert Mustacchi smb_pointdev_t point;
19591d77dcdaSRobert Mustacchi
1960d53cdfabSRobert Mustacchi if (stp == NULL) {
1961d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
1962d53cdfabSRobert Mustacchi }
1963d53cdfabSRobert Mustacchi
19641d77dcdaSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_POINTDEV) {
19651d77dcdaSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
19661d77dcdaSRobert Mustacchi }
19671d77dcdaSRobert Mustacchi
19681d77dcdaSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (point)) {
19691d77dcdaSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
19701d77dcdaSRobert Mustacchi }
19711d77dcdaSRobert Mustacchi
19721d77dcdaSRobert Mustacchi bzero(pd, sizeof (*pd));
19731d77dcdaSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &point, sizeof (point));
19741d77dcdaSRobert Mustacchi
19751d77dcdaSRobert Mustacchi pd->smbpd_type = point.smbpdev_type;
19761d77dcdaSRobert Mustacchi pd->smbpd_iface = point.smbpdev_iface;
19771d77dcdaSRobert Mustacchi pd->smbpd_nbuttons = point.smbpdev_nbuttons;
19781d77dcdaSRobert Mustacchi
19791d77dcdaSRobert Mustacchi return (0);
19801d77dcdaSRobert Mustacchi }
198146782190SRobert Mustacchi
198246782190SRobert Mustacchi int
smbios_info_battery(smbios_hdl_t * shp,id_t id,smbios_battery_t * bp)198346782190SRobert Mustacchi smbios_info_battery(smbios_hdl_t *shp, id_t id, smbios_battery_t *bp)
198446782190SRobert Mustacchi {
198546782190SRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
198646782190SRobert Mustacchi smb_battery_t bat;
198746782190SRobert Mustacchi
1988d53cdfabSRobert Mustacchi if (stp == NULL) {
1989d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
1990d53cdfabSRobert Mustacchi }
1991d53cdfabSRobert Mustacchi
199246782190SRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_BATTERY) {
199346782190SRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
199446782190SRobert Mustacchi }
199546782190SRobert Mustacchi
199646782190SRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (bat)) {
199746782190SRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
199846782190SRobert Mustacchi }
199946782190SRobert Mustacchi
200046782190SRobert Mustacchi bzero(bp, sizeof (*bp));
200146782190SRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &bat, sizeof (bat));
200246782190SRobert Mustacchi
200346782190SRobert Mustacchi /*
200446782190SRobert Mustacchi * This may be superseded by the SBDS data.
200546782190SRobert Mustacchi */
200646782190SRobert Mustacchi if (bat.smbbat_date != 0) {
200746782190SRobert Mustacchi bp->smbb_date = smb_strptr(stp, bat.smbbat_date);
200846782190SRobert Mustacchi } else {
200946782190SRobert Mustacchi bp->smbb_date = NULL;
201046782190SRobert Mustacchi }
201146782190SRobert Mustacchi
201246782190SRobert Mustacchi /*
201346782190SRobert Mustacchi * This may be superseded by the SBDS data.
201446782190SRobert Mustacchi */
201546782190SRobert Mustacchi if (bat.smbbat_serial != 0) {
201646782190SRobert Mustacchi bp->smbb_serial = smb_strptr(stp, bat.smbbat_serial);
201746782190SRobert Mustacchi } else {
201846782190SRobert Mustacchi bp->smbb_serial = NULL;
201946782190SRobert Mustacchi }
202046782190SRobert Mustacchi
202146782190SRobert Mustacchi bp->smbb_chem = bat.smbbat_chem;
202246782190SRobert Mustacchi bp->smbb_cap = bat.smbbat_cap;
202346782190SRobert Mustacchi if (bat.smbbat_mult > 0) {
202446782190SRobert Mustacchi bp->smbb_cap *= bat.smbbat_mult;
202546782190SRobert Mustacchi }
202646782190SRobert Mustacchi bp->smbb_volt = bat.smbbat_volt;
202746782190SRobert Mustacchi bp->smbb_version = smb_strptr(stp, bat.smbbat_version);
202846782190SRobert Mustacchi bp->smbb_err = bat.smbbat_err;
202946782190SRobert Mustacchi bp->smbb_ssn = bat.smbbat_ssn;
203046782190SRobert Mustacchi bp->smbb_syear = 1980 + (bat.smbbat_sdate >> 9);
203146782190SRobert Mustacchi bp->smbb_smonth = (bat.smbbat_sdate >> 5) & 0xf;
203246782190SRobert Mustacchi bp->smbb_sday = bat.smbbat_sdate & 0x1f;
203346782190SRobert Mustacchi bp->smbb_schem = smb_strptr(stp, bat.smbbat_schem);
203446782190SRobert Mustacchi bp->smbb_oemdata = bat.smbbat_oemdata;
203546782190SRobert Mustacchi
203646782190SRobert Mustacchi return (0);
203746782190SRobert Mustacchi }
2038d53cdfabSRobert Mustacchi
2039d53cdfabSRobert Mustacchi int
smbios_info_strprop(smbios_hdl_t * shp,id_t id,smbios_strprop_t * str)2040d53cdfabSRobert Mustacchi smbios_info_strprop(smbios_hdl_t *shp, id_t id, smbios_strprop_t *str)
2041d53cdfabSRobert Mustacchi {
2042d53cdfabSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
2043d53cdfabSRobert Mustacchi smb_strprop_t prop;
2044d53cdfabSRobert Mustacchi
2045d53cdfabSRobert Mustacchi if (stp == NULL) {
2046d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
2047d53cdfabSRobert Mustacchi }
2048d53cdfabSRobert Mustacchi
2049d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_STRPROP) {
2050d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
2051d53cdfabSRobert Mustacchi }
2052d53cdfabSRobert Mustacchi
2053d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (prop)) {
2054d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2055d53cdfabSRobert Mustacchi }
2056d53cdfabSRobert Mustacchi
2057d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_len > sizeof (prop)) {
2058d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_CORRUPT));
2059d53cdfabSRobert Mustacchi }
2060d53cdfabSRobert Mustacchi
2061d53cdfabSRobert Mustacchi bzero(str, sizeof (*str));
2062d53cdfabSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &prop, sizeof (prop));
2063d53cdfabSRobert Mustacchi
2064d53cdfabSRobert Mustacchi str->smbsp_parent = prop.smbstrp_phdl;
2065d53cdfabSRobert Mustacchi str->smbsp_prop_id = prop.smbstrp_prop_id;
2066d53cdfabSRobert Mustacchi str->smbsp_prop_val = smb_strptr(stp, prop.smbstrp_prop_val);
2067d53cdfabSRobert Mustacchi
2068d53cdfabSRobert Mustacchi return (0);
2069d53cdfabSRobert Mustacchi }
2070d53cdfabSRobert Mustacchi
2071d53cdfabSRobert Mustacchi int
smbios_info_fwinfo(smbios_hdl_t * shp,id_t id,smbios_fwinfo_t * fwinfo)2072d53cdfabSRobert Mustacchi smbios_info_fwinfo(smbios_hdl_t *shp, id_t id, smbios_fwinfo_t *fwinfo)
2073d53cdfabSRobert Mustacchi {
2074d53cdfabSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
2075d53cdfabSRobert Mustacchi smb_fwinfo_t fw;
2076d53cdfabSRobert Mustacchi
2077d53cdfabSRobert Mustacchi if (stp == NULL) {
2078d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
2079d53cdfabSRobert Mustacchi }
2080d53cdfabSRobert Mustacchi
2081d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_FWINFO) {
2082d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
2083d53cdfabSRobert Mustacchi }
2084d53cdfabSRobert Mustacchi
2085d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (fw)) {
2086d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2087d53cdfabSRobert Mustacchi }
2088d53cdfabSRobert Mustacchi
2089d53cdfabSRobert Mustacchi /*
2090d53cdfabSRobert Mustacchi * The verion and manufacturer are part of smbios_info_common().
2091d53cdfabSRobert Mustacchi */
2092d53cdfabSRobert Mustacchi bzero(fwinfo, sizeof (*fwinfo));
2093d53cdfabSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &fw, sizeof (fw));
2094d53cdfabSRobert Mustacchi fwinfo->smbfw_name = smb_strptr(stp, fw.smbfwii_name);
2095d53cdfabSRobert Mustacchi fwinfo->smbfw_id = smb_strptr(stp, fw.smbfwii_id);
2096d53cdfabSRobert Mustacchi fwinfo->smbfw_reldate = smb_strptr(stp, fw.smbfwii_reldate);
2097d53cdfabSRobert Mustacchi fwinfo->smbfw_lsv = smb_strptr(stp, fw.smbfwii_lsv);
2098d53cdfabSRobert Mustacchi fwinfo->smbfw_imgsz = fw.smbfwii_imgsz;
2099d53cdfabSRobert Mustacchi fwinfo->smbfw_chars = fw.smbfwii_chars;
2100d53cdfabSRobert Mustacchi fwinfo->smbfw_state = fw.smbfwii_state;
2101d53cdfabSRobert Mustacchi fwinfo->smbfw_ncomps = fw.smbfwii_ncomps;
2102d53cdfabSRobert Mustacchi fwinfo->smbfw_vers_fmt = fw.smbfwii_vers_fmt;
2103d53cdfabSRobert Mustacchi fwinfo->smbfw_id_fmt = fw.smbfwii_id_fmt;
2104d53cdfabSRobert Mustacchi
2105d53cdfabSRobert Mustacchi return (0);
2106d53cdfabSRobert Mustacchi }
2107d53cdfabSRobert Mustacchi
2108d53cdfabSRobert Mustacchi int
smbios_info_fwinfo_comps(smbios_hdl_t * shp,id_t id,uint_t * ncompsp,smbios_fwinfo_comp_t ** compsp)2109d53cdfabSRobert Mustacchi smbios_info_fwinfo_comps(smbios_hdl_t *shp, id_t id, uint_t *ncompsp,
2110d53cdfabSRobert Mustacchi smbios_fwinfo_comp_t **compsp)
2111d53cdfabSRobert Mustacchi {
2112d53cdfabSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
2113d53cdfabSRobert Mustacchi smbios_fwinfo_comp_t *comps;
2114d53cdfabSRobert Mustacchi smb_fwinfo_t fw;
2115d53cdfabSRobert Mustacchi size_t need;
2116d53cdfabSRobert Mustacchi uint_t i;
2117d53cdfabSRobert Mustacchi
2118d53cdfabSRobert Mustacchi if (stp == NULL) {
2119d53cdfabSRobert Mustacchi return (-1); /* errno is set for us */
2120d53cdfabSRobert Mustacchi }
2121d53cdfabSRobert Mustacchi
2122d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_FWINFO) {
2123d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
2124d53cdfabSRobert Mustacchi }
2125d53cdfabSRobert Mustacchi
2126d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (fw)) {
2127d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2128d53cdfabSRobert Mustacchi }
2129d53cdfabSRobert Mustacchi
2130d53cdfabSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &fw, sizeof (fw));
2131d53cdfabSRobert Mustacchi if (fw.smbfwii_ncomps == 0) {
2132d53cdfabSRobert Mustacchi *ncompsp = 0;
2133d53cdfabSRobert Mustacchi *compsp = NULL;
2134d53cdfabSRobert Mustacchi return (0);
2135d53cdfabSRobert Mustacchi }
2136d53cdfabSRobert Mustacchi
2137d53cdfabSRobert Mustacchi need = fw.smbfwii_ncomps * sizeof (uint16_t) + sizeof (smb_fwinfo_t);
2138d53cdfabSRobert Mustacchi if (stp->smbst_hdr->smbh_len < need) {
2139d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2140d53cdfabSRobert Mustacchi }
2141d53cdfabSRobert Mustacchi
2142d53cdfabSRobert Mustacchi comps = smb_alloc(fw.smbfwii_ncomps * sizeof (smbios_fwinfo_comp_t));
2143d53cdfabSRobert Mustacchi if (comps == NULL) {
2144d53cdfabSRobert Mustacchi return (smb_set_errno(shp, ESMB_NOMEM));
2145d53cdfabSRobert Mustacchi }
2146d53cdfabSRobert Mustacchi
2147d53cdfabSRobert Mustacchi for (i = 0; i < fw.smbfwii_ncomps; i++) {
2148d53cdfabSRobert Mustacchi uint16_t id;
2149d53cdfabSRobert Mustacchi size_t off = sizeof (smb_fwinfo_t) + sizeof (uint16_t) * i;
2150d53cdfabSRobert Mustacchi smb_info_bcopy_offset(stp->smbst_hdr, &id, sizeof (id), off);
2151d53cdfabSRobert Mustacchi comps[i].smbfwe_id = id;
2152d53cdfabSRobert Mustacchi }
2153d53cdfabSRobert Mustacchi
2154d53cdfabSRobert Mustacchi *ncompsp = fw.smbfwii_ncomps;
2155d53cdfabSRobert Mustacchi *compsp = comps;
2156d53cdfabSRobert Mustacchi
2157d53cdfabSRobert Mustacchi return (0);
2158d53cdfabSRobert Mustacchi }
2159d53cdfabSRobert Mustacchi
2160d53cdfabSRobert Mustacchi void
smbios_info_fwinfo_comps_free(smbios_hdl_t * shp,uint_t ncomps,smbios_fwinfo_comp_t * comps)2161d53cdfabSRobert Mustacchi smbios_info_fwinfo_comps_free(smbios_hdl_t *shp, uint_t ncomps,
2162d53cdfabSRobert Mustacchi smbios_fwinfo_comp_t *comps)
2163d53cdfabSRobert Mustacchi {
2164d53cdfabSRobert Mustacchi size_t sz = ncomps * sizeof (smbios_fwinfo_comp_t);
2165d53cdfabSRobert Mustacchi
2166d53cdfabSRobert Mustacchi if (ncomps == 0) {
2167d53cdfabSRobert Mustacchi ASSERT3P(comps, ==, NULL);
2168d53cdfabSRobert Mustacchi return;
2169d53cdfabSRobert Mustacchi }
2170d53cdfabSRobert Mustacchi
2171d53cdfabSRobert Mustacchi smb_free(comps, sz);
2172d53cdfabSRobert Mustacchi }
2173064d431aSRobert Mustacchi
2174064d431aSRobert Mustacchi int
smbios_info_addinfo_nents(smbios_hdl_t * shp,id_t id,uint_t * nentsp)2175064d431aSRobert Mustacchi smbios_info_addinfo_nents(smbios_hdl_t *shp, id_t id, uint_t *nentsp)
2176064d431aSRobert Mustacchi {
2177064d431aSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
2178064d431aSRobert Mustacchi smb_addinfo_t add;
2179064d431aSRobert Mustacchi
2180064d431aSRobert Mustacchi if (stp == NULL) {
2181064d431aSRobert Mustacchi return (-1); /* errno is set for us */
2182064d431aSRobert Mustacchi }
2183064d431aSRobert Mustacchi
2184064d431aSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_ADDINFO) {
2185064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
2186064d431aSRobert Mustacchi }
2187064d431aSRobert Mustacchi
2188064d431aSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (add)) {
2189064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2190064d431aSRobert Mustacchi }
2191064d431aSRobert Mustacchi
2192064d431aSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &add, sizeof (add));
2193064d431aSRobert Mustacchi *nentsp = add.smbai_nents;
2194064d431aSRobert Mustacchi
2195064d431aSRobert Mustacchi return (0);
2196064d431aSRobert Mustacchi }
2197064d431aSRobert Mustacchi
2198064d431aSRobert Mustacchi void
smbios_info_addinfo_ent_free(smbios_hdl_t * hdl,smbios_addinfo_ent_t * ent)2199064d431aSRobert Mustacchi smbios_info_addinfo_ent_free(smbios_hdl_t *hdl, smbios_addinfo_ent_t *ent)
2200064d431aSRobert Mustacchi {
2201064d431aSRobert Mustacchi if (ent->smbai_dlen > 0) {
2202064d431aSRobert Mustacchi ASSERT3P(ent->smbai_data, !=, NULL);
2203064d431aSRobert Mustacchi smb_free(ent->smbai_data, ent->smbai_dlen);
2204064d431aSRobert Mustacchi }
2205064d431aSRobert Mustacchi
2206064d431aSRobert Mustacchi smb_free(ent, sizeof (smbios_addinfo_ent_t));
2207064d431aSRobert Mustacchi }
2208064d431aSRobert Mustacchi
2209064d431aSRobert Mustacchi int
smbios_info_addinfo_ent(smbios_hdl_t * shp,id_t id,uint_t entno,smbios_addinfo_ent_t ** entp)2210064d431aSRobert Mustacchi smbios_info_addinfo_ent(smbios_hdl_t *shp, id_t id, uint_t entno,
2211064d431aSRobert Mustacchi smbios_addinfo_ent_t **entp)
2212064d431aSRobert Mustacchi {
2213064d431aSRobert Mustacchi const smb_struct_t *stp = smb_lookup_id(shp, id);
2214064d431aSRobert Mustacchi size_t off;
2215064d431aSRobert Mustacchi smb_addinfo_t add;
2216064d431aSRobert Mustacchi smb_addinfo_ent_t ent;
2217064d431aSRobert Mustacchi smbios_addinfo_ent_t *entry;
2218064d431aSRobert Mustacchi uint_t i;
2219064d431aSRobert Mustacchi
2220064d431aSRobert Mustacchi if (stp == NULL) {
2221064d431aSRobert Mustacchi return (-1); /* errno is set for us */
2222064d431aSRobert Mustacchi }
2223064d431aSRobert Mustacchi
2224064d431aSRobert Mustacchi if (stp->smbst_hdr->smbh_type != SMB_TYPE_ADDINFO) {
2225064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_TYPE));
2226064d431aSRobert Mustacchi }
2227064d431aSRobert Mustacchi
2228064d431aSRobert Mustacchi if (stp->smbst_hdr->smbh_len < sizeof (add)) {
2229064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2230064d431aSRobert Mustacchi }
2231064d431aSRobert Mustacchi
2232064d431aSRobert Mustacchi smb_info_bcopy(stp->smbst_hdr, &add, sizeof (add));
2233064d431aSRobert Mustacchi if (entno >= add.smbai_nents) {
2234064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_REQVAL));
2235064d431aSRobert Mustacchi }
2236064d431aSRobert Mustacchi
2237064d431aSRobert Mustacchi off = sizeof (add);
2238064d431aSRobert Mustacchi for (i = 0; i <= entno; i++) {
2239064d431aSRobert Mustacchi if (off + sizeof (ent) > stp->smbst_hdr->smbh_len) {
2240064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2241064d431aSRobert Mustacchi }
2242064d431aSRobert Mustacchi
2243064d431aSRobert Mustacchi smb_info_bcopy_offset(stp->smbst_hdr, &ent, sizeof (ent), off);
2244064d431aSRobert Mustacchi if (ent.smbaie_len < sizeof (ent)) {
2245064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_SHORT));
2246064d431aSRobert Mustacchi }
2247064d431aSRobert Mustacchi
2248064d431aSRobert Mustacchi if (ent.smbaie_len + off > stp->smbst_hdr->smbh_len) {
2249064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_CORRUPT));
2250064d431aSRobert Mustacchi }
2251064d431aSRobert Mustacchi
2252064d431aSRobert Mustacchi if (i != entno) {
2253064d431aSRobert Mustacchi off += ent.smbaie_len;
2254064d431aSRobert Mustacchi }
2255064d431aSRobert Mustacchi }
2256064d431aSRobert Mustacchi
2257064d431aSRobert Mustacchi entry = smb_alloc(sizeof (smbios_addinfo_ent_t));
2258064d431aSRobert Mustacchi if (entry == NULL) {
2259064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_NOMEM));
2260064d431aSRobert Mustacchi }
2261064d431aSRobert Mustacchi
2262064d431aSRobert Mustacchi entry->smbai_ref = ent.smbaie_rhdl;
2263064d431aSRobert Mustacchi entry->smbai_ref_off = ent.smbaie_off;
2264064d431aSRobert Mustacchi if (ent.smbaie_str != 0) {
2265064d431aSRobert Mustacchi entry->smbai_str = smb_strptr(stp, ent.smbaie_str);
2266064d431aSRobert Mustacchi } else {
2267064d431aSRobert Mustacchi entry->smbai_str = NULL;
2268064d431aSRobert Mustacchi }
2269064d431aSRobert Mustacchi entry->smbai_dlen = ent.smbaie_len - sizeof (ent);
2270064d431aSRobert Mustacchi if (entry->smbai_dlen > 0) {
2271064d431aSRobert Mustacchi entry->smbai_data = smb_alloc(entry->smbai_dlen);
2272064d431aSRobert Mustacchi if (entry->smbai_data == NULL) {
2273064d431aSRobert Mustacchi smb_free(entry, sizeof (smbios_addinfo_ent_t));
2274064d431aSRobert Mustacchi return (smb_set_errno(shp, ESMB_NOMEM));
2275064d431aSRobert Mustacchi }
2276064d431aSRobert Mustacchi smb_info_bcopy_offset(stp->smbst_hdr, entry->smbai_data,
2277064d431aSRobert Mustacchi entry->smbai_dlen, off + offsetof(smb_addinfo_ent_t,
2278064d431aSRobert Mustacchi smbaie_val));
2279064d431aSRobert Mustacchi } else {
2280064d431aSRobert Mustacchi entry->smbai_data = NULL;
2281064d431aSRobert Mustacchi }
2282064d431aSRobert Mustacchi
2283064d431aSRobert Mustacchi *entp = entry;
2284064d431aSRobert Mustacchi return (0);
2285064d431aSRobert Mustacchi }
2286