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