1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2020 Peter Tribble.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <alloca.h>
29 #include <unistd.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <kvm.h>
33 #include <varargs.h>
34 #include <time.h>
35 #include <dirent.h>
36 #include <fcntl.h>
37 #include <sys/param.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/utsname.h>
41 #include <sys/openpromio.h>
42 #include <libintl.h>
43 #include <syslog.h>
44 #include <sys/dkio.h>
45 #include <sys/systeminfo.h>
46 #include <picldefs.h>
47 #include <math.h>
48 #include <errno.h>
49 #include "pdevinfo.h"
50 #include "display.h"
51 #include "display_sun4v.h"
52 #include "libprtdiag.h"
53
54 #if !defined(TEXT_DOMAIN)
55 #define TEXT_DOMAIN "SYS_TEST"
56 #endif
57
58 #define MOTHERBOARD "MB"
59 #define NETWORK "network"
60 #define SUN4V_MACHINE "sun4v"
61 #define PARENT_NAMES 10
62
63 /*
64 * Additional OBP properties
65 */
66 #define OBP_PROP_COMPATIBLE "compatible"
67 #define OBP_PROP_MODEL "model"
68 #define OBP_PROP_SLOT_NAMES "slot-names"
69 #define OBP_PROP_VERSION "version"
70
71 #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform"
72 #define PICL_NODE_CHASSIS "chassis"
73 #define MEMORY_SIZE_FIELD 11
74 #define INVALID_THRESHOLD 1000000
75
76 /*
77 * Additional picl classes
78 */
79 #ifndef PICL_CLASS_SUN4V
80 #define PICL_CLASS_SUN4V "sun4v"
81 #endif
82
83 #ifndef PICL_PROP_NAC
84 #define PICL_PROP_NAC "nac"
85 #endif
86
87 extern int sys_clk;
88 extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
89 picl_nodehdl_t *);
90
91 static picl_nodehdl_t rooth = 0, phyplatformh = 0;
92 static picl_nodehdl_t chassish = 0;
93 static int class_node_found;
94 static int syserrlog;
95 static int all_status_ok;
96
97 /* local functions */
98 static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
99 static void sun4v_display_memory_conf(picl_nodehdl_t);
100 static int sun4v_disp_env_status();
101 static void sun4v_env_print_fan_sensors();
102 static void sun4v_env_print_fan_indicators();
103 static void sun4v_env_print_temp_sensors();
104 static void sun4v_env_print_temp_indicators();
105 static void sun4v_env_print_current_sensors();
106 static void sun4v_env_print_current_indicators();
107 static void sun4v_env_print_voltage_sensors();
108 static void sun4v_env_print_voltage_indicators();
109 static void sun4v_env_print_LEDs();
110 static void sun4v_print_fru_status();
111 static int is_fru_absent(picl_nodehdl_t);
112 static void sun4v_print_fw_rev();
113 static void sun4v_print_chassis_serial_no();
114 static int openprom_callback(picl_nodehdl_t openpromh, void *arg);
115 static void sun4v_print_openprom_rev();
116
117 int
sun4v_display(Sys_tree * tree,Prom_node * root,int log,picl_nodehdl_t plafh)118 sun4v_display(Sys_tree *tree, Prom_node *root, int log,
119 picl_nodehdl_t plafh)
120 {
121 void *value; /* used for opaque PROM data */
122 struct mem_total memory_total; /* Total memory in system */
123 char machine[MAXSTRLEN];
124 int exit_code = 0;
125
126 if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
127 return (1);
128 if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
129 return (1);
130
131 sys_clk = -1; /* System clock freq. (in MHz) */
132
133 /*
134 * Now display the machine's configuration. We do this if we
135 * are not logging.
136 */
137 if (!logging) {
138 struct utsname uts_buf;
139
140 /*
141 * Display system banner
142 */
143 (void) uname(&uts_buf);
144
145 log_printf(dgettext(TEXT_DOMAIN, "System Configuration: "
146 "Oracle Corporation %s %s\n"), uts_buf.machine,
147 get_prop_val(find_prop(root, "banner-name")), 0);
148
149 /* display system clock frequency */
150 value = get_prop_val(find_prop(root, "clock-frequency"));
151 if (value != NULL) {
152 sys_clk = ((*((int *)value)) + 500000) / 1000000;
153 log_printf(dgettext(TEXT_DOMAIN, "System clock "
154 "frequency: %d MHz\n"), sys_clk, 0);
155 }
156
157 /* Display the Memory Size */
158 display_memorysize(tree, NULL, &memory_total);
159
160 /* Display the CPU devices */
161 sun4v_display_cpu_devices(plafh);
162
163 /* Display the Memory configuration */
164 class_node_found = 0;
165 sun4v_display_memory_conf(plafh);
166
167 /* Display all the IO cards. */
168 (void) sun4v_display_pci(plafh);
169 sun4v_display_diaginfo((log || (logging)), root, plafh);
170
171 if (picl_get_root(&rooth) != PICL_SUCCESS)
172 return (1);
173
174 /*
175 * The physical-platform node may be missing on systems with
176 * older firmware so don't consider that an error.
177 */
178 if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
179 &phyplatformh) != PICL_SUCCESS)
180 return (0);
181
182 if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
183 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
184 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
185 return (1);
186
187 syserrlog = log;
188 exit_code = sun4v_disp_env_status();
189 }
190 return (exit_code);
191 }
192
193 /*
194 * The binding-name property encodes the bus type.
195 */
196 static void
get_bus_type(picl_nodehdl_t nodeh,struct io_card * card)197 get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
198 {
199 char val[PICL_PROPNAMELEN_MAX], *p, *q;
200
201 card->bus_type[0] = '\0';
202
203 if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val,
204 sizeof (val)) == PICL_SUCCESS) {
205 if (strstr(val, PICL_CLASS_PCIEX))
206 (void) strlcpy(card->bus_type, "PCIE",
207 sizeof (card->bus_type));
208 else if (strstr(val, PICL_CLASS_PCI))
209 (void) strlcpy(card->bus_type, "PCIX",
210 sizeof (card->bus_type));
211 else {
212 /*
213 * Not perfect: process the binding-name until
214 * we encounter something that we don't think would
215 * be part of a bus type. This may get confused a bit
216 * if a device or vendor id is encoded right after
217 * the bus class since there's no delimiter. If the
218 * id number begins with a hex digit [abcdef] then
219 * this will become part of the bus type string
220 * reported by prtdiag. This is all an effort to
221 * print something potentially useful for bus types
222 * other than PCI/PCIe.
223 *
224 * We do this because this code will get called for
225 * non-PCI class devices like the xaui (class sun4v.)
226 */
227 if (strstr(val, "SUNW,") != NULL)
228 p = strchr(val, ',') + 1;
229 else
230 p = val;
231 q = p;
232 while (*p != '\0') {
233 if (isdigit((char)*p) || ispunct((char)*p)) {
234 *p = '\0';
235 break;
236 }
237 *p = (char)_toupper((int)*p);
238 ++p;
239 }
240 (void) strlcpy(card->bus_type, q,
241 sizeof (card->bus_type));
242 }
243 }
244 }
245
246 /*
247 * Fetch the Label property for this device. If none is found then
248 * search all the siblings with the same device ID for a
249 * Label and return that Label. The plug-in can only match the canonical
250 * path from the PRI with a specific devfs path. So we take care of
251 * devices with multiple functions here. A leaf device downstream of
252 * a bridge should fall out of here with PICL_PROPNOTFOUND, and the
253 * caller can walk back up the tree in search of the slot's Label.
254 */
255 static picl_errno_t
get_slot_label(picl_nodehdl_t nodeh,struct io_card * card)256 get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
257 {
258 char val[PICL_PROPNAMELEN_MAX];
259 picl_errno_t err;
260 picl_nodehdl_t pnodeh;
261 uint32_t devid, sib_devid;
262 int32_t instance;
263
264 /*
265 * If there's a Label at this node then return it - we're
266 * done.
267 */
268 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
269 sizeof (val));
270 if (err == PICL_SUCCESS) {
271 (void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
272 return (err);
273 } else if (err != PICL_PROPNOTFOUND)
274 return (err);
275
276 /*
277 * At this point we're starting to extrapolate what the Label
278 * should be since there is none at this specific node.
279 * Note that until the value of "err" is overwritten in the
280 * loop below, its value should be PICL_PROPNOTFOUND.
281 */
282
283 /*
284 * The device must be attached, and we can figure that out if
285 * the instance number is present and is not equal to -1.
286 * This will prevent is from returning a Label for a sibling
287 * node when the node passed in would have a unique Label if the
288 * device were attached. But if the device is downstream of a
289 * node with a Label then pci_callback() will still find that
290 * and use it.
291 */
292 if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance,
293 sizeof (instance)) != PICL_SUCCESS)
294 return (err);
295 if (instance == -1)
296 return (err);
297
298 /*
299 * Narrow the search to just the one device ID.
300 */
301 if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid,
302 sizeof (devid)) != PICL_SUCCESS)
303 return (err);
304
305 /*
306 * Go find the first child of the parent so we can search
307 * all of the siblings.
308 */
309 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
310 sizeof (pnodeh)) != PICL_SUCCESS)
311 return (err);
312 if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh,
313 sizeof (pnodeh)) != PICL_SUCCESS)
314 return (err);
315
316 /*
317 * If the child's device ID matches, then fetch the Label and
318 * return it. The first child/device ID should have a Label
319 * associated with it.
320 */
321 do {
322 if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID,
323 &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) {
324 if (sib_devid == devid) {
325 if ((err = picl_get_propval_by_name(pnodeh,
326 PICL_PROP_LABEL, val, sizeof (val))) ==
327 PICL_SUCCESS) {
328 (void) strlcpy(card->slot_str, val,
329 sizeof (card->slot_str));
330 break;
331 }
332 }
333 }
334 } while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh,
335 sizeof (pnodeh)) == PICL_SUCCESS);
336
337 return (err);
338 }
339
340 static void
get_slot_number(picl_nodehdl_t nodeh,struct io_card * card)341 get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
342 {
343 picl_errno_t err;
344 picl_prophdl_t proph;
345 picl_propinfo_t pinfo;
346 picl_nodehdl_t pnodeh;
347 uint8_t *pval;
348 uint32_t dev_mask;
349 char uaddr[MAXSTRLEN];
350 int i;
351
352 err = PICL_SUCCESS;
353 while (err == PICL_SUCCESS) {
354 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
355 sizeof (pnodeh)) != PICL_SUCCESS) {
356 (void) strlcpy(card->slot_str, MOTHERBOARD,
357 sizeof (card->slot_str));
358 card->slot = -1;
359 return;
360 }
361 if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
362 &pinfo, &proph) == PICL_SUCCESS) {
363 break;
364 }
365 nodeh = pnodeh;
366 }
367 if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
368 sizeof (uaddr)) != PICL_SUCCESS) {
369 (void) strlcpy(card->slot_str, MOTHERBOARD,
370 sizeof (card->slot_str));
371 card->slot = -1;
372 return;
373 }
374 pval = (uint8_t *)malloc(pinfo.size);
375 if (!pval) {
376 (void) strlcpy(card->slot_str, MOTHERBOARD,
377 sizeof (card->slot_str));
378 card->slot = -1;
379 return;
380 }
381 if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
382 (void) strlcpy(card->slot_str, MOTHERBOARD,
383 sizeof (card->slot_str));
384 card->slot = -1;
385 free(pval);
386 return;
387 }
388
389 dev_mask = 0;
390 for (i = 0; i < sizeof (dev_mask); i++)
391 dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
392 for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
393 if (uaddr[i] == ',') {
394 uaddr[i] = '\0';
395 break;
396 }
397 }
398 card->slot = atol(uaddr);
399 if (((1 << card->slot) & dev_mask) == 0) {
400 (void) strlcpy(card->slot_str, MOTHERBOARD,
401 sizeof (card->slot_str));
402 card->slot = -1;
403 } else {
404 char *p = (char *)(pval+sizeof (dev_mask));
405 int shift = sizeof (uint32_t)*8-1-card->slot;
406 uint32_t x = (dev_mask << shift) >> shift;
407 int count = 0; /* count # of 1's in x */
408 int i = 0;
409 while (x != 0) {
410 count++;
411 x &= x-1;
412 }
413 while (count > 1) {
414 while (p[i++] != '\0')
415 ;
416 count--;
417 }
418 (void) strlcpy(card->slot_str, (char *)(p+i),
419 sizeof (card->slot_str));
420 }
421 free(pval);
422 }
423
424 /*
425 * add all io devices under pci in io list
426 */
427 /* ARGSUSED */
428 static int
sun4v_pci_callback(picl_nodehdl_t pcih,void * args)429 sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
430 {
431 char path[PICL_PROPNAMELEN_MAX];
432 char class[PICL_CLASSNAMELEN_MAX];
433 char name[PICL_PROPNAMELEN_MAX];
434 char model[PICL_PROPNAMELEN_MAX];
435 char binding_name[PICL_PROPNAMELEN_MAX];
436 char val[PICL_PROPNAMELEN_MAX];
437 char *compatible;
438 picl_errno_t err;
439 picl_nodehdl_t nodeh, pnodeh;
440 struct io_card pci_card;
441
442 /* Walk through the children */
443
444 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
445 sizeof (picl_nodehdl_t));
446
447 while (err == PICL_SUCCESS) {
448 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
449 class, sizeof (class));
450 if (err != PICL_SUCCESS)
451 return (err);
452
453 if (args) {
454 char *val = args;
455 if (strcmp(class, val) == 0) {
456 err = picl_get_propval_by_name(nodeh,
457 PICL_PROP_PEER, &nodeh,
458 sizeof (picl_nodehdl_t));
459 continue;
460 } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
461 strcmp(class, PICL_CLASS_PCI) == 0) {
462 err = picl_get_propval_by_name(nodeh,
463 PICL_PROP_PEER, &nodeh,
464 sizeof (picl_nodehdl_t));
465 continue;
466 } else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
467 strcmp(class, PICL_CLASS_PCIEX) == 0) {
468 err = picl_get_propval_by_name(nodeh,
469 PICL_PROP_PEER, &nodeh,
470 sizeof (picl_nodehdl_t));
471 continue;
472 }
473 }
474
475 err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
476 path, sizeof (path));
477 if (err != PICL_SUCCESS)
478 return (err);
479
480 (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
481
482 pnodeh = nodeh;
483 err = get_slot_label(nodeh, &pci_card);
484
485 /*
486 * No Label at this node, maybe we're looking at a device
487 * downstream of a bridge. Walk back up and find a Label and
488 * record that node in "pnodeh".
489 */
490 while (err != PICL_SUCCESS) {
491 if (err != PICL_PROPNOTFOUND)
492 break;
493 else if (picl_get_propval_by_name(pnodeh,
494 PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) ==
495 PICL_SUCCESS)
496 err = get_slot_label(pnodeh, &pci_card);
497 else
498 break;
499 }
500
501 /*
502 * Can't find a Label for this device in the PCI heirarchy.
503 * Try to synthesize a slot name from atoms. This depends
504 * on the OBP slot_names property being implemented, and this
505 * so far doesn't seem to be on sun4v. But just in case that
506 * is resurrected, the code is here.
507 */
508 if (err != PICL_SUCCESS) {
509 pnodeh = nodeh;
510 get_slot_number(nodeh, &pci_card);
511 }
512
513 /*
514 * Passing in pnodeh instead of nodeh will cause prtdiag
515 * to display the type of IO slot for the leaf node. For
516 * built-in devices and a lot of IO cards these will be
517 * the same thing. But for IO cards with bridge chips or
518 * for things like expansion chassis, prtdiag will report
519 * the bus type of the IO slot and not the leaf, which
520 * could be different things.
521 */
522 get_bus_type(pnodeh, &pci_card);
523
524 err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
525 sizeof (name));
526 if (err == PICL_PROPNOTFOUND)
527 (void) strlcpy(name, "", sizeof (name));
528 else if (err != PICL_SUCCESS)
529 return (err);
530
531 err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
532 sizeof (val));
533 if (err == PICL_PROPNOTFOUND)
534 (void) strlcpy(val, "", sizeof (val));
535 else if (err != PICL_SUCCESS)
536 return (err);
537
538 (void) snprintf(pci_card.status, sizeof (pci_card.status),
539 "%s", pci_card.slot_str);
540
541 /*
542 * Get the name of this card. If binding_name is found,
543 * name will be <nodename>-<binding_name>.
544 */
545 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
546 binding_name, sizeof (binding_name));
547 if (err == PICL_SUCCESS) {
548 if (strcmp(name, binding_name) != 0) {
549 (void) strlcat(name, "-", sizeof (name));
550 (void) strlcat(name, binding_name,
551 sizeof (name));
552 }
553 } else if (err == PICL_PROPNOTFOUND) {
554 /*
555 * if compatible prop is not found, name will be
556 * <nodename>-<compatible>
557 */
558 err = sun4v_get_first_compatible_value(nodeh,
559 &compatible);
560 if (err == PICL_SUCCESS) {
561 (void) strlcat(name, "-", sizeof (name));
562 (void) strlcat(name, compatible,
563 sizeof (name));
564 free(compatible);
565 }
566 } else
567 return (err);
568
569 (void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
570
571 /* Get the model of this card */
572
573 err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
574 model, sizeof (model));
575 if (err == PICL_PROPNOTFOUND)
576 (void) strlcpy(model, "", sizeof (model));
577 else if (err != PICL_SUCCESS)
578 return (err);
579 (void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
580
581 /* Print NAC name */
582 log_printf("%-18s", pci_card.status);
583 /* Print IO Type */
584 log_printf("%-6s", pci_card.bus_type);
585 /* Printf Card Name */
586 log_printf("%-34s", pci_card.name);
587 /* Print Card Model */
588 log_printf("%-8s", pci_card.model);
589 log_printf("\n");
590 /* Print Status */
591 log_printf("%-18s", val);
592 /* Print IO Type */
593 log_printf("%-6s", "");
594 /* Print Parent Path */
595 log_printf("%-44s", pci_card.notes);
596 log_printf("\n");
597
598 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
599 sizeof (picl_nodehdl_t));
600 }
601 return (PICL_WALK_CONTINUE);
602 }
603
604 /*
605 * display_pci
606 * Display all the PCI IO cards on this board.
607 */
608 void
sun4v_display_pci(picl_nodehdl_t plafh)609 sun4v_display_pci(picl_nodehdl_t plafh)
610 {
611 char *fmt = "%-17s %-5s %-33s %-8s";
612 /* Have we printed the column headings? */
613 static int banner = FALSE;
614
615 if (banner == FALSE) {
616 log_printf("\n");
617 log_printf("================================");
618 log_printf(" IO Devices ");
619 log_printf("================================");
620 log_printf("\n");
621 log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
622 log_printf("\n");
623 log_printf(fmt, "Status", "Type", "Path", "", 0);
624 log_printf("\n");
625 log_printf("---------------------------------"
626 "-------------------------------------------\n");
627 banner = TRUE;
628 }
629
630 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
631 PICL_CLASS_PCIEX, sun4v_pci_callback);
632 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
633 PICL_CLASS_PCI, sun4v_pci_callback);
634 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
635 PICL_CLASS_SUN4V, sun4v_pci_callback);
636 }
637
638 /*
639 * return the first compatible value
640 */
641 static int
sun4v_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)642 sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
643 {
644 picl_errno_t err;
645 picl_prophdl_t proph;
646 picl_propinfo_t pinfo;
647 picl_prophdl_t tblh;
648 picl_prophdl_t rowproph;
649 char *pval;
650
651 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
652 &pinfo, &proph);
653 if (err != PICL_SUCCESS)
654 return (err);
655
656 if (pinfo.type == PICL_PTYPE_CHARSTRING) {
657 pval = malloc(pinfo.size);
658 if (pval == NULL)
659 return (PICL_FAILURE);
660 err = picl_get_propval(proph, pval, pinfo.size);
661 if (err != PICL_SUCCESS) {
662 free(pval);
663 return (err);
664 }
665 *outbuf = pval;
666 return (PICL_SUCCESS);
667 }
668
669 if (pinfo.type != PICL_PTYPE_TABLE)
670 return (PICL_FAILURE);
671
672 /* get first string from table */
673 err = picl_get_propval(proph, &tblh, pinfo.size);
674 if (err != PICL_SUCCESS)
675 return (err);
676
677 err = picl_get_next_by_row(tblh, &rowproph);
678 if (err != PICL_SUCCESS)
679 return (err);
680
681 err = picl_get_propinfo(rowproph, &pinfo);
682 if (err != PICL_SUCCESS)
683 return (err);
684
685 pval = malloc(pinfo.size);
686 if (pval == NULL)
687 return (PICL_FAILURE);
688
689 err = picl_get_propval(rowproph, pval, pinfo.size);
690 if (err != PICL_SUCCESS) {
691 free(pval);
692 return (err);
693 }
694
695 *outbuf = pval;
696 return (PICL_SUCCESS);
697 }
698
699 /*
700 * print size of a memory segment
701 */
702 static void
print_memory_segment_size(uint64_t size)703 print_memory_segment_size(uint64_t size)
704 {
705 uint64_t kbyte = 1024;
706 uint64_t mbyte = kbyte * kbyte;
707 uint64_t gbyte = kbyte * mbyte;
708 uint64_t tbyte = kbyte * gbyte;
709 char buf[MEMORY_SIZE_FIELD];
710
711 if (size >= tbyte) {
712 if (size % tbyte == 0)
713 (void) snprintf(buf, sizeof (buf), "%d TB",
714 (int)(size / tbyte));
715 else
716 (void) snprintf(buf, sizeof (buf), "%.2f TB",
717 (float)size / tbyte);
718 } else if (size >= gbyte) {
719 if (size % gbyte == 0)
720 (void) snprintf(buf, sizeof (buf), "%d GB",
721 (int)(size / gbyte));
722 else
723 (void) snprintf(buf, sizeof (buf), "%.2f GB",
724 (float)size / gbyte);
725 } else if (size >= mbyte) {
726 if (size % mbyte == 0)
727 (void) snprintf(buf, sizeof (buf), "%d MB",
728 (int)(size / mbyte));
729 else
730 (void) snprintf(buf, sizeof (buf), "%.2f MB",
731 (float)size / mbyte);
732 } else {
733 if (size % kbyte == 0)
734 (void) snprintf(buf, sizeof (buf), "%d KB",
735 (int)(size / kbyte));
736 else
737 (void) snprintf(buf, sizeof (buf), "%.2f KB",
738 (float)size / kbyte);
739 }
740 log_printf("%-9s", buf);
741 }
742
743 /*
744 * Enumerate banks and dimms within a memory segment. We're handed
745 * the first bank within the segment - we assume there are dimms
746 * (memory-module) nodes underneath.
747 */
748 static void
print_memory_segment_contain(picl_nodehdl_t bank_nodeh)749 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
750 {
751 char val[PICL_PROPNAMELEN_MAX];
752 picl_nodehdl_t module_nodeh;
753 int flag = 0;
754 uint64_t size;
755
756 do {
757 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
758 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
759 continue;
760 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE,
761 &size, sizeof (size)) == PICL_SUCCESS) {
762 if (!flag) {
763 print_memory_segment_size(size);
764 } else {
765 log_printf(" "
766 " ");
767 print_memory_segment_size(size);
768 flag = 0;
769 }
770 }
771 do {
772 if (picl_get_propval_by_name(module_nodeh,
773 PICL_PROP_NAC, val, sizeof (val)) !=
774 PICL_SUCCESS)
775 continue;
776 else {
777 if (!flag) {
778 log_printf("%s\n", val);
779 flag = 1;
780 } else {
781 log_printf("%s%s\n",
782 " "
783 " ",
784 val);
785 }
786 }
787 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
788 &module_nodeh, sizeof (picl_nodehdl_t)) ==
789 PICL_SUCCESS);
790 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
791 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
792 }
793
794 /*
795 * Search node where _class=="memory-segment"
796 * print "Base Address", "Size", etc
797 */
798 /*ARGSUSED*/
799 static int
sun4v_memory_conf_callback(picl_nodehdl_t nodeh,void * args)800 sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
801 {
802 uint64_t base;
803 uint64_t size;
804 uint64_t ifactor;
805 picl_errno_t err = PICL_SUCCESS;
806
807 if (class_node_found == 0) {
808 class_node_found = 1;
809 return (PICL_WALK_TERMINATE);
810 }
811 while (err == PICL_SUCCESS) {
812 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
813 &base, sizeof (base));
814 if (err != PICL_SUCCESS)
815 break;
816 err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
817 &size, sizeof (size));
818 if (err != PICL_SUCCESS)
819 break;
820 err = picl_get_propval_by_name(nodeh,
821 PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
822 sizeof (ifactor));
823 if (err != PICL_SUCCESS)
824 break;
825 log_printf("0x%-13llx", base);
826 print_memory_segment_size(size);
827 log_printf("%-12lld", ifactor);
828 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
829 &nodeh, sizeof (nodeh));
830 if (err == PICL_SUCCESS)
831 print_memory_segment_contain(nodeh);
832 log_printf("\n");
833 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
834 sizeof (picl_nodehdl_t));
835 }
836
837 return (PICL_WALK_CONTINUE);
838 }
839
840 /*ARGSUSED*/
841 void
sun4v_display_memory_conf(picl_nodehdl_t plafh)842 sun4v_display_memory_conf(picl_nodehdl_t plafh)
843 {
844 char *fmt = "%-14s %-8s %-11s %-8s %-s";
845 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
846 NULL, sun4v_memory_conf_callback);
847 if (class_node_found == 0)
848 return;
849 log_printf("\n");
850 log_printf("=======================");
851 log_printf(" Physical Memory Configuration ");
852 log_printf("========================");
853 log_printf("\n");
854 log_printf("Segment Table:\n");
855 log_printf(
856 "--------------------------------------------------------------\n");
857 log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0);
858 log_printf("\n");
859 log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0);
860 log_printf("\n");
861 log_printf(
862 "--------------------------------------------------------------\n");
863 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
864 NULL, sun4v_memory_conf_callback);
865 }
866
867 void
sun4v_display_cpu_devices(picl_nodehdl_t plafh)868 sun4v_display_cpu_devices(picl_nodehdl_t plafh)
869 {
870 char *fmt = "%-6s %-9s %-22s %-6s";
871
872 /*
873 * Display the table header for CPUs . Then display the CPU
874 * frequency, cache size, and processor revision of all cpus.
875 */
876 log_printf(dgettext(TEXT_DOMAIN,
877 "\n"
878 "================================"
879 " Virtual CPUs "
880 "================================"
881 "\n"
882 "\n"));
883 log_printf("\n");
884 log_printf(fmt, "CPU ID", "Frequency", "Implementation",
885 "Status", 0);
886 log_printf("\n");
887 log_printf(fmt, "------", "---------",
888 "----------------------", "-------", 0);
889 log_printf("\n");
890
891 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
892 sun4v_display_cpus);
893 }
894
895 /*
896 * Display the CPUs present on this board.
897 */
898 /*ARGSUSED*/
899 int
sun4v_display_cpus(picl_nodehdl_t cpuh,void * args)900 sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
901 {
902 int status;
903 picl_prophdl_t proph;
904 picl_prophdl_t tblh;
905 picl_prophdl_t rowproph;
906 picl_propinfo_t propinfo;
907 int *int_value;
908 int cpuid;
909 char *comp_value;
910 char *no_prop_value = " ";
911 char freq_str[MAXSTRLEN];
912 char state[MAXSTRLEN];
913
914 /*
915 * Get cpuid property and print it and the NAC name
916 */
917 status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo,
918 &proph);
919 if (status == PICL_SUCCESS) {
920 status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
921 if (status != PICL_SUCCESS) {
922 log_printf("%-7s", no_prop_value);
923 } else {
924 log_printf("%-7d", cpuid);
925 }
926 } else {
927 log_printf("%-7s", no_prop_value);
928 }
929
930 clock_freq:
931 status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
932 &proph);
933 if (status == PICL_SUCCESS) {
934 int_value = malloc(propinfo.size);
935 if (int_value == NULL) {
936 log_printf("%-10s", no_prop_value);
937 goto compatible;
938 }
939 status = picl_get_propval(proph, int_value, propinfo.size);
940 if (status != PICL_SUCCESS) {
941 log_printf("%-10s", no_prop_value);
942 } else {
943 /* Running frequency */
944 (void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
945 CLK_FREQ_TO_MHZ(*int_value));
946 log_printf("%-10s", freq_str);
947 }
948 free(int_value);
949 } else
950 log_printf("%-10s", no_prop_value);
951
952 compatible:
953 status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
954 &proph);
955 if (status == PICL_SUCCESS) {
956 if (propinfo.type == PICL_PTYPE_CHARSTRING) {
957 /*
958 * Compatible Property only has 1 value
959 */
960 comp_value = malloc(propinfo.size);
961 if (comp_value == NULL) {
962 log_printf("%-23s", no_prop_value, 0);
963 goto state;
964 }
965 status = picl_get_propval(proph, comp_value,
966 propinfo.size);
967 if (status != PICL_SUCCESS)
968 log_printf("%-23s", no_prop_value, 0);
969 else
970 log_printf("%-23s", comp_value, 0);
971 free(comp_value);
972 } else if (propinfo.type == PICL_PTYPE_TABLE) {
973 /*
974 * Compatible Property has multiple values
975 */
976 status = picl_get_propval(proph, &tblh, propinfo.size);
977 if (status != PICL_SUCCESS) {
978 log_printf("%-23s", no_prop_value, 0);
979 goto state;
980 }
981 status = picl_get_next_by_row(tblh, &rowproph);
982 if (status != PICL_SUCCESS) {
983 log_printf("%-23s", no_prop_value, 0);
984 goto state;
985 }
986
987 status = picl_get_propinfo(rowproph, &propinfo);
988 if (status != PICL_SUCCESS) {
989 log_printf("%-23s", no_prop_value, 0);
990 goto state;
991 }
992
993 comp_value = malloc(propinfo.size);
994 if (comp_value == NULL) {
995 log_printf("%-23s", no_prop_value, 0);
996 goto state;
997 }
998 status = picl_get_propval(rowproph, comp_value,
999 propinfo.size);
1000 if (status != PICL_SUCCESS)
1001 log_printf("%-23s", no_prop_value, 0);
1002 else
1003 log_printf("%-23s", comp_value, 0);
1004 free(comp_value);
1005 }
1006 } else
1007 log_printf("%-23s", no_prop_value, 0);
1008
1009 state:
1010 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE,
1011 &propinfo, &proph);
1012 if (status == PICL_SUCCESS) {
1013 status = picl_get_propval(proph, state, sizeof (state));
1014 if (status != PICL_SUCCESS) {
1015 log_printf("%-9s", no_prop_value);
1016 } else {
1017 log_printf("%-9s", state);
1018 }
1019 } else
1020 log_printf("%-9s", no_prop_value);
1021
1022 done:
1023 log_printf("\n");
1024 return (PICL_WALK_CONTINUE);
1025 }
1026
1027 void
sun4v_display_diaginfo(int flag,Prom_node * root,picl_nodehdl_t plafh)1028 sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
1029 {
1030 #ifdef lint
1031 flag = flag;
1032 root = root;
1033 plafh = plafh;
1034 #endif
1035 /*
1036 * This function is intentionally empty
1037 */
1038 }
1039
1040 void
display_boardnum(int num)1041 display_boardnum(int num)
1042 {
1043 log_printf("%2d ", num, 0);
1044 }
1045
1046 static int
sun4v_disp_env_status()1047 sun4v_disp_env_status()
1048 {
1049 int exit_code = 0;
1050
1051 if (phyplatformh == 0)
1052 return (0);
1053 log_printf("\n");
1054 log_printf("============================");
1055 log_printf(" Environmental Status ");
1056 log_printf("============================");
1057 log_printf("\n");
1058
1059 class_node_found = 0;
1060 all_status_ok = 1;
1061 sun4v_env_print_fan_sensors();
1062 exit_code |= (!all_status_ok);
1063
1064 class_node_found = 0;
1065 all_status_ok = 1;
1066 sun4v_env_print_fan_indicators();
1067 exit_code |= (!all_status_ok);
1068
1069 class_node_found = 0;
1070 all_status_ok = 1;
1071 sun4v_env_print_temp_sensors();
1072 exit_code |= (!all_status_ok);
1073
1074 class_node_found = 0;
1075 all_status_ok = 1;
1076 sun4v_env_print_temp_indicators();
1077 exit_code |= (!all_status_ok);
1078
1079 class_node_found = 0;
1080 all_status_ok = 1;
1081 sun4v_env_print_current_sensors();
1082 exit_code |= (!all_status_ok);
1083
1084 class_node_found = 0;
1085 all_status_ok = 1;
1086 sun4v_env_print_current_indicators();
1087 exit_code |= (!all_status_ok);
1088
1089 class_node_found = 0;
1090 all_status_ok = 1;
1091 sun4v_env_print_voltage_sensors();
1092 exit_code |= (!all_status_ok);
1093
1094 class_node_found = 0;
1095 all_status_ok = 1;
1096 sun4v_env_print_voltage_indicators();
1097 exit_code |= (!all_status_ok);
1098
1099 class_node_found = 0;
1100 all_status_ok = 1;
1101 sun4v_env_print_LEDs();
1102 exit_code |= (!all_status_ok);
1103
1104 class_node_found = 0;
1105 all_status_ok = 1;
1106 sun4v_print_fru_status();
1107 exit_code |= (!all_status_ok);
1108
1109 class_node_found = 0;
1110 sun4v_print_fw_rev();
1111
1112 class_node_found = 0;
1113 sun4v_print_openprom_rev();
1114
1115 sun4v_print_chassis_serial_no();
1116
1117 return (exit_code);
1118 }
1119
1120 /*ARGSUSED*/
1121 static int
sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh,void * args)1122 sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
1123 {
1124 char val[PICL_PROPNAMELEN_MAX];
1125 picl_nodehdl_t parenth;
1126 char *names[PARENT_NAMES];
1127 char *base_units[PICL_PROPNAMELEN_MAX];
1128 char *loc;
1129 int i;
1130 char *prop;
1131 picl_errno_t err;
1132 int32_t lo_warning, lo_shutdown, lo_poweroff;
1133 int32_t hi_warning, hi_shutdown, hi_poweroff;
1134 int32_t current_val;
1135 int32_t exponent;
1136 double display_val;
1137 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
1138 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
1139 sensor_status_t sensor_status = SENSOR_OK;
1140
1141 if (class_node_found == 0) {
1142 class_node_found = 1;
1143 return (PICL_WALK_TERMINATE);
1144 }
1145
1146 prop = (char *)args;
1147 if (!prop) {
1148 sensor_status = SENSOR_UNKNOWN;
1149 all_status_ok = 0;
1150 } else {
1151 err = picl_get_propval_by_name(nodeh,
1152 PICL_PROP_OPERATIONAL_STATUS, val,
1153 sizeof (val));
1154 if (err == PICL_SUCCESS) {
1155 if (strcmp(val, "disabled") == 0) {
1156 sensor_status = SENSOR_DISABLED;
1157 }
1158 }
1159 }
1160
1161 if (sensor_status != SENSOR_DISABLED &&
1162 sensor_status != SENSOR_UNKNOWN) {
1163 if (picl_get_propval_by_name(nodeh, prop, ¤t_val,
1164 sizeof (current_val)) != PICL_SUCCESS) {
1165 sensor_status = SENSOR_UNKNOWN;
1166 } else {
1167 if (picl_get_propval_by_name(nodeh,
1168 PICL_PROP_LOW_WARNING,
1169 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
1170 lo_warning = INVALID_THRESHOLD;
1171 if (picl_get_propval_by_name(nodeh,
1172 PICL_PROP_LOW_SHUTDOWN,
1173 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
1174 lo_shutdown = INVALID_THRESHOLD;
1175 if (picl_get_propval_by_name(nodeh,
1176 PICL_PROP_LOW_POWER_OFF,
1177 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS)
1178 lo_poweroff = INVALID_THRESHOLD;
1179 if (picl_get_propval_by_name(nodeh,
1180 PICL_PROP_HIGH_WARNING,
1181 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
1182 hi_warning = INVALID_THRESHOLD;
1183 if (picl_get_propval_by_name(nodeh,
1184 PICL_PROP_HIGH_SHUTDOWN,
1185 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
1186 hi_shutdown = INVALID_THRESHOLD;
1187 if (picl_get_propval_by_name(nodeh,
1188 PICL_PROP_HIGH_POWER_OFF,
1189 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS)
1190 hi_poweroff = INVALID_THRESHOLD;
1191
1192 if ((lo_poweroff != INVALID_THRESHOLD &&
1193 current_val <= lo_poweroff) ||
1194 (hi_poweroff != INVALID_THRESHOLD &&
1195 current_val >= hi_poweroff)) {
1196 sensor_status = SENSOR_FAILED;
1197 } else if ((lo_shutdown != INVALID_THRESHOLD &&
1198 current_val <= lo_shutdown) ||
1199 (hi_shutdown != INVALID_THRESHOLD &&
1200 current_val >= hi_shutdown)) {
1201 sensor_status = SENSOR_FAILED;
1202 } else if ((lo_warning != INVALID_THRESHOLD &&
1203 current_val <= lo_warning) ||
1204 (hi_warning != INVALID_THRESHOLD &&
1205 current_val >= hi_warning)) {
1206 sensor_status = SENSOR_WARN;
1207 } else {
1208 sensor_status = SENSOR_OK;
1209 }
1210 }
1211 }
1212
1213 if (syserrlog == 0) {
1214 if (sensor_status != SENSOR_OK && all_status_ok == 1) {
1215 all_status_ok = 0;
1216 return (PICL_WALK_TERMINATE);
1217 }
1218 if (sensor_status == SENSOR_OK) {
1219 return (PICL_WALK_CONTINUE);
1220 }
1221 } else {
1222 if (sensor_status != SENSOR_OK && all_status_ok == 1) {
1223 all_status_ok = 0;
1224 }
1225 }
1226
1227 /*
1228 * If we're here then prtdiag was invoked with "-v" or we have
1229 * a sensor that is beyond a threshold, so give them a book to
1230 * read instead of the Cliff Notes.
1231 */
1232 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1233 sizeof (parenth));
1234 if (err != PICL_SUCCESS) {
1235 log_printf("\n");
1236 return (PICL_WALK_CONTINUE);
1237 }
1238
1239 /* gather up the path name for the sensor */
1240 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
1241 for (i = 0; i < PARENT_NAMES; i++) {
1242 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
1243 NULL) {
1244 while (--i > -1)
1245 free(names[i]);
1246 free(loc);
1247 loc = NULL;
1248 }
1249 }
1250 }
1251 i = 0;
1252 if (loc != 0) {
1253 while (err == PICL_SUCCESS) {
1254 if (parenth == phyplatformh)
1255 break;
1256 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1257 names[i++], PICL_PROPNAMELEN_MAX);
1258 if (err != PICL_SUCCESS) {
1259 i--;
1260 break;
1261 }
1262 if (i == PARENT_NAMES)
1263 break;
1264 err = picl_get_propval_by_name(parenth,
1265 PICL_PROP_PARENT, &parenth, sizeof (parenth));
1266 }
1267 loc[0] = '\0';
1268 if (--i > -1) {
1269 (void) strlcat(loc, names[i],
1270 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1271 }
1272 while (--i > -1) {
1273 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
1274 PARENT_NAMES);
1275 (void) strlcat(loc, names[i],
1276 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1277 }
1278 log_printf("%-35s", loc);
1279 for (i = 0; i < PARENT_NAMES; i++)
1280 free(names[i]);
1281 free(loc);
1282 } else {
1283 log_printf("%-35s", " ");
1284 }
1285 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1286 sizeof (val));
1287 if (err == PICL_SUCCESS)
1288 log_printf("%-19s", val);
1289
1290 /*
1291 * Get the exponent if present, and do a little math so that
1292 * if we need to we can print a normalized value for the
1293 * sensor reading.
1294 */
1295 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT,
1296 &exponent, sizeof (exponent)) != PICL_SUCCESS)
1297 exponent = 0;
1298 if (exponent == 0)
1299 display_val = (double)current_val;
1300 else {
1301 display_val = (double)current_val *
1302 pow((double)10, (double)exponent);
1303
1304 /*
1305 * Sometimes ILOM will scale a sensor reading but
1306 * there will be nothing to the right of the decimal
1307 * once that value is normalized. Setting the
1308 * exponent to zero will prevent the printf below
1309 * from printing extraneous zeros. Otherwise a
1310 * negative exponent is used to set the precision
1311 * for the printf.
1312 */
1313 if ((int)display_val == display_val || exponent > 0)
1314 exponent = 0;
1315 }
1316
1317 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS,
1318 base_units, sizeof (base_units));
1319 if (err != PICL_SUCCESS)
1320 base_units[0] = '\0';
1321
1322 switch (sensor_status) {
1323 case SENSOR_FAILED:
1324 log_printf("%-s", "failed (");
1325 log_printf("%-.*f", abs(exponent), display_val);
1326 log_printf("%-s %s", base_units, ")");
1327 break;
1328 case SENSOR_WARN:
1329 log_printf("%-s", "warning (");
1330 log_printf("%-.*f", abs(exponent), display_val);
1331 log_printf("%-s %s", base_units, ")");
1332 break;
1333 case SENSOR_DISABLED:
1334 log_printf("%-s", "disabled");
1335 break;
1336 case SENSOR_OK:
1337 log_printf("%-s", "ok");
1338 break;
1339 default:
1340 log_printf("%-s", "unknown");
1341 break;
1342 }
1343
1344 log_printf("\n");
1345 return (PICL_WALK_CONTINUE);
1346 }
1347
1348 /*ARGSUSED*/
1349 static int
sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh,void * args)1350 sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
1351 {
1352 char current_val[PICL_PROPNAMELEN_MAX];
1353 char expected_val[PICL_PROPNAMELEN_MAX];
1354 char label[PICL_PROPNAMELEN_MAX];
1355 picl_nodehdl_t parenth;
1356 char *names[PARENT_NAMES];
1357 char *loc;
1358 int i = 0;
1359 char *prop = (char *)args;
1360 picl_errno_t err = PICL_SUCCESS;
1361 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
1362 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
1363 sensor_status_t sensor_status = SENSOR_OK;
1364
1365 if (class_node_found == 0) {
1366 class_node_found = 1;
1367 return (PICL_WALK_TERMINATE);
1368 }
1369
1370 prop = (char *)args;
1371 if (!prop) {
1372 sensor_status = SENSOR_UNKNOWN;
1373 all_status_ok = 0;
1374 } else {
1375 err = picl_get_propval_by_name(nodeh,
1376 PICL_PROP_OPERATIONAL_STATUS, current_val,
1377 sizeof (current_val));
1378 if (err == PICL_SUCCESS) {
1379 if (strcmp(current_val, "disabled") == 0) {
1380 sensor_status = SENSOR_DISABLED;
1381 }
1382 }
1383 }
1384
1385 if (sensor_status != SENSOR_DISABLED &&
1386 sensor_status != SENSOR_UNKNOWN) {
1387 if (picl_get_propval_by_name(nodeh, prop, ¤t_val,
1388 sizeof (current_val)) != PICL_SUCCESS) {
1389 (void) strlcpy(current_val, "unknown",
1390 sizeof (current_val));
1391 sensor_status = SENSOR_UNKNOWN;
1392 } else {
1393 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED,
1394 &expected_val, sizeof (expected_val)) ==
1395 PICL_SUCCESS) {
1396 if (strncmp(current_val, expected_val,
1397 sizeof (current_val)) == 0) {
1398 sensor_status = SENSOR_OK;
1399 } else {
1400 sensor_status = SENSOR_FAILED;
1401 }
1402 }
1403 }
1404 }
1405
1406 if (syserrlog == 0) {
1407 if (sensor_status != SENSOR_OK && all_status_ok == 1) {
1408 all_status_ok = 0;
1409 return (PICL_WALK_TERMINATE);
1410 }
1411 if (sensor_status == SENSOR_OK) {
1412 return (PICL_WALK_CONTINUE);
1413 }
1414 } else {
1415 if (sensor_status != SENSOR_OK && all_status_ok == 1) {
1416 all_status_ok = 0;
1417 }
1418 }
1419
1420 /*
1421 * If we're here then prtdiag was invoked with "-v" or we have
1422 * a sensor that is beyond a threshold, so give them a book to
1423 * read instead of the Cliff Notes.
1424 */
1425 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1426 sizeof (parenth));
1427 if (err != PICL_SUCCESS) {
1428 log_printf("\n");
1429 return (PICL_WALK_CONTINUE);
1430 }
1431 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
1432 for (i = 0; i < PARENT_NAMES; i++) {
1433 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
1434 NULL) {
1435 while (--i > -1)
1436 free(names[i]);
1437 free(loc);
1438 loc = NULL;
1439 }
1440 }
1441 }
1442 i = 0;
1443 if (loc) {
1444 while (err == PICL_SUCCESS) {
1445 if (parenth == phyplatformh)
1446 break;
1447 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1448 names[i++], PICL_PROPNAMELEN_MAX);
1449 if (err != PICL_SUCCESS) {
1450 i--;
1451 break;
1452 }
1453 if (i == PARENT_NAMES)
1454 break;
1455 err = picl_get_propval_by_name(parenth,
1456 PICL_PROP_PARENT, &parenth, sizeof (parenth));
1457 }
1458 loc[0] = '\0';
1459 if (--i > -1) {
1460 (void) strlcat(loc, names[i],
1461 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1462 }
1463 while (--i > -1) {
1464 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
1465 PARENT_NAMES);
1466 (void) strlcat(loc, names[i],
1467 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1468 }
1469 log_printf("%-35s", loc);
1470 for (i = 0; i < PARENT_NAMES; i++)
1471 free(names[i]);
1472 free(loc);
1473 } else {
1474 log_printf("%-35s", "");
1475 }
1476
1477 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1478 sizeof (label));
1479 if (err != PICL_SUCCESS)
1480 (void) strlcpy(label, "", sizeof (label));
1481 log_printf("%-19s", label);
1482
1483 log_printf("%-8s", current_val);
1484
1485 log_printf("\n");
1486 return (PICL_WALK_CONTINUE);
1487 }
1488
1489 static void
sun4v_env_print_fan_sensors()1490 sun4v_env_print_fan_sensors()
1491 {
1492 char *fmt = "%-34s %-18s %-10s\n";
1493 /*
1494 * If there isn't any fan sensor node, return now.
1495 */
1496 (void) picl_walk_tree_by_class(phyplatformh,
1497 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
1498 sun4v_env_print_sensor_callback);
1499 if (!class_node_found)
1500 return;
1501 log_printf("Fan sensors:\n");
1502 if (syserrlog == 0) {
1503 (void) picl_walk_tree_by_class(phyplatformh,
1504 PICL_CLASS_RPM_SENSOR,
1505 PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
1506 if (all_status_ok) {
1507 log_printf("All fan sensors are OK.\n");
1508 return;
1509 }
1510 }
1511 log_printf("-------------------------------------------------"
1512 "---------------\n");
1513 log_printf(fmt, "Location", "Sensor", "Status", 0);
1514 log_printf("-------------------------------------------------"
1515 "---------------\n");
1516 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
1517 PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
1518 }
1519
1520 static void
sun4v_env_print_fan_indicators()1521 sun4v_env_print_fan_indicators()
1522 {
1523 char *fmt = "%-34s %-18s %-10s\n";
1524 (void) picl_walk_tree_by_class(phyplatformh,
1525 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
1526 sun4v_env_print_indicator_callback);
1527 if (!class_node_found)
1528 return;
1529 log_printf("\nFan indicators:\n");
1530 if (syserrlog == 0) {
1531 (void) picl_walk_tree_by_class(phyplatformh,
1532 PICL_CLASS_RPM_INDICATOR,
1533 (void *)PICL_PROP_CONDITION,
1534 sun4v_env_print_indicator_callback);
1535 if (all_status_ok) {
1536 log_printf("All fan indicators are OK.\n");
1537 return;
1538 }
1539 }
1540 log_printf("-------------------------------------------------"
1541 "---------------\n");
1542 log_printf(fmt, "Location", "Sensor", "Condition", 0);
1543 log_printf("-------------------------------------------------"
1544 "---------------\n");
1545 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
1546 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback);
1547 }
1548
1549 static void
sun4v_env_print_temp_sensors()1550 sun4v_env_print_temp_sensors()
1551 {
1552 char *fmt = "%-34s %-18s %-10s\n";
1553 (void) picl_walk_tree_by_class(phyplatformh,
1554 PICL_CLASS_TEMPERATURE_SENSOR,
1555 (void *)PICL_PROP_TEMPERATURE,
1556 sun4v_env_print_sensor_callback);
1557 if (!class_node_found)
1558 return;
1559
1560 log_printf("\nTemperature sensors:\n");
1561 if (syserrlog == 0) {
1562 (void) picl_walk_tree_by_class(phyplatformh,
1563 PICL_CLASS_TEMPERATURE_SENSOR,
1564 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
1565 if (all_status_ok) {
1566 log_printf("All temperature sensors are OK.\n");
1567 return;
1568 }
1569 }
1570 log_printf("-------------------------------------------------"
1571 "---------------\n");
1572 log_printf(fmt, "Location", "Sensor", "Status", 0);
1573 log_printf("-------------------------------------------------"
1574 "---------------\n");
1575 (void) picl_walk_tree_by_class(phyplatformh,
1576 PICL_CLASS_TEMPERATURE_SENSOR,
1577 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
1578 }
1579
1580 static void
sun4v_env_print_temp_indicators()1581 sun4v_env_print_temp_indicators()
1582 {
1583 char *fmt = "%-34s %-18s %-8s\n";
1584 (void) picl_walk_tree_by_class(phyplatformh,
1585 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
1586 sun4v_env_print_indicator_callback);
1587 if (!class_node_found)
1588 return;
1589 log_printf("\nTemperature indicators:\n");
1590 if (syserrlog == 0) {
1591 (void) picl_walk_tree_by_class(phyplatformh,
1592 PICL_CLASS_TEMPERATURE_INDICATOR,
1593 (void *)PICL_PROP_CONDITION,
1594 sun4v_env_print_indicator_callback);
1595 if (all_status_ok) {
1596 log_printf("All temperature indicators are OK.\n");
1597 return;
1598 }
1599 }
1600 log_printf("-------------------------------------------------"
1601 "---------------\n");
1602 log_printf(fmt, "Location", "Indicator", "Condition", 0);
1603 log_printf("-------------------------------------------------"
1604 "---------------\n");
1605 (void) picl_walk_tree_by_class(phyplatformh,
1606 PICL_CLASS_TEMPERATURE_INDICATOR,
1607 (void *)PICL_PROP_CONDITION,
1608 sun4v_env_print_indicator_callback);
1609 }
1610
1611 static void
sun4v_env_print_current_sensors()1612 sun4v_env_print_current_sensors()
1613 {
1614 char *fmt = "%-34s %-18s %-10s\n";
1615 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
1616 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
1617 if (!class_node_found)
1618 return;
1619 log_printf("\nCurrent sensors:\n");
1620 if (syserrlog == 0) {
1621 (void) picl_walk_tree_by_class(phyplatformh,
1622 PICL_CLASS_CURRENT_SENSOR,
1623 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
1624 if (all_status_ok) {
1625 log_printf("All current sensors are OK.\n");
1626 return;
1627 }
1628 }
1629 log_printf("-------------------------------------------------"
1630 "---------------\n");
1631 log_printf(fmt, "Location", "Sensor", "Status", 0);
1632 log_printf("-------------------------------------------------"
1633 "---------------\n");
1634 (void) picl_walk_tree_by_class(phyplatformh,
1635 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
1636 sun4v_env_print_sensor_callback);
1637 }
1638
1639 static void
sun4v_env_print_current_indicators()1640 sun4v_env_print_current_indicators()
1641 {
1642 char *fmt = "%-34s %-18s %-8s\n";
1643 (void) picl_walk_tree_by_class(phyplatformh,
1644 PICL_CLASS_CURRENT_INDICATOR,
1645 (void *)PICL_PROP_CONDITION,
1646 sun4v_env_print_indicator_callback);
1647 if (!class_node_found)
1648 return;
1649 log_printf("\nCurrent indicators:\n");
1650 if (syserrlog == 0) {
1651 (void) picl_walk_tree_by_class(phyplatformh,
1652 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION,
1653 sun4v_env_print_indicator_callback);
1654 if (all_status_ok) {
1655 log_printf("All current indicators are OK.\n");
1656 return;
1657 }
1658 }
1659 log_printf("-------------------------------------------------"
1660 "---------------\n");
1661 log_printf(fmt, "Location", "Indicator", "Condition", 0);
1662 log_printf("-------------------------------------------------"
1663 "---------------\n");
1664 (void) picl_walk_tree_by_class(phyplatformh,
1665 PICL_CLASS_CURRENT_INDICATOR,
1666 (void *)PICL_PROP_CONDITION,
1667 sun4v_env_print_indicator_callback);
1668 }
1669
1670 static void
sun4v_env_print_voltage_sensors()1671 sun4v_env_print_voltage_sensors()
1672 {
1673 char *fmt = "%-34s %-18s %-10s\n";
1674 (void) picl_walk_tree_by_class(phyplatformh,
1675 PICL_CLASS_VOLTAGE_SENSOR,
1676 PICL_PROP_VOLTAGE,
1677 sun4v_env_print_sensor_callback);
1678 if (!class_node_found)
1679 return;
1680 log_printf("\nVoltage sensors:\n");
1681 if (syserrlog == 0) {
1682 (void) picl_walk_tree_by_class(phyplatformh,
1683 PICL_CLASS_VOLTAGE_SENSOR,
1684 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback);
1685 if (all_status_ok) {
1686 log_printf("All voltage sensors are OK.\n");
1687 return;
1688 }
1689 }
1690 log_printf("-------------------------------------------------"
1691 "---------------\n");
1692 log_printf(fmt, "Location", "Sensor", "Status", 0);
1693 log_printf("-------------------------------------------------"
1694 "---------------\n");
1695 (void) picl_walk_tree_by_class(phyplatformh,
1696 PICL_CLASS_VOLTAGE_SENSOR,
1697 (void *)PICL_PROP_VOLTAGE,
1698 sun4v_env_print_sensor_callback);
1699 }
1700
1701 static void
sun4v_env_print_voltage_indicators()1702 sun4v_env_print_voltage_indicators()
1703 {
1704 char *fmt = "%-34s %-18s %-8s\n";
1705 (void) picl_walk_tree_by_class(phyplatformh,
1706 PICL_CLASS_VOLTAGE_INDICATOR,
1707 (void *)PICL_PROP_CONDITION,
1708 sun4v_env_print_indicator_callback);
1709 if (!class_node_found)
1710 return;
1711 log_printf("\nVoltage indicators:\n");
1712 if (syserrlog == 0) {
1713 (void) picl_walk_tree_by_class(phyplatformh,
1714 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION,
1715 sun4v_env_print_indicator_callback);
1716 if (all_status_ok) {
1717 log_printf("All voltage indicators are OK.\n");
1718 return;
1719 }
1720 }
1721 log_printf("-------------------------------------------------"
1722 "---------------\n");
1723 log_printf(fmt, "Location", "Indicator", "Condition", 0);
1724 log_printf("-------------------------------------------------"
1725 "---------------\n");
1726 (void) picl_walk_tree_by_class(phyplatformh,
1727 PICL_CLASS_VOLTAGE_INDICATOR,
1728 (void *)PICL_PROP_CONDITION,
1729 sun4v_env_print_indicator_callback);
1730 }
1731
1732 static void
sun4v_env_print_LEDs()1733 sun4v_env_print_LEDs()
1734 {
1735 char *fmt = "%-34s %-18s %-8s\n";
1736 if (syserrlog == 0)
1737 return;
1738 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1739 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
1740 if (!class_node_found)
1741 return;
1742 log_printf("\nLEDs:\n");
1743 log_printf("-------------------------------------------------"
1744 "---------------\n");
1745 log_printf(fmt, "Location", "LED", "State", 0);
1746 log_printf("-------------------------------------------------"
1747 "---------------\n");
1748 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1749 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
1750 }
1751
1752 /*ARGSUSED*/
1753 static int
sun4v_print_fru_status_callback(picl_nodehdl_t nodeh,void * args)1754 sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
1755 {
1756 char label[PICL_PROPNAMELEN_MAX];
1757 char status[PICL_PROPNAMELEN_MAX];
1758 picl_errno_t err;
1759 picl_prophdl_t proph;
1760 picl_nodehdl_t parenth;
1761 char *names[PARENT_NAMES];
1762 char *loc;
1763 int i;
1764
1765 if (!class_node_found) {
1766 class_node_found = 1;
1767 return (PICL_WALK_TERMINATE);
1768 }
1769 err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
1770 if (err != PICL_SUCCESS)
1771 return (PICL_WALK_CONTINUE);
1772 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1773 sizeof (label));
1774 if (err != PICL_SUCCESS)
1775 return (PICL_WALK_CONTINUE);
1776 err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
1777 status, sizeof (status));
1778 if (err != PICL_SUCCESS)
1779 return (PICL_WALK_CONTINUE);
1780 if (syserrlog == 0) {
1781 if (strcmp(status, "disabled") == 0) {
1782 if (all_status_ok) {
1783 all_status_ok = 0;
1784 return (PICL_WALK_TERMINATE);
1785 }
1786 } else
1787 return (PICL_WALK_CONTINUE);
1788 } else {
1789 if (all_status_ok && (strcmp(status, "disabled") == 0)) {
1790 all_status_ok = 0;
1791 }
1792 }
1793
1794 if (is_fru_absent(nodeh))
1795 (void) strcpy(status, "Not present");
1796
1797 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1798 sizeof (parenth));
1799 if (err != PICL_SUCCESS) {
1800 log_printf("\n");
1801 return (PICL_WALK_CONTINUE);
1802 }
1803 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
1804 return (PICL_WALK_TERMINATE);
1805 for (i = 0; i < PARENT_NAMES; i++)
1806 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
1807 while (--i > -1)
1808 free(names[i]);
1809 free(loc);
1810 return (PICL_WALK_TERMINATE);
1811 }
1812 i = 0;
1813 while (err == PICL_SUCCESS) {
1814 if (parenth == phyplatformh)
1815 break;
1816 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1817 names[i++], PICL_PROPNAMELEN_MAX);
1818 if (err != PICL_SUCCESS) {
1819 i--;
1820 break;
1821 }
1822 if (i == PARENT_NAMES)
1823 break;
1824 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1825 &parenth, sizeof (parenth));
1826 }
1827 loc[0] = '\0';
1828 if (--i > -1) {
1829 (void) strlcat(loc, names[i],
1830 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1831 }
1832 while (--i > -1) {
1833 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1834 (void) strlcat(loc, names[i],
1835 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1836 }
1837 log_printf("%-35s", loc);
1838 for (i = 0; i < PARENT_NAMES; i++)
1839 free(names[i]);
1840 free(loc);
1841 log_printf("%-10s", label);
1842 log_printf("%-9s", status);
1843 log_printf("\n");
1844 return (PICL_WALK_CONTINUE);
1845 }
1846
1847 static void
sun4v_print_fru_status()1848 sun4v_print_fru_status()
1849 {
1850 char *fmt = "%-34s %-9s %-8s\n";
1851
1852 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1853 sun4v_print_fru_status_callback);
1854 if (!class_node_found)
1855 return;
1856
1857 log_printf("\n");
1858 log_printf("============================");
1859 log_printf(" FRU Status ");
1860 log_printf("============================");
1861 log_printf("\n");
1862
1863 if (syserrlog == 0) {
1864 (void) picl_walk_tree_by_class(phyplatformh,
1865 NULL, NULL,
1866 sun4v_print_fru_status_callback);
1867 if (all_status_ok) {
1868 log_printf("All FRUs are enabled.\n");
1869 return;
1870 }
1871 }
1872 log_printf(fmt, "Location", "Name", "Status", 0);
1873 log_printf("------------------------------------------------------\n");
1874 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1875 sun4v_print_fru_status_callback);
1876 }
1877
1878 /* Check the children of the FRU node for a presence indicator */
1879 static int
is_fru_absent(picl_nodehdl_t fruh)1880 is_fru_absent(picl_nodehdl_t fruh)
1881 {
1882 char class [PICL_CLASSNAMELEN_MAX];
1883 char condition [PICL_PROPNAMELEN_MAX];
1884 picl_errno_t err;
1885 picl_nodehdl_t nodeh;
1886
1887 err = picl_get_propval_by_name(fruh, PICL_PROP_CHILD, &nodeh,
1888 sizeof (picl_nodehdl_t));
1889 while (err == PICL_SUCCESS) {
1890 err = picl_get_propval_by_name(nodeh,
1891 PICL_PROP_CLASSNAME, class, sizeof (class));
1892 if (err == PICL_SUCCESS &&
1893 strcmp(class, "presence-indicator") == 0) {
1894 err = picl_get_propval_by_name(nodeh,
1895 PICL_PROP_CONDITION, condition,
1896 sizeof (condition));
1897 if (err == PICL_SUCCESS) {
1898 if (strcmp(condition, "Absent") == 0) {
1899 return (1);
1900 } else {
1901 return (0);
1902 }
1903 }
1904 }
1905 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
1906 &nodeh, sizeof (picl_nodehdl_t));
1907 }
1908 return (0);
1909 }
1910
1911 /*ARGSUSED*/
1912 static int
sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh,void * args)1913 sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
1914 {
1915 char rev[PICL_PROPNAMELEN_MAX];
1916 picl_errno_t err;
1917
1918 if (!class_node_found) {
1919 class_node_found = 1;
1920 return (PICL_WALK_TERMINATE);
1921 }
1922
1923 err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
1924 sizeof (rev));
1925 if (err != PICL_SUCCESS)
1926 return (PICL_WALK_CONTINUE);
1927 if (strlen(rev) == 0)
1928 return (PICL_WALK_CONTINUE);
1929 log_printf("%s", rev);
1930 log_printf("\n");
1931 return (PICL_WALK_CONTINUE);
1932 }
1933
1934 static void
sun4v_print_fw_rev()1935 sun4v_print_fw_rev()
1936 {
1937 if (syserrlog == 0)
1938 return;
1939
1940 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1941 sun4v_print_fw_rev_callback);
1942 if (!class_node_found)
1943 return;
1944
1945 log_printf("\n");
1946 log_printf("============================");
1947 log_printf(" FW Version ");
1948 log_printf("============================");
1949 log_printf("\n");
1950 log_printf("Version\n");
1951 log_printf("-------------------------------------------------"
1952 "-----------\n");
1953 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1954 sun4v_print_fw_rev_callback);
1955 }
1956
1957 static void
sun4v_print_openprom_rev()1958 sun4v_print_openprom_rev()
1959 {
1960 if (syserrlog == 0)
1961 return;
1962
1963 (void) picl_walk_tree_by_class(rooth, "openprom", NULL,
1964 openprom_callback);
1965 if (!class_node_found)
1966 return;
1967
1968 log_printf("\n");
1969 log_printf("======================");
1970 log_printf(" System PROM revisions ");
1971 log_printf("=======================");
1972 log_printf("\n");
1973 log_printf("Version\n");
1974 log_printf("-------------------------------------------------"
1975 "-----------\n");
1976 (void) picl_walk_tree_by_class(rooth, "openprom", NULL,
1977 openprom_callback);
1978 }
1979
1980 /*
1981 * display the OBP and POST prom revisions (if present)
1982 */
1983 /* ARGSUSED */
1984 static int
openprom_callback(picl_nodehdl_t openpromh,void * arg)1985 openprom_callback(picl_nodehdl_t openpromh, void *arg)
1986 {
1987 picl_prophdl_t proph;
1988 picl_prophdl_t tblh;
1989 picl_prophdl_t rowproph;
1990 picl_propinfo_t pinfo;
1991 char *prom_version = NULL;
1992 char *obp_version = NULL;
1993 int err;
1994
1995 if (!class_node_found) {
1996 class_node_found = 1;
1997 return (PICL_WALK_TERMINATE);
1998 }
1999
2000 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION,
2001 &pinfo, &proph);
2002 if (err == PICL_PROPNOTFOUND)
2003 return (PICL_WALK_TERMINATE);
2004 else if (err != PICL_SUCCESS)
2005 return (err);
2006
2007 /*
2008 * If it's a table prop, the first element is OBP revision
2009 * The second one is POST revision.
2010 * If it's a charstring prop, the value will be only OBP revision
2011 */
2012 if (pinfo.type == PICL_PTYPE_CHARSTRING) {
2013 prom_version = (char *)alloca(pinfo.size);
2014 if (prom_version == NULL)
2015 return (PICL_FAILURE);
2016 err = picl_get_propval(proph, prom_version, pinfo.size);
2017 if (err != PICL_SUCCESS)
2018 return (err);
2019 log_printf("%s\n", prom_version);
2020 }
2021
2022 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */
2023 return (PICL_WALK_TERMINATE);
2024
2025 err = picl_get_propval(proph, &tblh, pinfo.size);
2026 if (err != PICL_SUCCESS)
2027 return (err);
2028
2029 err = picl_get_next_by_row(tblh, &rowproph);
2030 if (err == PICL_SUCCESS) {
2031 /* get first row */
2032 err = picl_get_propinfo(rowproph, &pinfo);
2033 if (err != PICL_SUCCESS)
2034 return (err);
2035
2036 prom_version = (char *)alloca(pinfo.size);
2037 if (prom_version == NULL)
2038 return (PICL_FAILURE);
2039
2040 err = picl_get_propval(rowproph, prom_version, pinfo.size);
2041 if (err != PICL_SUCCESS)
2042 return (err);
2043 log_printf("%s\n", prom_version);
2044
2045 /* get second row */
2046 err = picl_get_next_by_col(rowproph, &rowproph);
2047 if (err == PICL_SUCCESS) {
2048 err = picl_get_propinfo(rowproph, &pinfo);
2049 if (err != PICL_SUCCESS)
2050 return (err);
2051
2052 obp_version = (char *)alloca(pinfo.size);
2053 if (obp_version == NULL)
2054 return (PICL_FAILURE);
2055 err = picl_get_propval(rowproph, obp_version,
2056 pinfo.size);
2057 if (err != PICL_SUCCESS)
2058 return (err);
2059 log_printf("%s\n", obp_version);
2060 }
2061 }
2062
2063 return (PICL_WALK_TERMINATE);
2064 }
2065
2066 static void
sun4v_print_chassis_serial_no()2067 sun4v_print_chassis_serial_no()
2068 {
2069 char val[PICL_PROPNAMELEN_MAX];
2070 picl_errno_t err;
2071 if (syserrlog == 0 || chassish == 0)
2072 return;
2073
2074 log_printf("\n");
2075 log_printf("Chassis Serial Number");
2076 log_printf("\n");
2077 log_printf("---------------------\n");
2078 err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
2079 val, sizeof (val));
2080 if (err == PICL_SUCCESS)
2081 log_printf("%s", val);
2082 log_printf("\n");
2083 }
2084