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