#include <sys/sysmacros.h>
#include <sys/param.h>
#include <sys/bitext.h>
#include <sys/hexdump.h>
#include <smbios.h>
#include <alloca.h>
#include <limits.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <libjedec.h>
#define SMBIOS_SUCCESS 0
#define SMBIOS_ERROR 1
#define SMBIOS_USAGE 2
static const char *g_pname;
static int g_hdr;
static int opt_e;
static int opt_i = -1;
static int opt_O;
static int opt_s;
static int opt_t = -1;
static int opt_x;
static boolean_t
smbios_vergteq(smbios_version_t *v, uint_t major, uint_t minor)
{
if (v->smbv_major > major)
return (B_TRUE);
if (v->smbv_major == major &&
v->smbv_minor >= minor)
return (B_TRUE);
return (B_FALSE);
}
static void __PRINTFLIKE(2)
smbios_warn(smbios_hdl_t *shp, const char *format, ...)
{
va_list ap;
va_start(ap, format);
(void) vfprintf(stderr, format, ap);
va_end(ap);
if (shp != NULL) {
(void) fprintf(stderr, ": %s",
smbios_errmsg(smbios_errno(shp)));
}
(void) fprintf(stderr, "\n");
}
static void __PRINTFLIKE(2)
oprintf(FILE *fp, const char *format, ...)
{
va_list ap;
va_start(ap, format);
(void) vfprintf(fp, format, ap);
va_end(ap);
}
static void __PRINTFLIKE(3)
desc_printf(const char *d, FILE *fp, const char *format, ...)
{
va_list ap;
va_start(ap, format);
(void) vfprintf(fp, format, ap);
va_end(ap);
if (d != NULL)
(void) fprintf(fp, " (%s)\n", d);
else
(void) fprintf(fp, "\n");
}
static void
flag_printf(FILE *fp, const char *s, uint_t flags, size_t bits,
const char *(*flag_name)(uint_t), const char *(*flag_desc)(uint_t))
{
size_t i;
oprintf(fp, " %s: 0x%x\n", s, flags);
for (i = 0; i < bits; i++) {
uint_t f = 1 << i;
const char *n;
if (!(flags & f))
continue;
if ((n = flag_name(f)) != NULL)
desc_printf(flag_desc(f), fp, "\t%s", n);
else
desc_printf(flag_desc(f), fp, "\t0x%x", f);
}
}
static void
flag64_printf(FILE *fp, const char *s, uint64_t flags, size_t bits,
const char *(*flag_name)(uint64_t), const char *(*flag_desc)(uint64_t))
{
size_t i;
oprintf(fp, " %s: 0x%llx\n", s, (u_longlong_t)flags);
for (i = 0; i < bits; i++) {
u_longlong_t f = 1ULL << i;
const char *n;
if (!(flags & f))
continue;
if ((n = flag_name(f)) != NULL)
desc_printf(flag_desc(f), fp, "\t%s", n);
else
desc_printf(flag_desc(f), fp, "\t0x%llx", f);
}
}
static void
id_printf(FILE *fp, const char *s, id_t id)
{
switch (id) {
case SMB_ID_NONE:
oprintf(fp, "%sNone\n", s);
break;
case SMB_ID_NOTSUP:
oprintf(fp, "%sNot Supported\n", s);
break;
default:
oprintf(fp, "%s%u\n", s, (uint_t)id);
}
}
static void
jedec_print(FILE *fp, const char *desc, uint_t id)
{
const char *name;
uint_t cont, vendor;
vendor = id >> 8;
cont = id & 0x7f;
name = libjedec_vendor_string(cont, vendor);
if (name == NULL) {
oprintf(fp, " %s: Bank: 0x%x Vendor: 0x%x\n", desc, cont + 1,
vendor);
} else {
oprintf(fp, " %s: Bank: 0x%x Vendor: 0x%x (%s)\n", desc,
cont + 1, vendor, name);
}
}
static void
jedec_rev_print(FILE *fp, const char *desc, uint16_t raw_rev)
{
uint8_t rev = (uint8_t)bitx16(raw_rev, 15, 8);
uint8_t maj = bitx8(rev, 7, 4);
uint8_t min = bitx8(rev, 3, 0);
oprintf(fp, " %s: %x.%x\n", desc, maj, min);
}
static void
u128_print(FILE *fp, const char *desc, const uint8_t *data)
{
uint_t i;
oprintf(fp, "%s: ", desc);
for (i = 0; i < 16; i++) {
oprintf(fp, " %02x", data[i]);
}
oprintf(fp, "\n");
}
static void
str_print_label(FILE *fp, const char *header, const char *str, boolean_t label)
{
const char *c;
oprintf(fp, header);
if (label) {
oprintf(fp, ": ");
}
for (c = str; *c != '\0'; c++) {
if (isprint(*c)) {
oprintf(fp, "%c", *c);
} else {
oprintf(fp, "\\x%02x", *c);
}
}
oprintf(fp, "\n");
}
static void
str_print_nolabel(FILE *fp, const char *ws, const char *str)
{
return (str_print_label(fp, ws, str, B_FALSE));
}
static void
str_print(FILE *fp, const char *header, const char *str)
{
return (str_print_label(fp, header, str, B_TRUE));
}
static int
check_oem(smbios_hdl_t *shp)
{
int i;
int cnt;
int rv;
id_t oem_id;
smbios_struct_t s;
const char **oem_str;
rv = smbios_lookup_type(shp, SMB_TYPE_OEMSTR, &s);
if (rv != 0) {
return (-1);
}
oem_id = s.smbstr_id;
cnt = smbios_info_strtab(shp, oem_id, 0, NULL);
if (cnt > 0) {
oem_str = alloca(sizeof (char *) * cnt);
(void) smbios_info_strtab(shp, oem_id, cnt, oem_str);
for (i = 0; i < cnt; i++) {
if (strncmp(oem_str[i], SMB_PRMS1,
strlen(SMB_PRMS1) + 1) == 0) {
return (0);
}
}
}
return (-1);
}
static void
print_smbios_21(smbios_21_entry_t *ep, FILE *fp)
{
int i;
oprintf(fp, "Entry Point Anchor Tag: %*.*s\n",
(int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor),
ep->smbe_eanchor);
oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum);
oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen);
oprintf(fp, "Entry Point Version: %u.%u\n",
ep->smbe_major, ep->smbe_minor);
oprintf(fp, "Max Structure Size: %u\n", ep->smbe_maxssize);
oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision);
oprintf(fp, "Entry Point Revision Data:");
for (i = 0; i < sizeof (ep->smbe_format); i++)
oprintf(fp, " 0x%02x", ep->smbe_format[i]);
oprintf(fp, "\n");
oprintf(fp, "Intermediate Anchor Tag: %*.*s\n",
(int)sizeof (ep->smbe_ianchor), (int)sizeof (ep->smbe_ianchor),
ep->smbe_ianchor);
oprintf(fp, "Intermediate Checksum: 0x%x\n", ep->smbe_icksum);
oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen);
oprintf(fp, "Structure Table Address: 0x%x\n", ep->smbe_staddr);
oprintf(fp, "Structure Table Entries: %u\n", ep->smbe_stnum);
oprintf(fp, "DMI BCD Revision: 0x%x\n", ep->smbe_bcdrev);
}
static void
print_smbios_30(smbios_30_entry_t *ep, FILE *fp)
{
oprintf(fp, "Entry Point Anchor Tag: %*.*s\n",
(int)sizeof (ep->smbe_eanchor), (int)sizeof (ep->smbe_eanchor),
ep->smbe_eanchor);
oprintf(fp, "Entry Point Checksum: 0x%x\n", ep->smbe_ecksum);
oprintf(fp, "Entry Point Length: %u\n", ep->smbe_elen);
oprintf(fp, "SMBIOS Version: %u.%u\n",
ep->smbe_major, ep->smbe_minor);
oprintf(fp, "SMBIOS DocRev: 0x%x\n", ep->smbe_docrev);
oprintf(fp, "Entry Point Revision: 0x%x\n", ep->smbe_revision);
oprintf(fp, "Structure Table Length: %u\n", ep->smbe_stlen);
oprintf(fp, "Structure Table Address: 0x%" PRIx64 "\n",
ep->smbe_staddr);
}
static void
print_smbios(smbios_hdl_t *shp, FILE *fp)
{
smbios_entry_t ep;
switch (smbios_info_smbios(shp, &ep)) {
case SMBIOS_ENTRY_POINT_21:
print_smbios_21(&ep.ep21, fp);
break;
case SMBIOS_ENTRY_POINT_30:
print_smbios_30(&ep.ep30, fp);
break;
}
}
static void
print_common(const smbios_info_t *ip, FILE *fp)
{
if (ip->smbi_manufacturer[0] != '\0')
str_print(fp, " Manufacturer", ip->smbi_manufacturer);
if (ip->smbi_product[0] != '\0')
str_print(fp, " Product", ip->smbi_product);
if (ip->smbi_version[0] != '\0')
str_print(fp, " Version", ip->smbi_version);
if (ip->smbi_serial[0] != '\0')
str_print(fp, " Serial Number", ip->smbi_serial);
if (ip->smbi_asset[0] != '\0')
str_print(fp, " Asset Tag", ip->smbi_asset);
if (ip->smbi_location[0] != '\0')
str_print(fp, " Location Tag", ip->smbi_location);
if (ip->smbi_part[0] != '\0')
str_print(fp, " Part Number", ip->smbi_part);
}
static void
print_bios(smbios_hdl_t *shp, FILE *fp)
{
smbios_bios_t b;
if (smbios_info_bios(shp, &b) == -1) {
smbios_warn(shp, "failed to read BIOS information");
return;
}
str_print(fp, " Vendor", b.smbb_vendor);
str_print(fp, " Version String", b.smbb_version);
str_print(fp, " Release Date", b.smbb_reldate);
oprintf(fp, " Address Segment: 0x%x\n", b.smbb_segment);
oprintf(fp, " ROM Size: %" PRIu64 " bytes\n", b.smbb_extromsize);
oprintf(fp, " Image Size: %u bytes\n", b.smbb_runsize);
flag64_printf(fp, "Characteristics",
b.smbb_cflags, sizeof (b.smbb_cflags) * NBBY,
smbios_bios_flag_name, smbios_bios_flag_desc);
if (b.smbb_nxcflags > SMB_BIOSXB_1) {
flag_printf(fp, "Characteristics Extension Byte 1",
b.smbb_xcflags[SMB_BIOSXB_1],
sizeof (b.smbb_xcflags[SMB_BIOSXB_1]) * NBBY,
smbios_bios_xb1_name, smbios_bios_xb1_desc);
}
if (b.smbb_nxcflags > SMB_BIOSXB_2) {
flag_printf(fp, "Characteristics Extension Byte 2",
b.smbb_xcflags[SMB_BIOSXB_2],
sizeof (b.smbb_xcflags[SMB_BIOSXB_2]) * NBBY,
smbios_bios_xb2_name, smbios_bios_xb2_desc);
}
if (b.smbb_nxcflags > SMB_BIOSXB_BIOS_MIN) {
oprintf(fp, " Version Number: %u.%u\n",
b.smbb_biosv.smbv_major, b.smbb_biosv.smbv_minor);
}
if (b.smbb_nxcflags > SMB_BIOSXB_ECFW_MIN &&
b.smbb_ecfwv.smbv_major != 0xff &&
b.smbb_ecfwv.smbv_minor != 0xff) {
oprintf(fp, " Embedded Ctlr Firmware Version Number: %u.%u\n",
b.smbb_ecfwv.smbv_major, b.smbb_ecfwv.smbv_minor);
}
}
static void
print_system(smbios_hdl_t *shp, FILE *fp)
{
smbios_system_t s;
uint_t i;
if (smbios_info_system(shp, &s) == -1) {
smbios_warn(shp, "failed to read system information");
return;
}
oprintf(fp, " UUID: ");
oprintf(fp, "%02x%02x%02x%02x-%02x%02x-%02x%02x-",
s.smbs_uuid[0], s.smbs_uuid[1], s.smbs_uuid[2], s.smbs_uuid[3],
s.smbs_uuid[4], s.smbs_uuid[5], s.smbs_uuid[6], s.smbs_uuid[7]);
for (i = 8; i < s.smbs_uuidlen; i++) {
oprintf(fp, "%02x", s.smbs_uuid[i]);
if (i == 9)
oprintf(fp, "-");
}
oprintf(fp, "\n");
oprintf(fp, " UUID (Endian-corrected): ");
oprintf(fp, "%08x-%04hx-%04hx-", *((uint_t *)&s.smbs_uuid[0]),
*((ushort_t *)&s.smbs_uuid[4]),
*((ushort_t *)&s.smbs_uuid[6]));
for (i = 8; i < s.smbs_uuidlen; i++) {
oprintf(fp, "%02x", s.smbs_uuid[i]);
if (i == 9)
oprintf(fp, "-");
}
oprintf(fp, "\n");
desc_printf(smbios_system_wakeup_desc(s.smbs_wakeup),
fp, " Wake-Up Event: 0x%x", s.smbs_wakeup);
str_print(fp, " SKU Number", s.smbs_sku);
str_print(fp, " Family", s.smbs_family);
}
static void
print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_bboard_t b;
int chdl_cnt;
if (smbios_info_bboard(shp, id, &b) != 0) {
smbios_warn(shp, "failed to read baseboard information");
return;
}
oprintf(fp, " Chassis: %u\n", (uint_t)b.smbb_chassis);
flag_printf(fp, "Flags", b.smbb_flags, sizeof (b.smbb_flags) * NBBY,
smbios_bboard_flag_name, smbios_bboard_flag_desc);
desc_printf(smbios_bboard_type_desc(b.smbb_type),
fp, " Board Type: 0x%x", b.smbb_type);
chdl_cnt = b.smbb_contn;
if (chdl_cnt != 0) {
id_t *chdl;
uint16_t hdl;
int i, n, cnt;
chdl = alloca(chdl_cnt * sizeof (id_t));
cnt = smbios_info_contains(shp, id, chdl_cnt, chdl);
if (cnt > SMB_CONT_MAX)
return;
n = MIN(chdl_cnt, cnt);
oprintf(fp, "\n");
for (i = 0; i < n; i++) {
hdl = (uint16_t)chdl[i];
oprintf(fp, " Contained Handle: %u\n", hdl);
}
}
}
static void
print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_chassis_t c;
smbios_chassis_entry_t *elts;
uint_t nelts, i;
if (smbios_info_chassis(shp, id, &c) != 0) {
smbios_warn(shp, "failed to read chassis information");
return;
}
oprintf(fp, " OEM Data: 0x%x\n", c.smbc_oemdata);
str_print(fp, " SKU Number",
c.smbc_sku[0] == '\0' ? "<unknown>" : c.smbc_sku);
oprintf(fp, " Lock Present: %s\n", c.smbc_lock ? "Y" : "N");
desc_printf(smbios_chassis_type_desc(c.smbc_type),
fp, " Chassis Type: 0x%x", c.smbc_type);
desc_printf(smbios_chassis_state_desc(c.smbc_bustate),
fp, " Boot-Up State: 0x%x", c.smbc_bustate);
desc_printf(smbios_chassis_state_desc(c.smbc_psstate),
fp, " Power Supply State: 0x%x", c.smbc_psstate);
desc_printf(smbios_chassis_state_desc(c.smbc_thstate),
fp, " Thermal State: 0x%x", c.smbc_thstate);
const char *rtype = smbios_chassis_rack_type_desc(c.smbc_rtype);
if (rtype == NULL) {
rtype = " unknown unit";
}
if (c.smbc_uheight == 0xff) {
oprintf(fp, " Chassis Height: %u%s\n", c.smbc_rheight, rtype);
} else {
oprintf(fp, " Chassis Height: %uu\n", c.smbc_uheight);
}
oprintf(fp, " Power Cords: %u\n", c.smbc_cords);
oprintf(fp, " Element Records: %u\n", c.smbc_elems);
if (c.smbc_rtype == 0) {
oprintf(fp, " Rack Type: unspecified\n");
} else {
desc_printf(smbios_chassis_rack_type_desc(c.smbc_rtype),
fp, " Rack Type: 0x%x", c.smbc_rtype);
}
if (c.smbc_rheight != 0) {
oprintf(fp, " Rack Height: %u%s\n", c.smbc_rheight, rtype);
}
if (c.smbc_elems == 0) {
return;
}
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 < 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);
}
}
static void
print_processor(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_processor_t p;
uint_t status;
if (smbios_info_processor(shp, id, &p) != 0) {
smbios_warn(shp, "failed to read processor information");
return;
}
status = SMB_PRSTATUS_STATUS(p.smbp_status);
desc_printf(smbios_processor_family_desc(p.smbp_family),
fp, " Family: %u", p.smbp_family);
oprintf(fp, " CPUID: 0x%llx\n", (u_longlong_t)p.smbp_cpuid);
desc_printf(smbios_processor_type_desc(p.smbp_type),
fp, " Type: %u", p.smbp_type);
desc_printf(smbios_processor_upgrade_desc(p.smbp_upgrade),
fp, " Socket Upgrade: %u", p.smbp_upgrade);
oprintf(fp, " Socket Status: %s\n",
SMB_PRSTATUS_PRESENT(p.smbp_status) ?
"Populated" : "Not Populated");
desc_printf(smbios_processor_status_desc(status),
fp, " Processor Status: %u", status);
if (SMB_PRV_LEGACY(p.smbp_voltage)) {
oprintf(fp, " Supported Voltages:");
switch (p.smbp_voltage) {
case SMB_PRV_5V:
oprintf(fp, " 5.0V");
break;
case SMB_PRV_33V:
oprintf(fp, " 3.3V");
break;
case SMB_PRV_29V:
oprintf(fp, " 2.9V");
break;
}
oprintf(fp, "\n");
} else {
oprintf(fp, " Supported Voltages: %.1fV\n",
(float)SMB_PRV_VOLTAGE(p.smbp_voltage) / 10);
}
if (p.smbp_corecount != 0) {
oprintf(fp, " Core Count: %u\n", p.smbp_corecount);
} else {
oprintf(fp, " Core Count: Unknown\n");
}
if (p.smbp_coresenabled != 0) {
oprintf(fp, " Cores Enabled: %u\n", p.smbp_coresenabled);
} else {
oprintf(fp, " Cores Enabled: Unknown\n");
}
if (p.smbp_threadcount != 0) {
oprintf(fp, " Thread Count: %u\n", p.smbp_threadcount);
} else {
oprintf(fp, " Thread Count: Unknown\n");
}
if (p.smbp_cflags) {
flag_printf(fp, "Processor Characteristics",
p.smbp_cflags, sizeof (p.smbp_cflags) * NBBY,
smbios_processor_core_flag_name,
smbios_processor_core_flag_desc);
}
if (p.smbp_clkspeed != 0)
oprintf(fp, " External Clock Speed: %uMHz\n", p.smbp_clkspeed);
else
oprintf(fp, " External Clock Speed: Unknown\n");
if (p.smbp_maxspeed != 0)
oprintf(fp, " Maximum Speed: %uMHz\n", p.smbp_maxspeed);
else
oprintf(fp, " Maximum Speed: Unknown\n");
if (p.smbp_curspeed != 0)
oprintf(fp, " Current Speed: %uMHz\n", p.smbp_curspeed);
else
oprintf(fp, " Current Speed: Unknown\n");
id_printf(fp, " L1 Cache Handle: ", p.smbp_l1cache);
id_printf(fp, " L2 Cache Handle: ", p.smbp_l2cache);
id_printf(fp, " L3 Cache Handle: ", p.smbp_l3cache);
if (p.smbp_threadsenabled != 0) {
oprintf(fp, " Threads Enabled: %u\n", p.smbp_threadsenabled);
} else {
oprintf(fp, " Threads Enabled: Unknown\n");
}
if (*p.smbp_socktype != '\0') {
str_print(fp, " Socket Type", p.smbp_socktype);
}
}
static void
print_cache(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_cache_t c;
if (smbios_info_cache(shp, id, &c) != 0) {
smbios_warn(shp, "failed to read cache information");
return;
}
oprintf(fp, " Level: %u\n", c.smba_level);
oprintf(fp, " Maximum Installed Size: %" PRIu64 " bytes\n",
c.smba_maxsize2);
if (c.smba_size2 != 0) {
oprintf(fp, " Installed Size: %" PRIu64 " bytes\n",
c.smba_size2);
} else {
oprintf(fp, " Installed Size: Not Installed\n");
}
if (c.smba_speed != 0)
oprintf(fp, " Speed: %uns\n", c.smba_speed);
else
oprintf(fp, " Speed: Unknown\n");
flag_printf(fp, "Supported SRAM Types",
c.smba_stype, sizeof (c.smba_stype) * NBBY,
smbios_cache_ctype_name, smbios_cache_ctype_desc);
desc_printf(smbios_cache_ctype_desc(c.smba_ctype),
fp, " Current SRAM Type: 0x%x", c.smba_ctype);
desc_printf(smbios_cache_ecc_desc(c.smba_etype),
fp, " Error Correction Type: %u", c.smba_etype);
desc_printf(smbios_cache_logical_desc(c.smba_ltype),
fp, " Logical Cache Type: %u", c.smba_ltype);
desc_printf(smbios_cache_assoc_desc(c.smba_assoc),
fp, " Associativity: %u", c.smba_assoc);
desc_printf(smbios_cache_mode_desc(c.smba_mode),
fp, " Mode: %u", c.smba_mode);
desc_printf(smbios_cache_loc_desc(c.smba_location),
fp, " Location: %u", c.smba_location);
flag_printf(fp, "Flags", c.smba_flags, sizeof (c.smba_flags) * NBBY,
smbios_cache_flag_name, smbios_cache_flag_desc);
}
static void
print_port(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_port_t p;
if (smbios_info_port(shp, id, &p) != 0) {
smbios_warn(shp, "failed to read port information");
return;
}
str_print(fp, " Internal Reference Designator", p.smbo_iref);
str_print(fp, " External Reference Designator", p.smbo_eref);
desc_printf(smbios_port_conn_desc(p.smbo_itype),
fp, " Internal Connector Type: %u", p.smbo_itype);
desc_printf(smbios_port_conn_desc(p.smbo_etype),
fp, " External Connector Type: %u", p.smbo_etype);
desc_printf(smbios_port_type_desc(p.smbo_ptype),
fp, " Port Type: %u", p.smbo_ptype);
}
static void
print_slot(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_slot_t s;
smbios_version_t v;
if (smbios_info_slot(shp, id, &s) != 0) {
smbios_warn(shp, "failed to read slot information");
return;
}
smbios_info_smbios_version(shp, &v);
str_print(fp, " Reference Designator", s.smbl_name);
oprintf(fp, " Slot ID: 0x%x\n", s.smbl_id);
desc_printf(smbios_slot_type_desc(s.smbl_type),
fp, " Type: 0x%x", s.smbl_type);
desc_printf(smbios_slot_width_desc(s.smbl_width),
fp, " Width: 0x%x", s.smbl_width);
desc_printf(smbios_slot_usage_desc(s.smbl_usage),
fp, " Usage: 0x%x", s.smbl_usage);
desc_printf(smbios_slot_length_desc(s.smbl_length),
fp, " Length: 0x%x", s.smbl_length);
flag_printf(fp, "Slot Characteristics 1",
s.smbl_ch1, sizeof (s.smbl_ch1) * NBBY,
smbios_slot_ch1_name, smbios_slot_ch1_desc);
flag_printf(fp, "Slot Characteristics 2",
s.smbl_ch2, sizeof (s.smbl_ch2) * NBBY,
smbios_slot_ch2_name, smbios_slot_ch2_desc);
if (check_oem(shp) != 0 && !smbios_vergteq(&v, 2, 6))
return;
oprintf(fp, " Segment Group: %u\n", s.smbl_sg);
oprintf(fp, " Bus Number: %u\n", s.smbl_bus);
oprintf(fp, " Device/Function Number: %u/%u\n", s.smbl_df >> 3,
s.smbl_df & 0x7);
if (s.smbl_dbw != 0) {
oprintf(fp, " Data Bus Width: %d\n", s.smbl_dbw);
}
if (s.smbl_npeers > 0) {
smbios_slot_peer_t *peer;
uint_t i, npeers;
if (smbios_info_slot_peers(shp, id, &npeers, &peer) != 0) {
smbios_warn(shp, "failed to read slot peer "
"information");
return;
}
for (i = 0; i < npeers; i++) {
oprintf(fp, " Slot Peer %u:\n", i);
oprintf(fp, " Segment group: %u\n",
peer[i].smblp_group);
oprintf(fp, " Bus/Device/Function: %u/%u/%u\n",
peer[i].smblp_bus, peer[i].smblp_device,
peer[i].smblp_function);
oprintf(fp, " Electrical width: %u\n",
peer[i].smblp_data_width);
}
smbios_info_slot_peers_free(shp, npeers, peer);
}
if (s.smbl_info != 0) {
if (s.smbl_type >= SMB_SLT_PCIE &&
s.smbl_type <= SMB_SLT_PCIEG6P) {
oprintf(fp, " PCIe Generation: %d\n", s.smbl_info);
} else {
oprintf(fp, " Slot Type: 0x%x\n", s.smbl_info);
}
}
if (s.smbl_pwidth != 0) {
desc_printf(smbios_slot_width_desc(s.smbl_pwidth),
fp, " Physical Width: 0x%x", s.smbl_pwidth);
}
if (s.smbl_pitch != 0) {
oprintf(fp, " Slot Pitch: %u.%u mm\n", s.smbl_pitch / 100,
s.smbl_pitch % 100);
}
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
print_obdevs_ext(smbios_hdl_t *shp, id_t id, FILE *fp)
{
boolean_t enabled;
smbios_obdev_ext_t oe;
const char *type;
if (smbios_info_obdevs_ext(shp, id, &oe) != 0) {
smbios_warn(shp, "failed to read extended on-board devices "
"information");
return;
}
enabled = oe.smboe_dtype >> 7;
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" :
"false");
oprintf(fp, " Device Type: %s\n", type);
oprintf(fp, " Device Type Instance: %u\n", oe.smboe_dti);
oprintf(fp, " Segment Group Number: %u\n", oe.smboe_sg);
oprintf(fp, " Bus Number: %u\n", oe.smboe_bus);
oprintf(fp, " Device/Function Number: %u\n", oe.smboe_df);
}
static void
print_obdevs(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_obdev_t *argv;
int i, argc;
if ((argc = smbios_info_obdevs(shp, id, 0, NULL)) > 0) {
argv = alloca(sizeof (smbios_obdev_t) * argc);
if (smbios_info_obdevs(shp, id, argc, argv) == -1) {
smbios_warn(shp, "failed to read on-board device "
"information");
return;
}
for (i = 0; i < argc; i++)
str_print_nolabel(fp, " ", argv[i].smbd_name);
}
}
static void
print_strtab(smbios_hdl_t *shp, id_t id, FILE *fp)
{
const char **argv;
int i, argc;
if ((argc = smbios_info_strtab(shp, id, 0, NULL)) > 0) {
argv = alloca(sizeof (char *) * argc);
if (smbios_info_strtab(shp, id, argc, argv) == -1) {
smbios_warn(shp, "failed to read string table "
"information");
return;
}
for (i = 0; i < argc; i++)
str_print_nolabel(fp, " ", argv[i]);
}
}
static void
print_lang(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_lang_t l;
if (smbios_info_lang(shp, &l) == -1) {
smbios_warn(shp, "failed to read language information");
return;
}
str_print(fp, " Current Language", l.smbla_cur);
oprintf(fp, " Language String Format: %u\n", l.smbla_fmt);
oprintf(fp, " Number of Installed Languages: %u\n", l.smbla_num);
oprintf(fp, " Installed Languages:\n");
print_strtab(shp, id, fp);
}
static void
print_evlog(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_evlog_t ev;
uint32_t i;
if (smbios_info_eventlog(shp, &ev) == -1) {
smbios_warn(shp, "failed to read event log information");
return;
}
oprintf(fp, " Log Area Size: %lu bytes\n", (ulong_t)ev.smbev_size);
oprintf(fp, " Header Offset: %lu\n", (ulong_t)ev.smbev_hdr);
oprintf(fp, " Data Offset: %lu\n", (ulong_t)ev.smbev_data);
desc_printf(smbios_evlog_method_desc(ev.smbev_method),
fp, " Data Access Method: %u", ev.smbev_method);
flag_printf(fp, "Log Flags",
ev.smbev_flags, sizeof (ev.smbev_flags) * NBBY,
smbios_evlog_flag_name, smbios_evlog_flag_desc);
desc_printf(smbios_evlog_format_desc(ev.smbev_format),
fp, " Log Header Format: %u", ev.smbev_format);
oprintf(fp, " Update Token: 0x%x\n", ev.smbev_token);
oprintf(fp, " Data Access Address: ");
switch (ev.smbev_method) {
case SMB_EVM_1x1i_1x1d:
case SMB_EVM_2x1i_1x1d:
case SMB_EVM_1x2i_1x1d:
oprintf(fp, "Index Address 0x%x, Data Address 0x%x\n",
ev.smbev_addr.eva_io.evi_iaddr,
ev.smbev_addr.eva_io.evi_daddr);
break;
case SMB_EVM_GPNV:
oprintf(fp, "0x%x\n", ev.smbev_addr.eva_gpnv);
break;
default:
oprintf(fp, "0x%x\n", ev.smbev_addr.eva_addr);
}
oprintf(fp, " Type Descriptors:\n");
for (i = 0; i < ev.smbev_typec; i++) {
oprintf(fp, " %u: Log Type 0x%x, Data Type 0x%x\n", i,
ev.smbev_typev[i].smbevt_ltype,
ev.smbev_typev[i].smbevt_dtype);
}
}
static void
print_bytes(const uint8_t *data, size_t size, FILE *fp)
{
hexdump_t h;
hexdump_init(&h);
hexdump_set_grouping(&h, 4);
hexdump_set_indent(&h, 2);
(void) fprintf(fp, "\n");
(void) hexdump_fileh(&h, data, size, HDF_DEFAULT, fp);
(void) fprintf(fp, "\n");
hexdump_fini(&h);
}
static void
print_memarray(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_memarray_t ma;
if (smbios_info_memarray(shp, id, &ma) != 0) {
smbios_warn(shp, "failed to read memarray information");
return;
}
desc_printf(smbios_memarray_loc_desc(ma.smbma_location),
fp, " Location: %u", ma.smbma_location);
desc_printf(smbios_memarray_use_desc(ma.smbma_use),
fp, " Use: %u", ma.smbma_use);
desc_printf(smbios_memarray_ecc_desc(ma.smbma_ecc),
fp, " ECC: %u", ma.smbma_ecc);
oprintf(fp, " Number of Slots/Sockets: %u\n", ma.smbma_ndevs);
id_printf(fp, " Memory Error Data: ", ma.smbma_err);
oprintf(fp, " Max Capacity: %llu bytes\n",
(u_longlong_t)ma.smbma_size);
}
static void
print_memdevice(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_memdevice_t md;
if (smbios_info_memdevice(shp, id, &md) != 0) {
smbios_warn(shp, "failed to read memory device information");
return;
}
id_printf(fp, " Physical Memory Array: ", md.smbmd_array);
id_printf(fp, " Memory Error Data: ", md.smbmd_error);
if (md.smbmd_twidth != -1u)
oprintf(fp, " Total Width: %u bits\n", md.smbmd_twidth);
else
oprintf(fp, " Total Width: Unknown\n");
if (md.smbmd_dwidth != -1u)
oprintf(fp, " Data Width: %u bits\n", md.smbmd_dwidth);
else
oprintf(fp, " Data Width: Unknown\n");
switch (md.smbmd_size) {
case -1ull:
oprintf(fp, " Size: Unknown\n");
break;
case 0:
oprintf(fp, " Size: Not Populated\n");
break;
default:
oprintf(fp, " Size: %llu bytes\n",
(u_longlong_t)md.smbmd_size);
}
desc_printf(smbios_memdevice_form_desc(md.smbmd_form),
fp, " Form Factor: %u", md.smbmd_form);
if (md.smbmd_set == 0)
oprintf(fp, " Set: None\n");
else if (md.smbmd_set == (uint8_t)-1u)
oprintf(fp, " Set: Unknown\n");
else
oprintf(fp, " Set: %u\n", md.smbmd_set);
if (md.smbmd_rank != 0) {
desc_printf(smbios_memdevice_rank_desc(md.smbmd_rank),
fp, " Rank: %u", md.smbmd_rank);
} else {
oprintf(fp, " Rank: Unknown\n");
}
desc_printf(smbios_memdevice_type_desc(md.smbmd_type),
fp, " Memory Type: %u", md.smbmd_type);
flag_printf(fp, "Flags", md.smbmd_flags, sizeof (md.smbmd_flags) * NBBY,
smbios_memdevice_flag_name, smbios_memdevice_flag_desc);
if (md.smbmd_extspeed != 0) {
oprintf(fp, " Speed: %" PRIu64 " MT/s\n", md.smbmd_extspeed);
} else {
oprintf(fp, " Speed: Unknown\n");
}
if (md.smbmd_extclkspeed != 0) {
oprintf(fp, " Configured Speed: %" PRIu64 " MT/s\n",
md.smbmd_extclkspeed);
} else {
oprintf(fp, " Configured Speed: Unknown\n");
}
str_print(fp, " Device Locator", md.smbmd_dloc);
str_print(fp, " Bank Locator", md.smbmd_bloc);
if (md.smbmd_minvolt != 0) {
oprintf(fp, " Minimum Voltage: %.2fV\n",
md.smbmd_minvolt / 1000.0);
} else {
oprintf(fp, " Minimum Voltage: Unknown\n");
}
if (md.smbmd_maxvolt != 0) {
oprintf(fp, " Maximum Voltage: %.2fV\n",
md.smbmd_maxvolt / 1000.0);
} else {
oprintf(fp, " Maximum Voltage: Unknown\n");
}
if (md.smbmd_confvolt != 0) {
oprintf(fp, " Configured Voltage: %.2fV\n",
md.smbmd_confvolt / 1000.0);
} else {
oprintf(fp, " Configured Voltage: Unknown\n");
}
if (md.smbmd_memtech != 0) {
desc_printf(smbios_memdevice_memtech_desc(md.smbmd_memtech),
fp, " Memory Technology: %u", md.smbmd_memtech);
}
if (md.smbmd_opcap_flags != 0) {
flag_printf(fp, "Operating Mode Capabilities",
md.smbmd_opcap_flags, sizeof (md.smbmd_opcap_flags) * NBBY,
smbios_memdevice_op_capab_name,
smbios_memdevice_op_capab_desc);
}
if (md.smbmd_firmware_rev[0] != '\0') {
str_print(fp, " Firmware Revision", md.smbmd_firmware_rev);
}
if (md.smbmd_modmfg_id != SMB_MD_MFG_UNKNOWN) {
jedec_print(fp, "Module Manufacturer ID", md.smbmd_modmfg_id);
}
if (md.smbmd_modprod_id != 0) {
jedec_print(fp, "Module Product ID", md.smbmd_modprod_id);
}
if (md.smbmd_cntrlmfg_id != SMB_MD_MFG_UNKNOWN) {
jedec_print(fp, "Memory Subsystem Controller Manufacturer ID",
md.smbmd_cntrlmfg_id);
}
if (md.smbmd_cntrlprod_id != 0) {
jedec_print(fp, "Memory Subsystem Controller Product ID",
md.smbmd_cntrlprod_id);
}
if (md.smbmd_nvsize == UINT64_MAX) {
oprintf(fp, " Non-volatile Size: Unknown\n");
} else if (md.smbmd_nvsize != 0) {
oprintf(fp, " Non-volatile Size: %llu bytes\n",
(u_longlong_t)md.smbmd_nvsize);
}
if (md.smbmd_volatile_size == UINT64_MAX) {
oprintf(fp, " Volatile Size: Unknown\n");
} else if (md.smbmd_volatile_size != 0) {
oprintf(fp, " Volatile Size: %llu bytes\n",
(u_longlong_t)md.smbmd_volatile_size);
}
if (md.smbmd_cache_size == UINT64_MAX) {
oprintf(fp, " Cache Size: Unknown\n");
} else if (md.smbmd_cache_size != 0) {
oprintf(fp, " Cache Size: %llu bytes\n",
(u_longlong_t)md.smbmd_cache_size);
}
if (md.smbmd_logical_size == UINT64_MAX) {
oprintf(fp, " Logical Size: Unknown\n");
} else if (md.smbmd_logical_size != 0) {
oprintf(fp, " Logical Size: %llu bytes\n",
(u_longlong_t)md.smbmd_logical_size);
}
if (md.smbmd_pmic0_mfgid != SMB_MD_MFG_UNKNOWN) {
jedec_print(fp, "PMIC0 Manufacturer ID", md.smbmd_pmic0_mfgid);
}
if (md.smbmd_pmic0_rev != SMB_MD_REV_UNKNOWN) {
jedec_rev_print(fp, "PMIC0 Revision", md.smbmd_pmic0_rev);
}
if (md.smbmd_rcd_mfgid != SMB_MD_MFG_UNKNOWN) {
jedec_print(fp, "RCD Manufacturer ID", md.smbmd_rcd_mfgid);
}
if (md.smbmd_rcd_rev != SMB_MD_REV_UNKNOWN) {
jedec_rev_print(fp, "RCD Revision", md.smbmd_rcd_rev);
}
}
static void
print_memarrmap(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_memarrmap_t ma;
if (smbios_info_memarrmap(shp, id, &ma) != 0) {
smbios_warn(shp, "failed to read memory array map information");
return;
}
id_printf(fp, " Physical Memory Array: ", ma.smbmam_array);
oprintf(fp, " Devices per Row: %u\n", ma.smbmam_width);
oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n",
(u_longlong_t)ma.smbmam_addr, (u_longlong_t)ma.smbmam_size);
}
static void
print_memdevmap(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_memdevmap_t md;
if (smbios_info_memdevmap(shp, id, &md) != 0) {
smbios_warn(shp, "failed to read memory device map "
"information");
return;
}
id_printf(fp, " Memory Device: ", md.smbmdm_device);
id_printf(fp, " Memory Array Mapped Address: ", md.smbmdm_arrmap);
oprintf(fp, " Physical Address: 0x%llx\n Size: %llu bytes\n",
(u_longlong_t)md.smbmdm_addr, (u_longlong_t)md.smbmdm_size);
oprintf(fp, " Partition Row Position: %u\n", md.smbmdm_rpos);
oprintf(fp, " Interleave Position: %u\n", md.smbmdm_ipos);
oprintf(fp, " Interleave Data Depth: %u\n", md.smbmdm_idepth);
}
static void
print_hwsec(smbios_hdl_t *shp, FILE *fp)
{
smbios_hwsec_t h;
if (smbios_info_hwsec(shp, &h) == -1) {
smbios_warn(shp, "failed to read hwsec information");
return;
}
desc_printf(smbios_hwsec_desc(h.smbh_pwr_ps),
fp, " Power-On Password Status: %u", h.smbh_pwr_ps);
desc_printf(smbios_hwsec_desc(h.smbh_kbd_ps),
fp, " Keyboard Password Status: %u", h.smbh_kbd_ps);
desc_printf(smbios_hwsec_desc(h.smbh_adm_ps),
fp, " Administrator Password Status: %u", h.smbh_adm_ps);
desc_printf(smbios_hwsec_desc(h.smbh_pan_ps),
fp, " Front Panel Reset Status: %u", h.smbh_pan_ps);
}
static void
print_vprobe(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_vprobe_t vp;
if (smbios_info_vprobe(shp, id, &vp) != 0) {
smbios_warn(shp, "failed to read voltage probe information");
return;
}
str_print(fp, " Description", vp.smbvp_description != NULL ?
vp.smbvp_description : "unknown");
desc_printf(smbios_vprobe_loc_desc(vp.smbvp_location),
fp, " Location: %u", vp.smbvp_location);
desc_printf(smbios_vprobe_status_desc(vp.smbvp_status),
fp, " Status: %u", vp.smbvp_status);
if (vp.smbvp_maxval != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Maximum Possible Voltage: %u mV\n",
vp.smbvp_maxval);
} else {
oprintf(fp, " Maximum Possible Voltage: unknown\n");
}
if (vp.smbvp_minval != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Minimum Possible Voltage: %u mV\n",
vp.smbvp_minval);
} else {
oprintf(fp, " Minimum Possible Voltage: unknown\n");
}
if (vp.smbvp_resolution != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Resolution: %u.%u mV\n",
vp.smbvp_resolution / 10,
vp.smbvp_resolution % 10);
} else {
oprintf(fp, " Probe Resolution: unknown\n");
}
if (vp.smbvp_tolerance != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Tolerance: +/-%u mV\n",
vp.smbvp_tolerance);
} else {
oprintf(fp, " Probe Tolerance: unknown\n");
}
if (vp.smbvp_accuracy != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n",
vp.smbvp_accuracy / 100,
vp.smbvp_accuracy % 100);
} else {
oprintf(fp, " Probe Accuracy: unknown\n");
}
oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", vp.smbvp_oem);
if (vp.smbvp_nominal != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Nominal Value: %u mV\n", vp.smbvp_nominal);
} else {
oprintf(fp, " Probe Nominal Value: unknown\n");
}
}
static void
print_cooldev(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_cooldev_t cd;
if (smbios_info_cooldev(shp, id, &cd) != 0) {
smbios_warn(shp, "failed to read cooling device "
"information");
return;
}
id_printf(fp, " Temperature Probe Handle: ", cd.smbcd_tprobe);
desc_printf(smbios_cooldev_type_desc(cd.smbcd_type),
fp, " Device Type: %u", cd.smbcd_type);
desc_printf(smbios_cooldev_status_desc(cd.smbcd_status),
fp, " Status: %u", cd.smbcd_status);
oprintf(fp, " Cooling Unit Group: %u\n", cd.smbcd_group);
oprintf(fp, " OEM- or BIOS- defined data: 0x%x\n", cd.smbcd_oem);
if (cd.smbcd_nominal != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Nominal Speed: %u RPM\n", cd.smbcd_nominal);
} else {
oprintf(fp, " Nominal Speed: unknown\n");
}
if (cd.smbcd_descr != NULL && cd.smbcd_descr[0] != '\0') {
str_print(fp, " Description", cd.smbcd_descr);
}
}
static void
print_tprobe(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_tprobe_t tp;
if (smbios_info_tprobe(shp, id, &tp) != 0) {
smbios_warn(shp, "failed to read temperature probe "
"information");
return;
}
str_print(fp, " Description", tp.smbtp_description != NULL ?
tp.smbtp_description : "unknown");
desc_printf(smbios_tprobe_loc_desc(tp.smbtp_location),
fp, " Location: %u", tp.smbtp_location);
desc_printf(smbios_tprobe_status_desc(tp.smbtp_status),
fp, " Status: %u", tp.smbtp_status);
if (tp.smbtp_maxval != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Maximum Possible Temperature: %u.%u C\n",
tp.smbtp_maxval / 10, tp.smbtp_maxval % 10);
} else {
oprintf(fp, " Maximum Possible Temperature: unknown\n");
}
if (tp.smbtp_minval != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Minimum Possible Temperature: %u.%u C\n",
tp.smbtp_minval / 10, tp.smbtp_minval % 10);
} else {
oprintf(fp, " Minimum Possible Temperature: unknown\n");
}
if (tp.smbtp_resolution != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Resolution: %u.%03u C\n",
tp.smbtp_resolution / 1000,
tp.smbtp_resolution % 1000);
} else {
oprintf(fp, " Probe Resolution: unknown\n");
}
if (tp.smbtp_tolerance != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Tolerance: +/-%u.%u C\n",
tp.smbtp_tolerance / 10, tp.smbtp_tolerance % 10);
} else {
oprintf(fp, " Probe Tolerance: unknown\n");
}
if (tp.smbtp_accuracy != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n",
tp.smbtp_accuracy / 100,
tp.smbtp_accuracy % 100);
} else {
oprintf(fp, " Probe Accuracy: unknown\n");
}
oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", tp.smbtp_oem);
if (tp.smbtp_nominal != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Nominal Value: %u.%u C\n",
tp.smbtp_nominal / 10, tp.smbtp_nominal % 10);
} else {
oprintf(fp, " Probe Nominal Value: unknown\n");
}
}
static void
print_iprobe(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_iprobe_t ip;
if (smbios_info_iprobe(shp, id, &ip) != 0) {
smbios_warn(shp, "failed to read current probe information");
return;
}
str_print(fp, " Description", ip.smbip_description != NULL ?
ip.smbip_description : "unknown");
desc_printf(smbios_iprobe_loc_desc(ip.smbip_location),
fp, " Location: %u", ip.smbip_location);
desc_printf(smbios_iprobe_status_desc(ip.smbip_status),
fp, " Status: %u", ip.smbip_status);
if (ip.smbip_maxval != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Maximum Possible Current: %u mA\n",
ip.smbip_maxval);
} else {
oprintf(fp, " Maximum Possible Current: unknown\n");
}
if (ip.smbip_minval != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Minimum Possible Current: %u mA\n",
ip.smbip_minval);
} else {
oprintf(fp, " Minimum Possible Current: unknown\n");
}
if (ip.smbip_resolution != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Resolution: %u.%u mA\n",
ip.smbip_resolution / 10,
ip.smbip_resolution % 10);
} else {
oprintf(fp, " Probe Resolution: unknown\n");
}
if (ip.smbip_tolerance != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Tolerance: +/-%u mA\n",
ip.smbip_tolerance);
} else {
oprintf(fp, " Probe Tolerance: unknown\n");
}
if (ip.smbip_accuracy != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n",
ip.smbip_accuracy / 100,
ip.smbip_accuracy % 100);
} else {
oprintf(fp, " Probe Accuracy: unknown\n");
}
oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", ip.smbip_oem);
if (ip.smbip_nominal != SMB_PROBE_UNKNOWN_VALUE) {
oprintf(fp, " Probe Nominal Value: %u mA\n", ip.smbip_nominal);
} else {
oprintf(fp, " Probe Nominal Value: unknown\n");
}
}
static void
print_boot(smbios_hdl_t *shp, FILE *fp)
{
smbios_boot_t b;
if (smbios_info_boot(shp, &b) == -1) {
smbios_warn(shp, "failed to read boot information");
return;
}
desc_printf(smbios_boot_desc(b.smbt_status),
fp, " Boot Status Code: 0x%x", b.smbt_status);
if (b.smbt_size != 0) {
oprintf(fp, " Boot Data (%lu bytes):\n", (ulong_t)b.smbt_size);
print_bytes(b.smbt_data, b.smbt_size, fp);
}
}
static void
print_mgmtdev(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_mgmtdev_t md;
if (smbios_info_mgmtdev(shp, id, &md) == -1) {
smbios_warn(shp, "failed to read management device");
return;
}
str_print(fp, " Description", md.smbmd_desc);
desc_printf(smbios_mgmtdev_dtype_desc(md.smbmd_dtype), fp,
" Device Type: 0x%x", md.smbmd_dtype);
oprintf(fp, " Address: 0x%x\n", md.smbmd_addr);
desc_printf(smbios_mgmtdev_atype_desc(md.smbmd_atype), fp,
" Address Type: 0x%x", md.smbmd_atype);
}
static void
print_mgmtcomp(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_mgmtcomp_t mc;
if (smbios_info_mgmtcomp(shp, id, &mc) == -1) {
smbios_warn(shp, "failed to read management device component");
return;
}
str_print(fp, " Description", mc.smbmc_desc);
id_printf(fp, " Management Device Handle: ", mc.smbmc_mgmtdev);
id_printf(fp, " Component Handle: ", mc.smbmc_comp);
id_printf(fp, " Threshold Handle: ", mc.smbmc_thresh);
}
static void
print_ipmi(smbios_hdl_t *shp, FILE *fp)
{
smbios_ipmi_t i;
if (smbios_info_ipmi(shp, &i) == -1) {
smbios_warn(shp, "failed to read ipmi information");
return;
}
desc_printf(smbios_ipmi_type_desc(i.smbip_type),
fp, " Type: %u", i.smbip_type);
oprintf(fp, " BMC IPMI Version: %u.%u\n",
i.smbip_vers.smbv_major, i.smbip_vers.smbv_minor);
oprintf(fp, " i2c Bus Slave Address: 0x%x\n", i.smbip_i2c);
oprintf(fp, " NV Storage Device Bus ID: 0x%x\n", i.smbip_bus);
oprintf(fp, " BMC Base Address: 0x%llx\n", (u_longlong_t)i.smbip_addr);
oprintf(fp, " Interrupt Number: %u\n", i.smbip_intr);
oprintf(fp, " Register Spacing: %u\n", i.smbip_regspacing);
flag_printf(fp, "Flags", i.smbip_flags, sizeof (i.smbip_flags) * NBBY,
smbios_ipmi_flag_name, smbios_ipmi_flag_desc);
}
static void
print_powersup(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_powersup_t p;
if (smbios_info_powersup(shp, id, &p) != 0) {
smbios_warn(shp, "failed to read power supply information");
return;
}
oprintf(fp, " Power Supply Group: %u\n", p.smbps_group);
if (p.smbps_maxout != 0x8000) {
oprintf(fp, " Maximum Output: %" PRIu64 " mW\n",
p.smbps_maxout);
} else {
oprintf(fp, " Maximum Output: unknown\n");
}
flag_printf(fp, "Characteristics", p.smbps_flags,
sizeof (p.smbps_flags) * NBBY, smbios_powersup_flag_name,
smbios_powersup_flag_desc);
desc_printf(smbios_powersup_input_desc(p.smbps_ivrs),
fp, " Input Voltage Range Switching: %u", p.smbps_ivrs);
desc_printf(smbios_powersup_status_desc(p.smbps_status),
fp, " Status: %u", p.smbps_status);
desc_printf(smbios_powersup_type_desc(p.smbps_pstype),
fp, " Type: %u", p.smbps_pstype);
if (p.smbps_vprobe != 0xffff) {
oprintf(fp, " Voltage Probe Handle: %" _PRIuID "\n",
p.smbps_vprobe);
}
if (p.smbps_cooldev != 0xffff) {
oprintf(fp, " Cooling Device Handle: %" _PRIuID "\n",
p.smbps_cooldev);
}
if (p.smbps_iprobe != 0xffff) {
oprintf(fp, " Current Probe Handle: %" _PRIuID "\n",
p.smbps_iprobe);
}
}
static void
print_addinfo(smbios_hdl_t *shp, id_t id, FILE *fp)
{
uint_t nents, i;
if (smbios_info_addinfo_nents(shp, id, &nents) != 0) {
smbios_warn(shp, "failed to read additional information");
return;
}
oprintf(fp, " Number of Additional Information Entries: %u\n", nents);
for (i = 0; i < nents; i++) {
smbios_addinfo_ent_t *ent;
oprintf(fp, " Additional Information Entry %u\n", i);
if (smbios_info_addinfo_ent(shp, id, i, &ent) != 0) {
smbios_warn(shp, "failed to read additional "
"information entry %u", i);
continue;
}
oprintf(fp, " Referenced handle: %" _PRIuID "\n",
ent->smbai_ref);
oprintf(fp, " Handle offset: %u\n", ent->smbai_ref_off);
if (ent->smbai_str != NULL) {
str_print(fp, " Information String", ent->smbai_str);
}
if (ent->smbai_dlen > 0) {
oprintf(fp, " Data Length: %u\n", ent->smbai_dlen);
switch (ent->smbai_dlen) {
case 1:
oprintf(fp, " Data: 0x%x\n",
*(uint8_t *)ent->smbai_data);
break;
case 2:
oprintf(fp, " Data: 0x%x\n",
*(uint16_t *)ent->smbai_data);
break;
case 4:
oprintf(fp, " Data: 0x%x\n",
*(uint32_t *)ent->smbai_data);
break;
case 8:
oprintf(fp, " Data: 0x%" PRIx64 "\n",
*(uint64_t *)ent->smbai_data);
break;
default:
break;
}
}
smbios_info_addinfo_ent_free(shp, ent);
}
}
static void
print_processor_info_riscv(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_processor_info_riscv_t rv;
if (smbios_info_processor_riscv(shp, id, &rv) != 0) {
smbios_warn(shp, "failed to read RISC-V specific processor "
"information");
return;
}
if (rv.smbpirv_boothart != 0) {
oprintf(fp, " Boot Hart\n");
}
u128_print(fp, " Hart ID", rv.smbpirv_hartid);
u128_print(fp, " Vendor ID", rv.smbpirv_vendid);
u128_print(fp, " Architecture ID", rv.smbpirv_archid);
u128_print(fp, " Implementation ID", rv.smbpirv_machid);
flag64_printf(fp, " ISA", rv.smbpirv_isa,
sizeof (rv.smbpirv_isa) * NBBY, smbios_riscv_isa_name,
smbios_riscv_isa_desc);
flag_printf(fp, " Privilege Levels", rv.smbpirv_privlvl,
sizeof (rv.smbpirv_privlvl) * NBBY, smbios_riscv_priv_name,
smbios_riscv_priv_desc);
u128_print(fp, " Machine Exception Trap Delegation",
rv.smbpirv_metdi);
u128_print(fp, " Machine Interrupt Trap Delegation",
rv.smbpirv_mitdi);
desc_printf(smbios_riscv_width_desc(rv.smbpirv_xlen),
fp, " Register Width: 0x%x", rv.smbpirv_xlen);
desc_printf(smbios_riscv_width_desc(rv.smbpirv_mxlen),
fp, " M-Mode Register Width: 0x%x", rv.smbpirv_mxlen);
desc_printf(smbios_riscv_width_desc(rv.smbpirv_sxlen),
fp, " S-Mode Register Width: 0x%x", rv.smbpirv_sxlen);
desc_printf(smbios_riscv_width_desc(rv.smbpirv_uxlen),
fp, " U-Mode Register Width: 0x%x", rv.smbpirv_uxlen);
}
static void
print_processor_info(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_processor_info_t p;
if (smbios_info_processor_info(shp, id, &p) != 0) {
smbios_warn(shp, "failed to read processor additional "
"information");
return;
}
id_printf(fp, " Processor Handle: ", p.smbpi_processor);
desc_printf(smbios_processor_info_type_desc(p.smbpi_ptype),
fp, " Processor Type: %u", p.smbpi_ptype);
switch (p.smbpi_ptype) {
case SMB_PROCINFO_T_RV32:
case SMB_PROCINFO_T_RV64:
case SMB_PROCINFO_T_RV128:
oprintf(fp, " RISC-V Additional Processor Information:\n");
print_processor_info_riscv(shp, id, fp);
break;
default:
break;
}
}
static void
print_battery(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_battery_t bat;
if (smbios_info_battery(shp, id, &bat) != 0) {
smbios_warn(shp, "failed to read battery information");
return;
}
if (bat.smbb_date != NULL) {
str_print(fp, " Manufacture Date", bat.smbb_date);
}
if (bat.smbb_serial != NULL) {
str_print(fp, " Serial Number", bat.smbb_serial);
}
if (bat.smbb_chem != SMB_BDC_UNKNOWN) {
desc_printf(smbios_battery_chem_desc(bat.smbb_chem),
fp, " Battery Chemistry: 0x%x", bat.smbb_chem);
}
if (bat.smbb_cap != 0) {
oprintf(fp, " Design Capacity: %u mWh\n", bat.smbb_cap);
} else {
oprintf(fp, " Design Capacity: unknown\n");
}
if (bat.smbb_volt != 0) {
oprintf(fp, " Design Voltage: %u mV\n", bat.smbb_volt);
} else {
oprintf(fp, " Design Voltage: unknown\n");
}
str_print(fp, " SBDS Version Number", bat.smbb_version);
if (bat.smbb_err != UINT8_MAX) {
oprintf(fp, " Maximum Error: %u\n", bat.smbb_err);
} else {
oprintf(fp, " Maximum Error: unknown\n");
}
oprintf(fp, " SBDS Serial Number: %04x\n", bat.smbb_ssn);
oprintf(fp, " SBDS Manufacture Date: %u-%02u-%02u\n", bat.smbb_syear,
bat.smbb_smonth, bat.smbb_sday);
str_print(fp, " SBDS Device Chemistry", bat.smbb_schem);
oprintf(fp, " OEM-specific Information: 0x%08x\n", bat.smbb_oemdata);
}
static void
print_pointdev(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_pointdev_t pd;
if (smbios_info_pointdev(shp, id, &pd) != 0) {
smbios_warn(shp, "failed to read pointer device information");
return;
}
desc_printf(smbios_pointdev_type_desc(pd.smbpd_type),
fp, " Type: %u", pd.smbpd_type);
desc_printf(smbios_pointdev_iface_desc(pd.smbpd_iface),
fp, " Interface: %u", pd.smbpd_iface);
oprintf(fp, " Buttons: %u\n", pd.smbpd_nbuttons);
}
static void
print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp)
{
int i;
smbios_processor_ext_t ep;
if (check_oem(shp) != 0)
return;
if (smbios_info_extprocessor(shp, id, &ep) != 0) {
smbios_warn(shp, "failed to read extended processor "
"information");
return;
}
oprintf(fp, " Processor: %u\n", ep.smbpe_processor);
oprintf(fp, " FRU: %u\n", ep.smbpe_fru);
oprintf(fp, " Initial APIC ID count: %u\n\n", ep.smbpe_n);
for (i = 0; i < ep.smbpe_n; i++) {
oprintf(fp, " Logical Strand %u: Initial APIC ID: %u\n", i,
ep.smbpe_apicid[i]);
}
}
static void
print_extport(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_port_ext_t epo;
if (check_oem(shp) != 0)
return;
if (smbios_info_extport(shp, id, &epo) != 0) {
smbios_warn(shp, "failed to read extended port information");
return;
}
oprintf(fp, " Chassis Handle: %u\n", epo.smbporte_chassis);
oprintf(fp, " Port Connector Handle: %u\n", epo.smbporte_port);
oprintf(fp, " Device Type: %u\n", epo.smbporte_dtype);
oprintf(fp, " Device Handle: %u\n", epo.smbporte_devhdl);
oprintf(fp, " PHY: %u\n", epo.smbporte_phy);
}
static void
print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_pciexrc_t pcie;
if (check_oem(shp) != 0)
return;
if (smbios_info_pciexrc(shp, id, &pcie) != 0) {
smbios_warn(shp, "failed to read pciexrc information");
return;
}
oprintf(fp, " Component ID: %u\n", pcie.smbpcie_bb);
oprintf(fp, " BDF: 0x%x\n", pcie.smbpcie_bdf);
}
static void
print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_memarray_ext_t em;
if (check_oem(shp) != 0)
return;
if (smbios_info_extmemarray(shp, id, &em) != 0) {
smbios_warn(shp, "failed to read extmemarray information");
return;
}
oprintf(fp, " Physical Memory Array Handle: %u\n", em.smbmae_ma);
oprintf(fp, " Component Parent Handle: %u\n", em.smbmae_comp);
oprintf(fp, " BDF: 0x%x\n", em.smbmae_bdf);
}
static void
print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp)
{
uint_t i, ncs;
uint8_t *cs;
smbios_memdevice_ext_t emd;
if (check_oem(shp) != 0)
return;
if (smbios_info_extmemdevice(shp, id, &emd) != 0) {
smbios_warn(shp, "failed to read extmemdevice information");
return;
}
oprintf(fp, " Memory Device Handle: %u\n", emd.smbmdeve_md);
oprintf(fp, " DRAM Channel: %u\n", emd.smbmdeve_drch);
oprintf(fp, " Number of Chip Selects: %u\n", emd.smbmdeve_ncs);
if (emd.smbmdeve_ncs == 0)
return;
if (smbios_info_extmemdevice_cs(shp, id, &ncs, &cs) != 0) {
smbios_warn(shp, "failed to read extmemdevice cs information");
return;
}
for (i = 0; i < ncs; i++) {
oprintf(fp, " Chip Select: %u\n", cs[i]);
}
smbios_info_extmemdevice_cs_free(shp, ncs, cs);
}
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_tpm(smbios_hdl_t *shp, id_t id, FILE *fp)
{
size_t i;
smbios_tpm_t tpm;
if (smbios_info_tpm(shp, id, &tpm) != 0) {
smbios_warn(shp, "failed to read TPM information");
return;
}
oprintf(fp, " Vendor ID: ");
for (i = 0; i < ARRAY_SIZE(tpm.smbtpm_vid); i++) {
if (tpm.smbtpm_vid[i] == '\0')
break;
if (isascii(tpm.smbtpm_vid[i]) && isprint(tpm.smbtpm_vid[i])) {
(void) oprintf(fp, "%c", tpm.smbtpm_vid[i]);
} else {
oprintf(fp, "\\x%02x", tpm.smbtpm_vid[i]);
}
}
oprintf(fp, "\n");
oprintf(fp, " Spec Version: %u.%u\n", tpm.smbtpm_major,
tpm.smbtpm_minor);
oprintf(fp, " Firmware Version 1: 0x%x\n", tpm.smbtpm_fwv1);
oprintf(fp, " Firmware Version 2: 0x%x\n", tpm.smbtpm_fwv2);
str_print(fp, " Description", tpm.smbtpm_desc);
flag64_printf(fp, "Characteristics",
tpm.smbtpm_chars, sizeof (tpm.smbtpm_chars) * NBBY,
smbios_tpm_char_name, smbios_tpm_char_desc);
oprintf(fp, " OEM-defined: 0x%x", tpm.smbtpm_oem);
}
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, " %" _PRIdID "\n", comps[i].smbfwe_id);
}
}
static int
print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp)
{
smbios_info_t info;
int hex = opt_x;
const char *s;
if (opt_t != -1 && opt_t != sp->smbstr_type)
return (0);
if (!opt_O && (sp->smbstr_type == SMB_TYPE_MEMCTL ||
sp->smbstr_type == SMB_TYPE_MEMMOD))
return (0);
if (g_hdr++ == 0 || !opt_s)
oprintf(fp, "%-5s %-4s %s\n", "ID", "SIZE", "TYPE");
oprintf(fp, "%-5u %-4lu",
(uint_t)sp->smbstr_id, (ulong_t)sp->smbstr_size);
if ((s = smbios_type_name(sp->smbstr_type)) != NULL)
oprintf(fp, " %s (type %u)", s, sp->smbstr_type);
else if (sp->smbstr_type > SMB_TYPE_OEM_LO &&
sp->smbstr_type < SMB_TYPE_OEM_HI)
oprintf(fp, " %s+%u (type %u)", "SMB_TYPE_OEM_LO",
sp->smbstr_type - SMB_TYPE_OEM_LO, sp->smbstr_type);
else
oprintf(fp, " %u", sp->smbstr_type);
if ((s = smbios_type_desc(sp->smbstr_type)) != NULL)
oprintf(fp, " (%s)\n", s);
else
oprintf(fp, "\n");
if (opt_s)
return (0);
if (smbios_info_common(shp, sp->smbstr_id, &info) == 0) {
oprintf(fp, "\n");
print_common(&info, fp);
}
switch (sp->smbstr_type) {
case SMB_TYPE_BIOS:
oprintf(fp, "\n");
print_bios(shp, fp);
break;
case SMB_TYPE_SYSTEM:
oprintf(fp, "\n");
print_system(shp, fp);
break;
case SMB_TYPE_BASEBOARD:
oprintf(fp, "\n");
print_bboard(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_CHASSIS:
oprintf(fp, "\n");
print_chassis(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_PROCESSOR:
oprintf(fp, "\n");
print_processor(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_CACHE:
oprintf(fp, "\n");
print_cache(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_PORT:
oprintf(fp, "\n");
print_port(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_SLOT:
oprintf(fp, "\n");
print_slot(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_OBDEVS:
oprintf(fp, "\n");
print_obdevs(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_OEMSTR:
case SMB_TYPE_SYSCONFSTR:
oprintf(fp, "\n");
print_strtab(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_LANG:
oprintf(fp, "\n");
print_lang(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_EVENTLOG:
oprintf(fp, "\n");
print_evlog(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_MEMARRAY:
oprintf(fp, "\n");
print_memarray(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_MEMDEVICE:
oprintf(fp, "\n");
print_memdevice(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_MEMARRAYMAP:
oprintf(fp, "\n");
print_memarrmap(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_MEMDEVICEMAP:
oprintf(fp, "\n");
print_memdevmap(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_BATTERY:
oprintf(fp, "\n");
print_battery(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_POINTDEV:
oprintf(fp, "\n");
print_pointdev(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_SECURITY:
oprintf(fp, "\n");
print_hwsec(shp, fp);
break;
case SMB_TYPE_VPROBE:
oprintf(fp, "\n");
print_vprobe(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_COOLDEV:
oprintf(fp, "\n");
print_cooldev(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_TPROBE:
oprintf(fp, "\n");
print_tprobe(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_IPROBE:
oprintf(fp, "\n");
print_iprobe(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_BOOT:
oprintf(fp, "\n");
print_boot(shp, fp);
break;
case SMB_TYPE_MGMTDEV:
oprintf(fp, "\n");
print_mgmtdev(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_MGMTDEVCP:
oprintf(fp, "\n");
print_mgmtcomp(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_IPMIDEV:
oprintf(fp, "\n");
print_ipmi(shp, fp);
break;
case SMB_TYPE_POWERSUP:
oprintf(fp, "\n");
print_powersup(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_ADDINFO:
oprintf(fp, "\n");
print_addinfo(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_OBDEVEXT:
oprintf(fp, "\n");
print_obdevs_ext(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_PROCESSOR_INFO:
oprintf(fp, "\n");
print_processor_info(shp, sp->smbstr_id, fp);
break;
case SMB_TYPE_TPM:
oprintf(fp, "\n");
print_tpm(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);
break;
case SUN_OEM_EXT_PORT:
oprintf(fp, "\n");
print_extport(shp, sp->smbstr_id, fp);
break;
case SUN_OEM_PCIEXRC:
oprintf(fp, "\n");
print_pciexrc(shp, sp->smbstr_id, fp);
break;
case SUN_OEM_EXT_MEMARRAY:
oprintf(fp, "\n");
print_extmemarray(shp, sp->smbstr_id, fp);
break;
case SUN_OEM_EXT_MEMDEVICE:
oprintf(fp, "\n");
print_extmemdevice(shp, sp->smbstr_id, fp);
break;
default:
hex++;
}
if (hex)
print_bytes(sp->smbstr_data, sp->smbstr_size, fp);
else
oprintf(fp, "\n");
return (0);
}
static uint16_t
getu16(const char *name, const char *s)
{
u_longlong_t val;
char *p;
errno = 0;
val = strtoull(s, &p, 0);
if (errno != 0 || p == s || *p != '\0' || val > UINT16_MAX) {
(void) fprintf(stderr, "%s: invalid %s argument -- %s\n",
g_pname, name, s);
exit(SMBIOS_USAGE);
}
return ((uint16_t)val);
}
static uint16_t
getstype(const char *name, const char *s)
{
const char *ts;
uint16_t t;
for (t = 0; t < SMB_TYPE_OEM_LO; t++) {
if ((ts = smbios_type_name(t)) != NULL && strcmp(s, ts) == 0)
return (t);
}
(void) fprintf(stderr, "%s: invalid %s argument -- %s\n",
g_pname, name, s);
exit(SMBIOS_USAGE);
}
static int
usage(FILE *fp)
{
(void) fprintf(fp, "Usage: %s "
"[-BeOsx] [-i id] [-t type] [-w file] [file]\n\n", g_pname);
(void) fprintf(fp,
"\t-B disable header validation for broken BIOSes\n"
"\t-e display SMBIOS entry point information\n"
"\t-i display only the specified structure\n"
"\t-O display obsolete structure types\n"
"\t-s display only a summary of structure identifiers and types\n"
"\t-t display only the specified structure type\n"
"\t-w write the raw data to the specified file\n"
"\t-x display raw data for structures\n");
return (SMBIOS_USAGE);
}
int
main(int argc, char *argv[])
{
const char *ifile = NULL;
const char *ofile = NULL;
int oflags = 0;
smbios_hdl_t *shp;
smbios_struct_t s;
int err, fd, c;
char *p;
if ((p = strrchr(argv[0], '/')) == NULL)
g_pname = argv[0];
else
g_pname = p + 1;
while (optind < argc) {
while ((c = getopt(argc, argv, "Bei:Ost:w:xZ")) != EOF) {
switch (c) {
case 'B':
oflags |= SMB_O_NOCKSUM | SMB_O_NOVERS;
break;
case 'e':
opt_e++;
break;
case 'i':
opt_i = getu16("struct ID", optarg);
break;
case 'O':
opt_O++;
break;
case 's':
opt_s++;
break;
case 't':
if (isdigit(optarg[0]))
opt_t = getu16("struct type", optarg);
else
opt_t = getstype("struct type", optarg);
break;
case 'w':
ofile = optarg;
break;
case 'x':
opt_x++;
break;
case 'Z':
oflags |= SMB_O_ZIDS;
break;
default:
return (usage(stderr));
}
}
if (optind < argc) {
if (ifile != NULL) {
(void) fprintf(stderr, "%s: illegal "
"argument -- %s\n", g_pname, argv[optind]);
return (SMBIOS_USAGE);
}
ifile = argv[optind++];
}
}
if ((shp = smbios_open(ifile, SMB_VERSION, oflags, &err)) == NULL) {
(void) fprintf(stderr, "%s: failed to load SMBIOS: %s\n",
g_pname, smbios_errmsg(err));
return (SMBIOS_ERROR);
}
if (opt_i == -1 && opt_t == -1 && opt_e == 0 &&
smbios_truncated(shp))
(void) fprintf(stderr, "%s: SMBIOS table is truncated\n",
g_pname);
if (ofile != NULL) {
if ((fd = open(ofile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) {
(void) fprintf(stderr, "%s: failed to open %s: %s\n",
g_pname, ofile, strerror(errno));
err = SMBIOS_ERROR;
} else if (smbios_write(shp, fd) != 0) {
(void) fprintf(stderr, "%s: failed to write %s: %s\n",
g_pname, ofile, smbios_errmsg(smbios_errno(shp)));
err = SMBIOS_ERROR;
}
smbios_close(shp);
return (err);
}
if (opt_e) {
print_smbios(shp, stdout);
smbios_close(shp);
return (SMBIOS_SUCCESS);
}
if (opt_O && (opt_i != -1 || opt_t != -1))
opt_O++;
if (opt_i != -1)
err = smbios_lookup_id(shp, opt_i, &s);
else
err = smbios_iter(shp, print_struct, stdout);
if (err != 0) {
(void) fprintf(stderr, "%s: failed to access SMBIOS: %s\n",
g_pname, smbios_errmsg(smbios_errno(shp)));
smbios_close(shp);
return (SMBIOS_ERROR);
}
if (opt_i != -1)
(void) print_struct(shp, &s, stdout);
smbios_close(shp);
return (SMBIOS_SUCCESS);
}