4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * Platform-Specific SMBIOS Subroutines
31 * The routines in this file form part of <sys/smbios_impl.h> and combine with
32 * the usr/src/common/smbios code to form an in-kernel SMBIOS decoding service.
33 * The SMBIOS entry point is locating by scanning a range of physical memory
34 * assigned to BIOS as described in Section 2 of the DMTF SMBIOS specification.
37 #include <sys/smbios_impl.h>
38 #include <sys/sysmacros.h>
39 #include <sys/errno.h>
41 #include <sys/smp_impldefs.h>
43 smbios_hdl_t
*ksmbios
;
47 smb_open_error(smbios_hdl_t
*shp
, int *errp
, int err
)
56 cmn_err(CE_CONT
, "?SMBIOS not loaded (%s)", smbios_errmsg(err
));
62 smbios_open(const char *file
, int version
, int flags
, int *errp
)
64 smbios_hdl_t
*shp
= NULL
;
66 caddr_t stbuf
, bios
, p
, q
;
67 uint64_t startaddr
, startoff
= 0;
70 smbios_entry_point_t ep_type
= SMBIOS_ENTRY_POINT_21
;
71 uint8_t smbe_major
, smbe_minor
;
74 if (file
!= NULL
|| (flags
& ~SMB_O_MASK
))
75 return (smb_open_error(shp
, errp
, ESMB_INVAL
));
77 if ((startaddr
= ddi_prop_get_int64(DDI_DEV_T_ANY
, ddi_root_node(),
78 DDI_PROP_DONTPASS
, "smbios-address", 0)) == 0) {
79 startaddr
= SMB_RANGE_START
;
80 bioslen
= SMB_RANGE_LIMIT
- SMB_RANGE_START
+ 1;
82 /* We have smbios address from boot loader, map one page. */
83 bioslen
= MMU_PAGESIZE
;
84 startoff
= startaddr
& MMU_PAGEOFFSET
;
85 startaddr
&= MMU_PAGEMASK
;
87 /* If the address is not good, use memory scan instead. */
88 if (startaddr
> UINT32_MAX
) {
89 startaddr
= SMB_RANGE_START
;
90 bioslen
= SMB_RANGE_LIMIT
- SMB_RANGE_START
+ 1;
96 bios
= psm_map_phys(startaddr
, bioslen
, PSM_PROT_READ
);
99 return (smb_open_error(shp
, errp
, ESMB_MAPDEV
));
102 * In case we did map one page, make sure we will not cross
103 * the end of the page.
106 q
= bios
+ bioslen
- startoff
;
109 err
= strncmp(p
, SMB3_ENTRY_EANCHOR
, SMB3_ENTRY_EANCHORLEN
);
111 ep_type
= SMBIOS_ENTRY_POINT_30
;
115 if (strncmp(p
, SMB_ENTRY_EANCHOR
, SMB_ENTRY_EANCHORLEN
) == 0)
121 psm_unmap_phys(bios
, bioslen
);
122 return (smb_open_error(shp
, errp
, ESMB_NOTFOUND
));
125 ep
= smb_alloc(SMB_ENTRY_MAXLEN
);
126 bcopy(p
, ep
, sizeof (smbios_entry_t
));
127 if (ep_type
== SMBIOS_ENTRY_POINT_21
) {
128 ep
->ep21
.smbe_elen
= MIN(ep
->ep21
.smbe_elen
, SMB_ENTRY_MAXLEN
);
129 bcopy(p
, ep
, ep
->ep21
.smbe_elen
);
130 } else if (ep_type
== SMBIOS_ENTRY_POINT_30
) {
131 ep
->ep30
.smbe_elen
= MIN(ep
->ep30
.smbe_elen
, SMB_ENTRY_MAXLEN
);
132 bcopy(p
, ep
, ep
->ep30
.smbe_elen
);
135 psm_unmap_phys(bios
, bioslen
);
137 case SMBIOS_ENTRY_POINT_21
:
138 smbe_major
= ep
->ep21
.smbe_major
;
139 smbe_minor
= ep
->ep21
.smbe_minor
;
140 smbe_stlen
= ep
->ep21
.smbe_stlen
;
141 bios
= psm_map_phys(ep
->ep21
.smbe_staddr
, smbe_stlen
,
144 case SMBIOS_ENTRY_POINT_30
:
145 smbe_major
= ep
->ep30
.smbe_major
;
146 smbe_minor
= ep
->ep30
.smbe_minor
;
147 smbe_stlen
= ep
->ep30
.smbe_stlen
;
148 bios
= psm_map_phys_new(ep
->ep30
.smbe_staddr
, smbe_stlen
,
152 smb_free(ep
, SMB_ENTRY_MAXLEN
);
153 return (smb_open_error(shp
, errp
, ESMB_VERSION
));
157 smb_free(ep
, SMB_ENTRY_MAXLEN
);
158 return (smb_open_error(shp
, errp
, ESMB_MAPDEV
));
161 stbuf
= smb_alloc(smbe_stlen
);
162 bcopy(bios
, stbuf
, smbe_stlen
);
163 psm_unmap_phys(bios
, smbe_stlen
);
164 shp
= smbios_bufopen(ep
, stbuf
, smbe_stlen
, version
, flags
, &err
);
167 smb_free(stbuf
, smbe_stlen
);
168 smb_free(ep
, SMB_ENTRY_MAXLEN
);
169 return (smb_open_error(shp
, errp
, err
));
172 if (ksmbios
== NULL
) {
173 cmn_err(CE_CONT
, "?SMBIOS v%u.%u loaded (%u bytes)",
174 smbe_major
, smbe_minor
, smbe_stlen
);
175 if (shp
->sh_flags
& SMB_FL_TRUNC
)
176 cmn_err(CE_CONT
, "?SMBIOS table is truncated");
179 shp
->sh_flags
|= SMB_FL_BUFALLOC
;
180 smb_free(ep
, SMB_ENTRY_MAXLEN
);
187 smbios_fdopen(int fd
, int version
, int flags
, int *errp
)
189 return (smb_open_error(NULL
, errp
, ENOTSUP
));
194 smbios_write(smbios_hdl_t
*shp
, int fd
)
196 return (smb_set_errno(shp
, ENOTSUP
));