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
45smbios_hdl_t *ksmbios;
46int ksmbios_flags;
47
48smbios_hdl_t *
49smb_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
63smbios_hdl_t *
64smbios_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*/
127smbios_hdl_t *
128smbios_fdopen(int fd, int version, int flags, int *errp)
129{
130	return (smb_open_error(NULL, errp, ENOTSUP));
131}
132
133/*ARGSUSED*/
134int
135smbios_write(smbios_hdl_t *shp, int fd)
136{
137	return (smb_set_errno(shp, ENOTSUP));
138}
139