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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <alloca.h> 31 #include <unistd.h> 32 #include <ctype.h> 33 #include <string.h> 34 #include <kvm.h> 35 #include <varargs.h> 36 #include <time.h> 37 #include <dirent.h> 38 #include <fcntl.h> 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <sys/utsname.h> 43 #include <sys/openpromio.h> 44 #include <libintl.h> 45 #include <syslog.h> 46 #include <sys/dkio.h> 47 #include <sys/systeminfo.h> 48 #include <picldefs.h> 49 #include <math.h> 50 #include <errno.h> 51 #include "pdevinfo.h" 52 #include "display.h" 53 #include "display_sun4v.h" 54 #include "libprtdiag.h" 55 56 #if !defined(TEXT_DOMAIN) 57 #define TEXT_DOMAIN "SYS_TEST" 58 #endif 59 60 #define MOTHERBOARD "MB" 61 #define NETWORK "network" 62 #define SUN4V_MACHINE "sun4v" 63 #define PARENT_NAMES 10 64 65 /* 66 * Additional OBP properties 67 */ 68 #define OBP_PROP_COMPATIBLE "compatible" 69 #define OBP_PROP_MODEL "model" 70 #define OBP_PROP_SLOT_NAMES "slot-names" 71 #define OBP_PROP_VERSION "version" 72 73 #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform" 74 #define PICL_NODE_CHASSIS "chassis" 75 #define MEMORY_SIZE_FIELD 11 76 #define INVALID_THRESHOLD 1000000 77 78 /* 79 * Additional picl classes 80 */ 81 #ifndef PICL_CLASS_SUN4V 82 #define PICL_CLASS_SUN4V "sun4v" 83 #endif 84 85 #ifndef PICL_PROP_NAC 86 #define PICL_PROP_NAC "nac" 87 #endif 88 89 extern int sys_clk; 90 extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *, 91 picl_nodehdl_t *); 92 93 static picl_nodehdl_t rooth = 0, phyplatformh = 0; 94 static picl_nodehdl_t chassish = 0; 95 static int class_node_found; 96 static int syserrlog; 97 static int all_status_ok; 98 99 /* local functions */ 100 static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **); 101 static void sun4v_display_memory_conf(picl_nodehdl_t); 102 static int sun4v_disp_env_status(); 103 static void sun4v_env_print_fan_sensors(); 104 static void sun4v_env_print_fan_indicators(); 105 static void sun4v_env_print_temp_sensors(); 106 static void sun4v_env_print_temp_indicators(); 107 static void sun4v_env_print_current_sensors(); 108 static void sun4v_env_print_current_indicators(); 109 static void sun4v_env_print_voltage_sensors(); 110 static void sun4v_env_print_voltage_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_LEDs(); 1104 exit_code |= (!all_status_ok); 1105 1106 class_node_found = 0; 1107 all_status_ok = 1; 1108 sun4v_print_fru_status(); 1109 exit_code |= (!all_status_ok); 1110 1111 class_node_found = 0; 1112 sun4v_print_fw_rev(); 1113 1114 class_node_found = 0; 1115 sun4v_print_openprom_rev(); 1116 1117 sun4v_print_chassis_serial_no(); 1118 1119 return (exit_code); 1120 } 1121 1122 /*ARGSUSED*/ 1123 static int 1124 sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 1125 { 1126 char val[PICL_PROPNAMELEN_MAX]; 1127 picl_nodehdl_t parenth; 1128 char *names[PARENT_NAMES]; 1129 char *base_units[PICL_PROPNAMELEN_MAX]; 1130 char *loc; 1131 int i; 1132 char *prop; 1133 picl_errno_t err; 1134 int32_t lo_warning, lo_shutdown, lo_poweroff; 1135 int32_t hi_warning, hi_shutdown, hi_poweroff; 1136 int32_t current_val; 1137 int32_t exponent; 1138 double display_val; 1139 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 1140 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 1141 sensor_status_t sensor_status = SENSOR_OK; 1142 1143 if (class_node_found == 0) { 1144 class_node_found = 1; 1145 return (PICL_WALK_TERMINATE); 1146 } 1147 1148 prop = (char *)args; 1149 if (!prop) { 1150 sensor_status = SENSOR_UNKNOWN; 1151 all_status_ok = 0; 1152 } else { 1153 err = picl_get_propval_by_name(nodeh, 1154 PICL_PROP_OPERATIONAL_STATUS, val, 1155 sizeof (val)); 1156 if (err == PICL_SUCCESS) { 1157 if (strcmp(val, "disabled") == 0) { 1158 sensor_status = SENSOR_DISABLED; 1159 } 1160 } 1161 } 1162 1163 if (sensor_status != SENSOR_DISABLED && 1164 sensor_status != SENSOR_UNKNOWN) { 1165 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 1166 sizeof (current_val)) != PICL_SUCCESS) { 1167 sensor_status = SENSOR_UNKNOWN; 1168 } else { 1169 if (picl_get_propval_by_name(nodeh, 1170 PICL_PROP_LOW_WARNING, 1171 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 1172 lo_warning = INVALID_THRESHOLD; 1173 if (picl_get_propval_by_name(nodeh, 1174 PICL_PROP_LOW_SHUTDOWN, 1175 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 1176 lo_shutdown = INVALID_THRESHOLD; 1177 if (picl_get_propval_by_name(nodeh, 1178 PICL_PROP_LOW_POWER_OFF, 1179 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS) 1180 lo_poweroff = INVALID_THRESHOLD; 1181 if (picl_get_propval_by_name(nodeh, 1182 PICL_PROP_HIGH_WARNING, 1183 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 1184 hi_warning = INVALID_THRESHOLD; 1185 if (picl_get_propval_by_name(nodeh, 1186 PICL_PROP_HIGH_SHUTDOWN, 1187 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 1188 hi_shutdown = INVALID_THRESHOLD; 1189 if (picl_get_propval_by_name(nodeh, 1190 PICL_PROP_HIGH_POWER_OFF, 1191 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS) 1192 hi_poweroff = INVALID_THRESHOLD; 1193 1194 if ((lo_poweroff != INVALID_THRESHOLD && 1195 current_val <= lo_poweroff) || 1196 (hi_poweroff != INVALID_THRESHOLD && 1197 current_val >= hi_poweroff)) { 1198 sensor_status = SENSOR_FAILED; 1199 } else if ((lo_shutdown != INVALID_THRESHOLD && 1200 current_val <= lo_shutdown) || 1201 (hi_shutdown != INVALID_THRESHOLD && 1202 current_val >= hi_shutdown)) { 1203 sensor_status = SENSOR_FAILED; 1204 } else if ((lo_warning != INVALID_THRESHOLD && 1205 current_val <= lo_warning) || 1206 (hi_warning != INVALID_THRESHOLD && 1207 current_val >= hi_warning)) { 1208 sensor_status = SENSOR_WARN; 1209 } else { 1210 sensor_status = SENSOR_OK; 1211 } 1212 } 1213 } 1214 1215 if (syserrlog == 0) { 1216 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 1217 all_status_ok = 0; 1218 return (PICL_WALK_TERMINATE); 1219 } 1220 if (sensor_status == SENSOR_OK) { 1221 return (PICL_WALK_CONTINUE); 1222 } 1223 } 1224 1225 /* 1226 * If we're here then prtdiag was invoked with "-v" or we have 1227 * a sensor that is beyond a threshold, so give them a book to 1228 * read instead of the Cliff Notes. 1229 */ 1230 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1231 sizeof (parenth)); 1232 if (err != PICL_SUCCESS) { 1233 log_printf("\n"); 1234 return (PICL_WALK_CONTINUE); 1235 } 1236 1237 /* gather up the path name for the sensor */ 1238 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1239 for (i = 0; i < PARENT_NAMES; i++) { 1240 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1241 NULL) { 1242 while (--i > -1) 1243 free(names[i]); 1244 free(loc); 1245 loc = NULL; 1246 } 1247 } 1248 } 1249 i = 0; 1250 if (loc != 0) { 1251 while (err == PICL_SUCCESS) { 1252 if (parenth == phyplatformh) 1253 break; 1254 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1255 names[i++], PICL_PROPNAMELEN_MAX); 1256 if (err != PICL_SUCCESS) { 1257 i--; 1258 break; 1259 } 1260 if (i == PARENT_NAMES) 1261 break; 1262 err = picl_get_propval_by_name(parenth, 1263 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1264 } 1265 loc[0] = '\0'; 1266 if (--i > -1) { 1267 (void) strlcat(loc, names[i], 1268 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1269 } 1270 while (--i > -1) { 1271 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1272 PARENT_NAMES); 1273 (void) strlcat(loc, names[i], 1274 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1275 } 1276 log_printf("%-35s", loc); 1277 for (i = 0; i < PARENT_NAMES; i++) 1278 free(names[i]); 1279 free(loc); 1280 } else { 1281 log_printf("%-35s", " "); 1282 } 1283 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 1284 sizeof (val)); 1285 if (err == PICL_SUCCESS) 1286 log_printf("%-15s", val); 1287 1288 /* 1289 * Get the exponent if present, and do a little math so that 1290 * if we need to we can print a normalized value for the 1291 * sensor reading. 1292 */ 1293 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 1294 &exponent, sizeof (exponent)) != PICL_SUCCESS) 1295 exponent = 0; 1296 if (exponent == 0) 1297 display_val = (double)current_val; 1298 else { 1299 display_val = (double)current_val * 1300 pow((double)10, (double)exponent); 1301 1302 /* 1303 * Sometimes ILOM will scale a sensor reading but 1304 * there will be nothing to the right of the decimal 1305 * once that value is normalized. Setting the 1306 * exponent to zero will prevent the printf below 1307 * from printing extraneous zeros. Otherwise a 1308 * negative exponent is used to set the precision 1309 * for the printf. 1310 */ 1311 if ((int)display_val == display_val || exponent > 0) 1312 exponent = 0; 1313 } 1314 1315 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 1316 base_units, sizeof (base_units)); 1317 if (err != PICL_SUCCESS) 1318 base_units[0] = '\0'; 1319 1320 switch (sensor_status) { 1321 case SENSOR_FAILED: 1322 log_printf("%-s", "failed ("); 1323 log_printf("%-.*f", abs(exponent), display_val); 1324 log_printf("%-s %s", base_units, ")"); 1325 break; 1326 case SENSOR_WARN: 1327 log_printf("%-s", "warning ("); 1328 log_printf("%-.*f", abs(exponent), display_val); 1329 log_printf("%-s %s", base_units, ")"); 1330 break; 1331 case SENSOR_DISABLED: 1332 log_printf("%-s", "disabled"); 1333 break; 1334 case SENSOR_OK: 1335 log_printf("%-s", "ok"); 1336 break; 1337 default: 1338 log_printf("%-s", "unknown"); 1339 break; 1340 } 1341 1342 log_printf("\n"); 1343 return (PICL_WALK_CONTINUE); 1344 } 1345 1346 /*ARGSUSED*/ 1347 static int 1348 sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 1349 { 1350 char current_val[PICL_PROPNAMELEN_MAX]; 1351 char expected_val[PICL_PROPNAMELEN_MAX]; 1352 char label[PICL_PROPNAMELEN_MAX]; 1353 picl_nodehdl_t parenth; 1354 char *names[PARENT_NAMES]; 1355 char *loc; 1356 int i = 0; 1357 char *prop = (char *)args; 1358 picl_errno_t err = PICL_SUCCESS; 1359 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 1360 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 1361 sensor_status_t sensor_status = SENSOR_OK; 1362 1363 if (class_node_found == 0) { 1364 class_node_found = 1; 1365 return (PICL_WALK_TERMINATE); 1366 } 1367 1368 prop = (char *)args; 1369 if (!prop) { 1370 sensor_status = SENSOR_UNKNOWN; 1371 all_status_ok = 0; 1372 } else { 1373 err = picl_get_propval_by_name(nodeh, 1374 PICL_PROP_OPERATIONAL_STATUS, current_val, 1375 sizeof (current_val)); 1376 if (err == PICL_SUCCESS) { 1377 if (strcmp(current_val, "disabled") == 0) { 1378 sensor_status = SENSOR_DISABLED; 1379 } 1380 } 1381 } 1382 1383 if (sensor_status != SENSOR_DISABLED && 1384 sensor_status != SENSOR_UNKNOWN) { 1385 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 1386 sizeof (current_val)) != PICL_SUCCESS) { 1387 (void) strlcpy(current_val, "unknown", 1388 sizeof (current_val)); 1389 sensor_status = SENSOR_UNKNOWN; 1390 } else { 1391 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 1392 &expected_val, sizeof (expected_val)) != 1393 PICL_SUCCESS) { 1394 sensor_status = SENSOR_UNKNOWN; 1395 } else { 1396 if (strncmp(current_val, expected_val, 1397 sizeof (current_val)) == 0) { 1398 sensor_status = SENSOR_OK; 1399 } else { 1400 sensor_status = SENSOR_FAILED; 1401 } 1402 } 1403 } 1404 } 1405 1406 if (syserrlog == 0) { 1407 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 1408 all_status_ok = 0; 1409 return (PICL_WALK_TERMINATE); 1410 } 1411 if (sensor_status == SENSOR_OK) { 1412 return (PICL_WALK_CONTINUE); 1413 } 1414 } 1415 1416 /* 1417 * If we're here then prtdiag was invoked with "-v" or we have 1418 * a sensor that is beyond a threshold, so give them a book to 1419 * read instead of the Cliff Notes. 1420 */ 1421 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1422 sizeof (parenth)); 1423 if (err != PICL_SUCCESS) { 1424 log_printf("\n"); 1425 return (PICL_WALK_CONTINUE); 1426 } 1427 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1428 for (i = 0; i < PARENT_NAMES; i++) { 1429 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1430 NULL) { 1431 while (--i > -1) 1432 free(names[i]); 1433 free(loc); 1434 loc = NULL; 1435 } 1436 } 1437 } 1438 i = 0; 1439 if (loc) { 1440 while (err == PICL_SUCCESS) { 1441 if (parenth == phyplatformh) 1442 break; 1443 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1444 names[i++], PICL_PROPNAMELEN_MAX); 1445 if (err != PICL_SUCCESS) { 1446 i--; 1447 break; 1448 } 1449 if (i == PARENT_NAMES) 1450 break; 1451 err = picl_get_propval_by_name(parenth, 1452 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1453 } 1454 loc[0] = '\0'; 1455 if (--i > -1) { 1456 (void) strlcat(loc, names[i], 1457 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1458 } 1459 while (--i > -1) { 1460 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1461 PARENT_NAMES); 1462 (void) strlcat(loc, names[i], 1463 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1464 } 1465 log_printf("%-35s", loc); 1466 for (i = 0; i < PARENT_NAMES; i++) 1467 free(names[i]); 1468 free(loc); 1469 } else { 1470 log_printf("%-35s", ""); 1471 } 1472 1473 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1474 sizeof (label)); 1475 if (err != PICL_SUCCESS) 1476 (void) strlcpy(label, "", sizeof (label)); 1477 log_printf("%-15s", label); 1478 1479 log_printf("%-8s", current_val); 1480 1481 log_printf("\n"); 1482 return (PICL_WALK_CONTINUE); 1483 } 1484 1485 static void 1486 sun4v_env_print_fan_sensors() 1487 { 1488 char *fmt = "%-34s %-14s %-10s\n"; 1489 /* 1490 * If there isn't any fan sensor node, return now. 1491 */ 1492 (void) picl_walk_tree_by_class(phyplatformh, 1493 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 1494 sun4v_env_print_sensor_callback); 1495 if (!class_node_found) 1496 return; 1497 log_printf("Fan sensors:\n"); 1498 if (syserrlog == 0) { 1499 (void) picl_walk_tree_by_class(phyplatformh, 1500 PICL_CLASS_RPM_SENSOR, 1501 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 1502 if (all_status_ok) { 1503 log_printf("All fan sensors are OK.\n"); 1504 return; 1505 } 1506 } 1507 log_printf("-------------------------------------------------" 1508 "-----------\n"); 1509 log_printf(fmt, "Location", "Sensor", "Status", 0); 1510 log_printf("-------------------------------------------------" 1511 "-----------\n"); 1512 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 1513 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 1514 } 1515 1516 static void 1517 sun4v_env_print_fan_indicators() 1518 { 1519 char *fmt = "%-34s %-14s %-10s\n"; 1520 (void) picl_walk_tree_by_class(phyplatformh, 1521 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 1522 sun4v_env_print_indicator_callback); 1523 if (!class_node_found) 1524 return; 1525 log_printf("\nFan indicators:\n"); 1526 if (syserrlog == 0) { 1527 (void) picl_walk_tree_by_class(phyplatformh, 1528 PICL_CLASS_RPM_INDICATOR, 1529 (void *)PICL_PROP_CONDITION, 1530 sun4v_env_print_indicator_callback); 1531 if (all_status_ok) { 1532 log_printf("All fan indicators are OK.\n"); 1533 return; 1534 } 1535 } 1536 log_printf("-------------------------------------------------" 1537 "-----------\n"); 1538 log_printf(fmt, "Location", "Sensor", "Condition", 0); 1539 log_printf("-------------------------------------------------" 1540 "-----------\n"); 1541 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 1542 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 1543 } 1544 1545 static void 1546 sun4v_env_print_temp_sensors() 1547 { 1548 char *fmt = "%-34s %-14s %-10s\n"; 1549 (void) picl_walk_tree_by_class(phyplatformh, 1550 PICL_CLASS_TEMPERATURE_SENSOR, 1551 (void *)PICL_PROP_TEMPERATURE, 1552 sun4v_env_print_sensor_callback); 1553 if (!class_node_found) 1554 return; 1555 1556 log_printf("\nTemperature sensors:\n"); 1557 if (syserrlog == 0) { 1558 (void) picl_walk_tree_by_class(phyplatformh, 1559 PICL_CLASS_TEMPERATURE_SENSOR, 1560 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 1561 if (all_status_ok) { 1562 log_printf("All temperature sensors are OK.\n"); 1563 return; 1564 } 1565 } 1566 log_printf("-------------------------------------------------" 1567 "-----------\n"); 1568 log_printf(fmt, "Location", "Sensor", "Status", 0); 1569 log_printf("-------------------------------------------------" 1570 "-----------\n"); 1571 (void) picl_walk_tree_by_class(phyplatformh, 1572 PICL_CLASS_TEMPERATURE_SENSOR, 1573 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 1574 } 1575 1576 static void 1577 sun4v_env_print_temp_indicators() 1578 { 1579 char *fmt = "%-34s %-14s %-8s\n"; 1580 (void) picl_walk_tree_by_class(phyplatformh, 1581 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 1582 sun4v_env_print_indicator_callback); 1583 if (!class_node_found) 1584 return; 1585 log_printf("\nTemperature indicators:\n"); 1586 if (syserrlog == 0) { 1587 (void) picl_walk_tree_by_class(phyplatformh, 1588 PICL_CLASS_TEMPERATURE_INDICATOR, 1589 (void *)PICL_PROP_CONDITION, 1590 sun4v_env_print_indicator_callback); 1591 if (all_status_ok) { 1592 log_printf("All temperature indicators are OK.\n"); 1593 return; 1594 } 1595 } 1596 log_printf("-------------------------------------------------" 1597 "-----------\n"); 1598 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1599 log_printf("-------------------------------------------------" 1600 "-----------\n"); 1601 (void) picl_walk_tree_by_class(phyplatformh, 1602 PICL_CLASS_TEMPERATURE_INDICATOR, 1603 (void *)PICL_PROP_CONDITION, 1604 sun4v_env_print_indicator_callback); 1605 } 1606 1607 static void 1608 sun4v_env_print_current_sensors() 1609 { 1610 char *fmt = "%-34s %-14s %-10s\n"; 1611 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 1612 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 1613 if (!class_node_found) 1614 return; 1615 log_printf("\nCurrent sensors:\n"); 1616 if (syserrlog == 0) { 1617 (void) picl_walk_tree_by_class(phyplatformh, 1618 PICL_CLASS_CURRENT_SENSOR, 1619 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 1620 if (all_status_ok) { 1621 log_printf("All current sensors are OK.\n"); 1622 return; 1623 } 1624 } 1625 log_printf("-------------------------------------------------" 1626 "-----------\n"); 1627 log_printf(fmt, "Location", "Sensor", "Status", 0); 1628 log_printf("-------------------------------------------------" 1629 "-----------\n"); 1630 (void) picl_walk_tree_by_class(phyplatformh, 1631 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 1632 sun4v_env_print_sensor_callback); 1633 } 1634 1635 static void 1636 sun4v_env_print_current_indicators() 1637 { 1638 char *fmt = "%-34s %-14s %-8s\n"; 1639 (void) picl_walk_tree_by_class(phyplatformh, 1640 PICL_CLASS_CURRENT_INDICATOR, 1641 (void *)PICL_PROP_CONDITION, 1642 sun4v_env_print_indicator_callback); 1643 if (!class_node_found) 1644 return; 1645 log_printf("\nCurrent indicators:\n"); 1646 if (syserrlog == 0) { 1647 (void) picl_walk_tree_by_class(phyplatformh, 1648 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 1649 sun4v_env_print_indicator_callback); 1650 if (all_status_ok) { 1651 log_printf("All current indicators are OK.\n"); 1652 return; 1653 } 1654 } 1655 log_printf("-------------------------------------------------" 1656 "-----------\n"); 1657 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1658 log_printf("-------------------------------------------------" 1659 "-----------\n"); 1660 (void) picl_walk_tree_by_class(phyplatformh, 1661 PICL_CLASS_CURRENT_INDICATOR, 1662 (void *)PICL_PROP_CONDITION, 1663 sun4v_env_print_indicator_callback); 1664 } 1665 1666 static void 1667 sun4v_env_print_voltage_sensors() 1668 { 1669 char *fmt = "%-34s %-14s %-10s\n"; 1670 (void) picl_walk_tree_by_class(phyplatformh, 1671 PICL_CLASS_VOLTAGE_SENSOR, 1672 PICL_PROP_VOLTAGE, 1673 sun4v_env_print_sensor_callback); 1674 if (!class_node_found) 1675 return; 1676 log_printf("\nVoltage sensors:\n"); 1677 if (syserrlog == 0) { 1678 (void) picl_walk_tree_by_class(phyplatformh, 1679 PICL_CLASS_VOLTAGE_SENSOR, 1680 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 1681 if (all_status_ok) { 1682 log_printf("All voltage sensors are OK.\n"); 1683 return; 1684 } 1685 } 1686 log_printf("-------------------------------------------------" 1687 "-----------\n"); 1688 log_printf(fmt, "Location", "Sensor", "Status", 0); 1689 log_printf("-------------------------------------------------" 1690 "-----------\n"); 1691 (void) picl_walk_tree_by_class(phyplatformh, 1692 PICL_CLASS_VOLTAGE_SENSOR, 1693 (void *)PICL_PROP_VOLTAGE, 1694 sun4v_env_print_sensor_callback); 1695 } 1696 1697 static void 1698 sun4v_env_print_voltage_indicators() 1699 { 1700 char *fmt = "%-34s %-14s %-8s\n"; 1701 (void) picl_walk_tree_by_class(phyplatformh, 1702 PICL_CLASS_VOLTAGE_INDICATOR, 1703 (void *)PICL_PROP_CONDITION, 1704 sun4v_env_print_indicator_callback); 1705 if (!class_node_found) 1706 return; 1707 log_printf("\nVoltage indicators:\n"); 1708 if (syserrlog == 0) { 1709 (void) picl_walk_tree_by_class(phyplatformh, 1710 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 1711 sun4v_env_print_indicator_callback); 1712 if (all_status_ok) { 1713 log_printf("All voltage indicators are OK.\n"); 1714 return; 1715 } 1716 } 1717 log_printf("-------------------------------------------------" 1718 "-----------\n"); 1719 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1720 log_printf("-------------------------------------------------" 1721 "-----------\n"); 1722 (void) picl_walk_tree_by_class(phyplatformh, 1723 PICL_CLASS_VOLTAGE_INDICATOR, 1724 (void *)PICL_PROP_CONDITION, 1725 sun4v_env_print_indicator_callback); 1726 } 1727 1728 static void 1729 sun4v_env_print_LEDs() 1730 { 1731 char *fmt = "%-34s %-14s %-8s\n"; 1732 if (syserrlog == 0) 1733 return; 1734 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 1735 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 1736 if (!class_node_found) 1737 return; 1738 log_printf("\nLEDs:\n"); 1739 log_printf("-------------------------------------------------" 1740 "-----------\n"); 1741 log_printf(fmt, "Location", "LED", "State", 0); 1742 log_printf("-------------------------------------------------" 1743 "-----------\n"); 1744 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 1745 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 1746 } 1747 1748 /*ARGSUSED*/ 1749 static int 1750 sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 1751 { 1752 char label[PICL_PROPNAMELEN_MAX]; 1753 char status[PICL_PROPNAMELEN_MAX]; 1754 picl_errno_t err; 1755 picl_prophdl_t proph; 1756 picl_nodehdl_t parenth; 1757 char *names[PARENT_NAMES]; 1758 char *loc; 1759 int i; 1760 1761 if (!class_node_found) { 1762 class_node_found = 1; 1763 return (PICL_WALK_TERMINATE); 1764 } 1765 err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 1766 if (err != PICL_SUCCESS) 1767 return (PICL_WALK_CONTINUE); 1768 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1769 sizeof (label)); 1770 if (err != PICL_SUCCESS) 1771 return (PICL_WALK_CONTINUE); 1772 err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 1773 status, sizeof (status)); 1774 if (err != PICL_SUCCESS) 1775 return (PICL_WALK_CONTINUE); 1776 if (syserrlog == 0) { 1777 if (strcmp(status, "disabled") == 0) { 1778 if (all_status_ok) { 1779 all_status_ok = 0; 1780 return (PICL_WALK_TERMINATE); 1781 } 1782 } else 1783 return (PICL_WALK_CONTINUE); 1784 } 1785 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1786 sizeof (parenth)); 1787 if (err != PICL_SUCCESS) { 1788 log_printf("\n"); 1789 return (PICL_WALK_CONTINUE); 1790 } 1791 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 1792 return (PICL_WALK_TERMINATE); 1793 for (i = 0; i < PARENT_NAMES; i++) 1794 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 1795 while (--i > -1) 1796 free(names[i]); 1797 free(loc); 1798 return (PICL_WALK_TERMINATE); 1799 } 1800 i = 0; 1801 while (err == PICL_SUCCESS) { 1802 if (parenth == phyplatformh) 1803 break; 1804 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1805 names[i++], PICL_PROPNAMELEN_MAX); 1806 if (err != PICL_SUCCESS) { 1807 i--; 1808 break; 1809 } 1810 if (i == PARENT_NAMES) 1811 break; 1812 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 1813 &parenth, sizeof (parenth)); 1814 } 1815 loc[0] = '\0'; 1816 if (--i > -1) { 1817 (void) strlcat(loc, names[i], 1818 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1819 } 1820 while (--i > -1) { 1821 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1822 (void) strlcat(loc, names[i], 1823 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1824 } 1825 log_printf("%-35s", loc); 1826 for (i = 0; i < PARENT_NAMES; i++) 1827 free(names[i]); 1828 free(loc); 1829 log_printf("%-10s", label); 1830 log_printf("%-9s", status); 1831 log_printf("\n"); 1832 return (PICL_WALK_CONTINUE); 1833 } 1834 1835 static void 1836 sun4v_print_fru_status() 1837 { 1838 char *fmt = "%-34s %-9s %-8s\n"; 1839 1840 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1841 sun4v_print_fru_status_callback); 1842 if (!class_node_found) 1843 return; 1844 1845 log_printf("\n"); 1846 log_printf("============================"); 1847 log_printf(" FRU Status "); 1848 log_printf("============================"); 1849 log_printf("\n"); 1850 1851 if (syserrlog == 0) { 1852 (void) picl_walk_tree_by_class(phyplatformh, 1853 NULL, NULL, 1854 sun4v_print_fru_status_callback); 1855 if (all_status_ok) { 1856 log_printf("All FRUs are enabled.\n"); 1857 return; 1858 } 1859 } 1860 log_printf(fmt, "Location", "Name", "Status", 0); 1861 log_printf("------------------------------------------------------\n"); 1862 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1863 sun4v_print_fru_status_callback); 1864 } 1865 1866 /*ARGSUSED*/ 1867 static int 1868 sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 1869 { 1870 char rev[PICL_PROPNAMELEN_MAX]; 1871 picl_errno_t err; 1872 1873 if (!class_node_found) { 1874 class_node_found = 1; 1875 return (PICL_WALK_TERMINATE); 1876 } 1877 1878 err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 1879 sizeof (rev)); 1880 if (err != PICL_SUCCESS) 1881 return (PICL_WALK_CONTINUE); 1882 if (strlen(rev) == 0) 1883 return (PICL_WALK_CONTINUE); 1884 log_printf("%s", rev); 1885 log_printf("\n"); 1886 return (PICL_WALK_CONTINUE); 1887 } 1888 1889 static void 1890 sun4v_print_fw_rev() 1891 { 1892 if (syserrlog == 0) 1893 return; 1894 1895 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1896 sun4v_print_fw_rev_callback); 1897 if (!class_node_found) 1898 return; 1899 1900 log_printf("\n"); 1901 log_printf("============================"); 1902 log_printf(" FW Version "); 1903 log_printf("============================"); 1904 log_printf("\n"); 1905 log_printf("Version\n"); 1906 log_printf("-------------------------------------------------" 1907 "-----------\n"); 1908 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1909 sun4v_print_fw_rev_callback); 1910 } 1911 1912 static void 1913 sun4v_print_openprom_rev() 1914 { 1915 if (syserrlog == 0) 1916 return; 1917 1918 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 1919 openprom_callback); 1920 if (!class_node_found) 1921 return; 1922 1923 log_printf("\n"); 1924 log_printf("======================"); 1925 log_printf(" System PROM revisions "); 1926 log_printf("======================="); 1927 log_printf("\n"); 1928 log_printf("Version\n"); 1929 log_printf("-------------------------------------------------" 1930 "-----------\n"); 1931 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 1932 openprom_callback); 1933 } 1934 1935 /* 1936 * display the OBP and POST prom revisions (if present) 1937 */ 1938 /* ARGSUSED */ 1939 static int 1940 openprom_callback(picl_nodehdl_t openpromh, void *arg) 1941 { 1942 picl_prophdl_t proph; 1943 picl_prophdl_t tblh; 1944 picl_prophdl_t rowproph; 1945 picl_propinfo_t pinfo; 1946 char *prom_version = NULL; 1947 char *obp_version = NULL; 1948 int err; 1949 1950 if (!class_node_found) { 1951 class_node_found = 1; 1952 return (PICL_WALK_TERMINATE); 1953 } 1954 1955 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION, 1956 &pinfo, &proph); 1957 if (err == PICL_PROPNOTFOUND) 1958 return (PICL_WALK_TERMINATE); 1959 else if (err != PICL_SUCCESS) 1960 return (err); 1961 1962 /* 1963 * If it's a table prop, the first element is OBP revision 1964 * The second one is POST revision. 1965 * If it's a charstring prop, the value will be only OBP revision 1966 */ 1967 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 1968 prom_version = (char *)alloca(pinfo.size); 1969 if (prom_version == NULL) 1970 return (PICL_FAILURE); 1971 err = picl_get_propval(proph, prom_version, pinfo.size); 1972 if (err != PICL_SUCCESS) 1973 return (err); 1974 log_printf("%s\n", prom_version); 1975 } 1976 1977 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 1978 return (PICL_WALK_TERMINATE); 1979 1980 err = picl_get_propval(proph, &tblh, pinfo.size); 1981 if (err != PICL_SUCCESS) 1982 return (err); 1983 1984 err = picl_get_next_by_row(tblh, &rowproph); 1985 if (err == PICL_SUCCESS) { 1986 /* get first row */ 1987 err = picl_get_propinfo(rowproph, &pinfo); 1988 if (err != PICL_SUCCESS) 1989 return (err); 1990 1991 prom_version = (char *)alloca(pinfo.size); 1992 if (prom_version == NULL) 1993 return (PICL_FAILURE); 1994 1995 err = picl_get_propval(rowproph, prom_version, pinfo.size); 1996 if (err != PICL_SUCCESS) 1997 return (err); 1998 log_printf("%s\n", prom_version); 1999 2000 /* get second row */ 2001 err = picl_get_next_by_col(rowproph, &rowproph); 2002 if (err == PICL_SUCCESS) { 2003 err = picl_get_propinfo(rowproph, &pinfo); 2004 if (err != PICL_SUCCESS) 2005 return (err); 2006 2007 obp_version = (char *)alloca(pinfo.size); 2008 if (obp_version == NULL) 2009 return (PICL_FAILURE); 2010 err = picl_get_propval(rowproph, obp_version, 2011 pinfo.size); 2012 if (err != PICL_SUCCESS) 2013 return (err); 2014 log_printf("%s\n", obp_version); 2015 } 2016 } 2017 2018 return (PICL_WALK_TERMINATE); 2019 } 2020 2021 static void 2022 sun4v_print_chassis_serial_no() 2023 { 2024 char val[PICL_PROPNAMELEN_MAX]; 2025 picl_errno_t err; 2026 if (syserrlog == 0 || chassish == 0) 2027 return; 2028 2029 log_printf("\n"); 2030 log_printf("Chassis Serial Number"); 2031 log_printf("\n"); 2032 log_printf("---------------------\n"); 2033 err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 2034 val, sizeof (val)); 2035 if (err == PICL_SUCCESS) 2036 log_printf("%s", val); 2037 log_printf("\n"); 2038 } 2039