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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 #include <fm/fmd_api.h>
28 #include <fm/libtopo.h>
29 #include <sys/fm/protocol.h>
30 #include <cmd.h>
31 #include <string.h>
32 #include <cmd_hc_sun4v.h>
33
34 /* Using a global variable is safe because the DE is single threaded */
35
36 nvlist_t *dimm_nvl;
37 nvlist_t *mb_nvl;
38 nvlist_t *rsc_nvl;
39
40 nvlist_t *
cmd_fault_add_location(fmd_hdl_t * hdl,nvlist_t * flt,const char * locstr)41 cmd_fault_add_location(fmd_hdl_t *hdl, nvlist_t *flt, const char *locstr) {
42
43 char *t, *s;
44
45 if (nvlist_lookup_string(flt, FM_FAULT_LOCATION, &t) == 0)
46 return (flt); /* already has location value */
47
48 /* Replace occurrence of ": " with "/" to avoid confusing ILOM. */
49 t = fmd_hdl_zalloc(hdl, strlen(locstr) + 1, FMD_SLEEP);
50 s = strstr(locstr, ": ");
51 if (s != NULL) {
52 (void) strncpy(t, locstr, s - locstr);
53 (void) strcat(t, "/");
54 (void) strcat(t, s + 2);
55 } else {
56 (void) strcpy(t, locstr);
57 }
58
59 /* Also, remove any J number from end of this string. */
60 s = strstr(t, "/J");
61 if (s != NULL)
62 *s = '\0';
63
64 if (nvlist_add_string(flt, FM_FAULT_LOCATION, t) != 0)
65 fmd_hdl_error(hdl, "unable to alloc location for fault\n");
66 fmd_hdl_free(hdl, t, strlen(locstr) + 1);
67 return (flt);
68 }
69
70 typedef struct tr_ent {
71 const char *nac_component;
72 const char *hc_component;
73 } tr_ent_t;
74
75 static tr_ent_t tr_tbl[] = {
76 { "MB", "motherboard" },
77 { "CPU", "cpuboard" },
78 { "MEM", "memboard" },
79 { "CMP", "chip" },
80 { "BR", "branch" },
81 { "CH", "dram-channel" },
82 { "R", "rank" },
83 { "D", "dimm" }
84 };
85
86 #define tr_tbl_n sizeof (tr_tbl) / sizeof (tr_ent_t)
87
88 int
map_name(const char * p)89 map_name(const char *p) {
90 int i;
91
92 for (i = 0; i < tr_tbl_n; i++) {
93 if (strncmp(p, tr_tbl[i].nac_component,
94 strlen(tr_tbl[i].nac_component)) == 0)
95 return (i);
96 }
97 return (-1);
98 }
99
100 int
cmd_count_components(const char * str,char sep)101 cmd_count_components(const char *str, char sep)
102 {
103 int num = 0;
104 const char *cptr = str;
105
106 if (*cptr == sep) cptr++; /* skip initial sep */
107 if (strlen(cptr) > 0) num = 1;
108 while ((cptr = strchr(cptr, sep)) != NULL) {
109 cptr++;
110 if (cptr == NULL || strcmp(cptr, "") == 0) break;
111 if (map_name(cptr) >= 0) num++;
112 }
113 return (num);
114 }
115
116 /*
117 * This version of breakup_components assumes that all component names which
118 * it sees are of the form: <nonnumeric piece><numeric piece>
119 * i.e. no embedded numerals in component name which have to be spelled out.
120 */
121
122 int
cmd_breakup_components(char * str,char * sep,nvlist_t ** hc_nvl)123 cmd_breakup_components(char *str, char *sep, nvlist_t **hc_nvl)
124 {
125 char namebuf[64], instbuf[64];
126 char *token, *tokbuf;
127 int i, j, namelen, instlen;
128
129 i = 0;
130 for (token = strtok_r(str, sep, &tokbuf);
131 token != NULL;
132 token = strtok_r(NULL, sep, &tokbuf)) {
133 namelen = strcspn(token, "0123456789");
134 instlen = strspn(token+namelen, "0123456789");
135 (void) strncpy(namebuf, token, namelen);
136 namebuf[namelen] = '\0';
137
138 if ((j = map_name(namebuf)) < 0)
139 continue; /* skip names that don't map */
140
141 if (instlen == 0) {
142 (void) strncpy(instbuf, "0", 2);
143 } else {
144 (void) strncpy(instbuf, token+namelen, instlen);
145 instbuf[instlen] = '\0';
146 }
147 if (nvlist_add_string(hc_nvl[i], FM_FMRI_HC_NAME,
148 tr_tbl[j].hc_component) != 0 ||
149 nvlist_add_string(hc_nvl[i], FM_FMRI_HC_ID, instbuf) != 0)
150 return (-1);
151 i++;
152 }
153 return (1);
154 }
155
156 char *
cmd_getfru_loc(fmd_hdl_t * hdl,nvlist_t * asru)157 cmd_getfru_loc(fmd_hdl_t *hdl, nvlist_t *asru) {
158
159 char *fru_loc, *cpufru;
160 if (nvlist_lookup_string(asru, FM_FMRI_CPU_CPUFRU, &cpufru) == 0) {
161 fru_loc = strstr(cpufru, "MB");
162 if (fru_loc != NULL) {
163 fmd_hdl_debug(hdl, "cmd_getfru_loc: fruloc=%s\n",
164 fru_loc);
165 return (fmd_hdl_strdup(hdl, fru_loc, FMD_SLEEP));
166 }
167 }
168 fmd_hdl_debug(hdl, "cmd_getfru_loc: Default fruloc=empty string\n");
169 return (fmd_hdl_strdup(hdl, EMPTY_STR, FMD_SLEEP));
170 }
171
172 nvlist_t *
cmd_mkboard_fru(fmd_hdl_t * hdl,char * frustr,char * serialstr,char * partstr)173 cmd_mkboard_fru(fmd_hdl_t *hdl, char *frustr, char *serialstr, char *partstr) {
174
175 char *nac, *nac_name;
176 int n, i, len;
177 nvlist_t *fru, **hc_list;
178
179 if (frustr == NULL)
180 return (NULL);
181
182 if ((nac_name = strstr(frustr, "MB")) == NULL)
183 return (NULL);
184
185 len = strlen(nac_name) + 1;
186
187 nac = fmd_hdl_zalloc(hdl, len, FMD_SLEEP);
188 (void) strcpy(nac, nac_name);
189
190 n = cmd_count_components(nac, '/');
191
192 fmd_hdl_debug(hdl, "cmd_mkboard_fru: nac=%s components=%d\n", nac, n);
193
194 hc_list = fmd_hdl_zalloc(hdl, sizeof (nvlist_t *)*n, FMD_SLEEP);
195
196 for (i = 0; i < n; i++) {
197 (void) nvlist_alloc(&hc_list[i],
198 NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE, 0);
199 }
200
201 if (cmd_breakup_components(nac, "/", hc_list) < 0) {
202 for (i = 0; i < n; i++) {
203 if (hc_list[i] != NULL)
204 nvlist_free(hc_list[i]);
205 }
206 fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n);
207 fmd_hdl_free(hdl, nac, len);
208 return (NULL);
209 }
210
211 if (nvlist_alloc(&fru, NV_UNIQUE_NAME, 0) != 0) {
212 for (i = 0; i < n; i++) {
213 if (hc_list[i] != NULL)
214 nvlist_free(hc_list[i]);
215 }
216 fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n);
217 fmd_hdl_free(hdl, nac, len);
218 return (NULL);
219 }
220
221 if (nvlist_add_uint8(fru, FM_VERSION, FM_HC_SCHEME_VERSION) != 0 ||
222 nvlist_add_string(fru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0 ||
223 nvlist_add_string(fru, FM_FMRI_HC_ROOT, "") != 0 ||
224 nvlist_add_uint32(fru, FM_FMRI_HC_LIST_SZ, n) != 0 ||
225 nvlist_add_nvlist_array(fru, FM_FMRI_HC_LIST, hc_list, n) != 0) {
226 for (i = 0; i < n; i++) {
227 if (hc_list[i] != NULL)
228 nvlist_free(hc_list[i]);
229 }
230 fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n);
231 fmd_hdl_free(hdl, nac, len);
232 nvlist_free(fru);
233 return (NULL);
234 }
235
236 for (i = 0; i < n; i++) {
237 if (hc_list[i] != NULL)
238 nvlist_free(hc_list[i]);
239 }
240 fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n);
241 fmd_hdl_free(hdl, nac, len);
242
243 if ((serialstr != NULL &&
244 nvlist_add_string(fru, FM_FMRI_HC_SERIAL_ID, serialstr) != 0) ||
245 (partstr != NULL &&
246 nvlist_add_string(fru, FM_FMRI_HC_PART, partstr) != 0)) {
247 nvlist_free(fru);
248 return (NULL);
249 }
250
251 return (fru);
252 }
253
254 nvlist_t *
cmd_boardfru_create_fault(fmd_hdl_t * hdl,nvlist_t * asru,const char * fltnm,uint_t cert,char * loc)255 cmd_boardfru_create_fault(fmd_hdl_t *hdl, nvlist_t *asru, const char *fltnm,
256 uint_t cert, char *loc)
257 {
258 nvlist_t *flt, *nvlfru;
259 char *serialstr, *partstr;
260
261 if ((loc == NULL) || (strcmp(loc, EMPTY_STR) == 0))
262 return (NULL);
263
264 if (nvlist_lookup_string(asru, FM_FMRI_HC_SERIAL_ID, &serialstr) != 0)
265 serialstr = NULL;
266 if (nvlist_lookup_string(asru, FM_FMRI_HC_PART, &partstr) != 0)
267 partstr = NULL;
268
269 nvlfru = cmd_mkboard_fru(hdl, loc, serialstr, partstr);
270 if (nvlfru == NULL)
271 return (NULL);
272
273 flt = cmd_nvl_create_fault(hdl, fltnm, cert, nvlfru, nvlfru, NULL);
274 flt = cmd_fault_add_location(hdl, flt, loc);
275 if (nvlfru != NULL)
276 nvlist_free(nvlfru);
277 return (flt);
278 }
279
280 /* find_mb -- find hardware platform motherboard within libtopo */
281
282 /* ARGSUSED */
283 static int
find_mb(topo_hdl_t * thp,tnode_t * node,void * arg)284 find_mb(topo_hdl_t *thp, tnode_t *node, void *arg)
285 {
286 int err;
287 nvlist_t *rsrc, **hcl;
288 char *name;
289 uint_t n;
290
291 if (topo_node_resource(node, &rsrc, &err) < 0) {
292 return (TOPO_WALK_NEXT); /* no resource, try next */
293 }
294
295 if (nvlist_lookup_nvlist_array(rsrc, FM_FMRI_HC_LIST, &hcl, &n) < 0) {
296 nvlist_free(rsrc);
297 return (TOPO_WALK_NEXT);
298 }
299
300 if (nvlist_lookup_string(hcl[0], FM_FMRI_HC_NAME, &name) != 0) {
301 nvlist_free(rsrc);
302 return (TOPO_WALK_NEXT);
303 }
304
305 if (strcmp(name, "motherboard") != 0) {
306 nvlist_free(rsrc);
307 return (TOPO_WALK_NEXT); /* not MB hc list, try next */
308 }
309
310 (void) nvlist_dup(rsrc, &mb_nvl, NV_UNIQUE_NAME);
311
312 nvlist_free(rsrc);
313 return (TOPO_WALK_TERMINATE); /* if no space, give up */
314 }
315
316 /* init_mb -- read hardware platform motherboard from libtopo */
317
318 nvlist_t *
init_mb(fmd_hdl_t * hdl)319 init_mb(fmd_hdl_t *hdl)
320 {
321 topo_hdl_t *thp;
322 topo_walk_t *twp;
323 int err;
324
325 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
326 return (NULL);
327 if ((twp = topo_walk_init(thp,
328 FM_FMRI_SCHEME_HC, find_mb, NULL, &err))
329 == NULL) {
330 fmd_hdl_topo_rele(hdl, thp);
331 return (NULL);
332 }
333 (void) topo_walk_step(twp, TOPO_WALK_CHILD);
334 topo_walk_fini(twp);
335 fmd_hdl_topo_rele(hdl, thp);
336 return (mb_nvl);
337 }
338
339 /*ARGSUSED*/
340 static int
find_dimm_sn_mem(topo_hdl_t * thp,tnode_t * node,void * arg)341 find_dimm_sn_mem(topo_hdl_t *thp, tnode_t *node, void *arg)
342 {
343 int err;
344 uint_t n;
345 nvlist_t *rsrc;
346 char **sn;
347
348 if (topo_node_resource(node, &rsrc, &err) < 0) {
349 return (TOPO_WALK_NEXT); /* no resource, try next */
350 }
351 if (nvlist_lookup_string_array(rsrc,
352 FM_FMRI_HC_SERIAL_ID, &sn, &n) != 0) {
353 nvlist_free(rsrc);
354 return (TOPO_WALK_NEXT);
355 }
356 if (strcmp(*sn, (char *)arg) != 0) {
357 nvlist_free(rsrc);
358 return (TOPO_WALK_NEXT);
359 }
360 (void) nvlist_dup(rsrc, &dimm_nvl, NV_UNIQUE_NAME);
361 nvlist_free(rsrc);
362 return (TOPO_WALK_TERMINATE); /* if no space, give up */
363 }
364
365 /*ARGSUSED*/
366 static int
find_dimm_sn_hc(topo_hdl_t * thp,tnode_t * node,void * arg)367 find_dimm_sn_hc(topo_hdl_t *thp, tnode_t *node, void *arg)
368 {
369 int err;
370 nvlist_t *fru;
371 char *sn;
372
373 if (topo_node_fru(node, &fru, 0, &err) < 0) {
374 return (TOPO_WALK_NEXT); /* no fru, try next */
375 }
376 if (nvlist_lookup_string(fru, FM_FMRI_HC_SERIAL_ID, &sn) != 0) {
377 nvlist_free(fru);
378 return (TOPO_WALK_NEXT);
379 }
380 if (strcmp(sn, (char *)arg) != 0) {
381 nvlist_free(fru);
382 return (TOPO_WALK_NEXT);
383 }
384 (void) nvlist_dup(fru, &dimm_nvl, NV_UNIQUE_NAME);
385 nvlist_free(fru);
386 return (TOPO_WALK_TERMINATE); /* if no space, give up */
387 }
388
389 /* cmd_find_dimm_by_sn -- find fmri by sn from libtopo */
390
391 nvlist_t *
cmd_find_dimm_by_sn(fmd_hdl_t * hdl,char * schemename,char * sn)392 cmd_find_dimm_by_sn(fmd_hdl_t *hdl, char *schemename, char *sn)
393 {
394 topo_hdl_t *thp;
395 topo_walk_t *twp;
396 int err;
397
398 dimm_nvl = NULL;
399
400 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
401 return (NULL);
402 if (strcmp(schemename, FM_FMRI_SCHEME_MEM) == 0) {
403 if ((twp = topo_walk_init(thp,
404 schemename, find_dimm_sn_mem, sn, &err)) == NULL) {
405 fmd_hdl_topo_rele(hdl, thp);
406 return (NULL);
407 }
408 } else {
409 if ((twp = topo_walk_init(thp,
410 schemename, find_dimm_sn_hc, sn, &err)) == NULL) {
411 fmd_hdl_topo_rele(hdl, thp);
412 return (NULL);
413 }
414 }
415 (void) topo_walk_step(twp, TOPO_WALK_CHILD);
416 topo_walk_fini(twp);
417 fmd_hdl_topo_rele(hdl, thp);
418 return (dimm_nvl);
419 }
420
421 typedef struct cpuid {
422 char serial[100];
423 char id[10];
424 } cpuid_t;
425
426 /*ARGSUSED*/
427 static int
find_cpu_rsc_by_sn(topo_hdl_t * thp,tnode_t * node,void * arg)428 find_cpu_rsc_by_sn(topo_hdl_t *thp, tnode_t *node, void *arg)
429 {
430 int err;
431 nvlist_t *rsc;
432 cpuid_t *rscid = (cpuid_t *)arg;
433 char *sn, *name, *id;
434 nvlist_t **hcl;
435 uint_t n;
436
437 if (topo_node_resource(node, &rsc, &err) < 0) {
438 return (TOPO_WALK_NEXT); /* no rsc, try next */
439 }
440
441 if (nvlist_lookup_string(rsc, FM_FMRI_HC_SERIAL_ID, &sn) != 0) {
442 nvlist_free(rsc);
443 return (TOPO_WALK_NEXT);
444 }
445 if (strcmp(rscid->serial, sn) != 0) {
446 nvlist_free(rsc);
447 return (TOPO_WALK_NEXT);
448 }
449
450 if (nvlist_lookup_nvlist_array(rsc, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
451 nvlist_free(rsc);
452 return (TOPO_WALK_NEXT);
453 }
454
455 if ((nvlist_lookup_string(hcl[n - 1], FM_FMRI_HC_NAME, &name) != 0) ||
456 (nvlist_lookup_string(hcl[n - 1], FM_FMRI_HC_ID, &id) != 0)) {
457 nvlist_free(rsc);
458 return (TOPO_WALK_NEXT);
459 }
460
461 if ((strcmp(name, "cpu") != 0) || (strcmp(rscid->id, id) != 0)) {
462 nvlist_free(rsc);
463 return (TOPO_WALK_NEXT);
464 }
465
466 (void) nvlist_dup(rsc, &rsc_nvl, NV_UNIQUE_NAME);
467
468 nvlist_free(rsc);
469 return (TOPO_WALK_TERMINATE); /* if no space, give up */
470 }
471
472 nvlist_t *
cmd_find_cpu_rsc_by_sn(fmd_hdl_t * hdl,cpuid_t * cpuid)473 cmd_find_cpu_rsc_by_sn(fmd_hdl_t *hdl, cpuid_t *cpuid)
474 {
475 topo_hdl_t *thp;
476 topo_walk_t *twp;
477 int err;
478
479 rsc_nvl = NULL;
480 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
481 return (NULL);
482 if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC,
483 find_cpu_rsc_by_sn, cpuid, &err)) == NULL) {
484 fmd_hdl_topo_rele(hdl, thp);
485 return (NULL);
486 }
487 (void) topo_walk_step(twp, TOPO_WALK_CHILD);
488 topo_walk_fini(twp);
489 fmd_hdl_topo_rele(hdl, thp);
490 return (rsc_nvl);
491 }
492
493 nvlist_t *
get_cpu_fault_resource(fmd_hdl_t * hdl,nvlist_t * asru)494 get_cpu_fault_resource(fmd_hdl_t *hdl, nvlist_t *asru)
495 {
496 uint32_t cpu;
497 uint64_t serint;
498 char serial[64];
499 nvlist_t *rsc = NULL;
500 cpuid_t cpuid;
501 char strid[10];
502
503 if (nvlist_lookup_uint64(asru, FM_FMRI_CPU_SERIAL_ID, &serint) != 0 ||
504 nvlist_lookup_uint32(asru, FM_FMRI_CPU_ID, &cpu) != 0)
505 return (rsc);
506
507 (void) snprintf(serial, sizeof (serial), "%llx", serint);
508 (void) snprintf(strid, sizeof (strid), "%d", cpu);
509
510 (void) strcpy(cpuid.serial, serial);
511 (void) strcpy(cpuid.id, strid);
512
513 rsc = cmd_find_cpu_rsc_by_sn(hdl, &cpuid);
514 return (rsc);
515 }
516
517 /*ARGSUSED*/
518 static int
find_mem_rsc_hc(topo_hdl_t * thp,tnode_t * node,void * arg)519 find_mem_rsc_hc(topo_hdl_t *thp, tnode_t *node, void *arg)
520 {
521 int err;
522 nvlist_t *rsc;
523 char *sn;
524
525 if (topo_node_resource(node, &rsc, &err) < 0) {
526 return (TOPO_WALK_NEXT); /* no rsc, try next */
527 }
528 if (nvlist_lookup_string(rsc, FM_FMRI_HC_SERIAL_ID, &sn) != 0) {
529 nvlist_free(rsc);
530 return (TOPO_WALK_NEXT);
531 }
532 if (strcmp(sn, (char *)arg) != 0) {
533 nvlist_free(rsc);
534 return (TOPO_WALK_NEXT);
535 }
536 (void) nvlist_dup(rsc, &rsc_nvl, NV_UNIQUE_NAME);
537 nvlist_free(rsc);
538 return (TOPO_WALK_TERMINATE); /* if no space, give up */
539 }
540
541 nvlist_t *
cmd_find_mem_rsc_by_sn(fmd_hdl_t * hdl,char * sn)542 cmd_find_mem_rsc_by_sn(fmd_hdl_t *hdl, char *sn)
543 {
544 topo_hdl_t *thp;
545 topo_walk_t *twp;
546 int err;
547
548 rsc_nvl = NULL;
549
550 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
551 return (NULL);
552 if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC,
553 find_mem_rsc_hc, sn, &err)) == NULL) {
554 fmd_hdl_topo_rele(hdl, thp);
555 return (NULL);
556 }
557 (void) topo_walk_step(twp, TOPO_WALK_CHILD);
558 topo_walk_fini(twp);
559 fmd_hdl_topo_rele(hdl, thp);
560 return (rsc_nvl);
561 }
562
563 nvlist_t *
get_mem_fault_resource(fmd_hdl_t * hdl,nvlist_t * fru)564 get_mem_fault_resource(fmd_hdl_t *hdl, nvlist_t *fru)
565 {
566 char *sn;
567 uint_t n;
568 char **snarray;
569
570 if (nvlist_lookup_string(fru, FM_FMRI_HC_SERIAL_ID, &sn) == 0)
571 return (cmd_find_mem_rsc_by_sn(hdl, sn));
572
573 /*
574 * T1 platform fru is in mem scheme
575 */
576 if (nvlist_lookup_string_array(fru, FM_FMRI_MEM_SERIAL_ID,
577 &snarray, &n) == 0)
578 return (cmd_find_mem_rsc_by_sn(hdl, snarray[0]));
579
580 return (NULL);
581 }
582
583 int
is_T1_platform(nvlist_t * asru)584 is_T1_platform(nvlist_t *asru)
585 {
586 char *unum;
587 if (nvlist_lookup_string(asru, FM_FMRI_MEM_UNUM, &unum) == 0) {
588 if (strstr(unum, "BR") == NULL)
589 return (1);
590 }
591 return (0);
592 }
593
594 nvlist_t *
cmd_nvl_create_fault(fmd_hdl_t * hdl,const char * class,uint8_t cert,nvlist_t * asru,nvlist_t * fru,nvlist_t * rsrc)595 cmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, uint8_t cert,
596 nvlist_t *asru, nvlist_t *fru, nvlist_t *rsrc)
597 {
598 nvlist_t *fllist;
599 uint64_t offset, phyaddr;
600 nvlist_t *hsp = NULL;
601
602 rsrc = NULL;
603 (void) nvlist_add_nvlist(fru, FM_FMRI_AUTHORITY,
604 cmd.cmd_auth); /* not an error if this fails */
605
606 if (strstr(class, "fault.memory.") != NULL) {
607 /*
608 * For T1 platform fault.memory.bank and fault.memory.dimm,
609 * do not issue the hc schmem for resource and fru
610 */
611 if (is_T1_platform(asru) && (strstr(class, ".page") == NULL)) {
612 fllist = fmd_nvl_create_fault(hdl, class, cert, asru,
613 fru, fru);
614 return (fllist);
615 }
616
617 rsrc = get_mem_fault_resource(hdl, fru);
618 /*
619 * Need to append the phyaddr & offset into the
620 * hc-specific of the fault.memory.page resource
621 */
622 if ((rsrc != NULL) && strstr(class, ".page") != NULL) {
623 if (nvlist_alloc(&hsp, NV_UNIQUE_NAME, 0) == 0) {
624 if (nvlist_lookup_uint64(asru,
625 FM_FMRI_MEM_PHYSADDR, &phyaddr) == 0)
626 (void) (nvlist_add_uint64(hsp,
627 FM_FMRI_MEM_PHYSADDR,
628 phyaddr));
629
630 if (nvlist_lookup_uint64(asru,
631 FM_FMRI_MEM_OFFSET, &offset) == 0)
632 (void) nvlist_add_uint64(hsp,
633 FM_FMRI_HC_SPECIFIC_OFFSET, offset);
634
635 (void) nvlist_add_nvlist(rsrc,
636 FM_FMRI_HC_SPECIFIC, hsp);
637 }
638 }
639 fllist = fmd_nvl_create_fault(hdl, class, cert, asru,
640 fru, rsrc);
641 if (hsp != NULL)
642 nvlist_free(hsp);
643 } else {
644 rsrc = get_cpu_fault_resource(hdl, asru);
645 fllist = fmd_nvl_create_fault(hdl, class, cert, asru,
646 fru, rsrc);
647 }
648
649 if (rsrc != NULL)
650 nvlist_free(rsrc);
651
652 return (fllist);
653 }
654