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