1 /*
2 * CDDL HEADER START
3 *
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
7 * with the License.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #pragma ident "%Z%%M% %I% %E% SMI"
29
30 /*
31 * Platform-Specific SMBIOS Subroutines
32 *
33 * The routines in this file form part of <sys/smbios_impl.h> and combine with
34 * the usr/src/common/smbios code to form an in-kernel SMBIOS decoding service.
35 * The SMBIOS entry point is locating by scanning a range of physical memory
36 * assigned to BIOS as described in Section 2 of the DMTF SMBIOS specification.
37 */
38
39 #include <sys/smbios_impl.h>
40 #include <sys/sysmacros.h>
41 #include <sys/errno.h>
42 #include <sys/psm.h>
43 #include <sys/smp_impldefs.h>
44
45 smbios_hdl_t *ksmbios;
46 int ksmbios_flags;
47
48 smbios_hdl_t *
smb_open_error(smbios_hdl_t * shp,int * errp,int err)49 smb_open_error(smbios_hdl_t *shp, int *errp, int err)
50 {
51 if (shp != NULL)
52 smbios_close(shp);
53
54 if (errp != NULL)
55 *errp = err;
56
57 if (ksmbios == NULL)
58 cmn_err(CE_CONT, "?SMBIOS not loaded (%s)", smbios_errmsg(err));
59
60 return (NULL);
61 }
62
63 smbios_hdl_t *
smbios_open(const char * file,int version,int flags,int * errp)64 smbios_open(const char *file, int version, int flags, int *errp)
65 {
66 smbios_hdl_t *shp = NULL;
67 smbios_entry_t *ep;
68 caddr_t stbuf, bios, p, q;
69 size_t bioslen;
70 int err;
71
72 if (file != NULL || (flags & ~SMB_O_MASK))
73 return (smb_open_error(shp, errp, ESMB_INVAL));
74
75 bioslen = SMB_RANGE_LIMIT - SMB_RANGE_START + 1;
76 bios = psm_map_phys(SMB_RANGE_START, bioslen, PSM_PROT_READ);
77
78 if (bios == NULL)
79 return (smb_open_error(shp, errp, ESMB_MAPDEV));
80
81 for (p = bios, q = bios + bioslen; p < q; p += 16) {
82 if (strncmp(p, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN) == 0)
83 break;
84 }
85
86 if (p >= q) {
87 psm_unmap_phys(bios, bioslen);
88 return (smb_open_error(shp, errp, ESMB_NOTFOUND));
89 }
90
91 ep = smb_alloc(SMB_ENTRY_MAXLEN);
92 bcopy(p, ep, sizeof (smbios_entry_t));
93 ep->smbe_elen = MIN(ep->smbe_elen, SMB_ENTRY_MAXLEN);
94 bcopy(p, ep, ep->smbe_elen);
95
96 psm_unmap_phys(bios, bioslen);
97 bios = psm_map_phys(ep->smbe_staddr, ep->smbe_stlen, PSM_PROT_READ);
98
99 if (bios == NULL) {
100 smb_free(ep, SMB_ENTRY_MAXLEN);
101 return (smb_open_error(shp, errp, ESMB_MAPDEV));
102 }
103
104 stbuf = smb_alloc(ep->smbe_stlen);
105 bcopy(bios, stbuf, ep->smbe_stlen);
106 psm_unmap_phys(bios, ep->smbe_stlen);
107 shp = smbios_bufopen(ep, stbuf, ep->smbe_stlen, version, flags, &err);
108
109 if (shp == NULL) {
110 smb_free(stbuf, ep->smbe_stlen);
111 smb_free(ep, SMB_ENTRY_MAXLEN);
112 return (smb_open_error(shp, errp, err));
113 }
114
115 if (ksmbios == NULL) {
116 cmn_err(CE_CONT, "?SMBIOS v%u.%u loaded (%u bytes)",
117 ep->smbe_major, ep->smbe_minor, ep->smbe_stlen);
118 }
119
120 shp->sh_flags |= SMB_FL_BUFALLOC;
121 smb_free(ep, SMB_ENTRY_MAXLEN);
122
123 return (shp);
124 }
125
126 /*ARGSUSED*/
127 smbios_hdl_t *
smbios_fdopen(int fd,int version,int flags,int * errp)128 smbios_fdopen(int fd, int version, int flags, int *errp)
129 {
130 return (smb_open_error(NULL, errp, ENOTSUP));
131 }
132
133 /*ARGSUSED*/
134 int
smbios_write(smbios_hdl_t * shp,int fd)135 smbios_write(smbios_hdl_t *shp, int fd)
136 {
137 return (smb_set_errno(shp, ENOTSUP));
138 }
139