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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/time.h> 28 #include <sys/nvpair.h> 29 #include <sys/cmn_err.h> 30 #include <sys/fm/util.h> 31 #include <sys/fm/protocol.h> 32 #include <sys/smbios.h> 33 #include <sys/smbios_impl.h> 34 35 /* 36 * Variable used to determine if the x86 generic topology enumerator will 37 * revert to legacy enumeration. I.E. Big Kill Switch... tunable via 38 * /etc/system 39 */ 40 int x86gentopo_legacy = 0; 41 42 #define MC 0 43 #define PROC 1 44 #define MAX_PAIRS 20 45 #define MAX_CONT 40 46 47 typedef struct bbindex { 48 int count; 49 uint16_t index[MAX_PAIRS]; 50 } bbindex_t; 51 52 /* 53 * the enum values come from DMTF 54 */ 55 typedef enum baseb { 56 BB_BAD = 0, /* There is no bb value 0 */ 57 BB_UNKNOWN, /* Unknown */ 58 BB_OTHER, /* Other */ 59 BB_BLADE, /* Server Blade */ 60 BB_CONNSW, /* Connectivity Switch */ 61 BB_SMM, /* System Management Module */ 62 BB_PROCMOD, /* Processor Module */ 63 BB_IOMOD, /* I/O Module */ 64 BB_MEMMOD, /* Memory Module */ 65 BB_DBOARD, /* Daughter Board */ 66 BB_MBOARD, /* Motherboard */ 67 BB_PROCMMOD, /* Processor/Memory Module */ 68 BB_PROCIOMOD, /* Processor/IO Module */ 69 BB_ICONNBD /* Interconnect Board */ 70 } bbd_t; 71 72 static struct bboard_type { 73 bbd_t baseb; 74 const char *name; 75 } bbd_type[] = { 76 {BB_BAD, NULL}, 77 {BB_UNKNOWN, "unknown"}, 78 {BB_OTHER, "other"}, 79 {BB_BLADE, "systemboard"}, 80 {BB_CONNSW, "connswitch"}, 81 {BB_SMM, "smmodule"}, 82 {BB_PROCMOD, "cpuboard"}, 83 {BB_IOMOD, "ioboard"}, 84 {BB_MEMMOD, "memboard"}, 85 {BB_DBOARD, "systemboard"}, 86 {BB_MBOARD, "motherboard"}, 87 {BB_PROCMMOD, "systemboard"}, 88 {BB_PROCIOMOD, "systemboard"}, 89 {BB_ICONNBD, "systemboard"} 90 }; 91 92 typedef struct smbs_con_ids { 93 int id; 94 int inst; 95 int cont_count; 96 uint16_t **cont_ids; 97 int cont_by_id; 98 int visited; 99 } smbs_con_ids_t; 100 101 typedef struct smbs_cnt { 102 int type; /* SMBIOS stucture type */ 103 int count; /* number of table entries */ 104 smbs_con_ids_t **ids; /* SMBIOS table entry id(s) */ 105 } smbs_cnt_t; 106 107 /* 108 * dynamically allocate the storage for the smbs_cnt_t 109 */ 110 static smbs_cnt_t * 111 smb_create_strcnt(int count) 112 { 113 smbs_cnt_t *types = NULL; 114 int i, j; 115 116 types = kmem_zalloc(sizeof (smbs_cnt_t), KM_SLEEP); 117 118 types->ids = (smbs_con_ids_t **)kmem_zalloc( 119 count * sizeof (smbs_con_ids_t *), KM_SLEEP); 120 121 for (i = 0; i < count; i++) { 122 types->ids[i] = (smbs_con_ids_t *)kmem_zalloc( 123 sizeof (smbs_con_ids_t), KM_SLEEP); 124 } 125 126 for (i = 0; i < count; i++) { 127 types->ids[i]->cont_ids = (uint16_t **)kmem_zalloc( 128 MAX_CONT * sizeof (uint16_t *), KM_SLEEP); 129 } 130 131 for (i = 0; i < count; i++) { 132 for (j = 0; j < MAX_CONT; j++) { 133 types->ids[i]->cont_ids[j] = (uint16_t *)kmem_zalloc( 134 sizeof (uint16_t), KM_SLEEP); 135 } 136 } 137 return (types); 138 } 139 140 /* 141 * free the smbs_cnt_t memory 142 */ 143 static void 144 smb_free_strcnt(smbs_cnt_t *types, int count) 145 { 146 int i, j; 147 148 if (types == NULL) 149 return; 150 151 for (i = 0; i < count; i++) { 152 for (j = 0; j < MAX_CONT; j++) { 153 if (types->ids[i]->cont_ids[j] != NULL) 154 kmem_free(types->ids[i]->cont_ids[j], 155 sizeof (uint16_t)); 156 } 157 } 158 159 for (i = 0; i < count; i++) { 160 if (types->ids[i]->cont_ids != NULL) 161 kmem_free(types->ids[i]->cont_ids, 162 MAX_CONT * sizeof (uint16_t *)); 163 } 164 165 for (i = 0; i < count; i++) { 166 if (types->ids[i] != NULL) 167 kmem_free(types->ids[i], sizeof (smbs_con_ids_t)); 168 } 169 170 if (types->ids != NULL) 171 kmem_free(types->ids, count * sizeof (smbs_con_ids_t *)); 172 173 if (types != NULL) 174 kmem_free(types, sizeof (smbs_cnt_t)); 175 176 } 177 178 /* 179 * count number of the structure type in the ksmbios 180 */ 181 static int 182 smb_cnttypes(smbios_hdl_t *shp, int type) 183 { 184 const smb_struct_t *sp = shp->sh_structs; 185 int nstructs = shp->sh_nstructs; 186 int i; 187 int cnt = 0; 188 189 for (i = 0, cnt = 0; i < nstructs; i++, sp++) { 190 if (sp->smbst_hdr->smbh_type == type) 191 cnt++; 192 } 193 return (cnt); 194 } 195 196 static void 197 smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype) 198 { 199 const smb_struct_t *sp = shp->sh_structs; 200 int nstructs = shp->sh_nstructs; 201 smbios_bboard_t bb; 202 int i, cnt; 203 int mb_cnt = 0; 204 int cpub_cnt = 0; 205 int sysb_cnt = 0; 206 int memb_cnt = 0; 207 int iob_cnt = 0; 208 int inst = 0; 209 int rc = 0; 210 211 for (i = 0, cnt = 0; i < nstructs; i++, sp++) { 212 if (sp->smbst_hdr->smbh_type == stype->type) { 213 stype->ids[cnt]->id = sp->smbst_hdr->smbh_hdl; 214 stype->ids[cnt]->inst = cnt; 215 stype->ids[cnt]->visited = 0; 216 stype->ids[cnt]->cont_by_id = -1; 217 if (stype->type == SMB_TYPE_BASEBOARD) { 218 rc = smbios_info_bboard(shp, 219 stype->ids[cnt]->id, &bb); 220 if (rc == 0) { 221 switch (bb.smbb_type) { 222 case SMB_BBT_PROC : 223 inst = cpub_cnt++; 224 break; 225 case SMB_BBT_IO : 226 inst = iob_cnt++; 227 break; 228 case SMB_BBT_MEM : 229 inst = memb_cnt++; 230 break; 231 case SMB_BBT_MOTHER : 232 inst = mb_cnt++; 233 break; 234 default: 235 /* 236 * SMB_BBT_UNKNOWN 237 * SMB_BBT_OTHER 238 * SMB_BBT_SBLADE 239 * SMB_BBT_CSWITCH 240 * SMB_BBT_SMM 241 * SMB_BBT_DAUGHTER 242 * SMB_BBT_PROCMEM 243 * SMB_BBT_PROCIO 244 * SMB_BBT_INTER 245 */ 246 inst = sysb_cnt++; 247 break; 248 } 249 stype->ids[cnt]->inst = inst; 250 } 251 } 252 cnt++; 253 } 254 } 255 stype->count = cnt; 256 } 257 258 /* 259 * Go through the smbios structures looking for type 2. Fill in 260 * the cont_id and cont_by_id for each type 2 261 * 262 */ 263 static void 264 smb_bb_contains(smbios_hdl_t *shp, smbs_cnt_t *stype) 265 { 266 int i, j, cnt, c; 267 uint_t cont_count; 268 const smb_struct_t *spt; 269 smbios_bboard_t smb_bb; 270 uint16_t bb_id, cont_id; 271 uint_t cont_len; 272 id_t *cont_hdl = NULL; 273 int rc; 274 275 for (cnt = 0; cnt < stype->count; cnt++) { 276 bb_id = stype->ids[cnt]->id; 277 if (smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb) == -1) 278 continue; 279 cont_count = (uint_t)smb_bb.smbb_contn; 280 if (cont_count == 0) { 281 continue; 282 } 283 284 cont_len = sizeof (id_t); 285 cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP); 286 if (cont_hdl == NULL) 287 continue; 288 289 rc = smbios_info_contains(shp, stype->ids[cnt]->id, 290 cont_count, cont_hdl); 291 if (rc > SMB_CONT_MAX || rc < 0) { 292 kmem_free(cont_hdl, cont_count * cont_len); 293 continue; 294 } 295 cont_count = MIN(rc, cont_count); 296 297 /* 298 * fill in the type 2 and type 4 ids which are 299 * contained in this type 2 300 */ 301 c = 0; 302 for (j = 0; j < cont_count; j++) { 303 cont_id = (uint16_t)cont_hdl[j]; 304 spt = smb_lookup_id(shp, cont_id); 305 if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD || 306 spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) { 307 *stype->ids[cnt]->cont_ids[c] = cont_id; 308 c++; 309 } 310 311 if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) { 312 for (i = 0; i < stype->count; i++) { 313 if (stype->ids[i]->id == cont_id) { 314 stype->ids[i]->cont_by_id = 315 bb_id; 316 } 317 } 318 } 319 320 } 321 stype->ids[cnt]->cont_count = c; 322 if (cont_hdl != NULL) 323 kmem_free(cont_hdl, cont_count * cont_len); 324 } 325 } 326 327 /* 328 * Verify SMBIOS structures for x86 generic topology. 329 * 330 * Return (0) on success. 331 */ 332 static int 333 fm_smb_check(smbios_hdl_t *shp) 334 { 335 int i, j; 336 int bb_cnt = 0; 337 int pr_cnt = 0; 338 int expr_cnt = 0; 339 int ma_cnt = 0; 340 int exma_cnt = 0; 341 int mdev_cnt = 0; 342 int exmdev_cnt = 0; 343 uint16_t bb_id; 344 uint16_t pr_id, expr_id; 345 uint16_t ma_id, exma_id; 346 uint16_t mdev_id, exmdev_id; 347 uint16_t *sys_ma; 348 smbios_bboard_t bb; 349 smbios_processor_ext_t exproc; 350 smbios_memarray_t ma; 351 smbios_memarray_ext_t exma; 352 smbios_memdevice_t mdev; 353 smbios_memdevice_ext_t exmdev; 354 smbs_cnt_t *bb_stype; 355 smbs_cnt_t *pr_stype, *expr_stype; 356 smbs_cnt_t *ma_stype, *exma_stype; 357 smbs_cnt_t *mdev_stype, *exmdev_stype; 358 359 /* 360 * Verify the existance of the requuired extended OEM-Specific 361 * structures and they coincide with the structures they extend 362 * (e.g. the number of extended processor structures equal the 363 * number of processor structures). 364 */ 365 pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR); 366 expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR); 367 ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY); 368 exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY); 369 mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE); 370 exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE); 371 if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 || 372 expr_cnt != pr_cnt || exma_cnt > ma_cnt || 373 exmdev_cnt > mdev_cnt) { 374 #ifdef DEBUG 375 cmn_err(CE_NOTE, "!Structure mismatch: ext_proc (%d) " 376 "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n", 377 expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt, 378 mdev_cnt); 379 #endif /* DEBUG */ 380 return (-1); 381 } 382 383 /* 384 * Verify the OEM-Specific structrures are correctly 385 * linked to the SMBIOS structure types they extend. 386 */ 387 388 /* allocate processor stypes */ 389 pr_stype = smb_create_strcnt(pr_cnt); 390 expr_stype = smb_create_strcnt(expr_cnt); 391 392 /* fill in stypes */ 393 pr_stype->type = SMB_TYPE_PROCESSOR; 394 smb_strcnt(shp, pr_stype); 395 expr_stype->type = SUN_OEM_EXT_PROCESSOR; 396 smb_strcnt(shp, expr_stype); 397 398 /* verify the ext proc struct belong to the proc struct */ 399 for (i = 0; i < pr_cnt; i++) { 400 pr_id = pr_stype->ids[i]->id; 401 expr_id = expr_stype->ids[i]->id; 402 if (smbios_info_extprocessor(shp, expr_id, &exproc) == -1 || 403 exproc.smbpe_processor != pr_id) { 404 #ifdef DEBUG 405 cmn_err(CE_NOTE, "!Processor struct linkage (%d)", i); 406 #endif /* DEBUG */ 407 smb_free_strcnt(pr_stype, pr_cnt); 408 smb_free_strcnt(expr_stype, expr_cnt); 409 return (-1); 410 } 411 } 412 413 /* free stypes */ 414 smb_free_strcnt(pr_stype, pr_cnt); 415 smb_free_strcnt(expr_stype, expr_cnt); 416 417 /* allocate memory array stypes */ 418 ma_stype = smb_create_strcnt(ma_cnt); 419 exma_stype = smb_create_strcnt(exma_cnt); 420 sys_ma = kmem_zalloc(sizeof (uint16_t) * ma_cnt, KM_SLEEP); 421 422 /* fill in stypes */ 423 ma_stype->type = SMB_TYPE_MEMARRAY; 424 smb_strcnt(shp, ma_stype); 425 exma_stype->type = SUN_OEM_EXT_MEMARRAY; 426 smb_strcnt(shp, exma_stype); 427 428 /* verify linkage from ext memarray struct to memarray struct */ 429 for (i = 0; i < ma_cnt; i++) { 430 sys_ma[i] = (uint16_t)-1; 431 ma_id = ma_stype->ids[i]->id; 432 (void) smbios_info_memarray(shp, ma_id, &ma); 433 if (ma.smbma_use != SMB_MAU_SYSTEM) 434 continue; 435 /* this memarray is system memory */ 436 sys_ma[i] = ma_id; 437 exma_id = exma_stype->ids[i]->id; 438 (void) smbios_info_extmemarray(shp, exma_id, &exma); 439 if (exma.smbmae_ma != ma_id) { 440 #ifdef DEBUG 441 cmn_err(CE_NOTE, 442 "!Memory Array struct linkage (%d)", i); 443 #endif /* DEBUG */ 444 smb_free_strcnt(ma_stype, ma_cnt); 445 smb_free_strcnt(exma_stype, exma_cnt); 446 kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt); 447 return (-1); 448 } 449 } 450 451 /* free stypes */ 452 smb_free_strcnt(ma_stype, ma_cnt); 453 smb_free_strcnt(exma_stype, exma_cnt); 454 455 /* allocate memory device stypes */ 456 mdev_stype = smb_create_strcnt(mdev_cnt); 457 exmdev_stype = smb_create_strcnt(exmdev_cnt); 458 459 /* fill in stypes */ 460 mdev_stype->type = SMB_TYPE_MEMDEVICE; 461 smb_strcnt(shp, mdev_stype); 462 exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE; 463 smb_strcnt(shp, exmdev_stype); 464 465 /* verify linkage */ 466 for (i = 0; i < mdev_cnt; i++) { 467 mdev_id = mdev_stype->ids[i]->id; 468 (void) smbios_info_memdevice(shp, mdev_id, &mdev); 469 /* only check system memory devices */ 470 for (j = 0; j < ma_cnt; j++) { 471 if (sys_ma[j] == mdev.smbmd_array) 472 break; 473 } 474 if (j == ma_cnt) 475 continue; 476 exmdev_id = exmdev_stype->ids[i]->id; 477 (void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev); 478 if (exmdev.smbmdeve_md != mdev_id) { 479 #ifdef DEBUG 480 cmn_err(CE_NOTE, "!Memory Device struct linkage (%d)", 481 i); 482 #endif /* DEBUG */ 483 smb_free_strcnt(mdev_stype, mdev_cnt); 484 smb_free_strcnt(exmdev_stype, exmdev_cnt); 485 kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt); 486 return (-1); 487 } 488 } 489 490 /* free stypes */ 491 smb_free_strcnt(mdev_stype, mdev_cnt); 492 smb_free_strcnt(exmdev_stype, exmdev_cnt); 493 kmem_free(sys_ma, sizeof (uint16_t) * ma_cnt); 494 495 /* 496 * Verify the presece of contained handles if there are more 497 * than one Type-2 (Base Board) structures. 498 */ 499 bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD); 500 if (bb_cnt > 1) { 501 /* allocate base board stypes */ 502 bb_stype = smb_create_strcnt(bb_cnt); 503 504 /* fill in stypes */ 505 bb_stype->type = SMB_TYPE_BASEBOARD; 506 smb_strcnt(shp, bb_stype); 507 508 /* verify contained handles */ 509 for (i = 0; i < bb_cnt; i++) { 510 bb_id = bb_stype->ids[i]->id; 511 if (smbios_info_bboard(shp, bb_id, &bb) == -1 || 512 bb.smbb_contn == 0) { 513 #ifdef DEBUG 514 cmn_err(CE_NOTE, "!No contained hanldes (%d)", 515 i); 516 #endif /* DEBUG */ 517 smb_free_strcnt(bb_stype, bb_cnt); 518 return (-1); 519 } 520 } 521 522 /* free stypes */ 523 smb_free_strcnt(bb_stype, bb_cnt); 524 } 525 526 return (0); 527 } 528 529 void 530 fm_smb_fmacompat() 531 { 532 int i, j; 533 int id; 534 int cnt; 535 const char **oem_strings = NULL; 536 smbs_cnt_t *oemstypes; 537 smbios_hdl_t *shp; 538 int strcnt; 539 int compat = 0; 540 541 /* check for BKS */ 542 if (x86gentopo_legacy == 1) { 543 return; 544 } 545 546 shp = ksmbios; 547 if (shp == NULL) { 548 goto bad; 549 } 550 551 /* OEM strings (Type 11) */ 552 strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR); 553 if (strcnt == 0) 554 goto bad; 555 556 oemstypes = smb_create_strcnt(strcnt); 557 if (oemstypes == NULL) 558 goto bad; 559 560 oemstypes->type = SMB_TYPE_OEMSTR; 561 smb_strcnt(shp, oemstypes); 562 563 for (i = 0; i < oemstypes->count && compat == 0; i++) { 564 id = oemstypes->ids[i]->id; 565 cnt = smbios_info_strtab(shp, id, 0, NULL); 566 if (cnt > 0) { 567 oem_strings = kmem_zalloc(sizeof (char *) * cnt, 568 KM_SLEEP); 569 (void) smbios_info_strtab(shp, id, cnt, oem_strings); 570 571 for (j = 0; j < cnt; j++) { 572 if (strncmp(oem_strings[j], SMB_PRMS1, 573 strlen(SMB_PRMS1) + 1) == 0) { 574 compat = 1; 575 break; 576 } 577 } 578 kmem_free(oem_strings, sizeof (char *) * cnt); 579 } 580 } 581 smb_free_strcnt(oemstypes, strcnt); 582 583 /* sanity check SMBIOS structures */ 584 if ((compat != 0) && (fm_smb_check(shp) == 0)) 585 return; 586 587 bad: 588 /* not compatible with x86gentopo; revert to legacy enumeration */ 589 #ifdef DEBUG 590 cmn_err(CE_NOTE, 591 "!SMBIOS is not compatible with x86 generic topology."); 592 cmn_err(CE_NOTE, "!Invoking legacy x86 topology enumeration."); 593 #endif /* DEBUG */ 594 x86gentopo_legacy = 1; 595 } 596 597 static int 598 find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid) 599 { 600 uint16_t ext_id; 601 int i, j; 602 smbios_processor_ext_t ep; 603 smbs_cnt_t *pstypes; 604 int strcnt; 605 606 strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR); 607 if (strcnt == 0) 608 return (0); 609 610 pstypes = smb_create_strcnt(strcnt); 611 if (pstypes == NULL) 612 return (0); 613 614 pstypes->type = SUN_OEM_EXT_PROCESSOR; 615 smb_strcnt(shp, pstypes); 616 for (i = 0; i < pstypes->count; i++) { 617 ext_id = pstypes->ids[i]->id; 618 if (smbios_info_extprocessor(shp, ext_id, &ep) == 0 && 619 ep.smbpe_processor == proc_id) { 620 for (j = 0; j < ep.smbpe_n; j++) { 621 if (ep.smbpe_apicid[j] == strand_apicid) { 622 smb_free_strcnt(pstypes, strcnt); 623 return (1); 624 } 625 } 626 } 627 } 628 smb_free_strcnt(pstypes, strcnt); 629 return (0); 630 } 631 632 /* 633 * go throught the type 2 structure contained_ids looking for 634 * the type 4 which has strand_apicid == this strand_apicid 635 */ 636 static int 637 find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid, 638 uint16_t bb_id, uint16_t proc_hdl, int is_proc) 639 { 640 int n; 641 const smb_struct_t *sp; 642 smbios_bboard_t bb; 643 uint_t cont_count, cont_len; 644 uint16_t cont_id; 645 id_t *cont_hdl = NULL; 646 int rc; 647 648 649 if (smbios_info_bboard(shp, bb_id, &bb) == -1) 650 return (0); 651 cont_count = (uint_t)bb.smbb_contn; 652 if (cont_count == 0) 653 return (0); 654 655 cont_len = sizeof (id_t); 656 cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP); 657 if (cont_hdl == NULL) 658 return (0); 659 660 rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl); 661 if (rc > SMB_CONT_MAX || rc < 0) { 662 kmem_free(cont_hdl, cont_count * cont_len); 663 return (0); 664 } 665 cont_count = MIN(rc, cont_count); 666 667 for (n = 0; n < cont_count; n++) { 668 cont_id = (uint16_t)cont_hdl[n]; 669 sp = smb_lookup_id(shp, cont_id); 670 if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) { 671 if (is_proc) { 672 if (find_matching_apic(shp, cont_id, 673 strand_apicid)) { 674 kmem_free(cont_hdl, 675 cont_count * cont_len); 676 return (1); 677 } 678 } else { 679 if (cont_id == proc_hdl) { 680 kmem_free(cont_hdl, 681 cont_count * cont_len); 682 return (1); 683 } 684 } 685 } 686 } 687 if (cont_hdl != NULL) 688 kmem_free(cont_hdl, cont_count * cont_len); 689 690 return (0); 691 } 692 693 void 694 get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx) 695 { 696 int curr_id, tmp_id; 697 int i, j, nb; 698 bbindex_t tmp_idx; 699 700 for (i = 0; i < MAX_PAIRS; i++) 701 tmp_idx.index[i] = 0; 702 703 tmp_idx.count = 0; 704 705 curr_id = bb_id; 706 for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) { 707 tmp_id = bbstypes->ids[nb]->id; 708 if (tmp_id == curr_id) { 709 tmp_idx.index[i] = nb; 710 tmp_idx.count++; 711 curr_id = bbstypes->ids[nb]->cont_by_id; 712 if (curr_id == -1) 713 break; 714 i++; 715 } 716 } 717 718 for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) { 719 bb_idx->index[j] = tmp_idx.index[i]; 720 j++; 721 } 722 723 bb_idx->count = tmp_idx.count; 724 } 725 726 int 727 get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst, 728 uint16_t bb_id, int *chcnt) 729 { 730 int ch_strcnt; 731 smbs_cnt_t *chstypes; 732 uint16_t chassis_id, tmp_id; 733 smbios_bboard_t bb; 734 int rc = 0; 735 int i; 736 737 rc = smbios_info_bboard(shp, bb_id, &bb); 738 if (rc != 0) { 739 return (-1); 740 } 741 742 chassis_id = bb.smbb_chassis; 743 744 ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS); 745 746 if (ch_strcnt == 0) 747 return (-1); 748 749 chstypes = smb_create_strcnt(ch_strcnt); 750 if (chstypes == NULL) 751 return (-1); 752 753 chstypes->type = SMB_TYPE_CHASSIS; 754 smb_strcnt(shp, chstypes); 755 756 for (i = 0; i < chstypes->count; i++) { 757 tmp_id = chstypes->ids[i]->id; 758 if (tmp_id == chassis_id) { 759 *chassis_inst = chstypes->ids[i]->inst; 760 if (chstypes->ids[i]->inst != 0) 761 *chcnt = 2; 762 else 763 *chcnt = 1; 764 smb_free_strcnt(chstypes, ch_strcnt); 765 return (0); 766 } 767 } 768 769 smb_free_strcnt(chstypes, ch_strcnt); 770 return (-1); 771 } 772 773 int 774 smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri, uint_t parent, 775 smbs_cnt_t *bbstypes) 776 { 777 int rc = 0; 778 int i, j, n, cnt; 779 int id, index; 780 nvlist_t *pairs[MAX_PAIRS]; 781 smbios_bboard_t bb; 782 uint16_t chassis_inst, mch_inst; 783 char name[40]; 784 char idstr[11]; 785 bbindex_t bb_idx; 786 uint16_t bbid; 787 int chcnt = 0; 788 789 for (n = 0; n < MAX_PAIRS; n++) { 790 bb_idx.index[n] = 0; 791 pairs[n] = NULL; 792 } 793 bb_idx.count = 0; 794 795 get_bboard_index(bbstypes, parent, &bb_idx); 796 797 index = bb_idx.index[0]; 798 bbid = bbstypes->ids[index]->id; 799 800 rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt); 801 802 if (rc != 0) { 803 return (rc); 804 } 805 806 if ((bb_idx.count + chcnt) > MAX_PAIRS) { 807 return (-1); 808 } 809 810 i = 0; 811 if (chcnt > 1) { 812 /* 813 * create main chassis pair 814 */ 815 pairs[i] = fm_nvlist_create(NULL); 816 if (pairs[i] == NULL) { 817 return (-1); 818 } 819 mch_inst = 0; 820 (void) snprintf(idstr, sizeof (idstr), "%u", mch_inst); 821 if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, 822 "chassis") != 0) || 823 (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) { 824 fm_nvlist_destroy(pairs[i], FM_NVA_FREE); 825 return (-1); 826 } 827 i++; 828 } 829 830 /* 831 * create chassis pair 832 */ 833 pairs[i] = fm_nvlist_create(NULL); 834 if (pairs[i] == NULL) { 835 for (n = 0; n < MAX_PAIRS; n++) { 836 if (pairs[n] != NULL) 837 fm_nvlist_destroy(pairs[n], FM_NVA_FREE); 838 } 839 return (-1); 840 } 841 (void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst); 842 if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) || 843 (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) { 844 for (n = 0; n < MAX_PAIRS; n++) { 845 if (pairs[n] != NULL) 846 fm_nvlist_destroy(pairs[n], FM_NVA_FREE); 847 } 848 return (-1); 849 } 850 851 for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) { 852 index = bb_idx.index[j]; 853 bbid = bbstypes->ids[index]->id; 854 rc = smbios_info_bboard(shp, bbid, &bb); 855 if (rc != 0) { 856 rc = -1; 857 break; 858 } 859 860 pairs[i] = fm_nvlist_create(NULL); 861 if (pairs[i] == NULL) { 862 rc = -1; 863 break; 864 } 865 866 id = bbstypes->ids[index]->inst; 867 (void) snprintf(idstr, sizeof (idstr), "%u", id); 868 (void) strncpy(name, bbd_type[bb.smbb_type].name, 869 sizeof (name)); 870 cnt++; 871 872 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 || 873 nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) 874 != 0) { 875 rc = -1; 876 break; 877 } 878 i++; 879 } 880 881 if (rc != -1) { 882 if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, 883 pairs, cnt) != 0) { 884 rc = -1; 885 } 886 } 887 888 for (n = 0; n < cnt; n++) { 889 if (pairs[n] != NULL) 890 fm_nvlist_destroy(pairs[n], FM_NVA_FREE); 891 } 892 893 return (rc); 894 } 895 896 /* 897 * pass in strand_apic id 898 * return chip's bboards list which has strand_apicid == passed 899 * in strand_apic id 900 */ 901 static nvlist_t * 902 smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc) 903 { 904 smbios_hdl_t *shp; 905 smbs_cnt_t *bbstypes; 906 int nb; 907 int bb_smbid; 908 nvlist_t *fmri = NULL; 909 int rc = 0; 910 int bb_strcnt; 911 912 if (x86gentopo_legacy) 913 return (NULL); 914 915 shp = ksmbios; 916 if (shp == NULL) { 917 goto bad; 918 } 919 920 /* 921 * Type 2 structs : "base board" 922 */ 923 bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD); 924 if (bb_strcnt == 0) { 925 goto bad; 926 } 927 928 bbstypes = smb_create_strcnt(bb_strcnt); 929 if (bbstypes == NULL) { 930 goto bad; 931 } 932 933 bbstypes->type = SMB_TYPE_BASEBOARD; 934 smb_strcnt(shp, bbstypes); 935 smb_bb_contains(shp, bbstypes); 936 937 for (nb = 0; nb < bbstypes->count; nb++) { 938 if (bbstypes->ids[nb]->visited) { 939 continue; 940 } 941 942 bbstypes->ids[nb]->visited = 1; 943 bb_smbid = bbstypes->ids[nb]->id; 944 945 /* 946 * check if there is a matching processor under 947 * this board. If found, find base board(s) of this proc 948 * If proc is not in contained handle of a base board and 949 * there is only one base board in the system, treat that base 950 * board as the parent of the proc 951 */ 952 if (find_matching_proc(shp, strand_apicid, 953 bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) { 954 fmri = fm_nvlist_create(NULL); 955 if (fmri == NULL) { 956 smb_free_strcnt(bbstypes, bb_strcnt); 957 goto bad; 958 } 959 /* 960 * find parent by walking the cont_by_id 961 */ 962 rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes); 963 smb_free_strcnt(bbstypes, bb_strcnt); 964 if (rc == 0) { 965 return (fmri); 966 } else 967 goto bad; 968 } 969 970 } 971 972 smb_free_strcnt(bbstypes, bb_strcnt); 973 bad: 974 /* revert to legacy enumeration */ 975 x86gentopo_legacy = 1; 976 977 return (NULL); 978 } 979 980 nvlist_t * 981 fm_smb_bboard(uint_t strand_apicid) 982 { 983 return (smb_bboard(strand_apicid, 0, PROC)); 984 } 985 986 int 987 fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid) 988 { 989 int n; 990 smbios_hdl_t *shp; 991 uint16_t proc_id; 992 smbs_cnt_t *pstypes; 993 int strcnt; 994 995 if (x86gentopo_legacy) 996 return (-1); 997 998 shp = ksmbios; 999 if (shp == NULL) { 1000 goto bad; 1001 } 1002 1003 strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR); 1004 if (strcnt == 0) 1005 goto bad; 1006 1007 pstypes = smb_create_strcnt(strcnt); 1008 if (pstypes == NULL) 1009 goto bad; 1010 1011 pstypes->type = SMB_TYPE_PROCESSOR; 1012 smb_strcnt(shp, pstypes); 1013 for (n = 0; n < pstypes->count; n++) { 1014 proc_id = pstypes->ids[n]->id; 1015 if (find_matching_apic(shp, proc_id, strand_apicid)) { 1016 *chip_inst = pstypes->ids[n]->inst; 1017 *smbiosid = pstypes->ids[n]->id; 1018 smb_free_strcnt(pstypes, strcnt); 1019 return (0); 1020 } 1021 } 1022 smb_free_strcnt(pstypes, strcnt); 1023 bad: 1024 /* revert to legacy enumerarion */ 1025 x86gentopo_legacy = 1; 1026 1027 return (-1); 1028 } 1029 1030 nvlist_t * 1031 fm_smb_mc_bboards(uint_t bdf) 1032 { 1033 1034 int i; 1035 smbios_hdl_t *shp; 1036 uint16_t ext_id; 1037 smbios_memarray_ext_t em; 1038 nvlist_t *fmri = NULL; 1039 smbs_cnt_t *mastypes; 1040 int strcnt; 1041 1042 if (x86gentopo_legacy) 1043 return (NULL); 1044 1045 shp = ksmbios; 1046 if (shp == NULL) { 1047 goto bad; 1048 } 1049 1050 strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY); 1051 if (strcnt == 0) 1052 goto bad; 1053 1054 mastypes = smb_create_strcnt(strcnt); 1055 if (mastypes == NULL) 1056 goto bad; 1057 1058 mastypes->type = SUN_OEM_EXT_MEMARRAY; 1059 smb_strcnt(shp, mastypes); 1060 for (i = 0; i < mastypes->count; i++) { 1061 ext_id = mastypes->ids[i]->id; 1062 (void) smbios_info_extmemarray(shp, ext_id, &em); 1063 if (em.smbmae_bdf == bdf) { 1064 fmri = smb_bboard(0, em.smbmae_comp, MC); 1065 smb_free_strcnt(mastypes, strcnt); 1066 return (fmri); 1067 } 1068 } 1069 smb_free_strcnt(mastypes, strcnt); 1070 bad: 1071 /* revert to legacy enumerarion */ 1072 x86gentopo_legacy = 1; 1073 1074 return (NULL); 1075 } 1076 1077 int 1078 fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst) 1079 { 1080 1081 int i, j; 1082 smbios_hdl_t *shp; 1083 smbios_memarray_ext_t em; 1084 uint16_t ext_id, proc_id; 1085 smbs_cnt_t *mastypes; 1086 smbs_cnt_t *pstypes; 1087 int ma_strcnt, p_strcnt; 1088 1089 if (x86gentopo_legacy) 1090 return (-1); 1091 1092 shp = ksmbios; 1093 if (shp == NULL) { 1094 goto bad; 1095 } 1096 1097 ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY); 1098 if (ma_strcnt == 0) 1099 goto bad; 1100 1101 mastypes = smb_create_strcnt(ma_strcnt); 1102 if (mastypes == NULL) 1103 goto bad; 1104 1105 mastypes->type = SUN_OEM_EXT_MEMARRAY; 1106 smb_strcnt(shp, mastypes); 1107 pstypes = NULL; 1108 p_strcnt = 0; 1109 for (i = 0; i < mastypes->count; i++) { 1110 ext_id = mastypes->ids[i]->id; 1111 (void) smbios_info_extmemarray(shp, ext_id, &em); 1112 if (em.smbmae_bdf == bdf) { 1113 p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR); 1114 if (p_strcnt == 0) { 1115 smb_free_strcnt(mastypes, ma_strcnt); 1116 goto bad; 1117 } 1118 1119 pstypes = smb_create_strcnt(p_strcnt); 1120 if (pstypes == NULL) { 1121 smb_free_strcnt(mastypes, ma_strcnt); 1122 goto bad; 1123 } 1124 1125 pstypes->type = SMB_TYPE_PROCESSOR; 1126 smb_strcnt(shp, pstypes); 1127 for (j = 0; j < pstypes->count; j++) { 1128 proc_id = pstypes->ids[j]->id; 1129 if (proc_id == em.smbmae_comp) { 1130 *chip_inst = pstypes->ids[j]->inst; 1131 smb_free_strcnt(mastypes, ma_strcnt); 1132 smb_free_strcnt(pstypes, p_strcnt); 1133 return (0); 1134 } 1135 } 1136 } 1137 } 1138 smb_free_strcnt(mastypes, ma_strcnt); 1139 smb_free_strcnt(pstypes, p_strcnt); 1140 bad: 1141 /* revert to legacy enumeration */ 1142 x86gentopo_legacy = 1; 1143 1144 return (-1); 1145 } 1146