summaryrefslogtreecommitdiff
path: root/usr/src
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
parentec2c76eb1d5ecd7a4fccccefc1bc4aa7c1531606 (diff)
downloadillumos-joyent-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')
-rw-r--r--usr/src/cmd/smbios/smbios.c79
-rw-r--r--usr/src/common/smbios/smb_info.c10
-rw-r--r--usr/src/common/smbios/smb_open.c224
-rw-r--r--usr/src/lib/Makefile1
-rw-r--r--usr/src/lib/libsmbios/Makefile.com4
-rw-r--r--usr/src/lib/libsmbios/common/mapfile-vers1
-rw-r--r--usr/src/lib/libsmbios/common/smb_lib.c118
-rw-r--r--usr/src/uts/common/io/smbios.c10
-rw-r--r--usr/src/uts/common/sys/smbios.h36
-rw-r--r--usr/src/uts/common/sys/smbios_impl.h2
-rw-r--r--usr/src/uts/i86pc/os/smb_dev.c51
11 files changed, 415 insertions, 121 deletions
diff --git a/usr/src/cmd/smbios/smbios.c b/usr/src/cmd/smbios/smbios.c
index a61db53331..1f055bc015 100644
--- a/usr/src/cmd/smbios/smbios.c
+++ b/usr/src/cmd/smbios/smbios.c
@@ -175,38 +175,69 @@ check_oem(smbios_hdl_t *shp)
}
static void
-print_smbios(smbios_hdl_t *shp, FILE *fp)
+print_smbios_21(smbios_21_entry_t *ep, FILE *fp)
{
- smbios_entry_t ep;
int i;
- smbios_info_smbios(shp, &ep);
-
oprintf(fp, "Entry Point Anchor Tag: %*.*s\n",
- (int)sizeof (ep.smbe_eanchor), (int)sizeof (ep.smbe_eanchor),
- ep.smbe_eanchor);
+ (int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor),
+ ep->smbe_eanchor);
- oprintf(fp, "Entry Point Checksum: 0x%x\n", ep.smbe_ecksum);
- oprintf(fp, "Entry Point Length: %u\n", ep.smbe_elen);
+ oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum);
+ oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen);
oprintf(fp, "Entry Point Version: %u.%u\n",
- ep.smbe_major, ep.smbe_minor);
- oprintf(fp, "Max Structure Size: %u\n", ep.smbe_maxssize);
- oprintf(fp, "Entry Point Revision: 0x%x\n", ep.smbe_revision);
+ ep->smbe_major, ep->smbe_minor);
+ oprintf(fp, "Max Structure Size: %u\n", ep->smbe_maxssize);
+ oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision);
oprintf(fp, "Entry Point Revision Data:");
- for (i = 0; i < sizeof (ep.smbe_format); i++)
- oprintf(fp, " 0x%02x", ep.smbe_format[i]);
+ for (i = 0; i < sizeof (ep->smbe_format); i++)
+ oprintf(fp, " 0x%02x", ep->smbe_format[i]);
oprintf(fp, "\n");
oprintf(fp, "Intermediate Anchor Tag: %*.*s\n",
- (int)sizeof (ep.smbe_ianchor), (int)sizeof (ep.smbe_ianchor),
- ep.smbe_ianchor);
-
- oprintf(fp, "Intermediate Checksum: 0x%x\n", ep.smbe_icksum);
- oprintf(fp, "Structure Table Length: %u\n", ep.smbe_stlen);
- oprintf(fp, "Structure Table Address: 0x%x\n", ep.smbe_staddr);
- oprintf(fp, "Structure Table Entries: %u\n", ep.smbe_stnum);
- oprintf(fp, "DMI BCD Revision: 0x%x\n", ep.smbe_bcdrev);
+ (int)sizeof (ep->smbe_ianchor), (int)sizeof (ep->smbe_ianchor),
+ ep->smbe_ianchor);
+
+ oprintf(fp, "Intermediate Checksum: 0x%x\n", ep->smbe_icksum);
+ oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen);
+ oprintf(fp, "Structure Table Address: 0x%x\n", ep->smbe_staddr);
+ oprintf(fp, "Structure Table Entries: %u\n", ep->smbe_stnum);
+ oprintf(fp, "DMI BCD Revision: 0x%x\n", ep->smbe_bcdrev);
+}
+
+static void
+print_smbios_30(smbios_30_entry_t *ep, FILE *fp)
+{
+ oprintf(fp, "Entry Point Anchor Tag: %*.*s\n",
+ (int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor),
+ ep->smbe_eanchor);
+
+ oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum);
+ oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen);
+ oprintf(fp, "SMBIOS Version: %u.%u\n",
+ ep->smbe_major, ep->smbe_minor);
+ oprintf(fp, "SMBIOS DocRev: 0x%x\n", ep->smbe_docrev);
+ oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision);
+
+ oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen);
+ oprintf(fp, "Structure Table Address: 0x%" PRIx64 "\n",
+ ep->smbe_staddr);
+}
+
+static void
+print_smbios(smbios_hdl_t *shp, FILE *fp)
+{
+ smbios_entry_t ep;
+
+ switch (smbios_info_smbios(shp, &ep)) {
+ case SMBIOS_ENTRY_POINT_21:
+ print_smbios_21(&ep.ep21, fp);
+ break;
+ case SMBIOS_ENTRY_POINT_30:
+ print_smbios_30(&ep.ep30, fp);
+ break;
+ }
}
static void
@@ -573,10 +604,10 @@ static void
print_slot(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_slot_t s;
- smbios_entry_t e;
+ smbios_version_t v;
(void) smbios_info_slot(shp, id, &s);
- (void) smbios_info_smbios(shp, &e);
+ smbios_info_smbios_version(shp, &v);
oprintf(fp, " Reference Designator: %s\n", s.smbl_name);
oprintf(fp, " Slot ID: 0x%x\n", s.smbl_id);
@@ -601,7 +632,7 @@ print_slot(smbios_hdl_t *shp, id_t id, FILE *fp)
s.smbl_ch2, sizeof (s.smbl_ch2) * NBBY,
smbios_slot_ch2_name, smbios_slot_ch2_desc);
- if (check_oem(shp) != 0 && (e.smbe_major < 2 || e.smbe_minor < 6))
+ if (check_oem(shp) != 0 && (v.smbv_major < 2 || v.smbv_minor < 6))
return;
oprintf(fp, " Segment Group: %u\n", s.smbl_sg);
diff --git a/usr/src/common/smbios/smb_info.c b/usr/src/common/smbios/smb_info.c
index ea8caaed97..69a89e6e13 100644
--- a/usr/src/common/smbios/smb_info.c
+++ b/usr/src/common/smbios/smb_info.c
@@ -223,10 +223,18 @@ smb_info_bcopy(const smb_header_t *hp, void *dst, size_t dstlen)
bcopy(hp, dst, dstlen);
}
-void
+smbios_entry_point_t
smbios_info_smbios(smbios_hdl_t *shp, smbios_entry_t *ep)
{
bcopy(&shp->sh_ent, ep, sizeof (smbios_entry_t));
+ return (shp->sh_ent_type);
+}
+
+void
+smbios_info_smbios_version(smbios_hdl_t *shp, smbios_version_t *v)
+{
+ v->smbv_major = SMB_MAJOR(shp->sh_smbvers);
+ v->smbv_minor = SMB_MINOR(shp->sh_smbvers);
}
#ifndef _KERNEL
diff --git a/usr/src/common/smbios/smb_open.c b/usr/src/common/smbios/smb_open.c
index 23d4a0aaca..36472b491d 100644
--- a/usr/src/common/smbios/smb_open.c
+++ b/usr/src/common/smbios/smb_open.c
@@ -72,63 +72,36 @@ smb_strip(smbios_hdl_t *shp)
}
}
-smbios_hdl_t *
-smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len,
- int version, int flags, int *errp)
+static int
+smbios_bufopen_21(smbios_hdl_t *shp, const smbios_21_entry_t *ep, size_t len,
+ int flags)
{
- smbios_hdl_t *shp = smb_zalloc(sizeof (smbios_hdl_t));
- const smb_header_t *hp, *nhp;
- const uchar_t *p, *q, *s;
- uint_t i, h;
-
- switch (version) {
- case SMB_VERSION_23:
- case SMB_VERSION_24:
- case SMB_VERSION_25:
- case SMB_VERSION_26:
- case SMB_VERSION_27:
- case SMB_VERSION_28:
- case SMB_VERSION_30:
- case SMB_VERSION_31:
- break;
- default:
- return (smb_open_error(shp, errp, ESMB_VERSION));
- }
-
- if (ep == NULL || buf == NULL || len == 0 || (flags & ~SMB_O_MASK))
- return (smb_open_error(shp, errp, ESMB_INVAL));
-
- if (shp == NULL)
- return (smb_open_error(shp, errp, ESMB_NOMEM));
-
- if (_smb_debug)
- shp->sh_flags |= SMB_FL_DEBUG;
-
if (strncmp(ep->smbe_eanchor, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN))
- return (smb_open_error(shp, errp, ESMB_HEADER));
+ return (ESMB_HEADER);
if (strncmp(ep->smbe_ianchor, SMB_ENTRY_IANCHOR, SMB_ENTRY_IANCHORLEN))
- return (smb_open_error(shp, errp, ESMB_HEADER));
+ return (ESMB_HEADER);
smb_dprintf(shp, "opening SMBIOS version %u.%u bcdrev 0x%x\n",
ep->smbe_major, ep->smbe_minor, ep->smbe_bcdrev);
if (!(flags & SMB_O_NOVERS)) {
if (ep->smbe_major > SMB_MAJOR(SMB_VERSION))
- return (smb_open_error(shp, errp, ESMB_NEW));
+ return (ESMB_NEW);
if (ep->smbe_major < SMB_MAJOR(SMB_VERSION_23) || (
ep->smbe_major == SMB_MAJOR(SMB_VERSION_23) &&
ep->smbe_minor < SMB_MINOR(SMB_VERSION_23)))
- return (smb_open_error(shp, errp, ESMB_OLD));
+ return (ESMB_OLD);
}
if (len < sizeof (smb_header_t) ||
ep->smbe_stlen < sizeof (smb_header_t) || len < ep->smbe_stlen)
- return (smb_open_error(shp, errp, ESMB_SHORT));
+ return (ESMB_SHORT);
if (!(flags & SMB_O_NOCKSUM)) {
uint8_t esum = 0, isum = 0;
+ const uchar_t *p, *q;
q = (uchar_t *)ep;
for (p = q; p < q + ep->smbe_elen; p++)
@@ -139,7 +112,61 @@ smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len,
if (esum != 0 || isum != 0) {
smb_dprintf(shp, "bad cksum: e=%x i=%x\n", esum, isum);
- return (smb_open_error(shp, errp, ESMB_CKSUM));
+ return (ESMB_CKSUM);
+ }
+ }
+
+ /*
+ * Copy the entry point into our handle. The underlying entry point
+ * may be larger than our structure definition, so reset smbe_elen
+ * to our internal size and recompute good checksums for our copy.
+ */
+ shp->sh_ent_type = SMBIOS_ENTRY_POINT_21;
+ bcopy(ep, &shp->sh_ent, sizeof (smbios_entry_t));
+ shp->sh_ent.ep21.smbe_elen = sizeof (smbios_entry_t);
+ smbios_checksum(shp, &shp->sh_ent);
+
+ shp->sh_ent_stnum = ep->smbe_stnum;
+ shp->sh_smbvers = SMB_MAJMIN(ep->smbe_major, ep->smbe_minor);
+ return (0);
+}
+
+static int
+smbios_bufopen_30(smbios_hdl_t *shp, const smbios_30_entry_t *ep, size_t len,
+ int flags)
+{
+ if (strncmp(ep->smbe_eanchor, SMB3_ENTRY_EANCHOR,
+ SMB3_ENTRY_EANCHORLEN))
+ return (ESMB_HEADER);
+
+ smb_dprintf(shp, "opening SMBIOS version %u.%u\n",
+ ep->smbe_major, ep->smbe_minor);
+
+ if (!(flags & SMB_O_NOVERS)) {
+ if (ep->smbe_major > SMB_MAJOR(SMB_VERSION))
+ return (ESMB_NEW);
+
+ if (ep->smbe_major < SMB_MAJOR(SMB_VERSION_23) || (
+ ep->smbe_major == SMB_MAJOR(SMB_VERSION_23) &&
+ ep->smbe_minor < SMB_MINOR(SMB_VERSION_23)))
+ return (ESMB_OLD);
+ }
+
+ if (len < sizeof (smb_header_t) ||
+ ep->smbe_stlen < sizeof (smb_header_t) || len < ep->smbe_stlen)
+ return (ESMB_SHORT);
+
+ if (!(flags & SMB_O_NOCKSUM)) {
+ uint8_t esum = 0;
+ const uchar_t *p, *q;
+ q = (uchar_t *)ep;
+
+ for (p = q; p < q + ep->smbe_elen; p++)
+ esum += *p;
+
+ if (esum != 0) {
+ smb_dprintf(shp, "bad cksum: e=%x\n", esum);
+ return (ESMB_CKSUM);
}
}
@@ -148,26 +175,107 @@ smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len,
* may be larger than our structure definition, so reset smbe_elen
* to our internal size and recompute good checksums for our copy.
*/
+ shp->sh_ent_type = SMBIOS_ENTRY_POINT_30;
bcopy(ep, &shp->sh_ent, sizeof (smbios_entry_t));
- shp->sh_ent.smbe_elen = sizeof (smbios_entry_t);
+ shp->sh_ent.ep30.smbe_elen = sizeof (smbios_entry_t);
smbios_checksum(shp, &shp->sh_ent);
+ shp->sh_smbvers = SMB_MAJMIN(ep->smbe_major, ep->smbe_minor);
+
+ return (0);
+}
+
+static uint_t
+smbios_table_nentries(const char *smbe_staddr, uint32_t smbe_stlen)
+{
+ uint_t i = 0;
+ char *dmi;
+ smb_header_t *hdr;
+
+ if (smbe_staddr == NULL)
+ return (i);
+
+ for (dmi = (char *)smbe_staddr; dmi < smbe_staddr + smbe_stlen; i++) {
+ hdr = (smb_header_t *)dmi;
+ dmi += hdr->smbh_len;
+ /*
+ * Search for the end of the string area.
+ */
+ while (dmi + 1 < smbe_staddr + smbe_stlen &&
+ dmi[0] != '\0' && dmi[1] != '\0') {
+ dmi++;
+ }
+ dmi += 2;
+ }
+ return (i);
+}
+
+smbios_hdl_t *
+smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len,
+ int version, int flags, int *errp)
+{
+ smbios_hdl_t *shp = smb_zalloc(sizeof (smbios_hdl_t));
+ const smb_header_t *hp, *nhp;
+ const uchar_t *p, *q, *s;
+ uint_t i, h;
+ int err;
+
+ switch (version) {
+ case SMB_VERSION_23:
+ case SMB_VERSION_24:
+ case SMB_VERSION_25:
+ case SMB_VERSION_26:
+ case SMB_VERSION_27:
+ case SMB_VERSION_28:
+ case SMB_VERSION_30:
+ case SMB_VERSION_31:
+ break;
+ default:
+ return (smb_open_error(shp, errp, ESMB_VERSION));
+ }
+
+ if (ep == NULL || buf == NULL || len == 0 || (flags & ~SMB_O_MASK))
+ return (smb_open_error(shp, errp, ESMB_INVAL));
+
+ if (shp == NULL)
+ return (smb_open_error(shp, errp, ESMB_NOMEM));
+
+ if (_smb_debug)
+ shp->sh_flags |= SMB_FL_DEBUG;
+
+ err = smbios_bufopen_21(shp, &ep->ep21, len, flags);
+ if (err != 0) {
+ err = smbios_bufopen_30(shp, &ep->ep30, len, flags);
+ if (err != 0)
+ return (smb_open_error(shp, errp, err));
+ shp->sh_ent_stnum =
+ smbios_table_nentries(buf, ep->ep30.smbe_stlen);
+ }
+
shp->sh_buf = buf;
shp->sh_buflen = len;
- shp->sh_structs = smb_alloc(sizeof (smb_struct_t) * ep->smbe_stnum);
+ shp->sh_structs = smb_alloc(sizeof (smb_struct_t) * shp->sh_ent_stnum);
shp->sh_nstructs = 0;
shp->sh_hashlen = _smb_hashlen;
shp->sh_hash = smb_zalloc(sizeof (smb_struct_t *) * shp->sh_hashlen);
shp->sh_libvers = version;
- shp->sh_smbvers = SMB_MAJMIN(ep->smbe_major, ep->smbe_minor);
if (shp->sh_structs == NULL || shp->sh_hash == NULL)
return (smb_open_error(shp, errp, ESMB_NOMEM));
hp = shp->sh_buf;
- q = (const uchar_t *)buf + MIN(ep->smbe_stlen, len);
+ switch (shp->sh_ent_type) {
+ case SMBIOS_ENTRY_POINT_21:
+ q = (const uchar_t *)buf + MIN(ep->ep21.smbe_stlen, len);
+ break;
+ case SMBIOS_ENTRY_POINT_30:
+ q = (const uchar_t *)buf + MIN(ep->ep30.smbe_stlen, len);
+ break;
+ default:
+ return (smb_open_error(shp, errp, ESMB_VERSION));
+ }
- for (i = 0; i < ep->smbe_stnum; i++, hp = nhp) {
+ for (i = 0; i < shp->sh_ent_stnum; i++, hp = nhp) {
smb_struct_t *stp = &shp->sh_structs[i];
uint_t n = 0;
@@ -239,7 +347,6 @@ smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len,
void
smbios_close(smbios_hdl_t *shp)
{
- const smbios_entry_t *ep = &shp->sh_ent;
uint_t i;
for (i = 0; i < shp->sh_nstructs; i++) {
@@ -247,7 +354,7 @@ smbios_close(smbios_hdl_t *shp)
sizeof (uint16_t) * shp->sh_structs[i].smbst_strtablen);
}
- smb_free(shp->sh_structs, sizeof (smb_struct_t) * ep->smbe_stnum);
+ smb_free(shp->sh_structs, sizeof (smb_struct_t) * shp->sh_ent_stnum);
smb_free(shp->sh_hash, sizeof (smb_struct_t *) * shp->sh_hashlen);
if (shp->sh_flags & SMB_FL_BUFALLOC)
@@ -268,17 +375,32 @@ smbios_checksum(smbios_hdl_t *shp, smbios_entry_t *ep)
uchar_t *p, *q = (uchar_t *)ep;
uint8_t esum = 0, isum = 0;
- ep->smbe_ecksum = ep->smbe_icksum = 0;
+ switch (shp->sh_ent_type) {
+ case SMBIOS_ENTRY_POINT_21:
+ ep->ep21.smbe_ecksum = ep->ep21.smbe_icksum = 0;
- for (p = (uchar_t *)ep->smbe_ianchor; p < q + sizeof (*ep); p++)
- isum += *p;
+ for (p = (uchar_t *)ep->ep21.smbe_ianchor;
+ p < q + sizeof (*ep); p++) {
+ isum += *p;
+ }
- ep->smbe_icksum = -isum;
+ ep->ep21.smbe_icksum = -isum;
- for (p = q; p < q + ep->smbe_elen; p++)
- esum += *p;
+ for (p = q; p < q + ep->ep21.smbe_elen; p++)
+ esum += *p;
- ep->smbe_ecksum = -esum;
+ ep->ep21.smbe_ecksum = -esum;
+ break;
+ case SMBIOS_ENTRY_POINT_30:
+ ep->ep30.smbe_ecksum = 0;
+ for (p = q; p < q + ep->ep30.smbe_elen; p++)
+ esum += *p;
+
+ ep->ep30.smbe_ecksum = -esum;
+ break;
+ default:
+ break;
+ }
}
const void *
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 3adc66eb0f..05de71f42d 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -650,6 +650,7 @@ libshell: libast libcmd libdll libsecdb
libsip: libmd5
libsldap: libldap5 libscf
libsmbfs: libkrb5 libsec libidmap pkcs11
+libsmbios: libdevinfo
libsrpt: libstmf
libstmf: libscf
libstmfproxy: libstmf libpthread
diff --git a/usr/src/lib/libsmbios/Makefile.com b/usr/src/lib/libsmbios/Makefile.com
index 176df10d8d..40345a3848 100644
--- a/usr/src/lib/libsmbios/Makefile.com
+++ b/usr/src/lib/libsmbios/Makefile.com
@@ -22,8 +22,6 @@
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
LIBRARY = libsmbios.a
VERS = .1
@@ -54,7 +52,7 @@ CLEANFILES += ../common/smb_tables.c
CPPFLAGS += -I../common -I$(COMMON_SRCDIR)
CFLAGS += $(CCVERBOSE)
-LDLIBS += -lc
+LDLIBS += -ldevinfo -lc
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/libsmbios/common/mapfile-vers b/usr/src/lib/libsmbios/common/mapfile-vers
index e78f799b02..be6cac125c 100644
--- a/usr/src/lib/libsmbios/common/mapfile-vers
+++ b/usr/src/lib/libsmbios/common/mapfile-vers
@@ -102,6 +102,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
smbios_info_extprocessor;
smbios_info_slot;
smbios_info_smbios;
+ smbios_info_smbios_version;
smbios_info_strtab;
smbios_info_system;
smbios_info_pciexrc;
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 ||
diff --git a/usr/src/uts/common/io/smbios.c b/usr/src/uts/common/io/smbios.c
index 3628d6aac9..92d28cc4fa 100644
--- a/usr/src/uts/common/io/smbios.c
+++ b/usr/src/uts/common/io/smbios.c
@@ -126,8 +126,14 @@ smb_uiomove(smb_clone_t *cp, uio_t *uio)
smbios_entry_t *ep = kmem_zalloc(cp->c_eplen, KM_SLEEP);
size_t eprlen = MIN(len, cp->c_eplen - off);
- smbios_info_smbios(cp->c_hdl, ep);
- ep->smbe_staddr = (uint32_t)cp->c_eplen;
+ switch (smbios_info_smbios(cp->c_hdl, ep)) {
+ case SMBIOS_ENTRY_POINT_21:
+ ep->ep21.smbe_staddr = (uint32_t)cp->c_eplen;
+ break;
+ case SMBIOS_ENTRY_POINT_30:
+ ep->ep30.smbe_staddr = (uint64_t)cp->c_eplen;
+ break;
+ }
smbios_checksum(cp->c_hdl, ep);
err = uiomove((char *)ep + off, eprlen, UIO_READ, uio);
diff --git a/usr/src/uts/common/sys/smbios.h b/usr/src/uts/common/sys/smbios.h
index 86780e68dd..9ae65c0ad5 100644
--- a/usr/src/uts/common/sys/smbios.h
+++ b/usr/src/uts/common/sys/smbios.h
@@ -46,13 +46,18 @@
extern "C" {
#endif
+typedef enum smbios_entry_point_type {
+ SMBIOS_ENTRY_POINT_21,
+ SMBIOS_ENTRY_POINT_30
+} smbios_entry_point_t;
+
/*
* SMBIOS Structure Table Entry Point. See DSP0134 5.2.1 for more information.
* The structure table entry point is located by searching for the anchor.
*/
#pragma pack(1)
-typedef struct smbios_entry {
+typedef struct smbios_21_entry {
char smbe_eanchor[4]; /* anchor tag (SMB_ENTRY_EANCHOR) */
uint8_t smbe_ecksum; /* checksum of entry point structure */
uint8_t smbe_elen; /* length in bytes of entry point */
@@ -67,12 +72,37 @@ typedef struct smbios_entry {
uint32_t smbe_staddr; /* physical addr of structure table */
uint16_t smbe_stnum; /* number of structure table entries */
uint8_t smbe_bcdrev; /* BCD value representing DMI version */
+} smbios_21_entry_t;
+
+/*
+ * The 64-bit SMBIOS 3.0 Entry Point. See DSP0134 5.2.2 for more information.
+ * The structure table entry point is located by searching for the anchor.
+ */
+
+typedef struct smbios_30_entry {
+ char smbe_eanchor[5]; /* anchor tag (SMB3_ENTRY_EANCHOR) */
+ uint8_t smbe_ecksum; /* checksum of entry point structure */
+ uint8_t smbe_elen; /* length in bytes of entry point */
+ uint8_t smbe_major; /* major version of the SMBIOS spec */
+ uint8_t smbe_minor; /* minor version of the SMBIOS spec */
+ uint8_t smbe_docrev; /* specification docrev */
+ uint8_t smbe_revision; /* entry point structure revision */
+ uint8_t smbe_reserved;
+ uint32_t smbe_stlen; /* length in bytes of structure table */
+ uint64_t smbe_staddr; /* physical addr of structure table */
+} smbios_30_entry_t;
+
+typedef union {
+ smbios_21_entry_t ep21;
+ smbios_30_entry_t ep30;
} smbios_entry_t;
#pragma pack()
#define SMB_ENTRY_EANCHOR "_SM_" /* structure table entry point anchor */
#define SMB_ENTRY_EANCHORLEN 4 /* length of entry point anchor */
+#define SMB3_ENTRY_EANCHOR "_SM3_" /* structure table entry point anchor */
+#define SMB3_ENTRY_EANCHORLEN 5 /* length of entry point anchor */
#define SMB_ENTRY_IANCHOR "_DMI_" /* intermediate anchor string */
#define SMB_ENTRY_IANCHORLEN 5 /* length of intermediate anchor */
#define SMB_ENTRY_MAXLEN 255 /* maximum length of entry point */
@@ -1443,7 +1473,9 @@ extern int smbios_lookup_id(smbios_hdl_t *, id_t, smbios_struct_t *);
extern int smbios_lookup_type(smbios_hdl_t *, uint_t, smbios_struct_t *);
extern int smbios_iter(smbios_hdl_t *, smbios_struct_f *, void *);
-extern void smbios_info_smbios(smbios_hdl_t *, smbios_entry_t *);
+extern smbios_entry_point_t smbios_info_smbios(smbios_hdl_t *,
+ smbios_entry_t *);
+extern void smbios_info_smbios_version(smbios_hdl_t *, smbios_version_t *);
extern int smbios_info_common(smbios_hdl_t *, id_t, smbios_info_t *);
extern int smbios_info_contains(smbios_hdl_t *, id_t, uint_t, id_t *);
extern id_t smbios_info_bios(smbios_hdl_t *, smbios_bios_t *);
diff --git a/usr/src/uts/common/sys/smbios_impl.h b/usr/src/uts/common/sys/smbios_impl.h
index 97d7250e22..404be225a3 100644
--- a/usr/src/uts/common/sys/smbios_impl.h
+++ b/usr/src/uts/common/sys/smbios_impl.h
@@ -458,7 +458,9 @@ typedef struct smb_struct {
} smb_struct_t;
struct smbios_hdl {
+ smbios_entry_point_t sh_ent_type; /* structure table entry point type */
smbios_entry_t sh_ent; /* structure table entry point */
+ uint_t sh_ent_stnum; /* number of structure table entries */
const void *sh_buf; /* structure table buffer */
size_t sh_buflen; /* size of structure table buffer */
smb_struct_t *sh_structs; /* array of structure descriptors */
diff --git a/usr/src/uts/i86pc/os/smb_dev.c b/usr/src/uts/i86pc/os/smb_dev.c
index ab55811e54..fffb45cb37 100644
--- a/usr/src/uts/i86pc/os/smb_dev.c
+++ b/usr/src/uts/i86pc/os/smb_dev.c
@@ -66,6 +66,9 @@ smbios_open(const char *file, int version, int flags, int *errp)
caddr_t stbuf, bios, p, q;
uint64_t startaddr, startoff = 0;
size_t bioslen;
+ uint_t smbe_stlen;
+ smbios_entry_point_t ep_type = SMBIOS_ENTRY_POINT_21;
+ uint8_t smbe_major, smbe_minor;
int err;
if (file != NULL || (flags & ~SMB_O_MASK))
@@ -102,6 +105,13 @@ smbios_open(const char *file, int version, int flags, int *errp)
p = bios + startoff;
q = bios + bioslen - startoff;
while (p < q) {
+#if !defined(__i386)
+ err = strncmp(p, SMB3_ENTRY_EANCHOR, SMB3_ENTRY_EANCHORLEN);
+ if (err == 0) {
+ ep_type = SMBIOS_ENTRY_POINT_30;
+ break;
+ }
+#endif
if (strncmp(p, SMB_ENTRY_EANCHOR, SMB_ENTRY_EANCHORLEN) == 0)
break;
p += SMB_SCAN_STEP;
@@ -114,31 +124,54 @@ smbios_open(const char *file, int version, int flags, int *errp)
ep = smb_alloc(SMB_ENTRY_MAXLEN);
bcopy(p, ep, sizeof (smbios_entry_t));
- ep->smbe_elen = MIN(ep->smbe_elen, SMB_ENTRY_MAXLEN);
- bcopy(p, ep, ep->smbe_elen);
+ if (ep_type == SMBIOS_ENTRY_POINT_21) {
+ ep->ep21.smbe_elen = MIN(ep->ep21.smbe_elen, SMB_ENTRY_MAXLEN);
+ bcopy(p, ep, ep->ep21.smbe_elen);
+ } else if (ep_type == SMBIOS_ENTRY_POINT_30) {
+ ep->ep30.smbe_elen = MIN(ep->ep30.smbe_elen, SMB_ENTRY_MAXLEN);
+ bcopy(p, ep, ep->ep30.smbe_elen);
+ }
psm_unmap_phys(bios, bioslen);
- bios = psm_map_phys(ep->smbe_staddr, ep->smbe_stlen, PSM_PROT_READ);
+ switch (ep_type) {
+ case SMBIOS_ENTRY_POINT_21:
+ smbe_major = ep->ep21.smbe_major;
+ smbe_minor = ep->ep21.smbe_minor;
+ smbe_stlen = ep->ep21.smbe_stlen;
+ bios = psm_map_phys(ep->ep21.smbe_staddr, smbe_stlen,
+ PSM_PROT_READ);
+ break;
+ case SMBIOS_ENTRY_POINT_30:
+ smbe_major = ep->ep30.smbe_major;
+ smbe_minor = ep->ep30.smbe_minor;
+ smbe_stlen = ep->ep30.smbe_stlen;
+ bios = psm_map_phys_new(ep->ep30.smbe_staddr, smbe_stlen,
+ PSM_PROT_READ);
+ break;
+ default:
+ smb_free(ep, SMB_ENTRY_MAXLEN);
+ return (smb_open_error(shp, errp, ESMB_VERSION));
+ }
if (bios == NULL) {
smb_free(ep, SMB_ENTRY_MAXLEN);
return (smb_open_error(shp, errp, ESMB_MAPDEV));
}
- stbuf = smb_alloc(ep->smbe_stlen);
- bcopy(bios, stbuf, ep->smbe_stlen);
- psm_unmap_phys(bios, ep->smbe_stlen);
- shp = smbios_bufopen(ep, stbuf, ep->smbe_stlen, version, flags, &err);
+ stbuf = smb_alloc(smbe_stlen);
+ bcopy(bios, stbuf, smbe_stlen);
+ psm_unmap_phys(bios, smbe_stlen);
+ shp = smbios_bufopen(ep, stbuf, smbe_stlen, version, flags, &err);
if (shp == NULL) {
- smb_free(stbuf, ep->smbe_stlen);
+ smb_free(stbuf, smbe_stlen);
smb_free(ep, SMB_ENTRY_MAXLEN);
return (smb_open_error(shp, errp, err));
}
if (ksmbios == NULL) {
cmn_err(CE_CONT, "?SMBIOS v%u.%u loaded (%u bytes)",
- ep->smbe_major, ep->smbe_minor, ep->smbe_stlen);
+ smbe_major, smbe_minor, smbe_stlen);
if (shp->sh_flags & SMB_FL_TRUNC)
cmn_err(CE_CONT, "?SMBIOS table is truncated");
}