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