xref: /illumos-gate/usr/src/lib/libprtdiag_psr/sparc/opl/common/opl.c (revision 6e375c8351497b82ffa4f33cbf61d712999b4605)
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  * Opl Platform specific functions.
26  *
27  * 	called when :
28  *	machine_type == MTYPE_OPL
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <varargs.h>
39 #include <fcntl.h>
40 #include <assert.h>
41 #include <sys/param.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <sys/utsname.h>
45 #include <sys/systeminfo.h>
46 #include <sys/openpromio.h>
47 #include <libintl.h>
48 #include <syslog.h>
49 #include <sys/dkio.h>
50 #include <pdevinfo.h>
51 #include <libprtdiag.h>
52 #include <libdevinfo.h>
53 #include <kstat.h>
54 
55 /*
56  * Globals and externs
57  */
58 #define	KBYTE	1024
59 #define	MBYTE	(KBYTE * KBYTE)
60 #define	HZ_TO_MHZ(x)	((((uint64_t)(x)) + 500000) / 1000000)
61 #define	SCF_SECURE_MODE_KSTAT_NAMED	"secure_mode"
62 #define	SCF_STAT_MODE_UNLOCK	0
63 #define	SCF_STAT_MODE_LOCK	1
64 #define	SCF_SYSTEM_KSTAT_NAME	"scf"
65 #ifndef	TEXT_DOMAIN
66 #define	TEXT_DOMAIN	"SYS_TEST"
67 #endif	/* TEXT_DOMAIN */
68 
69 /*
70  * Global functions and variables
71  * these functions will overlay the symbol table of libprtdiag
72  * at runtime (Opl systems only)
73  */
74 struct  cs_status {
75 	int cs_number;
76 	int status;
77 	uint_t avail_hi;
78 	uint_t avail_lo;
79 	uint_t dimm_hi;
80 	uint_t dimm_lo;
81 	int dimms;
82 };
83 
84 int	do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
85 void	*get_prop_val(Prop *prop);
86 void	display_ffb(Board_node *, int);
87 void	display_sbus(Board_node *board);
88 void	display_cpu_devices(Sys_tree *tree);
89 void	display_cpus(Board_node *board);
90 void	display_memoryconf(Sys_tree *tree, struct grp_info *grps);
91 void	display_io_cards(struct io_card *list);
92 void	display_io_devices(Sys_tree *tree);
93 void	display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
94     struct system_kstat_data *kstats);
95 Prop 	*find_prop(Prom_node *pnode, char *name);
96 int	do_piclinfo(int);
97 int	get_proc_mode(void);
98 
99 /* Local functions */
100 static	void opl_disp_environ(void);
101 static	void opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root);
102 static	uint64_t print_opl_memory_line(int lsb, struct cs_status *cs_stat,
103     int ngrps, int mirror_mode);
104 static	uint64_t get_opl_mem_regs(Board_node *bnode);
105 void 	add_node(Sys_tree *root, Prom_node *pnode);
106 static	int get_prop_size(Prop *prop);
107 
108 static int v_flag = 0;
109 
110 /*
111  * Linked list of IO card info for display.
112  * Using file scope for use in a recursive function.
113  */
114 static struct io_card *card_list = NULL;
115 
116 /*
117  * Check prom node for a class-code. If it exists and it's not a bridge device
118  * then add an io_card to card_list. Then recursively call this function for
119  * its child and sibling nodes.
120  */
121 static void
122 walk_tree_for_pci_devices(Prom_node *node, int board_number)
123 {
124 	struct io_card card;
125 	char	*str;
126 	void	*val;
127 	int	ccode;
128 
129 	if (node == NULL) {
130 		return;
131 	}
132 
133 	/* Look for a class-code property. Skip, if it's a bridge */
134 	ccode = -1;
135 	val = get_prop_val(find_prop(node, "class-code"));
136 	if (val != NULL) {
137 		ccode = *(int *)val;
138 	}
139 	if ((ccode != -1) && (ccode < 0x60000 || ccode > 0x6ffff)) {
140 		(void) memset(&card, 0, sizeof (card));
141 		card.board = board_number;
142 
143 		str = (char *)get_prop_val(find_prop(node, "name"));
144 		(void) strlcpy(card.name, (str == NULL ? "N/A":str),
145 		    sizeof (card.name));
146 
147 		str = (char *)get_prop_val(find_prop(node, "model"));
148 		(void) strlcpy(card.model, (str == NULL ? "N/A":str),
149 		    sizeof (card.model));
150 
151 		/* insert card to the list */
152 		card_list = insert_io_card(card_list, &card);
153 	}
154 	/* Call this function for its child/sibling */
155 	walk_tree_for_pci_devices(node->child, board_number);
156 	walk_tree_for_pci_devices(node->sibling, board_number);
157 }
158 
159 /*
160  * For display of I/O devices for "prtdiag"
161  */
162 void
163 display_io_devices(Sys_tree *tree)
164 {
165 	Board_node *bnode;
166 
167 	if (v_flag) {
168 		/*
169 		 * OPL's PICL interface for display of PCI I/O devices
170 		 * for "prtdiag -v"
171 		 */
172 		(void) do_piclinfo(v_flag);
173 	} else {
174 		log_printf("\n", 0);
175 		log_printf("=========================", 0);
176 		log_printf(dgettext(TEXT_DOMAIN, " IO Cards "), 0);
177 		log_printf("=========================", 0);
178 		log_printf("\n", 0);
179 		log_printf("\n", 0);
180 		bnode = tree->bd_list;
181 		while (bnode != NULL) {
182 			walk_tree_for_pci_devices(bnode->nodes,
183 			    bnode->board_num);
184 			bnode = bnode->next;
185 		}
186 		display_io_cards(card_list);
187 		free_io_cards(card_list);
188 	}
189 }
190 
191 /*
192  * There are no FFB's on OPL.
193  */
194 /*ARGSUSED*/
195 void
196 display_ffb(Board_node *board, int table)
197 {
198 }
199 
200 /*
201  * There are no Sbus's on OPL.
202  */
203 /*ARGSUSED*/
204 void
205 display_sbus(Board_node *board)
206 {
207 }
208 
209 /*
210  * Details of I/O information. Print out all the io cards.
211  */
212 void
213 display_io_cards(struct io_card *list)
214 {
215 	char	*hdrfmt = "%-6.6s %-14.14s %-12.12s\n";
216 
217 	struct io_card *p;
218 
219 	if (list == NULL)
220 		return;
221 
222 	(void) textdomain(TEXT_DOMAIN);
223 
224 	log_printf(hdrfmt, gettext("LSB"), gettext("Name"), gettext("Model"),
225 	    0);
226 
227 	log_printf(hdrfmt, "---", "-----------------", "------------", 0);
228 
229 	for (p = list; p != NULL; p = p->next) {
230 
231 		/* Board number */
232 		log_printf(" %02d    ", p->board, 0);
233 
234 		/* Card name */
235 		log_printf("%-15.15s", p->name, 0);
236 
237 		/* Card model */
238 		log_printf("%-12.12s", p->model, 0);
239 
240 		log_printf("\n", 0);
241 	}
242 	log_printf("\n", 0);
243 }
244 
245 /*
246  * Details of CPU information.
247  */
248 void
249 display_cpu_devices(Sys_tree *tree)
250 {
251 	Board_node *bnode;
252 	char *hdrfmt =
253 	    "%-4.4s  %-4.4s  %-40.40s  %-5.5s  %-5.5s  %-5.5s %-4.4s\n";
254 
255 	(void) textdomain(TEXT_DOMAIN);
256 
257 	/*
258 	 * Display the table header for CPUs . Then display the CPU
259 	 * frequency, cache size, and processor revision of all cpus.
260 	 */
261 	log_printf("\n", 0);
262 	log_printf("====================================", 0);
263 	log_printf(gettext(" CPUs "), 0);
264 	log_printf("====================================", 0);
265 	log_printf("\n\n", 0);
266 
267 	log_printf(hdrfmt,
268 	    "",
269 	    gettext("CPU"),
270 	    gettext("              CPU                  "),
271 	    gettext("Run"),
272 	    gettext("L2$"),
273 	    gettext("CPU"),
274 	    gettext("CPU"), 0);
275 
276 	log_printf(hdrfmt,
277 	    gettext("LSB"),
278 	    gettext("Chip"),
279 	    gettext("               ID                 "),
280 	    gettext("MHz"),
281 	    gettext(" MB"),
282 	    gettext("Impl."),
283 	    gettext("Mask"), 0);
284 
285 	log_printf(hdrfmt,
286 	"---", "----", "----------------------------------------", "----",
287 	"---",  "-----", "----", 0);
288 
289 	/* Now display all of the cpus on each board */
290 	for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) {
291 		display_cpus(bnode);
292 	}
293 
294 	log_printf("\n", 0);
295 }
296 
297 /*
298  * Display the CPUs present on this board.
299  */
300 void
301 display_cpus(Board_node *board)
302 {
303 	int *impl, *mask, *cpuid, *portid, *l2cache_size;
304 	uint_t freq;		/* CPU clock frequency */
305 	Prom_node *pnode, *cpu;
306 	char *name;
307 
308 	(void) textdomain(TEXT_DOMAIN);
309 
310 	/*
311 	 * Get the Cpus' properties for display
312 	 */
313 	for (pnode = board->nodes; pnode != NULL; pnode = pnode->sibling) {
314 		char cpu_str[MAXSTRLEN], fcpu_str[MAXSTRLEN] = {0};
315 
316 		name = get_node_name(pnode);
317 		if ((name == NULL) || (strncmp(name, "cmp", 3) != 0)) {
318 			continue;
319 		}
320 
321 		portid = (int *)get_prop_val(find_prop(pnode, "portid"));
322 		freq = (HZ_TO_MHZ(get_cpu_freq(pnode->child)));
323 		l2cache_size = (int *)get_prop_val(find_prop(pnode->child,
324 		    "l2-cache-size"));
325 		impl = (int *)get_prop_val(find_prop(pnode->child,
326 		    "implementation#"));
327 		mask = (int *)get_prop_val(find_prop(pnode->child, "mask#"));
328 
329 		/* Lsb id */
330 		log_printf(" %02d   ", board->board_num, 0);
331 
332 		if (portid != NULL)
333 			log_printf("%3d   ", (((*portid)>>3)&0x3), 0);
334 
335 		/*
336 		 * OPL
337 		 * Specific parsing of the CMP/CORE/CPU chain.
338 		 * The internal cpu tree built by walk_di_tree()
339 		 * in common code can be illustrated by the diagram
340 		 * below:
341 		 *
342 		 * Olympus:
343 		 *
344 		 *   cmp->cpu->cpu->cpu->cpu->(next board nodes)
345 		 *   / \
346 		 * core core
347 		 *
348 		 * Jupiter:
349 		 *
350 		 * cmp->cpu->cpu->cpu->cpu->cpu->cpu->cpu->cpu->(board nodes)
351 		 *   |
352 		 *  _____________
353 		 * /   \    \    \
354 		 * core core core core
355 		 *
356 		 *
357 		 * where "/" or "\" are children
358 		 *    and "->" are siblings
359 		 *
360 		 */
361 		for (cpu = pnode->sibling; cpu != NULL; ) {
362 			Prom_node	*cpu_next = NULL;
363 
364 			name = get_node_name(cpu);
365 			if ((name == NULL) || (strncmp(name, "cpu", 3) != 0)) {
366 				break;
367 			}
368 
369 			/* Id assigned to Virtual processor core */
370 			cpuid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
371 			cpu_next = cpu->sibling;
372 
373 			if (cpu_next != NULL) {
374 				name = get_node_name(cpu_next);
375 
376 				if ((name == NULL) ||
377 				    (strncmp(name, "cpu", 3) != 0)) {
378 					cpu_next = NULL;
379 				}
380 			}
381 
382 			if (cpuid != NULL) {
383 				/* Used for printing in comma format */
384 				(void) sprintf(cpu_str, "%4d", *cpuid);
385 				(void) strlcat(fcpu_str, cpu_str, MAXSTRLEN);
386 
387 				if (cpu_next != NULL) {
388 					(void) strlcat(fcpu_str, ",",
389 					    MAXSTRLEN);
390 				}
391 			} else {
392 				(void) sprintf(cpu_str, "%4s", "N/A");
393 				(void) strlcat(fcpu_str, cpu_str, MAXSTRLEN);
394 
395 				if (cpu_next != NULL) {
396 					(void) strlcat(fcpu_str, ",",
397 					    MAXSTRLEN);
398 				}
399 			}
400 			cpu = cpu_next;
401 		}
402 
403 		log_printf("%-40.40s", fcpu_str, 0);
404 
405 		/* Running frequency */
406 		if (freq != 0)
407 			log_printf("  %4ld  ", freq, 0);
408 		else
409 			log_printf("  %4s  ", "N/A", 0);
410 
411 		/* L2 cache size */
412 		if (l2cache_size == NULL)
413 			log_printf(" %3s    ", "N/A", 0);
414 		else {
415 			log_printf("%4.1f   ",
416 			    (float)(*l2cache_size) / (float)(1<<20), 0);
417 		}
418 
419 
420 		/* Implementation number of processor */
421 		if (impl != NULL)
422 			log_printf("  %4d  ", *impl, 0);
423 		else
424 			log_printf(" %4s     ", "N/A", 0);
425 
426 		/* Mask Set version */
427 		/* Bits 31:24 of VER register is mask. */
428 		/* Mask value : Non MTP mode - 00-7f, MTP mode - 80-ff */
429 		if (mask == NULL)
430 			log_printf("%3s", "N/A", 0);
431 		else
432 			log_printf("%-3d", (*mask)&0xff, 0);
433 
434 		log_printf("\n", 0);
435 
436 	}
437 }
438 
439 /*
440  * Gather memory information: Details of memory information.
441  */
442 static uint64_t
443 get_opl_mem_regs(Board_node *bnode)
444 {
445 	Prom_node	*pnode;
446 	struct		cs_status	*cs_stat;
447 	uint64_t	total_mem = 0;
448 	int		cs_size, ngrps;
449 
450 	pnode = dev_find_node(bnode->nodes, "pseudo-mc");
451 	while (pnode != NULL) {
452 
453 		cs_size = get_prop_size(find_prop(pnode, "cs-status"));
454 
455 		if (cs_size > 0) {
456 			int	*mirror_mode = NULL;
457 			int	mode = 0;
458 
459 			/* OBP returns lists of 7 ints */
460 			cs_stat = (struct cs_status *)get_prop_val
461 			    (find_prop(pnode, "cs-status"));
462 
463 			mirror_mode = (int *)(get_prop_val
464 			    (find_prop(pnode, "mirror-mode")));
465 
466 			if (mirror_mode != NULL)
467 				mode = (*mirror_mode);
468 
469 			/*
470 			 * The units of cs_size will be either number of bytes
471 			 * or number of int array elements as this is derived
472 			 * from the libprtdiag Prop node size field which has
473 			 * inconsistent units.   Until this is addressed in
474 			 * libprtdiag, we need a heuristic to determine the
475 			 * number of CS groups.  Given that the maximum number
476 			 * of CS groups is 2, the maximum number of cs-status
477 			 * array elements will be 2*7=14.  Since this is smaller
478 			 * than the byte size of a single struct status, we use
479 			 * this to decide if we are dealing with bytes or array
480 			 * elements in determining the number of CS groups.
481 			 */
482 			if (cs_size < sizeof (struct cs_status)) {
483 				/* cs_size is number of total int [] elements */
484 				ngrps = cs_size / 7;
485 			} else {
486 				/* cs_size is total byte count */
487 				ngrps = cs_size/sizeof (struct cs_status);
488 			}
489 
490 			if (cs_stat != NULL) {
491 				total_mem +=
492 				    print_opl_memory_line(bnode->board_num,
493 				    cs_stat, ngrps, mode);
494 			}
495 		}
496 
497 		pnode = dev_next_node(pnode, "pseudo-mc");
498 	}
499 	return (total_mem);
500 }
501 
502 /*
503  * Display memory information.
504  */
505 /*ARGSUSED*/
506 void
507 display_memoryconf(Sys_tree *tree, struct grp_info *grps)
508 {
509 	Board_node	*bnode = tree->bd_list;
510 	uint64_t	total_mem = 0, total_sys_mem = 0;
511 	char *hdrfmt =  "\n%-5.5s  %-6.6s  %-18.18s  %-10.10s"
512 	    " %-6.6s  %-5.5s %-7.7s %-10.10s";
513 
514 	(void) textdomain(TEXT_DOMAIN);
515 
516 	log_printf("============================", 0);
517 	log_printf(gettext(" Memory Configuration "), 0);
518 	log_printf("============================", 0);
519 	log_printf("\n", 0);
520 
521 	log_printf(hdrfmt,
522 	    "",
523 	    gettext("Memory"),
524 	    gettext("Available"),
525 	    gettext("Memory"),
526 	    gettext("DIMM"),
527 	    gettext("# of"),
528 	    gettext("Mirror"),
529 	    gettext("Interleave"),
530 	    0);
531 
532 	log_printf(hdrfmt,
533 	    gettext("LSB"),
534 	    gettext("Group"),
535 	    gettext("Size"),
536 	    gettext("Status"),
537 	    gettext("Size"),
538 	    gettext("DIMMs"),
539 	    gettext("Mode"),
540 	    gettext("Factor"), 0);
541 
542 	log_printf(hdrfmt,
543 	    "---", "-------", "------------------", "-------", "------",
544 	    "-----", "-------", "----------",  0);
545 
546 	log_printf("\n", 0);
547 
548 	for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) {
549 		total_mem += get_opl_mem_regs(bnode);
550 	}
551 
552 	/*
553 	 * Sanity check to ensure that the total amount of system
554 	 * memory matches the total number of memory that
555 	 * we find here. Display error message if there is a mis-match.
556 	 */
557 	total_sys_mem = (((uint64_t)sysconf(_SC_PAGESIZE) * (uint64_t)sysconf
558 	    (_SC_PHYS_PAGES)) / MBYTE);
559 
560 	if (total_mem != total_sys_mem) {
561 		log_printf(dgettext(TEXT_DOMAIN, "\nError:total available "
562 		    "size [%lldMB] does not match total system memory "
563 		    "[%lldMB]\n"), total_mem, total_sys_mem, 0);
564 	}
565 
566 }
567 
568 /*
569  * This function provides Opl's formatting of the memory config
570  * information that get_opl_mem_regs() has gathered.
571  */
572 static uint64_t
573 print_opl_memory_line(int lsb, struct cs_status *cs_stat, int ngrps,
574 	int mirror_mode)
575 {
576 	int	i;
577 	uint64_t	total_board_mem = 0;
578 	int		i_factor = 2;   /* default to non-mirror mode */
579 	int		interleave;
580 
581 	(void) textdomain(TEXT_DOMAIN);
582 
583 	if (mirror_mode)
584 		i_factor *= 2;
585 
586 	/*
587 	 * Interleave factor calculation:
588 	 * Obtain "mirror-mode" property from pseudo-mc.
589 	 * cs_stat[0].dimms/i_factor represents interleave factor per
590 	 * pseudo-mc node. Must use cs_stat[0].dimms since this will yield
591 	 * interleave factor even if some DIMMs are isolated.
592 	 *
593 	 * Mirror mode:
594 	 *   interleave factor = (# of DIMMs on cs_stat[0]/4)
595 	 *
596 	 * Non-mirror mode:
597 	 *   interleave factor = (# of DIMMs on cs_stat[0]/2)
598 	 */
599 
600 	interleave = cs_stat[0].dimms/i_factor;
601 
602 
603 	for (i = 0; i < ngrps; i++) {
604 		uint64_t	mem_size;
605 
606 		mem_size = ((((uint64_t)cs_stat[i].avail_hi)<<32) +
607 		    cs_stat[i].avail_lo);
608 
609 		if (mem_size == 0)
610 			continue;
611 
612 		/* Lsb Id */
613 		log_printf(" %02d    ", lsb, 0);
614 
615 		/* Memory Group Number */
616 		if ((cs_stat[i].cs_number) == 0)
617 			log_printf("%-6.6s", "A", 0);
618 		else
619 			log_printf("%-6.6s", "B", 0);
620 
621 		/* Memory Group Size */
622 		log_printf("%8lldMB            ", mem_size/MBYTE, 0);
623 
624 		total_board_mem += (mem_size/MBYTE);
625 
626 		/* Memory Group Status */
627 		log_printf("%-11.11s",
628 		    cs_stat[i].status ? "partial": "okay", 0);
629 
630 		/* DIMM Size */
631 		log_printf("%4lldMB   ",
632 		    ((((uint64_t)cs_stat[i].dimm_hi)<<32)
633 		    + cs_stat[i].dimm_lo)/MBYTE, 0);
634 
635 		/* Number of DIMMs */
636 		log_printf("  %2d", cs_stat[i].dimms);
637 
638 		/* Mirror Mode */
639 		if (mirror_mode) {
640 			log_printf("%-4.4s", " yes");
641 		} else
642 			log_printf("%-4.4s", " no ");
643 
644 		/* Interleave Factor */
645 		if (interleave)
646 			log_printf("      %d-way\n", interleave);
647 		else
648 			log_printf("      None\n");
649 	}
650 	return (total_board_mem);
651 }
652 
653 /*
654  * Details of hardware revision and environmental status.
655  */
656 /*ARGSUSED*/
657 void
658 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
659 	struct system_kstat_data *kstats)
660 {
661 	/* Print the PROM revisions */
662 	opl_disp_hw_revisions(tree, root);
663 }
664 
665 /*
666  * Gather and display hardware revision and environmental status
667  */
668 /*ARGSUSED*/
669 static void
670 opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root)
671 {
672 	char		*version;
673 	Prom_node	*pnode;
674 	int		value;
675 
676 	(void) textdomain(TEXT_DOMAIN);
677 
678 	/* Print the header */
679 	log_printf("\n", 0);
680 	log_printf("====================", 0);
681 	log_printf(gettext(" Hardware Revisions "), 0);
682 	log_printf("====================", 0);
683 	log_printf("\n\n", 0);
684 
685 	/* Display Prom revision header */
686 	log_printf(gettext("System PROM revisions:"), 0);
687 	log_printf("\n----------------------\n", 0);
688 	log_printf("\n", 0);
689 
690 	/* Display OBP version info */
691 	pnode = dev_find_node(root, "openprom");
692 	if (pnode != NULL) {
693 		version = (char *)get_prop_val(find_prop(pnode, "version"));
694 		if (version != NULL)
695 			log_printf("%s\n\n", version, 0);
696 		else
697 			log_printf("%s\n\n", "N/A", 0);
698 	}
699 
700 	/* Print the header */
701 	log_printf("\n", 0);
702 	log_printf("===================", 0);
703 	log_printf(gettext(" Environmental Status "), 0);
704 	log_printf("===================", 0);
705 	log_printf("\n\n", 0);
706 
707 	opl_disp_environ();
708 
709 	/*
710 	 * PICL interface needs to be used for system processor mode display.
711 	 * Check existence of OBP property "SPARC64-VII-mode".
712 	 * No display if property does not exist.
713 	 * If property exists then system is in (Jupiter) SPARC64-VII-mode.
714 	 */
715 	value = get_proc_mode();
716 
717 	if (value == 0) {
718 		/* Print the header */
719 		log_printf("\n", 0);
720 		log_printf("===================", 0);
721 		log_printf(gettext(" System Processor Mode "), 0);
722 		log_printf("===================", 0);
723 		log_printf("\n\n", 0);
724 
725 		/* Jupiter mode */
726 		log_printf("%s\n\n", "SPARC64-VII mode");
727 	}
728 }
729 
730 /*
731  * Gather environmental information
732  */
733 static void
734 opl_disp_environ(void)
735 {
736 	kstat_ctl_t *kc;
737 	kstat_t *ksp;
738 	kstat_named_t   *k;
739 
740 	if ((kc = kstat_open()) == NULL)
741 		return;
742 
743 	if ((ksp = kstat_lookup
744 	    (kc, "scfd", 0, SCF_SYSTEM_KSTAT_NAME)) == NULL) {
745 		(void) kstat_close(kc);
746 		return;
747 	}
748 
749 	if (kstat_read(kc, ksp, NULL) == -1) {
750 		(void) kstat_close(kc);
751 		return;
752 	}
753 
754 	if ((k = (kstat_named_t *)kstat_data_lookup
755 	    (ksp, SCF_SECURE_MODE_KSTAT_NAMED)) == NULL) {
756 		(void) kstat_close(kc);
757 		return;
758 	}
759 
760 	if (k->value.c[0] == SCF_STAT_MODE_LOCK)
761 		log_printf("Mode switch is in LOCK mode ", 0);
762 	else if (k->value.c[0] == SCF_STAT_MODE_UNLOCK)
763 		log_printf("Mode switch is in UNLOCK mode", 0);
764 	else
765 		log_printf("Mode switch is in UNKNOWN mode", 0);
766 
767 	log_printf("\n", 0);
768 
769 	(void) kstat_close(kc);
770 }
771 
772 
773 /*
774  * Calls do_devinfo() in order to use the libdevinfo device tree
775  * instead of OBP's device tree.
776  */
777 int
778 do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
779 {
780 	v_flag = syserrlog;
781 	return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
782 }
783 
784 /*
785  * Return the property value for the Prop
786  * passed in. (When using libdevinfo)
787  */
788 void *
789 get_prop_val(Prop *prop)
790 {
791 	if (prop == NULL)
792 		return (NULL);
793 
794 	return ((void *)(prop->value.val_ptr));
795 }
796 
797 /*
798  * Return the property size for the Prop
799  * passed in. (When using libdevinfo)
800  */
801 static int
802 get_prop_size(Prop *prop)
803 {
804 
805 	if ((prop != NULL) && (prop->size > 0))
806 		return (prop->size);
807 	else
808 		return (0);
809 }
810 
811 
812 /*
813  * Search a Prom node and retrieve the property with the correct
814  * name. (When using libdevinfo)
815  */
816 Prop *
817 find_prop(Prom_node *pnode, char *name)
818 {
819 	Prop *prop;
820 
821 	if (pnode == NULL)
822 		return (NULL);
823 
824 	for (prop = pnode->props; prop != NULL; prop = prop->next) {
825 		if (prop->name.val_ptr != NULL &&
826 		    strcmp((char *)(prop->name.val_ptr), name) == 0)
827 			break;
828 	}
829 
830 	return (prop);
831 }
832 
833 /*
834  * This function adds a board node to the board structure where that
835  * that node's physical component lives.
836  */
837 void
838 add_node(Sys_tree *root, Prom_node *pnode)
839 {
840 	int board;
841 	Board_node *bnode;
842 	Prom_node *p;
843 	char *type;
844 
845 	if ((board = get_board_num(pnode)) == -1) {
846 		type = get_node_type(pnode);
847 		if ((type != NULL) && (strcmp(type, "cpu") == 0))
848 			board = get_board_num((pnode->parent)->parent);
849 	}
850 
851 	/* find the node with the same board number */
852 	if ((bnode = find_board(root, board)) == NULL) {
853 		bnode = insert_board(root, board);
854 		bnode->board_type = UNKNOWN_BOARD;
855 	}
856 
857 	/* now attach this prom node to the board list */
858 	/* Insert this node at the end of the list */
859 	pnode->sibling = NULL;
860 	if (bnode->nodes == NULL)
861 		bnode->nodes = pnode;
862 	else {
863 		p = bnode->nodes;
864 		while (p->sibling != NULL)
865 			p = p->sibling;
866 		p->sibling = pnode;
867 	}
868 
869 }
870