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