2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * Subroutines used by the i86pc Generic Topology Enumerator
2N/A */
2N/A
2N/A#include <sys/types.h>
2N/A#include <strings.h>
2N/A#include <deflt.h>
2N/A#include <fcntl.h>
2N/A#include <unistd.h>
2N/A#include <fm/topo_mod.h>
2N/A#include <fm/topo_hc.h>
2N/A#include <sys/devfm.h>
2N/A#include <sys/pci.h>
2N/A#include <sys/systeminfo.h>
2N/A#include <sys/fm/protocol.h>
2N/A#include <sys/utsname.h>
2N/A#include <sys/smbios.h>
2N/A#include <sys/smbios_impl.h>
2N/A#include <x86pi_impl.h>
2N/A
2N/A
2N/Astatic const topo_pgroup_info_t sys_pgroup = {
2N/A TOPO_PGROUP_SYSTEM,
2N/A TOPO_STABILITY_PRIVATE,
2N/A TOPO_STABILITY_PRIVATE,
2N/A 1
2N/A};
2N/A
2N/Astatic const topo_pgroup_info_t auth_pgroup = {
2N/A FM_FMRI_AUTHORITY,
2N/A TOPO_STABILITY_PRIVATE,
2N/A TOPO_STABILITY_PRIVATE,
2N/A 1
2N/A};
2N/A
2N/A
2N/A/*
2N/A * Free hcfmri strings.
2N/A */
2N/Avoid
2N/Ax86pi_hcfmri_info_fini(topo_mod_t *mod, x86pi_hcfmri_t *hc)
2N/A{
2N/A if (hc->hc_name != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->hc_name);
2N/A if (hc->manufacturer != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->manufacturer);
2N/A if (hc->product != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->product);
2N/A if (hc->version != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->version);
2N/A if (hc->serial_number != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->serial_number);
2N/A if (hc->asset_tag != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->asset_tag);
2N/A if (hc->location != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->location);
2N/A if (hc->part_number != NULL)
2N/A topo_mod_strfree(mod, (char *)hc->part_number);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Get the server hostname (the ID as far as the topo authority is
2N/A * concerned) from sysinfo and return a copy to the caller.
2N/A *
2N/A * The string must be freed with topo_mod_strfree()
2N/A */
2N/Achar *
2N/Ax86pi_get_serverid(topo_mod_t *mod)
2N/A{
2N/A int result;
2N/A char hostname[MAXNAMELEN];
2N/A
2N/A topo_mod_dprintf(mod, "x86pi_get_serverid\n");
2N/A
2N/A result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
2N/A /* Everything is freed up and it's time to return the platform-id */
2N/A if (result == -1) {
2N/A return (NULL);
2N/A }
2N/A topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname);
2N/A
2N/A return (topo_mod_strdup(mod, hostname));
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Go through the smbios structures looking for a type. Fill in
2N/A * the structure count as well as the id(s) of the struct types.
2N/A */
2N/Avoid
2N/Ax86pi_smb_strcnt(topo_mod_t *mod, smbs_cnt_t *stype)
2N/A{
2N/A const smb_struct_t *sp;
2N/A int nstructs;
2N/A int i, cnt;
2N/A smbios_hdl_t *shp;
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL) {
2N/A stype->count = 0;
2N/A return;
2N/A }
2N/A
2N/A nstructs = shp->sh_nstructs;
2N/A sp = shp->sh_structs;
2N/A
2N/A for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
2N/A if (sp->smbst_hdr->smbh_type == stype->type) {
2N/A stype->ids[cnt].node = NULL;
2N/A stype->ids[cnt].id = sp->smbst_hdr->smbh_hdl;
2N/A cnt++;
2N/A }
2N/A }
2N/A
2N/A stype->count = cnt;
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Calculate the authority information for a node. Always create the
2N/A * appropriate property group even if complete authority is not found.
2N/A */
2N/Aint
2N/Ax86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
2N/A tnode_t *t_node)
2N/A{
2N/A int result;
2N/A int err;
2N/A int is_chassis = 0;
2N/A int chassis_instance = 0;
2N/A nvlist_t *auth;
2N/A char *f = "x86pi_set_auth";
2N/A
2N/A if (mod == NULL || t_parent == NULL || t_node == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A if ((topo_pgroup_create(t_node, &auth_pgroup, &err) != 0) &&
2N/A (err != ETOPO_PROP_DEFD)) {
2N/A /*
2N/A * We failed to create the property group and it was not
2N/A * already defined. Set the err code and return failure.
2N/A */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A return (-1);
2N/A }
2N/A
2N/A
2N/A /* Determnine if this is a chassis node and set it's instance */
2N/A if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
2N/A strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
2N/A is_chassis = 1;
2N/A chassis_instance = hcfmri->instance;
2N/A }
2N/A
2N/A /*
2N/A * Set the authority data.
2N/A *
2N/A * Continue even if some authority information is not available
2N/A * to enumerate as much as possible.
2N/A */
2N/A
2N/A /* either not a chassis node, or chassis #0 */
2N/A if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
2N/A /*
2N/A * Get the chassis authority information.
2N/A */
2N/A auth = topo_mod_auth(mod, t_parent);
2N/A
2N/A result = topo_node_set_auth_chassis(mod, auth, t_node);
2N/A if (result != 0) {
2N/A topo_mod_dprintf(mod,
2N/A "%s: failed to set %s for %s node\n",
2N/A f, FM_FMRI_AUTHORITY, hcfmri->hc_name);
2N/A }
2N/A }
2N/A
2N/A nvlist_free(auth);
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Calculate a generic FRU for the given node. If the node is not a FRU,
2N/A * then inherit the FRU data from the nodes parent.
2N/A */
2N/Aint
2N/Ax86pi_set_frufmri(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
2N/A tnode_t *t_node, int flag)
2N/A{
2N/A int result;
2N/A int err;
2N/A
2N/A nvlist_t *auth = NULL;
2N/A nvlist_t *frufmri = NULL;
2N/A
2N/A if (t_node == NULL || mod == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A /*
2N/A * Determine if this node is a FRU
2N/A */
2N/A if (!(flag & X86PI_ENUM_FRU)) {
2N/A /* This node is not a FRU. Inherit from parent and return */
2N/A (void) topo_node_fru_set(t_node, NULL, 0, &result);
2N/A return (0);
2N/A }
2N/A
2N/A /*
2N/A * This node is a FRU. Create an FMRI.
2N/A */
2N/A auth = topo_mod_auth(mod, t_parent);
2N/A frufmri = topo_mod_hcfmri(mod, t_parent, FM_HC_SCHEME_VERSION,
2N/A hcfmri->hc_name, hcfmri->instance, NULL, auth,
2N/A hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
2N/A if (frufmri == NULL) {
2N/A topo_mod_dprintf(mod, "failed to create FRU: %s\n",
2N/A topo_strerror(topo_mod_errno(mod)));
2N/A }
2N/A nvlist_free(auth);
2N/A
2N/A /* Set the FRU, whether NULL or not */
2N/A result = topo_node_fru_set(t_node, frufmri, 0, &err);
2N/A if (result != 0) {
2N/A (void) topo_mod_seterrno(mod, err);
2N/A }
2N/A nvlist_free(frufmri);
2N/A
2N/A return (result);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Set the label for a topo node.
2N/A */
2N/Aint
2N/Ax86pi_set_label(topo_mod_t *mod, const char *label, const char *name,
2N/A tnode_t *t_node)
2N/A{
2N/A int result;
2N/A int err;
2N/A
2N/A if (mod == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A /*
2N/A * Set the label for this topology node.
2N/A * Note that a NULL label will inherit the label from topology
2N/A * node's parent.
2N/A */
2N/A result = topo_node_label_set(t_node, (char *)label, &err);
2N/A if (result != 0) {
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod, "x86pi_set_label: failed with label %s "
2N/A "on %s node: %s\n", (label == NULL ? "NULL" : label),
2N/A name, topo_strerror(err));
2N/A }
2N/A
2N/A return (result);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Calculate the system information for a node. Inherit the data if
2N/A * possible, but always create an appropriate property group.
2N/A */
2N/Aint
2N/Ax86pi_set_system(topo_mod_t *mod, tnode_t *t_node)
2N/A{
2N/A int result;
2N/A int err;
2N/A struct utsname uts;
2N/A char isa[MAXNAMELEN];
2N/A
2N/A if (mod == NULL || t_node == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A result = topo_pgroup_create(t_node, &sys_pgroup, &err);
2N/A if (result != 0 && err != ETOPO_PROP_DEFD) {
2N/A /*
2N/A * We failed to create the property group and it was not
2N/A * already defined. Set the err code and return failure.
2N/A */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A return (-1);
2N/A }
2N/A
2N/A result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
2N/A &err);
2N/A if (result != 0 && err != ETOPO_PROP_DEFD) {
2N/A isa[0] = '\0';
2N/A result = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
2N/A if (result == -1) {
2N/A /* Preserve the error and continue */
2N/A topo_mod_dprintf(mod, "x86pi_set_system: failed to "
2N/A "read SI_ARCHITECTURE: %d\n", errno);
2N/A }
2N/A if (strnlen(isa, MAXNAMELEN) > 0) {
2N/A result = topo_prop_set_string(t_node,
2N/A TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
2N/A TOPO_PROP_IMMUTABLE, isa, &err);
2N/A if (result != 0) {
2N/A /* Preserve the error and continue */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod,
2N/A "x86pi_set_auth: failed to "
2N/A "set property %s (%d) : %s\n",
2N/A TOPO_PROP_ISA, err, topo_strerror(err));
2N/A }
2N/A }
2N/A }
2N/A
2N/A result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM,
2N/A TOPO_PROP_MACHINE, &err);
2N/A if (result != 0 && err != ETOPO_PROP_DEFD) {
2N/A result = uname(&uts);
2N/A if (result == -1) {
2N/A /* Preserve the error and continue */
2N/A (void) topo_mod_seterrno(mod, errno);
2N/A topo_mod_dprintf(mod, "x86pi_set_system: failed to "
2N/A "read uname: %d\n", errno);
2N/A }
2N/A if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
2N/A result = topo_prop_set_string(t_node,
2N/A TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
2N/A TOPO_PROP_IMMUTABLE, uts.machine, &err);
2N/A if (result != 0) {
2N/A /* Preserve the error and continue */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod,
2N/A "x86pi_set_auth: failed to "
2N/A "set property %s (%d) : %s\n",
2N/A TOPO_PROP_MACHINE, err, topo_strerror(err));
2N/A }
2N/A }
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Topo module routine to update authority identity.
2N/A */
2N/Atypedef void topo_auth_fn_t(topo_mod_t *, tnode_t *, char *, char *, char *);
2N/A
2N/A/*
2N/A * Set the system/component system/chassis identity information to the topo
2N/A * handle auth structure. This data is held in SMBIOS structures.
2N/A *
2N/A * System - Type 129 System Extended Information SUN_OEM_EXT_SYSTEM 129
2N/A * System Component - Type 1 System Information SMB_TYPE_SYSTEM 1
2N/A * Chassis - Type 3 System Enclosure or Chassis SMB_TYPE_CHASSIS 3
2N/A */
2N/Aint
2N/Ax86pi_set_topo_auth(topo_mod_t *mod)
2N/A{
2N/A int rv;
2N/A int i = 0;
2N/A const char *mfg = NULL;
2N/A const char *name = NULL;
2N/A const char *part = NULL;
2N/A const char *serial = NULL;
2N/A const char *product_id = NULL; /* old school */
2N/A nvlist_t *nvl;
2N/A smbios_struct_t s;
2N/A smbios_info_t info;
2N/A smbios_hdl_t *shp;
2N/A id_t id;
2N/A int smb_type, auth_type;
2N/A boolean_t noex_sys = B_FALSE; /* no type 129 */
2N/A char *f = "x86pi_set_topo_auth";
2N/A
2N/A /* the order of the next two must be maintained */
2N/A int smb_types[] = {
2N/A SUN_OEM_EXT_SYSTEM, /* type 129 */
2N/A SMB_TYPE_SYSTEM, /* type 1 */
2N/A SMB_TYPE_CHASSIS, /* type 3 */
2N/A -1
2N/A };
2N/A int auth_types[] = {
2N/A FM_FMRI_AUTH_TYPE_SYSTEM,
2N/A FM_FMRI_AUTH_TYPE_SYS_COMP,
2N/A FM_FMRI_AUTH_TYPE_CHASSIS,
2N/A -1
2N/A };
2N/A
2N/A /* make sure we have an SMBIOS handle */
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL) {
2N/A topo_mod_dprintf(mod, "%s: failed to get smbios handle.", f);
2N/A return (-1);
2N/A }
2N/A
2N/A /* allocate the topo authority nvlist */
2N/A rv = topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME);
2N/A if (rv != 0) {
2N/A topo_mod_dprintf(mod,
2N/A "%s: failed to xalloc topo auth nvlist\n", f);
2N/A return (-1);
2N/A }
2N/A rv = nvlist_add_uint8(nvl, FM_VERSION, FM_FMRI_AUTH_VERSION);
2N/A if (rv != 0) {
2N/A topo_mod_dprintf(mod, "%s: failed to set FM_VERSION\n");
2N/A nvlist_free(nvl);
2N/A return (-1);
2N/A }
2N/A
2N/A /*
2N/A * There should only be one SMBIOS type 1 and type 129 structure, and
2N/A * we only want the first SMBIOS type 3 (chassis=0) structure. So use
2N/A * the first one found here.
2N/A */
2N/A for (i = 0, smb_type = smb_types[i], auth_type = auth_types[i];
2N/A smb_type != -1;
2N/A ++i, smb_type = smb_types[i], auth_type = auth_types[i]) {
2N/A /* find SMBIOS structure */
2N/A topo_mod_dprintf(mod,
2N/A "%s: get type %d SMBIOS structure\n", f, smb_type);
2N/A
2N/A rv = smbios_lookup_type(shp, smb_type, &s);
2N/A if (rv == 0) {
2N/A id = s.smbstr_id;
2N/A topo_mod_dprintf(mod, "%s: type: %d id: %d\n",
2N/A f, smb_type, id);
2N/A /* grab strings */
2N/A rv = smbios_info_common(shp, id, &info);
2N/A if (rv == 0) {
2N/A if (auth_type == -1) {
2N/A continue;
2N/A }
2N/A
2N/A topo_mod_dprintf(mod, "%s: SMBIOS type %d: "
2N/A "mfg(%s) product(%s) part(%s) serial(%s)\n",
2N/A f, smb_type, info.smbi_manufacturer,
2N/A info.smbi_product, info.smbi_part,
2N/A info.smbi_serial);
2N/A
2N/A /* cleanup strings */
2N/A mfg = x86pi_cleanup_smbios_str(mod,
2N/A info.smbi_manufacturer, 0);
2N/A if (smb_type == SMB_TYPE_CHASSIS) {
2N/A /* ch name is in version field */
2N/A name = x86pi_cleanup_smbios_str(mod,
2N/A info.smbi_version, 0);
2N/A } else {
2N/A name = x86pi_cleanup_smbios_str(mod,
2N/A info.smbi_product, 0);
2N/A }
2N/A if (smb_type == SMB_TYPE_SYSTEM) {
2N/A /* sys p/n is in SKU field */
2N/A smbios_system_t s;
2N/A (void) smbios_info_system(shp, &s);
2N/A part = x86pi_cleanup_smbios_str(mod,
2N/A s.smbs_sku, 0);
2N/A } else if (smb_type == SMB_TYPE_CHASSIS) {
2N/A /* ch p/n is in asset tag field */
2N/A part = x86pi_cleanup_smbios_str(mod,
2N/A info.smbi_asset, 0);
2N/A } else {
2N/A part = x86pi_cleanup_smbios_str(mod,
2N/A info.smbi_part, 0);
2N/A }
2N/A serial = x86pi_cleanup_smbios_str(mod,
2N/A info.smbi_serial, 0);
2N/A
2N/A /* save off product-id */
2N/A if (auth_type == FM_FMRI_AUTH_TYPE_SYS_COMP)
2N/A product_id = topo_mod_strdup(mod,
2N/A (char *)name);
2N/A } else {
2N/A topo_mod_dprintf(mod,
2N/A "%s: failed to get type %d strings\n",
2N/A f, smb_type);
2N/A }
2N/A } else {
2N/A if (smb_type == SUN_OEM_EXT_SYSTEM)
2N/A noex_sys = B_TRUE;
2N/A }
2N/A
2N/A topo_mod_dprintf(mod, "%s: %s auth: manufacturer(%s) "
2N/A "name(%s) part(%s) serial(%s)\n", f,
2N/A auth_type == FM_FMRI_AUTH_TYPE_SYSTEM ? "System" :
2N/A auth_type == FM_FMRI_AUTH_TYPE_SYS_COMP ?
2N/A "Component System" : auth_type ==
2N/A FM_FMRI_AUTH_TYPE_CHASSIS ? "Chassis" : "Unknown",
2N/A mfg ? mfg : "NULL", name ? name : "NULL",
2N/A part ? part : "NULL", serial ? serial : "NULL");
2N/A
2N/A /* use product_id if old BIOS or no chassis name */
2N/A if (auth_type == FM_FMRI_AUTH_TYPE_CHASSIS &&
2N/A (noex_sys || name == NULL)) {
2N/A if (name != NULL)
2N/A topo_mod_strfree(mod, (char *)name);
2N/A name = topo_mod_strdup(mod, (char *)product_id);
2N/A }
2N/A /* no values set to "unknown" */
2N/A if (mfg == NULL || *mfg == '\0')
2N/A mfg = topo_mod_strdup(mod, TOPO_AUTH_UNKNOWN);
2N/A if (name == NULL || *name == '\0')
2N/A name = topo_mod_strdup(mod, TOPO_AUTH_UNKNOWN);
2N/A if (part == NULL || *part == '\0')
2N/A part = topo_mod_strdup(mod, TOPO_AUTH_UNKNOWN);
2N/A if (serial == NULL || *serial == '\0')
2N/A serial = topo_mod_strdup(mod, TOPO_AUTH_UNKNOWN);
2N/A
2N/A /* set identity strings into topo handle */
2N/A topo_mod_auth_set_nvl(mod, &nvl, auth_type, (char *)mfg,
2N/A (char *)name, (char *)part, (char *)serial);
2N/A
2N/A /* free strings */
2N/A if (mfg != NULL)
2N/A topo_mod_strfree(mod, (char *)mfg);
2N/A if (name != NULL)
2N/A topo_mod_strfree(mod, (char *)name);
2N/A if (part != NULL)
2N/A topo_mod_strfree(mod, (char *)part);
2N/A if (serial != NULL)
2N/A topo_mod_strfree(mod, (char *)serial);
2N/A mfg = name = part = serial = NULL;
2N/A }
2N/A
2N/A /* copy the nvlist to the topo handle */
2N/A topo_mod_auth_set_th(mod, nvl);
2N/A
2N/A /* clean up */
2N/A if (product_id != NULL)
2N/A topo_mod_strfree(mod, (char *)product_id);
2N/A nvlist_free(nvl);
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * All the checks for compatibility are done within the kernel where the
2N/A * ereport generators are. They'll determine first if there's a problem
2N/A * and the topo enum will follow suit. The /dev/fm ioclt returns the value
2N/A * of the x86gentopo_legacy kernel variable which determines if this platform
2N/A * will provide an x86 generic topo or legacy topo enumeration.
2N/A */
2N/A/* ARGSUSED */
2N/Aint
2N/Ax86pi_check_comp(topo_mod_t *mod)
2N/A{
2N/A int rv;
2N/A int fd;
2N/A int32_t legacy;
2N/A nvlist_t *nvl = NULL;
2N/A fm_ioc_data_t fid;
2N/A char *ibuf = NULL, *obuf = NULL;
2N/A size_t insz = 0, outsz = 0;
2N/A char *f = "x86pi_check_comp";
2N/A smbios_hdl_t *shp;
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL)
2N/A return (X86PI_NONE);
2N/A
2N/A /* open /dev/fm */
2N/A fd = open("/dev/fm", O_RDONLY);
2N/A if (fd < 0) {
2N/A topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
2N/A return (X86PI_NONE);
2N/A }
2N/A
2N/A /* set up buffers and ioctl data structure */
2N/A outsz = FM_IOC_MAXBUFSZ;
2N/A obuf = topo_mod_alloc(mod, outsz);
2N/A if (obuf == NULL) {
2N/A perror("umem_alloc");
2N/A return (X86PI_NONE);
2N/A }
2N/A
2N/A fid.fid_version = 1;
2N/A fid.fid_insz = insz;
2N/A fid.fid_inbuf = ibuf;
2N/A fid.fid_outsz = outsz;
2N/A fid.fid_outbuf = obuf;
2N/A
2N/A /* send the ioctl to /dev/fm to retrieve legacy variable */
2N/A rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
2N/A if (rv < 0) {
2N/A topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
2N/A perror("fm_ioctl");
2N/A (void) close(fd);
2N/A return (X86PI_NONE);
2N/A }
2N/A (void) close(fd);
2N/A
2N/A (void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
2N/A (void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);
2N/A
2N/A nvlist_free(nvl);
2N/A topo_mod_free(mod, obuf, outsz);
2N/A
2N/A if (legacy == 1) {
2N/A /* legacy kernel variable set; will do the same */
2N/A return (X86PI_NONE);
2N/A }
2N/A
2N/A /* legacy kernel variable not set; generic topo enum */
2N/A return (X86PI_FULL);
2N/A}
2N/A
2N/Aconst char *
2N/Ax86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
2N/A{
2N/A char buf[MAXNAMELEN];
2N/A const char *end, *cp;
2N/A char *pp;
2N/A char c;
2N/A int i;
2N/A
2N/A end = begin + strlen(begin);
2N/A
2N/A while (begin < end && isspace(*begin))
2N/A begin++;
2N/A while (begin < end && isspace(*(end - 1)))
2N/A end--;
2N/A
2N/A if (begin >= end)
2N/A return (NULL);
2N/A
2N/A cp = begin;
2N/A for (i = 0; i < MAXNAMELEN - 1; i++) {
2N/A if (cp >= end)
2N/A break;
2N/A c = *cp;
2N/A if (str_type == LABEL) {
2N/A if (!isprint(c))
2N/A buf[i] = '-';
2N/A else
2N/A buf[i] = c;
2N/A } else {
2N/A if (c == ':' || c == '=' || c == '/' ||
2N/A isspace(c) || !isprint(c))
2N/A buf[i] = '-';
2N/A else
2N/A buf[i] = c;
2N/A }
2N/A cp++;
2N/A }
2N/A buf[i] = 0;
2N/A
2N/A pp = topo_mod_strdup(mod, buf);
2N/A
2N/A return (pp);
2N/A}
2N/A
2N/A/*
2N/A * Return Bus/Dev/Func from "reg" devinfo property.
2N/A */
2N/Auint16_t
2N/Ax86pi_bdf(topo_mod_t *mod, di_node_t node)
2N/A{
2N/A int *val;
2N/A
2N/A if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &val) < 0) {
2N/A topo_mod_dprintf(mod, "couldn't get \"reg\" prop: %s.\n",
2N/A strerror(errno));
2N/A return ((uint16_t)-1);
2N/A }
2N/A
2N/A return (uint16_t)((*val & PCI_REG_BDFR_M) >> PCI_REG_FUNC_SHIFT);
2N/A}
2N/A
2N/A/*
2N/A * Return PHY from "sata-phy" devinfo proporty.
2N/A */
2N/Aint
2N/Ax86pi_phy(topo_mod_t *mod, di_node_t node)
2N/A{
2N/A int *phy;
2N/A
2N/A if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "sata-phy", &phy) < 0) {
2N/A topo_mod_dprintf(mod, "couldn't get \"sata-phy\" prop: %s.\n",
2N/A strerror(errno));
2N/A return (-1);
2N/A }
2N/A
2N/A return (*phy);
2N/A}