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