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 * Create Base Board (MB) topology node from SMBIOS Type 2 structure
2N/A */
2N/A
2N/A#include <sys/types.h>
2N/A#include <strings.h>
2N/A#include <fm/topo_mod.h>
2N/A#include <fm/topo_hc.h>
2N/A#include <sys/systeminfo.h>
2N/A#include <sys/smbios_impl.h>
2N/A#include <sys/smbios.h>
2N/A#include <x86pi_impl.h>
2N/A
2N/A/* base board ID counts */
2N/Aextern bb_cnt_t bb_cnt;
2N/A
2N/A/* base baoed type values to hc-canonical-name */
2N/Astatic const struct x86pi_bb_name {
2N/A int type;
2N/A const char *name;
2N/A} x86pi_bb_names[] = {
2N/A { SMB_BBT_SBLADE, "systemboard" },
2N/A { SMB_BBT_PROC, "cpuboard" },
2N/A { SMB_BBT_IO, "ioboard" },
2N/A { SMB_BBT_MEM, "memboard" },
2N/A { SMB_BBT_DAUGHTER, "systemboard" },
2N/A { SMB_BBT_MOTHER, "motherboard" },
2N/A { SMB_BBT_PROCMEM, "systemboard" },
2N/A { SMB_BBT_PROCIO, "systemboard" },
2N/A { SMB_BBT_INTER, "systemboard" },
2N/A { 0x00 }
2N/A};
2N/A
2N/Atnode_t *
2N/Ax86pi_gen_bboard(topo_mod_t *mod, tnode_t *t_parent, int smb_id,
2N/A int instance, int psmb_id)
2N/A{
2N/A int rv;
2N/A smbios_info_t ip;
2N/A smbios_bboard_t bb;
2N/A smbios_struct_t sp;
2N/A x86pi_hcfmri_t bb_hcfmri;
2N/A tnode_t *bb_node;
2N/A const struct x86pi_bb_name *bbnp;
2N/A char *f = "x86pi_gen_bboard";
2N/A smbios_hdl_t *shp;
2N/A
2N/A topo_mod_dprintf(mod, "%s\n", f);
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL) {
2N/A topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
2N/A return (NULL);
2N/A }
2N/A
2N/A /* SMBIOS Base Board struct */
2N/A rv = smbios_info_bboard(shp, smb_id, &bb);
2N/A if (rv != 0) {
2N/A topo_mod_dprintf(mod, "%s: smbios_info_bboard() failed\n", f);
2N/A return (NULL);
2N/A }
2N/A (void) smbios_lookup_id(shp, psmb_id, &sp);
2N/A if (sp.smbstr_type == SMB_TYPE_CHASSIS &&
2N/A bb.smbb_chassis != psmb_id) {
2N/A topo_mod_dprintf(mod, "%s: base board (%d) does not belong to "
2N/A "chassis (%d)\n", f, smb_id, psmb_id);
2N/A return (NULL);
2N/A }
2N/A
2N/A /* SMBIOS Base Board strings */
2N/A rv = smbios_info_common(shp, smb_id, &ip);
2N/A if (rv != 0) {
2N/A return (NULL);
2N/A }
2N/A
2N/A /*
2N/A * populate string entries
2N/A *
2N/A * We don't set "product" because it may contain characters
2N/A * unacceptable by fmri. topo_mod_auth() will set the product-name
2N/A * for us and call topo_cleanup_auth_str() when necessary.
2N/A */
2N/A bb_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
2N/A ip.smbi_serial, 0);
2N/A bb_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
2N/A /* asset tag string contains the part number */
2N/A bb_hcfmri.part_number = x86pi_cleanup_smbios_str(mod,
2N/A ip.smbi_asset, 0);
2N/A bb_hcfmri.location = x86pi_cleanup_smbios_str(mod, ip.smbi_location,
2N/A LABEL);
2N/A
2N/A /* determine the hc-name */
2N/A for (bbnp = x86pi_bb_names; bbnp->type != 0x00; bbnp++) {
2N/A if (bbnp->type == bb.smbb_type) {
2N/A switch (bbnp->type) {
2N/A case SMB_BBT_PROC :
2N/A instance = bb_cnt.cpuboard++;
2N/A break;
2N/A case SMB_BBT_IO :
2N/A instance = bb_cnt.ioboard++;
2N/A break;
2N/A case SMB_BBT_MEM :
2N/A instance = bb_cnt.memboard++;
2N/A break;
2N/A case SMB_BBT_MOTHER :
2N/A instance = bb_cnt.motherboard++;
2N/A break;
2N/A default :
2N/A /*
2N/A * Enumerate any other baseboard type
2N/A * as systemboard.
2N/A *
2N/A * SMB_BBT_UNKNOWN
2N/A * SMB_BBT_OTHER
2N/A * SMB_BBT_SBLADE
2N/A * SMB_BBT_CSWITCH
2N/A * SMB_BBT_SMM
2N/A * SMB_BBT_DAUGHTER
2N/A * SMB_BBT_PROCMEM
2N/A * SMB_BBT_PROCIO
2N/A * SMB_BBT_INTER
2N/A */
2N/A instance = bb_cnt.systemboard++;
2N/A break;
2N/A }
2N/A break;
2N/A }
2N/A }
2N/A
2N/A bb_hcfmri.instance = instance;
2N/A if (bbnp->type != 0x00)
2N/A bb_hcfmri.hc_name = topo_mod_strdup(mod, bbnp->name);
2N/A else
2N/A bb_hcfmri.hc_name = topo_mod_strdup(mod, "NULL");
2N/A
2N/A topo_mod_dprintf(mod, "%s: S/N (%s)\n", f, bb_hcfmri.serial_number);
2N/A topo_mod_dprintf(mod, "%s: version/N (%s)\n", f, bb_hcfmri.version);
2N/A topo_mod_dprintf(mod, "%s: Part/N (%s)\n", f, bb_hcfmri.part_number);
2N/A topo_mod_dprintf(mod, "%s: location (%s)\n", f, bb_hcfmri.location);
2N/A topo_mod_dprintf(mod, "%s: instance (%d)\n", f, bb_hcfmri.instance);
2N/A topo_mod_dprintf(mod, "%s: hc_name (%s)\n", f, bb_hcfmri.hc_name);
2N/A
2N/A rv = x86pi_enum_generic(mod, &bb_hcfmri, t_parent, t_parent, &bb_node,
2N/A X86PI_ENUM_FRU);
2N/A if (rv != 0) {
2N/A topo_mod_dprintf(mod, "%s: failed to create tnode %d\n", f,
2N/A instance);
2N/A bb_node = NULL;
2N/A }
2N/A
2N/A /* free up strings */
2N/A if (bb_hcfmri.hc_name != NULL) {
2N/A topo_mod_strfree(mod, (char *)bb_hcfmri.hc_name);
2N/A }
2N/A if (bb_hcfmri.part_number != NULL) {
2N/A topo_mod_strfree(mod, (char *)bb_hcfmri.part_number);
2N/A }
2N/A if (bb_hcfmri.serial_number != NULL) {
2N/A topo_mod_strfree(mod, (char *)bb_hcfmri.serial_number);
2N/A }
2N/A if (bb_hcfmri.version != NULL) {
2N/A topo_mod_strfree(mod, (char *)bb_hcfmri.version);
2N/A }
2N/A if (bb_hcfmri.location != NULL) {
2N/A topo_mod_strfree(mod, (char *)bb_hcfmri.location);
2N/A }
2N/A
2N/A return (bb_node);
2N/A}
2N/A
2N/A
2N/Aint
2N/Ax86pi_bb_getchips(topo_mod_t *mod, int index, int nboards)
2N/A{
2N/A id_t *cid;
2N/A int count;
2N/A int ncmp = 0;
2N/A smbios_struct_t sp;
2N/A smbs_cnt_t *smbc = NULL;
2N/A smbios_hdl_t *shp;
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL)
2N/A return (ncmp);
2N/A
2N/A cid = stypes[SMB_TYPE_BASEBOARD].ids[index].con_ids;
2N/A count = stypes[SMB_TYPE_BASEBOARD].ids[index].con_cnt;
2N/A
2N/A for (int i = 0; i < count; i++) {
2N/A (void) smbios_lookup_id(shp, cid[i], &sp);
2N/A if (sp.smbstr_type == SMB_TYPE_PROCESSOR) {
2N/A ncmp++;
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * If there are missing SMB_TYPE_PROCESSOR structures
2N/A * contained within SMB_TYPE_BASEBOARD, and if the
2N/A * system has only one baseboard we enumerate
2N/A * all processors under it.
2N/A */
2N/A smbc = &stypes[SMB_TYPE_PROCESSOR];
2N/A smbc->type = SMB_TYPE_PROCESSOR;
2N/A x86pi_smb_strcnt(mod, smbc);
2N/A
2N/A if (nboards == 1) {
2N/A if (ncmp != stypes[SMB_TYPE_PROCESSOR].count)
2N/A ncmp = stypes[SMB_TYPE_PROCESSOR].count;
2N/A } else {
2N/A if (ncmp == 0) {
2N/A topo_mod_dprintf(mod, "failed to get processors"
2N/A " (or) no processors are contained"
2N/A " within baseboard instance %d, unable to"
2N/A " enumerate chips\n", index);
2N/A }
2N/A }
2N/A
2N/A return (ncmp);
2N/A}
2N/A
2N/A
2N/Aid_t
2N/Ax86pi_bb_topparent(topo_mod_t *mod, int index, tnode_t **pnode, id_t *psmbid)
2N/A{
2N/A
2N/A id_t top_bb_smbid = -1;
2N/A id_t smb_id;
2N/A int bb_count, ch_count;
2N/A smbios_struct_t sp;
2N/A smbios_hdl_t *shp;
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL)
2N/A return (top_bb_smbid);
2N/A
2N/A smb_id = stypes[SMB_TYPE_BASEBOARD].ids[index].con_by_id;
2N/A (void) smbios_lookup_id(shp, smb_id, &sp);
2N/A
2N/A if (sp.smbstr_type == SMB_TYPE_CHASSIS) {
2N/A top_bb_smbid = stypes[SMB_TYPE_BASEBOARD].ids[index].id;
2N/A *psmbid = smb_id;
2N/A ch_count = stypes[SMB_TYPE_CHASSIS].count;
2N/A for (int i = 0; i < ch_count; i++)
2N/A if (stypes[SMB_TYPE_CHASSIS].ids[i].id == *psmbid)
2N/A *pnode = stypes[SMB_TYPE_CHASSIS].ids[i].node;
2N/A
2N/A return (top_bb_smbid);
2N/A
2N/A } else if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
2N/A bb_count = stypes[SMB_TYPE_BASEBOARD].count;
2N/A for (int i = 0; i < bb_count; i++) {
2N/A if (stypes[SMB_TYPE_BASEBOARD].ids[i].id == smb_id) {
2N/A if (stypes[SMB_TYPE_BASEBOARD].ids[i].visited
2N/A == X86PI_VISITED) {
2N/A top_bb_smbid =
2N/A stypes[SMB_TYPE_BASEBOARD].\
2N/A ids[index].id;
2N/A *pnode =
2N/A stypes[SMB_TYPE_BASEBOARD].ids[i].\
2N/A node;
2N/A *psmbid =
2N/A stypes[SMB_TYPE_BASEBOARD].ids[i].\
2N/A id;
2N/A break;
2N/A }
2N/A top_bb_smbid = x86pi_bb_topparent(mod,
2N/A i, pnode, psmbid);
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A
2N/A return (top_bb_smbid);
2N/A}
2N/A
2N/A
2N/Aid_t
2N/Ax86pi_bb_chassis(topo_mod_t *mod, id_t bb_smbid)
2N/A{
2N/A smbios_bboard_t bb;
2N/A int rv;
2N/A smbios_hdl_t *shp;
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL)
2N/A return (-1);
2N/A
2N/A rv = smbios_info_bboard(shp, bb_smbid, &bb);
2N/A if (rv != 0)
2N/A return (-1);
2N/A
2N/A return (bb.smbb_chassis);
2N/A}
2N/A
2N/A
2N/Aint
2N/Ax86pi_bb_contains(topo_mod_t *mod)
2N/A{
2N/A int rv;
2N/A id_t smb_id;
2N/A smbios_bboard_t bb;
2N/A int bb_count = 0;
2N/A uint_t cont_cnt = 0;
2N/A smbios_struct_t sp;
2N/A smbios_hdl_t *shp;
2N/A
2N/A shp = topo_mod_smbios(mod);
2N/A if (shp == NULL)
2N/A return (-1);
2N/A
2N/A bb_count = stypes[SMB_TYPE_BASEBOARD].count;
2N/A for (int i = 0; i < bb_count; i++) {
2N/A smb_id = stypes[SMB_TYPE_BASEBOARD].ids[i].id;
2N/A /* SMBIOS Base Board struct */
2N/A rv = smbios_info_bboard(shp, smb_id, &bb);
2N/A if (rv != 0)
2N/A return (-1);
2N/A /* Set Baseboard - Chassis Relationship */
2N/A if (stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id == 0) {
2N/A stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id =
2N/A rv = x86pi_bb_chassis(mod, smb_id);
2N/A if (rv == -1) {
2N/A topo_mod_dprintf(mod, " failed to get"
2N/A " the chassis handle\n");
2N/A return (rv);
2N/A }
2N/A }
2N/A
2N/A /* SMBIOS contained object handles */
2N/A cont_cnt = bb.smbb_contn;
2N/A if (cont_cnt > 0) {
2N/A id_t *cont_hdl;
2N/A uint16_t hdl;
2N/A
2N/A /* allocate space for and get contained handles */
2N/A cont_hdl = topo_mod_alloc(mod, cont_cnt *
2N/A sizeof (id_t));
2N/A rv = smbios_info_contains(shp, smb_id, cont_cnt,
2N/A cont_hdl);
2N/A if (rv > SMB_CONT_MAX) {
2N/A topo_mod_free(mod, cont_hdl, cont_cnt *
2N/A sizeof (id_t));
2N/A return (-1);
2N/A }
2N/A cont_cnt = MIN(rv, cont_cnt);
2N/A
2N/A /* attach contained handles */
2N/A stypes[SMB_TYPE_BASEBOARD].ids[i].con_cnt = cont_cnt;
2N/A for (int j = 0; j < cont_cnt; j++) {
2N/A hdl = (uint16_t)cont_hdl[j];
2N/A topo_mod_dprintf(mod, "id %d contained handle"
2N/A " %d: %d\n", i, j, hdl);
2N/A stypes[SMB_TYPE_BASEBOARD].ids[i].\
2N/A con_ids[j] = hdl;
2N/A (void) smbios_lookup_id(shp, hdl, &sp);
2N/A if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
2N/A for (int k = 0; k < bb_count; k++)
2N/A if (stypes[SMB_TYPE_BASEBOARD].\
2N/A ids[k].id == hdl)
2N/A stypes[\
2N/A SMB_TYPE_BASEBOARD\
2N/A ].ids[k].con_by_id =
2N/A smb_id;
2N/A }
2N/A }
2N/A topo_mod_free(mod, cont_hdl, cont_cnt * sizeof (id_t));
2N/A }
2N/A }
2N/A return (0);
2N/A}