1*437Smws /* 2*437Smws * CDDL HEADER START 3*437Smws * 4*437Smws * The contents of this file are subject to the terms of the 5*437Smws * Common Development and Distribution License, Version 1.0 only 6*437Smws * (the "License"). You may not use this file except in compliance 7*437Smws * with the License. 8*437Smws * 9*437Smws * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*437Smws * or http://www.opensolaris.org/os/licensing. 11*437Smws * See the License for the specific language governing permissions 12*437Smws * and limitations under the License. 13*437Smws * 14*437Smws * When distributing Covered Code, include this CDDL HEADER in each 15*437Smws * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*437Smws * If applicable, add the following below this CDDL HEADER, with the 17*437Smws * fields enclosed by brackets "[]" replaced with your own identifying 18*437Smws * information: Portions Copyright [yyyy] [name of copyright owner] 19*437Smws * 20*437Smws * CDDL HEADER END 21*437Smws */ 22*437Smws 23*437Smws /* 24*437Smws * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*437Smws * Use is subject to license terms. 26*437Smws */ 27*437Smws 28*437Smws #pragma ident "%Z%%M% %I% %E% SMI" 29*437Smws 30*437Smws #include <sys/types.h> 31*437Smws #include <sys/smbios_impl.h> 32*437Smws #include <sys/sysmacros.h> 33*437Smws #include <sys/stat.h> 34*437Smws #include <sys/mman.h> 35*437Smws 36*437Smws #include <limits.h> 37*437Smws #include <unistd.h> 38*437Smws #include <strings.h> 39*437Smws #include <stdlib.h> 40*437Smws #include <errno.h> 41*437Smws #include <fcntl.h> 42*437Smws 43*437Smws #pragma init(smb_init) 44*437Smws static void 45*437Smws smb_init(void) 46*437Smws { 47*437Smws _smb_debug = getenv("SMB_DEBUG") != NULL; 48*437Smws } 49*437Smws 50*437Smws static smbios_hdl_t * 51*437Smws smb_fileopen(int fd, int version, int flags, int *errp) 52*437Smws { 53*437Smws smbios_hdl_t *shp = NULL; 54*437Smws smbios_entry_t ep; 55*437Smws void *stbuf; 56*437Smws ssize_t n; 57*437Smws 58*437Smws if ((n = pread64(fd, &ep, sizeof (ep), 0)) != sizeof (ep)) 59*437Smws return (smb_open_error(shp, errp, n < 0 ? errno : ESMB_NOHDR)); 60*437Smws 61*437Smws if (strncmp(ep.smbe_eanchor, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN)) 62*437Smws return (smb_open_error(shp, errp, ESMB_HEADER)); 63*437Smws 64*437Smws if ((stbuf = smb_alloc(ep.smbe_stlen)) == NULL) 65*437Smws return (smb_open_error(shp, errp, ESMB_NOMEM)); 66*437Smws 67*437Smws if ((n = pread64(fd, stbuf, ep.smbe_stlen, 68*437Smws (off64_t)ep.smbe_staddr)) != ep.smbe_stlen) { 69*437Smws smb_free(stbuf, ep.smbe_stlen); 70*437Smws return (smb_open_error(shp, errp, n < 0 ? errno : ESMB_NOSTAB)); 71*437Smws } 72*437Smws 73*437Smws shp = smbios_bufopen(&ep, stbuf, ep.smbe_stlen, version, flags, errp); 74*437Smws 75*437Smws if (shp != NULL) 76*437Smws shp->sh_flags |= SMB_FL_BUFALLOC; 77*437Smws else 78*437Smws smb_free(stbuf, ep.smbe_stlen); 79*437Smws 80*437Smws return (shp); 81*437Smws } 82*437Smws 83*437Smws static smbios_hdl_t * 84*437Smws smb_biosopen(int fd, int version, int flags, int *errp) 85*437Smws { 86*437Smws smbios_hdl_t *shp = NULL; 87*437Smws size_t pgsize, pgmask, pgoff; 88*437Smws void *stbuf, *bios, *p, *q; 89*437Smws smbios_entry_t ep; 90*437Smws 91*437Smws bios = mmap(NULL, SMB_RANGE_LIMIT - SMB_RANGE_START + 1, 92*437Smws PROT_READ, MAP_SHARED, fd, (uint32_t)SMB_RANGE_START); 93*437Smws 94*437Smws if (bios == MAP_FAILED) 95*437Smws return (smb_open_error(shp, errp, ESMB_MAPDEV)); 96*437Smws 97*437Smws q = (void *)((uintptr_t)bios + SMB_RANGE_LIMIT - SMB_RANGE_START + 1); 98*437Smws 99*437Smws for (p = bios; p < q; p = (void *)((uintptr_t)p + 16)) { 100*437Smws if (strncmp(p, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN) == 0) 101*437Smws break; 102*437Smws } 103*437Smws 104*437Smws if (p >= q) { 105*437Smws (void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1); 106*437Smws return (smb_open_error(NULL, errp, ESMB_NOTFOUND)); 107*437Smws } 108*437Smws 109*437Smws bcopy(p, &ep, sizeof (smbios_entry_t)); 110*437Smws (void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1); 111*437Smws 112*437Smws pgsize = getpagesize(); 113*437Smws pgmask = ~(pgsize - 1); 114*437Smws pgoff = ep.smbe_staddr & ~pgmask; 115*437Smws 116*437Smws bios = mmap(NULL, ep.smbe_stlen + pgoff, 117*437Smws PROT_READ, MAP_SHARED, fd, ep.smbe_staddr & pgmask); 118*437Smws 119*437Smws if (bios == MAP_FAILED) 120*437Smws return (smb_open_error(shp, errp, ESMB_MAPDEV)); 121*437Smws 122*437Smws if ((stbuf = smb_alloc(ep.smbe_stlen)) == NULL) { 123*437Smws (void) munmap(bios, ep.smbe_stlen + pgoff); 124*437Smws return (smb_open_error(shp, errp, ESMB_NOMEM)); 125*437Smws } 126*437Smws 127*437Smws bcopy((char *)bios + pgoff, stbuf, ep.smbe_stlen); 128*437Smws (void) munmap(bios, ep.smbe_stlen + pgoff); 129*437Smws shp = smbios_bufopen(&ep, stbuf, ep.smbe_stlen, version, flags, errp); 130*437Smws 131*437Smws if (shp != NULL) 132*437Smws shp->sh_flags |= SMB_FL_BUFALLOC; 133*437Smws else 134*437Smws smb_free(stbuf, ep.smbe_stlen); 135*437Smws 136*437Smws return (shp); 137*437Smws } 138*437Smws 139*437Smws smbios_hdl_t * 140*437Smws smbios_fdopen(int fd, int version, int flags, int *errp) 141*437Smws { 142*437Smws struct stat64 st1, st2; 143*437Smws 144*437Smws if (stat64(SMB_BIOS_DEVICE, &st1) == 0 && fstat64(fd, &st2) == 0 && 145*437Smws S_ISCHR(st2.st_mode) && st1.st_rdev == st2.st_rdev) 146*437Smws return (smb_biosopen(fd, version, flags, errp)); 147*437Smws else 148*437Smws return (smb_fileopen(fd, version, flags, errp)); 149*437Smws } 150*437Smws 151*437Smws smbios_hdl_t * 152*437Smws smbios_open(const char *file, int version, int flags, int *errp) 153*437Smws { 154*437Smws smbios_hdl_t *shp; 155*437Smws int fd; 156*437Smws 157*437Smws if ((fd = open64(file ? file : SMB_SMBIOS_DEVICE, O_RDONLY)) == -1) { 158*437Smws if ((errno == ENOENT || errno == ENXIO) && 159*437Smws (file == NULL || strcmp(file, SMB_SMBIOS_DEVICE) == 0)) 160*437Smws errno = ESMB_NOTFOUND; 161*437Smws return (smb_open_error(NULL, errp, errno)); 162*437Smws } 163*437Smws 164*437Smws shp = smbios_fdopen(fd, version, flags, errp); 165*437Smws (void) close(fd); 166*437Smws return (shp); 167*437Smws } 168*437Smws 169*437Smws static int 170*437Smws smbios_xwrite(smbios_hdl_t *shp, int fd, const void *buf, size_t buflen) 171*437Smws { 172*437Smws ssize_t resid = buflen; 173*437Smws ssize_t len; 174*437Smws 175*437Smws while (resid != 0) { 176*437Smws if ((len = write(fd, buf, resid)) <= 0) 177*437Smws return (smb_set_errno(shp, errno)); 178*437Smws resid -= len; 179*437Smws buf = (uchar_t *)buf + len; 180*437Smws } 181*437Smws 182*437Smws return (0); 183*437Smws } 184*437Smws 185*437Smws int 186*437Smws smbios_write(smbios_hdl_t *shp, int fd) 187*437Smws { 188*437Smws smbios_entry_t ep; 189*437Smws off64_t off = lseek64(fd, 0, SEEK_CUR) + P2ROUNDUP(sizeof (ep), 16); 190*437Smws 191*437Smws if (off > UINT32_MAX) 192*437Smws return (smb_set_errno(shp, EOVERFLOW)); 193*437Smws 194*437Smws bcopy(&shp->sh_ent, &ep, sizeof (ep)); 195*437Smws ep.smbe_staddr = (uint32_t)off; 196*437Smws smbios_checksum(shp, &ep); 197*437Smws 198*437Smws if (smbios_xwrite(shp, fd, &ep, sizeof (ep)) == -1 || 199*437Smws lseek64(fd, off, SEEK_SET) != off || 200*437Smws smbios_xwrite(shp, fd, shp->sh_buf, shp->sh_buflen) == -1) 201*437Smws return (-1); 202*437Smws 203*437Smws return (0); 204*437Smws } 205