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