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