summaryrefslogtreecommitdiff
path: root/usr/src/test/util-tests
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/test/util-tests')
-rw-r--r--usr/src/test/util-tests/cmd/utiltest.ksh2
-rw-r--r--usr/src/test/util-tests/runfiles/default.run7
-rw-r--r--usr/src/test/util-tests/tests/Makefile2
-rw-r--r--usr/src/test/util-tests/tests/sleep/Makefile47
-rw-r--r--usr/src/test/util-tests/tests/sleep/sleep.awk22
-rw-r--r--usr/src/test/util-tests/tests/sleep/sleep.d40
-rw-r--r--usr/src/test/util-tests/tests/sleep/sleeptest.ksh180
-rw-r--r--usr/src/test/util-tests/tests/smbios/Makefile20
-rw-r--r--usr/src/test/util-tests/tests/smbios/smbios.c376
-rw-r--r--usr/src/test/util-tests/tests/smbios/smbios_test.h110
-rw-r--r--usr/src/test/util-tests/tests/smbios/smbios_test_errors.c28
-rw-r--r--usr/src/test/util-tests/tests/smbios/smbios_test_memdevice.c355
-rw-r--r--usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c585
-rw-r--r--usr/src/test/util-tests/tests/smbios/smbios_test_slot.c188
14 files changed, 1754 insertions, 208 deletions
diff --git a/usr/src/test/util-tests/cmd/utiltest.ksh b/usr/src/test/util-tests/cmd/utiltest.ksh
index 231415fba8..e701aeb854 100644
--- a/usr/src/test/util-tests/cmd/utiltest.ksh
+++ b/usr/src/test/util-tests/cmd/utiltest.ksh
@@ -17,6 +17,8 @@
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
#
+export PATH="${PATH}:/opt/onbld/bin/$(uname -p)"
+export LC_ALL="C"
export MY_TESTS="/opt/util-tests"
runner="/opt/test-runner/bin/run"
diff --git a/usr/src/test/util-tests/runfiles/default.run b/usr/src/test/util-tests/runfiles/default.run
index 3170859794..628982c82d 100644
--- a/usr/src/test/util-tests/runfiles/default.run
+++ b/usr/src/test/util-tests/runfiles/default.run
@@ -35,6 +35,13 @@ outputdir = /var/tmp/test_results
[/opt/util-tests/tests/libjedec_test]
[/opt/util-tests/tests/smbios]
+#
+# The sleep tests require destructive DTrace. Therefore they must be run
+# as root.
+#
+[/opt/util-tests/tests/sleep/sleeptest]
+user = root
+
[/opt/util-tests/tests/xargs_test]
[/opt/util-tests/tests/mergeq/mqt]
diff --git a/usr/src/test/util-tests/tests/Makefile b/usr/src/test/util-tests/tests/Makefile
index 6fab960d55..a39762c2fc 100644
--- a/usr/src/test/util-tests/tests/Makefile
+++ b/usr/src/test/util-tests/tests/Makefile
@@ -19,7 +19,7 @@
#
SUBDIRS = date dis dladm iconv libnvpair_json libsff printf xargs grep_xpg4
-SUBDIRS += demangle mergeq workq chown ctf smbios libjedec awk make
+SUBDIRS += demangle mergeq workq chown ctf smbios libjedec awk make sleep
SUBDIRS += bunyan
include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/util-tests/tests/sleep/Makefile b/usr/src/test/util-tests/tests/sleep/Makefile
new file mode 100644
index 0000000000..3cf11e1f40
--- /dev/null
+++ b/usr/src/test/util-tests/tests/sleep/Makefile
@@ -0,0 +1,47 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Robert Mustacchi
+#
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests/tests/sleep
+PROG = sleeptest
+DATAFILES = sleep.d sleep.awk
+
+ROOTPROG = $(PROG:%=$(ROOTOPTPKG)/%)
+ROOTDATA = $(DATAFILES:%=$(ROOTOPTPKG)/%)
+
+$(ROOTDATA) := FILEMODE = 0444
+
+all:
+
+install: $(ROOTPROG) $(ROOTDATA)
+
+lint:
+
+clobber: clean
+
+clean:
+
+$(CMDS): $(TESTDIR)
+
+$(ROOTOPTPKG):
+ $(INS.dir)
+
+$(ROOTOPTPKG)/%: %.ksh $(ROOTOPTPKG)
+ $(INS.rename)
+
+$(ROOTOPTPKG)/%: % $(ROOTOPTPKG)
+ $(INS.file)
diff --git a/usr/src/test/util-tests/tests/sleep/sleep.awk b/usr/src/test/util-tests/tests/sleep/sleep.awk
new file mode 100644
index 0000000000..856773c815
--- /dev/null
+++ b/usr/src/test/util-tests/tests/sleep/sleep.awk
@@ -0,0 +1,22 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Robert Mustacchi
+#
+
+{
+ if ($1 == "slp") {
+ if ($2 >= min && $2 <= min * factor) {
+ exit 42
+ }
+ }
+}
diff --git a/usr/src/test/util-tests/tests/sleep/sleep.d b/usr/src/test/util-tests/tests/sleep/sleep.d
new file mode 100644
index 0000000000..23bfcea65c
--- /dev/null
+++ b/usr/src/test/util-tests/tests/sleep/sleep.d
@@ -0,0 +1,40 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Robert Mustacchi
+ */
+
+/*
+ * This is a companion DTrace script that is used by the sleep test. It
+ * checks if the executed program asks to sleep for the right amount of
+ * time and then exits in a way to indicate this. At the same time, it
+ * always uses the SIGALRM feature of sleep(1) to make sure that sleep
+ * doesn't continue executing (and also to make sure that the feature
+ * works).
+ *
+ * We expect the number of seconds in $1 and the number of nanoseconds
+ * in $2. This script should be invoked as dtrace -s sleep.d -c
+ * '/usr/bin/sleep <waittime>' <seconds> <nanoseconds>.
+ */
+pid$target::nanosleep:entry
+/args[0]->tv_sec == $1 && args[0]->tv_nsec == $2/
+{
+ raise(SIGALRM);
+ exit(0);
+}
+
+pid$target::nanosleep:entry
+{
+ print(*args[0]);
+ raise(SIGALRM);
+ exit(1);
+}
diff --git a/usr/src/test/util-tests/tests/sleep/sleeptest.ksh b/usr/src/test/util-tests/tests/sleep/sleeptest.ksh
new file mode 100644
index 0000000000..3cc107acf5
--- /dev/null
+++ b/usr/src/test/util-tests/tests/sleep/sleeptest.ksh
@@ -0,0 +1,180 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Robert Mustacchi
+#
+
+#
+# Basic tests of sleep(1). sleep is a little hard to test, especially
+# for longer running cases. Therefore to test it, we basically take
+# advantage of our knowledge of how it is implemented. We see that it
+# properly is sleeping for the right amount of time by looking at the
+# call to nanosleep in libc and make sure that the structures time is
+# what we expect.
+#
+
+unalias -a
+set -o pipefail
+
+#
+# Set the locale for the start of the test to be C.UTF-8 to make sure
+# that we have a good starting point and correct fractional
+# interpretation.
+#
+export LC_ALL=C.UTF-8
+
+sleep_arg0="$(basename $0)"
+sleep_prog=/usr/bin/sleep
+sleep_dir="$(dirname $0)"
+sleep_dscript=$sleep_dir/sleep.d
+sleep_awk=$sleep_dir/sleep.awk
+sleep_exit=0
+
+#
+# This is the factor by which we're going to basically say that the slp
+# microstate has to complete within. Because the system will usually
+# have a bit of additional latency, we will usually be greater than that
+# as well. This determines how much we should actually do that by.
+#
+sleep_factor=1.5
+
+warn()
+{
+ typeset msg="$*"
+ [[ -z "$msg" ]] && msg="failed"
+ echo "TEST FAILED: $sleep_arg0: $msg" >&2
+}
+
+sleep_bound()
+{
+ typeset min=$1
+ typeset test="sleep $min: bounding"
+
+ ptime -m $sleep_prog $min 2>&1 | nawk -f $sleep_awk min=$min \
+ factor=$sleep_factor
+ if [[ $? -ne 42 ]]; then
+ warn "$test"
+ sleep_exit=1
+ else
+ printf "TEST PASSED: %s\n" "$test"
+ fi
+}
+
+sleep_one()
+{
+ typeset arg=$1
+ typeset secs=$2
+ typeset nsecs=$3
+ typeset test="sleep $arg: $secs secs $nsecs ns"
+
+ if ! dtrace -qws $sleep_dscript -c "$sleep_prog $arg" $secs $nsecs; then
+ warn "$test"
+ sleep_exit=1
+ else
+ printf "TEST PASSED: %s\n" "$test"
+ fi
+}
+
+sleep_err()
+{
+ typeset test="negative test: sleep $*"
+
+ if $sleep_prog $* 2>/dev/null; then
+ warn "$test"
+ sleep_exit=1
+ else
+ printf "TEST PASSED: %s\n" "$test"
+ fi
+}
+
+if [[ -n $SLEEP ]]; then
+ sleep_prog=$SLEEP
+fi
+
+#
+# First test basic integer values. Both in base 10 and hex.
+#
+sleep_one 1 1 0
+sleep_one 23 23 0
+sleep_one 0xff 0xff 0
+sleep_one 123456789 123456789 0
+sleep_one 1e8 100000000 0
+
+#
+# Fractional values.
+#
+sleep_one 2.5 2 500000000
+sleep_one 0.9 0 900000000
+sleep_one 34.0051 34 5100000
+sleep_one 0x654.100 0x654 62500000
+
+#
+# Large values that are basically the same as infinity. The current
+# implementation will do a sleep in groups of INT32_MAX at a time. So
+# make sure our large values are the same.
+#
+sleep_one Inf 0x7fffffff 0
+sleep_one +Inf 0x7fffffff 0
+sleep_one 1e100 0x7fffffff 0
+sleep_one 0x123456789abc 0x7fffffff 0
+
+#
+# That all of our suffixes for time increments work and make sense.
+#
+sleep_one 1s 1 0
+sleep_one 1m 60 0
+sleep_one 1h 3600 0
+sleep_one 1d 86400 0
+sleep_one 1w 604800 0
+sleep_one 1y 31536000 0
+
+sleep_one 3.5s 3 500000000
+sleep_one 3.6d 311040 0
+sleep_one 2.001y 63103536 0
+
+#
+# Now we need to go through and use ptime -m to get the slp time for
+# things and make sure it is always greater than what we asked for and
+# less than a bound.
+#
+sleep_bound 0.01
+sleep_bound 0.1
+sleep_bound 0.25
+sleep_bound 0.5
+sleep_bound 0.75
+
+#
+# The next set of tests are negative tests that make sure that sleep
+# does not correctly execute in these cases.
+#
+sleep_err \"\"
+sleep_err 1 2 3
+sleep_err 1@23
+sleep_err 0,56
+sleep_err "hello"
+sleep_err s
+sleep_err 1z
+sleep_err -- -0.3
+
+#
+# Test a locale that uses a ',' character (de_DE.UTF-8 is one) as the
+# decimal point to make sure that sleep correctly is using LC_NUMERIC.
+#
+export LANG=de_DE.UTF-8
+sleep_err 21.45
+sleep_one 2,5 2 500000000
+sleep_one 34,0051 34 5100000
+sleep_one 3,6d 311040 0
+export LANG=C.UTF-8
+
+exit $sleep_exit
diff --git a/usr/src/test/util-tests/tests/smbios/Makefile b/usr/src/test/util-tests/tests/smbios/Makefile
index 5016e81a6d..e783a337dc 100644
--- a/usr/src/test/util-tests/tests/smbios/Makefile
+++ b/usr/src/test/util-tests/tests/smbios/Makefile
@@ -18,10 +18,13 @@ include $(SRC)/Makefile.master
ROOTOPTPKG = $(ROOT)/opt/util-tests
TESTDIR = $(ROOTOPTPKG)/tests/
+OBJS = smbios.o \
+ smbios_test_errors.o \
+ smbios_test_memdevice.o \
+ smbios_test_pinfo.o \
+ smbios_test_slot.o
PROGS = smbios
-LINTS = $(PROGS:%=%.ln)
-
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/test/Makefile.com
@@ -33,16 +36,15 @@ CFLAGS += -_gcc=-Wall -_gcc=-Wextra -_gcc=-Wno-unknown-pragmas
all: $(PROGS)
-install: all $(CMDS) $(OUTFILES)
+install: all $(CMDS)
clobber: clean
- -$(RM) $(PROGS) $(LINTS)
-
-lint:
+ -$(RM) $(PROGS)
clean:
+ -$(RM) $(OBJS)
-$(CMDS): $(TESTDIR) $(PROG)
+$(CMDS): $(TESTDIR) $(PROGS)
$(TESTDIR):
$(INS.dir)
@@ -50,6 +52,6 @@ $(TESTDIR):
$(TESTDIR)/%: %
$(INS.file)
-%: %.c
- $(LINK.c) -o $@ $< $(LDLIBS)
+$(PROGS): $(OBJS)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
diff --git a/usr/src/test/util-tests/tests/smbios/smbios.c b/usr/src/test/util-tests/tests/smbios/smbios.c
index 96b887c3cc..364cb9344f 100644
--- a/usr/src/test/util-tests/tests/smbios/smbios.c
+++ b/usr/src/test/util-tests/tests/smbios/smbios.c
@@ -19,33 +19,8 @@
* This should be evolved into a much fuller test suite.
*/
-#include <smbios.h>
#include <umem.h>
-#include <stdint.h>
-#include <endian.h>
-#include <stdio.h>
-#include <err.h>
-
-#include <sys/smbios.h>
-#include <sys/smbios_impl.h>
-
-static const char *smbios_test_name = "The One Slot";
-
-/*
- * Number of bytes we allocate at a given time for an SMBIOS table.
- */
-#define SMBIOS_TEST_ALLOC_SIZE 1024
-
-typedef struct smbios_test_table {
- smbios_entry_point_t stt_type;
- void *stt_data;
- size_t stt_buflen;
- size_t stt_offset;
- uint_t stt_nents;
- uint_t stt_version;
- uint_t stt_nextid;
- smbios_entry_t stt_entry;
-} smbios_test_table_t;
+#include "smbios_test.h"
const char *
_umem_debug_init(void)
@@ -59,7 +34,7 @@ _umem_logging_init(void)
return ("fail,contents");
}
-static smbios_test_table_t *
+smbios_test_table_t *
smbios_test_table_init(smbios_entry_point_t type, uint_t version)
{
smbios_test_table_t *table;
@@ -122,21 +97,21 @@ smbios_test_table_append_common(smbios_test_table_t *table, const void *buf,
return (start);
}
-static void
+void
smbios_test_table_append_raw(smbios_test_table_t *table, const void *buf,
size_t len)
{
(void) smbios_test_table_append_common(table, buf, len);
}
-static void
+void
smbios_test_table_append_string(smbios_test_table_t *table, const char *str)
{
size_t len = strlen(str) + 1;
(void) smbios_test_table_append_common(table, str, len);
}
-static uint16_t
+uint16_t
smbios_test_table_append(smbios_test_table_t *table, const void *buf,
size_t len)
{
@@ -153,6 +128,25 @@ smbios_test_table_append(smbios_test_table_t *table, const void *buf,
return (id);
}
+void
+smbios_test_table_append_eot(smbios_test_table_t *table)
+{
+ smb_header_t eot;
+ uint8_t endstring = 0;
+
+ bzero(&eot, sizeof (eot));
+ eot.smbh_type = SMB_TYPE_EOT;
+ eot.smbh_len = 4;
+ (void) smbios_test_table_append(table, &eot, sizeof (eot));
+ (void) smbios_test_table_append_raw(table, &endstring,
+ sizeof (endstring));
+ smbios_test_table_append_raw(table, &endstring,
+ sizeof (endstring));
+ smbios_test_table_append_raw(table, &endstring,
+ sizeof (endstring));
+
+}
+
static uint8_t
smbios_test_table_checksum(const uint8_t *buf, size_t len)
{
@@ -217,195 +211,181 @@ smbios_test_table_fini(smbios_test_table_t *table)
umem_free(table, sizeof (smbios_test_table_t));
}
-static void
-smbios_test_mktable(smbios_test_table_t *table)
+static const smbios_test_t smbios_tests[] = {
+ {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION_32,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_slot_mktable,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_slot_verify,
+ .st_desc = "slot tests"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = 0xffff,
+ .st_mktable = smbios_test_badvers_mktable,
+ .st_desc = "bad library version"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION_32,
+ .st_libvers = SMB_VERSION_32,
+ .st_mktable = smbios_test_memdevice_mktable_32,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_memdevice_verify_32,
+ .st_desc = "memory device 3.2 / 3.2"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION_32,
+ .st_libvers = SMB_VERSION_33,
+ .st_mktable = smbios_test_memdevice_mktable_32,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_memdevice_verify_32_33,
+ .st_desc = "memory device 3.2 / 3.3"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION_33,
+ .st_libvers = SMB_VERSION_33,
+ .st_mktable = smbios_test_memdevice_mktable_33,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_memdevice_verify_33,
+ .st_desc = "memory device 3.3"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION_33,
+ .st_libvers = SMB_VERSION_33,
+ .st_mktable = smbios_test_memdevice_mktable_33ext,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_memdevice_verify_33ext,
+ .st_desc = "memory device 3.3"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_pinfo_mktable_amd64,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_amd64,
+ .st_desc = "processor additional information - amd64"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_pinfo_mktable_riscv,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_riscv,
+ .st_desc = "processor additional information - riscv"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_pinfo_mktable_invlen1,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_invlen1,
+ .st_desc = "processor additional information - bad table length 1"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_pinfo_mktable_invlen2,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_invlen2,
+ .st_desc = "processor additional information - bad table length 2"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_pinfo_mktable_invlen3,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_invlen3,
+ .st_desc = "processor additional information - bad table length 3"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_pinfo_mktable_invlen4,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_invlen4,
+ .st_desc = "processor additional information - bad table length 4"
+ }, {
+ .st_entry = SMBIOS_ENTRY_POINT_30,
+ .st_tvers = SMB_VERSION,
+ .st_libvers = SMB_VERSION,
+ .st_mktable = smbios_test_memdevice_mktable_32,
+ .st_canopen = B_TRUE,
+ .st_verify = smbios_test_pinfo_verify_badtype,
+ .st_desc = "processor additional information - bad type"
+ },
+
+};
+
+static boolean_t
+smbios_test_run_one(const smbios_test_t *test)
{
- smb_slot_t slot;
- smb_slot_peer_t peers[2];
- smb_header_t eot;
- uint8_t endstring = 0;
-
- slot.smbsl_hdr.smbh_type = SMB_TYPE_SLOT;
- slot.smbsl_hdr.smbh_len = sizeof (smb_slot_t) + sizeof (peers);
-
- slot.smbsl_name = 1;
- slot.smbsl_type = SMB_SLT_PCIE3G16;
- slot.smbsl_width = SMB_SLW_16X;
- slot.smbsl_length = SMB_SLL_SHORT;
- slot.smbsl_id = htole16(1);
- slot.smbsl_ch1 = SMB_SLCH1_33V;
- slot.smbsl_ch2 = SMB_SLCH2_PME;
- slot.smbsl_sg = htole16(1);
- slot.smbsl_bus = 0x42;
- slot.smbsl_df = 0x23;
- slot.smbsl_dbw = SMB_SLW_16X;
- slot.smbsl_npeers = 2;
- peers[0].smbspb_group_no = htole16(1);
- peers[0].smbspb_bus = 0x42;
- peers[0].smbspb_df = 0x42;
- peers[0].smbspb_width = SMB_SLW_8X;
-
- peers[1].smbspb_group_no = htole16(1);
- peers[1].smbspb_bus = 0x23;
- peers[1].smbspb_df = 0x31;
- peers[1].smbspb_width = SMB_SLW_8X;
-
- (void) smbios_test_table_append(table, &slot, sizeof (slot));
- (void) smbios_test_table_append_raw(table, peers, sizeof (peers));
- (void) smbios_test_table_append_string(table, smbios_test_name);
- (void) smbios_test_table_append_raw(table, &endstring,
- sizeof (endstring));
-
- bzero(&eot, sizeof (eot));
- eot.smbh_type = SMB_TYPE_EOT;
- eot.smbh_len = 4;
- (void) smbios_test_table_append(table, &eot, sizeof (eot));
- (void) smbios_test_table_append_raw(table, &endstring,
- sizeof (endstring));
- (void) smbios_test_table_append_raw(table, &endstring,
- sizeof (endstring));
-}
-
-static void
-smbios_test_verify_table(smbios_hdl_t *hdl)
-{
- smbios_struct_t sp;
- smbios_slot_t slot;
- uint_t npeers;
- smbios_slot_peer_t *peers;
- uint_t errs = 0;
-
- if (smbios_lookup_type(hdl, SMB_TYPE_SLOT, &sp) == -1) {
- errx(EXIT_FAILURE, "failed to lookup SMBIOS slot: %s",
- smbios_errmsg(smbios_errno(hdl)));
- }
-
- if (smbios_info_slot(hdl, sp.smbstr_id, &slot) != 0) {
- errx(EXIT_FAILURE, "failed to get SMBIOS slot info: %s",
- smbios_errmsg(smbios_errno(hdl)));
- }
-
- /*
- * Verify everything we'd expect about the slot.
- */
- if (strcmp(slot.smbl_name, smbios_test_name) != 0) {
- warnx("slot name mismatch, expected %s, found %s",
- smbios_test_name, slot.smbl_name);
- errs++;
- }
-
- if (slot.smbl_type != SMB_SLT_PCIE3G16) {
- warnx("incorrect slot type, found %u", slot.smbl_type);
- errs++;
- }
-
- if (slot.smbl_width != SMB_SLW_16X) {
- warnx("incorrect slot width, found %u", slot.smbl_width);
- errs++;
- }
-
- if (slot.smbl_length != SMB_SLL_SHORT) {
- warnx("incorrect slot length, found %u", slot.smbl_length);
- errs++;
- }
-
- if (slot.smbl_dbw != SMB_SLW_16X) {
- warnx("incorrect slot data bus width, found %u", slot.smbl_dbw);
- errs++;
- }
-
- if (slot.smbl_npeers != 2) {
- warnx("incorrect number of slot peers, found %u",
- slot.smbl_npeers);
- errs++;
- }
-
- if (smbios_info_slot_peers(hdl, sp.smbstr_id, &npeers, &peers) != 0) {
- errx(EXIT_FAILURE, "failed to get SMBIOS peer info: %s",
- smbios_errmsg(smbios_errno(hdl)));
- }
-
- if (npeers != 2) {
- errx(EXIT_FAILURE, "got wrong number of slot peers: %u\n",
- npeers);
- }
-
- if (peers[0].smblp_group != 1) {
- warnx("incorrect group for peer 0: %u", peers[0].smblp_group);
- errs++;
- }
-
- if (peers[0].smblp_data_width != SMB_SLW_8X) {
- warnx("incorrect data width for peer 0: %u",
- peers[0].smblp_data_width);
- errs++;
- }
+ smbios_test_table_t *table = NULL;
+ smbios_hdl_t *hdl = NULL;
+ void *buf;
+ size_t len;
+ smbios_entry_t *entry;
+ int err = 0;
+ boolean_t ret = B_FALSE;
- if (peers[0].smblp_device != (0x42 >> 3)) {
- warnx("incorrect PCI device for peer 0: %u",
- peers[0].smblp_device);
- errs++;
+ table = smbios_test_table_init(test->st_entry, test->st_tvers);
+ if (!test->st_mktable(table)) {
+ goto out;
}
- if (peers[0].smblp_function != (0x42 & 0x7)) {
- warnx("incorrect PCI function for peer 0: %u",
- peers[0].smblp_function);
- errs++;
+ smbios_test_table_snapshot(table, &entry, &buf, &len);
+ hdl = smbios_bufopen(entry, buf, len, test->st_libvers, SMB_FL_DEBUG,
+ &err);
+ if (test->st_canopen) {
+ if (hdl == NULL) {
+ warnx("failed to create table for test %s: %s",
+ test->st_desc, smbios_errmsg(err));
+ goto out;
+ }
+ } else {
+ if (hdl != NULL) {
+ warnx("accidentally created table for test %s, "
+ "expected failure", test->st_desc);
+ } else {
+ ret = B_TRUE;
+ }
+ goto out;
}
- if (peers[1].smblp_group != 1) {
- warnx("incorrect group for peer 1: %u", peers[1].smblp_group);
- errs++;
+ if (test->st_verify(hdl)) {
+ ret = B_TRUE;
}
- if (peers[1].smblp_device != (0x31 >> 3)) {
- warnx("incorrect PCI device for peer 1: %u",
- peers[1].smblp_device);
- errs++;
+out:
+ if (hdl != NULL) {
+ smbios_close(hdl);
}
- if (peers[1].smblp_function != (0x31 & 0x7)) {
- warnx("incorrect PCI function for peer 1: %u",
- peers[1].smblp_function);
- errs++;
+ if (table != NULL) {
+ smbios_test_table_fini(table);
}
- if (peers[1].smblp_data_width != SMB_SLW_8X) {
- warnx("incorrect data width for peer 1: %u",
- peers[1].smblp_data_width);
- errs++;
+ if (ret) {
+ (void) printf("TEST PASSED: %s\n", test->st_desc);
+ } else {
+ (void) printf("TEST FAILED: %s\n", test->st_desc);
}
- smbios_info_slot_peers_free(hdl, npeers, peers);
-
- if (errs > 0) {
- errx(EXIT_FAILURE, "encountered fatal errors");
- }
+ return (ret);
}
int
main(void)
{
- void *buf;
- size_t len;
- smbios_test_table_t *table;
- smbios_entry_t *entry;
- smbios_hdl_t *hdl;
int err = 0;
+ size_t i;
- table = smbios_test_table_init(SMBIOS_ENTRY_POINT_30, SMB_VERSION_32);
- smbios_test_mktable(table);
- smbios_test_table_snapshot(table, &entry, &buf, &len);
-
- hdl = smbios_bufopen(entry, buf, len, SMB_VERSION_32, SMB_FL_DEBUG,
- &err);
- if (hdl == NULL) {
- errx(EXIT_FAILURE, "failed to create fake smbios table: %s",
- smbios_errmsg(err));
+ for (i = 0; i < ARRAY_SIZE(smbios_tests); i++) {
+ if (!smbios_test_run_one(&smbios_tests[i])) {
+ err = 1;
+ }
}
- smbios_test_verify_table(hdl);
- smbios_close(hdl);
- smbios_test_table_fini(table);
- return (0);
+ return (err);
}
diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test.h b/usr/src/test/util-tests/tests/smbios/smbios_test.h
new file mode 100644
index 0000000000..62baed7813
--- /dev/null
+++ b/usr/src/test/util-tests/tests/smbios/smbios_test.h
@@ -0,0 +1,110 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Robert Mustacchi
+ */
+
+#ifndef _SMBIOS_TEST_H
+#define _SMBIOS_TEST_H
+
+/*
+ * Test framework for SMBIOS tests
+ */
+
+#include <smbios.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+#include <err.h>
+#include <stdint.h>
+#include <endian.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Number of bytes we allocate at a given time for an SMBIOS table.
+ */
+#define SMBIOS_TEST_ALLOC_SIZE 1024
+
+typedef struct smbios_test_table {
+ smbios_entry_point_t stt_type;
+ void *stt_data;
+ size_t stt_buflen;
+ size_t stt_offset;
+ uint_t stt_nents;
+ uint_t stt_version;
+ uint_t stt_nextid;
+ smbios_entry_t stt_entry;
+} smbios_test_table_t;
+
+/*
+ * General Interfaces used to construct tables.
+ */
+extern smbios_test_table_t *smbios_test_table_init(smbios_entry_point_t,
+ uint_t);
+extern void smbios_test_table_append_raw(smbios_test_table_t *, const void *,
+ size_t);
+extern void smbios_test_table_append_string(smbios_test_table_t *,
+ const char *);
+extern uint16_t smbios_test_table_append(smbios_test_table_t *, const void *,
+ size_t);
+extern void smbios_test_table_append_eot(smbios_test_table_t *);
+
+typedef boolean_t (*smbios_test_mktable_f)(smbios_test_table_t *);
+typedef boolean_t (*smbios_test_verify_f)(smbios_hdl_t *);
+
+typedef struct smbios_test {
+ int st_entry;
+ int st_tvers;
+ int st_libvers;
+ smbios_test_mktable_f st_mktable;
+ boolean_t st_canopen;
+ smbios_test_verify_f st_verify;
+ const char *st_desc;
+} smbios_test_t;
+
+/*
+ * Test functions
+ */
+extern boolean_t smbios_test_slot_mktable(smbios_test_table_t *);
+extern boolean_t smbios_test_slot_verify(smbios_hdl_t *);
+extern boolean_t smbios_test_badvers_mktable(smbios_test_table_t *);
+
+extern boolean_t smbios_test_memdevice_mktable_32(smbios_test_table_t *);
+extern boolean_t smbios_test_memdevice_mktable_33(smbios_test_table_t *);
+extern boolean_t smbios_test_memdevice_mktable_33ext(smbios_test_table_t *);
+extern boolean_t smbios_test_memdevice_verify_32(smbios_hdl_t *);
+extern boolean_t smbios_test_memdevice_verify_32_33(smbios_hdl_t *);
+extern boolean_t smbios_test_memdevice_verify_33(smbios_hdl_t *);
+extern boolean_t smbios_test_memdevice_verify_33ext(smbios_hdl_t *);
+
+extern boolean_t smbios_test_pinfo_mktable_amd64(smbios_test_table_t *);
+extern boolean_t smbios_test_pinfo_verify_amd64(smbios_hdl_t *);
+extern boolean_t smbios_test_pinfo_mktable_riscv(smbios_test_table_t *);
+extern boolean_t smbios_test_pinfo_verify_riscv(smbios_hdl_t *);
+extern boolean_t smbios_test_pinfo_mktable_invlen1(smbios_test_table_t *);
+extern boolean_t smbios_test_pinfo_mktable_invlen2(smbios_test_table_t *);
+extern boolean_t smbios_test_pinfo_mktable_invlen3(smbios_test_table_t *);
+extern boolean_t smbios_test_pinfo_mktable_invlen4(smbios_test_table_t *);
+extern boolean_t smbios_test_pinfo_verify_invlen1(smbios_hdl_t *);
+extern boolean_t smbios_test_pinfo_verify_invlen2(smbios_hdl_t *);
+extern boolean_t smbios_test_pinfo_verify_invlen3(smbios_hdl_t *);
+extern boolean_t smbios_test_pinfo_verify_invlen4(smbios_hdl_t *);
+extern boolean_t smbios_test_pinfo_verify_badtype(smbios_hdl_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMBIOS_TEST_H */
diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_errors.c b/usr/src/test/util-tests/tests/smbios/smbios_test_errors.c
new file mode 100644
index 0000000000..0bca13c7bb
--- /dev/null
+++ b/usr/src/test/util-tests/tests/smbios/smbios_test_errors.c
@@ -0,0 +1,28 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Robert Mustacchi
+ */
+
+/*
+ * Collection of functions to be used with tests that will cause a handle to
+ * fail to open.
+ */
+
+#include "smbios_test.h"
+
+boolean_t
+smbios_test_badvers_mktable(smbios_test_table_t *table)
+{
+ smbios_test_table_append_eot(table);
+ return (B_TRUE);
+}
diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_memdevice.c b/usr/src/test/util-tests/tests/smbios/smbios_test_memdevice.c
new file mode 100644
index 0000000000..7e6e3b02d4
--- /dev/null
+++ b/usr/src/test/util-tests/tests/smbios/smbios_test_memdevice.c
@@ -0,0 +1,355 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Robert Mustacchi
+ */
+
+/*
+ * Basic testing of the SMBIOS 3.3 memory device extensions. We test these in a
+ * few different ways:
+ *
+ * 1. Using a 3.2 table with a 3.2 library to make sure we get the old fields.
+ * We also need to verify that we don't clobber memory in this case.
+ * 2. Using a 3.2 table with a 3.3 library to make sure we get the new fields.
+ * populated with the corresponding 3.2 values.
+ * 3. Using a 3.3 table with only the old values as valid.
+ * 4. Using a 3.3 table with both the old and new values as valid.
+ * memory.
+ */
+
+#include <stdlib.h>
+#include "smbios_test.h"
+
+static uint16_t smbios_memdevice_speed = 0xdeed;
+static uint16_t smbios_memdevice_clkspeed = 0xf00f;
+static uint32_t smbios_memdevice_extspeed = 0xbaddeed;
+static uint32_t smbios_memdevice_extclkspeed = 0xbadf00f;
+
+/*
+ * Fill in the basics of a single memory device. Callers need to fill in the
+ * speed, extspeed, clkspeed, and extclkspeed members.
+ */
+static void
+smbios_test_memdevice_fill(smb_memdevice_t *mem)
+{
+ mem->smbmdev_hdr.smbh_type = SMB_TYPE_MEMDEVICE;
+ mem->smbmdev_hdr.smbh_len = sizeof (smb_memdevice_t);
+
+ mem->smbmdev_array = 0xffff;
+ mem->smbmdev_error = htole16(0xfffe);
+ mem->smbmdev_twidth = 64;
+ mem->smbmdev_dwidth = 64;
+ mem->smbmdev_size = 0x7fff;
+ mem->smbmdev_form = SMB_MDFF_FBDIMM;
+ mem->smbmdev_set = 0;
+ mem->smbmdev_dloc = 0;
+ mem->smbmdev_bloc = 0;
+ mem->smbmdev_type = SMB_MDT_DDR4;
+ mem->smbmdev_manufacturer = 0;
+ mem->smbmdev_asset = 0;
+ mem->smbmdev_part = 0;
+ mem->smbmdev_attrs = 2;
+ mem->smbmdev_extsize = htole32(0x123456);
+ mem->smbmdev_minvolt = 0;
+ mem->smbmdev_maxvolt = 0;
+ mem->smbmdev_confvolt = 0;
+ mem->smbmdev_memtech = 0;
+ mem->smbmdev_opmode = 1 << 3;
+ mem->smbmdev_fwver = 0;
+ mem->smbmdev_modulemfgid = 0;
+ mem->smbmdev_moduleprodid = 0;
+ mem->smbmdev_memsysmfgid = 0;
+ mem->smbmdev_memsysprodid = 0;
+ mem->smbmdev_nvsize = htole64(UINT64_MAX);
+ mem->smbmdev_volsize = htole64(UINT64_MAX);
+ mem->smbmdev_cachesize = htole64(UINT64_MAX);
+ mem->smbmdev_logicalsize = htole64(UINT64_MAX);
+}
+
+boolean_t
+smbios_test_memdevice_mktable_32(smbios_test_table_t *table)
+{
+ smb_memdevice_t mem;
+ size_t len = 0x54;
+
+ smbios_test_memdevice_fill(&mem);
+ mem.smbmdev_speed = htole16(smbios_memdevice_speed);
+ mem.smbmdev_clkspeed = htole16(smbios_memdevice_clkspeed);
+ mem.smbmdev_extspeed = htole32(0);
+ mem.smbmdev_extclkspeed = htole32(0);
+
+ /*
+ * Because we're emulating an SMBIOS 3.2 table, we have to set it to the
+ * specification's defined size for that revision - 0x54.
+ */
+ mem.smbmdev_hdr.smbh_len = len;
+ (void) smbios_test_table_append(table, &mem, len);
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+boolean_t
+smbios_test_memdevice_mktable_33(smbios_test_table_t *table)
+{
+ smb_memdevice_t mem;
+
+ smbios_test_memdevice_fill(&mem);
+ mem.smbmdev_speed = htole16(smbios_memdevice_speed);
+ mem.smbmdev_clkspeed = htole16(smbios_memdevice_clkspeed);
+ mem.smbmdev_extspeed = htole32(0);
+ mem.smbmdev_extclkspeed = htole32(0);
+
+ (void) smbios_test_table_append(table, &mem, sizeof (mem));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+boolean_t
+smbios_test_memdevice_mktable_33ext(smbios_test_table_t *table)
+{
+ smb_memdevice_t mem;
+
+ smbios_test_memdevice_fill(&mem);
+ mem.smbmdev_speed = htole16(0xffff);
+ mem.smbmdev_clkspeed = htole16(0xffff);
+ mem.smbmdev_extspeed = htole32(smbios_memdevice_extspeed);
+ mem.smbmdev_extclkspeed = htole32(smbios_memdevice_extclkspeed);
+
+ (void) smbios_test_table_append(table, &mem, sizeof (mem));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+static boolean_t
+smbios_test_memdevice_verify_common(smbios_memdevice_t *mem)
+{
+ boolean_t ret = B_TRUE;
+
+ if (mem->smbmd_dwidth != 64) {
+ warnx("found wrong dwidth: %u", mem->smbmd_dwidth);
+ ret = B_FALSE;
+ }
+
+ if (mem->smbmd_twidth != 64) {
+ warnx("found wrong twidth: %u", mem->smbmd_twidth);
+ ret = B_FALSE;
+ }
+
+ if (mem->smbmd_form != SMB_MDFF_FBDIMM) {
+ warnx("found wrong form: %u", mem->smbmd_form);
+ ret = B_FALSE;
+ }
+
+ if (mem->smbmd_size != 0x123456ULL * 1024 * 1024) {
+ warnx("found wrong size: %u", mem->smbmd_size);
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+boolean_t
+smbios_test_memdevice_verify_32(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_memdevice_t mem;
+ boolean_t ret = B_TRUE;
+ uint64_t rval;
+
+ /*
+ * We expect that the SMBIOS 3.2 memory device values should not be
+ * touched here. As such we set them to a random value to verify and
+ * verify that it hasn't been set.
+ */
+ arc4random_buf(&rval, sizeof (rval));
+ mem.smbmd_extspeed = rval;
+ mem.smbmd_extclkspeed = rval;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) {
+ warnx("failed to lookup SMBIOS memory device: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) {
+ warnx("failed to get SMBIOS memory device info: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (mem.smbmd_extspeed != rval || mem.smbmd_extclkspeed != rval) {
+ warnx("smbios_memdevice_t had its memory cloberred!");
+ return (B_FALSE);
+ }
+
+ if (!smbios_test_memdevice_verify_common(&mem)) {
+ return (B_FALSE);
+ }
+
+ if (mem.smbmd_speed != smbios_memdevice_speed) {
+ warnx("found wrong device speed: %u", mem.smbmd_speed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_clkspeed != smbios_memdevice_clkspeed) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed);
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+/*
+ * This is a variant of smbios_test_memdevice_verify_32(), but instead of using
+ * an SMBIOS 3.2 library, we use an SMBIOS 3.3 handle. This means that we expect
+ * the extended values to be populated with the base values.
+ */
+boolean_t
+smbios_test_memdevice_verify_32_33(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_memdevice_t mem;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) {
+ warnx("failed to lookup SMBIOS memory device: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) {
+ warnx("failed to get SMBIOS memory device info: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (!smbios_test_memdevice_verify_common(&mem)) {
+ return (B_FALSE);
+ }
+
+ if (mem.smbmd_speed != smbios_memdevice_speed) {
+ warnx("found wrong device speed: %u", mem.smbmd_speed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_clkspeed != smbios_memdevice_clkspeed) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_extspeed != smbios_memdevice_speed) {
+ warnx("found wrong device speed: %u", mem.smbmd_extspeed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_extclkspeed != smbios_memdevice_clkspeed) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_extclkspeed);
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+boolean_t
+smbios_test_memdevice_verify_33(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_memdevice_t mem;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) {
+ warnx("failed to lookup SMBIOS memory device: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) {
+ warnx("failed to get SMBIOS memory device info: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (!smbios_test_memdevice_verify_common(&mem)) {
+ return (B_FALSE);
+ }
+
+ if (mem.smbmd_speed != smbios_memdevice_speed) {
+ warnx("found wrong device speed: %u", mem.smbmd_speed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_clkspeed != smbios_memdevice_clkspeed) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_extspeed != smbios_memdevice_speed) {
+ warnx("found wrong device speed: %u", mem.smbmd_extspeed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_extclkspeed != smbios_memdevice_clkspeed) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_extclkspeed);
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+boolean_t
+smbios_test_memdevice_verify_33ext(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_memdevice_t mem;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) {
+ warnx("failed to lookup SMBIOS memory device: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) {
+ warnx("failed to get SMBIOS memory device info: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (!smbios_test_memdevice_verify_common(&mem)) {
+ return (B_FALSE);
+ }
+
+ if (mem.smbmd_speed != 0xffff) {
+ warnx("found wrong device speed: %u", mem.smbmd_speed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_clkspeed != 0xffff) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_extspeed != smbios_memdevice_extspeed) {
+ warnx("found wrong device speed: %u", mem.smbmd_extspeed);
+ ret = B_FALSE;
+ }
+
+ if (mem.smbmd_extclkspeed != smbios_memdevice_extclkspeed) {
+ warnx("found wrong device clkspeed: %u", mem.smbmd_extclkspeed);
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c b/usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c
new file mode 100644
index 0000000000..178de212ae
--- /dev/null
+++ b/usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c
@@ -0,0 +1,585 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Robert Mustacchi
+ */
+
+/*
+ * Tests for SMBIOS type 44 - SMB_TYPE_PROCESSOR_INFO and the per-CPU type
+ * follow ups.
+ */
+
+#include "smbios_test.h"
+
+static uint16_t smbios_pinfo_phandle = 0x1;
+static uint64_t smbios_pinfo_isa = 0x4010d;
+static uint8_t smbios_pinfo_hartid[16];
+static uint8_t smbios_pinfo_vendid[16];
+static uint8_t smbios_pinfo_archid[16];
+static uint8_t smbios_pinfo_machid[16];
+static uint8_t smbios_pinfo_metdi[16];
+static uint8_t smbios_pinfo_mitdi[16];
+
+boolean_t
+smbios_test_pinfo_mktable_amd64(smbios_test_table_t *table)
+{
+ smb_processor_info_t pi;
+
+ pi.smbpai_hdr.smbh_type = SMB_TYPE_PROCESSOR_INFO;
+ pi.smbpai_hdr.smbh_len = sizeof (smb_processor_info_t);
+ pi.smbpai_proc = htole16(smbios_pinfo_phandle);
+ pi.smbpai_len = 0;
+ pi.smbpai_type = SMB_PROCINFO_T_AMD64;
+
+ (void) smbios_test_table_append(table, &pi, sizeof (pi));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+boolean_t
+smbios_test_pinfo_verify_amd64(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_processor_info_t pinfo;
+ smbios_processor_info_riscv_t rv;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_PROCESSOR_INFO, &sp) == -1) {
+ warnx("failed to lookup SMBIOS processor additional "
+ "information: %s", smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_processor_info(hdl, sp.smbstr_id, &pinfo) != 0) {
+
+ warnx("failed to get SMBIOS processor additional "
+ "information: %s", smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (pinfo.smbpi_processor != smbios_pinfo_phandle) {
+ warnx("processor handle incorrect, found 0x%x",
+ pinfo.smbpi_processor);
+ ret = B_FALSE;
+ }
+
+ if (pinfo.smbpi_ptype != SMB_PROCINFO_T_AMD64) {
+ warnx("processor type incorrect, found 0x%x",
+ pinfo.smbpi_ptype);
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_processor_info_type_desc(pinfo.smbpi_ptype),
+ "X64 (x86-64, Intel64, AMD64, EMT64)") != 0) {
+ warnx("processor type incorrect, found %s",
+ smbios_processor_info_type_desc(pinfo.smbpi_ptype));
+ ret = B_FALSE;
+ }
+
+ if (smbios_info_processor_riscv(hdl, sp.smbstr_id, &rv) != -1) {
+ warnx("accidentally got riscv info on non-riscv handle");
+ ret = B_FALSE;
+ }
+
+ if (smbios_errno(hdl) != ESMB_TYPE) {
+ warnx("encountered wrong errno for RISC-V info, found: 0x%x",
+ smbios_errno(hdl));
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+boolean_t
+smbios_test_pinfo_mktable_riscv(smbios_test_table_t *table)
+{
+ smb_processor_info_t pi;
+ smb_processor_info_riscv_t rv;
+
+ pi.smbpai_hdr.smbh_type = SMB_TYPE_PROCESSOR_INFO;
+ pi.smbpai_hdr.smbh_len = sizeof (smb_processor_info_t) +
+ sizeof (smb_processor_info_riscv_t);
+ pi.smbpai_proc = htole16(smbios_pinfo_phandle);
+ pi.smbpai_len = sizeof (smb_processor_info_riscv_t);
+ pi.smbpai_type = SMB_PROCINFO_T_RV64;
+
+ (void) smbios_test_table_append(table, &pi, sizeof (pi));
+
+ rv.smbpairv_vers = 1;
+ rv.smbpairv_len = sizeof (smb_processor_info_riscv_t);
+ arc4random_buf(smbios_pinfo_hartid, sizeof (smbios_pinfo_hartid));
+ bcopy(smbios_pinfo_hartid, rv.smbpairv_hartid,
+ sizeof (smbios_pinfo_hartid));
+ rv.smbpairv_boot = 1;
+ arc4random_buf(smbios_pinfo_vendid, sizeof (smbios_pinfo_vendid));
+ bcopy(smbios_pinfo_vendid, rv.smbpairv_vendid,
+ sizeof (smbios_pinfo_vendid));
+ arc4random_buf(smbios_pinfo_archid, sizeof (smbios_pinfo_archid));
+ bcopy(smbios_pinfo_archid, rv.smbpairv_archid,
+ sizeof (smbios_pinfo_archid));
+ arc4random_buf(smbios_pinfo_machid, sizeof (smbios_pinfo_machid));
+ bcopy(smbios_pinfo_machid, rv.smbpairv_machid,
+ sizeof (smbios_pinfo_machid));
+ rv.smbpairv_boot = 1;
+ rv.smbpairv_isa = htole64(smbios_pinfo_isa);
+ rv.smbpairv_privlvl = SMB_RV_PRIV_M | SMB_RV_PRIV_S;
+ arc4random_buf(smbios_pinfo_metdi, sizeof (smbios_pinfo_metdi));
+ bcopy(smbios_pinfo_metdi, rv.smbpairv_metdi,
+ sizeof (smbios_pinfo_metdi));
+ arc4random_buf(smbios_pinfo_mitdi, sizeof (smbios_pinfo_mitdi));
+ bcopy(smbios_pinfo_mitdi, rv.smbpairv_mitdi,
+ sizeof (smbios_pinfo_mitdi));
+ rv.smbpairv_xlen = SMB_RV_WIDTH_64B;
+ rv.smbpairv_mxlen = SMB_RV_WIDTH_64B;
+ rv.smbpairv_sxlen = SMB_RV_WIDTH_128B;
+ rv.smbpairv_uxlen = SMB_RV_WIDTH_32B;
+
+ smbios_test_table_append_raw(table, &rv, sizeof (rv));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+static void
+smbios_test_pinfo_id_mismatch(uint8_t *act, uint8_t *exp)
+{
+ uint_t i;
+ (void) fprintf(stderr, "found: ");
+ for (i = 0; i < 16; i++) {
+ (void) fprintf(stderr, " %02x", act[i]);
+ }
+ (void) fprintf(stderr, "\nexpected: ");
+ for (i = 0; i < 16; i++) {
+ (void) fprintf(stderr, " %02x", exp[i]);
+ }
+ (void) fprintf(stderr, "\n");
+}
+
+boolean_t
+smbios_test_pinfo_verify_riscv(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_processor_info_t pinfo;
+ smbios_processor_info_riscv_t rv;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_PROCESSOR_INFO, &sp) == -1) {
+ warnx("failed to lookup SMBIOS processor additional "
+ "information: %s", smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_processor_info(hdl, sp.smbstr_id, &pinfo) != 0) {
+ warnx("failed to get SMBIOS processor additional "
+ "information: %s", smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (pinfo.smbpi_processor != smbios_pinfo_phandle) {
+ warnx("processor handle incorrect, found 0x%x",
+ pinfo.smbpi_processor);
+ ret = B_FALSE;
+ }
+
+ if (pinfo.smbpi_ptype != SMB_PROCINFO_T_RV64) {
+ warnx("processor type incorrect, found 0x%x",
+ pinfo.smbpi_ptype);
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_processor_info_type_desc(pinfo.smbpi_ptype),
+ "64-bit RISC-V (RV64)") != 0) {
+ warnx("processor type incorrect, found %s",
+ smbios_processor_info_type_desc(pinfo.smbpi_ptype));
+ ret = B_FALSE;
+ }
+
+ if (smbios_info_processor_riscv(hdl, sp.smbstr_id, &rv) != 0) {
+
+ warnx("failed to get SMBIOS processor additional "
+ "information for RISC-V: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (bcmp(rv.smbpirv_hartid, smbios_pinfo_hartid,
+ sizeof (smbios_pinfo_hartid)) != 0) {
+ warnx("RISC-V hart id's don't match");
+ smbios_test_pinfo_id_mismatch(rv.smbpirv_hartid,
+ smbios_pinfo_hartid);
+ ret = B_FALSE;
+ }
+
+ if (bcmp(rv.smbpirv_vendid, smbios_pinfo_vendid,
+ sizeof (smbios_pinfo_vendid)) != 0) {
+ warnx("RISC-V vend id's don't match");
+ smbios_test_pinfo_id_mismatch(rv.smbpirv_vendid,
+ smbios_pinfo_vendid);
+ ret = B_FALSE;
+ }
+
+ if (bcmp(rv.smbpirv_archid, smbios_pinfo_archid,
+ sizeof (smbios_pinfo_archid)) != 0) {
+ warnx("RISC-V arch id's don't match");
+ smbios_test_pinfo_id_mismatch(rv.smbpirv_archid,
+ smbios_pinfo_archid);
+ ret = B_FALSE;
+ }
+
+ if (bcmp(rv.smbpirv_machid, smbios_pinfo_machid,
+ sizeof (smbios_pinfo_machid)) != 0) {
+ warnx("RISC-V mach id's don't match");
+ smbios_test_pinfo_id_mismatch(rv.smbpirv_machid,
+ smbios_pinfo_machid);
+ ret = B_FALSE;
+ }
+
+ if (bcmp(rv.smbpirv_metdi, smbios_pinfo_metdi,
+ sizeof (smbios_pinfo_metdi)) != 0) {
+ warnx("RISC-V METDI don't match");
+ smbios_test_pinfo_id_mismatch(rv.smbpirv_metdi,
+ smbios_pinfo_metdi);
+ ret = B_FALSE;
+ }
+
+ if (bcmp(rv.smbpirv_mitdi, smbios_pinfo_mitdi,
+ sizeof (smbios_pinfo_mitdi)) != 0) {
+ warnx("RISC-V METDI don't match");
+ smbios_test_pinfo_id_mismatch(rv.smbpirv_mitdi,
+ smbios_pinfo_mitdi);
+ ret = B_FALSE;
+ }
+
+ if (rv.smbpirv_isa != smbios_pinfo_isa) {
+ warnx("RISC-V ISA mismatch");
+ ret = B_FALSE;
+ }
+
+ if (rv.smbpirv_privlvl != (SMB_RV_PRIV_M | SMB_RV_PRIV_S)) {
+ warnx("RISC-V privilege level mismatch, found: 0x%x",
+ rv.smbpirv_privlvl);
+ ret = B_FALSE;
+ }
+
+ if (rv.smbpirv_xlen != SMB_RV_WIDTH_64B) {
+ warnx("RISC-V xlen mismatch, found: 0x%x", rv.smbpirv_xlen);
+ ret = B_FALSE;
+ }
+
+ if (rv.smbpirv_mxlen != SMB_RV_WIDTH_64B) {
+ warnx("RISC-V mxlen mismatch, found: 0x%x", rv.smbpirv_mxlen);
+ ret = B_FALSE;
+ }
+
+ if (rv.smbpirv_sxlen != SMB_RV_WIDTH_128B) {
+ warnx("RISC-V sxlen mismatch, found: 0x%x", rv.smbpirv_sxlen);
+ ret = B_FALSE;
+ }
+
+ if (rv.smbpirv_uxlen != SMB_RV_WIDTH_32B) {
+ warnx("RISC-V uxlen mismatch, found: 0x%x", rv.smbpirv_uxlen);
+ ret = B_FALSE;
+ }
+
+ /*
+ * Finally, use this to spot check several of the different RISC-V
+ * strings.
+ */
+ if (strcmp(smbios_riscv_priv_desc(SMB_RV_PRIV_M), "Machine Mode") !=
+ 0) {
+ warnx("SMB_RV_PRIV_M string desc mismatch, found %s",
+ smbios_riscv_priv_desc(SMB_RV_PRIV_M));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_priv_name(SMB_RV_PRIV_U), "SMB_RV_PRIV_U") !=
+ 0) {
+ warnx("SMB_RV_PRIV_U string name mismatch, found %s",
+ smbios_riscv_priv_name(SMB_RV_PRIV_U));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_width_desc(SMB_RV_WIDTH_64B), "64-bit") !=
+ 0) {
+ warnx("SMB_RV_WIDTH_64B string desc mismatch, found %s",
+ smbios_riscv_width_desc(SMB_RV_WIDTH_64B));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_width_desc(SMB_RV_WIDTH_128B), "128-bit") !=
+ 0) {
+ warnx("SMB_RV_WIDTH_128B string desc mismatch, found %s",
+ smbios_riscv_width_desc(SMB_RV_WIDTH_128B));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_isa_desc(SMB_RV_ISA_A), "Atomic") != 0) {
+ warnx("SMB_RV_ISA_A string desc mismatch, found %s",
+ smbios_riscv_isa_desc(SMB_RV_ISA_A));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_isa_desc(SMB_RV_ISA_C), "Compressed") != 0) {
+ warnx("SMB_RV_ISA_Q string desc mismatch, found %s",
+ smbios_riscv_isa_desc(SMB_RV_ISA_C));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_isa_desc(SMB_RV_ISA_Q),
+ "Quad-precision floating-poit") != 0) {
+ warnx("SMB_RV_ISA_Q string desc mismatch, found %s",
+ smbios_riscv_isa_desc(SMB_RV_ISA_Q));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_isa_name(SMB_RV_ISA_A), "SMB_RV_ISA_A") != 0) {
+ warnx("SMB_RV_ISA_A string name mismatch, found %s",
+ smbios_riscv_isa_name(SMB_RV_ISA_A));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_isa_name(SMB_RV_ISA_C), "SMB_RV_ISA_C") != 0) {
+ warnx("SMB_RV_ISA_Q string name mismatch, found %s",
+ smbios_riscv_isa_name(SMB_RV_ISA_C));
+ ret = B_FALSE;
+ }
+
+ if (strcmp(smbios_riscv_isa_name(SMB_RV_ISA_Q), "SMB_RV_ISA_Q") != 0) {
+ warnx("SMB_RV_ISA_Q string name mismatch, found %s",
+ smbios_riscv_isa_name(SMB_RV_ISA_Q));
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+/*
+ * This shows having an invalid table length.
+ */
+boolean_t
+smbios_test_pinfo_mktable_invlen1(smbios_test_table_t *table)
+{
+ smb_processor_info_t pi;
+
+ pi.smbpai_hdr.smbh_type = SMB_TYPE_PROCESSOR_INFO;
+ pi.smbpai_hdr.smbh_len = 2;
+ pi.smbpai_proc = htole16(smbios_pinfo_phandle);
+ pi.smbpai_len = 0;
+ pi.smbpai_type = SMB_PROCINFO_T_AMD64;
+
+ (void) smbios_test_table_append(table, &pi, sizeof (pi));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+/*
+ * This sets the internal length of the additional processor information data to
+ * go beyond the length of the basic structure.
+ */
+boolean_t
+smbios_test_pinfo_mktable_invlen2(smbios_test_table_t *table)
+{
+ smb_processor_info_t pi;
+ smb_processor_info_riscv_t rv;
+
+ pi.smbpai_hdr.smbh_type = SMB_TYPE_PROCESSOR_INFO;
+ pi.smbpai_hdr.smbh_len = sizeof (smb_processor_info_t);
+ pi.smbpai_proc = htole16(smbios_pinfo_phandle);
+ pi.smbpai_len = sizeof (smb_processor_info_riscv_t);
+ pi.smbpai_type = SMB_PROCINFO_T_RV64;
+
+ (void) smbios_test_table_append(table, &pi, sizeof (pi));
+
+ arc4random_buf(&rv, sizeof (rv));
+ rv.smbpairv_vers = 1;
+ rv.smbpairv_len = sizeof (smb_processor_info_riscv_t);
+
+ smbios_test_table_append_raw(table, &rv, sizeof (rv));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+/*
+ * This verifies that we can detect a header length that doesn't properly
+ * contain both the risc-v and base structure.
+ */
+boolean_t
+smbios_test_pinfo_mktable_invlen3(smbios_test_table_t *table)
+{
+ smb_processor_info_t pi;
+ smb_processor_info_riscv_t rv;
+
+ pi.smbpai_hdr.smbh_type = SMB_TYPE_PROCESSOR_INFO;
+ pi.smbpai_hdr.smbh_len = sizeof (smb_processor_info_t);
+ pi.smbpai_proc = htole16(smbios_pinfo_phandle);
+ pi.smbpai_len = 0;
+ pi.smbpai_type = SMB_PROCINFO_T_RV64;
+
+ (void) smbios_test_table_append(table, &pi, sizeof (pi));
+
+ arc4random_buf(&rv, sizeof (rv));
+ rv.smbpairv_vers = 1;
+ rv.smbpairv_len = sizeof (smb_processor_info_riscv_t);
+
+ smbios_test_table_append_raw(table, &rv, sizeof (rv));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+/*
+ * This verifies that we can detect an inner risc-v additional processor
+ * information section that declares its size to be beyond the header of the
+ * structure.
+ */
+boolean_t
+smbios_test_pinfo_mktable_invlen4(smbios_test_table_t *table)
+{
+ smb_processor_info_t pi;
+ smb_processor_info_riscv_t rv;
+
+ pi.smbpai_hdr.smbh_type = SMB_TYPE_PROCESSOR_INFO;
+ pi.smbpai_hdr.smbh_len = sizeof (smb_processor_info_t) +
+ sizeof (smb_processor_info_riscv_t);
+ pi.smbpai_proc = htole16(smbios_pinfo_phandle);
+ pi.smbpai_len = sizeof (smb_processor_info_riscv_t);
+ pi.smbpai_type = SMB_PROCINFO_T_RV64;
+
+ (void) smbios_test_table_append(table, &pi, sizeof (pi));
+
+ arc4random_buf(&rv, sizeof (rv));
+ rv.smbpairv_vers = 1;
+ rv.smbpairv_len = sizeof (smb_processor_info_riscv_t) * 2;
+
+ smbios_test_table_append_raw(table, &rv, sizeof (rv));
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+static boolean_t
+smbios_test_pinfo_verify_badtable(smbios_hdl_t *hdl, int smberr,
+ boolean_t valid_pinfo)
+{
+ smbios_struct_t sp;
+ smbios_processor_info_t pinfo;
+ smbios_processor_info_riscv_t rv;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_PROCESSOR_INFO, &sp) == -1) {
+ warnx("failed to lookup SMBIOS processor additional "
+ "information: %s", smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (!valid_pinfo) {
+ if (smbios_info_processor_info(hdl, sp.smbstr_id, &pinfo) !=
+ -1) {
+ warnx("accidentally parsed invalid processor "
+ "additional information as valid");
+ ret = B_FALSE;
+ }
+
+ if (smbios_errno(hdl) != smberr) {
+ warnx("encountered wrong error for processor info, "
+ "found: 0x%x", smbios_errno(hdl));
+ ret = B_FALSE;
+ }
+ } else {
+ if (smbios_info_processor_info(hdl, sp.smbstr_id, &pinfo) !=
+ 0) {
+ warnx("failed to get SMBIOS processor additional "
+ "information: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ ret = B_FALSE;
+ }
+ }
+
+ if (smbios_info_processor_riscv(hdl, sp.smbstr_id, &rv) != -1) {
+ warnx("accidentally got riscv info on invalid handle");
+ ret = B_FALSE;
+ }
+
+ if (smbios_errno(hdl) != smberr) {
+ warnx("encountered wrong error for amd64 info, found: 0x%x",
+ smbios_errno(hdl));
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
+
+boolean_t
+smbios_test_pinfo_verify_invlen1(smbios_hdl_t *hdl)
+{
+ return (smbios_test_pinfo_verify_badtable(hdl, ESMB_SHORT, B_FALSE));
+}
+
+boolean_t
+smbios_test_pinfo_verify_invlen2(smbios_hdl_t *hdl)
+{
+ return (smbios_test_pinfo_verify_badtable(hdl, ESMB_CORRUPT, B_FALSE));
+}
+
+boolean_t
+smbios_test_pinfo_verify_invlen3(smbios_hdl_t *hdl)
+{
+ return (smbios_test_pinfo_verify_badtable(hdl, ESMB_SHORT, B_TRUE));
+}
+
+boolean_t
+smbios_test_pinfo_verify_invlen4(smbios_hdl_t *hdl)
+{
+ return (smbios_test_pinfo_verify_badtable(hdl, ESMB_CORRUPT, B_TRUE));
+}
+
+boolean_t
+smbios_test_pinfo_verify_badtype(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_processor_info_t pinfo;
+ smbios_processor_info_riscv_t rv;
+ boolean_t ret = B_TRUE;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) {
+ warnx("failed to lookup SMBIOS memory device information: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_processor_info(hdl, sp.smbstr_id, &pinfo) != -1) {
+ warnx("accidentally parsed invalid processor additional "
+ "information as valid");
+ ret = B_FALSE;
+ }
+
+ if (smbios_errno(hdl) != ESMB_TYPE) {
+ warnx("encountered wrong error for processor info, found: 0x%x",
+ smbios_errno(hdl));
+ ret = B_FALSE;
+ }
+
+ if (smbios_info_processor_riscv(hdl, sp.smbstr_id, &rv) != -1) {
+ warnx("accidentally got riscv info on invalid handle");
+ ret = B_FALSE;
+ }
+
+ if (smbios_errno(hdl) != ESMB_TYPE) {
+ warnx("encountered wrong error for processor info, found: 0x%x",
+ smbios_errno(hdl));
+ ret = B_FALSE;
+ }
+
+ return (ret);
+}
diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_slot.c b/usr/src/test/util-tests/tests/smbios/smbios_test_slot.c
new file mode 100644
index 0000000000..d84cc10e91
--- /dev/null
+++ b/usr/src/test/util-tests/tests/smbios/smbios_test_slot.c
@@ -0,0 +1,188 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2018, Joyent, Inc.
+ */
+
+/*
+ * Basic testing of the SMBIOS 3.2 Slot extensions.
+ */
+
+#include "smbios_test.h"
+
+static const char *smbios_test_name = "The One Slot";
+
+boolean_t
+smbios_test_slot_mktable(smbios_test_table_t *table)
+{
+ smb_slot_t slot;
+ smb_slot_peer_t peers[2];
+ const uint8_t endstring = 0;
+
+ slot.smbsl_hdr.smbh_type = SMB_TYPE_SLOT;
+ slot.smbsl_hdr.smbh_len = sizeof (smb_slot_t) + sizeof (peers);
+
+ slot.smbsl_name = 1;
+ slot.smbsl_type = SMB_SLT_PCIE3G16;
+ slot.smbsl_width = SMB_SLW_16X;
+ slot.smbsl_length = SMB_SLL_SHORT;
+ slot.smbsl_id = htole16(1);
+ slot.smbsl_ch1 = SMB_SLCH1_33V;
+ slot.smbsl_ch2 = SMB_SLCH2_PME;
+ slot.smbsl_sg = htole16(1);
+ slot.smbsl_bus = 0x42;
+ slot.smbsl_df = 0x23;
+ slot.smbsl_dbw = SMB_SLW_16X;
+ slot.smbsl_npeers = 2;
+ peers[0].smbspb_group_no = htole16(1);
+ peers[0].smbspb_bus = 0x42;
+ peers[0].smbspb_df = 0x42;
+ peers[0].smbspb_width = SMB_SLW_8X;
+
+ peers[1].smbspb_group_no = htole16(1);
+ peers[1].smbspb_bus = 0x23;
+ peers[1].smbspb_df = 0x31;
+ peers[1].smbspb_width = SMB_SLW_8X;
+
+ (void) smbios_test_table_append(table, &slot, sizeof (slot));
+ (void) smbios_test_table_append_raw(table, peers, sizeof (peers));
+ (void) smbios_test_table_append_string(table, smbios_test_name);
+ (void) smbios_test_table_append_raw(table, &endstring,
+ sizeof (endstring));
+
+ smbios_test_table_append_eot(table);
+
+ return (B_TRUE);
+}
+
+boolean_t
+smbios_test_slot_verify(smbios_hdl_t *hdl)
+{
+ smbios_struct_t sp;
+ smbios_slot_t slot;
+ uint_t npeers;
+ smbios_slot_peer_t *peers;
+ uint_t errs = 0;
+
+ if (smbios_lookup_type(hdl, SMB_TYPE_SLOT, &sp) == -1) {
+ warnx("failed to lookup SMBIOS slot: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (smbios_info_slot(hdl, sp.smbstr_id, &slot) != 0) {
+ warnx("failed to get SMBIOS slot info: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ /*
+ * Verify everything we'd expect about the slot.
+ */
+ if (strcmp(slot.smbl_name, smbios_test_name) != 0) {
+ warnx("slot name mismatch, expected %s, found %s",
+ smbios_test_name, slot.smbl_name);
+ errs++;
+ }
+
+ if (slot.smbl_type != SMB_SLT_PCIE3G16) {
+ warnx("incorrect slot type, found %u", slot.smbl_type);
+ errs++;
+ }
+
+ if (slot.smbl_width != SMB_SLW_16X) {
+ warnx("incorrect slot width, found %u", slot.smbl_width);
+ errs++;
+ }
+
+ if (slot.smbl_length != SMB_SLL_SHORT) {
+ warnx("incorrect slot length, found %u", slot.smbl_length);
+ errs++;
+ }
+
+ if (slot.smbl_dbw != SMB_SLW_16X) {
+ warnx("incorrect slot data bus width, found %u", slot.smbl_dbw);
+ errs++;
+ }
+
+ if (slot.smbl_npeers != 2) {
+ warnx("incorrect number of slot peers, found %u",
+ slot.smbl_npeers);
+ errs++;
+ }
+
+ if (smbios_info_slot_peers(hdl, sp.smbstr_id, &npeers, &peers) != 0) {
+ warnx("failed to get SMBIOS peer info: %s",
+ smbios_errmsg(smbios_errno(hdl)));
+ return (B_FALSE);
+ }
+
+ if (npeers != 2) {
+ warnx("got wrong number of slot peers: %u\n",
+ npeers);
+ return (B_FALSE);
+ }
+
+ if (peers[0].smblp_group != 1) {
+ warnx("incorrect group for peer 0: %u", peers[0].smblp_group);
+ errs++;
+ }
+
+ if (peers[0].smblp_data_width != SMB_SLW_8X) {
+ warnx("incorrect data width for peer 0: %u",
+ peers[0].smblp_data_width);
+ errs++;
+ }
+
+ if (peers[0].smblp_device != (0x42 >> 3)) {
+ warnx("incorrect PCI device for peer 0: %u",
+ peers[0].smblp_device);
+ errs++;
+ }
+
+ if (peers[0].smblp_function != (0x42 & 0x7)) {
+ warnx("incorrect PCI function for peer 0: %u",
+ peers[0].smblp_function);
+ errs++;
+ }
+
+ if (peers[1].smblp_group != 1) {
+ warnx("incorrect group for peer 1: %u", peers[1].smblp_group);
+ errs++;
+ }
+
+ if (peers[1].smblp_device != (0x31 >> 3)) {
+ warnx("incorrect PCI device for peer 1: %u",
+ peers[1].smblp_device);
+ errs++;
+ }
+
+ if (peers[1].smblp_function != (0x31 & 0x7)) {
+ warnx("incorrect PCI function for peer 1: %u",
+ peers[1].smblp_function);
+ errs++;
+ }
+
+ if (peers[1].smblp_data_width != SMB_SLW_8X) {
+ warnx("incorrect data width for peer 1: %u",
+ peers[1].smblp_data_width);
+ errs++;
+ }
+
+ smbios_info_slot_peers_free(hdl, npeers, peers);
+
+ if (errs > 0) {
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}