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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <kvm.h>
34 #include <varargs.h>
35 #include <time.h>
36 #include <dirent.h>
37 #include <fcntl.h>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/utsname.h>
42 #include <sys/openpromio.h>
43 #include <libintl.h>
44 #include <syslog.h>
45 #include <sys/dkio.h>
46 #include <sys/systeminfo.h>
47 #include <picldefs.h>
48 #include "pdevinfo.h"
49 #include "display.h"
50 #include "display_sun4v.h"
51 #include "libprtdiag.h"
52 
53 #if !defined(TEXT_DOMAIN)
54 #define	TEXT_DOMAIN	"SYS_TEST"
55 #endif
56 
57 #define	MOTHERBOARD			"MB"
58 #define	NETWORK				"network"
59 #define	PCIE_COMPATIBLE_STR		"pciex"
60 #define	PCIX_COMPATIBLE_STR		"pci"
61 #define	SUN4V_MACHINE			"sun4v"
62 #define	PARENT_NAMES			10
63 
64 /*
65  * Additional OBP properties
66  */
67 #define	OBP_PROP_COMPATIBLE		"compatible"
68 #define	OBP_PROP_MODEL			"model"
69 #define	OBP_PROP_SLOT_NAMES		"slot-names"
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 void 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 void sun4v_print_fw_rev();
112 static void sun4v_print_chassis_serial_no();
113 
114 int
115 sun4v_display(Sys_tree *tree, Prom_node *root, int log,
116 	picl_nodehdl_t plafh)
117 {
118 	void *value;		/* used for opaque PROM data */
119 	struct mem_total memory_total;	/* Total memory in system */
120 	struct grp_info grps;	/* Info on all groups in system */
121 	char machine[MAXSTRLEN];
122 
123 	if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
124 		return (1);
125 	if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
126 		return (1);
127 
128 	sys_clk = -1;  /* System clock freq. (in MHz) */
129 
130 	/*
131 	 * Now display the machine's configuration. We do this if we
132 	 * are not logging.
133 	 */
134 	if (!logging) {
135 		struct utsname uts_buf;
136 
137 		/*
138 		 * Display system banner
139 		 */
140 		(void) uname(&uts_buf);
141 
142 		log_printf(dgettext(TEXT_DOMAIN, "System Configuration:  "
143 		    "Sun Microsystems  %s %s\n"), uts_buf.machine,
144 		    get_prop_val(find_prop(root, "banner-name")), 0);
145 
146 		/* display system clock frequency */
147 		value = get_prop_val(find_prop(root, "clock-frequency"));
148 		if (value != NULL) {
149 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
150 			log_printf(dgettext(TEXT_DOMAIN, "System clock "
151 			    "frequency: %d MHz\n"), sys_clk, 0);
152 		}
153 
154 		/* Display the Memory Size */
155 		display_memorysize(tree, NULL, &grps, &memory_total);
156 
157 		/* Display the CPU devices */
158 		sun4v_display_cpu_devices(plafh);
159 
160 		/* Display the Memory configuration */
161 		class_node_found = 0;
162 		sun4v_display_memory_conf(plafh);
163 
164 		/* Display all the IO cards. */
165 		(void) sun4v_display_pci(plafh);
166 		sun4v_display_diaginfo((log || (logging)), root, plafh);
167 
168 		if (picl_get_root(&rooth) != PICL_SUCCESS)
169 			return (1);
170 		if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
171 		    &phyplatformh) != PICL_SUCCESS)
172 			return (1);
173 
174 		if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
175 		    PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
176 		    strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
177 			return (1);
178 
179 		syserrlog = log;
180 		sun4v_disp_env_status();
181 	}
182 	return (0);
183 }
184 
185 static void
186 get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
187 {
188 	char *compatible;
189 
190 	(void) strlcpy(card->bus_type, "PCIX", sizeof (card->bus_type));
191 	if (sun4v_get_first_compatible_value(nodeh, &compatible)
192 	    == PICL_SUCCESS) {
193 		if (strncmp(compatible, PCIE_COMPATIBLE_STR,
194 		    strlen(PCIE_COMPATIBLE_STR)) == 0)
195 			(void) strlcpy(card->bus_type, "PCIE",
196 			    sizeof (card->bus_type));
197 		free(compatible);
198 	}
199 }
200 
201 static picl_errno_t
202 get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
203 {
204 	char val[PICL_PROPNAMELEN_MAX];
205 	picl_errno_t err;
206 
207 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
208 	    sizeof (val));
209 	if (err != PICL_SUCCESS)
210 		return (err);
211 
212 	(void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
213 	card->slot = -1;
214 	return (PICL_SUCCESS);
215 }
216 
217 static void
218 get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
219 {
220 	picl_errno_t err;
221 	picl_prophdl_t proph;
222 	picl_propinfo_t pinfo;
223 	picl_nodehdl_t pnodeh;
224 	uint8_t *pval;
225 	uint32_t dev_mask;
226 	char uaddr[MAXSTRLEN];
227 	int i;
228 
229 	if (get_slot_label(nodeh, card) == PICL_SUCCESS)
230 		return;
231 	err = PICL_SUCCESS;
232 	while (err == PICL_SUCCESS) {
233 		if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
234 		    sizeof (pnodeh)) != PICL_SUCCESS) {
235 			(void) strlcpy(card->slot_str, MOTHERBOARD,
236 			    sizeof (card->slot_str));
237 			card->slot = -1;
238 			return;
239 		}
240 		if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
241 		    &pinfo, &proph) == PICL_SUCCESS) {
242 			break;
243 		}
244 		nodeh = pnodeh;
245 	}
246 	if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
247 	    sizeof (uaddr)) != PICL_SUCCESS) {
248 		(void) strlcpy(card->slot_str, MOTHERBOARD,
249 		    sizeof (card->slot_str));
250 		card->slot = -1;
251 		return;
252 	}
253 	pval = (uint8_t *)malloc(pinfo.size);
254 	if (!pval) {
255 		(void) strlcpy(card->slot_str, MOTHERBOARD,
256 		    sizeof (card->slot_str));
257 		card->slot = -1;
258 		return;
259 	}
260 	if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
261 		(void) strlcpy(card->slot_str, MOTHERBOARD,
262 		    sizeof (card->slot_str));
263 		card->slot = -1;
264 		free(pval);
265 		return;
266 	}
267 
268 	dev_mask = 0;
269 	for (i = 0; i < sizeof (dev_mask); i++)
270 		dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
271 	for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
272 		if (uaddr[i] == ',') {
273 			uaddr[i] = '\0';
274 			break;
275 		}
276 	}
277 	card->slot = atol(uaddr);
278 	if (((1 << card->slot) & dev_mask) == 0) {
279 		(void) strlcpy(card->slot_str, MOTHERBOARD,
280 		    sizeof (card->slot_str));
281 		card->slot = -1;
282 	} else {
283 		char *p = (char *)(pval+sizeof (dev_mask));
284 		int shift = sizeof (uint32_t)*8-1-card->slot;
285 		uint32_t x = (dev_mask << shift) >> shift;
286 		int count = 0;	/* count # of 1's in x */
287 		int i = 0;
288 		while (x != 0) {
289 			count++;
290 			x &= x-1;
291 		}
292 		while (count > 1) {
293 			while (p[i++] != '\0')
294 				;
295 			count--;
296 		}
297 		(void) strlcpy(card->slot_str, (char *)(p+i),
298 		    sizeof (card->slot_str));
299 	}
300 	free(pval);
301 }
302 
303 /*
304  * add all io devices under pci in io list
305  */
306 /* ARGSUSED */
307 static int
308 sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
309 {
310 	char path[PICL_PROPNAMELEN_MAX];
311 	char class[PICL_CLASSNAMELEN_MAX];
312 	char name[PICL_PROPNAMELEN_MAX];
313 	char model[PICL_PROPNAMELEN_MAX];
314 	char binding_name[PICL_PROPNAMELEN_MAX];
315 	char val[PICL_PROPNAMELEN_MAX];
316 	char *compatible;
317 	picl_errno_t err;
318 	picl_nodehdl_t nodeh;
319 	struct io_card pci_card;
320 
321 	/* Walk through the children */
322 
323 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
324 	    sizeof (picl_nodehdl_t));
325 
326 	while (err == PICL_SUCCESS) {
327 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
328 		    class, sizeof (class));
329 		if (err !=  PICL_SUCCESS)
330 			return (err);
331 
332 		if (args) {
333 			char *val = args;
334 			if (strcmp(class, val) == 0) {
335 				err = picl_get_propval_by_name(nodeh,
336 				    PICL_PROP_PEER, &nodeh,
337 				    sizeof (picl_nodehdl_t));
338 				continue;
339 			} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
340 			    strcmp(class, PICL_CLASS_PCI) == 0) {
341 				err = picl_get_propval_by_name(nodeh,
342 				    PICL_PROP_PEER, &nodeh,
343 				    sizeof (picl_nodehdl_t));
344 				continue;
345 			} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
346 			    strcmp(class, PICL_CLASS_PCIEX) == 0) {
347 				err = picl_get_propval_by_name(nodeh,
348 				    PICL_PROP_PEER, &nodeh,
349 				    sizeof (picl_nodehdl_t));
350 				continue;
351 			}
352 		}
353 
354 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
355 		    path, sizeof (path));
356 		if (err != PICL_SUCCESS)
357 			return (err);
358 
359 		(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
360 
361 		get_bus_type(nodeh, &pci_card);
362 		get_slot_number(nodeh, &pci_card);
363 
364 		err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
365 		    sizeof (name));
366 		if (err == PICL_PROPNOTFOUND)
367 			(void) strlcpy(name, "", sizeof (name));
368 		else if (err != PICL_SUCCESS)
369 			return (err);
370 
371 		err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
372 		    sizeof (val));
373 		if (err == PICL_PROPNOTFOUND)
374 			(void) strlcpy(val, "", sizeof (val));
375 		else if (err != PICL_SUCCESS)
376 			return (err);
377 
378 		/* Figure NAC name */
379 		if (pci_card.slot != -1)
380 			(void) snprintf(pci_card.status,
381 			    sizeof (pci_card.status),
382 			    "%s%d", pci_card.slot_str,
383 			    pci_card.slot);
384 		else
385 			(void) snprintf(pci_card.status,
386 			    sizeof (pci_card.status),
387 			    "%s", pci_card.slot_str);
388 
389 		/*
390 		 * Get the name of this card. If binding_name is found,
391 		 * name will be <nodename>-<binding_name>.
392 		 */
393 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
394 		    binding_name, sizeof (binding_name));
395 		if (err == PICL_SUCCESS) {
396 			if (strcmp(name, binding_name) != 0) {
397 				(void) strlcat(name, "-", sizeof (name));
398 				(void) strlcat(name, binding_name,
399 				    sizeof (name));
400 			}
401 		} else if (err == PICL_PROPNOTFOUND) {
402 			/*
403 			 * if compatible prop is not found, name will be
404 			 * <nodename>-<compatible>
405 			 */
406 			err = sun4v_get_first_compatible_value(nodeh,
407 			    &compatible);
408 			if (err == PICL_SUCCESS) {
409 				(void) strlcat(name, "-", sizeof (name));
410 				(void) strlcat(name, compatible,
411 				    sizeof (name));
412 				free(compatible);
413 			}
414 		} else
415 			return (err);
416 
417 		(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
418 
419 		/* Get the model of this card */
420 
421 		err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
422 		    model, sizeof (model));
423 		if (err == PICL_PROPNOTFOUND)
424 			(void) strlcpy(model, "", sizeof (model));
425 		else if (err != PICL_SUCCESS)
426 			return (err);
427 		(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
428 
429 		/* Print NAC name */
430 		log_printf("%-12s", pci_card.status);
431 		/* Print IO Type */
432 		log_printf("%-6s", pci_card.bus_type);
433 		/* Printf Card Name */
434 		log_printf("%-46s", pci_card.name);
435 		/* Print Card Model */
436 		log_printf("%-8s", pci_card.model);
437 		log_printf("\n");
438 		/* Print Status */
439 		log_printf("%-12s", val);
440 		/* Print IO Type */
441 		log_printf("%-6s", "");
442 		/* Print Parent Path */
443 		log_printf("%-46s", pci_card.notes);
444 		log_printf("\n");
445 
446 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
447 		    sizeof (picl_nodehdl_t));
448 	}
449 	return (PICL_WALK_CONTINUE);
450 }
451 
452 /*
453  * display_pci
454  * Display all the PCI IO cards on this board.
455  */
456 void
457 sun4v_display_pci(picl_nodehdl_t plafh)
458 {
459 	char *fmt = "%-11s %-5s %-45s %-8s";
460 	/* Have we printed the column headings? */
461 	static int banner = FALSE;
462 
463 	if (banner == FALSE) {
464 		log_printf("\n");
465 		log_printf("============================");
466 		log_printf(" IO Devices ");
467 		log_printf("============================");
468 		log_printf("\n");
469 		log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
470 		log_printf("\n");
471 		log_printf(fmt, "Status", "Type", "Path", "", 0);
472 		log_printf("\n");
473 		log_printf("---------------------------------"
474 		    "------------------------------------\n");
475 		banner = TRUE;
476 	}
477 
478 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
479 	    PICL_CLASS_PCIEX, sun4v_pci_callback);
480 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
481 	    PICL_CLASS_PCI, sun4v_pci_callback);
482 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
483 	    PICL_CLASS_SUN4V, sun4v_pci_callback);
484 }
485 
486 /*
487  * return the first compatible value
488  */
489 static int
490 sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
491 {
492 	picl_errno_t err;
493 	picl_prophdl_t proph;
494 	picl_propinfo_t pinfo;
495 	picl_prophdl_t tblh;
496 	picl_prophdl_t rowproph;
497 	char *pval;
498 
499 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
500 	    &pinfo, &proph);
501 	if (err != PICL_SUCCESS)
502 		return (err);
503 
504 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
505 		pval = malloc(pinfo.size);
506 		if (pval == NULL)
507 			return (PICL_FAILURE);
508 		err = picl_get_propval(proph, pval, pinfo.size);
509 		if (err != PICL_SUCCESS) {
510 			free(pval);
511 			return (err);
512 		}
513 		*outbuf = pval;
514 		return (PICL_SUCCESS);
515 	}
516 
517 	if (pinfo.type != PICL_PTYPE_TABLE)
518 		return (PICL_FAILURE);
519 
520 	/* get first string from table */
521 	err = picl_get_propval(proph, &tblh, pinfo.size);
522 	if (err != PICL_SUCCESS)
523 		return (err);
524 
525 	err = picl_get_next_by_row(tblh, &rowproph);
526 	if (err != PICL_SUCCESS)
527 		return (err);
528 
529 	err = picl_get_propinfo(rowproph, &pinfo);
530 	if (err != PICL_SUCCESS)
531 		return (err);
532 
533 	pval = malloc(pinfo.size);
534 	if (pval == NULL)
535 		return (PICL_FAILURE);
536 
537 	err = picl_get_propval(rowproph, pval, pinfo.size);
538 	if (err != PICL_SUCCESS) {
539 		free(pval);
540 		return (err);
541 	}
542 
543 	*outbuf = pval;
544 	return (PICL_SUCCESS);
545 }
546 
547 /*
548  * print size of a memory segment
549  */
550 static void
551 print_memory_segment_size(uint64_t size)
552 {
553 	uint64_t kbyte = 1024;
554 	uint64_t mbyte = kbyte * kbyte;
555 	uint64_t gbyte = kbyte * mbyte;
556 	char buf[MEMORY_SIZE_FIELD];
557 
558 	if (size >= gbyte) {
559 		if (size % gbyte == 0)
560 			(void) snprintf(buf, sizeof (buf), "%d GB",
561 			    (int)(size / gbyte));
562 		else
563 			(void) snprintf(buf, sizeof (buf), "%.2f GB",
564 			    (float)size / gbyte);
565 	} else if (size >= mbyte) {
566 		if (size % mbyte == 0)
567 			(void) snprintf(buf, sizeof (buf), "%d MB",
568 			    (int)(size / mbyte));
569 		else
570 			(void) snprintf(buf, sizeof (buf), "%.2f MB",
571 			    (float)size / mbyte);
572 	} else {
573 		if (size % kbyte == 0)
574 			(void) snprintf(buf, sizeof (buf), "%d KB",
575 			    (int)(size / kbyte));
576 		else
577 			(void) snprintf(buf, sizeof (buf), "%.2f KB",
578 			    (float)size / kbyte);
579 	}
580 	log_printf("%-7s ", buf);
581 }
582 
583 /*
584  * Enumerate banks and dimms within a memory segment.  We're handed
585  * the first bank within the segment - we assume there are dimms
586  * (memory-module) nodes underneath.
587  */
588 static void
589 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
590 {
591 	char val[PICL_PROPNAMELEN_MAX];
592 	picl_nodehdl_t module_nodeh;
593 	int flag = 0;
594 
595 	do {
596 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
597 		    &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
598 			continue;
599 		do {
600 			if (picl_get_propval_by_name(module_nodeh,
601 			    PICL_PROP_NAC, val, sizeof (val)) !=
602 			    PICL_SUCCESS)
603 				continue;
604 			else {
605 				if (!flag) {
606 					log_printf("%-30s\n", val);
607 					flag = 1;
608 				} else
609 					log_printf("%57s\n", val);
610 			}
611 		} while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
612 		    &module_nodeh, sizeof (picl_nodehdl_t)) ==
613 		    PICL_SUCCESS);
614 	} while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
615 	    &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
616 }
617 
618 /*
619  * Search node where _class=="memory-segment"
620  * print "Base Address", "Size", etc
621  */
622 /*ARGSUSED*/
623 static int
624 sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
625 {
626 	uint64_t base;
627 	uint64_t size;
628 	uint64_t ifactor;
629 	picl_errno_t err = PICL_SUCCESS;
630 
631 	if (class_node_found == 0) {
632 		class_node_found = 1;
633 		return (PICL_WALK_TERMINATE);
634 	}
635 	while (err == PICL_SUCCESS) {
636 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
637 		    &base, sizeof (base));
638 		if (err !=  PICL_SUCCESS)
639 			break;
640 		err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
641 		    &size, sizeof (size));
642 		if (err !=  PICL_SUCCESS)
643 			break;
644 		err = picl_get_propval_by_name(nodeh,
645 		    PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
646 		    sizeof (ifactor));
647 		if (err !=  PICL_SUCCESS)
648 			break;
649 		log_printf("%-13llx", base);
650 		print_memory_segment_size(size);
651 		log_printf("%-18lld", ifactor);
652 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
653 		    &nodeh, sizeof (nodeh));
654 		if (err ==  PICL_SUCCESS)
655 			print_memory_segment_contain(nodeh);
656 		log_printf("\n");
657 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
658 		    sizeof (picl_nodehdl_t));
659 	}
660 
661 	return (PICL_WALK_CONTINUE);
662 }
663 
664 /*ARGSUSED*/
665 void
666 sun4v_display_memory_conf(picl_nodehdl_t plafh)
667 {
668 	char *fmt = "%-12s %-7s %-9s %-20s";
669 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
670 	    NULL, sun4v_memory_conf_callback);
671 	if (class_node_found == 0)
672 		return;
673 	log_printf("\n");
674 	log_printf("============================");
675 	log_printf(" Memory Configuration ");
676 	log_printf("============================");
677 	log_printf("\n");
678 	log_printf("Segment Table:\n");
679 	log_printf(
680 	    "---------------------------------------------------------\n");
681 	log_printf(fmt, "Base Address", "Size", "Interleave Factor",
682 	    "Contains", 0);
683 	log_printf("\n");
684 	log_printf(
685 	    "---------------------------------------------------------\n");
686 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
687 	    NULL, sun4v_memory_conf_callback);
688 }
689 
690 void
691 sun4v_display_cpu_devices(picl_nodehdl_t plafh)
692 {
693 	char *fmt = "%-12s %-5s %-8s %-19s %-5s";
694 
695 	/*
696 	 * Display the table header for CPUs . Then display the CPU
697 	 * frequency, cache size, and processor revision of all cpus.
698 	 */
699 	log_printf(dgettext(TEXT_DOMAIN,
700 	    "\n"
701 	    "========================="
702 	    " CPUs "
703 	    "==============================================="
704 	    "\n"
705 	    "\n"));
706 	log_printf(fmt, "", "", "", "CPU", "CPU", 0);
707 	log_printf("\n");
708 	log_printf(fmt, "Location", "CPU", "Freq",
709 	    "Implementation", "Mask", 0);
710 	log_printf("\n");
711 	log_printf(fmt, "------------", "-----", "--------",
712 	    "-------------------", "-----", 0);
713 	log_printf("\n");
714 
715 	(void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus);
716 }
717 
718 /*
719  * Display the CPUs present on this board.
720  */
721 /*ARGSUSED*/
722 int
723 sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
724 {
725 	int status;
726 	picl_prophdl_t proph;
727 	picl_prophdl_t tblh;
728 	picl_prophdl_t rowproph;
729 	picl_propinfo_t propinfo;
730 	int *int_value;
731 	uint64_t cpuid, mask_no;
732 	char *comp_value;
733 	char *no_prop_value = "   ";
734 	char freq_str[MAXSTRLEN];
735 	char fru_name[MAXSTRLEN];
736 
737 	/*
738 	 * Get cpuid property and print it and the NAC name
739 	 */
740 	status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph);
741 	if (status == PICL_SUCCESS) {
742 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
743 		if (status != PICL_SUCCESS) {
744 			log_printf("%-13s", no_prop_value);
745 			log_printf("%-6s", no_prop_value);
746 		} else {
747 			(void) snprintf(fru_name, sizeof (fru_name), "%s%d",
748 			    CPU_STRAND_NAC, (int)cpuid);
749 			log_printf("%-13s", fru_name);
750 			log_printf("%-6d", (int)cpuid);
751 		}
752 	} else {
753 		log_printf("%-13s", no_prop_value);
754 		log_printf("%-6s", no_prop_value);
755 	}
756 
757 clock_freq:
758 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
759 	    &proph);
760 	if (status == PICL_SUCCESS) {
761 		int_value = malloc(propinfo.size);
762 		if (int_value == NULL) {
763 			log_printf("%-9s", no_prop_value);
764 			goto compatible;
765 		}
766 		status = picl_get_propval(proph, int_value, propinfo.size);
767 		if (status != PICL_SUCCESS) {
768 			log_printf("%-9s", no_prop_value);
769 		} else {
770 			/* Running frequency */
771 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
772 			    CLK_FREQ_TO_MHZ(*int_value));
773 			log_printf("%-9s", freq_str);
774 		}
775 		free(int_value);
776 	} else
777 		log_printf("%-9s", no_prop_value);
778 
779 compatible:
780 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
781 	    &proph);
782 	if (status == PICL_SUCCESS) {
783 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
784 			/*
785 			 * Compatible Property only has 1 value
786 			 */
787 			comp_value = malloc(propinfo.size);
788 			if (comp_value == NULL) {
789 				log_printf("%-20s", no_prop_value, 0);
790 				goto mask;
791 			}
792 			status = picl_get_propval(proph, comp_value,
793 			    propinfo.size);
794 			if (status != PICL_SUCCESS)
795 				log_printf("%-20s", no_prop_value, 0);
796 			else
797 				log_printf("%-20s", comp_value, 0);
798 			free(comp_value);
799 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
800 			/*
801 			 * Compatible Property has multiple values
802 			 */
803 			status = picl_get_propval(proph, &tblh, propinfo.size);
804 			if (status != PICL_SUCCESS) {
805 				log_printf("%-20s", no_prop_value, 0);
806 				goto mask;
807 			}
808 			status = picl_get_next_by_row(tblh, &rowproph);
809 			if (status != PICL_SUCCESS) {
810 				log_printf("%-20s", no_prop_value, 0);
811 				goto mask;
812 			}
813 
814 			status = picl_get_propinfo(rowproph, &propinfo);
815 			if (status != PICL_SUCCESS) {
816 				log_printf("%-20s", no_prop_value, 0);
817 				goto mask;
818 			}
819 
820 			comp_value = malloc(propinfo.size);
821 			if (comp_value == NULL) {
822 				log_printf("%-20s", no_prop_value, 0);
823 				goto mask;
824 			}
825 			status = picl_get_propval(rowproph, comp_value,
826 			    propinfo.size);
827 			if (status != PICL_SUCCESS)
828 				log_printf("%-20s", no_prop_value, 0);
829 			else
830 				log_printf("%-20s", comp_value, 0);
831 			free(comp_value);
832 		}
833 	} else
834 		log_printf("%-20s", no_prop_value, 0);
835 
836 mask:
837 	status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph);
838 	if (status == PICL_SUCCESS) {
839 		status = picl_get_propval(proph, &mask_no, sizeof (mask_no));
840 		if (status != PICL_SUCCESS) {
841 			log_printf("%-9s", no_prop_value);
842 		} else {
843 			log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
844 			    (mask_no>> 4) & 0xf, mask_no & 0xf);
845 		}
846 	} else
847 		log_printf("%-9s", no_prop_value);
848 
849 done:
850 	log_printf("\n");
851 	return (PICL_WALK_CONTINUE);
852 }
853 
854 void
855 sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
856 {
857 #ifdef	lint
858 	flag = flag;
859 	root = root;
860 	plafh = plafh;
861 #endif
862 	/*
863 	 * This function is intentionally empty
864 	 */
865 }
866 
867 void
868 display_boardnum(int num)
869 {
870 	log_printf("%2d   ", num, 0);
871 }
872 
873 static void
874 sun4v_disp_env_status()
875 {
876 	if (phyplatformh == 0)
877 		return;
878 	log_printf("\n");
879 	log_printf("============================");
880 	log_printf(" Environmental Status ");
881 	log_printf("============================");
882 	log_printf("\n");
883 
884 	class_node_found = 0;
885 	all_status_ok = 1;
886 	sun4v_env_print_fan_sensors();
887 
888 	class_node_found = 0;
889 	all_status_ok = 1;
890 	sun4v_env_print_fan_indicators();
891 
892 	class_node_found = 0;
893 	all_status_ok = 1;
894 	sun4v_env_print_temp_sensors();
895 
896 	class_node_found = 0;
897 	all_status_ok = 1;
898 	sun4v_env_print_temp_indicators();
899 
900 	class_node_found = 0;
901 	all_status_ok = 1;
902 	sun4v_env_print_current_sensors();
903 
904 	class_node_found = 0;
905 	all_status_ok = 1;
906 	sun4v_env_print_current_indicators();
907 
908 	class_node_found = 0;
909 	all_status_ok = 1;
910 	sun4v_env_print_voltage_sensors();
911 
912 	class_node_found = 0;
913 	all_status_ok = 1;
914 	sun4v_env_print_voltage_indicators();
915 
916 	class_node_found = 0;
917 	sun4v_env_print_LEDs();
918 
919 	class_node_found = 0;
920 	all_status_ok = 1;
921 	sun4v_print_fru_status();
922 
923 	class_node_found = 0;
924 	sun4v_print_fw_rev();
925 
926 	sun4v_print_chassis_serial_no();
927 }
928 
929 /*ARGSUSED*/
930 static int
931 sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
932 {
933 	char val[PICL_PROPNAMELEN_MAX];
934 	picl_nodehdl_t parenth;
935 	char *names[PARENT_NAMES];
936 	char *loc;
937 	int i;
938 	char *prop;
939 	picl_errno_t err;
940 	int32_t lo_warning, lo_shutdown;
941 	int32_t hi_warning, hi_shutdown;
942 	int32_t current_val;
943 
944 	if (class_node_found == 0) {
945 		class_node_found = 1;
946 		return (PICL_WALK_TERMINATE);
947 	}
948 
949 	if (syserrlog == 0) {
950 		err = picl_get_propval_by_name(nodeh,
951 		    PICL_PROP_OPERATIONAL_STATUS, val,
952 		    sizeof (val));
953 		if (err == PICL_SUCCESS) {
954 			if (strcmp(val, "disabled") == 0) {
955 				if (all_status_ok) {
956 					all_status_ok = 0;
957 					return (PICL_WALK_TERMINATE);
958 				}
959 			} else
960 				return (PICL_WALK_CONTINUE);
961 		} else {
962 			all_status_ok = 0;
963 			return (PICL_WALK_TERMINATE);
964 		}
965 	}
966 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
967 	    sizeof (parenth));
968 	if (err != PICL_SUCCESS) {
969 		log_printf("\n");
970 		return (PICL_WALK_CONTINUE);
971 	}
972 
973 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
974 		return (PICL_WALK_TERMINATE);
975 	for (i = 0; i < PARENT_NAMES; i++)
976 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
977 			while (--i > -1)
978 				free(names[i]);
979 			free(loc);
980 			return (PICL_WALK_TERMINATE);
981 		}
982 	i = 0;
983 	while (err == PICL_SUCCESS) {
984 		if (parenth == chassish || parenth == phyplatformh)
985 			break;
986 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
987 		    names[i++], PICL_PROPNAMELEN_MAX);
988 		if (err != PICL_SUCCESS) {
989 			i--;
990 			break;
991 		}
992 		if (i == PARENT_NAMES)
993 			break;
994 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
995 		    &parenth, sizeof (parenth));
996 	}
997 	loc[0] = '\0';
998 	if (--i > -1) {
999 		(void) strlcat(loc, names[i],
1000 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1001 	}
1002 	while (--i > -1) {
1003 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX*PARENT_NAMES);
1004 		(void) strlcat(loc, names[i],
1005 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1006 	}
1007 	log_printf("%-21s", loc);
1008 	for (i = 0; i < PARENT_NAMES; i++)
1009 		free(names[i]);
1010 	free(loc);
1011 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1012 	    sizeof (val));
1013 	if (err == PICL_SUCCESS)
1014 		log_printf("%-15s", val);
1015 
1016 	prop = (char *)args;
1017 	if (!prop) {
1018 		log_printf("\n");
1019 		return (PICL_WALK_CONTINUE);
1020 	}
1021 	if (picl_get_propval_by_name(nodeh, prop, &current_val,
1022 	    sizeof (current_val)) != PICL_SUCCESS) {
1023 		log_printf("\n");
1024 		return (PICL_WALK_CONTINUE);
1025 	}
1026 	if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_WARNING,
1027 	    &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
1028 		lo_warning = INVALID_THRESHOLD;
1029 	if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_SHUTDOWN,
1030 	    &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
1031 		lo_shutdown = INVALID_THRESHOLD;
1032 	if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_WARNING,
1033 	    &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
1034 		hi_warning = INVALID_THRESHOLD;
1035 	if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_SHUTDOWN,
1036 	    &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
1037 		hi_shutdown = INVALID_THRESHOLD;
1038 
1039 	if ((lo_shutdown != INVALID_THRESHOLD &&
1040 	    current_val <= lo_shutdown) ||
1041 	    (hi_shutdown != INVALID_THRESHOLD &&
1042 	    current_val >= hi_shutdown)) {
1043 		log_printf("%-s", "failed (");
1044 		log_printf("%-d", current_val);
1045 		log_printf("%-s", ")");
1046 	} else if ((lo_warning != INVALID_THRESHOLD &&
1047 	    current_val <= lo_warning) ||
1048 	    (hi_warning != INVALID_THRESHOLD &&
1049 	    current_val >= hi_warning)) {
1050 		log_printf("%-s", "warning (");
1051 		log_printf("%-d", current_val);
1052 		log_printf("%-s", ")");
1053 	} else
1054 		log_printf("%-s", "ok");
1055 
1056 	log_printf("\n");
1057 	return (PICL_WALK_CONTINUE);
1058 }
1059 
1060 /*ARGSUSED*/
1061 static int
1062 sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
1063 {
1064 	char val[PICL_PROPNAMELEN_MAX];
1065 	char status[PICL_PROPNAMELEN_MAX];
1066 	picl_nodehdl_t parenth;
1067 	char *names[PARENT_NAMES];
1068 	char *loc;
1069 	int i = 0;
1070 	char *prop = (char *)args;
1071 	picl_errno_t err = PICL_SUCCESS;
1072 
1073 	if (class_node_found == 0) {
1074 		class_node_found = 1;
1075 		return (PICL_WALK_TERMINATE);
1076 	}
1077 	if (syserrlog == 0) {
1078 		err = picl_get_propval_by_name(nodeh,
1079 		    PICL_PROP_OPERATIONAL_STATUS, status,
1080 		    sizeof (status));
1081 		if (err == PICL_SUCCESS) {
1082 			if (strcmp(status, "disabled") == 0) {
1083 				if (all_status_ok) {
1084 					all_status_ok = 0;
1085 					return (PICL_WALK_TERMINATE);
1086 				}
1087 			} else
1088 				return (PICL_WALK_CONTINUE);
1089 		} else {
1090 			all_status_ok = 0;
1091 			return (PICL_WALK_TERMINATE);
1092 		}
1093 	}
1094 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1095 	    sizeof (parenth));
1096 	if (err != PICL_SUCCESS) {
1097 		log_printf("\n");
1098 		return (PICL_WALK_CONTINUE);
1099 	}
1100 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
1101 		return (PICL_WALK_TERMINATE);
1102 	for (i = 0; i < PARENT_NAMES; i++)
1103 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
1104 			while (--i > -1)
1105 				free(names[i]);
1106 			free(loc);
1107 			return (PICL_WALK_TERMINATE);
1108 		}
1109 	i = 0;
1110 	while (err == PICL_SUCCESS) {
1111 		if (parenth == chassish || parenth == phyplatformh)
1112 			break;
1113 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1114 		    names[i++], PICL_PROPNAMELEN_MAX);
1115 		if (err != PICL_SUCCESS) {
1116 			i--;
1117 			break;
1118 		}
1119 		if (i == PARENT_NAMES)
1120 			break;
1121 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1122 		    &parenth, sizeof (parenth));
1123 	}
1124 	loc[0] = '\0';
1125 	if (--i > -1) {
1126 		(void) strlcat(loc, names[i],
1127 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1128 	}
1129 	while (--i > -1) {
1130 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1131 		(void) strlcat(loc, names[i],
1132 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1133 	}
1134 	log_printf("%-21s", loc);
1135 	for (i = 0; i < PARENT_NAMES; i++)
1136 		free(names[i]);
1137 	free(loc);
1138 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1139 	    sizeof (val));
1140 	if (err == PICL_SUCCESS)
1141 		log_printf("%-15s", val);
1142 	if (syserrlog == 0) {
1143 		log_printf("%-8s", status);
1144 		return (PICL_WALK_CONTINUE);
1145 	}
1146 	err = picl_get_propval_by_name(nodeh, prop, val, sizeof (val));
1147 	if (err == PICL_SUCCESS)
1148 		log_printf("%-8s", val);
1149 	log_printf("\n");
1150 	return (PICL_WALK_CONTINUE);
1151 }
1152 
1153 static void
1154 sun4v_env_print_fan_sensors()
1155 {
1156 	char *fmt = "%-20s %-14s %-10s\n";
1157 	/*
1158 	 * If there isn't any fan sensor node, return now.
1159 	 */
1160 	(void) picl_walk_tree_by_class(phyplatformh,
1161 	    PICL_CLASS_RPM_SENSOR, (void *)PICL_CLASS_RPM_SENSOR,
1162 	    sun4v_env_print_sensor_callback);
1163 	if (!class_node_found)
1164 		return;
1165 	log_printf("Fan sensors:\n");
1166 	if (syserrlog == 0) {
1167 		(void) picl_walk_tree_by_class(phyplatformh,
1168 		    PICL_CLASS_RPM_SENSOR,
1169 		    NULL, sun4v_env_print_sensor_callback);
1170 		if (all_status_ok) {
1171 			log_printf("All fan sensors are OK.\n");
1172 			return;
1173 		}
1174 	}
1175 	log_printf("------------------------------------------\n");
1176 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1177 	log_printf("------------------------------------------\n");
1178 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
1179 	    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
1180 }
1181 
1182 static void
1183 sun4v_env_print_fan_indicators()
1184 {
1185 	char *fmt = "%-20s %-14s %-10s\n";
1186 	(void) picl_walk_tree_by_class(phyplatformh,
1187 	    PICL_CLASS_RPM_INDICATOR, (void *)PICL_CLASS_RPM_INDICATOR,
1188 	    sun4v_env_print_indicator_callback);
1189 	if (!class_node_found)
1190 		return;
1191 	log_printf("\nFan indicators:\n");
1192 	if (syserrlog == 0) {
1193 		(void) picl_walk_tree_by_class(phyplatformh,
1194 		    PICL_CLASS_RPM_INDICATOR,
1195 		    NULL, sun4v_env_print_indicator_callback);
1196 		if (all_status_ok) {
1197 			log_printf("All fan indicators are OK.\n");
1198 			return;
1199 		}
1200 	}
1201 	log_printf("---------------------------------------------\n");
1202 	log_printf(fmt, "Location", "Sensor", "Condition", 0);
1203 	log_printf("---------------------------------------------\n");
1204 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
1205 	    PICL_CLASS_RPM_INDICATOR, sun4v_env_print_indicator_callback);
1206 }
1207 
1208 static void
1209 sun4v_env_print_temp_sensors()
1210 {
1211 	char *fmt = "%-20s %-14s %-10s\n";
1212 	(void) picl_walk_tree_by_class(phyplatformh,
1213 	    PICL_CLASS_TEMPERATURE_SENSOR,
1214 	    (void *)PICL_PROP_TEMPERATURE,
1215 	    sun4v_env_print_sensor_callback);
1216 	if (!class_node_found)
1217 		return;
1218 
1219 	log_printf("\nTemperature sensors:\n");
1220 	if (syserrlog == 0) {
1221 		(void) picl_walk_tree_by_class(phyplatformh,
1222 		    PICL_CLASS_TEMPERATURE_SENSOR,
1223 		    NULL, sun4v_env_print_sensor_callback);
1224 		if (all_status_ok) {
1225 			log_printf("All temperature sensors are OK.\n");
1226 			return;
1227 		}
1228 	}
1229 	log_printf("------------------------------------------\n");
1230 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1231 	log_printf("------------------------------------------\n");
1232 	(void) picl_walk_tree_by_class(phyplatformh,
1233 	    PICL_CLASS_TEMPERATURE_SENSOR,
1234 	    (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
1235 }
1236 
1237 static void
1238 sun4v_env_print_temp_indicators()
1239 {
1240 	char *fmt = "%-20s %-14s %-8s\n";
1241 	(void) picl_walk_tree_by_class(phyplatformh,
1242 	    PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
1243 	    sun4v_env_print_indicator_callback);
1244 	if (!class_node_found)
1245 		return;
1246 	log_printf("\nTemperature indicators:\n");
1247 	if (syserrlog == 0) {
1248 		(void) picl_walk_tree_by_class(phyplatformh,
1249 		    PICL_CLASS_TEMPERATURE_INDICATOR, NULL,
1250 		    sun4v_env_print_indicator_callback);
1251 		if (all_status_ok) {
1252 			log_printf("All temperature indicators are OK.\n");
1253 			return;
1254 		}
1255 	}
1256 	log_printf("---------------------------------------\n");
1257 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1258 	log_printf("---------------------------------------\n");
1259 	(void) picl_walk_tree_by_class(phyplatformh,
1260 	    PICL_CLASS_TEMPERATURE_INDICATOR,
1261 	    (void *)PICL_PROP_CONDITION,
1262 	    sun4v_env_print_indicator_callback);
1263 }
1264 
1265 static void
1266 sun4v_env_print_current_sensors()
1267 {
1268 	char *fmt = "%-20s %-14s %-10s\n";
1269 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
1270 	    (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
1271 	if (!class_node_found)
1272 		return;
1273 	log_printf("\nCurrent sensors:\n");
1274 	if (syserrlog == 0) {
1275 		(void) picl_walk_tree_by_class(phyplatformh,
1276 		    PICL_CLASS_CURRENT_SENSOR,
1277 		    NULL, sun4v_env_print_sensor_callback);
1278 		if (all_status_ok) {
1279 			log_printf("All current sensors are OK.\n");
1280 			return;
1281 		}
1282 	}
1283 	log_printf("------------------------------------------\n");
1284 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1285 	log_printf("------------------------------------------\n");
1286 	(void) picl_walk_tree_by_class(phyplatformh,
1287 	    PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
1288 	    sun4v_env_print_sensor_callback);
1289 }
1290 
1291 static void
1292 sun4v_env_print_current_indicators()
1293 {
1294 	char *fmt = "%-20s %-14s %-8s\n";
1295 	(void) picl_walk_tree_by_class(phyplatformh,
1296 	    PICL_CLASS_CURRENT_INDICATOR,
1297 	    (void *)PICL_PROP_CONDITION,
1298 	    sun4v_env_print_indicator_callback);
1299 	if (!class_node_found)
1300 		return;
1301 	log_printf("\nCurrent indicators:\n");
1302 	if (syserrlog == 0) {
1303 		(void) picl_walk_tree_by_class(phyplatformh,
1304 		    PICL_CLASS_CURRENT_INDICATOR, NULL,
1305 		    sun4v_env_print_indicator_callback);
1306 		if (all_status_ok) {
1307 			log_printf("All current indicators are OK.\n");
1308 			return;
1309 		}
1310 	}
1311 	log_printf("---------------------------------------------\n");
1312 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1313 	log_printf("---------------------------------------------\n");
1314 	(void) picl_walk_tree_by_class(phyplatformh,
1315 	    PICL_CLASS_CURRENT_INDICATOR,
1316 	    (void *)PICL_PROP_CONDITION,
1317 	    sun4v_env_print_indicator_callback);
1318 }
1319 
1320 static void
1321 sun4v_env_print_voltage_sensors()
1322 {
1323 	char *fmt = "%-20s %-14s %-10s\n";
1324 	(void) picl_walk_tree_by_class(phyplatformh,
1325 	    PICL_CLASS_VOLTAGE_SENSOR,
1326 	    PICL_PROP_VOLTAGE,
1327 	    sun4v_env_print_sensor_callback);
1328 	if (!class_node_found)
1329 		return;
1330 	log_printf("\nVoltage sensors:\n");
1331 	if (syserrlog == 0) {
1332 		(void) picl_walk_tree_by_class(phyplatformh,
1333 		    PICL_CLASS_VOLTAGE_SENSOR,
1334 		    NULL, sun4v_env_print_sensor_callback);
1335 		if (all_status_ok) {
1336 			log_printf("All voltage sensors are OK.\n");
1337 			return;
1338 		}
1339 	}
1340 	log_printf("------------------------------------------\n");
1341 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1342 	log_printf("------------------------------------------\n");
1343 	(void) picl_walk_tree_by_class(phyplatformh,
1344 	    PICL_CLASS_VOLTAGE_SENSOR,
1345 	    (void *)PICL_PROP_VOLTAGE,
1346 	    sun4v_env_print_sensor_callback);
1347 }
1348 
1349 static void
1350 sun4v_env_print_voltage_indicators()
1351 {
1352 	char *fmt = "%-20s %-14s %-8s\n";
1353 	(void) picl_walk_tree_by_class(phyplatformh,
1354 	    PICL_CLASS_VOLTAGE_INDICATOR,
1355 	    (void *)PICL_PROP_CONDITION,
1356 	    sun4v_env_print_indicator_callback);
1357 	if (!class_node_found)
1358 		return;
1359 	log_printf("\nVoltage indicators:\n");
1360 	if (syserrlog == 0) {
1361 		(void) picl_walk_tree_by_class(phyplatformh,
1362 		    PICL_CLASS_VOLTAGE_INDICATOR, NULL,
1363 		    sun4v_env_print_indicator_callback);
1364 		if (all_status_ok) {
1365 			log_printf("All voltage indicators are OK.\n");
1366 			return;
1367 		}
1368 	}
1369 	log_printf("---------------------------------------------\n");
1370 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1371 	log_printf("---------------------------------------------\n");
1372 	(void) picl_walk_tree_by_class(phyplatformh,
1373 	    PICL_CLASS_VOLTAGE_INDICATOR,
1374 	    (void *)PICL_PROP_CONDITION,
1375 	    sun4v_env_print_indicator_callback);
1376 }
1377 
1378 static void
1379 sun4v_env_print_LEDs()
1380 {
1381 	char *fmt = "%-20s %-14s %-8s\n";
1382 	if (syserrlog == 0)
1383 		return;
1384 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1385 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
1386 	if (!class_node_found)
1387 		return;
1388 	log_printf("\nLEDs:\n");
1389 	log_printf("-----------------------------------------\n");
1390 	log_printf(fmt, "Location", "LED", "State", 0);
1391 	log_printf("-----------------------------------------\n");
1392 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1393 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
1394 }
1395 
1396 /*ARGSUSED*/
1397 static int
1398 sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
1399 {
1400 	char label[PICL_PROPNAMELEN_MAX];
1401 	char status[PICL_PROPNAMELEN_MAX];
1402 	picl_errno_t err;
1403 	picl_prophdl_t proph;
1404 	picl_nodehdl_t parenth;
1405 	char *names[PARENT_NAMES];
1406 	char *loc;
1407 	int i;
1408 
1409 	if (!class_node_found) {
1410 		class_node_found = 1;
1411 		return (PICL_WALK_TERMINATE);
1412 	}
1413 	err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
1414 	if (err != PICL_SUCCESS)
1415 		return (PICL_WALK_CONTINUE);
1416 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1417 	    sizeof (label));
1418 	if (err != PICL_SUCCESS)
1419 		return (PICL_WALK_CONTINUE);
1420 	err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
1421 	    status, sizeof (status));
1422 	if (err != PICL_SUCCESS)
1423 		return (PICL_WALK_CONTINUE);
1424 	if (syserrlog == 0) {
1425 		if (strcmp(status, "disabled") == 0) {
1426 			if (all_status_ok) {
1427 				all_status_ok = 0;
1428 				return (PICL_WALK_TERMINATE);
1429 			}
1430 		} else
1431 			return (PICL_WALK_CONTINUE);
1432 	}
1433 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1434 	    sizeof (parenth));
1435 	if (err != PICL_SUCCESS) {
1436 		log_printf("\n");
1437 		return (PICL_WALK_CONTINUE);
1438 	}
1439 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
1440 		return (PICL_WALK_TERMINATE);
1441 	for (i = 0; i < PARENT_NAMES; i++)
1442 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
1443 			while (--i > -1)
1444 				free(names[i]);
1445 			free(loc);
1446 			return (PICL_WALK_TERMINATE);
1447 		}
1448 	i = 0;
1449 	while (err == PICL_SUCCESS) {
1450 		if (parenth == chassish || parenth == phyplatformh)
1451 			break;
1452 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1453 		    names[i++], PICL_PROPNAMELEN_MAX);
1454 		if (err != PICL_SUCCESS) {
1455 			i--;
1456 			break;
1457 		}
1458 		if (i == PARENT_NAMES)
1459 			break;
1460 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1461 		    &parenth, sizeof (parenth));
1462 	}
1463 	loc[0] = '\0';
1464 	if (--i > -1) {
1465 		(void) strlcat(loc, names[i],
1466 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1467 	}
1468 	while (--i > -1) {
1469 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1470 		(void) strlcat(loc, names[i],
1471 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1472 	}
1473 	log_printf("%-21s", loc);
1474 	for (i = 0; i < PARENT_NAMES; i++)
1475 		free(names[i]);
1476 	free(loc);
1477 	log_printf("%-10s", label);
1478 	log_printf("%-9s", status);
1479 	log_printf("\n");
1480 	return (PICL_WALK_CONTINUE);
1481 }
1482 
1483 static void
1484 sun4v_print_fru_status()
1485 {
1486 	char *fmt = "%-20s %-9s %-8s\n";
1487 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1488 	    sun4v_print_fru_status_callback);
1489 	if (!class_node_found)
1490 		return;
1491 	log_printf("\n");
1492 	log_printf("============================");
1493 	log_printf(" FRU Status ");
1494 	log_printf("============================");
1495 	log_printf("\n");
1496 
1497 	if (syserrlog == 0) {
1498 		(void) picl_walk_tree_by_class(phyplatformh,
1499 		    PICL_CLASS_MODULE, NULL,
1500 		    sun4v_print_fru_status_callback);
1501 		if (all_status_ok) {
1502 			log_printf("All FRUs are enabled.\n");
1503 			return;
1504 		}
1505 	}
1506 	log_printf(fmt, "Location", "Name", "Status", 0);
1507 	log_printf("----------------------------------------\n");
1508 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_MODULE, NULL,
1509 	    sun4v_print_fru_status_callback);
1510 }
1511 
1512 /*ARGSUSED*/
1513 static int
1514 sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
1515 {
1516 	char label[PICL_PROPNAMELEN_MAX];
1517 	char rev[PICL_PROPNAMELEN_MAX];
1518 	picl_errno_t err;
1519 
1520 	if (!class_node_found) {
1521 		class_node_found = 1;
1522 		return (PICL_WALK_TERMINATE);
1523 	}
1524 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1525 	    sizeof (label));
1526 	if (err != PICL_SUCCESS)
1527 		return (PICL_WALK_CONTINUE);
1528 	err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
1529 	    sizeof (rev));
1530 	if (err != PICL_SUCCESS)
1531 		return (PICL_WALK_CONTINUE);
1532 	if (strlen(rev) == 0)
1533 		return (PICL_WALK_CONTINUE);
1534 	log_printf("%-21s", label);
1535 	log_printf("%-40s", rev);
1536 	log_printf("\n");
1537 	return (PICL_WALK_CONTINUE);
1538 }
1539 
1540 static void
1541 sun4v_print_fw_rev()
1542 {
1543 	char *fmt = "%-20s %-10s\n";
1544 	if (syserrlog == 0)
1545 		return;
1546 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1547 	    sun4v_print_fw_rev_callback);
1548 	if (!class_node_found)
1549 		return;
1550 	log_printf("\n");
1551 	log_printf("============================");
1552 	log_printf(" FW Version ");
1553 	log_printf("============================");
1554 	log_printf("\n");
1555 	log_printf(fmt, "Name", "Version", 0);
1556 	log_printf("----------------------------\n");
1557 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1558 	    sun4v_print_fw_rev_callback);
1559 }
1560 
1561 static void
1562 sun4v_print_chassis_serial_no()
1563 {
1564 	char val[PICL_PROPNAMELEN_MAX];
1565 	picl_errno_t err;
1566 	if (syserrlog == 0 || chassish == 0)
1567 		return;
1568 
1569 	log_printf("\n");
1570 	log_printf("Chassis Serial Number");
1571 	log_printf("\n");
1572 	log_printf("---------------------\n");
1573 	err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
1574 	    val, sizeof (val));
1575 	if (err == PICL_SUCCESS)
1576 		log_printf("%s", val);
1577 	log_printf("\n");
1578 }
1579