xref: /onnv-gate/usr/src/lib/libfru/libnvfru/nvfru.c (revision 12126:60364f3f65c7)
111015SSundeep.Panicker@Sun.COM /*
211015SSundeep.Panicker@Sun.COM  * CDDL HEADER START
311015SSundeep.Panicker@Sun.COM  *
411015SSundeep.Panicker@Sun.COM  * The contents of this file are subject to the terms of the
511015SSundeep.Panicker@Sun.COM  * Common Development and Distribution License (the "License").
611015SSundeep.Panicker@Sun.COM  * You may not use this file except in compliance with the License.
711015SSundeep.Panicker@Sun.COM  *
811015SSundeep.Panicker@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911015SSundeep.Panicker@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011015SSundeep.Panicker@Sun.COM  * See the License for the specific language governing permissions
1111015SSundeep.Panicker@Sun.COM  * and limitations under the License.
1211015SSundeep.Panicker@Sun.COM  *
1311015SSundeep.Panicker@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411015SSundeep.Panicker@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511015SSundeep.Panicker@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611015SSundeep.Panicker@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711015SSundeep.Panicker@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811015SSundeep.Panicker@Sun.COM  *
1911015SSundeep.Panicker@Sun.COM  * CDDL HEADER END
2011015SSundeep.Panicker@Sun.COM  */
2111015SSundeep.Panicker@Sun.COM 
2211015SSundeep.Panicker@Sun.COM /*
23*12126SHyon.Kim@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2411015SSundeep.Panicker@Sun.COM  */
2511015SSundeep.Panicker@Sun.COM 
2611015SSundeep.Panicker@Sun.COM #include <stdio.h>
2711015SSundeep.Panicker@Sun.COM #include <stdlib.h>
2811015SSundeep.Panicker@Sun.COM #include <stdint.h>
2911015SSundeep.Panicker@Sun.COM #include <strings.h>
3011015SSundeep.Panicker@Sun.COM #include <assert.h>
3111015SSundeep.Panicker@Sun.COM #include <pthread.h>
3211015SSundeep.Panicker@Sun.COM #include <sys/byteorder.h>
3311015SSundeep.Panicker@Sun.COM #include <sys/types.h>
3411015SSundeep.Panicker@Sun.COM #include <sys/nvpair.h>
3511015SSundeep.Panicker@Sun.COM 
3611015SSundeep.Panicker@Sun.COM #include "libfru.h"
3711015SSundeep.Panicker@Sun.COM #include "libfrup.h"
3811015SSundeep.Panicker@Sun.COM #include "fru_tag.h"
3911015SSundeep.Panicker@Sun.COM #include "libfrureg.h"
4011063SSundeep.Panicker@Sun.COM #include "nvfru.h"
4111015SSundeep.Panicker@Sun.COM 
4211015SSundeep.Panicker@Sun.COM #define	NUM_ITER_BYTES	4
4311063SSundeep.Panicker@Sun.COM #define	HEAD_ITER	0
4411015SSundeep.Panicker@Sun.COM #define	TAIL_ITER	1
4511015SSundeep.Panicker@Sun.COM #define	NUM_ITER	2
4611015SSundeep.Panicker@Sun.COM #define	MAX_ITER	3
4711015SSundeep.Panicker@Sun.COM #define	TIMESTRINGLEN	128
4811015SSundeep.Panicker@Sun.COM 
4911015SSundeep.Panicker@Sun.COM #define	PARSE_TIME	1
5011015SSundeep.Panicker@Sun.COM 
5111015SSundeep.Panicker@Sun.COM static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
5211015SSundeep.Panicker@Sun.COM 
5311015SSundeep.Panicker@Sun.COM 
5411015SSundeep.Panicker@Sun.COM 
5511015SSundeep.Panicker@Sun.COM static void
convert_field(const uint8_t * field,const fru_regdef_t * def,const char * path,nvlist_t * nv)5611015SSundeep.Panicker@Sun.COM convert_field(const uint8_t *field, const fru_regdef_t *def, const char *path,
5711015SSundeep.Panicker@Sun.COM     nvlist_t *nv)
5811015SSundeep.Panicker@Sun.COM {
5911015SSundeep.Panicker@Sun.COM 	char timestring[TIMESTRINGLEN];
6011015SSundeep.Panicker@Sun.COM 	int i;
6111015SSundeep.Panicker@Sun.COM 	uint64_t value;
6211015SSundeep.Panicker@Sun.COM 	time_t timefield;
6311015SSundeep.Panicker@Sun.COM 
6411015SSundeep.Panicker@Sun.COM 	switch (def->dataType) {
6511015SSundeep.Panicker@Sun.COM 	case FDTYPE_Binary:
6611015SSundeep.Panicker@Sun.COM 		assert(def->payloadLen <= sizeof (value));
6711015SSundeep.Panicker@Sun.COM 		switch (def->dispType) {
6811015SSundeep.Panicker@Sun.COM #if PARSE_TIME == 1
6911015SSundeep.Panicker@Sun.COM 		case FDISP_Time:
7011015SSundeep.Panicker@Sun.COM 			if (def->payloadLen > sizeof (timefield)) {
7111015SSundeep.Panicker@Sun.COM 				/* too big for formatting */
7211015SSundeep.Panicker@Sun.COM 				return;
7311015SSundeep.Panicker@Sun.COM 			}
7411015SSundeep.Panicker@Sun.COM 			(void) memcpy(&timefield, field, sizeof (timefield));
7511015SSundeep.Panicker@Sun.COM 			timefield = BE_32(timefield);
7611015SSundeep.Panicker@Sun.COM 			if (strftime(timestring, sizeof (timestring), "%C",
7711015SSundeep.Panicker@Sun.COM 			    localtime(&timefield)) == 0) {
7811015SSundeep.Panicker@Sun.COM 				/* buffer too small */
7911015SSundeep.Panicker@Sun.COM 				return;
8011015SSundeep.Panicker@Sun.COM 			}
8111015SSundeep.Panicker@Sun.COM 			(void) nvlist_add_string(nv, path, timestring);
8211015SSundeep.Panicker@Sun.COM 			return;
8311015SSundeep.Panicker@Sun.COM #endif
8411015SSundeep.Panicker@Sun.COM 
8511015SSundeep.Panicker@Sun.COM 		case FDISP_Binary:
8611015SSundeep.Panicker@Sun.COM 		case FDISP_Octal:
8711015SSundeep.Panicker@Sun.COM 		case FDISP_Decimal:
8811015SSundeep.Panicker@Sun.COM 		case FDISP_Hex:
8911015SSundeep.Panicker@Sun.COM 		default:
9011015SSundeep.Panicker@Sun.COM 			value = 0;
9111015SSundeep.Panicker@Sun.COM 			(void) memcpy((((uint8_t *)&value) +
9211015SSundeep.Panicker@Sun.COM 			    sizeof (value) - def->payloadLen),
9311015SSundeep.Panicker@Sun.COM 			    field, def->payloadLen);
9411015SSundeep.Panicker@Sun.COM 			value = BE_64(value);
9511015SSundeep.Panicker@Sun.COM 			switch (def->payloadLen) {
9611015SSundeep.Panicker@Sun.COM 			case 1:
9711015SSundeep.Panicker@Sun.COM 				(void) nvlist_add_uint8(nv, path,
9811015SSundeep.Panicker@Sun.COM 				    (uint8_t)value);
9911015SSundeep.Panicker@Sun.COM 				break;
10011015SSundeep.Panicker@Sun.COM 			case 2:
10111015SSundeep.Panicker@Sun.COM 				(void) nvlist_add_uint16(nv, path,
10211015SSundeep.Panicker@Sun.COM 				    (uint16_t)value);
10311015SSundeep.Panicker@Sun.COM 				break;
10411015SSundeep.Panicker@Sun.COM 			case 4:
10511015SSundeep.Panicker@Sun.COM 				(void) nvlist_add_uint32(nv, path,
10611015SSundeep.Panicker@Sun.COM 				    (uint32_t)value);
10711015SSundeep.Panicker@Sun.COM 				break;
10811015SSundeep.Panicker@Sun.COM 			default:
10911015SSundeep.Panicker@Sun.COM 				(void) nvlist_add_uint64(nv, path, value);
11011015SSundeep.Panicker@Sun.COM 			}
11111015SSundeep.Panicker@Sun.COM 			return;
11211015SSundeep.Panicker@Sun.COM 		}
11311015SSundeep.Panicker@Sun.COM 
11411015SSundeep.Panicker@Sun.COM 	case FDTYPE_ASCII:
11511015SSundeep.Panicker@Sun.COM 		(void) nvlist_add_string(nv, path, (char *)field);
11611015SSundeep.Panicker@Sun.COM 		return;
11711015SSundeep.Panicker@Sun.COM 
11811015SSundeep.Panicker@Sun.COM 	case FDTYPE_Enumeration:
11911015SSundeep.Panicker@Sun.COM 		value = 0;
12011015SSundeep.Panicker@Sun.COM 		(void) memcpy((((uint8_t *)&value) + sizeof (value) -
12111015SSundeep.Panicker@Sun.COM 		    def->payloadLen), field, def->payloadLen);
12211015SSundeep.Panicker@Sun.COM 		value = BE_64(value);
12311015SSundeep.Panicker@Sun.COM 		for (i = 0; i < def->enumCount; i++) {
12411015SSundeep.Panicker@Sun.COM 			if (def->enumTable[i].value == value) {
12511015SSundeep.Panicker@Sun.COM 				(void) nvlist_add_string(nv, path,
12611015SSundeep.Panicker@Sun.COM 				    def->enumTable[i].text);
12711015SSundeep.Panicker@Sun.COM 				return;
12811015SSundeep.Panicker@Sun.COM 			}
12911015SSundeep.Panicker@Sun.COM 		}
13011015SSundeep.Panicker@Sun.COM 	}
13111015SSundeep.Panicker@Sun.COM 
13211015SSundeep.Panicker@Sun.COM 	/* nothing matched above, use byte array */
13311015SSundeep.Panicker@Sun.COM 	(void) nvlist_add_byte_array(nv, path, (uchar_t *)field,
13411015SSundeep.Panicker@Sun.COM 	    def->payloadLen);
13511015SSundeep.Panicker@Sun.COM }
13611015SSundeep.Panicker@Sun.COM 
13711015SSundeep.Panicker@Sun.COM 
13811015SSundeep.Panicker@Sun.COM 
13911015SSundeep.Panicker@Sun.COM static void
convert_element(const uint8_t * data,const fru_regdef_t * def,char * ppath,nvlist_t * nv,boolean_t from_iter)14011015SSundeep.Panicker@Sun.COM convert_element(const uint8_t *data, const fru_regdef_t *def, char *ppath,
14111015SSundeep.Panicker@Sun.COM     nvlist_t *nv, boolean_t from_iter)
14211015SSundeep.Panicker@Sun.COM {
14311015SSundeep.Panicker@Sun.COM 	int i;
14411015SSundeep.Panicker@Sun.COM 	char *path;
14511015SSundeep.Panicker@Sun.COM 
14611015SSundeep.Panicker@Sun.COM 	/* construct path */
14711015SSundeep.Panicker@Sun.COM 	if ((def->iterationCount == 0) &&
14811015SSundeep.Panicker@Sun.COM 	    (def->iterationType != FRU_NOT_ITERATED)) {
14911015SSundeep.Panicker@Sun.COM 		path = ppath;
15011015SSundeep.Panicker@Sun.COM 	} else {
15111015SSundeep.Panicker@Sun.COM 		path = (char *)def->name;
15211015SSundeep.Panicker@Sun.COM 	}
15311015SSundeep.Panicker@Sun.COM 
15411015SSundeep.Panicker@Sun.COM 	/* iteration, record and field */
15511015SSundeep.Panicker@Sun.COM 	if (def->iterationCount) {
15611015SSundeep.Panicker@Sun.COM 		int iterlen, n;
15711015SSundeep.Panicker@Sun.COM 		uint8_t head, num;
15811015SSundeep.Panicker@Sun.COM 		fru_regdef_t newdef;
15911015SSundeep.Panicker@Sun.COM 		nvlist_t **nv_elems;
16011015SSundeep.Panicker@Sun.COM 		char num_str[32];
16111015SSundeep.Panicker@Sun.COM 
16211015SSundeep.Panicker@Sun.COM 		iterlen = (def->payloadLen - NUM_ITER_BYTES) /
16311015SSundeep.Panicker@Sun.COM 		    def->iterationCount;
16411015SSundeep.Panicker@Sun.COM 
16511015SSundeep.Panicker@Sun.COM 		/*
16611015SSundeep.Panicker@Sun.COM 		 * make a new element definition to describe the components of
16711015SSundeep.Panicker@Sun.COM 		 * the iteration.
16811015SSundeep.Panicker@Sun.COM 		 */
16911015SSundeep.Panicker@Sun.COM 		(void) memcpy(&newdef, def, sizeof (newdef));
17011015SSundeep.Panicker@Sun.COM 		newdef.iterationCount = 0;
17111015SSundeep.Panicker@Sun.COM 		newdef.payloadLen = iterlen;
17211015SSundeep.Panicker@Sun.COM 
17311015SSundeep.Panicker@Sun.COM 		/* validate the content of the iteration control bytes */
17411015SSundeep.Panicker@Sun.COM 		if ((data[HEAD_ITER] >= def->iterationCount) ||
17511015SSundeep.Panicker@Sun.COM 		    (data[NUM_ITER] > def->iterationCount) ||
17611015SSundeep.Panicker@Sun.COM 		    (data[MAX_ITER] != def->iterationCount)) {
17711015SSundeep.Panicker@Sun.COM 			/* invalid. show all iterations */
17811015SSundeep.Panicker@Sun.COM 			head = 0;
17911015SSundeep.Panicker@Sun.COM 			num = def->iterationCount;
18011015SSundeep.Panicker@Sun.COM 		} else {
18111015SSundeep.Panicker@Sun.COM 			head = data[HEAD_ITER];
18211015SSundeep.Panicker@Sun.COM 			num = data[NUM_ITER];
18311015SSundeep.Panicker@Sun.COM 		}
18411015SSundeep.Panicker@Sun.COM 
18511015SSundeep.Panicker@Sun.COM 		nv_elems = (nvlist_t **)malloc(num * sizeof (nvlist_t *));
18611015SSundeep.Panicker@Sun.COM 		if (!nv_elems)
18711015SSundeep.Panicker@Sun.COM 			return;
18811015SSundeep.Panicker@Sun.COM 		for (i = head, n = 0, data += sizeof (uint32_t); n < num;
18911015SSundeep.Panicker@Sun.COM 		    i = ((i + 1) % def->iterationCount), n++) {
190*12126SHyon.Kim@Sun.COM 			if (nvlist_alloc(&nv_elems[n], NV_UNIQUE_NAME, 0) != 0)
19111015SSundeep.Panicker@Sun.COM 				return;
19211015SSundeep.Panicker@Sun.COM 			(void) snprintf(num_str, sizeof (num_str), "%d", n);
19311015SSundeep.Panicker@Sun.COM 			convert_element((data + i*iterlen), &newdef, num_str,
19411015SSundeep.Panicker@Sun.COM 			    nv_elems[n], B_TRUE);
19511015SSundeep.Panicker@Sun.COM 		}
19611015SSundeep.Panicker@Sun.COM 		(void) nvlist_add_nvlist_array(nv, path, nv_elems, num);
19711015SSundeep.Panicker@Sun.COM 
19811015SSundeep.Panicker@Sun.COM 	} else if (def->dataType == FDTYPE_Record) {
19911015SSundeep.Panicker@Sun.COM 		const fru_regdef_t *component;
20011015SSundeep.Panicker@Sun.COM 		nvlist_t *nv_record;
20111015SSundeep.Panicker@Sun.COM 
20211015SSundeep.Panicker@Sun.COM 		if (!from_iter) {
203*12126SHyon.Kim@Sun.COM 			if (nvlist_alloc(&nv_record, NV_UNIQUE_NAME, 0) != 0) {
20411015SSundeep.Panicker@Sun.COM 				return;
20511015SSundeep.Panicker@Sun.COM 			}
20611015SSundeep.Panicker@Sun.COM 		} else {
20711015SSundeep.Panicker@Sun.COM 			nv_record = nv;
20811015SSundeep.Panicker@Sun.COM 		}
20911015SSundeep.Panicker@Sun.COM 
21011015SSundeep.Panicker@Sun.COM 		for (i = 0; i < def->enumCount; i++,
21111015SSundeep.Panicker@Sun.COM 		    data += component->payloadLen) {
21211015SSundeep.Panicker@Sun.COM 			component = fru_reg_lookup_def_by_name(
21311015SSundeep.Panicker@Sun.COM 			    def->enumTable[i].text);
21411015SSundeep.Panicker@Sun.COM 			convert_element(data, component, "", nv_record,
21511015SSundeep.Panicker@Sun.COM 			    B_FALSE);
21611015SSundeep.Panicker@Sun.COM 		}
21711015SSundeep.Panicker@Sun.COM 
21811015SSundeep.Panicker@Sun.COM 		(void) nvlist_add_nvlist(nv, path, nv_record);
21911015SSundeep.Panicker@Sun.COM 
22011015SSundeep.Panicker@Sun.COM 	} else {
22111015SSundeep.Panicker@Sun.COM 		convert_field(data, def, path, nv);
22211015SSundeep.Panicker@Sun.COM 	}
22311015SSundeep.Panicker@Sun.COM }
22411015SSundeep.Panicker@Sun.COM 
22511015SSundeep.Panicker@Sun.COM 
22611015SSundeep.Panicker@Sun.COM static fru_regdef_t *
alloc_unknown_fru_regdef(void)22711015SSundeep.Panicker@Sun.COM alloc_unknown_fru_regdef(void)
22811015SSundeep.Panicker@Sun.COM {
22911015SSundeep.Panicker@Sun.COM 	fru_regdef_t *p;
23011015SSundeep.Panicker@Sun.COM 
23111015SSundeep.Panicker@Sun.COM 	p = malloc(sizeof (fru_regdef_t));
23211015SSundeep.Panicker@Sun.COM 	if (!p) {
23311015SSundeep.Panicker@Sun.COM 		return (NULL);
23411015SSundeep.Panicker@Sun.COM 	}
23511015SSundeep.Panicker@Sun.COM 	p->version = REGDEF_VERSION;
23611015SSundeep.Panicker@Sun.COM 	p->name = NULL;
23711015SSundeep.Panicker@Sun.COM 	p->tagType = -1;
23811015SSundeep.Panicker@Sun.COM 	p->tagDense = -1;
23911015SSundeep.Panicker@Sun.COM 	p->payloadLen = -1;
24011015SSundeep.Panicker@Sun.COM 	p->dataLength = -1;
24111015SSundeep.Panicker@Sun.COM 	p->dataType = FDTYPE_ByteArray;
24211015SSundeep.Panicker@Sun.COM 	p->dispType = FDISP_Hex;
24311015SSundeep.Panicker@Sun.COM 	p->purgeable = FRU_WHICH_UNDEFINED;
24411015SSundeep.Panicker@Sun.COM 	p->relocatable = FRU_WHICH_UNDEFINED;
24511015SSundeep.Panicker@Sun.COM 	p->enumCount = 0;
24611015SSundeep.Panicker@Sun.COM 	p-> enumTable = NULL;
24711015SSundeep.Panicker@Sun.COM 	p->iterationCount = 0;
24811015SSundeep.Panicker@Sun.COM 	p->iterationType = FRU_NOT_ITERATED;
24911015SSundeep.Panicker@Sun.COM 	p->exampleString = NULL;
25011015SSundeep.Panicker@Sun.COM 
25111015SSundeep.Panicker@Sun.COM 	return (p);
25211015SSundeep.Panicker@Sun.COM }
25311015SSundeep.Panicker@Sun.COM 
25411015SSundeep.Panicker@Sun.COM static int
convert_packet(fru_tag_t * tag,uint8_t * payload,size_t length,void * args)25511015SSundeep.Panicker@Sun.COM convert_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
25611015SSundeep.Panicker@Sun.COM {
25711015SSundeep.Panicker@Sun.COM 	int tag_type;
25811015SSundeep.Panicker@Sun.COM 	size_t payload_length;
25911015SSundeep.Panicker@Sun.COM 	const fru_regdef_t *def;
26011015SSundeep.Panicker@Sun.COM 	nvlist_t *nv = (nvlist_t *)args;
26111015SSundeep.Panicker@Sun.COM 	char tagname[sizeof ("?_0123456789_0123456789")];
26211015SSundeep.Panicker@Sun.COM 	tag_type = get_tag_type(tag);
26311015SSundeep.Panicker@Sun.COM 	payload_length = 0;
26411015SSundeep.Panicker@Sun.COM 
26511015SSundeep.Panicker@Sun.COM 	/* check for unrecognized tag */
26611015SSundeep.Panicker@Sun.COM 	if ((tag_type == -1) ||
26711015SSundeep.Panicker@Sun.COM 	    ((payload_length = get_payload_length(tag)) != length)) {
26811015SSundeep.Panicker@Sun.COM 		fru_regdef_t *unknown;
26911015SSundeep.Panicker@Sun.COM 
27011015SSundeep.Panicker@Sun.COM 		unknown = alloc_unknown_fru_regdef();
27111015SSundeep.Panicker@Sun.COM 		unknown->payloadLen = length;
27211015SSundeep.Panicker@Sun.COM 		unknown->dataLength = unknown->payloadLen;
27311015SSundeep.Panicker@Sun.COM 
27411015SSundeep.Panicker@Sun.COM 		if (tag_type == -1) {
27511015SSundeep.Panicker@Sun.COM 			(void) snprintf(tagname, sizeof (tagname),
27611015SSundeep.Panicker@Sun.COM 			    "INVALID");
27711015SSundeep.Panicker@Sun.COM 		} else {
27811015SSundeep.Panicker@Sun.COM 			(void) snprintf(tagname, sizeof (tagname),
27911015SSundeep.Panicker@Sun.COM 			    "%s_%u_%u_%u", get_tagtype_str(tag_type),
28011015SSundeep.Panicker@Sun.COM 			    get_tag_dense(tag), payload_length, length);
28111015SSundeep.Panicker@Sun.COM 		}
28211015SSundeep.Panicker@Sun.COM 		unknown->name = tagname;
28311015SSundeep.Panicker@Sun.COM 		convert_element(payload, unknown, "", nv, B_FALSE);
28411015SSundeep.Panicker@Sun.COM 		free(unknown);
28511015SSundeep.Panicker@Sun.COM 
28611015SSundeep.Panicker@Sun.COM 	} else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
28711015SSundeep.Panicker@Sun.COM 		fru_regdef_t *unknown;
28811015SSundeep.Panicker@Sun.COM 
28911015SSundeep.Panicker@Sun.COM 		unknown = alloc_unknown_fru_regdef();
29011015SSundeep.Panicker@Sun.COM 		unknown->payloadLen = length;
29111015SSundeep.Panicker@Sun.COM 		unknown->dataLength = unknown->payloadLen;
29211015SSundeep.Panicker@Sun.COM 
29311015SSundeep.Panicker@Sun.COM 		(void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
29411015SSundeep.Panicker@Sun.COM 		    get_tagtype_str(tag_type),
29511015SSundeep.Panicker@Sun.COM 		    unknown->tagDense, payload_length);
29611015SSundeep.Panicker@Sun.COM 
29711015SSundeep.Panicker@Sun.COM 		unknown->name = tagname;
29811015SSundeep.Panicker@Sun.COM 		convert_element(payload, unknown, "", nv, B_FALSE);
29911015SSundeep.Panicker@Sun.COM 		free(unknown);
30011015SSundeep.Panicker@Sun.COM 
30111015SSundeep.Panicker@Sun.COM 	} else {
30211015SSundeep.Panicker@Sun.COM 
30311015SSundeep.Panicker@Sun.COM 		convert_element(payload, def, "", nv, B_FALSE);
30411015SSundeep.Panicker@Sun.COM 
30511015SSundeep.Panicker@Sun.COM 	}
30611015SSundeep.Panicker@Sun.COM 
30711015SSundeep.Panicker@Sun.COM 	return (FRU_SUCCESS);
30811015SSundeep.Panicker@Sun.COM }
30911015SSundeep.Panicker@Sun.COM 
31011015SSundeep.Panicker@Sun.COM 
31111015SSundeep.Panicker@Sun.COM static int
convert_packets_in_segment(fru_seghdl_t segment,void * args)31211015SSundeep.Panicker@Sun.COM convert_packets_in_segment(fru_seghdl_t segment, void *args)
31311015SSundeep.Panicker@Sun.COM {
31411015SSundeep.Panicker@Sun.COM 	char *name;
31511015SSundeep.Panicker@Sun.COM 	int ret;
31611015SSundeep.Panicker@Sun.COM 	nvlist_t *nv = (nvlist_t *)args;
31711015SSundeep.Panicker@Sun.COM 	nvlist_t *nv_segment;
31811015SSundeep.Panicker@Sun.COM 
31911015SSundeep.Panicker@Sun.COM 	ret = fru_get_segment_name(segment, &name);
32011015SSundeep.Panicker@Sun.COM 	if (ret != FRU_SUCCESS) {
32111015SSundeep.Panicker@Sun.COM 		return (ret);
32211015SSundeep.Panicker@Sun.COM 	}
32311015SSundeep.Panicker@Sun.COM 
32411015SSundeep.Panicker@Sun.COM 	/* create a new nvlist for each segment */
325*12126SHyon.Kim@Sun.COM 	ret = nvlist_alloc(&nv_segment, NV_UNIQUE_NAME, 0);
32611015SSundeep.Panicker@Sun.COM 	if (ret) {
32711015SSundeep.Panicker@Sun.COM 		free(name);
32811015SSundeep.Panicker@Sun.COM 		return (FRU_FAILURE);
32911015SSundeep.Panicker@Sun.COM 	}
33011015SSundeep.Panicker@Sun.COM 
33111015SSundeep.Panicker@Sun.COM 	/* convert the segment to an nvlist */
33211015SSundeep.Panicker@Sun.COM 	ret = fru_for_each_packet(segment, convert_packet, nv_segment);
33311015SSundeep.Panicker@Sun.COM 	if (ret != FRU_SUCCESS) {
33411015SSundeep.Panicker@Sun.COM 		nvlist_free(nv_segment);
33511015SSundeep.Panicker@Sun.COM 		free(name);
33611015SSundeep.Panicker@Sun.COM 		return (ret);
33711015SSundeep.Panicker@Sun.COM 	}
33811015SSundeep.Panicker@Sun.COM 
33911015SSundeep.Panicker@Sun.COM 	/* add the nvlist for this segment */
34011015SSundeep.Panicker@Sun.COM 	(void) nvlist_add_nvlist(nv, name, nv_segment);
34111015SSundeep.Panicker@Sun.COM 
34211015SSundeep.Panicker@Sun.COM 	free(name);
34311015SSundeep.Panicker@Sun.COM 
34411015SSundeep.Panicker@Sun.COM 	return (FRU_SUCCESS);
34511015SSundeep.Panicker@Sun.COM }
34611015SSundeep.Panicker@Sun.COM 
34711015SSundeep.Panicker@Sun.COM 
34811015SSundeep.Panicker@Sun.COM static int
convert_fru(fru_nodehdl_t hdl,nvlist_t ** nvlist)34911015SSundeep.Panicker@Sun.COM convert_fru(fru_nodehdl_t hdl, nvlist_t **nvlist)
35011015SSundeep.Panicker@Sun.COM {
35111015SSundeep.Panicker@Sun.COM 	int err;
35211015SSundeep.Panicker@Sun.COM 	nvlist_t *nv;
35311015SSundeep.Panicker@Sun.COM 	fru_node_t fru_type;
35411015SSundeep.Panicker@Sun.COM 
35511015SSundeep.Panicker@Sun.COM 	if (fru_get_node_type(hdl, &fru_type) != FRU_SUCCESS) {
35611015SSundeep.Panicker@Sun.COM 		return (-1);
35711015SSundeep.Panicker@Sun.COM 	}
35811015SSundeep.Panicker@Sun.COM 
35911015SSundeep.Panicker@Sun.COM 	if (fru_type != FRU_NODE_CONTAINER) {
36011015SSundeep.Panicker@Sun.COM 		return (-1);
36111015SSundeep.Panicker@Sun.COM 	}
36211015SSundeep.Panicker@Sun.COM 
363*12126SHyon.Kim@Sun.COM 	err = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
36411015SSundeep.Panicker@Sun.COM 	if (err) {
36511015SSundeep.Panicker@Sun.COM 		return (err);
36611015SSundeep.Panicker@Sun.COM 	}
36711015SSundeep.Panicker@Sun.COM 
36811015SSundeep.Panicker@Sun.COM 	if (fru_for_each_segment(hdl, convert_packets_in_segment, nv) !=
36911015SSundeep.Panicker@Sun.COM 	    FRU_SUCCESS) {
37011015SSundeep.Panicker@Sun.COM 		nvlist_free(nv);
37111015SSundeep.Panicker@Sun.COM 		return (-1);
37211015SSundeep.Panicker@Sun.COM 	}
37311015SSundeep.Panicker@Sun.COM 
37411015SSundeep.Panicker@Sun.COM 	*nvlist = nv;
37511015SSundeep.Panicker@Sun.COM 
37611015SSundeep.Panicker@Sun.COM 	return (0);
37711015SSundeep.Panicker@Sun.COM }
37811015SSundeep.Panicker@Sun.COM 
37911015SSundeep.Panicker@Sun.COM 
38011015SSundeep.Panicker@Sun.COM int
rawfru_to_nvlist(uint8_t * buffer,size_t bufsize,char * cont_type,nvlist_t ** nvlist)38111015SSundeep.Panicker@Sun.COM rawfru_to_nvlist(uint8_t *buffer, size_t bufsize, char *cont_type,
38211015SSundeep.Panicker@Sun.COM     nvlist_t **nvlist)
38311015SSundeep.Panicker@Sun.COM {
38411015SSundeep.Panicker@Sun.COM 	fru_errno_t fru_err;
38511015SSundeep.Panicker@Sun.COM 	fru_nodehdl_t hdl;
38611015SSundeep.Panicker@Sun.COM 	int err;
38711015SSundeep.Panicker@Sun.COM 
38811015SSundeep.Panicker@Sun.COM 	(void) pthread_mutex_lock(&gLock);
38911015SSundeep.Panicker@Sun.COM 	fru_err = fru_open_data_source("raw", buffer, bufsize, cont_type,
39011015SSundeep.Panicker@Sun.COM 	    NULL);
39111015SSundeep.Panicker@Sun.COM 	if (fru_err != FRU_SUCCESS) {
39211015SSundeep.Panicker@Sun.COM 		(void) pthread_mutex_unlock(&gLock);
39311015SSundeep.Panicker@Sun.COM 		return (-1);
39411015SSundeep.Panicker@Sun.COM 	}
39511015SSundeep.Panicker@Sun.COM 	fru_err = fru_get_root(&hdl);
39611015SSundeep.Panicker@Sun.COM 	if (fru_err != FRU_SUCCESS) {
39711015SSundeep.Panicker@Sun.COM 		(void) pthread_mutex_unlock(&gLock);
39811015SSundeep.Panicker@Sun.COM 		return (-1);
39911015SSundeep.Panicker@Sun.COM 	}
40011015SSundeep.Panicker@Sun.COM 
40111015SSundeep.Panicker@Sun.COM 	err = convert_fru(hdl, nvlist);
40211015SSundeep.Panicker@Sun.COM 
40311015SSundeep.Panicker@Sun.COM 	fru_close_data_source();
40411015SSundeep.Panicker@Sun.COM 
40511015SSundeep.Panicker@Sun.COM 	(void) pthread_mutex_unlock(&gLock);
40611015SSundeep.Panicker@Sun.COM 
40711015SSundeep.Panicker@Sun.COM 	return (err);
40811015SSundeep.Panicker@Sun.COM }
409