1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <alloca.h>
30 #include <errno.h>
31 #include <libintl.h>
32 #include <sys/utsname.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/openpromio.h>
36 #include <sys/ddi.h>
37 #include <syslog.h>
38 #include <fcntl.h>
39 #include <dirent.h>
40 #include <unistd.h>
41 #include <locale.h>
42 #include <picl.h>
43 #include "pdevinfo.h"
44 #include "display.h"
45 #include "display_sun4u.h"
46 #include "picldefs.h"
47 #include "libprtdiag.h"
48
49 #if !defined(TEXT_DOMAIN)
50 #define TEXT_DOMAIN "SYS_TEST"
51 #endif
52
53 #define EM_INIT_FAIL dgettext(TEXT_DOMAIN,\
54 "picl_initialize failed: %s\n")
55 #define EM_GET_ROOT_FAIL dgettext(TEXT_DOMAIN,\
56 "Getting root node failed: %s\n")
57 #define EM_PRTDIAG_FAIL dgettext(TEXT_DOMAIN, "Prtdiag failed!\n")
58
59 #define SIGN_ON_MSG dgettext(TEXT_DOMAIN,\
60 "System Configuration: Oracle Corporation ")
61 #define SYSCLK_FREQ_MSG dgettext(TEXT_DOMAIN,\
62 "System clock frequency: %d MHZ\n")
63 #define MEM_SIZE_MSG dgettext(TEXT_DOMAIN, "Memory size: ")
64 #define FFB_DOUBLE_BUF dgettext(TEXT_DOMAIN, "FFB, Double Buffered")
65 #define FFB_SINGLE_BUF dgettext(TEXT_DOMAIN, "FFB, Single Buffered")
66
67 #define DEFAULT_BOARD_NUM 0
68 #define DEFAULT_PORTID 0
69 #define CLK_FREQ_66MHZ 66
70 #define USB -1
71 #define HUB -2
72
73 /* bus id */
74 #define SBUS_TYPE 0
75 #define PCI_TYPE 1
76 #define UPA_TYPE 2
77
78 #define UPA_NAME "upa"
79
80 /*
81 * PICL classes
82 */
83 #define PICL_CLASS_OPTIONS "options"
84
85 /*
86 * Property names
87 */
88
89 #define OBP_PROP_REG "reg"
90 #define OBP_PROP_CLOCK_FREQ "clock-frequency"
91 #define OBP_PROP_BOARD_NUM "board#"
92 #define OBP_PROP_REVISION_ID "revision-id"
93 #define OBP_PROP_VERSION_NUM "version#"
94 #define OBP_PROP_BOARD_TYPE "board_type"
95 #define OBP_PROP_ECACHE_SIZE "ecache-size"
96 #define OBP_PROP_L2_CACHE_SIZE "l2-cache-size"
97 #define OBP_PROP_L3_CACHE_SIZE "l3-cache-size"
98 #define OBP_PROP_IMPLEMENTATION "implementation#"
99 #define OBP_PROP_MASK "mask#"
100 #define OBP_PROP_COMPATIBLE "compatible"
101 #define OBP_PROP_STATUS "status"
102 #define OBP_PROP_BANNER_NAME "banner-name"
103 #define OBP_PROP_MODEL "model"
104 #define OBP_PROP_66MHZ_CAPABLE "66mhz-capable"
105 #define OBP_PROP_FBC_REG_ID "fbc_reg_id"
106 #define OBP_PROP_VERSION "version"
107
108 #define PROP_POWERFAIL_TIME "powerfail-time"
109 #define PICL_PROP_LOW_WARNING_THRESHOLD "LowWarningThreshold"
110
111 #define DEFAULT_LINE_WIDTH 85
112 #define HEADING_SYMBOL "="
113
114 #define MAX_IWAYS 32
115
116 typedef struct bank_list {
117 picl_nodehdl_t nodeh;
118 uint32_t iway_count;
119 uint32_t iway[MAX_IWAYS];
120 struct bank_list *next;
121 } bank_list_t;
122
123 typedef struct {
124 uint64_t base;
125 uint64_t size;
126 int ifactor;
127 int bank_count;
128 } seg_info_t;
129
130 static struct io_card *io_card_list = NULL; /* The head of the IO card list */
131 static bank_list_t *mem_banks = NULL;
132 static int mem_xfersize;
133 static int no_xfer_size = 0;
134
135 static char *io_device_table[] = {
136 "block",
137 "disk",
138 "cdrom",
139 "floppy",
140 "tape",
141 "network",
142 "display",
143 "serial",
144 "parallel",
145 "scsi",
146 "scsi-2",
147 "scsi-3",
148 "ide",
149 "fcal",
150 "keyboard",
151 "mouse",
152 "dma"
153 };
154
155 #define NIODEVICE sizeof (io_device_table) / sizeof (io_device_table[0])
156
157 static char *bus_table[] = {
158 "ebus",
159 "isa",
160 "pmu"
161 };
162
163 #define NBUS sizeof (bus_table) / sizeof (bus_table[0])
164
165 /* prtdiag exit codes */
166 #define PD_SUCCESS 0
167 #define PD_SYSTEM_FAILURE 1
168 #define PD_INTERNAL_FAILURE 2
169
170 /*
171 * Use of global assumes do_prominfo only called from main in prtdiag and
172 * access does not need to be multi-thread safe.
173 */
174 static int exit_code = PD_SUCCESS;
175
176 /*
177 * This function is called from every location where a status value is output.
178 * It checks the status arg and sets exit_code if an error is detected.
179 * The status is typically returned from a PICL query. A case-insensitive
180 * string comparison is done to check for any status that starts with "fail"
181 * or "fault".
182 */
183 static void
set_exit_code(char * status)184 set_exit_code(char *status)
185 {
186 if (status == NULL)
187 return;
188
189 if (strncasecmp(status, "fail", 4) == 0 ||
190 strncasecmp(status, "fault", 5) == 0)
191 exit_code = PD_SYSTEM_FAILURE;
192 }
193
194 /*
195 * check if it is an IO deice
196 */
197 static int
is_io_device(char * device_class)198 is_io_device(char *device_class)
199 {
200 int i;
201
202 for (i = 0; i < NIODEVICE; i++) {
203 if (strcmp(device_class, io_device_table[i]) == 0)
204 return (1);
205 }
206
207 return (0);
208 }
209
210 /*
211 * check if it is a bus
212 */
213 static int
is_bus(char * device_class)214 is_bus(char *device_class)
215 {
216 int i;
217
218 for (i = 0; i < NBUS; i++) {
219 if (strcmp(device_class, bus_table[i]) == 0)
220 return (1);
221 }
222
223 return (0);
224 }
225
226 /*
227 * search children to get the node by the nodename
228 */
229 static int
picldiag_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)230 picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
231 picl_nodehdl_t *nodeh)
232 {
233 picl_nodehdl_t childh;
234 int err;
235 char *nodename;
236
237 nodename = alloca(strlen(name) + 1);
238 if (nodename == NULL)
239 return (PICL_FAILURE);
240
241 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
242 sizeof (picl_nodehdl_t));
243
244 while (err == PICL_SUCCESS) {
245 err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
246 nodename, (strlen(name) + 1));
247 if (err != PICL_SUCCESS) {
248 err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
249 &childh, sizeof (picl_nodehdl_t));
250 continue;
251 }
252
253 if (strcmp(nodename, name) == 0) {
254 *nodeh = childh;
255 return (PICL_SUCCESS);
256 }
257
258 err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
259 &childh, sizeof (picl_nodehdl_t));
260 }
261
262 return (err);
263 }
264
265 /*
266 * get the value by the property name of the string prop
267 * Caller must free the outbuf
268 */
269 static int
picldiag_get_string_propval(picl_nodehdl_t modh,char * prop_name,char ** outbuf)270 picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
271 {
272 int err;
273 picl_prophdl_t proph;
274 picl_propinfo_t pinfo;
275 char *prop_value;
276
277 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
278 if (err != PICL_SUCCESS)
279 return (err);
280
281 /*
282 * If it is not a string prop, return NULL
283 */
284 if (pinfo.type != PICL_PTYPE_CHARSTRING)
285 return (PICL_FAILURE);
286
287 prop_value = malloc(pinfo.size);
288 if (prop_value == NULL)
289 return (PICL_FAILURE);
290
291 err = picl_get_propval(proph, prop_value, pinfo.size);
292 if (err != PICL_SUCCESS) {
293 free(prop_value);
294 return (err);
295 }
296
297 *outbuf = prop_value;
298 return (PICL_SUCCESS);
299 }
300
301
302 /*
303 * return the value as a signed integer
304 */
305
306 static int64_t
picldiag_get_int_propval(picl_nodehdl_t modh,char * prop_name,int * ret)307 picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
308 {
309 int err;
310 picl_prophdl_t proph;
311 picl_propinfo_t pinfo;
312 int8_t int8v;
313 int16_t int16v;
314 int32_t int32v;
315 int64_t int64v;
316
317 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
318 if (err != PICL_SUCCESS) {
319 *ret = err;
320 return (0);
321 }
322
323 /*
324 * If it is not an int or uint prop, return failure
325 */
326 if ((pinfo.type != PICL_PTYPE_INT) &&
327 (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
328 *ret = PICL_FAILURE;
329 return (0);
330 }
331
332 switch (pinfo.size) {
333 case sizeof (int8_t):
334 err = picl_get_propval(proph, &int8v, sizeof (int8v));
335 *ret = err;
336 return (int8v);
337 case sizeof (int16_t):
338 err = picl_get_propval(proph, &int16v, sizeof (int16v));
339 *ret = err;
340 return (int16v);
341 case sizeof (int32_t):
342 err = picl_get_propval(proph, &int32v, sizeof (int32v));
343 *ret = err;
344 return (int32v);
345 case sizeof (int64_t):
346 err = picl_get_propval(proph, &int64v, sizeof (int64v));
347 *ret = err;
348 return (int64v);
349 default: /* not supported size */
350 *ret = PICL_FAILURE;
351 return (0);
352 }
353 }
354
355 /*
356 * return the value of the uint prop
357 */
358 static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)359 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
360 {
361 int err;
362 picl_prophdl_t proph;
363 picl_propinfo_t pinfo;
364 uint8_t uint8v;
365 uint16_t uint16v;
366 uint32_t uint32v;
367 uint64_t uint64v;
368
369 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
370 if (err != PICL_SUCCESS) {
371 *ret = err;
372 return (0);
373 }
374
375 /*
376 * If it is not an int or uint prop, return failure
377 */
378 if ((pinfo.type != PICL_PTYPE_INT) &&
379 (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
380 *ret = PICL_FAILURE;
381 return (0);
382 }
383
384 /* uint prop */
385
386 switch (pinfo.size) {
387 case sizeof (uint8_t):
388 err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
389 *ret = err;
390 return (uint8v);
391 case sizeof (uint16_t):
392 err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
393 *ret = err;
394 return (uint16v);
395 case sizeof (uint32_t):
396 err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
397 *ret = err;
398 return (uint32v);
399 case sizeof (uint64_t):
400 err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
401 *ret = err;
402 return (uint64v);
403 default: /* not supported size */
404 *ret = PICL_FAILURE;
405 return (0);
406 }
407 }
408
409 /*
410 * return the value of the float prop
411 */
412 static float
picldiag_get_float_propval(picl_nodehdl_t modh,char * prop_name,int * ret)413 picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
414 {
415 int err;
416 picl_prophdl_t proph;
417 picl_propinfo_t pinfo;
418 float floatv;
419
420 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
421 if (err != PICL_SUCCESS) {
422 *ret = err;
423 return ((float)0);
424 }
425
426 /*
427 * If it is not a float prop, return failure
428 */
429 if (pinfo.type != PICL_PTYPE_FLOAT) {
430 *ret = PICL_FAILURE;
431 return ((float)0);
432 }
433
434 *ret = picl_get_propval(proph, &floatv, sizeof (floatv));
435 return (floatv);
436 }
437
438 /*
439 * get the clock frequency
440 */
441 static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq)442 picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
443 {
444 #define ROUND_TO_MHZ(x) (((x) + 500000)/ 1000000)
445 int err;
446 uint64_t clk_freq;
447
448 clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
449 if (err != PICL_SUCCESS)
450 return (err);
451
452 *freq = ROUND_TO_MHZ(clk_freq);
453
454 return (PICL_SUCCESS);
455 }
456
457 /*
458 * get the clock frequency from parent
459 */
460 static int
picldiag_get_clock_from_parent(picl_nodehdl_t nodeh,uint32_t * clk)461 picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk)
462 {
463 picl_nodehdl_t parenth;
464 int err;
465
466
467 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
468 &parenth, sizeof (parenth));
469
470 while (err == PICL_SUCCESS) {
471 err = picldiag_get_clock_freq(parenth, clk);
472 if (err != PICL_PROPNOTFOUND)
473 return (err);
474
475 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
476 &parenth, sizeof (parenth));
477 }
478
479 return (err);
480 }
481
482 /*
483 * get _fru_parent prop
484 * If not found, then travese superiors (parent nodes) until
485 * a _fru_parent property is found.
486 * If not found, no fru parent
487 */
488 static int
picldiag_get_fru_parent(picl_nodehdl_t nodeh,picl_nodehdl_t * fruparenth)489 picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth)
490 {
491 picl_nodehdl_t fruh;
492 int err;
493
494 /* find fru parent */
495 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
496 &fruh, sizeof (fruh));
497
498 if (err != PICL_SUCCESS)
499 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT,
500 &fruh, sizeof (fruh));
501
502 while (err == PICL_PROPNOTFOUND) {
503 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
504 &nodeh, sizeof (nodeh));
505 if (err != PICL_SUCCESS)
506 return (err);
507
508 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
509 &fruh, sizeof (fruh));
510 if (err != PICL_SUCCESS)
511 err = picl_get_propval_by_name(nodeh,
512 PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh));
513 }
514
515 if (err == PICL_SUCCESS)
516 *fruparenth = fruh;
517
518 return (err);
519 }
520
521 /*
522 * get label
523 *
524 * To get the label, use the following algorithm:
525 * Lookup "Label" property in the fru node itself. If no
526 * Label found, then traverse superiors (parent nodes) until
527 * a Label property is found.
528 * if not found, then no label
529 */
530 static int
picldiag_get_label(picl_nodehdl_t nodeh,char ** label)531 picldiag_get_label(picl_nodehdl_t nodeh, char **label)
532 {
533 int err;
534
535 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label);
536
537 while (err == PICL_PROPNOTFOUND) {
538 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
539 &nodeh, sizeof (nodeh));
540 if (err != PICL_SUCCESS)
541 return (err);
542
543 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL,
544 label);
545 }
546
547 return (err);
548 }
549
550 /*
551 * get combined label
552 *
553 * like picldiag_get_label, except concatenates the labels of parent locations
554 * eg SB0/P3 for processor P3 on system board SB0
555 *
556 * if caller specifies non-zero label length, label will be cut to specified
557 * length.
558 * negative length is left justified, non-negative length is right justified
559 */
560 static int
picldiag_get_combined_label(picl_nodehdl_t nodeh,char ** label,int lablen)561 picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen)
562 {
563 int err;
564 char *ptr;
565 char *ptr1 = NULL;
566 char *ptr2;
567 int len;
568
569 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1);
570 if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS)
571 return (err);
572
573 for (;;) {
574 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
575 &nodeh, sizeof (nodeh));
576 if (err == PICL_PROPNOTFOUND)
577 break;
578 if (err != PICL_SUCCESS)
579 return (err);
580
581 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr);
582 if (err == PICL_SUCCESS) {
583 if (ptr1 == NULL) {
584 ptr1 = ptr;
585 } else {
586 ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2);
587 if (ptr2 == NULL)
588 return (PICL_FAILURE);
589 (void) strcpy(ptr2, ptr);
590 (void) strcat(ptr2, "/");
591 (void) strcat(ptr2, ptr1);
592 (void) free(ptr);
593 (void) free(ptr1);
594 ptr1 = ptr2;
595 }
596 } else if (err != PICL_PROPNOTFOUND) {
597 return (err);
598 }
599 }
600
601 if (ptr1 == NULL)
602 return (PICL_PROPNOTFOUND);
603
604 len = strlen(ptr1);
605 /* if no string truncation is desired or required */
606 if ((lablen == 0) || (len <= abs(lablen))) {
607 *label = ptr1;
608 return (PICL_SUCCESS);
609 }
610
611 /* string truncation is required; alloc space for (lablen + \0) */
612 ptr = malloc(abs(lablen) + 1);
613 if (ptr == 0)
614 return (PICL_FAILURE);
615 if (lablen > 0) {
616 /* right justification; label = "+<string>\0" */
617 strcpy(ptr, "+");
618 strncat(ptr, ptr1 + len - lablen + 1, lablen + 1);
619 } else {
620 /* left justification; label = "<string>+\0" */
621 strncpy(ptr, ptr1, abs(lablen) - 1);
622 strcat(ptr, "+");
623 }
624
625 *label = ptr;
626 return (PICL_SUCCESS);
627 }
628
629 /*
630 * return the first compatible value
631 */
632 static int
picldiag_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)633 picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
634 {
635 int err;
636 picl_prophdl_t proph;
637 picl_propinfo_t pinfo;
638 picl_prophdl_t tblh;
639 picl_prophdl_t rowproph;
640 char *pval;
641
642 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
643 &pinfo, &proph);
644 if (err != PICL_SUCCESS)
645 return (err);
646
647 if (pinfo.type == PICL_PTYPE_CHARSTRING) {
648 pval = malloc(pinfo.size);
649 if (pval == NULL)
650 return (PICL_FAILURE);
651 err = picl_get_propval(proph, pval, pinfo.size);
652 if (err != PICL_SUCCESS) {
653 free(pval);
654 return (err);
655 }
656 *outbuf = pval;
657 return (PICL_SUCCESS);
658 }
659
660 if (pinfo.type != PICL_PTYPE_TABLE)
661 return (PICL_FAILURE);
662
663 /* get first string from table */
664 err = picl_get_propval(proph, &tblh, pinfo.size);
665 if (err != PICL_SUCCESS)
666 return (err);
667
668 err = picl_get_next_by_row(tblh, &rowproph);
669 if (err != PICL_SUCCESS)
670 return (err);
671
672 err = picl_get_propinfo(rowproph, &pinfo);
673 if (err != PICL_SUCCESS)
674 return (err);
675
676 pval = malloc(pinfo.size);
677 if (pval == NULL)
678 return (PICL_FAILURE);
679
680 err = picl_get_propval(rowproph, pval, pinfo.size);
681 if (err != PICL_SUCCESS) {
682 free(pval);
683 return (err);
684 }
685
686 *outbuf = pval;
687 return (PICL_SUCCESS);
688 }
689
690 /*
691 * print the header in the center
692 */
693 static void
logprintf_header(char * header,size_t line_width)694 logprintf_header(char *header, size_t line_width)
695 {
696 size_t start_pos;
697 size_t i;
698
699 log_printf("\n");
700 start_pos = (line_width - strlen(header) - 2) / 2;
701
702 for (i = 0; i < start_pos; i++)
703 log_printf("%s", HEADING_SYMBOL);
704
705 log_printf(" %s ", header);
706
707 for (i = 0; i < start_pos; i++)
708 log_printf("%s", HEADING_SYMBOL);
709
710 log_printf("\n");
711 }
712
713 /*
714 * print the size
715 */
716 static void
logprintf_size(uint64_t size)717 logprintf_size(uint64_t size)
718 {
719 #define SIZE_FIELD 11
720
721 uint64_t kbyte = 1024;
722 uint64_t mbyte = 1024 * 1024;
723 uint64_t gbyte = 1024 * 1024 * 1024;
724 uint64_t residue;
725 char buf[SIZE_FIELD];
726
727 if (size >= gbyte) {
728 residue = size % gbyte;
729 if (residue == 0)
730 snprintf(buf, sizeof (buf), "%dGB",
731 (int)(size / gbyte));
732 else
733 snprintf(buf, sizeof (buf), "%.2fGB",
734 (float)size / gbyte);
735 } else if (size >= mbyte) {
736 residue = size % mbyte;
737 if (residue == 0)
738 snprintf(buf, sizeof (buf), "%dMB",
739 (int)(size / mbyte));
740 else
741 snprintf(buf, sizeof (buf), "%.2fMB",
742 (float)size / mbyte);
743 } else {
744 residue = size % kbyte;
745 if (residue == 0)
746 snprintf(buf, sizeof (buf), "%dKB",
747 (int)(size / kbyte));
748 else
749 snprintf(buf, sizeof (buf), "%.2fKB",
750 (float)size / kbyte);
751 }
752
753 log_printf("%-10s ", buf);
754 }
755
756 /*
757 * display platform banner
758 */
759 static int
display_platform_banner(picl_nodehdl_t plafh)760 display_platform_banner(picl_nodehdl_t plafh)
761 {
762 char *platform;
763 char *banner_name;
764 int err;
765
766 /*
767 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
768 */
769 log_printf(SIGN_ON_MSG);
770 err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
771 &platform);
772 if (err != PICL_SUCCESS)
773 return (err);
774 log_printf(" %s", platform);
775 free(platform);
776
777 err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
778 &banner_name);
779 if (err != PICL_SUCCESS)
780 return (err);
781 log_printf(" %s", banner_name);
782 free(banner_name);
783
784 log_printf("\n");
785 return (PICL_SUCCESS);
786 }
787
788 /*
789 * display the clock frequency
790 */
791 static int
display_system_clock(picl_nodehdl_t plafh)792 display_system_clock(picl_nodehdl_t plafh)
793 {
794 uint32_t system_clk;
795 int err;
796
797 err = picldiag_get_clock_freq(plafh, &system_clk);
798 if (err != PICL_SUCCESS)
799 return (err);
800
801 log_printf(SYSCLK_FREQ_MSG, system_clk);
802
803 return (PICL_SUCCESS);
804 }
805
806 /*
807 * callback function to display the memory size
808 */
809 /*ARGSUSED*/
810 static int
memory_callback(picl_nodehdl_t memh,void * args)811 memory_callback(picl_nodehdl_t memh, void *args)
812 {
813 uint64_t mem_size;
814 int err;
815
816 log_printf(MEM_SIZE_MSG);
817 mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err);
818 if (err == PICL_SUCCESS)
819 logprintf_size(mem_size);
820 log_printf("\n");
821 no_xfer_size = 0;
822 mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE,
823 &err);
824 if (err == PICL_PROPNOTFOUND)
825 no_xfer_size = 1;
826 return (PICL_WALK_TERMINATE);
827 }
828
829 /*
830 * callback function to print cpu information
831 */
832 /*ARGSUSED*/
833 static int
cpu_callback(picl_nodehdl_t nodeh,void * args)834 cpu_callback(picl_nodehdl_t nodeh, void *args)
835 {
836 int err;
837 int id0, id1;
838 uint64_t uintval;
839 uint64_t decoded_mask;
840 uint32_t freq;
841 char *impl_name;
842 char *status;
843 picl_prophdl_t parenth;
844 picl_prophdl_t peerh;
845 char *label;
846 int is_cmp = 0;
847 int is_cheetah = 0;
848
849 /*
850 * first check the implementation. If it's a CMP
851 * we need to combine info from both cores.
852 */
853
854 impl_name = NULL;
855 uintval = picldiag_get_uint_propval(nodeh,
856 OBP_PROP_IMPLEMENTATION, &err);
857 if (err == PICL_SUCCESS) {
858 if (CPU_IMPL_IS_CMP(uintval)) {
859 is_cmp = 1;
860 err = picldiag_get_first_compatible_value(nodeh,
861 &impl_name);
862 if (err != PICL_SUCCESS)
863 impl_name = NULL;
864 } else if (IS_CHEETAH(uintval) || IS_CHEETAH_PLUS(uintval)) {
865 is_cheetah = 1;
866 err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME,
867 &impl_name);
868 if (err != PICL_SUCCESS)
869 impl_name = NULL;
870 }
871 } else {
872 err = picldiag_get_string_propval(nodeh,
873 PICL_PROP_NAME, &impl_name);
874 if (err != PICL_SUCCESS)
875 impl_name = NULL;
876 }
877
878 /*
879 * In the CMP case, combine info from both cores. If we
880 * are being called with the first core handle, we display
881 * info on the sibling core handle too. If we are being
882 * called with the second core hanlde as an argument, simply
883 * return.
884 */
885
886 if (is_cmp) {
887 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
888 &peerh, sizeof (picl_nodehdl_t));
889 if (err != PICL_SUCCESS)
890 return (PICL_WALK_CONTINUE);
891 id1 = picldiag_get_uint_propval(peerh, PICL_PROP_ID, &err);
892 if (err == PICL_PROPNOTFOUND)
893 return (PICL_WALK_CONTINUE);
894 else if (err != PICL_SUCCESS)
895 return (err);
896 }
897
898 /*
899 * If no ID is found, return
900 */
901 id0 = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err);
902 if (err == PICL_PROPNOTFOUND)
903 return (PICL_WALK_CONTINUE);
904 else if (err != PICL_SUCCESS)
905 return (err);
906 if (is_cmp) {
907 log_printf("%3d,%3d ", id0, id1);
908 } else {
909 log_printf("%7d ", id0);
910 }
911
912 /*
913 * If no freq is found, return
914 */
915 err = picldiag_get_clock_freq(nodeh, &freq);
916 if (err == PICL_PROPNOTFOUND)
917 return (PICL_WALK_CONTINUE);
918 else if (err != PICL_SUCCESS)
919 return (err);
920 log_printf("%4d MHz ", freq);
921
922 /* Ecache size */
923
924 if (is_cmp) {
925 uintval = picldiag_get_uint_propval(nodeh,
926 OBP_PROP_L3_CACHE_SIZE, &err);
927 if (err == PICL_SUCCESS) {
928 /*
929 * Panther L3 is logically shared, so the total E$
930 * size is equal to the core size.
931 */
932 logprintf_size(uintval);
933 } else {
934 uintval = picldiag_get_uint_propval(nodeh,
935 OBP_PROP_L2_CACHE_SIZE, &err);
936 if (err == PICL_SUCCESS) {
937 /*
938 * Jaguar has a split E$, so the total size
939 * is the sum of both cores.
940 */
941 logprintf_size(uintval * 2);
942 } else
943 log_printf(" - ");
944 }
945 } else {
946 uintval = picldiag_get_uint_propval(nodeh,
947 OBP_PROP_ECACHE_SIZE, &err);
948 if (err == PICL_SUCCESS)
949 logprintf_size(uintval);
950 else
951 log_printf(" - ");
952 }
953
954 /* Implementation */
955 if (impl_name != NULL)
956 log_printf(" %-20s ", impl_name);
957 else
958 log_printf(" <unknown> ");
959
960 /* CPU Mask */
961 uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err);
962 if (err == PICL_PROPNOTFOUND)
963 log_printf(" - ");
964 else if (err == PICL_SUCCESS) {
965 if (is_cheetah) {
966 decoded_mask = REMAP_CHEETAH_MASK(uintval);
967 } else {
968 decoded_mask = uintval;
969 }
970 log_printf("%2lld.%-2lld ", (decoded_mask >> 4) & 0xf,
971 decoded_mask & 0xf);
972 } else
973 return (err);
974
975 /*
976 * Status - if the node has a status property then display that
977 * otherwise display the State property
978 */
979 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status);
980 if (err == PICL_SUCCESS) {
981 log_printf("%-12s", status);
982 set_exit_code(status);
983 free(status);
984 } else if (err != PICL_PROPNOTFOUND && err !=
985 PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) {
986 return (err);
987 } else {
988 err = picldiag_get_string_propval(nodeh,
989 PICL_PROP_STATE, &status);
990 if (err == PICL_SUCCESS) {
991 log_printf("%-12s", status);
992 set_exit_code(status);
993 free(status);
994 } else if (err != PICL_PROPNOTFOUND && err !=
995 PICL_PROPVALUNAVAILABLE && err !=
996 PICL_ENDOFLIST) {
997 return (err);
998 } else {
999 log_printf("unknown ");
1000 }
1001 }
1002
1003 /*
1004 * Location: use label of fru parent
1005 */
1006 err = picldiag_get_fru_parent(nodeh, &parenth);
1007 if (err == PICL_PROPNOTFOUND) {
1008 log_printf(" - ");
1009 } else if (err == PICL_SUCCESS) {
1010 err = picldiag_get_combined_label(parenth, &label, 12);
1011 if (err == PICL_PROPNOTFOUND)
1012 log_printf(" - ");
1013 else if (err == PICL_SUCCESS) {
1014 log_printf("%s", label);
1015 free(label);
1016 } else
1017 return (err);
1018 } else
1019 return (err);
1020
1021 log_printf("\n");
1022 return (PICL_WALK_CONTINUE);
1023 }
1024
1025 /*
1026 * display cpu information
1027 */
1028 static int
display_cpu_info(picl_nodehdl_t plafh)1029 display_cpu_info(picl_nodehdl_t plafh)
1030 {
1031 int err;
1032
1033 /*
1034 * Display the table header for CPUs . Then display the CPU
1035 * frequency, cache size, and processor revision on all the boards.
1036 */
1037 logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH);
1038 log_printf(" E$ CPU "
1039 "CPU\n");
1040 log_printf("CPU Freq Size Implementation "
1041 "Mask Status Location\n");
1042 log_printf("------- -------- ---------- ------------------- "
1043 "----- ------ --------\n");
1044
1045 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
1046 cpu_callback);
1047 return (err);
1048 }
1049
1050 /*
1051 * Inserts an io_card structure into the list.
1052 */
1053 static void
add_io_card(uint32_t board,uint32_t bus_id,uint32_t slot,char * label,uint32_t freq,char * name,char * model,char * status,char * devfs_path)1054 add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label,
1055 uint32_t freq, char *name, char *model, char *status, char *devfs_path)
1056 {
1057 struct io_card card;
1058
1059 card.display = 1;
1060 card.board = board;
1061 switch (bus_id) {
1062 case SBUS_TYPE:
1063 strlcpy(card.bus_type, SBUS_NAME, MAXSTRLEN);
1064 break;
1065 case PCI_TYPE:
1066 strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN);
1067 break;
1068 case UPA_TYPE:
1069 strlcpy(card.bus_type, UPA_NAME, MAXSTRLEN);
1070 break;
1071 default: /* won't reach here */
1072 strlcpy(card.bus_type, "", MAXSTRLEN);
1073 break;
1074 }
1075 if (label == NULL)
1076 card.slot = slot;
1077 else {
1078 card.slot = PCI_SLOT_IS_STRING;
1079 (void) strlcpy(card.slot_str, label, MAXSTRLEN);
1080 }
1081 card.freq = freq;
1082 card.status[0] = '\0';
1083 card.name[0] = '\0';
1084 card.model[0] = '\0';
1085 card.notes[0] = '\0';
1086 if (status != NULL)
1087 strlcpy(card.status, status, MAXSTRLEN);
1088 if (name != NULL)
1089 strlcpy(card.name, name, MAXSTRLEN);
1090 if (model != NULL)
1091 strlcpy(card.model, model, MAXSTRLEN);
1092 if (status != NULL)
1093 strlcpy(card.status, status, MAXSTRLEN);
1094 if (devfs_path != NULL)
1095 strlcpy(card.notes, devfs_path, MAXSTRLEN);
1096
1097 io_card_list = insert_io_card(io_card_list, &card);
1098 }
1099
1100 static void
append_to_bank_list(bank_list_t * newptr)1101 append_to_bank_list(bank_list_t *newptr)
1102 {
1103 bank_list_t *ptr;
1104
1105 if (mem_banks == NULL) {
1106 mem_banks = newptr;
1107 return;
1108 }
1109 ptr = mem_banks;
1110 while (ptr->next != NULL)
1111 ptr = ptr->next;
1112
1113 ptr->next = newptr;
1114 }
1115
1116 static void
free_bank_list(void)1117 free_bank_list(void)
1118 {
1119 bank_list_t *ptr;
1120 bank_list_t *tmp;
1121
1122 for (ptr = mem_banks; ptr != NULL; ptr = tmp) {
1123 tmp = ptr->next;
1124 free(ptr);
1125 }
1126 mem_banks = NULL;
1127 }
1128
1129
1130 /*
1131 * print label for memory module
1132 */
1133 static int
logprintf_memory_module_label(picl_nodehdl_t moduleh)1134 logprintf_memory_module_label(picl_nodehdl_t moduleh)
1135 {
1136 picl_nodehdl_t fruparenth;
1137 int err;
1138 char *label;
1139
1140 err = picldiag_get_fru_parent(moduleh, &fruparenth);
1141 if (err == PICL_PROPNOTFOUND) {
1142 log_printf("-");
1143 return (PICL_SUCCESS);
1144 } else if (err != PICL_SUCCESS)
1145 return (err);
1146
1147 err = picldiag_get_combined_label(fruparenth, &label, 30);
1148 if (err == PICL_PROPNOTFOUND)
1149 log_printf("-");
1150 else if (err == PICL_SUCCESS) {
1151 log_printf("%-15s", label);
1152 free(label);
1153 } else
1154 return (err);
1155
1156 return (PICL_SUCCESS);
1157 }
1158
1159 /*
1160 * print the bank id and add the bank handle in the bank list
1161 * return the head of the bank list
1162 */
1163 static int
membank_callback(picl_nodehdl_t bankh,void * args)1164 membank_callback(picl_nodehdl_t bankh, void *args)
1165 {
1166 int err;
1167 int64_t id;
1168 uint64_t match;
1169 uint64_t mask;
1170 int i;
1171 bank_list_t *newptr;
1172 seg_info_t *segp = args;
1173
1174 /*
1175 * print the bank id in the segment table contains column
1176 */
1177 id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
1178 if (segp->bank_count > 0)
1179 log_printf(",");
1180 if (err == PICL_PROPNOTFOUND)
1181 log_printf("-");
1182 else if (err == PICL_SUCCESS)
1183 log_printf("%-lld", id);
1184 else
1185 return (err);
1186 segp->bank_count++;
1187
1188 /*
1189 * Save the bank information for later (print_bank_table)
1190 */
1191 newptr = malloc(sizeof (*newptr));
1192 if (newptr == NULL)
1193 return (PICL_FAILURE);
1194
1195 newptr->nodeh = bankh;
1196 newptr->iway_count = 0;
1197 newptr->next = NULL;
1198 append_to_bank_list(newptr);
1199
1200 /*
1201 * Compute the way numbers for the bank
1202 */
1203 if (no_xfer_size)
1204 return (PICL_WALK_CONTINUE);
1205
1206 match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err);
1207 if (err == PICL_PROPNOTFOUND)
1208 return (PICL_WALK_CONTINUE);
1209 else if (err != PICL_SUCCESS)
1210 return (err);
1211
1212 mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err);
1213 if (err == PICL_PROPNOTFOUND)
1214 return (PICL_WALK_CONTINUE);
1215 else if (err != PICL_SUCCESS)
1216 return (err);
1217
1218 i = 0;
1219 while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) {
1220 if (((segp->base + i * mem_xfersize) & mask) == match)
1221 newptr->iway[newptr->iway_count++] = i;
1222 ++i;
1223 }
1224 return (PICL_WALK_CONTINUE);
1225 }
1226
1227
1228 /*
1229 * find the memory bank and add the bank handle in the bank list
1230 * return the head of the bank list
1231 */
1232 static int
logprintf_bankinfo(picl_nodehdl_t segh,seg_info_t * segp)1233 logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp)
1234 {
1235 int err;
1236
1237 log_printf("BankIDs ");
1238 /*
1239 * find memory-bank
1240 */
1241 segp->bank_count = 0;
1242 err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp,
1243 membank_callback);
1244 log_printf("\n");
1245 return (err);
1246 }
1247
1248 /*
1249 * print the label of memory module or the memory module bank ids
1250 */
1251 static int
logprintf_seg_contains_col(picl_nodehdl_t nodeh,seg_info_t * segp)1252 logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp)
1253 {
1254 picl_nodehdl_t moduleh;
1255 int err;
1256
1257 /*
1258 * find memory-module if referenced directly from the memory-segment
1259 * (ie no memory banks)
1260 */
1261 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE,
1262 &moduleh, sizeof (moduleh));
1263 if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
1264 return (err);
1265 if (err == PICL_SUCCESS) {
1266 err = logprintf_memory_module_label(moduleh);
1267 log_printf("\n");
1268 return (err);
1269 }
1270
1271 /*
1272 * memory-module not referenced directly from the memory segment
1273 * so list memory banks instead
1274 */
1275 err = logprintf_bankinfo(nodeh, segp);
1276 return (err);
1277 }
1278
1279 /*
1280 * find all memory modules under the given memory module group
1281 * and print its label
1282 */
1283 static int
logprintf_memory_module_group_info(picl_nodehdl_t memgrph,uint64_t mcid)1284 logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid)
1285 {
1286 int err;
1287 int64_t id;
1288 picl_nodehdl_t moduleh;
1289 char piclclass[PICL_CLASSNAMELEN_MAX];
1290 picl_nodehdl_t fruparenth;
1291 char *status;
1292
1293 id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err);
1294 if (err == PICL_PROPNOTFOUND)
1295 id = -1;
1296 else if (err != PICL_SUCCESS)
1297 return (err);
1298
1299 err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh,
1300 sizeof (picl_nodehdl_t));
1301
1302 while (err == PICL_SUCCESS) {
1303 /* controller id */
1304 log_printf("%-8lld ", mcid);
1305
1306 /* group id */
1307 if (id == -1) {
1308 log_printf("- ");
1309 } else {
1310 log_printf("%-8lld ", id);
1311 }
1312
1313 err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME,
1314 piclclass, sizeof (piclclass));
1315 if (err != PICL_SUCCESS)
1316 return (err);
1317
1318 if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) {
1319 err = logprintf_memory_module_label(moduleh);
1320 if (err != PICL_SUCCESS)
1321 return (err);
1322 }
1323
1324 err = picldiag_get_fru_parent(moduleh, &fruparenth);
1325 if (err == PICL_SUCCESS) {
1326 err = picldiag_get_string_propval(fruparenth,
1327 PICL_PROP_OPERATIONAL_STATUS, &status);
1328 if (err == PICL_SUCCESS) {
1329 log_printf("%s", status);
1330 set_exit_code(status);
1331 free(status);
1332 } else if (err != PICL_PROPNOTFOUND)
1333 return (err);
1334 } else if (err != PICL_PROPNOTFOUND)
1335 return (err);
1336
1337 err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER,
1338 &moduleh, sizeof (picl_nodehdl_t));
1339
1340 log_printf("\n");
1341 }
1342 if (err == PICL_PROPNOTFOUND)
1343 return (PICL_SUCCESS);
1344 return (err);
1345 }
1346
1347 /*
1348 * search children to find memory module group under memory-controller
1349 */
1350 static int
find_memory_module_group(picl_nodehdl_t mch,int * print_header)1351 find_memory_module_group(picl_nodehdl_t mch, int *print_header)
1352 {
1353 picl_nodehdl_t memgrph;
1354 uint64_t mcid;
1355 int err;
1356 char piclclass[PICL_CLASSNAMELEN_MAX];
1357
1358 mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err);
1359 if (err == PICL_PROPNOTFOUND)
1360 mcid = DEFAULT_PORTID;
1361 else if (err != PICL_SUCCESS)
1362 return (err);
1363
1364 err = picl_get_propval_by_name(mch, PICL_PROP_CHILD,
1365 &memgrph, sizeof (picl_nodehdl_t));
1366 while (err == PICL_SUCCESS) {
1367 err = picl_get_propval_by_name(memgrph,
1368 PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass));
1369 if (err != PICL_SUCCESS)
1370 return (err);
1371
1372 if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) {
1373 if (*print_header == 1) {
1374 log_printf(
1375 dgettext(TEXT_DOMAIN,
1376 "\nMemory Module Groups:\n"));
1377 log_printf("--------------------------");
1378 log_printf("------------------------\n");
1379 log_printf("ControllerID GroupID Labels");
1380 log_printf(" Status\n");
1381 log_printf("--------------------------");
1382 log_printf("------------------------\n");
1383 *print_header = 0;
1384 }
1385 err = logprintf_memory_module_group_info(memgrph, mcid);
1386 if (err != PICL_SUCCESS)
1387 return (err);
1388 }
1389
1390 err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER,
1391 &memgrph, sizeof (picl_nodehdl_t));
1392 }
1393 if (err == PICL_PROPNOTFOUND)
1394 return (PICL_SUCCESS);
1395 return (err);
1396 }
1397
1398 /*
1399 * print memory module group table per memory-controller
1400 */
1401 static int
print_memory_module_group_table(picl_nodehdl_t plafh)1402 print_memory_module_group_table(picl_nodehdl_t plafh)
1403 {
1404 picl_nodehdl_t mch;
1405 int err;
1406 char piclclass[PICL_CLASSNAMELEN_MAX];
1407 int print_header;
1408
1409 print_header = 1;
1410
1411 /*
1412 * find memory-controller
1413 */
1414 err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch,
1415 sizeof (picl_nodehdl_t));
1416 while (err == PICL_SUCCESS) {
1417 err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME,
1418 piclclass, sizeof (piclclass));
1419 if (err != PICL_SUCCESS)
1420 return (err);
1421
1422 if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) {
1423 err = print_memory_module_group_table(mch);
1424 if (err != PICL_SUCCESS)
1425 return (err);
1426 err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
1427 &mch, sizeof (picl_nodehdl_t));
1428 continue;
1429 }
1430
1431 err = find_memory_module_group(mch, &print_header);
1432 if (err != PICL_SUCCESS)
1433 return (err);
1434
1435 err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
1436 &mch, sizeof (picl_nodehdl_t));
1437 }
1438 if (err == PICL_PROPNOTFOUND)
1439 return (PICL_SUCCESS);
1440
1441 return (err);
1442 }
1443
1444 /*
1445 * print bank table
1446 */
1447 static int
print_bank_table(void)1448 print_bank_table(void)
1449 {
1450 bank_list_t *ptr;
1451 picl_nodehdl_t bankh;
1452 picl_nodehdl_t memgrph;
1453 picl_nodehdl_t mch;
1454 int err;
1455 int32_t i;
1456 uint64_t size;
1457 int id;
1458
1459 log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n"));
1460 log_printf("---------------------------------------");
1461 log_printf("--------------------\n");
1462 log_printf(dgettext(TEXT_DOMAIN, " Physical Location\n"));
1463 log_printf(dgettext(TEXT_DOMAIN, "ID ControllerID GroupID "));
1464 log_printf(dgettext(TEXT_DOMAIN, "Size Interleave Way\n"));
1465 log_printf("---------------------------------------");
1466 log_printf("--------------------\n");
1467
1468 for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) {
1469 bankh = ptr->nodeh;
1470 id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
1471 if (err != PICL_SUCCESS)
1472 log_printf("%-8s ", "-");
1473 else
1474 log_printf("%-8d ", id);
1475
1476 /* find memory-module-group */
1477 err = picl_get_propval_by_name(bankh,
1478 PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph,
1479 sizeof (memgrph));
1480 if (err == PICL_PROPNOTFOUND) {
1481 log_printf("%-8s ", "-");
1482 log_printf("%-8s ", "-");
1483 } else if (err != PICL_SUCCESS)
1484 return (err);
1485 else {
1486 /*
1487 * get controller id
1488 */
1489 err = picl_get_propval_by_name(memgrph,
1490 PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t));
1491 if (err != PICL_SUCCESS)
1492 return (err);
1493
1494 id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID,
1495 &err);
1496 if (err == PICL_PROPNOTFOUND)
1497 id = DEFAULT_PORTID; /* use default */
1498 else if (err != PICL_SUCCESS)
1499 return (err);
1500
1501 log_printf("%-8d ", id);
1502
1503 /* get group id */
1504 id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID,
1505 &err);
1506 if (err == PICL_PROPNOTFOUND)
1507 log_printf("- ");
1508 else if (err == PICL_SUCCESS)
1509 log_printf("%-8d ", id);
1510 else
1511 return (err);
1512 }
1513
1514 size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err);
1515 if (err == PICL_PROPNOTFOUND)
1516 log_printf("- ");
1517 else if (err == PICL_SUCCESS)
1518 logprintf_size(size);
1519 else
1520 return (err);
1521
1522 log_printf(" ");
1523 for (i = 0; i < ptr->iway_count; i++) {
1524 if (i != 0)
1525 log_printf(",");
1526 log_printf("%d", ptr->iway[i]);
1527 }
1528
1529 log_printf("\n");
1530 }
1531 return (PICL_SUCCESS);
1532 }
1533
1534 /*
1535 * callback function to print segment, add the bank in the list and
1536 * return the bank list
1537 */
1538 /* ARGSUSED */
1539 static int
memseg_callback(picl_nodehdl_t segh,void * args)1540 memseg_callback(picl_nodehdl_t segh, void *args)
1541 {
1542 seg_info_t seginfo;
1543 int err;
1544
1545 /* get base address */
1546 seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS,
1547 &err);
1548 if (err == PICL_PROPNOTFOUND) {
1549 log_printf("-\n");
1550 return (PICL_WALK_CONTINUE);
1551 } else if (err == PICL_SUCCESS)
1552 log_printf("0x%-16llx ", seginfo.base);
1553 else
1554 return (err);
1555
1556 /* get size */
1557 seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err);
1558 if (err == PICL_PROPNOTFOUND) {
1559 log_printf("-\n");
1560 return (PICL_WALK_CONTINUE);
1561 } else if (err == PICL_SUCCESS)
1562 logprintf_size(seginfo.size);
1563 else
1564 return (err);
1565
1566 /* get interleave factor */
1567 seginfo.ifactor = picldiag_get_uint_propval(segh,
1568 PICL_PROP_INTERLEAVE_FACTOR, &err);
1569
1570 if (err == PICL_PROPNOTFOUND) {
1571 log_printf(" -\n");
1572 return (PICL_WALK_CONTINUE);
1573 } else if (err == PICL_SUCCESS)
1574 log_printf(" %-2d ", seginfo.ifactor);
1575 else
1576 return (err);
1577
1578 seginfo.bank_count = 0;
1579 err = logprintf_seg_contains_col(segh, &seginfo);
1580 if (err != PICL_SUCCESS)
1581 return (err);
1582 return (PICL_WALK_CONTINUE);
1583 }
1584
1585 /*
1586 * search children to find memory-segment and set up the bank list
1587 */
1588 static int
find_segments(picl_nodehdl_t plafh)1589 find_segments(picl_nodehdl_t plafh)
1590 {
1591 int err;
1592
1593 log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n"));
1594 log_printf("------------------------------");
1595 log_printf("-----------------------------------------\n");
1596 log_printf(dgettext(TEXT_DOMAIN, "Base Address Size "));
1597 log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor Contains\n"));
1598 log_printf("------------------------------");
1599 log_printf("-----------------------------------------\n");
1600
1601 err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
1602 NULL, memseg_callback);
1603 return (err);
1604 }
1605
1606 /*
1607 * display memory configuration
1608 */
1609 static int
display_memory_config(picl_nodehdl_t plafh)1610 display_memory_config(picl_nodehdl_t plafh)
1611 {
1612 int err;
1613
1614 logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"),
1615 DEFAULT_LINE_WIDTH);
1616
1617 mem_banks = NULL;
1618 err = find_segments(plafh);
1619
1620 if ((err == PICL_SUCCESS) && (mem_banks != NULL))
1621 print_bank_table();
1622
1623 free_bank_list();
1624
1625 return (print_memory_module_group_table(plafh));
1626 }
1627
1628 /*
1629 * print the hub device
1630 */
1631 static int
logprintf_hub_devices(picl_nodehdl_t hubh)1632 logprintf_hub_devices(picl_nodehdl_t hubh)
1633 {
1634 char *name;
1635 int portnum;
1636 int err;
1637
1638 err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name);
1639 if (err != PICL_SUCCESS)
1640 return (err);
1641 log_printf("%-12.12s ", name);
1642 free(name);
1643
1644 err = picl_get_propval_by_name(hubh, OBP_PROP_REG,
1645 &portnum, sizeof (portnum));
1646 if (err == PICL_PROPNOTFOUND)
1647 log_printf("-\n");
1648 else if (err == PICL_SUCCESS)
1649 log_printf("%3d\n", portnum);
1650 else
1651 return (err);
1652
1653 return (PICL_SUCCESS);
1654 }
1655
1656 /*
1657 * callback functions to display hub devices
1658 */
1659 /* ARGSUSED */
1660 static int
print_usb_devices(picl_nodehdl_t hubh,void * arg)1661 print_usb_devices(picl_nodehdl_t hubh, void *arg)
1662 {
1663 picl_nodehdl_t chdh;
1664 char *rootname;
1665 int type = *(int *)arg;
1666 int hubnum;
1667 int err;
1668
1669 err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh,
1670 sizeof (picl_nodehdl_t));
1671
1672 /* print header */
1673 if (err == PICL_SUCCESS) {
1674 err = picldiag_get_string_propval(hubh, PICL_PROP_NAME,
1675 &rootname);
1676 if (err != PICL_SUCCESS)
1677 return (err);
1678
1679 if (type == USB) {
1680 log_printf("\n===============================");
1681 log_printf(dgettext(TEXT_DOMAIN,
1682 " %s Devices "), rootname);
1683 } else {
1684 /* Get its hub number */
1685 err = picl_get_propval_by_name(hubh,
1686 OBP_PROP_REG, &hubnum, sizeof (hubnum));
1687 if ((err != PICL_SUCCESS) &&
1688 (err != PICL_PROPNOTFOUND)) {
1689 free(rootname);
1690 return (err);
1691 }
1692
1693 log_printf("\n===============================");
1694 if (err == PICL_SUCCESS)
1695 log_printf(dgettext(TEXT_DOMAIN,
1696 " %s#%d Devices "),
1697 rootname, hubnum);
1698 else
1699 log_printf(dgettext(TEXT_DOMAIN,
1700 " %s Devices "), rootname);
1701 }
1702
1703 log_printf("===============================\n\n");
1704 log_printf("Name Port#\n");
1705 log_printf("------------ -----\n");
1706 free(rootname);
1707
1708 do {
1709 logprintf_hub_devices(chdh);
1710
1711 err = picl_get_propval_by_name(chdh, PICL_PROP_PEER,
1712 &chdh, sizeof (picl_nodehdl_t));
1713 } while (err == PICL_SUCCESS);
1714 }
1715
1716
1717 if (err == PICL_PROPNOTFOUND)
1718 return (PICL_WALK_CONTINUE);
1719 return (err);
1720 }
1721
1722 /*
1723 * callback functions to display usb devices
1724 */
1725 /* ARGSUSED */
1726 static int
usb_callback(picl_nodehdl_t usbh,void * args)1727 usb_callback(picl_nodehdl_t usbh, void *args)
1728 {
1729 int err;
1730 int type;
1731
1732 type = USB;
1733 err = print_usb_devices(usbh, &type);
1734 if (err != PICL_WALK_CONTINUE)
1735 return (err);
1736 type = HUB;
1737 err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices);
1738 if (err == PICL_SUCCESS)
1739 err = PICL_WALK_CONTINUE;
1740 return (err);
1741 }
1742
1743
1744 /*
1745 * find usb devices and print its information
1746 */
1747 static int
display_usb_devices(picl_nodehdl_t plafh)1748 display_usb_devices(picl_nodehdl_t plafh)
1749 {
1750 int err;
1751
1752 /*
1753 * get the usb node
1754 */
1755 err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL,
1756 usb_callback);
1757 return (err);
1758 }
1759
1760
1761
1762 /*
1763 * If nodeh is the io device, add it into the io list and return
1764 * If it is not an io device and it has the subtree, traverse the subtree
1765 * and add all leaf io devices
1766 */
1767 static int
add_io_leaves(picl_nodehdl_t nodeh,char * parentname,uint32_t board,uint32_t bus_id,uint64_t slot,uint32_t freq,char * model,char * status)1768 add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board,
1769 uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status)
1770 {
1771 picl_nodehdl_t childh;
1772 picl_prophdl_t proph;
1773 picl_propinfo_t pinfo;
1774 int err;
1775 char *nameval;
1776 char piclclass[PICL_CLASSNAMELEN_MAX];
1777 char nodename[MAXSTRLEN];
1778 char name[MAXSTRLEN];
1779 char *devfs_path;
1780 char *compatible;
1781 picl_nodehdl_t fruparenth;
1782 char *label;
1783 char binding_name[MAXSTRLEN];
1784
1785 err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo,
1786 &proph);
1787 if (err != PICL_SUCCESS)
1788 return (err);
1789
1790 nameval = alloca(pinfo.size);
1791 if (nameval == NULL)
1792 return (PICL_FAILURE);
1793
1794 err = picl_get_propval(proph, nameval, pinfo.size);
1795 if (err != PICL_SUCCESS)
1796 return (err);
1797
1798 (void) strlcpy(nodename, nameval, MAXSTRLEN);
1799
1800 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
1801 piclclass, sizeof (piclclass));
1802 if (err != PICL_SUCCESS)
1803 return (err);
1804
1805 /* if binding_name is found, name will be <nodename>-<binding_name> */
1806 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
1807 binding_name, sizeof (binding_name));
1808 if (err == PICL_PROPNOTFOUND) {
1809 /*
1810 * if compatible prop is found, name will be
1811 * <nodename>-<compatible>
1812 */
1813 err = picldiag_get_first_compatible_value(nodeh, &compatible);
1814 if (err == PICL_SUCCESS) {
1815 strlcat(nodename, "-", MAXSTRLEN);
1816 strlcat(nodename, compatible, MAXSTRLEN);
1817 free(compatible);
1818 } else if (err != PICL_PROPNOTFOUND) {
1819 return (err);
1820 }
1821 } else if (err != PICL_SUCCESS) {
1822 return (err);
1823 } else if (strcmp(nodename, binding_name) != 0) {
1824 if (strcmp(nodename, piclclass) == 0) {
1825 /*
1826 * nodename same as binding name -
1827 * no need to display twice
1828 */
1829 strlcpy(nodename, binding_name, MAXSTRLEN);
1830 } else {
1831 strlcat(nodename, "-", MAXSTRLEN);
1832 strlcat(nodename, binding_name, MAXSTRLEN);
1833 }
1834 }
1835
1836 /*
1837 * If it is an immediate child under pci/sbus/upa and not
1838 * a bus node, add it to the io list.
1839 * If it is a child under sub-bus and it is in an io
1840 * device, add it to the io list.
1841 */
1842 if (((parentname == NULL) && (!is_bus(piclclass))) ||
1843 ((parentname != NULL) && (is_io_device(piclclass)))) {
1844 if (parentname == NULL)
1845 (void) snprintf(name, MAXSTRLEN, "%s", nodename);
1846 else
1847 (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
1848 nodename);
1849
1850 /*
1851 * append the class if its class is not a generic
1852 * obp-device class
1853 */
1854 if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE))
1855 (void) snprintf(name, MAXSTRLEN, "%s (%s)", name,
1856 piclclass);
1857
1858 err = picldiag_get_fru_parent(nodeh, &fruparenth);
1859 if (err == PICL_PROPNOTFOUND) {
1860 label = NULL;
1861 } else if (err != PICL_SUCCESS) {
1862 return (err);
1863 } else {
1864 err = picldiag_get_combined_label(fruparenth, &label,
1865 15);
1866 if (err == PICL_PROPNOTFOUND)
1867 label = NULL;
1868 else if (err != PICL_SUCCESS)
1869 return (err);
1870 }
1871 /* devfs-path */
1872 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
1873 &devfs_path);
1874 if (err == PICL_PROPNOTFOUND)
1875 devfs_path = NULL;
1876 else if (err != PICL_SUCCESS)
1877 return (err);
1878
1879 add_io_card(board, bus_id, slot, label, freq, name,
1880 model, status, devfs_path);
1881 if (label != NULL)
1882 free(label);
1883 if (devfs_path != NULL)
1884 free(devfs_path);
1885 return (PICL_SUCCESS);
1886 }
1887
1888 /*
1889 * If there is any child, Go through each child.
1890 */
1891
1892 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
1893 &childh, sizeof (picl_nodehdl_t));
1894
1895 /* there is a child */
1896 while (err == PICL_SUCCESS) {
1897 if (parentname == NULL)
1898 (void) strlcpy(name, nodename, MAXSTRLEN);
1899 else
1900 (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
1901 nodename);
1902
1903 err = add_io_leaves(childh, name, board, bus_id, slot, freq,
1904 model, status);
1905 if (err != PICL_SUCCESS)
1906 return (err);
1907 /*
1908 * get next child
1909 */
1910 err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
1911 &childh, sizeof (picl_nodehdl_t));
1912 }
1913
1914 if (err == PICL_PROPNOTFOUND)
1915 return (PICL_SUCCESS);
1916 return (err);
1917 }
1918
1919 /*
1920 * callback function to add all io devices under sbus in io list
1921 */
1922 /*ARGSUSED*/
1923 static int
sbus_callback(picl_nodehdl_t sbush,void * args)1924 sbus_callback(picl_nodehdl_t sbush, void *args)
1925 {
1926 picl_nodehdl_t nodeh;
1927 int err;
1928 uint32_t boardnum;
1929 uint32_t bus_id;
1930 uint32_t slot;
1931 uint32_t freq;
1932 char *model;
1933 char *status;
1934
1935 /* Fill in common infomation */
1936 bus_id = SBUS_TYPE;
1937
1938 err = picldiag_get_clock_freq(sbush, &freq);
1939 if (err == PICL_PROPNOTFOUND)
1940 return (PICL_WALK_CONTINUE);
1941 else if (err != PICL_SUCCESS)
1942 return (err);
1943 /*
1944 * If no board# is found, set boardnum to 0
1945 */
1946 boardnum = picldiag_get_uint_propval(sbush, OBP_PROP_BOARD_NUM, &err);
1947 if (err == PICL_PROPNOTFOUND)
1948 boardnum = DEFAULT_BOARD_NUM;
1949 else if (err != PICL_SUCCESS)
1950 return (err);
1951
1952 err = picl_get_propval_by_name(sbush, PICL_PROP_CHILD, &nodeh,
1953 sizeof (picl_nodehdl_t));
1954
1955 while (err == PICL_SUCCESS) {
1956 slot = picldiag_get_uint_propval(nodeh,
1957 PICL_PROP_SLOT, &err);
1958 if (err == PICL_PROPNOTFOUND) {
1959 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
1960 &nodeh, sizeof (picl_nodehdl_t));
1961 continue;
1962 } else if (err != PICL_SUCCESS)
1963 return (err);
1964
1965 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
1966 &model);
1967 if (err == PICL_PROPNOTFOUND)
1968 model = NULL;
1969 else if (err != PICL_SUCCESS)
1970 return (err);
1971
1972 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS,
1973 &status);
1974 if (err == PICL_PROPNOTFOUND) {
1975 status = malloc(5);
1976 strncpy(status, "okay", 5);
1977 } else if (err != PICL_SUCCESS)
1978 return (err);
1979
1980 err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, freq,
1981 model, status);
1982 if (model != NULL)
1983 free(model);
1984 if (status != NULL)
1985 free(status);
1986 if (err != PICL_SUCCESS)
1987 return (err);
1988
1989 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
1990 sizeof (picl_nodehdl_t));
1991 }
1992 if (err == PICL_PROPNOTFOUND)
1993 return (PICL_WALK_CONTINUE);
1994 return (err);
1995 }
1996
1997 /*
1998 * add all io devices under pci in io list
1999 */
2000 /* ARGSUSED */
2001 static int
pci_callback(picl_nodehdl_t pcih,void * args)2002 pci_callback(picl_nodehdl_t pcih, void *args)
2003 {
2004 picl_nodehdl_t nodeh;
2005 int err;
2006 char piclclass[PICL_CLASSNAMELEN_MAX];
2007 uint32_t boardnum;
2008 uint32_t bus_id;
2009 uint32_t slot;
2010 uint32_t freq;
2011 char *model;
2012 char *status;
2013
2014 /* Fill in common infomation */
2015 bus_id = PCI_TYPE;
2016
2017 /*
2018 * Check if it has the freq, if not,
2019 * If not, use its parent's freq
2020 * if its parent's freq is not found, return
2021 */
2022 err = picldiag_get_clock_freq(pcih, &freq);
2023 if (err == PICL_PROPNOTFOUND) {
2024 err = picldiag_get_clock_from_parent(pcih, &freq);
2025 if (err == PICL_PROPNOTFOUND)
2026 return (PICL_WALK_CONTINUE);
2027 else if (err != PICL_SUCCESS)
2028 return (err);
2029 } else if (err != PICL_SUCCESS)
2030 return (err);
2031
2032 /*
2033 * If no board# is found, set boardnum to 0
2034 */
2035 boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err);
2036 if (err == PICL_PROPNOTFOUND)
2037 boardnum = DEFAULT_BOARD_NUM;
2038 else if (err != PICL_SUCCESS)
2039 return (err);
2040
2041 /* Walk through the children */
2042
2043 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
2044 sizeof (picl_nodehdl_t));
2045 while (err == PICL_SUCCESS) {
2046 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2047 piclclass, sizeof (piclclass));
2048 if (err != PICL_SUCCESS)
2049 return (err);
2050
2051 /*
2052 * Skip PCI bridge and USB devices because they will be
2053 * processed later
2054 */
2055 if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) ||
2056 (strcmp(piclclass, PICL_CLASS_USB) == 0)) {
2057 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
2058 &nodeh, sizeof (picl_nodehdl_t));
2059 continue;
2060 }
2061
2062 /* Get the device id for pci card */
2063 slot = picldiag_get_uint_propval(nodeh,
2064 PICL_PROP_DEVICE_ID, &err);
2065 if (err == PICL_PROPNOTFOUND) {
2066 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
2067 &nodeh, sizeof (picl_nodehdl_t));
2068 continue;
2069 } else if (err != PICL_SUCCESS)
2070 return (err);
2071
2072 /* Get the model of this card */
2073 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
2074 &model);
2075 if (err == PICL_PROPNOTFOUND)
2076 model = NULL;
2077 else if (err != PICL_SUCCESS)
2078 return (err);
2079
2080 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS,
2081 &status);
2082 if (err == PICL_PROPNOTFOUND) {
2083 status = malloc(5);
2084 strncpy(status, "okay", 5);
2085 } else if (err != PICL_SUCCESS)
2086 return (err);
2087
2088 err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot,
2089 freq, model, status);
2090
2091 if (model != NULL)
2092 free(model);
2093
2094 if (status != NULL)
2095 free(status);
2096
2097 if (err != PICL_SUCCESS)
2098 return (err);
2099
2100 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
2101 sizeof (picl_nodehdl_t));
2102
2103 }
2104
2105 if (err == PICL_PROPNOTFOUND)
2106 return (PICL_WALK_CONTINUE);
2107
2108 return (err);
2109 }
2110
2111 /*
2112 * add io devices in io list
2113 * Its slot number is drived from upa-portid
2114 */
2115 static int
add_io_devices(picl_nodehdl_t nodeh)2116 add_io_devices(picl_nodehdl_t nodeh)
2117 {
2118 int err;
2119 uint64_t board_type;
2120 char piclclass[PICL_CLASSNAMELEN_MAX];
2121 char name[MAXSTRLEN];
2122 char *devfs_path;
2123 char *nameval;
2124 uint32_t boardnum;
2125 uint32_t bus_id;
2126 uint32_t slot;
2127 uint32_t freq;
2128 char *model;
2129 char *status;
2130 picl_prophdl_t proph;
2131 picl_propinfo_t pinfo;
2132 picl_nodehdl_t fruparenth;
2133 char *label;
2134
2135
2136 bus_id = UPA_TYPE;
2137
2138 /*
2139 * If clock frequency can't be found from its parent, don't add
2140 */
2141 err = picldiag_get_clock_from_parent(nodeh, &freq);
2142 if (err == PICL_PROPNOTFOUND)
2143 return (PICL_SUCCESS);
2144 else if (err != PICL_SUCCESS)
2145 return (err);
2146
2147 /*
2148 * If no board# is found, set boardnum to 0
2149 */
2150 boardnum = picldiag_get_uint_propval(nodeh, OBP_PROP_BOARD_NUM, &err);
2151 if (err == PICL_PROPNOTFOUND)
2152 boardnum = DEFAULT_BOARD_NUM;
2153 else if (err != PICL_SUCCESS)
2154 return (err);
2155
2156 /*
2157 * get upa portid as slot number
2158 * If upa portid is not found, don't add the card.
2159 */
2160 slot = picldiag_get_uint_propval(nodeh, OBP_PROP_UPA_PORTID,
2161 &err);
2162 if (err == PICL_PROPNOTFOUND)
2163 return (PICL_SUCCESS);
2164 else if (err != PICL_SUCCESS)
2165 return (err);
2166
2167 /* Get the model of this card */
2168 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, &model);
2169 if (err == PICL_PROPNOTFOUND)
2170 model = NULL;
2171 else if (err != PICL_SUCCESS)
2172 return (err);
2173
2174 /*
2175 * check if it is a ffb device
2176 * If it's a ffb device, append its board type to name
2177 * otherwise, use its nodename
2178 */
2179 err = picl_get_prop_by_name(nodeh, PICL_PROP_FFB_BOARD_REV, &proph);
2180 if (err == PICL_PROPNOTFOUND) {
2181 err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME,
2182 &pinfo, &proph);
2183 if (err != PICL_SUCCESS)
2184 return (err);
2185
2186 nameval = alloca(pinfo.size);
2187 if (nameval == NULL)
2188 return (PICL_FAILURE);
2189
2190 err = picl_get_propval(proph, nameval, pinfo.size);
2191 if (err != PICL_SUCCESS)
2192 return (err);
2193
2194 (void) strlcpy(name, nameval, MAXSTRLEN);
2195 } else if (err == PICL_SUCCESS) {
2196 /* Find out if it's single or double buffered */
2197 board_type = picldiag_get_uint_propval(nodeh,
2198 OBP_PROP_BOARD_TYPE, &err);
2199 if (err == PICL_PROPNOTFOUND)
2200 (void) strlcpy(name, FFB_NAME, sizeof (name));
2201 if (err == PICL_SUCCESS) {
2202 if (board_type & FFB_B_BUFF)
2203 (void) strlcpy(name, FFB_DOUBLE_BUF,
2204 sizeof (name));
2205 else
2206 (void) strlcpy(name, FFB_SINGLE_BUF,
2207 sizeof (name));
2208 } else
2209 return (err);
2210 } else
2211 return (err);
2212
2213 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2214 piclclass, sizeof (piclclass));
2215 if (err != PICL_SUCCESS)
2216 return (err);
2217
2218 (void) snprintf(name, sizeof (name), "%s (%s)", name, piclclass);
2219
2220 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status);
2221 if (err == PICL_PROPNOTFOUND) {
2222 status = malloc(5);
2223 strncpy(status, "okay", 5);
2224 } else if (err != PICL_SUCCESS)
2225 return (err);
2226
2227 err = picldiag_get_fru_parent(nodeh, &fruparenth);
2228 if (err == PICL_PROPNOTFOUND) {
2229 label = NULL;
2230 } else if (err != PICL_SUCCESS) {
2231 return (err);
2232 } else {
2233 err = picldiag_get_combined_label(fruparenth, &label, 15);
2234 if (err == PICL_PROPNOTFOUND)
2235 label = NULL;
2236 else if (err != PICL_SUCCESS)
2237 return (err);
2238 }
2239 /* devfs-path */
2240 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
2241 &devfs_path);
2242 if (err == PICL_PROPNOTFOUND)
2243 devfs_path = NULL;
2244 else if (err != PICL_SUCCESS)
2245 return (err);
2246
2247 add_io_card(boardnum, bus_id, slot, label, freq, name, model, status,
2248 devfs_path);
2249 if (label != NULL)
2250 free(label);
2251 if (model != NULL)
2252 free(model);
2253 if (status != NULL)
2254 free(status);
2255 if (devfs_path != NULL)
2256 free(devfs_path);
2257
2258 return (PICL_SUCCESS);
2259 }
2260
2261 /*
2262 * loop through all children and add io devices in io list
2263 */
2264 static int
process_io_leaves(picl_nodehdl_t rooth)2265 process_io_leaves(picl_nodehdl_t rooth)
2266 {
2267 picl_nodehdl_t nodeh;
2268 char classval[PICL_CLASSNAMELEN_MAX];
2269 int err;
2270
2271 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
2272 sizeof (picl_nodehdl_t));
2273 while (err == PICL_SUCCESS) {
2274 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2275 classval, sizeof (classval));
2276 if (err != PICL_SUCCESS)
2277 return (err);
2278
2279 if (is_io_device(classval))
2280 err = add_io_devices(nodeh);
2281
2282 if (err != PICL_SUCCESS)
2283 return (err);
2284
2285 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
2286 sizeof (picl_nodehdl_t));
2287 }
2288
2289 if (err == PICL_PROPNOTFOUND)
2290 return (PICL_SUCCESS);
2291
2292 return (err);
2293 }
2294
2295 /*
2296 * callback function to add all io devices under upa in io list
2297 */
2298 /*ARGSUSED*/
2299 static int
upa_callback(picl_nodehdl_t upah,void * args)2300 upa_callback(picl_nodehdl_t upah, void *args)
2301 {
2302 int err;
2303
2304 err = process_io_leaves(upah);
2305
2306 if (err == PICL_SUCCESS)
2307 return (PICL_WALK_CONTINUE);
2308 return (err);
2309 }
2310
2311 /*
2312 * display ffb hardware configuration
2313 */
2314 /* ARGSUSED */
2315 static int
ffbconfig_callback(picl_nodehdl_t ffbh,void * arg)2316 ffbconfig_callback(picl_nodehdl_t ffbh, void *arg)
2317 {
2318 int err;
2319 uint64_t board_rev;
2320 uint64_t fbc_ver;
2321 char *dac_ver;
2322 char *fbram_ver;
2323
2324 /*
2325 * If it has PICL_PROP_FFB_BOARD_REV, it is a ffb device
2326 * Otherwise, return.
2327 */
2328 board_rev = picldiag_get_uint_propval(ffbh, PICL_PROP_FFB_BOARD_REV,
2329 &err);
2330 if (err == PICL_PROPNOTFOUND)
2331 return (PICL_WALK_CONTINUE);
2332 else if (err != PICL_SUCCESS)
2333 return (err);
2334
2335 log_printf("FFB Hardware Configuration:\n");
2336 log_printf("-----------------------------------\n");
2337 log_printf("Board rev: %lld\n", board_rev);
2338
2339 fbc_ver = picldiag_get_uint_propval(ffbh, OBP_PROP_FBC_REG_ID,
2340 &err);
2341 if (err == PICL_SUCCESS)
2342 log_printf("FBC version: 0x%llx\n", fbc_ver);
2343 else if (err != PICL_PROPNOTFOUND)
2344 return (err);
2345
2346 err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_DAC_VER,
2347 &dac_ver);
2348 if (err == PICL_SUCCESS) {
2349 log_printf("DAC: %s\n", dac_ver);
2350 free(dac_ver);
2351 } else if (err != PICL_PROPNOTFOUND)
2352 return (err);
2353
2354 err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_FBRAM_VER,
2355 &fbram_ver);
2356 if (err == PICL_SUCCESS) {
2357 log_printf("3DRAM: %s\n", fbram_ver);
2358 free(fbram_ver);
2359 } else if (err != PICL_PROPNOTFOUND)
2360 return (err);
2361
2362 log_printf("\n");
2363 return (PICL_WALK_CONTINUE);
2364 }
2365
2366 /*
2367 * find all io devices and add them in the io list
2368 */
2369 static int
gather_io_cards(picl_nodehdl_t plafh)2370 gather_io_cards(picl_nodehdl_t plafh)
2371 {
2372 int err;
2373
2374 /*
2375 * look for io devices under the immediate children of platform
2376 */
2377 err = process_io_leaves(plafh);
2378
2379 if (err != PICL_SUCCESS)
2380 return (err);
2381
2382 err = picl_walk_tree_by_class(plafh, PICL_CLASS_SBUS,
2383 PICL_CLASS_SBUS, sbus_callback);
2384 if (err != PICL_SUCCESS)
2385 return (err);
2386 err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
2387 PICL_CLASS_PCI, pci_callback);
2388 if (err != PICL_SUCCESS)
2389 return (err);
2390 err = picl_walk_tree_by_class(plafh, PICL_CLASS_UPA,
2391 PICL_CLASS_UPA, upa_callback);
2392 return (err);
2393 }
2394
2395 static void
picldiag_display_io_cards(struct io_card * list)2396 picldiag_display_io_cards(struct io_card *list)
2397 {
2398 static int banner = 0; /* Have we printed the column headings? */
2399 struct io_card *p;
2400
2401 if (list == NULL)
2402 return;
2403
2404 if (banner == 0) {
2405 log_printf("Bus Freq Slot + Name +\n", 0);
2406 log_printf("Type MHz Status "
2407 "Path "
2408 "Model", 0);
2409 log_printf("\n", 0);
2410 log_printf("---- ---- ---------- "
2411 "---------------------------- "
2412 "--------------------", 0);
2413 log_printf("\n", 0);
2414 banner = 1;
2415 }
2416
2417 for (p = list; p != NULL; p = p -> next) {
2418 log_printf("%-4s ", p->bus_type, 0);
2419 log_printf("%3d ", p->freq, 0);
2420 /*
2421 * We check to see if it's an int or
2422 * a char string to display for slot.
2423 */
2424 if (p->slot == PCI_SLOT_IS_STRING)
2425 log_printf("%10s ", p->slot_str, 0);
2426 else
2427 log_printf("%10d ", p->slot, 0);
2428
2429 log_printf("%-28.28s", p->name, 0);
2430 if (strlen(p->name) > 28)
2431 log_printf("+ ", 0);
2432 else
2433 log_printf(" ", 0);
2434 log_printf("%-19.19s", p->model, 0);
2435 if (strlen(p->model) > 19)
2436 log_printf("+", 0);
2437 log_printf("\n", 0);
2438 log_printf(" %10s ", p->status, 0);
2439 set_exit_code(p->status);
2440 if (strlen(p->notes) > 0)
2441 log_printf("%s", p->notes, 0);
2442 log_printf("\n\n", 0);
2443 }
2444 }
2445
2446 /*
2447 * display all io devices
2448 */
2449 static int
display_io_device_info(picl_nodehdl_t plafh)2450 display_io_device_info(picl_nodehdl_t plafh)
2451 {
2452 int err;
2453
2454 err = gather_io_cards(plafh);
2455 if (err != PICL_SUCCESS)
2456 return (err);
2457
2458 logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"),
2459 DEFAULT_LINE_WIDTH);
2460
2461 picldiag_display_io_cards(io_card_list);
2462
2463 free_io_cards(io_card_list);
2464
2465 return (PICL_SUCCESS);
2466 }
2467
2468 /*
2469 * print fan device information
2470 */
2471 static int
logprintf_fan_info(picl_nodehdl_t fanh)2472 logprintf_fan_info(picl_nodehdl_t fanh)
2473 {
2474 int err;
2475 char *label;
2476 char *unit;
2477 int64_t speed;
2478 int64_t min_speed;
2479 picl_nodehdl_t fruph;
2480
2481 err = picldiag_get_fru_parent(fanh, &fruph);
2482 if (err != PICL_SUCCESS)
2483 return (err);
2484
2485 err = picldiag_get_combined_label(fruph, &label, 14);
2486 if (err != PICL_SUCCESS)
2487 return (err);
2488
2489 log_printf("%-14s ", label);
2490 free(label);
2491
2492 err = picldiag_get_label(fanh, &label);
2493 if (err == PICL_SUCCESS) {
2494 log_printf("%-14s ", label);
2495 free(label);
2496 } else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
2497 log_printf(" - ");
2498 } else
2499 return (err);
2500
2501 speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err);
2502 if (err == PICL_SUCCESS) {
2503 min_speed = picldiag_get_uint_propval(fanh,
2504 PICL_PROP_LOW_WARNING_THRESHOLD, &err);
2505 if (err != PICL_SUCCESS)
2506 min_speed = 1;
2507 if (speed < min_speed) {
2508 log_printf("failed (%lld", speed);
2509 err = picldiag_get_string_propval(fanh,
2510 PICL_PROP_FAN_SPEED_UNIT, &unit);
2511 if (err == PICL_SUCCESS) {
2512 log_printf("%s", unit);
2513 free(unit);
2514 }
2515 log_printf(")");
2516 exit_code = PD_SYSTEM_FAILURE;
2517 } else {
2518 log_printf("okay");
2519 }
2520 } else {
2521 err = picldiag_get_string_propval(fanh,
2522 PICL_PROP_FAN_SPEED_UNIT, &unit);
2523 if (err == PICL_SUCCESS) {
2524 log_printf("%-12s ", unit);
2525 free(unit);
2526 }
2527 }
2528
2529 log_printf("\n");
2530 return (PICL_SUCCESS);
2531 }
2532
2533 static int
fan_callback(picl_nodehdl_t fanh,void * arg)2534 fan_callback(picl_nodehdl_t fanh, void *arg)
2535 {
2536 int *countp = arg;
2537 int err;
2538
2539 if (*countp == 0) {
2540 log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n"));
2541 log_printf("---------------------------------------\n");
2542 log_printf("Location Sensor Status \n");
2543 log_printf("---------------------------------------\n");
2544 }
2545 *countp += 1;
2546 err = logprintf_fan_info(fanh);
2547 if (err == PICL_SUCCESS)
2548 return (PICL_WALK_CONTINUE);
2549 return (err);
2550 }
2551
2552 /*
2553 * callback function search children to find fan device and print its speed
2554 */
2555 static int
display_fan_speed(picl_nodehdl_t plafh)2556 display_fan_speed(picl_nodehdl_t plafh)
2557 {
2558 int err;
2559 int print_header;
2560
2561 print_header = 0;
2562 err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN,
2563 &print_header, fan_callback);
2564 return (err);
2565 }
2566
2567 /*
2568 * print temperature sensor information
2569 */
2570 static int
logprintf_temp_info(picl_nodehdl_t temph)2571 logprintf_temp_info(picl_nodehdl_t temph)
2572 {
2573 int err;
2574 char *label;
2575 int64_t temperature;
2576 int64_t threshold;
2577 picl_nodehdl_t fruph;
2578 char *status = "unknown";
2579 int got_temp = 0;
2580
2581 err = picldiag_get_fru_parent(temph, &fruph);
2582 if (err != PICL_SUCCESS)
2583 return (err);
2584
2585 err = picldiag_get_combined_label(fruph, &label, 14);
2586 if (err != PICL_SUCCESS)
2587 return (err);
2588
2589 log_printf("%-14s ", label);
2590 free(label);
2591
2592 err = picldiag_get_label(temph, &label);
2593 if (err != PICL_SUCCESS)
2594 return (err);
2595 log_printf("%-14s ", label);
2596 free(label);
2597
2598 temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE,
2599 &err);
2600 if (err == PICL_SUCCESS) {
2601 got_temp = 1;
2602 status = "okay";
2603 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2604 return (err);
2605 }
2606
2607 threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING,
2608 &err);
2609 if (err == PICL_SUCCESS) {
2610 if (got_temp && temperature < threshold)
2611 status = "warning";
2612 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2613 return (err);
2614 }
2615
2616 threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN,
2617 &err);
2618 if (err == PICL_SUCCESS) {
2619 if (got_temp && temperature < threshold)
2620 status = "failed";
2621 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2622 return (err);
2623 }
2624
2625 threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING,
2626 &err);
2627 if (err == PICL_SUCCESS) {
2628 if (got_temp && temperature > threshold)
2629 status = "warning";
2630 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2631 return (err);
2632 }
2633
2634 threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN,
2635 &err);
2636 if (err == PICL_SUCCESS) {
2637 if (got_temp && temperature > threshold)
2638 status = "failed";
2639 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2640 return (err);
2641 }
2642
2643 err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status);
2644 if (err == PICL_SUCCESS) {
2645 log_printf("%s", status);
2646 set_exit_code(status);
2647 free(status);
2648 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2649 return (err);
2650 } else {
2651 log_printf("%s ", status);
2652 set_exit_code(status);
2653 if (strcmp(status, "failed") == 0 ||
2654 strcmp(status, "warning") == 0)
2655 log_printf("(%.2lldC)", temperature);
2656 }
2657
2658 log_printf("\n");
2659 return (PICL_SUCCESS);
2660 }
2661
2662 static int
temp_callback(picl_nodehdl_t temph,void * arg)2663 temp_callback(picl_nodehdl_t temph, void *arg)
2664 {
2665 int err;
2666 int *countp = arg;
2667
2668 if (*countp == 0) {
2669 log_printf("\n");
2670 log_printf("---------------------------------------\n");
2671 log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n"));
2672 log_printf("------------------------------------\n");
2673 log_printf("Location Sensor Status\n");
2674 log_printf("------------------------------------\n");
2675 }
2676 *countp += 1;
2677 err = logprintf_temp_info(temph);
2678 if (err == PICL_SUCCESS)
2679 return (PICL_WALK_CONTINUE);
2680 return (err);
2681 }
2682
2683 /*
2684 * callback function search children to find temp sensors and print the temp
2685 */
2686 /* ARGSUSED */
2687 static int
display_temp(picl_nodehdl_t plafh)2688 display_temp(picl_nodehdl_t plafh)
2689 {
2690 int err;
2691 int print_header;
2692
2693 print_header = 0;
2694 err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR,
2695 &print_header, temp_callback);
2696 if (err != PICL_SUCCESS)
2697 return (err);
2698 err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR,
2699 &print_header, temp_callback);
2700 return (err);
2701 }
2702
2703 /*
2704 * print current sensor information
2705 */
2706 static int
logprintf_current_info(picl_nodehdl_t currenth)2707 logprintf_current_info(picl_nodehdl_t currenth)
2708 {
2709 int err;
2710 char *label;
2711 float current;
2712 float threshold;
2713 picl_nodehdl_t fruph;
2714 char *status = "unknown";
2715 int got_current = 0;
2716
2717 err = picldiag_get_fru_parent(currenth, &fruph);
2718 if (err != PICL_SUCCESS)
2719 return (err);
2720
2721 err = picldiag_get_combined_label(fruph, &label, 10);
2722 if (err != PICL_SUCCESS)
2723 return (err);
2724
2725 log_printf("%-10s ", label);
2726 free(label);
2727
2728 err = picldiag_get_label(currenth, &label);
2729 if (err != PICL_SUCCESS)
2730 return (err);
2731 log_printf("%-10s ", label);
2732 free(label);
2733
2734 current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err);
2735 if (err == PICL_SUCCESS) {
2736 status = "okay";
2737 got_current = 1;
2738 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2739 return (err);
2740 }
2741
2742 threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING,
2743 &err);
2744 if (err == PICL_SUCCESS) {
2745 if (got_current && current < threshold)
2746 status = "warning";
2747 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2748 return (err);
2749 }
2750
2751 threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN,
2752 &err);
2753 if (err == PICL_SUCCESS) {
2754 if (got_current && current < threshold)
2755 status = "failed";
2756 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2757 return (err);
2758 }
2759
2760 threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING,
2761 &err);
2762 if (err == PICL_SUCCESS) {
2763 if (got_current && current > threshold)
2764 status = "warning";
2765 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2766 return (err);
2767 }
2768
2769 threshold = picldiag_get_float_propval(currenth,
2770 PICL_PROP_HIGH_SHUTDOWN, &err);
2771 if (err == PICL_SUCCESS) {
2772 if (got_current && current > threshold)
2773 status = "failed";
2774 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2775 return (err);
2776 }
2777
2778 err = picldiag_get_string_propval(currenth,
2779 PICL_PROP_CONDITION, &status);
2780 if (err == PICL_SUCCESS) {
2781 log_printf(" %s", status);
2782 set_exit_code(status);
2783 free(status);
2784 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2785 return (err);
2786 } else {
2787 log_printf("%s ", status);
2788 set_exit_code(status);
2789 if (strcmp(status, "failed") == 0 ||
2790 strcmp(status, "warning") == 0)
2791 log_printf("(%.2fA)", current);
2792 }
2793
2794 log_printf("\n");
2795 return (PICL_SUCCESS);
2796 }
2797
2798 static int
current_callback(picl_nodehdl_t currh,void * arg)2799 current_callback(picl_nodehdl_t currh, void *arg)
2800 {
2801 int err;
2802 int *countp = arg;
2803
2804 if (*countp == 0) {
2805 log_printf("------------------------------------\n");
2806 log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n"));
2807 log_printf("------------------------------\n");
2808 log_printf("Location Sensor Status\n");
2809 log_printf("------------------------------\n");
2810 }
2811 *countp += 1;
2812 err = logprintf_current_info(currh);
2813 if (err == PICL_SUCCESS)
2814 return (PICL_WALK_CONTINUE);
2815 return (err);
2816 }
2817
2818 /*
2819 * callback function search children to find curr sensors and print the curr
2820 */
2821 /* ARGSUSED */
2822 static int
display_current(picl_nodehdl_t plafh)2823 display_current(picl_nodehdl_t plafh)
2824 {
2825 int err;
2826 int print_header;
2827
2828 print_header = 0;
2829 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR,
2830 &print_header, current_callback);
2831 if (err != PICL_SUCCESS)
2832 return (err);
2833 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR,
2834 &print_header, current_callback);
2835 return (err);
2836 }
2837
2838 /*
2839 * print voltage sensor information
2840 */
2841 static int
logprintf_voltage_info(picl_nodehdl_t voltageh)2842 logprintf_voltage_info(picl_nodehdl_t voltageh)
2843 {
2844 int err;
2845 char *label;
2846 float voltage;
2847 float threshold;
2848 picl_nodehdl_t fruph;
2849 char *status = "unknown";
2850 int got_voltage = 0;
2851
2852 err = picldiag_get_fru_parent(voltageh, &fruph);
2853 if (err != PICL_SUCCESS)
2854 return (err);
2855
2856 err = picldiag_get_combined_label(fruph, &label, 10);
2857 if (err != PICL_SUCCESS)
2858 return (err);
2859
2860 log_printf("%-10s ", label);
2861 free(label);
2862
2863 err = picldiag_get_label(voltageh, &label);
2864 if (err != PICL_SUCCESS)
2865 return (err);
2866 log_printf("%-12s ", label);
2867 free(label);
2868
2869 voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err);
2870 if (err == PICL_SUCCESS) {
2871 status = "okay";
2872 got_voltage = 1;
2873 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2874 return (err);
2875 }
2876
2877 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING,
2878 &err);
2879 if (err == PICL_SUCCESS) {
2880 if (got_voltage && voltage < threshold)
2881 status = "warning";
2882 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2883 return (err);
2884 }
2885
2886 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN,
2887 &err);
2888 if (err == PICL_SUCCESS) {
2889 if (got_voltage && voltage < threshold)
2890 status = "failed";
2891 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2892 return (err);
2893 }
2894
2895 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING,
2896 &err);
2897 if (err == PICL_SUCCESS) {
2898 if (got_voltage && voltage > threshold)
2899 status = "warning";
2900 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2901 return (err);
2902 }
2903
2904 threshold = picldiag_get_float_propval(voltageh,
2905 PICL_PROP_HIGH_SHUTDOWN, &err);
2906 if (err == PICL_SUCCESS) {
2907 if (got_voltage && voltage > threshold)
2908 status = "failed";
2909 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2910 return (err);
2911 }
2912
2913 err = picldiag_get_string_propval(voltageh,
2914 PICL_PROP_CONDITION, &status);
2915 if (err == PICL_SUCCESS) {
2916 log_printf("%s", status);
2917 set_exit_code(status);
2918 free(status);
2919 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2920 return (err);
2921 } else {
2922 log_printf("%s ", status);
2923 set_exit_code(status);
2924 if (strcmp(status, "warning") == 0 ||
2925 strcmp(status, "failed") == 0)
2926 log_printf("(%.2fV)", voltage);
2927 }
2928
2929 log_printf("\n");
2930 return (PICL_SUCCESS);
2931 }
2932
2933 static int
voltage_callback(picl_nodehdl_t voltageh,void * arg)2934 voltage_callback(picl_nodehdl_t voltageh, void *arg)
2935 {
2936 int *countp = arg;
2937 int err;
2938
2939 if (*countp == 0) {
2940 log_printf("--------------------------------\n");
2941 log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n"));
2942 log_printf("-------------------------------\n");
2943 log_printf("Location Sensor Status\n");
2944 log_printf("-------------------------------\n");
2945 }
2946 *countp += 1;
2947 err = logprintf_voltage_info(voltageh);
2948 if (err == PICL_SUCCESS)
2949 return (PICL_WALK_CONTINUE);
2950 return (err);
2951 }
2952
2953 /*
2954 * callback function search children to find voltage sensors and print voltage
2955 */
2956 /* ARGSUSED */
2957 static int
display_voltage(picl_nodehdl_t plafh)2958 display_voltage(picl_nodehdl_t plafh)
2959 {
2960 int err;
2961 int print_header;
2962
2963 print_header = 0;
2964 err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR,
2965 &print_header, voltage_callback);
2966 if (err != PICL_SUCCESS)
2967 return (err);
2968 err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR,
2969 &print_header, voltage_callback);
2970 return (err);
2971 }
2972
2973 /*
2974 * print led device information
2975 */
2976 static int
logprintf_led_info(picl_nodehdl_t ledh)2977 logprintf_led_info(picl_nodehdl_t ledh)
2978 {
2979 int err;
2980 char *label;
2981 char *state;
2982 char *color;
2983 picl_nodehdl_t fruph;
2984
2985 err = picldiag_get_fru_parent(ledh, &fruph);
2986 if (err != PICL_SUCCESS)
2987 return (err);
2988
2989 err = picldiag_get_combined_label(fruph, &label, 10);
2990 if (err != PICL_SUCCESS) {
2991 log_printf(" - ", label);
2992 } else {
2993 log_printf("%-10s ", label);
2994 free(label);
2995 }
2996
2997 err = picldiag_get_label(ledh, &label);
2998 if (err != PICL_SUCCESS)
2999 return (err);
3000 log_printf("%-20s ", label);
3001 free(label);
3002
3003 err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state);
3004 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
3005 log_printf(" - ");
3006 } else if (err != PICL_SUCCESS) {
3007 return (err);
3008 } else {
3009 log_printf("%-10s ", state);
3010 free(state);
3011 }
3012
3013 err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color);
3014 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
3015 log_printf("\n");
3016 } else if (err != PICL_SUCCESS) {
3017 return (err);
3018 } else {
3019 log_printf("%-16s\n", color);
3020 free(color);
3021 }
3022
3023 return (PICL_SUCCESS);
3024 }
3025
3026 static int
led_callback(picl_nodehdl_t ledh,void * arg)3027 led_callback(picl_nodehdl_t ledh, void *arg)
3028 {
3029 int *countp = arg;
3030 int err;
3031
3032 if (*countp == 0) {
3033
3034 log_printf("--------------------------------------"
3035 "------------\n");
3036 log_printf(dgettext(TEXT_DOMAIN, "Led State:\n"));
3037 log_printf("--------------------------------------"
3038 "------------\n");
3039 log_printf("Location Led State"
3040 " Color\n");
3041 log_printf("--------------------------------------"
3042 "------------\n");
3043 }
3044 *countp += 1;
3045 err = logprintf_led_info(ledh);
3046 if (err == PICL_SUCCESS)
3047 return (PICL_WALK_CONTINUE);
3048 return (err);
3049 }
3050
3051 /*
3052 * callback function search children to find led devices and print status
3053 */
3054 /* ARGSUSED */
3055 static int
display_led_status(picl_nodehdl_t plafh)3056 display_led_status(picl_nodehdl_t plafh)
3057 {
3058 int print_header;
3059
3060 print_header = 0;
3061 picl_walk_tree_by_class(plafh, PICL_CLASS_LED,
3062 &print_header, led_callback);
3063 return (PICL_SUCCESS);
3064 }
3065
3066 /*
3067 * print keyswitch device information
3068 */
3069 static int
logprintf_keyswitch_info(picl_nodehdl_t keyswitchh,picl_nodehdl_t fruph)3070 logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph)
3071 {
3072 int err;
3073 char *label;
3074 char *state;
3075
3076 err = picldiag_get_combined_label(fruph, &label, 10);
3077 if (err != PICL_SUCCESS) {
3078 log_printf("%-14s", " -");
3079 } else {
3080 log_printf("%-14s ", label);
3081 free(label);
3082 }
3083
3084 err = picldiag_get_label(keyswitchh, &label);
3085 if (err != PICL_SUCCESS)
3086 return (err);
3087 log_printf("%-11s ", label);
3088 free(label);
3089
3090 err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state);
3091 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
3092 log_printf(" -\n");
3093 } else if (err != PICL_SUCCESS) {
3094 return (err);
3095 } else {
3096 log_printf("%s\n", state);
3097 free(state);
3098 }
3099
3100 return (PICL_SUCCESS);
3101 }
3102
3103 static int
keyswitch_callback(picl_nodehdl_t keyswitchh,void * arg)3104 keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg)
3105 {
3106 int *countp = arg;
3107 int err;
3108 picl_nodehdl_t fruph;
3109
3110 /*
3111 * Tamale simulates a key-switch on ENxS. So the presence of a
3112 * node of class keyswitch is not sufficient. If it has a fru parent
3113 * or location parent, then believe it.
3114 */
3115 err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT,
3116 &fruph, sizeof (fruph));
3117 if (err == PICL_PROPNOTFOUND) {
3118 err = picl_get_propval_by_name(keyswitchh,
3119 PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
3120 }
3121 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
3122 return (PICL_WALK_CONTINUE);
3123 if (err != PICL_SUCCESS)
3124 return (err);
3125
3126 if (*countp == 0) {
3127 log_printf("-----------------------------------------\n");
3128 log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n"));
3129 log_printf("-----------------------------------------\n");
3130 log_printf(dgettext(TEXT_DOMAIN,
3131 "Location Keyswitch State\n"));
3132 log_printf("-----------------------------------------\n");
3133 }
3134 *countp += 1;
3135 err = logprintf_keyswitch_info(keyswitchh, fruph);
3136 if (err == PICL_SUCCESS)
3137 return (PICL_WALK_CONTINUE);
3138 return (err);
3139 }
3140
3141 /*
3142 * search children to find keyswitch device(s) and print status
3143 */
3144 /* ARGSUSED */
3145 static int
display_keyswitch(picl_nodehdl_t plafh)3146 display_keyswitch(picl_nodehdl_t plafh)
3147 {
3148 int print_header = 0;
3149
3150 picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH,
3151 &print_header, keyswitch_callback);
3152 return (PICL_SUCCESS);
3153 }
3154
3155 /*
3156 * display environment status
3157 */
3158 static int
display_envctrl_status(picl_nodehdl_t plafh)3159 display_envctrl_status(picl_nodehdl_t plafh)
3160 {
3161 logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"),
3162 DEFAULT_LINE_WIDTH);
3163
3164 display_fan_speed(plafh);
3165 display_temp(plafh);
3166 display_current(plafh);
3167 display_voltage(plafh);
3168 display_keyswitch(plafh);
3169 display_led_status(plafh);
3170
3171 return (PICL_SUCCESS);
3172 }
3173
3174 /*
3175 * print fru operational status
3176 */
3177 static int
logprintf_fru_oper_status(picl_nodehdl_t fruh,int * countp)3178 logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp)
3179 {
3180 int err;
3181 char *label;
3182 char *status;
3183
3184 err = picldiag_get_combined_label(fruh, &label, 15);
3185 if (err != PICL_SUCCESS)
3186 return (PICL_WALK_CONTINUE);
3187
3188 err = picldiag_get_string_propval(fruh,
3189 PICL_PROP_OPERATIONAL_STATUS, &status);
3190 if (err == PICL_SUCCESS) {
3191 if (*countp == 0) {
3192 logprintf_header(dgettext(TEXT_DOMAIN,
3193 "FRU Operational Status"),
3194 DEFAULT_LINE_WIDTH);
3195 log_printf("-------------------------\n");
3196 log_printf(dgettext(TEXT_DOMAIN,
3197 "Fru Operational Status:\n"));
3198 log_printf("-------------------------\n");
3199 log_printf("Location Status \n");
3200 log_printf("-------------------------\n");
3201 }
3202 *countp += 1;
3203 log_printf("%-15s ", label);
3204 free(label);
3205 log_printf("%s\n", status);
3206 set_exit_code(status);
3207 free(status);
3208 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
3209 free(label);
3210 return (err);
3211 } else {
3212 free(label);
3213 }
3214 return (PICL_WALK_CONTINUE);
3215 }
3216
3217 static int
fru_oper_status_callback(picl_nodehdl_t fruh,void * arg)3218 fru_oper_status_callback(picl_nodehdl_t fruh, void *arg)
3219 {
3220 int err;
3221
3222 err = logprintf_fru_oper_status(fruh, (int *)arg);
3223 return (err);
3224 }
3225
3226 /*
3227 * display fru operational status
3228 */
3229 static int
display_fru_oper_status(picl_nodehdl_t frutreeh)3230 display_fru_oper_status(picl_nodehdl_t frutreeh)
3231 {
3232 int print_header;
3233
3234 print_header = 0;
3235 picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU,
3236 &print_header, fru_oper_status_callback);
3237 return (PICL_SUCCESS);
3238 }
3239
3240 /*
3241 * check if the node having the version prop
3242 * If yes, print its nodename and version
3243 */
3244 /* ARGSUSED */
3245 static int
asicrev_callback(picl_nodehdl_t nodeh,void * arg)3246 asicrev_callback(picl_nodehdl_t nodeh, void *arg)
3247 {
3248 uint32_t version;
3249 char *name;
3250 char *model;
3251 char *status;
3252 int err;
3253
3254 version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM,
3255 &err);
3256 if (err == PICL_PROPNOTFOUND)
3257 return (PICL_WALK_CONTINUE);
3258 else if (err != PICL_SUCCESS)
3259 return (err);
3260
3261 /* devfs-path */
3262 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name);
3263 if (err == PICL_PROPNOTFOUND)
3264 name = NULL;
3265 else if (err != PICL_SUCCESS)
3266 return (err);
3267
3268 /* model */
3269 err = picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME,
3270 &model);
3271 if (err == PICL_PROPNOTFOUND)
3272 model = NULL;
3273 else if (err != PICL_SUCCESS)
3274 return (err);
3275
3276 /* status */
3277 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status);
3278 if (err == PICL_PROPNOTFOUND)
3279 status = NULL;
3280 else if (err != PICL_SUCCESS)
3281 return (err);
3282
3283 /*
3284 * Display the data
3285 */
3286
3287 /* name */
3288 if (name != NULL) {
3289 log_printf("%-22s ", name);
3290 free(name);
3291 } else
3292 log_printf("%-22s ", "unknown");
3293 /* model */
3294 if (model != NULL) {
3295 log_printf("%-15s ", model);
3296 free(model);
3297 } else
3298 log_printf("%-15s ", "unknown");
3299 /* status */
3300 if (status == NULL)
3301 log_printf("%-15s ", "okay");
3302 else {
3303 log_printf("%-15s ", status);
3304 set_exit_code(status);
3305 free(status);
3306 }
3307 /* revision */
3308 log_printf(" %-4d\n", version);
3309
3310 return (PICL_WALK_CONTINUE);
3311 }
3312
3313 /*
3314 * traverse the tree to display asic revision id for ebus
3315 */
3316 /* ARGSUSED */
3317 static int
ebus_callback(picl_nodehdl_t ebush,void * arg)3318 ebus_callback(picl_nodehdl_t ebush, void *arg)
3319 {
3320 uint32_t id;
3321 char *name;
3322 int err;
3323 char *model;
3324 char *status;
3325
3326 id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err);
3327 if (err == PICL_PROPNOTFOUND)
3328 return (PICL_WALK_CONTINUE);
3329 else if (err != PICL_SUCCESS)
3330 return (err);
3331
3332 /* devfs-path */
3333 err = picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name);
3334 if (err == PICL_PROPNOTFOUND)
3335 name = NULL;
3336 else if (err != PICL_SUCCESS)
3337 return (err);
3338
3339 /* model */
3340 err = picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME,
3341 &model);
3342 if (err == PICL_PROPNOTFOUND)
3343 model = NULL;
3344 else if (err != PICL_SUCCESS)
3345 return (err);
3346
3347 /* status */
3348 err = picldiag_get_string_propval(ebush, OBP_PROP_STATUS, &status);
3349 if (err == PICL_PROPNOTFOUND)
3350 status = NULL;
3351 else if (err != PICL_SUCCESS)
3352 return (err);
3353
3354 /*
3355 * Display the data
3356 */
3357
3358 /* name */
3359 if (name != NULL) {
3360 log_printf("%-22s ", name);
3361 free(name);
3362 } else
3363 log_printf("%-22s ", "unknown");
3364 /* model */
3365 if (model != NULL) {
3366 log_printf("%-15s ", model);
3367 free(model);
3368 } else
3369 log_printf("%-15s ", "unknown");
3370 /* status */
3371 if (status == NULL)
3372 log_printf("%-15s ", "okay");
3373 else {
3374 log_printf("%-15s ", status);
3375 set_exit_code(status);
3376 free(status);
3377 }
3378 /* revision */
3379 log_printf(" %-4d\n", id);
3380
3381 return (PICL_WALK_CONTINUE);
3382 }
3383
3384 /*
3385 * display asic revision id
3386 */
3387 static int
display_hw_revisions(picl_nodehdl_t plafh)3388 display_hw_revisions(picl_nodehdl_t plafh)
3389 {
3390 int err;
3391
3392 /* Print the header */
3393 logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"),
3394 DEFAULT_LINE_WIDTH);
3395
3396 log_printf("ASIC Revisions:\n");
3397 log_printf("-----------------------------");
3398 log_printf("--------------------------------------\n");
3399 log_printf("Path Device");
3400 log_printf(" Status Revision\n");
3401 log_printf("-----------------------------");
3402 log_printf("--------------------------------------\n");
3403
3404 err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback);
3405 if (err != PICL_SUCCESS)
3406 return (err);
3407
3408 err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS,
3409 NULL, ebus_callback);
3410 if (err != PICL_SUCCESS)
3411 return (err);
3412
3413 log_printf("\n");
3414
3415 err = picl_walk_tree_by_class(plafh, PICL_CLASS_DISPLAY,
3416 NULL, ffbconfig_callback);
3417 return (err);
3418 }
3419
3420 /*
3421 * find the options node and its powerfail_time prop
3422 * If found, display the list of latest powerfail.
3423 */
3424 /* ARGSUSED */
3425 static int
options_callback(picl_nodehdl_t nodeh,void * arg)3426 options_callback(picl_nodehdl_t nodeh, void *arg)
3427 {
3428 time_t value;
3429 char *failtime;
3430 int err;
3431
3432 err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME,
3433 &failtime);
3434 if (err == PICL_PROPNOTFOUND)
3435 return (PICL_WALK_TERMINATE);
3436 else if (err != PICL_SUCCESS)
3437 return (err);
3438
3439 value = (time_t)atoi(failtime);
3440 free(failtime);
3441 if (value == 0)
3442 return (PICL_WALK_TERMINATE);
3443
3444 log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n"));
3445 log_printf("=============================\n");
3446 log_printf("%s", ctime(&value));
3447 log_printf("\n");
3448 return (PICL_WALK_TERMINATE);
3449 }
3450
3451 /*
3452 * display the OBP and POST prom revisions
3453 */
3454 /* ARGSUSED */
3455 static int
flashprom_callback(picl_nodehdl_t flashpromh,void * arg)3456 flashprom_callback(picl_nodehdl_t flashpromh, void *arg)
3457 {
3458 picl_prophdl_t proph;
3459 picl_prophdl_t tblh;
3460 picl_prophdl_t rowproph;
3461 picl_propinfo_t pinfo;
3462 char *prom_version = NULL;
3463 char *obp_version = NULL;
3464 int err;
3465
3466 err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION,
3467 &pinfo, &proph);
3468 if (err == PICL_PROPNOTFOUND)
3469 return (PICL_WALK_TERMINATE);
3470 else if (err != PICL_SUCCESS)
3471 return (err);
3472
3473 log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n"));
3474 log_printf("----------------------\n");
3475
3476 /*
3477 * If it's a table prop, the first element is OBP revision
3478 * The second one is POST revision.
3479 * If it's a charstring prop, the value will be only OBP revision
3480 */
3481 if (pinfo.type == PICL_PTYPE_CHARSTRING) {
3482 prom_version = alloca(pinfo.size);
3483 if (prom_version == NULL)
3484 return (PICL_FAILURE);
3485 err = picl_get_propval(proph, prom_version, pinfo.size);
3486 if (err != PICL_SUCCESS)
3487 return (err);
3488 log_printf("%s\n", prom_version);
3489 }
3490
3491 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */
3492 return (PICL_WALK_TERMINATE);
3493
3494 err = picl_get_propval(proph, &tblh, pinfo.size);
3495 if (err != PICL_SUCCESS)
3496 return (err);
3497
3498 err = picl_get_next_by_row(tblh, &rowproph);
3499 if (err == PICL_SUCCESS) {
3500 /* get first row */
3501 err = picl_get_propinfo(rowproph, &pinfo);
3502 if (err != PICL_SUCCESS)
3503 return (err);
3504
3505 prom_version = alloca(pinfo.size);
3506 if (prom_version == NULL)
3507 return (PICL_FAILURE);
3508
3509 err = picl_get_propval(rowproph, prom_version, pinfo.size);
3510 if (err != PICL_SUCCESS)
3511 return (err);
3512 log_printf("%s\n", prom_version);
3513
3514 /* get second row */
3515 err = picl_get_next_by_col(rowproph, &rowproph);
3516 if (err == PICL_SUCCESS) {
3517 err = picl_get_propinfo(rowproph, &pinfo);
3518 if (err != PICL_SUCCESS)
3519 return (err);
3520
3521 obp_version = alloca(pinfo.size);
3522 if (obp_version == NULL)
3523 return (PICL_FAILURE);
3524 err = picl_get_propval(rowproph, obp_version,
3525 pinfo.size);
3526 if (err != PICL_SUCCESS)
3527 return (err);
3528 log_printf("%s\n", obp_version);
3529 }
3530 }
3531
3532 return (PICL_WALK_TERMINATE);
3533 }
3534
3535 static int
display_system_info(int serrlog,int log_flag,picl_nodehdl_t rooth)3536 display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth)
3537 {
3538 int err;
3539 picl_nodehdl_t plafh;
3540 picl_nodehdl_t frutreeh;
3541
3542 err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
3543 if (err != PICL_SUCCESS)
3544 return (err);
3545
3546 if (!log_flag) {
3547 err = display_platform_banner(plafh);
3548 if (err != PICL_SUCCESS)
3549 return (err);
3550
3551 err = display_system_clock(plafh);
3552 if (err != PICL_SUCCESS)
3553 return (err);
3554
3555 err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY,
3556 PICL_CLASS_MEMORY, memory_callback);
3557 if (err != PICL_SUCCESS)
3558 return (err);
3559
3560 err = display_cpu_info(plafh);
3561 if (err != PICL_SUCCESS)
3562 return (err);
3563
3564 err = display_io_device_info(plafh);
3565 if (err != PICL_SUCCESS)
3566 return (err);
3567
3568 err = display_memory_config(plafh);
3569 if (err != PICL_SUCCESS)
3570 return (err);
3571
3572 err = display_usb_devices(plafh);
3573 if (err != PICL_SUCCESS)
3574 return (err);
3575 }
3576
3577 if (serrlog) {
3578 err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS,
3579 NULL, options_callback);
3580 if (err != PICL_SUCCESS)
3581 return (err);
3582
3583 err = display_envctrl_status(plafh);
3584 if (err != PICL_SUCCESS)
3585 return (err);
3586
3587 err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE,
3588 &frutreeh);
3589 if (err != PICL_SUCCESS)
3590 return (err);
3591
3592 err = display_fru_oper_status(frutreeh);
3593 if (err != PICL_SUCCESS)
3594 return (err);
3595
3596 err = display_hw_revisions(plafh);
3597 if (err != PICL_SUCCESS)
3598 return (err);
3599
3600 err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM,
3601 NULL, flashprom_callback);
3602 if (err != PICL_SUCCESS)
3603 return (err);
3604 }
3605
3606 return (PICL_SUCCESS);
3607 }
3608
3609 /*
3610 * do_prominfo is called from main in prtdiag. It returns PD_SYSTEM_FAILURE if
3611 * any system failure is detected, PD_INTERNAL_FAILURE for internal errors and
3612 * PD_SUCCESS otherwise. main uses the return value as the exit code.
3613 */
3614 /* ARGSUSED */
3615 int
do_prominfo(int serrlog,char * pgname,int log_flag,int prt_flag)3616 do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag)
3617 {
3618 int err;
3619 char *errstr;
3620 int done;
3621 picl_nodehdl_t rooth;
3622
3623 err = picl_initialize();
3624 if (err != PICL_SUCCESS) {
3625 fprintf(stderr, EM_INIT_FAIL, picl_strerror(err));
3626 return (PD_INTERNAL_FAILURE);
3627 }
3628
3629 do {
3630 done = 1;
3631 err = picl_get_root(&rooth);
3632 if (err != PICL_SUCCESS) {
3633 fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err));
3634 return (PD_INTERNAL_FAILURE);
3635 }
3636
3637 err = display_system_info(serrlog, log_flag, rooth);
3638
3639 if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
3640 done = 0;
3641 } while (!done);
3642
3643 if (err != PICL_SUCCESS) {
3644 errstr = picl_strerror(err);
3645 fprintf(stderr, EM_PRTDIAG_FAIL);
3646 fprintf(stderr, "%s\n", errstr? errstr : " ");
3647 exit_code = PD_INTERNAL_FAILURE;
3648 }
3649
3650 (void) picl_shutdown();
3651
3652 return (exit_code);
3653 }
3654