xref: /illumos-gate/usr/src/lib/libfru/libnvfru/nvfru.c (revision 6bbe0590)
1*6bbe0590SSundeep Panicker /*
2*6bbe0590SSundeep Panicker  * CDDL HEADER START
3*6bbe0590SSundeep Panicker  *
4*6bbe0590SSundeep Panicker  * The contents of this file are subject to the terms of the
5*6bbe0590SSundeep Panicker  * Common Development and Distribution License (the "License").
6*6bbe0590SSundeep Panicker  * You may not use this file except in compliance with the License.
7*6bbe0590SSundeep Panicker  *
8*6bbe0590SSundeep Panicker  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6bbe0590SSundeep Panicker  * or http://www.opensolaris.org/os/licensing.
10*6bbe0590SSundeep Panicker  * See the License for the specific language governing permissions
11*6bbe0590SSundeep Panicker  * and limitations under the License.
12*6bbe0590SSundeep Panicker  *
13*6bbe0590SSundeep Panicker  * When distributing Covered Code, include this CDDL HEADER in each
14*6bbe0590SSundeep Panicker  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6bbe0590SSundeep Panicker  * If applicable, add the following below this CDDL HEADER, with the
16*6bbe0590SSundeep Panicker  * fields enclosed by brackets "[]" replaced with your own identifying
17*6bbe0590SSundeep Panicker  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6bbe0590SSundeep Panicker  *
19*6bbe0590SSundeep Panicker  * CDDL HEADER END
20*6bbe0590SSundeep Panicker  */
21*6bbe0590SSundeep Panicker 
22*6bbe0590SSundeep Panicker /*
23*6bbe0590SSundeep Panicker  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*6bbe0590SSundeep Panicker  * Use is subject to license terms.
25*6bbe0590SSundeep Panicker  */
26*6bbe0590SSundeep Panicker 
27*6bbe0590SSundeep Panicker #include <stdio.h>
28*6bbe0590SSundeep Panicker #include <stdlib.h>
29*6bbe0590SSundeep Panicker #include <stdint.h>
30*6bbe0590SSundeep Panicker #include <strings.h>
31*6bbe0590SSundeep Panicker #include <assert.h>
32*6bbe0590SSundeep Panicker #include <pthread.h>
33*6bbe0590SSundeep Panicker #include <sys/byteorder.h>
34*6bbe0590SSundeep Panicker #include <sys/types.h>
35*6bbe0590SSundeep Panicker #include <sys/nvpair.h>
36*6bbe0590SSundeep Panicker 
37*6bbe0590SSundeep Panicker #include "libfru.h"
38*6bbe0590SSundeep Panicker #include "libfrup.h"
39*6bbe0590SSundeep Panicker #include "fru_tag.h"
40*6bbe0590SSundeep Panicker #include "libfrureg.h"
41*6bbe0590SSundeep Panicker 
42*6bbe0590SSundeep Panicker 
43*6bbe0590SSundeep Panicker #define	NUM_ITER_BYTES	4
44*6bbe0590SSundeep Panicker #define	HEAD_ITER 	0
45*6bbe0590SSundeep Panicker #define	TAIL_ITER	1
46*6bbe0590SSundeep Panicker #define	NUM_ITER	2
47*6bbe0590SSundeep Panicker #define	MAX_ITER	3
48*6bbe0590SSundeep Panicker #define	TIMESTRINGLEN	128
49*6bbe0590SSundeep Panicker 
50*6bbe0590SSundeep Panicker #define	PARSE_TIME	1
51*6bbe0590SSundeep Panicker 
52*6bbe0590SSundeep Panicker static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
53*6bbe0590SSundeep Panicker 
54*6bbe0590SSundeep Panicker 
55*6bbe0590SSundeep Panicker 
56*6bbe0590SSundeep Panicker static void
57*6bbe0590SSundeep Panicker convert_field(const uint8_t *field, const fru_regdef_t *def, const char *path,
58*6bbe0590SSundeep Panicker     nvlist_t *nv)
59*6bbe0590SSundeep Panicker {
60*6bbe0590SSundeep Panicker 	char timestring[TIMESTRINGLEN];
61*6bbe0590SSundeep Panicker 	int i;
62*6bbe0590SSundeep Panicker 	uint64_t value;
63*6bbe0590SSundeep Panicker 	time_t timefield;
64*6bbe0590SSundeep Panicker 
65*6bbe0590SSundeep Panicker 	switch (def->dataType) {
66*6bbe0590SSundeep Panicker 	case FDTYPE_Binary:
67*6bbe0590SSundeep Panicker 		assert(def->payloadLen <= sizeof (value));
68*6bbe0590SSundeep Panicker 		switch (def->dispType) {
69*6bbe0590SSundeep Panicker #if PARSE_TIME == 1
70*6bbe0590SSundeep Panicker 		case FDISP_Time:
71*6bbe0590SSundeep Panicker 			if (def->payloadLen > sizeof (timefield)) {
72*6bbe0590SSundeep Panicker 				/* too big for formatting */
73*6bbe0590SSundeep Panicker 				return;
74*6bbe0590SSundeep Panicker 			}
75*6bbe0590SSundeep Panicker 			(void) memcpy(&timefield, field, sizeof (timefield));
76*6bbe0590SSundeep Panicker 			timefield = BE_32(timefield);
77*6bbe0590SSundeep Panicker 			if (strftime(timestring, sizeof (timestring), "%C",
78*6bbe0590SSundeep Panicker 			    localtime(&timefield)) == 0) {
79*6bbe0590SSundeep Panicker 				/* buffer too small */
80*6bbe0590SSundeep Panicker 				return;
81*6bbe0590SSundeep Panicker 			}
82*6bbe0590SSundeep Panicker 			(void) nvlist_add_string(nv, path, timestring);
83*6bbe0590SSundeep Panicker 			return;
84*6bbe0590SSundeep Panicker #endif
85*6bbe0590SSundeep Panicker 
86*6bbe0590SSundeep Panicker 		case FDISP_Binary:
87*6bbe0590SSundeep Panicker 		case FDISP_Octal:
88*6bbe0590SSundeep Panicker 		case FDISP_Decimal:
89*6bbe0590SSundeep Panicker 		case FDISP_Hex:
90*6bbe0590SSundeep Panicker 		default:
91*6bbe0590SSundeep Panicker 			value = 0;
92*6bbe0590SSundeep Panicker 			(void) memcpy((((uint8_t *)&value) +
93*6bbe0590SSundeep Panicker 			    sizeof (value) - def->payloadLen),
94*6bbe0590SSundeep Panicker 			    field, def->payloadLen);
95*6bbe0590SSundeep Panicker 			value = BE_64(value);
96*6bbe0590SSundeep Panicker 			switch (def->payloadLen) {
97*6bbe0590SSundeep Panicker 			case 1:
98*6bbe0590SSundeep Panicker 				(void) nvlist_add_uint8(nv, path,
99*6bbe0590SSundeep Panicker 				    (uint8_t)value);
100*6bbe0590SSundeep Panicker 				break;
101*6bbe0590SSundeep Panicker 			case 2:
102*6bbe0590SSundeep Panicker 				(void) nvlist_add_uint16(nv, path,
103*6bbe0590SSundeep Panicker 				    (uint16_t)value);
104*6bbe0590SSundeep Panicker 				break;
105*6bbe0590SSundeep Panicker 			case 4:
106*6bbe0590SSundeep Panicker 				(void) nvlist_add_uint32(nv, path,
107*6bbe0590SSundeep Panicker 				    (uint32_t)value);
108*6bbe0590SSundeep Panicker 				break;
109*6bbe0590SSundeep Panicker 			default:
110*6bbe0590SSundeep Panicker 				(void) nvlist_add_uint64(nv, path, value);
111*6bbe0590SSundeep Panicker 			}
112*6bbe0590SSundeep Panicker 			return;
113*6bbe0590SSundeep Panicker 		}
114*6bbe0590SSundeep Panicker 
115*6bbe0590SSundeep Panicker 	case FDTYPE_ASCII:
116*6bbe0590SSundeep Panicker 		(void) nvlist_add_string(nv, path, (char *)field);
117*6bbe0590SSundeep Panicker 		return;
118*6bbe0590SSundeep Panicker 
119*6bbe0590SSundeep Panicker 	case FDTYPE_Enumeration:
120*6bbe0590SSundeep Panicker 		value = 0;
121*6bbe0590SSundeep Panicker 		(void) memcpy((((uint8_t *)&value) + sizeof (value) -
122*6bbe0590SSundeep Panicker 		    def->payloadLen), field, def->payloadLen);
123*6bbe0590SSundeep Panicker 		value = BE_64(value);
124*6bbe0590SSundeep Panicker 		for (i = 0; i < def->enumCount; i++) {
125*6bbe0590SSundeep Panicker 			if (def->enumTable[i].value == value) {
126*6bbe0590SSundeep Panicker 				(void) nvlist_add_string(nv, path,
127*6bbe0590SSundeep Panicker 				    def->enumTable[i].text);
128*6bbe0590SSundeep Panicker 				return;
129*6bbe0590SSundeep Panicker 			}
130*6bbe0590SSundeep Panicker 		}
131*6bbe0590SSundeep Panicker 	}
132*6bbe0590SSundeep Panicker 
133*6bbe0590SSundeep Panicker 	/* nothing matched above, use byte array */
134*6bbe0590SSundeep Panicker 	(void) nvlist_add_byte_array(nv, path, (uchar_t *)field,
135*6bbe0590SSundeep Panicker 	    def->payloadLen);
136*6bbe0590SSundeep Panicker }
137*6bbe0590SSundeep Panicker 
138*6bbe0590SSundeep Panicker 
139*6bbe0590SSundeep Panicker 
140*6bbe0590SSundeep Panicker static void
141*6bbe0590SSundeep Panicker convert_element(const uint8_t *data, const fru_regdef_t *def, char *ppath,
142*6bbe0590SSundeep Panicker     nvlist_t *nv, boolean_t from_iter)
143*6bbe0590SSundeep Panicker {
144*6bbe0590SSundeep Panicker 	int i;
145*6bbe0590SSundeep Panicker 	char *path;
146*6bbe0590SSundeep Panicker 
147*6bbe0590SSundeep Panicker 	/* construct path */
148*6bbe0590SSundeep Panicker 	if ((def->iterationCount == 0) &&
149*6bbe0590SSundeep Panicker 	    (def->iterationType != FRU_NOT_ITERATED)) {
150*6bbe0590SSundeep Panicker 		path = ppath;
151*6bbe0590SSundeep Panicker 	} else {
152*6bbe0590SSundeep Panicker 		path = (char *)def->name;
153*6bbe0590SSundeep Panicker 	}
154*6bbe0590SSundeep Panicker 
155*6bbe0590SSundeep Panicker 	/* iteration, record and field */
156*6bbe0590SSundeep Panicker 	if (def->iterationCount) {
157*6bbe0590SSundeep Panicker 		int iterlen, n;
158*6bbe0590SSundeep Panicker 		uint8_t head, num;
159*6bbe0590SSundeep Panicker 		fru_regdef_t newdef;
160*6bbe0590SSundeep Panicker 		nvlist_t **nv_elems;
161*6bbe0590SSundeep Panicker 		char num_str[32];
162*6bbe0590SSundeep Panicker 
163*6bbe0590SSundeep Panicker 		iterlen = (def->payloadLen - NUM_ITER_BYTES) /
164*6bbe0590SSundeep Panicker 		    def->iterationCount;
165*6bbe0590SSundeep Panicker 
166*6bbe0590SSundeep Panicker 		/*
167*6bbe0590SSundeep Panicker 		 * make a new element definition to describe the components of
168*6bbe0590SSundeep Panicker 		 * the iteration.
169*6bbe0590SSundeep Panicker 		 */
170*6bbe0590SSundeep Panicker 		(void) memcpy(&newdef, def, sizeof (newdef));
171*6bbe0590SSundeep Panicker 		newdef.iterationCount = 0;
172*6bbe0590SSundeep Panicker 		newdef.payloadLen = iterlen;
173*6bbe0590SSundeep Panicker 
174*6bbe0590SSundeep Panicker 		/* validate the content of the iteration control bytes */
175*6bbe0590SSundeep Panicker 		if ((data[HEAD_ITER] >= def->iterationCount) ||
176*6bbe0590SSundeep Panicker 		    (data[NUM_ITER] > def->iterationCount) ||
177*6bbe0590SSundeep Panicker 		    (data[MAX_ITER] != def->iterationCount)) {
178*6bbe0590SSundeep Panicker 			/* invalid. show all iterations */
179*6bbe0590SSundeep Panicker 			head = 0;
180*6bbe0590SSundeep Panicker 			num = def->iterationCount;
181*6bbe0590SSundeep Panicker 		} else {
182*6bbe0590SSundeep Panicker 			head = data[HEAD_ITER];
183*6bbe0590SSundeep Panicker 			num = data[NUM_ITER];
184*6bbe0590SSundeep Panicker 		}
185*6bbe0590SSundeep Panicker 
186*6bbe0590SSundeep Panicker 		nv_elems = (nvlist_t **)malloc(num * sizeof (nvlist_t *));
187*6bbe0590SSundeep Panicker 		if (!nv_elems)
188*6bbe0590SSundeep Panicker 			return;
189*6bbe0590SSundeep Panicker 		for (i = head, n = 0, data += sizeof (uint32_t); n < num;
190*6bbe0590SSundeep Panicker 		    i = ((i + 1) % def->iterationCount), n++) {
191*6bbe0590SSundeep Panicker 			if (nvlist_alloc(&nv_elems[n], 0, 0) != 0)
192*6bbe0590SSundeep Panicker 				return;
193*6bbe0590SSundeep Panicker 			(void) snprintf(num_str, sizeof (num_str), "%d", n);
194*6bbe0590SSundeep Panicker 			convert_element((data + i*iterlen), &newdef, num_str,
195*6bbe0590SSundeep Panicker 			    nv_elems[n], B_TRUE);
196*6bbe0590SSundeep Panicker 		}
197*6bbe0590SSundeep Panicker 		(void) nvlist_add_nvlist_array(nv, path, nv_elems, num);
198*6bbe0590SSundeep Panicker 
199*6bbe0590SSundeep Panicker 	} else if (def->dataType == FDTYPE_Record) {
200*6bbe0590SSundeep Panicker 		const fru_regdef_t *component;
201*6bbe0590SSundeep Panicker 		nvlist_t *nv_record;
202*6bbe0590SSundeep Panicker 
203*6bbe0590SSundeep Panicker 		if (!from_iter) {
204*6bbe0590SSundeep Panicker 			if (nvlist_alloc(&nv_record, 0, 0) != 0) {
205*6bbe0590SSundeep Panicker 				return;
206*6bbe0590SSundeep Panicker 			}
207*6bbe0590SSundeep Panicker 		} else {
208*6bbe0590SSundeep Panicker 			nv_record = nv;
209*6bbe0590SSundeep Panicker 		}
210*6bbe0590SSundeep Panicker 
211*6bbe0590SSundeep Panicker 		for (i = 0; i < def->enumCount; i++,
212*6bbe0590SSundeep Panicker 		    data += component->payloadLen) {
213*6bbe0590SSundeep Panicker 			component = fru_reg_lookup_def_by_name(
214*6bbe0590SSundeep Panicker 			    def->enumTable[i].text);
215*6bbe0590SSundeep Panicker 			convert_element(data, component, "", nv_record,
216*6bbe0590SSundeep Panicker 			    B_FALSE);
217*6bbe0590SSundeep Panicker 		}
218*6bbe0590SSundeep Panicker 
219*6bbe0590SSundeep Panicker 		(void) nvlist_add_nvlist(nv, path, nv_record);
220*6bbe0590SSundeep Panicker 
221*6bbe0590SSundeep Panicker 	} else {
222*6bbe0590SSundeep Panicker 		convert_field(data, def, path, nv);
223*6bbe0590SSundeep Panicker 	}
224*6bbe0590SSundeep Panicker }
225*6bbe0590SSundeep Panicker 
226*6bbe0590SSundeep Panicker 
227*6bbe0590SSundeep Panicker static fru_regdef_t *
228*6bbe0590SSundeep Panicker alloc_unknown_fru_regdef(void)
229*6bbe0590SSundeep Panicker {
230*6bbe0590SSundeep Panicker 	fru_regdef_t *p;
231*6bbe0590SSundeep Panicker 
232*6bbe0590SSundeep Panicker 	p = malloc(sizeof (fru_regdef_t));
233*6bbe0590SSundeep Panicker 	if (!p) {
234*6bbe0590SSundeep Panicker 		return (NULL);
235*6bbe0590SSundeep Panicker 	}
236*6bbe0590SSundeep Panicker 	p->version = REGDEF_VERSION;
237*6bbe0590SSundeep Panicker 	p->name = NULL;
238*6bbe0590SSundeep Panicker 	p->tagType = -1;
239*6bbe0590SSundeep Panicker 	p->tagDense = -1;
240*6bbe0590SSundeep Panicker 	p->payloadLen = -1;
241*6bbe0590SSundeep Panicker 	p->dataLength = -1;
242*6bbe0590SSundeep Panicker 	p->dataType = FDTYPE_ByteArray;
243*6bbe0590SSundeep Panicker 	p->dispType = FDISP_Hex;
244*6bbe0590SSundeep Panicker 	p->purgeable = FRU_WHICH_UNDEFINED;
245*6bbe0590SSundeep Panicker 	p->relocatable = FRU_WHICH_UNDEFINED;
246*6bbe0590SSundeep Panicker 	p->enumCount = 0;
247*6bbe0590SSundeep Panicker 	p-> enumTable = NULL;
248*6bbe0590SSundeep Panicker 	p->iterationCount = 0;
249*6bbe0590SSundeep Panicker 	p->iterationType = FRU_NOT_ITERATED;
250*6bbe0590SSundeep Panicker 	p->exampleString = NULL;
251*6bbe0590SSundeep Panicker 
252*6bbe0590SSundeep Panicker 	return (p);
253*6bbe0590SSundeep Panicker }
254*6bbe0590SSundeep Panicker 
255*6bbe0590SSundeep Panicker static int
256*6bbe0590SSundeep Panicker convert_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
257*6bbe0590SSundeep Panicker {
258*6bbe0590SSundeep Panicker 	int tag_type;
259*6bbe0590SSundeep Panicker 	size_t payload_length;
260*6bbe0590SSundeep Panicker 	const fru_regdef_t *def;
261*6bbe0590SSundeep Panicker 	nvlist_t *nv = (nvlist_t *)args;
262*6bbe0590SSundeep Panicker 	char tagname[sizeof ("?_0123456789_0123456789")];
263*6bbe0590SSundeep Panicker 	tag_type = get_tag_type(tag);
264*6bbe0590SSundeep Panicker 	payload_length = 0;
265*6bbe0590SSundeep Panicker 
266*6bbe0590SSundeep Panicker 	/* check for unrecognized tag */
267*6bbe0590SSundeep Panicker 	if ((tag_type == -1) ||
268*6bbe0590SSundeep Panicker 	    ((payload_length = get_payload_length(tag)) != length)) {
269*6bbe0590SSundeep Panicker 		fru_regdef_t *unknown;
270*6bbe0590SSundeep Panicker 
271*6bbe0590SSundeep Panicker 		unknown = alloc_unknown_fru_regdef();
272*6bbe0590SSundeep Panicker 		unknown->payloadLen = length;
273*6bbe0590SSundeep Panicker 		unknown->dataLength = unknown->payloadLen;
274*6bbe0590SSundeep Panicker 
275*6bbe0590SSundeep Panicker 		if (tag_type == -1) {
276*6bbe0590SSundeep Panicker 			(void) snprintf(tagname, sizeof (tagname),
277*6bbe0590SSundeep Panicker 			    "INVALID");
278*6bbe0590SSundeep Panicker 		} else {
279*6bbe0590SSundeep Panicker 			(void) snprintf(tagname, sizeof (tagname),
280*6bbe0590SSundeep Panicker 			    "%s_%u_%u_%u", get_tagtype_str(tag_type),
281*6bbe0590SSundeep Panicker 			    get_tag_dense(tag), payload_length, length);
282*6bbe0590SSundeep Panicker 		}
283*6bbe0590SSundeep Panicker 		unknown->name = tagname;
284*6bbe0590SSundeep Panicker 		convert_element(payload, unknown, "", nv, B_FALSE);
285*6bbe0590SSundeep Panicker 		free(unknown);
286*6bbe0590SSundeep Panicker 
287*6bbe0590SSundeep Panicker 	} else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
288*6bbe0590SSundeep Panicker 		fru_regdef_t *unknown;
289*6bbe0590SSundeep Panicker 
290*6bbe0590SSundeep Panicker 		unknown = alloc_unknown_fru_regdef();
291*6bbe0590SSundeep Panicker 		unknown->payloadLen = length;
292*6bbe0590SSundeep Panicker 		unknown->dataLength = unknown->payloadLen;
293*6bbe0590SSundeep Panicker 
294*6bbe0590SSundeep Panicker 		(void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
295*6bbe0590SSundeep Panicker 		    get_tagtype_str(tag_type),
296*6bbe0590SSundeep Panicker 		    unknown->tagDense, payload_length);
297*6bbe0590SSundeep Panicker 
298*6bbe0590SSundeep Panicker 		unknown->name = tagname;
299*6bbe0590SSundeep Panicker 		convert_element(payload, unknown, "", nv, B_FALSE);
300*6bbe0590SSundeep Panicker 		free(unknown);
301*6bbe0590SSundeep Panicker 
302*6bbe0590SSundeep Panicker 	} else {
303*6bbe0590SSundeep Panicker 
304*6bbe0590SSundeep Panicker 		convert_element(payload, def, "", nv, B_FALSE);
305*6bbe0590SSundeep Panicker 
306*6bbe0590SSundeep Panicker 	}
307*6bbe0590SSundeep Panicker 
308*6bbe0590SSundeep Panicker 	return (FRU_SUCCESS);
309*6bbe0590SSundeep Panicker }
310*6bbe0590SSundeep Panicker 
311*6bbe0590SSundeep Panicker 
312*6bbe0590SSundeep Panicker static int
313*6bbe0590SSundeep Panicker convert_packets_in_segment(fru_seghdl_t segment, void *args)
314*6bbe0590SSundeep Panicker {
315*6bbe0590SSundeep Panicker 	char *name;
316*6bbe0590SSundeep Panicker 	int ret;
317*6bbe0590SSundeep Panicker 	nvlist_t *nv = (nvlist_t *)args;
318*6bbe0590SSundeep Panicker 	nvlist_t *nv_segment;
319*6bbe0590SSundeep Panicker 
320*6bbe0590SSundeep Panicker 	ret = fru_get_segment_name(segment, &name);
321*6bbe0590SSundeep Panicker 	if (ret != FRU_SUCCESS) {
322*6bbe0590SSundeep Panicker 		return (ret);
323*6bbe0590SSundeep Panicker 	}
324*6bbe0590SSundeep Panicker 
325*6bbe0590SSundeep Panicker 	/* create a new nvlist for each segment */
326*6bbe0590SSundeep Panicker 	ret = nvlist_alloc(&nv_segment, 0, 0);
327*6bbe0590SSundeep Panicker 	if (ret) {
328*6bbe0590SSundeep Panicker 		free(name);
329*6bbe0590SSundeep Panicker 		return (FRU_FAILURE);
330*6bbe0590SSundeep Panicker 	}
331*6bbe0590SSundeep Panicker 
332*6bbe0590SSundeep Panicker 	/* convert the segment to an nvlist */
333*6bbe0590SSundeep Panicker 	ret = fru_for_each_packet(segment, convert_packet, nv_segment);
334*6bbe0590SSundeep Panicker 	if (ret != FRU_SUCCESS) {
335*6bbe0590SSundeep Panicker 		nvlist_free(nv_segment);
336*6bbe0590SSundeep Panicker 		free(name);
337*6bbe0590SSundeep Panicker 		return (ret);
338*6bbe0590SSundeep Panicker 	}
339*6bbe0590SSundeep Panicker 
340*6bbe0590SSundeep Panicker 	/* add the nvlist for this segment */
341*6bbe0590SSundeep Panicker 	(void) nvlist_add_nvlist(nv, name, nv_segment);
342*6bbe0590SSundeep Panicker 
343*6bbe0590SSundeep Panicker 	free(name);
344*6bbe0590SSundeep Panicker 
345*6bbe0590SSundeep Panicker 	return (FRU_SUCCESS);
346*6bbe0590SSundeep Panicker }
347*6bbe0590SSundeep Panicker 
348*6bbe0590SSundeep Panicker 
349*6bbe0590SSundeep Panicker static int
350*6bbe0590SSundeep Panicker convert_fru(fru_nodehdl_t hdl, nvlist_t **nvlist)
351*6bbe0590SSundeep Panicker {
352*6bbe0590SSundeep Panicker 	int err;
353*6bbe0590SSundeep Panicker 	nvlist_t *nv;
354*6bbe0590SSundeep Panicker 	fru_node_t fru_type;
355*6bbe0590SSundeep Panicker 
356*6bbe0590SSundeep Panicker 	if (fru_get_node_type(hdl, &fru_type) != FRU_SUCCESS) {
357*6bbe0590SSundeep Panicker 		return (-1);
358*6bbe0590SSundeep Panicker 	}
359*6bbe0590SSundeep Panicker 
360*6bbe0590SSundeep Panicker 	if (fru_type != FRU_NODE_CONTAINER) {
361*6bbe0590SSundeep Panicker 		return (-1);
362*6bbe0590SSundeep Panicker 	}
363*6bbe0590SSundeep Panicker 
364*6bbe0590SSundeep Panicker 	err = nvlist_alloc(&nv, 0, 0);
365*6bbe0590SSundeep Panicker 	if (err) {
366*6bbe0590SSundeep Panicker 		return (err);
367*6bbe0590SSundeep Panicker 	}
368*6bbe0590SSundeep Panicker 
369*6bbe0590SSundeep Panicker 	if (fru_for_each_segment(hdl, convert_packets_in_segment, nv) !=
370*6bbe0590SSundeep Panicker 	    FRU_SUCCESS) {
371*6bbe0590SSundeep Panicker 		nvlist_free(nv);
372*6bbe0590SSundeep Panicker 		return (-1);
373*6bbe0590SSundeep Panicker 	}
374*6bbe0590SSundeep Panicker 
375*6bbe0590SSundeep Panicker 	*nvlist = nv;
376*6bbe0590SSundeep Panicker 
377*6bbe0590SSundeep Panicker 	return (0);
378*6bbe0590SSundeep Panicker }
379*6bbe0590SSundeep Panicker 
380*6bbe0590SSundeep Panicker 
381*6bbe0590SSundeep Panicker int
382*6bbe0590SSundeep Panicker rawfru_to_nvlist(uint8_t *buffer, size_t bufsize, char *cont_type,
383*6bbe0590SSundeep Panicker     nvlist_t **nvlist)
384*6bbe0590SSundeep Panicker {
385*6bbe0590SSundeep Panicker 	fru_errno_t fru_err;
386*6bbe0590SSundeep Panicker 	fru_nodehdl_t hdl;
387*6bbe0590SSundeep Panicker 	int err;
388*6bbe0590SSundeep Panicker 
389*6bbe0590SSundeep Panicker 	(void) pthread_mutex_lock(&gLock);
390*6bbe0590SSundeep Panicker 	fru_err = fru_open_data_source("raw", buffer, bufsize, cont_type,
391*6bbe0590SSundeep Panicker 	    NULL);
392*6bbe0590SSundeep Panicker 	if (fru_err != FRU_SUCCESS) {
393*6bbe0590SSundeep Panicker 		(void) pthread_mutex_unlock(&gLock);
394*6bbe0590SSundeep Panicker 		return (-1);
395*6bbe0590SSundeep Panicker 	}
396*6bbe0590SSundeep Panicker 	fru_err = fru_get_root(&hdl);
397*6bbe0590SSundeep Panicker 	if (fru_err != FRU_SUCCESS) {
398*6bbe0590SSundeep Panicker 		(void) pthread_mutex_unlock(&gLock);
399*6bbe0590SSundeep Panicker 		return (-1);
400*6bbe0590SSundeep Panicker 	}
401*6bbe0590SSundeep Panicker 
402*6bbe0590SSundeep Panicker 	err = convert_fru(hdl, nvlist);
403*6bbe0590SSundeep Panicker 
404*6bbe0590SSundeep Panicker 	fru_close_data_source();
405*6bbe0590SSundeep Panicker 
406*6bbe0590SSundeep Panicker 	(void) pthread_mutex_unlock(&gLock);
407*6bbe0590SSundeep Panicker 
408*6bbe0590SSundeep Panicker 	return (err);
409*6bbe0590SSundeep Panicker }
410