summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbios/common/smb_lib.c
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2019-02-11 19:51:43 +0000
committerRobert Mustacchi <rm@joyent.com>2019-07-09 13:33:41 +0000
commit1566bc3431383e39ac9bc7fb7f00feff9c06acda (patch)
treeb97efc285d2be15904b95595aaf0eda164270bfe /usr/src/lib/libsmbios/common/smb_lib.c
parent6f2b04a2ce785423fe988216ae694366499884b2 (diff)
downloadillumos-gate-1566bc3431383e39ac9bc7fb7f00feff9c06acda.tar.gz
10395 Add support for SMBIOS 3.2
10396 Want libjedec 10397 Check for SMBIOS table with higher version 10398 smbios slot version check is broken for smbios 3.x 10399 smbios CPU Cache extended size not correctly calculated 10400 smbios(1M) slot printing could be clearer Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Jordan Hendricks <jordan.hendricks@joyent.com> Reviewed by: C Fraire <cfraire@me.com> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libsmbios/common/smb_lib.c')
-rw-r--r--usr/src/lib/libsmbios/common/smb_lib.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/usr/src/lib/libsmbios/common/smb_lib.c b/usr/src/lib/libsmbios/common/smb_lib.c
index 6c1f375004..55ffee66cd 100644
--- a/usr/src/lib/libsmbios/common/smb_lib.c
+++ b/usr/src/lib/libsmbios/common/smb_lib.c
@@ -23,6 +23,7 @@
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#include <sys/types.h>
@@ -109,8 +110,9 @@ 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 elen, pgsize, pgmask, pgoff;
+ size_t pgsize, pgmask, pgoff;
void *stbuf, *bios, *p, *q;
+ void *smb2, *smb3;
di_node_t root;
int64_t *val64;
uint32_t smbe_stlen;
@@ -135,41 +137,75 @@ smb_biosopen(int fd, int version, int flags, int *errp)
q = (void *)((uintptr_t)bios + SMB_RANGE_LIMIT - SMB_RANGE_START + 1);
+ smb2 = smb3 = NULL;
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);
+ if (smb2 != NULL && smb3 != NULL)
break;
- }
- if (strncmp(p, SMB3_ENTRY_EANCHOR,
+ if (smb3 == NULL && 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;
+ smb3 = p;
+ } else if (smb2 == NULL && strncmp(p, SMB_ENTRY_EANCHOR,
+ SMB_ENTRY_EANCHORLEN) == 0) {
+ smb2 = p;
}
}
- if (p >= q) {
+ /*
+ * While they're not supposed to (as per the SMBIOS 3.2 spec), some
+ * vendors end up having a newer version in one of the two entry points
+ * than the other. If we found multiple tables then we will prefer the
+ * one with the newer version. If they're equivalent, we prefer the
+ * 32-bit version. If only one is present, then we use that.
+ */
+ if (smb2 != NULL && smb3 != NULL) {
+ uint8_t smb2maj, smb2min, smb3maj, smb3min;
+
+ bcopy(smb2, ep, sizeof (smbios_entry_t));
+ smb2maj = ep->ep21.smbe_major;
+ smb2min = ep->ep21.smbe_minor;
+ bcopy(smb3, ep, sizeof (smbios_entry_t));
+ smb3maj = ep->ep30.smbe_major;
+ smb3min = ep->ep30.smbe_minor;
+
+ if (smb3maj > smb2maj ||
+ (smb3maj == smb2maj && smb3min > smb2min)) {
+ ep_type = SMBIOS_ENTRY_POINT_30;
+ p = smb3;
+ } else {
+ ep_type = SMBIOS_ENTRY_POINT_21;
+ p = smb2;
+ }
+ } else if (smb3 != NULL) {
+ ep_type = SMBIOS_ENTRY_POINT_30;
+ p = smb3;
+ } else if (smb2 != NULL) {
+ ep_type = SMBIOS_ENTRY_POINT_21;
+ p = smb2;
+ } else {
(void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1);
return (smb_open_error(NULL, errp, ESMB_NOTFOUND));
}
bcopy(p, ep, sizeof (smbios_entry_t));
- bcopy(p, ep, elen);
- (void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1);
switch (ep_type) {
case SMBIOS_ENTRY_POINT_21:
+ ep->ep21.smbe_elen = MIN(ep->ep21.smbe_elen, SMB_ENTRY_MAXLEN);
+ bcopy(p, ep, ep->ep21.smbe_elen);
smbe_stlen = ep->ep21.smbe_stlen;
smbe_staddr = ep->ep21.smbe_staddr;
break;
case SMBIOS_ENTRY_POINT_30:
+ ep->ep30.smbe_elen = MIN(ep->ep30.smbe_elen, SMB_ENTRY_MAXLEN);
+ bcopy(p, ep, ep->ep30.smbe_elen);
smbe_stlen = ep->ep30.smbe_stlen;
smbe_staddr = ep->ep30.smbe_staddr;
break;
default:
+ (void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1);
return (smb_open_error(NULL, errp, ESMB_VERSION));
}
+ (void) munmap(bios, SMB_RANGE_LIMIT - SMB_RANGE_START + 1);
pgsize = getpagesize();
pgmask = ~(pgsize - 1);