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 /*
22043728a3Sdt207653 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <alloca.h>
277c478bd9Sstevel@tonic-gate #include <assert.h>
287c478bd9Sstevel@tonic-gate #include <errno.h>
297c478bd9Sstevel@tonic-gate #include <libintl.h>
307c478bd9Sstevel@tonic-gate #include <stdarg.h>
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
34f3af4981Sdt207653 #include <ctype.h>
35*48215d30SDipti Tarai #include <wchar.h>
36*48215d30SDipti Tarai #include <wctype.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
535bc0fc0eSdt207653 #define MIN_VERSION 17
54bdad7b9cSaa222140 #define GMT "%a, %b %d %Y %H:%M:%S GMT"
557c478bd9Sstevel@tonic-gate
56*48215d30SDipti Tarai typedef struct
57*48215d30SDipti Tarai {
58*48215d30SDipti Tarai uint8_t value;
59*48215d30SDipti Tarai char *data;
60*48215d30SDipti Tarai } Status_CurrentR;
61*48215d30SDipti Tarai
62*48215d30SDipti Tarai Status_CurrentR Status_CurrentR_status[] = {
63*48215d30SDipti Tarai { 0x00, "OK"},
64*48215d30SDipti Tarai { 0x04, "DEEMED FAULTY"},
65*48215d30SDipti Tarai { 0x08, "FRU DETECTED"},
66*48215d30SDipti Tarai { 0x0c, "FRU DETECTED, DEEMED FAULTY"},
67*48215d30SDipti Tarai { 0x10, "PROXIED FAULT"},
68*48215d30SDipti Tarai { 0x14, "DEEMED FAULTY. Also PROXIED FAULT"},
69*48215d30SDipti Tarai { 0x18, "FRU DETECTED. Also PROXIED FAULT"},
70*48215d30SDipti Tarai { 0x1c, "FRU DETECTED, DEEMED FAULTY. Also PROXIED FAULT"},
71*48215d30SDipti Tarai { 0x20, "SUSPECT"},
72*48215d30SDipti Tarai { 0x24, "SUSPECT, DEEMED FAULTY"},
73*48215d30SDipti Tarai { 0x28, "SUSPECT, FRU DETECTED"},
74*48215d30SDipti Tarai { 0x2c, "SUSPECT, FRU DETECTED, DEEMED FAULTY"},
75*48215d30SDipti Tarai { 0x30, "SUSPECT. Also PROXIED FAULT"},
76*48215d30SDipti Tarai { 0x34, "SUSPECT, DEEMED FAULTY. Also PROXIED FAULT"},
77*48215d30SDipti Tarai { 0x38, "SUSPECT, FRU DETECTED. Also PROXIED FAULT"},
78*48215d30SDipti Tarai { 0x3c, "SUSPECT, FRU DETECTED, DEEMED FAULTY. Also PROXIED FAULT"},
79*48215d30SDipti Tarai { 0x40, "MAINTENANCE REQUIRED"},
80*48215d30SDipti Tarai { 0x44, "MAINTENANCE REQUIRED, DEEMED FAULTY"},
81*48215d30SDipti Tarai { 0x48, "MAINTENANCE REQUIRED, FRU DETECTED"},
82*48215d30SDipti Tarai { 0x4c, "MAINTENANCE REQUIRED, FRU DETECTED, DEEMED FAULTY"},
83*48215d30SDipti Tarai { 0x50, "MAINTENANCE REQUIRED. Also PROXIED FAULT"},
84*48215d30SDipti Tarai { 0x54, "MAINTENANCE REQUIRED, DEEMED FAULTY. Also PROXIED FAULT"},
85*48215d30SDipti Tarai { 0x58, "MAINTENANCE REQUIRED, FRU DETECTED. Also PROXIED FAULT"},
86*48215d30SDipti Tarai { 0x5c, "MAINTENANCE REQUIRED, FRU DETECTED, DEEMED FAULTY. \
87*48215d30SDipti Tarai Also PROXIED FAULT"},
88*48215d30SDipti Tarai { 0x60, "MAINTENANCE REQUIRED, SUSPECT"},
89*48215d30SDipti Tarai { 0x64, "MAINTENANCE REQUIRED, SUSPECT, DEEMED FAULTY"},
90*48215d30SDipti Tarai { 0x68, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED"},
91*48215d30SDipti Tarai { 0x6c, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED, DEEMED FAULTY"},
92*48215d30SDipti Tarai { 0x70, "MAINTENANCE REQUIRED, SUSPECT. Also PROXIED FAULT"},
93*48215d30SDipti Tarai { 0x74, "MAINTENANCE REQUIRED, SUSPECT, DEEMED FAULTY.\
94*48215d30SDipti Tarai Also PROXIED FAULT"},
95*48215d30SDipti Tarai { 0x78, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED. \
96*48215d30SDipti Tarai Also PROXIED FAULT"},
97*48215d30SDipti Tarai { 0x7c, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED, \
98*48215d30SDipti Tarai DEEMED FAULTY. Also PROXIED FAULT"},
99*48215d30SDipti Tarai { 0x80, "DISABLED"},
100*48215d30SDipti Tarai { 0x84, "DISABLED, DEEMED FAULTY"},
101*48215d30SDipti Tarai { 0x88, "DISABLED, FRU DETECTED"},
102*48215d30SDipti Tarai { 0x8c, "DISABLED, FRU DETECTED, DEEMED FAULTY"},
103*48215d30SDipti Tarai { 0x90, "DISABLED. Also PROXIED FAULT"},
104*48215d30SDipti Tarai { 0x94, "DISABLED, DEEMED FAULTY. Also PROXIED FAULT"},
105*48215d30SDipti Tarai { 0x98, "DISABLED, FRU DETECTED. Also PROXIED FAULT"},
106*48215d30SDipti Tarai { 0x9c, "DISABLED, FRU DETECTED, DEEMED FAULTY. Also PROXIED FAULT"},
107*48215d30SDipti Tarai { 0xa0, "DISABLED, SUSPECT"},
108*48215d30SDipti Tarai { 0xa4, "DISABLED, SUSPECT, DEEMED FAULTY"},
109*48215d30SDipti Tarai { 0xa8, "DISABLED, SUSPECT, FRU DETECTED"},
110*48215d30SDipti Tarai { 0xac, "DISABLED, SUSPECT, FRU DETECTED, DEEMED FAULTY"},
111*48215d30SDipti Tarai { 0xb0, "DISABLED, SUSPECT. Also PROXIED FAULT"},
112*48215d30SDipti Tarai { 0xb4, "DISABLED, SUSPECT, DEEMED FAULTY. Also PROXIED FAULT"},
113*48215d30SDipti Tarai { 0xb8, "DISABLED, SUSPECT, FRU DETECTED. Also PROXIED FAULT"},
114*48215d30SDipti Tarai { 0xbc, "DISABLED, SUSPECT, FRU DETECTED, \
115*48215d30SDipti Tarai DEEMED FAULTY. Also PROXIED FAULT"},
116*48215d30SDipti Tarai { 0xc0, "DISABLED, MAINTENANCE REQUIRED"},
117*48215d30SDipti Tarai { 0xc4, "DISABLED, MAINTENANCE REQUIRED, DEEMED FAULTY"},
118*48215d30SDipti Tarai { 0xc8, "DISABLED, MAINTENANCE REQUIRED, FRU DETECTED"},
119*48215d30SDipti Tarai { 0xcc, "DISABLED, MAINTENANCE REQUIRED, FRU DETECTED, DEEMED FAULTY"},
120*48215d30SDipti Tarai { 0xd0, "DISABLED, MAINTENANCE REQUIRED. Also PROXIED FAULT"},
121*48215d30SDipti Tarai { 0xd4, "DISABLED, MAINTENANCE REQUIRED, \
122*48215d30SDipti Tarai DEEMED FAULTY. Also PROXIED FAULT"},
123*48215d30SDipti Tarai { 0xd8, "DISABLED, MAINTENANCE REQUIRED, \
124*48215d30SDipti Tarai FRU DETECTED. Also PROXIED FAULT"},
125*48215d30SDipti Tarai { 0xdc, "DISABLED, MAINTENANCE REQUIRED, FRU DETECTED, \
126*48215d30SDipti Tarai DEEMED FAULTY. Also PROXIED FAULT"},
127*48215d30SDipti Tarai { 0xe0, "DISABLED, MAINTENANCE REQUIRED, SUSPECT"},
128*48215d30SDipti Tarai { 0xe4, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, DEEMED FAULTY"},
129*48215d30SDipti Tarai { 0xe8, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED"},
130*48215d30SDipti Tarai { 0xec, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
131*48215d30SDipti Tarai FRU DETECTED, DEEMED FAULTY"},
132*48215d30SDipti Tarai { 0xf0, "DISABLED, MAINTENANCE REQUIRED, SUSPECT. Also PROXIED FAULT"},
133*48215d30SDipti Tarai { 0xf4, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
134*48215d30SDipti Tarai DEEMED FAULTY. Also PROXIED FAULT"},
135*48215d30SDipti Tarai { 0xf8, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
136*48215d30SDipti Tarai FRU DETECTED. Also PROXIED FAULT"},
137*48215d30SDipti Tarai { 0xfc, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
138*48215d30SDipti Tarai FRU DETECTED, DEEMED FAULTY. Also PROXIED FAULT"},
139*48215d30SDipti Tarai { 0xff, "RETIRED"}
140*48215d30SDipti Tarai };
141*48215d30SDipti Tarai
1427c478bd9Sstevel@tonic-gate static void (*print_node)(fru_node_t fru_type, const char *path,
1437c478bd9Sstevel@tonic-gate const char *name, end_node_fp_t *end_node,
1447c478bd9Sstevel@tonic-gate void **end_args);
1457c478bd9Sstevel@tonic-gate
146f3af4981Sdt207653 static void print_element(const uint8_t *data, const fru_regdef_t *def,
147f3af4981Sdt207653 const char *parent_path, int indent);
148f3af4981Sdt207653
1497c478bd9Sstevel@tonic-gate static char tagname[sizeof ("?_0123456789_0123456789_0123456789")];
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate static int containers_only = 0, list_only = 0, saved_status = 0, xml = 0;
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate static FILE *errlog;
1547c478bd9Sstevel@tonic-gate
155f3af4981Sdt207653 int iterglobal = 0;
156f3af4981Sdt207653 int FMAmessageR = -1;
15746a7ef8aSdt207653 int Fault_Install_DataR_flag = 0;
15846a7ef8aSdt207653 int Power_On_DataR_flag = 0;
1595bc0fc0eSdt207653 int spd_memtype = 0;
1605bc0fc0eSdt207653 int spd_revision = 0;
1617c478bd9Sstevel@tonic-gate /*
1627c478bd9Sstevel@tonic-gate * Definition for data elements found in devices but not found in
1637c478bd9Sstevel@tonic-gate * the system's version of libfrureg
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate static fru_regdef_t unknown = {
1667c478bd9Sstevel@tonic-gate REGDEF_VERSION,
1677c478bd9Sstevel@tonic-gate tagname,
1687c478bd9Sstevel@tonic-gate -1,
1697c478bd9Sstevel@tonic-gate -1,
1707c478bd9Sstevel@tonic-gate -1,
1717c478bd9Sstevel@tonic-gate -1,
1727c478bd9Sstevel@tonic-gate FDTYPE_ByteArray,
1737c478bd9Sstevel@tonic-gate FDISP_Hex,
1747c478bd9Sstevel@tonic-gate FRU_WHICH_UNDEFINED,
1757c478bd9Sstevel@tonic-gate FRU_WHICH_UNDEFINED,
1767c478bd9Sstevel@tonic-gate 0,
1777c478bd9Sstevel@tonic-gate NULL,
1787c478bd9Sstevel@tonic-gate 0,
1797c478bd9Sstevel@tonic-gate FRU_NOT_ITERATED,
1807c478bd9Sstevel@tonic-gate NULL
1817c478bd9Sstevel@tonic-gate };
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate * Write message to standard error and possibly the error log buffer
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate static void
error(const char * format,...)1887c478bd9Sstevel@tonic-gate error(const char *format, ...)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate va_list args;
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /* make relevant output appear before error message */
1947c478bd9Sstevel@tonic-gate if (fflush(stdout) == EOF) {
1957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Error flushing output: %s\n",
1967c478bd9Sstevel@tonic-gate strerror(errno));
1977c478bd9Sstevel@tonic-gate exit(1);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate va_start(args, format);
2017c478bd9Sstevel@tonic-gate if (vfprintf(stderr, format, args) < 0) exit(1);
2027c478bd9Sstevel@tonic-gate if (errlog && (vfprintf(errlog, format, args) < 0)) exit(1);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate /*
2067c478bd9Sstevel@tonic-gate * Write message to standard output
2077c478bd9Sstevel@tonic-gate */
2087c478bd9Sstevel@tonic-gate static void
output(const char * format,...)2097c478bd9Sstevel@tonic-gate output(const char *format, ...)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate va_list args;
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate va_start(args, format);
2157c478bd9Sstevel@tonic-gate if (vfprintf(stdout, format, args) < 0) {
2167c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"),
2177c478bd9Sstevel@tonic-gate strerror(errno));
2187c478bd9Sstevel@tonic-gate exit(1);
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate * Safe wrapper for putchar()
2247c478bd9Sstevel@tonic-gate */
2257c478bd9Sstevel@tonic-gate static void
voidputchar(int c)2267c478bd9Sstevel@tonic-gate voidputchar(int c)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate if (putchar(c) == EOF) {
2297c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"),
2307c478bd9Sstevel@tonic-gate strerror(errno));
2317c478bd9Sstevel@tonic-gate exit(1);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate static void (*safeputchar)(int c) = voidputchar;
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate * Safe wrapper for puts()
2397c478bd9Sstevel@tonic-gate */
2407c478bd9Sstevel@tonic-gate static void
voidputs(const char * s)2417c478bd9Sstevel@tonic-gate voidputs(const char *s)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate if (fputs(s, stdout) == EOF) {
2447c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"),
2457c478bd9Sstevel@tonic-gate strerror(errno));
2467c478bd9Sstevel@tonic-gate exit(1);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate static void (*safeputs)(const char *s) = voidputs;
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate * XML-safe wrapper for putchar(): quotes XML-special characters
2547c478bd9Sstevel@tonic-gate */
2557c478bd9Sstevel@tonic-gate static void
xputchar(int c)2567c478bd9Sstevel@tonic-gate xputchar(int c)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate switch (c) {
2597c478bd9Sstevel@tonic-gate case '<':
2607c478bd9Sstevel@tonic-gate c = fputs("<", stdout);
2617c478bd9Sstevel@tonic-gate break;
2627c478bd9Sstevel@tonic-gate case '>':
2637c478bd9Sstevel@tonic-gate c = fputs(">", stdout);
2647c478bd9Sstevel@tonic-gate break;
2657c478bd9Sstevel@tonic-gate case '&':
2667c478bd9Sstevel@tonic-gate c = fputs("&", stdout);
2677c478bd9Sstevel@tonic-gate break;
2687c478bd9Sstevel@tonic-gate case '"':
2697c478bd9Sstevel@tonic-gate c = fputs(""", stdout);
2707c478bd9Sstevel@tonic-gate break;
2717c478bd9Sstevel@tonic-gate default:
2727c478bd9Sstevel@tonic-gate c = putchar(c);
2737c478bd9Sstevel@tonic-gate break;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate if (c == EOF) {
2777c478bd9Sstevel@tonic-gate error(gettext("Error writing output: %s\n"),
2787c478bd9Sstevel@tonic-gate strerror(errno));
2797c478bd9Sstevel@tonic-gate exit(1);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate * XML-safe analog of puts(): quotes XML-special characters
2857c478bd9Sstevel@tonic-gate */
2867c478bd9Sstevel@tonic-gate static void
xputs(const char * s)2877c478bd9Sstevel@tonic-gate xputs(const char *s)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate char c;
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate for (/* */; ((c = *s) != 0); s++)
2927c478bd9Sstevel@tonic-gate xputchar(c);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate * Output the XML DTD derived from the registry provided by libfrureg
2977c478bd9Sstevel@tonic-gate */
2987c478bd9Sstevel@tonic-gate int
output_dtd(void)2997c478bd9Sstevel@tonic-gate output_dtd(void)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate char **element;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate unsigned int i, j, num_elements = 0;
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate uint8_t *tagged;
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate const fru_regdef_t *def;
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate if (((element = fru_reg_list_entries(&num_elements)) == NULL) ||
3117c478bd9Sstevel@tonic-gate (num_elements == 0)) {
3127c478bd9Sstevel@tonic-gate error(gettext("No FRU ID Registry elements"));
3137c478bd9Sstevel@tonic-gate return (1);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate if ((tagged = calloc(num_elements, sizeof (*tagged))) == NULL) {
3177c478bd9Sstevel@tonic-gate error(gettext("Unable to get memory for tagged element list"),
3187c478bd9Sstevel@tonic-gate strerror(errno));
3197c478bd9Sstevel@tonic-gate return (1);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate /*
3237c478bd9Sstevel@tonic-gate * Output the DTD preamble
3247c478bd9Sstevel@tonic-gate */
3257c478bd9Sstevel@tonic-gate output("<!ELEMENT FRUID_XML_Tree (Parameter*, "
3267c478bd9Sstevel@tonic-gate "(Fru | Location | Container)*,\n"
3277c478bd9Sstevel@tonic-gate " Parameter*, ErrorLog?, Parameter*)>\n"
3287c478bd9Sstevel@tonic-gate "<!ATTLIST FRUID_XML_Tree>\n"
3297c478bd9Sstevel@tonic-gate "\n"
3307c478bd9Sstevel@tonic-gate "<!ELEMENT Parameter EMPTY>\n"
3317c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter type CDATA #REQUIRED>\n"
3327c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter name CDATA #REQUIRED>\n"
3337c478bd9Sstevel@tonic-gate "<!ATTLIST Parameter value CDATA #REQUIRED>\n"
3347c478bd9Sstevel@tonic-gate "\n"
3357c478bd9Sstevel@tonic-gate "<!ELEMENT Fru (Fru | Location | Container)*>\n"
3367c478bd9Sstevel@tonic-gate "<!ATTLIST Fru name CDATA #REQUIRED>\n"
3377c478bd9Sstevel@tonic-gate "\n"
3387c478bd9Sstevel@tonic-gate "<!ELEMENT Location (Fru | Location | Container)*>\n"
33994bc7577Sps154918 "<!ATTLIST Location\n"
34094bc7577Sps154918 " name CDATA #IMPLIED\n"
34194bc7577Sps154918 " value CDATA #IMPLIED\n"
34294bc7577Sps154918 ">\n"
3437c478bd9Sstevel@tonic-gate "\n"
3447c478bd9Sstevel@tonic-gate "<!ELEMENT Container (ContainerData?, "
3457c478bd9Sstevel@tonic-gate "(Fru | Location | Container)*)>\n"
3467c478bd9Sstevel@tonic-gate "<!ATTLIST Container name CDATA #REQUIRED>\n"
3477c478bd9Sstevel@tonic-gate "<!ATTLIST Container imagefile CDATA #IMPLIED>\n"
3487c478bd9Sstevel@tonic-gate "\n"
3497c478bd9Sstevel@tonic-gate "<!ELEMENT ContainerData (Segment*)>\n"
3507c478bd9Sstevel@tonic-gate "<!ATTLIST ContainerData>\n"
3517c478bd9Sstevel@tonic-gate "\n"
3527c478bd9Sstevel@tonic-gate "<!ATTLIST Segment name CDATA #REQUIRED>\n"
3537c478bd9Sstevel@tonic-gate "\n"
3547c478bd9Sstevel@tonic-gate "<!ELEMENT Index EMPTY>\n"
3557c478bd9Sstevel@tonic-gate "<!ATTLIST Index value CDATA #REQUIRED>\n"
3567c478bd9Sstevel@tonic-gate "\n"
3577c478bd9Sstevel@tonic-gate "<!ELEMENT ErrorLog (#PCDATA)>\n"
3587c478bd9Sstevel@tonic-gate "<!ATTLIST ErrorLog>\n"
3597c478bd9Sstevel@tonic-gate "\n");
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate /*
3627c478bd9Sstevel@tonic-gate * Output the definition for each element
3637c478bd9Sstevel@tonic-gate */
3647c478bd9Sstevel@tonic-gate for (i = 0; i < num_elements; i++) {
3657c478bd9Sstevel@tonic-gate assert(element[i] != NULL);
36694bc7577Sps154918 /* Prevent incompatible duplicate defn. from FRUID Registry. */
36794bc7577Sps154918 if ((strcmp("Location", element[i])) == 0) continue;
3687c478bd9Sstevel@tonic-gate if ((def = fru_reg_lookup_def_by_name(element[i])) == NULL) {
3697c478bd9Sstevel@tonic-gate error(gettext("Error looking up registry "
3707c478bd9Sstevel@tonic-gate "definition for \"%s\"\n"),
3717c478bd9Sstevel@tonic-gate element[i]);
3727c478bd9Sstevel@tonic-gate return (1);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate if (def->tagType != FRU_X) tagged[i] = 1;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Record) {
3787c478bd9Sstevel@tonic-gate if (def->iterationType == FRU_NOT_ITERATED)
3797c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (%s", element[i],
3807c478bd9Sstevel@tonic-gate def->enumTable[0].text);
3817c478bd9Sstevel@tonic-gate else
3827c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (Index_%s*)>\n"
3837c478bd9Sstevel@tonic-gate "<!ATTLIST Index_%s>\n"
3847c478bd9Sstevel@tonic-gate "<!ELEMENT Index_%s (%s",
3857c478bd9Sstevel@tonic-gate element[i], element[i], element[i],
3867c478bd9Sstevel@tonic-gate element[i], def->enumTable[0].text);
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate for (j = 1; j < def->enumCount; j++)
3897c478bd9Sstevel@tonic-gate output(",\n\t%s", def->enumTable[j].text);
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate output(")>\n");
3927c478bd9Sstevel@tonic-gate } else if (def->iterationType == FRU_NOT_ITERATED) {
3937c478bd9Sstevel@tonic-gate output("<!ELEMENT %s EMPTY>\n"
3947c478bd9Sstevel@tonic-gate "<!ATTLIST %s value CDATA #REQUIRED>\n",
3957c478bd9Sstevel@tonic-gate element[i], element[i]);
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Enumeration) {
3987c478bd9Sstevel@tonic-gate output("<!-- %s valid enumeration values\n");
3997c478bd9Sstevel@tonic-gate for (j = 0; j < def->enumCount; j++) {
4007c478bd9Sstevel@tonic-gate output("\t\"");
4017c478bd9Sstevel@tonic-gate xputs(def->enumTable[j].text);
4027c478bd9Sstevel@tonic-gate output("\"\n");
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate output("-->\n");
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate else
4087c478bd9Sstevel@tonic-gate output("<!ELEMENT %s (Index*)>\n", element[i]);
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate output("\n");
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /* Provide for returning the tag for an "unknown" element */
4147c478bd9Sstevel@tonic-gate output("<!ATTLIST UNKNOWN tag CDATA \"UNKNOWN\">\n\n");
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate * List all data elements as possible members of "Segment"
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate output("<!ELEMENT Segment ((UNKNOWN");
4217c478bd9Sstevel@tonic-gate for (i = 0; i < num_elements; i++) {
4227c478bd9Sstevel@tonic-gate if (tagged[i]) output("\n\t| %s", element[i]);
4237c478bd9Sstevel@tonic-gate free(element[i]);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate output(")*)>\n");
4267c478bd9Sstevel@tonic-gate free(element);
4277c478bd9Sstevel@tonic-gate free(tagged);
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate return (0);
4307c478bd9Sstevel@tonic-gate }
431f3af4981Sdt207653 /*
432f3af4981Sdt207653 * Function to convert bcd to binary to correct the SPD_Manufacturer_Week
433f3af4981Sdt207653 *
434f3af4981Sdt207653 */
convertbcdtobinary(int * val)435f3af4981Sdt207653 static void convertbcdtobinary(int *val)
436f3af4981Sdt207653 {
4375bc0fc0eSdt207653 unsigned int newval = (unsigned int)*val, tmpval = 0;
4385bc0fc0eSdt207653 while (newval > 0) {
4395bc0fc0eSdt207653 tmpval = (tmpval << 4) | (newval & 0xF);
4405bc0fc0eSdt207653 newval >>= 4;
4415bc0fc0eSdt207653 }
4425bc0fc0eSdt207653 while (tmpval > 0) {
4435bc0fc0eSdt207653 newval = (newval * 10) + (tmpval & 0xF);
4445bc0fc0eSdt207653 tmpval >>= 4;
445f3af4981Sdt207653 }
446f3af4981Sdt207653 *val = newval;
447f3af4981Sdt207653 }
448f3af4981Sdt207653
449*48215d30SDipti Tarai /*
450*48215d30SDipti Tarai * Checking UTF-8 printable charecter
451*48215d30SDipti Tarai */
check_utf_char(const uint8_t * field,int len)452*48215d30SDipti Tarai static int check_utf_char(const uint8_t *field, int len)
453*48215d30SDipti Tarai {
454*48215d30SDipti Tarai int i, status = 0;
455*48215d30SDipti Tarai char tmp[128], tmp1[128], tmp2[128];
456*48215d30SDipti Tarai (void) sprintf(tmp, " (Invalid Data");
457*48215d30SDipti Tarai (void) sprintf(tmp2, "0x");
458*48215d30SDipti Tarai for (i = 0; i < len && field[i]; i++) {
459*48215d30SDipti Tarai (void) sprintf(tmp1, "%2.2X", field[i]);
460*48215d30SDipti Tarai (void) strcat(tmp2, tmp1);
461*48215d30SDipti Tarai if (iswprint(field[i]) == 0) {
462*48215d30SDipti Tarai status = 1;
463*48215d30SDipti Tarai (void) sprintf(tmp1, " : 0x%2.2X", field[i]);
464*48215d30SDipti Tarai (void) strcat(tmp, tmp1);
465*48215d30SDipti Tarai }
466*48215d30SDipti Tarai }
467*48215d30SDipti Tarai if (status) {
468*48215d30SDipti Tarai (void) sprintf(tmp1, ")");
469*48215d30SDipti Tarai (void) strcat(tmp, tmp1);
470*48215d30SDipti Tarai (void) strcat(tmp2, tmp);
471*48215d30SDipti Tarai output("%s", tmp2);
472*48215d30SDipti Tarai }
473*48215d30SDipti Tarai return (status);
474*48215d30SDipti Tarai }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate /*
4777c478bd9Sstevel@tonic-gate * Safely pretty-print the value of a field
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate static void
print_field(const uint8_t * field,const fru_regdef_t * def)4807c478bd9Sstevel@tonic-gate print_field(const uint8_t *field, const fru_regdef_t *def)
4817c478bd9Sstevel@tonic-gate {
482f3af4981Sdt207653 char *errmsg = NULL, timestring[TIMESTRINGLEN], path[16384];
4837c478bd9Sstevel@tonic-gate
484f3af4981Sdt207653 int i, valueint;
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate uint64_t value;
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate time_t timefield;
4897c478bd9Sstevel@tonic-gate
490f3af4981Sdt207653 struct tm *tm;
4917c478bd9Sstevel@tonic-gate
492f3af4981Sdt207653 uchar_t first_byte, data[128];
493f3af4981Sdt207653
494f3af4981Sdt207653 const fru_regdef_t *new_def;
495f3af4981Sdt207653
496f3af4981Sdt207653 const char *elem_name = NULL;
497f3af4981Sdt207653 const char *parent_path;
4987c478bd9Sstevel@tonic-gate switch (def->dataType) {
4997c478bd9Sstevel@tonic-gate case FDTYPE_Binary:
5007c478bd9Sstevel@tonic-gate assert(def->payloadLen <= sizeof (value));
5017c478bd9Sstevel@tonic-gate switch (def->dispType) {
5027c478bd9Sstevel@tonic-gate case FDISP_Binary:
5037c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen; i++)
5047c478bd9Sstevel@tonic-gate output("%c%c%c%c%c%c%c%c",
5057c478bd9Sstevel@tonic-gate ((field[i] & 0x80) ? '1' : '0'),
5067c478bd9Sstevel@tonic-gate ((field[i] & 0x40) ? '1' : '0'),
5077c478bd9Sstevel@tonic-gate ((field[i] & 0x20) ? '1' : '0'),
5087c478bd9Sstevel@tonic-gate ((field[i] & 0x10) ? '1' : '0'),
5097c478bd9Sstevel@tonic-gate ((field[i] & 0x08) ? '1' : '0'),
5107c478bd9Sstevel@tonic-gate ((field[i] & 0x04) ? '1' : '0'),
5117c478bd9Sstevel@tonic-gate ((field[i] & 0x02) ? '1' : '0'),
5127c478bd9Sstevel@tonic-gate ((field[i] & 0x01) ? '1' : '0'));
5137c478bd9Sstevel@tonic-gate return;
5147c478bd9Sstevel@tonic-gate case FDISP_Octal:
5157c478bd9Sstevel@tonic-gate case FDISP_Decimal:
5167c478bd9Sstevel@tonic-gate value = 0;
517f3af4981Sdt207653 valueint = 0;
5187c478bd9Sstevel@tonic-gate (void) memcpy((((uint8_t *)&value) +
5197c478bd9Sstevel@tonic-gate sizeof (value) - def->payloadLen),
5207c478bd9Sstevel@tonic-gate field, def->payloadLen);
52194bc7577Sps154918 if ((value != 0) &&
522f3af4981Sdt207653 (strcmp(def->name, "SPD_Manufacture_Week") == 0)) {
523f3af4981Sdt207653 valueint = (int)value;
5245bc0fc0eSdt207653 if (spd_memtype && spd_revision) {
525f3af4981Sdt207653 convertbcdtobinary(&valueint);
5265bc0fc0eSdt207653 spd_memtype = 0;
5275bc0fc0eSdt207653 spd_revision = 0;
5285bc0fc0eSdt207653 }
529f3af4981Sdt207653 output("%d", valueint);
530f3af4981Sdt207653 return;
531f3af4981Sdt207653 }
532f3af4981Sdt207653 if ((value != 0) &&
53394bc7577Sps154918 ((strcmp(def->name, "Lowest") == 0) ||
53494bc7577Sps154918 (strcmp(def->name, "Highest") == 0) ||
53594bc7577Sps154918 (strcmp(def->name, "Latest") == 0)))
5361e3549a6Sps154918 output((def->dispType == FDISP_Octal) ?
5371e3549a6Sps154918 "%llo" : "%lld (%lld degrees C)",
5381e3549a6Sps154918 value, (value - TEMPERATURE_OFFSET));
5391e3549a6Sps154918 else
5407c478bd9Sstevel@tonic-gate output((def->dispType == FDISP_Octal) ?
5417c478bd9Sstevel@tonic-gate "%llo" : "%lld", value);
5427c478bd9Sstevel@tonic-gate return;
5437c478bd9Sstevel@tonic-gate case FDISP_Time:
5447c478bd9Sstevel@tonic-gate if (def->payloadLen > sizeof (timefield)) {
5457c478bd9Sstevel@tonic-gate errmsg = "time value too large for formatting";
5467c478bd9Sstevel@tonic-gate break;
5477c478bd9Sstevel@tonic-gate }
548f3af4981Sdt207653 timefield = 0;
549f3af4981Sdt207653 (void) memcpy((((uint8_t *)&timefield) +
550f3af4981Sdt207653 sizeof (timefield) - def->payloadLen),
551f3af4981Sdt207653 field, def->payloadLen);
552f3af4981Sdt207653 if (timefield == 0) {
553f3af4981Sdt207653 errmsg = "No Value Recorded";
554f3af4981Sdt207653 break;
555f3af4981Sdt207653 }
556bdad7b9cSaa222140 if ((tm = gmtime(&timefield)) == NULL) {
557f3af4981Sdt207653 errmsg = "cannot convert time value";
558f3af4981Sdt207653 break;
559f3af4981Sdt207653 }
560bdad7b9cSaa222140 if (strftime(timestring, sizeof (timestring), GMT, tm)
561f3af4981Sdt207653 == 0) {
5627c478bd9Sstevel@tonic-gate errmsg = "formatted time would overflow buffer";
5637c478bd9Sstevel@tonic-gate break;
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate safeputs(timestring);
5667c478bd9Sstevel@tonic-gate return;
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate break;
5697c478bd9Sstevel@tonic-gate case FDTYPE_ASCII:
570f3af4981Sdt207653 if (!xml) {
571f3af4981Sdt207653 if (strcmp(def->name, "Message") == 0) {
572f3af4981Sdt207653 if (FMAmessageR == 0)
573f3af4981Sdt207653 elem_name = "FMA_Event_DataR";
574f3af4981Sdt207653 else if (FMAmessageR == 1)
575f3af4981Sdt207653 elem_name = "FMA_MessageR";
576f3af4981Sdt207653 if (elem_name != NULL) {
577f3af4981Sdt207653 (void) memcpy(data, field,
578f3af4981Sdt207653 def->payloadLen);
579f3af4981Sdt207653 new_def =
58046a7ef8aSdt207653 fru_reg_lookup_def_by_name
58146a7ef8aSdt207653 (elem_name);
582aad09a1cSdt207653 (void) snprintf(path, sizeof (path),
583f3af4981Sdt207653 "/Status_EventsR[%d]/Message(FMA)",
584f3af4981Sdt207653 iterglobal);
585f3af4981Sdt207653 parent_path = path;
586f3af4981Sdt207653 output("\n");
587f3af4981Sdt207653 print_element(data, new_def,
588f3af4981Sdt207653 parent_path, 2*INDENT);
589f3af4981Sdt207653 return;
590f3af4981Sdt207653 }
591f3af4981Sdt207653 }
592f3af4981Sdt207653 }
593*48215d30SDipti Tarai if (strcmp(def->name, "Fru_Path") == 0) {
594*48215d30SDipti Tarai if (check_utf_char(field, def->payloadLen) == 1)
595*48215d30SDipti Tarai return;
596*48215d30SDipti Tarai }
5977c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen && field[i]; i++)
5987c478bd9Sstevel@tonic-gate safeputchar(field[i]);
5997c478bd9Sstevel@tonic-gate return;
6007c478bd9Sstevel@tonic-gate case FDTYPE_Enumeration:
6017c478bd9Sstevel@tonic-gate value = 0;
6027c478bd9Sstevel@tonic-gate (void) memcpy((((uint8_t *)&value) + sizeof (value)
6037c478bd9Sstevel@tonic-gate - def->payloadLen),
6047c478bd9Sstevel@tonic-gate field, def->payloadLen);
6057c478bd9Sstevel@tonic-gate for (i = 0; i < def->enumCount; i++)
6067c478bd9Sstevel@tonic-gate if (def->enumTable[i].value == value) {
607f3af4981Sdt207653 if (strcmp(def->name, "Event_Code") == 0) {
608f3af4981Sdt207653 if (strcmp(def->enumTable[i].text,
609f3af4981Sdt207653 "FMA Message R") == 0)
610f3af4981Sdt207653 FMAmessageR = 1;
611f3af4981Sdt207653 else
612f3af4981Sdt207653 if (strcmp(def->enumTable[i].text,
613f3af4981Sdt207653 "FMA Event Data R") == 0)
614f3af4981Sdt207653 FMAmessageR = 0;
615f3af4981Sdt207653 }
6165bc0fc0eSdt207653 if (strcmp(def->name,
6175bc0fc0eSdt207653 "SPD_Fundamental_Memory_Type") == 0) {
6185bc0fc0eSdt207653 if (strcmp(def->enumTable[i].text,
6195bc0fc0eSdt207653 "DDR II SDRAM") == 0)
6205bc0fc0eSdt207653 spd_memtype = 1;
6215bc0fc0eSdt207653 }
6227c478bd9Sstevel@tonic-gate safeputs(def->enumTable[i].text);
6237c478bd9Sstevel@tonic-gate return;
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate errmsg = "unrecognized value";
6277c478bd9Sstevel@tonic-gate break;
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate /* If nothing matched above, print the field in hex */
631f3af4981Sdt207653 switch (def->dispType) {
632f3af4981Sdt207653 case FDISP_MSGID:
633f3af4981Sdt207653 (void) memcpy((uchar_t *)&first_byte, field, 1);
634f3af4981Sdt207653 if (isprint(first_byte)) {
635f3af4981Sdt207653 for (i = 0; i < def->payloadLen && field[i];
636f3af4981Sdt207653 i++)
637f3af4981Sdt207653 safeputchar(field[i]);
638f3af4981Sdt207653 }
639f3af4981Sdt207653 break;
640f3af4981Sdt207653 case FDISP_UUID:
641f3af4981Sdt207653 for (i = 0; i < def->payloadLen; i++) {
642f3af4981Sdt207653 if ((i == 4) || (i == 6) ||
643f3af4981Sdt207653 (i == 8) || (i == 10))
644f3af4981Sdt207653 output("-");
645f3af4981Sdt207653 output("%2.2x", field[i]);
646f3af4981Sdt207653 }
647f3af4981Sdt207653 break;
648f3af4981Sdt207653 default:
649*48215d30SDipti Tarai if ((strcmp(def->name, "Status") == 0) ||
650*48215d30SDipti Tarai (strcmp(def->name, "Old_Status") == 0) ||
651*48215d30SDipti Tarai (strcmp(def->name, "New_Status") == 0)) {
652*48215d30SDipti Tarai int status_length = \
653*48215d30SDipti Tarai sizeof (Status_CurrentR_status) / \
654*48215d30SDipti Tarai sizeof (*(Status_CurrentR_status));
655*48215d30SDipti Tarai i = 0;
656*48215d30SDipti Tarai do {
657*48215d30SDipti Tarai if (Status_CurrentR_status[i].value == \
658*48215d30SDipti Tarai *(field))
659*48215d30SDipti Tarai break;
660*48215d30SDipti Tarai i++;
661*48215d30SDipti Tarai } while (i < status_length);
662*48215d30SDipti Tarai if (i < status_length)
663*48215d30SDipti Tarai output("0x%2.2X (%s)", *(field),
664*48215d30SDipti Tarai Status_CurrentR_status[i].data);
665*48215d30SDipti Tarai else
666*48215d30SDipti Tarai output("0x%2.2X (UNKNOWN)", *(field));
667*48215d30SDipti Tarai break;
668*48215d30SDipti Tarai }
6695bc0fc0eSdt207653 if (strcmp(def->name,
6705bc0fc0eSdt207653 "SPD_Data_Revision_Code") == 0) {
6715bc0fc0eSdt207653 value = 0;
6725bc0fc0eSdt207653 valueint = 0;
6735bc0fc0eSdt207653 (void) memcpy((((uint8_t *)&value)
6745bc0fc0eSdt207653 + sizeof (value) - def->payloadLen),
6755bc0fc0eSdt207653 field, def->payloadLen);
6765bc0fc0eSdt207653 valueint = (int)value;
6775bc0fc0eSdt207653 if ((valueint >= MIN_VERSION) && (spd_memtype))
6785bc0fc0eSdt207653 spd_revision = 1;
6795bc0fc0eSdt207653 }
6807c478bd9Sstevel@tonic-gate for (i = 0; i < def->payloadLen; i++)
6817c478bd9Sstevel@tonic-gate output("%2.2X", field[i]);
682f3af4981Sdt207653 break;
683f3af4981Sdt207653 }
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate /* Safely print any error message associated with the field */
6867c478bd9Sstevel@tonic-gate if (errmsg) {
687f3af4981Sdt207653 if (strcmp(def->name, "Fault_Diag_Secs") != 0) {
6887c478bd9Sstevel@tonic-gate output(" (");
6897c478bd9Sstevel@tonic-gate safeputs(errmsg);
690f3af4981Sdt207653 output(")");
691f3af4981Sdt207653 }
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate /*
6967c478bd9Sstevel@tonic-gate * Recursively print the contents of a data element
6977c478bd9Sstevel@tonic-gate */
6987c478bd9Sstevel@tonic-gate static void
print_element(const uint8_t * data,const fru_regdef_t * def,const char * parent_path,int indent)6997c478bd9Sstevel@tonic-gate print_element(const uint8_t *data, const fru_regdef_t *def,
7007c478bd9Sstevel@tonic-gate const char *parent_path, int indent)
7017c478bd9Sstevel@tonic-gate {
7027c478bd9Sstevel@tonic-gate char *path;
7037c478bd9Sstevel@tonic-gate size_t len;
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate int bytes = 0, i;
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate indent = (xml) ? (indent + INDENT) : (2*INDENT);
70946a7ef8aSdt207653 if (strcmp(def->name, "Sun_SPD_DataR") == 0) {
71046a7ef8aSdt207653 Fault_Install_DataR_flag = indent;
71146a7ef8aSdt207653 Power_On_DataR_flag = indent;
71246a7ef8aSdt207653 }
7137c478bd9Sstevel@tonic-gate /*
7147c478bd9Sstevel@tonic-gate * Construct the path, or, for XML, the name, for the current
7157c478bd9Sstevel@tonic-gate * data element
7167c478bd9Sstevel@tonic-gate */
7177c478bd9Sstevel@tonic-gate if ((def->iterationCount == 0) &&
7187c478bd9Sstevel@tonic-gate (def->iterationType != FRU_NOT_ITERATED)) {
7197c478bd9Sstevel@tonic-gate if (xml) {
7207c478bd9Sstevel@tonic-gate if (def->dataType == FDTYPE_Record) {
7217c478bd9Sstevel@tonic-gate len = strlen("Index_") + strlen(def->name) + 1;
7227c478bd9Sstevel@tonic-gate path = alloca(len);
7237c478bd9Sstevel@tonic-gate (void) snprintf(path, len,
7247c478bd9Sstevel@tonic-gate "Index_%s", def->name);
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate else
7277c478bd9Sstevel@tonic-gate path = "Index";
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate else
7307c478bd9Sstevel@tonic-gate path = (char *)parent_path;
7317c478bd9Sstevel@tonic-gate } else {
7327c478bd9Sstevel@tonic-gate if (xml)
7337c478bd9Sstevel@tonic-gate path = (char *)def->name;
7347c478bd9Sstevel@tonic-gate else {
7357c478bd9Sstevel@tonic-gate len = strlen(parent_path) + sizeof ("/") +
7367c478bd9Sstevel@tonic-gate strlen(def->name) +
7377c478bd9Sstevel@tonic-gate (def->iterationCount ? sizeof ("[255]") : 0);
7387c478bd9Sstevel@tonic-gate path = alloca(len);
7397c478bd9Sstevel@tonic-gate bytes = snprintf(path, len,
7407c478bd9Sstevel@tonic-gate "%s/%s", parent_path, def->name);
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate
74446a7ef8aSdt207653 if ((Fault_Install_DataR_flag) &&
74546a7ef8aSdt207653 (strcmp(path, "E_1_46") == 0) || (strcmp(path, "/E_1_46") == 0)) {
74646a7ef8aSdt207653 int cnt;
74746a7ef8aSdt207653 char timestring[128];
74846a7ef8aSdt207653 time_t timefield = 0;
74946a7ef8aSdt207653 struct tm *tm;
75046a7ef8aSdt207653 indent = Fault_Install_DataR_flag;
75146a7ef8aSdt207653 (void) memcpy((uint8_t *)&timefield, data, 4);
75246a7ef8aSdt207653 if (timefield == 0) {
75346a7ef8aSdt207653 (void) sprintf(timestring,
75446a7ef8aSdt207653 "00000000 (No Value Recorded)\"");
75546a7ef8aSdt207653 } else {
756bdad7b9cSaa222140 if ((tm = gmtime(&timefield)) == NULL)
75746a7ef8aSdt207653 (void) sprintf(timestring,
75846a7ef8aSdt207653 "cannot convert time value");
75946a7ef8aSdt207653 if (strftime(timestring,
760bdad7b9cSaa222140 sizeof (timestring), GMT, tm) == 0)
76146a7ef8aSdt207653 (void) sprintf(timestring,
76246a7ef8aSdt207653 "formatted time would overflow buffer");
76346a7ef8aSdt207653 }
76446a7ef8aSdt207653 if (xml) {
76546a7ef8aSdt207653 (void) sprintf(path, "Fault_Install_DataR");
76646a7ef8aSdt207653 output("%*s<%s>\n", indent, "", path);
76746a7ef8aSdt207653 indent = Fault_Install_DataR_flag + INDENT;
76846a7ef8aSdt207653 (void) sprintf(path, "UNIX_Timestamp32");
76946a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
77046a7ef8aSdt207653 /*CSTYLED*/
77146a7ef8aSdt207653 output("%s\"/>\n", timestring);
77246a7ef8aSdt207653 (void) sprintf(path, "MACADDR");
77346a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
77446a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 6; cnt++) {
77546a7ef8aSdt207653 output("%2.2x", data[cnt]);
77646a7ef8aSdt207653 if (cnt < 4 + 6 - 1)
77746a7ef8aSdt207653 output(":");
77846a7ef8aSdt207653 }
77946a7ef8aSdt207653 /*CSTYLED*/
78046a7ef8aSdt207653 output("\"/>\n");
78146a7ef8aSdt207653 (void) sprintf(path, "Status");
78246a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
78346a7ef8aSdt207653 /*CSTYLED*/
78446a7ef8aSdt207653 output("%2.2x\"/>\n", data[10]);
78546a7ef8aSdt207653 (void) sprintf(path, "Initiator");
78646a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
78746a7ef8aSdt207653 /*CSTYLED*/
78846a7ef8aSdt207653 output("%2.2x\"/>\n", data[11]);
78946a7ef8aSdt207653 (void) sprintf(path, "Message_Type");
79046a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
79146a7ef8aSdt207653 /*CSTYLED*/
79246a7ef8aSdt207653 output("%2.2x\"/>\n", data[12]);
79346a7ef8aSdt207653 (void) sprintf(path, "Message_32");
79446a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
79546a7ef8aSdt207653 for (cnt = 13; cnt < 13 + 32; cnt++)
79646a7ef8aSdt207653 output("%2.2x", data[cnt]);
79746a7ef8aSdt207653 /*CSTYLED*/
79846a7ef8aSdt207653 output("\"/>\n");
79946a7ef8aSdt207653 indent = Fault_Install_DataR_flag;
80046a7ef8aSdt207653 (void) sprintf(path, "Fault_Install_DataR");
80146a7ef8aSdt207653 output("%*s</%s>\n", indent, "", path);
80246a7ef8aSdt207653 } else {
80346a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR");
80446a7ef8aSdt207653 output("%*s%s\n", indent, "", path);
80546a7ef8aSdt207653 (void) sprintf(path,
80646a7ef8aSdt207653 "/Fault_Install_DataR/UNIX_Timestamp32");
80746a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
80846a7ef8aSdt207653 output("%s\n", timestring);
80946a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/MACADDR");
81046a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
81146a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 6; cnt++) {
81246a7ef8aSdt207653 output("%2.2x", data[cnt]);
81346a7ef8aSdt207653 if (cnt < 4 + 6 - 1)
81446a7ef8aSdt207653 output(":");
81546a7ef8aSdt207653 }
81646a7ef8aSdt207653 output("\n");
81746a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/Status");
81846a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
81946a7ef8aSdt207653 output("%2.2x\n", data[10]);
82046a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/Initiator");
82146a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
82246a7ef8aSdt207653 output("%2.2x\n", data[11]);
82346a7ef8aSdt207653 (void) sprintf(path,
82446a7ef8aSdt207653 "/Fault_Install_DataR/Message_Type");
82546a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
82646a7ef8aSdt207653 output("%2.2x\n", data[12]);
82746a7ef8aSdt207653 (void) sprintf(path, "/Fault_Install_DataR/Message_32");
82846a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
82946a7ef8aSdt207653 for (cnt = 13; cnt < 13 + 32; cnt++)
83046a7ef8aSdt207653 output("%2.2x", data[cnt]);
83146a7ef8aSdt207653 output("\n");
83246a7ef8aSdt207653 }
83346a7ef8aSdt207653 Fault_Install_DataR_flag = 0;
83446a7ef8aSdt207653 return;
83546a7ef8aSdt207653 } else if ((Power_On_DataR_flag) && (
83646a7ef8aSdt207653 strcmp(path, "C_10_8") == 0 ||
83746a7ef8aSdt207653 (strcmp(path, "/C_10_8") == 0))) {
83846a7ef8aSdt207653 int cnt;
83946a7ef8aSdt207653 char timestring[128];
84046a7ef8aSdt207653 time_t timefield = 0;
84146a7ef8aSdt207653 struct tm *tm;
84246a7ef8aSdt207653 indent = Power_On_DataR_flag;
84346a7ef8aSdt207653 (void) memcpy((uint8_t *)&timefield, data, 4);
84446a7ef8aSdt207653 if (timefield == 0) {
84546a7ef8aSdt207653 (void) sprintf(timestring,
84646a7ef8aSdt207653 "00000000 (No Value Recorded)");
84746a7ef8aSdt207653 } else {
848bdad7b9cSaa222140 if ((tm = gmtime(&timefield)) == NULL)
84946a7ef8aSdt207653 (void) sprintf(timestring,
85046a7ef8aSdt207653 "cannot convert time value");
85146a7ef8aSdt207653 if (strftime(timestring,
852bdad7b9cSaa222140 sizeof (timestring), GMT, tm) == 0)
85346a7ef8aSdt207653 (void) sprintf(timestring,
85446a7ef8aSdt207653 "formatted time would overflow buffer");
85546a7ef8aSdt207653 }
85646a7ef8aSdt207653 if (xml) {
85746a7ef8aSdt207653 (void) sprintf(path, "Power_On_DataR");
85846a7ef8aSdt207653 output("%*s<%s>\n", indent, "", path);
85946a7ef8aSdt207653 indent = Power_On_DataR_flag + INDENT;
86046a7ef8aSdt207653 (void) sprintf(path, "UNIX_Timestamp32");
86146a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
86246a7ef8aSdt207653 /*CSTYLED*/
86346a7ef8aSdt207653 output("%s\"/>\n", timestring);
86446a7ef8aSdt207653 (void) sprintf(path, "Power_On_Minutes");
86546a7ef8aSdt207653 output("%*s<%s value=\"", indent, "", path);
86646a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 4; cnt++)
86746a7ef8aSdt207653 output("%2.2x", data[cnt]);
86846a7ef8aSdt207653 /*CSTYLED*/
86946a7ef8aSdt207653 output("\"/>\n");
87046a7ef8aSdt207653 indent = Power_On_DataR_flag;
87146a7ef8aSdt207653 (void) sprintf(path, "Power_On_DataR");
87246a7ef8aSdt207653 output("%*s</%s>\n", indent, "", path);
87346a7ef8aSdt207653 } else {
87446a7ef8aSdt207653 (void) sprintf(path, "/Power_On_DataR");
87546a7ef8aSdt207653 output("%*s%s\n", indent, "", path);
87646a7ef8aSdt207653 (void) sprintf(path,
87746a7ef8aSdt207653 "/Power_On_DataR/UNIX_Timestamp32");
87846a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
87946a7ef8aSdt207653 output("%s\n", timestring);
88046a7ef8aSdt207653 (void) sprintf(path,
88146a7ef8aSdt207653 "/Power_On_DataR/Power_On_Minutes");
88246a7ef8aSdt207653 output("%*s%s: ", indent, "", path);
88346a7ef8aSdt207653 for (cnt = 4; cnt < 4 + 4; cnt++)
88446a7ef8aSdt207653 output("%2.2x", data[cnt]);
88546a7ef8aSdt207653 output("\n");
88646a7ef8aSdt207653 }
88746a7ef8aSdt207653 Power_On_DataR_flag = 0;
88846a7ef8aSdt207653 return;
88946a7ef8aSdt207653 }
8907c478bd9Sstevel@tonic-gate /*
8917c478bd9Sstevel@tonic-gate * Handle the various categories of data elements: iteration,
8927c478bd9Sstevel@tonic-gate * record, and field
8937c478bd9Sstevel@tonic-gate */
8947c478bd9Sstevel@tonic-gate if (def->iterationCount) {
8957c478bd9Sstevel@tonic-gate int iterlen = (def->payloadLen - NUM_ITER_BYTES)/
8967c478bd9Sstevel@tonic-gate def->iterationCount,
8977c478bd9Sstevel@tonic-gate n, valid = 1;
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate uint8_t head, num;
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate fru_regdef_t newdef;
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate /*
9057c478bd9Sstevel@tonic-gate * Make a new element definition to describe the components
9067c478bd9Sstevel@tonic-gate * of the iteration
9077c478bd9Sstevel@tonic-gate */
9087c478bd9Sstevel@tonic-gate (void) memcpy(&newdef, def, sizeof (newdef));
9097c478bd9Sstevel@tonic-gate newdef.iterationCount = 0;
9107c478bd9Sstevel@tonic-gate newdef.payloadLen = iterlen;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate /*
9137c478bd9Sstevel@tonic-gate * Validate the contents of the iteration control bytes
9147c478bd9Sstevel@tonic-gate */
9157c478bd9Sstevel@tonic-gate if (data[HEAD_ITER] >= def->iterationCount) {
9167c478bd9Sstevel@tonic-gate valid = 0;
9177c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration head: %d "
9187c478bd9Sstevel@tonic-gate "(should be less than %d)\n"),
9197c478bd9Sstevel@tonic-gate path, data[HEAD_ITER], def->iterationCount);
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate if (data[NUM_ITER] > def->iterationCount) {
9237c478bd9Sstevel@tonic-gate valid = 0;
9247c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration count: %d "
9257c478bd9Sstevel@tonic-gate "(should not be greater than %d)\n"),
9267c478bd9Sstevel@tonic-gate path, data[NUM_ITER], def->iterationCount);
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate if (data[MAX_ITER] != def->iterationCount) {
9307c478bd9Sstevel@tonic-gate valid = 0;
9317c478bd9Sstevel@tonic-gate error(gettext("%s: Invalid iteration maximum: %d "
9327c478bd9Sstevel@tonic-gate "(should equal %d)\n"),
9337c478bd9Sstevel@tonic-gate path, data[MAX_ITER], def->iterationCount);
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate if (valid) {
9377c478bd9Sstevel@tonic-gate head = data[HEAD_ITER];
9387c478bd9Sstevel@tonic-gate num = data[NUM_ITER];
9397c478bd9Sstevel@tonic-gate } else {
9407c478bd9Sstevel@tonic-gate head = 0;
9417c478bd9Sstevel@tonic-gate num = def->iterationCount;
9427c478bd9Sstevel@tonic-gate error(gettext("%s: Showing all iterations\n"), path);
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate if (xml)
9467c478bd9Sstevel@tonic-gate output("%*s<%s>\n", indent, "", path);
9477c478bd9Sstevel@tonic-gate else
9487c478bd9Sstevel@tonic-gate output("%*s%s (%d iterations)\n", indent, "", path,
9497c478bd9Sstevel@tonic-gate num);
9507c478bd9Sstevel@tonic-gate
9517c478bd9Sstevel@tonic-gate /*
9527c478bd9Sstevel@tonic-gate * Print each component of the iteration
9537c478bd9Sstevel@tonic-gate */
9547c478bd9Sstevel@tonic-gate for (i = head, n = 0, data += 4;
9557c478bd9Sstevel@tonic-gate n < num;
9567c478bd9Sstevel@tonic-gate i = ((i + 1) % def->iterationCount), n++) {
9577c478bd9Sstevel@tonic-gate if (!xml) (void) sprintf((path + bytes), "[%d]", n);
958f3af4981Sdt207653 iterglobal = n;
9597c478bd9Sstevel@tonic-gate print_element((data + i*iterlen), &newdef, path,
9607c478bd9Sstevel@tonic-gate indent);
9617c478bd9Sstevel@tonic-gate }
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate if (xml) output("%*s</%s>\n", indent, "", path);
9647c478bd9Sstevel@tonic-gate
9657c478bd9Sstevel@tonic-gate } else if (def->dataType == FDTYPE_Record) {
9667c478bd9Sstevel@tonic-gate const fru_regdef_t *component;
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate if (xml)
9697c478bd9Sstevel@tonic-gate output("%*s<%s>\n", indent, "", path);
9707c478bd9Sstevel@tonic-gate else
9717c478bd9Sstevel@tonic-gate output("%*s%s\n", indent, "", path);
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate /*
9747c478bd9Sstevel@tonic-gate * Print each component of the record
9757c478bd9Sstevel@tonic-gate */
9767c478bd9Sstevel@tonic-gate for (i = 0; i < def->enumCount;
9777c478bd9Sstevel@tonic-gate i++, data += component->payloadLen) {
9787c478bd9Sstevel@tonic-gate component = fru_reg_lookup_def_by_name(
9797c478bd9Sstevel@tonic-gate def->enumTable[i].text);
9807c478bd9Sstevel@tonic-gate assert(component != NULL);
9817c478bd9Sstevel@tonic-gate print_element(data, component, path, indent);
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate if (xml) output("%*s</%s>\n", indent, "", path);
9857c478bd9Sstevel@tonic-gate } else if (xml) {
9867c478bd9Sstevel@tonic-gate /*
9877c478bd9Sstevel@tonic-gate * Base case: print the field formatted for XML
9887c478bd9Sstevel@tonic-gate */
9897c478bd9Sstevel@tonic-gate char *format = ((def == &unknown)
9907c478bd9Sstevel@tonic-gate ? "%*s<UNKNOWN tag=\"%s\" value=\""
9917c478bd9Sstevel@tonic-gate : "%*s<%s value=\"");
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate output(format, indent, "", path);
9947c478bd9Sstevel@tonic-gate print_field(data, def);
9957c478bd9Sstevel@tonic-gate /*CSTYLED*/
9967c478bd9Sstevel@tonic-gate output("\"/>\n"); /* \" confuses cstyle */
997f3af4981Sdt207653
998f3af4981Sdt207653 if ((strcmp(def->name, "Message") == 0) &&
999f3af4981Sdt207653 ((FMAmessageR == 0) || (FMAmessageR == 1))) {
1000f3af4981Sdt207653 const char *elem_name = NULL;
1001f3af4981Sdt207653 const char *parent_path;
1002f3af4981Sdt207653 uchar_t tmpdata[128];
1003f3af4981Sdt207653 char path[16384];
1004f3af4981Sdt207653 const fru_regdef_t *new_def;
1005f3af4981Sdt207653
1006f3af4981Sdt207653 if (FMAmessageR == 0)
1007f3af4981Sdt207653 elem_name = "FMA_Event_DataR";
1008f3af4981Sdt207653 else if (FMAmessageR == 1)
1009f3af4981Sdt207653 elem_name = "FMA_MessageR";
1010f3af4981Sdt207653 if (elem_name != NULL) {
1011f3af4981Sdt207653 (void) memcpy(tmpdata, data, def->payloadLen);
1012f3af4981Sdt207653 new_def = fru_reg_lookup_def_by_name(elem_name);
101377acf672Sdt207653 (void) snprintf(path, sizeof (path),
1014f3af4981Sdt207653 "/Status_EventsR[%d]/Message(FMA)", iterglobal);
1015f3af4981Sdt207653 parent_path = path;
1016f3af4981Sdt207653 print_element(tmpdata, new_def,
1017f3af4981Sdt207653 parent_path, 2*INDENT);
1018f3af4981Sdt207653 FMAmessageR = -1;
1019f3af4981Sdt207653 }
1020f3af4981Sdt207653 }
1021f3af4981Sdt207653
10227c478bd9Sstevel@tonic-gate } else {
10237c478bd9Sstevel@tonic-gate /*
10247c478bd9Sstevel@tonic-gate * Base case: print the field
10257c478bd9Sstevel@tonic-gate */
10267c478bd9Sstevel@tonic-gate output("%*s%s: ", indent, "", path);
10277c478bd9Sstevel@tonic-gate print_field(data, def);
10287c478bd9Sstevel@tonic-gate output("\n");
10297c478bd9Sstevel@tonic-gate }
10307c478bd9Sstevel@tonic-gate }
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate /*
10337c478bd9Sstevel@tonic-gate * Print the contents of a packet (i.e., a tagged data element)
10347c478bd9Sstevel@tonic-gate */
10357c478bd9Sstevel@tonic-gate /* ARGSUSED */
10367c478bd9Sstevel@tonic-gate static int
print_packet(fru_tag_t * tag,uint8_t * payload,size_t length,void * args)10377c478bd9Sstevel@tonic-gate print_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
10387c478bd9Sstevel@tonic-gate {
10397c478bd9Sstevel@tonic-gate int tag_type = get_tag_type(tag);
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate size_t payload_length = 0;
10427c478bd9Sstevel@tonic-gate
10437c478bd9Sstevel@tonic-gate const fru_regdef_t *def;
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate /*
10467c478bd9Sstevel@tonic-gate * Build a definition for unrecognized tags (e.g., not in libfrureg)
10477c478bd9Sstevel@tonic-gate */
10487c478bd9Sstevel@tonic-gate if ((tag_type == -1) ||
10497c478bd9Sstevel@tonic-gate ((payload_length = get_payload_length(tag)) != length)) {
10507c478bd9Sstevel@tonic-gate def = &unknown;
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate unknown.tagType = -1;
10537c478bd9Sstevel@tonic-gate unknown.tagDense = -1;
10547c478bd9Sstevel@tonic-gate unknown.payloadLen = length;
10557c478bd9Sstevel@tonic-gate unknown.dataLength = unknown.payloadLen;
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate if (tag_type == -1)
10587c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), "INVALID");
10597c478bd9Sstevel@tonic-gate else
10607c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname),
10617c478bd9Sstevel@tonic-gate "%s_%u_%u_%u", get_tagtype_str(tag_type),
10627c478bd9Sstevel@tonic-gate get_tag_dense(tag), payload_length, length);
10637c478bd9Sstevel@tonic-gate } else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
10647c478bd9Sstevel@tonic-gate def = &unknown;
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate unknown.tagType = tag_type;
10677c478bd9Sstevel@tonic-gate unknown.tagDense = get_tag_dense(tag);
10687c478bd9Sstevel@tonic-gate unknown.payloadLen = payload_length;
10697c478bd9Sstevel@tonic-gate unknown.dataLength = unknown.payloadLen;
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate (void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
10727c478bd9Sstevel@tonic-gate get_tagtype_str(unknown.tagType),
10737c478bd9Sstevel@tonic-gate unknown.tagDense, payload_length);
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate /*
10787c478bd9Sstevel@tonic-gate * Print the defined element
10797c478bd9Sstevel@tonic-gate */
10807c478bd9Sstevel@tonic-gate print_element(payload, def, "", INDENT);
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate return (FRU_SUCCESS);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate /*
10867c478bd9Sstevel@tonic-gate * Print a segment's name and the contents of each data element in the segment
10877c478bd9Sstevel@tonic-gate */
10887c478bd9Sstevel@tonic-gate static int
print_packets_in_segment(fru_seghdl_t segment,void * args)10897c478bd9Sstevel@tonic-gate print_packets_in_segment(fru_seghdl_t segment, void *args)
10907c478bd9Sstevel@tonic-gate {
10917c478bd9Sstevel@tonic-gate char *name;
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate int status;
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate if ((status = fru_get_segment_name(segment, &name)) != FRU_SUCCESS) {
10977c478bd9Sstevel@tonic-gate saved_status = status;
10987c478bd9Sstevel@tonic-gate name = "";
10997c478bd9Sstevel@tonic-gate error(gettext("Error getting segment name: %s\n"),
11007c478bd9Sstevel@tonic-gate fru_strerror(status));
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate if (xml)
11057c478bd9Sstevel@tonic-gate output("%*s<Segment name=\"%s\">\n", INDENT, "", name);
11067c478bd9Sstevel@tonic-gate else
11077c478bd9Sstevel@tonic-gate output("%*sSEGMENT: %s\n", INDENT, "", name);
11087c478bd9Sstevel@tonic-gate
1109*48215d30SDipti Tarai if (strcmp(name, "ED") == 0) {
1110*48215d30SDipti Tarai if (xml) output("%*s</Segment>\n", INDENT, "");
1111*48215d30SDipti Tarai free(name);
1112*48215d30SDipti Tarai return (FRU_SUCCESS);
1113*48215d30SDipti Tarai }
11147c478bd9Sstevel@tonic-gate /* Iterate over the packets in the segment, printing the contents */
11157c478bd9Sstevel@tonic-gate if ((status = fru_for_each_packet(segment, print_packet, args))
11167c478bd9Sstevel@tonic-gate != FRU_SUCCESS) {
11177c478bd9Sstevel@tonic-gate saved_status = status;
11187c478bd9Sstevel@tonic-gate error(gettext("Error processing data in segment \"%s\": %s\n"),
11197c478bd9Sstevel@tonic-gate name, fru_strerror(status));
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate if (xml) output("%*s</Segment>\n", INDENT, "");
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate free(name);
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate return (FRU_SUCCESS);
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate
11297c478bd9Sstevel@tonic-gate /* ARGSUSED */
11307c478bd9Sstevel@tonic-gate static void
print_node_path(fru_node_t fru_type,const char * path,const char * name,end_node_fp_t * end_node,void ** end_args)11317c478bd9Sstevel@tonic-gate print_node_path(fru_node_t fru_type, const char *path, const char *name,
11327c478bd9Sstevel@tonic-gate end_node_fp_t *end_node, void **end_args)
11337c478bd9Sstevel@tonic-gate {
11347c478bd9Sstevel@tonic-gate output("%s%s\n", path,
11357c478bd9Sstevel@tonic-gate ((fru_type == FRU_NODE_CONTAINER) ? " (container)"
11367c478bd9Sstevel@tonic-gate : ((fru_type == FRU_NODE_FRU) ? " (fru)" : "")));
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate /*
11407c478bd9Sstevel@tonic-gate * Close the XML element for a "location" node
11417c478bd9Sstevel@tonic-gate */
11427c478bd9Sstevel@tonic-gate /* ARGSUSED */
11437c478bd9Sstevel@tonic-gate static void
end_location_xml(fru_nodehdl_t node,const char * path,const char * name,void * args)11447c478bd9Sstevel@tonic-gate end_location_xml(fru_nodehdl_t node, const char *path, const char *name,
11457c478bd9Sstevel@tonic-gate void *args)
11467c478bd9Sstevel@tonic-gate {
11477c478bd9Sstevel@tonic-gate assert(args != NULL);
11487c478bd9Sstevel@tonic-gate output("</Location> <!-- %s -->\n", args);
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate /*
11527c478bd9Sstevel@tonic-gate * Close the XML element for a "fru" node
11537c478bd9Sstevel@tonic-gate */
11547c478bd9Sstevel@tonic-gate /* ARGSUSED */
11557c478bd9Sstevel@tonic-gate static void
end_fru_xml(fru_nodehdl_t node,const char * path,const char * name,void * args)11567c478bd9Sstevel@tonic-gate end_fru_xml(fru_nodehdl_t node, const char *path, const char *name, void *args)
11577c478bd9Sstevel@tonic-gate {
11587c478bd9Sstevel@tonic-gate assert(args != NULL);
11597c478bd9Sstevel@tonic-gate output("</Fru> <!-- %s -->\n", args);
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate /*
11637c478bd9Sstevel@tonic-gate * Close the XML element for a "container" node
11647c478bd9Sstevel@tonic-gate */
11657c478bd9Sstevel@tonic-gate /* ARGSUSED */
11667c478bd9Sstevel@tonic-gate static void
end_container_xml(fru_nodehdl_t node,const char * path,const char * name,void * args)11677c478bd9Sstevel@tonic-gate end_container_xml(fru_nodehdl_t node, const char *path, const char *name,
11687c478bd9Sstevel@tonic-gate void *args)
11697c478bd9Sstevel@tonic-gate {
11707c478bd9Sstevel@tonic-gate assert(args != NULL);
11717c478bd9Sstevel@tonic-gate output("</Container> <!-- %s -->\n", args);
11727c478bd9Sstevel@tonic-gate }
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate /*
11757c478bd9Sstevel@tonic-gate * Introduce a node in XML and set the appropriate node-closing function
11767c478bd9Sstevel@tonic-gate */
11777c478bd9Sstevel@tonic-gate /* ARGSUSED */
11787c478bd9Sstevel@tonic-gate static void
print_node_xml(fru_node_t fru_type,const char * path,const char * name,end_node_fp_t * end_node,void ** end_args)11797c478bd9Sstevel@tonic-gate print_node_xml(fru_node_t fru_type, const char *path, const char *name,
11807c478bd9Sstevel@tonic-gate end_node_fp_t *end_node, void **end_args)
11817c478bd9Sstevel@tonic-gate {
11827c478bd9Sstevel@tonic-gate switch (fru_type) {
11837c478bd9Sstevel@tonic-gate case FRU_NODE_FRU:
11847c478bd9Sstevel@tonic-gate output("<Fru name=\"%s\">\n", name);
11857c478bd9Sstevel@tonic-gate *end_node = end_fru_xml;
11867c478bd9Sstevel@tonic-gate break;
11877c478bd9Sstevel@tonic-gate case FRU_NODE_CONTAINER:
11887c478bd9Sstevel@tonic-gate output("<Container name=\"%s\">\n", name);
11897c478bd9Sstevel@tonic-gate *end_node = end_container_xml;
11907c478bd9Sstevel@tonic-gate break;
11917c478bd9Sstevel@tonic-gate default:
11927c478bd9Sstevel@tonic-gate output("<Location name=\"%s\">\n", name);
11937c478bd9Sstevel@tonic-gate *end_node = end_location_xml;
11947c478bd9Sstevel@tonic-gate break;
11957c478bd9Sstevel@tonic-gate }
11967c478bd9Sstevel@tonic-gate
11977c478bd9Sstevel@tonic-gate *end_args = (void *) name;
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate /*
12017c478bd9Sstevel@tonic-gate * Print node info and, where appropriate, node contents
12027c478bd9Sstevel@tonic-gate */
12037c478bd9Sstevel@tonic-gate /* ARGSUSED */
12047c478bd9Sstevel@tonic-gate static fru_errno_t
process_node(fru_nodehdl_t node,const char * path,const char * name,void * args,end_node_fp_t * end_node,void ** end_args)12057c478bd9Sstevel@tonic-gate process_node(fru_nodehdl_t node, const char *path, const char *name,
12067c478bd9Sstevel@tonic-gate void *args, end_node_fp_t *end_node, void **end_args)
12077c478bd9Sstevel@tonic-gate {
12087c478bd9Sstevel@tonic-gate int status;
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate fru_node_t fru_type = FRU_NODE_UNKNOWN;
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate
12137c478bd9Sstevel@tonic-gate if ((status = fru_get_node_type(node, &fru_type)) != FRU_SUCCESS) {
12147c478bd9Sstevel@tonic-gate saved_status = status;
12157c478bd9Sstevel@tonic-gate error(gettext("Error getting node type: %s\n"),
12167c478bd9Sstevel@tonic-gate fru_strerror(status));
12177c478bd9Sstevel@tonic-gate }
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate if (containers_only) {
12207c478bd9Sstevel@tonic-gate if (fru_type != FRU_NODE_CONTAINER)
12217c478bd9Sstevel@tonic-gate return (FRU_SUCCESS);
12227c478bd9Sstevel@tonic-gate name = path;
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate
12257c478bd9Sstevel@tonic-gate /* Introduce the node */
12267c478bd9Sstevel@tonic-gate assert(print_node != NULL);
12277c478bd9Sstevel@tonic-gate print_node(fru_type, path, name, end_node, end_args);
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate if (list_only)
12307c478bd9Sstevel@tonic-gate return (FRU_SUCCESS);
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate /* Print the contents of each packet in each segment of a container */
12337c478bd9Sstevel@tonic-gate if (fru_type == FRU_NODE_CONTAINER) {
12347c478bd9Sstevel@tonic-gate if (xml) output("<ContainerData>\n");
12357c478bd9Sstevel@tonic-gate if ((status =
12367c478bd9Sstevel@tonic-gate fru_for_each_segment(node, print_packets_in_segment,
12377c478bd9Sstevel@tonic-gate NULL))
12387c478bd9Sstevel@tonic-gate != FRU_SUCCESS) {
12397c478bd9Sstevel@tonic-gate saved_status = status;
12407c478bd9Sstevel@tonic-gate error(gettext("Error processing node \"%s\": %s\n"),
12417c478bd9Sstevel@tonic-gate name, fru_strerror(status));
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate if (xml) output("</ContainerData>\n");
12447c478bd9Sstevel@tonic-gate }
12457c478bd9Sstevel@tonic-gate
12467c478bd9Sstevel@tonic-gate return (FRU_SUCCESS);
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate /*
12507c478bd9Sstevel@tonic-gate * Process the node if its path matches the search path in "args"
12517c478bd9Sstevel@tonic-gate */
12527c478bd9Sstevel@tonic-gate /* ARGSUSED */
12537c478bd9Sstevel@tonic-gate static fru_errno_t
process_matching_node(fru_nodehdl_t node,const char * path,const char * name,void * args,end_node_fp_t * end_node,void ** end_args)12547c478bd9Sstevel@tonic-gate process_matching_node(fru_nodehdl_t node, const char *path, const char *name,
12557c478bd9Sstevel@tonic-gate void *args, end_node_fp_t *end_node, void **end_args)
12567c478bd9Sstevel@tonic-gate {
12577c478bd9Sstevel@tonic-gate int status;
12587c478bd9Sstevel@tonic-gate
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate if (!fru_pathmatch(path, args))
12617c478bd9Sstevel@tonic-gate return (FRU_SUCCESS);
12627c478bd9Sstevel@tonic-gate
12637c478bd9Sstevel@tonic-gate status = process_node(node, path, path, args, end_node, end_args);
12647c478bd9Sstevel@tonic-gate
12657c478bd9Sstevel@tonic-gate return ((status == FRU_SUCCESS) ? FRU_WALK_TERMINATE : status);
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate /*
12697c478bd9Sstevel@tonic-gate * Write the trailer required for well-formed DTD-compliant XML
12707c478bd9Sstevel@tonic-gate */
12717c478bd9Sstevel@tonic-gate static void
terminate_xml()12727c478bd9Sstevel@tonic-gate terminate_xml()
12737c478bd9Sstevel@tonic-gate {
12747c478bd9Sstevel@tonic-gate errno = 0;
12757c478bd9Sstevel@tonic-gate if (ftell(errlog) > 0) {
12767c478bd9Sstevel@tonic-gate char c;
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate output("<ErrorLog>\n");
12797c478bd9Sstevel@tonic-gate rewind(errlog);
12807c478bd9Sstevel@tonic-gate if (!errno)
12817c478bd9Sstevel@tonic-gate while ((c = getc(errlog)) != EOF)
12827c478bd9Sstevel@tonic-gate xputchar(c);
12837c478bd9Sstevel@tonic-gate output("</ErrorLog>\n");
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate
12867c478bd9Sstevel@tonic-gate if (errno) {
12877c478bd9Sstevel@tonic-gate /*NOTREACHED*/
12887c478bd9Sstevel@tonic-gate errlog = NULL;
12897c478bd9Sstevel@tonic-gate error(gettext("Error copying error messages to \"ErrorLog\""),
12907c478bd9Sstevel@tonic-gate strerror(errno));
12917c478bd9Sstevel@tonic-gate }
12927c478bd9Sstevel@tonic-gate
12937c478bd9Sstevel@tonic-gate output("</FRUID_XML_Tree>\n");
12947c478bd9Sstevel@tonic-gate }
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate /*
12977c478bd9Sstevel@tonic-gate * Print available FRU ID information
12987c478bd9Sstevel@tonic-gate */
12997c478bd9Sstevel@tonic-gate int
prtfru(const char * searchpath,int containers_only_flag,int list_only_flag,int xml_flag)13007c478bd9Sstevel@tonic-gate prtfru(const char *searchpath, int containers_only_flag, int list_only_flag,
13017c478bd9Sstevel@tonic-gate int xml_flag)
13027c478bd9Sstevel@tonic-gate {
13037c478bd9Sstevel@tonic-gate fru_errno_t status;
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate fru_nodehdl_t frutree = 0;
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate /* Copy parameter flags to global flags */
13097c478bd9Sstevel@tonic-gate containers_only = containers_only_flag;
13107c478bd9Sstevel@tonic-gate list_only = list_only_flag;
13117c478bd9Sstevel@tonic-gate xml = xml_flag;
13127c478bd9Sstevel@tonic-gate
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate /* Help arrange for correct, efficient interleaving of output */
13157c478bd9Sstevel@tonic-gate (void) setvbuf(stderr, NULL, _IOLBF, 0);
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate /* Initialize for XML--or not */
13197c478bd9Sstevel@tonic-gate if (xml) {
13207c478bd9Sstevel@tonic-gate safeputchar = xputchar;
13217c478bd9Sstevel@tonic-gate safeputs = xputs;
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate print_node = print_node_xml;
13247c478bd9Sstevel@tonic-gate
13257c478bd9Sstevel@tonic-gate if ((errlog = tmpfile()) == NULL) {
13267c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
13277c478bd9Sstevel@tonic-gate "Error creating error log file: %s\n",
13287c478bd9Sstevel@tonic-gate strerror(errno));
13297c478bd9Sstevel@tonic-gate return (1);
13307c478bd9Sstevel@tonic-gate }
13317c478bd9Sstevel@tonic-gate
13327c478bd9Sstevel@tonic-gate /* Output the XML preamble */
13337c478bd9Sstevel@tonic-gate output("<?xml version=\"1.0\" ?>\n"
13347c478bd9Sstevel@tonic-gate "<!--\n"
13357c478bd9Sstevel@tonic-gate " Copyright 2000-2002 Sun Microsystems, Inc. "
13367c478bd9Sstevel@tonic-gate "All rights reserved.\n"
13377c478bd9Sstevel@tonic-gate " Use is subject to license terms.\n"
13387c478bd9Sstevel@tonic-gate "-->\n\n"
13397c478bd9Sstevel@tonic-gate "<!DOCTYPE FRUID_XML_Tree SYSTEM \"prtfrureg.dtd\">\n\n"
13407c478bd9Sstevel@tonic-gate "<FRUID_XML_Tree>\n");
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate /* Arrange to always properly terminate XML */
13437c478bd9Sstevel@tonic-gate if (atexit(terminate_xml))
13447c478bd9Sstevel@tonic-gate error(gettext("Warning: XML will not be terminated: "
13457c478bd9Sstevel@tonic-gate "%s\n"), strerror(errno));
13467c478bd9Sstevel@tonic-gate } else
13477c478bd9Sstevel@tonic-gate print_node = print_node_path;
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate
13507c478bd9Sstevel@tonic-gate /* Get the root node */
13517c478bd9Sstevel@tonic-gate if ((status = fru_get_root(&frutree)) == FRU_NODENOTFOUND) {
1352043728a3Sdt207653 error(gettext("This system does not support PICL "
1353043728a3Sdt207653 "infrastructure to provide FRUID data\n"
1354043728a3Sdt207653 "Please use the platform SP to access the FRUID "
1355043728a3Sdt207653 "information\n"));
13567c478bd9Sstevel@tonic-gate return (1);
13577c478bd9Sstevel@tonic-gate } else if (status != FRU_SUCCESS) {
13587c478bd9Sstevel@tonic-gate error(gettext("Unable to access FRU ID data: %s\n"),
13597c478bd9Sstevel@tonic-gate fru_strerror(status));
13607c478bd9Sstevel@tonic-gate return (1);
13617c478bd9Sstevel@tonic-gate }
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate /* Process the tree */
13647c478bd9Sstevel@tonic-gate if (searchpath == NULL) {
13657c478bd9Sstevel@tonic-gate status = fru_walk_tree(frutree, "", process_node, NULL);
13667c478bd9Sstevel@tonic-gate } else {
13677c478bd9Sstevel@tonic-gate status = fru_walk_tree(frutree, "", process_matching_node,
13687c478bd9Sstevel@tonic-gate (void *)searchpath);
13697c478bd9Sstevel@tonic-gate if (status == FRU_WALK_TERMINATE) {
13707c478bd9Sstevel@tonic-gate status = FRU_SUCCESS;
13717c478bd9Sstevel@tonic-gate } else if (status == FRU_SUCCESS) {
13727c478bd9Sstevel@tonic-gate error(gettext("\"%s\" not found\n"), searchpath);
13737c478bd9Sstevel@tonic-gate return (1);
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate if (status != FRU_SUCCESS)
13787c478bd9Sstevel@tonic-gate error(gettext("Error processing FRU tree: %s\n"),
13797c478bd9Sstevel@tonic-gate fru_strerror(status));
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate return (((status == FRU_SUCCESS) && (saved_status == 0)) ? 0 : 1);
13827c478bd9Sstevel@tonic-gate }
1383