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 2009 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 (void) smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb); 278 cont_count = (uint_t)smb_bb.smbb_contn; 279 if (cont_count == 0) { 280 continue; 281 } 282 283 cont_len = sizeof (id_t); 284 cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP); 285 if (cont_hdl == NULL) 286 continue; 287 288 rc = smbios_info_contains(shp, stype->ids[cnt]->id, 289 cont_count, cont_hdl); 290 if (rc > SMB_CONT_MAX) { 291 kmem_free(cont_hdl, cont_count * cont_len); 292 continue; 293 } 294 cont_count = MIN(rc, cont_count); 295 296 /* 297 * fill in the type 2 and type 4 ids which are 298 * contained in this type 2 299 */ 300 c = 0; 301 for (j = 0; j < cont_count; j++) { 302 cont_id = (uint16_t)cont_hdl[j]; 303 spt = smb_lookup_id(shp, cont_id); 304 if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD || 305 spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) { 306 *stype->ids[cnt]->cont_ids[c] = cont_id; 307 c++; 308 } 309 310 if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) { 311 for (i = 0; i < stype->count; i++) { 312 if (stype->ids[i]->id == cont_id) { 313 stype->ids[i]->cont_by_id = 314 bb_id; 315 } 316 } 317 } 318 319 } 320 stype->ids[cnt]->cont_count = c; 321 if (cont_hdl != NULL) 322 kmem_free(cont_hdl, cont_count * cont_len); 323 } 324 } 325 326 /* 327 * Verify SMBIOS structures for x86 generic topology. 328 * 329 * Return (0) on success. 330 */ 331 static int 332 fm_smb_check(smbios_hdl_t *shp) 333 { 334 int i; 335 int bb_cnt = 0; 336 int pr_cnt = 0; 337 int expr_cnt = 0; 338 int ma_cnt = 0; 339 int exma_cnt = 0; 340 int mdev_cnt = 0; 341 int exmdev_cnt = 0; 342 uint16_t bb_id; 343 uint16_t pr_id, expr_id; 344 uint16_t ma_id, exma_id; 345 uint16_t mdev_id, exmdev_id; 346 smbios_bboard_t bb; 347 smbios_processor_ext_t exproc; 348 smbios_memarray_ext_t exma; 349 smbios_memdevice_ext_t exmdev; 350 smbs_cnt_t *bb_stype; 351 smbs_cnt_t *pr_stype, *expr_stype; 352 smbs_cnt_t *ma_stype, *exma_stype; 353 smbs_cnt_t *mdev_stype, *exmdev_stype; 354 355 /* 356 * Verify the existance of the requuired extended OEM-Specific 357 * structures and they coincide with the structures they extend 358 * (e.g. the number of extended processor structures equal the 359 * number of processor structures). 360 */ 361 pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR); 362 expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR); 363 ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY); 364 exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY); 365 mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE); 366 exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE); 367 if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 || 368 expr_cnt != pr_cnt || exma_cnt != ma_cnt || 369 exmdev_cnt != mdev_cnt) { 370 #ifdef DEBUG 371 cmn_err(CE_NOTE, "Structure mismatch: ext_proc (%d) " 372 "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n", 373 expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt, 374 mdev_cnt); 375 #endif /* DEBUG */ 376 return (-1); 377 } 378 379 /* 380 * Verify the OEM-Specific structrures are correctly 381 * linked to the SMBIOS structure types they extend. 382 */ 383 384 /* allocate processor stypes */ 385 pr_stype = smb_create_strcnt(pr_cnt); 386 expr_stype = smb_create_strcnt(expr_cnt); 387 388 /* fill in stypes */ 389 pr_stype->type = SMB_TYPE_PROCESSOR; 390 smb_strcnt(shp, pr_stype); 391 expr_stype->type = SUN_OEM_EXT_PROCESSOR; 392 smb_strcnt(shp, expr_stype); 393 394 /* verify the ext proc struct belong to the proc struct */ 395 for (i = 0; i < pr_cnt; i++) { 396 pr_id = pr_stype->ids[i]->id; 397 expr_id = expr_stype->ids[i]->id; 398 (void) smbios_info_extprocessor(shp, expr_id, &exproc); 399 if (exproc.smbpe_processor != pr_id) { 400 #ifdef DEBUG 401 cmn_err(CE_NOTE, "Processor struct linkage (%d)", i); 402 #endif /* DEBUG */ 403 smb_free_strcnt(pr_stype, pr_cnt); 404 smb_free_strcnt(expr_stype, expr_cnt); 405 return (-1); 406 } 407 } 408 409 /* free stypes */ 410 smb_free_strcnt(pr_stype, pr_cnt); 411 smb_free_strcnt(expr_stype, expr_cnt); 412 413 /* allocate memory array stypes */ 414 ma_stype = smb_create_strcnt(ma_cnt); 415 exma_stype = smb_create_strcnt(exma_cnt); 416 417 /* fill in stypes */ 418 ma_stype->type = SMB_TYPE_MEMARRAY; 419 smb_strcnt(shp, ma_stype); 420 exma_stype->type = SUN_OEM_EXT_MEMARRAY; 421 smb_strcnt(shp, exma_stype); 422 423 /* verify linkage from ext memarray struct to memarray struct */ 424 for (i = 0; i < ma_cnt; i++) { 425 ma_id = ma_stype->ids[i]->id; 426 exma_id = exma_stype->ids[i]->id; 427 (void) smbios_info_extmemarray(shp, exma_id, &exma); 428 if (exma.smbmae_ma != ma_id) { 429 #ifdef DEBUG 430 cmn_err(CE_NOTE, "Memory Array struct linkage (%d)", i); 431 #endif /* DEBUG */ 432 smb_free_strcnt(ma_stype, ma_cnt); 433 smb_free_strcnt(exma_stype, exma_cnt); 434 return (-1); 435 } 436 } 437 438 /* free stypes */ 439 smb_free_strcnt(ma_stype, ma_cnt); 440 smb_free_strcnt(exma_stype, exma_cnt); 441 442 /* allocate memory device stypes */ 443 mdev_stype = smb_create_strcnt(mdev_cnt); 444 exmdev_stype = smb_create_strcnt(exmdev_cnt); 445 446 /* fill in stypes */ 447 mdev_stype->type = SMB_TYPE_MEMDEVICE; 448 smb_strcnt(shp, mdev_stype); 449 exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE; 450 smb_strcnt(shp, exmdev_stype); 451 452 /* verify linkage */ 453 for (i = 0; i < mdev_cnt; i++) { 454 mdev_id = mdev_stype->ids[i]->id; 455 exmdev_id = exmdev_stype->ids[i]->id; 456 (void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev); 457 if (exmdev.smbmdeve_md != mdev_id) { 458 #ifdef DEBUG 459 cmn_err(CE_NOTE, "Memory Device struct linkage (%d)", 460 i); 461 #endif /* DEBUG */ 462 smb_free_strcnt(mdev_stype, mdev_cnt); 463 smb_free_strcnt(exmdev_stype, exmdev_cnt); 464 return (-1); 465 } 466 } 467 468 /* free stypes */ 469 smb_free_strcnt(mdev_stype, mdev_cnt); 470 smb_free_strcnt(exmdev_stype, exmdev_cnt); 471 472 /* 473 * Verify the presece of contained handles if there are more 474 * than one Type-2 (Base Board) structures. 475 */ 476 bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD); 477 if (bb_cnt > 1) { 478 /* allocate base board stypes */ 479 bb_stype = smb_create_strcnt(bb_cnt); 480 481 /* fill in stypes */ 482 bb_stype->type = SMB_TYPE_BASEBOARD; 483 smb_strcnt(shp, bb_stype); 484 485 /* verify contained handles */ 486 for (i = 0; i < bb_cnt; i++) { 487 bb_id = bb_stype->ids[i]->id; 488 (void) smbios_info_bboard(shp, bb_id, &bb); 489 if (bb.smbb_contn == 0) { 490 #ifdef DEBUG 491 cmn_err(CE_NOTE, "No contained hanldes (%d)", 492 i); 493 #endif /* DEBUG */ 494 smb_free_strcnt(bb_stype, bb_cnt); 495 return (-1); 496 } 497 } 498 499 /* free stypes */ 500 smb_free_strcnt(bb_stype, bb_cnt); 501 } 502 503 return (0); 504 } 505 506 void 507 fm_smb_fmacompat() 508 { 509 int i, j; 510 int id; 511 int cnt; 512 const char **oem_strings = NULL; 513 smbs_cnt_t *oemstypes; 514 smbios_hdl_t *shp; 515 int strcnt; 516 int compat = 0; 517 518 /* check for BKS */ 519 if (x86gentopo_legacy == 1) { 520 #ifdef DEBUG 521 cmn_err(CE_NOTE, "forced legacy x86 topology enumeration"); 522 #endif /* DEBUG */ 523 return; 524 } 525 526 shp = ksmbios; 527 if (shp == NULL) { 528 goto bad; 529 } 530 531 /* OEM strings (Type 11) */ 532 strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR); 533 if (strcnt == 0) 534 goto bad; 535 536 oemstypes = smb_create_strcnt(strcnt); 537 if (oemstypes == NULL) 538 goto bad; 539 540 oemstypes->type = SMB_TYPE_OEMSTR; 541 smb_strcnt(shp, oemstypes); 542 543 for (i = 0; i < oemstypes->count; i++) { 544 id = oemstypes->ids[i]->id; 545 cnt = smbios_info_strtab(shp, id, 0, NULL); 546 if (cnt > 0) { 547 oem_strings = kmem_zalloc(sizeof (char *) * cnt, 548 KM_SLEEP); 549 (void) smbios_info_strtab(shp, id, cnt, oem_strings); 550 551 for (j = 0; j < cnt; j++) { 552 if (strncmp(oem_strings[j], SMB_PRMS1, 553 strlen(SMB_PRMS1) + 1) == 0) { 554 kmem_free(oem_strings, 555 sizeof (char *) * cnt); 556 smb_free_strcnt(oemstypes, strcnt); 557 compat = 1; 558 break; 559 } 560 } 561 } 562 } 563 564 if (compat == 0) { 565 /* didn't find x86pi magic cookie */ 566 if (oem_strings != NULL) 567 kmem_free(oem_strings, sizeof (char *) * cnt); 568 smb_free_strcnt(oemstypes, strcnt); 569 goto bad; 570 } 571 572 /* sanity check SMBIOS structures */ 573 if (fm_smb_check(shp) == 0) 574 return; 575 576 bad: 577 /* not compatible with x86gentopo; revert to legacy enumeration */ 578 #ifdef DEBUG 579 cmn_err(CE_NOTE, "SMBIOS is not compatible with x86 generic topology."); 580 cmn_err(CE_NOTE, "Invoking legacy x86 topology enumeration."); 581 #endif /* DEBUG */ 582 x86gentopo_legacy = 1; 583 } 584 585 static int 586 find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid) 587 { 588 uint16_t ext_id; 589 int i, j; 590 smbios_processor_ext_t ep; 591 smbs_cnt_t *pstypes; 592 int strcnt; 593 594 strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR); 595 if (strcnt == 0) 596 return (0); 597 598 pstypes = smb_create_strcnt(strcnt); 599 if (pstypes == NULL) 600 return (0); 601 602 pstypes->type = SUN_OEM_EXT_PROCESSOR; 603 smb_strcnt(shp, pstypes); 604 for (i = 0; i < pstypes->count; i++) { 605 ext_id = pstypes->ids[i]->id; 606 (void) smbios_info_extprocessor(shp, ext_id, &ep); 607 if (ep.smbpe_processor == proc_id) { 608 for (j = 0; j < ep.smbpe_n; j++) { 609 if (ep.smbpe_apicid[j] == strand_apicid) { 610 smb_free_strcnt(pstypes, strcnt); 611 return (1); 612 } 613 } 614 } 615 } 616 smb_free_strcnt(pstypes, strcnt); 617 return (0); 618 } 619 620 /* 621 * go throught the type 2 structure contained_ids looking for 622 * the type 4 which has strand_apicid == this strand_apicid 623 */ 624 static int 625 find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid, 626 uint16_t bb_id, uint16_t proc_hdl, int is_proc) 627 { 628 int n; 629 const smb_struct_t *sp; 630 smbios_bboard_t bb; 631 uint_t cont_count, cont_len; 632 uint16_t cont_id; 633 id_t *cont_hdl = NULL; 634 int rc; 635 636 637 (void) smbios_info_bboard(shp, bb_id, &bb); 638 cont_count = (uint_t)bb.smbb_contn; 639 if (cont_count == 0) 640 return (0); 641 642 cont_len = sizeof (id_t); 643 cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP); 644 if (cont_hdl == NULL) 645 return (0); 646 647 rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl); 648 if (rc > SMB_CONT_MAX) { 649 kmem_free(cont_hdl, cont_count * cont_len); 650 return (0); 651 } 652 cont_count = MIN(rc, cont_count); 653 654 for (n = 0; n < cont_count; n++) { 655 cont_id = (uint16_t)cont_hdl[n]; 656 sp = smb_lookup_id(shp, cont_id); 657 if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) { 658 if (is_proc) { 659 if (find_matching_apic(shp, cont_id, 660 strand_apicid)) { 661 kmem_free(cont_hdl, 662 cont_count * cont_len); 663 return (1); 664 } 665 } else { 666 if (cont_id == proc_hdl) { 667 kmem_free(cont_hdl, 668 cont_count * cont_len); 669 return (1); 670 } 671 } 672 } 673 } 674 if (cont_hdl != NULL) 675 kmem_free(cont_hdl, cont_count * cont_len); 676 677 return (0); 678 } 679 680 void 681 get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx) 682 { 683 int curr_id, tmp_id; 684 int i, j, nb; 685 bbindex_t tmp_idx; 686 687 for (i = 0; i < MAX_PAIRS; i++) 688 tmp_idx.index[i] = 0; 689 690 tmp_idx.count = 0; 691 692 curr_id = bb_id; 693 for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) { 694 tmp_id = bbstypes->ids[nb]->id; 695 if (tmp_id == curr_id) { 696 tmp_idx.index[i] = nb; 697 tmp_idx.count++; 698 curr_id = bbstypes->ids[nb]->cont_by_id; 699 if (curr_id == -1) 700 break; 701 i++; 702 } 703 } 704 705 for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) { 706 bb_idx->index[j] = tmp_idx.index[i]; 707 j++; 708 } 709 710 bb_idx->count = tmp_idx.count; 711 } 712 713 int 714 get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst, 715 uint16_t bb_id, int *chcnt) 716 { 717 int ch_strcnt; 718 smbs_cnt_t *chstypes; 719 uint16_t chassis_id, tmp_id; 720 smbios_bboard_t bb; 721 int rc = 0; 722 int i; 723 724 rc = smbios_info_bboard(shp, bb_id, &bb); 725 if (rc != 0) { 726 return (-1); 727 } 728 729 chassis_id = bb.smbb_chassis; 730 731 ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS); 732 733 if (ch_strcnt == 0) 734 return (-1); 735 736 chstypes = smb_create_strcnt(ch_strcnt); 737 if (chstypes == NULL) 738 return (-1); 739 740 chstypes->type = SMB_TYPE_CHASSIS; 741 smb_strcnt(shp, chstypes); 742 743 for (i = 0; i < chstypes->count; i++) { 744 tmp_id = chstypes->ids[i]->id; 745 if (tmp_id == chassis_id) { 746 *chassis_inst = chstypes->ids[i]->inst; 747 if (chstypes->ids[i]->inst != 0) 748 *chcnt = 2; 749 else 750 *chcnt = 1; 751 smb_free_strcnt(chstypes, ch_strcnt); 752 return (0); 753 } 754 } 755 756 smb_free_strcnt(chstypes, ch_strcnt); 757 return (-1); 758 } 759 760 int 761 smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri, uint_t parent, 762 smbs_cnt_t *bbstypes) 763 { 764 int rc = 0; 765 int i, j, n, cnt; 766 int id, index; 767 nvlist_t *pairs[MAX_PAIRS]; 768 smbios_bboard_t bb; 769 uint16_t chassis_inst, mch_inst; 770 char name[40]; 771 char idstr[11]; 772 bbindex_t bb_idx; 773 uint16_t bbid; 774 int chcnt = 0; 775 776 for (n = 0; n < MAX_PAIRS; n++) { 777 bb_idx.index[n] = 0; 778 pairs[n] = NULL; 779 } 780 bb_idx.count = 0; 781 782 get_bboard_index(bbstypes, parent, &bb_idx); 783 784 index = bb_idx.index[0]; 785 bbid = bbstypes->ids[index]->id; 786 787 rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt); 788 789 if (rc != 0) { 790 return (rc); 791 } 792 793 if ((bb_idx.count + chcnt) > MAX_PAIRS) { 794 return (-1); 795 } 796 797 i = 0; 798 if (chcnt > 1) { 799 /* 800 * create main chassis pair 801 */ 802 pairs[i] = fm_nvlist_create(NULL); 803 if (pairs[i] == NULL) { 804 return (-1); 805 } 806 mch_inst = 0; 807 (void) snprintf(idstr, sizeof (idstr), "%u", mch_inst); 808 if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, 809 "chassis") != 0) || 810 (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) { 811 fm_nvlist_destroy(pairs[i], FM_NVA_FREE); 812 return (-1); 813 } 814 i++; 815 } 816 817 /* 818 * create chassis pair 819 */ 820 pairs[i] = fm_nvlist_create(NULL); 821 if (pairs[i] == NULL) { 822 for (n = 0; n < MAX_PAIRS; n++) { 823 if (pairs[n] != NULL) 824 fm_nvlist_destroy(pairs[n], FM_NVA_FREE); 825 } 826 return (-1); 827 } 828 (void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst); 829 if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) || 830 (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) { 831 for (n = 0; n < MAX_PAIRS; n++) { 832 if (pairs[n] != NULL) 833 fm_nvlist_destroy(pairs[n], FM_NVA_FREE); 834 } 835 return (-1); 836 } 837 838 for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) { 839 index = bb_idx.index[j]; 840 bbid = bbstypes->ids[index]->id; 841 rc = smbios_info_bboard(shp, bbid, &bb); 842 if (rc != 0) { 843 rc = -1; 844 break; 845 } 846 847 pairs[i] = fm_nvlist_create(NULL); 848 if (pairs[i] == NULL) { 849 rc = -1; 850 break; 851 } 852 853 id = bbstypes->ids[index]->inst; 854 (void) snprintf(idstr, sizeof (idstr), "%u", id); 855 (void) strncpy(name, bbd_type[bb.smbb_type].name, 856 sizeof (name)); 857 cnt++; 858 859 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 || 860 nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) 861 != 0) { 862 rc = -1; 863 break; 864 } 865 i++; 866 } 867 868 if (rc != -1) { 869 if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, 870 pairs, cnt) != 0) { 871 rc = -1; 872 } 873 } 874 875 for (n = 0; n < cnt; n++) { 876 if (pairs[n] != NULL) 877 fm_nvlist_destroy(pairs[n], FM_NVA_FREE); 878 } 879 880 return (rc); 881 } 882 883 /* 884 * pass in strand_apic id 885 * return chip's bboards list which has strand_apicid == passed 886 * in strand_apic id 887 */ 888 static nvlist_t * 889 smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc) 890 { 891 smbios_hdl_t *shp; 892 smbs_cnt_t *bbstypes; 893 int nb; 894 int bb_smbid; 895 nvlist_t *fmri = NULL; 896 int rc = 0; 897 int bb_strcnt; 898 899 if (x86gentopo_legacy) 900 return (NULL); 901 902 shp = ksmbios; 903 if (shp == NULL) { 904 goto bad; 905 } 906 907 /* 908 * Type 2 structs : "base board" 909 */ 910 bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD); 911 if (bb_strcnt == 0) { 912 goto bad; 913 } 914 915 bbstypes = smb_create_strcnt(bb_strcnt); 916 if (bbstypes == NULL) { 917 goto bad; 918 } 919 920 bbstypes->type = SMB_TYPE_BASEBOARD; 921 smb_strcnt(shp, bbstypes); 922 smb_bb_contains(shp, bbstypes); 923 924 for (nb = 0; nb < bbstypes->count; nb++) { 925 if (bbstypes->ids[nb]->visited) { 926 continue; 927 } 928 929 bbstypes->ids[nb]->visited = 1; 930 bb_smbid = bbstypes->ids[nb]->id; 931 932 /* 933 * check if there is a matching processor under 934 * this board. If found, find base board(s) of this proc 935 * If proc is not in contained handle of a base board and 936 * there is only one base board in the system, treat that base 937 * board as the parent of the proc 938 */ 939 if (find_matching_proc(shp, strand_apicid, 940 bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) { 941 fmri = fm_nvlist_create(NULL); 942 if (fmri == NULL) { 943 smb_free_strcnt(bbstypes, bb_strcnt); 944 goto bad; 945 } 946 /* 947 * find parent by walking the cont_by_id 948 */ 949 rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes); 950 smb_free_strcnt(bbstypes, bb_strcnt); 951 if (rc == 0) { 952 return (fmri); 953 } else 954 goto bad; 955 } 956 957 } 958 959 smb_free_strcnt(bbstypes, bb_strcnt); 960 bad: 961 /* revert to legacy enumeration */ 962 x86gentopo_legacy = 1; 963 964 return (NULL); 965 } 966 967 nvlist_t * 968 fm_smb_bboard(uint_t strand_apicid) 969 { 970 return (smb_bboard(strand_apicid, 0, PROC)); 971 } 972 973 int 974 fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid) 975 { 976 int n; 977 smbios_hdl_t *shp; 978 uint16_t proc_id; 979 smbs_cnt_t *pstypes; 980 int strcnt; 981 982 if (x86gentopo_legacy) 983 return (-1); 984 985 shp = ksmbios; 986 if (shp == NULL) { 987 goto bad; 988 } 989 990 strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR); 991 if (strcnt == 0) 992 goto bad; 993 994 pstypes = smb_create_strcnt(strcnt); 995 if (pstypes == NULL) 996 goto bad; 997 998 pstypes->type = SMB_TYPE_PROCESSOR; 999 smb_strcnt(shp, pstypes); 1000 for (n = 0; n < pstypes->count; n++) { 1001 proc_id = pstypes->ids[n]->id; 1002 if (find_matching_apic(shp, proc_id, strand_apicid)) { 1003 *chip_inst = pstypes->ids[n]->inst; 1004 *smbiosid = pstypes->ids[n]->id; 1005 smb_free_strcnt(pstypes, strcnt); 1006 return (0); 1007 } 1008 } 1009 smb_free_strcnt(pstypes, strcnt); 1010 bad: 1011 /* revert to legacy enumerarion */ 1012 x86gentopo_legacy = 1; 1013 1014 return (-1); 1015 } 1016 1017 nvlist_t * 1018 fm_smb_mc_bboards(uint_t bdf) 1019 { 1020 1021 int i; 1022 smbios_hdl_t *shp; 1023 uint16_t ext_id; 1024 smbios_memarray_ext_t em; 1025 nvlist_t *fmri = NULL; 1026 smbs_cnt_t *mastypes; 1027 int strcnt; 1028 1029 if (x86gentopo_legacy) 1030 return (NULL); 1031 1032 shp = ksmbios; 1033 if (shp == NULL) { 1034 goto bad; 1035 } 1036 1037 strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY); 1038 if (strcnt == 0) 1039 goto bad; 1040 1041 mastypes = smb_create_strcnt(strcnt); 1042 if (mastypes == NULL) 1043 goto bad; 1044 1045 mastypes->type = SUN_OEM_EXT_MEMARRAY; 1046 smb_strcnt(shp, mastypes); 1047 for (i = 0; i < mastypes->count; i++) { 1048 ext_id = mastypes->ids[i]->id; 1049 (void) smbios_info_extmemarray(shp, ext_id, &em); 1050 if (em.smbmae_bdf == bdf) { 1051 fmri = smb_bboard(0, em.smbmae_comp, MC); 1052 smb_free_strcnt(mastypes, strcnt); 1053 return (fmri); 1054 } 1055 } 1056 smb_free_strcnt(mastypes, strcnt); 1057 bad: 1058 /* revert to legacy enumerarion */ 1059 x86gentopo_legacy = 1; 1060 1061 return (NULL); 1062 } 1063 1064 int 1065 fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst) { 1066 1067 int i, j; 1068 smbios_hdl_t *shp; 1069 smbios_memarray_ext_t em; 1070 uint16_t ext_id, proc_id; 1071 smbs_cnt_t *mastypes; 1072 smbs_cnt_t *pstypes; 1073 int ma_strcnt, p_strcnt; 1074 1075 if (x86gentopo_legacy) 1076 return (-1); 1077 1078 shp = ksmbios; 1079 if (shp == NULL) { 1080 goto bad; 1081 } 1082 1083 ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY); 1084 if (ma_strcnt == 0) 1085 goto bad; 1086 1087 mastypes = smb_create_strcnt(ma_strcnt); 1088 if (mastypes == NULL) 1089 goto bad; 1090 1091 mastypes->type = SUN_OEM_EXT_MEMARRAY; 1092 smb_strcnt(shp, mastypes); 1093 for (i = 0; i < mastypes->count; i++) { 1094 ext_id = mastypes->ids[i]->id; 1095 (void) smbios_info_extmemarray(shp, ext_id, &em); 1096 if (em.smbmae_bdf == bdf) { 1097 p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR); 1098 if (p_strcnt == 0) { 1099 smb_free_strcnt(mastypes, ma_strcnt); 1100 goto bad; 1101 } 1102 1103 pstypes = smb_create_strcnt(p_strcnt); 1104 if (pstypes == NULL) { 1105 smb_free_strcnt(mastypes, ma_strcnt); 1106 goto bad; 1107 } 1108 1109 pstypes->type = SMB_TYPE_PROCESSOR; 1110 smb_strcnt(shp, pstypes); 1111 for (j = 0; j < pstypes->count; j++) { 1112 proc_id = pstypes->ids[j]->id; 1113 if (proc_id == em.smbmae_comp) { 1114 *chip_inst = pstypes->ids[j]->inst; 1115 smb_free_strcnt(mastypes, ma_strcnt); 1116 smb_free_strcnt(pstypes, p_strcnt); 1117 return (0); 1118 } 1119 } 1120 } 1121 } 1122 smb_free_strcnt(mastypes, ma_strcnt); 1123 smb_free_strcnt(pstypes, p_strcnt); 1124 bad: 1125 /* revert to legacy enumeration */ 1126 x86gentopo_legacy = 1; 1127 1128 return (-1); 1129 } 1130