diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/cmd/smbios/smbios.c | 147 | ||||
| -rw-r--r-- | usr/src/common/smbios/mktables.sh | 13 | ||||
| -rw-r--r-- | usr/src/common/smbios/smb_info.c | 332 | ||||
| -rw-r--r-- | usr/src/common/smbios/smb_open.c | 2 | ||||
| -rw-r--r-- | usr/src/lib/libsmbios/common/mapfile-vers | 17 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/Makefile | 16 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios.c | 257 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test.h | 41 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_chassis.c | 556 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_errors.c | 61 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_fwinfo.c | 429 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c | 5 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_slot.c | 222 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_strings.c | 157 | ||||
| -rw-r--r-- | usr/src/test/util-tests/tests/smbios/smbios_test_strprop.c | 255 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/smbios.h | 153 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/smbios_impl.h | 78 |
17 files changed, 2592 insertions, 149 deletions
diff --git a/usr/src/cmd/smbios/smbios.c b/usr/src/cmd/smbios/smbios.c index e4cf35c189..859d8d71c7 100644 --- a/usr/src/cmd/smbios/smbios.c +++ b/usr/src/cmd/smbios/smbios.c @@ -480,7 +480,8 @@ static void print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp) { smbios_chassis_t c; - int elem_cnt; + smbios_chassis_entry_t *elts; + uint_t nelts, i; (void) smbios_info_chassis(shp, id, &c); @@ -504,35 +505,38 @@ print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp) oprintf(fp, " Chassis Height: %uu\n", c.smbc_uheight); oprintf(fp, " Power Cords: %u\n", c.smbc_cords); - elem_cnt = c.smbc_elems; - oprintf(fp, " Element Records: %u\n", elem_cnt); + oprintf(fp, " Element Records: %u\n", c.smbc_elems); - if (elem_cnt > 0) { - id_t *elems; - uint8_t type; - int i, n, cnt; + if (c.smbc_elems == 0) { + return; + } - elems = alloca(c.smbc_elems * sizeof (id_t)); - cnt = smbios_info_contains(shp, id, elem_cnt, elems); - if (cnt > SMB_CONT_MAX) - return; - n = MIN(elem_cnt, cnt); + if (smbios_info_chassis_elts(shp, id, &nelts, &elts) != 0) { + smbios_warn(shp, "failed to read chassis elements"); + return; + } - oprintf(fp, "\n"); - for (i = 0; i < n; i++) { - type = (uint8_t)elems[i]; - if (type & 0x80) { - /* SMBIOS structrure Type */ - desc_printf(smbios_type_name(type & 0x7f), fp, - " Contained SMBIOS structure Type: %u", - type & 0x80); - } else { - /* SMBIOS Base Board Type */ - desc_printf(smbios_bboard_type_desc(type), fp, - " Contained SMBIOS Base Board Type: 0x%x", - type); - } + oprintf(fp, "\n"); + + for (i = 0; i < nelts; i++) { + switch (elts[i].smbce_type) { + case SMB_CELT_BBOARD: + desc_printf(smbios_bboard_type_desc(elts[i].smbce_elt), + fp, " Contained SMBIOS Base Board Type: 0x%x", + elts[i].smbce_elt); + break; + case SMB_CELT_SMBIOS: + desc_printf(smbios_type_name(elts[i].smbce_elt), fp, + " Contained SMBIOS structure Type: %u", + elts[i].smbce_elt); + break; + default: + oprintf(fp, " Unknown contained Type: %u/%u\n", + elts[i].smbce_type, elts[i].smbce_elt); + break; } + oprintf(fp, " Minimum number: %u\n", elts[i].smbce_min); + oprintf(fp, " Maximum number: %u\n", elts[i].smbce_max); } } @@ -782,6 +786,19 @@ print_slot(smbios_hdl_t *shp, id_t id, FILE *fp) oprintf(fp, " Slot Pitch: %u.%u mm\n", s.smbl_pitch / 100, s.smbl_pitch % 100); } + + /* + * The slot height was introduced in SMBIOS 3.5. However, a value of + * zero here does not mean that it is unknown, but rather that the + * concept is not applicable. Therefore we cannot use a standard check + * against zero for this and instead use the version. + */ + if (smbios_vergteq(&v, 3, 5)) { + desc_printf(smbios_slot_height_desc(s.smbl_height), fp, + " Height: 0x%x", s.smbl_height); + } else { + oprintf(fp, " Height: unknown\n"); + } } static void @@ -798,7 +815,7 @@ print_obdevs_ext(smbios_hdl_t *shp, id_t id, FILE *fp) * are the actual device type. */ enabled = oe.smboe_dtype >> 7; - type = smbios_onboard_type_desc(oe.smboe_dtype & 0x7f); + type = smbios_onboard_ext_type_desc(oe.smboe_dtype & 0x7f); str_print(fp, " Reference Designator", oe.smboe_name); oprintf(fp, " Device Enabled: %s\n", enabled == B_TRUE ? "true" : @@ -1685,6 +1702,74 @@ print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp) } } +static void +print_strprop_info(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_strprop_t prop; + + if (smbios_info_strprop(shp, id, &prop) != 0) { + smbios_warn(shp, "failed to read string property information"); + return; + } + + desc_printf(smbios_strprop_id_desc(prop.smbsp_prop_id), fp, + " Property ID: %u", prop.smbsp_prop_id); + if (prop.smbsp_prop_val != NULL) { + str_print(fp, " Property Value", prop.smbsp_prop_val); + } + id_printf(fp, " Parent Handle: ", prop.smbsp_parent); +} + +static void +print_fwinfo(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_fwinfo_t fw; + smbios_fwinfo_comp_t *comps; + uint_t ncomps, i; + + if (smbios_info_fwinfo(shp, id, &fw) != 0) { + smbios_warn(shp, "failed to read firmware inventory"); + return; + } + + str_print(fp, " Component Name", fw.smbfw_name); + str_print(fp, " ID", fw.smbfw_id); + str_print(fp, " Release Date", fw.smbfw_reldate); + str_print(fp, " Lowest Supported Version", fw.smbfw_lsv); + desc_printf(smbios_fwinfo_vers_desc(fw.smbfw_vers_fmt), fp, + " Version Format: %u", fw.smbfw_vers_fmt); + desc_printf(smbios_fwinfo_id_desc(fw.smbfw_id_fmt), fp, + " ID Format: %u", fw.smbfw_id_fmt); + if (fw.smbfw_imgsz != UINT64_MAX) { + oprintf(fp, " Image Size: %" PRIu64 "\n", fw.smbfw_imgsz); + } else { + oprintf(fp, " Image Size: unknown\n"); + } + + flag_printf(fp, "Characteristics", fw.smbfw_chars, + sizeof (fw.smbfw_chars) * NBBY, smbios_fwinfo_ch_name, + smbios_fwinfo_ch_desc); + + desc_printf(smbios_fwinfo_state_desc(fw.smbfw_state), fp, " State: %u", + fw.smbfw_state); + oprintf(fp, " Number of Associated Components: %u\n", + fw.smbfw_ncomps); + + if (fw.smbfw_ncomps == 0) + return; + + if (smbios_info_fwinfo_comps(shp, id, &ncomps, &comps) == -1) { + smbios_warn(shp, "failed to read firmware inventory " + "components"); + return; + } + + oprintf(fp, "\n Component Handles:\n"); + for (i = 0; i < ncomps; i++) { + oprintf(fp, " %ld\n", comps[i]); + } +} + static int print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) { @@ -1841,6 +1926,14 @@ print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) oprintf(fp, "\n"); print_processor_info(shp, sp->smbstr_id, fp); break; + case SMB_TYPE_STRPROP: + oprintf(fp, "\n"); + print_strprop_info(shp, sp->smbstr_id, fp); + break; + case SMB_TYPE_FWINFO: + oprintf(fp, "\n"); + print_fwinfo(shp, sp->smbstr_id, fp); + break; case SUN_OEM_EXT_PROCESSOR: oprintf(fp, "\n"); print_extprocessor(shp, sp->smbstr_id, fp); diff --git a/usr/src/common/smbios/mktables.sh b/usr/src/common/smbios/mktables.sh index 95bd9d6f8b..7256eedfb8 100644 --- a/usr/src/common/smbios/mktables.sh +++ b/usr/src/common/smbios/mktables.sh @@ -23,6 +23,7 @@ # # Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. # Copyright (c) 2018, Joyent, Inc. +# Copyright 2021 Oxide Computer Company # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -47,6 +48,7 @@ SMB_BIOSXB2_ smbios_bios_xb2_name uint_t SMB_CAT_ smbios_cache_ctype_name uint_t SMB_CAF_ smbios_cache_flag_name uint_t SMB_EVFL_ smbios_evlog_flag_name uint_t +SMB_FWC_ smbios_fwinfo_ch_name uint_t SMB_IPMI_F_ smbios_ipmi_flag_name uint_t SMB_POWERSUP_F_ smbios_powersup_flag_name uint_t SMB_MOMC_ smbios_memdevice_op_capab_name uint_t @@ -81,6 +83,10 @@ SMB_COOLDEV_T_ smbios_cooldev_type_desc uint_t SMB_EVFL_ smbios_evlog_flag_desc uint_t SMB_EVHF_ smbios_evlog_format_desc uint_t SMB_EVM_ smbios_evlog_method_desc uint_t +SMB_FWC_ smbios_fwinfo_ch_desc uint_t +SMB_FWI_ smbios_fwinfo_id_desc uint_t +SMB_FWS_ smbios_fwinfo_state_desc uint_t +SMB_FWV_ smbios_fwinfo_vers_desc uint_t SMB_HWSEC_PS_ smbios_hwsec_desc uint_t SMB_IPMI_F_ smbios_ipmi_flag_desc uint_t SMB_IPMI_T_ smbios_ipmi_type_desc uint_t @@ -100,6 +106,7 @@ SMB_MDR_ smbios_memdevice_rank_desc uint_t SMB_MTECH_ smbios_memdevice_memtech_desc uint_t SMB_MOMC_ smbios_memdevice_op_capab_desc uint_t SMB_OBT_ smbios_onboard_type_desc uint_t +SMB_OBET_ smbios_onboard_ext_type_desc uint_t SMB_PDI_ smbios_pointdev_iface_desc uint_t SMB_PDT_ smbios_pointdev_type_desc uint_t SMB_POC_ smbios_port_conn_desc uint_t @@ -115,10 +122,12 @@ SMB_RV_PRIV_ smbios_riscv_priv_desc uint_t SMB_RV_WIDTH_ smbios_riscv_width_desc uint_t SMB_SLCH1_ smbios_slot_ch1_desc uint_t SMB_SLCH2_ smbios_slot_ch2_desc uint_t +SMB_SLHT_ smbios_slot_height_desc uint_t SMB_SLL_ smbios_slot_length_desc uint_t SMB_SLT_ smbios_slot_type_desc uint_t SMB_SLU_ smbios_slot_usage_desc uint_t SMB_SLW_ smbios_slot_width_desc uint_t +SMB_STRP_ smbios_strprop_id_desc uint_t SMB_TPROBE_L_ smbios_tprobe_loc_desc uint_t SMB_TPROBE_S_ smbios_tprobe_status_desc uint_t SMB_TYPE_ smbios_type_desc uint_t @@ -143,7 +152,7 @@ echo "\ echo "$name_funcs" | while read p name type; do [ -z "$p" ] && continue - pattern="^#define[ ]\($p[A-Za-z0-9_]*\)[ ]*[A-Z0-9]*.*$" + pattern="^#define[ ]\(${p}[A-Za-z0-9_]*\)[ ]*[A-Z0-9]*.*\$" replace=' case \1: return ("\1");' echo "\nconst char *\n$name($type x)\n{\n\tswitch (x) {" @@ -162,7 +171,7 @@ done # echo "$desc_funcs" | while read p name type; do [ -z "$p" ] && continue - pattern="^#define[ ]\($p[A-Za-z0-9_]*\)[ ]*.*/\\* \(.*\) \\*/$" + pattern="^#define[ ]\(${p}[A-Za-z0-9_]*\)[ ]*.*/\\* \(.*\) \\*/\$" replace=' case \1: return (\2);' echo "\nconst char *\n$name($type x)\n{\n\tswitch (x) {" diff --git a/usr/src/common/smbios/smb_info.c b/usr/src/common/smbios/smb_info.c index 9aba4deba8..09d7d5374a 100644 --- a/usr/src/common/smbios/smb_info.c +++ b/usr/src/common/smbios/smb_info.c @@ -22,7 +22,7 @@ /* * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2019 Joyent, Inc. - * Copyright 2020 Oxide Computer Company + * Copyright 2021 Oxide Computer Company * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -78,6 +78,8 @@ #include <string.h> #endif +#define SMB_CONT_WORD 2 /* contained elements are word size */ + /* * A large number of SMBIOS structures contain a set of common strings used to * describe a h/w component's serial number, manufacturer, etc. These fields @@ -130,9 +132,9 @@ static const struct smb_infospec { offsetof(smb_chassis_t, smbch_asset), 0, 0, - offsetof(smb_chassis_t, smbch_cn), - SMB_CONT_BYTE, - offsetof(smb_chassis_t, smbch_cv) }, + 0, + 0, + 0 }, { SMB_TYPE_PROCESSOR, offsetof(smb_processor_t, smbpr_manufacturer), 0, @@ -216,6 +218,18 @@ static const struct smb_infospec { 0, 0 }, + { SMB_TYPE_FWINFO, + offsetof(smb_fwinfo_t, smbfwii_mfg), + 0, + offsetof(smb_fwinfo_t, smbfwii_vers), + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, { SMB_TYPE_EOT } }; @@ -363,9 +377,7 @@ smbios_info_contains(smbios_hdl_t *shp, id_t id, uint_t idc, id_t *idv) n = MIN(cnt, idc); for (i = 0; i < n; i++) { if (size == SMB_CONT_WORD) - idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 2)); - else if (size == SMB_CONT_BYTE) - idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 3)); + idv[i] = *((uint16_t *)(uintptr_t)cp + (i * 2)); else return (smb_set_errno(shp, ESMB_INVAL)); } @@ -516,43 +528,156 @@ int smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp) { const smb_struct_t *stp = smb_lookup_id(shp, id); - /* Length is measurable by one byte, so it'll be no more than 255. */ - uint8_t buf[256]; - smb_chassis_t *ch = (smb_chassis_t *)&buf[0]; + smb_chassis_t ch; - if (stp == NULL) + if (stp == NULL) { return (-1); /* errno is set for us */ + } - if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) + if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) { return (smb_set_errno(shp, ESMB_TYPE)); + } - smb_info_bcopy(stp->smbst_hdr, ch, sizeof (buf)); + if (stp->smbst_hdr->smbh_len < sizeof (ch)) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch)); bzero(chp, sizeof (smb_base_chassis_t)); - if (smb_libgteq(shp, SMB_VERSION_27)) { - bzero(chp->smbc_sku, sizeof (chp->smbc_sku)); + + /* + * See the comments for the smb_chassis_pre35_t in sys/smbios_impl.h for + * an explanation as to why this is here. The use of smb_strptr with + * index 0 below ensures that we initialize this to an empty string. + */ + if (smb_libgteq(shp, SMB_VERSION_35)) { + chp->smbc_sku = smb_strptr(stp, 0); + } else if (smb_libgteq(shp, SMB_VERSION_27)) { + smb_chassis_pre35_t *p35 = (smb_chassis_pre35_t *)chp; + bzero(p35->smbc_sku, sizeof (p35->smbc_sku)); } - chp->smbc_oemdata = ch->smbch_oemdata; - chp->smbc_lock = (ch->smbch_type & SMB_CHT_LOCK) != 0; - chp->smbc_type = ch->smbch_type & ~SMB_CHT_LOCK; - chp->smbc_bustate = ch->smbch_bustate; - chp->smbc_psstate = ch->smbch_psstate; - chp->smbc_thstate = ch->smbch_thstate; - chp->smbc_security = ch->smbch_security; - chp->smbc_uheight = ch->smbch_uheight; - chp->smbc_cords = ch->smbch_cords; - chp->smbc_elems = ch->smbch_cn; - chp->smbc_elemlen = ch->smbch_cm; + chp->smbc_oemdata = ch.smbch_oemdata; + chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0; + chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK; + chp->smbc_bustate = ch.smbch_bustate; + chp->smbc_psstate = ch.smbch_psstate; + chp->smbc_thstate = ch.smbch_thstate; + chp->smbc_security = ch.smbch_security; + chp->smbc_uheight = ch.smbch_uheight; + chp->smbc_cords = ch.smbch_cords; + chp->smbc_elems = ch.smbch_cn; + chp->smbc_elemlen = ch.smbch_cm; + + /* + * If the table is older than version 2.7 which added support for the + * chassis SKU, there's no reason to proceed. + */ + if (!smb_gteq(shp, SMB_VERSION_27)) { + return (0); + } if (smb_libgteq(shp, SMB_VERSION_27)) { - (void) strlcpy(chp->smbc_sku, SMB_CH_SKU(ch), - sizeof (chp->smbc_sku)); + uint8_t strno; + const char *str; + off_t off = sizeof (ch) + ch.smbch_cn * ch.smbch_cm; + if (stp->smbst_hdr->smbh_len < off + 1) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + smb_info_bcopy_offset(stp->smbst_hdr, &strno, sizeof (strno), + off); + str = smb_strptr(stp, strno); + if (smb_libgteq(shp, SMB_VERSION_35)) { + chp->smbc_sku = str; + } else { + smb_chassis_pre35_t *p35 = (smb_chassis_pre35_t *)chp; + (void) strlcpy(p35->smbc_sku, str, + sizeof (p35->smbc_sku)); + } } return (0); } int +smbios_info_chassis_elts(smbios_hdl_t *shp, id_t id, uint_t *nentsp, + smbios_chassis_entry_t **entsp) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smbios_chassis_entry_t *entry; + smb_chassis_t ch; + size_t entlen; + uint_t i; + + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) { + return (smb_set_errno(shp, ESMB_TYPE)); + } + + if (stp->smbst_hdr->smbh_len < sizeof (ch)) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch)); + if (ch.smbch_cm != sizeof (smb_chassis_entry_t)) { + return (smb_set_errno(shp, ESMB_CORRUPT)); + } + + if (ch.smbch_cn == 0) { + *nentsp = 0; + *entsp = NULL; + return (0); + } + + entlen = ch.smbch_cm * ch.smbch_cn; + if (stp->smbst_hdr->smbh_len < sizeof (ch) + entlen) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + if ((entry = smb_alloc(entlen)) == NULL) { + return (smb_set_errno(shp, ESMB_NOMEM)); + } + + for (i = 0; i < ch.smbch_cn; i++) { + smb_chassis_entry_t e; + size_t off = sizeof (ch) + i * sizeof (e); + + smb_info_bcopy_offset(stp->smbst_hdr, &e, sizeof (e), off); + /* + * The top bit is used to indicate what type of record this is, + * while the lower 7-bits indicate the actual type. + */ + entry[i].smbce_type = e.smbce_type & 0x80 ? + SMB_CELT_SMBIOS : SMB_CELT_BBOARD; + entry[i].smbce_elt = e.smbce_type & 0x7f; + entry[i].smbce_min = e.smbce_min; + entry[i].smbce_max = e.smbce_max; + } + + *entsp = entry; + *nentsp = ch.smbch_cn; + + return (0); +} + +void +smbios_info_chassis_elts_free(smbios_hdl_t *shp, uint_t nents, + smbios_chassis_entry_t *ent) +{ + size_t sz = nents * sizeof (smbios_chassis_entry_t); + + if (nents == 0) { + ASSERT3P(ent, ==, NULL); + return; + } + + smb_free(ent, sz); +} + +int smbios_info_processor(smbios_hdl_t *shp, id_t id, smbios_processor_t *pp) { const smb_struct_t *stp = smb_lookup_id(shp, id); @@ -733,6 +858,10 @@ smbios_info_slot(smbios_hdl_t *shp, id_t id, smbios_slot_t *sp) sp->smbl_pwidth = cont.smbsl_pwidth; sp->smbl_pitch = cont.smbsl_pitch; + if (smb_libgteq(shp, SMB_VERSION_35)) { + sp->smbl_height = cont.smbsl_height; + } + return (0); } @@ -1671,6 +1800,10 @@ smbios_info_processor_riscv(smbios_hdl_t *shp, id_t id, const smb_processor_info_t *proc; const smb_processor_info_riscv_t *rv; + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO) { return (smb_set_errno(shp, ESMB_TYPE)); } @@ -1730,6 +1863,10 @@ smbios_info_pointdev(smbios_hdl_t *shp, id_t id, smbios_pointdev_t *pd) const smb_struct_t *stp = smb_lookup_id(shp, id); smb_pointdev_t point; + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + if (stp->smbst_hdr->smbh_type != SMB_TYPE_POINTDEV) { return (smb_set_errno(shp, ESMB_TYPE)); } @@ -1754,6 +1891,10 @@ smbios_info_battery(smbios_hdl_t *shp, id_t id, smbios_battery_t *bp) const smb_struct_t *stp = smb_lookup_id(shp, id); smb_battery_t bat; + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + if (stp->smbst_hdr->smbh_type != SMB_TYPE_BATTERY) { return (smb_set_errno(shp, ESMB_TYPE)); } @@ -1800,3 +1941,138 @@ smbios_info_battery(smbios_hdl_t *shp, id_t id, smbios_battery_t *bp) return (0); } + +int +smbios_info_strprop(smbios_hdl_t *shp, id_t id, smbios_strprop_t *str) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smb_strprop_t prop; + + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_STRPROP) { + return (smb_set_errno(shp, ESMB_TYPE)); + } + + if (stp->smbst_hdr->smbh_len < sizeof (prop)) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + if (stp->smbst_hdr->smbh_len > sizeof (prop)) { + return (smb_set_errno(shp, ESMB_CORRUPT)); + } + + bzero(str, sizeof (*str)); + smb_info_bcopy(stp->smbst_hdr, &prop, sizeof (prop)); + + str->smbsp_parent = prop.smbstrp_phdl; + str->smbsp_prop_id = prop.smbstrp_prop_id; + str->smbsp_prop_val = smb_strptr(stp, prop.smbstrp_prop_val); + + return (0); +} + +int +smbios_info_fwinfo(smbios_hdl_t *shp, id_t id, smbios_fwinfo_t *fwinfo) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smb_fwinfo_t fw; + + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_FWINFO) { + return (smb_set_errno(shp, ESMB_TYPE)); + } + + if (stp->smbst_hdr->smbh_len < sizeof (fw)) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + /* + * The verion and manufacturer are part of smbios_info_common(). + */ + bzero(fwinfo, sizeof (*fwinfo)); + smb_info_bcopy(stp->smbst_hdr, &fw, sizeof (fw)); + fwinfo->smbfw_name = smb_strptr(stp, fw.smbfwii_name); + fwinfo->smbfw_id = smb_strptr(stp, fw.smbfwii_id); + fwinfo->smbfw_reldate = smb_strptr(stp, fw.smbfwii_reldate); + fwinfo->smbfw_lsv = smb_strptr(stp, fw.smbfwii_lsv); + fwinfo->smbfw_imgsz = fw.smbfwii_imgsz; + fwinfo->smbfw_chars = fw.smbfwii_chars; + fwinfo->smbfw_state = fw.smbfwii_state; + fwinfo->smbfw_ncomps = fw.smbfwii_ncomps; + fwinfo->smbfw_vers_fmt = fw.smbfwii_vers_fmt; + fwinfo->smbfw_id_fmt = fw.smbfwii_id_fmt; + + return (0); +} + +int +smbios_info_fwinfo_comps(smbios_hdl_t *shp, id_t id, uint_t *ncompsp, + smbios_fwinfo_comp_t **compsp) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smbios_fwinfo_comp_t *comps; + smb_fwinfo_t fw; + size_t need; + uint_t i; + + if (stp == NULL) { + return (-1); /* errno is set for us */ + } + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_FWINFO) { + return (smb_set_errno(shp, ESMB_TYPE)); + } + + if (stp->smbst_hdr->smbh_len < sizeof (fw)) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + smb_info_bcopy(stp->smbst_hdr, &fw, sizeof (fw)); + if (fw.smbfwii_ncomps == 0) { + *ncompsp = 0; + *compsp = NULL; + return (0); + } + + need = fw.smbfwii_ncomps * sizeof (uint16_t) + sizeof (smb_fwinfo_t); + if (stp->smbst_hdr->smbh_len < need) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + comps = smb_alloc(fw.smbfwii_ncomps * sizeof (smbios_fwinfo_comp_t)); + if (comps == NULL) { + return (smb_set_errno(shp, ESMB_NOMEM)); + } + + for (i = 0; i < fw.smbfwii_ncomps; i++) { + uint16_t id; + size_t off = sizeof (smb_fwinfo_t) + sizeof (uint16_t) * i; + smb_info_bcopy_offset(stp->smbst_hdr, &id, sizeof (id), off); + comps[i].smbfwe_id = id; + } + + *ncompsp = fw.smbfwii_ncomps; + *compsp = comps; + + return (0); +} + +void +smbios_info_fwinfo_comps_free(smbios_hdl_t *shp, uint_t ncomps, + smbios_fwinfo_comp_t *comps) +{ + size_t sz = ncomps * sizeof (smbios_fwinfo_comp_t); + + if (ncomps == 0) { + ASSERT3P(comps, ==, NULL); + return; + } + + smb_free(comps, sz); +} diff --git a/usr/src/common/smbios/smb_open.c b/usr/src/common/smbios/smb_open.c index 6747c84499..454fb61b8b 100644 --- a/usr/src/common/smbios/smb_open.c +++ b/usr/src/common/smbios/smb_open.c @@ -22,6 +22,7 @@ /* * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2021 Oxide Computer Company * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -232,6 +233,7 @@ smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len, case SMB_VERSION_32: case SMB_VERSION_33: case SMB_VERSION_34: + case SMB_VERSION_35: break; default: return (smb_open_error(shp, errp, ESMB_VERSION)); diff --git a/usr/src/lib/libsmbios/common/mapfile-vers b/usr/src/lib/libsmbios/common/mapfile-vers index 70667deb49..49d8d04096 100644 --- a/usr/src/lib/libsmbios/common/mapfile-vers +++ b/usr/src/lib/libsmbios/common/mapfile-vers @@ -22,6 +22,7 @@ # Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. # Copyright (c) 2018, Joyent, Inc. # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2021 Oxide Computer Company # # @@ -80,6 +81,11 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_evlog_format_desc; smbios_evlog_method_desc; smbios_fdopen; + smbios_fwinfo_ch_name; + smbios_fwinfo_ch_desc; + smbios_fwinfo_id_desc; + smbios_fwinfo_state_desc; + smbios_fwinfo_vers_desc; smbios_hwsec_desc; smbios_info_battery; smbios_info_bboard; @@ -87,10 +93,15 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_info_boot; smbios_info_cache; smbios_info_chassis; + smbios_info_chassis_elts; + smbios_info_chassis_elts_free; smbios_info_cooldev; smbios_info_common; smbios_info_contains; smbios_info_eventlog; + smbios_info_fwinfo; + smbios_info_fwinfo_comps; + smbios_info_fwinfo_comps_free; smbios_info_hwsec; smbios_info_ipmi; smbios_info_iprobe; @@ -116,6 +127,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_info_slot_peers_free; smbios_info_smbios; smbios_info_smbios_version; + smbios_info_strprop; smbios_info_strtab; smbios_info_system; smbios_info_pciexrc; @@ -140,8 +152,9 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_memdevice_memtech_desc; smbios_memdevice_type_desc; smbios_memdevice_rank_desc; - smbios_open; + smbios_onboard_ext_type_desc; smbios_onboard_type_desc; + smbios_open; smbios_pointdev_iface_desc; smbios_pointdev_type_desc; smbios_port_conn_desc; @@ -168,10 +181,12 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_slot_ch1_name; smbios_slot_ch2_desc; smbios_slot_ch2_name; + smbios_slot_height_desc; smbios_slot_length_desc; smbios_slot_type_desc; smbios_slot_usage_desc; smbios_slot_width_desc; + smbios_strprop_id_desc; smbios_system_wakeup_desc; smbios_tprobe_loc_desc; smbios_tprobe_status_desc; diff --git a/usr/src/test/util-tests/tests/smbios/Makefile b/usr/src/test/util-tests/tests/smbios/Makefile index e783a337dc..819ebe5be6 100644 --- a/usr/src/test/util-tests/tests/smbios/Makefile +++ b/usr/src/test/util-tests/tests/smbios/Makefile @@ -11,6 +11,7 @@ # # Copyright (c) 2018, Joyent, Inc. +# Copyright 2021 Oxide Computer Company # include $(SRC)/Makefile.master @@ -19,10 +20,14 @@ ROOTOPTPKG = $(ROOT)/opt/util-tests TESTDIR = $(ROOTOPTPKG)/tests/ OBJS = smbios.o \ + smbios_test_chassis.o \ smbios_test_errors.o \ + smbios_test_fwinfo.o \ smbios_test_memdevice.o \ smbios_test_pinfo.o \ - smbios_test_slot.o + smbios_test_slot.o \ + smbios_test_strings.o \ + smbios_test_strprop.o PROGS = smbios include $(SRC)/cmd/Makefile.cmd @@ -30,6 +35,15 @@ include $(SRC)/test/Makefile.com CMDS = $(PROGS:%=$(TESTDIR)/%) $(CMDS) := FILEMODE = 0555 +CSTD = $(GNU_C99) + +# +# Since this program uses quite a number of variables declared on the +# stack that are then written to by libsmbios, we opt to pay the cost +# of always have the stack protector on every function as an additional +# means of checking ourselves. +# +STACKPROTECT = all LDLIBS += -lsmbios -lumem CFLAGS += -_gcc=-Wall -_gcc=-Wextra -_gcc=-Wno-unknown-pragmas diff --git a/usr/src/test/util-tests/tests/smbios/smbios.c b/usr/src/test/util-tests/tests/smbios/smbios.c index 429d4f81be..73958dda71 100644 --- a/usr/src/test/util-tests/tests/smbios/smbios.c +++ b/usr/src/test/util-tests/tests/smbios/smbios.c @@ -11,7 +11,7 @@ /* * Copyright (c) 2018, Joyent, Inc. - * Copyright 2020 Oxide Computer Company + * Copyright 2021 Oxide Computer Company */ /* @@ -21,8 +21,15 @@ */ #include <umem.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <limits.h> +#include <unistd.h> #include "smbios_test.h" +static int test_dirfd = -1; + const char * _umem_debug_init(void) { @@ -112,6 +119,14 @@ smbios_test_table_append_string(smbios_test_table_t *table, const char *str) (void) smbios_test_table_append_common(table, str, len); } +void +smbios_test_table_str_fini(smbios_test_table_t *table) +{ + const uint8_t endstring = 0; + + smbios_test_table_append_raw(table, &endstring, sizeof (endstring)); +} + uint16_t smbios_test_table_append(smbios_test_table_t *table, const void *buf, size_t len) @@ -215,6 +230,34 @@ smbios_test_table_fini(smbios_test_table_t *table) static const smbios_test_t smbios_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, + .st_libvers = 0, + .st_mktable = smbios_test_badvers_mktable, + .st_desc = "bad library version (zeros)" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_slot_mktable, + .st_canopen = B_TRUE, + .st_verify = smbios_test_verify_badids, + .st_desc = "smbios_info_* with bad id" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_slot_mktable, + .st_canopen = B_TRUE, + .st_verify = smbios_test_verify_strings, + .st_desc = "smbios string functions" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, .st_tvers = SMB_VERSION_32, .st_libvers = SMB_VERSION, .st_mktable = smbios_test_slot_mktable, @@ -239,10 +282,20 @@ static const smbios_test_t smbios_tests[] = { .st_desc = "slot 3.4 with peers" }, { .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_tvers = SMB_VERSION_35, + .st_libvers = SMB_VERSION_34, + .st_mktable = smbios_test_slot_mktable_35, + .st_canopen = B_TRUE, + .st_verify = smbios_test_slot_verify_34_overrun, + .st_desc = "slot 3.5 against 3.4 lib" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION_35, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_slot_mktable_35, + .st_canopen = B_TRUE, + .st_verify = smbios_test_slot_verify_35, + .st_desc = "slot 3.5" }, { .st_entry = SMBIOS_ENTRY_POINT_30, .st_tvers = SMB_VERSION_32, @@ -250,7 +303,7 @@ static const smbios_test_t smbios_tests[] = { .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_desc = "memory device 3.2 % 3.2" }, { .st_entry = SMBIOS_ENTRY_POINT_30, .st_tvers = SMB_VERSION_32, @@ -258,7 +311,7 @@ static const smbios_test_t smbios_tests[] = { .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_desc = "memory device 3.2 % 3.3" }, { .st_entry = SMBIOS_ENTRY_POINT_30, .st_tvers = SMB_VERSION_33, @@ -331,8 +384,143 @@ static const smbios_test_t smbios_tests[] = { .st_canopen = B_TRUE, .st_verify = smbios_test_pinfo_verify_badtype, .st_desc = "processor additional information - bad type" - }, - + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_strprop_mktable_invlen1, + .st_canopen = B_TRUE, + .st_verify = smbios_test_strprop_verify_invlen1, + .st_desc = "string property - bad table length 1" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_strprop_mktable_invlen2, + .st_canopen = B_TRUE, + .st_verify = smbios_test_strprop_verify_invlen2, + .st_desc = "string property - bad table length 2" + }, { + .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_strprop_verify_badtype, + .st_desc = "string property - bad type" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_strprop_mktable_basic, + .st_canopen = B_TRUE, + .st_verify = smbios_test_strprop_verify_basic, + .st_desc = "string property - basic" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_strprop_mktable_badstr, + .st_canopen = B_TRUE, + .st_verify = smbios_test_strprop_verify_badstr, + .st_desc = "string property - bad string" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_fwinfo_mktable_invlen_base, + .st_canopen = B_TRUE, + .st_verify = smbios_test_fwinfo_verify_invlen_base, + .st_desc = "firmware inventory - bad base length" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_fwinfo_mktable_invlen_comps, + .st_canopen = B_TRUE, + .st_verify = smbios_test_fwinfo_verify_invlen_comps, + .st_desc = "firmware inventory - bad comp length" + }, { + .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_fwinfo_verify_badtype, + .st_desc = "firmware inventory - bad type" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_fwinfo_mktable_nocomps, + .st_canopen = B_TRUE, + .st_verify = smbios_test_fwinfo_verify_nocomps, + .st_desc = "firmware inventory - no components" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_fwinfo_mktable_comps, + .st_canopen = B_TRUE, + .st_verify = smbios_test_fwinfo_verify_comps, + .st_desc = "firmware inventory - components" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION_24, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_invlen_base, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_invlen, + .st_desc = "chassis - bad length (2.4 table)" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_invlen_base, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_invlen, + .st_desc = "chassis - bad length (latest version)" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_base, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_invlen, + .st_desc = "chassis - bad length, expect sku" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION_24, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_base, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_base, + .st_desc = "chassis - basic 2.4 version" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_sku_nocomps, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_sku_nocomps, + .st_desc = "chassis - sku, but no components" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION_24, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_comps, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_comps, + .st_desc = "chassis - 2.4 version with comps" + }, { + .st_entry = SMBIOS_ENTRY_POINT_30, + .st_tvers = SMB_VERSION, + .st_libvers = SMB_VERSION, + .st_mktable = smbios_test_chassis_mktable_sku_nocomps, + .st_canopen = B_TRUE, + .st_verify = smbios_test_chassis_verify_sku_nocomps, + .st_desc = "chassis - sku + comps" + } }; static boolean_t @@ -374,6 +562,26 @@ smbios_test_run_one(const smbios_test_t *test) ret = B_TRUE; } + if (hdl != NULL && test_dirfd > -1) { + int fd; + char fname[PATH_MAX]; + + (void) snprintf(fname, sizeof (fname), "%s.smbios", + test->st_desc); + fd = openat(test_dirfd, fname, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + warn("failed to dump test %s, failed to open output " + "file", test->st_desc); + } else { + if (smbios_write(hdl, fd) != 0) { + warnx("failed to dump test %s: %s", + test->st_desc, + smbios_errmsg(smbios_errno(hdl))); + } else { + (void) close(fd); + } + } + } out: if (hdl != NULL) { smbios_close(hdl); @@ -393,16 +601,39 @@ out: } int -main(void) +main(int argc, char *argv[]) { - int err = 0; + int ret = 0, c; size_t i; + const char *outdir = NULL; + + while ((c = getopt(argc, argv, ":d:")) != -1) { + switch (c) { + case 'd': + outdir = optarg; + break; + case '?': + errx(EXIT_FAILURE, "unknown option: -%c", optopt); + case ':': + errx(EXIT_FAILURE, "-%c requires an operand", optopt); + } + } + + if (outdir != NULL) { + if ((test_dirfd = open(outdir, O_RDONLY)) < 0) { + err(EXIT_FAILURE, "failed to open %s", outdir); + } + } for (i = 0; i < ARRAY_SIZE(smbios_tests); i++) { if (!smbios_test_run_one(&smbios_tests[i])) { - err = 1; + ret = 1; } } - return (err); + if (ret == 0) { + (void) printf("All tests passed successfully\n"); + } + + return (ret); } diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test.h b/usr/src/test/util-tests/tests/smbios/smbios_test.h index c6490f1d13..341eb47255 100644 --- a/usr/src/test/util-tests/tests/smbios/smbios_test.h +++ b/usr/src/test/util-tests/tests/smbios/smbios_test.h @@ -11,7 +11,7 @@ /* * Copyright 2019 Robert Mustacchi - * Copyright 2020 Oxide Computer Company + * Copyright 2021 Oxide Computer Company */ #ifndef _SMBIOS_TEST_H @@ -58,6 +58,7 @@ 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 void smbios_test_table_str_fini(smbios_test_table_t *); 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 *); @@ -81,10 +82,15 @@ typedef struct smbios_test { extern boolean_t smbios_test_slot_mktable(smbios_test_table_t *); extern boolean_t smbios_test_slot_mktable_34_nopeers(smbios_test_table_t *); extern boolean_t smbios_test_slot_mktable_34_peers(smbios_test_table_t *); +extern boolean_t smbios_test_slot_mktable_35(smbios_test_table_t *); extern boolean_t smbios_test_slot_verify(smbios_hdl_t *); extern boolean_t smbios_test_slot_verify_34_nopeers(smbios_hdl_t *); extern boolean_t smbios_test_slot_verify_34_peers(smbios_hdl_t *); +extern boolean_t smbios_test_slot_verify_34_overrun(smbios_hdl_t *); +extern boolean_t smbios_test_slot_verify_35(smbios_hdl_t *); + extern boolean_t smbios_test_badvers_mktable(smbios_test_table_t *); +extern boolean_t smbios_test_verify_badids(smbios_hdl_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 *); @@ -108,6 +114,39 @@ 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 *); +extern boolean_t smbios_test_strprop_mktable_invlen1(smbios_test_table_t *); +extern boolean_t smbios_test_strprop_mktable_invlen2(smbios_test_table_t *); +extern boolean_t smbios_test_strprop_mktable_badstr(smbios_test_table_t *); +extern boolean_t smbios_test_strprop_mktable_basic(smbios_test_table_t *); +extern boolean_t smbios_test_strprop_verify_invlen1(smbios_hdl_t *); +extern boolean_t smbios_test_strprop_verify_invlen2(smbios_hdl_t *); +extern boolean_t smbios_test_strprop_verify_badstr(smbios_hdl_t *); +extern boolean_t smbios_test_strprop_verify_badtype(smbios_hdl_t *); +extern boolean_t smbios_test_strprop_verify_basic(smbios_hdl_t *); + +extern boolean_t smbios_test_fwinfo_mktable_invlen_base(smbios_test_table_t *); +extern boolean_t smbios_test_fwinfo_mktable_invlen_comps(smbios_test_table_t *); +extern boolean_t smbios_test_fwinfo_mktable_nocomps(smbios_test_table_t *); +extern boolean_t smbios_test_fwinfo_mktable_comps(smbios_test_table_t *); +extern boolean_t smbios_test_fwinfo_verify_invlen_base(smbios_hdl_t *); +extern boolean_t smbios_test_fwinfo_verify_invlen_comps(smbios_hdl_t *); +extern boolean_t smbios_test_fwinfo_verify_badtype(smbios_hdl_t *); +extern boolean_t smbios_test_fwinfo_verify_nocomps(smbios_hdl_t *); +extern boolean_t smbios_test_fwinfo_verify_comps(smbios_hdl_t *); + +extern boolean_t smbios_test_verify_strings(smbios_hdl_t *); + +extern boolean_t smbios_test_chassis_mktable_invlen_base(smbios_test_table_t *); +extern boolean_t smbios_test_chassis_mktable_base(smbios_test_table_t *); +extern boolean_t smbios_test_chassis_mktable_comps(smbios_test_table_t *); +extern boolean_t smbios_test_chassis_mktable_sku(smbios_test_table_t *); +extern boolean_t smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t *); +extern boolean_t smbios_test_chassis_verify_invlen(smbios_hdl_t *); +extern boolean_t smbios_test_chassis_verify_base(smbios_hdl_t *); +extern boolean_t smbios_test_chassis_verify_comps(smbios_hdl_t *); +extern boolean_t smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t *); +extern boolean_t smbios_test_chassis_verify_sku(smbios_hdl_t *); + #ifdef __cplusplus } #endif diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_chassis.c b/usr/src/test/util-tests/tests/smbios/smbios_test_chassis.c new file mode 100644 index 0000000000..1d6ef45505 --- /dev/null +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_chassis.c @@ -0,0 +1,556 @@ +/* + * 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 2021 Oxide Computer Company + */ + +/* + * Tests for SMBIOS Type 3 - SMB_TYPE_CHASSIS. + */ + +#include "smbios_test.h" + +static const char *smbios_chassis_mfg = "Shrina"; +static const char *smbios_chassis_vers = "7R"; +static const char *smbios_chassis_serial = "What's my number?"; +static const char *smbios_chassis_asset = "lost"; +static const char *smbios_chassis_sku = "Proud"; +static const uint32_t smbios_chassis_oem = 0x36105997; +static const uint8_t smbios_chassis_uheight = 7; + +boolean_t +smbios_test_chassis_mktable_invlen_base(smbios_test_table_t *table) +{ + smb_header_t hdr; + + hdr.smbh_type = SMB_TYPE_CHASSIS; + hdr.smbh_len = sizeof (hdr); + + (void) smbios_test_table_append(table, &hdr, sizeof (hdr)); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +static void +smbios_test_chassis_mktable_fill_chassis(smb_chassis_t *ch) +{ + ch->smbch_hdr.smbh_type = SMB_TYPE_CHASSIS; + ch->smbch_hdr.smbh_len = sizeof (*ch); + ch->smbch_manufacturer = 1; + ch->smbch_type = SMB_CHT_LUNCHBOX; + ch->smbch_version = 2; + ch->smbch_serial = 3; + ch->smbch_asset = 4; + ch->smbch_bustate = SMB_CHST_SAFE; + ch->smbch_psstate = SMB_CHST_NONREC; + ch->smbch_thstate = SMB_CHST_WARNING; + ch->smbch_security = SMB_CHSC_NONE; + ch->smbch_oemdata = htole32(smbios_chassis_oem); + ch->smbch_uheight = smbios_chassis_uheight; + ch->smbch_cords = smbios_chassis_uheight - 1; + ch->smbch_cn = 0; + ch->smbch_cm = sizeof (smb_chassis_entry_t); +} + +static void +smbios_test_chassis_mktable_fill_entries(smb_chassis_entry_t *ents) +{ + ents[0].smbce_type = SMB_TYPE_COOLDEV | (1 << 7); + ents[0].smbce_min = 1; + ents[0].smbce_max = 42; + ents[1].smbce_type = SMB_BBT_IO; + ents[1].smbce_min = 5; + ents[1].smbce_max = 123; +} + +static void +smbios_test_chassis_mktable_append_strings(smbios_test_table_t *table) +{ + smbios_test_table_append_string(table, smbios_chassis_mfg); + smbios_test_table_append_string(table, smbios_chassis_vers); + smbios_test_table_append_string(table, smbios_chassis_serial); + smbios_test_table_append_string(table, smbios_chassis_asset); +} + +/* + * This is an SMBIOS 2.4-esque table. + */ +boolean_t +smbios_test_chassis_mktable_base(smbios_test_table_t *table) +{ + smb_chassis_t ch; + + smbios_test_chassis_mktable_fill_chassis(&ch); + (void) smbios_test_table_append(table, &ch, sizeof (ch)); + smbios_test_chassis_mktable_append_strings(table); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_chassis_mktable_comps(smbios_test_table_t *table) +{ + smb_chassis_t ch; + smb_chassis_entry_t ents[2]; + + smbios_test_chassis_mktable_fill_chassis(&ch); + smbios_test_chassis_mktable_fill_entries(ents); + ch.smbch_hdr.smbh_len += sizeof (ents); + ch.smbch_cn = 2; + (void) smbios_test_table_append(table, &ch, sizeof (ch)); + smbios_test_table_append_raw(table, ents, sizeof (ents)); + smbios_test_chassis_mktable_append_strings(table); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t *table) +{ + smb_chassis_t ch; + const uint8_t sku_str = 5; + + smbios_test_chassis_mktable_fill_chassis(&ch); + ch.smbch_hdr.smbh_len++; + (void) smbios_test_table_append(table, &ch, sizeof (ch)); + smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str)); + smbios_test_chassis_mktable_append_strings(table); + smbios_test_table_append_string(table, smbios_chassis_sku); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_chassis_mktable_sku(smbios_test_table_t *table) +{ + smb_chassis_t ch; + const uint8_t sku_str = 5; + smb_chassis_entry_t ents[2]; + + ch.smbch_cn = 2; + + smbios_test_chassis_mktable_fill_chassis(&ch); + smbios_test_chassis_mktable_fill_entries(ents); + ch.smbch_hdr.smbh_len += sizeof (ents) + 1; + (void) smbios_test_table_append(table, &ch, sizeof (ch)); + smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str)); + smbios_test_chassis_mktable_append_strings(table); + smbios_test_table_append_string(table, smbios_chassis_sku); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_chassis_verify_invlen(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_chassis_t ch; + + if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { + warnx("failed to lookup SMBIOS chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) != -1) { + warnx("accidentally parsed invalid chassis as valid"); + return (B_FALSE); + } + + if (smbios_errno(hdl) != ESMB_SHORT) { + warnx("encountered wrong error for chassis, expected: " + "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); + return (B_FALSE); + } + + return (B_TRUE); +} + +static boolean_t +smbios_test_chassis_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp, + smbios_chassis_t *ch) +{ + boolean_t ret = B_TRUE; + smbios_info_t info; + + if (ch->smbc_oemdata != smbios_chassis_oem) { + warnx("chassis state mismatch, found unexpected oem data: 0x%x", + ch->smbc_oemdata); + ret = B_FALSE; + } + + if (ch->smbc_lock != 0) { + warnx("chassis state mismatch, found unexpected lock: 0x%x", + ch->smbc_lock); + ret = B_FALSE; + } + + if (ch->smbc_type != SMB_CHT_LUNCHBOX) { + warnx("chassis state mismatch, found unexpected type: 0x%x", + ch->smbc_type); + ret = B_FALSE; + } + + if (ch->smbc_bustate != SMB_CHST_SAFE) { + warnx("chassis state mismatch, found unexpected boot state: " + "0x%x", ch->smbc_bustate); + ret = B_FALSE; + } + + if (ch->smbc_psstate != SMB_CHST_NONREC) { + warnx("chassis state mismatch, found unexpected power state: " + "0x%x", ch->smbc_psstate); + ret = B_FALSE; + } + + if (ch->smbc_thstate != SMB_CHST_WARNING) { + warnx("chassis state mismatch, found unexpected thermal state: " + "0x%x", ch->smbc_thstate); + ret = B_FALSE; + } + + if (ch->smbc_security != SMB_CHSC_NONE) { + warnx("chassis state mismatch, found unexpected security " + "value: 0x%x", ch->smbc_security); + ret = B_FALSE; + } + + if (ch->smbc_uheight != smbios_chassis_uheight) { + warnx("chassis state mismatch, found unexpected uheight value: " + "0x%x", ch->smbc_uheight); + ret = B_FALSE; + } + + if (ch->smbc_cords != smbios_chassis_uheight - 1) { + warnx("chassis state mismatch, found unexpected cords value: " + "0x%x", ch->smbc_cords); + ret = B_FALSE; + } + + if (ch->smbc_elemlen != sizeof (smb_chassis_entry_t)) { + warnx("chassis state mismatch, found unexpected elemlen value: " + "0x%x", ch->smbc_elemlen); + ret = B_FALSE; + } + + if (smbios_info_common(hdl, sp->smbstr_id, &info) != 0) { + warnx("failed to get common chassis info: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (strcmp(info.smbi_manufacturer, smbios_chassis_mfg) != 0) { + warnx("chassis state mismatch, found unexpected mfg: " + "%s", info.smbi_manufacturer); + ret = B_FALSE; + } + + if (strcmp(info.smbi_version, smbios_chassis_vers) != 0) { + warnx("chassis state mismatch, found unexpected version: %s", + info.smbi_version); + ret = B_FALSE; + } + + if (strcmp(info.smbi_serial, smbios_chassis_serial) != 0) { + warnx("chassis state mismatch, found unexpected serial: %s", + info.smbi_serial); + ret = B_FALSE; + } + + if (strcmp(info.smbi_asset, smbios_chassis_asset) != 0) { + warnx("chassis state mismatch, found unexpected asset: %s", + info.smbi_asset); + ret = B_FALSE; + } + + return (ret); +} + +boolean_t +smbios_test_chassis_verify_base(smbios_hdl_t *hdl) +{ + boolean_t ret = B_TRUE; + smbios_struct_t sp; + smbios_chassis_t ch; + smbios_chassis_entry_t *elts; + uint_t nelts; + + if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { + warnx("failed to lookup SMBIOS chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { + warnx("failed to get chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { + ret = B_FALSE; + } + + if (ch.smbc_elems != 0) { + warnx("chassis state mismatch, found unexpected number of " + "elements: 0x%x", ch.smbc_elems); + ret = B_FALSE; + } + + if (strcmp(ch.smbc_sku, "") != 0) { + warnx("chassis state mismatch, found unexpected sku: %s", + ch.smbc_sku); + ret = B_FALSE; + } + + if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) { + warnx("failed to get chassis elements: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (nelts != 0) { + warnx("chassis state mismatch, smbios_info_chassis_elts() " + "returned a non-zero number of entries: %u", nelts); + ret = B_FALSE; + } + + if (elts != NULL) { + warnx("chassis state mismatch, smbios_info_chassis_elts() " + "returned a non-NULL pointer: %p", elts); + ret = B_FALSE; + } + + return (ret); +} + +boolean_t +smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t *hdl) +{ + boolean_t ret = B_TRUE; + smbios_struct_t sp; + smbios_chassis_t ch; + smbios_chassis_entry_t *elts; + uint_t nelts; + + if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { + warnx("failed to lookup SMBIOS chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { + warnx("failed to get chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { + ret = B_FALSE; + } + + if (ch.smbc_elems != 0) { + warnx("chassis state mismatch, found unexpected number of " + "elements: 0x%x", ch.smbc_elems); + ret = B_FALSE; + } + + if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) { + warnx("chassis state mismatch, found unexpected sku: %s", + ch.smbc_sku); + ret = B_FALSE; + } + + if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) { + warnx("failed to get chassis elements: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (nelts != 0) { + warnx("chassis state mismatch, smbios_info_chassis_elts() " + "returned a non-zero number of entries: %u", nelts); + ret = B_FALSE; + } + + if (elts != NULL) { + warnx("chassis state mismatch, smbios_info_chassis_elts() " + "returned a non-NULL pointer: %p", elts); + ret = B_FALSE; + } + + + return (ret); +} + +static boolean_t +smbios_test_chassis_verify_common_comps(smbios_hdl_t *hdl, smbios_struct_t *sp) +{ + boolean_t ret = B_TRUE; + smbios_chassis_entry_t *elts; + uint_t nelts; + + if (smbios_info_chassis_elts(hdl, sp->smbstr_id, &nelts, &elts) != 0) { + warnx("failed to get chassis elements: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (nelts != 2) { + warnx("chassis state mismatch, smbios_info_chassis_elts() " + "returned the wrong number of entries: %u", nelts); + return (B_FALSE); + } + + if (elts[0].smbce_type != SMB_CELT_SMBIOS) { + warnx("chassis elts[0] type mismatch, found: %u", + elts[0].smbce_type); + ret = B_FALSE; + } + + if (elts[0].smbce_elt != SMB_TYPE_COOLDEV) { + warnx("chassis elts[0] elt type mismatch, found: %u", + elts[0].smbce_elt); + ret = B_FALSE; + } + + if (elts[0].smbce_min != 1) { + warnx("chassis elts[0] minimum number mismatch, found: %u", + elts[0].smbce_min); + ret = B_FALSE; + } + + if (elts[0].smbce_max != 42) { + warnx("chassis elts[0] maximum number mismatch, found: %u", + elts[0].smbce_max); + ret = B_FALSE; + } + + if (elts[1].smbce_type != SMB_CELT_BBOARD) { + warnx("chassis elts[1] type mismatch, found: %u", + elts[1].smbce_type); + ret = B_FALSE; + } + + if (elts[1].smbce_elt != SMB_BBT_IO) { + warnx("chassis elts[1] elt type mismatch, found: %u", + elts[1].smbce_elt); + ret = B_FALSE; + } + + if (elts[1].smbce_min != 5) { + warnx("chassis elts[1] minimum number mismatch, found: %u", + elts[1].smbce_min); + ret = B_FALSE; + } + + if (elts[1].smbce_max != 123) { + warnx("chassis elts[1] maximum number mismatch, found: %u", + elts[1].smbce_max); + ret = B_FALSE; + } + return (ret); +} + +boolean_t +smbios_test_chassis_verify_comps(smbios_hdl_t *hdl) +{ + boolean_t ret = B_TRUE; + smbios_struct_t sp; + smbios_chassis_t ch; + + if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { + warnx("failed to lookup SMBIOS chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { + warnx("failed to get chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { + ret = B_FALSE; + } + + if (ch.smbc_elems != 2) { + warnx("chassis state mismatch, found unexpected number of " + "elements: 0x%x", ch.smbc_elems); + ret = B_FALSE; + } + + if (strcmp(ch.smbc_sku, "") != 0) { + warnx("chassis state mismatch, found unexpected sku: %s", + ch.smbc_sku); + ret = B_FALSE; + } + + if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) { + ret = B_FALSE; + } + + return (ret); +} + + +boolean_t +smbios_test_chassis_verify_sku(smbios_hdl_t *hdl) +{ + boolean_t ret = B_TRUE; + smbios_struct_t sp; + smbios_chassis_t ch; + + if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { + warnx("failed to lookup SMBIOS chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { + warnx("failed to get chassis: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { + ret = B_FALSE; + } + + if (ch.smbc_elems != 2) { + warnx("chassis state mismatch, found unexpected number of " + "elements: 0x%x", ch.smbc_elems); + ret = B_FALSE; + } + + if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) { + warnx("chassis state mismatch, found unexpected sku: %s", + ch.smbc_sku); + ret = B_FALSE; + } + + if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) { + ret = B_FALSE; + } + + return (ret); +} 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 index 0bca13c7bb..5211eebc74 100644 --- a/usr/src/test/util-tests/tests/smbios/smbios_test_errors.c +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_errors.c @@ -11,6 +11,7 @@ /* * Copyright 2019 Robert Mustacchi + * Copyright 2021 Oxide Computer Company */ /* @@ -26,3 +27,63 @@ smbios_test_badvers_mktable(smbios_test_table_t *table) smbios_test_table_append_eot(table); return (B_TRUE); } + +typedef int (*smbios_lookup_f)(smbios_hdl_t *, id_t, void *); +typedef struct { + smbios_lookup_f sif_func; + const char *sif_name; +} smbios_info_func_t; + +static smbios_info_func_t smbios_lookup_funcs[] = { + { (smbios_lookup_f)smbios_info_bboard, "bboard" }, + { (smbios_lookup_f)smbios_info_chassis, "chassis" }, + { (smbios_lookup_f)smbios_info_processor, "processor" }, + { (smbios_lookup_f)smbios_info_extprocessor, "extprocessor" }, + { (smbios_lookup_f)smbios_info_cache, "cache" }, + { (smbios_lookup_f)smbios_info_pointdev, "pointdev" }, + { (smbios_lookup_f)smbios_info_battery, "battery" }, + { (smbios_lookup_f)smbios_info_port, "port" }, + { (smbios_lookup_f)smbios_info_extport, "extport" }, + { (smbios_lookup_f)smbios_info_slot, "slot" }, + { (smbios_lookup_f)smbios_info_obdevs_ext, "obdevs_ext" }, + { (smbios_lookup_f)smbios_info_memarray, "memarray" }, + { (smbios_lookup_f)smbios_info_extmemarray, "extmemarray" }, + { (smbios_lookup_f)smbios_info_memarrmap, "memarrmap" }, + { (smbios_lookup_f)smbios_info_memdevice, "memdevice" }, + { (smbios_lookup_f)smbios_info_extmemdevice, "extmemdevice" }, + { (smbios_lookup_f)smbios_info_memdevmap, "memdevmap" }, + { (smbios_lookup_f)smbios_info_vprobe, "vprobe" }, + { (smbios_lookup_f)smbios_info_cooldev, "cooldev" }, + { (smbios_lookup_f)smbios_info_tprobe, "tprobe" }, + { (smbios_lookup_f)smbios_info_iprobe, "iprobe" }, + { (smbios_lookup_f)smbios_info_powersup, "powersup" }, + { (smbios_lookup_f)smbios_info_pciexrc, "pciexrc" }, + { (smbios_lookup_f)smbios_info_processor_info, "processor_info" }, + { (smbios_lookup_f)smbios_info_processor_riscv, "processor_riscv" }, + { (smbios_lookup_f)smbios_info_strprop, "strprop" }, + { (smbios_lookup_f)smbios_info_fwinfo, "fwinfo" } +}; + +/* + * Go through and verify that if we give an explicit lookup a bad id, it + * properly detects that and errors. We simply use SMB_ID_NOTSUP, which should + * always trigger the internal lookup to fail. In addition, we always pass NULL + * for the actual data pointer to make sure that if we get further, we'll crash + * on writing to a NULL pointer. + */ +boolean_t +smbios_test_verify_badids(smbios_hdl_t *hdl) +{ + boolean_t ret = B_TRUE; + + for (size_t i = 0; i < ARRAY_SIZE(smbios_lookup_funcs); i++) { + if (smbios_lookup_funcs[i].sif_func(hdl, SMB_ID_NOTSUP, NULL) != + -1) { + warnx("smbios_info_%s somehow didn't fail?!", + smbios_lookup_funcs[i].sif_name); + ret = B_FALSE; + } + } + + return (ret); +} diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_fwinfo.c b/usr/src/test/util-tests/tests/smbios/smbios_test_fwinfo.c new file mode 100644 index 0000000000..4567293590 --- /dev/null +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_fwinfo.c @@ -0,0 +1,429 @@ +/* + * 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 2021 Oxide Computer Company + */ + +/* + * Tests for SMBIOS type 46 - SMB_TYPE_STRPROP. + */ + +#include "smbios_test.h" + +static const char *smbios_fwinfo_name = "Sheikah Slate"; +static const char *smbios_fwinfo_vers = "1.3.1"; +static const char *smbios_fwinfo_id = "ganon"; +static const char *smbios_fwinfo_reldate = "2017-03-03"; +static const char *smbios_fwinfo_mfg = "The Goddess Hylia"; +static const char *smbios_fwinfo_lsv = "zelda"; +static const uint64_t smbios_fwinfo_size = 0xb0111b; +static const uint_t smbios_fwinfo_ncomps = 23; +static const uint8_t smbios_fwinfo_versid = 0x66; + +static void +smbios_test_fwinfo_mktable_common_fwinfo(smb_fwinfo_t *fw) +{ + fw->smbfwii_hdr.smbh_type = SMB_TYPE_FWINFO; + fw->smbfwii_hdr.smbh_len = sizeof (*fw); + fw->smbfwii_name = 1; + fw->smbfwii_vers = 2; + fw->smbfwii_vers_fmt = smbios_fwinfo_versid; + fw->smbfwii_id = 3; + fw->smbfwii_id_fmt = smbios_fwinfo_versid; + fw->smbfwii_reldate = 4; + fw->smbfwii_mfg = 5; + fw->smbfwii_lsv = 6; + fw->smbfwii_imgsz = htole64(smbios_fwinfo_size); + fw->smbfwii_chars = SMB_FWC_WP; + fw->smbfwii_state = SMB_FWS_UA_OFFLINE; + fw->smbfwii_ncomps = 0; +} + +static void +smbios_test_fwinfo_mktable_common_fini(smbios_test_table_t *table) +{ + smbios_test_table_append_string(table, smbios_fwinfo_name); + smbios_test_table_append_string(table, smbios_fwinfo_vers); + smbios_test_table_append_string(table, smbios_fwinfo_id); + smbios_test_table_append_string(table, smbios_fwinfo_reldate); + smbios_test_table_append_string(table, smbios_fwinfo_mfg); + smbios_test_table_append_string(table, smbios_fwinfo_lsv); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); +} + +/* + * Generate a table that's too short to get basic info. + */ +boolean_t +smbios_test_fwinfo_mktable_invlen_base(smbios_test_table_t *table) +{ + smb_header_t hdr; + + hdr.smbh_type = SMB_TYPE_FWINFO; + hdr.smbh_len = sizeof (hdr); + + (void) smbios_test_table_append(table, &hdr, sizeof (hdr)); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +/* + * Generate a table where the table is too short for a specified number of + * components. + */ +boolean_t +smbios_test_fwinfo_mktable_invlen_comps(smbios_test_table_t *table) +{ + smb_fwinfo_t fw; + + smbios_test_fwinfo_mktable_common_fwinfo(&fw); + fw.smbfwii_ncomps = smbios_fwinfo_ncomps; + (void) smbios_test_table_append(table, &fw, sizeof (fw)); + smbios_test_fwinfo_mktable_common_fini(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_fwinfo_mktable_nocomps(smbios_test_table_t *table) +{ + smb_fwinfo_t fw; + + smbios_test_fwinfo_mktable_common_fwinfo(&fw); + (void) smbios_test_table_append(table, &fw, sizeof (fw)); + smbios_test_fwinfo_mktable_common_fini(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_fwinfo_mktable_comps(smbios_test_table_t *table) +{ + smb_fwinfo_t fw; + + smbios_test_fwinfo_mktable_common_fwinfo(&fw); + + fw.smbfwii_hdr.smbh_len += smbios_fwinfo_ncomps * sizeof (uint16_t); + fw.smbfwii_ncomps = smbios_fwinfo_ncomps; + (void) smbios_test_table_append(table, &fw, sizeof (fw)); + + for (uint_t i = 0; i < fw.smbfwii_ncomps; i++) { + uint16_t comp = 0x2300 + i; + + smbios_test_table_append_raw(table, &comp, sizeof (comp)); + } + smbios_test_fwinfo_mktable_common_fini(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_fwinfo_verify_badtype(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_fwinfo_t fw; + + 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_fwinfo(hdl, sp.smbstr_id, &fw) != -1) { + warnx("accidentally parsed invalid fwinfo information as " + "valid"); + return (B_FALSE); + } + + if (smbios_errno(hdl) != ESMB_TYPE) { + warnx("encountered wrong error for fwinfo, expected: " + "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); + return (B_FALSE); + } + + return (B_TRUE); +} + +boolean_t +smbios_test_fwinfo_verify_invlen_base(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_fwinfo_t fw; + + if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { + warnx("failed to lookup SMBIOS fwinfo: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) != -1) { + warnx("accidentally parsed invalid fwinfo information as " + "valid"); + return (B_FALSE); + } + + if (smbios_errno(hdl) != ESMB_SHORT) { + warnx("encountered wrong error for fwinfo, expected: " + "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); + return (B_FALSE); + } + + return (B_TRUE); +} + +static boolean_t +smbios_test_fwinfo_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp, + const smbios_fwinfo_t *fw) +{ + boolean_t ret = B_TRUE; + smbios_info_t info; + + if (strcmp(fw->smbfw_name, smbios_fwinfo_name) != 0) { + warnx("firmware inventory name mismatch, found %s", + fw->smbfw_name); + ret = B_FALSE; + } + + if (strcmp(fw->smbfw_id, smbios_fwinfo_id) != 0) { + warnx("firmware inventory id mismatch, found %s", + fw->smbfw_id); + ret = B_FALSE; + } + + if (strcmp(fw->smbfw_reldate, smbios_fwinfo_reldate) != 0) { + warnx("firmware inventory release date mismatch, found %s", + fw->smbfw_reldate); + ret = B_FALSE; + } + + if (strcmp(fw->smbfw_lsv, smbios_fwinfo_lsv) != 0) { + warnx("firmware inventory lsv mismatch, found %s", + fw->smbfw_lsv); + ret = B_FALSE; + } + + if (fw->smbfw_imgsz != smbios_fwinfo_size) { + warnx("firmware inventory size mismatch, found 0x%" PRIx64, + fw->smbfw_imgsz); + ret = B_FALSE; + } + + if (fw->smbfw_chars != SMB_FWC_WP) { + warnx("firmware inventory chars mismatch, found 0x%x", + fw->smbfw_chars); + ret = B_FALSE; + } + + if (fw->smbfw_state != SMB_FWS_UA_OFFLINE) { + warnx("firmware inventory state mismatch, found 0x%x", + fw->smbfw_state); + ret = B_FALSE; + } + + if (fw->smbfw_vers_fmt != smbios_fwinfo_versid) { + warnx("firmware inventory version format mismatch, found 0x%x", + fw->smbfw_vers_fmt); + ret = B_FALSE; + } + + if (fw->smbfw_id_fmt != smbios_fwinfo_versid) { + warnx("firmware inventory ID format mismatch, found 0x%x", + fw->smbfw_id_fmt); + ret = B_FALSE; + } + + if (smbios_info_common(hdl, sp->smbstr_id, &info) == -1) { + warnx("failed to get firmware inventory common items: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (strcmp(info.smbi_manufacturer, smbios_fwinfo_mfg) != 0) { + warnx("firmware inventory manufacturer mismatch, found %s", + info.smbi_manufacturer); + ret = B_FALSE; + } + + if (strcmp(info.smbi_version, smbios_fwinfo_vers) != 0) { + warnx("firmware inventory version mismatch, found %s", + info.smbi_version); + ret = B_FALSE; + } + + return (ret); +} + +boolean_t +smbios_test_fwinfo_verify_nocomps(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_fwinfo_t fw; + uint_t ncomps; + smbios_fwinfo_comp_t *comps; + boolean_t ret = B_TRUE; + + if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { + warnx("failed to lookup SMBIOS fwinfo: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) == -1) { + warnx("failed to get firmware inventory: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_fwinfo_verify_common(hdl, &sp, &fw)) { + ret = B_FALSE; + } + + if (fw.smbfw_ncomps != 0) { + warnx("firmware inventory ncomps mismatch, found 0x%x", + fw.smbfw_ncomps); + ret = B_FALSE; + } + + if (smbios_info_fwinfo_comps(hdl, sp.smbstr_id, &ncomps, &comps) != 0) { + warnx("failed to get components: %s", + smbios_errmsg(smbios_errno(hdl))); + ret = B_FALSE; + } + + if (ncomps != 0) { + warnx("smbios_info_fwinfo_comps() returned wrong number of " + "comps: 0x%x", ncomps); + ret = B_FALSE; + } + + if (comps != NULL) { + warnx("smbios_info_fwinfo_comps() gave a non-NULL comps " + "pointer: %p", comps); + ret = B_FALSE; + } + + smbios_info_fwinfo_comps_free(hdl, ncomps, comps); + + return (ret); +} + +boolean_t +smbios_test_fwinfo_verify_invlen_comps(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_fwinfo_t fw; + uint_t ncomps; + smbios_fwinfo_comp_t *comps; + boolean_t ret = B_TRUE; + + if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { + warnx("failed to lookup SMBIOS fwinfo: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) == -1) { + warnx("failed to get firmware inventory: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_fwinfo_verify_common(hdl, &sp, &fw)) { + ret = B_FALSE; + } + + if (fw.smbfw_ncomps != smbios_fwinfo_ncomps) { + warnx("firmware inventory ncomps mismatch, found 0x%x", + fw.smbfw_ncomps); + ret = B_FALSE; + } + + if (smbios_info_fwinfo_comps(hdl, sp.smbstr_id, &ncomps, &comps) != + -1) { + warnx("accidentally parsed invalid fwinfo components as " + "valid"); + return (B_FALSE); + } + + if (smbios_errno(hdl) != ESMB_SHORT) { + warnx("encountered wrong error for fwinfo comps, expected: " + "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); + return (B_FALSE); + } + + return (ret); +} + + + +boolean_t +smbios_test_fwinfo_verify_comps(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_fwinfo_t fw; + uint_t ncomps; + smbios_fwinfo_comp_t *comps; + boolean_t ret = B_TRUE; + + if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { + warnx("failed to lookup SMBIOS fwinfo: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) == -1) { + warnx("failed to get firmware inventory: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (!smbios_test_fwinfo_verify_common(hdl, &sp, &fw)) { + ret = B_FALSE; + } + + if (fw.smbfw_ncomps != smbios_fwinfo_ncomps) { + warnx("firmware inventory ncomps mismatch, found 0x%x", + fw.smbfw_ncomps); + ret = B_FALSE; + } + + if (smbios_info_fwinfo_comps(hdl, sp.smbstr_id, &ncomps, &comps) != 0) { + warnx("failed to get components: %s", + smbios_errmsg(smbios_errno(hdl))); + ret = B_FALSE; + } + + if (ncomps != smbios_fwinfo_ncomps) { + warnx("smbios_info_fwinfo_comps() returned wrong number of " + "comps: 0x%x", ncomps); + ret = B_FALSE; + } + + if (comps == NULL) { + warnx("smbios_info_fwinfo_comps() gave a NULL comps pointer"); + ret = B_FALSE; + } else { + for (uint_t i = 0; i < smbios_fwinfo_ncomps; i++) { + if (comps[i].smbfwe_id != 0x2300 + i) { + warnx("component id %u is wrong: 0x%x", i, + comps[i]); + ret = B_FALSE; + } + } + } + + smbios_info_fwinfo_comps_free(hdl, ncomps, comps); + + 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 index 178de212ae..a3455f9de7 100644 --- a/usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_pinfo.c @@ -11,6 +11,7 @@ /* * Copyright 2019 Robert Mustacchi + * Copyright 2021 Oxide Computer Company */ /* @@ -330,13 +331,13 @@ smbios_test_pinfo_verify_riscv(smbios_hdl_t *hdl) } if (strcmp(smbios_riscv_isa_desc(SMB_RV_ISA_C), "Compressed") != 0) { - warnx("SMB_RV_ISA_Q string desc mismatch, found %s", + warnx("SMB_RV_ISA_C 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) { + "Quad-precision floating-point") != 0) { warnx("SMB_RV_ISA_Q string desc mismatch, found %s", smbios_riscv_isa_desc(SMB_RV_ISA_Q)); ret = B_FALSE; 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 index 95a709a088..819234aece 100644 --- a/usr/src/test/util-tests/tests/smbios/smbios_test_slot.c +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_slot.c @@ -11,7 +11,7 @@ /* * Copyright (c) 2018, Joyent, Inc. - * Copyright 2020 Oxide Computer Company + * Copyright 2021 Oxide Computer Company */ /* @@ -26,6 +26,8 @@ static uint8_t smbios_slot_df = 0x23; static uint8_t smbios_slot_info = 0x65; static uint16_t smbios_slot_pitch = 0x12af; +static size_t smbios_slot_34_contlen = offsetof(smb_slot_cont_t, smbsl_height); + static void smbios_test_slot_fill(smb_slot_t *slot) { @@ -50,7 +52,6 @@ smbios_test_slot_mktable(smbios_test_table_t *table) { smb_slot_t slot; smb_slot_peer_t peers[2]; - const uint8_t endstring = 0; smbios_test_slot_fill(&slot); @@ -68,61 +69,72 @@ smbios_test_slot_mktable(smbios_test_table_t *table) 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_raw(table, peers, sizeof (peers)); + smbios_test_table_append_string(table, smbios_test_name); + smbios_test_table_str_fini(table); smbios_test_table_append_eot(table); return (B_TRUE); } -/* - * 3.4 introduced additional data after peers. This verison constructs a variant - * with no peers. - */ -boolean_t -smbios_test_slot_mktable_34_nopeers(smbios_test_table_t *table) +static boolean_t +smbios_test_slot_mktable_nopeers(smbios_test_table_t *table, boolean_t is_35) { smb_slot_t slot; smb_slot_cont_t cont; - const uint8_t endstring = 0; + size_t contlen; + + if (is_35) { + contlen = sizeof (cont); + } else { + contlen = smbios_slot_34_contlen; + } smbios_test_slot_fill(&slot); - slot.smbsl_hdr.smbh_len = SMB_SLOT_CONT_START + sizeof (cont); + slot.smbsl_hdr.smbh_len = SMB_SLOT_CONT_START + contlen; cont.smbsl_info = smbios_slot_info; cont.smbsl_pwidth = SMB_SLW_32X; cont.smbsl_pitch = htole16(smbios_slot_pitch); + cont.smbsl_height = SMB_SLHT_LP; (void) smbios_test_table_append(table, &slot, sizeof (slot)); - /* - * Append a raw zero to fill in the gaps that the peers would have had - * so the cont structure starts at the right offset. - */ - (void) smbios_test_table_append_raw(table, &endstring, - sizeof (endstring)); - (void) smbios_test_table_append_raw(table, &cont, sizeof (cont)); - (void) smbios_test_table_append_string(table, smbios_test_name); - (void) smbios_test_table_append_raw(table, &endstring, - sizeof (endstring)); + smbios_test_table_append_raw(table, &cont, contlen); + smbios_test_table_append_string(table, smbios_test_name); + smbios_test_table_str_fini(table); smbios_test_table_append_eot(table); + return (B_TRUE); } +/* + * 3.4 introduced additional data after peers. This version constructs a variant + * with no peers. + */ +boolean_t +smbios_test_slot_mktable_34_nopeers(smbios_test_table_t *table) +{ + return (smbios_test_slot_mktable_nopeers(table, B_FALSE)); +} + +boolean_t +smbios_test_slot_mktable_35(smbios_test_table_t *table) +{ + return (smbios_test_slot_mktable_nopeers(table, B_TRUE)); +} + boolean_t smbios_test_slot_mktable_34_peers(smbios_test_table_t *table) { smb_slot_t slot; smb_slot_cont_t cont; smb_slot_peer_t peers[1]; - const uint8_t endstring = 0; smbios_test_slot_fill(&slot); slot.smbsl_npeers = 1; slot.smbsl_hdr.smbh_len = SMB_SLOT_CONT_START + 5 * slot.smbsl_npeers + - sizeof (cont); + smbios_slot_34_contlen; peers[0].smbspb_group_no = htole16(1); peers[0].smbspb_bus = 0x42; @@ -134,18 +146,14 @@ smbios_test_slot_mktable_34_peers(smbios_test_table_t *table) cont.smbsl_pitch = htole16(smbios_slot_pitch); (void) smbios_test_table_append(table, &slot, sizeof (slot)); - (void) smbios_test_table_append_raw(table, peers, sizeof (peers)); - (void) smbios_test_table_append_raw(table, &endstring, - sizeof (endstring)); - (void) smbios_test_table_append_raw(table, &cont, sizeof (cont)); - (void) smbios_test_table_append_string(table, smbios_test_name); - (void) smbios_test_table_append_raw(table, &endstring, - sizeof (endstring)); + smbios_test_table_append_raw(table, peers, sizeof (peers)); + smbios_test_table_append_raw(table, &cont, smbios_slot_34_contlen); + smbios_test_table_append_string(table, smbios_test_name); + smbios_test_table_str_fini(table); smbios_test_table_append_eot(table); return (B_TRUE); } - static boolean_t smbios_test_slot_common(smbios_slot_t *slot) { @@ -306,13 +314,64 @@ smbios_test_slot_verify(smbios_hdl_t *hdl) return (B_TRUE); } +static boolean_t +smbios_test_slot_common_nopeers(smbios_hdl_t *hdl, smbios_struct_t *sp, + smbios_slot_t *slot) +{ + uint_t errs = 0; + uint_t npeers; + smbios_slot_peer_t *peers; + + if (slot->smbl_npeers != 0) { + 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 != 0) { + warnx("got wrong number of slot peers: %u", npeers); + errs++; + } + + if (peers != NULL) { + warnx("expected NULL peers pointer, but found %p", peers); + errs++; + } + + smbios_info_slot_peers_free(hdl, npeers, peers); + + if (slot->smbl_info != smbios_slot_info) { + warnx("found wrong slot info: 0x%x, expected 0x%x", + slot->smbl_info, smbios_slot_info); + errs++; + } + + if (slot->smbl_pwidth != SMB_SLW_32X) { + warnx("found wrong slot physical width: 0x%x, expected 0x%x", + slot->smbl_pwidth, SMB_SLW_32X); + errs++; + } + + if (slot->smbl_pitch != smbios_slot_pitch) { + warnx("found wrong slot pitch: 0x%x, expected 0x%x", + slot->smbl_pitch, smbios_slot_pitch); + errs++; + } + + return (errs == 0); +} + boolean_t smbios_test_slot_verify_34_nopeers(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) { @@ -331,45 +390,98 @@ smbios_test_slot_verify_34_nopeers(smbios_hdl_t *hdl) errs++; } - if (slot.smbl_npeers != 0) { - warnx("incorrect number of slot peers, found %u", - slot.smbl_npeers); + if (!smbios_test_slot_common_nopeers(hdl, &sp, &slot)) { errs++; } - if (smbios_info_slot_peers(hdl, sp.smbstr_id, &npeers, &peers) != 0) { - warnx("failed to get SMBIOS peer info: %s", + if (errs > 0) { + return (B_FALSE); + } + + return (B_TRUE); +} + +/* + * This is a variant of smbios_test_slot_verify_34_nopeers() that specifically + * uses an older library version and ensures that we don't overrun the + * smbios_slot_t. + */ +boolean_t +smbios_test_slot_verify_34_overrun(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_slot_t slot; + uint_t errs = 0; + + /* + * We purposefully set the values that are part of SMBIOS 3.5+ to bad + * values to make sure that we don't end up zeroing them. + */ + slot.smbl_height = 0xba; + + 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 (npeers != 0) { - warnx("got wrong number of slot peers: %u", npeers); + 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); + } + + if (slot.smbl_height != 0xba) { + warnx("smbios 3.4 slot structure was overrun, smbl_height " + "unexpectedly set to 0x%x", slot.smbl_height); errs++; } - if (peers != NULL) { - warnx("expected NULL peers pointer, but found %p", peers); + if (!smbios_test_slot_common(&slot)) { errs++; } - smbios_info_slot_peers_free(hdl, npeers, peers); + if (!smbios_test_slot_common_nopeers(hdl, &sp, &slot)) { + errs++; + } - if (slot.smbl_info != smbios_slot_info) { - warnx("found wrong slot info: 0x%x, expected 0x%x", - slot.smbl_info, smbios_slot_info); + if (errs > 0) { + return (B_FALSE); + } + + return (B_TRUE); +} + +boolean_t +smbios_test_slot_verify_35(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_slot_t slot; + 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); + } + + if (!smbios_test_slot_common(&slot)) { errs++; } - if (slot.smbl_pwidth != SMB_SLW_32X) { - warnx("found wrong slot physical width: 0x%x, expected 0x%x", - slot.smbl_pwidth, SMB_SLW_32X); + if (!smbios_test_slot_common_nopeers(hdl, &sp, &slot)) { errs++; } - if (slot.smbl_pitch != smbios_slot_pitch) { - warnx("found wrong slot pitch: 0x%x, expected 0x%x", - slot.smbl_pitch, smbios_slot_pitch); + if (slot.smbl_height != SMB_SLHT_LP) { + warnx("found wrong slot height: 0x%x, expected 0x%x", + slot.smbl_height, SMB_SLHT_LP); errs++; } diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_strings.c b/usr/src/test/util-tests/tests/smbios/smbios_test_strings.c new file mode 100644 index 0000000000..aef035266d --- /dev/null +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_strings.c @@ -0,0 +1,157 @@ +/* + * 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 2021 Oxide Computer Company + */ + +/* + * This is a hodgepodge to validate that the string tables are directionally + * correct. + */ + +#include "smbios_test.h" + +typedef const char *(*smbios_strfunc_f)(uint_t); + +typedef struct smbios_strtest { + smbios_strfunc_f ss_func; + uint_t ss_num; + const char *ss_str; +} smbios_strtest_t; + +static smbios_strtest_t smbios_strs[] = { + { smbios_battery_chem_desc, SMB_BDC_LEADACID, "Lead Acid" }, + { smbios_bboard_flag_name, SMB_BBFL_NEEDAUX, "SMB_BBFL_NEEDAUX" }, + { smbios_bboard_flag_name, SMB_BBFL_HOTSWAP, "SMB_BBFL_HOTSWAP" }, + { smbios_bboard_flag_desc, SMB_BBFL_REMOVABLE, "board is removable" }, + { smbios_bboard_flag_desc, SMB_BBFL_HOTSWAP, "board is hot-swappable" }, + { smbios_bboard_type_desc, SMB_BBT_PROC, "processor module" }, + { smbios_bboard_type_desc, SMB_BBT_MOTHER, "motherboard" }, + { smbios_bios_xb1_desc, SMB_BIOSXB1_ACPI, "ACPI is supported" }, + { smbios_bios_xb1_name, SMB_BIOSXB1_ACPI, "SMB_BIOSXB1_ACPI" }, + { smbios_bios_xb2_desc, SMB_BIOSXB2_VM, "SMBIOS table describes a VM" }, + { smbios_bios_xb2_name, SMB_BIOSXB2_UEFI, "SMB_BIOSXB2_UEFI" }, + { smbios_boot_desc, SMB_BOOT_NOMEDIA, "no bootable media" }, + { smbios_cache_assoc_desc, SMB_CAA_4WAY, "4-way set associative" }, + { smbios_cache_ctype_desc, SMB_CAT_BURST, "burst" }, + { smbios_cache_ctype_desc, SMB_CAT_SYNC, "synchronous" }, + { smbios_cache_ctype_name, SMB_CAT_ASYNC, "SMB_CAT_ASYNC" }, + { smbios_cache_ecc_desc, SMB_CAE_PARITY, "parity" }, + { smbios_cache_flag_desc, SMB_CAF_SOCKETED, "cache is socketed" }, + { smbios_cache_flag_name, SMB_CAF_ENABLED, "SMB_CAF_ENABLED" }, + { smbios_cache_logical_desc, SMB_CAG_INSTR, "instruction" }, + { smbios_cache_mode_desc, SMB_CAM_WB, "write-back" }, + { smbios_chassis_type_desc, SMB_CHT_PIZZA, "pizza box" }, + { smbios_chassis_state_desc, SMB_CHST_SAFE, "safe" }, + { smbios_evlog_flag_desc, SMB_EVFL_VALID, "log area valid" }, + { smbios_evlog_flag_name, SMB_EVFL_FULL, "SMB_EVFL_FULL" }, + { smbios_evlog_format_desc, SMB_EVHF_F1, "DMTF log header type 1" }, + { smbios_evlog_method_desc, SMB_EVM_GPNV, + "GP Non-Volatile API Access" }, + { smbios_fwinfo_ch_name, SMB_FWC_UPDATE, "SMB_FWC_UPDATE" }, + { smbios_fwinfo_ch_desc, SMB_FWC_WP, "write-protect" }, + { smbios_fwinfo_id_desc, SMB_FWI_UEFI, "UEFI GUID" }, + { smbios_fwinfo_state_desc, SMB_FWS_DISABLED, "disabled" }, + { smbios_fwinfo_state_desc, SMB_FWS_STB_SPARE, "standby spare" }, + { smbios_fwinfo_vers_desc, SMB_FWV_HEX64, "64-bit hex" }, + { smbios_vprobe_loc_desc, SMB_VPROBE_L_PROC, "processor" }, + { smbios_vprobe_loc_desc, SMB_VPROBE_L_PROCMOD, "processor module" }, + { smbios_vprobe_status_desc, SMB_VPROBE_S_CRIT, "critical" }, + { smbios_cooldev_status_desc, SMB_COOLDEV_S_OK, "OK" }, + { smbios_cooldev_type_desc, SMB_COOLDEV_T_FAN, "fan" }, + { smbios_tprobe_loc_desc, SMB_TPROBE_L_DISK, "disk" }, + { smbios_tprobe_status_desc, SMB_TPROBE_S_NONRECOV, "non-recoverable" }, + { smbios_iprobe_loc_desc, SMB_IPROBE_L_AIC, "add-in card" }, + { smbios_iprobe_status_desc, SMB_IPROBE_S_UNKNOWN, "unknown" }, + { smbios_ipmi_flag_desc, SMB_IPMI_F_INTRHIGH, + "intr active high (else low)" }, + { smbios_ipmi_flag_name, SMB_IPMI_F_IOADDR, + "SMB_IPMI_F_IOADDR" }, + { smbios_ipmi_type_desc, SMB_IPMI_T_KCS, + "KCS: Keyboard Controller Style" }, + { smbios_powersup_flag_name, SMB_POWERSUP_F_PRESENT, + "SMB_POWERSUP_F_PRESENT" }, + { smbios_powersup_flag_desc, SMB_POWERSUP_F_HOT, + "PSU is hot-replaceable" }, + { smbios_powersup_input_desc, SMB_POWERSUP_I_WIDE, "wide range" }, + { smbios_powersup_status_desc, SMB_POWERSUP_S_OK, "OK" }, + { smbios_powersup_type_desc, SMB_POWERSUP_T_UPS, "UPS" }, + { smbios_hwsec_desc, SMB_HWSEC_PS_ENABLED, "password enabled" }, + { smbios_memarray_loc_desc, SMB_MAL_NUBUS, "NuBus" }, + { smbios_memarray_use_desc, SMB_MAU_CACHE, "cache memory" }, + { smbios_memarray_ecc_desc, SMB_MAE_CRC, "CRC" }, + { smbios_memdevice_form_desc, SMB_MDFF_ZIP, "ZIP" }, + { smbios_memdevice_type_desc, SMB_MDT_LPDDR5, "LPDDR5" }, + { smbios_memdevice_flag_name, SMB_MDF_EDO, "SMB_MDF_EDO" }, + { smbios_memdevice_flag_desc, SMB_MDF_PSTATIC, "pseudo-static" }, + { smbios_memdevice_rank_desc, SMB_MDR_OCTAL, "octal" }, + { smbios_memdevice_memtech_desc, SMB_MTECH_DRAM, "DRAM" }, + { smbios_memdevice_op_capab_name, SMB_MOMC_VOLATILE, + "SMB_MOMC_VOLATILE" }, + { smbios_memdevice_op_capab_desc, SMB_MOMC_BLOCK_PM, + "Block-accessible persistent memory" }, + { smbios_onboard_type_desc, SMB_OBT_SAS, "sas" }, + { smbios_onboard_ext_type_desc, SMB_OBET_EMMC, "eMMC" }, + { smbios_pointdev_iface_desc, SMB_PDI_PS2, "PS/2" }, + { smbios_pointdev_type_desc, SMB_PDT_TOPAD, "Touch Pad" }, + { smbios_port_conn_desc, SMB_POC_RJ45, "RJ-45" }, + { smbios_port_type_desc, SMB_POT_NETWORK, "Network port" }, + { smbios_processor_family_desc, SMB_PRF_HOBBIT, "Hobbit" }, + { smbios_processor_status_desc, SMB_PRS_IDLE, "waiting to be enabled" }, + { smbios_processor_type_desc, SMB_PRT_DSP, "DSP processor" }, + { smbios_processor_upgrade_desc, SMB_PRU_SP3, "socket SP3" }, + { smbios_processor_core_flag_name, SMB_PRC_PM, "SMB_PRC_PM" }, + { smbios_processor_core_flag_desc, SMB_PRC_MC, "multi-core" }, + { smbios_processor_info_type_desc, SMB_PROCINFO_T_AARCH64, + "64-bit ARM (aarch64)" }, + { smbios_riscv_priv_desc, SMB_RV_PRIV_S, "Supervisor Mode" }, + { smbios_riscv_priv_name, SMB_RV_PRIV_U, "SMB_RV_PRIV_U" }, + { smbios_riscv_width_desc, SMB_RV_WIDTH_64B, "64-bit" }, + { smbios_slot_type_desc, SMB_SLT_AGP, "AGP" }, + { smbios_slot_width_desc, SMB_SLW_32X, "32x or x32" }, + { smbios_slot_usage_desc, SMB_SLU_AVAIL, "available" }, + { smbios_slot_length_desc, SMB_SLL_LONG, "long length" }, + { smbios_slot_ch1_desc, SMB_SLCH1_33V, "provides 3.3V" }, + { smbios_slot_ch1_name, SMB_SLCH1_PCMRR, "SMB_SLCH1_PCMRR" }, + { smbios_slot_ch2_desc, SMB_SLCH2_HOTPLUG, + "slot supports hot-plug devices" }, + { smbios_slot_ch2_name, SMB_SLCH2_CXL2, "SMB_SLCH2_CXL2" }, + { smbios_slot_height_desc, SMB_SLHT_FULL, "full height" }, + { smbios_strprop_id_desc, SMB_STRP_UEFI_DEVPATH, "UEFI device path" }, + { smbios_type_desc, SMB_TYPE_COOLDEV, "cooling device" }, + { smbios_type_name, SMB_TYPE_POWERSUP, "SMB_TYPE_POWERSUP" }, + { smbios_system_wakeup_desc, SMB_WAKEUP_LAN, "LAN remote" }, +}; + +boolean_t +smbios_test_verify_strings(smbios_hdl_t *hdl) +{ + boolean_t ret = B_TRUE; + + for (uint_t i = 0; i < ARRAY_SIZE(smbios_strs); i++) { + uint_t in = smbios_strs[i].ss_num; + const char *exp = smbios_strs[i].ss_str; + const char *out = smbios_strs[i].ss_func(in); + + if (out == NULL) { + warnx("failed to look up string, expected %u->%s", + in, exp); + ret = B_FALSE; + } else if (strcmp(exp, out) != 0) { + warnx("found wrong string for %u->%s: %s", in, exp, + out); + ret = B_FALSE; + } + } + + return (ret); +} diff --git a/usr/src/test/util-tests/tests/smbios/smbios_test_strprop.c b/usr/src/test/util-tests/tests/smbios/smbios_test_strprop.c new file mode 100644 index 0000000000..20d0928ebb --- /dev/null +++ b/usr/src/test/util-tests/tests/smbios/smbios_test_strprop.c @@ -0,0 +1,255 @@ +/* + * 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 2021 Oxide Computer Company + */ + +/* + * Tests for SMBIOS type 46 - SMB_TYPE_STRPROP. + */ + +#include "smbios_test.h" + +static const char *smbios_strprop_path = "/not/really/uefi"; +static uint16_t smbios_strprop_hdl = 0xcafe; + +boolean_t +smbios_test_strprop_mktable_basic(smbios_test_table_t *table) +{ + smb_strprop_t str; + + str.smbstrp_hdr.smbh_type = SMB_TYPE_STRPROP; + str.smbstrp_hdr.smbh_len = sizeof (str); + str.smbstrp_prop_id = htole16(SMB_STRP_UEFI_DEVPATH); + str.smbstrp_prop_val = 1; + str.smbstrp_phdl = htole16(smbios_strprop_hdl); + + (void) smbios_test_table_append(table, &str, sizeof (str)); + smbios_test_table_append_string(table, smbios_strprop_path); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_strprop_mktable_badstr(smbios_test_table_t *table) +{ + smb_strprop_t str; + + str.smbstrp_hdr.smbh_type = SMB_TYPE_STRPROP; + str.smbstrp_hdr.smbh_len = sizeof (str); + str.smbstrp_prop_id = htole16(SMB_STRP_UEFI_DEVPATH); + str.smbstrp_prop_val = 0x23; + str.smbstrp_phdl = htole16(smbios_strprop_hdl); + + (void) smbios_test_table_append(table, &str, sizeof (str)); + smbios_test_table_append_string(table, smbios_strprop_path); + smbios_test_table_str_fini(table); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_strprop_mktable_invlen1(smbios_test_table_t *table) +{ + smb_header_t hdr; + + hdr.smbh_type = SMB_TYPE_STRPROP; + hdr.smbh_len = sizeof (hdr); + + (void) smbios_test_table_append(table, &hdr, sizeof (hdr)); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +boolean_t +smbios_test_strprop_mktable_invlen2(smbios_test_table_t *table) +{ + smb_strprop_t str; + const uint8_t endstring = 0; + + str.smbstrp_hdr.smbh_type = SMB_TYPE_STRPROP; + str.smbstrp_hdr.smbh_len = sizeof (str) + 1; + str.smbstrp_prop_id = htole16(0); + str.smbstrp_prop_val = 0; + str.smbstrp_phdl = htole16(0); + + /* + * Append the end string again as to get us to our additional byte of + * actual table length. + */ + (void) smbios_test_table_append(table, &str, sizeof (str)); + (void) smbios_test_table_append_raw(table, &endstring, + sizeof (endstring)); + (void) smbios_test_table_append_string(table, smbios_strprop_path); + (void) smbios_test_table_append_raw(table, &endstring, + sizeof (endstring)); + smbios_test_table_append_eot(table); + + return (B_TRUE); +} + +static boolean_t +smbios_test_strprop_verify_badtable(smbios_hdl_t *hdl, int smberr) +{ + smbios_struct_t sp; + smbios_strprop_t prop; + + if (smbios_lookup_type(hdl, SMB_TYPE_STRPROP, &sp) == -1) { + warnx("failed to lookup SMBIOS strprop: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_strprop(hdl, sp.smbstr_id, &prop) != -1) { + warnx("accidentally parsed invalid strprop information as " + "valid"); + return (B_FALSE); + } + + if (smbios_errno(hdl) != smberr) { + warnx("encountered wrong error for strprop, expected: " + "0x%x, found: 0x%x", smberr, smbios_errno(hdl)); + return (B_FALSE); + } + + return (B_TRUE); +} + +boolean_t +smbios_test_strprop_verify_invlen1(smbios_hdl_t *hdl) +{ + return (smbios_test_strprop_verify_badtable(hdl, ESMB_SHORT)); +} + +boolean_t +smbios_test_strprop_verify_invlen2(smbios_hdl_t *hdl) +{ + return (smbios_test_strprop_verify_badtable(hdl, ESMB_CORRUPT)); +} + +boolean_t +smbios_test_strprop_verify_badtype(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_strprop_t prop; + + /* + * Here we've explicitly created a table with a memory device that we're + * going to try and look up as well, not that. + */ + 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_strprop(hdl, sp.smbstr_id, &prop) != -1) { + warnx("accidentally parsed invalid strprop information as " + "valid"); + return (B_FALSE); + } + + if (smbios_errno(hdl) != ESMB_TYPE) { + warnx("encountered wrong error for strprop, expected: " + "0x%x, found: 0x%x", ESMB_TYPE, smbios_errno(hdl)); + return (B_FALSE); + } + + return (B_TRUE); + +} + +boolean_t +smbios_test_strprop_verify_basic(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_strprop_t prop; + boolean_t ret = B_TRUE; + + if (smbios_lookup_type(hdl, SMB_TYPE_STRPROP, &sp) == -1) { + warnx("failed to lookup SMBIOS strprop: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_strprop(hdl, sp.smbstr_id, &prop) != 0) { + warnx("failed to get SMBIOS strprop: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (prop.smbsp_prop_id != SMB_STRP_UEFI_DEVPATH) { + warnx("property id incorrect, expected 0x%x, found 0x %x", + SMB_STRP_UEFI_DEVPATH, prop.smbsp_prop_id); + ret = B_FALSE; + } + + if (strcmp(smbios_strprop_id_desc(prop.smbsp_prop_id), + "UEFI device path") != 0) { + warnx("property id string incorrect, found %s", + smbios_strprop_id_desc(prop.smbsp_prop_id)); + ret = B_FALSE; + } + + if (strcmp(prop.smbsp_prop_val, smbios_strprop_path) != 0) { + warnx("property value incorrect, found %s", + prop.smbsp_prop_val); + ret = B_FALSE; + } + + return (ret); +} + +boolean_t +smbios_test_strprop_verify_badstr(smbios_hdl_t *hdl) +{ + smbios_struct_t sp; + smbios_strprop_t prop; + boolean_t ret = B_TRUE; + + if (smbios_lookup_type(hdl, SMB_TYPE_STRPROP, &sp) == -1) { + warnx("failed to lookup SMBIOS strprop: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (smbios_info_strprop(hdl, sp.smbstr_id, &prop) != 0) { + warnx("failed to get SMBIOS strprop: %s", + smbios_errmsg(smbios_errno(hdl))); + return (B_FALSE); + } + + if (prop.smbsp_prop_id != SMB_STRP_UEFI_DEVPATH) { + warnx("property id incorrect, expected 0x%x, found 0x %x", + SMB_STRP_UEFI_DEVPATH, prop.smbsp_prop_id); + ret = B_FALSE; + } + + if (strcmp(smbios_strprop_id_desc(prop.smbsp_prop_id), + "UEFI device path") != 0) { + warnx("property id string incorrect, found %s", + smbios_strprop_id_desc(prop.smbsp_prop_id)); + ret = B_FALSE; + } + + if (strcmp(prop.smbsp_prop_val, "") != 0) { + warnx("property value incorrect, found %s", + prop.smbsp_prop_val); + ret = B_FALSE; + } + + return (ret); +} diff --git a/usr/src/uts/common/sys/smbios.h b/usr/src/uts/common/sys/smbios.h index b8b470b79a..3ce9e2c7a3 100644 --- a/usr/src/uts/common/sys/smbios.h +++ b/usr/src/uts/common/sys/smbios.h @@ -22,7 +22,7 @@ /* * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright (c) 2018, Joyent, Inc. - * Copyright 2020 Oxide Computer Company + * Copyright 2021 Oxide Computer Company * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -158,12 +158,14 @@ typedef union { #define SMB_TYPE_MCHI 42 /* mgmt controller host interface */ #define SMB_TYPE_TPM 43 /* TPM device */ #define SMB_TYPE_PROCESSOR_INFO 44 /* Processor Additional Information */ +#define SMB_TYPE_FWINFO 45 /* Firmware Inventory Information */ +#define SMB_TYPE_STRPROP 46 /* String Property */ #define SMB_TYPE_INACTIVE 126 /* inactive table entry */ #define SMB_TYPE_EOT 127 /* end of table */ #define SMB_TYPE_OEM_LO 128 /* start of OEM-specific type range */ #define SUN_OEM_EXT_PROCESSOR 132 /* processor extended info */ -#define SUN_OEM_EXT_PORT 136 /* port exteded info */ +#define SUN_OEM_EXT_PORT 136 /* port extended info */ #define SUN_OEM_PCIEXRC 138 /* PCIE RootComplex/RootPort info */ #define SUN_OEM_EXT_MEMARRAY 144 /* phys memory array extended info */ #define SUN_OEM_EXT_MEMDEVICE 145 /* memory device extended info */ @@ -202,8 +204,6 @@ typedef struct smbios_version { uint8_t smbv_minor; /* version minor number */ } smbios_version_t; -#define SMB_CONT_BYTE 1 /* contained elements are byte size */ -#define SMB_CONT_WORD 2 /* contained elements are word size */ #define SMB_CONT_MAX 255 /* maximum contained objects */ /* @@ -286,6 +286,8 @@ typedef struct smbios_bios { #define SMB_BIOSXB2_ETCDIST 0x04 /* Enable Targeted Content Distrib. */ #define SMB_BIOSXB2_UEFI 0x08 /* UEFI Specification supported */ #define SMB_BIOSXB2_VM 0x10 /* SMBIOS table describes a VM */ +#define SMB_BIOSXB2_MFG_MODE 0x20 /* Manufacturing mode is supported */ +#define SMB_BIOSXB2_MFG_EN 0x40 /* Manufacturing mode is enabled */ /* * SMBIOS System Information. See DSP0134 Section 7.2 for more information. @@ -323,7 +325,7 @@ typedef struct smbios_bboard { #define SMB_BBFL_MOTHERBOARD 0x01 /* board is a motherboard */ #define SMB_BBFL_NEEDAUX 0x02 /* auxiliary card or daughter req'd */ #define SMB_BBFL_REMOVABLE 0x04 /* board is removable */ -#define SMB_BBFL_REPLACABLE 0x08 /* board is field-replacable */ +#define SMB_BBFL_REPLACABLE 0x08 /* board is field-replaceable */ #define SMB_BBFL_HOTSWAP 0x10 /* board is hot-swappable */ #define SMB_BBT_UNKNOWN 0x1 /* unknown */ @@ -356,7 +358,7 @@ typedef struct smbios_chassis { uint8_t smbc_cords; /* number of power cords */ uint8_t smbc_elems; /* number of element records (n) */ uint8_t smbc_elemlen; /* length of contained element (m) */ - char smbc_sku[256]; /* SKU number (as a string) */ + const char *smbc_sku; /* SKU number (as a string) */ } smbios_chassis_t; #define SMB_CHT_OTHER 0x01 /* other */ @@ -410,6 +412,19 @@ typedef struct smbios_chassis { #define SMB_CHSC_EIENAB 0x05 /* external interface enabled */ /* + * Chassis element record types + */ +typedef struct smbios_chassis_entry { + uint8_t smbce_type; /* Type of elt */ + uint8_t smbce_elt; /* Containing Element */ + uint8_t smbce_min; /* minimum number of elt */ + uint8_t smbce_max; /* minimum number of elt */ +} smbios_chassis_entry_t; + +#define SMB_CELT_BBOARD 0 /* smbce_elt is a base board type */ +#define SMB_CELT_SMBIOS 1 /* smbce_elt is an smbios type */ + +/* * SMBIOS Processor description. See DSP0134 Section 7.5 for more details. * If the L1, L2, or L3 cache handle is -1, the cache information is unknown. * If the handle refers to something of size 0, that type of cache is absent. @@ -530,6 +545,7 @@ typedef struct smbios_processor { #define SMB_PRU_BGA1528 0x3C /* Socket BGA1528 */ #define SMB_PRU_LGA4189 0x3D /* Socket LGA4189 */ #define SMB_PRU_LGA1200 0x3E /* Socket LGA1200 */ +#define SMB_PRU_LGA4677 0x3F /* Socket LGA4677 */ #define SMB_PRC_RESERVED 0x0001 /* reserved */ #define SMB_PRC_UNKNOWN 0x0002 /* unknown */ @@ -950,6 +966,7 @@ typedef struct smbios_slot { uint8_t smbl_info; /* slot info */ uint8_t smbl_pwidth; /* slot physical width */ uint32_t smbl_pitch; /* slot pitch in 10um */ + uint8_t smbl_height; /* slot height */ } smbios_slot_t; #define SMB_SLT_OTHER 0x01 /* other */ @@ -1081,6 +1098,12 @@ typedef struct smbios_slot { #define SMB_SLCH2_CXL1 0x20 /* Flexbus slot, CXL 1.0 capable */ #define SMB_SLCH2_CXL2 0x40 /* Flexbus slot, CXL 2.0 capable */ +#define SMB_SLHT_NA 0x00 /* not applicable */ +#define SMB_SLHT_OTHER 0x01 /* other */ +#define SMB_SLHT_UNKNOWN 0x02 /* unknown */ +#define SMB_SLHT_FULL 0x03 /* full height */ +#define SMB_SLHT_LP 0x04 /* low profile */ + /* * SMBIOS 7.10.9 Slot Peer Devices * @@ -1404,7 +1427,9 @@ typedef struct smbios_pointdev { #define SMB_PDI_ADB 0x08 /* ADB (Apple Desktop Bus) */ #define SMB_PDI_BUSM_DB9 0xA0 /* Bus mouse DB-9 */ #define SMB_PDI_BUSM_UDIN 0xA1 /* Bus mouse micro-DIN */ -#define SMB_PDI_BUSM_USB 0xA2 /* USB */ +#define SMB_PDI_USB 0xA2 /* USB */ +#define SMB_PDI_I2C 0xA3 /* I2C */ +#define SMB_PDI_SPI 0xA4 /* SPI */ /* * SMBIOS Portable Battery. See DSP0134 Section 7.23 for more information. @@ -1711,8 +1736,25 @@ typedef struct smbios_obdev_ext { uint8_t smboe_df; /* device/function number */ } smbios_obdev_ext_t; +#define SMB_OBET_OTHER 0x01 /* Other */ +#define SMB_OBET_UNKNOWN 0x02 /* Unknown */ +#define SMB_OBET_VIDEO 0x03 /* video */ +#define SMB_OBET_SCSI 0x04 /* SCSI */ +#define SMB_OBET_ETHERNET 0x05 /* Ethernet */ +#define SMB_OBET_TOKEN 0x06 /* Token Ring */ +#define SMB_OBET_SOUND 0x07 /* Sound */ +#define SMB_OBET_PATA 0x08 /* PATA */ +#define SMB_OBET_SATA 0x09 /* SATA */ +#define SMB_OBET_SAS 0x0A /* SAS */ +#define SMB_OBET_WLAN 0x0B /* Wireless LAN */ +#define SMB_OBET_BT 0x0C /* Bluetooth */ +#define SMB_OBET_WWAN 0x0D /* WWAN */ +#define SMB_OBET_EMMC 0x0E /* eMMC */ +#define SMB_OBET_NVME 0x0F /* NVMe */ +#define SMB_OBET_UFS 0x10 /* UFS */ + /* - * SMBIOS Processor Additional Information (Type 44). See sectoin 7.45 for more + * SMBIOS Processor Additional Information (Type 44). See section 7.45 for more * information. */ typedef struct smbios_processor_info { @@ -1784,7 +1826,7 @@ typedef struct smbios_processor_info_riscv { #define SMB_RV_ISA_N (1 << 13) /* User-level interrupts */ #define SMB_RV_ISA_O (1 << 14) /* Reserved */ #define SMB_RV_ISA_P (1 << 15) /* Reserved */ -#define SMB_RV_ISA_Q (1 << 16) /* Quad-precision floating-poit */ +#define SMB_RV_ISA_Q (1 << 16) /* Quad-precision floating-point */ #define SMB_RV_ISA_R (1 << 17) /* Reserved */ #define SMB_RV_ISA_S (1 << 18) /* Supervisor mode */ #define SMB_RV_ISA_T (1 << 19) /* Reserved */ @@ -1797,11 +1839,78 @@ typedef struct smbios_processor_info_riscv { /* END CSTYLED */ /* + * SMBIOS Firmware Inventory Information (Type 45). + */ +typedef struct smbios_fwinfo { + const char *smbfw_name; /* Firmware component name */ + const char *smbfw_id; /* Firmware ID */ + const char *smbfw_reldate; /* Release date */ + const char *smbfw_lsv; /* Lowest supported version */ + uint64_t smbfw_imgsz; /* Image size */ + uint16_t smbfw_chars; /* Characteristics */ + uint16_t smbfw_state; /* State */ + uint16_t smbfw_ncomps; /* Number of associated components */ + uint8_t smbfw_vers_fmt; /* Firmware version format */ + uint8_t smbfw_id_fmt; /* Firmware ID format */ +} smbios_fwinfo_t; + +typedef struct smbios_fwinfo_comp { + id_t smbfwe_id; /* Contained element ID */ +} smbios_fwinfo_comp_t; + +/* + * Firmware version format constants. + */ +#define SMB_FWV_FF 0x00 /* free-form */ +#define SMB_FWV_MM 0x01 /* major.minor */ +#define SMB_FWV_HEX32 0x02 /* 32-bit hex */ +#define SMB_FWV_HEX64 0x03 /* 64-bit hex */ + +/* + * Firmware ID format constants. + */ +#define SMB_FWI_FF 0x00 /* free-form */ +#define SMB_FWI_UEFI 0x01 /* UEFI GUID */ + +/* + * Firmware characteristic bitfields. + */ +#define SMB_FWC_UPDATE 0x01 /* updatable */ +#define SMB_FWC_WP 0x02 /* write-protect */ + +/* + * Firmware state constants. + */ +#define SMB_FWS_OTHER 0x01 /* other */ +#define SMB_FWS_UNKNOWN 0x02 /* unknown */ +#define SMB_FWS_DISABLED 0x03 /* disabled */ +#define SMB_FWS_ENABLED 0x04 /* enabled */ +#define SMB_FWS_ABSENT 0x05 /* absent */ +#define SMB_FWS_STB_OFFLINE 0x06 /* standby offline */ +#define SMB_FWS_STB_SPARE 0x07 /* standby spare */ +#define SMB_FWS_UA_OFFLINE 0x08 /* unavailable offline */ + +/* + * SMBIOS String Property (Type 46). See section 7.47 for more information. + */ +typedef struct smbios_strprop { + uint32_t smbsp_prop_id; /* property ID */ + const char *smbsp_prop_val; /* property Value */ + id_t smbsp_parent; /* parent handle */ +} smbios_strprop_t; + +/* + * String Property IDs + */ +#define SMB_STRP_RESERVED 0x00 /* reserved */ +#define SMB_STRP_UEFI_DEVPATH 0x01 /* UEFI device path */ + +/* * SMBIOS OEM-specific (Type 132) Processor Extended Information. */ typedef struct smbios_processor_ext { uint16_t smbpe_processor; /* extending processor handle */ - uint8_t smbpe_fru; /* FRU indicaor */ + uint8_t smbpe_fru; /* FRU indicator */ uint8_t smbpe_n; /* number of APIC IDs */ uint16_t *smbpe_apicid; /* strand Inital APIC IDs */ } smbios_processor_ext_t; @@ -1866,7 +1975,8 @@ typedef struct smbios_memdevice_ext { #define SMB_VERSION_32 0x0302 /* SMBIOS encoding for DMTF spec 3.2 */ #define SMB_VERSION_33 0x0303 /* SMBIOS encoding for DMTF spec 3.3 */ #define SMB_VERSION_34 0x0304 /* SMBIOS encoding for DMTF spec 3.4 */ -#define SMB_VERSION SMB_VERSION_34 /* SMBIOS latest version definitions */ +#define SMB_VERSION_35 0x0305 /* SMBIOS encoding for DMTF spec 3.5 */ +#define SMB_VERSION SMB_VERSION_35 /* SMBIOS latest version definitions */ #define SMB_O_NOCKSUM 0x1 /* do not verify header checksums */ #define SMB_O_NOVERS 0x2 /* do not verify header versions */ @@ -1919,6 +2029,10 @@ extern id_t smbios_info_bios(smbios_hdl_t *, smbios_bios_t *); extern id_t smbios_info_system(smbios_hdl_t *, smbios_system_t *); extern int smbios_info_bboard(smbios_hdl_t *, id_t, smbios_bboard_t *); extern int smbios_info_chassis(smbios_hdl_t *, id_t, smbios_chassis_t *); +extern int smbios_info_chassis_elts(smbios_hdl_t *, id_t, uint_t *, + smbios_chassis_entry_t **); +extern void smbios_info_chassis_elts_free(smbios_hdl_t *, uint_t, + smbios_chassis_entry_t *); extern int smbios_info_processor(smbios_hdl_t *, id_t, smbios_processor_t *); extern int smbios_info_extprocessor(smbios_hdl_t *, id_t, smbios_processor_ext_t *); @@ -1958,7 +2072,12 @@ extern int smbios_info_processor_info(smbios_hdl_t *, id_t, smbios_processor_info_t *); extern int smbios_info_processor_riscv(smbios_hdl_t *, id_t, smbios_processor_info_riscv_t *); - +extern int smbios_info_strprop(smbios_hdl_t *, id_t, smbios_strprop_t *); +extern int smbios_info_fwinfo(smbios_hdl_t *, id_t, smbios_fwinfo_t *); +extern int smbios_info_fwinfo_comps(smbios_hdl_t *, id_t, uint_t *, + smbios_fwinfo_comp_t **); +extern void smbios_info_fwinfo_comps_free(smbios_hdl_t *, uint_t, + smbios_fwinfo_comp_t *); extern const char *smbios_psn(smbios_hdl_t *); extern const char *smbios_csn(smbios_hdl_t *); @@ -2004,6 +2123,12 @@ extern const char *smbios_evlog_flag_name(uint_t); extern const char *smbios_evlog_format_desc(uint_t); extern const char *smbios_evlog_method_desc(uint_t); +extern const char *smbios_fwinfo_ch_name(uint_t); +extern const char *smbios_fwinfo_ch_desc(uint_t); +extern const char *smbios_fwinfo_id_desc(uint_t); +extern const char *smbios_fwinfo_state_desc(uint_t); +extern const char *smbios_fwinfo_vers_desc(uint_t); + extern const char *smbios_vprobe_loc_desc(uint_t); extern const char *smbios_vprobe_status_desc(uint_t); @@ -2042,6 +2167,7 @@ extern const char *smbios_memdevice_op_capab_name(uint_t); extern const char *smbios_memdevice_op_capab_desc(uint_t); extern const char *smbios_onboard_type_desc(uint_t); +extern const char *smbios_onboard_ext_type_desc(uint_t); extern const char *smbios_pointdev_iface_desc(uint_t); extern const char *smbios_pointdev_type_desc(uint_t); @@ -2071,6 +2197,9 @@ extern const char *smbios_slot_ch1_desc(uint_t); extern const char *smbios_slot_ch1_name(uint_t); extern const char *smbios_slot_ch2_desc(uint_t); extern const char *smbios_slot_ch2_name(uint_t); +extern const char *smbios_slot_height_desc(uint_t); + +extern const char *smbios_strprop_id_desc(uint_t); extern const char *smbios_type_desc(uint_t); extern const char *smbios_type_name(uint_t); diff --git a/usr/src/uts/common/sys/smbios_impl.h b/usr/src/uts/common/sys/smbios_impl.h index 4b951b702f..41424aa03a 100644 --- a/usr/src/uts/common/sys/smbios_impl.h +++ b/usr/src/uts/common/sys/smbios_impl.h @@ -22,7 +22,7 @@ /* * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright (c) 2018, Joyent, Inc. - * Copyright 2020 Oxide Computer Company + * Copyright 2021 Oxide Computer Company * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -134,14 +134,20 @@ typedef struct smb_chassis { uint8_t smbch_cords; /* number of power cords */ uint8_t smbch_cn; /* number of contained records */ uint8_t smbch_cm; /* size of contained records */ - uint8_t smbch_cv[1]; /* array of contained records */ + uint8_t smbch_cv[]; /* array of contained records */ } smb_chassis_t; -/* WARNING: the argument is evaluated three times! */ -#define SMB_CH_SKU(smbcp) ((char *) \ - (smbcp)->smbch_cv + ((smbcp)->smbch_cn * (smbcp)->smbch_cm)) #define SMB_CHT_LOCK 0x80 /* lock bit within smbch_type */ +typedef struct smb_chassis_entry { + uint8_t smbce_type; /* Containing Element and Type */ + uint8_t smbce_min; /* minimum number of elt */ + uint8_t smbce_max; /* minimum number of elt */ +} smb_chassis_entry_t; + +#define SMB_CHE_TYPE_IS_SMB(x) (((x) & 0x80) == 0x80) +#define SMB_CHE_TYPE_TYPE(x) (((x) & 0x7f)) + /* * SMBIOS implementation structure for SMB_TYPE_PROCESSOR. */ @@ -263,12 +269,18 @@ typedef struct smb_slot_cont { uint8_t smbsl_info; /* slot info */ uint8_t smbsl_pwidth; /* slot physical width */ uint16_t smbsl_pitch; /* slot pitch */ + /* Added in SMBIOS 3.5 */ + uint8_t smbsl_height; /* slot height */ } smb_slot_cont_t; /* - * The first byte that the smb_slot_cont_t is defined to start at. + * The first byte that the smb_slot_cont_t is defined to start at. Note, this + * was originally indicated to be 0x14 in the SMBIOS 3.4 specification. This has + * been noted as an errata. Right now we assume that most things have the + * updated behavior in SMBIOS 3.5. However, if we encounter things in the wild + * that have the other offset then we will need to condition this on 3.4. */ -#define SMB_SLOT_CONT_START 0x14 +#define SMB_SLOT_CONT_START 0x13 /* * SMBIOS implementation structure for SMB_TYPE_OBDEVS. @@ -650,6 +662,36 @@ typedef struct smb_processor_info_riscv { } smb_processor_info_riscv_t; /* + * SMBIOS implementation structure for SMBIOS_TYPE_FWINFO. + */ +typedef struct smb_fwinfo { + smb_header_t smbfwii_hdr; /* structure handle */ + uint8_t smbfwii_name; /* Firmware component name */ + uint8_t smbfwii_vers; /* Firmware version */ + uint8_t smbfwii_vers_fmt; /* Version format */ + uint8_t smbfwii_id; /* Firmware ID */ + uint8_t smbfwii_id_fmt; /* Firmware ID format */ + uint8_t smbfwii_reldate; /* Release Date */ + uint8_t smbfwii_mfg; /* Manufacturer */ + uint8_t smbfwii_lsv; /* Lowest supported version */ + uint64_t smbfwii_imgsz; /* Image size */ + uint16_t smbfwii_chars; /* Characteristics */ + uint8_t smbfwii_state; /* State */ + uint8_t smbfwii_ncomps; /* Number of associated components */ + uint16_t smbfwii_comps[]; /* Variable handles */ +} smb_fwinfo_t; + +/* + * SMBIOS implementation structure for SMBIOS_TYPE_STRPROP. + */ +typedef struct smb_strprop { + smb_header_t smbstrp_hdr; /* structure handle */ + uint16_t smbstrp_prop_id; /* string property ID */ + uint8_t smbstrp_prop_val; /* string property value */ + uint16_t smbstrp_phdl; /* parent handle */ +} smb_strprop_t; + +/* * SMBIOS implementation structure for SUN_OEM_EXT_PROCESSOR. */ typedef struct smb_processor_ext { @@ -883,6 +925,28 @@ typedef struct smb_base_slot { uint8_t smbbl_df; /* device/function number */ } smb_base_slot_t; +/* + * Prior to reivison 3.5 of the library and interface we had embedded a 256 byte + * string for the SKU into here rather than pointing to constant data. This, + * combined withe bugs in the implementation, generally led to strings with + * garbage. As part of fixing this with the 3.5 support, we moved the struct to + * ve more inline with everything else. + */ +typedef struct smb_chassis_pre35 { + uint32_t smbc_oemdata; /* OEM-specific data */ + uint8_t smbc_lock; /* lock present? */ + uint8_t smbc_type; /* type */ + uint8_t smbc_bustate; /* boot-up state */ + uint8_t smbc_psstate; /* power supply state */ + uint8_t smbc_thstate; /* thermal state */ + uint8_t smbc_security; /* security status */ + uint8_t smbc_uheight; /* enclosure height in U's */ + uint8_t smbc_cords; /* number of power cords */ + uint8_t smbc_elems; /* number of element records (n) */ + uint8_t smbc_elemlen; /* length of contained element (m) */ + char smbc_sku[256]; +} smb_chassis_pre35_t; + #ifdef __cplusplus } #endif |
