184ab085aSmws /* 284ab085aSmws * CDDL HEADER START 384ab085aSmws * 484ab085aSmws * The contents of this file are subject to the terms of the 584ab085aSmws * Common Development and Distribution License, Version 1.0 only 684ab085aSmws * (the "License"). You may not use this file except in compliance 784ab085aSmws * with the License. 884ab085aSmws * 984ab085aSmws * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1084ab085aSmws * or http://www.opensolaris.org/os/licensing. 1184ab085aSmws * See the License for the specific language governing permissions 1284ab085aSmws * and limitations under the License. 1384ab085aSmws * 1484ab085aSmws * When distributing Covered Code, include this CDDL HEADER in each 1584ab085aSmws * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1684ab085aSmws * If applicable, add the following below this CDDL HEADER, with the 1784ab085aSmws * fields enclosed by brackets "[]" replaced with your own identifying 1884ab085aSmws * information: Portions Copyright [yyyy] [name of copyright owner] 1984ab085aSmws * 2084ab085aSmws * CDDL HEADER END 2184ab085aSmws */ 2284ab085aSmws 2384ab085aSmws /* 24e4586ebfSmws * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2584ab085aSmws * Use is subject to license terms. 2684ab085aSmws */ 2784ab085aSmws 2884ab085aSmws /* 2984ab085aSmws * Platform-Specific SMBIOS Subroutines 3084ab085aSmws * 3184ab085aSmws * The routines in this file form part of <sys/smbios_impl.h> and combine with 3284ab085aSmws * the usr/src/common/smbios code to form an in-kernel SMBIOS decoding service. 3384ab085aSmws * The SMBIOS entry point is locating by scanning a range of physical memory 3484ab085aSmws * assigned to BIOS as described in Section 2 of the DMTF SMBIOS specification. 3584ab085aSmws */ 3684ab085aSmws 3784ab085aSmws #include <sys/smbios_impl.h> 3884ab085aSmws #include <sys/sysmacros.h> 3984ab085aSmws #include <sys/errno.h> 4084ab085aSmws #include <sys/psm.h> 4184ab085aSmws #include <sys/smp_impldefs.h> 4284ab085aSmws 4384ab085aSmws smbios_hdl_t *ksmbios; 4484ab085aSmws int ksmbios_flags; 4584ab085aSmws 4684ab085aSmws smbios_hdl_t * 4784ab085aSmws smb_open_error(smbios_hdl_t *shp, int *errp, int err) 4884ab085aSmws { 4984ab085aSmws if (shp != NULL) 5084ab085aSmws smbios_close(shp); 5184ab085aSmws 5284ab085aSmws if (errp != NULL) 5384ab085aSmws *errp = err; 5484ab085aSmws 5584ab085aSmws if (ksmbios == NULL) 5684ab085aSmws cmn_err(CE_CONT, "?SMBIOS not loaded (%s)", smbios_errmsg(err)); 5784ab085aSmws 5884ab085aSmws return (NULL); 5984ab085aSmws } 6084ab085aSmws 6184ab085aSmws smbios_hdl_t * 6284ab085aSmws smbios_open(const char *file, int version, int flags, int *errp) 6384ab085aSmws { 6484ab085aSmws smbios_hdl_t *shp = NULL; 65e4586ebfSmws smbios_entry_t *ep; 6684ab085aSmws caddr_t stbuf, bios, p, q; 67*96e7037fSToomas Soome uint64_t startaddr, startoff = 0; 6884ab085aSmws size_t bioslen; 6984ab085aSmws int err; 7084ab085aSmws 7184ab085aSmws if (file != NULL || (flags & ~SMB_O_MASK)) 7284ab085aSmws return (smb_open_error(shp, errp, ESMB_INVAL)); 7384ab085aSmws 74*96e7037fSToomas Soome if ((startaddr = ddi_prop_get_int64(DDI_DEV_T_ANY, ddi_root_node(), 75*96e7037fSToomas Soome DDI_PROP_DONTPASS, "smbios-address", 0)) == 0) { 76*96e7037fSToomas Soome startaddr = SMB_RANGE_START; 7784ab085aSmws bioslen = SMB_RANGE_LIMIT - SMB_RANGE_START + 1; 78*96e7037fSToomas Soome } else { 79*96e7037fSToomas Soome /* We have smbios address from boot loader, map one page. */ 80*96e7037fSToomas Soome bioslen = MMU_PAGESIZE; 81*96e7037fSToomas Soome startoff = startaddr & MMU_PAGEOFFSET; 82*96e7037fSToomas Soome startaddr &= MMU_PAGEMASK; 83*96e7037fSToomas Soome #if defined(__i386) 84*96e7037fSToomas Soome /* If the address is not good, use memory scan instead. */ 85*96e7037fSToomas Soome if (startaddr > UINT32_MAX) { 86*96e7037fSToomas Soome startaddr = SMB_RANGE_START; 87*96e7037fSToomas Soome bioslen = SMB_RANGE_LIMIT - SMB_RANGE_START + 1; 88*96e7037fSToomas Soome startoff = 0; 89*96e7037fSToomas Soome } 90*96e7037fSToomas Soome #endif 91*96e7037fSToomas Soome } 92*96e7037fSToomas Soome 93*96e7037fSToomas Soome bios = psm_map_phys(startaddr, bioslen, PSM_PROT_READ); 9484ab085aSmws 9584ab085aSmws if (bios == NULL) 9684ab085aSmws return (smb_open_error(shp, errp, ESMB_MAPDEV)); 9784ab085aSmws 98*96e7037fSToomas Soome /* 99*96e7037fSToomas Soome * In case we did map one page, make sure we will not cross 100*96e7037fSToomas Soome * the end of the page. 101*96e7037fSToomas Soome */ 102*96e7037fSToomas Soome p = bios + startoff; 103*96e7037fSToomas Soome q = bios + bioslen - startoff; 104*96e7037fSToomas Soome while (p < q) { 10584ab085aSmws if (strncmp(p, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN) == 0) 10684ab085aSmws break; 107*96e7037fSToomas Soome p += SMB_SCAN_STEP; 10884ab085aSmws } 10984ab085aSmws 11084ab085aSmws if (p >= q) { 11184ab085aSmws psm_unmap_phys(bios, bioslen); 11284ab085aSmws return (smb_open_error(shp, errp, ESMB_NOTFOUND)); 11384ab085aSmws } 11484ab085aSmws 115e4586ebfSmws ep = smb_alloc(SMB_ENTRY_MAXLEN); 116e4586ebfSmws bcopy(p, ep, sizeof (smbios_entry_t)); 117e4586ebfSmws ep->smbe_elen = MIN(ep->smbe_elen, SMB_ENTRY_MAXLEN); 118e4586ebfSmws bcopy(p, ep, ep->smbe_elen); 119e4586ebfSmws 12084ab085aSmws psm_unmap_phys(bios, bioslen); 121e4586ebfSmws bios = psm_map_phys(ep->smbe_staddr, ep->smbe_stlen, PSM_PROT_READ); 12284ab085aSmws 123e4586ebfSmws if (bios == NULL) { 124e4586ebfSmws smb_free(ep, SMB_ENTRY_MAXLEN); 12584ab085aSmws return (smb_open_error(shp, errp, ESMB_MAPDEV)); 126e4586ebfSmws } 12784ab085aSmws 128e4586ebfSmws stbuf = smb_alloc(ep->smbe_stlen); 129e4586ebfSmws bcopy(bios, stbuf, ep->smbe_stlen); 130e4586ebfSmws psm_unmap_phys(bios, ep->smbe_stlen); 131e4586ebfSmws shp = smbios_bufopen(ep, stbuf, ep->smbe_stlen, version, flags, &err); 13284ab085aSmws 13384ab085aSmws if (shp == NULL) { 134e4586ebfSmws smb_free(stbuf, ep->smbe_stlen); 135e4586ebfSmws smb_free(ep, SMB_ENTRY_MAXLEN); 13684ab085aSmws return (smb_open_error(shp, errp, err)); 13784ab085aSmws } 13884ab085aSmws 13984ab085aSmws if (ksmbios == NULL) { 14084ab085aSmws cmn_err(CE_CONT, "?SMBIOS v%u.%u loaded (%u bytes)", 141e4586ebfSmws ep->smbe_major, ep->smbe_minor, ep->smbe_stlen); 142516627f3SJonathan Matthew if (shp->sh_flags & SMB_FL_TRUNC) 143516627f3SJonathan Matthew cmn_err(CE_CONT, "?SMBIOS table is truncated"); 14484ab085aSmws } 14584ab085aSmws 14684ab085aSmws shp->sh_flags |= SMB_FL_BUFALLOC; 147e4586ebfSmws smb_free(ep, SMB_ENTRY_MAXLEN); 148e4586ebfSmws 14984ab085aSmws return (shp); 15084ab085aSmws } 15184ab085aSmws 15284ab085aSmws /*ARGSUSED*/ 15384ab085aSmws smbios_hdl_t * 15484ab085aSmws smbios_fdopen(int fd, int version, int flags, int *errp) 15584ab085aSmws { 15684ab085aSmws return (smb_open_error(NULL, errp, ENOTSUP)); 15784ab085aSmws } 15884ab085aSmws 15984ab085aSmws /*ARGSUSED*/ 16084ab085aSmws int 16184ab085aSmws smbios_write(smbios_hdl_t *shp, int fd) 16284ab085aSmws { 16384ab085aSmws return (smb_set_errno(shp, ENOTSUP)); 16484ab085aSmws } 165