1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Create Base Board (MB) topology node from SMBIOS Type 2 structure 29 */ 30 31 #include <sys/types.h> 32 #include <strings.h> 33 #include <fm/topo_mod.h> 34 #include <fm/topo_hc.h> 35 #include <sys/systeminfo.h> 36 #include <sys/smbios_impl.h> 37 #include <sys/smbios.h> 38 #include <x86pi_impl.h> 39 40 /* base baoed type values to hc-canonical-name */ 41 static const struct x86pi_bb_name { 42 int type; 43 const char *name; 44 } x86pi_bb_names[] = { 45 { SMB_BBT_SBLADE, "systemboard" }, 46 { SMB_BBT_PROC, "cpuboard" }, 47 { SMB_BBT_IO, "ioboard" }, 48 { SMB_BBT_MEM, "memboard" }, 49 { SMB_BBT_DAUGHTER, "systemboard" }, 50 { SMB_BBT_MOTHER, "motherboard" }, 51 { SMB_BBT_PROCMEM, "systemboard" }, 52 { SMB_BBT_PROCIO, "systemboard" }, 53 { SMB_BBT_INTER, "systemboard" }, 54 { 0x00 } 55 }; 56 57 tnode_t * 58 x86pi_gen_bboard(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp, 59 int smb_id, int instance, int psmb_id) 60 { 61 int rv; 62 smbios_info_t ip; 63 smbios_bboard_t bb; 64 smbios_struct_t sp; 65 x86pi_hcfmri_t bb_hcfmri; 66 tnode_t *bb_node; 67 const struct x86pi_bb_name *bbnp; 68 static int cpuboard = 0; 69 static int memboard = 0; 70 static int ioboard = 0; 71 static int systemboard = 0; 72 static int motherboard = 0; 73 char *f = "x86pi_gen_bboard"; 74 75 topo_mod_dprintf(mod, "%s\n", f); 76 77 /* SMBIOS Base Board struct */ 78 rv = smbios_info_bboard(shp, smb_id, &bb); 79 if (rv != 0) { 80 topo_mod_dprintf(mod, "%s: smbios_info_bboard() failed\n", f); 81 return (NULL); 82 } 83 (void) smbios_lookup_id(shp, psmb_id, &sp); 84 if (sp.smbstr_type == SMB_TYPE_CHASSIS && 85 bb.smbb_chassis != psmb_id) { 86 topo_mod_dprintf(mod, "%s: base board (%d) does not belong to " 87 "chassis (%d)\n", f, smb_id, psmb_id); 88 return (NULL); 89 } 90 91 /* SMBIOS Base Board strings */ 92 rv = smbios_info_common(shp, smb_id, &ip); 93 if (rv != 0) { 94 return (NULL); 95 } 96 97 /* 98 * populate string entries 99 * 100 * We don't set "product" because it may contain characters 101 * unacceptable by fmri. topo_mod_auth() will set the product-id 102 * for us and call topo_cleanup_auth_str() when necessary. 103 */ 104 bb_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod, 105 ip.smbi_serial, 0); 106 bb_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0); 107 /* asset tag string contains the part number */ 108 bb_hcfmri.part_number = x86pi_cleanup_smbios_str(mod, 109 ip.smbi_asset, 0); 110 bb_hcfmri.location = x86pi_cleanup_smbios_str(mod, ip.smbi_location, 0); 111 112 /* determine the hc-name */ 113 for (bbnp = x86pi_bb_names; bbnp->type != 0x00; bbnp++) { 114 if (bbnp->type == bb.smbb_type) { 115 switch (bbnp->type) { 116 case SMB_BBT_PROC : 117 instance = cpuboard++; 118 break; 119 case SMB_BBT_IO : 120 instance = ioboard++; 121 break; 122 case SMB_BBT_MEM : 123 instance = memboard++; 124 break; 125 case SMB_BBT_MOTHER : 126 instance = motherboard++; 127 break; 128 default : 129 /* 130 * Enumerate any other baseboard type 131 * as systemboard. 132 * 133 * SMB_BBT_UNKNOWN 134 * SMB_BBT_OTHER 135 * SMB_BBT_SBLADE 136 * SMB_BBT_CSWITCH 137 * SMB_BBT_SMM 138 * SMB_BBT_DAUGHTER 139 * SMB_BBT_PROCMEM 140 * SMB_BBT_PROCIO 141 * SMB_BBT_INTER 142 */ 143 instance = systemboard++; 144 break; 145 } 146 break; 147 } 148 } 149 150 bb_hcfmri.instance = instance; 151 if (bbnp->type != 0x00) 152 bb_hcfmri.hc_name = topo_mod_strdup(mod, bbnp->name); 153 else 154 bb_hcfmri.hc_name = topo_mod_strdup(mod, "NULL"); 155 156 topo_mod_dprintf(mod, "%s: S/N (%s)\n", f, bb_hcfmri.serial_number); 157 topo_mod_dprintf(mod, "%s: version/N (%s)\n", f, bb_hcfmri.version); 158 topo_mod_dprintf(mod, "%s: Part/N (%s)\n", f, bb_hcfmri.part_number); 159 topo_mod_dprintf(mod, "%s: location (%s)\n", f, bb_hcfmri.location); 160 topo_mod_dprintf(mod, "%s: instance (%d)\n", f, bb_hcfmri.instance); 161 topo_mod_dprintf(mod, "%s: hc_name (%s)\n", f, bb_hcfmri.hc_name); 162 163 rv = x86pi_enum_generic(mod, &bb_hcfmri, t_parent, t_parent, &bb_node, 164 X86PI_ENUM_FRU); 165 if (rv != 0) { 166 topo_mod_dprintf(mod, "%s: failed to create tnode %d\n", f, 167 instance); 168 bb_node = NULL; 169 } 170 171 /* free up strings */ 172 if (bb_hcfmri.hc_name != NULL) { 173 topo_mod_strfree(mod, (char *)bb_hcfmri.hc_name); 174 } 175 if (bb_hcfmri.part_number != NULL) { 176 topo_mod_strfree(mod, (char *)bb_hcfmri.part_number); 177 } 178 if (bb_hcfmri.serial_number != NULL) { 179 topo_mod_strfree(mod, (char *)bb_hcfmri.serial_number); 180 } 181 if (bb_hcfmri.version != NULL) { 182 topo_mod_strfree(mod, (char *)bb_hcfmri.version); 183 } 184 if (bb_hcfmri.location != NULL) { 185 topo_mod_strfree(mod, (char *)bb_hcfmri.location); 186 } 187 188 return (bb_node); 189 } 190 191 192 int 193 x86pi_bb_getchips(topo_mod_t *mod, smbios_hdl_t *shp, int index, int nboards) 194 { 195 id_t *cid; 196 int count; 197 int ncmp = 0; 198 smbios_struct_t sp; 199 smbs_cnt_t *smbc = NULL; 200 201 cid = stypes[SMB_TYPE_BASEBOARD].ids[index].con_ids; 202 count = stypes[SMB_TYPE_BASEBOARD].ids[index].con_cnt; 203 204 for (int i = 0; i < count; i++) { 205 (void) smbios_lookup_id(shp, cid[i], &sp); 206 if (sp.smbstr_type == SMB_TYPE_PROCESSOR) { 207 ncmp++; 208 } 209 } 210 211 /* 212 * If there are missing SMB_TYPE_PROCESSOR structures 213 * contained within SMB_TYPE_BASEBOARD, and if the 214 * system has only one baseboard we enumerate 215 * all processors under it. 216 */ 217 smbc = &stypes[SMB_TYPE_PROCESSOR]; 218 smbc->type = SMB_TYPE_PROCESSOR; 219 x86pi_smb_strcnt(shp, smbc); 220 221 if (nboards == 1) { 222 if (ncmp != stypes[SMB_TYPE_PROCESSOR].count) 223 ncmp = stypes[SMB_TYPE_PROCESSOR].count; 224 } else { 225 if (ncmp == 0) { 226 topo_mod_dprintf(mod, "failed to get processors" 227 " (or) no processors are contained" 228 " within baseboard instance %d, unable to" 229 " enumerate chips\n", index); 230 } 231 } 232 233 return (ncmp); 234 } 235 236 237 id_t 238 x86pi_bb_topparent(smbios_hdl_t *shp, int index, tnode_t **pnode, id_t *psmbid) 239 { 240 241 id_t top_bb_smbid = -1; 242 id_t smb_id; 243 int bb_count, ch_count; 244 smbios_struct_t sp; 245 246 smb_id = stypes[SMB_TYPE_BASEBOARD].ids[index].con_by_id; 247 (void) smbios_lookup_id(shp, smb_id, &sp); 248 249 if (sp.smbstr_type == SMB_TYPE_CHASSIS) { 250 top_bb_smbid = stypes[SMB_TYPE_BASEBOARD].ids[index].id; 251 *psmbid = smb_id; 252 ch_count = stypes[SMB_TYPE_CHASSIS].count; 253 for (int i = 0; i < ch_count; i++) 254 if (stypes[SMB_TYPE_CHASSIS].ids[i].id == *psmbid) 255 *pnode = stypes[SMB_TYPE_CHASSIS].ids[i].node; 256 257 return (top_bb_smbid); 258 259 } else if (sp.smbstr_type == SMB_TYPE_BASEBOARD) { 260 bb_count = stypes[SMB_TYPE_BASEBOARD].count; 261 for (int i = 0; i < bb_count; i++) { 262 if (stypes[SMB_TYPE_BASEBOARD].ids[i].id == smb_id) { 263 if (stypes[SMB_TYPE_BASEBOARD].ids[i].visited 264 == X86PI_VISITED) { 265 top_bb_smbid = 266 stypes[SMB_TYPE_BASEBOARD].\ 267 ids[index].id; 268 *pnode = 269 stypes[SMB_TYPE_BASEBOARD].ids[i].\ 270 node; 271 *psmbid = 272 stypes[SMB_TYPE_BASEBOARD].ids[i].\ 273 id; 274 break; 275 } 276 top_bb_smbid = x86pi_bb_topparent(shp, 277 i, pnode, psmbid); 278 break; 279 } 280 } 281 } 282 283 return (top_bb_smbid); 284 } 285 286 287 id_t 288 x86pi_bb_chassis(smbios_hdl_t *shp, id_t bb_smbid) 289 { 290 smbios_bboard_t bb; 291 int rv; 292 293 rv = smbios_info_bboard(shp, bb_smbid, &bb); 294 if (rv != 0) 295 return (-1); 296 297 return (bb.smbb_chassis); 298 } 299 300 301 int 302 x86pi_bb_contains(topo_mod_t *mod, smbios_hdl_t *shp) 303 { 304 int rv; 305 id_t smb_id; 306 smbios_bboard_t bb; 307 int bb_count = 0; 308 uint_t cont_cnt = 0; 309 smbios_struct_t sp; 310 311 bb_count = stypes[SMB_TYPE_BASEBOARD].count; 312 for (int i = 0; i < bb_count; i++) { 313 smb_id = stypes[SMB_TYPE_BASEBOARD].ids[i].id; 314 /* SMBIOS Base Board struct */ 315 rv = smbios_info_bboard(shp, smb_id, &bb); 316 if (rv != 0) 317 return (-1); 318 /* Set Baseboard - Chassis Relationship */ 319 if (stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id == 0) { 320 stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id = 321 rv = x86pi_bb_chassis(shp, smb_id); 322 if (rv == -1) { 323 topo_mod_dprintf(mod, " failed to get" 324 " the chassis handle\n"); 325 return (rv); 326 } 327 } 328 329 /* SMBIOS contained object handles */ 330 cont_cnt = bb.smbb_contn; 331 if (cont_cnt > 0) { 332 id_t *cont_hdl; 333 uint16_t hdl; 334 335 /* allocate space for and get contained handles */ 336 cont_hdl = topo_mod_alloc(mod, cont_cnt * 337 sizeof (id_t)); 338 rv = smbios_info_contains(shp, smb_id, cont_cnt, 339 cont_hdl); 340 if (rv > SMB_CONT_MAX) { 341 topo_mod_free(mod, cont_hdl, cont_cnt * 342 sizeof (id_t)); 343 return (-1); 344 } 345 cont_cnt = MIN(rv, cont_cnt); 346 347 /* attach contained handles */ 348 stypes[SMB_TYPE_BASEBOARD].ids[i].con_cnt = cont_cnt; 349 for (int j = 0; j < cont_cnt; j++) { 350 hdl = (uint16_t)cont_hdl[j]; 351 topo_mod_dprintf(mod, "id %d contained handle" 352 " %d: %d\n", i, j, hdl); 353 stypes[SMB_TYPE_BASEBOARD].ids[i].\ 354 con_ids[j] = hdl; 355 (void) smbios_lookup_id(shp, hdl, &sp); 356 if (sp.smbstr_type == SMB_TYPE_BASEBOARD) { 357 for (int k = 0; k < bb_count; k++) 358 if (stypes[SMB_TYPE_BASEBOARD].\ 359 ids[k].id == hdl) 360 stypes[\ 361 SMB_TYPE_BASEBOARD\ 362 ].ids[k].con_by_id = 363 smb_id; 364 } 365 } 366 topo_mod_free(mod, cont_hdl, cont_cnt * sizeof (id_t)); 367 } 368 } 369 return (0); 370 } 371