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 (c) 2017, Joyent, Inc.
25 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
30 * SMBIOS Information Routines
32 * The routines in this file are used to convert from the SMBIOS data format to
33 * a more reasonable and stable set of structures offered as part of our ABI.
34 * These functions take the general form:
36 * stp = smb_lookup_type(shp, foo);
39 * smb_info_bcopy(stp->smbst_hdr, &foo, sizeof (foo));
40 * bzero(caller's struct);
42 * copy/convert foo members into caller's struct
44 * We copy the internal structure on to an automatic variable so as to avoid
45 * checks everywhere for structures that the BIOS has improperly truncated, and
46 * also to automatically handle the case of a structure that has been extended.
47 * When necessary, this code can use smb_gteq() to determine whether the SMBIOS
48 * data is of a particular revision that is supposed to contain a new field.
50 * Note, when trying to bzero the caller's struct you have to be careful about
51 * versions. One can only bzero the initial version that existed in illumos. In
52 * other words, if someone passes an older library handle that doesn't support a
53 * version you cannot assume that their structures have those additional members
54 * in them. Instead, a 'base' version is introduced for such types that have
55 * differences and instead we only bzero out the base version and then handle
56 * the additional members. In general, because all additional members will be
57 * assigned, there's no reason to zero them out unless they are arrays that
58 * won't be entirely filled in.
60 * Due to history, anything added after the update from version 2.4, in other
61 * words additions from or after '5094 Update libsmbios with recent items'
62 * (4e901881) is currently being used for this. While we don't allow software
63 * compiling against this to get an older form, this was the first major update
64 * and a good starting point for us to enforce this behavior which is useful for
65 * moving forward to making this more public.
68 #include <sys/smbios_impl.h>
69 #include <sys/byteorder.h>
72 #include <sys/sunddi.h>
80 * A large number of SMBIOS structures contain a set of common strings used to
81 * describe a h/w component's serial number, manufacturer, etc. These fields
82 * helpfully have different names and offsets and sometimes aren't consistent.
83 * To simplify life for our clients, we factor these common things out into
84 * smbios_info_t, which can be retrieved for any structure. The following
85 * table describes the mapping from a given structure to the smbios_info_t.
86 * Multiple SMBIOS stuctures' contained objects are also handled here.
88 static const struct smb_infospec
{
89 uint8_t is_type
; /* structure type */
90 uint8_t is_manu
; /* manufacturer offset */
91 uint8_t is_product
; /* product name offset */
92 uint8_t is_version
; /* version offset */
93 uint8_t is_serial
; /* serial number offset */
94 uint8_t is_asset
; /* asset tag offset */
95 uint8_t is_location
; /* location string offset */
96 uint8_t is_part
; /* part number offset */
97 uint8_t is_contc
; /* contained count */
98 uint8_t is_contsz
; /* contained size */
99 uint8_t is_contv
; /* contained objects */
100 } _smb_infospecs
[] = {
102 offsetof(smb_system_t
, smbsi_manufacturer
),
103 offsetof(smb_system_t
, smbsi_product
),
104 offsetof(smb_system_t
, smbsi_version
),
105 offsetof(smb_system_t
, smbsi_serial
),
112 { SMB_TYPE_BASEBOARD
,
113 offsetof(smb_bboard_t
, smbbb_manufacturer
),
114 offsetof(smb_bboard_t
, smbbb_product
),
115 offsetof(smb_bboard_t
, smbbb_version
),
116 offsetof(smb_bboard_t
, smbbb_serial
),
117 offsetof(smb_bboard_t
, smbbb_asset
),
118 offsetof(smb_bboard_t
, smbbb_location
),
120 offsetof(smb_bboard_t
, smbbb_cn
),
122 offsetof(smb_bboard_t
, smbbb_cv
) },
124 offsetof(smb_chassis_t
, smbch_manufacturer
),
126 offsetof(smb_chassis_t
, smbch_version
),
127 offsetof(smb_chassis_t
, smbch_serial
),
128 offsetof(smb_chassis_t
, smbch_asset
),
131 offsetof(smb_chassis_t
, smbch_cn
),
133 offsetof(smb_chassis_t
, smbch_cv
) },
134 { SMB_TYPE_PROCESSOR
,
135 offsetof(smb_processor_t
, smbpr_manufacturer
),
137 offsetof(smb_processor_t
, smbpr_version
),
138 offsetof(smb_processor_t
, smbpr_serial
),
139 offsetof(smb_processor_t
, smbpr_asset
),
140 offsetof(smb_processor_t
, smbpr_socket
),
141 offsetof(smb_processor_t
, smbpr_part
),
151 offsetof(smb_cache_t
, smbca_socket
),
162 offsetof(smb_port_t
, smbpo_iref
),
173 offsetof(smb_slot_t
, smbsl_name
),
178 { SMB_TYPE_MEMDEVICE
,
179 offsetof(smb_memdevice_t
, smbmdev_manufacturer
),
182 offsetof(smb_memdevice_t
, smbmdev_serial
),
183 offsetof(smb_memdevice_t
, smbmdev_asset
),
184 offsetof(smb_memdevice_t
, smbmdev_dloc
),
185 offsetof(smb_memdevice_t
, smbmdev_part
),
190 offsetof(smb_powersup_t
, smbpsup_manufacturer
),
191 offsetof(smb_powersup_t
, smbpsup_devname
),
192 offsetof(smb_powersup_t
, smbpsup_rev
),
193 offsetof(smb_powersup_t
, smbpsup_serial
),
194 offsetof(smb_powersup_t
, smbpsup_asset
),
195 offsetof(smb_powersup_t
, smbpsup_loc
),
196 offsetof(smb_powersup_t
, smbpsup_part
),
204 smb_info_strptr(const smb_struct_t
*stp
, uint8_t off
, int *n
)
206 const uint8_t *sp
= (const uint8_t *)(uintptr_t)stp
->smbst_hdr
;
208 if (off
!= 0 && sp
+ off
< stp
->smbst_end
) {
209 (*n
)++; /* indicate success for caller */
210 return (smb_strptr(stp
, sp
[off
]));
213 return (smb_strptr(stp
, 0));
217 smb_info_bcopy(const smb_header_t
*hp
, void *dst
, size_t dstlen
)
219 if (dstlen
> hp
->smbh_len
) {
220 bcopy(hp
, dst
, hp
->smbh_len
);
221 bzero((char *)dst
+ hp
->smbh_len
, dstlen
- hp
->smbh_len
);
223 bcopy(hp
, dst
, dstlen
);
227 smbios_info_smbios(smbios_hdl_t
*shp
, smbios_entry_t
*ep
)
229 bcopy(&shp
->sh_ent
, ep
, sizeof (smbios_entry_t
));
230 return (shp
->sh_ent_type
);
234 smbios_info_smbios_version(smbios_hdl_t
*shp
, smbios_version_t
*v
)
236 v
->smbv_major
= SMB_MAJOR(shp
->sh_smbvers
);
237 v
->smbv_minor
= SMB_MINOR(shp
->sh_smbvers
);
241 static char smbios_product_override
[256];
242 static boolean_t smbios_product_checked
;
246 smbios_info_common(smbios_hdl_t
*shp
, id_t id
, smbios_info_t
*ip
)
248 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
249 const struct smb_infospec
*isp
;
253 return (-1); /* errno is set for us */
255 for (isp
= _smb_infospecs
; isp
->is_type
!= SMB_TYPE_EOT
; isp
++) {
256 if (isp
->is_type
== stp
->smbst_hdr
->smbh_type
)
260 ip
->smbi_manufacturer
= smb_info_strptr(stp
, isp
->is_manu
, &n
);
261 ip
->smbi_product
= smb_info_strptr(stp
, isp
->is_product
, &n
);
262 ip
->smbi_version
= smb_info_strptr(stp
, isp
->is_version
, &n
);
263 ip
->smbi_serial
= smb_info_strptr(stp
, isp
->is_serial
, &n
);
264 ip
->smbi_asset
= smb_info_strptr(stp
, isp
->is_asset
, &n
);
265 ip
->smbi_location
= smb_info_strptr(stp
, isp
->is_location
, &n
);
266 ip
->smbi_part
= smb_info_strptr(stp
, isp
->is_part
, &n
);
269 * This private file allows developers to experiment with reporting
270 * different platform strings from SMBIOS. It is not a supported
271 * mechanism in the long term, and does not work in the kernel.
274 if (isp
->is_type
== SMB_TYPE_SYSTEM
) {
275 if (!smbios_product_checked
) {
276 int fd
= open("/etc/smbios_product", O_RDONLY
);
278 (void) read(fd
, smbios_product_override
,
279 sizeof (smbios_product_override
) - 1);
282 smbios_product_checked
= B_TRUE
;
285 if (smbios_product_override
[0] != '\0')
286 ip
->smbi_product
= smbios_product_override
;
291 * If we have a port with an empty internal reference designator string
292 * try using the external reference designator string instead.
294 if (isp
->is_type
== SMB_TYPE_PORT
&& ip
->smbi_location
[0] == '\0') {
295 ip
->smbi_location
= smb_info_strptr(stp
,
296 offsetof(smb_port_t
, smbpo_eref
), &n
);
299 return (n
? 0 : smb_set_errno(shp
, ESMB_NOINFO
));
303 * Returns the actual number of contained objects.
305 * idc - number of contained objects
306 * idv - returned array of contained objects
309 smbios_info_contains(smbios_hdl_t
*shp
, id_t id
, uint_t idc
, id_t
*idv
)
311 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
312 const struct smb_infospec
*isp
;
319 return (-1); /* errno is set for us */
322 for (isp
= _smb_infospecs
; isp
->is_type
!= SMB_TYPE_EOT
; isp
++) {
323 if (isp
->is_type
== stp
->smbst_hdr
->smbh_type
)
326 if (isp
->is_type
== SMB_TYPE_EOT
)
327 return (smb_set_errno(shp
, ESMB_TYPE
));
329 size
= isp
->is_contsz
;
330 cnt
= *((uint8_t *)(uintptr_t)stp
->smbst_hdr
+ isp
->is_contc
);
331 cp
= (id_t
*)((uintptr_t)stp
->smbst_hdr
+ isp
->is_contv
);
334 for (i
= 0; i
< n
; i
++) {
335 if (size
== SMB_CONT_WORD
)
336 idv
[i
] = *((uint8_t *)(uintptr_t)cp
+ (i
* 2));
337 else if (size
== SMB_CONT_BYTE
)
338 idv
[i
] = *((uint8_t *)(uintptr_t)cp
+ (i
* 3));
340 return (smb_set_errno(shp
, ESMB_INVAL
));
347 smbios_info_bios(smbios_hdl_t
*shp
, smbios_bios_t
*bp
)
349 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_BIOS
);
350 const smb_bios_t
*bip
;
353 return (-1); /* errno is set for us */
355 if (stp
->smbst_hdr
->smbh_len
< sizeof (smb_bios_t
) - sizeof (uint8_t))
356 return (smb_set_errno(shp
, ESMB_CORRUPT
));
358 bip
= (smb_bios_t
*)(uintptr_t)stp
->smbst_hdr
;
359 bzero(bp
, sizeof (smb_base_bios_t
));
360 if (smb_libgteq(shp
, SMB_VERSION_31
)) {
361 bp
->smbb_extromsize
= 0;
364 bp
->smbb_vendor
= smb_strptr(stp
, bip
->smbbi_vendor
);
365 bp
->smbb_version
= smb_strptr(stp
, bip
->smbbi_version
);
366 bp
->smbb_segment
= bip
->smbbi_segment
;
367 bp
->smbb_reldate
= smb_strptr(stp
, bip
->smbbi_reldate
);
368 bp
->smbb_romsize
= 64 * 1024 * ((uint32_t)bip
->smbbi_romsize
+ 1);
369 bp
->smbb_runsize
= 16 * (0x10000 - (uint32_t)bip
->smbbi_segment
);
370 bp
->smbb_cflags
= bip
->smbbi_cflags
;
373 * If one or more extension bytes are present, reset smbb_xcflags to
374 * point to them. Otherwise leave this member set to NULL.
376 if (stp
->smbst_hdr
->smbh_len
>= sizeof (smb_bios_t
)) {
377 bp
->smbb_xcflags
= bip
->smbbi_xcflags
;
378 bp
->smbb_nxcflags
= stp
->smbst_hdr
->smbh_len
-
379 sizeof (smb_bios_t
) + 1;
381 if (bp
->smbb_nxcflags
> SMB_BIOSXB_ECFW_MIN
&&
382 smb_gteq(shp
, SMB_VERSION_24
)) {
383 bp
->smbb_biosv
.smbv_major
=
384 bip
->smbbi_xcflags
[SMB_BIOSXB_BIOS_MAJ
];
385 bp
->smbb_biosv
.smbv_minor
=
386 bip
->smbbi_xcflags
[SMB_BIOSXB_BIOS_MIN
];
387 bp
->smbb_ecfwv
.smbv_major
=
388 bip
->smbbi_xcflags
[SMB_BIOSXB_ECFW_MAJ
];
389 bp
->smbb_ecfwv
.smbv_minor
=
390 bip
->smbbi_xcflags
[SMB_BIOSXB_ECFW_MIN
];
393 if (bp
->smbb_nxcflags
> SMB_BIOSXB_EXTROM
+ 1 &&
394 smb_gteq(shp
, SMB_VERSION_31
)) {
399 * Because of the fact that the extended size is a
400 * uint16_t and we'd need to define an explicit
401 * endian-aware way to access it, we don't include it in
402 * the number of extended flags below and thus subtract
405 bp
->smbb_nxcflags
-= sizeof (uint16_t);
406 bcopy(&bip
->smbbi_xcflags
[SMB_BIOSXB_EXTROM
], &val
,
411 * The upper two bits of the extended rom size are used
412 * to indicate whether the other 14 bits are in MB or
415 rs
= SMB_BIOS_EXTROM_VALUE_MASK(val
);
416 switch (SMB_BIOS_EXTROM_SHIFT_MASK(val
)) {
418 rs
*= 1024ULL * 1024ULL;
421 rs
*= 1024ULL * 1024ULL * 1024ULL;
428 if (smb_libgteq(shp
, SMB_VERSION_31
)) {
429 bp
->smbb_extromsize
= rs
;
434 if (smb_libgteq(shp
, SMB_VERSION_31
) && bp
->smbb_extromsize
== 0) {
435 bp
->smbb_extromsize
= bp
->smbb_romsize
;
438 return (stp
->smbst_hdr
->smbh_hdl
);
442 smbios_info_system(smbios_hdl_t
*shp
, smbios_system_t
*sip
)
444 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_SYSTEM
);
448 return (-1); /* errno is set for us */
450 smb_info_bcopy(stp
->smbst_hdr
, &si
, sizeof (si
));
451 bzero(sip
, sizeof (smbios_system_t
));
453 sip
->smbs_uuid
= ((smb_system_t
*)stp
->smbst_hdr
)->smbsi_uuid
;
454 sip
->smbs_uuidlen
= sizeof (si
.smbsi_uuid
);
455 sip
->smbs_wakeup
= si
.smbsi_wakeup
;
456 sip
->smbs_sku
= smb_strptr(stp
, si
.smbsi_sku
);
457 sip
->smbs_family
= smb_strptr(stp
, si
.smbsi_family
);
459 return (stp
->smbst_hdr
->smbh_hdl
);
463 smbios_info_bboard(smbios_hdl_t
*shp
, id_t id
, smbios_bboard_t
*bbp
)
465 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
469 return (-1); /* errno is set for us */
471 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_BASEBOARD
)
472 return (smb_set_errno(shp
, ESMB_TYPE
));
474 smb_info_bcopy(stp
->smbst_hdr
, &bb
, sizeof (bb
));
475 bzero(bbp
, sizeof (smbios_bboard_t
));
477 bbp
->smbb_chassis
= bb
.smbbb_chassis
;
478 bbp
->smbb_flags
= bb
.smbbb_flags
;
479 bbp
->smbb_type
= bb
.smbbb_type
;
480 bbp
->smbb_contn
= bb
.smbbb_cn
;
486 smbios_info_chassis(smbios_hdl_t
*shp
, id_t id
, smbios_chassis_t
*chp
)
488 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
489 /* Length is measurable by one byte, so it'll be no more than 255. */
491 smb_chassis_t
*ch
= (smb_chassis_t
*)&buf
[0];
494 return (-1); /* errno is set for us */
496 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_CHASSIS
)
497 return (smb_set_errno(shp
, ESMB_TYPE
));
499 smb_info_bcopy(stp
->smbst_hdr
, ch
, sizeof (buf
));
500 bzero(chp
, sizeof (smb_base_chassis_t
));
501 if (smb_libgteq(shp
, SMB_VERSION_27
)) {
502 bzero(chp
->smbc_sku
, sizeof (chp
->smbc_sku
));
505 chp
->smbc_oemdata
= ch
->smbch_oemdata
;
506 chp
->smbc_lock
= (ch
->smbch_type
& SMB_CHT_LOCK
) != 0;
507 chp
->smbc_type
= ch
->smbch_type
& ~SMB_CHT_LOCK
;
508 chp
->smbc_bustate
= ch
->smbch_bustate
;
509 chp
->smbc_psstate
= ch
->smbch_psstate
;
510 chp
->smbc_thstate
= ch
->smbch_thstate
;
511 chp
->smbc_security
= ch
->smbch_security
;
512 chp
->smbc_uheight
= ch
->smbch_uheight
;
513 chp
->smbc_cords
= ch
->smbch_cords
;
514 chp
->smbc_elems
= ch
->smbch_cn
;
515 chp
->smbc_elemlen
= ch
->smbch_cm
;
517 if (smb_libgteq(shp
, SMB_VERSION_27
)) {
518 (void) strlcpy(chp
->smbc_sku
, SMB_CH_SKU(ch
),
519 sizeof (chp
->smbc_sku
));
526 smbios_info_processor(smbios_hdl_t
*shp
, id_t id
, smbios_processor_t
*pp
)
528 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
532 return (-1); /* errno is set for us */
534 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_PROCESSOR
)
535 return (smb_set_errno(shp
, ESMB_TYPE
));
537 smb_info_bcopy(stp
->smbst_hdr
, &p
, sizeof (p
));
538 bzero(pp
, sizeof (smb_base_processor_t
));
540 pp
->smbp_cpuid
= p
.smbpr_cpuid
;
541 pp
->smbp_type
= p
.smbpr_type
;
542 pp
->smbp_family
= p
.smbpr_family
;
543 pp
->smbp_voltage
= p
.smbpr_voltage
;
544 pp
->smbp_maxspeed
= p
.smbpr_maxspeed
;
545 pp
->smbp_curspeed
= p
.smbpr_curspeed
;
546 pp
->smbp_status
= p
.smbpr_status
;
547 pp
->smbp_upgrade
= p
.smbpr_upgrade
;
548 pp
->smbp_l1cache
= p
.smbpr_l1cache
;
549 pp
->smbp_l2cache
= p
.smbpr_l2cache
;
550 pp
->smbp_l3cache
= p
.smbpr_l3cache
;
552 if (smb_libgteq(shp
, SMB_VERSION_25
)) {
553 pp
->smbp_corecount
= p
.smbpr_corecount
;
554 pp
->smbp_coresenabled
= p
.smbpr_coresenabled
;
555 pp
->smbp_threadcount
= p
.smbpr_threadcount
;
556 pp
->smbp_cflags
= p
.smbpr_cflags
;
559 if (smb_libgteq(shp
, SMB_VERSION_26
)) {
560 pp
->smbp_family2
= p
.smbpr_family2
;
563 if (smb_libgteq(shp
, SMB_VERSION_30
)) {
564 pp
->smbp_corecount2
= p
.smbpr_corecount2
;
565 pp
->smbp_coresenabled2
= p
.smbpr_coresenabled2
;
566 pp
->smbp_threadcount2
= p
.smbpr_threadcount2
;
573 smbios_info_cache(smbios_hdl_t
*shp
, id_t id
, smbios_cache_t
*cap
)
575 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
579 return (-1); /* errno is set for us */
581 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_CACHE
)
582 return (smb_set_errno(shp
, ESMB_TYPE
));
584 smb_info_bcopy(stp
->smbst_hdr
, &c
, sizeof (c
));
585 bzero(cap
, sizeof (smb_base_cache_t
));
587 cap
->smba_maxsize
= SMB_CACHE_SIZE(c
.smbca_maxsize
);
588 cap
->smba_size
= SMB_CACHE_SIZE(c
.smbca_size
);
589 cap
->smba_stype
= c
.smbca_stype
;
590 cap
->smba_ctype
= c
.smbca_ctype
;
591 cap
->smba_speed
= c
.smbca_speed
;
592 cap
->smba_etype
= c
.smbca_etype
;
593 cap
->smba_ltype
= c
.smbca_ltype
;
594 cap
->smba_assoc
= c
.smbca_assoc
;
595 cap
->smba_level
= SMB_CACHE_CFG_LEVEL(c
.smbca_config
);
596 cap
->smba_mode
= SMB_CACHE_CFG_MODE(c
.smbca_config
);
597 cap
->smba_location
= SMB_CACHE_CFG_LOCATION(c
.smbca_config
);
599 if (SMB_CACHE_CFG_ENABLED(c
.smbca_config
))
600 cap
->smba_flags
|= SMB_CAF_ENABLED
;
602 if (SMB_CACHE_CFG_SOCKETED(c
.smbca_config
))
603 cap
->smba_flags
|= SMB_CAF_SOCKETED
;
605 if (smb_libgteq(shp
, SMB_VERSION_31
)) {
606 if (smb_gteq(shp
, SMB_VERSION_31
)) {
608 SMB_CACHE_EXT_SIZE(c
.smbca_maxsize2
);
609 cap
->smba_size2
= SMB_CACHE_EXT_SIZE(c
.smbca_size2
);
611 cap
->smba_maxsize2
= cap
->smba_maxsize
;
612 cap
->smba_size2
= cap
->smba_size
;
620 smbios_info_port(smbios_hdl_t
*shp
, id_t id
, smbios_port_t
*pop
)
622 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
626 return (-1); /* errno is set for us */
628 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_PORT
)
629 return (smb_set_errno(shp
, ESMB_TYPE
));
631 smb_info_bcopy(stp
->smbst_hdr
, &p
, sizeof (p
));
632 bzero(pop
, sizeof (smbios_port_t
));
634 pop
->smbo_iref
= smb_strptr(stp
, p
.smbpo_iref
);
635 pop
->smbo_eref
= smb_strptr(stp
, p
.smbpo_eref
);
637 pop
->smbo_itype
= p
.smbpo_itype
;
638 pop
->smbo_etype
= p
.smbpo_etype
;
639 pop
->smbo_ptype
= p
.smbpo_ptype
;
645 smbios_info_slot(smbios_hdl_t
*shp
, id_t id
, smbios_slot_t
*sp
)
647 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
651 return (-1); /* errno is set for us */
653 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_SLOT
)
654 return (smb_set_errno(shp
, ESMB_TYPE
));
656 smb_info_bcopy(stp
->smbst_hdr
, &s
, sizeof (s
));
657 bzero(sp
, sizeof (smbios_slot_t
));
659 sp
->smbl_name
= smb_strptr(stp
, s
.smbsl_name
);
660 sp
->smbl_type
= s
.smbsl_type
;
661 sp
->smbl_width
= s
.smbsl_width
;
662 sp
->smbl_usage
= s
.smbsl_usage
;
663 sp
->smbl_length
= s
.smbsl_length
;
664 sp
->smbl_id
= s
.smbsl_id
;
665 sp
->smbl_ch1
= s
.smbsl_ch1
;
666 sp
->smbl_ch2
= s
.smbsl_ch2
;
667 sp
->smbl_sg
= s
.smbsl_sg
;
668 sp
->smbl_bus
= s
.smbsl_bus
;
669 sp
->smbl_df
= s
.smbsl_df
;
675 smbios_info_obdevs_ext(smbios_hdl_t
*shp
, id_t id
, smbios_obdev_ext_t
*oep
)
677 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
681 return (-1); /* errno is set for us */
683 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OBDEVEXT
)
684 return (smb_set_errno(shp
, ESMB_TYPE
));
686 smb_info_bcopy(stp
->smbst_hdr
, &obe
, sizeof (obe
));
687 bzero(oep
, sizeof (smbios_obdev_ext_t
));
689 oep
->smboe_name
= smb_strptr(stp
, obe
.smbobe_name
);
690 oep
->smboe_dtype
= obe
.smbobe_dtype
;
691 oep
->smboe_dti
= obe
.smbobe_dti
;
692 oep
->smboe_sg
= obe
.smbobe_sg
;
693 oep
->smboe_bus
= obe
.smbobe_bus
;
694 oep
->smboe_df
= obe
.smbobe_df
;
700 smbios_info_obdevs(smbios_hdl_t
*shp
, id_t id
, int obc
, smbios_obdev_t
*obp
)
702 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
703 const smb_obdev_t
*op
;
707 return (-1); /* errno is set for us */
709 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OBDEVS
)
710 return (smb_set_errno(shp
, ESMB_TYPE
));
712 op
= (smb_obdev_t
*)((uintptr_t)stp
->smbst_hdr
+ sizeof (smb_header_t
));
713 m
= (stp
->smbst_hdr
->smbh_len
- sizeof (smb_header_t
)) / sizeof (*op
);
716 for (i
= 0; i
< n
; i
++, op
++, obp
++) {
717 obp
->smbd_name
= smb_strptr(stp
, op
->smbob_name
);
718 obp
->smbd_type
= op
->smbob_type
& ~SMB_OBT_ENABLED
;
719 obp
->smbd_enabled
= (op
->smbob_type
& SMB_OBT_ENABLED
) != 0;
726 * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the
727 * first byte to indicate the size of a string table at the end of the record.
728 * Therefore, smbios_info_strtab() can be used to retrieve the table size and
729 * strings for any of these underlying record types.
732 smbios_info_strtab(smbios_hdl_t
*shp
, id_t id
, int argc
, const char *argv
[])
734 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
739 return (-1); /* errno is set for us */
741 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OEMSTR
&&
742 stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_SYSCONFSTR
&&
743 stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_LANG
)
744 return (smb_set_errno(shp
, ESMB_TYPE
));
746 smb_info_bcopy(stp
->smbst_hdr
, &s
, sizeof (s
));
747 n
= MIN(s
.smbtb_count
, argc
);
749 for (i
= 0; i
< n
; i
++)
750 argv
[i
] = smb_strptr(stp
, i
+ 1);
752 return (s
.smbtb_count
);
756 smbios_info_lang(smbios_hdl_t
*shp
, smbios_lang_t
*lp
)
758 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_LANG
);
762 return (-1); /* errno is set for us */
764 smb_info_bcopy(stp
->smbst_hdr
, &l
, sizeof (l
));
765 bzero(lp
, sizeof (smbios_lang_t
));
767 lp
->smbla_cur
= smb_strptr(stp
, l
.smblang_cur
);
768 lp
->smbla_fmt
= l
.smblang_flags
& 1;
769 lp
->smbla_num
= l
.smblang_num
;
771 return (stp
->smbst_hdr
->smbh_hdl
);
775 smbios_info_eventlog(smbios_hdl_t
*shp
, smbios_evlog_t
*evp
)
777 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_EVENTLOG
);
778 const smb_sel_t
*sel
;
782 return (-1); /* errno is set for us */
784 if (stp
->smbst_hdr
->smbh_len
< sizeof (smb_sel_t
) - sizeof (uint8_t))
785 return (smb_set_errno(shp
, ESMB_CORRUPT
));
787 sel
= (smb_sel_t
*)(uintptr_t)stp
->smbst_hdr
;
788 len
= stp
->smbst_hdr
->smbh_len
- sizeof (smb_sel_t
) + sizeof (uint8_t);
789 bzero(evp
, sizeof (smbios_evlog_t
));
791 if (len
< sel
->smbsel_typec
* sel
->smbsel_typesz
)
792 return (smb_set_errno(shp
, ESMB_CORRUPT
));
794 evp
->smbev_size
= sel
->smbsel_len
;
795 evp
->smbev_hdr
= sel
->smbsel_hdroff
;
796 evp
->smbev_data
= sel
->smbsel_dataoff
;
797 evp
->smbev_method
= sel
->smbsel_method
;
798 evp
->smbev_flags
= sel
->smbsel_status
;
799 evp
->smbev_format
= sel
->smbsel_format
;
800 evp
->smbev_token
= sel
->smbsel_token
;
801 evp
->smbev_addr
.eva_addr
= sel
->smbsel_addr
;
803 if (sel
->smbsel_typesz
== sizeof (smbios_evtype_t
)) {
804 evp
->smbev_typec
= sel
->smbsel_typec
;
805 evp
->smbev_typev
= (void *)(uintptr_t)sel
->smbsel_typev
;
808 return (stp
->smbst_hdr
->smbh_hdl
);
812 smbios_info_memarray(smbios_hdl_t
*shp
, id_t id
, smbios_memarray_t
*map
)
814 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
818 return (-1); /* errno is set for us */
820 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMARRAY
)
821 return (smb_set_errno(shp
, ESMB_TYPE
));
823 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
824 bzero(map
, sizeof (smbios_memarray_t
));
826 map
->smbma_location
= m
.smbmarr_loc
;
827 map
->smbma_use
= m
.smbmarr_use
;
828 map
->smbma_ecc
= m
.smbmarr_ecc
;
829 map
->smbma_ndevs
= m
.smbmarr_ndevs
;
830 map
->smbma_err
= m
.smbmarr_err
;
832 if (m
.smbmarr_cap
!= 0x80000000)
833 map
->smbma_size
= (uint64_t)m
.smbmarr_cap
* 1024;
834 else if (m
.smbmarr_extcap
!= 0)
835 map
->smbma_size
= m
.smbmarr_extcap
;
837 map
->smbma_size
= 0; /* unknown */
843 smbios_info_memarrmap(smbios_hdl_t
*shp
, id_t id
, smbios_memarrmap_t
*map
)
845 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
849 return (-1); /* errno is set for us */
851 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMARRAYMAP
)
852 return (smb_set_errno(shp
, ESMB_TYPE
));
854 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
855 bzero(map
, sizeof (smbios_memarrmap_t
));
857 map
->smbmam_array
= m
.smbamap_array
;
858 map
->smbmam_width
= m
.smbamap_width
;
860 if (m
.smbamap_start
!= 0xFFFFFFFF && m
.smbamap_end
!= 0xFFFFFFFF) {
861 map
->smbmam_addr
= (uint64_t)m
.smbamap_start
* 1024;
862 map
->smbmam_size
= (uint64_t)
863 (m
.smbamap_end
- m
.smbamap_start
+ 1) * 1024;
864 } else if (m
.smbamap_extstart
!= 0 && m
.smbamap_extend
!= 0) {
865 map
->smbmam_addr
= m
.smbamap_extstart
;
866 map
->smbmam_size
= m
.smbamap_extend
- m
.smbamap_extstart
+ 1;
873 smbios_info_memdevice(smbios_hdl_t
*shp
, id_t id
, smbios_memdevice_t
*mdp
)
875 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
879 return (-1); /* errno is set for us */
881 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMDEVICE
)
882 return (smb_set_errno(shp
, ESMB_TYPE
));
884 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
885 bzero(mdp
, sizeof (smb_base_memdevice_t
));
887 mdp
->smbmd_array
= m
.smbmdev_array
;
888 mdp
->smbmd_error
= m
.smbmdev_error
;
889 mdp
->smbmd_twidth
= m
.smbmdev_twidth
== 0xFFFF ? -1U : m
.smbmdev_twidth
;
890 mdp
->smbmd_dwidth
= m
.smbmdev_dwidth
== 0xFFFF ? -1U : m
.smbmdev_dwidth
;
892 if (m
.smbmdev_size
== 0x7FFF) {
893 mdp
->smbmd_size
= (uint64_t)m
.smbmdev_extsize
;
894 mdp
->smbmd_size
*= 1024 * 1024; /* convert MB to bytes */
895 } else if (m
.smbmdev_size
!= 0xFFFF) {
896 mdp
->smbmd_size
= (uint64_t)(m
.smbmdev_size
& ~SMB_MDS_KBYTES
);
897 if (m
.smbmdev_size
& SMB_MDS_KBYTES
)
898 mdp
->smbmd_size
*= 1024;
900 mdp
->smbmd_size
*= 1024 * 1024;
902 mdp
->smbmd_size
= -1ULL; /* size unknown */
904 mdp
->smbmd_form
= m
.smbmdev_form
;
905 mdp
->smbmd_set
= m
.smbmdev_set
;
906 mdp
->smbmd_type
= m
.smbmdev_type
;
907 mdp
->smbmd_speed
= m
.smbmdev_speed
;
908 mdp
->smbmd_flags
= m
.smbmdev_flags
;
909 mdp
->smbmd_dloc
= smb_strptr(stp
, m
.smbmdev_dloc
);
910 mdp
->smbmd_bloc
= smb_strptr(stp
, m
.smbmdev_bloc
);
912 if (smb_libgteq(shp
, SMB_VERSION_26
)) {
913 mdp
->smbmd_rank
= m
.smbmdev_attrs
& 0x0F;
916 if (smb_libgteq(shp
, SMB_VERSION_27
)) {
917 mdp
->smbmd_clkspeed
= m
.smbmdev_clkspeed
;
920 if (smb_libgteq(shp
, SMB_VERSION_28
)) {
921 mdp
->smbmd_minvolt
= m
.smbmdev_minvolt
;
922 mdp
->smbmd_maxvolt
= m
.smbmdev_maxvolt
;
923 mdp
->smbmd_confvolt
= m
.smbmdev_confvolt
;
930 smbios_info_memdevmap(smbios_hdl_t
*shp
, id_t id
, smbios_memdevmap_t
*mdp
)
932 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
936 return (-1); /* errno is set for us */
938 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_MEMDEVICEMAP
)
939 return (smb_set_errno(shp
, ESMB_TYPE
));
941 smb_info_bcopy(stp
->smbst_hdr
, &m
, sizeof (m
));
942 bzero(mdp
, sizeof (smbios_memdevmap_t
));
944 mdp
->smbmdm_device
= m
.smbdmap_device
;
945 mdp
->smbmdm_arrmap
= m
.smbdmap_array
;
946 mdp
->smbmdm_rpos
= m
.smbdmap_rpos
;
947 mdp
->smbmdm_ipos
= m
.smbdmap_ipos
;
948 mdp
->smbmdm_idepth
= m
.smbdmap_idepth
;
950 if (m
.smbdmap_start
!= 0xFFFFFFFF && m
.smbdmap_end
!= 0xFFFFFFFF) {
951 mdp
->smbmdm_addr
= (uint64_t)m
.smbdmap_start
* 1024;
952 mdp
->smbmdm_size
= (uint64_t)
953 (m
.smbdmap_end
- m
.smbdmap_start
+ 1) * 1024;
954 } else if (m
.smbdmap_extstart
!= 0 && m
.smbdmap_extend
!= 0) {
955 mdp
->smbmdm_addr
= m
.smbdmap_extstart
;
956 mdp
->smbmdm_size
= m
.smbdmap_extend
- m
.smbdmap_extstart
+ 1;
963 smbios_info_hwsec(smbios_hdl_t
*shp
, smbios_hwsec_t
*hsp
)
965 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_SECURITY
);
969 return (-1); /* errno is set for us */
971 smb_info_bcopy(stp
->smbst_hdr
, &hs
, sizeof (hs
));
972 bzero(hsp
, sizeof (smbios_hwsec_t
));
974 hsp
->smbh_pwr_ps
= SMB_HWS_PWR_PS(hs
.smbhs_settings
);
975 hsp
->smbh_kbd_ps
= SMB_HWS_KBD_PS(hs
.smbhs_settings
);
976 hsp
->smbh_adm_ps
= SMB_HWS_ADM_PS(hs
.smbhs_settings
);
977 hsp
->smbh_pan_ps
= SMB_HWS_PAN_PS(hs
.smbhs_settings
);
979 return (stp
->smbst_hdr
->smbh_hdl
);
983 smbios_info_boot(smbios_hdl_t
*shp
, smbios_boot_t
*bp
)
985 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_BOOT
);
986 const smb_boot_t
*b
= (smb_boot_t
*)(uintptr_t)stp
->smbst_hdr
;
989 return (-1); /* errno is set for us */
991 bzero(bp
, sizeof (smbios_boot_t
));
993 bp
->smbt_status
= b
->smbbo_status
[0];
994 bp
->smbt_size
= stp
->smbst_hdr
->smbh_len
- sizeof (smb_boot_t
);
995 bp
->smbt_data
= bp
->smbt_size
? &b
->smbbo_status
[1] : NULL
;
997 return (stp
->smbst_hdr
->smbh_hdl
);
1001 smbios_info_ipmi(smbios_hdl_t
*shp
, smbios_ipmi_t
*ip
)
1003 const smb_struct_t
*stp
= smb_lookup_type(shp
, SMB_TYPE_IPMIDEV
);
1007 return (-1); /* errno is set for us */
1009 smb_info_bcopy(stp
->smbst_hdr
, &i
, sizeof (i
));
1010 bzero(ip
, sizeof (smbios_ipmi_t
));
1012 ip
->smbip_type
= i
.smbipm_type
;
1013 ip
->smbip_vers
.smbv_major
= SMB_IPM_SPEC_MAJOR(i
.smbipm_spec
);
1014 ip
->smbip_vers
.smbv_minor
= SMB_IPM_SPEC_MINOR(i
.smbipm_spec
);
1015 ip
->smbip_i2c
= i
.smbipm_i2c
;
1016 ip
->smbip_addr
= i
.smbipm_addr
& ~SMB_IPM_ADDR_IO
;
1017 ip
->smbip_intr
= i
.smbipm_intr
;
1019 if (i
.smbipm_bus
!= (uint8_t)-1)
1020 ip
->smbip_bus
= i
.smbipm_bus
;
1022 ip
->smbip_bus
= -1u;
1024 if (SMB_IPM_INFO_LSB(i
.smbipm_info
))
1025 ip
->smbip_addr
|= 1; /* turn on least-significant bit of addr */
1027 if (i
.smbipm_addr
& SMB_IPM_ADDR_IO
) {
1028 switch (SMB_IPM_INFO_REGS(i
.smbipm_info
)) {
1029 case SMB_IPM_REGS_1B
:
1030 ip
->smbip_regspacing
= 1;
1032 case SMB_IPM_REGS_4B
:
1033 ip
->smbip_regspacing
= 4;
1035 case SMB_IPM_REGS_16B
:
1036 ip
->smbip_regspacing
= 16;
1039 ip
->smbip_regspacing
= 1;
1041 ip
->smbip_flags
|= SMB_IPMI_F_IOADDR
;
1044 if (SMB_IPM_INFO_ISPEC(i
.smbipm_info
))
1045 ip
->smbip_flags
|= SMB_IPMI_F_INTRSPEC
;
1047 if (SMB_IPM_INFO_IPOL(i
.smbipm_info
) == SMB_IPM_IPOL_HI
)
1048 ip
->smbip_flags
|= SMB_IPMI_F_INTRHIGH
;
1050 if (SMB_IPM_INFO_IMODE(i
.smbipm_info
) == SMB_IPM_IMODE_EDGE
)
1051 ip
->smbip_flags
|= SMB_IPMI_F_INTREDGE
;
1053 return (stp
->smbst_hdr
->smbh_hdl
);
1057 smbios_has_oemstr(smbios_hdl_t
*shp
, const char *oemstr
)
1059 const smb_struct_t
*stp
= shp
->sh_structs
;
1063 for (i
= 0; i
< shp
->sh_nstructs
; i
++, stp
++) {
1064 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_OEMSTR
)
1067 smb_info_bcopy(stp
->smbst_hdr
, &s
, sizeof (s
));
1068 for (j
= 0; j
< s
.smbtb_count
; j
++)
1069 if (strcmp(smb_strptr(stp
, j
+ 1), oemstr
) == 0)
1077 smb_serial_valid(const char *serial
)
1079 char buf
[MAXNAMELEN
];
1085 (void) strlcpy(buf
, serial
, sizeof (buf
));
1087 while (buf
[i
] != '\0' && buf
[i
] == ' ')
1090 if (buf
[i
] == '\0' || strstr(buf
, SMB_DEFAULT1
) != NULL
||
1091 strstr(buf
, SMB_DEFAULT2
) != NULL
)
1098 * Get chassis SN or product SN
1101 smb_get_sn(smbios_hdl_t
*shp
, const char **psnp
, const char **csnp
)
1103 const smb_struct_t
*stp
;
1104 smbios_info_t s1
, s3
;
1106 if (psnp
== NULL
|| csnp
== NULL
)
1107 return (smb_set_errno(shp
, ESMB_INVAL
));
1109 *psnp
= *csnp
= NULL
;
1112 * If SMBIOS meets Sun's PRMS requirements, retrieve product SN
1113 * from type 1 structure, and chassis SN from type 3 structure.
1114 * Otherwise return SN in type 1 structure as chassis SN.
1118 if ((stp
= smb_lookup_type(shp
, SMB_TYPE_SYSTEM
)) == NULL
||
1119 smbios_info_common(shp
, stp
->smbst_hdr
->smbh_hdl
, &s1
) == SMB_ERR
)
1120 s1
.smbi_serial
= NULL
;
1123 if ((stp
= smb_lookup_type(shp
, SMB_TYPE_CHASSIS
)) == NULL
||
1124 smbios_info_common(shp
, stp
->smbst_hdr
->smbh_hdl
, &s3
) == SMB_ERR
)
1125 s3
.smbi_serial
= NULL
;
1127 if (smbios_has_oemstr(shp
, SMB_PRMS1
)) {
1128 *psnp
= smb_serial_valid(s1
.smbi_serial
);
1129 *csnp
= smb_serial_valid(s3
.smbi_serial
);
1131 *csnp
= smb_serial_valid(s1
.smbi_serial
);
1138 smbios_psn(smbios_hdl_t
*shp
)
1140 const char *psn
, *csn
;
1142 return (smb_get_sn(shp
, &psn
, &csn
) == SMB_ERR
? NULL
: psn
);
1146 smbios_csn(smbios_hdl_t
*shp
)
1148 const char *psn
, *csn
;
1150 return (smb_get_sn(shp
, &psn
, &csn
) == SMB_ERR
? NULL
: csn
);
1154 smbios_info_extprocessor(smbios_hdl_t
*shp
, id_t id
,
1155 smbios_processor_ext_t
*epp
)
1157 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1158 smb_processor_ext_t
*exp
;
1161 return (-1); /* errno is set for us */
1163 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_PROCESSOR
)
1164 return (smb_set_errno(shp
, ESMB_TYPE
));
1166 exp
= (smb_processor_ext_t
*)(uintptr_t)stp
->smbst_hdr
;
1167 bzero(epp
, sizeof (smbios_processor_ext_t
));
1169 epp
->smbpe_processor
= exp
->smbpre_processor
;
1170 epp
->smbpe_fru
= exp
->smbpre_fru
;
1171 epp
->smbpe_n
= exp
->smbpre_n
;
1172 epp
->smbpe_apicid
= exp
->smbpre_apicid
;
1178 smbios_info_extport(smbios_hdl_t
*shp
, id_t id
, smbios_port_ext_t
*eportp
)
1180 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1184 return (-1); /* errno is set for us */
1186 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_PORT
)
1187 return (smb_set_errno(shp
, ESMB_TYPE
));
1189 ep
= (smb_port_ext_t
*)(uintptr_t)stp
->smbst_hdr
;
1190 bzero(eportp
, sizeof (smbios_port_ext_t
));
1192 eportp
->smbporte_chassis
= ep
->smbpoe_chassis
;
1193 eportp
->smbporte_port
= ep
->smbpoe_port
;
1194 eportp
->smbporte_dtype
= ep
->smbpoe_dtype
;
1195 eportp
->smbporte_devhdl
= ep
->smbpoe_devhdl
;
1196 eportp
->smbporte_phy
= ep
->smbpoe_phy
;
1202 smbios_info_pciexrc(smbios_hdl_t
*shp
, id_t id
,
1203 smbios_pciexrc_t
*rcp
)
1205 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1209 return (-1); /* errno is set for us */
1211 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_PCIEXRC
)
1212 return (smb_set_errno(shp
, ESMB_TYPE
));
1214 smb_info_bcopy(stp
->smbst_hdr
, &rc
, sizeof (rc
));
1215 bzero(rcp
, sizeof (smbios_pciexrc_t
));
1217 rcp
->smbpcie_bb
= rc
.smbpciexrc_bboard
;
1218 rcp
->smbpcie_bdf
= rc
.smbpciexrc_bdf
;
1224 smbios_info_extmemarray(smbios_hdl_t
*shp
, id_t id
, smbios_memarray_ext_t
*emap
)
1226 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1227 smb_memarray_ext_t exma
;
1230 return (-1); /* errno is set for us */
1232 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_MEMARRAY
)
1233 return (smb_set_errno(shp
, ESMB_TYPE
));
1235 smb_info_bcopy(stp
->smbst_hdr
, &exma
, sizeof (exma
));
1236 bzero(emap
, sizeof (smbios_memarray_ext_t
));
1238 emap
->smbmae_ma
= exma
.smbmarre_ma
;
1239 emap
->smbmae_comp
= exma
.smbmarre_component
;
1240 emap
->smbmae_bdf
= exma
.smbmarre_bdf
;
1246 smbios_info_extmemdevice(smbios_hdl_t
*shp
, id_t id
,
1247 smbios_memdevice_ext_t
*emdp
)
1249 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1250 smb_memdevice_ext_t exmd
;
1253 return (-1); /* errno is set for us */
1255 if (stp
->smbst_hdr
->smbh_type
!= SUN_OEM_EXT_MEMDEVICE
)
1256 return (smb_set_errno(shp
, ESMB_TYPE
));
1258 smb_info_bcopy(stp
->smbst_hdr
, &exmd
, sizeof (exmd
));
1259 bzero(emdp
, sizeof (smbios_memdevice_ext_t
));
1261 emdp
->smbmdeve_md
= exmd
.smbmdeve_mdev
;
1262 emdp
->smbmdeve_drch
= exmd
.smbmdeve_dchan
;
1263 emdp
->smbmdeve_ncs
= exmd
.smbmdeve_ncs
;
1264 emdp
->smbmdeve_cs
= exmd
.smbmdeve_cs
;
1270 smbios_info_powersup(smbios_hdl_t
*shp
, id_t id
, smbios_powersup_t
*psup
)
1272 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1276 return (-1); /* errno is set for us */
1278 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_POWERSUP
)
1279 return (smb_set_errno(shp
, ESMB_TYPE
));
1281 /* The minimum length required by the spec is 0x10. */
1282 if (stp
->smbst_hdr
->smbh_len
< 0x10)
1283 return (smb_set_errno(shp
, ESMB_SHORT
));
1285 bzero(psup
, sizeof (*psup
));
1286 smb_info_bcopy(stp
->smbst_hdr
, &psu
, sizeof (psu
));
1287 psup
->smbps_group
= psu
.smbpsup_group
;
1288 psup
->smbps_maxout
= psu
.smbpsup_max
;
1290 if (SMB_PSU_CHARS_ISHOT(psu
.smbpsup_char
))
1291 psup
->smbps_flags
|= SMB_POWERSUP_F_HOT
;
1292 if (SMB_PSU_CHARS_ISPRES(psu
.smbpsup_char
))
1293 psup
->smbps_flags
|= SMB_POWERSUP_F_PRESENT
;
1294 if (SMB_PSU_CHARS_ISUNPLUG(psu
.smbpsup_char
))
1295 psup
->smbps_flags
|= SMB_POWERSUP_F_UNPLUG
;
1297 psup
->smbps_ivrs
= SMB_PSU_CHARS_IVRS(psu
.smbpsup_char
);
1298 psup
->smbps_status
= SMB_PSU_CHARS_STATUS(psu
.smbpsup_char
);
1299 psup
->smbps_pstype
= SMB_PSU_CHARS_TYPE(psu
.smbpsup_char
);
1301 if (stp
->smbst_hdr
->smbh_len
>= 0x12) {
1302 psup
->smbps_vprobe
= psu
.smbpsup_vprobe
;
1304 psup
->smbps_vprobe
= 0xffff;
1307 if (stp
->smbst_hdr
->smbh_len
>= 0x14) {
1308 psup
->smbps_cooldev
= psu
.smbpsup_cooldev
;
1310 psup
->smbps_cooldev
= 0xffff;
1313 if (stp
->smbst_hdr
->smbh_len
>= 0x16) {
1314 psup
->smbps_iprobe
= psu
.smbpsup_iprobe
;
1316 psup
->smbps_iprobe
= 0xffff;
1323 smbios_info_vprobe(smbios_hdl_t
*shp
, id_t id
, smbios_vprobe_t
*vprobe
)
1325 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1329 return (-1); /* errno is set for us */
1331 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_VPROBE
)
1332 return (smb_set_errno(shp
, ESMB_TYPE
));
1334 if (stp
->smbst_hdr
->smbh_len
< SMB_VPROBE_MINLEN
)
1335 return (smb_set_errno(shp
, ESMB_SHORT
));
1337 bzero(vprobe
, sizeof (*vprobe
));
1338 smb_info_bcopy(stp
->smbst_hdr
, &vp
, sizeof (vp
));
1339 vprobe
->smbvp_description
= smb_strptr(stp
, vp
.smbvpr_descr
);
1340 vprobe
->smbvp_location
= SMB_VPROBE_LOCATION(vp
.smbvpr_locstat
);
1341 vprobe
->smbvp_status
= SMB_VPROBE_STATUS(vp
.smbvpr_locstat
);
1342 vprobe
->smbvp_maxval
= vp
.smbvpr_maxval
;
1343 vprobe
->smbvp_minval
= vp
.smbvpr_minval
;
1344 vprobe
->smbvp_resolution
= vp
.smbvpr_resolution
;
1345 vprobe
->smbvp_tolerance
= vp
.smbvpr_tolerance
;
1346 vprobe
->smbvp_accuracy
= vp
.smbvpr_accuracy
;
1348 if (stp
->smbst_hdr
->smbh_len
>= SMB_VPROBE_NOMINAL_MINLEN
) {
1349 vprobe
->smbvp_nominal
= vp
.smbvpr_nominal
;
1351 vprobe
->smbvp_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1358 smbios_info_cooldev(smbios_hdl_t
*shp
, id_t id
, smbios_cooldev_t
*cooldev
)
1360 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1364 return (-1); /* errno is set for us */
1366 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_COOLDEV
)
1367 return (smb_set_errno(shp
, ESMB_TYPE
));
1369 if (stp
->smbst_hdr
->smbh_len
< SMB_COOLDEV_MINLEN
)
1370 return (smb_set_errno(shp
, ESMB_SHORT
));
1372 bzero(cooldev
, sizeof (*cooldev
));
1373 smb_info_bcopy(stp
->smbst_hdr
, &cd
, sizeof (cd
));
1374 cooldev
->smbcd_tprobe
= cd
.smbcdev_tprobe
;
1375 cooldev
->smbcd_type
= SMB_COOLDEV_TYPE(cd
.smbcdev_typstat
);
1376 cooldev
->smbcd_status
= SMB_COOLDEV_STATUS(cd
.smbcdev_typstat
);
1377 cooldev
->smbcd_group
= cd
.smbcdev_group
;
1378 cooldev
->smbcd_oem
= cd
.smbcdev_oem
;
1380 if (stp
->smbst_hdr
->smbh_len
>= SMB_COOLDEV_NOMINAL_MINLEN
) {
1381 cooldev
->smbcd_nominal
= cd
.smbcdev_nominal
;
1383 cooldev
->smbcd_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1387 * The description field was added in SMBIOS version 2.7. The
1388 * SMB_TYPE_COOLDEV support was only added after all of the 2.7+ fields
1389 * were added in the spec. So while a user may request an older version,
1390 * we don't have to worry about old structures and just simply skip it
1391 * if they're not asking for it.
1393 if (smb_libgteq(shp
, SMB_VERSION_27
) &&
1394 smb_gteq(shp
, SMB_VERSION_27
) &&
1395 stp
->smbst_hdr
->smbh_len
>= SMB_COOLDEV_DESCR_MINLEN
) {
1396 cooldev
->smbcd_descr
= smb_strptr(stp
, cd
.smbcdev_descr
);
1398 cooldev
->smbcd_descr
= NULL
;
1405 smbios_info_tprobe(smbios_hdl_t
*shp
, id_t id
, smbios_tprobe_t
*tprobe
)
1407 const smb_struct_t
*stp
= smb_lookup_id(shp
, id
);
1411 return (-1); /* errno is set for us */
1413 if (stp
->smbst_hdr
->smbh_type
!= SMB_TYPE_TPROBE
)
1414 return (smb_set_errno(shp
, ESMB_TYPE
));
1416 if (stp
->smbst_hdr
->smbh_len
< SMB_TPROBE_MINLEN
)
1417 return (smb_set_errno(shp
, ESMB_SHORT
));
1419 bzero(tprobe
, sizeof (*tprobe
));
1420 smb_info_bcopy(stp
->smbst_hdr
, &tp
, sizeof (tp
));
1421 tprobe
->smbtp_description
= smb_strptr(stp
, tp
.smbtpr_descr
);
1422 tprobe
->smbtp_location
= SMB_TPROBE_LOCATION(tp
.smbtpr_locstat
);
1423 tprobe
->smbtp_status
= SMB_TPROBE_STATUS(tp
.smbtpr_locstat
);
1424 tprobe
->smbtp_maxval
= tp
.smbtpr_maxval
;
1425 tprobe
->smbtp_minval
= tp
.smbtpr_minval
;
1426 tprobe
->smbtp_resolution
= tp
.smbtpr_resolution
;
1427 tprobe
->smbtp_tolerance
= tp
.smbtpr_tolerance
;
1428 tprobe
->smbtp_accuracy
= tp
.smbtpr_accuracy
;
1430 if (stp
->smbst_hdr
->smbh_len
>= SMB_TPROBE_NOMINAL_MINLEN
) {
1431 tprobe
->smbtp_nominal
= tp
.smbtpr_nominal
;
1433 tprobe
->smbtp_nominal
= SMB_PROBE_UNKNOWN_VALUE
;
1440 smbios_info_iprobe(smbios_hdl_t
*shp
, id_t id
, smbios_iprobe_t
*iprobe
)
1442 const smb_struct_t
*sip
= smb_lookup_id(shp
, id
);
1446 return (-1); /* errno is set for us */
1448 if (sip
->smbst_hdr
->smbh_type
!= SMB_TYPE_IPROBE
)
1449 return (smb_set_errno(shp
, ESMB_TYPE
));
1451 if (sip
->smbst_hdr
->smbh_len
< SMB_IPROBE_MINLEN
)
1452 return (smb_set_errno(shp
, ESMB_SHORT
));
1454 bzero(iprobe
, sizeof (*iprobe
));
1455 smb_info_bcopy(sip
->smbst_hdr
, &ip
, sizeof (ip
));
1456 iprobe
->smbip_description
= smb_strptr(sip
, ip
.smbipr_descr
);
1457 iprobe
->smbip_location
= SMB_IPROBE_LOCATION(ip
.smbipr_locstat
);
1458 iprobe
->smbip_status
= SMB_IPROBE_STATUS(ip
.smbipr_locstat
);
1459 iprobe
->smbip_maxval
= ip
.smbipr_maxval
;
1460 iprobe
->smbip_minval
= ip
.smbipr_minval
;
1461 iprobe
->smbip_resolution
= ip
.smbipr_resolution
;
1462 iprobe
->smbip_tolerance
= ip
.smbipr_tolerance
;
1463 iprobe
->smbip_accuracy
= ip
.smbipr_accuracy
;
1465 if (sip
->smbst_hdr
->smbh_len
>= SMB_IPROBE_NOMINAL_MINLEN
) {
1466 iprobe
->smbip_nominal
= ip
.smbipr_nominal
;
1468 iprobe
->smbip_nominal
= SMB_PROBE_UNKNOWN_VALUE
;