4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
24 * Copyright 2019 Joyent, Inc.
25 * Copyright 2024 Oxide Computer Company
26 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
31 * SMBIOS Information Routines
33 * The routines in this file are used to convert from the SMBIOS data format to
34 * a more reasonable and stable set of structures offered as part of our ABI.
35 * These functions take the general form:
37 * stp = smb_lookup_type(shp, foo);
40 * smb_info_bcopy(stp->smbst_hdr, &foo, sizeof (foo));
41 * bzero(caller's struct);
43 * copy/convert foo members into caller's struct
45 * We copy the internal structure on to an automatic variable so as to avoid
46 * checks everywhere for structures that the BIOS has improperly truncated, and
47 * also to automatically handle the case of a structure that has been extended.
48 * When necessary, this code can use smb_gteq() to determine whether the SMBIOS
49 * data is of a particular revision that is supposed to contain a new field.
51 * Note, when trying to bzero the caller's struct you have to be careful about
52 * versions. One can only bzero the initial version that existed in illumos. In
53 * other words, if someone passes an older library handle that doesn't support a
54 * version you cannot assume that their structures have those additional members
55 * in them. Instead, a 'base' version is introduced for such types that have
56 * differences and instead we only bzero out the base version and then handle
57 * the additional members. In general, because all additional members will be
58 * assigned, there's no reason to zero them out unless they are arrays that
59 * won't be entirely filled in.
61 * Due to history, anything added after the update from version 2.4, in other
62 * words additions from or after '5094 Update libsmbios with recent items'
63 * (4e901881) is currently being used for this. While we don't allow software
64 * compiling against this to get an older form, this was the first major update
65 * and a good starting point for us to enforce this behavior which is useful for
66 * moving forward to making this more public.
69 #include <sys/smbios_impl.h>
70 #include <sys/byteorder.h>
71 #include <sys/debug.h>
74 #include <sys/sunddi.h>
81 #define SMB_CONT_WORD 2 /* contained elements are word size */
84 * A large number of SMBIOS structures contain a set of common strings used to
85 * describe a h/w component's serial number, manufacturer, etc. These fields
86 * helpfully have different names and offsets and sometimes aren't consistent.
87 * To simplify life for our clients, we factor these common things out into
88 * smbios_info_t, which can be retrieved for any structure. The following
89 * table describes the mapping from a given structure to the smbios_info_t.
90 * Multiple SMBIOS stuctures' contained objects are also handled here.
92 static const struct smb_infospec
{
93 uint8_t is_type
; /* structure type */
94 uint8_t is_manu
; /* manufacturer offset */
95 uint8_t is_product
; /* product name offset */
96 uint8_t is_version
; /* version offset */
97 uint8_t is_serial
; /* serial number offset */
98 uint8_t is_asset
; /* asset tag offset */
99 uint8_t is_location
; /* location string offset */
100 uint8_t is_part
; /* part number offset */
101 uint8_t is_contc
; /* contained count */
102 uint8_t is_contsz
; /* contained size */
103 uint8_t is_contv
; /* contained objects */
104 } _smb_infospecs
[] = {
106 offsetof(smb_system_t
, smbsi_manufacturer
),
107 offsetof(smb_system_t
, smbsi_product
),
108 offsetof(smb_system_t
, smbsi_version
),
109 offsetof(smb_system_t
, smbsi_serial
),
116 { SMB_TYPE_BASEBOARD
,
117 offsetof(smb_bboard_t
, smbbb_manufacturer
),
118 offsetof(smb_bboard_t
, smbbb_product
),
119 offsetof(smb_bboard_t
, smbbb_version
),
120 offsetof(smb_bboard_t
, smbbb_serial
),
121 offsetof(smb_bboard_t
, smbbb_asset
),
122 offsetof(smb_bboard_t
, smbbb_location
),
124 offsetof(smb_bboard_t
, smbbb_cn
),
126 offsetof(smb_bboard_t
, smbbb_cv
) },
128 offsetof(smb_chassis_t
, smbch_manufacturer
),
130 offsetof(smb_chassis_t
, smbch_version
),
131 offsetof(smb_chassis_t
, smbch_serial
),
132 offsetof(smb_chassis_t
, smbch_asset
),
138 { SMB_TYPE_PROCESSOR
,
139 offsetof(smb_processor_t
, smbpr_manufacturer
),
141 offsetof(smb_processor_t
, smbpr_version
),
142 offsetof(smb_processor_t
, smbpr_serial
),
143 offsetof(smb_processor_t
, smbpr_asset
),
144 offsetof(smb_processor_t
, smbpr_socket
),
145 offsetof(smb_processor_t
, smbpr_part
),
155 offsetof(smb_cache_t
, smbca_socket
),
166 offsetof(smb_port_t
, smbpo_iref
),
177 offsetof(smb_slot_t
, smbsl_name
),
182 { SMB_TYPE_MEMDEVICE
,
183 offsetof(smb_memdevice_t
, smbmdev_manufacturer
),
186 offsetof(smb_memdevice_t
, smbmdev_serial
),
187 offsetof(smb_memdevice_t
, smbmdev_asset
),
188 offsetof(smb_memdevice_t
, smbmdev_dloc
),
189 offsetof(smb_memdevice_t
, smbmdev_part
),
194 offsetof(smb_powersup_t
, smbpsup_manufacturer
),
195 offsetof(smb_powersup_t
, smbpsup_devname
),
196 offsetof(smb_powersup_t
, smbpsup_rev
),
197 offsetof(smb_powersup_t
, smbpsup_serial
),
198 offsetof(smb_powersup_t
, smbpsup_asset
),
199 offsetof(smb_powersup_t
, smbpsup_loc
),
200 offsetof(smb_powersup_t
, smbpsup_part
),
205 offsetof(smb_battery_t
, smbbat_manufacturer
),
206 offsetof(smb_battery_t
, smbbat_devname
),
209 * While the serial number is a part of the device, because of
210 * the fact that the battery has two different serial numbers,
211 * we don't include it here.
215 offsetof(smb_battery_t
, smbbat_loc
),
222 offsetof(smb_fwinfo_t
, smbfwii_mfg
),
224 offsetof(smb_fwinfo_t
, smbfwii_vers
),
237 smb_info_strptr(const smb_struct_t
*stp
, uint8_t off
, int *n
)
239 const uint8_t *sp
= (const uint8_t *)(uintptr_t)stp
->smbst_hdr
;
241 if (off
!= 0 && sp
+ off
< stp
->smbst_end
) {
242 (*n
)++; /* indicate success for caller */
243 return (smb_strptr(stp
, sp
[off
]));
246 return (smb_strptr(stp
, 0));
250 smb_info_bcopy_offset(const smb_header_t
*hp
, void *dst
, size_t dstlen
,
253 if (offset
>= hp
->smbh_len
) {
255 } else if (offset
+ dstlen
> hp
->smbh_len
) {
256 size_t nvalid
= MIN(hp
->smbh_len
- offset
, dstlen
);
257 bcopy((char *)hp
+ offset
, dst
, nvalid
);
258 bzero((char *)dst
+ nvalid
, dstlen
- nvalid
);
260 bcopy((char *)hp
+ offset
, dst
, dstlen
);
265 smb_info_bcopy(const smb_header_t
*hp
, void *dst
, size_t dstlen
)
267 return (smb_info_bcopy_offset(hp
, dst
, dstlen
, 0));
271 smbios_info_smbios(smbios_hdl_t
*shp
, smbios_entry_t
*ep
)
273 bcopy(&shp
->sh_ent
, ep
, sizeof (smbios_entry_t
));
274 return (shp
->sh_ent_type
);
278 smbios_info_smbios_version(smbios_hdl_t
*shp
, smbios_version_t
*v
)
280 v
->smbv_major
= SMB_MAJOR(shp
->sh_smbvers
);
281 v
->smbv_minor
= SMB_MINOR(shp
->sh_smbvers
);
285 static char smbios_product_override
[256];
286 static boolean_t smbios_product_checked
;
290 smbios_info_common(smbios_hdl_t
*shp
, id_t id
, smbios_info_t
*ip
)
292 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
293 const struct smb_infospec
*isp
;
297 return (-1); /* errno is set for us */
299 for (isp
= _smb_infospecs
; isp
->is_type
!= SMB_TYPE_EOT
; isp
++) {
300 if (isp
->is_type
== stp
->smbst_hdr
->smbh_type
)
304 ip
->smbi_manufacturer
= smb_info_strptr(stp
, isp
->is_manu
, &n
);
305 ip
->smbi_product
= smb_info_strptr(stp
, isp
->is_product
, &n
);
306 ip
->smbi_version
= smb_info_strptr(stp
, isp
->is_version
, &n
);
307 ip
->smbi_serial
= smb_info_strptr(stp
, isp
->is_serial
, &n
);
308 ip
->smbi_asset
= smb_info_strptr(stp
, isp
->is_asset
, &n
);
309 ip
->smbi_location
= smb_info_strptr(stp
, isp
->is_location
, &n
);
310 ip
->smbi_part
= smb_info_strptr(stp
, isp
->is_part
, &n
);
313 * This private file allows developers to experiment with reporting
314 * different platform strings from SMBIOS. It is not a supported
315 * mechanism in the long term, and does not work in the kernel.
318 if (isp
->is_type
== SMB_TYPE_SYSTEM
) {
319 if (!smbios_product_checked
) {
320 int fd
= open("/etc/smbios_product", O_RDONLY
);
322 (void) read(fd
, smbios_product_override
,
323 sizeof (smbios_product_override
) - 1);
326 smbios_product_checked
= B_TRUE
;
329 if (smbios_product_override
[0] != '\0')
330 ip
->smbi_product
= smbios_product_override
;
335 * If we have a port with an empty internal reference designator string
336 * try using the external reference designator string instead.
338 if (isp
->is_type
== SMB_TYPE_PORT
&& ip
->smbi_location
[0] == '\0') {
339 ip
->smbi_location
= smb_info_strptr(stp
,
340 offsetof(smb_port_t
, smbpo_eref
), &n
);
343 return (n
? 0 : smb_set_errno(shp
, ESMB_NOINFO
));
347 * Returns the actual number of contained objects.
349 * idc - number of contained objects
350 * idv - returned array of contained objects
353 smbios_info_contains(smbios_hdl_t
*shp
, id_t id
, uint_t idc
, id_t
*idv
)
355 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
356 const struct smb_infospec
*isp
;
363 return (-1); /* errno is set for us */
366 for (isp
= _smb_infospecs
; isp
->is_type
!= SMB_TYPE_EOT
; isp
++) {
367 if (isp
->is_type
== stp
->smbst_hdr
->smbh_type
)
370 if (isp
->is_type
== SMB_TYPE_EOT
)
371 return (smb_set_errno(shp
, ESMB_TYPE
));
373 size
= isp
->is_contsz
;
374 cnt
= *((uint8_t *)(uintptr_t)stp
->smbst_hdr
+ isp
->is_contc
);
375 cp
= (id_t
*)((uintptr_t)stp
->smbst_hdr
+ isp
->is_contv
);
378 for (i
= 0; i
< n
; i
++) {
379 if (size
== SMB_CONT_WORD
)
380 idv
[i
] = *((uint16_t *)(uintptr_t)cp
+ (i
* 2));
382 return (smb_set_errno(shp
, ESMB_INVAL
));
389 smbios_info_bios(smbios_hdl_t
*shp
, smbios_bios_t
*bp
)
391 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_BIOS
);
392 const smb_bios_t
*bip
;
395 return (-1); /* errno is set for us */
397 if (stp
->smbst_hdr
->smbh_len
< sizeof (smb_bios_t
) - sizeof (uint8_t))
398 return (smb_set_errno(shp
, ESMB_CORRUPT
));
400 bip
= (smb_bios_t
*)(uintptr_t)stp
->smbst_hdr
;
401 bzero(bp
, sizeof (smb_base_bios_t
));
402 if (smb_libgteq(shp
, SMB_VERSION_31
)) {
403 bp
->smbb_extromsize
= 0;
406 bp
->smbb_vendor
= smb_strptr(stp
, bip
->smbbi_vendor
);
407 bp
->smbb_version
= smb_strptr(stp
, bip
->smbbi_version
);
408 bp
->smbb_segment
= bip
->smbbi_segment
;
409 bp
->smbb_reldate
= smb_strptr(stp
, bip
->smbbi_reldate
);
410 bp
->smbb_romsize
= 64 * 1024 * ((uint32_t)bip
->smbbi_romsize
+ 1);
411 bp
->smbb_runsize
= 16 * (0x10000 - (uint32_t)bip
->smbbi_segment
);
412 bp
->smbb_cflags
= bip
->smbbi_cflags
;
415 * If one or more extension bytes are present, reset smbb_xcflags to
416 * point to them. Otherwise leave this member set to NULL.
418 if (stp
->smbst_hdr
->smbh_len
>= sizeof (smb_bios_t
)) {
419 bp
->smbb_xcflags
= bip
->smbbi_xcflags
;
420 bp
->smbb_nxcflags
= stp
->smbst_hdr
->smbh_len
-
421 sizeof (smb_bios_t
) + 1;
423 if (bp
->smbb_nxcflags
> SMB_BIOSXB_ECFW_MIN
&&
424 smb_gteq(shp
, SMB_VERSION_24
)) {
425 bp
->smbb_biosv
.smbv_major
=
426 bip
->smbbi_xcflags
[SMB_BIOSXB_BIOS_MAJ
];
427 bp
->smbb_biosv
.smbv_minor
=
428 bip
->smbbi_xcflags
[SMB_BIOSXB_BIOS_MIN
];
429 bp
->smbb_ecfwv
.smbv_major
=
430 bip
->smbbi_xcflags
[SMB_BIOSXB_ECFW_MAJ
];
431 bp
->smbb_ecfwv
.smbv_minor
=
432 bip
->smbbi_xcflags
[SMB_BIOSXB_ECFW_MIN
];
435 if (bp
->smbb_nxcflags
> SMB_BIOSXB_EXTROM
+ 1 &&
436 smb_gteq(shp
, SMB_VERSION_31
)) {
441 * Because of the fact that the extended size is a
442 * uint16_t and we'd need to define an explicit
443 * endian-aware way to access it, we don't include it in
444 * the number of extended flags below and thus subtract
447 bp
->smbb_nxcflags
-= sizeof (uint16_t);
448 bcopy(&bip
->smbbi_xcflags
[SMB_BIOSXB_EXTROM
], &val
,
453 * The upper two bits of the extended rom size are used
454 * to indicate whether the other 14 bits are in MB or
457 rs
= SMB_BIOS_EXTROM_VALUE_MASK(val
);
458 switch (SMB_BIOS_EXTROM_SHIFT_MASK(val
)) {
460 rs
*= 1024ULL * 1024ULL;
463 rs
*= 1024ULL * 1024ULL * 1024ULL;
470 if (smb_libgteq(shp
, SMB_VERSION_31
)) {
471 bp
->smbb_extromsize
= rs
;
476 if (smb_libgteq(shp
, SMB_VERSION_31
) && bp
->smbb_extromsize
== 0) {
477 bp
->smbb_extromsize
= bp
->smbb_romsize
;
480 return (stp
->smbst_hdr
->smbh_hdl
);
484 smbios_info_system(smbios_hdl_t
*shp
, smbios_system_t
*sip
)
486 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_SYSTEM
);
490 return (-1); /* errno is set for us */
492 smb_info_bcopy(stp
->smbst_hdr
, &si
, sizeof (si
));
493 bzero(sip
, sizeof (smbios_system_t
));
495 sip
->smbs_uuid
= ((smb_system_t
*)stp
->smbst_hdr
)->smbsi_uuid
;
496 sip
->smbs_uuidlen
= sizeof (si
.smbsi_uuid
);
497 sip
->smbs_wakeup
= si
.smbsi_wakeup
;
498 sip
->smbs_sku
= smb_strptr(stp
, si
.smbsi_sku
);
499 sip
->smbs_family
= smb_strptr(stp
, si
.smbsi_family
);
501 return (stp
->smbst_hdr
->smbh_hdl
);
505 smbios_info_bboard(smbios_hdl_t
*shp
, id_t id
, smbios_bboard_t
*bbp
)
507 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
511 return (-1); /* errno is set for us */
513 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_BASEBOARD
)
514 return (smb_set_errno(shp
, ESMB_TYPE
));
516 smb_info_bcopy(stp
->smbst_hdr
, &bb
, sizeof (bb
));
517 bzero(bbp
, sizeof (smbios_bboard_t
));
519 bbp
->smbb_chassis
= bb
.smbbb_chassis
;
520 bbp
->smbb_flags
= bb
.smbbb_flags
;
521 bbp
->smbb_type
= bb
.smbbb_type
;
522 bbp
->smbb_contn
= bb
.smbbb_cn
;
528 smbios_info_chassis(smbios_hdl_t
*shp
, id_t id
, smbios_chassis_t
*chp
)
530 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
534 return (-1); /* errno is set for us */
537 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_CHASSIS
) {
538 return (smb_set_errno(shp
, ESMB_TYPE
));
541 if (stp
->smbst_hdr
->smbh_len
< sizeof (ch
)) {
542 return (smb_set_errno(shp
, ESMB_SHORT
));
545 smb_info_bcopy(stp
->smbst_hdr
, &ch
, sizeof (ch
));
546 bzero(chp
, sizeof (smb_base_chassis_t
));
549 * See the comments for the smb_chassis_pre35_t in sys/smbios_impl.h for
550 * an explanation as to why this is here. The use of smb_strptr with
551 * index 0 below ensures that we initialize this to an empty string.
553 if (smb_libgteq(shp
, SMB_VERSION_35
)) {
554 chp
->smbc_sku
= smb_strptr(stp
, 0);
555 } else if (smb_libgteq(shp
, SMB_VERSION_27
)) {
556 smb_chassis_pre35_t
*p35
= (smb_chassis_pre35_t
*)chp
;
557 bzero(p35
->smbc_sku
, sizeof (p35
->smbc_sku
));
560 chp
->smbc_oemdata
= ch
.smbch_oemdata
;
561 chp
->smbc_lock
= (ch
.smbch_type
& SMB_CHT_LOCK
) != 0;
562 chp
->smbc_type
= ch
.smbch_type
& ~SMB_CHT_LOCK
;
563 chp
->smbc_bustate
= ch
.smbch_bustate
;
564 chp
->smbc_psstate
= ch
.smbch_psstate
;
565 chp
->smbc_thstate
= ch
.smbch_thstate
;
566 chp
->smbc_security
= ch
.smbch_security
;
567 chp
->smbc_uheight
= ch
.smbch_uheight
;
568 chp
->smbc_cords
= ch
.smbch_cords
;
569 chp
->smbc_elems
= ch
.smbch_cn
;
570 chp
->smbc_elemlen
= ch
.smbch_cm
;
573 * If the table is older than version 2.7 which added support for the
574 * chassis SKU, there's no reason to proceed.
576 if (!smb_gteq(shp
, SMB_VERSION_27
)) {
580 if (smb_libgteq(shp
, SMB_VERSION_27
)) {
583 off_t off
= sizeof (ch
) + ch
.smbch_cn
* ch
.smbch_cm
;
584 if (stp
->smbst_hdr
->smbh_len
< off
+ 1) {
585 return (smb_set_errno(shp
, ESMB_SHORT
));
587 smb_info_bcopy_offset(stp
->smbst_hdr
, &strno
, sizeof (strno
),
589 str
= smb_strptr(stp
, strno
);
590 if (smb_libgteq(shp
, SMB_VERSION_35
)) {
593 smb_chassis_pre35_t
*p35
= (smb_chassis_pre35_t
*)chp
;
594 (void) strlcpy(p35
->smbc_sku
, str
,
595 sizeof (p35
->smbc_sku
));
603 smbios_info_chassis_elts(smbios_hdl_t
*shp
, id_t id
, uint_t
*nentsp
,
604 smbios_chassis_entry_t
**entsp
)
606 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
607 smbios_chassis_entry_t
*entry
;
613 return (-1); /* errno is set for us */
616 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_CHASSIS
) {
617 return (smb_set_errno(shp
, ESMB_TYPE
));
620 if (stp
->smbst_hdr
->smbh_len
< sizeof (ch
)) {
621 return (smb_set_errno(shp
, ESMB_SHORT
));
624 smb_info_bcopy(stp
->smbst_hdr
, &ch
, sizeof (ch
));
625 if (ch
.smbch_cm
!= sizeof (smb_chassis_entry_t
)) {
626 return (smb_set_errno(shp
, ESMB_CORRUPT
));
629 if (ch
.smbch_cn
== 0) {
635 entlen
= ch
.smbch_cm
* ch
.smbch_cn
;
636 if (stp
->smbst_hdr
->smbh_len
< sizeof (ch
) + entlen
) {
637 return (smb_set_errno(shp
, ESMB_SHORT
));
640 if ((entry
= smb_alloc(entlen
)) == NULL
) {
641 return (smb_set_errno(shp
, ESMB_NOMEM
));
644 for (i
= 0; i
< ch
.smbch_cn
; i
++) {
645 smb_chassis_entry_t e
;
646 size_t off
= sizeof (ch
) + i
* sizeof (e
);
648 smb_info_bcopy_offset(stp
->smbst_hdr
, &e
, sizeof (e
), off
);
650 * The top bit is used to indicate what type of record this is,
651 * while the lower 7-bits indicate the actual type.
653 entry
[i
].smbce_type
= e
.smbce_type
& 0x80 ?
654 SMB_CELT_SMBIOS
: SMB_CELT_BBOARD
;
655 entry
[i
].smbce_elt
= e
.smbce_type
& 0x7f;
656 entry
[i
].smbce_min
= e
.smbce_min
;
657 entry
[i
].smbce_max
= e
.smbce_max
;
661 *nentsp
= ch
.smbch_cn
;
667 smbios_info_chassis_elts_free(smbios_hdl_t
*shp
, uint_t nents
,
668 smbios_chassis_entry_t
*ent
)
670 size_t sz
= nents
* sizeof (smbios_chassis_entry_t
);
673 ASSERT3P(ent
, ==, NULL
);
681 smbios_info_processor(smbios_hdl_t
*shp
, id_t id
, smbios_processor_t
*pp
)
683 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
687 return (-1); /* errno is set for us */
689 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_PROCESSOR
)
690 return (smb_set_errno(shp
, ESMB_TYPE
));
692 smb_info_bcopy(stp
->smbst_hdr
, &p
, sizeof (p
));
693 bzero(pp
, sizeof (smb_base_processor_t
));
695 pp
->smbp_cpuid
= p
.smbpr_cpuid
;
696 pp
->smbp_type
= p
.smbpr_type
;
697 pp
->smbp_family
= p
.smbpr_family
;
698 pp
->smbp_voltage
= p
.smbpr_voltage
;
699 pp
->smbp_clkspeed
= p
.smbpr_clkspeed
;
700 pp
->smbp_maxspeed
= p
.smbpr_maxspeed
;
701 pp
->smbp_curspeed
= p
.smbpr_curspeed
;
702 pp
->smbp_status
= p
.smbpr_status
;
703 pp
->smbp_upgrade
= p
.smbpr_upgrade
;
704 pp
->smbp_l1cache
= p
.smbpr_l1cache
;
705 pp
->smbp_l2cache
= p
.smbpr_l2cache
;
706 pp
->smbp_l3cache
= p
.smbpr_l3cache
;
708 if (smb_libgteq(shp
, SMB_VERSION_25
)) {
709 pp
->smbp_corecount
= p
.smbpr_corecount
;
710 pp
->smbp_coresenabled
= p
.smbpr_coresenabled
;
711 pp
->smbp_threadcount
= p
.smbpr_threadcount
;
712 pp
->smbp_cflags
= p
.smbpr_cflags
;
715 if (smb_libgteq(shp
, SMB_VERSION_26
)) {
716 if (pp
->smbp_family
== 0xfe) {
717 pp
->smbp_family
= p
.smbpr_family2
;
721 if (smb_libgteq(shp
, SMB_VERSION_30
)) {
722 if (pp
->smbp_corecount
== 0xff) {
723 pp
->smbp_corecount
= p
.smbpr_corecount2
;
725 if (pp
->smbp_coresenabled
== 0xff) {
726 pp
->smbp_coresenabled
= p
.smbpr_coresenabled2
;
728 if (pp
->smbp_threadcount
== 0xff) {
729 pp
->smbp_threadcount
= p
.smbpr_threadcount2
;
733 if (smb_libgteq(shp
, SMB_VERSION_36
)) {
734 pp
->smbp_threadsenabled
= p
.smpbr_threaden
;
741 smbios_info_cache(smbios_hdl_t
*shp
, id_t id
, smbios_cache_t
*cap
)
743 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
747 return (-1); /* errno is set for us */
749 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_CACHE
)
750 return (smb_set_errno(shp
, ESMB_TYPE
));
752 smb_info_bcopy(stp
->smbst_hdr
, &c
, sizeof (c
));
753 bzero(cap
, sizeof (smb_base_cache_t
));
755 cap
->smba_maxsize
= SMB_CACHE_SIZE(c
.smbca_maxsize
);
756 cap
->smba_size
= SMB_CACHE_SIZE(c
.smbca_size
);
757 cap
->smba_stype
= c
.smbca_stype
;
758 cap
->smba_ctype
= c
.smbca_ctype
;
759 cap
->smba_speed
= c
.smbca_speed
;
760 cap
->smba_etype
= c
.smbca_etype
;
761 cap
->smba_ltype
= c
.smbca_ltype
;
762 cap
->smba_assoc
= c
.smbca_assoc
;
763 cap
->smba_level
= SMB_CACHE_CFG_LEVEL(c
.smbca_config
);
764 cap
->smba_mode
= SMB_CACHE_CFG_MODE(c
.smbca_config
);
765 cap
->smba_location
= SMB_CACHE_CFG_LOCATION(c
.smbca_config
);
767 if (SMB_CACHE_CFG_ENABLED(c
.smbca_config
))
768 cap
->smba_flags
|= SMB_CAF_ENABLED
;
770 if (SMB_CACHE_CFG_SOCKETED(c
.smbca_config
))
771 cap
->smba_flags
|= SMB_CAF_SOCKETED
;
773 if (smb_libgteq(shp
, SMB_VERSION_31
)) {
774 cap
->smba_maxsize2
= SMB_CACHE_EXT_SIZE(c
.smbca_maxsize2
);
775 cap
->smba_size2
= SMB_CACHE_EXT_SIZE(c
.smbca_size2
);
777 if (cap
->smba_maxsize2
== 0) {
778 cap
->smba_maxsize2
= cap
->smba_maxsize
;
781 if (cap
->smba_size2
== 0) {
782 cap
->smba_size2
= cap
->smba_size
;
790 smbios_info_port(smbios_hdl_t
*shp
, id_t id
, smbios_port_t
*pop
)
792 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
796 return (-1); /* errno is set for us */
798 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_PORT
)
799 return (smb_set_errno(shp
, ESMB_TYPE
));
801 smb_info_bcopy(stp
->smbst_hdr
, &p
, sizeof (p
));
802 bzero(pop
, sizeof (smbios_port_t
));
804 pop
->smbo_iref
= smb_strptr(stp
, p
.smbpo_iref
);
805 pop
->smbo_eref
= smb_strptr(stp
, p
.smbpo_eref
);
807 pop
->smbo_itype
= p
.smbpo_itype
;
808 pop
->smbo_etype
= p
.smbpo_etype
;
809 pop
->smbo_ptype
= p
.smbpo_ptype
;
815 smbios_info_slot(smbios_hdl_t
*shp
, id_t id
, smbios_slot_t
*sp
)
817 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
819 smb_slot_cont_t cont
;
823 return (-1); /* errno is set for us */
825 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_SLOT
)
826 return (smb_set_errno(shp
, ESMB_TYPE
));
828 smb_info_bcopy(stp
->smbst_hdr
, &s
, sizeof (s
));
829 bzero(sp
, sizeof (smb_base_slot_t
));
831 sp
->smbl_name
= smb_strptr(stp
, s
.smbsl_name
);
832 sp
->smbl_type
= s
.smbsl_type
;
833 sp
->smbl_width
= s
.smbsl_width
;
834 sp
->smbl_usage
= s
.smbsl_usage
;
835 sp
->smbl_length
= s
.smbsl_length
;
836 sp
->smbl_id
= s
.smbsl_id
;
837 sp
->smbl_ch1
= s
.smbsl_ch1
;
838 sp
->smbl_ch2
= s
.smbsl_ch2
;
839 sp
->smbl_sg
= s
.smbsl_sg
;
840 sp
->smbl_bus
= s
.smbsl_bus
;
841 sp
->smbl_df
= s
.smbsl_df
;
843 if (smb_libgteq(shp
, SMB_VERSION_32
)) {
844 sp
->smbl_dbw
= s
.smbsl_dbw
;
845 sp
->smbl_npeers
= s
.smbsl_npeers
;
848 if (!smb_libgteq(shp
, SMB_VERSION_34
)) {
853 * In SMBIOS 3.4, several members were added to follow the variable
854 * number of peers. These are defined to start at byte 0x14 + 5 *
855 * npeers. If the table is from before 3.4, we simple zero things out.
856 * Otherwise we check if the length covers the peers and this addendum
857 * to include it as the table length is allowed to be less than this and
860 off
= SMB_SLOT_CONT_START
+ 5 * s
.smbsl_npeers
;
861 smb_info_bcopy_offset(stp
->smbst_hdr
, &cont
, sizeof (cont
), off
);
862 sp
->smbl_info
= cont
.smbsl_info
;
863 sp
->smbl_pwidth
= cont
.smbsl_pwidth
;
864 sp
->smbl_pitch
= cont
.smbsl_pitch
;
866 if (smb_libgteq(shp
, SMB_VERSION_35
)) {
867 sp
->smbl_height
= cont
.smbsl_height
;
874 smbios_info_slot_peers_free(smbios_hdl_t
*shp
, uint_t npeers
,
875 smbios_slot_peer_t
*peer
)
877 size_t sz
= npeers
* sizeof (smbios_slot_peer_t
);
880 ASSERT3P(peer
, ==, NULL
);
888 smbios_info_slot_peers(smbios_hdl_t
*shp
, id_t id
, uint_t
*npeers
,
889 smbios_slot_peer_t
**peerp
)
891 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
892 const smb_slot_t
*slotp
;
893 smbios_slot_peer_t
*peer
;
898 return (-1); /* errno is set for us */
900 slotp
= (const smb_slot_t
*)stp
->smbst_hdr
;
902 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_SLOT
)
903 return (smb_set_errno(shp
, ESMB_TYPE
));
905 if (stp
->smbst_hdr
->smbh_len
<= offsetof(smb_slot_t
, smbsl_npeers
) ||
906 slotp
->smbsl_npeers
== 0) {
913 * Make sure that the size of the structure makes sense for the number
916 minlen
= slotp
->smbsl_npeers
* sizeof (smb_slot_peer_t
) +
917 offsetof(smb_slot_t
, smbsl_npeers
);
918 if (stp
->smbst_hdr
->smbh_len
< minlen
) {
919 return (smb_set_errno(shp
, ESMB_SHORT
));
922 if ((peer
= smb_alloc(slotp
->smbsl_npeers
*
923 sizeof (smbios_slot_peer_t
))) == NULL
) {
924 return (smb_set_errno(shp
, ESMB_NOMEM
));
927 for (i
= 0; i
< slotp
->smbsl_npeers
; i
++) {
928 peer
[i
].smblp_group
= slotp
->smbsl_peers
[i
].smbspb_group_no
;
929 peer
[i
].smblp_bus
= slotp
->smbsl_peers
[i
].smbspb_bus
;
930 peer
[i
].smblp_device
= slotp
->smbsl_peers
[i
].smbspb_df
>> 3;
931 peer
[i
].smblp_function
= slotp
->smbsl_peers
[i
].smbspb_df
& 0x7;
932 peer
[i
].smblp_data_width
= slotp
->smbsl_peers
[i
].smbspb_width
;
935 *npeers
= slotp
->smbsl_npeers
;
942 smbios_info_obdevs_ext(smbios_hdl_t
*shp
, id_t id
, smbios_obdev_ext_t
*oep
)
944 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
948 return (-1); /* errno is set for us */
950 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OBDEVEXT
)
951 return (smb_set_errno(shp
, ESMB_TYPE
));
953 smb_info_bcopy(stp
->smbst_hdr
, &obe
, sizeof (obe
));
954 bzero(oep
, sizeof (smbios_obdev_ext_t
));
956 oep
->smboe_name
= smb_strptr(stp
, obe
.smbobe_name
);
957 oep
->smboe_dtype
= obe
.smbobe_dtype
;
958 oep
->smboe_dti
= obe
.smbobe_dti
;
959 oep
->smboe_sg
= obe
.smbobe_sg
;
960 oep
->smboe_bus
= obe
.smbobe_bus
;
961 oep
->smboe_df
= obe
.smbobe_df
;
967 smbios_info_obdevs(smbios_hdl_t
*shp
, id_t id
, int obc
, smbios_obdev_t
*obp
)
969 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
970 const smb_obdev_t
*op
;
974 return (-1); /* errno is set for us */
976 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OBDEVS
)
977 return (smb_set_errno(shp
, ESMB_TYPE
));
979 op
= (smb_obdev_t
*)((uintptr_t)stp
->smbst_hdr
+ sizeof (smb_header_t
));
980 m
= (stp
->smbst_hdr
->smbh_len
- sizeof (smb_header_t
)) / sizeof (*op
);
983 for (i
= 0; i
< n
; i
++, op
++, obp
++) {
984 obp
->smbd_name
= smb_strptr(stp
, op
->smbob_name
);
985 obp
->smbd_type
= op
->smbob_type
& ~SMB_OBT_ENABLED
;
986 obp
->smbd_enabled
= (op
->smbob_type
& SMB_OBT_ENABLED
) != 0;
993 * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the
994 * first byte to indicate the size of a string table at the end of the record.
995 * Therefore, smbios_info_strtab() can be used to retrieve the table size and
996 * strings for any of these underlying record types.
999 smbios_info_strtab(smbios_hdl_t
*shp
, id_t id
, int argc
, const char *argv
[])
1001 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1006 return (-1); /* errno is set for us */
1008 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OEMSTR
&&
1009 stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_SYSCONFSTR
&&
1010 stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_LANG
)
1011 return (smb_set_errno(shp
, ESMB_TYPE
));
1013 smb_info_bcopy(stp
->smbst_hdr
, &s
, sizeof (s
));
1014 n
= MIN(s
.smbtb_count
, argc
);
1016 for (i
= 0; i
< n
; i
++)
1017 argv
[i
] = smb_strptr(stp
, i
+ 1);
1019 return (s
.smbtb_count
);
1023 smbios_info_lang(smbios_hdl_t
*shp
, smbios_lang_t
*lp
)
1025 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_LANG
);
1029 return (-1); /* errno is set for us */
1031 smb_info_bcopy(stp
->smbst_hdr
, &l
, sizeof (l
));
1032 bzero(lp
, sizeof (smbios_lang_t
));
1034 lp
->smbla_cur
= smb_strptr(stp
, l
.smblang_cur
);
1035 lp
->smbla_fmt
= l
.smblang_flags
& 1;
1036 lp
->smbla_num
= l
.smblang_num
;
1038 return (stp
->smbst_hdr
->smbh_hdl
);
1042 smbios_info_eventlog(smbios_hdl_t
*shp
, smbios_evlog_t
*evp
)
1044 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_EVENTLOG
);
1045 const smb_sel_t
*sel
;
1049 return (-1); /* errno is set for us */
1051 if (stp
->smbst_hdr
->smbh_len
< sizeof (smb_sel_t
) - sizeof (uint8_t))
1052 return (smb_set_errno(shp
, ESMB_CORRUPT
));
1054 sel
= (smb_sel_t
*)(uintptr_t)stp
->smbst_hdr
;
1055 len
= stp
->smbst_hdr
->smbh_len
- sizeof (smb_sel_t
) + sizeof (uint8_t);
1056 bzero(evp
, sizeof (smbios_evlog_t
));
1058 if (len
< sel
->smbsel_typec
* sel
->smbsel_typesz
)
1059 return (smb_set_errno(shp
, ESMB_CORRUPT
));
1061 evp
->smbev_size
= sel
->smbsel_len
;
1062 evp
->smbev_hdr
= sel
->smbsel_hdroff
;
1063 evp
->smbev_data
= sel
->smbsel_dataoff
;
1064 evp
->smbev_method
= sel
->smbsel_method
;
1065 evp
->smbev_flags
= sel
->smbsel_status
;
1066 evp
->smbev_format
= sel
->smbsel_format
;
1067 evp
->smbev_token
= sel
->smbsel_token
;
1068 evp
->smbev_addr
.eva_addr
= sel
->smbsel_addr
;
1070 if (sel
->smbsel_typesz
== sizeof (smbios_evtype_t
)) {
1071 evp
->smbev_typec
= sel
->smbsel_typec
;
1072 evp
->smbev_typev
= (void *)(uintptr_t)sel
->smbsel_typev
;
1075 return (stp
->smbst_hdr
->smbh_hdl
);
1079 smbios_info_memarray(smbios_hdl_t
*shp
, id_t id
, smbios_memarray_t
*map
)
1081 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1085 return (-1); /* errno is set for us */
1087 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMARRAY
)
1088 return (smb_set_errno(shp
, ESMB_TYPE
));
1090 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
1091 bzero(map
, sizeof (smbios_memarray_t
));
1093 map
->smbma_location
= m
.smbmarr_loc
;
1094 map
->smbma_use
= m
.smbmarr_use
;
1095 map
->smbma_ecc
= m
.smbmarr_ecc
;
1096 map
->smbma_ndevs
= m
.smbmarr_ndevs
;
1097 map
->smbma_err
= m
.smbmarr_err
;
1099 if (m
.smbmarr_cap
!= 0x80000000)
1100 map
->smbma_size
= (uint64_t)m
.smbmarr_cap
* 1024;
1101 else if (m
.smbmarr_extcap
!= 0)
1102 map
->smbma_size
= m
.smbmarr_extcap
;
1104 map
->smbma_size
= 0; /* unknown */
1110 smbios_info_memarrmap(smbios_hdl_t
*shp
, id_t id
, smbios_memarrmap_t
*map
)
1112 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1116 return (-1); /* errno is set for us */
1118 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMARRAYMAP
)
1119 return (smb_set_errno(shp
, ESMB_TYPE
));
1121 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
1122 bzero(map
, sizeof (smbios_memarrmap_t
));
1124 map
->smbmam_array
= m
.smbamap_array
;
1125 map
->smbmam_width
= m
.smbamap_width
;
1127 if (m
.smbamap_start
!= 0xFFFFFFFF && m
.smbamap_end
!= 0xFFFFFFFF) {
1128 map
->smbmam_addr
= (uint64_t)m
.smbamap_start
* 1024;
1129 map
->smbmam_size
= (uint64_t)
1130 (m
.smbamap_end
- m
.smbamap_start
+ 1) * 1024;
1131 } else if (m
.smbamap_extstart
!= 0 && m
.smbamap_extend
!= 0) {
1132 map
->smbmam_addr
= m
.smbamap_extstart
;
1133 map
->smbmam_size
= m
.smbamap_extend
- m
.smbamap_extstart
+ 1;
1140 smbios_info_memdevice(smbios_hdl_t
*shp
, id_t id
, smbios_memdevice_t
*mdp
)
1142 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1146 return (-1); /* errno is set for us */
1148 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMDEVICE
)
1149 return (smb_set_errno(shp
, ESMB_TYPE
));
1151 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
1152 bzero(mdp
, sizeof (smb_base_memdevice_t
));
1154 mdp
->smbmd_array
= m
.smbmdev_array
;
1155 mdp
->smbmd_error
= m
.smbmdev_error
;
1156 mdp
->smbmd_twidth
= m
.smbmdev_twidth
== 0xFFFF ? -1U : m
.smbmdev_twidth
;
1157 mdp
->smbmd_dwidth
= m
.smbmdev_dwidth
== 0xFFFF ? -1U : m
.smbmdev_dwidth
;
1159 if (m
.smbmdev_size
== 0x7FFF) {
1160 mdp
->smbmd_size
= (uint64_t)m
.smbmdev_extsize
;
1161 mdp
->smbmd_size
*= 1024 * 1024; /* convert MB to bytes */
1162 } else if (m
.smbmdev_size
!= 0xFFFF) {
1163 mdp
->smbmd_size
= (uint64_t)(m
.smbmdev_size
& ~SMB_MDS_KBYTES
);
1164 if (m
.smbmdev_size
& SMB_MDS_KBYTES
)
1165 mdp
->smbmd_size
*= 1024;
1167 mdp
->smbmd_size
*= 1024 * 1024;
1169 mdp
->smbmd_size
= -1ULL; /* size unknown */
1171 mdp
->smbmd_form
= m
.smbmdev_form
;
1172 mdp
->smbmd_set
= m
.smbmdev_set
;
1173 mdp
->smbmd_type
= m
.smbmdev_type
;
1174 mdp
->smbmd_speed
= m
.smbmdev_speed
;
1175 mdp
->smbmd_flags
= m
.smbmdev_flags
;
1176 mdp
->smbmd_dloc
= smb_strptr(stp
, m
.smbmdev_dloc
);
1177 mdp
->smbmd_bloc
= smb_strptr(stp
, m
.smbmdev_bloc
);
1179 if (smb_libgteq(shp
, SMB_VERSION_26
)) {
1180 mdp
->smbmd_rank
= m
.smbmdev_attrs
& 0x0F;
1183 if (smb_libgteq(shp
, SMB_VERSION_27
)) {
1184 mdp
->smbmd_clkspeed
= m
.smbmdev_clkspeed
;
1187 if (smb_libgteq(shp
, SMB_VERSION_28
)) {
1188 mdp
->smbmd_minvolt
= m
.smbmdev_minvolt
;
1189 mdp
->smbmd_maxvolt
= m
.smbmdev_maxvolt
;
1190 mdp
->smbmd_confvolt
= m
.smbmdev_confvolt
;
1193 if (smb_libgteq(shp
, SMB_VERSION_32
)) {
1194 mdp
->smbmd_memtech
= m
.smbmdev_memtech
;
1195 mdp
->smbmd_opcap_flags
= m
.smbmdev_opmode
;
1196 mdp
->smbmd_firmware_rev
= smb_strptr(stp
,
1198 mdp
->smbmd_modmfg_id
= m
.smbmdev_modulemfgid
;
1199 mdp
->smbmd_modprod_id
= m
.smbmdev_moduleprodid
;
1200 mdp
->smbmd_cntrlmfg_id
= m
.smbmdev_memsysmfgid
;
1201 mdp
->smbmd_cntrlprod_id
= m
.smbmdev_memsysprodid
;
1202 mdp
->smbmd_nvsize
= m
.smbmdev_nvsize
;
1203 mdp
->smbmd_volatile_size
= m
.smbmdev_volsize
;
1204 mdp
->smbmd_cache_size
= m
.smbmdev_cachesize
;
1205 mdp
->smbmd_logical_size
= m
.smbmdev_logicalsize
;
1208 if (smb_libgteq(shp
, SMB_VERSION_33
)) {
1209 if (m
.smbmdev_speed
== 0xffff) {
1210 mdp
->smbmd_extspeed
= m
.smbmdev_extspeed
;
1212 mdp
->smbmd_extspeed
= m
.smbmdev_speed
;
1215 if (m
.smbmdev_clkspeed
== 0xffff) {
1216 mdp
->smbmd_extclkspeed
= m
.smbmdev_extclkspeed
;
1218 mdp
->smbmd_extclkspeed
= m
.smbmdev_clkspeed
;
1223 * The unknown key for missing revision information for the RCD and
1224 * PMIC0 is not all zeros. As such, we need to look if the device SMBIOS
1225 * table is not 3.7 then we need to fix up the bits that we copied.
1226 * After that we need to go back and check the consumer's version to
1227 * actually place this data there.
1229 if (!smb_gteq(shp
, SMB_VERSION_37
)) {
1230 m
.smbmdev_pmic0mfgid
= SMB_MD_MFG_UNKNOWN
;
1231 m
.smbmdev_pmic0rev
= SMB_MD_REV_UNKNOWN
;
1232 m
.smbmdev_rcdmfgid
= SMB_MD_MFG_UNKNOWN
;
1233 m
.smbmdev_rcdrev
= SMB_MD_REV_UNKNOWN
;
1236 if (smb_libgteq(shp
, SMB_VERSION_37
)) {
1237 mdp
->smbmd_pmic0_mfgid
= m
.smbmdev_pmic0mfgid
;
1238 mdp
->smbmd_pmic0_rev
= m
.smbmdev_pmic0rev
;
1239 mdp
->smbmd_rcd_mfgid
= m
.smbmdev_rcdmfgid
;
1240 mdp
->smbmd_rcd_rev
= m
.smbmdev_rcdrev
;
1247 smbios_info_memdevmap(smbios_hdl_t
*shp
, id_t id
, smbios_memdevmap_t
*mdp
)
1249 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1253 return (-1); /* errno is set for us */
1255 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMDEVICEMAP
)
1256 return (smb_set_errno(shp
, ESMB_TYPE
));
1258 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
1259 bzero(mdp
, sizeof (smbios_memdevmap_t
));
1261 mdp
->smbmdm_device
= m
.smbdmap_device
;
1262 mdp
->smbmdm_arrmap
= m
.smbdmap_array
;
1263 mdp
->smbmdm_rpos
= m
.smbdmap_rpos
;
1264 mdp
->smbmdm_ipos
= m
.smbdmap_ipos
;
1265 mdp
->smbmdm_idepth
= m
.smbdmap_idepth
;
1267 if (m
.smbdmap_start
!= 0xFFFFFFFF && m
.smbdmap_end
!= 0xFFFFFFFF) {
1268 mdp
->smbmdm_addr
= (uint64_t)m
.smbdmap_start
* 1024;
1269 mdp
->smbmdm_size
= (uint64_t)
1270 (m
.smbdmap_end
- m
.smbdmap_start
+ 1) * 1024;
1271 } else if (m
.smbdmap_extstart
!= 0 && m
.smbdmap_extend
!= 0) {
1272 mdp
->smbmdm_addr
= m
.smbdmap_extstart
;
1273 mdp
->smbmdm_size
= m
.smbdmap_extend
- m
.smbdmap_extstart
+ 1;
1280 smbios_info_hwsec(smbios_hdl_t
*shp
, smbios_hwsec_t
*hsp
)
1282 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_SECURITY
);
1286 return (-1); /* errno is set for us */
1288 smb_info_bcopy(stp
->smbst_hdr
, &hs
, sizeof (hs
));
1289 bzero(hsp
, sizeof (smbios_hwsec_t
));
1291 hsp
->smbh_pwr_ps
= SMB_HWS_PWR_PS(hs
.smbhs_settings
);
1292 hsp
->smbh_kbd_ps
= SMB_HWS_KBD_PS(hs
.smbhs_settings
);
1293 hsp
->smbh_adm_ps
= SMB_HWS_ADM_PS(hs
.smbhs_settings
);
1294 hsp
->smbh_pan_ps
= SMB_HWS_PAN_PS(hs
.smbhs_settings
);
1296 return (stp
->smbst_hdr
->smbh_hdl
);
1300 smbios_info_boot(smbios_hdl_t
*shp
, smbios_boot_t
*bp
)
1302 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_BOOT
);
1303 const smb_boot_t
*b
;
1306 return (-1); /* errno is set for us */
1308 bzero(bp
, sizeof (smbios_boot_t
));
1310 b
= (smb_boot_t
*)(uintptr_t)stp
->smbst_hdr
;
1312 bp
->smbt_status
= b
->smbbo_status
[0];
1313 bp
->smbt_size
= stp
->smbst_hdr
->smbh_len
- sizeof (smb_boot_t
);
1314 bp
->smbt_data
= bp
->smbt_size
? &b
->smbbo_status
[1] : NULL
;
1316 return (stp
->smbst_hdr
->smbh_hdl
);
1320 smbios_info_ipmi(smbios_hdl_t
*shp
, smbios_ipmi_t
*ip
)
1322 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_IPMIDEV
);
1326 return (-1); /* errno is set for us */
1328 smb_info_bcopy(stp
->smbst_hdr
, &i
, sizeof (i
));
1329 bzero(ip
, sizeof (smbios_ipmi_t
));
1331 ip
->smbip_type
= i
.smbipm_type
;
1332 ip
->smbip_vers
.smbv_major
= SMB_IPM_SPEC_MAJOR(i
.smbipm_spec
);
1333 ip
->smbip_vers
.smbv_minor
= SMB_IPM_SPEC_MINOR(i
.smbipm_spec
);
1334 ip
->smbip_i2c
= i
.smbipm_i2c
;
1335 ip
->smbip_addr
= i
.smbipm_addr
& ~SMB_IPM_ADDR_IO
;
1336 ip
->smbip_intr
= i
.smbipm_intr
;
1338 if (i
.smbipm_bus
!= (uint8_t)-1)
1339 ip
->smbip_bus
= i
.smbipm_bus
;
1341 ip
->smbip_bus
= -1u;
1343 if (SMB_IPM_INFO_LSB(i
.smbipm_info
))
1344 ip
->smbip_addr
|= 1; /* turn on least-significant bit of addr */
1346 if (i
.smbipm_addr
& SMB_IPM_ADDR_IO
) {
1347 switch (SMB_IPM_INFO_REGS(i
.smbipm_info
)) {
1348 case SMB_IPM_REGS_1B
:
1349 ip
->smbip_regspacing
= 1;
1351 case SMB_IPM_REGS_4B
:
1352 ip
->smbip_regspacing
= 4;
1354 case SMB_IPM_REGS_16B
:
1355 ip
->smbip_regspacing
= 16;
1358 ip
->smbip_regspacing
= 1;
1360 ip
->smbip_flags
|= SMB_IPMI_F_IOADDR
;
1363 if (SMB_IPM_INFO_ISPEC(i
.smbipm_info
))
1364 ip
->smbip_flags
|= SMB_IPMI_F_INTRSPEC
;
1366 if (SMB_IPM_INFO_IPOL(i
.smbipm_info
) == SMB_IPM_IPOL_HI
)
1367 ip
->smbip_flags
|= SMB_IPMI_F_INTRHIGH
;
1369 if (SMB_IPM_INFO_IMODE(i
.smbipm_info
) == SMB_IPM_IMODE_EDGE
)
1370 ip
->smbip_flags
|= SMB_IPMI_F_INTREDGE
;
1372 return (stp
->smbst_hdr
->smbh_hdl
);
1376 smbios_has_oemstr(smbios_hdl_t
*shp
, const char *oemstr
)
1378 const smb_struct_t
*stp
= shp
->sh_structs
;
1382 for (i
= 0; i
< shp
->sh_nstructs
; i
++, stp
++) {
1383 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OEMSTR
)
1386 smb_info_bcopy(stp
->smbst_hdr
, &s
, sizeof (s
));
1387 for (j
= 0; j
< s
.smbtb_count
; j
++)
1388 if (strcmp(smb_strptr(stp
, j
+ 1), oemstr
) == 0)
1396 smb_serial_valid(const char *serial
)
1398 char buf
[MAXNAMELEN
];
1404 (void) strlcpy(buf
, serial
, sizeof (buf
));
1406 while (buf
[i
] != '\0' && buf
[i
] == ' ')
1409 if (buf
[i
] == '\0' || strstr(buf
, SMB_DEFAULT1
) != NULL
||
1410 strstr(buf
, SMB_DEFAULT2
) != NULL
)
1417 * Get chassis SN or product SN
1420 smb_get_sn(smbios_hdl_t
*shp
, const char **psnp
, const char **csnp
)
1422 const smb_struct_t
*stp
;
1423 smbios_info_t s1
, s3
;
1425 if (psnp
== NULL
|| csnp
== NULL
)
1426 return (smb_set_errno(shp
, ESMB_INVAL
));
1428 *psnp
= *csnp
= NULL
;
1431 * If SMBIOS meets Sun's PRMS requirements, retrieve product SN
1432 * from type 1 structure, and chassis SN from type 3 structure.
1433 * Otherwise return SN in type 1 structure as chassis SN.
1437 if ((stp
= smb_lookup_type(shp
, SMB_TYPE_SYSTEM
)) == NULL
||
1438 smbios_info_common(shp
, stp
->smbst_hdr
->smbh_hdl
, &s1
) == SMB_ERR
)
1439 s1
.smbi_serial
= NULL
;
1442 if ((stp
= smb_lookup_type(shp
, SMB_TYPE_CHASSIS
)) == NULL
||
1443 smbios_info_common(shp
, stp
->smbst_hdr
->smbh_hdl
, &s3
) == SMB_ERR
)
1444 s3
.smbi_serial
= NULL
;
1446 if (smbios_has_oemstr(shp
, SMB_PRMS1
)) {
1447 *psnp
= smb_serial_valid(s1
.smbi_serial
);
1448 *csnp
= smb_serial_valid(s3
.smbi_serial
);
1450 *csnp
= smb_serial_valid(s1
.smbi_serial
);
1457 smbios_psn(smbios_hdl_t
*shp
)
1459 const char *psn
, *csn
;
1461 return (smb_get_sn(shp
, &psn
, &csn
) == SMB_ERR
? NULL
: psn
);
1465 smbios_csn(smbios_hdl_t
*shp
)
1467 const char *psn
, *csn
;
1469 return (smb_get_sn(shp
, &psn
, &csn
) == SMB_ERR
? NULL
: csn
);
1473 smbios_info_extprocessor(smbios_hdl_t
*shp
, id_t id
,
1474 smbios_processor_ext_t
*epp
)
1476 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1477 smb_processor_ext_t
*exp
;
1480 return (-1); /* errno is set for us */
1482 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_PROCESSOR
)
1483 return (smb_set_errno(shp
, ESMB_TYPE
));
1485 exp
= (smb_processor_ext_t
*)(uintptr_t)stp
->smbst_hdr
;
1486 bzero(epp
, sizeof (smbios_processor_ext_t
));
1488 epp
->smbpe_processor
= exp
->smbpre_processor
;
1489 epp
->smbpe_fru
= exp
->smbpre_fru
;
1490 epp
->smbpe_n
= exp
->smbpre_n
;
1491 epp
->smbpe_apicid
= exp
->smbpre_apicid
;
1497 smbios_info_extport(smbios_hdl_t
*shp
, id_t id
, smbios_port_ext_t
*eportp
)
1499 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1503 return (-1); /* errno is set for us */
1505 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_PORT
)
1506 return (smb_set_errno(shp
, ESMB_TYPE
));
1508 ep
= (smb_port_ext_t
*)(uintptr_t)stp
->smbst_hdr
;
1509 bzero(eportp
, sizeof (smbios_port_ext_t
));
1511 eportp
->smbporte_chassis
= ep
->smbpoe_chassis
;
1512 eportp
->smbporte_port
= ep
->smbpoe_port
;
1513 eportp
->smbporte_dtype
= ep
->smbpoe_dtype
;
1514 eportp
->smbporte_devhdl
= ep
->smbpoe_devhdl
;
1515 eportp
->smbporte_phy
= ep
->smbpoe_phy
;
1521 smbios_info_pciexrc(smbios_hdl_t
*shp
, id_t id
,
1522 smbios_pciexrc_t
*rcp
)
1524 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1528 return (-1); /* errno is set for us */
1530 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_PCIEXRC
)
1531 return (smb_set_errno(shp
, ESMB_TYPE
));
1533 smb_info_bcopy(stp
->smbst_hdr
, &rc
, sizeof (rc
));
1534 bzero(rcp
, sizeof (smbios_pciexrc_t
));
1536 rcp
->smbpcie_bb
= rc
.smbpciexrc_bboard
;
1537 rcp
->smbpcie_bdf
= rc
.smbpciexrc_bdf
;
1543 smbios_info_extmemarray(smbios_hdl_t
*shp
, id_t id
, smbios_memarray_ext_t
*emap
)
1545 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1546 smb_memarray_ext_t exma
;
1549 return (-1); /* errno is set for us */
1551 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_MEMARRAY
)
1552 return (smb_set_errno(shp
, ESMB_TYPE
));
1554 smb_info_bcopy(stp
->smbst_hdr
, &exma
, sizeof (exma
));
1555 bzero(emap
, sizeof (smbios_memarray_ext_t
));
1557 emap
->smbmae_ma
= exma
.smbmarre_ma
;
1558 emap
->smbmae_comp
= exma
.smbmarre_component
;
1559 emap
->smbmae_bdf
= exma
.smbmarre_bdf
;
1565 smbios_info_extmemdevice(smbios_hdl_t
*shp
, id_t id
,
1566 smbios_memdevice_ext_t
*emdp
)
1568 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1569 smb_memdevice_ext_t exmd
;
1572 return (-1); /* errno is set for us */
1574 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_MEMDEVICE
)
1575 return (smb_set_errno(shp
, ESMB_TYPE
));
1577 smb_info_bcopy(stp
->smbst_hdr
, &exmd
, sizeof (exmd
));
1578 bzero(emdp
, sizeof (smbios_memdevice_ext_t
));
1580 emdp
->smbmdeve_md
= exmd
.smbmdeve_mdev
;
1581 emdp
->smbmdeve_drch
= exmd
.smbmdeve_dchan
;
1582 emdp
->smbmdeve_ncs
= exmd
.smbmdeve_ncs
;
1588 smbios_info_extmemdevice_cs(smbios_hdl_t
*shp
, id_t id
, uint_t
*ncsp
,
1591 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1592 smb_memdevice_ext_t exmd
;
1597 return (-1); /* errno is set for us */
1599 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_MEMDEVICE
)
1600 return (smb_set_errno(shp
, ESMB_TYPE
));
1602 smb_info_bcopy(stp
->smbst_hdr
, &exmd
, sizeof (exmd
));
1603 if (exmd
.smbmdeve_ncs
== 0) {
1609 size
= exmd
.smbmdeve_ncs
* sizeof (*exmd
.smbmdeve_cs
);
1611 if (stp
->smbst_hdr
->smbh_len
< sizeof (exmd
) + size
)
1612 return (smb_set_errno(shp
, ESMB_SHORT
));
1614 buf
= smb_alloc(size
);
1616 return (smb_set_errno(shp
, ESMB_NOMEM
));
1617 smb_info_bcopy_offset(stp
->smbst_hdr
, buf
, size
, sizeof (exmd
));
1619 *ncsp
= exmd
.smbmdeve_ncs
;
1625 smbios_info_extmemdevice_cs_free(smbios_hdl_t
*shp __unused
, uint_t ncs
,
1628 size_t size
= ncs
* sizeof (uint8_t);
1631 ASSERT3P(csp
, ==, NULL
);
1634 smb_free(csp
, size
);
1638 smbios_info_powersup(smbios_hdl_t
*shp
, id_t id
, smbios_powersup_t
*psup
)
1640 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1644 return (-1); /* errno is set for us */
1646 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_POWERSUP
)
1647 return (smb_set_errno(shp
, ESMB_TYPE
));
1649 /* The minimum length required by the spec is 0x10. */
1650 if (stp
->smbst_hdr
->smbh_len
< 0x10)
1651 return (smb_set_errno(shp
, ESMB_SHORT
));
1653 bzero(psup
, sizeof (*psup
));
1654 smb_info_bcopy(stp
->smbst_hdr
, &psu
, sizeof (psu
));
1655 psup
->smbps_group
= psu
.smbpsup_group
;
1656 psup
->smbps_maxout
= psu
.smbpsup_max
;
1658 if (SMB_PSU_CHARS_ISHOT(psu
.smbpsup_char
))
1659 psup
->smbps_flags
|= SMB_POWERSUP_F_HOT
;
1660 if (SMB_PSU_CHARS_ISPRES(psu
.smbpsup_char
))
1661 psup
->smbps_flags
|= SMB_POWERSUP_F_PRESENT
;
1662 if (SMB_PSU_CHARS_ISUNPLUG(psu
.smbpsup_char
))
1663 psup
->smbps_flags
|= SMB_POWERSUP_F_UNPLUG
;
1665 psup
->smbps_ivrs
= SMB_PSU_CHARS_IVRS(psu
.smbpsup_char
);
1666 psup
->smbps_status
= SMB_PSU_CHARS_STATUS(psu
.smbpsup_char
);
1667 psup
->smbps_pstype
= SMB_PSU_CHARS_TYPE(psu
.smbpsup_char
);
1669 if (stp
->smbst_hdr
->smbh_len
>= 0x12) {
1670 psup
->smbps_vprobe
= psu
.smbpsup_vprobe
;
1672 psup
->smbps_vprobe
= 0xffff;
1675 if (stp
->smbst_hdr
->smbh_len
>= 0x14) {
1676 psup
->smbps_cooldev
= psu
.smbpsup_cooldev
;
1678 psup
->smbps_cooldev
= 0xffff;
1681 if (stp
->smbst_hdr
->smbh_len
>= 0x16) {
1682 psup
->smbps_iprobe
= psu
.smbpsup_iprobe
;
1684 psup
->smbps_iprobe
= 0xffff;
1691 smbios_info_vprobe(smbios_hdl_t
*shp
, id_t id
, smbios_vprobe_t
*vprobe
)
1693 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1697 return (-1); /* errno is set for us */
1699 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_VPROBE
)
1700 return (smb_set_errno(shp
, ESMB_TYPE
));
1702 if (stp
->smbst_hdr
->smbh_len
< SMB_VPROBE_MINLEN
)
1703 return (smb_set_errno(shp
, ESMB_SHORT
));
1705 bzero(vprobe
, sizeof (*vprobe
));
1706 smb_info_bcopy(stp
->smbst_hdr
, &vp
, sizeof (vp
));
1707 vprobe
->smbvp_description
= smb_strptr(stp
, vp
.smbvpr_descr
);
1708 vprobe
->smbvp_location
= SMB_VPROBE_LOCATION(vp
.smbvpr_locstat
);
1709 vprobe
->smbvp_status
= SMB_VPROBE_STATUS(vp
.smbvpr_locstat
);
1710 vprobe
->smbvp_maxval
= vp
.smbvpr_maxval
;
1711 vprobe
->smbvp_minval
= vp
.smbvpr_minval
;
1712 vprobe
->smbvp_resolution
= vp
.smbvpr_resolution
;
1713 vprobe
->smbvp_tolerance
= vp
.smbvpr_tolerance
;
1714 vprobe
->smbvp_accuracy
= vp
.smbvpr_accuracy
;
1716 if (stp
->smbst_hdr
->smbh_len
>= SMB_VPROBE_NOMINAL_MINLEN
) {
1717 vprobe
->smbvp_nominal
= vp
.smbvpr_nominal
;
1719 vprobe
->smbvp_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1726 smbios_info_cooldev(smbios_hdl_t
*shp
, id_t id
, smbios_cooldev_t
*cooldev
)
1728 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1732 return (-1); /* errno is set for us */
1734 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_COOLDEV
)
1735 return (smb_set_errno(shp
, ESMB_TYPE
));
1737 if (stp
->smbst_hdr
->smbh_len
< SMB_COOLDEV_MINLEN
)
1738 return (smb_set_errno(shp
, ESMB_SHORT
));
1740 bzero(cooldev
, sizeof (*cooldev
));
1741 smb_info_bcopy(stp
->smbst_hdr
, &cd
, sizeof (cd
));
1742 cooldev
->smbcd_tprobe
= cd
.smbcdev_tprobe
;
1743 cooldev
->smbcd_type
= SMB_COOLDEV_TYPE(cd
.smbcdev_typstat
);
1744 cooldev
->smbcd_status
= SMB_COOLDEV_STATUS(cd
.smbcdev_typstat
);
1745 cooldev
->smbcd_group
= cd
.smbcdev_group
;
1746 cooldev
->smbcd_oem
= cd
.smbcdev_oem
;
1748 if (stp
->smbst_hdr
->smbh_len
>= SMB_COOLDEV_NOMINAL_MINLEN
) {
1749 cooldev
->smbcd_nominal
= cd
.smbcdev_nominal
;
1751 cooldev
->smbcd_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1755 * The description field was added in SMBIOS version 2.7. The
1756 * SMB_TYPE_COOLDEV support was only added after all of the 2.7+ fields
1757 * were added in the spec. So while a user may request an older version,
1758 * we don't have to worry about old structures and just simply skip it
1759 * if they're not asking for it.
1761 if (smb_libgteq(shp
, SMB_VERSION_27
) &&
1762 smb_gteq(shp
, SMB_VERSION_27
) &&
1763 stp
->smbst_hdr
->smbh_len
>= SMB_COOLDEV_DESCR_MINLEN
) {
1764 cooldev
->smbcd_descr
= smb_strptr(stp
, cd
.smbcdev_descr
);
1766 cooldev
->smbcd_descr
= NULL
;
1773 smbios_info_tprobe(smbios_hdl_t
*shp
, id_t id
, smbios_tprobe_t
*tprobe
)
1775 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1779 return (-1); /* errno is set for us */
1781 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_TPROBE
)
1782 return (smb_set_errno(shp
, ESMB_TYPE
));
1784 if (stp
->smbst_hdr
->smbh_len
< SMB_TPROBE_MINLEN
)
1785 return (smb_set_errno(shp
, ESMB_SHORT
));
1787 bzero(tprobe
, sizeof (*tprobe
));
1788 smb_info_bcopy(stp
->smbst_hdr
, &tp
, sizeof (tp
));
1789 tprobe
->smbtp_description
= smb_strptr(stp
, tp
.smbtpr_descr
);
1790 tprobe
->smbtp_location
= SMB_TPROBE_LOCATION(tp
.smbtpr_locstat
);
1791 tprobe
->smbtp_status
= SMB_TPROBE_STATUS(tp
.smbtpr_locstat
);
1792 tprobe
->smbtp_maxval
= tp
.smbtpr_maxval
;
1793 tprobe
->smbtp_minval
= tp
.smbtpr_minval
;
1794 tprobe
->smbtp_resolution
= tp
.smbtpr_resolution
;
1795 tprobe
->smbtp_tolerance
= tp
.smbtpr_tolerance
;
1796 tprobe
->smbtp_accuracy
= tp
.smbtpr_accuracy
;
1798 if (stp
->smbst_hdr
->smbh_len
>= SMB_TPROBE_NOMINAL_MINLEN
) {
1799 tprobe
->smbtp_nominal
= tp
.smbtpr_nominal
;
1801 tprobe
->smbtp_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1808 smbios_info_iprobe(smbios_hdl_t
*shp
, id_t id
, smbios_iprobe_t
*iprobe
)
1810 const smb_struct_t
*sip
= smb_lookup_id(shp
, id
);
1814 return (-1); /* errno is set for us */
1816 if (sip
->smbst_hdr
->smbh_type
!= SMB_TYPE_IPROBE
)
1817 return (smb_set_errno(shp
, ESMB_TYPE
));
1819 if (sip
->smbst_hdr
->smbh_len
< SMB_IPROBE_MINLEN
)
1820 return (smb_set_errno(shp
, ESMB_SHORT
));
1822 bzero(iprobe
, sizeof (*iprobe
));
1823 smb_info_bcopy(sip
->smbst_hdr
, &ip
, sizeof (ip
));
1824 iprobe
->smbip_description
= smb_strptr(sip
, ip
.smbipr_descr
);
1825 iprobe
->smbip_location
= SMB_IPROBE_LOCATION(ip
.smbipr_locstat
);
1826 iprobe
->smbip_status
= SMB_IPROBE_STATUS(ip
.smbipr_locstat
);
1827 iprobe
->smbip_maxval
= ip
.smbipr_maxval
;
1828 iprobe
->smbip_minval
= ip
.smbipr_minval
;
1829 iprobe
->smbip_resolution
= ip
.smbipr_resolution
;
1830 iprobe
->smbip_tolerance
= ip
.smbipr_tolerance
;
1831 iprobe
->smbip_accuracy
= ip
.smbipr_accuracy
;
1833 if (sip
->smbst_hdr
->smbh_len
>= SMB_IPROBE_NOMINAL_MINLEN
) {
1834 iprobe
->smbip_nominal
= ip
.smbipr_nominal
;
1836 iprobe
->smbip_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1843 smbios_info_processor_info(smbios_hdl_t
*shp
, id_t id
,
1844 smbios_processor_info_t
*proc
)
1846 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1847 smb_processor_info_t pi
;
1850 return (-1); /* errno is set for us */
1852 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_PROCESSOR_INFO
)
1853 return (smb_set_errno(shp
, ESMB_TYPE
));
1855 if (stp
->smbst_hdr
->smbh_len
< sizeof (pi
))
1856 return (smb_set_errno(shp
, ESMB_SHORT
));
1858 bzero(proc
, sizeof (*proc
));
1859 smb_info_bcopy(stp
->smbst_hdr
, &pi
, sizeof (pi
));
1861 if (sizeof (pi
) + pi
.smbpai_len
> stp
->smbst_hdr
->smbh_len
)
1862 return (smb_set_errno(shp
, ESMB_CORRUPT
));
1864 proc
->smbpi_processor
= pi
.smbpai_proc
;
1865 proc
->smbpi_ptype
= pi
.smbpai_type
;
1871 smbios_info_processor_riscv(smbios_hdl_t
*shp
, id_t id
,
1872 smbios_processor_info_riscv_t
*riscv
)
1874 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1875 const smb_processor_info_t
*proc
;
1876 const smb_processor_info_riscv_t
*rv
;
1879 return (-1); /* errno is set for us */
1882 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_PROCESSOR_INFO
) {
1883 return (smb_set_errno(shp
, ESMB_TYPE
));
1886 if (stp
->smbst_hdr
->smbh_len
< sizeof (*proc
)) {
1887 return (smb_set_errno(shp
, ESMB_SHORT
));
1890 proc
= (const smb_processor_info_t
*)stp
->smbst_hdr
;
1891 if (sizeof (*proc
) + proc
->smbpai_len
> stp
->smbst_hdr
->smbh_len
) {
1892 return (smb_set_errno(shp
, ESMB_CORRUPT
));
1895 switch (proc
->smbpai_type
) {
1896 case SMB_PROCINFO_T_RV32
:
1897 case SMB_PROCINFO_T_RV64
:
1898 case SMB_PROCINFO_T_RV128
:
1901 return (smb_set_errno(shp
, ESMB_TYPE
));
1904 if (stp
->smbst_hdr
->smbh_len
< sizeof (*proc
) + sizeof (*rv
)) {
1905 return (smb_set_errno(shp
, ESMB_SHORT
));
1907 rv
= (const smb_processor_info_riscv_t
*)&proc
->smbpai_data
[0];
1908 if (rv
->smbpairv_len
!= sizeof (*rv
)) {
1909 return (smb_set_errno(shp
, ESMB_CORRUPT
));
1912 bcopy(rv
->smbpairv_hartid
, riscv
->smbpirv_hartid
,
1913 sizeof (riscv
->smbpirv_hartid
));
1914 bcopy(rv
->smbpairv_vendid
, riscv
->smbpirv_vendid
,
1915 sizeof (riscv
->smbpirv_vendid
));
1916 bcopy(rv
->smbpairv_archid
, riscv
->smbpirv_archid
,
1917 sizeof (riscv
->smbpirv_archid
));
1918 bcopy(rv
->smbpairv_machid
, riscv
->smbpirv_machid
,
1919 sizeof (riscv
->smbpirv_machid
));
1920 bcopy(rv
->smbpairv_metdi
, riscv
->smbpirv_metdi
,
1921 sizeof (riscv
->smbpirv_metdi
));
1922 bcopy(rv
->smbpairv_mitdi
, riscv
->smbpirv_mitdi
,
1923 sizeof (riscv
->smbpirv_mitdi
));
1924 riscv
->smbpirv_isa
= rv
->smbpairv_isa
;
1925 riscv
->smbpirv_privlvl
= rv
->smbpairv_privlvl
;
1926 riscv
->smbpirv_boothart
= rv
->smbpairv_boot
;
1927 riscv
->smbpirv_xlen
= rv
->smbpairv_xlen
;
1928 riscv
->smbpirv_mxlen
= rv
->smbpairv_mxlen
;
1929 riscv
->smbpirv_sxlen
= rv
->smbpairv_sxlen
;
1930 riscv
->smbpirv_uxlen
= rv
->smbpairv_uxlen
;
1936 smbios_info_pointdev(smbios_hdl_t
*shp
, id_t id
, smbios_pointdev_t
*pd
)
1938 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1939 smb_pointdev_t point
;
1942 return (-1); /* errno is set for us */
1945 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_POINTDEV
) {
1946 return (smb_set_errno(shp
, ESMB_TYPE
));
1949 if (stp
->smbst_hdr
->smbh_len
< sizeof (point
)) {
1950 return (smb_set_errno(shp
, ESMB_SHORT
));
1953 bzero(pd
, sizeof (*pd
));
1954 smb_info_bcopy(stp
->smbst_hdr
, &point
, sizeof (point
));
1956 pd
->smbpd_type
= point
.smbpdev_type
;
1957 pd
->smbpd_iface
= point
.smbpdev_iface
;
1958 pd
->smbpd_nbuttons
= point
.smbpdev_nbuttons
;
1964 smbios_info_battery(smbios_hdl_t
*shp
, id_t id
, smbios_battery_t
*bp
)
1966 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1970 return (-1); /* errno is set for us */
1973 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_BATTERY
) {
1974 return (smb_set_errno(shp
, ESMB_TYPE
));
1977 if (stp
->smbst_hdr
->smbh_len
< sizeof (bat
)) {
1978 return (smb_set_errno(shp
, ESMB_SHORT
));
1981 bzero(bp
, sizeof (*bp
));
1982 smb_info_bcopy(stp
->smbst_hdr
, &bat
, sizeof (bat
));
1985 * This may be superseded by the SBDS data.
1987 if (bat
.smbbat_date
!= 0) {
1988 bp
->smbb_date
= smb_strptr(stp
, bat
.smbbat_date
);
1990 bp
->smbb_date
= NULL
;
1994 * This may be superseded by the SBDS data.
1996 if (bat
.smbbat_serial
!= 0) {
1997 bp
->smbb_serial
= smb_strptr(stp
, bat
.smbbat_serial
);
1999 bp
->smbb_serial
= NULL
;
2002 bp
->smbb_chem
= bat
.smbbat_chem
;
2003 bp
->smbb_cap
= bat
.smbbat_cap
;
2004 if (bat
.smbbat_mult
> 0) {
2005 bp
->smbb_cap
*= bat
.smbbat_mult
;
2007 bp
->smbb_volt
= bat
.smbbat_volt
;
2008 bp
->smbb_version
= smb_strptr(stp
, bat
.smbbat_version
);
2009 bp
->smbb_err
= bat
.smbbat_err
;
2010 bp
->smbb_ssn
= bat
.smbbat_ssn
;
2011 bp
->smbb_syear
= 1980 + (bat
.smbbat_sdate
>> 9);
2012 bp
->smbb_smonth
= (bat
.smbbat_sdate
>> 5) & 0xf;
2013 bp
->smbb_sday
= bat
.smbbat_sdate
& 0x1f;
2014 bp
->smbb_schem
= smb_strptr(stp
, bat
.smbbat_schem
);
2015 bp
->smbb_oemdata
= bat
.smbbat_oemdata
;
2021 smbios_info_strprop(smbios_hdl_t
*shp
, id_t id
, smbios_strprop_t
*str
)
2023 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
2027 return (-1); /* errno is set for us */
2030 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_STRPROP
) {
2031 return (smb_set_errno(shp
, ESMB_TYPE
));
2034 if (stp
->smbst_hdr
->smbh_len
< sizeof (prop
)) {
2035 return (smb_set_errno(shp
, ESMB_SHORT
));
2038 if (stp
->smbst_hdr
->smbh_len
> sizeof (prop
)) {
2039 return (smb_set_errno(shp
, ESMB_CORRUPT
));
2042 bzero(str
, sizeof (*str
));
2043 smb_info_bcopy(stp
->smbst_hdr
, &prop
, sizeof (prop
));
2045 str
->smbsp_parent
= prop
.smbstrp_phdl
;
2046 str
->smbsp_prop_id
= prop
.smbstrp_prop_id
;
2047 str
->smbsp_prop_val
= smb_strptr(stp
, prop
.smbstrp_prop_val
);
2053 smbios_info_fwinfo(smbios_hdl_t
*shp
, id_t id
, smbios_fwinfo_t
*fwinfo
)
2055 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
2059 return (-1); /* errno is set for us */
2062 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_FWINFO
) {
2063 return (smb_set_errno(shp
, ESMB_TYPE
));
2066 if (stp
->smbst_hdr
->smbh_len
< sizeof (fw
)) {
2067 return (smb_set_errno(shp
, ESMB_SHORT
));
2071 * The verion and manufacturer are part of smbios_info_common().
2073 bzero(fwinfo
, sizeof (*fwinfo
));
2074 smb_info_bcopy(stp
->smbst_hdr
, &fw
, sizeof (fw
));
2075 fwinfo
->smbfw_name
= smb_strptr(stp
, fw
.smbfwii_name
);
2076 fwinfo
->smbfw_id
= smb_strptr(stp
, fw
.smbfwii_id
);
2077 fwinfo
->smbfw_reldate
= smb_strptr(stp
, fw
.smbfwii_reldate
);
2078 fwinfo
->smbfw_lsv
= smb_strptr(stp
, fw
.smbfwii_lsv
);
2079 fwinfo
->smbfw_imgsz
= fw
.smbfwii_imgsz
;
2080 fwinfo
->smbfw_chars
= fw
.smbfwii_chars
;
2081 fwinfo
->smbfw_state
= fw
.smbfwii_state
;
2082 fwinfo
->smbfw_ncomps
= fw
.smbfwii_ncomps
;
2083 fwinfo
->smbfw_vers_fmt
= fw
.smbfwii_vers_fmt
;
2084 fwinfo
->smbfw_id_fmt
= fw
.smbfwii_id_fmt
;
2090 smbios_info_fwinfo_comps(smbios_hdl_t
*shp
, id_t id
, uint_t
*ncompsp
,
2091 smbios_fwinfo_comp_t
**compsp
)
2093 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
2094 smbios_fwinfo_comp_t
*comps
;
2100 return (-1); /* errno is set for us */
2103 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_FWINFO
) {
2104 return (smb_set_errno(shp
, ESMB_TYPE
));
2107 if (stp
->smbst_hdr
->smbh_len
< sizeof (fw
)) {
2108 return (smb_set_errno(shp
, ESMB_SHORT
));
2111 smb_info_bcopy(stp
->smbst_hdr
, &fw
, sizeof (fw
));
2112 if (fw
.smbfwii_ncomps
== 0) {
2118 need
= fw
.smbfwii_ncomps
* sizeof (uint16_t) + sizeof (smb_fwinfo_t
);
2119 if (stp
->smbst_hdr
->smbh_len
< need
) {
2120 return (smb_set_errno(shp
, ESMB_SHORT
));
2123 comps
= smb_alloc(fw
.smbfwii_ncomps
* sizeof (smbios_fwinfo_comp_t
));
2124 if (comps
== NULL
) {
2125 return (smb_set_errno(shp
, ESMB_NOMEM
));
2128 for (i
= 0; i
< fw
.smbfwii_ncomps
; i
++) {
2130 size_t off
= sizeof (smb_fwinfo_t
) + sizeof (uint16_t) * i
;
2131 smb_info_bcopy_offset(stp
->smbst_hdr
, &id
, sizeof (id
), off
);
2132 comps
[i
].smbfwe_id
= id
;
2135 *ncompsp
= fw
.smbfwii_ncomps
;
2142 smbios_info_fwinfo_comps_free(smbios_hdl_t
*shp
, uint_t ncomps
,
2143 smbios_fwinfo_comp_t
*comps
)
2145 size_t sz
= ncomps
* sizeof (smbios_fwinfo_comp_t
);
2148 ASSERT3P(comps
, ==, NULL
);
2152 smb_free(comps
, sz
);
2156 smbios_info_addinfo_nents(smbios_hdl_t
*shp
, id_t id
, uint_t
*nentsp
)
2158 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
2162 return (-1); /* errno is set for us */
2165 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_ADDINFO
) {
2166 return (smb_set_errno(shp
, ESMB_TYPE
));
2169 if (stp
->smbst_hdr
->smbh_len
< sizeof (add
)) {
2170 return (smb_set_errno(shp
, ESMB_SHORT
));
2173 smb_info_bcopy(stp
->smbst_hdr
, &add
, sizeof (add
));
2174 *nentsp
= add
.smbai_nents
;
2180 smbios_info_addinfo_ent_free(smbios_hdl_t
*hdl
, smbios_addinfo_ent_t
*ent
)
2182 if (ent
->smbai_dlen
> 0) {
2183 ASSERT3P(ent
->smbai_data
, !=, NULL
);
2184 smb_free(ent
->smbai_data
, ent
->smbai_dlen
);
2187 smb_free(ent
, sizeof (smbios_addinfo_ent_t
));
2191 smbios_info_addinfo_ent(smbios_hdl_t
*shp
, id_t id
, uint_t entno
,
2192 smbios_addinfo_ent_t
**entp
)
2194 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
2197 smb_addinfo_ent_t ent
;
2198 smbios_addinfo_ent_t
*entry
;
2202 return (-1); /* errno is set for us */
2205 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_ADDINFO
) {
2206 return (smb_set_errno(shp
, ESMB_TYPE
));
2209 if (stp
->smbst_hdr
->smbh_len
< sizeof (add
)) {
2210 return (smb_set_errno(shp
, ESMB_SHORT
));
2213 smb_info_bcopy(stp
->smbst_hdr
, &add
, sizeof (add
));
2214 if (entno
>= add
.smbai_nents
) {
2215 return (smb_set_errno(shp
, ESMB_REQVAL
));
2219 for (i
= 0; i
<= entno
; i
++) {
2220 if (off
+ sizeof (ent
) > stp
->smbst_hdr
->smbh_len
) {
2221 return (smb_set_errno(shp
, ESMB_SHORT
));
2224 smb_info_bcopy_offset(stp
->smbst_hdr
, &ent
, sizeof (ent
), off
);
2225 if (ent
.smbaie_len
< sizeof (ent
)) {
2226 return (smb_set_errno(shp
, ESMB_SHORT
));
2229 if (ent
.smbaie_len
+ off
> stp
->smbst_hdr
->smbh_len
) {
2230 return (smb_set_errno(shp
, ESMB_CORRUPT
));
2234 off
+= ent
.smbaie_len
;
2238 entry
= smb_alloc(sizeof (smbios_addinfo_ent_t
));
2239 if (entry
== NULL
) {
2240 return (smb_set_errno(shp
, ESMB_NOMEM
));
2243 entry
->smbai_ref
= ent
.smbaie_rhdl
;
2244 entry
->smbai_ref_off
= ent
.smbaie_off
;
2245 if (ent
.smbaie_str
!= 0) {
2246 entry
->smbai_str
= smb_strptr(stp
, ent
.smbaie_str
);
2248 entry
->smbai_str
= NULL
;
2250 entry
->smbai_dlen
= ent
.smbaie_len
- sizeof (ent
);
2251 if (entry
->smbai_dlen
> 0) {
2252 entry
->smbai_data
= smb_alloc(entry
->smbai_dlen
);
2253 if (entry
->smbai_data
== NULL
) {
2254 smb_free(entry
, sizeof (smbios_addinfo_ent_t
));
2255 return (smb_set_errno(shp
, ESMB_NOMEM
));
2257 smb_info_bcopy_offset(stp
->smbst_hdr
, entry
->smbai_data
,
2258 entry
->smbai_dlen
, off
+ offsetof(smb_addinfo_ent_t
,
2261 entry
->smbai_data
= NULL
;