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