17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 594bc7577Sps154918 * Common Development and Distribution License (the "License"). 694bc7577Sps154918 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22f3af4981Sdt207653 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <alloca.h> 297c478bd9Sstevel@tonic-gate #include <assert.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 317c478bd9Sstevel@tonic-gate #include <libintl.h> 327c478bd9Sstevel@tonic-gate #include <stdarg.h> 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 36f3af4981Sdt207653 #include <ctype.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include "fru_tag.h" 397c478bd9Sstevel@tonic-gate #include "libfrup.h" 407c478bd9Sstevel@tonic-gate #include "libfrureg.h" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #define NUM_ITER_BYTES 4 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #define HEAD_ITER 0 467c478bd9Sstevel@tonic-gate #define TAIL_ITER 1 /* not used */ 477c478bd9Sstevel@tonic-gate #define NUM_ITER 2 487c478bd9Sstevel@tonic-gate #define MAX_ITER 3 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define INDENT 3 517c478bd9Sstevel@tonic-gate #define TIMESTRINGLEN 128 5294bc7577Sps154918 #define TEMPERATURE_OFFSET 73 53*5bc0fc0eSdt207653 #define MIN_VERSION 17 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static void (*print_node)(fru_node_t fru_type, const char *path, 567c478bd9Sstevel@tonic-gate const char *name, end_node_fp_t *end_node, 577c478bd9Sstevel@tonic-gate void **end_args); 587c478bd9Sstevel@tonic-gate 59f3af4981Sdt207653 static void print_element(const uint8_t *data, const fru_regdef_t *def, 60f3af4981Sdt207653 const char *parent_path, int indent); 61f3af4981Sdt207653 627c478bd9Sstevel@tonic-gate static char tagname[sizeof ("?_0123456789_0123456789_0123456789")]; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static int containers_only = 0, list_only = 0, saved_status = 0, xml = 0; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static FILE *errlog; 677c478bd9Sstevel@tonic-gate 68f3af4981Sdt207653 int iterglobal = 0; 69f3af4981Sdt207653 int FMAmessageR = -1; 7046a7ef8aSdt207653 int Fault_Install_DataR_flag = 0; 7146a7ef8aSdt207653 int Power_On_DataR_flag = 0; 72*5bc0fc0eSdt207653 int spd_memtype = 0; 73*5bc0fc0eSdt207653 int spd_revision = 0; 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * Definition for data elements found in devices but not found in 767c478bd9Sstevel@tonic-gate * the system's version of libfrureg 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate static fru_regdef_t unknown = { 797c478bd9Sstevel@tonic-gate REGDEF_VERSION, 807c478bd9Sstevel@tonic-gate tagname, 817c478bd9Sstevel@tonic-gate -1, 827c478bd9Sstevel@tonic-gate -1, 837c478bd9Sstevel@tonic-gate -1, 847c478bd9Sstevel@tonic-gate -1, 857c478bd9Sstevel@tonic-gate FDTYPE_ByteArray, 867c478bd9Sstevel@tonic-gate FDISP_Hex, 877c478bd9Sstevel@tonic-gate FRU_WHICH_UNDEFINED, 887c478bd9Sstevel@tonic-gate FRU_WHICH_UNDEFINED, 897c478bd9Sstevel@tonic-gate 0, 907c478bd9Sstevel@tonic-gate NULL, 917c478bd9Sstevel@tonic-gate 0, 927c478bd9Sstevel@tonic-gate FRU_NOT_ITERATED, 937c478bd9Sstevel@tonic-gate NULL 947c478bd9Sstevel@tonic-gate }; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * Write message to standard error and possibly the error log buffer 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate static void 1017c478bd9Sstevel@tonic-gate error(const char *format, ...) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate va_list args; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* make relevant output appear before error message */ 1077c478bd9Sstevel@tonic-gate if (fflush(stdout) == EOF) { 1087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Error flushing output: %s\n", 1097c478bd9Sstevel@tonic-gate strerror(errno)); 1107c478bd9Sstevel@tonic-gate exit(1); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate va_start(args, format); 1147c478bd9Sstevel@tonic-gate if (vfprintf(stderr, format, args) < 0) exit(1); 1157c478bd9Sstevel@tonic-gate if (errlog && (vfprintf(errlog, format, args) < 0)) exit(1); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * Write message to standard output 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate static void 1227c478bd9Sstevel@tonic-gate output(const char *format, ...) 1237c478bd9Sstevel@tonic-gate { 1247c478bd9Sstevel@tonic-gate va_list args; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate va_start(args, format); 1287c478bd9Sstevel@tonic-gate if (vfprintf(stdout, format, args) < 0) { 1297c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1307c478bd9Sstevel@tonic-gate strerror(errno)); 1317c478bd9Sstevel@tonic-gate exit(1); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Safe wrapper for putchar() 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate static void 1397c478bd9Sstevel@tonic-gate voidputchar(int c) 1407c478bd9Sstevel@tonic-gate { 1417c478bd9Sstevel@tonic-gate if (putchar(c) == EOF) { 1427c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1437c478bd9Sstevel@tonic-gate strerror(errno)); 1447c478bd9Sstevel@tonic-gate exit(1); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate static void (*safeputchar)(int c) = voidputchar; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * Safe wrapper for puts() 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate static void 1547c478bd9Sstevel@tonic-gate voidputs(const char *s) 1557c478bd9Sstevel@tonic-gate { 1567c478bd9Sstevel@tonic-gate if (fputs(s, stdout) == EOF) { 1577c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1587c478bd9Sstevel@tonic-gate strerror(errno)); 1597c478bd9Sstevel@tonic-gate exit(1); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate static void (*safeputs)(const char *s) = voidputs; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * XML-safe wrapper for putchar(): quotes XML-special characters 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate static void 1697c478bd9Sstevel@tonic-gate xputchar(int c) 1707c478bd9Sstevel@tonic-gate { 1717c478bd9Sstevel@tonic-gate switch (c) { 1727c478bd9Sstevel@tonic-gate case '<': 1737c478bd9Sstevel@tonic-gate c = fputs("<", stdout); 1747c478bd9Sstevel@tonic-gate break; 1757c478bd9Sstevel@tonic-gate case '>': 1767c478bd9Sstevel@tonic-gate c = fputs(">", stdout); 1777c478bd9Sstevel@tonic-gate break; 1787c478bd9Sstevel@tonic-gate case '&': 1797c478bd9Sstevel@tonic-gate c = fputs("&", stdout); 1807c478bd9Sstevel@tonic-gate break; 1817c478bd9Sstevel@tonic-gate case '"': 1827c478bd9Sstevel@tonic-gate c = fputs(""", stdout); 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate default: 1857c478bd9Sstevel@tonic-gate c = putchar(c); 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (c == EOF) { 1907c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1917c478bd9Sstevel@tonic-gate strerror(errno)); 1927c478bd9Sstevel@tonic-gate exit(1); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * XML-safe analog of puts(): quotes XML-special characters 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate static void 2007c478bd9Sstevel@tonic-gate xputs(const char *s) 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate char c; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate for (/* */; ((c = *s) != 0); s++) 2057c478bd9Sstevel@tonic-gate xputchar(c); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Output the XML DTD derived from the registry provided by libfrureg 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate int 2127c478bd9Sstevel@tonic-gate output_dtd(void) 2137c478bd9Sstevel@tonic-gate { 2147c478bd9Sstevel@tonic-gate char **element; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate unsigned int i, j, num_elements = 0; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate uint8_t *tagged; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate const fru_regdef_t *def; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if (((element = fru_reg_list_entries(&num_elements)) == NULL) || 2247c478bd9Sstevel@tonic-gate (num_elements == 0)) { 2257c478bd9Sstevel@tonic-gate error(gettext("No FRU ID Registry elements")); 2267c478bd9Sstevel@tonic-gate return (1); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate if ((tagged = calloc(num_elements, sizeof (*tagged))) == NULL) { 2307c478bd9Sstevel@tonic-gate error(gettext("Unable to get memory for tagged element list"), 2317c478bd9Sstevel@tonic-gate strerror(errno)); 2327c478bd9Sstevel@tonic-gate return (1); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /* 2367c478bd9Sstevel@tonic-gate * Output the DTD preamble 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate output("<!ELEMENT FRUID_XML_Tree (Parameter*, " 2397c478bd9Sstevel@tonic-gate "(Fru | Location | Container)*,\n" 2407c478bd9Sstevel@tonic-gate " Parameter*, ErrorLog?, Parameter*)>\n" 2417c478bd9Sstevel@tonic-gate "<!ATTLIST FRUID_XML_Tree>\n" 2427c478bd9Sstevel@tonic-gate "\n" 2437c478bd9Sstevel@tonic-gate "<!ELEMENT Parameter EMPTY>\n" 2447c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter type CDATA #REQUIRED>\n" 2457c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter name CDATA #REQUIRED>\n" 2467c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter value CDATA #REQUIRED>\n" 2477c478bd9Sstevel@tonic-gate "\n" 2487c478bd9Sstevel@tonic-gate "<!ELEMENT Fru (Fru | Location | Container)*>\n" 2497c478bd9Sstevel@tonic-gate "<!ATTLIST Fru name CDATA #REQUIRED>\n" 2507c478bd9Sstevel@tonic-gate "\n" 2517c478bd9Sstevel@tonic-gate "<!ELEMENT Location (Fru | Location | Container)*>\n" 25294bc7577Sps154918 "<!ATTLIST Location\n" 25394bc7577Sps154918 " name CDATA #IMPLIED\n" 25494bc7577Sps154918 " value CDATA #IMPLIED\n" 25594bc7577Sps154918 ">\n" 2567c478bd9Sstevel@tonic-gate "\n" 2577c478bd9Sstevel@tonic-gate "<!ELEMENT Container (ContainerData?, " 2587c478bd9Sstevel@tonic-gate "(Fru | Location | Container)*)>\n" 2597c478bd9Sstevel@tonic-gate "<!ATTLIST Container name CDATA #REQUIRED>\n" 2607c478bd9Sstevel@tonic-gate "<!ATTLIST Container imagefile CDATA #IMPLIED>\n" 2617c478bd9Sstevel@tonic-gate "\n" 2627c478bd9Sstevel@tonic-gate "<!ELEMENT ContainerData (Segment*)>\n" 2637c478bd9Sstevel@tonic-gate "<!ATTLIST ContainerData>\n" 2647c478bd9Sstevel@tonic-gate "\n" 2657c478bd9Sstevel@tonic-gate "<!ATTLIST Segment name CDATA #REQUIRED>\n" 2667c478bd9Sstevel@tonic-gate "\n" 2677c478bd9Sstevel@tonic-gate "<!ELEMENT Index EMPTY>\n" 2687c478bd9Sstevel@tonic-gate "<!ATTLIST Index value CDATA #REQUIRED>\n" 2697c478bd9Sstevel@tonic-gate "\n" 2707c478bd9Sstevel@tonic-gate "<!ELEMENT ErrorLog (#PCDATA)>\n" 2717c478bd9Sstevel@tonic-gate "<!ATTLIST ErrorLog>\n" 2727c478bd9Sstevel@tonic-gate "\n"); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Output the definition for each element 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate for (i = 0; i < num_elements; i++) { 2787c478bd9Sstevel@tonic-gate assert(element[i] != NULL); 27994bc7577Sps154918 /* Prevent incompatible duplicate defn. from FRUID Registry. */ 28094bc7577Sps154918 if ((strcmp("Location", element[i])) == 0) continue; 2817c478bd9Sstevel@tonic-gate if ((def = fru_reg_lookup_def_by_name(element[i])) == NULL) { 2827c478bd9Sstevel@tonic-gate error(gettext("Error looking up registry " 2837c478bd9Sstevel@tonic-gate "definition for \"%s\"\n"), 2847c478bd9Sstevel@tonic-gate element[i]); 2857c478bd9Sstevel@tonic-gate return (1); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate if (def->tagType != FRU_X) tagged[i] = 1; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Record) { 2917c478bd9Sstevel@tonic-gate if (def->iterationType == FRU_NOT_ITERATED) 2927c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (%s", element[i], 2937c478bd9Sstevel@tonic-gate def->enumTable[0].text); 2947c478bd9Sstevel@tonic-gate else 2957c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (Index_%s*)>\n" 2967c478bd9Sstevel@tonic-gate "<!ATTLIST Index_%s>\n" 2977c478bd9Sstevel@tonic-gate "<!ELEMENT Index_%s (%s", 2987c478bd9Sstevel@tonic-gate element[i], element[i], element[i], 2997c478bd9Sstevel@tonic-gate element[i], def->enumTable[0].text); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate for (j = 1; j < def->enumCount; j++) 3027c478bd9Sstevel@tonic-gate output(",\n\t%s", def->enumTable[j].text); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate output(")>\n"); 3057c478bd9Sstevel@tonic-gate } else if (def->iterationType == FRU_NOT_ITERATED) { 3067c478bd9Sstevel@tonic-gate output("<!ELEMENT %s EMPTY>\n" 3077c478bd9Sstevel@tonic-gate "<!ATTLIST %s value CDATA #REQUIRED>\n", 3087c478bd9Sstevel@tonic-gate element[i], element[i]); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Enumeration) { 3117c478bd9Sstevel@tonic-gate output("<!-- %s valid enumeration values\n"); 3127c478bd9Sstevel@tonic-gate for (j = 0; j < def->enumCount; j++) { 3137c478bd9Sstevel@tonic-gate output("\t\""); 3147c478bd9Sstevel@tonic-gate xputs(def->enumTable[j].text); 3157c478bd9Sstevel@tonic-gate output("\"\n"); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate output("-->\n"); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate else 3217c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (Index*)>\n", element[i]); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate output("\n"); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* Provide for returning the tag for an "unknown" element */ 3277c478bd9Sstevel@tonic-gate output("<!ATTLIST UNKNOWN tag CDATA \"UNKNOWN\">\n\n"); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * List all data elements as possible members of "Segment" 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate output("<!ELEMENT Segment ((UNKNOWN"); 3347c478bd9Sstevel@tonic-gate for (i = 0; i < num_elements; i++) { 3357c478bd9Sstevel@tonic-gate if (tagged[i]) output("\n\t| %s", element[i]); 3367c478bd9Sstevel@tonic-gate free(element[i]); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate output(")*)>\n"); 3397c478bd9Sstevel@tonic-gate free(element); 3407c478bd9Sstevel@tonic-gate free(tagged); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate return (0); 3437c478bd9Sstevel@tonic-gate } 344f3af4981Sdt207653 /* 345f3af4981Sdt207653 * Function to convert bcd to binary to correct the SPD_Manufacturer_Week 346f3af4981Sdt207653 * 347f3af4981Sdt207653 */ 348f3af4981Sdt207653 static void convertbcdtobinary(int *val) 349f3af4981Sdt207653 { 350*5bc0fc0eSdt207653 unsigned int newval = (unsigned int)*val, tmpval = 0; 351*5bc0fc0eSdt207653 while (newval > 0) { 352*5bc0fc0eSdt207653 tmpval = (tmpval << 4) | (newval & 0xF); 353*5bc0fc0eSdt207653 newval >>= 4; 354*5bc0fc0eSdt207653 } 355*5bc0fc0eSdt207653 while (tmpval > 0) { 356*5bc0fc0eSdt207653 newval = (newval * 10) + (tmpval & 0xF); 357*5bc0fc0eSdt207653 tmpval >>= 4; 358f3af4981Sdt207653 } 359f3af4981Sdt207653 *val = newval; 360f3af4981Sdt207653 } 361f3af4981Sdt207653 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Safely pretty-print the value of a field 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate static void 3677c478bd9Sstevel@tonic-gate print_field(const uint8_t *field, const fru_regdef_t *def) 3687c478bd9Sstevel@tonic-gate { 369f3af4981Sdt207653 char *errmsg = NULL, timestring[TIMESTRINGLEN], path[16384]; 3707c478bd9Sstevel@tonic-gate 371f3af4981Sdt207653 int i, valueint; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate uint64_t value; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate time_t timefield; 3767c478bd9Sstevel@tonic-gate 377f3af4981Sdt207653 struct tm *tm; 3787c478bd9Sstevel@tonic-gate 379f3af4981Sdt207653 uchar_t first_byte, data[128]; 380f3af4981Sdt207653 381f3af4981Sdt207653 const fru_regdef_t *new_def; 382f3af4981Sdt207653 383f3af4981Sdt207653 const char *elem_name = NULL; 384f3af4981Sdt207653 const char *parent_path; 3857c478bd9Sstevel@tonic-gate switch (def->dataType) { 3867c478bd9Sstevel@tonic-gate case FDTYPE_Binary: 3877c478bd9Sstevel@tonic-gate assert(def->payloadLen <= sizeof (value)); 3887c478bd9Sstevel@tonic-gate switch (def->dispType) { 3897c478bd9Sstevel@tonic-gate case FDISP_Binary: 3907c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen; i++) 3917c478bd9Sstevel@tonic-gate output("%c%c%c%c%c%c%c%c", 3927c478bd9Sstevel@tonic-gate ((field[i] & 0x80) ? '1' : '0'), 3937c478bd9Sstevel@tonic-gate ((field[i] & 0x40) ? '1' : '0'), 3947c478bd9Sstevel@tonic-gate ((field[i] & 0x20) ? '1' : '0'), 3957c478bd9Sstevel@tonic-gate ((field[i] & 0x10) ? '1' : '0'), 3967c478bd9Sstevel@tonic-gate ((field[i] & 0x08) ? '1' : '0'), 3977c478bd9Sstevel@tonic-gate ((field[i] & 0x04) ? '1' : '0'), 3987c478bd9Sstevel@tonic-gate ((field[i] & 0x02) ? '1' : '0'), 3997c478bd9Sstevel@tonic-gate ((field[i] & 0x01) ? '1' : '0')); 4007c478bd9Sstevel@tonic-gate return; 4017c478bd9Sstevel@tonic-gate case FDISP_Octal: 4027c478bd9Sstevel@tonic-gate case FDISP_Decimal: 4037c478bd9Sstevel@tonic-gate value = 0; 404f3af4981Sdt207653 valueint = 0; 4057c478bd9Sstevel@tonic-gate (void) memcpy((((uint8_t *)&value) + 4067c478bd9Sstevel@tonic-gate sizeof (value) - def->payloadLen), 4077c478bd9Sstevel@tonic-gate field, def->payloadLen); 40894bc7577Sps154918 if ((value != 0) && 409f3af4981Sdt207653 (strcmp(def->name, "SPD_Manufacture_Week") == 0)) { 410f3af4981Sdt207653 valueint = (int)value; 411*5bc0fc0eSdt207653 if (spd_memtype && spd_revision) { 412f3af4981Sdt207653 convertbcdtobinary(&valueint); 413*5bc0fc0eSdt207653 spd_memtype = 0; 414*5bc0fc0eSdt207653 spd_revision = 0; 415*5bc0fc0eSdt207653 } 416f3af4981Sdt207653 output("%d", valueint); 417f3af4981Sdt207653 return; 418f3af4981Sdt207653 } 419f3af4981Sdt207653 if ((value != 0) && 42094bc7577Sps154918 ((strcmp(def->name, "Lowest") == 0) || 42194bc7577Sps154918 (strcmp(def->name, "Highest") == 0) || 42294bc7577Sps154918 (strcmp(def->name, "Latest") == 0))) 4231e3549a6Sps154918 output((def->dispType == FDISP_Octal) ? 4241e3549a6Sps154918 "%llo" : "%lld (%lld degrees C)", 4251e3549a6Sps154918 value, (value - TEMPERATURE_OFFSET)); 4261e3549a6Sps154918 else 4277c478bd9Sstevel@tonic-gate output((def->dispType == FDISP_Octal) ? 4287c478bd9Sstevel@tonic-gate "%llo" : "%lld", value); 4297c478bd9Sstevel@tonic-gate return; 4307c478bd9Sstevel@tonic-gate case FDISP_Time: 4317c478bd9Sstevel@tonic-gate if (def->payloadLen > sizeof (timefield)) { 4327c478bd9Sstevel@tonic-gate errmsg = "time value too large for formatting"; 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate } 435f3af4981Sdt207653 timefield = 0; 436f3af4981Sdt207653 (void) memcpy((((uint8_t *)&timefield) + 437f3af4981Sdt207653 sizeof (timefield) - def->payloadLen), 438f3af4981Sdt207653 field, def->payloadLen); 439f3af4981Sdt207653 if (timefield == 0) { 440f3af4981Sdt207653 errmsg = "No Value Recorded"; 441f3af4981Sdt207653 break; 442f3af4981Sdt207653 } 443f3af4981Sdt207653 if ((tm = localtime(&timefield)) == NULL) { 444f3af4981Sdt207653 errmsg = "cannot convert time value"; 445f3af4981Sdt207653 break; 446f3af4981Sdt207653 } 447f3af4981Sdt207653 if (strftime(timestring, sizeof (timestring), "%C", tm) 448f3af4981Sdt207653 == 0) { 4497c478bd9Sstevel@tonic-gate errmsg = "formatted time would overflow buffer"; 4507c478bd9Sstevel@tonic-gate break; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate safeputs(timestring); 4537c478bd9Sstevel@tonic-gate return; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate break; 4567c478bd9Sstevel@tonic-gate case FDTYPE_ASCII: 457f3af4981Sdt207653 if (!xml) { 458f3af4981Sdt207653 if (strcmp(def->name, "Message") == 0) { 459f3af4981Sdt207653 if (FMAmessageR == 0) 460f3af4981Sdt207653 elem_name = "FMA_Event_DataR"; 461f3af4981Sdt207653 else if (FMAmessageR == 1) 462f3af4981Sdt207653 elem_name = "FMA_MessageR"; 463f3af4981Sdt207653 if (elem_name != NULL) { 464f3af4981Sdt207653 (void) memcpy(data, field, 465f3af4981Sdt207653 def->payloadLen); 466f3af4981Sdt207653 new_def = 46746a7ef8aSdt207653 fru_reg_lookup_def_by_name 46846a7ef8aSdt207653 (elem_name); 469aad09a1cSdt207653 (void) snprintf(path, sizeof (path), 470f3af4981Sdt207653 "/Status_EventsR[%d]/Message(FMA)", 471f3af4981Sdt207653 iterglobal); 472f3af4981Sdt207653 parent_path = path; 473f3af4981Sdt207653 output("\n"); 474f3af4981Sdt207653 print_element(data, new_def, 475f3af4981Sdt207653 parent_path, 2*INDENT); 476f3af4981Sdt207653 return; 477f3af4981Sdt207653 } 478f3af4981Sdt207653 } 479f3af4981Sdt207653 } 4807c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen && field[i]; i++) 4817c478bd9Sstevel@tonic-gate safeputchar(field[i]); 4827c478bd9Sstevel@tonic-gate return; 4837c478bd9Sstevel@tonic-gate case FDTYPE_Enumeration: 4847c478bd9Sstevel@tonic-gate value = 0; 4857c478bd9Sstevel@tonic-gate (void) memcpy((((uint8_t *)&value) + sizeof (value) 4867c478bd9Sstevel@tonic-gate - def->payloadLen), 4877c478bd9Sstevel@tonic-gate field, def->payloadLen); 4887c478bd9Sstevel@tonic-gate for (i = 0; i < def->enumCount; i++) 4897c478bd9Sstevel@tonic-gate if (def->enumTable[i].value == value) { 490f3af4981Sdt207653 if (strcmp(def->name, "Event_Code") == 0) { 491f3af4981Sdt207653 if (strcmp(def->enumTable[i].text, 492f3af4981Sdt207653 "FMA Message R") == 0) 493f3af4981Sdt207653 FMAmessageR = 1; 494f3af4981Sdt207653 else 495f3af4981Sdt207653 if (strcmp(def->enumTable[i].text, 496f3af4981Sdt207653 "FMA Event Data R") == 0) 497f3af4981Sdt207653 FMAmessageR = 0; 498f3af4981Sdt207653 } 499*5bc0fc0eSdt207653 if (strcmp(def->name, 500*5bc0fc0eSdt207653 "SPD_Fundamental_Memory_Type") == 0) { 501*5bc0fc0eSdt207653 if (strcmp(def->enumTable[i].text, 502*5bc0fc0eSdt207653 "DDR II SDRAM") == 0) 503*5bc0fc0eSdt207653 spd_memtype = 1; 504*5bc0fc0eSdt207653 } 5057c478bd9Sstevel@tonic-gate safeputs(def->enumTable[i].text); 5067c478bd9Sstevel@tonic-gate return; 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate errmsg = "unrecognized value"; 5107c478bd9Sstevel@tonic-gate break; 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate /* If nothing matched above, print the field in hex */ 514f3af4981Sdt207653 switch (def->dispType) { 515f3af4981Sdt207653 case FDISP_MSGID: 516f3af4981Sdt207653 (void) memcpy((uchar_t *)&first_byte, field, 1); 517f3af4981Sdt207653 if (isprint(first_byte)) { 518f3af4981Sdt207653 for (i = 0; i < def->payloadLen && field[i]; 519f3af4981Sdt207653 i++) 520f3af4981Sdt207653 safeputchar(field[i]); 521f3af4981Sdt207653 } 522f3af4981Sdt207653 break; 523f3af4981Sdt207653 case FDISP_UUID: 524f3af4981Sdt207653 for (i = 0; i < def->payloadLen; i++) { 525f3af4981Sdt207653 if ((i == 4) || (i == 6) || 526f3af4981Sdt207653 (i == 8) || (i == 10)) 527f3af4981Sdt207653 output("-"); 528f3af4981Sdt207653 output("%2.2x", field[i]); 529f3af4981Sdt207653 } 530f3af4981Sdt207653 break; 531f3af4981Sdt207653 default: 532*5bc0fc0eSdt207653 if (strcmp(def->name, 533*5bc0fc0eSdt207653 "SPD_Data_Revision_Code") == 0) { 534*5bc0fc0eSdt207653 value = 0; 535*5bc0fc0eSdt207653 valueint = 0; 536*5bc0fc0eSdt207653 (void) memcpy((((uint8_t *)&value) 537*5bc0fc0eSdt207653 + sizeof (value) - def->payloadLen), 538*5bc0fc0eSdt207653 field, def->payloadLen); 539*5bc0fc0eSdt207653 valueint = (int)value; 540*5bc0fc0eSdt207653 if ((valueint >= MIN_VERSION) && (spd_memtype)) 541*5bc0fc0eSdt207653 spd_revision = 1; 542*5bc0fc0eSdt207653 } 5437c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen; i++) 5447c478bd9Sstevel@tonic-gate output("%2.2X", field[i]); 545f3af4981Sdt207653 break; 546f3af4981Sdt207653 } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* Safely print any error message associated with the field */ 5497c478bd9Sstevel@tonic-gate if (errmsg) { 550f3af4981Sdt207653 if (strcmp(def->name, "Fault_Diag_Secs") != 0) { 5517c478bd9Sstevel@tonic-gate output(" ("); 5527c478bd9Sstevel@tonic-gate safeputs(errmsg); 553f3af4981Sdt207653 output(")"); 554f3af4981Sdt207653 } 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* 5597c478bd9Sstevel@tonic-gate * Recursively print the contents of a data element 5607c478bd9Sstevel@tonic-gate */ 5617c478bd9Sstevel@tonic-gate static void 5627c478bd9Sstevel@tonic-gate print_element(const uint8_t *data, const fru_regdef_t *def, 5637c478bd9Sstevel@tonic-gate const char *parent_path, int indent) 5647c478bd9Sstevel@tonic-gate { 5657c478bd9Sstevel@tonic-gate char *path; 5667c478bd9Sstevel@tonic-gate size_t len; 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate int bytes = 0, i; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate indent = (xml) ? (indent + INDENT) : (2*INDENT); 57246a7ef8aSdt207653 if (strcmp(def->name, "Sun_SPD_DataR") == 0) { 57346a7ef8aSdt207653 Fault_Install_DataR_flag = indent; 57446a7ef8aSdt207653 Power_On_DataR_flag = indent; 57546a7ef8aSdt207653 } 5767c478bd9Sstevel@tonic-gate /* 5777c478bd9Sstevel@tonic-gate * Construct the path, or, for XML, the name, for the current 5787c478bd9Sstevel@tonic-gate * data element 5797c478bd9Sstevel@tonic-gate */ 5807c478bd9Sstevel@tonic-gate if ((def->iterationCount == 0) && 5817c478bd9Sstevel@tonic-gate (def->iterationType != FRU_NOT_ITERATED)) { 5827c478bd9Sstevel@tonic-gate if (xml) { 5837c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Record) { 5847c478bd9Sstevel@tonic-gate len = strlen("Index_") + strlen(def->name) + 1; 5857c478bd9Sstevel@tonic-gate path = alloca(len); 5867c478bd9Sstevel@tonic-gate (void) snprintf(path, len, 5877c478bd9Sstevel@tonic-gate "Index_%s", def->name); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate else 5907c478bd9Sstevel@tonic-gate path = "Index"; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate else 5937c478bd9Sstevel@tonic-gate path = (char *)parent_path; 5947c478bd9Sstevel@tonic-gate } else { 5957c478bd9Sstevel@tonic-gate if (xml) 5967c478bd9Sstevel@tonic-gate path = (char *)def->name; 5977c478bd9Sstevel@tonic-gate else { 5987c478bd9Sstevel@tonic-gate len = strlen(parent_path) + sizeof ("/") + 5997c478bd9Sstevel@tonic-gate strlen(def->name) + 6007c478bd9Sstevel@tonic-gate (def->iterationCount ? sizeof ("[255]") : 0); 6017c478bd9Sstevel@tonic-gate path = alloca(len); 6027c478bd9Sstevel@tonic-gate bytes = snprintf(path, len, 6037c478bd9Sstevel@tonic-gate "%s/%s", parent_path, def->name); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 60746a7ef8aSdt207653 if ((Fault_Install_DataR_flag) && 60846a7ef8aSdt207653 (strcmp(path, "E_1_46") == 0) || (strcmp(path, "/E_1_46") == 0)) { 60946a7ef8aSdt207653 int cnt; 61046a7ef8aSdt207653 char timestring[128]; 61146a7ef8aSdt207653 time_t timefield = 0; 61246a7ef8aSdt207653 struct tm *tm; 61346a7ef8aSdt207653 indent = Fault_Install_DataR_flag; 61446a7ef8aSdt207653 (void) memcpy((uint8_t *)&timefield, data, 4); 61546a7ef8aSdt207653 if (timefield == 0) { 61646a7ef8aSdt207653 (void) sprintf(timestring, 61746a7ef8aSdt207653 "00000000 (No Value Recorded)\""); 61846a7ef8aSdt207653 } else { 61946a7ef8aSdt207653 if ((tm = localtime(&timefield)) == NULL) 62046a7ef8aSdt207653 (void) sprintf(timestring, 62146a7ef8aSdt207653 "cannot convert time value"); 62246a7ef8aSdt207653 if (strftime(timestring, 62346a7ef8aSdt207653 sizeof (timestring), "%C", tm) == 0) 62446a7ef8aSdt207653 (void) sprintf(timestring, 62546a7ef8aSdt207653 "formatted time would overflow buffer"); 62646a7ef8aSdt207653 } 62746a7ef8aSdt207653 if (xml) { 62846a7ef8aSdt207653 (void) sprintf(path, "Fault_Install_DataR"); 62946a7ef8aSdt207653 output("%*s<%s>\n", indent, "", path); 63046a7ef8aSdt207653 indent = Fault_Install_DataR_flag + INDENT; 63146a7ef8aSdt207653 (void) sprintf(path, "UNIX_Timestamp32"); 63246a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 63346a7ef8aSdt207653 /*CSTYLED*/ 63446a7ef8aSdt207653 output("%s\"/>\n", timestring); 63546a7ef8aSdt207653 (void) sprintf(path, "MACADDR"); 63646a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 63746a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 6; cnt++) { 63846a7ef8aSdt207653 output("%2.2x", data[cnt]); 63946a7ef8aSdt207653 if (cnt < 4 + 6 - 1) 64046a7ef8aSdt207653 output(":"); 64146a7ef8aSdt207653 } 64246a7ef8aSdt207653 /*CSTYLED*/ 64346a7ef8aSdt207653 output("\"/>\n"); 64446a7ef8aSdt207653 (void) sprintf(path, "Status"); 64546a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 64646a7ef8aSdt207653 /*CSTYLED*/ 64746a7ef8aSdt207653 output("%2.2x\"/>\n", data[10]); 64846a7ef8aSdt207653 (void) sprintf(path, "Initiator"); 64946a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 65046a7ef8aSdt207653 /*CSTYLED*/ 65146a7ef8aSdt207653 output("%2.2x\"/>\n", data[11]); 65246a7ef8aSdt207653 (void) sprintf(path, "Message_Type"); 65346a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 65446a7ef8aSdt207653 /*CSTYLED*/ 65546a7ef8aSdt207653 output("%2.2x\"/>\n", data[12]); 65646a7ef8aSdt207653 (void) sprintf(path, "Message_32"); 65746a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 65846a7ef8aSdt207653 for (cnt = 13; cnt < 13 + 32; cnt++) 65946a7ef8aSdt207653 output("%2.2x", data[cnt]); 66046a7ef8aSdt207653 /*CSTYLED*/ 66146a7ef8aSdt207653 output("\"/>\n"); 66246a7ef8aSdt207653 indent = Fault_Install_DataR_flag; 66346a7ef8aSdt207653 (void) sprintf(path, "Fault_Install_DataR"); 66446a7ef8aSdt207653 output("%*s</%s>\n", indent, "", path); 66546a7ef8aSdt207653 } else { 66646a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR"); 66746a7ef8aSdt207653 output("%*s%s\n", indent, "", path); 66846a7ef8aSdt207653 (void) sprintf(path, 66946a7ef8aSdt207653 "/Fault_Install_DataR/UNIX_Timestamp32"); 67046a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 67146a7ef8aSdt207653 output("%s\n", timestring); 67246a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/MACADDR"); 67346a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 67446a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 6; cnt++) { 67546a7ef8aSdt207653 output("%2.2x", data[cnt]); 67646a7ef8aSdt207653 if (cnt < 4 + 6 - 1) 67746a7ef8aSdt207653 output(":"); 67846a7ef8aSdt207653 } 67946a7ef8aSdt207653 output("\n"); 68046a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/Status"); 68146a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 68246a7ef8aSdt207653 output("%2.2x\n", data[10]); 68346a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/Initiator"); 68446a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 68546a7ef8aSdt207653 output("%2.2x\n", data[11]); 68646a7ef8aSdt207653 (void) sprintf(path, 68746a7ef8aSdt207653 "/Fault_Install_DataR/Message_Type"); 68846a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 68946a7ef8aSdt207653 output("%2.2x\n", data[12]); 69046a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/Message_32"); 69146a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 69246a7ef8aSdt207653 for (cnt = 13; cnt < 13 + 32; cnt++) 69346a7ef8aSdt207653 output("%2.2x", data[cnt]); 69446a7ef8aSdt207653 output("\n"); 69546a7ef8aSdt207653 } 69646a7ef8aSdt207653 Fault_Install_DataR_flag = 0; 69746a7ef8aSdt207653 return; 69846a7ef8aSdt207653 } else if ((Power_On_DataR_flag) && ( 69946a7ef8aSdt207653 strcmp(path, "C_10_8") == 0 || 70046a7ef8aSdt207653 (strcmp(path, "/C_10_8") == 0))) { 70146a7ef8aSdt207653 int cnt; 70246a7ef8aSdt207653 char timestring[128]; 70346a7ef8aSdt207653 time_t timefield = 0; 70446a7ef8aSdt207653 struct tm *tm; 70546a7ef8aSdt207653 indent = Power_On_DataR_flag; 70646a7ef8aSdt207653 (void) memcpy((uint8_t *)&timefield, data, 4); 70746a7ef8aSdt207653 if (timefield == 0) { 70846a7ef8aSdt207653 (void) sprintf(timestring, 70946a7ef8aSdt207653 "00000000 (No Value Recorded)"); 71046a7ef8aSdt207653 } else { 71146a7ef8aSdt207653 if ((tm = localtime(&timefield)) == NULL) 71246a7ef8aSdt207653 (void) sprintf(timestring, 71346a7ef8aSdt207653 "cannot convert time value"); 71446a7ef8aSdt207653 if (strftime(timestring, 71546a7ef8aSdt207653 sizeof (timestring), "%C", tm) == 0) 71646a7ef8aSdt207653 (void) sprintf(timestring, 71746a7ef8aSdt207653 "formatted time would overflow buffer"); 71846a7ef8aSdt207653 } 71946a7ef8aSdt207653 if (xml) { 72046a7ef8aSdt207653 (void) sprintf(path, "Power_On_DataR"); 72146a7ef8aSdt207653 output("%*s<%s>\n", indent, "", path); 72246a7ef8aSdt207653 indent = Power_On_DataR_flag + INDENT; 72346a7ef8aSdt207653 (void) sprintf(path, "UNIX_Timestamp32"); 72446a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 72546a7ef8aSdt207653 /*CSTYLED*/ 72646a7ef8aSdt207653 output("%s\"/>\n", timestring); 72746a7ef8aSdt207653 (void) sprintf(path, "Power_On_Minutes"); 72846a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path); 72946a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 4; cnt++) 73046a7ef8aSdt207653 output("%2.2x", data[cnt]); 73146a7ef8aSdt207653 /*CSTYLED*/ 73246a7ef8aSdt207653 output("\"/>\n"); 73346a7ef8aSdt207653 indent = Power_On_DataR_flag; 73446a7ef8aSdt207653 (void) sprintf(path, "Power_On_DataR"); 73546a7ef8aSdt207653 output("%*s</%s>\n", indent, "", path); 73646a7ef8aSdt207653 } else { 73746a7ef8aSdt207653 (void) sprintf(path, "/Power_On_DataR"); 73846a7ef8aSdt207653 output("%*s%s\n", indent, "", path); 73946a7ef8aSdt207653 (void) sprintf(path, 74046a7ef8aSdt207653 "/Power_On_DataR/UNIX_Timestamp32"); 74146a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 74246a7ef8aSdt207653 output("%s\n", timestring); 74346a7ef8aSdt207653 (void) sprintf(path, 74446a7ef8aSdt207653 "/Power_On_DataR/Power_On_Minutes"); 74546a7ef8aSdt207653 output("%*s%s: ", indent, "", path); 74646a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 4; cnt++) 74746a7ef8aSdt207653 output("%2.2x", data[cnt]); 74846a7ef8aSdt207653 output("\n"); 74946a7ef8aSdt207653 } 75046a7ef8aSdt207653 Power_On_DataR_flag = 0; 75146a7ef8aSdt207653 return; 75246a7ef8aSdt207653 } 7537c478bd9Sstevel@tonic-gate /* 7547c478bd9Sstevel@tonic-gate * Handle the various categories of data elements: iteration, 7557c478bd9Sstevel@tonic-gate * record, and field 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate if (def->iterationCount) { 7587c478bd9Sstevel@tonic-gate int iterlen = (def->payloadLen - NUM_ITER_BYTES)/ 7597c478bd9Sstevel@tonic-gate def->iterationCount, 7607c478bd9Sstevel@tonic-gate n, valid = 1; 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate uint8_t head, num; 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate fru_regdef_t newdef; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate /* 7687c478bd9Sstevel@tonic-gate * Make a new element definition to describe the components 7697c478bd9Sstevel@tonic-gate * of the iteration 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate (void) memcpy(&newdef, def, sizeof (newdef)); 7727c478bd9Sstevel@tonic-gate newdef.iterationCount = 0; 7737c478bd9Sstevel@tonic-gate newdef.payloadLen = iterlen; 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate /* 7767c478bd9Sstevel@tonic-gate * Validate the contents of the iteration control bytes 7777c478bd9Sstevel@tonic-gate */ 7787c478bd9Sstevel@tonic-gate if (data[HEAD_ITER] >= def->iterationCount) { 7797c478bd9Sstevel@tonic-gate valid = 0; 7807c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration head: %d " 7817c478bd9Sstevel@tonic-gate "(should be less than %d)\n"), 7827c478bd9Sstevel@tonic-gate path, data[HEAD_ITER], def->iterationCount); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate if (data[NUM_ITER] > def->iterationCount) { 7867c478bd9Sstevel@tonic-gate valid = 0; 7877c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration count: %d " 7887c478bd9Sstevel@tonic-gate "(should not be greater than %d)\n"), 7897c478bd9Sstevel@tonic-gate path, data[NUM_ITER], def->iterationCount); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (data[MAX_ITER] != def->iterationCount) { 7937c478bd9Sstevel@tonic-gate valid = 0; 7947c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration maximum: %d " 7957c478bd9Sstevel@tonic-gate "(should equal %d)\n"), 7967c478bd9Sstevel@tonic-gate path, data[MAX_ITER], def->iterationCount); 7977c478bd9Sstevel@tonic-gate } 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate if (valid) { 8007c478bd9Sstevel@tonic-gate head = data[HEAD_ITER]; 8017c478bd9Sstevel@tonic-gate num = data[NUM_ITER]; 8027c478bd9Sstevel@tonic-gate } else { 8037c478bd9Sstevel@tonic-gate head = 0; 8047c478bd9Sstevel@tonic-gate num = def->iterationCount; 8057c478bd9Sstevel@tonic-gate error(gettext("%s: Showing all iterations\n"), path); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate if (xml) 8097c478bd9Sstevel@tonic-gate output("%*s<%s>\n", indent, "", path); 8107c478bd9Sstevel@tonic-gate else 8117c478bd9Sstevel@tonic-gate output("%*s%s (%d iterations)\n", indent, "", path, 8127c478bd9Sstevel@tonic-gate num); 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* 8157c478bd9Sstevel@tonic-gate * Print each component of the iteration 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate for (i = head, n = 0, data += 4; 8187c478bd9Sstevel@tonic-gate n < num; 8197c478bd9Sstevel@tonic-gate i = ((i + 1) % def->iterationCount), n++) { 8207c478bd9Sstevel@tonic-gate if (!xml) (void) sprintf((path + bytes), "[%d]", n); 821f3af4981Sdt207653 iterglobal = n; 8227c478bd9Sstevel@tonic-gate print_element((data + i*iterlen), &newdef, path, 8237c478bd9Sstevel@tonic-gate indent); 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate if (xml) output("%*s</%s>\n", indent, "", path); 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate } else if (def->dataType == FDTYPE_Record) { 8297c478bd9Sstevel@tonic-gate const fru_regdef_t *component; 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate if (xml) 8327c478bd9Sstevel@tonic-gate output("%*s<%s>\n", indent, "", path); 8337c478bd9Sstevel@tonic-gate else 8347c478bd9Sstevel@tonic-gate output("%*s%s\n", indent, "", path); 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate /* 8377c478bd9Sstevel@tonic-gate * Print each component of the record 8387c478bd9Sstevel@tonic-gate */ 8397c478bd9Sstevel@tonic-gate for (i = 0; i < def->enumCount; 8407c478bd9Sstevel@tonic-gate i++, data += component->payloadLen) { 8417c478bd9Sstevel@tonic-gate component = fru_reg_lookup_def_by_name( 8427c478bd9Sstevel@tonic-gate def->enumTable[i].text); 8437c478bd9Sstevel@tonic-gate assert(component != NULL); 8447c478bd9Sstevel@tonic-gate print_element(data, component, path, indent); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate if (xml) output("%*s</%s>\n", indent, "", path); 8487c478bd9Sstevel@tonic-gate } else if (xml) { 8497c478bd9Sstevel@tonic-gate /* 8507c478bd9Sstevel@tonic-gate * Base case: print the field formatted for XML 8517c478bd9Sstevel@tonic-gate */ 8527c478bd9Sstevel@tonic-gate char *format = ((def == &unknown) 8537c478bd9Sstevel@tonic-gate ? "%*s<UNKNOWN tag=\"%s\" value=\"" 8547c478bd9Sstevel@tonic-gate : "%*s<%s value=\""); 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate output(format, indent, "", path); 8577c478bd9Sstevel@tonic-gate print_field(data, def); 8587c478bd9Sstevel@tonic-gate /*CSTYLED*/ 8597c478bd9Sstevel@tonic-gate output("\"/>\n"); /* \" confuses cstyle */ 860f3af4981Sdt207653 861f3af4981Sdt207653 if ((strcmp(def->name, "Message") == 0) && 862f3af4981Sdt207653 ((FMAmessageR == 0) || (FMAmessageR == 1))) { 863f3af4981Sdt207653 const char *elem_name = NULL; 864f3af4981Sdt207653 const char *parent_path; 865f3af4981Sdt207653 uchar_t tmpdata[128]; 866f3af4981Sdt207653 char path[16384]; 867f3af4981Sdt207653 const fru_regdef_t *new_def; 868f3af4981Sdt207653 869f3af4981Sdt207653 if (FMAmessageR == 0) 870f3af4981Sdt207653 elem_name = "FMA_Event_DataR"; 871f3af4981Sdt207653 else if (FMAmessageR == 1) 872f3af4981Sdt207653 elem_name = "FMA_MessageR"; 873f3af4981Sdt207653 if (elem_name != NULL) { 874f3af4981Sdt207653 (void) memcpy(tmpdata, data, def->payloadLen); 875f3af4981Sdt207653 new_def = fru_reg_lookup_def_by_name(elem_name); 87677acf672Sdt207653 (void) snprintf(path, sizeof (path), 877f3af4981Sdt207653 "/Status_EventsR[%d]/Message(FMA)", iterglobal); 878f3af4981Sdt207653 parent_path = path; 879f3af4981Sdt207653 print_element(tmpdata, new_def, 880f3af4981Sdt207653 parent_path, 2*INDENT); 881f3af4981Sdt207653 FMAmessageR = -1; 882f3af4981Sdt207653 } 883f3af4981Sdt207653 } 884f3af4981Sdt207653 8857c478bd9Sstevel@tonic-gate } else { 8867c478bd9Sstevel@tonic-gate /* 8877c478bd9Sstevel@tonic-gate * Base case: print the field 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate output("%*s%s: ", indent, "", path); 8907c478bd9Sstevel@tonic-gate print_field(data, def); 8917c478bd9Sstevel@tonic-gate output("\n"); 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate /* 8967c478bd9Sstevel@tonic-gate * Print the contents of a packet (i.e., a tagged data element) 8977c478bd9Sstevel@tonic-gate */ 8987c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8997c478bd9Sstevel@tonic-gate static int 9007c478bd9Sstevel@tonic-gate print_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args) 9017c478bd9Sstevel@tonic-gate { 9027c478bd9Sstevel@tonic-gate int tag_type = get_tag_type(tag); 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate size_t payload_length = 0; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate const fru_regdef_t *def; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate /* 9097c478bd9Sstevel@tonic-gate * Build a definition for unrecognized tags (e.g., not in libfrureg) 9107c478bd9Sstevel@tonic-gate */ 9117c478bd9Sstevel@tonic-gate if ((tag_type == -1) || 9127c478bd9Sstevel@tonic-gate ((payload_length = get_payload_length(tag)) != length)) { 9137c478bd9Sstevel@tonic-gate def = &unknown; 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate unknown.tagType = -1; 9167c478bd9Sstevel@tonic-gate unknown.tagDense = -1; 9177c478bd9Sstevel@tonic-gate unknown.payloadLen = length; 9187c478bd9Sstevel@tonic-gate unknown.dataLength = unknown.payloadLen; 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate if (tag_type == -1) 9217c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), "INVALID"); 9227c478bd9Sstevel@tonic-gate else 9237c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), 9247c478bd9Sstevel@tonic-gate "%s_%u_%u_%u", get_tagtype_str(tag_type), 9257c478bd9Sstevel@tonic-gate get_tag_dense(tag), payload_length, length); 9267c478bd9Sstevel@tonic-gate } else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) { 9277c478bd9Sstevel@tonic-gate def = &unknown; 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate unknown.tagType = tag_type; 9307c478bd9Sstevel@tonic-gate unknown.tagDense = get_tag_dense(tag); 9317c478bd9Sstevel@tonic-gate unknown.payloadLen = payload_length; 9327c478bd9Sstevel@tonic-gate unknown.dataLength = unknown.payloadLen; 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), "%s_%u_%u", 9357c478bd9Sstevel@tonic-gate get_tagtype_str(unknown.tagType), 9367c478bd9Sstevel@tonic-gate unknown.tagDense, payload_length); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate /* 9417c478bd9Sstevel@tonic-gate * Print the defined element 9427c478bd9Sstevel@tonic-gate */ 9437c478bd9Sstevel@tonic-gate print_element(payload, def, "", INDENT); 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* 9497c478bd9Sstevel@tonic-gate * Print a segment's name and the contents of each data element in the segment 9507c478bd9Sstevel@tonic-gate */ 9517c478bd9Sstevel@tonic-gate static int 9527c478bd9Sstevel@tonic-gate print_packets_in_segment(fru_seghdl_t segment, void *args) 9537c478bd9Sstevel@tonic-gate { 9547c478bd9Sstevel@tonic-gate char *name; 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate int status; 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate if ((status = fru_get_segment_name(segment, &name)) != FRU_SUCCESS) { 9607c478bd9Sstevel@tonic-gate saved_status = status; 9617c478bd9Sstevel@tonic-gate name = ""; 9627c478bd9Sstevel@tonic-gate error(gettext("Error getting segment name: %s\n"), 9637c478bd9Sstevel@tonic-gate fru_strerror(status)); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate if (xml) 9687c478bd9Sstevel@tonic-gate output("%*s<Segment name=\"%s\">\n", INDENT, "", name); 9697c478bd9Sstevel@tonic-gate else 9707c478bd9Sstevel@tonic-gate output("%*sSEGMENT: %s\n", INDENT, "", name); 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* Iterate over the packets in the segment, printing the contents */ 9737c478bd9Sstevel@tonic-gate if ((status = fru_for_each_packet(segment, print_packet, args)) 9747c478bd9Sstevel@tonic-gate != FRU_SUCCESS) { 9757c478bd9Sstevel@tonic-gate saved_status = status; 9767c478bd9Sstevel@tonic-gate error(gettext("Error processing data in segment \"%s\": %s\n"), 9777c478bd9Sstevel@tonic-gate name, fru_strerror(status)); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if (xml) output("%*s</Segment>\n", INDENT, ""); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate free(name); 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9887c478bd9Sstevel@tonic-gate static void 9897c478bd9Sstevel@tonic-gate print_node_path(fru_node_t fru_type, const char *path, const char *name, 9907c478bd9Sstevel@tonic-gate end_node_fp_t *end_node, void **end_args) 9917c478bd9Sstevel@tonic-gate { 9927c478bd9Sstevel@tonic-gate output("%s%s\n", path, 9937c478bd9Sstevel@tonic-gate ((fru_type == FRU_NODE_CONTAINER) ? " (container)" 9947c478bd9Sstevel@tonic-gate : ((fru_type == FRU_NODE_FRU) ? " (fru)" : ""))); 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate /* 9987c478bd9Sstevel@tonic-gate * Close the XML element for a "location" node 9997c478bd9Sstevel@tonic-gate */ 10007c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10017c478bd9Sstevel@tonic-gate static void 10027c478bd9Sstevel@tonic-gate end_location_xml(fru_nodehdl_t node, const char *path, const char *name, 10037c478bd9Sstevel@tonic-gate void *args) 10047c478bd9Sstevel@tonic-gate { 10057c478bd9Sstevel@tonic-gate assert(args != NULL); 10067c478bd9Sstevel@tonic-gate output("</Location> <!-- %s -->\n", args); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* 10107c478bd9Sstevel@tonic-gate * Close the XML element for a "fru" node 10117c478bd9Sstevel@tonic-gate */ 10127c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10137c478bd9Sstevel@tonic-gate static void 10147c478bd9Sstevel@tonic-gate end_fru_xml(fru_nodehdl_t node, const char *path, const char *name, void *args) 10157c478bd9Sstevel@tonic-gate { 10167c478bd9Sstevel@tonic-gate assert(args != NULL); 10177c478bd9Sstevel@tonic-gate output("</Fru> <!-- %s -->\n", args); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* 10217c478bd9Sstevel@tonic-gate * Close the XML element for a "container" node 10227c478bd9Sstevel@tonic-gate */ 10237c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10247c478bd9Sstevel@tonic-gate static void 10257c478bd9Sstevel@tonic-gate end_container_xml(fru_nodehdl_t node, const char *path, const char *name, 10267c478bd9Sstevel@tonic-gate void *args) 10277c478bd9Sstevel@tonic-gate { 10287c478bd9Sstevel@tonic-gate assert(args != NULL); 10297c478bd9Sstevel@tonic-gate output("</Container> <!-- %s -->\n", args); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 10337c478bd9Sstevel@tonic-gate * Introduce a node in XML and set the appropriate node-closing function 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10367c478bd9Sstevel@tonic-gate static void 10377c478bd9Sstevel@tonic-gate print_node_xml(fru_node_t fru_type, const char *path, const char *name, 10387c478bd9Sstevel@tonic-gate end_node_fp_t *end_node, void **end_args) 10397c478bd9Sstevel@tonic-gate { 10407c478bd9Sstevel@tonic-gate switch (fru_type) { 10417c478bd9Sstevel@tonic-gate case FRU_NODE_FRU: 10427c478bd9Sstevel@tonic-gate output("<Fru name=\"%s\">\n", name); 10437c478bd9Sstevel@tonic-gate *end_node = end_fru_xml; 10447c478bd9Sstevel@tonic-gate break; 10457c478bd9Sstevel@tonic-gate case FRU_NODE_CONTAINER: 10467c478bd9Sstevel@tonic-gate output("<Container name=\"%s\">\n", name); 10477c478bd9Sstevel@tonic-gate *end_node = end_container_xml; 10487c478bd9Sstevel@tonic-gate break; 10497c478bd9Sstevel@tonic-gate default: 10507c478bd9Sstevel@tonic-gate output("<Location name=\"%s\">\n", name); 10517c478bd9Sstevel@tonic-gate *end_node = end_location_xml; 10527c478bd9Sstevel@tonic-gate break; 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate *end_args = (void *) name; 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate /* 10597c478bd9Sstevel@tonic-gate * Print node info and, where appropriate, node contents 10607c478bd9Sstevel@tonic-gate */ 10617c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10627c478bd9Sstevel@tonic-gate static fru_errno_t 10637c478bd9Sstevel@tonic-gate process_node(fru_nodehdl_t node, const char *path, const char *name, 10647c478bd9Sstevel@tonic-gate void *args, end_node_fp_t *end_node, void **end_args) 10657c478bd9Sstevel@tonic-gate { 10667c478bd9Sstevel@tonic-gate int status; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate fru_node_t fru_type = FRU_NODE_UNKNOWN; 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate if ((status = fru_get_node_type(node, &fru_type)) != FRU_SUCCESS) { 10727c478bd9Sstevel@tonic-gate saved_status = status; 10737c478bd9Sstevel@tonic-gate error(gettext("Error getting node type: %s\n"), 10747c478bd9Sstevel@tonic-gate fru_strerror(status)); 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate if (containers_only) { 10787c478bd9Sstevel@tonic-gate if (fru_type != FRU_NODE_CONTAINER) 10797c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 10807c478bd9Sstevel@tonic-gate name = path; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* Introduce the node */ 10847c478bd9Sstevel@tonic-gate assert(print_node != NULL); 10857c478bd9Sstevel@tonic-gate print_node(fru_type, path, name, end_node, end_args); 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate if (list_only) 10887c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate /* Print the contents of each packet in each segment of a container */ 10917c478bd9Sstevel@tonic-gate if (fru_type == FRU_NODE_CONTAINER) { 10927c478bd9Sstevel@tonic-gate if (xml) output("<ContainerData>\n"); 10937c478bd9Sstevel@tonic-gate if ((status = 10947c478bd9Sstevel@tonic-gate fru_for_each_segment(node, print_packets_in_segment, 10957c478bd9Sstevel@tonic-gate NULL)) 10967c478bd9Sstevel@tonic-gate != FRU_SUCCESS) { 10977c478bd9Sstevel@tonic-gate saved_status = status; 10987c478bd9Sstevel@tonic-gate error(gettext("Error processing node \"%s\": %s\n"), 10997c478bd9Sstevel@tonic-gate name, fru_strerror(status)); 11007c478bd9Sstevel@tonic-gate } 11017c478bd9Sstevel@tonic-gate if (xml) output("</ContainerData>\n"); 11027c478bd9Sstevel@tonic-gate } 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* 11087c478bd9Sstevel@tonic-gate * Process the node if its path matches the search path in "args" 11097c478bd9Sstevel@tonic-gate */ 11107c478bd9Sstevel@tonic-gate /* ARGSUSED */ 11117c478bd9Sstevel@tonic-gate static fru_errno_t 11127c478bd9Sstevel@tonic-gate process_matching_node(fru_nodehdl_t node, const char *path, const char *name, 11137c478bd9Sstevel@tonic-gate void *args, end_node_fp_t *end_node, void **end_args) 11147c478bd9Sstevel@tonic-gate { 11157c478bd9Sstevel@tonic-gate int status; 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate if (!fru_pathmatch(path, args)) 11197c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate status = process_node(node, path, path, args, end_node, end_args); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate return ((status == FRU_SUCCESS) ? FRU_WALK_TERMINATE : status); 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate /* 11277c478bd9Sstevel@tonic-gate * Write the trailer required for well-formed DTD-compliant XML 11287c478bd9Sstevel@tonic-gate */ 11297c478bd9Sstevel@tonic-gate static void 11307c478bd9Sstevel@tonic-gate terminate_xml() 11317c478bd9Sstevel@tonic-gate { 11327c478bd9Sstevel@tonic-gate errno = 0; 11337c478bd9Sstevel@tonic-gate if (ftell(errlog) > 0) { 11347c478bd9Sstevel@tonic-gate char c; 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate output("<ErrorLog>\n"); 11377c478bd9Sstevel@tonic-gate rewind(errlog); 11387c478bd9Sstevel@tonic-gate if (!errno) 11397c478bd9Sstevel@tonic-gate while ((c = getc(errlog)) != EOF) 11407c478bd9Sstevel@tonic-gate xputchar(c); 11417c478bd9Sstevel@tonic-gate output("</ErrorLog>\n"); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate if (errno) { 11457c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 11467c478bd9Sstevel@tonic-gate errlog = NULL; 11477c478bd9Sstevel@tonic-gate error(gettext("Error copying error messages to \"ErrorLog\""), 11487c478bd9Sstevel@tonic-gate strerror(errno)); 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate output("</FRUID_XML_Tree>\n"); 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate * Print available FRU ID information 11567c478bd9Sstevel@tonic-gate */ 11577c478bd9Sstevel@tonic-gate int 11587c478bd9Sstevel@tonic-gate prtfru(const char *searchpath, int containers_only_flag, int list_only_flag, 11597c478bd9Sstevel@tonic-gate int xml_flag) 11607c478bd9Sstevel@tonic-gate { 11617c478bd9Sstevel@tonic-gate fru_errno_t status; 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate fru_nodehdl_t frutree = 0; 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate /* Copy parameter flags to global flags */ 11677c478bd9Sstevel@tonic-gate containers_only = containers_only_flag; 11687c478bd9Sstevel@tonic-gate list_only = list_only_flag; 11697c478bd9Sstevel@tonic-gate xml = xml_flag; 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate /* Help arrange for correct, efficient interleaving of output */ 11737c478bd9Sstevel@tonic-gate (void) setvbuf(stderr, NULL, _IOLBF, 0); 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate /* Initialize for XML--or not */ 11777c478bd9Sstevel@tonic-gate if (xml) { 11787c478bd9Sstevel@tonic-gate safeputchar = xputchar; 11797c478bd9Sstevel@tonic-gate safeputs = xputs; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate print_node = print_node_xml; 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate if ((errlog = tmpfile()) == NULL) { 11847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11857c478bd9Sstevel@tonic-gate "Error creating error log file: %s\n", 11867c478bd9Sstevel@tonic-gate strerror(errno)); 11877c478bd9Sstevel@tonic-gate return (1); 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate /* Output the XML preamble */ 11917c478bd9Sstevel@tonic-gate output("<?xml version=\"1.0\" ?>\n" 11927c478bd9Sstevel@tonic-gate "<!--\n" 11937c478bd9Sstevel@tonic-gate " Copyright 2000-2002 Sun Microsystems, Inc. " 11947c478bd9Sstevel@tonic-gate "All rights reserved.\n" 11957c478bd9Sstevel@tonic-gate " Use is subject to license terms.\n" 11967c478bd9Sstevel@tonic-gate "-->\n\n" 11977c478bd9Sstevel@tonic-gate "<!DOCTYPE FRUID_XML_Tree SYSTEM \"prtfrureg.dtd\">\n\n" 11987c478bd9Sstevel@tonic-gate "<FRUID_XML_Tree>\n"); 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* Arrange to always properly terminate XML */ 12017c478bd9Sstevel@tonic-gate if (atexit(terminate_xml)) 12027c478bd9Sstevel@tonic-gate error(gettext("Warning: XML will not be terminated: " 12037c478bd9Sstevel@tonic-gate "%s\n"), strerror(errno)); 12047c478bd9Sstevel@tonic-gate } else 12057c478bd9Sstevel@tonic-gate print_node = print_node_path; 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate /* Get the root node */ 12097c478bd9Sstevel@tonic-gate if ((status = fru_get_root(&frutree)) == FRU_NODENOTFOUND) { 12107c478bd9Sstevel@tonic-gate error(gettext("This system does not provide FRU ID data\n")); 12117c478bd9Sstevel@tonic-gate return (1); 12127c478bd9Sstevel@tonic-gate } else if (status != FRU_SUCCESS) { 12137c478bd9Sstevel@tonic-gate error(gettext("Unable to access FRU ID data: %s\n"), 12147c478bd9Sstevel@tonic-gate fru_strerror(status)); 12157c478bd9Sstevel@tonic-gate return (1); 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* Process the tree */ 12197c478bd9Sstevel@tonic-gate if (searchpath == NULL) { 12207c478bd9Sstevel@tonic-gate status = fru_walk_tree(frutree, "", process_node, NULL); 12217c478bd9Sstevel@tonic-gate } else { 12227c478bd9Sstevel@tonic-gate status = fru_walk_tree(frutree, "", process_matching_node, 12237c478bd9Sstevel@tonic-gate (void *)searchpath); 12247c478bd9Sstevel@tonic-gate if (status == FRU_WALK_TERMINATE) { 12257c478bd9Sstevel@tonic-gate status = FRU_SUCCESS; 12267c478bd9Sstevel@tonic-gate } else if (status == FRU_SUCCESS) { 12277c478bd9Sstevel@tonic-gate error(gettext("\"%s\" not found\n"), searchpath); 12287c478bd9Sstevel@tonic-gate return (1); 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate if (status != FRU_SUCCESS) 12337c478bd9Sstevel@tonic-gate error(gettext("Error processing FRU tree: %s\n"), 12347c478bd9Sstevel@tonic-gate fru_strerror(status)); 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate return (((status == FRU_SUCCESS) && (saved_status == 0)) ? 0 : 1); 12377c478bd9Sstevel@tonic-gate } 1238