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 | |
| parent | ec2c76eb1d5ecd7a4fccccefc1bc4aa7c1531606 (diff) | |
| download | illumos-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.c | 79 | ||||
| -rw-r--r-- | usr/src/common/smbios/smb_info.c | 10 | ||||
| -rw-r--r-- | usr/src/common/smbios/smb_open.c | 224 | ||||
| -rw-r--r-- | usr/src/lib/Makefile | 1 | ||||
| -rw-r--r-- | usr/src/lib/libsmbios/Makefile.com | 4 | ||||
| -rw-r--r-- | usr/src/lib/libsmbios/common/mapfile-vers | 1 | ||||
| -rw-r--r-- | usr/src/lib/libsmbios/common/smb_lib.c | 118 | ||||
| -rw-r--r-- | usr/src/uts/common/io/smbios.c | 10 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/smbios.h | 36 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/smbios_impl.h | 2 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/os/smb_dev.c | 51 |
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"); } |
