diff options
| author | Toomas Soome <tsoome@me.com> | 2016-12-10 01:03:02 +0200 |
|---|---|---|
| committer | Dan McDonald <danmcd@omniti.com> | 2017-02-22 21:02:01 -0500 |
| commit | 1951a93366b3e52f7c49ec9b2dbfb21bccc56a3e (patch) | |
| tree | 87f7268eab136503d4695aec8da01a58f88ef6a1 /usr/src/lib/libsmbios/common/smb_lib.c | |
| parent | ec2c76eb1d5ecd7a4fccccefc1bc4aa7c1531606 (diff) | |
| download | illumos-gate-1951a93366b3e52f7c49ec9b2dbfb21bccc56a3e.tar.gz | |
7837 smbios3 64-bit entry point support
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/lib/libsmbios/common/smb_lib.c')
| -rw-r--r-- | usr/src/lib/libsmbios/common/smb_lib.c | 118 |
1 files changed, 89 insertions, 29 deletions
diff --git a/usr/src/lib/libsmbios/common/smb_lib.c b/usr/src/lib/libsmbios/common/smb_lib.c index d5dd5502db..6c1f375004 100644 --- a/usr/src/lib/libsmbios/common/smb_lib.c +++ b/usr/src/lib/libsmbios/common/smb_lib.c @@ -25,8 +25,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/smbios_impl.h> #include <sys/sysmacros.h> @@ -40,6 +38,7 @@ #include <stdlib.h> #include <errno.h> #include <fcntl.h> +#include <libdevinfo.h> #pragma init(smb_init) static void @@ -52,36 +51,54 @@ static smbios_hdl_t * smb_fileopen(int fd, int version, int flags, int *errp) { smbios_entry_t *ep = alloca(SMB_ENTRY_MAXLEN); + smbios_entry_point_t ep_type; smbios_hdl_t *shp = NULL; + uint32_t smbe_stlen; + off64_t smbe_staddr; ssize_t n, elen; void *stbuf; if ((n = pread64(fd, ep, sizeof (*ep), 0)) != sizeof (*ep)) return (smb_open_error(shp, errp, n < 0 ? errno : ESMB_NOHDR)); - if (strncmp(ep->smbe_eanchor, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN)) + if (strncmp(ep->ep21.smbe_eanchor, SMB_ENTRY_EANCHOR, + SMB_ENTRY_EANCHORLEN) == 0) { + ep_type = SMBIOS_ENTRY_POINT_21; + elen = MIN(ep->ep21.smbe_elen, SMB_ENTRY_MAXLEN); + } else if (strncmp(ep->ep30.smbe_eanchor, SMB3_ENTRY_EANCHOR, + SMB3_ENTRY_EANCHORLEN) == 0) { + ep_type = SMBIOS_ENTRY_POINT_30; + elen = MIN(ep->ep30.smbe_elen, SMB_ENTRY_MAXLEN); + } else { return (smb_open_error(shp, errp, ESMB_HEADER)); - - elen = MIN(ep->smbe_elen, SMB_ENTRY_MAXLEN); + } if ((n = pread64(fd, ep, elen, 0)) != elen) return (smb_open_error(shp, errp, n < 0 ? errno : ESMB_NOHDR)); - if ((stbuf = smb_alloc(ep->smbe_stlen)) == NULL) + if (ep_type == SMBIOS_ENTRY_POINT_21) { + smbe_stlen = ep->ep21.smbe_stlen; + smbe_staddr = (off64_t)ep->ep21.smbe_staddr; + } else { + smbe_stlen = ep->ep30.smbe_stlen; + smbe_staddr = (off64_t)ep->ep30.smbe_staddr; + } + stbuf = smb_alloc(smbe_stlen); + + if (stbuf == NULL) return (smb_open_error(shp, errp, ESMB_NOMEM)); - if ((n = pread64(fd, stbuf, ep->smbe_stlen, - (off64_t)ep->smbe_staddr)) != ep->smbe_stlen) { - smb_free(stbuf, ep->smbe_stlen); + if ((n = pread64(fd, stbuf, smbe_stlen, smbe_staddr)) != smbe_stlen) { + smb_free(stbuf, smbe_stlen); return (smb_open_error(shp, errp, n < 0 ? errno : ESMB_NOSTAB)); } - shp = smbios_bufopen(ep, stbuf, ep->smbe_stlen, version, flags, errp); + shp = smbios_bufopen(ep, stbuf, smbe_stlen, version, flags, errp); if (shp != NULL) shp->sh_flags |= SMB_FL_BUFALLOC; else - smb_free(stbuf, ep->smbe_stlen); + smb_free(stbuf, smbe_stlen); return (shp); } @@ -90,21 +107,46 @@ static smbios_hdl_t * smb_biosopen(int fd, int version, int flags, int *errp) { smbios_entry_t *ep = alloca(SMB_ENTRY_MAXLEN); + smbios_entry_point_t ep_type; smbios_hdl_t *shp = NULL; - size_t pgsize, pgmask, pgoff; + size_t elen, pgsize, pgmask, pgoff; void *stbuf, *bios, *p, *q; - - bios = mmap(NULL, SMB_RANGE_LIMIT - SMB_RANGE_START + 1, - PROT_READ, MAP_SHARED, fd, (uint32_t)SMB_RANGE_START); + di_node_t root; + int64_t *val64; + uint32_t smbe_stlen; + off64_t smbe_staddr; + + bios = MAP_FAILED; + if ((root = di_init("/", DINFOPROP)) != DI_NODE_NIL) { + if (di_prop_lookup_int64(DDI_DEV_T_ANY, root, + "smbios-address", &val64) == 1) { + bios = mmap(NULL, SMB_RANGE_LIMIT - SMB_RANGE_START + 1, + PROT_READ, MAP_SHARED, fd, (off_t)*val64); + } + di_fini(root); + } + if (bios == MAP_FAILED) { + bios = mmap(NULL, SMB_RANGE_LIMIT - SMB_RANGE_START + 1, + PROT_READ, MAP_SHARED, fd, (uint32_t)SMB_RANGE_START); + } if (bios == MAP_FAILED) return (smb_open_error(shp, errp, ESMB_MAPDEV)); q = (void *)((uintptr_t)bios + SMB_RANGE_LIMIT - SMB_RANGE_START + 1); - for (p = bios; p < q; p = (void *)((uintptr_t)p + 16)) { - if (strncmp(p, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN) == 0) + for (p = bios; p < q; p = (void *)((uintptr_t)p + SMB_SCAN_STEP)) { + if (strncmp(p, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN) == 0) { + ep_type = SMBIOS_ENTRY_POINT_21; + elen = MIN(ep->ep21.smbe_elen, SMB_ENTRY_MAXLEN); + break; + } + if (strncmp(p, SMB3_ENTRY_EANCHOR, + SMB3_ENTRY_EANCHORLEN) == 0) { + ep_type = SMBIOS_ENTRY_POINT_30; + elen = MIN(ep->ep30.smbe_elen, SMB_ENTRY_MAXLEN); break; + } } if (p >= q) { @@ -113,33 +155,45 @@ smb_biosopen(int fd, int version, int flags, int *errp) } bcopy(p, ep, sizeof (smbios_entry_t)); - ep->smbe_elen = MIN(ep->smbe_elen, SMB_ENTRY_MAXLEN); - bcopy(p, ep, ep->smbe_elen); + bcopy(p, ep, elen); (void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1); + switch (ep_type) { + case SMBIOS_ENTRY_POINT_21: + smbe_stlen = ep->ep21.smbe_stlen; + smbe_staddr = ep->ep21.smbe_staddr; + break; + case SMBIOS_ENTRY_POINT_30: + smbe_stlen = ep->ep30.smbe_stlen; + smbe_staddr = ep->ep30.smbe_staddr; + break; + default: + return (smb_open_error(NULL, errp, ESMB_VERSION)); + } + pgsize = getpagesize(); pgmask = ~(pgsize - 1); - pgoff = ep->smbe_staddr & ~pgmask; + pgoff = smbe_staddr & ~pgmask; - bios = mmap(NULL, ep->smbe_stlen + pgoff, - PROT_READ, MAP_SHARED, fd, ep->smbe_staddr & pgmask); + bios = mmap(NULL, smbe_stlen + pgoff, + PROT_READ, MAP_SHARED, fd, smbe_staddr & pgmask); if (bios == MAP_FAILED) return (smb_open_error(shp, errp, ESMB_MAPDEV)); - if ((stbuf = smb_alloc(ep->smbe_stlen)) == NULL) { - (void) munmap(bios, ep->smbe_stlen + pgoff); + if ((stbuf = smb_alloc(smbe_stlen)) == NULL) { + (void) munmap(bios, smbe_stlen + pgoff); return (smb_open_error(shp, errp, ESMB_NOMEM)); } - bcopy((char *)bios + pgoff, stbuf, ep->smbe_stlen); - (void) munmap(bios, ep->smbe_stlen + pgoff); - shp = smbios_bufopen(ep, stbuf, ep->smbe_stlen, version, flags, errp); + bcopy((char *)bios + pgoff, stbuf, smbe_stlen); + (void) munmap(bios, smbe_stlen + pgoff); + shp = smbios_bufopen(ep, stbuf, smbe_stlen, version, flags, errp); if (shp != NULL) shp->sh_flags |= SMB_FL_BUFALLOC; else - smb_free(stbuf, ep->smbe_stlen); + smb_free(stbuf, smbe_stlen); return (shp); } @@ -200,7 +254,13 @@ smbios_write(smbios_hdl_t *shp, int fd) return (smb_set_errno(shp, EOVERFLOW)); bcopy(&shp->sh_ent, &ep, sizeof (ep)); - ep.smbe_staddr = (uint32_t)off; + if (shp->sh_ent_type == SMBIOS_ENTRY_POINT_21) + ep.ep21.smbe_staddr = (uint32_t)off; + else if (shp->sh_ent_type == SMBIOS_ENTRY_POINT_30) + ep.ep30.smbe_staddr = (uint64_t)off; + else + return (-1); + smbios_checksum(shp, &ep); if (smbios_xwrite(shp, fd, &ep, sizeof (ep)) == -1 || |
