xref: /illumos-gate/usr/src/lib/libfru/libnvfru/nvfru.c (revision 29c3ebdb)
16bbe0590SSundeep Panicker /*
26bbe0590SSundeep Panicker  * CDDL HEADER START
36bbe0590SSundeep Panicker  *
46bbe0590SSundeep Panicker  * The contents of this file are subject to the terms of the
56bbe0590SSundeep Panicker  * Common Development and Distribution License (the "License").
66bbe0590SSundeep Panicker  * You may not use this file except in compliance with the License.
76bbe0590SSundeep Panicker  *
86bbe0590SSundeep Panicker  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96bbe0590SSundeep Panicker  * or http://www.opensolaris.org/os/licensing.
106bbe0590SSundeep Panicker  * See the License for the specific language governing permissions
116bbe0590SSundeep Panicker  * and limitations under the License.
126bbe0590SSundeep Panicker  *
136bbe0590SSundeep Panicker  * When distributing Covered Code, include this CDDL HEADER in each
146bbe0590SSundeep Panicker  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156bbe0590SSundeep Panicker  * If applicable, add the following below this CDDL HEADER, with the
166bbe0590SSundeep Panicker  * fields enclosed by brackets "[]" replaced with your own identifying
176bbe0590SSundeep Panicker  * information: Portions Copyright [yyyy] [name of copyright owner]
186bbe0590SSundeep Panicker  *
196bbe0590SSundeep Panicker  * CDDL HEADER END
206bbe0590SSundeep Panicker  */
216bbe0590SSundeep Panicker 
226bbe0590SSundeep Panicker /*
23ee169c7eSGary Mills  * Copyright (c) 2014 Gary Mills
24ee169c7eSGary Mills  *
25ac88567aSHyon Kim  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
26*29c3ebdbSJohn Levon  *
27*29c3ebdbSJohn Levon  * Copyright (c) 2018, Joyent, Inc.
286bbe0590SSundeep Panicker  */
296bbe0590SSundeep Panicker 
306bbe0590SSundeep Panicker #include <stdio.h>
316bbe0590SSundeep Panicker #include <stdlib.h>
326bbe0590SSundeep Panicker #include <stdint.h>
336bbe0590SSundeep Panicker #include <strings.h>
346bbe0590SSundeep Panicker #include <assert.h>
356bbe0590SSundeep Panicker #include <pthread.h>
366bbe0590SSundeep Panicker #include <sys/byteorder.h>
376bbe0590SSundeep Panicker #include <sys/types.h>
386bbe0590SSundeep Panicker #include <sys/nvpair.h>
396bbe0590SSundeep Panicker 
406bbe0590SSundeep Panicker #include "libfru.h"
416bbe0590SSundeep Panicker #include "libfrup.h"
426bbe0590SSundeep Panicker #include "fru_tag.h"
436bbe0590SSundeep Panicker #include "libfrureg.h"
44d946b6ceSSundeep Panicker #include "nvfru.h"
456bbe0590SSundeep Panicker 
466bbe0590SSundeep Panicker #define	NUM_ITER_BYTES	4
47d946b6ceSSundeep Panicker #define	HEAD_ITER	0
486bbe0590SSundeep Panicker #define	TAIL_ITER	1
496bbe0590SSundeep Panicker #define	NUM_ITER	2
506bbe0590SSundeep Panicker #define	MAX_ITER	3
516bbe0590SSundeep Panicker #define	TIMESTRINGLEN	128
526bbe0590SSundeep Panicker 
536bbe0590SSundeep Panicker #define	PARSE_TIME	1
546bbe0590SSundeep Panicker 
556bbe0590SSundeep Panicker static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
566bbe0590SSundeep Panicker 
576bbe0590SSundeep Panicker 
586bbe0590SSundeep Panicker 
596bbe0590SSundeep Panicker static void
convert_field(const uint8_t * field,const fru_regdef_t * def,const char * path,nvlist_t * nv)606bbe0590SSundeep Panicker convert_field(const uint8_t *field, const fru_regdef_t *def, const char *path,
616bbe0590SSundeep Panicker     nvlist_t *nv)
626bbe0590SSundeep Panicker {
636bbe0590SSundeep Panicker 	char timestring[TIMESTRINGLEN];
646bbe0590SSundeep Panicker 	int i;
656bbe0590SSundeep Panicker 	uint64_t value;
666bbe0590SSundeep Panicker 	time_t timefield;
676bbe0590SSundeep Panicker 
686bbe0590SSundeep Panicker 	switch (def->dataType) {
696bbe0590SSundeep Panicker 	case FDTYPE_Binary:
706bbe0590SSundeep Panicker 		assert(def->payloadLen <= sizeof (value));
716bbe0590SSundeep Panicker 		switch (def->dispType) {
726bbe0590SSundeep Panicker #if PARSE_TIME == 1
736bbe0590SSundeep Panicker 		case FDISP_Time:
746bbe0590SSundeep Panicker 			if (def->payloadLen > sizeof (timefield)) {
756bbe0590SSundeep Panicker 				/* too big for formatting */
766bbe0590SSundeep Panicker 				return;
776bbe0590SSundeep Panicker 			}
786bbe0590SSundeep Panicker 			(void) memcpy(&timefield, field, sizeof (timefield));
796bbe0590SSundeep Panicker 			timefield = BE_32(timefield);
80ee169c7eSGary Mills 			if (strftime(timestring, sizeof (timestring), "%c",
816bbe0590SSundeep Panicker 			    localtime(&timefield)) == 0) {
826bbe0590SSundeep Panicker 				/* buffer too small */
836bbe0590SSundeep Panicker 				return;
846bbe0590SSundeep Panicker 			}
856bbe0590SSundeep Panicker 			(void) nvlist_add_string(nv, path, timestring);
866bbe0590SSundeep Panicker 			return;
876bbe0590SSundeep Panicker #endif
886bbe0590SSundeep Panicker 
896bbe0590SSundeep Panicker 		case FDISP_Binary:
906bbe0590SSundeep Panicker 		case FDISP_Octal:
916bbe0590SSundeep Panicker 		case FDISP_Decimal:
926bbe0590SSundeep Panicker 		case FDISP_Hex:
936bbe0590SSundeep Panicker 		default:
946bbe0590SSundeep Panicker 			value = 0;
956bbe0590SSundeep Panicker 			(void) memcpy((((uint8_t *)&value) +
966bbe0590SSundeep Panicker 			    sizeof (value) - def->payloadLen),
976bbe0590SSundeep Panicker 			    field, def->payloadLen);
986bbe0590SSundeep Panicker 			value = BE_64(value);
996bbe0590SSundeep Panicker 			switch (def->payloadLen) {
1006bbe0590SSundeep Panicker 			case 1:
1016bbe0590SSundeep Panicker 				(void) nvlist_add_uint8(nv, path,
1026bbe0590SSundeep Panicker 				    (uint8_t)value);
1036bbe0590SSundeep Panicker 				break;
1046bbe0590SSundeep Panicker 			case 2:
1056bbe0590SSundeep Panicker 				(void) nvlist_add_uint16(nv, path,
1066bbe0590SSundeep Panicker 				    (uint16_t)value);
1076bbe0590SSundeep Panicker 				break;
1086bbe0590SSundeep Panicker 			case 4:
1096bbe0590SSundeep Panicker 				(void) nvlist_add_uint32(nv, path,
1106bbe0590SSundeep Panicker 				    (uint32_t)value);
1116bbe0590SSundeep Panicker 				break;
1126bbe0590SSundeep Panicker 			default:
1136bbe0590SSundeep Panicker 				(void) nvlist_add_uint64(nv, path, value);
1146bbe0590SSundeep Panicker 			}
1156bbe0590SSundeep Panicker 			return;
1166bbe0590SSundeep Panicker 		}
1176bbe0590SSundeep Panicker 
1186bbe0590SSundeep Panicker 	case FDTYPE_ASCII:
1196bbe0590SSundeep Panicker 		(void) nvlist_add_string(nv, path, (char *)field);
1206bbe0590SSundeep Panicker 		return;
1216bbe0590SSundeep Panicker 
1226bbe0590SSundeep Panicker 	case FDTYPE_Enumeration:
1236bbe0590SSundeep Panicker 		value = 0;
1246bbe0590SSundeep Panicker 		(void) memcpy((((uint8_t *)&value) + sizeof (value) -
1256bbe0590SSundeep Panicker 		    def->payloadLen), field, def->payloadLen);
1266bbe0590SSundeep Panicker 		value = BE_64(value);
1276bbe0590SSundeep Panicker 		for (i = 0; i < def->enumCount; i++) {
1286bbe0590SSundeep Panicker 			if (def->enumTable[i].value == value) {
1296bbe0590SSundeep Panicker 				(void) nvlist_add_string(nv, path,
1306bbe0590SSundeep Panicker 				    def->enumTable[i].text);
1316bbe0590SSundeep Panicker 				return;
1326bbe0590SSundeep Panicker 			}
1336bbe0590SSundeep Panicker 		}
1346bbe0590SSundeep Panicker 	}
1356bbe0590SSundeep Panicker 
1366bbe0590SSundeep Panicker 	/* nothing matched above, use byte array */
1376bbe0590SSundeep Panicker 	(void) nvlist_add_byte_array(nv, path, (uchar_t *)field,
1386bbe0590SSundeep Panicker 	    def->payloadLen);
1396bbe0590SSundeep Panicker }
1406bbe0590SSundeep Panicker 
1416bbe0590SSundeep Panicker 
1426bbe0590SSundeep Panicker 
1436bbe0590SSundeep Panicker static void
convert_element(const uint8_t * data,const fru_regdef_t * def,char * ppath,nvlist_t * nv,boolean_t from_iter)1446bbe0590SSundeep Panicker convert_element(const uint8_t *data, const fru_regdef_t *def, char *ppath,
1456bbe0590SSundeep Panicker     nvlist_t *nv, boolean_t from_iter)
1466bbe0590SSundeep Panicker {
1476bbe0590SSundeep Panicker 	int i;
1486bbe0590SSundeep Panicker 	char *path;
1496bbe0590SSundeep Panicker 
1506bbe0590SSundeep Panicker 	/* construct path */
1516bbe0590SSundeep Panicker 	if ((def->iterationCount == 0) &&
1526bbe0590SSundeep Panicker 	    (def->iterationType != FRU_NOT_ITERATED)) {
1536bbe0590SSundeep Panicker 		path = ppath;
1546bbe0590SSundeep Panicker 	} else {
1556bbe0590SSundeep Panicker 		path = (char *)def->name;
1566bbe0590SSundeep Panicker 	}
1576bbe0590SSundeep Panicker 
1586bbe0590SSundeep Panicker 	/* iteration, record and field */
1596bbe0590SSundeep Panicker 	if (def->iterationCount) {
1606bbe0590SSundeep Panicker 		int iterlen, n;
1616bbe0590SSundeep Panicker 		uint8_t head, num;
1626bbe0590SSundeep Panicker 		fru_regdef_t newdef;
1636bbe0590SSundeep Panicker 		nvlist_t **nv_elems;
1646bbe0590SSundeep Panicker 		char num_str[32];
1656bbe0590SSundeep Panicker 
1666bbe0590SSundeep Panicker 		iterlen = (def->payloadLen - NUM_ITER_BYTES) /
1676bbe0590SSundeep Panicker 		    def->iterationCount;
1686bbe0590SSundeep Panicker 
1696bbe0590SSundeep Panicker 		/*
1706bbe0590SSundeep Panicker 		 * make a new element definition to describe the components of
1716bbe0590SSundeep Panicker 		 * the iteration.
1726bbe0590SSundeep Panicker 		 */
1736bbe0590SSundeep Panicker 		(void) memcpy(&newdef, def, sizeof (newdef));
1746bbe0590SSundeep Panicker 		newdef.iterationCount = 0;
1756bbe0590SSundeep Panicker 		newdef.payloadLen = iterlen;
1766bbe0590SSundeep Panicker 
1776bbe0590SSundeep Panicker 		/* validate the content of the iteration control bytes */
1786bbe0590SSundeep Panicker 		if ((data[HEAD_ITER] >= def->iterationCount) ||
1796bbe0590SSundeep Panicker 		    (data[NUM_ITER] > def->iterationCount) ||
1806bbe0590SSundeep Panicker 		    (data[MAX_ITER] != def->iterationCount)) {
1816bbe0590SSundeep Panicker 			/* invalid. show all iterations */
1826bbe0590SSundeep Panicker 			head = 0;
1836bbe0590SSundeep Panicker 			num = def->iterationCount;
1846bbe0590SSundeep Panicker 		} else {
1856bbe0590SSundeep Panicker 			head = data[HEAD_ITER];
1866bbe0590SSundeep Panicker 			num = data[NUM_ITER];
1876bbe0590SSundeep Panicker 		}
1886bbe0590SSundeep Panicker 
1896bbe0590SSundeep Panicker 		nv_elems = (nvlist_t **)malloc(num * sizeof (nvlist_t *));
1906bbe0590SSundeep Panicker 		if (!nv_elems)
1916bbe0590SSundeep Panicker 			return;
1926bbe0590SSundeep Panicker 		for (i = head, n = 0, data += sizeof (uint32_t); n < num;
1936bbe0590SSundeep Panicker 		    i = ((i + 1) % def->iterationCount), n++) {
194ac88567aSHyon Kim 			if (nvlist_alloc(&nv_elems[n], NV_UNIQUE_NAME, 0) != 0)
1956bbe0590SSundeep Panicker 				return;
1966bbe0590SSundeep Panicker 			(void) snprintf(num_str, sizeof (num_str), "%d", n);
1976bbe0590SSundeep Panicker 			convert_element((data + i*iterlen), &newdef, num_str,
1986bbe0590SSundeep Panicker 			    nv_elems[n], B_TRUE);
1996bbe0590SSundeep Panicker 		}
2006bbe0590SSundeep Panicker 		(void) nvlist_add_nvlist_array(nv, path, nv_elems, num);
2016bbe0590SSundeep Panicker 
2026bbe0590SSundeep Panicker 	} else if (def->dataType == FDTYPE_Record) {
2036bbe0590SSundeep Panicker 		const fru_regdef_t *component;
2046bbe0590SSundeep Panicker 		nvlist_t *nv_record;
2056bbe0590SSundeep Panicker 
2066bbe0590SSundeep Panicker 		if (!from_iter) {
207ac88567aSHyon Kim 			if (nvlist_alloc(&nv_record, NV_UNIQUE_NAME, 0) != 0) {
2086bbe0590SSundeep Panicker 				return;
2096bbe0590SSundeep Panicker 			}
2106bbe0590SSundeep Panicker 		} else {
2116bbe0590SSundeep Panicker 			nv_record = nv;
2126bbe0590SSundeep Panicker 		}
2136bbe0590SSundeep Panicker 
2146bbe0590SSundeep Panicker 		for (i = 0; i < def->enumCount; i++,
2156bbe0590SSundeep Panicker 		    data += component->payloadLen) {
2166bbe0590SSundeep Panicker 			component = fru_reg_lookup_def_by_name(
2176bbe0590SSundeep Panicker 			    def->enumTable[i].text);
2186bbe0590SSundeep Panicker 			convert_element(data, component, "", nv_record,
2196bbe0590SSundeep Panicker 			    B_FALSE);
2206bbe0590SSundeep Panicker 		}
2216bbe0590SSundeep Panicker 
2226bbe0590SSundeep Panicker 		(void) nvlist_add_nvlist(nv, path, nv_record);
2236bbe0590SSundeep Panicker 
2246bbe0590SSundeep Panicker 	} else {
2256bbe0590SSundeep Panicker 		convert_field(data, def, path, nv);
2266bbe0590SSundeep Panicker 	}
2276bbe0590SSundeep Panicker }
2286bbe0590SSundeep Panicker 
2296bbe0590SSundeep Panicker 
2306bbe0590SSundeep Panicker static fru_regdef_t *
alloc_unknown_fru_regdef(void)2316bbe0590SSundeep Panicker alloc_unknown_fru_regdef(void)
2326bbe0590SSundeep Panicker {
2336bbe0590SSundeep Panicker 	fru_regdef_t *p;
2346bbe0590SSundeep Panicker 
2356bbe0590SSundeep Panicker 	p = malloc(sizeof (fru_regdef_t));
2366bbe0590SSundeep Panicker 	if (!p) {
2376bbe0590SSundeep Panicker 		return (NULL);
2386bbe0590SSundeep Panicker 	}
2396bbe0590SSundeep Panicker 	p->version = REGDEF_VERSION;
2406bbe0590SSundeep Panicker 	p->name = NULL;
2416bbe0590SSundeep Panicker 	p->tagType = -1;
2426bbe0590SSundeep Panicker 	p->tagDense = -1;
2436bbe0590SSundeep Panicker 	p->payloadLen = -1;
2446bbe0590SSundeep Panicker 	p->dataLength = -1;
2456bbe0590SSundeep Panicker 	p->dataType = FDTYPE_ByteArray;
2466bbe0590SSundeep Panicker 	p->dispType = FDISP_Hex;
2476bbe0590SSundeep Panicker 	p->purgeable = FRU_WHICH_UNDEFINED;
2486bbe0590SSundeep Panicker 	p->relocatable = FRU_WHICH_UNDEFINED;
2496bbe0590SSundeep Panicker 	p->enumCount = 0;
2506bbe0590SSundeep Panicker 	p-> enumTable = NULL;
2516bbe0590SSundeep Panicker 	p->iterationCount = 0;
2526bbe0590SSundeep Panicker 	p->iterationType = FRU_NOT_ITERATED;
2536bbe0590SSundeep Panicker 	p->exampleString = NULL;
2546bbe0590SSundeep Panicker 
2556bbe0590SSundeep Panicker 	return (p);
2566bbe0590SSundeep Panicker }
2576bbe0590SSundeep Panicker 
2586bbe0590SSundeep Panicker static int
convert_packet(fru_tag_t * tag,uint8_t * payload,size_t length,void * args)2596bbe0590SSundeep Panicker convert_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
2606bbe0590SSundeep Panicker {
2616bbe0590SSundeep Panicker 	int tag_type;
2626bbe0590SSundeep Panicker 	size_t payload_length;
2636bbe0590SSundeep Panicker 	const fru_regdef_t *def;
2646bbe0590SSundeep Panicker 	nvlist_t *nv = (nvlist_t *)args;
2656bbe0590SSundeep Panicker 	char tagname[sizeof ("?_0123456789_0123456789")];
2666bbe0590SSundeep Panicker 	tag_type = get_tag_type(tag);
2676bbe0590SSundeep Panicker 	payload_length = 0;
2686bbe0590SSundeep Panicker 
2696bbe0590SSundeep Panicker 	/* check for unrecognized tag */
2706bbe0590SSundeep Panicker 	if ((tag_type == -1) ||
2716bbe0590SSundeep Panicker 	    ((payload_length = get_payload_length(tag)) != length)) {
2726bbe0590SSundeep Panicker 		fru_regdef_t *unknown;
2736bbe0590SSundeep Panicker 
2746bbe0590SSundeep Panicker 		unknown = alloc_unknown_fru_regdef();
2756bbe0590SSundeep Panicker 		unknown->payloadLen = length;
2766bbe0590SSundeep Panicker 		unknown->dataLength = unknown->payloadLen;
2776bbe0590SSundeep Panicker 
2786bbe0590SSundeep Panicker 		if (tag_type == -1) {
2796bbe0590SSundeep Panicker 			(void) snprintf(tagname, sizeof (tagname),
2806bbe0590SSundeep Panicker 			    "INVALID");
2816bbe0590SSundeep Panicker 		} else {
2826bbe0590SSundeep Panicker 			(void) snprintf(tagname, sizeof (tagname),
2836bbe0590SSundeep Panicker 			    "%s_%u_%u_%u", get_tagtype_str(tag_type),
2846bbe0590SSundeep Panicker 			    get_tag_dense(tag), payload_length, length);
2856bbe0590SSundeep Panicker 		}
2866bbe0590SSundeep Panicker 		unknown->name = tagname;
2876bbe0590SSundeep Panicker 		convert_element(payload, unknown, "", nv, B_FALSE);
2886bbe0590SSundeep Panicker 		free(unknown);
2896bbe0590SSundeep Panicker 
2906bbe0590SSundeep Panicker 	} else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
2916bbe0590SSundeep Panicker 		fru_regdef_t *unknown;
2926bbe0590SSundeep Panicker 
2936bbe0590SSundeep Panicker 		unknown = alloc_unknown_fru_regdef();
2946bbe0590SSundeep Panicker 		unknown->payloadLen = length;
2956bbe0590SSundeep Panicker 		unknown->dataLength = unknown->payloadLen;
2966bbe0590SSundeep Panicker 
2976bbe0590SSundeep Panicker 		(void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
2986bbe0590SSundeep Panicker 		    get_tagtype_str(tag_type),
2996bbe0590SSundeep Panicker 		    unknown->tagDense, payload_length);
3006bbe0590SSundeep Panicker 
3016bbe0590SSundeep Panicker 		unknown->name = tagname;
3026bbe0590SSundeep Panicker 		convert_element(payload, unknown, "", nv, B_FALSE);
3036bbe0590SSundeep Panicker 		free(unknown);
3046bbe0590SSundeep Panicker 
3056bbe0590SSundeep Panicker 	} else {
3066bbe0590SSundeep Panicker 
3076bbe0590SSundeep Panicker 		convert_element(payload, def, "", nv, B_FALSE);
3086bbe0590SSundeep Panicker 
3096bbe0590SSundeep Panicker 	}
3106bbe0590SSundeep Panicker 
3116bbe0590SSundeep Panicker 	return (FRU_SUCCESS);
3126bbe0590SSundeep Panicker }
3136bbe0590SSundeep Panicker 
3146bbe0590SSundeep Panicker 
3156bbe0590SSundeep Panicker static int
convert_packets_in_segment(fru_seghdl_t segment,void * args)3166bbe0590SSundeep Panicker convert_packets_in_segment(fru_seghdl_t segment, void *args)
3176bbe0590SSundeep Panicker {
3186bbe0590SSundeep Panicker 	char *name;
3196bbe0590SSundeep Panicker 	int ret;
3206bbe0590SSundeep Panicker 	nvlist_t *nv = (nvlist_t *)args;
3216bbe0590SSundeep Panicker 	nvlist_t *nv_segment;
3226bbe0590SSundeep Panicker 
3236bbe0590SSundeep Panicker 	ret = fru_get_segment_name(segment, &name);
3246bbe0590SSundeep Panicker 	if (ret != FRU_SUCCESS) {
3256bbe0590SSundeep Panicker 		return (ret);
3266bbe0590SSundeep Panicker 	}
3276bbe0590SSundeep Panicker 
3286bbe0590SSundeep Panicker 	/* create a new nvlist for each segment */
329ac88567aSHyon Kim 	ret = nvlist_alloc(&nv_segment, NV_UNIQUE_NAME, 0);
3306bbe0590SSundeep Panicker 	if (ret) {
3316bbe0590SSundeep Panicker 		free(name);
3326bbe0590SSundeep Panicker 		return (FRU_FAILURE);
3336bbe0590SSundeep Panicker 	}
3346bbe0590SSundeep Panicker 
3356bbe0590SSundeep Panicker 	/* convert the segment to an nvlist */
3366bbe0590SSundeep Panicker 	ret = fru_for_each_packet(segment, convert_packet, nv_segment);
3376bbe0590SSundeep Panicker 	if (ret != FRU_SUCCESS) {
3386bbe0590SSundeep Panicker 		nvlist_free(nv_segment);
3396bbe0590SSundeep Panicker 		free(name);
3406bbe0590SSundeep Panicker 		return (ret);
3416bbe0590SSundeep Panicker 	}
3426bbe0590SSundeep Panicker 
3436bbe0590SSundeep Panicker 	/* add the nvlist for this segment */
3446bbe0590SSundeep Panicker 	(void) nvlist_add_nvlist(nv, name, nv_segment);
3456bbe0590SSundeep Panicker 
3466bbe0590SSundeep Panicker 	free(name);
3476bbe0590SSundeep Panicker 
3486bbe0590SSundeep Panicker 	return (FRU_SUCCESS);
3496bbe0590SSundeep Panicker }
3506bbe0590SSundeep Panicker 
3516bbe0590SSundeep Panicker 
3526bbe0590SSundeep Panicker static int
convert_fru(fru_nodehdl_t hdl,nvlist_t ** nvlist)3536bbe0590SSundeep Panicker convert_fru(fru_nodehdl_t hdl, nvlist_t **nvlist)
3546bbe0590SSundeep Panicker {
3556bbe0590SSundeep Panicker 	int err;
3566bbe0590SSundeep Panicker 	nvlist_t *nv;
3576bbe0590SSundeep Panicker 	fru_node_t fru_type;
3586bbe0590SSundeep Panicker 
3596bbe0590SSundeep Panicker 	if (fru_get_node_type(hdl, &fru_type) != FRU_SUCCESS) {
3606bbe0590SSundeep Panicker 		return (-1);
3616bbe0590SSundeep Panicker 	}
3626bbe0590SSundeep Panicker 
3636bbe0590SSundeep Panicker 	if (fru_type != FRU_NODE_CONTAINER) {
3646bbe0590SSundeep Panicker 		return (-1);
3656bbe0590SSundeep Panicker 	}
3666bbe0590SSundeep Panicker 
367ac88567aSHyon Kim 	err = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
3686bbe0590SSundeep Panicker 	if (err) {
3696bbe0590SSundeep Panicker 		return (err);
3706bbe0590SSundeep Panicker 	}
3716bbe0590SSundeep Panicker 
3726bbe0590SSundeep Panicker 	if (fru_for_each_segment(hdl, convert_packets_in_segment, nv) !=
3736bbe0590SSundeep Panicker 	    FRU_SUCCESS) {
3746bbe0590SSundeep Panicker 		nvlist_free(nv);
3756bbe0590SSundeep Panicker 		return (-1);
3766bbe0590SSundeep Panicker 	}
3776bbe0590SSundeep Panicker 
3786bbe0590SSundeep Panicker 	*nvlist = nv;
3796bbe0590SSundeep Panicker 
3806bbe0590SSundeep Panicker 	return (0);
3816bbe0590SSundeep Panicker }
3826bbe0590SSundeep Panicker 
3836bbe0590SSundeep Panicker 
3846bbe0590SSundeep Panicker int
rawfru_to_nvlist(uint8_t * buffer,size_t bufsize,char * cont_type,nvlist_t ** nvlist)3856bbe0590SSundeep Panicker rawfru_to_nvlist(uint8_t *buffer, size_t bufsize, char *cont_type,
3866bbe0590SSundeep Panicker     nvlist_t **nvlist)
3876bbe0590SSundeep Panicker {
3886bbe0590SSundeep Panicker 	fru_errno_t fru_err;
3896bbe0590SSundeep Panicker 	fru_nodehdl_t hdl;
3906bbe0590SSundeep Panicker 	int err;
3916bbe0590SSundeep Panicker 
3926bbe0590SSundeep Panicker 	(void) pthread_mutex_lock(&gLock);
3936bbe0590SSundeep Panicker 	fru_err = fru_open_data_source("raw", buffer, bufsize, cont_type,
3946bbe0590SSundeep Panicker 	    NULL);
3956bbe0590SSundeep Panicker 	if (fru_err != FRU_SUCCESS) {
3966bbe0590SSundeep Panicker 		(void) pthread_mutex_unlock(&gLock);
3976bbe0590SSundeep Panicker 		return (-1);
3986bbe0590SSundeep Panicker 	}
3996bbe0590SSundeep Panicker 	fru_err = fru_get_root(&hdl);
4006bbe0590SSundeep Panicker 	if (fru_err != FRU_SUCCESS) {
4016bbe0590SSundeep Panicker 		(void) pthread_mutex_unlock(&gLock);
4026bbe0590SSundeep Panicker 		return (-1);
4036bbe0590SSundeep Panicker 	}
4046bbe0590SSundeep Panicker 
4056bbe0590SSundeep Panicker 	err = convert_fru(hdl, nvlist);
4066bbe0590SSundeep Panicker 
407*29c3ebdbSJohn Levon 	(void) fru_close_data_source();
4086bbe0590SSundeep Panicker 
4096bbe0590SSundeep Panicker 	(void) pthread_mutex_unlock(&gLock);
4106bbe0590SSundeep Panicker 
4116bbe0590SSundeep Panicker 	return (err);
4126bbe0590SSundeep Panicker }
413