summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbios/common/smb_lib.c
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2016-12-10 01:03:02 +0200
committerDan McDonald <danmcd@omniti.com>2017-02-22 21:02:01 -0500
commit1951a93366b3e52f7c49ec9b2dbfb21bccc56a3e (patch)
tree87f7268eab136503d4695aec8da01a58f88ef6a1 /usr/src/lib/libsmbios/common/smb_lib.c
parentec2c76eb1d5ecd7a4fccccefc1bc4aa7c1531606 (diff)
downloadillumos-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.c118
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 ||