#include <smbios.h>
#include <alloca.h>
#include <locale.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <pcidb.h>
#include <fm/libtopo.h>
#include <fm/topo_hc.h>
#include <sys/fm/protocol.h>
static pcidb_hdl_t *prt_php;
static int
do_procs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
{
smbios_processor_t p;
smbios_info_t info;
const char *v;
char *s;
size_t n;
if (sp->smbstr_type == SMB_TYPE_PROCESSOR &&
smbios_info_processor(shp, sp->smbstr_id, &p) != SMB_ERR &&
smbios_info_common(shp, sp->smbstr_id, &info) != SMB_ERR &&
SMB_PRSTATUS_PRESENT(p.smbp_status)) {
if (info.smbi_version != NULL && *info.smbi_version != '\0') {
n = strlen(info.smbi_version);
v = s = alloca(n + 1);
(void) strcpy(s, info.smbi_version);
if (s[n - 1] == '\r')
s[--n] = '\0';
while (n != 0 && isspace(s[n - 1]))
s[--n] = '\0';
} else if ((v = smbios_processor_family_desc(
p.smbp_family)) == NULL) {
v = gettext("Unknown");
}
(void) printf(gettext("%-32s %s\n"), v, info.smbi_location);
}
return (0);
}
static int
do_memdevs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
{
smbios_memdevice_t md;
if (sp->smbstr_type == SMB_TYPE_MEMDEVICE &&
smbios_info_memdevice(shp, sp->smbstr_id, &md) != SMB_ERR) {
const char *t = smbios_memdevice_type_desc(md.smbmd_type);
char buf[8];
if (md.smbmd_set != (uint8_t)-1)
(void) snprintf(buf, sizeof (buf), "%u", md.smbmd_set);
else
(void) strcpy(buf, "-");
(void) printf(gettext("%-11s %-6s %-3s %-19s %s\n"),
t ? t : gettext("Unknown"),
md.smbmd_size ? gettext("in use") : gettext("empty"),
buf, md.smbmd_dloc, md.smbmd_bloc);
}
return (0);
}
static int
do_obdevs(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
{
smbios_obdev_t *argv;
int i, argc;
if (sp->smbstr_type == SMB_TYPE_OBDEVS &&
(argc = smbios_info_obdevs(shp, sp->smbstr_id, 0, NULL)) > 0) {
argv = alloca(sizeof (smbios_obdev_t) * argc);
(void) smbios_info_obdevs(shp, sp->smbstr_id, argc, argv);
for (i = 0; i < argc; i++)
(void) printf(gettext("%s\n"), argv[i].smbd_name);
}
return (0);
}
static int
do_slot_mapping_cb(topo_hdl_t *thp, tnode_t *node, void *arg)
{
int err, ret;
nvlist_t *rsrc = NULL;
const char *match = arg;
char *s, *fmri = NULL;
char *didstr = NULL, *driver = NULL, *vidstr = NULL;
boolean_t printed = B_FALSE;
ret = TOPO_WALK_NEXT;
if (topo_node_resource(node, &rsrc, &err) < 0)
goto next;
if (topo_fmri_nvl2str(thp, rsrc, &fmri, &err) < 0)
goto next;
if ((s = strstr(fmri, match)) == NULL)
goto next;
if (s[strlen(match)] != '\0')
goto next;
ret = TOPO_WALK_TERMINATE;
if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DRIVER, &driver,
&err) != 0)
driver = NULL;
if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_VENDID,
&vidstr, &err) != 0)
goto next;
if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_DEVID,
&didstr, &err) != 0)
goto next;
if (prt_php != NULL) {
long vid, did;
vid = strtol(vidstr, NULL, 16);
did = strtol(didstr, NULL, 16);
if (vid >= 0 && vid <= UINT16_MAX &&
did >= 0 && did <= UINT16_MAX) {
pcidb_device_t *pdev;
pdev = pcidb_lookup_device(prt_php, vid, did);
if (pdev != NULL) {
pcidb_vendor_t *pvend;
pvend = pcidb_device_vendor(pdev);
(void) printf(gettext(", %s %s (%s)"),
pcidb_vendor_name(pvend),
pcidb_device_name(pdev),
driver != NULL ? driver : "<unknown>");
printed = B_TRUE;
}
}
}
if (printed == B_FALSE) {
(void) printf(gettext(", pci%s,%s (%s)"), vidstr, didstr,
driver != NULL ? driver : "<unknown>");
}
next:
topo_hdl_strfree(thp, didstr);
topo_hdl_strfree(thp, driver);
topo_hdl_strfree(thp, vidstr);
topo_hdl_strfree(thp, fmri);
nvlist_free(rsrc);
return (ret);
}
static void
do_slot_mapping(smbios_slot_t *s, topo_hdl_t *thp)
{
int err;
uint_t dev, func;
topo_walk_t *twp;
char pciex[256];
dev = s->smbl_df >> 3;
func = s->smbl_df & 0x7;
(void) snprintf(pciex, sizeof (pciex), "%s=%u/%s=%u/%s=%d",
PCIEX_BUS, s->smbl_bus, PCIEX_DEVICE, dev, PCIEX_FUNCTION, func);
twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, do_slot_mapping_cb, pciex,
&err);
if (twp == NULL)
return;
(void) topo_walk_step(twp, TOPO_WALK_CHILD);
topo_walk_fini(twp);
}
static int
do_slots(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
{
smbios_slot_t s;
if (sp->smbstr_type == SMB_TYPE_SLOT &&
smbios_info_slot(shp, sp->smbstr_id, &s) != SMB_ERR) {
const char *t = smbios_slot_type_desc(s.smbl_type);
const char *u = smbios_slot_usage_desc(s.smbl_usage);
(void) printf(gettext("%-3u %-9s %-16s %s"),
s.smbl_id, u ? u : gettext("Unknown"),
t ? t : gettext("Unknown"), s.smbl_name);
if (s.smbl_sg != 0xff && s.smbl_bus != 0xff &&
s.smbl_df != 0xff && arg != NULL)
do_slot_mapping(&s, arg);
(void) printf(gettext("\n"));
}
return (0);
}
int
do_prominfo(int opt_v, char *progname, int opt_l, int opt_p)
{
smbios_hdl_t *shp;
smbios_system_t sys;
smbios_bios_t bios;
smbios_ipmi_t ipmi;
smbios_info_t info;
topo_hdl_t *thp;
char *uuid;
const char *s;
id_t id;
int err;
if ((shp = smbios_open(NULL, SMB_VERSION, 0, &err)) == NULL) {
(void) fprintf(stderr,
gettext("%s: failed to open SMBIOS: %s\n"),
progname, smbios_errmsg(err));
return (1);
}
if ((id = smbios_info_system(shp, &sys)) != SMB_ERR &&
smbios_info_common(shp, id, &info) != SMB_ERR) {
(void) printf(gettext("System Configuration: %s %s\n"),
info.smbi_manufacturer, info.smbi_product);
} else {
(void) fprintf(stderr,
gettext("%s: failed to get system info: %s\n"),
progname, smbios_errmsg(smbios_errno(shp)));
}
if (smbios_info_bios(shp, &bios) != SMB_ERR) {
(void) printf(gettext("BIOS Configuration: %s %s %s\n"),
bios.smbb_vendor, bios.smbb_version, bios.smbb_reldate);
} else {
(void) fprintf(stderr,
gettext("%s: failed to get bios info: %s\n"),
progname, smbios_errmsg(smbios_errno(shp)));
}
if (smbios_info_ipmi(shp, &ipmi) != SMB_ERR) {
if ((s = smbios_ipmi_type_desc(ipmi.smbip_type)) == NULL)
s = gettext("Unknown");
(void) printf(gettext("BMC Configuration: IPMI %u.%u (%s)\n"),
ipmi.smbip_vers.smbv_major, ipmi.smbip_vers.smbv_minor, s);
}
uuid = NULL;
if ((thp = topo_open(TOPO_VERSION, NULL, &err)) != NULL) {
if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
topo_close(thp);
thp = NULL;
}
}
prt_php = pcidb_open(PCIDB_VERSION);
(void) printf(gettext(
"\n==== Processor Sockets ====================================\n"));
(void) printf(gettext("\n%-32s %s"), "Version", "Location Tag");
(void) printf(gettext(
"\n-------------------------------- --------------------------\n"));
(void) smbios_iter(shp, do_procs, NULL);
(void) printf(gettext(
"\n==== Memory Device Sockets ================================\n"));
(void) printf(gettext("\n%-11s %-6s %-3s %-19s %s"),
"Type", "Status", "Set", "Device Locator", "Bank Locator");
(void) printf(gettext(
"\n----------- ------ --- ------------------- ----------------\n"));
(void) smbios_iter(shp, do_memdevs, NULL);
(void) printf(gettext(
"\n==== On-Board Devices =====================================\n"));
(void) smbios_iter(shp, do_obdevs, NULL);
(void) printf(gettext(
"\n==== Upgradeable Slots ====================================\n"));
(void) printf(gettext("\n%-3s %-9s %-16s %s"),
"ID", "Status", "Type", "Description");
(void) printf(gettext(
"\n--- --------- ---------------- ----------------------------\n"));
(void) smbios_iter(shp, do_slots, thp);
smbios_close(shp);
topo_hdl_strfree(thp, uuid);
if (thp != NULL) {
topo_snap_release(thp);
topo_close(thp);
}
pcidb_close(prt_php);
return (0);
}