diff options
| author | Dan McDonald <danmcd@joyent.com> | 2021-11-19 07:53:07 -0500 |
|---|---|---|
| committer | Dan McDonald <danmcd@joyent.com> | 2021-11-19 07:53:07 -0500 |
| commit | a9abe3f2aacb7ff5172ef7d55241b1d9b969c359 (patch) | |
| tree | a3752430b7cb23b73ab893525e9ed06804292993 /usr/src/common | |
| parent | fb06a756a0ecba732e1563d1f6085aa2b0741bec (diff) | |
| parent | d53cdfab6d4896af92b7a3df87a26060caf179ae (diff) | |
| download | illumos-joyent-a9abe3f2aacb7ff5172ef7d55241b1d9b969c359.tar.gz | |
[illumos-gate merge]
commit d53cdfab6d4896af92b7a3df87a26060caf179ae
14231 want support for SMBIOS 3.5
14232 several smbios_info_* routines don't check for bad ids
14233 smbios_info_chassis calculates sku number incorrectly
14234 smbios chassis elements need work
commit e43afc9605f99023dbdb4a7b5309de87e6016db6
14230 badseg test leaves coreadm in maintenance
Diffstat (limited to 'usr/src/common')
| -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 |
3 files changed, 317 insertions, 30 deletions
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)); |
