Home | History | Annotate | Download | only in prtfru
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  1699  ps154918  * Common Development and Distribution License (the "License").
      6  1699  ps154918  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21     0    stevel /*
     22  6201  dt207653  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23     0    stevel  * Use is subject to license terms.
     24     0    stevel  */
     25     0    stevel 
     26     0    stevel #include <alloca.h>
     27     0    stevel #include <assert.h>
     28     0    stevel #include <errno.h>
     29     0    stevel #include <libintl.h>
     30     0    stevel #include <stdarg.h>
     31     0    stevel #include <stdio.h>
     32     0    stevel #include <stdlib.h>
     33     0    stevel #include <string.h>
     34  4392  dt207653 #include <ctype.h>
     35  8244     Dipti #include <wchar.h>
     36  8244     Dipti #include <wctype.h>
     37     0    stevel 
     38     0    stevel #include "fru_tag.h"
     39     0    stevel #include "libfrup.h"
     40     0    stevel #include "libfrureg.h"
     41     0    stevel 
     42     0    stevel 
     43     0    stevel #define	NUM_ITER_BYTES 4
     44     0    stevel 
     45     0    stevel #define	HEAD_ITER 0
     46     0    stevel #define	TAIL_ITER 1	/*  not used  */
     47     0    stevel #define	NUM_ITER  2
     48     0    stevel #define	MAX_ITER  3
     49     0    stevel 
     50     0    stevel #define	INDENT 3
     51     0    stevel #define	TIMESTRINGLEN 128
     52  1699  ps154918 #define	TEMPERATURE_OFFSET 73
     53  5270  dt207653 #define	MIN_VERSION 17
     54  7247  aa222140 #define	GMT "%a, %b %d %Y %H:%M:%S GMT"
     55  8244     Dipti 
     56  8244     Dipti typedef struct
     57  8244     Dipti {
     58  8244     Dipti     uint8_t value;
     59  8244     Dipti     char *data;
     60  8244     Dipti } Status_CurrentR;
     61  8244     Dipti 
     62  8244     Dipti Status_CurrentR Status_CurrentR_status[] = {
     63  8244     Dipti 	{ 0x00, "OK"},
     64  8244     Dipti 	{ 0x04, "DEEMED FAULTY"},
     65  8244     Dipti 	{ 0x08, "FRU DETECTED"},
     66  8244     Dipti 	{ 0x0c, "FRU DETECTED, DEEMED FAULTY"},
     67  8244     Dipti 	{ 0x10, "PROXIED FAULT"},
     68  8244     Dipti 	{ 0x14, "DEEMED FAULTY.  Also PROXIED FAULT"},
     69  8244     Dipti 	{ 0x18, "FRU DETECTED.  Also PROXIED FAULT"},
     70  8244     Dipti 	{ 0x1c, "FRU DETECTED, DEEMED FAULTY.  Also PROXIED FAULT"},
     71  8244     Dipti 	{ 0x20, "SUSPECT"},
     72  8244     Dipti 	{ 0x24, "SUSPECT, DEEMED FAULTY"},
     73  8244     Dipti 	{ 0x28, "SUSPECT, FRU DETECTED"},
     74  8244     Dipti 	{ 0x2c, "SUSPECT, FRU DETECTED, DEEMED FAULTY"},
     75  8244     Dipti 	{ 0x30, "SUSPECT.  Also PROXIED FAULT"},
     76  8244     Dipti 	{ 0x34, "SUSPECT, DEEMED FAULTY.  Also PROXIED FAULT"},
     77  8244     Dipti 	{ 0x38, "SUSPECT, FRU DETECTED.  Also PROXIED FAULT"},
     78  8244     Dipti 	{ 0x3c, "SUSPECT, FRU DETECTED, DEEMED FAULTY.  Also PROXIED FAULT"},
     79  8244     Dipti 	{ 0x40, "MAINTENANCE REQUIRED"},
     80  8244     Dipti 	{ 0x44, "MAINTENANCE REQUIRED, DEEMED FAULTY"},
     81  8244     Dipti 	{ 0x48, "MAINTENANCE REQUIRED, FRU DETECTED"},
     82  8244     Dipti 	{ 0x4c, "MAINTENANCE REQUIRED, FRU DETECTED, DEEMED FAULTY"},
     83  8244     Dipti 	{ 0x50, "MAINTENANCE REQUIRED.  Also PROXIED FAULT"},
     84  8244     Dipti 	{ 0x54, "MAINTENANCE REQUIRED, DEEMED FAULTY.  Also PROXIED FAULT"},
     85  8244     Dipti 	{ 0x58, "MAINTENANCE REQUIRED, FRU DETECTED.  Also PROXIED FAULT"},
     86  8244     Dipti 	{ 0x5c, "MAINTENANCE REQUIRED, FRU DETECTED, DEEMED FAULTY. \
     87  8244     Dipti 	    Also PROXIED FAULT"},
     88  8244     Dipti 	{ 0x60, "MAINTENANCE REQUIRED, SUSPECT"},
     89  8244     Dipti 	{ 0x64, "MAINTENANCE REQUIRED, SUSPECT, DEEMED FAULTY"},
     90  8244     Dipti 	{ 0x68, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED"},
     91  8244     Dipti 	{ 0x6c, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED, DEEMED FAULTY"},
     92  8244     Dipti 	{ 0x70, "MAINTENANCE REQUIRED, SUSPECT.  Also PROXIED FAULT"},
     93  8244     Dipti 	{ 0x74, "MAINTENANCE REQUIRED, SUSPECT, DEEMED FAULTY.\
     94  8244     Dipti 	    Also PROXIED FAULT"},
     95  8244     Dipti 	{ 0x78, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED. \
     96  8244     Dipti 	    Also PROXIED FAULT"},
     97  8244     Dipti 	{ 0x7c, "MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED, \
     98  8244     Dipti 	    DEEMED FAULTY.  Also PROXIED FAULT"},
     99  8244     Dipti 	{ 0x80, "DISABLED"},
    100  8244     Dipti 	{ 0x84, "DISABLED, DEEMED FAULTY"},
    101  8244     Dipti 	{ 0x88, "DISABLED, FRU DETECTED"},
    102  8244     Dipti 	{ 0x8c, "DISABLED, FRU DETECTED, DEEMED FAULTY"},
    103  8244     Dipti 	{ 0x90, "DISABLED.  Also PROXIED FAULT"},
    104  8244     Dipti 	{ 0x94, "DISABLED, DEEMED FAULTY.  Also PROXIED FAULT"},
    105  8244     Dipti 	{ 0x98, "DISABLED, FRU DETECTED.  Also PROXIED FAULT"},
    106  8244     Dipti 	{ 0x9c, "DISABLED, FRU DETECTED, DEEMED FAULTY.  Also PROXIED FAULT"},
    107  8244     Dipti 	{ 0xa0, "DISABLED, SUSPECT"},
    108  8244     Dipti 	{ 0xa4, "DISABLED, SUSPECT, DEEMED FAULTY"},
    109  8244     Dipti 	{ 0xa8, "DISABLED, SUSPECT, FRU DETECTED"},
    110  8244     Dipti 	{ 0xac, "DISABLED, SUSPECT, FRU DETECTED, DEEMED FAULTY"},
    111  8244     Dipti 	{ 0xb0, "DISABLED, SUSPECT.  Also PROXIED FAULT"},
    112  8244     Dipti 	{ 0xb4, "DISABLED, SUSPECT, DEEMED FAULTY.  Also PROXIED FAULT"},
    113  8244     Dipti 	{ 0xb8, "DISABLED, SUSPECT, FRU DETECTED.  Also PROXIED FAULT"},
    114  8244     Dipti 	{ 0xbc, "DISABLED, SUSPECT, FRU DETECTED, \
    115  8244     Dipti 	    DEEMED FAULTY.  Also PROXIED FAULT"},
    116  8244     Dipti 	{ 0xc0, "DISABLED, MAINTENANCE REQUIRED"},
    117  8244     Dipti 	{ 0xc4, "DISABLED, MAINTENANCE REQUIRED, DEEMED FAULTY"},
    118  8244     Dipti 	{ 0xc8, "DISABLED, MAINTENANCE REQUIRED, FRU DETECTED"},
    119  8244     Dipti 	{ 0xcc, "DISABLED, MAINTENANCE REQUIRED, FRU DETECTED, DEEMED FAULTY"},
    120  8244     Dipti 	{ 0xd0, "DISABLED, MAINTENANCE REQUIRED.  Also PROXIED FAULT"},
    121  8244     Dipti 	{ 0xd4, "DISABLED, MAINTENANCE REQUIRED, \
    122  8244     Dipti 	    DEEMED FAULTY.  Also PROXIED FAULT"},
    123  8244     Dipti 	{ 0xd8, "DISABLED, MAINTENANCE REQUIRED, \
    124  8244     Dipti 	    FRU DETECTED.  Also PROXIED FAULT"},
    125  8244     Dipti 	{ 0xdc, "DISABLED, MAINTENANCE REQUIRED, FRU DETECTED, \
    126  8244     Dipti 	    DEEMED FAULTY.  Also PROXIED FAULT"},
    127  8244     Dipti 	{ 0xe0, "DISABLED, MAINTENANCE REQUIRED, SUSPECT"},
    128  8244     Dipti 	{ 0xe4, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, DEEMED FAULTY"},
    129  8244     Dipti 	{ 0xe8, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, FRU DETECTED"},
    130  8244     Dipti 	{ 0xec, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
    131  8244     Dipti 	    FRU DETECTED, DEEMED FAULTY"},
    132  8244     Dipti 	{ 0xf0, "DISABLED, MAINTENANCE REQUIRED, SUSPECT.  Also PROXIED FAULT"},
    133  8244     Dipti 	{ 0xf4, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
    134  8244     Dipti 	    DEEMED FAULTY.  Also PROXIED FAULT"},
    135  8244     Dipti 	{ 0xf8, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
    136  8244     Dipti 	    FRU DETECTED.  Also PROXIED FAULT"},
    137  8244     Dipti 	{ 0xfc, "DISABLED, MAINTENANCE REQUIRED, SUSPECT, \
    138  8244     Dipti 	    FRU DETECTED, DEEMED FAULTY.  Also PROXIED FAULT"},
    139  8244     Dipti 	{ 0xff, "RETIRED"}
    140  8244     Dipti };
    141     0    stevel 
    142     0    stevel static void	(*print_node)(fru_node_t fru_type, const char *path,
    143     0    stevel 				const char *name, end_node_fp_t *end_node,
    144     0    stevel 				void **end_args);
    145     0    stevel 
    146  4392  dt207653 static void	print_element(const uint8_t *data, const fru_regdef_t *def,
    147  4392  dt207653 const char *parent_path, int indent);
    148  4392  dt207653 
    149     0    stevel static char	tagname[sizeof ("?_0123456789_0123456789_0123456789")];
    150     0    stevel 
    151     0    stevel static int	containers_only = 0, list_only = 0, saved_status = 0, xml = 0;
    152     0    stevel 
    153     0    stevel static FILE	*errlog;
    154     0    stevel 
    155  4392  dt207653 int iterglobal = 0;
    156  4392  dt207653 int FMAmessageR = -1;
    157  5015  dt207653 int Fault_Install_DataR_flag = 0;
    158  5015  dt207653 int Power_On_DataR_flag = 0;
    159  5270  dt207653 int spd_memtype = 0;
    160  5270  dt207653 int spd_revision = 0;
    161     0    stevel /*
    162     0    stevel  * Definition for data elements found in devices but not found in
    163     0    stevel  * the system's version of libfrureg
    164     0    stevel  */
    165     0    stevel static fru_regdef_t  unknown = {
    166     0    stevel 	REGDEF_VERSION,
    167     0    stevel 	tagname,
    168     0    stevel 	-1,
    169     0    stevel 	-1,
    170     0    stevel 	-1,
    171     0    stevel 	-1,
    172     0    stevel 	FDTYPE_ByteArray,
    173     0    stevel 	FDISP_Hex,
    174     0    stevel 	FRU_WHICH_UNDEFINED,
    175     0    stevel 	FRU_WHICH_UNDEFINED,
    176     0    stevel 	0,
    177     0    stevel 	NULL,
    178     0    stevel 	0,
    179     0    stevel 	FRU_NOT_ITERATED,
    180     0    stevel 	NULL
    181     0    stevel };
    182     0    stevel 
    183     0    stevel 
    184     0    stevel /*
    185     0    stevel  * Write message to standard error and possibly the error log buffer
    186     0    stevel  */
    187     0    stevel static void
    188     0    stevel error(const char *format, ...)
    189     0    stevel {
    190     0    stevel 	va_list	args;
    191     0    stevel 
    192     0    stevel 
    193     0    stevel 	/* make relevant output appear before error message */
    194     0    stevel 	if (fflush(stdout) == EOF) {
    195     0    stevel 		(void) fprintf(stderr, "Error flushing output:  %s\n",
    196  5015  dt207653 		    strerror(errno));
    197     0    stevel 		exit(1);
    198     0    stevel 	}
    199     0    stevel 
    200     0    stevel 	va_start(args, format);
    201     0    stevel 	if (vfprintf(stderr, format, args) < 0) exit(1);
    202     0    stevel 	if (errlog && (vfprintf(errlog, format, args) < 0)) exit(1);
    203     0    stevel }
    204     0    stevel 
    205     0    stevel /*
    206     0    stevel  * Write message to standard output
    207     0    stevel  */
    208     0    stevel static void
    209     0    stevel output(const char *format, ...)
    210     0    stevel {
    211     0    stevel 	va_list   args;
    212     0    stevel 
    213     0    stevel 
    214     0    stevel 	va_start(args, format);
    215     0    stevel 	if (vfprintf(stdout, format, args) < 0) {
    216     0    stevel 		error(gettext("Error writing output:  %s\n"),
    217  5015  dt207653 		    strerror(errno));
    218     0    stevel 		exit(1);
    219     0    stevel 	}
    220     0    stevel }
    221     0    stevel 
    222     0    stevel /*
    223     0    stevel  * Safe wrapper for putchar()
    224     0    stevel  */
    225     0    stevel static void
    226     0    stevel voidputchar(int c)
    227     0    stevel {
    228     0    stevel 	if (putchar(c) == EOF) {
    229     0    stevel 		error(gettext("Error writing output:  %s\n"),
    230  5015  dt207653 		    strerror(errno));
    231     0    stevel 		exit(1);
    232     0    stevel 	}
    233     0    stevel }
    234     0    stevel 
    235     0    stevel static void  (*safeputchar)(int c) = voidputchar;
    236     0    stevel 
    237     0    stevel /*
    238     0    stevel  * Safe wrapper for puts()
    239     0    stevel  */
    240     0    stevel static void
    241     0    stevel voidputs(const char *s)
    242     0    stevel {
    243     0    stevel 	if (fputs(s, stdout) == EOF) {
    244     0    stevel 		error(gettext("Error writing output:  %s\n"),
    245  5015  dt207653 		    strerror(errno));
    246     0    stevel 		exit(1);
    247     0    stevel 	}
    248     0    stevel }
    249     0    stevel 
    250     0    stevel static void  (*safeputs)(const char *s) = voidputs;
    251     0    stevel 
    252     0    stevel /*
    253     0    stevel  * XML-safe wrapper for putchar():  quotes XML-special characters
    254     0    stevel  */
    255     0    stevel static void
    256     0    stevel xputchar(int c)
    257     0    stevel {
    258     0    stevel 	switch (c) {
    259     0    stevel 	case '<':
    260     0    stevel 		c = fputs("&lt;", stdout);
    261     0    stevel 		break;
    262     0    stevel 	case '>':
    263     0    stevel 		c = fputs("&gt;", stdout);
    264     0    stevel 		break;
    265     0    stevel 	case '&':
    266     0    stevel 		c = fputs("&amp;", stdout);
    267     0    stevel 		break;
    268     0    stevel 	case '"':
    269     0    stevel 		c = fputs("&quot;", stdout);
    270     0    stevel 		break;
    271     0    stevel 	default:
    272     0    stevel 		c = putchar(c);
    273     0    stevel 		break;
    274     0    stevel 	}
    275     0    stevel 
    276     0    stevel 	if (c == EOF) {
    277     0    stevel 		error(gettext("Error writing output:  %s\n"),
    278  5015  dt207653 		    strerror(errno));
    279     0    stevel 		exit(1);
    280     0    stevel 	}
    281     0    stevel }
    282     0    stevel 
    283     0    stevel /*
    284     0    stevel  * XML-safe analog of puts():  quotes XML-special characters
    285     0    stevel  */
    286     0    stevel static void
    287     0    stevel xputs(const char *s)
    288     0    stevel {
    289     0    stevel 	char c;
    290     0    stevel 
    291     0    stevel 	for (/* */; ((c = *s) != 0); s++)
    292     0    stevel 		xputchar(c);
    293     0    stevel }
    294     0    stevel 
    295     0    stevel /*
    296     0    stevel  * Output the XML DTD derived from the registry provided by libfrureg
    297     0    stevel  */
    298     0    stevel int
    299     0    stevel output_dtd(void)
    300     0    stevel {
    301     0    stevel 	char			**element;
    302     0    stevel 
    303     0    stevel 	unsigned int		i, j, num_elements = 0;
    304     0    stevel 
    305     0    stevel 	uint8_t			*tagged;
    306     0    stevel 
    307     0    stevel 	const fru_regdef_t	*def;
    308     0    stevel 
    309     0    stevel 
    310     0    stevel 	if (((element = fru_reg_list_entries(&num_elements)) == NULL) ||
    311     0    stevel 	    (num_elements == 0)) {
    312     0    stevel 		error(gettext("No FRU ID Registry elements"));
    313     0    stevel 		return (1);
    314     0    stevel 	}
    315     0    stevel 
    316     0    stevel 	if ((tagged = calloc(num_elements, sizeof (*tagged))) == NULL) {
    317     0    stevel 		error(gettext("Unable to get memory for tagged element list"),
    318  5015  dt207653 		    strerror(errno));
    319     0    stevel 		return (1);
    320     0    stevel 	}
    321     0    stevel 
    322     0    stevel 	/*
    323     0    stevel 	 * Output the DTD preamble
    324     0    stevel 	 */
    325     0    stevel 	output("<!ELEMENT FRUID_XML_Tree (Parameter*, "
    326     0    stevel 	    "(Fru | Location | Container)*,\n"
    327     0    stevel 	    "                          Parameter*, ErrorLog?, Parameter*)>\n"
    328     0    stevel 	    "<!ATTLIST FRUID_XML_Tree>\n"
    329     0    stevel 	    "\n"
    330     0    stevel 	    "<!ELEMENT Parameter EMPTY>\n"
    331     0    stevel 	    "<!ATTLIST Parameter type CDATA #REQUIRED>\n"
    332     0    stevel 	    "<!ATTLIST Parameter name CDATA #REQUIRED>\n"
    333     0    stevel 	    "<!ATTLIST Parameter value CDATA #REQUIRED>\n"
    334     0    stevel 	    "\n"
    335     0    stevel 	    "<!ELEMENT Fru (Fru | Location | Container)*>\n"
    336     0    stevel 	    "<!ATTLIST Fru name CDATA #REQUIRED>\n"
    337     0    stevel 	    "\n"
    338     0    stevel 	    "<!ELEMENT Location (Fru | Location | Container)*>\n"
    339  1699  ps154918 	    "<!ATTLIST Location\n"
    340  1699  ps154918 	    "	name CDATA #IMPLIED\n"
    341  1699  ps154918 	    "	value CDATA #IMPLIED\n"
    342  1699  ps154918 	    ">\n"
    343     0    stevel 	    "\n"
    344     0    stevel 	    "<!ELEMENT Container (ContainerData?, "
    345     0    stevel 	    "(Fru | Location | Container)*)>\n"
    346     0    stevel 	    "<!ATTLIST Container name CDATA #REQUIRED>\n"
    347     0    stevel 	    "<!ATTLIST Container imagefile CDATA #IMPLIED>\n"
    348     0    stevel 	    "\n"
    349     0    stevel 	    "<!ELEMENT ContainerData (Segment*)>\n"
    350     0    stevel 	    "<!ATTLIST ContainerData>\n"
    351     0    stevel 	    "\n"
    352     0    stevel 	    "<!ATTLIST Segment name CDATA #REQUIRED>\n"
    353     0    stevel 	    "\n"
    354     0    stevel 	    "<!ELEMENT Index EMPTY>\n"
    355     0    stevel 	    "<!ATTLIST Index value CDATA #REQUIRED>\n"
    356     0    stevel 	    "\n"
    357     0    stevel 	    "<!ELEMENT ErrorLog (#PCDATA)>\n"
    358     0    stevel 	    "<!ATTLIST ErrorLog>\n"
    359     0    stevel 	    "\n");
    360     0    stevel 
    361     0    stevel 	/*
    362     0    stevel 	 * Output the definition for each element
    363     0    stevel 	 */
    364     0    stevel 	for (i = 0; i < num_elements; i++) {
    365     0    stevel 		assert(element[i] != NULL);
    366  1699  ps154918 		/* Prevent incompatible duplicate defn. from FRUID Registry. */
    367  1699  ps154918 		if ((strcmp("Location", element[i])) == 0) continue;
    368     0    stevel 		if ((def = fru_reg_lookup_def_by_name(element[i])) == NULL) {
    369     0    stevel 			error(gettext("Error looking up registry "
    370  5015  dt207653 			    "definition for \"%s\"\n"),
    371  5015  dt207653 			    element[i]);
    372     0    stevel 			return (1);
    373     0    stevel 		}
    374     0    stevel 
    375     0    stevel 		if (def->tagType != FRU_X) tagged[i] = 1;
    376     0    stevel 
    377     0    stevel 		if (def->dataType == FDTYPE_Record) {
    378     0    stevel 			if (def->iterationType == FRU_NOT_ITERATED)
    379     0    stevel 				output("<!ELEMENT %s (%s", element[i],
    380     0    stevel 				    def->enumTable[0].text);
    381     0    stevel 			else
    382     0    stevel 				output("<!ELEMENT %s (Index_%s*)>\n"
    383     0    stevel 				    "<!ATTLIST Index_%s>\n"
    384     0    stevel 				    "<!ELEMENT Index_%s (%s",
    385     0    stevel 				    element[i], element[i], element[i],
    386     0    stevel 				    element[i], def->enumTable[0].text);
    387     0    stevel 
    388     0    stevel 			for (j = 1; j < def->enumCount; j++)
    389     0    stevel 				output(",\n\t%s", def->enumTable[j].text);
    390     0    stevel 
    391     0    stevel 			output(")>\n");
    392     0    stevel 		} else if (def->iterationType == FRU_NOT_ITERATED) {
    393     0    stevel 			output("<!ELEMENT %s EMPTY>\n"
    394     0    stevel 			    "<!ATTLIST %s value CDATA #REQUIRED>\n",
    395     0    stevel 			    element[i], element[i]);
    396     0    stevel 
    397     0    stevel 			if (def->dataType == FDTYPE_Enumeration) {
    398     0    stevel 				output("<!-- %s valid enumeration values\n");
    399     0    stevel 				for (j = 0; j < def->enumCount; j++) {
    400     0    stevel 					output("\t\"");
    401     0    stevel 					xputs(def->enumTable[j].text);
    402     0    stevel 					output("\"\n");
    403     0    stevel 				}
    404     0    stevel 				output("-->\n");
    405     0    stevel 			}
    406     0    stevel 		}
    407     0    stevel 		else
    408     0    stevel 			output("<!ELEMENT %s (Index*)>\n", element[i]);
    409     0    stevel 
    410     0    stevel 		output("\n");
    411     0    stevel 	}
    412     0    stevel 
    413     0    stevel 	/* Provide for returning the tag for an "unknown" element */
    414     0    stevel 	output("<!ATTLIST UNKNOWN tag CDATA \"UNKNOWN\">\n\n");
    415     0    stevel 
    416     0    stevel 
    417     0    stevel 	/*
    418     0    stevel 	 * List all data elements as possible members of "Segment"
    419     0    stevel 	 */
    420     0    stevel 	output("<!ELEMENT Segment ((UNKNOWN");
    421     0    stevel 	for (i = 0; i < num_elements; i++) {
    422     0    stevel 		if (tagged[i]) output("\n\t| %s", element[i]);
    423     0    stevel 		free(element[i]);
    424     0    stevel 	}
    425     0    stevel 	output(")*)>\n");
    426     0    stevel 	free(element);
    427     0    stevel 	free(tagged);
    428     0    stevel 
    429     0    stevel 	return (0);
    430     0    stevel }
    431  4392  dt207653 /*
    432  4392  dt207653  * Function to convert bcd to binary to correct the SPD_Manufacturer_Week
    433  4392  dt207653  *
    434  4392  dt207653  */
    435  4392  dt207653 static void convertbcdtobinary(int *val)
    436  4392  dt207653 {
    437  5270  dt207653 	unsigned int newval = (unsigned int)*val, tmpval = 0;
    438  5270  dt207653 	while (newval > 0) {
    439  5270  dt207653 		tmpval = (tmpval << 4) | (newval & 0xF);
    440  5270  dt207653 		newval >>= 4;
    441  5270  dt207653 	}
    442  5270  dt207653 	while (tmpval > 0) {
    443  5270  dt207653 		newval = (newval * 10) + (tmpval & 0xF);
    444  5270  dt207653 		tmpval >>= 4;
    445  4392  dt207653 	}
    446  4392  dt207653 	*val = newval;
    447  4392  dt207653 }
    448  4392  dt207653 
    449  8244     Dipti /*
    450  8244     Dipti  * Checking UTF-8 printable charecter
    451  8244     Dipti  */
    452  8244     Dipti static int check_utf_char(const uint8_t *field, int len)
    453  8244     Dipti {
    454  8244     Dipti 	int i, status = 0;
    455  8244     Dipti 	char tmp[128], tmp1[128], tmp2[128];
    456  8244     Dipti 	(void) sprintf(tmp, " (Invalid Data");
    457  8244     Dipti 	(void) sprintf(tmp2, "0x");
    458  8244     Dipti 	for (i = 0; i < len && field[i]; i++) {
    459  8244     Dipti 		(void) sprintf(tmp1, "%2.2X", field[i]);
    460  8244     Dipti 		(void) strcat(tmp2, tmp1);
    461  8244     Dipti 		if (iswprint(field[i]) == 0) {
    462  8244     Dipti 			status = 1;
    463  8244     Dipti 			(void) sprintf(tmp1, " : 0x%2.2X", field[i]);
    464  8244     Dipti 			(void) strcat(tmp, tmp1);
    465  8244     Dipti 		}
    466  8244     Dipti 	}
    467  8244     Dipti 	if (status) {
    468  8244     Dipti 		(void) sprintf(tmp1, ")");
    469  8244     Dipti 		(void) strcat(tmp, tmp1);
    470  8244     Dipti 		(void) strcat(tmp2, tmp);
    471  8244     Dipti 		output("%s", tmp2);
    472  8244     Dipti 	}
    473  8244     Dipti 	return (status);
    474  8244     Dipti }
    475     0    stevel 
    476     0    stevel /*
    477     0    stevel  * Safely pretty-print the value of a field
    478     0    stevel  */
    479     0    stevel static void
    480     0    stevel print_field(const uint8_t *field, const fru_regdef_t *def)
    481     0    stevel {
    482  4392  dt207653 	char		*errmsg = NULL, timestring[TIMESTRINGLEN], path[16384];
    483     0    stevel 
    484  4392  dt207653 	int		i, valueint;
    485     0    stevel 
    486     0    stevel 	uint64_t	value;
    487     0    stevel 
    488     0    stevel 	time_t		timefield;
    489     0    stevel 
    490  4392  dt207653 	struct tm	*tm;
    491     0    stevel 
    492  4392  dt207653 	uchar_t		first_byte, data[128];
    493  4392  dt207653 
    494  4392  dt207653 	const fru_regdef_t	*new_def;
    495  4392  dt207653 
    496  4392  dt207653 	const char 	*elem_name = NULL;
    497  4392  dt207653 	const char	*parent_path;
    498     0    stevel 	switch (def->dataType) {
    499     0    stevel 	case FDTYPE_Binary:
    500     0    stevel 		assert(def->payloadLen <= sizeof (value));
    501     0    stevel 		switch (def->dispType) {
    502     0    stevel 		case FDISP_Binary:
    503     0    stevel 			for (i = 0; i < def->payloadLen; i++)
    504     0    stevel 				output("%c%c%c%c%c%c%c%c",
    505     0    stevel 				    ((field[i] & 0x80) ? '1' : '0'),
    506     0    stevel 				    ((field[i] & 0x40) ? '1' : '0'),
    507     0    stevel 				    ((field[i] & 0x20) ? '1' : '0'),
    508     0    stevel 				    ((field[i] & 0x10) ? '1' : '0'),
    509     0    stevel 				    ((field[i] & 0x08) ? '1' : '0'),
    510     0    stevel 				    ((field[i] & 0x04) ? '1' : '0'),
    511     0    stevel 				    ((field[i] & 0x02) ? '1' : '0'),
    512     0    stevel 				    ((field[i] & 0x01) ? '1' : '0'));
    513     0    stevel 			return;
    514     0    stevel 		case FDISP_Octal:
    515     0    stevel 		case FDISP_Decimal:
    516     0    stevel 			value = 0;
    517  4392  dt207653 			valueint = 0;
    518     0    stevel 			(void) memcpy((((uint8_t *)&value) +
    519  5015  dt207653 			    sizeof (value) - def->payloadLen),
    520  5015  dt207653 			    field, def->payloadLen);
    521  4392  dt207653 			if ((value != 0) &&
    522  5015  dt207653 			    (strcmp(def->name, "SPD_Manufacture_Week") == 0)) {
    523  4392  dt207653 				valueint = (int)value;
    524  5270  dt207653 				if (spd_memtype && spd_revision) {
    525  5270  dt207653 					convertbcdtobinary(&valueint);
    526  5270  dt207653 					spd_memtype = 0;
    527  5270  dt207653 					spd_revision = 0;
    528  5270  dt207653 				}
    529  4392  dt207653 				output("%d", valueint);
    530  4392  dt207653 				return;
    531  4392  dt207653 			}
    532  1699  ps154918 			if ((value != 0) &&
    533  5015  dt207653 			    ((strcmp(def->name, "Lowest") == 0) ||
    534  5015  dt207653 			    (strcmp(def->name, "Highest") == 0) ||
    535  5015  dt207653 			    (strcmp(def->name, "Latest") == 0)))
    536  1944  ps154918 				output((def->dispType == FDISP_Octal) ?
    537  1944  ps154918 				"%llo" : "%lld (%lld degrees C)",
    538  5015  dt207653 				    value, (value - TEMPERATURE_OFFSET));
    539  1944  ps154918 			else
    540  1944  ps154918 				output((def->dispType == FDISP_Octal) ?
    541     0    stevel 				"%llo" : "%lld", value);
    542     0    stevel 			return;
    543     0    stevel 		case FDISP_Time:
    544     0    stevel 			if (def->payloadLen > sizeof (timefield)) {
    545     0    stevel 				errmsg = "time value too large for formatting";
    546     0    stevel 				break;
    547     0    stevel 			}
    548  4392  dt207653 			timefield = 0;
    549  4392  dt207653 			(void) memcpy((((uint8_t *)&timefield) +
    550  5015  dt207653 			    sizeof (timefield) - def->payloadLen),
    551  5015  dt207653 			    field, def->payloadLen);
    552  4392  dt207653 			if (timefield == 0) {
    553  4392  dt207653 				errmsg = "No Value Recorded";
    554  4392  dt207653 				break;
    555  4392  dt207653 			}
    556  7247  aa222140 			if ((tm = gmtime(&timefield)) == NULL) {
    557  4392  dt207653 				errmsg = "cannot convert time value";
    558  4392  dt207653 				break;
    559  4392  dt207653 			}
    560  7247  aa222140 			if (strftime(timestring, sizeof (timestring), GMT, tm)
    561  4392  dt207653 			    == 0) {
    562     0    stevel 				errmsg = "formatted time would overflow buffer";
    563     0    stevel 				break;
    564     0    stevel 			}
    565     0    stevel 			safeputs(timestring);
    566     0    stevel 			return;
    567     0    stevel 		}
    568     0    stevel 		break;
    569     0    stevel 	case FDTYPE_ASCII:
    570  4392  dt207653 		if (!xml) {
    571  4392  dt207653 			if (strcmp(def->name, "Message") == 0) {
    572  4392  dt207653 				if (FMAmessageR == 0)
    573  4392  dt207653 					elem_name = "FMA_Event_DataR";
    574  4392  dt207653 				else if (FMAmessageR == 1)
    575  4392  dt207653 					elem_name = "FMA_MessageR";
    576  4392  dt207653 				if (elem_name != NULL) {
    577  4392  dt207653 					(void) memcpy(data, field,
    578  5015  dt207653 					    def->payloadLen);
    579  4392  dt207653 					new_def =
    580  5015  dt207653 					    fru_reg_lookup_def_by_name
    581  5015  dt207653 					    (elem_name);
    582  4402  dt207653 					(void) snprintf(path, sizeof (path),
    583  4392  dt207653 					"/Status_EventsR[%d]/Message(FMA)",
    584  5015  dt207653 					    iterglobal);
    585  4392  dt207653 					parent_path = path;
    586  4392  dt207653 					output("\n");
    587  4392  dt207653 					print_element(data, new_def,
    588  5015  dt207653 					    parent_path, 2*INDENT);
    589  4392  dt207653 					return;
    590  4392  dt207653 				}
    591  4392  dt207653 			}
    592  4392  dt207653 		}
    593  8244     Dipti 		if (strcmp(def->name, "Fru_Path") == 0) {
    594  8244     Dipti 			if (check_utf_char(field, def->payloadLen) == 1)
    595  8244     Dipti 				return;
    596  8244     Dipti 		}
    597     0    stevel 		for (i = 0; i < def->payloadLen && field[i]; i++)
    598     0    stevel 			safeputchar(field[i]);
    599     0    stevel 		return;
    600     0    stevel 	case FDTYPE_Enumeration:
    601     0    stevel 		value = 0;
    602     0    stevel 		(void) memcpy((((uint8_t *)&value) + sizeof (value)
    603  5015  dt207653 		    - def->payloadLen),
    604  5015  dt207653 		    field, def->payloadLen);
    605     0    stevel 		for (i = 0; i < def->enumCount; i++)
    606     0    stevel 			if (def->enumTable[i].value == value) {
    607  4392  dt207653 				if (strcmp(def->name, "Event_Code") == 0) {
    608  4392  dt207653 					if (strcmp(def->enumTable[i].text,
    609  4392  dt207653 "FMA Message R") == 0)
    610  4392  dt207653 						FMAmessageR = 1;
    611  4392  dt207653 				else
    612  4392  dt207653 					if (strcmp(def->enumTable[i].text,
    613  4392  dt207653 "FMA Event Data R") == 0)
    614  4392  dt207653 						FMAmessageR = 0;
    615  4392  dt207653 				}
    616  5270  dt207653 				if (strcmp(def->name,
    617  5270  dt207653 "SPD_Fundamental_Memory_Type") == 0) {
    618  5270  dt207653 					if (strcmp(def->enumTable[i].text,
    619  5270  dt207653 "DDR II SDRAM") == 0)
    620  5270  dt207653 						spd_memtype = 1;
    621  5270  dt207653 				}
    622     0    stevel 				safeputs(def->enumTable[i].text);
    623     0    stevel 				return;
    624     0    stevel 			}
    625     0    stevel 
    626     0    stevel 		errmsg = "unrecognized value";
    627     0    stevel 		break;
    628     0    stevel 	}
    629     0    stevel 
    630     0    stevel 	/* If nothing matched above, print the field in hex */
    631  4392  dt207653 	switch (def->dispType) {
    632  4392  dt207653 		case FDISP_MSGID:
    633  4392  dt207653 			(void) memcpy((uchar_t *)&first_byte, field, 1);
    634  4392  dt207653 			if (isprint(first_byte)) {
    635  4392  dt207653 				for (i = 0; i < def->payloadLen && field[i];
    636  5015  dt207653 				    i++)
    637  4392  dt207653 					safeputchar(field[i]);
    638  4392  dt207653 			}
    639  4392  dt207653 			break;
    640  4392  dt207653 		case FDISP_UUID:
    641  4392  dt207653 			for (i = 0; i < def->payloadLen; i++) {
    642  4392  dt207653 				if ((i == 4) || (i == 6) ||
    643  5015  dt207653 				    (i == 8) || (i == 10))
    644  4392  dt207653 				output("-");
    645  4392  dt207653 				output("%2.2x", field[i]);
    646  4392  dt207653 			}
    647  4392  dt207653 			break;
    648  4392  dt207653 		default:
    649  8244     Dipti 			if ((strcmp(def->name, "Status") == 0) ||
    650  8244     Dipti 			    (strcmp(def->name, "Old_Status") == 0) ||
    651  8244     Dipti 			    (strcmp(def->name, "New_Status") == 0)) {
    652  8244     Dipti 				int status_length = \
    653  8244     Dipti 				    sizeof (Status_CurrentR_status) / \
    654  8244     Dipti 				    sizeof (*(Status_CurrentR_status));
    655  8244     Dipti 				i = 0;
    656  8244     Dipti 				do {
    657  8244     Dipti 					if (Status_CurrentR_status[i].value == \
    658  8244     Dipti 					    *(field))
    659  8244     Dipti 						break;
    660  8244     Dipti 					i++;
    661  8244     Dipti 				} while (i < status_length);
    662  8244     Dipti 				if (i < status_length)
    663  8244     Dipti 					output("0x%2.2X (%s)", *(field),
    664  8244     Dipti 					    Status_CurrentR_status[i].data);
    665  8244     Dipti 				else
    666  8244     Dipti 					output("0x%2.2X (UNKNOWN)", *(field));
    667  8244     Dipti 				break;
    668  8244     Dipti 			}
    669  5270  dt207653 			if (strcmp(def->name,
    670  5270  dt207653 			"SPD_Data_Revision_Code") == 0) {
    671  5270  dt207653 				value = 0;
    672  5270  dt207653 				valueint = 0;
    673  5270  dt207653 				(void) memcpy((((uint8_t *)&value)
    674  5270  dt207653 				    + sizeof (value) - def->payloadLen),
    675  5270  dt207653 				    field, def->payloadLen);
    676  5270  dt207653 				valueint = (int)value;
    677  5270  dt207653 				if ((valueint >= MIN_VERSION) && (spd_memtype))
    678  5270  dt207653 					spd_revision = 1;
    679  5270  dt207653 			}
    680  4392  dt207653 			for (i = 0; i < def->payloadLen; i++)
    681  4392  dt207653 				output("%2.2X", field[i]);
    682  4392  dt207653 			break;
    683  4392  dt207653 	}
    684     0    stevel 
    685     0    stevel 	/* Safely print any error message associated with the field */
    686     0    stevel 	if (errmsg) {
    687  4392  dt207653 		if (strcmp(def->name, "Fault_Diag_Secs") != 0) {
    688  4392  dt207653 			output(" (");
    689  4392  dt207653 			safeputs(errmsg);
    690  4392  dt207653 			output(")");
    691  4392  dt207653 		}
    692     0    stevel 	}
    693     0    stevel }
    694     0    stevel 
    695     0    stevel /*
    696     0    stevel  * Recursively print the contents of a data element
    697     0    stevel  */
    698     0    stevel static void
    699     0    stevel print_element(const uint8_t *data, const fru_regdef_t *def,
    700     0    stevel     const char *parent_path, int indent)
    701     0    stevel {
    702     0    stevel 	char	*path;
    703     0    stevel 	size_t	len;
    704     0    stevel 
    705     0    stevel 	int	bytes = 0, i;
    706     0    stevel 
    707     0    stevel 
    708     0    stevel 	indent = (xml) ? (indent + INDENT) : (2*INDENT);
    709  5015  dt207653 	if (strcmp(def->name, "Sun_SPD_DataR") == 0) {
    710  5015  dt207653 		Fault_Install_DataR_flag = indent;
    711  5015  dt207653 		Power_On_DataR_flag = indent;
    712  5015  dt207653 	}
    713     0    stevel 	/*
    714     0    stevel 	 * Construct the path, or, for XML, the name, for the current
    715     0    stevel 	 * data element
    716     0    stevel 	 */
    717     0    stevel 	if ((def->iterationCount == 0) &&
    718     0    stevel 	    (def->iterationType != FRU_NOT_ITERATED)) {
    719     0    stevel 		if (xml) {
    720     0    stevel 			if (def->dataType == FDTYPE_Record) {
    721     0    stevel 				len = strlen("Index_") + strlen(def->name) + 1;
    722     0    stevel 				path = alloca(len);
    723     0    stevel 				(void) snprintf(path, len,
    724     0    stevel 				    "Index_%s", def->name);
    725     0    stevel 			}
    726     0    stevel 			else
    727     0    stevel 				path = "Index";
    728     0    stevel 		}
    729     0    stevel 		else
    730     0    stevel 			path = (char *)parent_path;
    731     0    stevel 	} else {
    732     0    stevel 		if (xml)
    733     0    stevel 			path = (char *)def->name;
    734     0    stevel 		else {
    735     0    stevel 			len = strlen(parent_path) + sizeof ("/") +
    736     0    stevel 			    strlen(def->name) +
    737     0    stevel 			    (def->iterationCount ? sizeof ("[255]") : 0);
    738     0    stevel 			path = alloca(len);
    739     0    stevel 			bytes = snprintf(path, len,
    740     0    stevel 			    "%s/%s", parent_path, def->name);
    741     0    stevel 		}
    742     0    stevel 	}
    743     0    stevel 
    744  5015  dt207653 	if ((Fault_Install_DataR_flag) &&
    745  5015  dt207653 	    (strcmp(path, "E_1_46") == 0) || (strcmp(path, "/E_1_46") == 0)) {
    746  5015  dt207653 		int cnt;
    747  5015  dt207653 		char timestring[128];
    748  5015  dt207653 		time_t timefield = 0;
    749  5015  dt207653 		struct tm *tm;
    750  5015  dt207653 		indent = Fault_Install_DataR_flag;
    751  5015  dt207653 		(void) memcpy((uint8_t *)&timefield, data, 4);
    752  5015  dt207653 		if (timefield == 0) {
    753  5015  dt207653 			(void) sprintf(timestring,
    754  5015  dt207653 			    "00000000 (No Value Recorded)\"");
    755  5015  dt207653 		} else {
    756  7247  aa222140 			if ((tm = gmtime(&timefield)) == NULL)
    757  5015  dt207653 				(void) sprintf(timestring,
    758  5015  dt207653 				    "cannot convert time value");
    759  5015  dt207653 			if (strftime(timestring,
    760  7247  aa222140 			    sizeof (timestring), GMT, tm) == 0)
    761  5015  dt207653 				(void) sprintf(timestring,
    762  5015  dt207653 				    "formatted time would overflow buffer");
    763  5015  dt207653 		}
    764  5015  dt207653 		if (xml) {
    765  5015  dt207653 			(void) sprintf(path, "Fault_Install_DataR");
    766  5015  dt207653 			output("%*s<%s>\n", indent, "", path);
    767  5015  dt207653 			indent = Fault_Install_DataR_flag + INDENT;
    768  5015  dt207653 			(void) sprintf(path, "UNIX_Timestamp32");
    769  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    770  5015  dt207653 			/*CSTYLED*/
    771  5015  dt207653 			output("%s\"/>\n", timestring);
    772  5015  dt207653 			(void) sprintf(path, "MACADDR");
    773  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    774  5015  dt207653 			for (cnt = 4; cnt < 4 + 6; cnt++) {
    775  5015  dt207653 				output("%2.2x", data[cnt]);
    776  5015  dt207653 				if (cnt < 4 + 6 - 1)
    777  5015  dt207653 					output(":");
    778  5015  dt207653 			}
    779  5015  dt207653 			/*CSTYLED*/
    780  5015  dt207653 			output("\"/>\n");
    781  5015  dt207653 			(void) sprintf(path, "Status");
    782  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    783  5015  dt207653 			/*CSTYLED*/
    784  5015  dt207653 			output("%2.2x\"/>\n", data[10]);
    785  5015  dt207653 			(void) sprintf(path, "Initiator");
    786  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    787  5015  dt207653 			/*CSTYLED*/
    788  5015  dt207653 			output("%2.2x\"/>\n", data[11]);
    789  5015  dt207653 			(void) sprintf(path, "Message_Type");
    790  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    791  5015  dt207653 			/*CSTYLED*/
    792  5015  dt207653 			output("%2.2x\"/>\n", data[12]);
    793  5015  dt207653 			(void) sprintf(path, "Message_32");
    794  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    795  5015  dt207653 			for (cnt = 13; cnt < 13 + 32; cnt++)
    796  5015  dt207653 				output("%2.2x", data[cnt]);
    797  5015  dt207653 			/*CSTYLED*/
    798  5015  dt207653 			output("\"/>\n");
    799  5015  dt207653 			indent = Fault_Install_DataR_flag;
    800  5015  dt207653 			(void) sprintf(path, "Fault_Install_DataR");
    801  5015  dt207653 			output("%*s</%s>\n", indent, "", path);
    802  5015  dt207653 		} else {
    803  5015  dt207653 			(void) sprintf(path, "/Fault_Install_DataR");
    804  5015  dt207653 			output("%*s%s\n", indent, "", path);
    805  5015  dt207653 			(void) sprintf(path,
    806  5015  dt207653 			    "/Fault_Install_DataR/UNIX_Timestamp32");
    807  5015  dt207653 			output("%*s%s: ", indent, "", path);
    808  5015  dt207653 			output("%s\n", timestring);
    809  5015  dt207653 			(void) sprintf(path, "/Fault_Install_DataR/MACADDR");
    810  5015  dt207653 			output("%*s%s: ", indent, "", path);
    811  5015  dt207653 			for (cnt = 4; cnt < 4 + 6; cnt++) {
    812  5015  dt207653 				output("%2.2x", data[cnt]);
    813  5015  dt207653 				if (cnt < 4 + 6 - 1)
    814  5015  dt207653 					output(":");
    815  5015  dt207653 			}
    816  5015  dt207653 			output("\n");
    817  5015  dt207653 			(void) sprintf(path, "/Fault_Install_DataR/Status");
    818  5015  dt207653 			output("%*s%s: ", indent, "", path);
    819  5015  dt207653 			output("%2.2x\n", data[10]);
    820  5015  dt207653 			(void) sprintf(path, "/Fault_Install_DataR/Initiator");
    821  5015  dt207653 			output("%*s%s: ", indent, "", path);
    822  5015  dt207653 			output("%2.2x\n", data[11]);
    823  5015  dt207653 			(void) sprintf(path,
    824  5015  dt207653 			    "/Fault_Install_DataR/Message_Type");
    825  5015  dt207653 			output("%*s%s: ", indent, "", path);
    826  5015  dt207653 			output("%2.2x\n", data[12]);
    827  5015  dt207653 			(void) sprintf(path, "/Fault_Install_DataR/Message_32");
    828  5015  dt207653 			output("%*s%s: ", indent, "", path);
    829  5015  dt207653 			for (cnt = 13; cnt < 13 + 32; cnt++)
    830  5015  dt207653 				output("%2.2x", data[cnt]);
    831  5015  dt207653 			output("\n");
    832  5015  dt207653 		}
    833  5015  dt207653 		Fault_Install_DataR_flag = 0;
    834  5015  dt207653 		return;
    835  5015  dt207653 	} else if ((Power_On_DataR_flag) && (
    836  5015  dt207653 	    strcmp(path, "C_10_8") == 0 ||
    837  5015  dt207653 	    (strcmp(path, "/C_10_8") == 0))) {
    838  5015  dt207653 		int cnt;
    839  5015  dt207653 		char timestring[128];
    840  5015  dt207653 		time_t timefield = 0;
    841  5015  dt207653 		struct tm *tm;
    842  5015  dt207653 		indent = Power_On_DataR_flag;
    843  5015  dt207653 		(void) memcpy((uint8_t *)&timefield, data, 4);
    844  5015  dt207653 		if (timefield == 0) {
    845  5015  dt207653 			(void) sprintf(timestring,
    846  5015  dt207653 			    "00000000 (No Value Recorded)");
    847  5015  dt207653 		} else {
    848  7247  aa222140 			if ((tm = gmtime(&timefield)) == NULL)
    849  5015  dt207653 				(void) sprintf(timestring,
    850  5015  dt207653 				    "cannot convert time value");
    851  5015  dt207653 			if (strftime(timestring,
    852  7247  aa222140 			    sizeof (timestring), GMT, tm) == 0)
    853  5015  dt207653 				(void) sprintf(timestring,
    854  5015  dt207653 				    "formatted time would overflow buffer");
    855  5015  dt207653 		}
    856  5015  dt207653 		if (xml) {
    857  5015  dt207653 			(void) sprintf(path, "Power_On_DataR");
    858  5015  dt207653 			output("%*s<%s>\n", indent, "", path);
    859  5015  dt207653 			indent = Power_On_DataR_flag + INDENT;
    860  5015  dt207653 			(void) sprintf(path, "UNIX_Timestamp32");
    861  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    862  5015  dt207653 			/*CSTYLED*/
    863  5015  dt207653 			output("%s\"/>\n", timestring);
    864  5015  dt207653 			(void) sprintf(path, "Power_On_Minutes");
    865  5015  dt207653 			output("%*s<%s value=\"", indent, "", path);
    866  5015  dt207653 			for (cnt = 4; cnt < 4 + 4; cnt++)
    867  5015  dt207653 				output("%2.2x", data[cnt]);
    868  5015  dt207653 			/*CSTYLED*/
    869  5015  dt207653 			output("\"/>\n");
    870  5015  dt207653 			indent = Power_On_DataR_flag;
    871  5015  dt207653 			(void) sprintf(path, "Power_On_DataR");
    872  5015  dt207653 			output("%*s</%s>\n", indent, "", path);
    873  5015  dt207653 		} else {
    874  5015  dt207653 			(void) sprintf(path, "/Power_On_DataR");
    875  5015  dt207653 			output("%*s%s\n", indent, "", path);
    876  5015  dt207653 			(void) sprintf(path,
    877  5015  dt207653 			    "/Power_On_DataR/UNIX_Timestamp32");
    878  5015  dt207653 			output("%*s%s: ", indent, "", path);
    879  5015  dt207653 			output("%s\n", timestring);
    880  5015  dt207653 			(void) sprintf(path,
    881  5015  dt207653 			    "/Power_On_DataR/Power_On_Minutes");
    882  5015  dt207653 			output("%*s%s: ", indent, "", path);
    883  5015  dt207653 			for (cnt = 4; cnt < 4 + 4; cnt++)
    884  5015  dt207653 				output("%2.2x", data[cnt]);
    885  5015  dt207653 			output("\n");
    886  5015  dt207653 		}
    887  5015  dt207653 		Power_On_DataR_flag = 0;
    888  5015  dt207653 		return;
    889  5015  dt207653 	}
    890     0    stevel 	/*
    891     0    stevel 	 * Handle the various categories of data elements:  iteration,
    892     0    stevel 	 * record, and field
    893     0    stevel 	 */
    894     0    stevel 	if (def->iterationCount) {
    895     0    stevel 		int		iterlen = (def->payloadLen - NUM_ITER_BYTES)/
    896  5015  dt207653 		    def->iterationCount,
    897  5015  dt207653 		    n, valid = 1;
    898     0    stevel 
    899     0    stevel 		uint8_t		head, num;
    900     0    stevel 
    901     0    stevel 		fru_regdef_t	newdef;
    902     0    stevel 
    903     0    stevel 
    904     0    stevel 		/*
    905     0    stevel 		 * Make a new element definition to describe the components
    906     0    stevel 		 * of the iteration
    907     0    stevel 		 */
    908     0    stevel 		(void) memcpy(&newdef, def, sizeof (newdef));
    909     0    stevel 		newdef.iterationCount = 0;
    910     0    stevel 		newdef.payloadLen = iterlen;
    911     0    stevel 
    912     0    stevel 		/*
    913     0    stevel 		 * Validate the contents of the iteration control bytes
    914     0    stevel 		 */
    915     0    stevel 		if (data[HEAD_ITER] >= def->iterationCount) {
    916     0    stevel 			valid = 0;
    917     0    stevel 			error(gettext("%s:  Invalid iteration head:  %d "
    918     0    stevel 			    "(should be less than %d)\n"),
    919     0    stevel 			    path, data[HEAD_ITER], def->iterationCount);
    920     0    stevel 		}
    921     0    stevel 
    922     0    stevel 		if (data[NUM_ITER] > def->iterationCount) {
    923     0    stevel 			valid = 0;
    924     0    stevel 			error(gettext("%s:  Invalid iteration count:  %d "
    925     0    stevel 			    "(should not be greater than %d)\n"),
    926     0    stevel 			    path, data[NUM_ITER], def->iterationCount);
    927     0    stevel 		}
    928     0    stevel 
    929     0    stevel 		if (data[MAX_ITER] != def->iterationCount) {
    930     0    stevel 			valid = 0;
    931     0    stevel 			error(gettext("%s:  Invalid iteration maximum:  %d "
    932     0    stevel 			    "(should equal %d)\n"),
    933     0    stevel 			    path, data[MAX_ITER], def->iterationCount);
    934     0    stevel 		}
    935     0    stevel 
    936     0    stevel 		if (valid) {
    937     0    stevel 			head = data[HEAD_ITER];
    938     0    stevel 			num  = data[NUM_ITER];
    939     0    stevel 		} else {
    940     0    stevel 			head = 0;
    941     0    stevel 			num  = def->iterationCount;
    942     0    stevel 			error(gettext("%s:  Showing all iterations\n"), path);
    943     0    stevel 		}
    944     0    stevel 
    945     0    stevel 		if (xml)
    946     0    stevel 			output("%*s<%s>\n", indent, "", path);
    947     0    stevel 		else
    948     0    stevel 			output("%*s%s (%d iterations)\n", indent, "", path,
    949  5015  dt207653 			    num);
    950     0    stevel 
    951     0    stevel 		/*
    952     0    stevel 		 * Print each component of the iteration
    953     0    stevel 		 */
    954     0    stevel 		for (i = head, n = 0, data += 4;
    955  5015  dt207653 		    n < num;
    956  5015  dt207653 		    i = ((i + 1) % def->iterationCount), n++) {
    957     0    stevel 			if (!xml) (void) sprintf((path + bytes), "[%d]", n);
    958  4392  dt207653 			iterglobal = n;
    959     0    stevel 			print_element((data + i*iterlen), &newdef, path,
    960  5015  dt207653 			    indent);
    961     0    stevel 		}
    962     0    stevel 
    963     0    stevel 		if (xml) output("%*s</%s>\n", indent, "", path);
    964     0    stevel 
    965     0    stevel 	} else if (def->dataType == FDTYPE_Record) {
    966     0    stevel 		const fru_regdef_t  *component;
    967     0    stevel 
    968     0    stevel 		if (xml)
    969     0    stevel 			output("%*s<%s>\n", indent, "", path);
    970     0    stevel 		else
    971     0    stevel 			output("%*s%s\n", indent, "", path);
    972     0    stevel 
    973     0    stevel 		/*
    974     0    stevel 		 * Print each component of the record
    975     0    stevel 		 */
    976     0    stevel 		for (i = 0; i < def->enumCount;
    977  5015  dt207653 		    i++, data += component->payloadLen) {
    978     0    stevel 			component = fru_reg_lookup_def_by_name(
    979  5015  dt207653 			    def->enumTable[i].text);
    980     0    stevel 			assert(component != NULL);
    981     0    stevel 			print_element(data, component, path, indent);
    982     0    stevel 		}
    983     0    stevel 
    984     0    stevel 		if (xml) output("%*s</%s>\n", indent, "", path);
    985     0    stevel 	} else if (xml) {
    986     0    stevel 		/*
    987     0    stevel 		 * Base case:  print the field formatted for XML
    988     0    stevel 		 */
    989     0    stevel 		char  *format = ((def == &unknown)
    990     0    stevel 		    ? "%*s<UNKNOWN tag=\"%s\" value=\""
    991     0    stevel 		    : "%*s<%s value=\"");
    992     0    stevel 
    993     0    stevel 		output(format, indent, "", path);
    994     0    stevel 		print_field(data, def);
    995     0    stevel 		/*CSTYLED*/
    996     0    stevel 		output("\"/>\n");	/* \" confuses cstyle */
    997  4392  dt207653 
    998  4392  dt207653 		if ((strcmp(def->name, "Message") == 0) &&
    999  5015  dt207653 		    ((FMAmessageR == 0) || (FMAmessageR == 1))) {
   1000  4392  dt207653 			const char	*elem_name = NULL;
   1001  4392  dt207653 			const char	*parent_path;
   1002  4392  dt207653 			uchar_t		tmpdata[128];
   1003  4392  dt207653 			char		path[16384];
   1004  4392  dt207653 			const fru_regdef_t	*new_def;
   1005  4392  dt207653 
   1006  4392  dt207653 			if (FMAmessageR == 0)
   1007  4392  dt207653 				elem_name = "FMA_Event_DataR";
   1008  4392  dt207653 			else if (FMAmessageR == 1)
   1009  4392  dt207653 				elem_name = "FMA_MessageR";
   1010  4392  dt207653 			if (elem_name != NULL) {
   1011  4392  dt207653 				(void) memcpy(tmpdata, data, def->payloadLen);
   1012  4392  dt207653 				new_def = fru_reg_lookup_def_by_name(elem_name);
   1013  4430  dt207653 				(void) snprintf(path, sizeof (path),
   1014  4392  dt207653 				"/Status_EventsR[%d]/Message(FMA)", iterglobal);
   1015  4392  dt207653 				parent_path = path;
   1016  4392  dt207653 				print_element(tmpdata, new_def,
   1017  5015  dt207653 				    parent_path, 2*INDENT);
   1018  4392  dt207653 				FMAmessageR = -1;
   1019  4392  dt207653 			}
   1020  4392  dt207653 		}
   1021  4392  dt207653 
   1022     0    stevel 	} else {
   1023     0    stevel 		/*
   1024     0    stevel 		 * Base case:  print the field
   1025     0    stevel 		 */
   1026     0    stevel 		output("%*s%s: ", indent, "", path);
   1027     0    stevel 		print_field(data, def);
   1028     0    stevel 		output("\n");
   1029     0    stevel 	}
   1030     0    stevel }
   1031     0    stevel 
   1032     0    stevel /*
   1033     0    stevel  * Print the contents of a packet (i.e., a tagged data element)
   1034     0    stevel  */
   1035     0    stevel /* ARGSUSED */
   1036     0    stevel static int
   1037     0    stevel print_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
   1038     0    stevel {
   1039     0    stevel 	int			tag_type = get_tag_type(tag);
   1040     0    stevel 
   1041     0    stevel 	size_t			payload_length = 0;
   1042     0    stevel 
   1043     0    stevel 	const fru_regdef_t	*def;
   1044     0    stevel 
   1045     0    stevel 	/*
   1046     0    stevel 	 * Build a definition for unrecognized tags (e.g., not in libfrureg)
   1047     0    stevel 	 */
   1048     0    stevel 	if ((tag_type == -1) ||
   1049     0    stevel 	    ((payload_length = get_payload_length(tag)) != length)) {
   1050     0    stevel 		def = &unknown;
   1051     0    stevel 
   1052     0    stevel 		unknown.tagType    = -1;
   1053     0    stevel 		unknown.tagDense   = -1;
   1054     0    stevel 		unknown.payloadLen = length;
   1055     0    stevel 		unknown.dataLength = unknown.payloadLen;
   1056     0    stevel 
   1057     0    stevel 		if (tag_type == -1)
   1058     0    stevel 			(void) snprintf(tagname, sizeof (tagname), "INVALID");
   1059     0    stevel 		else
   1060     0    stevel 			(void) snprintf(tagname, sizeof (tagname),
   1061     0    stevel 			    "%s_%u_%u_%u", get_tagtype_str(tag_type),
   1062     0    stevel 			    get_tag_dense(tag), payload_length, length);
   1063     0    stevel 	} else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
   1064     0    stevel 		def = &unknown;
   1065     0    stevel 
   1066     0    stevel 		unknown.tagType    = tag_type;
   1067     0    stevel 		unknown.tagDense   = get_tag_dense(tag);
   1068     0    stevel 		unknown.payloadLen = payload_length;
   1069     0    stevel 		unknown.dataLength = unknown.payloadLen;
   1070     0    stevel 
   1071     0    stevel 		(void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
   1072     0    stevel 		    get_tagtype_str(unknown.tagType),
   1073     0    stevel 		    unknown.tagDense, payload_length);
   1074     0    stevel 	}
   1075     0    stevel 
   1076     0    stevel 
   1077     0    stevel 	/*
   1078     0    stevel 	 * Print the defined element
   1079     0    stevel 	 */
   1080     0    stevel 	print_element(payload, def, "", INDENT);
   1081     0    stevel 
   1082     0    stevel 	return (FRU_SUCCESS);
   1083     0    stevel }
   1084     0    stevel 
   1085     0    stevel /*
   1086     0    stevel  * Print a segment's name and the contents of each data element in the segment
   1087     0    stevel  */
   1088     0    stevel static int
   1089     0    stevel print_packets_in_segment(fru_seghdl_t segment, void *args)
   1090     0    stevel {
   1091     0    stevel 	char	*name;
   1092     0    stevel 
   1093     0    stevel 	int	status;
   1094     0    stevel 
   1095     0    stevel 
   1096     0    stevel 	if ((status = fru_get_segment_name(segment, &name)) != FRU_SUCCESS) {
   1097     0    stevel 		saved_status = status;
   1098     0    stevel 		name = "";
   1099     0    stevel 		error(gettext("Error getting segment name:  %s\n"),
   1100     0    stevel 		    fru_strerror(status));
   1101     0    stevel 	}
   1102     0    stevel 
   1103     0    stevel 
   1104     0    stevel 	if (xml)
   1105     0    stevel 		output("%*s<Segment name=\"%s\">\n", INDENT, "", name);
   1106     0    stevel 	else
   1107     0    stevel 		output("%*sSEGMENT: %s\n", INDENT, "", name);
   1108     0    stevel 
   1109  8244     Dipti 	if (strcmp(name, "ED") == 0) {
   1110  8244     Dipti 		if (xml) output("%*s</Segment>\n", INDENT, "");
   1111  8244     Dipti 		free(name);
   1112  8244     Dipti 		return (FRU_SUCCESS);
   1113  8244     Dipti 	}
   1114     0    stevel 	/* Iterate over the packets in the segment, printing the contents */
   1115     0    stevel 	if ((status = fru_for_each_packet(segment, print_packet, args))
   1116     0    stevel 	    != FRU_SUCCESS) {
   1117     0    stevel 		saved_status = status;
   1118     0    stevel 		error(gettext("Error processing data in segment \"%s\":  %s\n"),
   1119  5015  dt207653 		    name, fru_strerror(status));
   1120     0    stevel 	}
   1121     0    stevel 
   1122     0    stevel 	if (xml) output("%*s</Segment>\n", INDENT, "");
   1123     0    stevel 
   1124     0    stevel 	free(name);
   1125     0    stevel 
   1126     0    stevel 	return (FRU_SUCCESS);
   1127     0    stevel }
   1128     0    stevel 
   1129     0    stevel /* ARGSUSED */
   1130     0    stevel static void
   1131     0    stevel print_node_path(fru_node_t fru_type, const char *path, const char *name,
   1132     0    stevel     end_node_fp_t *end_node, void **end_args)
   1133     0    stevel {
   1134     0    stevel 	output("%s%s\n", path,
   1135     0    stevel 	    ((fru_type == FRU_NODE_CONTAINER) ? " (container)"
   1136  5015  dt207653 	    : ((fru_type == FRU_NODE_FRU) ? " (fru)" : "")));
   1137     0    stevel }
   1138     0    stevel 
   1139     0    stevel /*
   1140     0    stevel  * Close the XML element for a "location" node
   1141     0    stevel  */
   1142     0    stevel /* ARGSUSED */
   1143     0    stevel static void
   1144     0    stevel end_location_xml(fru_nodehdl_t node, const char *path, const char *name,
   1145     0    stevel     void *args)
   1146     0    stevel {
   1147     0    stevel 	assert(args != NULL);
   1148     0    stevel 	output("</Location> <!-- %s -->\n", args);
   1149     0    stevel }
   1150     0    stevel 
   1151     0    stevel /*
   1152     0    stevel  * Close the XML element for a "fru" node
   1153     0    stevel  */
   1154     0    stevel /* ARGSUSED */
   1155     0    stevel static void
   1156     0    stevel end_fru_xml(fru_nodehdl_t node, const char *path, const char *name, void *args)
   1157     0    stevel {
   1158     0    stevel 	assert(args != NULL);
   1159     0    stevel 	output("</Fru> <!-- %s -->\n", args);
   1160     0    stevel }
   1161     0    stevel 
   1162     0    stevel /*
   1163     0    stevel  * Close the XML element for a "container" node
   1164     0    stevel  */
   1165     0    stevel /* ARGSUSED */
   1166     0    stevel static void
   1167     0    stevel end_container_xml(fru_nodehdl_t node, const char *path, const char *name,
   1168     0    stevel     void *args)
   1169     0    stevel {
   1170     0    stevel 	assert(args != NULL);
   1171     0    stevel 	output("</Container> <!-- %s -->\n", args);
   1172     0    stevel }
   1173     0    stevel 
   1174     0    stevel /*
   1175     0    stevel  * Introduce a node in XML and set the appropriate node-closing function
   1176     0    stevel  */
   1177     0    stevel /* ARGSUSED */
   1178     0    stevel static void
   1179     0    stevel print_node_xml(fru_node_t fru_type, const char *path, const char *name,
   1180     0    stevel     end_node_fp_t *end_node, void **end_args)
   1181     0    stevel {
   1182     0    stevel 	switch (fru_type) {
   1183     0    stevel 	case FRU_NODE_FRU:
   1184     0    stevel 		output("<Fru name=\"%s\">\n", name);
   1185     0    stevel 		*end_node = end_fru_xml;
   1186     0    stevel 		break;
   1187     0    stevel 	case FRU_NODE_CONTAINER:
   1188     0    stevel 		output("<Container name=\"%s\">\n", name);
   1189     0    stevel 		*end_node = end_container_xml;
   1190     0    stevel 		break;
   1191     0    stevel 	default:
   1192     0    stevel 		output("<Location name=\"%s\">\n", name);
   1193     0    stevel 		*end_node = end_location_xml;
   1194     0    stevel 		break;
   1195     0    stevel 	}
   1196     0    stevel 
   1197     0    stevel 	*end_args = (void *) name;
   1198     0    stevel }
   1199     0    stevel 
   1200     0    stevel /*
   1201     0    stevel  * Print node info and, where appropriate, node contents
   1202     0    stevel  */
   1203     0    stevel /* ARGSUSED */
   1204     0    stevel static fru_errno_t
   1205     0    stevel process_node(fru_nodehdl_t node, const char *path, const char *name,
   1206     0    stevel 		void *args, end_node_fp_t *end_node, void **end_args)
   1207     0    stevel {
   1208     0    stevel 	int		status;
   1209     0    stevel 
   1210     0    stevel 	fru_node_t	fru_type = FRU_NODE_UNKNOWN;
   1211     0    stevel 
   1212     0    stevel 
   1213     0    stevel 	if ((status = fru_get_node_type(node, &fru_type)) != FRU_SUCCESS) {
   1214     0    stevel 		saved_status = status;
   1215     0    stevel 		error(gettext("Error getting node type:  %s\n"),
   1216  5015  dt207653 		    fru_strerror(status));
   1217     0    stevel 	}
   1218     0    stevel 
   1219     0    stevel 	if (containers_only) {
   1220     0    stevel 		if (fru_type != FRU_NODE_CONTAINER)
   1221     0    stevel 			return (FRU_SUCCESS);
   1222     0    stevel 		name = path;
   1223     0    stevel 	}
   1224     0    stevel 
   1225     0    stevel 	/* Introduce the node */
   1226     0    stevel 	assert(print_node != NULL);
   1227     0    stevel 	print_node(fru_type, path, name, end_node, end_args);
   1228     0    stevel 
   1229     0    stevel 	if (list_only)
   1230     0    stevel 		return (FRU_SUCCESS);
   1231     0    stevel 
   1232     0    stevel 	/* Print the contents of each packet in each segment of a container */
   1233     0    stevel 	if (fru_type == FRU_NODE_CONTAINER) {
   1234     0    stevel 		if (xml) output("<ContainerData>\n");
   1235     0    stevel 		if ((status =
   1236  5015  dt207653 		    fru_for_each_segment(node, print_packets_in_segment,
   1237  5015  dt207653 		    NULL))
   1238     0    stevel 		    != FRU_SUCCESS) {
   1239     0    stevel 			saved_status = status;
   1240     0    stevel 			error(gettext("Error  processing node \"%s\":  %s\n"),
   1241  5015  dt207653 			    name, fru_strerror(status));
   1242     0    stevel 		}
   1243     0    stevel 		if (xml) output("</ContainerData>\n");
   1244     0    stevel 	}
   1245     0    stevel 
   1246     0    stevel 	return (FRU_SUCCESS);
   1247     0    stevel }
   1248     0    stevel 
   1249     0    stevel /*
   1250     0    stevel  * Process the node if its path matches the search path in "args"
   1251     0    stevel  */
   1252     0    stevel /* ARGSUSED */
   1253     0    stevel static fru_errno_t
   1254     0    stevel process_matching_node(fru_nodehdl_t node, const char *path, const char *name,
   1255     0    stevel     void *args, end_node_fp_t *end_node, void **end_args)
   1256  5015  dt207653 	{
   1257     0    stevel 	int  status;
   1258     0    stevel 
   1259     0    stevel 
   1260     0    stevel 	if (!fru_pathmatch(path, args))
   1261     0    stevel 		return (FRU_SUCCESS);
   1262     0    stevel 
   1263     0    stevel 	status = process_node(node, path, path, args, end_node, end_args);
   1264     0    stevel 
   1265     0    stevel 	return ((status == FRU_SUCCESS) ? FRU_WALK_TERMINATE : status);
   1266     0    stevel }
   1267     0    stevel 
   1268     0    stevel /*
   1269     0    stevel  * Write the trailer required for well-formed DTD-compliant XML
   1270     0    stevel  */
   1271     0    stevel static void
   1272     0    stevel terminate_xml()
   1273     0    stevel {
   1274     0    stevel 	errno = 0;
   1275     0    stevel 	if (ftell(errlog) > 0) {
   1276     0    stevel 		char  c;
   1277     0    stevel 
   1278     0    stevel 		output("<ErrorLog>\n");
   1279     0    stevel 		rewind(errlog);
   1280     0    stevel 		if (!errno)
   1281     0    stevel 			while ((c = getc(errlog)) != EOF)
   1282     0    stevel 				xputchar(c);
   1283     0    stevel 		output("</ErrorLog>\n");
   1284     0    stevel 	}
   1285     0    stevel 
   1286     0    stevel 	if (errno) {
   1287     0    stevel 		/*NOTREACHED*/
   1288     0    stevel 		errlog = NULL;
   1289     0    stevel 		error(gettext("Error copying error messages to \"ErrorLog\""),
   1290     0    stevel 		    strerror(errno));
   1291     0    stevel 	}
   1292     0    stevel 
   1293     0    stevel 	output("</FRUID_XML_Tree>\n");
   1294     0    stevel }
   1295     0    stevel 
   1296     0    stevel /*
   1297     0    stevel  * Print available FRU ID information
   1298     0    stevel  */
   1299     0    stevel int
   1300     0    stevel prtfru(const char *searchpath, int containers_only_flag, int list_only_flag,
   1301     0    stevel 	int xml_flag)
   1302     0    stevel {
   1303     0    stevel 	fru_errno_t    status;
   1304     0    stevel 
   1305     0    stevel 	fru_nodehdl_t  frutree = 0;
   1306     0    stevel 
   1307     0    stevel 
   1308     0    stevel 	/* Copy parameter flags to global flags */
   1309     0    stevel 	containers_only	= containers_only_flag;
   1310     0    stevel 	list_only	= list_only_flag;
   1311     0    stevel 	xml		= xml_flag;
   1312     0    stevel 
   1313     0    stevel 
   1314     0    stevel 	/* Help arrange for correct, efficient interleaving of output */
   1315     0    stevel 	(void) setvbuf(stderr, NULL, _IOLBF, 0);
   1316     0    stevel 
   1317     0    stevel 
   1318     0    stevel 	/* Initialize for XML--or not */
   1319     0    stevel 	if (xml) {
   1320     0    stevel 		safeputchar = xputchar;
   1321     0    stevel 		safeputs    = xputs;
   1322     0    stevel 
   1323     0    stevel 		print_node  = print_node_xml;
   1324     0    stevel 
   1325     0    stevel 		if ((errlog = tmpfile()) == NULL) {
   1326     0    stevel 			(void) fprintf(stderr,
   1327     0    stevel 			    "Error creating error log file:  %s\n",
   1328     0    stevel 			    strerror(errno));
   1329     0    stevel 			return (1);
   1330     0    stevel 		}
   1331     0    stevel 
   1332     0    stevel 		/* Output the XML preamble */
   1333     0    stevel 		output("<?xml version=\"1.0\" ?>\n"
   1334     0    stevel 		    "<!--\n"
   1335     0    stevel 		    " Copyright 2000-2002 Sun Microsystems, Inc.  "
   1336     0    stevel 		    "All rights reserved.\n"
   1337     0    stevel 		    " Use is subject to license terms.\n"
   1338     0    stevel 		    "-->\n\n"
   1339     0    stevel 		    "<!DOCTYPE FRUID_XML_Tree SYSTEM \"prtfrureg.dtd\">\n\n"
   1340     0    stevel 		    "<FRUID_XML_Tree>\n");
   1341     0    stevel 
   1342     0    stevel 		/* Arrange to always properly terminate XML */
   1343     0    stevel 		if (atexit(terminate_xml))
   1344     0    stevel 			error(gettext("Warning:  XML will not be terminated:  "
   1345  5015  dt207653 			    "%s\n"), strerror(errno));
   1346     0    stevel 	} else
   1347     0    stevel 		print_node = print_node_path;
   1348     0    stevel 
   1349     0    stevel 
   1350     0    stevel 	/* Get the root node */
   1351     0    stevel 	if ((status = fru_get_root(&frutree)) == FRU_NODENOTFOUND) {
   1352  6201  dt207653 		error(gettext("This system does not support PICL "
   1353  6201  dt207653 		    "infrastructure to provide FRUID data\n"
   1354  6201  dt207653 		    "Please use the platform SP to access the FRUID "
   1355  6201  dt207653 		    "information\n"));
   1356     0    stevel 		return (1);
   1357     0    stevel 	} else if (status != FRU_SUCCESS) {
   1358     0    stevel 		error(gettext("Unable to access FRU ID data:  %s\n"),
   1359  5015  dt207653 		    fru_strerror(status));
   1360     0    stevel 		return (1);
   1361     0    stevel 	}
   1362     0    stevel 
   1363     0    stevel 	/* Process the tree */
   1364     0    stevel 	if (searchpath == NULL) {
   1365     0    stevel 		status = fru_walk_tree(frutree, "", process_node, NULL);
   1366     0    stevel 	} else {
   1367     0    stevel 		status = fru_walk_tree(frutree, "", process_matching_node,
   1368  5015  dt207653 		    (void *)searchpath);
   1369     0    stevel 		if (status == FRU_WALK_TERMINATE) {
   1370     0    stevel 			status = FRU_SUCCESS;
   1371     0    stevel 		} else if (status == FRU_SUCCESS) {
   1372     0    stevel 			error(gettext("\"%s\" not found\n"), searchpath);
   1373     0    stevel 			return (1);
   1374     0    stevel 		}
   1375     0    stevel 	}
   1376     0    stevel 
   1377     0    stevel 	if (status != FRU_SUCCESS)
   1378     0    stevel 		error(gettext("Error processing FRU tree:  %s\n"),
   1379  5015  dt207653 		    fru_strerror(status));
   1380     0    stevel 
   1381     0    stevel 	return (((status == FRU_SUCCESS) && (saved_status == 0)) ? 0 : 1);
   1382     0    stevel }
   1383