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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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