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 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static void (*print_node)(fru_node_t fru_type, const char *path, 557c478bd9Sstevel@tonic-gate const char *name, end_node_fp_t *end_node, 567c478bd9Sstevel@tonic-gate void **end_args); 577c478bd9Sstevel@tonic-gate 58f3af4981Sdt207653 static void print_element(const uint8_t *data, const fru_regdef_t *def, 59f3af4981Sdt207653 const char *parent_path, int indent); 60f3af4981Sdt207653 617c478bd9Sstevel@tonic-gate static char tagname[sizeof ("?_0123456789_0123456789_0123456789")]; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static int containers_only = 0, list_only = 0, saved_status = 0, xml = 0; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static FILE *errlog; 667c478bd9Sstevel@tonic-gate 67f3af4981Sdt207653 int iterglobal = 0; 68f3af4981Sdt207653 int FMAmessageR = -1; 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Definition for data elements found in devices but not found in 717c478bd9Sstevel@tonic-gate * the system's version of libfrureg 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate static fru_regdef_t unknown = { 747c478bd9Sstevel@tonic-gate REGDEF_VERSION, 757c478bd9Sstevel@tonic-gate tagname, 767c478bd9Sstevel@tonic-gate -1, 777c478bd9Sstevel@tonic-gate -1, 787c478bd9Sstevel@tonic-gate -1, 797c478bd9Sstevel@tonic-gate -1, 807c478bd9Sstevel@tonic-gate FDTYPE_ByteArray, 817c478bd9Sstevel@tonic-gate FDISP_Hex, 827c478bd9Sstevel@tonic-gate FRU_WHICH_UNDEFINED, 837c478bd9Sstevel@tonic-gate FRU_WHICH_UNDEFINED, 847c478bd9Sstevel@tonic-gate 0, 857c478bd9Sstevel@tonic-gate NULL, 867c478bd9Sstevel@tonic-gate 0, 877c478bd9Sstevel@tonic-gate FRU_NOT_ITERATED, 887c478bd9Sstevel@tonic-gate NULL 897c478bd9Sstevel@tonic-gate }; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Write message to standard error and possibly the error log buffer 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate static void 967c478bd9Sstevel@tonic-gate error(const char *format, ...) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate va_list args; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* make relevant output appear before error message */ 1027c478bd9Sstevel@tonic-gate if (fflush(stdout) == EOF) { 1037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Error flushing output: %s\n", 1047c478bd9Sstevel@tonic-gate strerror(errno)); 1057c478bd9Sstevel@tonic-gate exit(1); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate va_start(args, format); 1097c478bd9Sstevel@tonic-gate if (vfprintf(stderr, format, args) < 0) exit(1); 1107c478bd9Sstevel@tonic-gate if (errlog && (vfprintf(errlog, format, args) < 0)) exit(1); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * Write message to standard output 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate static void 1177c478bd9Sstevel@tonic-gate output(const char *format, ...) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate va_list args; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate va_start(args, format); 1237c478bd9Sstevel@tonic-gate if (vfprintf(stdout, format, args) < 0) { 1247c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1257c478bd9Sstevel@tonic-gate strerror(errno)); 1267c478bd9Sstevel@tonic-gate exit(1); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * Safe wrapper for putchar() 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate static void 1347c478bd9Sstevel@tonic-gate voidputchar(int c) 1357c478bd9Sstevel@tonic-gate { 1367c478bd9Sstevel@tonic-gate if (putchar(c) == EOF) { 1377c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1387c478bd9Sstevel@tonic-gate strerror(errno)); 1397c478bd9Sstevel@tonic-gate exit(1); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate static void (*safeputchar)(int c) = voidputchar; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * Safe wrapper for puts() 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate static void 1497c478bd9Sstevel@tonic-gate voidputs(const char *s) 1507c478bd9Sstevel@tonic-gate { 1517c478bd9Sstevel@tonic-gate if (fputs(s, stdout) == EOF) { 1527c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1537c478bd9Sstevel@tonic-gate strerror(errno)); 1547c478bd9Sstevel@tonic-gate exit(1); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate static void (*safeputs)(const char *s) = voidputs; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /* 1617c478bd9Sstevel@tonic-gate * XML-safe wrapper for putchar(): quotes XML-special characters 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate static void 1647c478bd9Sstevel@tonic-gate xputchar(int c) 1657c478bd9Sstevel@tonic-gate { 1667c478bd9Sstevel@tonic-gate switch (c) { 1677c478bd9Sstevel@tonic-gate case '<': 1687c478bd9Sstevel@tonic-gate c = fputs("<", stdout); 1697c478bd9Sstevel@tonic-gate break; 1707c478bd9Sstevel@tonic-gate case '>': 1717c478bd9Sstevel@tonic-gate c = fputs(">", stdout); 1727c478bd9Sstevel@tonic-gate break; 1737c478bd9Sstevel@tonic-gate case '&': 1747c478bd9Sstevel@tonic-gate c = fputs("&", stdout); 1757c478bd9Sstevel@tonic-gate break; 1767c478bd9Sstevel@tonic-gate case '"': 1777c478bd9Sstevel@tonic-gate c = fputs(""", stdout); 1787c478bd9Sstevel@tonic-gate break; 1797c478bd9Sstevel@tonic-gate default: 1807c478bd9Sstevel@tonic-gate c = putchar(c); 1817c478bd9Sstevel@tonic-gate break; 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (c == EOF) { 1857c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"), 1867c478bd9Sstevel@tonic-gate strerror(errno)); 1877c478bd9Sstevel@tonic-gate exit(1); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * XML-safe analog of puts(): quotes XML-special characters 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate static void 1957c478bd9Sstevel@tonic-gate xputs(const char *s) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate char c; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate for (/* */; ((c = *s) != 0); s++) 2007c478bd9Sstevel@tonic-gate xputchar(c); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Output the XML DTD derived from the registry provided by libfrureg 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate int 2077c478bd9Sstevel@tonic-gate output_dtd(void) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate char **element; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate unsigned int i, j, num_elements = 0; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate uint8_t *tagged; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate const fru_regdef_t *def; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if (((element = fru_reg_list_entries(&num_elements)) == NULL) || 2197c478bd9Sstevel@tonic-gate (num_elements == 0)) { 2207c478bd9Sstevel@tonic-gate error(gettext("No FRU ID Registry elements")); 2217c478bd9Sstevel@tonic-gate return (1); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if ((tagged = calloc(num_elements, sizeof (*tagged))) == NULL) { 2257c478bd9Sstevel@tonic-gate error(gettext("Unable to get memory for tagged element list"), 2267c478bd9Sstevel@tonic-gate strerror(errno)); 2277c478bd9Sstevel@tonic-gate return (1); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * Output the DTD preamble 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate output("<!ELEMENT FRUID_XML_Tree (Parameter*, " 2347c478bd9Sstevel@tonic-gate "(Fru | Location | Container)*,\n" 2357c478bd9Sstevel@tonic-gate " Parameter*, ErrorLog?, Parameter*)>\n" 2367c478bd9Sstevel@tonic-gate "<!ATTLIST FRUID_XML_Tree>\n" 2377c478bd9Sstevel@tonic-gate "\n" 2387c478bd9Sstevel@tonic-gate "<!ELEMENT Parameter EMPTY>\n" 2397c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter type CDATA #REQUIRED>\n" 2407c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter name CDATA #REQUIRED>\n" 2417c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter value CDATA #REQUIRED>\n" 2427c478bd9Sstevel@tonic-gate "\n" 2437c478bd9Sstevel@tonic-gate "<!ELEMENT Fru (Fru | Location | Container)*>\n" 2447c478bd9Sstevel@tonic-gate "<!ATTLIST Fru name CDATA #REQUIRED>\n" 2457c478bd9Sstevel@tonic-gate "\n" 2467c478bd9Sstevel@tonic-gate "<!ELEMENT Location (Fru | Location | Container)*>\n" 24794bc7577Sps154918 "<!ATTLIST Location\n" 24894bc7577Sps154918 " name CDATA #IMPLIED\n" 24994bc7577Sps154918 " value CDATA #IMPLIED\n" 25094bc7577Sps154918 ">\n" 2517c478bd9Sstevel@tonic-gate "\n" 2527c478bd9Sstevel@tonic-gate "<!ELEMENT Container (ContainerData?, " 2537c478bd9Sstevel@tonic-gate "(Fru | Location | Container)*)>\n" 2547c478bd9Sstevel@tonic-gate "<!ATTLIST Container name CDATA #REQUIRED>\n" 2557c478bd9Sstevel@tonic-gate "<!ATTLIST Container imagefile CDATA #IMPLIED>\n" 2567c478bd9Sstevel@tonic-gate "\n" 2577c478bd9Sstevel@tonic-gate "<!ELEMENT ContainerData (Segment*)>\n" 2587c478bd9Sstevel@tonic-gate "<!ATTLIST ContainerData>\n" 2597c478bd9Sstevel@tonic-gate "\n" 2607c478bd9Sstevel@tonic-gate "<!ATTLIST Segment name CDATA #REQUIRED>\n" 2617c478bd9Sstevel@tonic-gate "\n" 2627c478bd9Sstevel@tonic-gate "<!ELEMENT Index EMPTY>\n" 2637c478bd9Sstevel@tonic-gate "<!ATTLIST Index value CDATA #REQUIRED>\n" 2647c478bd9Sstevel@tonic-gate "\n" 2657c478bd9Sstevel@tonic-gate "<!ELEMENT ErrorLog (#PCDATA)>\n" 2667c478bd9Sstevel@tonic-gate "<!ATTLIST ErrorLog>\n" 2677c478bd9Sstevel@tonic-gate "\n"); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * Output the definition for each element 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate for (i = 0; i < num_elements; i++) { 2737c478bd9Sstevel@tonic-gate assert(element[i] != NULL); 27494bc7577Sps154918 /* Prevent incompatible duplicate defn. from FRUID Registry. */ 27594bc7577Sps154918 if ((strcmp("Location", element[i])) == 0) continue; 2767c478bd9Sstevel@tonic-gate if ((def = fru_reg_lookup_def_by_name(element[i])) == NULL) { 2777c478bd9Sstevel@tonic-gate error(gettext("Error looking up registry " 2787c478bd9Sstevel@tonic-gate "definition for \"%s\"\n"), 2797c478bd9Sstevel@tonic-gate element[i]); 2807c478bd9Sstevel@tonic-gate return (1); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if (def->tagType != FRU_X) tagged[i] = 1; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Record) { 2867c478bd9Sstevel@tonic-gate if (def->iterationType == FRU_NOT_ITERATED) 2877c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (%s", element[i], 2887c478bd9Sstevel@tonic-gate def->enumTable[0].text); 2897c478bd9Sstevel@tonic-gate else 2907c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (Index_%s*)>\n" 2917c478bd9Sstevel@tonic-gate "<!ATTLIST Index_%s>\n" 2927c478bd9Sstevel@tonic-gate "<!ELEMENT Index_%s (%s", 2937c478bd9Sstevel@tonic-gate element[i], element[i], element[i], 2947c478bd9Sstevel@tonic-gate element[i], def->enumTable[0].text); 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate for (j = 1; j < def->enumCount; j++) 2977c478bd9Sstevel@tonic-gate output(",\n\t%s", def->enumTable[j].text); 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate output(")>\n"); 3007c478bd9Sstevel@tonic-gate } else if (def->iterationType == FRU_NOT_ITERATED) { 3017c478bd9Sstevel@tonic-gate output("<!ELEMENT %s EMPTY>\n" 3027c478bd9Sstevel@tonic-gate "<!ATTLIST %s value CDATA #REQUIRED>\n", 3037c478bd9Sstevel@tonic-gate element[i], element[i]); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Enumeration) { 3067c478bd9Sstevel@tonic-gate output("<!-- %s valid enumeration values\n"); 3077c478bd9Sstevel@tonic-gate for (j = 0; j < def->enumCount; j++) { 3087c478bd9Sstevel@tonic-gate output("\t\""); 3097c478bd9Sstevel@tonic-gate xputs(def->enumTable[j].text); 3107c478bd9Sstevel@tonic-gate output("\"\n"); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate output("-->\n"); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate else 3167c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (Index*)>\n", element[i]); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate output("\n"); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* Provide for returning the tag for an "unknown" element */ 3227c478bd9Sstevel@tonic-gate output("<!ATTLIST UNKNOWN tag CDATA \"UNKNOWN\">\n\n"); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * List all data elements as possible members of "Segment" 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate output("<!ELEMENT Segment ((UNKNOWN"); 3297c478bd9Sstevel@tonic-gate for (i = 0; i < num_elements; i++) { 3307c478bd9Sstevel@tonic-gate if (tagged[i]) output("\n\t| %s", element[i]); 3317c478bd9Sstevel@tonic-gate free(element[i]); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate output(")*)>\n"); 3347c478bd9Sstevel@tonic-gate free(element); 3357c478bd9Sstevel@tonic-gate free(tagged); 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate return (0); 3387c478bd9Sstevel@tonic-gate } 339f3af4981Sdt207653 /* 340f3af4981Sdt207653 * Function to convert bcd to binary to correct the SPD_Manufacturer_Week 341f3af4981Sdt207653 * 342f3af4981Sdt207653 */ 343f3af4981Sdt207653 static void convertbcdtobinary(int *val) 344f3af4981Sdt207653 { 345f3af4981Sdt207653 int newval, tmpval, rem, origval, poweroften; 346f3af4981Sdt207653 int i; 347f3af4981Sdt207653 tmpval = 0; 348f3af4981Sdt207653 newval = 0; 349f3af4981Sdt207653 i = 0; 350f3af4981Sdt207653 rem = 0; 351f3af4981Sdt207653 poweroften = 1; 352f3af4981Sdt207653 origval = (int)(*val); 353f3af4981Sdt207653 tmpval = (int)(*val); 354f3af4981Sdt207653 while (tmpval != 0) { 355f3af4981Sdt207653 if (i >= 1) 356f3af4981Sdt207653 poweroften = poweroften * 10; 357f3af4981Sdt207653 origval = tmpval; 358f3af4981Sdt207653 tmpval = (int)(tmpval/16); 359f3af4981Sdt207653 rem = origval - (tmpval * 16); 360f3af4981Sdt207653 newval = newval +(int)(poweroften * rem); 361f3af4981Sdt207653 i ++; 362f3af4981Sdt207653 } 363f3af4981Sdt207653 *val = newval; 364f3af4981Sdt207653 } 365f3af4981Sdt207653 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * Safely pretty-print the value of a field 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate static void 3717c478bd9Sstevel@tonic-gate print_field(const uint8_t *field, const fru_regdef_t *def) 3727c478bd9Sstevel@tonic-gate { 373f3af4981Sdt207653 char *errmsg = NULL, timestring[TIMESTRINGLEN], path[16384]; 3747c478bd9Sstevel@tonic-gate 375f3af4981Sdt207653 int i, valueint; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate uint64_t value; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate time_t timefield; 3807c478bd9Sstevel@tonic-gate 381f3af4981Sdt207653 struct tm *tm; 3827c478bd9Sstevel@tonic-gate 383f3af4981Sdt207653 uchar_t first_byte, data[128]; 384f3af4981Sdt207653 385f3af4981Sdt207653 const fru_regdef_t *new_def; 386f3af4981Sdt207653 387f3af4981Sdt207653 const char *elem_name = NULL; 388f3af4981Sdt207653 const char *parent_path; 3897c478bd9Sstevel@tonic-gate switch (def->dataType) { 3907c478bd9Sstevel@tonic-gate case FDTYPE_Binary: 3917c478bd9Sstevel@tonic-gate assert(def->payloadLen <= sizeof (value)); 3927c478bd9Sstevel@tonic-gate switch (def->dispType) { 3937c478bd9Sstevel@tonic-gate case FDISP_Binary: 3947c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen; i++) 3957c478bd9Sstevel@tonic-gate output("%c%c%c%c%c%c%c%c", 3967c478bd9Sstevel@tonic-gate ((field[i] & 0x80) ? '1' : '0'), 3977c478bd9Sstevel@tonic-gate ((field[i] & 0x40) ? '1' : '0'), 3987c478bd9Sstevel@tonic-gate ((field[i] & 0x20) ? '1' : '0'), 3997c478bd9Sstevel@tonic-gate ((field[i] & 0x10) ? '1' : '0'), 4007c478bd9Sstevel@tonic-gate ((field[i] & 0x08) ? '1' : '0'), 4017c478bd9Sstevel@tonic-gate ((field[i] & 0x04) ? '1' : '0'), 4027c478bd9Sstevel@tonic-gate ((field[i] & 0x02) ? '1' : '0'), 4037c478bd9Sstevel@tonic-gate ((field[i] & 0x01) ? '1' : '0')); 4047c478bd9Sstevel@tonic-gate return; 4057c478bd9Sstevel@tonic-gate case FDISP_Octal: 4067c478bd9Sstevel@tonic-gate case FDISP_Decimal: 4077c478bd9Sstevel@tonic-gate value = 0; 408f3af4981Sdt207653 valueint = 0; 4097c478bd9Sstevel@tonic-gate (void) memcpy((((uint8_t *)&value) + 4107c478bd9Sstevel@tonic-gate sizeof (value) - def->payloadLen), 4117c478bd9Sstevel@tonic-gate field, def->payloadLen); 41294bc7577Sps154918 if ((value != 0) && 413f3af4981Sdt207653 (strcmp(def->name, "SPD_Manufacture_Week") == 0)) { 414f3af4981Sdt207653 valueint = (int)value; 415f3af4981Sdt207653 convertbcdtobinary(&valueint); 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 = 467f3af4981Sdt207653 fru_reg_lookup_def_by_name(elem_name); 468aad09a1cSdt207653 (void) snprintf(path, sizeof (path), 469f3af4981Sdt207653 "/Status_EventsR[%d]/Message(FMA)", 470f3af4981Sdt207653 iterglobal); 471f3af4981Sdt207653 parent_path = path; 472f3af4981Sdt207653 output("\n"); 473f3af4981Sdt207653 print_element(data, new_def, 474f3af4981Sdt207653 parent_path, 2*INDENT); 475f3af4981Sdt207653 return; 476f3af4981Sdt207653 } 477f3af4981Sdt207653 } 478f3af4981Sdt207653 } 4797c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen && field[i]; i++) 4807c478bd9Sstevel@tonic-gate safeputchar(field[i]); 4817c478bd9Sstevel@tonic-gate return; 4827c478bd9Sstevel@tonic-gate case FDTYPE_Enumeration: 4837c478bd9Sstevel@tonic-gate value = 0; 4847c478bd9Sstevel@tonic-gate (void) memcpy((((uint8_t *)&value) + sizeof (value) 4857c478bd9Sstevel@tonic-gate - def->payloadLen), 4867c478bd9Sstevel@tonic-gate field, def->payloadLen); 4877c478bd9Sstevel@tonic-gate for (i = 0; i < def->enumCount; i++) 4887c478bd9Sstevel@tonic-gate if (def->enumTable[i].value == value) { 489f3af4981Sdt207653 if (strcmp(def->name, "Event_Code") == 0) { 490f3af4981Sdt207653 if (strcmp(def->enumTable[i].text, 491f3af4981Sdt207653 "FMA Message R") == 0) 492f3af4981Sdt207653 FMAmessageR = 1; 493f3af4981Sdt207653 else 494f3af4981Sdt207653 if (strcmp(def->enumTable[i].text, 495f3af4981Sdt207653 "FMA Event Data R") == 0) 496f3af4981Sdt207653 FMAmessageR = 0; 497f3af4981Sdt207653 } 4987c478bd9Sstevel@tonic-gate safeputs(def->enumTable[i].text); 4997c478bd9Sstevel@tonic-gate return; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate errmsg = "unrecognized value"; 5037c478bd9Sstevel@tonic-gate break; 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate /* If nothing matched above, print the field in hex */ 507f3af4981Sdt207653 switch (def->dispType) { 508f3af4981Sdt207653 case FDISP_MSGID: 509f3af4981Sdt207653 (void) memcpy((uchar_t *)&first_byte, field, 1); 510f3af4981Sdt207653 if (isprint(first_byte)) { 511f3af4981Sdt207653 for (i = 0; i < def->payloadLen && field[i]; 512f3af4981Sdt207653 i++) 513f3af4981Sdt207653 safeputchar(field[i]); 514f3af4981Sdt207653 } 515f3af4981Sdt207653 break; 516f3af4981Sdt207653 case FDISP_UUID: 517f3af4981Sdt207653 for (i = 0; i < def->payloadLen; i++) { 518f3af4981Sdt207653 if ((i == 4) || (i == 6) || 519f3af4981Sdt207653 (i == 8) || (i == 10)) 520f3af4981Sdt207653 output("-"); 521f3af4981Sdt207653 output("%2.2x", field[i]); 522f3af4981Sdt207653 } 523f3af4981Sdt207653 break; 524f3af4981Sdt207653 default: 5257c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen; i++) 5267c478bd9Sstevel@tonic-gate output("%2.2X", field[i]); 527f3af4981Sdt207653 break; 528f3af4981Sdt207653 } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* Safely print any error message associated with the field */ 5317c478bd9Sstevel@tonic-gate if (errmsg) { 532f3af4981Sdt207653 if (strcmp(def->name, "Fault_Diag_Secs") != 0) { 5337c478bd9Sstevel@tonic-gate output(" ("); 5347c478bd9Sstevel@tonic-gate safeputs(errmsg); 535f3af4981Sdt207653 output(")"); 536f3af4981Sdt207653 } 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* 5417c478bd9Sstevel@tonic-gate * Recursively print the contents of a data element 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate static void 5447c478bd9Sstevel@tonic-gate print_element(const uint8_t *data, const fru_regdef_t *def, 5457c478bd9Sstevel@tonic-gate const char *parent_path, int indent) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate char *path; 5487c478bd9Sstevel@tonic-gate size_t len; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate int bytes = 0, i; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate indent = (xml) ? (indent + INDENT) : (2*INDENT); 5547c478bd9Sstevel@tonic-gate /* 5557c478bd9Sstevel@tonic-gate * Construct the path, or, for XML, the name, for the current 5567c478bd9Sstevel@tonic-gate * data element 5577c478bd9Sstevel@tonic-gate */ 5587c478bd9Sstevel@tonic-gate if ((def->iterationCount == 0) && 5597c478bd9Sstevel@tonic-gate (def->iterationType != FRU_NOT_ITERATED)) { 5607c478bd9Sstevel@tonic-gate if (xml) { 5617c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Record) { 5627c478bd9Sstevel@tonic-gate len = strlen("Index_") + strlen(def->name) + 1; 5637c478bd9Sstevel@tonic-gate path = alloca(len); 5647c478bd9Sstevel@tonic-gate (void) snprintf(path, len, 5657c478bd9Sstevel@tonic-gate "Index_%s", def->name); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate else 5687c478bd9Sstevel@tonic-gate path = "Index"; 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate else 5717c478bd9Sstevel@tonic-gate path = (char *)parent_path; 5727c478bd9Sstevel@tonic-gate } else { 5737c478bd9Sstevel@tonic-gate if (xml) 5747c478bd9Sstevel@tonic-gate path = (char *)def->name; 5757c478bd9Sstevel@tonic-gate else { 5767c478bd9Sstevel@tonic-gate len = strlen(parent_path) + sizeof ("/") + 5777c478bd9Sstevel@tonic-gate strlen(def->name) + 5787c478bd9Sstevel@tonic-gate (def->iterationCount ? sizeof ("[255]") : 0); 5797c478bd9Sstevel@tonic-gate path = alloca(len); 5807c478bd9Sstevel@tonic-gate bytes = snprintf(path, len, 5817c478bd9Sstevel@tonic-gate "%s/%s", parent_path, def->name); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * Handle the various categories of data elements: iteration, 5877c478bd9Sstevel@tonic-gate * record, and field 5887c478bd9Sstevel@tonic-gate */ 5897c478bd9Sstevel@tonic-gate if (def->iterationCount) { 5907c478bd9Sstevel@tonic-gate int iterlen = (def->payloadLen - NUM_ITER_BYTES)/ 5917c478bd9Sstevel@tonic-gate def->iterationCount, 5927c478bd9Sstevel@tonic-gate n, valid = 1; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate uint8_t head, num; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate fru_regdef_t newdef; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* 6007c478bd9Sstevel@tonic-gate * Make a new element definition to describe the components 6017c478bd9Sstevel@tonic-gate * of the iteration 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate (void) memcpy(&newdef, def, sizeof (newdef)); 6047c478bd9Sstevel@tonic-gate newdef.iterationCount = 0; 6057c478bd9Sstevel@tonic-gate newdef.payloadLen = iterlen; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate /* 6087c478bd9Sstevel@tonic-gate * Validate the contents of the iteration control bytes 6097c478bd9Sstevel@tonic-gate */ 6107c478bd9Sstevel@tonic-gate if (data[HEAD_ITER] >= def->iterationCount) { 6117c478bd9Sstevel@tonic-gate valid = 0; 6127c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration head: %d " 6137c478bd9Sstevel@tonic-gate "(should be less than %d)\n"), 6147c478bd9Sstevel@tonic-gate path, data[HEAD_ITER], def->iterationCount); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate if (data[NUM_ITER] > def->iterationCount) { 6187c478bd9Sstevel@tonic-gate valid = 0; 6197c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration count: %d " 6207c478bd9Sstevel@tonic-gate "(should not be greater than %d)\n"), 6217c478bd9Sstevel@tonic-gate path, data[NUM_ITER], def->iterationCount); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate if (data[MAX_ITER] != def->iterationCount) { 6257c478bd9Sstevel@tonic-gate valid = 0; 6267c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration maximum: %d " 6277c478bd9Sstevel@tonic-gate "(should equal %d)\n"), 6287c478bd9Sstevel@tonic-gate path, data[MAX_ITER], def->iterationCount); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate if (valid) { 6327c478bd9Sstevel@tonic-gate head = data[HEAD_ITER]; 6337c478bd9Sstevel@tonic-gate num = data[NUM_ITER]; 6347c478bd9Sstevel@tonic-gate } else { 6357c478bd9Sstevel@tonic-gate head = 0; 6367c478bd9Sstevel@tonic-gate num = def->iterationCount; 6377c478bd9Sstevel@tonic-gate error(gettext("%s: Showing all iterations\n"), path); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate if (xml) 6417c478bd9Sstevel@tonic-gate output("%*s<%s>\n", indent, "", path); 6427c478bd9Sstevel@tonic-gate else 6437c478bd9Sstevel@tonic-gate output("%*s%s (%d iterations)\n", indent, "", path, 6447c478bd9Sstevel@tonic-gate num); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * Print each component of the iteration 6487c478bd9Sstevel@tonic-gate */ 6497c478bd9Sstevel@tonic-gate for (i = head, n = 0, data += 4; 6507c478bd9Sstevel@tonic-gate n < num; 6517c478bd9Sstevel@tonic-gate i = ((i + 1) % def->iterationCount), n++) { 6527c478bd9Sstevel@tonic-gate if (!xml) (void) sprintf((path + bytes), "[%d]", n); 653f3af4981Sdt207653 iterglobal = n; 6547c478bd9Sstevel@tonic-gate print_element((data + i*iterlen), &newdef, path, 6557c478bd9Sstevel@tonic-gate indent); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (xml) output("%*s</%s>\n", indent, "", path); 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate } else if (def->dataType == FDTYPE_Record) { 6617c478bd9Sstevel@tonic-gate const fru_regdef_t *component; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (xml) 6647c478bd9Sstevel@tonic-gate output("%*s<%s>\n", indent, "", path); 6657c478bd9Sstevel@tonic-gate else 6667c478bd9Sstevel@tonic-gate output("%*s%s\n", indent, "", path); 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate /* 6697c478bd9Sstevel@tonic-gate * Print each component of the record 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate for (i = 0; i < def->enumCount; 6727c478bd9Sstevel@tonic-gate i++, data += component->payloadLen) { 6737c478bd9Sstevel@tonic-gate component = fru_reg_lookup_def_by_name( 6747c478bd9Sstevel@tonic-gate def->enumTable[i].text); 6757c478bd9Sstevel@tonic-gate assert(component != NULL); 6767c478bd9Sstevel@tonic-gate print_element(data, component, path, indent); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate if (xml) output("%*s</%s>\n", indent, "", path); 6807c478bd9Sstevel@tonic-gate } else if (xml) { 6817c478bd9Sstevel@tonic-gate /* 6827c478bd9Sstevel@tonic-gate * Base case: print the field formatted for XML 6837c478bd9Sstevel@tonic-gate */ 6847c478bd9Sstevel@tonic-gate char *format = ((def == &unknown) 6857c478bd9Sstevel@tonic-gate ? "%*s<UNKNOWN tag=\"%s\" value=\"" 6867c478bd9Sstevel@tonic-gate : "%*s<%s value=\""); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate output(format, indent, "", path); 6897c478bd9Sstevel@tonic-gate print_field(data, def); 6907c478bd9Sstevel@tonic-gate /*CSTYLED*/ 6917c478bd9Sstevel@tonic-gate output("\"/>\n"); /* \" confuses cstyle */ 692f3af4981Sdt207653 693f3af4981Sdt207653 if ((strcmp(def->name, "Message") == 0) && 694f3af4981Sdt207653 ((FMAmessageR == 0) || (FMAmessageR == 1))) { 695f3af4981Sdt207653 const char *elem_name = NULL; 696f3af4981Sdt207653 const char *parent_path; 697f3af4981Sdt207653 uchar_t tmpdata[128]; 698f3af4981Sdt207653 char path[16384]; 699f3af4981Sdt207653 const fru_regdef_t *new_def; 700f3af4981Sdt207653 701f3af4981Sdt207653 if (FMAmessageR == 0) 702f3af4981Sdt207653 elem_name = "FMA_Event_DataR"; 703f3af4981Sdt207653 else if (FMAmessageR == 1) 704f3af4981Sdt207653 elem_name = "FMA_MessageR"; 705f3af4981Sdt207653 if (elem_name != NULL) { 706f3af4981Sdt207653 (void) memcpy(tmpdata, data, def->payloadLen); 707f3af4981Sdt207653 new_def = fru_reg_lookup_def_by_name(elem_name); 708*77acf672Sdt207653 (void) snprintf(path, sizeof (path), 709f3af4981Sdt207653 "/Status_EventsR[%d]/Message(FMA)", iterglobal); 710f3af4981Sdt207653 parent_path = path; 711f3af4981Sdt207653 print_element(tmpdata, new_def, 712f3af4981Sdt207653 parent_path, 2*INDENT); 713f3af4981Sdt207653 FMAmessageR = -1; 714f3af4981Sdt207653 } 715f3af4981Sdt207653 } 716f3af4981Sdt207653 7177c478bd9Sstevel@tonic-gate } else { 7187c478bd9Sstevel@tonic-gate /* 7197c478bd9Sstevel@tonic-gate * Base case: print the field 7207c478bd9Sstevel@tonic-gate */ 7217c478bd9Sstevel@tonic-gate output("%*s%s: ", indent, "", path); 7227c478bd9Sstevel@tonic-gate print_field(data, def); 7237c478bd9Sstevel@tonic-gate output("\n"); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate /* 7287c478bd9Sstevel@tonic-gate * Print the contents of a packet (i.e., a tagged data element) 7297c478bd9Sstevel@tonic-gate */ 7307c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7317c478bd9Sstevel@tonic-gate static int 7327c478bd9Sstevel@tonic-gate print_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args) 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate int tag_type = get_tag_type(tag); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate size_t payload_length = 0; 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate const fru_regdef_t *def; 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate /* 7417c478bd9Sstevel@tonic-gate * Build a definition for unrecognized tags (e.g., not in libfrureg) 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate if ((tag_type == -1) || 7447c478bd9Sstevel@tonic-gate ((payload_length = get_payload_length(tag)) != length)) { 7457c478bd9Sstevel@tonic-gate def = &unknown; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate unknown.tagType = -1; 7487c478bd9Sstevel@tonic-gate unknown.tagDense = -1; 7497c478bd9Sstevel@tonic-gate unknown.payloadLen = length; 7507c478bd9Sstevel@tonic-gate unknown.dataLength = unknown.payloadLen; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate if (tag_type == -1) 7537c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), "INVALID"); 7547c478bd9Sstevel@tonic-gate else 7557c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), 7567c478bd9Sstevel@tonic-gate "%s_%u_%u_%u", get_tagtype_str(tag_type), 7577c478bd9Sstevel@tonic-gate get_tag_dense(tag), payload_length, length); 7587c478bd9Sstevel@tonic-gate } else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) { 7597c478bd9Sstevel@tonic-gate def = &unknown; 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate unknown.tagType = tag_type; 7627c478bd9Sstevel@tonic-gate unknown.tagDense = get_tag_dense(tag); 7637c478bd9Sstevel@tonic-gate unknown.payloadLen = payload_length; 7647c478bd9Sstevel@tonic-gate unknown.dataLength = unknown.payloadLen; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), "%s_%u_%u", 7677c478bd9Sstevel@tonic-gate get_tagtype_str(unknown.tagType), 7687c478bd9Sstevel@tonic-gate unknown.tagDense, payload_length); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * Print the defined element 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate print_element(payload, def, "", INDENT); 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate /* 7817c478bd9Sstevel@tonic-gate * Print a segment's name and the contents of each data element in the segment 7827c478bd9Sstevel@tonic-gate */ 7837c478bd9Sstevel@tonic-gate static int 7847c478bd9Sstevel@tonic-gate print_packets_in_segment(fru_seghdl_t segment, void *args) 7857c478bd9Sstevel@tonic-gate { 7867c478bd9Sstevel@tonic-gate char *name; 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate int status; 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate if ((status = fru_get_segment_name(segment, &name)) != FRU_SUCCESS) { 7927c478bd9Sstevel@tonic-gate saved_status = status; 7937c478bd9Sstevel@tonic-gate name = ""; 7947c478bd9Sstevel@tonic-gate error(gettext("Error getting segment name: %s\n"), 7957c478bd9Sstevel@tonic-gate fru_strerror(status)); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate if (xml) 8007c478bd9Sstevel@tonic-gate output("%*s<Segment name=\"%s\">\n", INDENT, "", name); 8017c478bd9Sstevel@tonic-gate else 8027c478bd9Sstevel@tonic-gate output("%*sSEGMENT: %s\n", INDENT, "", name); 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* Iterate over the packets in the segment, printing the contents */ 8057c478bd9Sstevel@tonic-gate if ((status = fru_for_each_packet(segment, print_packet, args)) 8067c478bd9Sstevel@tonic-gate != FRU_SUCCESS) { 8077c478bd9Sstevel@tonic-gate saved_status = status; 8087c478bd9Sstevel@tonic-gate error(gettext("Error processing data in segment \"%s\": %s\n"), 8097c478bd9Sstevel@tonic-gate name, fru_strerror(status)); 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate if (xml) output("%*s</Segment>\n", INDENT, ""); 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate free(name); 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8207c478bd9Sstevel@tonic-gate static void 8217c478bd9Sstevel@tonic-gate print_node_path(fru_node_t fru_type, const char *path, const char *name, 8227c478bd9Sstevel@tonic-gate end_node_fp_t *end_node, void **end_args) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate output("%s%s\n", path, 8257c478bd9Sstevel@tonic-gate ((fru_type == FRU_NODE_CONTAINER) ? " (container)" 8267c478bd9Sstevel@tonic-gate : ((fru_type == FRU_NODE_FRU) ? " (fru)" : ""))); 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate /* 8307c478bd9Sstevel@tonic-gate * Close the XML element for a "location" node 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8337c478bd9Sstevel@tonic-gate static void 8347c478bd9Sstevel@tonic-gate end_location_xml(fru_nodehdl_t node, const char *path, const char *name, 8357c478bd9Sstevel@tonic-gate void *args) 8367c478bd9Sstevel@tonic-gate { 8377c478bd9Sstevel@tonic-gate assert(args != NULL); 8387c478bd9Sstevel@tonic-gate output("</Location> <!-- %s -->\n", args); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate /* 8427c478bd9Sstevel@tonic-gate * Close the XML element for a "fru" node 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8457c478bd9Sstevel@tonic-gate static void 8467c478bd9Sstevel@tonic-gate end_fru_xml(fru_nodehdl_t node, const char *path, const char *name, void *args) 8477c478bd9Sstevel@tonic-gate { 8487c478bd9Sstevel@tonic-gate assert(args != NULL); 8497c478bd9Sstevel@tonic-gate output("</Fru> <!-- %s -->\n", args); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate /* 8537c478bd9Sstevel@tonic-gate * Close the XML element for a "container" node 8547c478bd9Sstevel@tonic-gate */ 8557c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8567c478bd9Sstevel@tonic-gate static void 8577c478bd9Sstevel@tonic-gate end_container_xml(fru_nodehdl_t node, const char *path, const char *name, 8587c478bd9Sstevel@tonic-gate void *args) 8597c478bd9Sstevel@tonic-gate { 8607c478bd9Sstevel@tonic-gate assert(args != NULL); 8617c478bd9Sstevel@tonic-gate output("</Container> <!-- %s -->\n", args); 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * Introduce a node in XML and set the appropriate node-closing function 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8687c478bd9Sstevel@tonic-gate static void 8697c478bd9Sstevel@tonic-gate print_node_xml(fru_node_t fru_type, const char *path, const char *name, 8707c478bd9Sstevel@tonic-gate end_node_fp_t *end_node, void **end_args) 8717c478bd9Sstevel@tonic-gate { 8727c478bd9Sstevel@tonic-gate switch (fru_type) { 8737c478bd9Sstevel@tonic-gate case FRU_NODE_FRU: 8747c478bd9Sstevel@tonic-gate output("<Fru name=\"%s\">\n", name); 8757c478bd9Sstevel@tonic-gate *end_node = end_fru_xml; 8767c478bd9Sstevel@tonic-gate break; 8777c478bd9Sstevel@tonic-gate case FRU_NODE_CONTAINER: 8787c478bd9Sstevel@tonic-gate output("<Container name=\"%s\">\n", name); 8797c478bd9Sstevel@tonic-gate *end_node = end_container_xml; 8807c478bd9Sstevel@tonic-gate break; 8817c478bd9Sstevel@tonic-gate default: 8827c478bd9Sstevel@tonic-gate output("<Location name=\"%s\">\n", name); 8837c478bd9Sstevel@tonic-gate *end_node = end_location_xml; 8847c478bd9Sstevel@tonic-gate break; 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate *end_args = (void *) name; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate /* 8917c478bd9Sstevel@tonic-gate * Print node info and, where appropriate, node contents 8927c478bd9Sstevel@tonic-gate */ 8937c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8947c478bd9Sstevel@tonic-gate static fru_errno_t 8957c478bd9Sstevel@tonic-gate process_node(fru_nodehdl_t node, const char *path, const char *name, 8967c478bd9Sstevel@tonic-gate void *args, end_node_fp_t *end_node, void **end_args) 8977c478bd9Sstevel@tonic-gate { 8987c478bd9Sstevel@tonic-gate int status; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate fru_node_t fru_type = FRU_NODE_UNKNOWN; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate if ((status = fru_get_node_type(node, &fru_type)) != FRU_SUCCESS) { 9047c478bd9Sstevel@tonic-gate saved_status = status; 9057c478bd9Sstevel@tonic-gate error(gettext("Error getting node type: %s\n"), 9067c478bd9Sstevel@tonic-gate fru_strerror(status)); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate if (containers_only) { 9107c478bd9Sstevel@tonic-gate if (fru_type != FRU_NODE_CONTAINER) 9117c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 9127c478bd9Sstevel@tonic-gate name = path; 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* Introduce the node */ 9167c478bd9Sstevel@tonic-gate assert(print_node != NULL); 9177c478bd9Sstevel@tonic-gate print_node(fru_type, path, name, end_node, end_args); 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (list_only) 9207c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* Print the contents of each packet in each segment of a container */ 9237c478bd9Sstevel@tonic-gate if (fru_type == FRU_NODE_CONTAINER) { 9247c478bd9Sstevel@tonic-gate if (xml) output("<ContainerData>\n"); 9257c478bd9Sstevel@tonic-gate if ((status = 9267c478bd9Sstevel@tonic-gate fru_for_each_segment(node, print_packets_in_segment, 9277c478bd9Sstevel@tonic-gate NULL)) 9287c478bd9Sstevel@tonic-gate != FRU_SUCCESS) { 9297c478bd9Sstevel@tonic-gate saved_status = status; 9307c478bd9Sstevel@tonic-gate error(gettext("Error processing node \"%s\": %s\n"), 9317c478bd9Sstevel@tonic-gate name, fru_strerror(status)); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate if (xml) output("</ContainerData>\n"); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * Process the node if its path matches the search path in "args" 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9437c478bd9Sstevel@tonic-gate static fru_errno_t 9447c478bd9Sstevel@tonic-gate process_matching_node(fru_nodehdl_t node, const char *path, const char *name, 9457c478bd9Sstevel@tonic-gate void *args, end_node_fp_t *end_node, void **end_args) 9467c478bd9Sstevel@tonic-gate { 9477c478bd9Sstevel@tonic-gate int status; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate if (!fru_pathmatch(path, args)) 9517c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate status = process_node(node, path, path, args, end_node, end_args); 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate return ((status == FRU_SUCCESS) ? FRU_WALK_TERMINATE : status); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 9597c478bd9Sstevel@tonic-gate * Write the trailer required for well-formed DTD-compliant XML 9607c478bd9Sstevel@tonic-gate */ 9617c478bd9Sstevel@tonic-gate static void 9627c478bd9Sstevel@tonic-gate terminate_xml() 9637c478bd9Sstevel@tonic-gate { 9647c478bd9Sstevel@tonic-gate errno = 0; 9657c478bd9Sstevel@tonic-gate if (ftell(errlog) > 0) { 9667c478bd9Sstevel@tonic-gate char c; 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate output("<ErrorLog>\n"); 9697c478bd9Sstevel@tonic-gate rewind(errlog); 9707c478bd9Sstevel@tonic-gate if (!errno) 9717c478bd9Sstevel@tonic-gate while ((c = getc(errlog)) != EOF) 9727c478bd9Sstevel@tonic-gate xputchar(c); 9737c478bd9Sstevel@tonic-gate output("</ErrorLog>\n"); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate if (errno) { 9777c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 9787c478bd9Sstevel@tonic-gate errlog = NULL; 9797c478bd9Sstevel@tonic-gate error(gettext("Error copying error messages to \"ErrorLog\""), 9807c478bd9Sstevel@tonic-gate strerror(errno)); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate output("</FRUID_XML_Tree>\n"); 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate /* 9877c478bd9Sstevel@tonic-gate * Print available FRU ID information 9887c478bd9Sstevel@tonic-gate */ 9897c478bd9Sstevel@tonic-gate int 9907c478bd9Sstevel@tonic-gate prtfru(const char *searchpath, int containers_only_flag, int list_only_flag, 9917c478bd9Sstevel@tonic-gate int xml_flag) 9927c478bd9Sstevel@tonic-gate { 9937c478bd9Sstevel@tonic-gate fru_errno_t status; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate fru_nodehdl_t frutree = 0; 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate /* Copy parameter flags to global flags */ 9997c478bd9Sstevel@tonic-gate containers_only = containers_only_flag; 10007c478bd9Sstevel@tonic-gate list_only = list_only_flag; 10017c478bd9Sstevel@tonic-gate xml = xml_flag; 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate /* Help arrange for correct, efficient interleaving of output */ 10057c478bd9Sstevel@tonic-gate (void) setvbuf(stderr, NULL, _IOLBF, 0); 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate /* Initialize for XML--or not */ 10097c478bd9Sstevel@tonic-gate if (xml) { 10107c478bd9Sstevel@tonic-gate safeputchar = xputchar; 10117c478bd9Sstevel@tonic-gate safeputs = xputs; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate print_node = print_node_xml; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate if ((errlog = tmpfile()) == NULL) { 10167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10177c478bd9Sstevel@tonic-gate "Error creating error log file: %s\n", 10187c478bd9Sstevel@tonic-gate strerror(errno)); 10197c478bd9Sstevel@tonic-gate return (1); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate /* Output the XML preamble */ 10237c478bd9Sstevel@tonic-gate output("<?xml version=\"1.0\" ?>\n" 10247c478bd9Sstevel@tonic-gate "<!--\n" 10257c478bd9Sstevel@tonic-gate " Copyright 2000-2002 Sun Microsystems, Inc. " 10267c478bd9Sstevel@tonic-gate "All rights reserved.\n" 10277c478bd9Sstevel@tonic-gate " Use is subject to license terms.\n" 10287c478bd9Sstevel@tonic-gate "-->\n\n" 10297c478bd9Sstevel@tonic-gate "<!DOCTYPE FRUID_XML_Tree SYSTEM \"prtfrureg.dtd\">\n\n" 10307c478bd9Sstevel@tonic-gate "<FRUID_XML_Tree>\n"); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* Arrange to always properly terminate XML */ 10337c478bd9Sstevel@tonic-gate if (atexit(terminate_xml)) 10347c478bd9Sstevel@tonic-gate error(gettext("Warning: XML will not be terminated: " 10357c478bd9Sstevel@tonic-gate "%s\n"), strerror(errno)); 10367c478bd9Sstevel@tonic-gate } else 10377c478bd9Sstevel@tonic-gate print_node = print_node_path; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* Get the root node */ 10417c478bd9Sstevel@tonic-gate if ((status = fru_get_root(&frutree)) == FRU_NODENOTFOUND) { 10427c478bd9Sstevel@tonic-gate error(gettext("This system does not provide FRU ID data\n")); 10437c478bd9Sstevel@tonic-gate return (1); 10447c478bd9Sstevel@tonic-gate } else if (status != FRU_SUCCESS) { 10457c478bd9Sstevel@tonic-gate error(gettext("Unable to access FRU ID data: %s\n"), 10467c478bd9Sstevel@tonic-gate fru_strerror(status)); 10477c478bd9Sstevel@tonic-gate return (1); 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate /* Process the tree */ 10517c478bd9Sstevel@tonic-gate if (searchpath == NULL) { 10527c478bd9Sstevel@tonic-gate status = fru_walk_tree(frutree, "", process_node, NULL); 10537c478bd9Sstevel@tonic-gate } else { 10547c478bd9Sstevel@tonic-gate status = fru_walk_tree(frutree, "", process_matching_node, 10557c478bd9Sstevel@tonic-gate (void *)searchpath); 10567c478bd9Sstevel@tonic-gate if (status == FRU_WALK_TERMINATE) { 10577c478bd9Sstevel@tonic-gate status = FRU_SUCCESS; 10587c478bd9Sstevel@tonic-gate } else if (status == FRU_SUCCESS) { 10597c478bd9Sstevel@tonic-gate error(gettext("\"%s\" not found\n"), searchpath); 10607c478bd9Sstevel@tonic-gate return (1); 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (status != FRU_SUCCESS) 10657c478bd9Sstevel@tonic-gate error(gettext("Error processing FRU tree: %s\n"), 10667c478bd9Sstevel@tonic-gate fru_strerror(status)); 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate return (((status == FRU_SUCCESS) && (saved_status == 0)) ? 0 : 1); 10697c478bd9Sstevel@tonic-gate } 1070