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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <alloca.h> 33 #include <errno.h> 34 #include <libintl.h> 35 #include <sys/utsname.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <sys/openpromio.h> 39 #include <sys/ddi.h> 40 #include <syslog.h> 41 #include <fcntl.h> 42 #include <dirent.h> 43 #include <unistd.h> 44 #include <locale.h> 45 #include <picl.h> 46 #include "pdevinfo.h" 47 #include "display.h" 48 #include "display_sun4u.h" 49 #include "picldefs.h" 50 #include "libprtdiag.h" 51 52 #if !defined(TEXT_DOMAIN) 53 #define TEXT_DOMAIN "SYS_TEST" 54 #endif 55 56 #define EM_INIT_FAIL dgettext(TEXT_DOMAIN,\ 57 "picl_initialize failed: %s\n") 58 #define EM_GET_ROOT_FAIL dgettext(TEXT_DOMAIN,\ 59 "Getting root node failed: %s\n") 60 #define EM_PRTDIAG_FAIL dgettext(TEXT_DOMAIN, "Prtdiag failed!\n") 61 62 #define SIGN_ON_MSG dgettext(TEXT_DOMAIN,\ 63 "System Configuration: Sun Microsystems ") 64 #define SYSCLK_FREQ_MSG dgettext(TEXT_DOMAIN,\ 65 "System clock frequency: %d MHZ\n") 66 #define SERIAL_NUM_MSG dgettext(TEXT_DOMAIN,\ 67 "Chassis Serial Number:\n") 68 #define MEM_SIZE_MSG dgettext(TEXT_DOMAIN, "Memory size: ") 69 #define FFB_DOUBLE_BUF dgettext(TEXT_DOMAIN, "FFB, Double Buffered") 70 #define FFB_SINGLE_BUF dgettext(TEXT_DOMAIN, "FFB, Single Buffered") 71 72 #define DEFAULT_BOARD_NUM 0 73 #define DEFAULT_PORTID 0 74 #define CLK_FREQ_66MHZ 66 75 #define USB -1 76 #define HUB -2 77 78 /* bus id */ 79 #define SBUS_TYPE 0 80 #define PCI_TYPE 1 81 #define UPA_TYPE 2 82 #define PCIEX_TYPE 3 83 84 #define UPA_NAME "upa" 85 #define PCIEX_NAME "pciex" 86 87 /* 88 * PICL classes 89 */ 90 #define PICL_CLASS_OPTIONS "options" 91 92 /* 93 * Property names 94 */ 95 96 #define OBP_PROP_REG "reg" 97 #define OBP_PROP_CLOCK_FREQ "clock-frequency" 98 #define OBP_PROP_BOARD_NUM "board#" 99 #define OBP_PROP_REVISION_ID "revision-id" 100 #define OBP_PROP_VERSION_NUM "version#" 101 #define OBP_PROP_MODREV_NUM "module-revision#" 102 #define OBP_PROP_BOARD_TYPE "board_type" 103 #define OBP_PROP_ECACHE_SIZE "ecache-size" 104 #define OBP_PROP_IMPLEMENTATION "implementation#" 105 #define OBP_PROP_MASK "mask#" 106 #define OBP_PROP_COMPATIBLE "compatible" 107 #define OBP_PROP_BANNER_NAME "banner-name" 108 #define OBP_PROP_MODEL "model" 109 #define OBP_PROP_66MHZ_CAPABLE "66mhz-capable" 110 #define OBP_PROP_FBC_REG_ID "fbc_reg_id" 111 #define OBP_PROP_VERSION "version" 112 113 #define PROP_POWERFAIL_TIME "powerfail-time" 114 #define PICL_PROP_LOW_WARNING_THRESHOLD "LowWarningThreshold" 115 116 #define DEFAULT_LINE_WIDTH 78 117 #define HEADING_SYMBOL "=" 118 119 #define MAX_IWAYS 32 120 121 typedef struct bank_list { 122 picl_nodehdl_t nodeh; 123 uint32_t iway_count; 124 uint32_t iway[MAX_IWAYS]; 125 struct bank_list *next; 126 } bank_list_t; 127 128 typedef struct { 129 uint64_t base; 130 uint64_t size; 131 int ifactor; 132 int bank_count; 133 } seg_info_t; 134 135 static struct io_card *io_card_list = NULL; /* The head of the IO card list */ 136 static bank_list_t *mem_banks = NULL; 137 static int mem_xfersize; 138 static int no_xfer_size = 0; 139 140 static char *io_device_table[] = { 141 "block", 142 "disk", 143 "cdrom", 144 "floppy", 145 "tape", 146 "network", 147 "display", 148 "serial", 149 "parallel", 150 "scsi", 151 "scsi-2", 152 "scsi-3", 153 "ide", 154 "fcal", 155 "keyboard", 156 "mouse", 157 "dma" 158 }; 159 160 #define NIODEVICE sizeof (io_device_table) / sizeof (io_device_table[0]) 161 162 static char *bus_table[] = { 163 "ebus", 164 "isa", 165 "pmu", 166 "pci", 167 "pciex" 168 }; 169 170 #define NBUS sizeof (bus_table) / sizeof (bus_table[0]) 171 172 /* prtdiag exit codes */ 173 #define PD_SUCCESS 0 174 #define PD_SYSTEM_FAILURE 1 175 #define PD_INTERNAL_FAILURE 2 176 177 /* 178 * Use of global assumes do_prominfo only called from main in prtdiag and 179 * access does not need to be multi-thread safe. 180 */ 181 static int exit_code = PD_SUCCESS; 182 183 /* 184 * This function is called from every location where a status value is output. 185 * It checks the status arg and sets exit_code if an error is detected. 186 * The status is typically returned from a PICL query. A case-insensitive 187 * string comparison is done to check for any status that starts with "fail" 188 * or "fault". 189 */ 190 static void 191 set_exit_code(char *status) 192 { 193 if (status == NULL) 194 return; 195 196 if (strncasecmp(status, "fail", 4) == 0 || 197 strncasecmp(status, "fault", 5) == 0) 198 exit_code = PD_SYSTEM_FAILURE; 199 } 200 201 /* 202 * check if it is an IO deice 203 */ 204 static int 205 is_io_device(char *device_class) 206 { 207 int i; 208 209 for (i = 0; i < NIODEVICE; i++) { 210 if (strcmp(device_class, io_device_table[i]) == 0) 211 return (1); 212 } 213 214 return (0); 215 } 216 217 /* 218 * check if it is a bus 219 */ 220 static int 221 is_bus(char *device_class) 222 { 223 int i; 224 225 for (i = 0; i < NBUS; i++) { 226 if (strcmp(device_class, bus_table[i]) == 0) 227 return (1); 228 } 229 230 return (0); 231 } 232 233 /* 234 * search children to get the node by the nodename 235 */ 236 static int 237 picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name, 238 picl_nodehdl_t *nodeh) 239 { 240 picl_nodehdl_t childh; 241 int err; 242 char *nodename; 243 244 nodename = alloca(strlen(name) + 1); 245 if (nodename == NULL) 246 return (PICL_FAILURE); 247 248 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh, 249 sizeof (picl_nodehdl_t)); 250 251 while (err == PICL_SUCCESS) { 252 err = picl_get_propval_by_name(childh, PICL_PROP_NAME, 253 nodename, (strlen(name) + 1)); 254 if (err != PICL_SUCCESS) { 255 err = picl_get_propval_by_name(childh, PICL_PROP_PEER, 256 &childh, sizeof (picl_nodehdl_t)); 257 continue; 258 } 259 260 if (strcmp(nodename, name) == 0) { 261 *nodeh = childh; 262 return (PICL_SUCCESS); 263 } 264 265 err = picl_get_propval_by_name(childh, PICL_PROP_PEER, 266 &childh, sizeof (picl_nodehdl_t)); 267 } 268 269 return (err); 270 } 271 272 /* 273 * get the value by the property name of the string prop 274 * Caller must free the outbuf 275 */ 276 static int 277 picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf) 278 { 279 int err; 280 picl_prophdl_t proph; 281 picl_propinfo_t pinfo; 282 char *prop_value; 283 284 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 285 if (err != PICL_SUCCESS) 286 return (err); 287 288 /* 289 * If it is not a string prop, return NULL 290 */ 291 if (pinfo.type != PICL_PTYPE_CHARSTRING) 292 return (PICL_FAILURE); 293 294 prop_value = malloc(pinfo.size); 295 if (prop_value == NULL) 296 return (PICL_FAILURE); 297 298 err = picl_get_propval(proph, prop_value, pinfo.size); 299 if (err != PICL_SUCCESS) { 300 free(prop_value); 301 return (err); 302 } 303 304 *outbuf = prop_value; 305 return (PICL_SUCCESS); 306 } 307 308 309 /* 310 * return the value as a signed integer 311 */ 312 313 static int64_t 314 picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 315 { 316 int err; 317 picl_prophdl_t proph; 318 picl_propinfo_t pinfo; 319 int8_t int8v; 320 int16_t int16v; 321 int32_t int32v; 322 int64_t int64v; 323 324 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 325 if (err != PICL_SUCCESS) { 326 *ret = err; 327 return (0); 328 } 329 330 /* 331 * If it is not an int, uint or byte array prop, return failure 332 */ 333 if ((pinfo.type != PICL_PTYPE_INT) && 334 (pinfo.type != PICL_PTYPE_UNSIGNED_INT) && 335 (pinfo.type != PICL_PTYPE_BYTEARRAY)) { 336 *ret = PICL_FAILURE; 337 return (0); 338 } 339 340 switch (pinfo.size) { 341 case sizeof (int8_t): 342 err = picl_get_propval(proph, &int8v, sizeof (int8v)); 343 *ret = err; 344 return (int8v); 345 case sizeof (int16_t): 346 err = picl_get_propval(proph, &int16v, sizeof (int16v)); 347 *ret = err; 348 return (int16v); 349 case sizeof (int32_t): 350 err = picl_get_propval(proph, &int32v, sizeof (int32v)); 351 *ret = err; 352 return (int32v); 353 case sizeof (int64_t): 354 err = picl_get_propval(proph, &int64v, sizeof (int64v)); 355 *ret = err; 356 return (int64v); 357 default: /* not supported size */ 358 *ret = PICL_FAILURE; 359 return (0); 360 } 361 } 362 363 /* 364 * return the value of the uint prop 365 */ 366 static uint64_t 367 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 368 { 369 int err; 370 picl_prophdl_t proph; 371 picl_propinfo_t pinfo; 372 uint8_t uint8v; 373 uint16_t uint16v; 374 uint32_t uint32v; 375 uint64_t uint64v; 376 377 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 378 if (err != PICL_SUCCESS) { 379 *ret = err; 380 return (0); 381 } 382 383 /* 384 * If it is not an int or uint prop, return failure 385 */ 386 if ((pinfo.type != PICL_PTYPE_INT) && 387 (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) { 388 *ret = PICL_FAILURE; 389 return (0); 390 } 391 392 /* uint prop */ 393 394 switch (pinfo.size) { 395 case sizeof (uint8_t): 396 err = picl_get_propval(proph, &uint8v, sizeof (uint8v)); 397 *ret = err; 398 return (uint8v); 399 case sizeof (uint16_t): 400 err = picl_get_propval(proph, &uint16v, sizeof (uint16v)); 401 *ret = err; 402 return (uint16v); 403 case sizeof (uint32_t): 404 err = picl_get_propval(proph, &uint32v, sizeof (uint32v)); 405 *ret = err; 406 return (uint32v); 407 case sizeof (uint64_t): 408 err = picl_get_propval(proph, &uint64v, sizeof (uint64v)); 409 *ret = err; 410 return (uint64v); 411 default: /* not supported size */ 412 *ret = PICL_FAILURE; 413 return (0); 414 } 415 } 416 417 /* 418 * return the value of the float prop 419 */ 420 static float 421 picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 422 { 423 int err; 424 picl_prophdl_t proph; 425 picl_propinfo_t pinfo; 426 float floatv; 427 428 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 429 if (err != PICL_SUCCESS) { 430 *ret = err; 431 return ((float)0); 432 } 433 434 /* 435 * If it is not a float prop, return failure 436 */ 437 if (pinfo.type != PICL_PTYPE_FLOAT) { 438 *ret = PICL_FAILURE; 439 return ((float)0); 440 } 441 442 *ret = picl_get_propval(proph, &floatv, sizeof (floatv)); 443 return (floatv); 444 } 445 446 /* 447 * get the clock frequency 448 */ 449 static int 450 picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq) 451 { 452 #define ROUND_TO_MHZ(x) (((x) + 500000)/ 1000000) 453 int err; 454 uint64_t clk_freq; 455 456 clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err); 457 if (err != PICL_SUCCESS) 458 return (err); 459 460 *freq = ROUND_TO_MHZ(clk_freq); 461 462 return (PICL_SUCCESS); 463 } 464 465 /* 466 * get the clock frequency from parent 467 */ 468 static int 469 picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk) 470 { 471 picl_nodehdl_t parenth; 472 int err; 473 474 475 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 476 &parenth, sizeof (parenth)); 477 478 while (err == PICL_SUCCESS) { 479 err = picldiag_get_clock_freq(parenth, clk); 480 if (err != PICL_PROPNOTFOUND) 481 return (err); 482 483 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 484 &parenth, sizeof (parenth)); 485 } 486 487 return (err); 488 } 489 490 /* 491 * get _fru_parent prop 492 * If not found, then travese superiors (parent nodes) until 493 * a _fru_parent property is found. 494 * If not found, no fru parent 495 */ 496 static int 497 picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth) 498 { 499 picl_nodehdl_t fruh; 500 int err; 501 502 /* find fru parent */ 503 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT, 504 &fruh, sizeof (fruh)); 505 if (err != PICL_SUCCESS) 506 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT, 507 &fruh, sizeof (fruh)); 508 509 while (err == PICL_PROPNOTFOUND) { 510 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 511 &nodeh, sizeof (nodeh)); 512 if (err != PICL_SUCCESS) 513 return (err); 514 515 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT, 516 &fruh, sizeof (fruh)); 517 if (err != PICL_SUCCESS) 518 err = picl_get_propval_by_name(nodeh, 519 PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh)); 520 } 521 522 if (err == PICL_SUCCESS) 523 *fruparenth = fruh; 524 525 return (err); 526 } 527 528 /* 529 * get label 530 * 531 * To get the label, use the following algorithm: 532 * Lookup "Label" property in the fru node itself. If no 533 * Label found, then traverse superiors (parent nodes) until 534 * a Label property is found. 535 * if not found, then no label 536 */ 537 static int 538 picldiag_get_label(picl_nodehdl_t nodeh, char **label) 539 { 540 int err; 541 542 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label); 543 544 while (err == PICL_PROPNOTFOUND) { 545 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 546 &nodeh, sizeof (nodeh)); 547 if (err != PICL_SUCCESS) 548 return (err); 549 550 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, 551 label); 552 } 553 554 return (err); 555 } 556 557 /* 558 * get combined label 559 * 560 * like picldiag_get_label, except concatenates the labels of parent locations 561 * eg SB0/P3 for processor P3 on system board SB0 562 * 563 * if caller specifies non-zero label length, label will be cut to specified 564 * length. 565 * negative length is left justified, non-negative length is right justified 566 */ 567 static int 568 picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen) 569 { 570 int err; 571 char *ptr; 572 char *ptr1 = NULL; 573 char *ptr2; 574 int len; 575 576 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1); 577 if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS) 578 return (err); 579 580 for (;;) { 581 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 582 &nodeh, sizeof (nodeh)); 583 if (err == PICL_PROPNOTFOUND) 584 break; 585 if (err != PICL_SUCCESS) 586 return (err); 587 588 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr); 589 if (err == PICL_SUCCESS) { 590 if (ptr1 == NULL) { 591 ptr1 = ptr; 592 } else { 593 ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2); 594 if (ptr2 == NULL) 595 return (PICL_FAILURE); 596 (void) strcpy(ptr2, ptr); 597 (void) strcat(ptr2, "/"); 598 (void) strcat(ptr2, ptr1); 599 (void) free(ptr); 600 (void) free(ptr1); 601 ptr1 = ptr2; 602 } 603 } else if (err != PICL_PROPNOTFOUND) { 604 return (err); 605 } 606 } 607 608 if (ptr1 == NULL) 609 return (PICL_PROPNOTFOUND); 610 611 len = strlen(ptr1); 612 /* if no string truncation is desired or required */ 613 if ((lablen == 0) || (len <= abs(lablen))) { 614 *label = ptr1; 615 return (PICL_SUCCESS); 616 } 617 618 /* string truncation is required; alloc space for (lablen + \0) */ 619 ptr = malloc(abs(lablen) + 1); 620 if (ptr == 0) 621 return (PICL_FAILURE); 622 if (lablen > 0) { 623 /* right justification; label = "+<string>\0" */ 624 strcpy(ptr, "+"); 625 strncat(ptr, ptr1 + len - lablen + 1, lablen + 1); 626 } else { 627 /* left justification; label = "<string>+\0" */ 628 strncpy(ptr, ptr1, abs(lablen) - 1); 629 strcat(ptr, "+"); 630 } 631 632 *label = ptr; 633 return (PICL_SUCCESS); 634 } 635 636 /* 637 * return the first compatible value 638 */ 639 static int 640 picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 641 { 642 int err; 643 picl_prophdl_t proph; 644 picl_propinfo_t pinfo; 645 picl_prophdl_t tblh; 646 picl_prophdl_t rowproph; 647 char *pval; 648 649 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 650 &pinfo, &proph); 651 if (err != PICL_SUCCESS) 652 return (err); 653 654 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 655 pval = malloc(pinfo.size); 656 if (pval == NULL) 657 return (PICL_FAILURE); 658 err = picl_get_propval(proph, pval, pinfo.size); 659 if (err != PICL_SUCCESS) { 660 free(pval); 661 return (err); 662 } 663 *outbuf = pval; 664 return (PICL_SUCCESS); 665 } 666 667 if (pinfo.type != PICL_PTYPE_TABLE) 668 return (PICL_FAILURE); 669 670 /* get first string from table */ 671 err = picl_get_propval(proph, &tblh, pinfo.size); 672 if (err != PICL_SUCCESS) 673 return (err); 674 675 err = picl_get_next_by_row(tblh, &rowproph); 676 if (err != PICL_SUCCESS) 677 return (err); 678 679 err = picl_get_propinfo(rowproph, &pinfo); 680 if (err != PICL_SUCCESS) 681 return (err); 682 683 pval = malloc(pinfo.size); 684 if (pval == NULL) 685 return (PICL_FAILURE); 686 687 err = picl_get_propval(rowproph, pval, pinfo.size); 688 if (err != PICL_SUCCESS) { 689 free(pval); 690 return (err); 691 } 692 693 *outbuf = pval; 694 return (PICL_SUCCESS); 695 } 696 697 /* 698 * print the header in the center 699 */ 700 static void 701 logprintf_header(char *header, size_t line_width) 702 { 703 size_t start_pos; 704 size_t i; 705 706 log_printf("\n"); 707 start_pos = (line_width - strlen(header) - 2) / 2; 708 709 for (i = 0; i < start_pos; i++) 710 log_printf("%s", HEADING_SYMBOL); 711 712 log_printf(" %s ", header); 713 714 for (i = 0; i < start_pos; i++) 715 log_printf("%s", HEADING_SYMBOL); 716 717 log_printf("\n"); 718 } 719 720 /* 721 * print the size 722 */ 723 static void 724 logprintf_size(uint64_t size) 725 { 726 #define SIZE_FIELD 11 727 728 uint64_t kbyte = 1024; 729 uint64_t mbyte = 1024 * 1024; 730 uint64_t gbyte = 1024 * 1024 * 1024; 731 uint64_t residue; 732 char buf[SIZE_FIELD]; 733 734 if (size >= gbyte) { 735 residue = size % gbyte; 736 if (residue == 0) 737 snprintf(buf, sizeof (buf), "%dGB", 738 (int)(size / gbyte)); 739 else 740 snprintf(buf, sizeof (buf), "%.2fGB", 741 (float)size / gbyte); 742 } else if (size >= mbyte) { 743 residue = size % mbyte; 744 if (residue == 0) 745 snprintf(buf, sizeof (buf), "%dMB", 746 (int)(size / mbyte)); 747 else 748 snprintf(buf, sizeof (buf), "%.2fMB", 749 (float)size / mbyte); 750 } else { 751 residue = size % kbyte; 752 if (residue == 0) 753 snprintf(buf, sizeof (buf), "%dKB", 754 (int)(size / kbyte)); 755 else 756 snprintf(buf, sizeof (buf), "%.2fKB", 757 (float)size / kbyte); 758 } 759 760 log_printf("%-10s ", buf); 761 } 762 763 /* 764 * display platform banner 765 */ 766 static int 767 display_platform_banner(picl_nodehdl_t plafh) 768 { 769 char *platform; 770 char *banner_name; 771 int err; 772 773 /* 774 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME 775 */ 776 log_printf(SIGN_ON_MSG); 777 err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE, 778 &platform); 779 if (err != PICL_SUCCESS) 780 return (err); 781 log_printf(" %s", platform); 782 free(platform); 783 784 err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME, 785 &banner_name); 786 if (err != PICL_SUCCESS) 787 return (err); 788 log_printf(" %s", banner_name); 789 free(banner_name); 790 791 log_printf("\n"); 792 return (PICL_SUCCESS); 793 } 794 795 static int 796 serialnum_callback(picl_nodehdl_t serialh, void *arg) 797 { 798 int *countp = arg; 799 int err; 800 picl_nodehdl_t fruph; 801 char *buf; 802 803 err = picl_get_propval_by_name(serialh, PICL_REFPROP_FRU_PARENT, 804 &fruph, sizeof (fruph)); 805 if (err == PICL_PROPNOTFOUND) { 806 err = picl_get_propval_by_name(serialh, 807 PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph)); 808 } 809 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) 810 return (PICL_WALK_CONTINUE); 811 if (err != PICL_SUCCESS) 812 return (err); 813 814 err = picldiag_get_string_propval(serialh, 815 PICL_PROP_SERIAL_NUMBER, &buf); 816 if (err == PICL_SUCCESS) { 817 log_printf("\n"); 818 log_printf(SERIAL_NUM_MSG); 819 log_printf("----------------------\n"); 820 log_printf("%s\n", buf); 821 free(buf); 822 return (PICL_WALK_TERMINATE); 823 } 824 return (err); 825 } 826 827 /* 828 * display the chassis serial number 829 */ 830 static int 831 display_serial_number(picl_nodehdl_t plafh) 832 { 833 int print_header; 834 835 picl_walk_tree_by_class(plafh, PICL_CLASS_CHASSIS_SERIAL_NUM, 836 &print_header, serialnum_callback); 837 return (PICL_SUCCESS); 838 } 839 840 /* 841 * display the clock frequency 842 */ 843 static int 844 display_system_clock(picl_nodehdl_t plafh) 845 { 846 uint32_t system_clk; 847 int err; 848 849 err = picldiag_get_clock_freq(plafh, &system_clk); 850 if (err != PICL_SUCCESS) 851 return (err); 852 853 log_printf(SYSCLK_FREQ_MSG, system_clk); 854 855 return (PICL_SUCCESS); 856 } 857 858 /* 859 * callback function to display the memory size 860 */ 861 /*ARGSUSED*/ 862 static int 863 memory_callback(picl_nodehdl_t memh, void *args) 864 { 865 uint64_t mem_size; 866 int err; 867 868 log_printf(MEM_SIZE_MSG); 869 mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err); 870 if (err == PICL_SUCCESS) 871 logprintf_size(mem_size); 872 log_printf("\n"); 873 no_xfer_size = 0; 874 mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE, 875 &err); 876 if (err == PICL_PROPNOTFOUND) 877 no_xfer_size = 1; 878 return (PICL_WALK_TERMINATE); 879 } 880 881 /* 882 * callback function to print cpu information 883 */ 884 /*ARGSUSED*/ 885 static int 886 cpu_callback(picl_nodehdl_t nodeh, void *args) 887 { 888 int err; 889 int id; 890 uint64_t uintval; 891 uint32_t freq; 892 char *impl_name; 893 char *status; 894 picl_prophdl_t parenth; 895 char *label; 896 897 /* 898 * If no ID is found, return 899 */ 900 id = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err); 901 if (err == PICL_PROPNOTFOUND) 902 return (PICL_WALK_CONTINUE); 903 else if (err != PICL_SUCCESS) 904 return (err); 905 log_printf("%-3d ", id); 906 907 /* 908 * If no freq is found, return 909 */ 910 err = picldiag_get_clock_freq(nodeh, &freq); 911 if (err == PICL_PROPNOTFOUND) 912 return (PICL_WALK_CONTINUE); 913 else if (err != PICL_SUCCESS) 914 return (err); 915 log_printf("%4d MHz ", freq); 916 917 /* Ecache size */ 918 uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_ECACHE_SIZE, &err); 919 if (err == PICL_PROPNOTFOUND) 920 log_printf(" - "); 921 else if (err == PICL_SUCCESS) 922 logprintf_size(uintval); 923 else 924 return (err); 925 926 /* Implementation */ 927 impl_name = NULL; 928 err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME, &impl_name); 929 if (err != PICL_SUCCESS) 930 log_printf(" <unknown> "); 931 else 932 log_printf(" %-22s ", impl_name); 933 934 /* CPU Mask */ 935 uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err); 936 if (err == PICL_PROPNOTFOUND) 937 log_printf(" - "); 938 else if (err == PICL_SUCCESS) 939 log_printf("%2lld.%-2lld ", (uintval >> 4) & 0xf, 940 uintval & 0xf); 941 else 942 return (err); 943 944 /* 945 * Status - if the node has a status property then display that 946 * otherwise display the State property 947 */ 948 err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status); 949 if (err == PICL_SUCCESS) { 950 log_printf("%-12s", status); 951 set_exit_code(status); 952 free(status); 953 } else if (err != PICL_PROPNOTFOUND && err != 954 PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) { 955 return (err); 956 } else { 957 err = picldiag_get_string_propval(nodeh, 958 PICL_PROP_STATE, &status); 959 if (err == PICL_SUCCESS) { 960 log_printf("%-12s", status); 961 set_exit_code(status); 962 free(status); 963 } else if (err != PICL_PROPNOTFOUND && err != 964 PICL_PROPVALUNAVAILABLE && err != 965 PICL_ENDOFLIST) { 966 return (err); 967 } else { 968 log_printf("unknown "); 969 } 970 } 971 972 /* 973 * Location: use label of fru parent 974 */ 975 err = picldiag_get_fru_parent(nodeh, &parenth); 976 if (err == PICL_PROPNOTFOUND) { 977 log_printf(" - "); 978 } else if (err == PICL_SUCCESS) { 979 err = picldiag_get_combined_label(parenth, &label, 12); 980 if (err == PICL_PROPNOTFOUND) 981 log_printf(" - "); 982 else if (err == PICL_SUCCESS) { 983 log_printf("%s", label); 984 free(label); 985 } else 986 return (err); 987 } else 988 return (err); 989 990 log_printf("\n"); 991 return (PICL_WALK_CONTINUE); 992 } 993 994 /* 995 * display cpu information 996 */ 997 static int 998 display_cpu_info(picl_nodehdl_t plafh) 999 { 1000 int err; 1001 1002 /* 1003 * Display the table header for CPUs . Then display the CPU 1004 * frequency, cache size, and processor revision on all the boards. 1005 */ 1006 logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH); 1007 log_printf(" E$ CPU " 1008 "CPU\n"); 1009 log_printf("CPU Freq Size Implementation " 1010 "Mask Status Location\n"); 1011 log_printf("--- -------- ---------- --------------------- " 1012 "----- ------ --------\n"); 1013 1014 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU, 1015 cpu_callback); 1016 return (err); 1017 } 1018 1019 /* 1020 * Inserts an io_card structure into the list. 1021 */ 1022 static void 1023 add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label, 1024 uint32_t freq, char *name, char *model, char *status, char *devfs_path) 1025 { 1026 struct io_card card; 1027 1028 card.display = 1; 1029 card.board = board; 1030 switch (bus_id) { 1031 case SBUS_TYPE: 1032 strlcpy(card.bus_type, SBUS_NAME, MAXSTRLEN); 1033 break; 1034 case PCI_TYPE: 1035 strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN); 1036 break; 1037 case PCIEX_TYPE: 1038 strlcpy(card.bus_type, PCIEX_NAME, MAXSTRLEN); 1039 break; 1040 case UPA_TYPE: 1041 strlcpy(card.bus_type, UPA_NAME, MAXSTRLEN); 1042 break; 1043 default: /* won't reach here */ 1044 strlcpy(card.bus_type, "", MAXSTRLEN); 1045 break; 1046 } 1047 if (label == NULL) 1048 card.slot = slot; 1049 else { 1050 card.slot = PCI_SLOT_IS_STRING; 1051 (void) strlcpy(card.slot_str, label, MAXSTRLEN); 1052 } 1053 card.freq = freq; 1054 card.status[0] = '\0'; 1055 card.name[0] = '\0'; 1056 card.model[0] = '\0'; 1057 card.notes[0] = '\0'; 1058 if (status != NULL) 1059 strlcpy(card.status, status, MAXSTRLEN); 1060 if (name != NULL) 1061 strlcpy(card.name, name, MAXSTRLEN); 1062 if (model != NULL) 1063 strlcpy(card.model, model, MAXSTRLEN); 1064 if (status != NULL) 1065 strlcpy(card.status, status, MAXSTRLEN); 1066 if (devfs_path != NULL) 1067 strlcpy(card.notes, devfs_path, MAXSTRLEN); 1068 1069 io_card_list = insert_io_card(io_card_list, &card); 1070 } 1071 1072 static void 1073 append_to_bank_list(bank_list_t *newptr) 1074 { 1075 bank_list_t *ptr; 1076 1077 if (mem_banks == NULL) { 1078 mem_banks = newptr; 1079 return; 1080 } 1081 ptr = mem_banks; 1082 while (ptr->next != NULL) 1083 ptr = ptr->next; 1084 1085 ptr->next = newptr; 1086 } 1087 1088 static void 1089 free_bank_list(void) 1090 { 1091 bank_list_t *ptr; 1092 bank_list_t *tmp; 1093 1094 for (ptr = mem_banks; ptr != NULL; ptr = tmp) { 1095 tmp = ptr->next; 1096 free(ptr); 1097 } 1098 mem_banks = NULL; 1099 } 1100 1101 1102 /* 1103 * print label for memory module 1104 */ 1105 static int 1106 logprintf_memory_module_label(picl_nodehdl_t moduleh) 1107 { 1108 picl_nodehdl_t fruparenth; 1109 int err; 1110 char *label; 1111 1112 err = picldiag_get_fru_parent(moduleh, &fruparenth); 1113 if (err == PICL_PROPNOTFOUND) { 1114 log_printf("-"); 1115 return (PICL_SUCCESS); 1116 } else if (err != PICL_SUCCESS) 1117 return (err); 1118 1119 err = picldiag_get_combined_label(fruparenth, &label, 30); 1120 if (err == PICL_PROPNOTFOUND) 1121 log_printf("-"); 1122 else if (err == PICL_SUCCESS) { 1123 log_printf("%-15s", label); 1124 free(label); 1125 } else 1126 return (err); 1127 1128 return (PICL_SUCCESS); 1129 } 1130 1131 /* 1132 * print the bank id and add the bank handle in the bank list 1133 * return the head of the bank list 1134 */ 1135 static int 1136 membank_callback(picl_nodehdl_t bankh, void *args) 1137 { 1138 int err; 1139 int64_t id; 1140 uint64_t match; 1141 uint64_t mask; 1142 int i; 1143 bank_list_t *newptr; 1144 seg_info_t *segp = args; 1145 1146 /* 1147 * print the bank id in the segment table contains column 1148 */ 1149 id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err); 1150 if (segp->bank_count > 0) 1151 log_printf(","); 1152 if (err == PICL_PROPNOTFOUND) 1153 log_printf("-"); 1154 else if (err == PICL_SUCCESS) 1155 log_printf("%-lld", id); 1156 else 1157 return (err); 1158 segp->bank_count++; 1159 1160 /* 1161 * Save the bank information for later (print_bank_table) 1162 */ 1163 newptr = malloc(sizeof (*newptr)); 1164 if (newptr == NULL) 1165 return (PICL_FAILURE); 1166 1167 newptr->nodeh = bankh; 1168 newptr->iway_count = 0; 1169 newptr->next = NULL; 1170 append_to_bank_list(newptr); 1171 1172 /* 1173 * Compute the way numbers for the bank 1174 */ 1175 if (no_xfer_size) 1176 return (PICL_WALK_CONTINUE); 1177 1178 match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err); 1179 if (err == PICL_PROPNOTFOUND) 1180 return (PICL_WALK_CONTINUE); 1181 else if (err != PICL_SUCCESS) 1182 return (err); 1183 1184 mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err); 1185 if (err == PICL_PROPNOTFOUND) 1186 return (PICL_WALK_CONTINUE); 1187 else if (err != PICL_SUCCESS) 1188 return (err); 1189 1190 i = 0; 1191 while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) { 1192 if (((segp->base + i * mem_xfersize) & mask) == match) 1193 newptr->iway[newptr->iway_count++] = i; 1194 ++i; 1195 } 1196 return (PICL_WALK_CONTINUE); 1197 } 1198 1199 1200 /* 1201 * find the memory bank and add the bank handle in the bank list 1202 * return the head of the bank list 1203 */ 1204 static int 1205 logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp) 1206 { 1207 int err; 1208 1209 log_printf("BankIDs "); 1210 /* 1211 * find memory-bank 1212 */ 1213 segp->bank_count = 0; 1214 err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp, 1215 membank_callback); 1216 log_printf("\n"); 1217 return (err); 1218 } 1219 1220 /* 1221 * print the label of memory module or the memory module bank ids 1222 */ 1223 static int 1224 logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp) 1225 { 1226 picl_nodehdl_t moduleh; 1227 int err; 1228 1229 /* 1230 * find memory-module if referenced directly from the memory-segment 1231 * (ie no memory banks) 1232 */ 1233 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE, 1234 &moduleh, sizeof (moduleh)); 1235 if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 1236 return (err); 1237 if (err == PICL_SUCCESS) { 1238 err = logprintf_memory_module_label(moduleh); 1239 log_printf("\n"); 1240 return (err); 1241 } 1242 1243 /* 1244 * memory-module not referenced directly from the memory segment 1245 * so list memory banks instead 1246 */ 1247 err = logprintf_bankinfo(nodeh, segp); 1248 return (err); 1249 } 1250 1251 /* 1252 * find all memory modules under the given memory module group 1253 * and print its label 1254 */ 1255 static int 1256 logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid) 1257 { 1258 int err; 1259 int64_t id; 1260 boolean_t got_status; 1261 picl_nodehdl_t moduleh; 1262 char piclclass[PICL_CLASSNAMELEN_MAX]; 1263 picl_nodehdl_t fruparenth; 1264 char *status; 1265 1266 id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err); 1267 if (err == PICL_PROPNOTFOUND) 1268 id = -1; 1269 else if (err != PICL_SUCCESS) 1270 return (err); 1271 1272 err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh, 1273 sizeof (picl_nodehdl_t)); 1274 1275 while (err == PICL_SUCCESS) { 1276 /* controller id */ 1277 log_printf("%-8lld ", mcid); 1278 1279 /* group id */ 1280 if (id == -1) { 1281 log_printf("- "); 1282 } else { 1283 log_printf("%-8lld ", id); 1284 } 1285 1286 err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME, 1287 piclclass, sizeof (piclclass)); 1288 if (err != PICL_SUCCESS) 1289 return (err); 1290 1291 if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) { 1292 err = logprintf_memory_module_label(moduleh); 1293 if (err != PICL_SUCCESS) 1294 return (err); 1295 } 1296 1297 got_status = B_FALSE; 1298 err = picldiag_get_fru_parent(moduleh, &fruparenth); 1299 if (err == PICL_SUCCESS) { 1300 err = picldiag_get_string_propval(fruparenth, 1301 PICL_PROP_OPERATIONAL_STATUS, &status); 1302 if (err == PICL_SUCCESS) { 1303 got_status = B_TRUE; 1304 } else if (err != PICL_PROPNOTFOUND) 1305 return (err); 1306 } else if (err != PICL_PROPNOTFOUND) 1307 return (err); 1308 1309 if (!got_status) { 1310 err = picldiag_get_string_propval(moduleh, 1311 PICL_PROP_STATUS, &status); 1312 if (err == PICL_SUCCESS) 1313 got_status = B_TRUE; 1314 else if (err != PICL_PROPNOTFOUND) 1315 return (err); 1316 } 1317 if (got_status) { 1318 log_printf("%s", status); 1319 set_exit_code(status); 1320 free(status); 1321 } 1322 err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER, 1323 &moduleh, sizeof (picl_nodehdl_t)); 1324 1325 log_printf("\n"); 1326 } 1327 if (err == PICL_PROPNOTFOUND) 1328 return (PICL_SUCCESS); 1329 return (err); 1330 } 1331 1332 /* 1333 * search children to find memory module group under memory-controller 1334 */ 1335 static int 1336 find_memory_module_group(picl_nodehdl_t mch, int *print_header) 1337 { 1338 picl_nodehdl_t memgrph; 1339 uint64_t mcid; 1340 int err; 1341 char piclclass[PICL_CLASSNAMELEN_MAX]; 1342 1343 mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err); 1344 if (err == PICL_PROPNOTFOUND) 1345 mcid = DEFAULT_PORTID; 1346 else if (err != PICL_SUCCESS) 1347 return (err); 1348 1349 err = picl_get_propval_by_name(mch, PICL_PROP_CHILD, 1350 &memgrph, sizeof (picl_nodehdl_t)); 1351 while (err == PICL_SUCCESS) { 1352 err = picl_get_propval_by_name(memgrph, 1353 PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass)); 1354 if (err != PICL_SUCCESS) 1355 return (err); 1356 1357 if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) { 1358 if (*print_header == 1) { 1359 log_printf( 1360 dgettext(TEXT_DOMAIN, 1361 "\nMemory Module Groups:\n")); 1362 log_printf("--------------------------"); 1363 log_printf("------------------------\n"); 1364 log_printf("ControllerID GroupID Labels"); 1365 log_printf(" Status\n"); 1366 log_printf("--------------------------"); 1367 log_printf("------------------------\n"); 1368 *print_header = 0; 1369 } 1370 err = logprintf_memory_module_group_info(memgrph, mcid); 1371 if (err != PICL_SUCCESS) 1372 return (err); 1373 } 1374 1375 err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER, 1376 &memgrph, sizeof (picl_nodehdl_t)); 1377 } 1378 if (err == PICL_PROPNOTFOUND) 1379 return (PICL_SUCCESS); 1380 return (err); 1381 } 1382 1383 /* 1384 * print memory module group table per memory-controller 1385 */ 1386 static int 1387 print_memory_module_group_table(picl_nodehdl_t plafh) 1388 { 1389 picl_nodehdl_t mch; 1390 int err; 1391 char piclclass[PICL_CLASSNAMELEN_MAX]; 1392 int print_header; 1393 1394 print_header = 1; 1395 1396 /* 1397 * find memory-controller 1398 */ 1399 err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch, 1400 sizeof (picl_nodehdl_t)); 1401 while (err == PICL_SUCCESS) { 1402 err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME, 1403 piclclass, sizeof (piclclass)); 1404 if (err != PICL_SUCCESS) 1405 return (err); 1406 1407 if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) { 1408 err = print_memory_module_group_table(mch); 1409 if (err != PICL_SUCCESS) 1410 return (err); 1411 err = picl_get_propval_by_name(mch, PICL_PROP_PEER, 1412 &mch, sizeof (picl_nodehdl_t)); 1413 continue; 1414 } 1415 1416 err = find_memory_module_group(mch, &print_header); 1417 if (err != PICL_SUCCESS) 1418 return (err); 1419 1420 err = picl_get_propval_by_name(mch, PICL_PROP_PEER, 1421 &mch, sizeof (picl_nodehdl_t)); 1422 } 1423 if (err == PICL_PROPNOTFOUND) 1424 return (PICL_SUCCESS); 1425 1426 return (err); 1427 } 1428 1429 /* 1430 * print bank table 1431 */ 1432 static int 1433 print_bank_table(void) 1434 { 1435 bank_list_t *ptr; 1436 picl_nodehdl_t bankh; 1437 picl_nodehdl_t memgrph; 1438 picl_nodehdl_t mch; 1439 int err; 1440 int32_t i; 1441 uint64_t size; 1442 int id; 1443 1444 log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n")); 1445 log_printf("---------------------------------------"); 1446 log_printf("--------------------\n"); 1447 log_printf(dgettext(TEXT_DOMAIN, " Physical Location\n")); 1448 log_printf(dgettext(TEXT_DOMAIN, "ID ControllerID GroupID ")); 1449 log_printf(dgettext(TEXT_DOMAIN, "Size Interleave Way\n")); 1450 log_printf("---------------------------------------"); 1451 log_printf("--------------------\n"); 1452 1453 for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) { 1454 bankh = ptr->nodeh; 1455 id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err); 1456 if (err != PICL_SUCCESS) 1457 log_printf("%-8s ", "-"); 1458 else 1459 log_printf("%-8d ", id); 1460 1461 /* find memory-module-group */ 1462 err = picl_get_propval_by_name(bankh, 1463 PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph, 1464 sizeof (memgrph)); 1465 if (err == PICL_PROPNOTFOUND) { 1466 log_printf("%-8s ", "-"); 1467 log_printf("%-8s ", "-"); 1468 } else if (err != PICL_SUCCESS) 1469 return (err); 1470 else { 1471 /* 1472 * get controller id 1473 */ 1474 err = picl_get_propval_by_name(memgrph, 1475 PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t)); 1476 if (err != PICL_SUCCESS) 1477 return (err); 1478 1479 id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, 1480 &err); 1481 if (err == PICL_PROPNOTFOUND) 1482 id = DEFAULT_PORTID; /* use default */ 1483 else if (err != PICL_SUCCESS) 1484 return (err); 1485 1486 log_printf("%-8d ", id); 1487 1488 /* get group id */ 1489 id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, 1490 &err); 1491 if (err == PICL_PROPNOTFOUND) 1492 log_printf("- "); 1493 else if (err == PICL_SUCCESS) 1494 log_printf("%-8d ", id); 1495 else 1496 return (err); 1497 } 1498 1499 size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err); 1500 if (err == PICL_PROPNOTFOUND) 1501 log_printf("- "); 1502 else if (err == PICL_SUCCESS) 1503 logprintf_size(size); 1504 else 1505 return (err); 1506 1507 log_printf(" "); 1508 for (i = 0; i < ptr->iway_count; i++) { 1509 if (i != 0) 1510 log_printf(","); 1511 log_printf("%d", ptr->iway[i]); 1512 } 1513 1514 log_printf("\n"); 1515 } 1516 return (PICL_SUCCESS); 1517 } 1518 1519 /* 1520 * callback function to print segment, add the bank in the list and 1521 * return the bank list 1522 */ 1523 /* ARGSUSED */ 1524 static int 1525 memseg_callback(picl_nodehdl_t segh, void *args) 1526 { 1527 seg_info_t seginfo; 1528 int err; 1529 1530 /* get base address */ 1531 seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS, 1532 &err); 1533 if (err == PICL_PROPNOTFOUND) { 1534 log_printf("-\n"); 1535 return (PICL_WALK_CONTINUE); 1536 } else if (err == PICL_SUCCESS) 1537 log_printf("0x%-16llx ", seginfo.base); 1538 else 1539 return (err); 1540 1541 /* get size */ 1542 seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err); 1543 if (err == PICL_PROPNOTFOUND) { 1544 log_printf("-\n"); 1545 return (PICL_WALK_CONTINUE); 1546 } else if (err == PICL_SUCCESS) 1547 logprintf_size(seginfo.size); 1548 else 1549 return (err); 1550 1551 /* get interleave factor */ 1552 seginfo.ifactor = picldiag_get_uint_propval(segh, 1553 PICL_PROP_INTERLEAVE_FACTOR, &err); 1554 1555 if (err == PICL_PROPNOTFOUND) { 1556 log_printf(" -\n"); 1557 return (PICL_WALK_CONTINUE); 1558 } else if (err == PICL_SUCCESS) 1559 log_printf(" %-2d ", seginfo.ifactor); 1560 else 1561 return (err); 1562 1563 seginfo.bank_count = 0; 1564 err = logprintf_seg_contains_col(segh, &seginfo); 1565 if (err != PICL_SUCCESS) 1566 return (err); 1567 return (PICL_WALK_CONTINUE); 1568 } 1569 1570 /* 1571 * search children to find memory-segment and set up the bank list 1572 */ 1573 static int 1574 find_segments(picl_nodehdl_t plafh) 1575 { 1576 int err; 1577 1578 log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n")); 1579 log_printf("------------------------------"); 1580 log_printf("-----------------------------------------\n"); 1581 log_printf(dgettext(TEXT_DOMAIN, "Base Address Size ")); 1582 log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor Contains\n")); 1583 log_printf("------------------------------"); 1584 log_printf("-----------------------------------------\n"); 1585 1586 err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 1587 NULL, memseg_callback); 1588 return (err); 1589 } 1590 1591 /* 1592 * display memory configuration 1593 */ 1594 static int 1595 display_memory_config(picl_nodehdl_t plafh) 1596 { 1597 int err; 1598 1599 logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"), 1600 DEFAULT_LINE_WIDTH); 1601 1602 mem_banks = NULL; 1603 err = find_segments(plafh); 1604 1605 if ((err == PICL_SUCCESS) && (mem_banks != NULL)) 1606 print_bank_table(); 1607 1608 free_bank_list(); 1609 1610 return (print_memory_module_group_table(plafh)); 1611 } 1612 1613 /* 1614 * print the hub device 1615 */ 1616 static int 1617 logprintf_hub_devices(picl_nodehdl_t hubh) 1618 { 1619 char *name; 1620 int portnum; 1621 char *labelp; 1622 picl_nodehdl_t parenth; 1623 int err; 1624 1625 err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name); 1626 if (err != PICL_SUCCESS) 1627 return (err); 1628 log_printf("%-12.12s ", name); 1629 free(name); 1630 1631 err = picl_get_propval_by_name(hubh, PICL_REFPROP_LOC_PARENT, &parenth, 1632 sizeof (picl_nodehdl_t)); 1633 1634 if (err == PICL_SUCCESS) { 1635 /* Read the Label */ 1636 err = picldiag_get_label(parenth, &labelp); 1637 if (err == PICL_SUCCESS) { 1638 log_printf("%s\n", labelp); 1639 free(labelp); 1640 return (PICL_SUCCESS); 1641 } else if (err != PICL_PROPNOTFOUND) { 1642 log_printf("\n"); 1643 return (err); 1644 } 1645 } else if (err != PICL_PROPNOTFOUND) { 1646 log_printf("\n"); 1647 return (err); 1648 } 1649 1650 /* No Label, try the reg */ 1651 err = picl_get_propval_by_name(hubh, OBP_PROP_REG, &portnum, 1652 sizeof (portnum)); 1653 if (err == PICL_PROPNOTFOUND) 1654 log_printf(" -\n"); 1655 else if (err != PICL_SUCCESS) { 1656 log_printf("\n"); 1657 return (err); 1658 } else 1659 log_printf("%3d\n", portnum); 1660 1661 return (PICL_SUCCESS); 1662 } 1663 1664 /* 1665 * callback functions to display hub devices 1666 */ 1667 /* ARGSUSED */ 1668 static int 1669 print_usb_devices(picl_nodehdl_t hubh, void *arg) 1670 { 1671 picl_nodehdl_t chdh; 1672 char *rootname; 1673 int type = *(int *)arg; 1674 int hubnum; 1675 int err; 1676 1677 err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh, 1678 sizeof (picl_nodehdl_t)); 1679 1680 /* print header */ 1681 if (err == PICL_SUCCESS) { 1682 err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, 1683 &rootname); 1684 if (err != PICL_SUCCESS) 1685 return (err); 1686 1687 if (type == USB) { 1688 log_printf("\n==============================="); 1689 log_printf(dgettext(TEXT_DOMAIN, 1690 " %s Devices "), rootname); 1691 } else { 1692 /* Get its hub number */ 1693 err = picl_get_propval_by_name(hubh, 1694 OBP_PROP_REG, &hubnum, sizeof (hubnum)); 1695 if ((err != PICL_SUCCESS) && 1696 (err != PICL_PROPNOTFOUND)) { 1697 free(rootname); 1698 return (err); 1699 } 1700 1701 log_printf("\n==============================="); 1702 if (err == PICL_SUCCESS) 1703 log_printf(dgettext(TEXT_DOMAIN, 1704 " %s#%d Devices "), 1705 rootname, hubnum); 1706 else 1707 log_printf(dgettext(TEXT_DOMAIN, 1708 " %s Devices "), rootname); 1709 } 1710 1711 log_printf("===============================\n\n"); 1712 log_printf("Name Port#\n"); 1713 log_printf("------------ -----\n"); 1714 free(rootname); 1715 1716 do { 1717 logprintf_hub_devices(chdh); 1718 1719 err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, 1720 &chdh, sizeof (picl_nodehdl_t)); 1721 } while (err == PICL_SUCCESS); 1722 } 1723 1724 1725 if (err == PICL_PROPNOTFOUND) 1726 return (PICL_WALK_CONTINUE); 1727 return (err); 1728 } 1729 1730 /* 1731 * callback functions to display usb devices 1732 */ 1733 /* ARGSUSED */ 1734 static int 1735 usb_callback(picl_nodehdl_t usbh, void *args) 1736 { 1737 int err; 1738 int type; 1739 1740 type = USB; 1741 err = print_usb_devices(usbh, &type); 1742 if (err != PICL_WALK_CONTINUE) 1743 return (err); 1744 type = HUB; 1745 err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices); 1746 if (err == PICL_SUCCESS) 1747 err = PICL_WALK_CONTINUE; 1748 return (err); 1749 } 1750 1751 1752 /* 1753 * find usb devices and print its information 1754 */ 1755 static int 1756 display_usb_devices(picl_nodehdl_t plafh) 1757 { 1758 int err; 1759 1760 /* 1761 * get the usb node 1762 */ 1763 err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL, 1764 usb_callback); 1765 return (err); 1766 } 1767 1768 1769 1770 /* 1771 * If nodeh is the io device, add it into the io list and return 1772 * If it is not an io device and it has the subtree, traverse the subtree 1773 * and add all leaf io devices 1774 */ 1775 static int 1776 add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board, 1777 uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status) 1778 { 1779 picl_nodehdl_t childh; 1780 picl_prophdl_t proph; 1781 picl_propinfo_t pinfo; 1782 int err; 1783 char *nameval; 1784 char piclclass[PICL_CLASSNAMELEN_MAX]; 1785 char nodename[MAXSTRLEN]; 1786 char name[MAXSTRLEN]; 1787 char *devfs_path; 1788 char *compatible; 1789 picl_nodehdl_t fruparenth; 1790 char *label; 1791 char binding_name[MAXSTRLEN]; 1792 1793 err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo, 1794 &proph); 1795 if (err != PICL_SUCCESS) 1796 return (err); 1797 1798 nameval = alloca(pinfo.size); 1799 if (nameval == NULL) 1800 return (PICL_FAILURE); 1801 1802 err = picl_get_propval(proph, nameval, pinfo.size); 1803 if (err != PICL_SUCCESS) 1804 return (err); 1805 1806 (void) strlcpy(nodename, nameval, MAXSTRLEN); 1807 1808 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 1809 piclclass, sizeof (piclclass)); 1810 if (err != PICL_SUCCESS) 1811 return (err); 1812 1813 /* if binding_name is found, name will be <nodename>-<binding_name> */ 1814 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 1815 binding_name, sizeof (binding_name)); 1816 if (err == PICL_PROPNOTFOUND) { 1817 /* 1818 * if compatible prop is found, name will be 1819 * <nodename>-<compatible> 1820 */ 1821 err = picldiag_get_first_compatible_value(nodeh, &compatible); 1822 if (err == PICL_SUCCESS) { 1823 strlcat(nodename, "-", MAXSTRLEN); 1824 strlcat(nodename, compatible, MAXSTRLEN); 1825 free(compatible); 1826 } else if (err != PICL_PROPNOTFOUND) { 1827 return (err); 1828 } 1829 } else if (err != PICL_SUCCESS) { 1830 return (err); 1831 } else if (strcmp(nodename, binding_name) != 0) { 1832 if (strcmp(nodename, piclclass) == 0) { 1833 /* 1834 * nodename same as binding name - 1835 * no need to display twice 1836 */ 1837 strlcpy(nodename, binding_name, MAXSTRLEN); 1838 } else { 1839 strlcat(nodename, "-", MAXSTRLEN); 1840 strlcat(nodename, binding_name, MAXSTRLEN); 1841 } 1842 } 1843 1844 /* 1845 * If it is an immediate child under pci/pciex/sbus/upa and not 1846 * a bus node, add it to the io list. 1847 * If it is a child under sub-bus and it is in an io 1848 * device, add it to the io list. 1849 */ 1850 if (((parentname == NULL) && (!is_bus(piclclass))) || 1851 ((parentname != NULL) && (is_io_device(piclclass)))) { 1852 if (parentname == NULL) 1853 (void) snprintf(name, MAXSTRLEN, "%s", nodename); 1854 else 1855 (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname, 1856 nodename); 1857 1858 /* 1859 * append the class if its class is not a generic 1860 * obp-device class 1861 */ 1862 if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE)) 1863 (void) snprintf(name, MAXSTRLEN, "%s (%s)", name, 1864 piclclass); 1865 1866 err = picldiag_get_fru_parent(nodeh, &fruparenth); 1867 if (err == PICL_PROPNOTFOUND) { 1868 label = NULL; 1869 } else if (err != PICL_SUCCESS) { 1870 return (err); 1871 } else { 1872 err = picldiag_get_combined_label(fruparenth, &label, 1873 15); 1874 if (err == PICL_PROPNOTFOUND) 1875 label = NULL; 1876 else if (err != PICL_SUCCESS) 1877 return (err); 1878 } 1879 /* devfs-path */ 1880 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, 1881 &devfs_path); 1882 if (err == PICL_PROPNOTFOUND) 1883 devfs_path = NULL; 1884 else if (err != PICL_SUCCESS) 1885 return (err); 1886 1887 add_io_card(board, bus_id, slot, label, freq, name, 1888 model, status, devfs_path); 1889 if (label != NULL) 1890 free(label); 1891 if (devfs_path != NULL) 1892 free(devfs_path); 1893 return (PICL_SUCCESS); 1894 } 1895 1896 /* 1897 * If there is any child, Go through each child. 1898 */ 1899 1900 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 1901 &childh, sizeof (picl_nodehdl_t)); 1902 1903 /* there is a child */ 1904 while (err == PICL_SUCCESS) { 1905 if (parentname == NULL) 1906 (void) strlcpy(name, nodename, MAXSTRLEN); 1907 else 1908 (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname, 1909 nodename); 1910 1911 err = add_io_leaves(childh, name, board, bus_id, slot, freq, 1912 model, status); 1913 if (err != PICL_SUCCESS) 1914 return (err); 1915 /* 1916 * get next child 1917 */ 1918 err = picl_get_propval_by_name(childh, PICL_PROP_PEER, 1919 &childh, sizeof (picl_nodehdl_t)); 1920 } 1921 1922 if (err == PICL_PROPNOTFOUND) 1923 return (PICL_SUCCESS); 1924 return (err); 1925 } 1926 1927 /* 1928 * callback function to add all io devices under sbus in io list 1929 */ 1930 /*ARGSUSED*/ 1931 static int 1932 sbus_callback(picl_nodehdl_t sbush, void *args) 1933 { 1934 picl_nodehdl_t nodeh; 1935 int err; 1936 uint32_t boardnum; 1937 uint32_t bus_id; 1938 uint32_t slot; 1939 uint32_t freq; 1940 char *model; 1941 char *status; 1942 1943 /* Fill in common infomation */ 1944 bus_id = SBUS_TYPE; 1945 1946 err = picldiag_get_clock_freq(sbush, &freq); 1947 if (err == PICL_PROPNOTFOUND) 1948 return (PICL_WALK_CONTINUE); 1949 else if (err != PICL_SUCCESS) 1950 return (err); 1951 /* 1952 * If no board# is found, set boardnum to 0 1953 */ 1954 boardnum = picldiag_get_uint_propval(sbush, OBP_PROP_BOARD_NUM, &err); 1955 if (err == PICL_PROPNOTFOUND) 1956 boardnum = DEFAULT_BOARD_NUM; 1957 else if (err != PICL_SUCCESS) 1958 return (err); 1959 1960 err = picl_get_propval_by_name(sbush, PICL_PROP_CHILD, &nodeh, 1961 sizeof (picl_nodehdl_t)); 1962 1963 while (err == PICL_SUCCESS) { 1964 slot = picldiag_get_uint_propval(nodeh, 1965 PICL_PROP_SLOT, &err); 1966 if (err == PICL_PROPNOTFOUND) { 1967 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 1968 &nodeh, sizeof (picl_nodehdl_t)); 1969 continue; 1970 } else if (err != PICL_SUCCESS) 1971 return (err); 1972 1973 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, 1974 &model); 1975 if (err == PICL_PROPNOTFOUND) 1976 model = NULL; 1977 else if (err != PICL_SUCCESS) 1978 return (err); 1979 1980 err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, 1981 &status); 1982 if (err == PICL_PROPNOTFOUND) { 1983 status = malloc(5); 1984 if (status == NULL) 1985 return (PICL_FAILURE); 1986 strncpy(status, "okay", 5); 1987 } else if (err != PICL_SUCCESS) 1988 return (err); 1989 1990 err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, freq, 1991 model, status); 1992 if (model != NULL) 1993 free(model); 1994 if (status != NULL) 1995 free(status); 1996 if (err != PICL_SUCCESS) 1997 return (err); 1998 1999 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 2000 sizeof (picl_nodehdl_t)); 2001 } 2002 if (err == PICL_PROPNOTFOUND) 2003 return (PICL_WALK_CONTINUE); 2004 return (err); 2005 } 2006 2007 /* 2008 * add all io devices under pci/pciex in io list 2009 */ 2010 /* ARGSUSED */ 2011 static int 2012 pci_pciex_callback(picl_nodehdl_t pcih, void *args) 2013 { 2014 picl_nodehdl_t nodeh; 2015 int err; 2016 char piclclass[PICL_CLASSNAMELEN_MAX]; 2017 uint32_t boardnum; 2018 uint32_t bus_id; 2019 uint32_t slot; 2020 uint32_t freq; 2021 char *model; 2022 char *status; 2023 2024 if (strcmp(args, PICL_CLASS_PCIEX) == 0) 2025 bus_id = PCIEX_TYPE; 2026 else 2027 bus_id = PCI_TYPE; 2028 2029 /* 2030 * Check if it has the freq, if not, 2031 * If not, use its parent's freq 2032 * if its parent's freq is not found, return 2033 */ 2034 err = picldiag_get_clock_freq(pcih, &freq); 2035 if (err == PICL_PROPNOTFOUND) { 2036 err = picldiag_get_clock_from_parent(pcih, &freq); 2037 if (err == PICL_PROPNOTFOUND) 2038 return (PICL_WALK_CONTINUE); 2039 else if (err != PICL_SUCCESS) 2040 return (err); 2041 } else if (err != PICL_SUCCESS) 2042 return (err); 2043 2044 /* 2045 * If no board# is found, set boardnum to 0 2046 */ 2047 boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err); 2048 if (err == PICL_PROPNOTFOUND) 2049 boardnum = DEFAULT_BOARD_NUM; 2050 else if (err != PICL_SUCCESS) 2051 return (err); 2052 2053 /* Walk through the children */ 2054 2055 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 2056 sizeof (picl_nodehdl_t)); 2057 while (err == PICL_SUCCESS) { 2058 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 2059 piclclass, sizeof (piclclass)); 2060 if (err != PICL_SUCCESS) 2061 return (err); 2062 2063 /* 2064 * Skip PCIEX, PCI bridge and USB devices because they will be 2065 * processed later 2066 */ 2067 if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) || 2068 (strcmp(piclclass, PICL_CLASS_PCIEX) == 0) || 2069 (strcmp(piclclass, PICL_CLASS_USB) == 0)) { 2070 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 2071 &nodeh, sizeof (picl_nodehdl_t)); 2072 continue; 2073 } 2074 2075 /* Get the device id for pci card */ 2076 slot = picldiag_get_uint_propval(nodeh, 2077 PICL_PROP_DEVICE_ID, &err); 2078 if (err == PICL_PROPNOTFOUND) { 2079 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 2080 &nodeh, sizeof (picl_nodehdl_t)); 2081 continue; 2082 } else if (err != PICL_SUCCESS) 2083 return (err); 2084 2085 /* Get the model of this card */ 2086 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, 2087 &model); 2088 if (err == PICL_PROPNOTFOUND) 2089 model = NULL; 2090 else if (err != PICL_SUCCESS) 2091 return (err); 2092 2093 err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, 2094 &status); 2095 if (err == PICL_PROPNOTFOUND) { 2096 status = malloc(5); 2097 if (status == NULL) 2098 return (PICL_FAILURE); 2099 strncpy(status, "okay", 5); 2100 } else if (err != PICL_SUCCESS) 2101 return (err); 2102 2103 err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, 2104 freq, model, status); 2105 2106 if (model != NULL) 2107 free(model); 2108 2109 if (status != NULL) 2110 free(status); 2111 2112 if (err != PICL_SUCCESS) 2113 return (err); 2114 2115 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 2116 sizeof (picl_nodehdl_t)); 2117 2118 } 2119 2120 if (err == PICL_PROPNOTFOUND) 2121 return (PICL_WALK_CONTINUE); 2122 2123 return (err); 2124 } 2125 2126 /* 2127 * add io devices in io list 2128 * Its slot number is drived from upa-portid 2129 */ 2130 static int 2131 add_io_devices(picl_nodehdl_t nodeh) 2132 { 2133 int err; 2134 uint64_t board_type; 2135 char piclclass[PICL_CLASSNAMELEN_MAX]; 2136 char name[MAXSTRLEN]; 2137 char *devfs_path; 2138 char *nameval; 2139 uint32_t boardnum; 2140 uint32_t bus_id; 2141 uint32_t slot; 2142 uint32_t freq; 2143 char *model; 2144 char *status; 2145 picl_prophdl_t proph; 2146 picl_propinfo_t pinfo; 2147 picl_nodehdl_t fruparenth; 2148 char *label; 2149 2150 2151 bus_id = UPA_TYPE; 2152 2153 /* 2154 * If clock frequency can't be found from its parent, don't add 2155 */ 2156 err = picldiag_get_clock_from_parent(nodeh, &freq); 2157 if (err == PICL_PROPNOTFOUND) 2158 return (PICL_SUCCESS); 2159 else if (err != PICL_SUCCESS) 2160 return (err); 2161 2162 /* 2163 * If no board# is found, set boardnum to 0 2164 */ 2165 boardnum = picldiag_get_uint_propval(nodeh, OBP_PROP_BOARD_NUM, &err); 2166 if (err == PICL_PROPNOTFOUND) 2167 boardnum = DEFAULT_BOARD_NUM; 2168 else if (err != PICL_SUCCESS) 2169 return (err); 2170 2171 /* 2172 * get upa portid as slot number 2173 * If upa portid is not found, don't add the card. 2174 */ 2175 slot = picldiag_get_uint_propval(nodeh, OBP_PROP_UPA_PORTID, 2176 &err); 2177 if (err == PICL_PROPNOTFOUND) 2178 return (PICL_SUCCESS); 2179 else if (err != PICL_SUCCESS) 2180 return (err); 2181 2182 /* Get the model of this card */ 2183 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, &model); 2184 if (err == PICL_PROPNOTFOUND) 2185 model = NULL; 2186 else if (err != PICL_SUCCESS) 2187 return (err); 2188 2189 /* 2190 * check if it is a ffb device 2191 * If it's a ffb device, append its board type to name 2192 * otherwise, use its nodename 2193 */ 2194 err = picl_get_prop_by_name(nodeh, PICL_PROP_FFB_BOARD_REV, &proph); 2195 if (err == PICL_PROPNOTFOUND) { 2196 err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, 2197 &pinfo, &proph); 2198 if (err != PICL_SUCCESS) 2199 return (err); 2200 2201 nameval = alloca(pinfo.size); 2202 if (nameval == NULL) 2203 return (PICL_FAILURE); 2204 2205 err = picl_get_propval(proph, nameval, pinfo.size); 2206 if (err != PICL_SUCCESS) 2207 return (err); 2208 2209 (void) strlcpy(name, nameval, MAXSTRLEN); 2210 } else if (err == PICL_SUCCESS) { 2211 /* Find out if it's single or double buffered */ 2212 board_type = picldiag_get_uint_propval(nodeh, 2213 OBP_PROP_BOARD_TYPE, &err); 2214 if (err == PICL_PROPNOTFOUND) 2215 (void) strlcpy(name, FFB_NAME, sizeof (name)); 2216 if (err == PICL_SUCCESS) { 2217 if (board_type & FFB_B_BUFF) 2218 (void) strlcpy(name, FFB_DOUBLE_BUF, 2219 sizeof (name)); 2220 else 2221 (void) strlcpy(name, FFB_SINGLE_BUF, 2222 sizeof (name)); 2223 } else 2224 return (err); 2225 } else 2226 return (err); 2227 2228 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 2229 piclclass, sizeof (piclclass)); 2230 if (err != PICL_SUCCESS) 2231 return (err); 2232 2233 (void) snprintf(name, sizeof (name), "%s (%s)", name, piclclass); 2234 2235 err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status); 2236 if (err == PICL_PROPNOTFOUND) { 2237 status = malloc(5); 2238 if (status == NULL) 2239 return (PICL_FAILURE); 2240 strncpy(status, "okay", 5); 2241 } else if (err != PICL_SUCCESS) 2242 return (err); 2243 2244 err = picldiag_get_fru_parent(nodeh, &fruparenth); 2245 if (err == PICL_PROPNOTFOUND) { 2246 label = NULL; 2247 } else if (err != PICL_SUCCESS) { 2248 return (err); 2249 } else { 2250 err = picldiag_get_combined_label(fruparenth, &label, 15); 2251 if (err == PICL_PROPNOTFOUND) 2252 label = NULL; 2253 else if (err != PICL_SUCCESS) 2254 return (err); 2255 } 2256 /* devfs-path */ 2257 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, 2258 &devfs_path); 2259 if (err == PICL_PROPNOTFOUND) 2260 devfs_path = NULL; 2261 else if (err != PICL_SUCCESS) 2262 return (err); 2263 2264 add_io_card(boardnum, bus_id, slot, label, freq, name, model, status, 2265 devfs_path); 2266 if (label != NULL) 2267 free(label); 2268 if (model != NULL) 2269 free(model); 2270 if (status != NULL) 2271 free(status); 2272 if (devfs_path != NULL) 2273 free(devfs_path); 2274 2275 return (PICL_SUCCESS); 2276 } 2277 2278 /* 2279 * loop through all children and add io devices in io list 2280 */ 2281 static int 2282 process_io_leaves(picl_nodehdl_t rooth) 2283 { 2284 picl_nodehdl_t nodeh; 2285 char classval[PICL_CLASSNAMELEN_MAX]; 2286 int err; 2287 2288 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh, 2289 sizeof (picl_nodehdl_t)); 2290 while (err == PICL_SUCCESS) { 2291 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 2292 classval, sizeof (classval)); 2293 if (err != PICL_SUCCESS) 2294 return (err); 2295 2296 if (is_io_device(classval)) 2297 err = add_io_devices(nodeh); 2298 2299 if (err != PICL_SUCCESS) 2300 return (err); 2301 2302 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 2303 sizeof (picl_nodehdl_t)); 2304 } 2305 2306 if (err == PICL_PROPNOTFOUND) 2307 return (PICL_SUCCESS); 2308 2309 return (err); 2310 } 2311 2312 /* 2313 * callback function to add all io devices under upa in io list 2314 */ 2315 /*ARGSUSED*/ 2316 static int 2317 upa_callback(picl_nodehdl_t upah, void *args) 2318 { 2319 int err; 2320 2321 err = process_io_leaves(upah); 2322 2323 if (err == PICL_SUCCESS) 2324 return (PICL_WALK_CONTINUE); 2325 return (err); 2326 } 2327 2328 /* 2329 * display ffb hardware configuration 2330 */ 2331 /* ARGSUSED */ 2332 static int 2333 ffbconfig_callback(picl_nodehdl_t ffbh, void *arg) 2334 { 2335 int err; 2336 uint64_t board_rev; 2337 uint64_t fbc_ver; 2338 char *dac_ver; 2339 char *fbram_ver; 2340 2341 /* 2342 * If it has PICL_PROP_FFB_BOARD_REV, it is a ffb device 2343 * Otherwise, return. 2344 */ 2345 board_rev = picldiag_get_uint_propval(ffbh, PICL_PROP_FFB_BOARD_REV, 2346 &err); 2347 if (err == PICL_PROPNOTFOUND) 2348 return (PICL_WALK_CONTINUE); 2349 else if (err != PICL_SUCCESS) 2350 return (err); 2351 2352 log_printf("FFB Hardware Configuration:\n"); 2353 log_printf("-----------------------------------\n"); 2354 log_printf("Board rev: %lld\n", board_rev); 2355 2356 fbc_ver = picldiag_get_uint_propval(ffbh, OBP_PROP_FBC_REG_ID, 2357 &err); 2358 if (err == PICL_SUCCESS) 2359 log_printf("FBC version: 0x%llx\n", fbc_ver); 2360 else if (err != PICL_PROPNOTFOUND) 2361 return (err); 2362 2363 err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_DAC_VER, 2364 &dac_ver); 2365 if (err == PICL_SUCCESS) { 2366 log_printf("DAC: %s\n", dac_ver); 2367 free(dac_ver); 2368 } else if (err != PICL_PROPNOTFOUND) 2369 return (err); 2370 2371 err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_FBRAM_VER, 2372 &fbram_ver); 2373 if (err == PICL_SUCCESS) { 2374 log_printf("3DRAM: %s\n", fbram_ver); 2375 free(fbram_ver); 2376 } else if (err != PICL_PROPNOTFOUND) 2377 return (err); 2378 2379 log_printf("\n"); 2380 return (PICL_WALK_CONTINUE); 2381 } 2382 2383 /* 2384 * find all io devices and add them in the io list 2385 */ 2386 static int 2387 gather_io_cards(picl_nodehdl_t plafh) 2388 { 2389 int err; 2390 2391 /* 2392 * look for io devices under the immediate children of platform 2393 */ 2394 err = process_io_leaves(plafh); 2395 if (err != PICL_SUCCESS) 2396 return (err); 2397 2398 err = picl_walk_tree_by_class(plafh, PICL_CLASS_SBUS, 2399 PICL_CLASS_SBUS, sbus_callback); 2400 if (err != PICL_SUCCESS) 2401 return (err); 2402 2403 err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 2404 PICL_CLASS_PCI, pci_pciex_callback); 2405 if (err != PICL_SUCCESS) 2406 return (err); 2407 2408 err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, 2409 PICL_CLASS_PCIEX, pci_pciex_callback); 2410 if (err != PICL_SUCCESS) 2411 return (err); 2412 2413 err = picl_walk_tree_by_class(plafh, PICL_CLASS_UPA, 2414 PICL_CLASS_UPA, upa_callback); 2415 2416 return (err); 2417 } 2418 2419 static void 2420 picldiag_display_io_cards(struct io_card *list) 2421 { 2422 static int banner = 0; /* Have we printed the column headings? */ 2423 struct io_card *p; 2424 2425 if (list == NULL) 2426 return; 2427 2428 if (banner == 0) { 2429 log_printf("Bus Freq Slot + Name +\n", 0); 2430 log_printf("Type MHz Status Path" 2431 " Model", 0); 2432 log_printf("\n", 0); 2433 log_printf("------ ---- ---------- " 2434 "---------------------------- " 2435 "--------------------", 0); 2436 log_printf("\n", 0); 2437 banner = 1; 2438 } 2439 2440 for (p = list; p != NULL; p = p -> next) { 2441 log_printf("%-6s ", p->bus_type, 0); 2442 log_printf("%-3d ", p->freq, 0); 2443 /* 2444 * We check to see if it's an int or 2445 * a char string to display for slot. 2446 */ 2447 if (p->slot == PCI_SLOT_IS_STRING) 2448 log_printf("%-10s ", p->slot_str, 0); 2449 else 2450 log_printf("%-10d ", p->slot, 0); 2451 2452 log_printf("%-28.28s", p->name, 0); 2453 if (strlen(p->name) > 28) 2454 log_printf("+ ", 0); 2455 else 2456 log_printf(" ", 0); 2457 log_printf("%-19.19s", p->model, 0); 2458 if (strlen(p->model) > 19) 2459 log_printf("+", 0); 2460 log_printf("\n", 0); 2461 log_printf(" %-10s ", p->status, 0); 2462 set_exit_code(p->status); 2463 if (strlen(p->notes) > 0) 2464 log_printf("%s", p->notes, 0); 2465 log_printf("\n\n", 0); 2466 } 2467 } 2468 2469 /* 2470 * display all io devices 2471 */ 2472 static int 2473 display_io_device_info(picl_nodehdl_t plafh) 2474 { 2475 int err; 2476 2477 err = gather_io_cards(plafh); 2478 if (err != PICL_SUCCESS) 2479 return (err); 2480 2481 logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"), 2482 DEFAULT_LINE_WIDTH); 2483 2484 picldiag_display_io_cards(io_card_list); 2485 2486 free_io_cards(io_card_list); 2487 2488 return (PICL_SUCCESS); 2489 } 2490 2491 /* 2492 * print fan device information 2493 */ 2494 static int 2495 logprintf_fan_info(picl_nodehdl_t fanh) 2496 { 2497 int err; 2498 char *label; 2499 char *unit; 2500 int64_t speed; 2501 int64_t min_speed; 2502 picl_nodehdl_t fruph; 2503 2504 err = picldiag_get_fru_parent(fanh, &fruph); 2505 if (err != PICL_SUCCESS) 2506 return (err); 2507 2508 err = picldiag_get_combined_label(fruph, &label, 20); 2509 if (err != PICL_SUCCESS) 2510 return (err); 2511 2512 log_printf("%-20s ", label); 2513 free(label); 2514 2515 err = picldiag_get_label(fanh, &label); 2516 if (err == PICL_SUCCESS) { 2517 log_printf("%-14s ", label); 2518 free(label); 2519 } else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 2520 log_printf(" - "); 2521 } else 2522 return (err); 2523 2524 speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err); 2525 if (err == PICL_SUCCESS) { 2526 min_speed = picldiag_get_uint_propval(fanh, 2527 PICL_PROP_LOW_WARNING_THRESHOLD, &err); 2528 if (err != PICL_SUCCESS) 2529 min_speed = 0; 2530 2531 if (speed < min_speed) { 2532 log_printf("failed (%lld", speed); 2533 err = picldiag_get_string_propval(fanh, 2534 PICL_PROP_FAN_SPEED_UNIT, &unit); 2535 if (err == PICL_SUCCESS) { 2536 log_printf("%s", unit); 2537 free(unit); 2538 } 2539 log_printf(")"); 2540 exit_code = PD_SYSTEM_FAILURE; 2541 } else { 2542 log_printf("okay"); 2543 } 2544 } else { 2545 err = picldiag_get_string_propval(fanh, 2546 PICL_PROP_FAN_SPEED_UNIT, &unit); 2547 if (err == PICL_SUCCESS) { 2548 log_printf("%-12s ", unit); 2549 free(unit); 2550 } 2551 } 2552 2553 log_printf("\n"); 2554 return (PICL_SUCCESS); 2555 } 2556 2557 static int 2558 fan_callback(picl_nodehdl_t fanh, void *arg) 2559 { 2560 int *countp = arg; 2561 2562 if (*countp == 0) { 2563 log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n")); 2564 log_printf("-------------------------------------------\n"); 2565 log_printf("Location Sensor Status\n"); 2566 log_printf("-------------------------------------------\n"); 2567 } 2568 *countp += 1; 2569 2570 (void) logprintf_fan_info(fanh); 2571 2572 return (PICL_WALK_CONTINUE); 2573 } 2574 2575 /* 2576 * callback function search children to find fan device and print its speed 2577 */ 2578 static int 2579 display_fan_speed(picl_nodehdl_t plafh) 2580 { 2581 int err; 2582 int print_header; 2583 2584 print_header = 0; 2585 err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN, 2586 &print_header, fan_callback); 2587 return (err); 2588 } 2589 2590 /* 2591 * print temperature sensor information 2592 */ 2593 static int 2594 logprintf_temp_info(picl_nodehdl_t temph) 2595 { 2596 int err; 2597 char *label; 2598 int64_t temperature; 2599 int64_t threshold; 2600 picl_nodehdl_t fruph; 2601 char *status = "unknown"; 2602 int got_temp = 0; 2603 2604 err = picldiag_get_fru_parent(temph, &fruph); 2605 if (err != PICL_SUCCESS) 2606 return (err); 2607 2608 err = picldiag_get_combined_label(fruph, &label, 14); 2609 if (err != PICL_SUCCESS) 2610 return (err); 2611 2612 log_printf("%-14s ", label); 2613 free(label); 2614 2615 err = picldiag_get_label(temph, &label); 2616 if (err != PICL_SUCCESS) 2617 return (err); 2618 log_printf("%-19s ", label); 2619 free(label); 2620 2621 temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE, 2622 &err); 2623 if (err == PICL_SUCCESS) { 2624 got_temp = 1; 2625 status = "okay"; 2626 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2627 return (err); 2628 } 2629 2630 threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING, 2631 &err); 2632 if (err == PICL_SUCCESS) { 2633 if (got_temp && temperature < threshold) 2634 status = "warning"; 2635 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2636 return (err); 2637 } 2638 2639 threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN, 2640 &err); 2641 if (err == PICL_SUCCESS) { 2642 if (got_temp && temperature < threshold) 2643 status = "failed"; 2644 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2645 return (err); 2646 } 2647 2648 threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING, 2649 &err); 2650 if (err == PICL_SUCCESS) { 2651 if (got_temp && temperature > threshold) 2652 status = "warning"; 2653 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2654 return (err); 2655 } 2656 2657 threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN, 2658 &err); 2659 if (err == PICL_SUCCESS) { 2660 if (got_temp && temperature > threshold) 2661 status = "failed"; 2662 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2663 return (err); 2664 } 2665 2666 err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status); 2667 if (err == PICL_SUCCESS) { 2668 log_printf("%s", status); 2669 set_exit_code(status); 2670 free(status); 2671 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2672 return (err); 2673 } else { 2674 log_printf("%s ", status); 2675 set_exit_code(status); 2676 if (strcmp(status, "failed") == 0 || 2677 strcmp(status, "warning") == 0) 2678 log_printf("(%.2lldC)", temperature); 2679 } 2680 2681 log_printf("\n"); 2682 return (PICL_SUCCESS); 2683 } 2684 2685 static int 2686 temp_callback(picl_nodehdl_t temph, void *arg) 2687 { 2688 int err; 2689 int *countp = arg; 2690 2691 if (*countp == 0) { 2692 log_printf("\n"); 2693 log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n")); 2694 log_printf("-----------------------------------------\n"); 2695 log_printf("Location Sensor Status\n"); 2696 log_printf("-----------------------------------------\n"); 2697 } 2698 *countp += 1; 2699 err = logprintf_temp_info(temph); 2700 if (err == PICL_SUCCESS) 2701 return (PICL_WALK_CONTINUE); 2702 return (err); 2703 } 2704 2705 /* 2706 * callback function search children to find temp sensors and print the temp 2707 */ 2708 /* ARGSUSED */ 2709 static int 2710 display_temp(picl_nodehdl_t plafh) 2711 { 2712 int err; 2713 int print_header; 2714 2715 print_header = 0; 2716 err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR, 2717 &print_header, temp_callback); 2718 if (err != PICL_SUCCESS) 2719 return (err); 2720 err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR, 2721 &print_header, temp_callback); 2722 return (err); 2723 } 2724 2725 /* 2726 * print current sensor information 2727 */ 2728 static int 2729 logprintf_current_info(picl_nodehdl_t currenth) 2730 { 2731 int err; 2732 char *label; 2733 float current; 2734 float threshold; 2735 picl_nodehdl_t fruph; 2736 char *status = "unknown"; 2737 int got_current = 0; 2738 2739 err = picldiag_get_fru_parent(currenth, &fruph); 2740 if (err != PICL_SUCCESS) 2741 return (err); 2742 2743 err = picldiag_get_combined_label(fruph, &label, 20); 2744 if (err != PICL_SUCCESS) 2745 return (err); 2746 2747 log_printf("%-20s ", label); 2748 free(label); 2749 2750 err = picldiag_get_label(currenth, &label); 2751 if (err != PICL_SUCCESS) 2752 return (err); 2753 log_printf("%-10s ", label); 2754 free(label); 2755 2756 current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err); 2757 if (err == PICL_SUCCESS) { 2758 status = "okay"; 2759 got_current = 1; 2760 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2761 return (err); 2762 } 2763 2764 threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING, 2765 &err); 2766 if (err == PICL_SUCCESS) { 2767 if (got_current && current < threshold) 2768 status = "warning"; 2769 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2770 return (err); 2771 } 2772 2773 threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN, 2774 &err); 2775 if (err == PICL_SUCCESS) { 2776 if (got_current && current < threshold) 2777 status = "failed"; 2778 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2779 return (err); 2780 } 2781 2782 threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING, 2783 &err); 2784 if (err == PICL_SUCCESS) { 2785 if (got_current && current > threshold) 2786 status = "warning"; 2787 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2788 return (err); 2789 } 2790 2791 threshold = picldiag_get_float_propval(currenth, 2792 PICL_PROP_HIGH_SHUTDOWN, &err); 2793 if (err == PICL_SUCCESS) { 2794 if (got_current && current > threshold) 2795 status = "failed"; 2796 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2797 return (err); 2798 } 2799 2800 err = picldiag_get_string_propval(currenth, 2801 PICL_PROP_CONDITION, &status); 2802 if (err == PICL_SUCCESS) { 2803 log_printf(" %s", status); 2804 set_exit_code(status); 2805 free(status); 2806 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2807 return (err); 2808 } else { 2809 log_printf("%s ", status); 2810 set_exit_code(status); 2811 if (strcmp(status, "failed") == 0 || 2812 strcmp(status, "warning") == 0) 2813 log_printf("(%.2fA)", current); 2814 } 2815 2816 log_printf("\n"); 2817 return (PICL_SUCCESS); 2818 } 2819 2820 static int 2821 current_callback(picl_nodehdl_t currh, void *arg) 2822 { 2823 int err; 2824 int *countp = arg; 2825 2826 if (*countp == 0) { 2827 log_printf("------------------------------------\n"); 2828 log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n")); 2829 log_printf("----------------------------------------\n"); 2830 log_printf("Location Sensor Status\n"); 2831 log_printf("----------------------------------------\n"); 2832 } 2833 *countp += 1; 2834 err = logprintf_current_info(currh); 2835 if (err == PICL_SUCCESS) 2836 return (PICL_WALK_CONTINUE); 2837 return (err); 2838 } 2839 2840 /* 2841 * callback function search children to find curr sensors and print the curr 2842 */ 2843 /* ARGSUSED */ 2844 static int 2845 display_current(picl_nodehdl_t plafh) 2846 { 2847 int err; 2848 int print_header; 2849 2850 print_header = 0; 2851 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR, 2852 &print_header, current_callback); 2853 if (err != PICL_SUCCESS) 2854 return (err); 2855 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR, 2856 &print_header, current_callback); 2857 return (err); 2858 } 2859 2860 /* 2861 * print voltage sensor information 2862 */ 2863 static int 2864 logprintf_voltage_info(picl_nodehdl_t voltageh) 2865 { 2866 int err; 2867 char *label; 2868 float voltage; 2869 float threshold; 2870 picl_nodehdl_t fruph; 2871 char *status = "unknown"; 2872 int got_voltage = 0; 2873 2874 err = picldiag_get_fru_parent(voltageh, &fruph); 2875 if (err != PICL_SUCCESS) 2876 return (err); 2877 2878 err = picldiag_get_combined_label(fruph, &label, 14); 2879 if (err != PICL_SUCCESS) 2880 return (err); 2881 2882 log_printf("%-14s ", label); 2883 free(label); 2884 2885 err = picldiag_get_label(voltageh, &label); 2886 if (err != PICL_SUCCESS) 2887 return (err); 2888 log_printf("%-12s ", label); 2889 free(label); 2890 2891 voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err); 2892 if (err == PICL_SUCCESS) { 2893 status = "okay"; 2894 got_voltage = 1; 2895 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2896 return (err); 2897 } 2898 2899 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING, 2900 &err); 2901 if (err == PICL_SUCCESS) { 2902 if (got_voltage && voltage < threshold) 2903 status = "warning"; 2904 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2905 return (err); 2906 } 2907 2908 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN, 2909 &err); 2910 if (err == PICL_SUCCESS) { 2911 if (got_voltage && voltage < threshold) 2912 status = "failed"; 2913 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2914 return (err); 2915 } 2916 2917 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING, 2918 &err); 2919 if (err == PICL_SUCCESS) { 2920 if (got_voltage && voltage > threshold) 2921 status = "warning"; 2922 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2923 return (err); 2924 } 2925 2926 threshold = picldiag_get_float_propval(voltageh, 2927 PICL_PROP_HIGH_SHUTDOWN, &err); 2928 if (err == PICL_SUCCESS) { 2929 if (got_voltage && voltage > threshold) 2930 status = "failed"; 2931 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2932 return (err); 2933 } 2934 2935 err = picldiag_get_string_propval(voltageh, 2936 PICL_PROP_CONDITION, &status); 2937 if (err == PICL_SUCCESS) { 2938 log_printf("%s", status); 2939 set_exit_code(status); 2940 free(status); 2941 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2942 return (err); 2943 } else { 2944 log_printf("%s ", status); 2945 set_exit_code(status); 2946 if (strcmp(status, "warning") == 0 || 2947 strcmp(status, "failed") == 0) 2948 log_printf("(%.2fV)", voltage); 2949 } 2950 2951 log_printf("\n"); 2952 return (PICL_SUCCESS); 2953 } 2954 2955 static int 2956 voltage_callback(picl_nodehdl_t voltageh, void *arg) 2957 { 2958 int *countp = arg; 2959 int err; 2960 2961 if (*countp == 0) { 2962 log_printf("------------------------------------\n"); 2963 log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n")); 2964 log_printf("-----------------------------------\n"); 2965 log_printf("Location Sensor Status\n"); 2966 log_printf("-----------------------------------\n"); 2967 } 2968 *countp += 1; 2969 err = logprintf_voltage_info(voltageh); 2970 if (err == PICL_SUCCESS) 2971 return (PICL_WALK_CONTINUE); 2972 return (err); 2973 } 2974 2975 /* 2976 * callback function search children to find voltage sensors and print voltage 2977 */ 2978 /* ARGSUSED */ 2979 static int 2980 display_voltage(picl_nodehdl_t plafh) 2981 { 2982 int err; 2983 int print_header; 2984 2985 print_header = 0; 2986 err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR, 2987 &print_header, voltage_callback); 2988 if (err != PICL_SUCCESS) 2989 return (err); 2990 err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR, 2991 &print_header, voltage_callback); 2992 return (err); 2993 } 2994 2995 /* 2996 * print led device information 2997 */ 2998 static int 2999 logprintf_led_info(picl_nodehdl_t ledh) 3000 { 3001 int err; 3002 char *label; 3003 char *state; 3004 char *color; 3005 picl_nodehdl_t fruph; 3006 3007 err = picldiag_get_fru_parent(ledh, &fruph); 3008 if (err != PICL_SUCCESS) 3009 return (err); 3010 3011 err = picldiag_get_combined_label(fruph, &label, 22); 3012 if (err != PICL_SUCCESS) { 3013 log_printf(" - ", label); 3014 } else { 3015 log_printf("%-22s ", label); 3016 free(label); 3017 } 3018 3019 err = picldiag_get_label(ledh, &label); 3020 if (err != PICL_SUCCESS) 3021 return (err); 3022 log_printf("%-20s ", label); 3023 free(label); 3024 3025 err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state); 3026 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 3027 log_printf(" - "); 3028 } else if (err != PICL_SUCCESS) { 3029 return (err); 3030 } else { 3031 log_printf("%-10s ", state); 3032 free(state); 3033 } 3034 3035 err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color); 3036 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 3037 log_printf("\n"); 3038 } else if (err != PICL_SUCCESS) { 3039 return (err); 3040 } else { 3041 log_printf("%-16s\n", color); 3042 free(color); 3043 } 3044 3045 return (PICL_SUCCESS); 3046 } 3047 3048 static int 3049 led_callback(picl_nodehdl_t ledh, void *arg) 3050 { 3051 int *countp = arg; 3052 int err; 3053 3054 if (*countp == 0) { 3055 3056 log_printf("--------------------------------------" 3057 "------------\n"); 3058 log_printf(dgettext(TEXT_DOMAIN, "Led State:\n")); 3059 log_printf("----------------------------------------" 3060 "----------------------\n"); 3061 log_printf("Location Led State" 3062 " Color\n"); 3063 log_printf("----------------------------------------" 3064 "----------------------\n"); 3065 } 3066 *countp += 1; 3067 err = logprintf_led_info(ledh); 3068 if (err == PICL_SUCCESS) 3069 return (PICL_WALK_CONTINUE); 3070 return (err); 3071 } 3072 3073 /* 3074 * callback function search children to find led devices and print status 3075 */ 3076 /* ARGSUSED */ 3077 static int 3078 display_led_status(picl_nodehdl_t plafh) 3079 { 3080 int print_header; 3081 3082 print_header = 0; 3083 picl_walk_tree_by_class(plafh, PICL_CLASS_LED, 3084 &print_header, led_callback); 3085 return (PICL_SUCCESS); 3086 } 3087 3088 /* 3089 * print keyswitch device information 3090 */ 3091 static int 3092 logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph) 3093 { 3094 int err; 3095 char *label; 3096 char *state; 3097 3098 err = picldiag_get_combined_label(fruph, &label, 10); 3099 if (err != PICL_SUCCESS) { 3100 log_printf("%-14s", " -"); 3101 } else { 3102 log_printf("%-14s ", label); 3103 free(label); 3104 } 3105 3106 err = picldiag_get_label(keyswitchh, &label); 3107 if (err != PICL_SUCCESS) 3108 return (err); 3109 log_printf("%-11s ", label); 3110 free(label); 3111 3112 err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state); 3113 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 3114 log_printf(" -\n"); 3115 } else if (err != PICL_SUCCESS) { 3116 return (err); 3117 } else { 3118 log_printf("%s\n", state); 3119 free(state); 3120 } 3121 3122 return (PICL_SUCCESS); 3123 } 3124 3125 static int 3126 keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg) 3127 { 3128 int *countp = arg; 3129 int err; 3130 picl_nodehdl_t fruph; 3131 3132 /* 3133 * Tamale simulates a key-switch on ENxS. So the presence of a 3134 * node of class keyswitch is not sufficient. If it has a fru parent 3135 * or location parent, then believe it. 3136 */ 3137 err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT, 3138 &fruph, sizeof (fruph)); 3139 if (err == PICL_PROPNOTFOUND) { 3140 err = picl_get_propval_by_name(keyswitchh, 3141 PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph)); 3142 } 3143 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) 3144 return (PICL_WALK_CONTINUE); 3145 if (err != PICL_SUCCESS) 3146 return (err); 3147 3148 if (*countp == 0) { 3149 log_printf("-----------------------------------------\n"); 3150 log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n")); 3151 log_printf("-----------------------------------------\n"); 3152 log_printf(dgettext(TEXT_DOMAIN, 3153 "Location Keyswitch State\n")); 3154 log_printf("-----------------------------------------\n"); 3155 } 3156 *countp += 1; 3157 err = logprintf_keyswitch_info(keyswitchh, fruph); 3158 if (err == PICL_SUCCESS) 3159 return (PICL_WALK_CONTINUE); 3160 return (err); 3161 } 3162 3163 /* 3164 * search children to find keyswitch device(s) and print status 3165 */ 3166 /* ARGSUSED */ 3167 static int 3168 display_keyswitch(picl_nodehdl_t plafh) 3169 { 3170 int print_header = 0; 3171 3172 picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH, 3173 &print_header, keyswitch_callback); 3174 return (PICL_SUCCESS); 3175 } 3176 3177 /* 3178 * display environment status 3179 */ 3180 static int 3181 display_envctrl_status(picl_nodehdl_t plafh) 3182 { 3183 logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"), 3184 DEFAULT_LINE_WIDTH); 3185 3186 display_fan_speed(plafh); 3187 display_temp(plafh); 3188 display_current(plafh); 3189 display_voltage(plafh); 3190 display_keyswitch(plafh); 3191 display_led_status(plafh); 3192 3193 return (PICL_SUCCESS); 3194 } 3195 3196 /* 3197 * print fru operational status 3198 */ 3199 static int 3200 logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp) 3201 { 3202 int err; 3203 char *label; 3204 char *status; 3205 3206 err = picldiag_get_combined_label(fruh, &label, 23); 3207 if (err != PICL_SUCCESS) 3208 return (PICL_WALK_CONTINUE); 3209 3210 err = picldiag_get_string_propval(fruh, 3211 PICL_PROP_OPERATIONAL_STATUS, &status); 3212 if (err == PICL_SUCCESS) { 3213 if (*countp == 0) { 3214 logprintf_header(dgettext(TEXT_DOMAIN, 3215 "FRU Operational Status"), 3216 DEFAULT_LINE_WIDTH); 3217 log_printf("---------------------------------\n"); 3218 log_printf(dgettext(TEXT_DOMAIN, 3219 "Fru Operational Status:\n")); 3220 log_printf("---------------------------------\n"); 3221 log_printf("Location Status\n"); 3222 log_printf("---------------------------------\n"); 3223 } 3224 *countp += 1; 3225 log_printf("%-23s ", label); 3226 free(label); 3227 log_printf("%s\n", status); 3228 set_exit_code(status); 3229 free(status); 3230 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 3231 free(label); 3232 return (err); 3233 } else { 3234 free(label); 3235 } 3236 return (PICL_WALK_CONTINUE); 3237 } 3238 3239 static int 3240 fru_oper_status_callback(picl_nodehdl_t fruh, void *arg) 3241 { 3242 int err; 3243 3244 err = logprintf_fru_oper_status(fruh, (int *)arg); 3245 return (err); 3246 } 3247 3248 /* 3249 * display fru operational status 3250 */ 3251 static int 3252 display_fru_oper_status(picl_nodehdl_t frutreeh) 3253 { 3254 int print_header; 3255 3256 print_header = 0; 3257 picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU, 3258 &print_header, fru_oper_status_callback); 3259 return (PICL_SUCCESS); 3260 } 3261 3262 /* 3263 * check if the node having the version prop 3264 * If yes, print its nodename and version 3265 */ 3266 /* ARGSUSED */ 3267 static int 3268 asicrev_callback(picl_nodehdl_t nodeh, void *arg) 3269 { 3270 uint32_t version; 3271 char *name; 3272 char *model; 3273 char *status; 3274 int err; 3275 3276 /* 3277 * Fire based platforms use "module-revision#" in place of "version#", 3278 * so we need to look for this property if we don't find "version#" 3279 */ 3280 version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM, &err); 3281 if (err == PICL_PROPNOTFOUND) { 3282 version = picldiag_get_uint_propval(nodeh, OBP_PROP_MODREV_NUM, 3283 &err); 3284 if (err == PICL_PROPNOTFOUND) 3285 return (PICL_WALK_CONTINUE); 3286 } 3287 if (err != PICL_SUCCESS) 3288 return (err); 3289 3290 /* devfs-path */ 3291 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name); 3292 if (err == PICL_PROPNOTFOUND) 3293 name = NULL; 3294 else if (err != PICL_SUCCESS) 3295 return (err); 3296 3297 /* model */ 3298 err = picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME, 3299 &model); 3300 if (err == PICL_PROPNOTFOUND) 3301 model = NULL; 3302 else if (err != PICL_SUCCESS) 3303 return (err); 3304 3305 /* status */ 3306 err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status); 3307 if (err == PICL_PROPNOTFOUND) 3308 status = NULL; 3309 else if (err != PICL_SUCCESS) 3310 return (err); 3311 3312 /* 3313 * Display the data 3314 */ 3315 3316 /* name */ 3317 if (name != NULL) { 3318 log_printf("%-22s ", name); 3319 free(name); 3320 } else 3321 log_printf("%-22s ", "unknown"); 3322 /* model */ 3323 if (model != NULL) { 3324 log_printf("%-15s ", model); 3325 free(model); 3326 } else 3327 log_printf("%-15s ", "unknown"); 3328 /* status */ 3329 if (status == NULL) 3330 log_printf("%-15s ", "okay"); 3331 else { 3332 log_printf("%-15s ", status); 3333 set_exit_code(status); 3334 free(status); 3335 } 3336 /* revision */ 3337 log_printf(" %-4d\n", version); 3338 3339 return (PICL_WALK_CONTINUE); 3340 } 3341 3342 /* 3343 * traverse the tree to display asic revision id for ebus 3344 */ 3345 /* ARGSUSED */ 3346 static int 3347 ebus_callback(picl_nodehdl_t ebush, void *arg) 3348 { 3349 uint32_t id; 3350 char *name; 3351 int err; 3352 char *model; 3353 char *status; 3354 3355 id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err); 3356 if (err == PICL_PROPNOTFOUND) 3357 return (PICL_WALK_CONTINUE); 3358 else if (err != PICL_SUCCESS) 3359 return (err); 3360 3361 /* devfs-path */ 3362 err = picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name); 3363 if (err == PICL_PROPNOTFOUND) 3364 name = NULL; 3365 else if (err != PICL_SUCCESS) 3366 return (err); 3367 3368 /* model */ 3369 err = picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME, 3370 &model); 3371 if (err == PICL_PROPNOTFOUND) 3372 model = NULL; 3373 else if (err != PICL_SUCCESS) 3374 return (err); 3375 3376 /* status */ 3377 err = picldiag_get_string_propval(ebush, PICL_PROP_STATUS, &status); 3378 if (err == PICL_PROPNOTFOUND) 3379 status = NULL; 3380 else if (err != PICL_SUCCESS) 3381 return (err); 3382 3383 /* 3384 * Display the data 3385 */ 3386 3387 /* name */ 3388 if (name != NULL) { 3389 log_printf("%-22s ", name); 3390 free(name); 3391 } else 3392 log_printf("%-22s ", "unknown"); 3393 /* model */ 3394 if (model != NULL) { 3395 log_printf("%-15s ", model); 3396 free(model); 3397 } else 3398 log_printf("%-15s ", "unknown"); 3399 /* status */ 3400 if (status == NULL) 3401 log_printf("%-15s ", "okay"); 3402 else { 3403 log_printf("%-15s ", status); 3404 set_exit_code(status); 3405 free(status); 3406 } 3407 /* revision */ 3408 log_printf(" %-4d\n", id); 3409 3410 return (PICL_WALK_CONTINUE); 3411 } 3412 3413 /* 3414 * display asic revision id 3415 */ 3416 static int 3417 display_hw_revisions(picl_nodehdl_t plafh) 3418 { 3419 int err; 3420 3421 /* Print the header */ 3422 logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"), 3423 DEFAULT_LINE_WIDTH); 3424 3425 log_printf("ASIC Revisions:\n"); 3426 log_printf("-----------------------------"); 3427 log_printf("--------------------------------------\n"); 3428 log_printf("Path Device"); 3429 log_printf(" Status Revision\n"); 3430 log_printf("-----------------------------"); 3431 log_printf("--------------------------------------\n"); 3432 3433 err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback); 3434 if (err != PICL_SUCCESS) 3435 return (err); 3436 3437 err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS, 3438 NULL, ebus_callback); 3439 if (err != PICL_SUCCESS) 3440 return (err); 3441 3442 log_printf("\n"); 3443 3444 err = picl_walk_tree_by_class(plafh, PICL_CLASS_DISPLAY, 3445 NULL, ffbconfig_callback); 3446 return (err); 3447 } 3448 3449 /* 3450 * find the options node and its powerfail_time prop 3451 * If found, display the list of latest powerfail. 3452 */ 3453 /* ARGSUSED */ 3454 static int 3455 options_callback(picl_nodehdl_t nodeh, void *arg) 3456 { 3457 time_t value; 3458 char *failtime; 3459 int err; 3460 3461 err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME, 3462 &failtime); 3463 if (err == PICL_PROPNOTFOUND) 3464 return (PICL_WALK_TERMINATE); 3465 else if (err != PICL_SUCCESS) 3466 return (err); 3467 3468 value = (time_t)atoi(failtime); 3469 free(failtime); 3470 if (value == 0) 3471 return (PICL_WALK_TERMINATE); 3472 3473 log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n")); 3474 log_printf("=============================\n"); 3475 log_printf("%s", ctime(&value)); 3476 log_printf("\n"); 3477 return (PICL_WALK_TERMINATE); 3478 } 3479 3480 /* 3481 * display the OBP and POST prom revisions 3482 */ 3483 /* ARGSUSED */ 3484 static int 3485 flashprom_callback(picl_nodehdl_t flashpromh, void *arg) 3486 { 3487 picl_prophdl_t proph; 3488 picl_prophdl_t tblh; 3489 picl_prophdl_t rowproph; 3490 picl_propinfo_t pinfo; 3491 char *prom_version = NULL; 3492 char *obp_version = NULL; 3493 int err; 3494 3495 err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION, 3496 &pinfo, &proph); 3497 if (err == PICL_PROPNOTFOUND) 3498 return (PICL_WALK_TERMINATE); 3499 else if (err != PICL_SUCCESS) 3500 return (err); 3501 3502 log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n")); 3503 log_printf("----------------------\n"); 3504 3505 /* 3506 * If it's a table prop, the first element is OBP revision 3507 * The second one is POST revision. 3508 * If it's a charstring prop, the value will be only OBP revision 3509 */ 3510 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 3511 prom_version = alloca(pinfo.size); 3512 if (prom_version == NULL) 3513 return (PICL_FAILURE); 3514 err = picl_get_propval(proph, prom_version, pinfo.size); 3515 if (err != PICL_SUCCESS) 3516 return (err); 3517 log_printf("%s\n", prom_version); 3518 } 3519 3520 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 3521 return (PICL_WALK_TERMINATE); 3522 3523 err = picl_get_propval(proph, &tblh, pinfo.size); 3524 if (err != PICL_SUCCESS) 3525 return (err); 3526 3527 err = picl_get_next_by_row(tblh, &rowproph); 3528 if (err == PICL_SUCCESS) { 3529 /* get first row */ 3530 err = picl_get_propinfo(rowproph, &pinfo); 3531 if (err != PICL_SUCCESS) 3532 return (err); 3533 3534 prom_version = alloca(pinfo.size); 3535 if (prom_version == NULL) 3536 return (PICL_FAILURE); 3537 3538 err = picl_get_propval(rowproph, prom_version, pinfo.size); 3539 if (err != PICL_SUCCESS) 3540 return (err); 3541 log_printf("%s\n", prom_version); 3542 3543 /* get second row */ 3544 err = picl_get_next_by_col(rowproph, &rowproph); 3545 if (err == PICL_SUCCESS) { 3546 err = picl_get_propinfo(rowproph, &pinfo); 3547 if (err != PICL_SUCCESS) 3548 return (err); 3549 3550 obp_version = alloca(pinfo.size); 3551 if (obp_version == NULL) 3552 return (PICL_FAILURE); 3553 err = picl_get_propval(rowproph, obp_version, 3554 pinfo.size); 3555 if (err != PICL_SUCCESS) 3556 return (err); 3557 log_printf("%s\n", obp_version); 3558 } 3559 } 3560 3561 return (PICL_WALK_TERMINATE); 3562 } 3563 3564 static int 3565 display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth) 3566 { 3567 int err; 3568 picl_nodehdl_t plafh; 3569 picl_nodehdl_t frutreeh; 3570 3571 err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh); 3572 if (err != PICL_SUCCESS) 3573 return (err); 3574 3575 if (!log_flag) { 3576 err = display_platform_banner(plafh); 3577 if (err != PICL_SUCCESS) 3578 return (err); 3579 3580 err = display_system_clock(plafh); 3581 if (err != PICL_SUCCESS) 3582 return (err); 3583 3584 err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY, 3585 PICL_CLASS_MEMORY, memory_callback); 3586 if (err != PICL_SUCCESS) 3587 return (err); 3588 3589 err = display_cpu_info(plafh); 3590 if (err != PICL_SUCCESS) 3591 return (err); 3592 3593 err = display_io_device_info(plafh); 3594 if (err != PICL_SUCCESS) 3595 return (err); 3596 3597 err = display_memory_config(plafh); 3598 if (err != PICL_SUCCESS) 3599 return (err); 3600 3601 err = display_usb_devices(plafh); 3602 if (err != PICL_SUCCESS) 3603 return (err); 3604 } 3605 3606 if (serrlog) { 3607 err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS, 3608 NULL, options_callback); 3609 if (err != PICL_SUCCESS) 3610 return (err); 3611 3612 err = display_envctrl_status(plafh); 3613 if (err != PICL_SUCCESS) 3614 return (err); 3615 3616 err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE, 3617 &frutreeh); 3618 if (err != PICL_SUCCESS) 3619 return (err); 3620 3621 err = display_fru_oper_status(frutreeh); 3622 if (err != PICL_SUCCESS) 3623 return (err); 3624 3625 err = display_hw_revisions(plafh); 3626 if (err != PICL_SUCCESS) 3627 return (err); 3628 3629 err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM, 3630 NULL, flashprom_callback); 3631 if (err != PICL_SUCCESS) 3632 return (err); 3633 3634 err = display_serial_number(plafh); 3635 if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 3636 return (err); 3637 } 3638 3639 return (PICL_SUCCESS); 3640 } 3641 3642 /* 3643 * do_prominfo is called from main in prtdiag. It returns PD_SYSTEM_FAILURE if 3644 * any system failure is detected, PD_INTERNAL_FAILURE for internal errors and 3645 * PD_SUCCESS otherwise. main uses the return value as the exit code. 3646 */ 3647 /* ARGSUSED */ 3648 int 3649 do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag) 3650 { 3651 int err; 3652 char *errstr; 3653 int done; 3654 picl_nodehdl_t rooth; 3655 3656 err = picl_initialize(); 3657 if (err != PICL_SUCCESS) { 3658 fprintf(stderr, EM_INIT_FAIL, picl_strerror(err)); 3659 return (PD_INTERNAL_FAILURE); 3660 } 3661 3662 do { 3663 done = 1; 3664 err = picl_get_root(&rooth); 3665 if (err != PICL_SUCCESS) { 3666 fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err)); 3667 return (PD_INTERNAL_FAILURE); 3668 } 3669 3670 err = display_system_info(serrlog, log_flag, rooth); 3671 3672 if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE)) 3673 done = 0; 3674 } while (!done); 3675 3676 if (err != PICL_SUCCESS) { 3677 errstr = picl_strerror(err); 3678 fprintf(stderr, EM_PRTDIAG_FAIL); 3679 fprintf(stderr, "%s\n", errstr? errstr : " "); 3680 exit_code = PD_INTERNAL_FAILURE; 3681 } 3682 3683 (void) picl_shutdown(); 3684 3685 return (exit_code); 3686 } 3687