6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker/*
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * CDDL HEADER START
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker *
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * The contents of this file are subject to the terms of the
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * Common Development and Distribution License (the "License").
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * You may not use this file except in compliance with the License.
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker *
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * or http://www.opensolaris.org/os/licensing.
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * See the License for the specific language governing permissions
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * and limitations under the License.
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker *
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * When distributing Covered Code, include this CDDL HEADER in each
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * If applicable, add the following below this CDDL HEADER, with the
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * fields enclosed by brackets "[]" replaced with your own identifying
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * information: Portions Copyright [yyyy] [name of copyright owner]
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker *
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * CDDL HEADER END
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker/*
ee169c7e77bc5d28a401dde8533cbd38afd24ae1Gary Mills * Copyright (c) 2014 Gary Mills
ee169c7e77bc5d28a401dde8533cbd38afd24ae1Gary Mills *
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <stdio.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <stdlib.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <stdint.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <strings.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <assert.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <pthread.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <sys/byteorder.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <sys/types.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include <sys/nvpair.h>
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include "libfru.h"
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include "libfrup.h"
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include "fru_tag.h"
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#include "libfrureg.h"
d946b6ce5789701c889b59efe11b3a2fa8885ab4Sundeep Panicker#include "nvfru.h"
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#define NUM_ITER_BYTES 4
d946b6ce5789701c889b59efe11b3a2fa8885ab4Sundeep Panicker#define HEAD_ITER 0
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#define TAIL_ITER 1
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#define NUM_ITER 2
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#define MAX_ITER 3
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#define TIMESTRINGLEN 128
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#define PARSE_TIME 1
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic void
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerconvert_field(const uint8_t *field, const fru_regdef_t *def, const char *path,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker char timestring[TIMESTRINGLEN];
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int i;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker uint64_t value;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker time_t timefield;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker switch (def->dataType) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDTYPE_Binary:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker assert(def->payloadLen <= sizeof (value));
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker switch (def->dispType) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#if PARSE_TIME == 1
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDISP_Time:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (def->payloadLen > sizeof (timefield)) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* too big for formatting */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) memcpy(&timefield, field, sizeof (timefield));
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker timefield = BE_32(timefield);
ee169c7e77bc5d28a401dde8533cbd38afd24ae1Gary Mills if (strftime(timestring, sizeof (timestring), "%c",
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker localtime(&timefield)) == 0) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* buffer too small */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_string(nv, path, timestring);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker#endif
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDISP_Binary:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDISP_Octal:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDISP_Decimal:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDISP_Hex:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker default:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker value = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) memcpy((((uint8_t *)&value) +
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker sizeof (value) - def->payloadLen),
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker field, def->payloadLen);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker value = BE_64(value);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker switch (def->payloadLen) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case 1:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_uint8(nv, path,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (uint8_t)value);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker break;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case 2:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_uint16(nv, path,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (uint16_t)value);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker break;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case 4:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_uint32(nv, path,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (uint32_t)value);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker break;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker default:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_uint64(nv, path, value);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDTYPE_ASCII:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_string(nv, path, (char *)field);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker case FDTYPE_Enumeration:
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker value = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) memcpy((((uint8_t *)&value) + sizeof (value) -
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker def->payloadLen), field, def->payloadLen);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker value = BE_64(value);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker for (i = 0; i < def->enumCount; i++) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (def->enumTable[i].value == value) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_string(nv, path,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker def->enumTable[i].text);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* nothing matched above, use byte array */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_byte_array(nv, path, (uchar_t *)field,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker def->payloadLen);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic void
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerconvert_element(const uint8_t *data, const fru_regdef_t *def, char *ppath,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv, boolean_t from_iter)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int i;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker char *path;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* construct path */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if ((def->iterationCount == 0) &&
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (def->iterationType != FRU_NOT_ITERATED)) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker path = ppath;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker path = (char *)def->name;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* iteration, record and field */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (def->iterationCount) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int iterlen, n;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker uint8_t head, num;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_regdef_t newdef;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t **nv_elems;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker char num_str[32];
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker iterlen = (def->payloadLen - NUM_ITER_BYTES) /
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker def->iterationCount;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /*
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * make a new element definition to describe the components of
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker * the iteration.
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) memcpy(&newdef, def, sizeof (newdef));
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker newdef.iterationCount = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker newdef.payloadLen = iterlen;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* validate the content of the iteration control bytes */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if ((data[HEAD_ITER] >= def->iterationCount) ||
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (data[NUM_ITER] > def->iterationCount) ||
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (data[MAX_ITER] != def->iterationCount)) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* invalid. show all iterations */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker head = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker num = def->iterationCount;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker head = data[HEAD_ITER];
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker num = data[NUM_ITER];
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nv_elems = (nvlist_t **)malloc(num * sizeof (nvlist_t *));
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (!nv_elems)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker for (i = head, n = 0, data += sizeof (uint32_t); n < num;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker i = ((i + 1) % def->iterationCount), n++) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (nvlist_alloc(&nv_elems[n], NV_UNIQUE_NAME, 0) != 0)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) snprintf(num_str, sizeof (num_str), "%d", n);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker convert_element((data + i*iterlen), &newdef, num_str,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nv_elems[n], B_TRUE);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_nvlist_array(nv, path, nv_elems, num);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else if (def->dataType == FDTYPE_Record) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker const fru_regdef_t *component;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv_record;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (!from_iter) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (nvlist_alloc(&nv_record, NV_UNIQUE_NAME, 0) != 0) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nv_record = nv;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker for (i = 0; i < def->enumCount; i++,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker data += component->payloadLen) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker component = fru_reg_lookup_def_by_name(
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker def->enumTable[i].text);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker convert_element(data, component, "", nv_record,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker B_FALSE);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_nvlist(nv, path, nv_record);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker convert_field(data, def, path, nv);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic fru_regdef_t *
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickeralloc_unknown_fru_regdef(void)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_regdef_t *p;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p = malloc(sizeof (fru_regdef_t));
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (!p) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (NULL);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->version = REGDEF_VERSION;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->name = NULL;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->tagType = -1;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->tagDense = -1;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->payloadLen = -1;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->dataLength = -1;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->dataType = FDTYPE_ByteArray;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->dispType = FDISP_Hex;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->purgeable = FRU_WHICH_UNDEFINED;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->relocatable = FRU_WHICH_UNDEFINED;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->enumCount = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p-> enumTable = NULL;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->iterationCount = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->iterationType = FRU_NOT_ITERATED;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker p->exampleString = NULL;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (p);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic int
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerconvert_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int tag_type;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker size_t payload_length;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker const fru_regdef_t *def;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv = (nvlist_t *)args;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker char tagname[sizeof ("?_0123456789_0123456789")];
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker tag_type = get_tag_type(tag);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker payload_length = 0;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* check for unrecognized tag */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if ((tag_type == -1) ||
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker ((payload_length = get_payload_length(tag)) != length)) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_regdef_t *unknown;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown = alloc_unknown_fru_regdef();
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->payloadLen = length;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->dataLength = unknown->payloadLen;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (tag_type == -1) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) snprintf(tagname, sizeof (tagname),
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker "INVALID");
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) snprintf(tagname, sizeof (tagname),
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker "%s_%u_%u_%u", get_tagtype_str(tag_type),
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker get_tag_dense(tag), payload_length, length);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->name = tagname;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker convert_element(payload, unknown, "", nv, B_FALSE);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker free(unknown);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_regdef_t *unknown;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown = alloc_unknown_fru_regdef();
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->payloadLen = length;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->dataLength = unknown->payloadLen;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker get_tagtype_str(tag_type),
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->tagDense, payload_length);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker unknown->name = tagname;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker convert_element(payload, unknown, "", nv, B_FALSE);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker free(unknown);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker } else {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker convert_element(payload, def, "", nv, B_FALSE);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (FRU_SUCCESS);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic int
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerconvert_packets_in_segment(fru_seghdl_t segment, void *args)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker char *name;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int ret;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv = (nvlist_t *)args;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv_segment;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker ret = fru_get_segment_name(segment, &name);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (ret != FRU_SUCCESS) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (ret);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* create a new nvlist for each segment */
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim ret = nvlist_alloc(&nv_segment, NV_UNIQUE_NAME, 0);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (ret) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker free(name);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (FRU_FAILURE);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* convert the segment to an nvlist */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker ret = fru_for_each_packet(segment, convert_packet, nv_segment);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (ret != FRU_SUCCESS) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_free(nv_segment);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker free(name);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (ret);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker /* add the nvlist for this segment */
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) nvlist_add_nvlist(nv, name, nv_segment);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker free(name);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (FRU_SUCCESS);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerstatic int
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerconvert_fru(fru_nodehdl_t hdl, nvlist_t **nvlist)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int err;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t *nv;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_node_t fru_type;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (fru_get_node_type(hdl, &fru_type) != FRU_SUCCESS) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (-1);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (fru_type != FRU_NODE_CONTAINER) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (-1);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim err = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (err) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (err);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (fru_for_each_segment(hdl, convert_packets_in_segment, nv) !=
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker FRU_SUCCESS) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_free(nv);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (-1);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker *nvlist = nv;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (0);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerint
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panickerrawfru_to_nvlist(uint8_t *buffer, size_t bufsize, char *cont_type,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker nvlist_t **nvlist)
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker{
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_errno_t fru_err;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_nodehdl_t hdl;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker int err;
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) pthread_mutex_lock(&gLock);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_err = fru_open_data_source("raw", buffer, bufsize, cont_type,
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker NULL);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (fru_err != FRU_SUCCESS) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) pthread_mutex_unlock(&gLock);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (-1);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_err = fru_get_root(&hdl);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker if (fru_err != FRU_SUCCESS) {
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) pthread_mutex_unlock(&gLock);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (-1);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker }
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker err = convert_fru(hdl, nvlist);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker fru_close_data_source();
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker (void) pthread_mutex_unlock(&gLock);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker return (err);
6bbe05905a1c10a2703f95fb4912eb14b87f6670Sundeep Panicker}