xref: /illumos-gate/usr/src/lib/libfru/libfru/libfru.cc (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
524da5b34Srie  * Common Development and Distribution License (the "License").
624da5b34Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2224da5b34Srie  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * libfru is divided into the following modules:
287c478bd9Sstevel@tonic-gate  * 1) This file.  Support for the API and ties together all the sub-modules.
297c478bd9Sstevel@tonic-gate  * 2) The parser which parses the field_paths supplied by the user.
307c478bd9Sstevel@tonic-gate  * 3) The data_source sub-libraries which provide payloads(tags) and the tree
317c478bd9Sstevel@tonic-gate  *    structure of frus and locations.
327c478bd9Sstevel@tonic-gate  * 4) The PayloadReader which given a payload and a path definition can extract
337c478bd9Sstevel@tonic-gate  *    the exact field the user is looking for.
347c478bd9Sstevel@tonic-gate  * 5) The Registry which provides the definitions for all the Data Elements
357c478bd9Sstevel@tonic-gate  *    supported.
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * The basic algorithim for reading/updating fields is this:
387c478bd9Sstevel@tonic-gate  * 1) Parse the field_path given by the user.
397c478bd9Sstevel@tonic-gate  * 2) Using the registry determine which payloads this data MAY appear in.
407c478bd9Sstevel@tonic-gate  * 3) Figure out which tags of this type are in the container.
417c478bd9Sstevel@tonic-gate  * 4) Find the specific tag which contains the instance of this data the user
427c478bd9Sstevel@tonic-gate  *    requested.
437c478bd9Sstevel@tonic-gate  * 5) Get this tag from the data source and read it with the PayloadReader to
447c478bd9Sstevel@tonic-gate  *    read/write data.
457c478bd9Sstevel@tonic-gate  * 6) For UPDATES write this tag back to the data source.
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * This algorithim is altered only when dealing with "UNKNOWN" payloads where
487c478bd9Sstevel@tonic-gate  * it simplifies slightly.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <assert.h>
527c478bd9Sstevel@tonic-gate #include <string.h>
537c478bd9Sstevel@tonic-gate #include <stdlib.h>
547c478bd9Sstevel@tonic-gate #include <stdio.h>
557c478bd9Sstevel@tonic-gate #include <libintl.h>
567c478bd9Sstevel@tonic-gate #include <pthread.h>
577c478bd9Sstevel@tonic-gate #include <stdarg.h>
587c478bd9Sstevel@tonic-gate #include <dlfcn.h>
597c478bd9Sstevel@tonic-gate #include <alloca.h>
607c478bd9Sstevel@tonic-gate #include <limits.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include "libfru.h"
637c478bd9Sstevel@tonic-gate #include "libfrup.h"
647c478bd9Sstevel@tonic-gate #include "libfruds.h"
657c478bd9Sstevel@tonic-gate #include "Ancestor.h"
667c478bd9Sstevel@tonic-gate #include "libfrureg.h"
677c478bd9Sstevel@tonic-gate #include "Parser.h"
687c478bd9Sstevel@tonic-gate #include "PayloadReader.h"
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #define	DATA_SOURCE_OBJ_NAME "data_source"
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #define	ENCRYPTION_LIB_NAME "libfrucrypt.so.1"
737c478bd9Sstevel@tonic-gate #define	FRU_ENCRYPT_FUNC_NAME "fru_encrypt_func"
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #define	UNKNOWN_PATH "UNKNOWN"
767c478bd9Sstevel@tonic-gate #define	IS_UNKNOWN_PATH(path) \
777c478bd9Sstevel@tonic-gate ((strcmp(path, "/UNKNOWN") == 0) || (strcmp(path, "UNKNOWN") == 0))
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #define	NODEHDL_TO_TREEHDL(nodehdl) (fru_treehdl_t)nodehdl
807c478bd9Sstevel@tonic-gate #define	TREEHDL_TO_NODEHDL(treehdl) (fru_nodehdl_t)treehdl
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /* ========================================================================= */
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * Define a hash of rwlocks for each container.
857c478bd9Sstevel@tonic-gate  */
867c478bd9Sstevel@tonic-gate struct cont_lock
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate 	fru_nodehdl_t handle;
897c478bd9Sstevel@tonic-gate 	pthread_rwlock_t lock;
907c478bd9Sstevel@tonic-gate 	struct cont_lock *next;
917c478bd9Sstevel@tonic-gate };
927c478bd9Sstevel@tonic-gate typedef struct cont_lock cont_lock_t;
937c478bd9Sstevel@tonic-gate 
9424da5b34Srie fru_encrypt_func_t encrypt_func;
9524da5b34Srie 
967c478bd9Sstevel@tonic-gate #define	CONT_LOCK_HASH_NUM 128
977c478bd9Sstevel@tonic-gate cont_lock_t *cont_lock_hash[CONT_LOCK_HASH_NUM];
987c478bd9Sstevel@tonic-gate pthread_mutex_t cont_lock_hash_lock;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate typedef enum { WRITE_LOCK, READ_LOCK } lock_mode_t;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate  * These control the Data sources available.
1047c478bd9Sstevel@tonic-gate  */
1057c478bd9Sstevel@tonic-gate static pthread_mutex_t ds_lock;
1067c478bd9Sstevel@tonic-gate static fru_datasource_t *data_source = NULL;
1077c478bd9Sstevel@tonic-gate static void *ds_lib = NULL;
1087c478bd9Sstevel@tonic-gate static int ds_lib_ref_cnt = 0;
1097c478bd9Sstevel@tonic-gate static char *ds_lib_name = NULL;
1107c478bd9Sstevel@tonic-gate 
11135551380Skmohan #define	FRU_NORESPONSE_RETRY 500
11235551380Skmohan 
11335551380Skmohan #define RETRY(expr) 						\
11435551380Skmohan 	{ for (int loop = 0; loop < FRU_NORESPONSE_RETRY &&	\
11535551380Skmohan 		(expr) == FRU_NORESPONSE; loop++) ;		\
116*1da57d55SToomas Soome 	}
11735551380Skmohan 
1187c478bd9Sstevel@tonic-gate /* ========================================================================= */
1197c478bd9Sstevel@tonic-gate static const char *fru_errmsg[] =
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	"Success",
1227c478bd9Sstevel@tonic-gate 	"Node not found",
1237c478bd9Sstevel@tonic-gate 	"IO error",
1247c478bd9Sstevel@tonic-gate 	"No registry definition for this element",
1257c478bd9Sstevel@tonic-gate 	"Not container",
1267c478bd9Sstevel@tonic-gate 	"Invalid handle",
1277c478bd9Sstevel@tonic-gate 	"Invalid Segment",
1287c478bd9Sstevel@tonic-gate 	"Invalid Path",
1297c478bd9Sstevel@tonic-gate 	"Invalid Element",
1307c478bd9Sstevel@tonic-gate 	"Invalid Data size (does not match registry definition)",
1317c478bd9Sstevel@tonic-gate 	"Duplicate Segment",
1327c478bd9Sstevel@tonic-gate 	"Not Field",
1337c478bd9Sstevel@tonic-gate 	"No space available",
1347c478bd9Sstevel@tonic-gate 	"Data could not be found",
1357c478bd9Sstevel@tonic-gate 	"Iteration full",
1367c478bd9Sstevel@tonic-gate 	"Invalid Permisions",
1377c478bd9Sstevel@tonic-gate 	"Feature not Supported",
1387c478bd9Sstevel@tonic-gate 	"Element is not Tagged",
1397c478bd9Sstevel@tonic-gate 	"Failed to read container device",
1407c478bd9Sstevel@tonic-gate 	"Segment Corrupt",
1417c478bd9Sstevel@tonic-gate 	"Data Corrupt",
1427c478bd9Sstevel@tonic-gate 	"General LIBFRU FAILURE",
1437c478bd9Sstevel@tonic-gate 	"Walk terminated",
14435551380Skmohan 	"FRU No response",
1457c478bd9Sstevel@tonic-gate 	"Unknown error"
1467c478bd9Sstevel@tonic-gate };
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate fru_errno_t
fru_encryption_supported(void)1497c478bd9Sstevel@tonic-gate fru_encryption_supported(void)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate 	if (encrypt_func == NULL)
1527c478bd9Sstevel@tonic-gate 		return (FRU_NOTSUP);
1537c478bd9Sstevel@tonic-gate 	else
1547c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate extern "C" {
1587c478bd9Sstevel@tonic-gate void
init_libfru(void)1597c478bd9Sstevel@tonic-gate init_libfru(void)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	// attempt to find the encryption library.
1627c478bd9Sstevel@tonic-gate 	void *crypt_lib = NULL;
1637c478bd9Sstevel@tonic-gate 	encrypt_func = NULL;
1647c478bd9Sstevel@tonic-gate 	crypt_lib = dlopen(ENCRYPTION_LIB_NAME, RTLD_LAZY);
1657c478bd9Sstevel@tonic-gate 	if (crypt_lib != NULL) {
1667c478bd9Sstevel@tonic-gate 		encrypt_func = (fru_encrypt_func_t)dlsym(crypt_lib,
1677c478bd9Sstevel@tonic-gate 						FRU_ENCRYPT_FUNC_NAME);
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate #pragma init(init_libfru)
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /* ========================================================================= */
1747c478bd9Sstevel@tonic-gate static void
add_cont_lock(cont_lock_t * lock)1757c478bd9Sstevel@tonic-gate add_cont_lock(cont_lock_t *lock)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	cont_lock_t *prev = NULL;
1787c478bd9Sstevel@tonic-gate 	int hash_bucket = lock->handle % CONT_LOCK_HASH_NUM;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	/* insert at tail */
1817c478bd9Sstevel@tonic-gate 	if (cont_lock_hash[hash_bucket] == NULL) {
1827c478bd9Sstevel@tonic-gate 		cont_lock_hash[hash_bucket] = lock;
1837c478bd9Sstevel@tonic-gate 	} else {
1847c478bd9Sstevel@tonic-gate 		cont_lock_t *prev = cont_lock_hash[hash_bucket];
1857c478bd9Sstevel@tonic-gate 		while (prev->next != NULL) {
1867c478bd9Sstevel@tonic-gate 			prev = prev->next;
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 		prev->next = lock;
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate /* ========================================================================= */
1937c478bd9Sstevel@tonic-gate static cont_lock_t *
find_cont_lock(fru_nodehdl_t handle)1947c478bd9Sstevel@tonic-gate find_cont_lock(fru_nodehdl_t handle)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 	int hash_bucket = handle % CONT_LOCK_HASH_NUM;
1977c478bd9Sstevel@tonic-gate 	cont_lock_t *which = cont_lock_hash[hash_bucket];
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	while (which != NULL) {
2007c478bd9Sstevel@tonic-gate 		if (which->handle == handle) {
2017c478bd9Sstevel@tonic-gate 			break;
2027c478bd9Sstevel@tonic-gate 		}
2037c478bd9Sstevel@tonic-gate 		which = which->next;
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 	return (which);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /* ========================================================================= */
2097c478bd9Sstevel@tonic-gate static cont_lock_t *
alloc_cont_lock(fru_nodehdl_t handle)2107c478bd9Sstevel@tonic-gate alloc_cont_lock(fru_nodehdl_t handle)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate 	cont_lock_t *lock = (cont_lock_t *)malloc(sizeof (cont_lock_t));
2137c478bd9Sstevel@tonic-gate 	if (lock == NULL) {
2147c478bd9Sstevel@tonic-gate 		return (NULL);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 	lock->handle = handle;
2177c478bd9Sstevel@tonic-gate 	if (pthread_rwlock_init(&(lock->lock), NULL) != 0) {
2187c478bd9Sstevel@tonic-gate 		free(lock);
2197c478bd9Sstevel@tonic-gate 		return (NULL);
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 	lock->next = NULL;
2227c478bd9Sstevel@tonic-gate 	return (lock);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /* ========================================================================= */
2267c478bd9Sstevel@tonic-gate static fru_errno_t
lock_container(lock_mode_t mode,fru_nodehdl_t handle)2277c478bd9Sstevel@tonic-gate lock_container(lock_mode_t mode, fru_nodehdl_t handle)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	cont_lock_t *which = NULL;
2307c478bd9Sstevel@tonic-gate 	int hash_bucket = 0;
2317c478bd9Sstevel@tonic-gate 	int lock_rc;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&cont_lock_hash_lock);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	which = find_cont_lock(handle);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/* if not found add to hash */
2387c478bd9Sstevel@tonic-gate 	if (which == NULL) {
2397c478bd9Sstevel@tonic-gate 		if ((which = alloc_cont_lock(handle)) == NULL) {
2407c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&cont_lock_hash_lock);
2417c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 		add_cont_lock(which);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/* execute lock */
2477c478bd9Sstevel@tonic-gate 	lock_rc = 0;
2487c478bd9Sstevel@tonic-gate 	switch (mode) {
2497c478bd9Sstevel@tonic-gate 		case READ_LOCK:
2507c478bd9Sstevel@tonic-gate 			lock_rc = pthread_rwlock_rdlock(&(which->lock));
2517c478bd9Sstevel@tonic-gate 			break;
2527c478bd9Sstevel@tonic-gate 		case WRITE_LOCK:
2537c478bd9Sstevel@tonic-gate 			lock_rc = pthread_rwlock_wrlock(&(which->lock));
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&cont_lock_hash_lock);
2587c478bd9Sstevel@tonic-gate 	if (lock_rc != 0) {
2597c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate /* ========================================================================= */
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate  * Macro to make checking unlock_conatiner error code easier
2677c478bd9Sstevel@tonic-gate  */
2687c478bd9Sstevel@tonic-gate #define	CHK_UNLOCK_CONTAINER(handle) \
2697c478bd9Sstevel@tonic-gate 	if (unlock_container(handle) != FRU_SUCCESS) { \
2707c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE); \
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate static fru_errno_t
unlock_container(fru_nodehdl_t handle)2737c478bd9Sstevel@tonic-gate unlock_container(fru_nodehdl_t handle)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	cont_lock_t *which = NULL;
2767c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&cont_lock_hash_lock);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	which = find_cont_lock(handle);
2797c478bd9Sstevel@tonic-gate 	if (which == NULL) {
2807c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&cont_lock_hash_lock);
2817c478bd9Sstevel@tonic-gate 		return (FRU_NODENOTFOUND);
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	if (pthread_rwlock_unlock(&(which->lock)) != 0) {
2857c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&cont_lock_hash_lock);
2867c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&cont_lock_hash_lock);
2907c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate /* ========================================================================= */
2947c478bd9Sstevel@tonic-gate static fru_errno_t
clear_cont_locks(void)2957c478bd9Sstevel@tonic-gate clear_cont_locks(void)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&cont_lock_hash_lock);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	// for each bucket
3007c478bd9Sstevel@tonic-gate 	for (int i = 0; i < CONT_LOCK_HASH_NUM; i++) {
3017c478bd9Sstevel@tonic-gate 		// free all the locks
3027c478bd9Sstevel@tonic-gate 		cont_lock_t *cur = cont_lock_hash[i];
3037c478bd9Sstevel@tonic-gate 		while (cur != NULL) {
3047c478bd9Sstevel@tonic-gate 			cont_lock_t *tmp = cur;
3057c478bd9Sstevel@tonic-gate 			cur = cur->next;
3067c478bd9Sstevel@tonic-gate 			pthread_rwlock_destroy(&(tmp->lock));
3077c478bd9Sstevel@tonic-gate 			free(tmp);
3087c478bd9Sstevel@tonic-gate 		}
3097c478bd9Sstevel@tonic-gate 		cont_lock_hash[i] = NULL;
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&cont_lock_hash_lock);
3137c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /* ========================================================================= */
3187c478bd9Sstevel@tonic-gate /* VARARGS */
3197c478bd9Sstevel@tonic-gate fru_errno_t
fru_open_data_source(const char * name,...)3207c478bd9Sstevel@tonic-gate fru_open_data_source(const char *name, ...)
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	va_list args;
3257c478bd9Sstevel@tonic-gate 	int num_args = 0;
3267c478bd9Sstevel@tonic-gate 	char **init_args = NULL;
3277c478bd9Sstevel@tonic-gate 	char *tmp;
3287c478bd9Sstevel@tonic-gate 	int i = 0;
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	char ds_name[PATH_MAX];
3317c478bd9Sstevel@tonic-gate 	fru_datasource_t *ds = NULL;
3327c478bd9Sstevel@tonic-gate 	void *tmp_lib = NULL;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&ds_lock);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	if ((ds_lib_name != NULL) && (data_source != NULL)) {
3377c478bd9Sstevel@tonic-gate 		// we already have a DS assigned.
3387c478bd9Sstevel@tonic-gate 		if ((strcmp(ds_lib_name, name) == 0)) {
3397c478bd9Sstevel@tonic-gate 			// user wants to open the same one... ok.
3407c478bd9Sstevel@tonic-gate 			ds_lib_ref_cnt++;
3417c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&ds_lock);
3427c478bd9Sstevel@tonic-gate 			return (FRU_SUCCESS);
3437c478bd9Sstevel@tonic-gate 		} else {
3447c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&ds_lock);
3457c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
3467c478bd9Sstevel@tonic-gate 		}
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	snprintf(ds_name, sizeof (ds_name), "libfru%s.so.%d",
3507c478bd9Sstevel@tonic-gate 				name, LIBFRU_DS_VER);
3517c478bd9Sstevel@tonic-gate 	tmp_lib = dlopen(ds_name, RTLD_LAZY);
3527c478bd9Sstevel@tonic-gate 	if (tmp_lib == NULL) {
3537c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&ds_lock);
3547c478bd9Sstevel@tonic-gate 		return (FRU_NOTSUP);
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 	ds = (fru_datasource_t *)dlsym(tmp_lib,
3577c478bd9Sstevel@tonic-gate 				DATA_SOURCE_OBJ_NAME);
3587c478bd9Sstevel@tonic-gate 	if (ds == NULL) {
3597c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&ds_lock);
3607c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	va_start(args, name);
3647c478bd9Sstevel@tonic-gate 	tmp = va_arg(args, char *);
3657c478bd9Sstevel@tonic-gate 	while (tmp != NULL) {
3667c478bd9Sstevel@tonic-gate 		num_args++;
3677c478bd9Sstevel@tonic-gate 		tmp = va_arg(args, char *);
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 	va_end(args);
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	init_args = (char **)malloc(sizeof (char *) * num_args);
3727c478bd9Sstevel@tonic-gate 	if (init_args == NULL) {
3737c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&ds_lock);
3747c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	va_start(args, name);
3787c478bd9Sstevel@tonic-gate 	for (tmp = va_arg(args, char *), i = 0;
3797c478bd9Sstevel@tonic-gate 		(tmp != NULL) && (i < num_args);
3807c478bd9Sstevel@tonic-gate 			tmp = va_arg(args, char *), i++) {
3817c478bd9Sstevel@tonic-gate 		init_args[i] = tmp;
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate 	va_end(args);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	if ((err = ds->initialize(num_args, init_args)) == FRU_SUCCESS) {
3867c478bd9Sstevel@tonic-gate 		// don't switch unless the source connects ok.
3877c478bd9Sstevel@tonic-gate 		ds_lib = tmp_lib;
3887c478bd9Sstevel@tonic-gate 		data_source = ds;
3897c478bd9Sstevel@tonic-gate 		ds_lib_name = strdup(name);
3907c478bd9Sstevel@tonic-gate 		ds_lib_ref_cnt++;
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	free(init_args);
3947c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&ds_lock);
3957c478bd9Sstevel@tonic-gate 	return (err);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate /* ========================================================================= */
4007c478bd9Sstevel@tonic-gate fru_errno_t
fru_close_data_source(void)4017c478bd9Sstevel@tonic-gate fru_close_data_source(void)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	if (ds_lib_ref_cnt == 0) {
4067c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&ds_lock);
4107c478bd9Sstevel@tonic-gate 	if ((--ds_lib_ref_cnt) == 0) {
4117c478bd9Sstevel@tonic-gate 		/* don't check err code here */
4127c478bd9Sstevel@tonic-gate 		err = data_source->shutdown();
4137c478bd9Sstevel@tonic-gate 		/* continue to clean up libfru and return the err at the end */
4147c478bd9Sstevel@tonic-gate 		clear_cont_locks();
4157c478bd9Sstevel@tonic-gate 		dlclose(ds_lib);
4167c478bd9Sstevel@tonic-gate 		ds_lib = NULL;
4177c478bd9Sstevel@tonic-gate 		free(ds_lib_name);
4187c478bd9Sstevel@tonic-gate 		ds_lib_name = NULL;
4197c478bd9Sstevel@tonic-gate 		data_source = NULL;
4207c478bd9Sstevel@tonic-gate 	}
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&ds_lock);
4237c478bd9Sstevel@tonic-gate 	return (err);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate /* ========================================================================= */
4277c478bd9Sstevel@tonic-gate int
segment_is_encrypted(fru_nodehdl_t container,const char * seg_name)4287c478bd9Sstevel@tonic-gate segment_is_encrypted(fru_nodehdl_t container, const char *seg_name)
4297c478bd9Sstevel@tonic-gate {
43035551380Skmohan 	fru_errno_t err = FRU_SUCCESS;
4317c478bd9Sstevel@tonic-gate 	fru_segdef_t segdef;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
4347c478bd9Sstevel@tonic-gate 		return (0);
4357c478bd9Sstevel@tonic-gate 	}
43635551380Skmohan 
43735551380Skmohan 	RETRY(err = data_source->get_seg_def(NODEHDL_TO_TREEHDL(container),
43835551380Skmohan 							seg_name, &segdef))
43935551380Skmohan 
44035551380Skmohan 	if (err != FRU_SUCCESS) {
4417c478bd9Sstevel@tonic-gate 		return (0);
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	return (segdef.desc.field.encrypted == 1);
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate /* ========================================================================= */
4487c478bd9Sstevel@tonic-gate static fru_errno_t
get_seg_list_from_ds(fru_nodehdl_t node,fru_strlist_t * list)4497c478bd9Sstevel@tonic-gate get_seg_list_from_ds(fru_nodehdl_t node, fru_strlist_t *list)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
4527c478bd9Sstevel@tonic-gate 	fru_strlist_t raw_list;
4537c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
4547c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/* get a list of all segments */
45835551380Skmohan 	RETRY(err = data_source->get_seg_list(NODEHDL_TO_TREEHDL(node),
45935551380Skmohan 								&raw_list))
46035551380Skmohan 
46135551380Skmohan 	if (err != FRU_SUCCESS) {
4627c478bd9Sstevel@tonic-gate 		return (err);
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	/* leave out the encrypted segments if necessary */
4667c478bd9Sstevel@tonic-gate 	list->num = 0;
4677c478bd9Sstevel@tonic-gate 	list->strs = (char **)malloc(sizeof (*(list->strs)) * raw_list.num);
4687c478bd9Sstevel@tonic-gate 	if (list->strs == NULL) {
4697c478bd9Sstevel@tonic-gate 		fru_destroy_strlist(&raw_list);
4707c478bd9Sstevel@tonic-gate 		return (err);
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 	for (int i = 0; i < raw_list.num; i++) {
4737c478bd9Sstevel@tonic-gate 		if (segment_is_encrypted(node, raw_list.strs[i])) {
4747c478bd9Sstevel@tonic-gate 			if (fru_encryption_supported() == FRU_SUCCESS) {
4757c478bd9Sstevel@tonic-gate 				list->strs[list->num]
4767c478bd9Sstevel@tonic-gate 					= strdup(raw_list.strs[i]);
4777c478bd9Sstevel@tonic-gate 				list->num++;
4787c478bd9Sstevel@tonic-gate 			} // else leave it out.
4797c478bd9Sstevel@tonic-gate 		} else {
4807c478bd9Sstevel@tonic-gate 			list->strs[list->num] = strdup(raw_list.strs[i]);
4817c478bd9Sstevel@tonic-gate 			list->num++;
4827c478bd9Sstevel@tonic-gate 		}
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	fru_destroy_strlist(&raw_list);
4867c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate /* ========================================================================= */
4917c478bd9Sstevel@tonic-gate const char *
fru_strerror(fru_errno_t errnum)4927c478bd9Sstevel@tonic-gate fru_strerror(fru_errno_t errnum)
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate 	if ((errnum < (sizeof (fru_errmsg)/sizeof (*fru_errmsg))) &&
4957c478bd9Sstevel@tonic-gate 			(errnum >= 0)) {
4967c478bd9Sstevel@tonic-gate 		return (gettext(fru_errmsg[errnum]));
4977c478bd9Sstevel@tonic-gate 	}
4987c478bd9Sstevel@tonic-gate 	return (gettext
4997c478bd9Sstevel@tonic-gate 		(fru_errmsg[(sizeof (fru_errmsg)/sizeof (*fru_errmsg))]));
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate /* ========================================================================= */
5037c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_root(fru_nodehdl_t * handle)5047c478bd9Sstevel@tonic-gate fru_get_root(fru_nodehdl_t *handle)
5057c478bd9Sstevel@tonic-gate {
5067c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
5077c478bd9Sstevel@tonic-gate 	fru_treehdl_t tr_root;
5087c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
5097c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
51235551380Skmohan 	RETRY(err = data_source->get_root(&tr_root))
5137c478bd9Sstevel@tonic-gate 	if (err == FRU_SUCCESS) {
5147c478bd9Sstevel@tonic-gate 		*handle = TREEHDL_TO_NODEHDL(tr_root);
5157c478bd9Sstevel@tonic-gate 	}
5167c478bd9Sstevel@tonic-gate 	return (err);
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate /* ========================================================================= */
5207c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_child(fru_nodehdl_t handle,fru_nodehdl_t * child)5217c478bd9Sstevel@tonic-gate fru_get_child(fru_nodehdl_t handle, fru_nodehdl_t *child)
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
5247c478bd9Sstevel@tonic-gate 	fru_treehdl_t tr_child;
5257c478bd9Sstevel@tonic-gate 	fru_node_t type;
5267c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
5277c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
5287c478bd9Sstevel@tonic-gate 	}
52935551380Skmohan 
53035551380Skmohan 	RETRY(err = data_source->get_child(NODEHDL_TO_TREEHDL(handle),
53135551380Skmohan 								&tr_child))
53235551380Skmohan 	if (err != FRU_SUCCESS) {
5337c478bd9Sstevel@tonic-gate 		return (err);
5347c478bd9Sstevel@tonic-gate 	}
53535551380Skmohan 
53635551380Skmohan 	RETRY(err = data_source->get_node_type(tr_child, &type))
53735551380Skmohan 
53835551380Skmohan 	if (err != FRU_SUCCESS) {
5397c478bd9Sstevel@tonic-gate 		return (err);
5407c478bd9Sstevel@tonic-gate 	}
5417c478bd9Sstevel@tonic-gate 	if ((type == FRU_NODE_LOCATION) ||
5427c478bd9Sstevel@tonic-gate 		(type == FRU_NODE_FRU) ||
5437c478bd9Sstevel@tonic-gate 		(type == FRU_NODE_CONTAINER)) {
5447c478bd9Sstevel@tonic-gate 		*child = TREEHDL_TO_NODEHDL(tr_child);
5457c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate /*
5497c478bd9Sstevel@tonic-gate  * if the child is not valid try and find a peer of the child which is
5507c478bd9Sstevel@tonic-gate  * valid
5517c478bd9Sstevel@tonic-gate  */
5527c478bd9Sstevel@tonic-gate 	do {
55335551380Skmohan 		RETRY(err = data_source->get_peer(tr_child, &tr_child))
55435551380Skmohan 		if (err != FRU_SUCCESS) {
5557c478bd9Sstevel@tonic-gate 			return (err);
5567c478bd9Sstevel@tonic-gate 		}
557*1da57d55SToomas Soome 
55835551380Skmohan 		RETRY(err = data_source->get_node_type(tr_child, &type))
55935551380Skmohan 		if (err != FRU_SUCCESS) {
5607c478bd9Sstevel@tonic-gate 			return (err);
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 		if ((type == FRU_NODE_LOCATION) ||
5637c478bd9Sstevel@tonic-gate 			(type == FRU_NODE_FRU) ||
5647c478bd9Sstevel@tonic-gate 			(type == FRU_NODE_CONTAINER)) {
5657c478bd9Sstevel@tonic-gate 			*child = TREEHDL_TO_NODEHDL(tr_child);
5667c478bd9Sstevel@tonic-gate 			return (FRU_SUCCESS);
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 	} while (1);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate /* ========================================================================= */
5727c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_peer(fru_nodehdl_t handle,fru_nodehdl_t * peer)5737c478bd9Sstevel@tonic-gate fru_get_peer(fru_nodehdl_t handle, fru_nodehdl_t *peer)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
5767c478bd9Sstevel@tonic-gate 	fru_treehdl_t tr_peer = NODEHDL_TO_TREEHDL(handle);
5777c478bd9Sstevel@tonic-gate 	fru_node_t type;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
5807c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	do {
58435551380Skmohan 		RETRY(err = data_source->get_peer(tr_peer, &tr_peer))
58535551380Skmohan 
58635551380Skmohan 		if (err != FRU_SUCCESS) {
5877c478bd9Sstevel@tonic-gate 			return (err);
5887c478bd9Sstevel@tonic-gate 		}
58935551380Skmohan 
59035551380Skmohan 		RETRY(err = data_source->get_node_type(tr_peer, &type))
59135551380Skmohan 		if (err != FRU_SUCCESS) {
5927c478bd9Sstevel@tonic-gate 			return (err);
5937c478bd9Sstevel@tonic-gate 		}
5947c478bd9Sstevel@tonic-gate 		if ((type == FRU_NODE_LOCATION) ||
5957c478bd9Sstevel@tonic-gate 			(type == FRU_NODE_FRU) ||
5967c478bd9Sstevel@tonic-gate 			(type == FRU_NODE_CONTAINER)) {
5977c478bd9Sstevel@tonic-gate 			*peer = TREEHDL_TO_NODEHDL(tr_peer);
5987c478bd9Sstevel@tonic-gate 			return (FRU_SUCCESS);
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 	} while (1);
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate /* ========================================================================= */
6037c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_parent(fru_nodehdl_t handle,fru_nodehdl_t * parent)6047c478bd9Sstevel@tonic-gate fru_get_parent(fru_nodehdl_t handle, fru_nodehdl_t *parent)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
6077c478bd9Sstevel@tonic-gate 	fru_treehdl_t tr_parent;
6087c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
6097c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
6107c478bd9Sstevel@tonic-gate 	}
61135551380Skmohan 
61235551380Skmohan 	RETRY(err = data_source->get_parent(NODEHDL_TO_TREEHDL(handle),
61335551380Skmohan 								&tr_parent))
6147c478bd9Sstevel@tonic-gate 	if (err == FRU_SUCCESS) {
6157c478bd9Sstevel@tonic-gate 		*parent = TREEHDL_TO_NODEHDL(tr_parent);
6167c478bd9Sstevel@tonic-gate 	}
6177c478bd9Sstevel@tonic-gate 	return (err);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate /* ========================================================================= */
6227c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_name_from_hdl(fru_nodehdl_t handle,char ** name)6237c478bd9Sstevel@tonic-gate fru_get_name_from_hdl(fru_nodehdl_t handle, char **name)
6247c478bd9Sstevel@tonic-gate {
62535551380Skmohan 	fru_errno_t	err = FRU_SUCCESS;
62635551380Skmohan 
6277c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
6287c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
6297c478bd9Sstevel@tonic-gate 	}
63035551380Skmohan 
63135551380Skmohan 	RETRY(err = data_source->get_name_from_hdl(NODEHDL_TO_TREEHDL(handle),
63235551380Skmohan 									name))
63335551380Skmohan 	return (err);
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate /* ========================================================================= */
6377c478bd9Sstevel@tonic-gate /*
6387c478bd9Sstevel@tonic-gate  * Project-private interface
6397c478bd9Sstevel@tonic-gate  *
6407c478bd9Sstevel@tonic-gate  * Apply process_node() to each node in the tree rooted at "node".
6417c478bd9Sstevel@tonic-gate  *
6427c478bd9Sstevel@tonic-gate  * process_node() has available the handle, path (in the subtree from the root
6437c478bd9Sstevel@tonic-gate  * "node" passed to fru_walk_tree()), and name of the node to which it is
6447c478bd9Sstevel@tonic-gate  * applied, as well as any arguments provided via the generic pointer "args".
6457c478bd9Sstevel@tonic-gate  * process_node() also takes a pointer to an end_node() function pointer
6467c478bd9Sstevel@tonic-gate  * argument and a pointer to a generic pointer "end_args" argument.  If
6477c478bd9Sstevel@tonic-gate  * non-null, end_node() is called after the node and its children have been
6487c478bd9Sstevel@tonic-gate  * processed, but before the node's siblings are visited.
6497c478bd9Sstevel@tonic-gate  */
6507c478bd9Sstevel@tonic-gate extern "C" fru_errno_t
fru_walk_tree(fru_nodehdl_t node,const char * prior_path,fru_errno_t (* process_node)(fru_nodehdl_t node,const char * path,const char * name,void * args,end_node_fp_t * end_node,void ** end_args),void * args)6517c478bd9Sstevel@tonic-gate fru_walk_tree(fru_nodehdl_t node, const char *prior_path,
6527c478bd9Sstevel@tonic-gate 		fru_errno_t (*process_node)(fru_nodehdl_t node,
6537c478bd9Sstevel@tonic-gate 						const char *path,
6547c478bd9Sstevel@tonic-gate 						const char *name, void *args,
6557c478bd9Sstevel@tonic-gate 						end_node_fp_t *end_node,
6567c478bd9Sstevel@tonic-gate 						void **end_args),
6577c478bd9Sstevel@tonic-gate 		void *args)
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate 	void		*end_args = NULL;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	char		*name = NULL, *path;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	int		prior_length;
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	fru_errno_t	status;
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	fru_nodehdl_t	next;
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	end_node_fp_t	end_node = NULL;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	/* Build node's path */
6737c478bd9Sstevel@tonic-gate 	if ((status = fru_get_name_from_hdl(node, &name)) != FRU_SUCCESS)
6747c478bd9Sstevel@tonic-gate 		return (status);
6757c478bd9Sstevel@tonic-gate 	else if (name == NULL)
6767c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	prior_length = strlen(prior_path);
6797c478bd9Sstevel@tonic-gate 	path = (char *)alloca(prior_length + sizeof ("/") + strlen(name));
6807c478bd9Sstevel@tonic-gate 	(void) sprintf(path, "%s/%s", prior_path, name);
6817c478bd9Sstevel@tonic-gate 	free(name);
6827c478bd9Sstevel@tonic-gate 	name = path + prior_length + 1;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	/* Process node */
6867c478bd9Sstevel@tonic-gate 	assert(process_node != NULL);
6877c478bd9Sstevel@tonic-gate 	if ((status = process_node(node, path, name, args,
6887c478bd9Sstevel@tonic-gate 					&end_node, &end_args))
6897c478bd9Sstevel@tonic-gate 	    != FRU_SUCCESS) {
6907c478bd9Sstevel@tonic-gate 		if (end_node) end_node(node, path, name, end_args);
6917c478bd9Sstevel@tonic-gate 		return (status);
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/* Process children */
6967c478bd9Sstevel@tonic-gate 	if ((status = fru_get_child(node, &next)) == FRU_SUCCESS)
6977c478bd9Sstevel@tonic-gate 		status = fru_walk_tree(next, path, process_node, args);
6987c478bd9Sstevel@tonic-gate 	else if (status == FRU_NODENOTFOUND)
6997c478bd9Sstevel@tonic-gate 		status = FRU_SUCCESS;
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	/* "Close" node */
7027c478bd9Sstevel@tonic-gate 	if (end_node) end_node(node, path, name, end_args);
7037c478bd9Sstevel@tonic-gate 	if (status != FRU_SUCCESS)
7047c478bd9Sstevel@tonic-gate 		return (status);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	/* Process siblings */
7077c478bd9Sstevel@tonic-gate 	if ((status = fru_get_peer(node, &next)) == FRU_SUCCESS)
7087c478bd9Sstevel@tonic-gate 		status = fru_walk_tree(next, prior_path, process_node, args);
7097c478bd9Sstevel@tonic-gate 	else if (status == FRU_NODENOTFOUND)
7107c478bd9Sstevel@tonic-gate 		status = FRU_SUCCESS;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	return (status);
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate /* ========================================================================= */
7167c478bd9Sstevel@tonic-gate /*
7177c478bd9Sstevel@tonic-gate  * Project-private interface
7187c478bd9Sstevel@tonic-gate  *
7197c478bd9Sstevel@tonic-gate  * Return true if "searchpath" equals "path" or is a tail of "path" and
7207c478bd9Sstevel@tonic-gate  * begins at a component name within "path"
7217c478bd9Sstevel@tonic-gate  */
7227c478bd9Sstevel@tonic-gate int
fru_pathmatch(const char * path,const char * searchpath)7237c478bd9Sstevel@tonic-gate fru_pathmatch(const char *path, const char *searchpath)
7247c478bd9Sstevel@tonic-gate {
7257c478bd9Sstevel@tonic-gate 	const char	*match;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	if (((match = strstr(path, searchpath)) != NULL) &&
7287c478bd9Sstevel@tonic-gate 	    ((match + strlen(searchpath)) == (path + strlen(path))) &&
7297c478bd9Sstevel@tonic-gate 	    ((match == path) || (*(match - 1) == '/')))
7307c478bd9Sstevel@tonic-gate 		return (1);
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	return (0);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate /* ========================================================================= */
7367c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_node_type(fru_nodehdl_t handle,fru_node_t * type)7377c478bd9Sstevel@tonic-gate fru_get_node_type(fru_nodehdl_t handle, fru_node_t *type)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
7407c478bd9Sstevel@tonic-gate 	fru_node_t tmp;
7417c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
7427c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
7437c478bd9Sstevel@tonic-gate 	}
744*1da57d55SToomas Soome 
74535551380Skmohan 	RETRY(err = data_source->get_node_type(NODEHDL_TO_TREEHDL(handle),
74635551380Skmohan 								&tmp))
74735551380Skmohan 	if (err == FRU_SUCCESS) {
74835551380Skmohan 		*type = tmp;
7497c478bd9Sstevel@tonic-gate 	}
75035551380Skmohan 	return (err);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate /* ========================================================================= */
7547c478bd9Sstevel@tonic-gate static fru_errno_t
is_container(fru_nodehdl_t handle)7557c478bd9Sstevel@tonic-gate is_container(fru_nodehdl_t handle)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
7587c478bd9Sstevel@tonic-gate 	fru_node_t type;
7597c478bd9Sstevel@tonic-gate 	if ((err = fru_get_node_type(handle, &type)) != FRU_SUCCESS) {
7607c478bd9Sstevel@tonic-gate 		return (err);
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate 	if (type == FRU_NODE_CONTAINER) {
7637c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
7647c478bd9Sstevel@tonic-gate 	}
7657c478bd9Sstevel@tonic-gate 	return (FRU_NOTCONTAINER);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate /* ========================================================================= */
7697c478bd9Sstevel@tonic-gate fru_errno_t
fru_destroy_enum(fru_enum_t * e)7707c478bd9Sstevel@tonic-gate fru_destroy_enum(fru_enum_t *e)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate 	if (e == NULL) {
7737c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate 	if (e->text != NULL)
7767c478bd9Sstevel@tonic-gate 		free(e->text);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate /* ========================================================================= */
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * NOTE: does not free list.  This is allocated by the user and should be
7847c478bd9Sstevel@tonic-gate  * deallocated by the user.
7857c478bd9Sstevel@tonic-gate  */
7867c478bd9Sstevel@tonic-gate fru_errno_t
fru_destroy_strlist(fru_strlist_t * list)7877c478bd9Sstevel@tonic-gate fru_destroy_strlist(fru_strlist_t *list)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate 	if (list == NULL) {
7907c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
7917c478bd9Sstevel@tonic-gate 	}
7927c478bd9Sstevel@tonic-gate 	if (list->strs != NULL) {
7937c478bd9Sstevel@tonic-gate 		for (int i = 0; i < list->num; i++) {
7947c478bd9Sstevel@tonic-gate 			if (list->strs[i] != NULL)
7957c478bd9Sstevel@tonic-gate 				free(list->strs[i]);
7967c478bd9Sstevel@tonic-gate 		}
7977c478bd9Sstevel@tonic-gate 		free(list->strs);
7987c478bd9Sstevel@tonic-gate 	}
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 	list->num = 0;
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate /* ========================================================================= */
8067c478bd9Sstevel@tonic-gate fru_errno_t
fru_destroy_elemdef(fru_elemdef_t * def)8077c478bd9Sstevel@tonic-gate fru_destroy_elemdef(fru_elemdef_t *def)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	if (def == NULL) {
8107c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 	if (def->enum_table != NULL) {
8137c478bd9Sstevel@tonic-gate 		for (int i = 0; i < def->enum_count; i++)
8147c478bd9Sstevel@tonic-gate 			fru_destroy_enum(&(def->enum_table[i]));
8157c478bd9Sstevel@tonic-gate 		free(def->enum_table);
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 	def->enum_count = 0;
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	if (def->example_string != NULL)
8207c478bd9Sstevel@tonic-gate 		free(def->example_string);
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate /* ========================================================================= */
8267c478bd9Sstevel@tonic-gate fru_errno_t
fru_list_segments(fru_nodehdl_t container,fru_strlist_t * list)8277c478bd9Sstevel@tonic-gate fru_list_segments(fru_nodehdl_t container, fru_strlist_t *list)
8287c478bd9Sstevel@tonic-gate {
8297c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
8327c478bd9Sstevel@tonic-gate 		return (err);
8337c478bd9Sstevel@tonic-gate 	}
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	if (lock_container(READ_LOCK, container) != FRU_SUCCESS) {
8367c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
8377c478bd9Sstevel@tonic-gate 	}
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	err = get_seg_list_from_ds(container, list);
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
8427c478bd9Sstevel@tonic-gate 	return (err);
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate /* ========================================================================= */
8467c478bd9Sstevel@tonic-gate fru_errno_t
fru_create_segment(fru_nodehdl_t container,fru_segdef_t * def)8477c478bd9Sstevel@tonic-gate fru_create_segment(fru_nodehdl_t container, fru_segdef_t *def)
8487c478bd9Sstevel@tonic-gate {
8497c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
8507c478bd9Sstevel@tonic-gate 	int i = 0;
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
8537c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
8547c478bd9Sstevel@tonic-gate 	}
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 	if ((def->desc.field.encrypted == 1) &&
8577c478bd9Sstevel@tonic-gate 	       (fru_encryption_supported() == FRU_NOTSUP)) {
8587c478bd9Sstevel@tonic-gate 		return (FRU_NOTSUP);
8597c478bd9Sstevel@tonic-gate 	}
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
8627c478bd9Sstevel@tonic-gate 		return (err);
8637c478bd9Sstevel@tonic-gate 	}
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	if (lock_container(WRITE_LOCK, container) != FRU_SUCCESS) {
8667c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
8677c478bd9Sstevel@tonic-gate 	}
8687c478bd9Sstevel@tonic-gate 	fru_strlist_t seg_list;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	/* get a list of all segments */
8717c478bd9Sstevel@tonic-gate 	/* here we do not want to leave out the encrypted segments. */
87235551380Skmohan 	RETRY(err = data_source->get_seg_list(NODEHDL_TO_TREEHDL(container),
87335551380Skmohan 								&seg_list))
87435551380Skmohan 	if (err != FRU_SUCCESS) {
8757c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
8767c478bd9Sstevel@tonic-gate 		return (err);
8777c478bd9Sstevel@tonic-gate 	}
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	for (i = 0; i < seg_list.num; i++) {
8807c478bd9Sstevel@tonic-gate 		if (strncmp(seg_list.strs[i], def->name, FRU_SEGNAMELEN)
8817c478bd9Sstevel@tonic-gate 			== 0) {
8827c478bd9Sstevel@tonic-gate 			fru_destroy_strlist(&seg_list);
8837c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
8847c478bd9Sstevel@tonic-gate 			return (FRU_DUPSEG);
8857c478bd9Sstevel@tonic-gate 		}
8867c478bd9Sstevel@tonic-gate 	}
8877c478bd9Sstevel@tonic-gate 	fru_destroy_strlist(&seg_list);
8887c478bd9Sstevel@tonic-gate 
88935551380Skmohan 	RETRY(err = data_source->add_seg(NODEHDL_TO_TREEHDL(container), def))
89035551380Skmohan 
8917c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
8927c478bd9Sstevel@tonic-gate 	return (err);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate /* ========================================================================= */
8967c478bd9Sstevel@tonic-gate fru_errno_t
fru_remove_segment(fru_nodehdl_t container,const char * seg_name)8977c478bd9Sstevel@tonic-gate fru_remove_segment(fru_nodehdl_t container, const char *seg_name)
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
9007c478bd9Sstevel@tonic-gate 	if ((seg_name == NULL) || (strlen(seg_name) > FRU_SEGNAMELEN)) {
9017c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
9057c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
9067c478bd9Sstevel@tonic-gate 	}
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
9097c478bd9Sstevel@tonic-gate 		return (err);
9107c478bd9Sstevel@tonic-gate 	}
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	if (lock_container(WRITE_LOCK, container) != FRU_SUCCESS) {
9137c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
9147c478bd9Sstevel@tonic-gate 	}
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	/* do not allow encrypted segments to be removed */
9177c478bd9Sstevel@tonic-gate 	/* unless encryption is supported */
9187c478bd9Sstevel@tonic-gate 	if ((segment_is_encrypted(container, seg_name)) &&
9197c478bd9Sstevel@tonic-gate 		(fru_encryption_supported() == FRU_NOTSUP)) {
9207c478bd9Sstevel@tonic-gate 		err = FRU_INVALSEG;
9217c478bd9Sstevel@tonic-gate 	} else {
92235551380Skmohan 		RETRY(err =
92335551380Skmohan 			data_source->delete_seg(NODEHDL_TO_TREEHDL(container),
92435551380Skmohan 								seg_name))
9257c478bd9Sstevel@tonic-gate 	}
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
9287c478bd9Sstevel@tonic-gate 	return (err);
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate /* ========================================================================= */
9327c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_segment_def(fru_nodehdl_t container,const char * seg_name,fru_segdef_t * definition)9337c478bd9Sstevel@tonic-gate fru_get_segment_def(fru_nodehdl_t container, const char *seg_name,
9347c478bd9Sstevel@tonic-gate 			fru_segdef_t *definition)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
9377c478bd9Sstevel@tonic-gate 	if ((seg_name == NULL) || (strlen(seg_name) > 2)) {
9387c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
9397c478bd9Sstevel@tonic-gate 	}
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
9427c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
9437c478bd9Sstevel@tonic-gate 	}
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
9467c478bd9Sstevel@tonic-gate 		return (err);
9477c478bd9Sstevel@tonic-gate 	}
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	if (lock_container(READ_LOCK, container) != FRU_SUCCESS) {
9507c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
9517c478bd9Sstevel@tonic-gate 	}
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	// NOTE: not passing "definition" to this function such that I may
9547c478bd9Sstevel@tonic-gate 	// check for encryption before allowing the user to get the data.
9557c478bd9Sstevel@tonic-gate 	fru_segdef_t segdef;
95635551380Skmohan 
95735551380Skmohan 	RETRY(err = data_source->get_seg_def(NODEHDL_TO_TREEHDL(container),
95835551380Skmohan 							seg_name, &segdef))
95935551380Skmohan 
96035551380Skmohan 	if (err != FRU_SUCCESS) {
9617c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
9627c478bd9Sstevel@tonic-gate 		return (err);
9637c478bd9Sstevel@tonic-gate 	}
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	if ((segdef.desc.field.encrypted == 1) &&
9667c478bd9Sstevel@tonic-gate 		(fru_encryption_supported() == FRU_NOTSUP)) {
9677c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
9687c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	// After encryption check, copy from my def to users.
9727c478bd9Sstevel@tonic-gate 	definition->version = segdef.version;
9737c478bd9Sstevel@tonic-gate 	strlcpy(definition->name, segdef.name, FRU_SEGNAMELEN+1);
9747c478bd9Sstevel@tonic-gate 	definition->desc = segdef.desc;
9757c478bd9Sstevel@tonic-gate 	definition->size = segdef.size;
9767c478bd9Sstevel@tonic-gate 	definition->address = segdef.address;
9777c478bd9Sstevel@tonic-gate 	definition->hw_desc = segdef.hw_desc;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
9807c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate /* ========================================================================= */
9847c478bd9Sstevel@tonic-gate fru_errno_t
fru_list_elems_in(fru_nodehdl_t container,const char * seg_name,fru_strlist_t * list)9857c478bd9Sstevel@tonic-gate fru_list_elems_in(fru_nodehdl_t container, const char *seg_name,
9867c478bd9Sstevel@tonic-gate 		fru_strlist_t *list)
9877c478bd9Sstevel@tonic-gate {
9887c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
9897c478bd9Sstevel@tonic-gate 	fru_tag_t *tags = NULL;
9907c478bd9Sstevel@tonic-gate 	int i = 0;
9917c478bd9Sstevel@tonic-gate 	int num_tags = 0;
9927c478bd9Sstevel@tonic-gate 	fru_strlist_t rc_list;
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	if ((seg_name == NULL) || (strlen(seg_name) > 2)) {
9957c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
9967c478bd9Sstevel@tonic-gate 	}
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
9997c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
10037c478bd9Sstevel@tonic-gate 		return (err);
10047c478bd9Sstevel@tonic-gate 	}
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 	if (lock_container(READ_LOCK, container) != FRU_SUCCESS) {
10077c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
10087c478bd9Sstevel@tonic-gate 	}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 	if ((segment_is_encrypted(container, seg_name)) &&
10117c478bd9Sstevel@tonic-gate 		(fru_encryption_supported() == FRU_NOTSUP)) {
10127c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
10137c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
101635551380Skmohan 	RETRY(err = data_source->get_tag_list(NODEHDL_TO_TREEHDL(container),
101735551380Skmohan 						seg_name, &tags, &num_tags))
101835551380Skmohan 	if (err != FRU_SUCCESS) {
10197c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
10207c478bd9Sstevel@tonic-gate 		return (err);
10217c478bd9Sstevel@tonic-gate 	}
10227c478bd9Sstevel@tonic-gate 	if (num_tags == 0) {
10237c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
10247c478bd9Sstevel@tonic-gate 		list->num = 0;
10257c478bd9Sstevel@tonic-gate 		list->strs = NULL;
10267c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	// allocate the memory for the names.
10307c478bd9Sstevel@tonic-gate 	rc_list.num = 0;
10317c478bd9Sstevel@tonic-gate 	rc_list.strs = (char **)malloc(num_tags * sizeof (char *));
10327c478bd9Sstevel@tonic-gate 	if (rc_list.strs == NULL) {
10337c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
10347c478bd9Sstevel@tonic-gate 		free(tags);
10357c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
10367c478bd9Sstevel@tonic-gate 	}
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 	// for each tag fill in it's name.
10397c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_tags; i++) {
10407c478bd9Sstevel@tonic-gate 		const fru_regdef_t *def = fru_reg_lookup_def_by_tag(tags[i]);
10417c478bd9Sstevel@tonic-gate 		if (def != NULL) {
10427c478bd9Sstevel@tonic-gate 			rc_list.strs[i] = strdup(def->name);
10437c478bd9Sstevel@tonic-gate 			if (rc_list.strs[i] == NULL) {
10447c478bd9Sstevel@tonic-gate 				CHK_UNLOCK_CONTAINER(container);
10457c478bd9Sstevel@tonic-gate 				fru_destroy_strlist(&rc_list);
10467c478bd9Sstevel@tonic-gate 				free(tags);
10477c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
10487c478bd9Sstevel@tonic-gate 			}
10497c478bd9Sstevel@tonic-gate 		} else {
10507c478bd9Sstevel@tonic-gate 			// instead of failing return "UNKNOWN"
10517c478bd9Sstevel@tonic-gate 			rc_list.strs[i] = strdup(UNKNOWN_PATH);
10527c478bd9Sstevel@tonic-gate 			if (rc_list.strs[i] == NULL) {
10537c478bd9Sstevel@tonic-gate 				CHK_UNLOCK_CONTAINER(container);
10547c478bd9Sstevel@tonic-gate 				fru_destroy_strlist(&rc_list);
10557c478bd9Sstevel@tonic-gate 				free(tags);
10567c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
10577c478bd9Sstevel@tonic-gate 			}
10587c478bd9Sstevel@tonic-gate 		}
10597c478bd9Sstevel@tonic-gate 		rc_list.num++;
10607c478bd9Sstevel@tonic-gate 	}
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
10637c478bd9Sstevel@tonic-gate 	list->num = rc_list.num;
10647c478bd9Sstevel@tonic-gate 	list->strs = rc_list.strs;
10657c478bd9Sstevel@tonic-gate 	free(tags);
10667c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate /* ========================================================================= */
10707c478bd9Sstevel@tonic-gate /* Project-private interface */
10717c478bd9Sstevel@tonic-gate extern "C" fru_errno_t
fru_for_each_segment(fru_nodehdl_t container,int (* function)(fru_seghdl_t segment,void * args),void * args)10727c478bd9Sstevel@tonic-gate fru_for_each_segment(fru_nodehdl_t container,
10737c478bd9Sstevel@tonic-gate 			int (*function)(fru_seghdl_t segment, void *args),
10747c478bd9Sstevel@tonic-gate 			void *args)
10757c478bd9Sstevel@tonic-gate {
10767c478bd9Sstevel@tonic-gate 	fru_errno_t	status;
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
10807c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	if (lock_container(READ_LOCK, container) != FRU_SUCCESS) {
10847c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
10857c478bd9Sstevel@tonic-gate 	}
108635551380Skmohan 	RETRY(status =
108735551380Skmohan 		data_source->for_each_segment(NODEHDL_TO_TREEHDL(container),
108835551380Skmohan 							function, args))
10897c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
10907c478bd9Sstevel@tonic-gate 	return (status);
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate /* ========================================================================= */
10947c478bd9Sstevel@tonic-gate /*
10957c478bd9Sstevel@tonic-gate  * Project-private interface
10967c478bd9Sstevel@tonic-gate  *
10977c478bd9Sstevel@tonic-gate  * This routine is only safe when called from within fru_for_each_segment()
10987c478bd9Sstevel@tonic-gate  * (which is currently the only way to get a segment handle) so that the
10997c478bd9Sstevel@tonic-gate  * segment's container will be locked
11007c478bd9Sstevel@tonic-gate  */
11017c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_segment_name(fru_seghdl_t segment,char ** name)11027c478bd9Sstevel@tonic-gate fru_get_segment_name(fru_seghdl_t segment, char **name)
11037c478bd9Sstevel@tonic-gate {
110435551380Skmohan 	fru_errno_t	err = FRU_SUCCESS;
110535551380Skmohan 
11067c478bd9Sstevel@tonic-gate 	assert(data_source != NULL);
110735551380Skmohan 
110835551380Skmohan 	RETRY(err = data_source->get_segment_name(NODEHDL_TO_TREEHDL(segment),
110935551380Skmohan 									name))
111035551380Skmohan 	return (err);
11117c478bd9Sstevel@tonic-gate }
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate /* ========================================================================= */
11147c478bd9Sstevel@tonic-gate /*
11157c478bd9Sstevel@tonic-gate  * Project-private interface
11167c478bd9Sstevel@tonic-gate  *
11177c478bd9Sstevel@tonic-gate  * This routine is only safe when called from within fru_for_each_segment()
11187c478bd9Sstevel@tonic-gate  * (which is currently the only way to get a segment handle) so that the
11197c478bd9Sstevel@tonic-gate  * segment's container will be locked
11207c478bd9Sstevel@tonic-gate  */
11217c478bd9Sstevel@tonic-gate extern "C" fru_errno_t
fru_for_each_packet(fru_seghdl_t segment,int (* function)(fru_tag_t * tag,uint8_t * payload,size_t length,void * args),void * args)11227c478bd9Sstevel@tonic-gate fru_for_each_packet(fru_seghdl_t segment,
11237c478bd9Sstevel@tonic-gate 			int (*function)(fru_tag_t *tag, uint8_t *payload,
11247c478bd9Sstevel@tonic-gate 					size_t length, void *args),
11257c478bd9Sstevel@tonic-gate 			void *args)
11267c478bd9Sstevel@tonic-gate {
112735551380Skmohan 	fru_errno_t	err = FRU_SUCCESS;
112835551380Skmohan 
11297c478bd9Sstevel@tonic-gate 	assert(data_source != NULL);
113035551380Skmohan 
113135551380Skmohan 	RETRY(err = data_source->for_each_packet(NODEHDL_TO_TREEHDL(segment),
113235551380Skmohan 							function, args))
113335551380Skmohan 	return (err);
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate /* ========================================================================= */
11387c478bd9Sstevel@tonic-gate // To keep track of the number of instances for each type of tag which
11397c478bd9Sstevel@tonic-gate // might occur.
11407c478bd9Sstevel@tonic-gate struct TagInstPair
11417c478bd9Sstevel@tonic-gate {
11427c478bd9Sstevel@tonic-gate 	int inst;
11437c478bd9Sstevel@tonic-gate 	fru_tag_t tag;
11447c478bd9Sstevel@tonic-gate };
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate struct tag_inst_hist_t
11477c478bd9Sstevel@tonic-gate {
11487c478bd9Sstevel@tonic-gate 	TagInstPair *pairs;
11497c478bd9Sstevel@tonic-gate 	unsigned size;
11507c478bd9Sstevel@tonic-gate 	unsigned numStored;
11517c478bd9Sstevel@tonic-gate };
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate static fru_errno_t
update_tag_inst_hist(tag_inst_hist_t * hist,fru_tag_t tag)11547c478bd9Sstevel@tonic-gate update_tag_inst_hist(tag_inst_hist_t *hist, fru_tag_t tag)
11557c478bd9Sstevel@tonic-gate {
11567c478bd9Sstevel@tonic-gate 	// find if this tag has occured before.
11577c478bd9Sstevel@tonic-gate 	int found = 0;
11587c478bd9Sstevel@tonic-gate 	for (int s = 0; s < (hist->numStored); s++) {
11597c478bd9Sstevel@tonic-gate 		if (tags_equal((hist->pairs)[s].tag, tag)) {
11607c478bd9Sstevel@tonic-gate 		// if so just add to the instance.
11617c478bd9Sstevel@tonic-gate 			hist->pairs[s].inst++;
11627c478bd9Sstevel@tonic-gate 			found = 1;
11637c478bd9Sstevel@tonic-gate 			break;
11647c478bd9Sstevel@tonic-gate 		}
11657c478bd9Sstevel@tonic-gate 	}
11667c478bd9Sstevel@tonic-gate 	// if not add to the end of the array of instance 0.
11677c478bd9Sstevel@tonic-gate 	if (!found) {
11687c478bd9Sstevel@tonic-gate 		if (hist->numStored > hist->size) {
11697c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
11707c478bd9Sstevel@tonic-gate 		}
11717c478bd9Sstevel@tonic-gate 		(hist->pairs)[(hist->numStored)].tag.raw_data = tag.raw_data;
11727c478bd9Sstevel@tonic-gate 		(hist->pairs)[(hist->numStored)].inst = 0;
11737c478bd9Sstevel@tonic-gate 		(hist->numStored)++;
11747c478bd9Sstevel@tonic-gate 	}
11757c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate static fru_errno_t
get_tag_inst_from_hist(tag_inst_hist_t * hist,fru_tag_t tag,int * instance)11797c478bd9Sstevel@tonic-gate get_tag_inst_from_hist(tag_inst_hist_t *hist, fru_tag_t tag, int *instance)
11807c478bd9Sstevel@tonic-gate {
11817c478bd9Sstevel@tonic-gate 	int j = 0;
11827c478bd9Sstevel@tonic-gate 	for (j = 0; j < hist->numStored; j++) {
11837c478bd9Sstevel@tonic-gate 		if (tags_equal((hist->pairs)[j].tag, tag)) {
11847c478bd9Sstevel@tonic-gate 			*instance = (hist->pairs)[j].inst;
11857c478bd9Sstevel@tonic-gate 			return (FRU_SUCCESS);
11867c478bd9Sstevel@tonic-gate 		}
11877c478bd9Sstevel@tonic-gate 	}
11887c478bd9Sstevel@tonic-gate 	return (FRU_FAILURE);
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate /* ========================================================================= */
11927c478bd9Sstevel@tonic-gate // Input:
11937c478bd9Sstevel@tonic-gate // a list of tags and number of them
11947c478bd9Sstevel@tonic-gate // and an instance of the unknown payload you are looking for.
11957c478bd9Sstevel@tonic-gate // Returns:
11967c478bd9Sstevel@tonic-gate // on FRU_SUCCESS
11977c478bd9Sstevel@tonic-gate // instance == the instance of the tag "tag" to read from the list
11987c478bd9Sstevel@tonic-gate // else
11997c478bd9Sstevel@tonic-gate // instance == the number of instances remaining.
12007c478bd9Sstevel@tonic-gate //
12017c478bd9Sstevel@tonic-gate static fru_errno_t
find_unknown_element(fru_tag_t * tags,int num_tags,int * instance,fru_tag_t * tag)12027c478bd9Sstevel@tonic-gate find_unknown_element(fru_tag_t *tags, int num_tags,
12037c478bd9Sstevel@tonic-gate 			int *instance, fru_tag_t *tag)
12047c478bd9Sstevel@tonic-gate {
12057c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	tag_inst_hist_t hist;
12087c478bd9Sstevel@tonic-gate 	hist.pairs = (TagInstPair *)alloca(sizeof (TagInstPair) * num_tags);
12097c478bd9Sstevel@tonic-gate 	if (hist.pairs == NULL) {
12107c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
12117c478bd9Sstevel@tonic-gate 	}
12127c478bd9Sstevel@tonic-gate 	hist.numStored = 0;
12137c478bd9Sstevel@tonic-gate 	hist.size = num_tags;
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	// search all the tags untill they are exhausted or we find
12167c478bd9Sstevel@tonic-gate 	// the instance we want.
12177c478bd9Sstevel@tonic-gate 	int found = 0;
12187c478bd9Sstevel@tonic-gate 	int instFound = 0;
12197c478bd9Sstevel@tonic-gate 	// NOTE: instancesFound is a running total of the instances in the tags
12207c478bd9Sstevel@tonic-gate 	// WE SKIPED!
12217c478bd9Sstevel@tonic-gate 	// (ie instances left over == instance - instancesFound)
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 	int i = 0;
12247c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_tags; i++) {
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 		const fru_regdef_t *def = fru_reg_lookup_def_by_tag(tags[i]);
12277c478bd9Sstevel@tonic-gate 		// unknown tag encountered.
12287c478bd9Sstevel@tonic-gate 		if (def == NULL) {
12297c478bd9Sstevel@tonic-gate 			if (update_tag_inst_hist(&hist, tags[i])
12307c478bd9Sstevel@tonic-gate 					!= FRU_SUCCESS) {
12317c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
12327c478bd9Sstevel@tonic-gate 			}
12337c478bd9Sstevel@tonic-gate 			// do this check because everything is 0 based.
12347c478bd9Sstevel@tonic-gate 			// if we do the add before the check we will go
12357c478bd9Sstevel@tonic-gate 			// to far.
12367c478bd9Sstevel@tonic-gate 			if ((instFound + 1) > (*instance)) {
12377c478bd9Sstevel@tonic-gate 				found = 1;
12387c478bd9Sstevel@tonic-gate 				break;
12397c478bd9Sstevel@tonic-gate 			} else {
12407c478bd9Sstevel@tonic-gate 				instFound++;
12417c478bd9Sstevel@tonic-gate 			}
12427c478bd9Sstevel@tonic-gate 		}
12437c478bd9Sstevel@tonic-gate 	}
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	*instance -= instFound;
12467c478bd9Sstevel@tonic-gate 	if (!found) {
12477c478bd9Sstevel@tonic-gate 		return (FRU_DATANOTFOUND);
12487c478bd9Sstevel@tonic-gate 	}
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 	(*tag).raw_data = tags[i].raw_data;
12517c478bd9Sstevel@tonic-gate 	if (get_tag_inst_from_hist(&hist, tags[i], instance) != FRU_SUCCESS) {
12527c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
12537c478bd9Sstevel@tonic-gate 	}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
12567c478bd9Sstevel@tonic-gate }
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate // Input:
12597c478bd9Sstevel@tonic-gate // a list of tags and number of them
12607c478bd9Sstevel@tonic-gate // a list of Ancestors
12617c478bd9Sstevel@tonic-gate // the instance we are looking for
12627c478bd9Sstevel@tonic-gate // Returns:
12637c478bd9Sstevel@tonic-gate // on FRU_SUCCESS
12647c478bd9Sstevel@tonic-gate // instance == the instance of the field within the payload to read.
12657c478bd9Sstevel@tonic-gate // correct == pointer into ants which is correct.
12667c478bd9Sstevel@tonic-gate // tagInstance == instance of the tag
12677c478bd9Sstevel@tonic-gate // else
12687c478bd9Sstevel@tonic-gate // instance == the number of instances remaining.
12697c478bd9Sstevel@tonic-gate // correct == NULL
12707c478bd9Sstevel@tonic-gate // tagInstance == UNDEFINED
12717c478bd9Sstevel@tonic-gate //
12727c478bd9Sstevel@tonic-gate static fru_errno_t
find_known_element(fru_tag_t * tags,int num_tags,Ancestor * ants,int * instance,Ancestor ** correct,int * tagInstance)12737c478bd9Sstevel@tonic-gate find_known_element(fru_tag_t *tags, int num_tags, Ancestor *ants,
12747c478bd9Sstevel@tonic-gate 			int *instance, Ancestor **correct,
12757c478bd9Sstevel@tonic-gate 			int *tagInstance)
12767c478bd9Sstevel@tonic-gate {
12777c478bd9Sstevel@tonic-gate 	int j = 0;
12787c478bd9Sstevel@tonic-gate 	Ancestor *cur = ants;
12797c478bd9Sstevel@tonic-gate 	int num_posible = 0;
12807c478bd9Sstevel@tonic-gate 	while (cur != NULL) {
12817c478bd9Sstevel@tonic-gate 		num_posible++;
12827c478bd9Sstevel@tonic-gate 		cur = cur->next;
12837c478bd9Sstevel@tonic-gate 	}
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	tag_inst_hist_t hist;
12867c478bd9Sstevel@tonic-gate 	hist.pairs = (TagInstPair *)alloca(sizeof (TagInstPair) * num_posible);
12877c478bd9Sstevel@tonic-gate 	hist.size = num_posible;
12887c478bd9Sstevel@tonic-gate 	if (hist.pairs == NULL) {
12897c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
12907c478bd9Sstevel@tonic-gate 	}
12917c478bd9Sstevel@tonic-gate 	hist.numStored = 0;
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	*correct = NULL;
12947c478bd9Sstevel@tonic-gate 	int i = 0;
12957c478bd9Sstevel@tonic-gate 	int found = 0;
12967c478bd9Sstevel@tonic-gate 	int instancesFound = 0;
12977c478bd9Sstevel@tonic-gate 	// NOTE: instancesFound is a running total of the instances in the tags
12987c478bd9Sstevel@tonic-gate 	//	WE SKIPED!
12997c478bd9Sstevel@tonic-gate 	//	(ie instances left over == instance - instancesFound)
13007c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_tags; i++) {
13017c478bd9Sstevel@tonic-gate 		cur = ants;
13027c478bd9Sstevel@tonic-gate 		while (cur != NULL) {
13037c478bd9Sstevel@tonic-gate 			if (tags_equal(cur->getTag(), tags[i])) {
13047c478bd9Sstevel@tonic-gate 				if (update_tag_inst_hist(&hist, tags[i])
13057c478bd9Sstevel@tonic-gate 						!= FRU_SUCCESS) {
13067c478bd9Sstevel@tonic-gate 					return (FRU_FAILURE);
13077c478bd9Sstevel@tonic-gate 				}
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 				// do this check because everything is 0 based.
13107c478bd9Sstevel@tonic-gate 				// if we do the add before the check we will go
13117c478bd9Sstevel@tonic-gate 				// to far.
13127c478bd9Sstevel@tonic-gate 				if ((instancesFound + cur->getNumInstances())
13137c478bd9Sstevel@tonic-gate 						> (*instance)) {
13147c478bd9Sstevel@tonic-gate 					*correct = cur;
13157c478bd9Sstevel@tonic-gate 					found = 1;
13167c478bd9Sstevel@tonic-gate 					break; /* while loop */
13177c478bd9Sstevel@tonic-gate 				}
13187c478bd9Sstevel@tonic-gate 				instancesFound += cur->getNumInstances();
13197c478bd9Sstevel@tonic-gate 			}
13207c478bd9Sstevel@tonic-gate 			cur = cur->next;
13217c478bd9Sstevel@tonic-gate 		}
13227c478bd9Sstevel@tonic-gate 		/* when found break out of both "for" and "while" loops */
13237c478bd9Sstevel@tonic-gate 		if (found == 1) {
13247c478bd9Sstevel@tonic-gate 			break; /* for loop */
13257c478bd9Sstevel@tonic-gate 		}
13267c478bd9Sstevel@tonic-gate 	}
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate 	*instance -= instancesFound;
13297c478bd9Sstevel@tonic-gate 	if (!found) {
13307c478bd9Sstevel@tonic-gate 		return (FRU_DATANOTFOUND);
13317c478bd9Sstevel@tonic-gate 	}
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	if (get_tag_inst_from_hist(&hist, tags[i], tagInstance)
13347c478bd9Sstevel@tonic-gate 			!= FRU_SUCCESS) {
13357c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
13367c478bd9Sstevel@tonic-gate 	}
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
13397c478bd9Sstevel@tonic-gate }
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate /*
13427c478bd9Sstevel@tonic-gate  * Same as find_known_element but ONLY searches for absolute paths
13437c478bd9Sstevel@tonic-gate  * (ie PathDef->head == tag)
13447c478bd9Sstevel@tonic-gate  */
13457c478bd9Sstevel@tonic-gate static fru_errno_t
find_known_element_abs(fru_tag_t * tags,int num_tags,int * instance,PathDef * head,Ancestor * ants,Ancestor ** correct,int * tagInstance)13467c478bd9Sstevel@tonic-gate find_known_element_abs(fru_tag_t *tags, int num_tags, int *instance,
13477c478bd9Sstevel@tonic-gate 		PathDef *head, Ancestor *ants, Ancestor **correct,
13487c478bd9Sstevel@tonic-gate 		int *tagInstance)
13497c478bd9Sstevel@tonic-gate {
13507c478bd9Sstevel@tonic-gate 	*correct = NULL;
13517c478bd9Sstevel@tonic-gate 	// find the exact ancestor we want.
13527c478bd9Sstevel@tonic-gate 	Ancestor *cur = ants;
13537c478bd9Sstevel@tonic-gate 	while (cur != NULL) {
13547c478bd9Sstevel@tonic-gate 		if (strcmp(cur->getDef()->name, head->def->name) == 0) {
13557c478bd9Sstevel@tonic-gate 			*correct = cur;
13567c478bd9Sstevel@tonic-gate 			break;
13577c478bd9Sstevel@tonic-gate 		}
13587c478bd9Sstevel@tonic-gate 		cur = cur->next;
13597c478bd9Sstevel@tonic-gate 	}
13607c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
13617c478bd9Sstevel@tonic-gate 		// serious parser bug might cause this, double check.
13627c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
13637c478bd9Sstevel@tonic-gate 	}
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 	int found = 0;
13667c478bd9Sstevel@tonic-gate 	(*tagInstance) = 0;
13677c478bd9Sstevel@tonic-gate 	for (int i = 0; i < num_tags; i++) {
13687c478bd9Sstevel@tonic-gate 		if (tags_equal(cur->getTag(), tags[i])) {
13697c478bd9Sstevel@tonic-gate 			// do this check because everything is 0 based.
13707c478bd9Sstevel@tonic-gate 			// if we do the add before the check we will go
13717c478bd9Sstevel@tonic-gate 			// to far.
13727c478bd9Sstevel@tonic-gate 			if (((*tagInstance) +1) > (*instance)) {
13737c478bd9Sstevel@tonic-gate 				*correct = cur;
13747c478bd9Sstevel@tonic-gate 				found = 1;
13757c478bd9Sstevel@tonic-gate 				break;
13767c478bd9Sstevel@tonic-gate 			}
13777c478bd9Sstevel@tonic-gate 			(*tagInstance)++;
13787c478bd9Sstevel@tonic-gate 		}
13797c478bd9Sstevel@tonic-gate 	}
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	*instance -= (*tagInstance);
13827c478bd9Sstevel@tonic-gate 	if (!found) {
13837c478bd9Sstevel@tonic-gate 		return (FRU_DATANOTFOUND);
13847c478bd9Sstevel@tonic-gate 	}
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
13877c478bd9Sstevel@tonic-gate }
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate /* ========================================================================= */
13917c478bd9Sstevel@tonic-gate // From the container, seg_name, instance, and field_path get me...
13927c478bd9Sstevel@tonic-gate // pathDef:	A linked list of Path Def objects which represent the
13937c478bd9Sstevel@tonic-gate //		field_path
13947c478bd9Sstevel@tonic-gate // ancestors:	A linked list of Tagged Ancestors which represent the
13957c478bd9Sstevel@tonic-gate //		possible payloads this data MAY reside in.
13967c478bd9Sstevel@tonic-gate // correct:	A pointer into the above list which indicates the Ancestor
13977c478bd9Sstevel@tonic-gate //		in which this instance actually resides.
13987c478bd9Sstevel@tonic-gate // tagInstance:	The instance of this ancestor in the segment.  (ie Tag
13997c478bd9Sstevel@tonic-gate //		instance)
14007c478bd9Sstevel@tonic-gate // instWICur:	The instance of this element within the tag itself.
14017c478bd9Sstevel@tonic-gate //		Or in other words "the instances left"
14027c478bd9Sstevel@tonic-gate // payload:	The payload data
14037c478bd9Sstevel@tonic-gate //
14047c478bd9Sstevel@tonic-gate // For an "UNKNOWN" payload this will return NULL for the pathDef, ancestors,
14057c478bd9Sstevel@tonic-gate // cur pointers.  This will indicate to read that this payload should be
14067c478bd9Sstevel@tonic-gate // returned with a special definition for it (UNKNOWN)...  What a HACK I
14077c478bd9Sstevel@tonic-gate // know...
14087c478bd9Sstevel@tonic-gate #define	READ_MODE 0
14097c478bd9Sstevel@tonic-gate #define	UPDATE_MODE 1
get_payload(fru_nodehdl_t container,const char * seg_name,int instance,const char * field_path,PathDef ** pathDef,Ancestor ** ancestors,Ancestor ** correct,int * tagInstance,int * instLeft,uint8_t ** payload,size_t * payloadLen,int mode)14107c478bd9Sstevel@tonic-gate static fru_errno_t get_payload(fru_nodehdl_t container,
14117c478bd9Sstevel@tonic-gate 			const char *seg_name,
14127c478bd9Sstevel@tonic-gate 			int instance,
14137c478bd9Sstevel@tonic-gate 			const char *field_path,
14147c478bd9Sstevel@tonic-gate 			// returns the following...
14157c478bd9Sstevel@tonic-gate 			PathDef **pathDef,
14167c478bd9Sstevel@tonic-gate 			Ancestor **ancestors,
14177c478bd9Sstevel@tonic-gate 			Ancestor **correct,
14187c478bd9Sstevel@tonic-gate 			int *tagInstance, // instance of the tag within the seg
14197c478bd9Sstevel@tonic-gate 			int *instLeft,    // within this payload
14207c478bd9Sstevel@tonic-gate 			uint8_t **payload,
14217c478bd9Sstevel@tonic-gate 			size_t *payloadLen,
14227c478bd9Sstevel@tonic-gate 			int mode)
14237c478bd9Sstevel@tonic-gate {
14247c478bd9Sstevel@tonic-gate 	int abs_path_flg = 0;
14257c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
14267c478bd9Sstevel@tonic-gate 	int num_tags = 0;
14277c478bd9Sstevel@tonic-gate 	fru_tag_t *tags = NULL;
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
14307c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
14317c478bd9Sstevel@tonic-gate 	}
143235551380Skmohan 	RETRY(err = data_source->get_tag_list(NODEHDL_TO_TREEHDL(container),
143335551380Skmohan 						seg_name, &tags, &num_tags))
143435551380Skmohan 	if (err != FRU_SUCCESS) {
14357c478bd9Sstevel@tonic-gate 		return (err);
14367c478bd9Sstevel@tonic-gate 	}
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	if (num_tags == 0) {
14397c478bd9Sstevel@tonic-gate 		*instLeft = instance;
14407c478bd9Sstevel@tonic-gate 		return (FRU_DATANOTFOUND);
14417c478bd9Sstevel@tonic-gate 	}
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	if (IS_UNKNOWN_PATH(field_path)) {
14447c478bd9Sstevel@tonic-gate 		fru_tag_t tagToRead;
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 		*pathDef = NULL;
14477c478bd9Sstevel@tonic-gate 		*correct = *ancestors = NULL;
14487c478bd9Sstevel@tonic-gate 		*tagInstance = 0;
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 		int unknown_inst = instance;
14517c478bd9Sstevel@tonic-gate 		if ((err = find_unknown_element(tags, num_tags, &unknown_inst,
14527c478bd9Sstevel@tonic-gate 			&tagToRead)) != FRU_SUCCESS) {
14537c478bd9Sstevel@tonic-gate 			*instLeft = unknown_inst;
14547c478bd9Sstevel@tonic-gate 			free(tags);
14557c478bd9Sstevel@tonic-gate 			return (err);
14567c478bd9Sstevel@tonic-gate 		}
145735551380Skmohan 		RETRY(err =
145835551380Skmohan 			data_source->get_tag_data(NODEHDL_TO_TREEHDL(container),
145935551380Skmohan 				seg_name, tagToRead, unknown_inst, payload,
146035551380Skmohan 								payloadLen))
14617c478bd9Sstevel@tonic-gate 		free(tags);
14627c478bd9Sstevel@tonic-gate 		return (err);
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate 
14657c478bd9Sstevel@tonic-gate 	err = fru_field_parser(field_path, ancestors,
14667c478bd9Sstevel@tonic-gate 					&abs_path_flg, pathDef);
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
14697c478bd9Sstevel@tonic-gate 		free(tags);
14707c478bd9Sstevel@tonic-gate 		return (err);
14717c478bd9Sstevel@tonic-gate 	} else if (ancestors == NULL) {
14727c478bd9Sstevel@tonic-gate 		/* without valid ancestors we can't find payloads for this */
14737c478bd9Sstevel@tonic-gate 		free(tags);
14747c478bd9Sstevel@tonic-gate 		delete pathDef;
14757c478bd9Sstevel@tonic-gate 		return (FRU_INVALELEMENT);
14767c478bd9Sstevel@tonic-gate 	}
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 	if ((mode == UPDATE_MODE) && (abs_path_flg != 1)) {
14797c478bd9Sstevel@tonic-gate 		free(tags);
14807c478bd9Sstevel@tonic-gate 		delete *ancestors; // linked list
14817c478bd9Sstevel@tonic-gate 		delete *pathDef;
14827c478bd9Sstevel@tonic-gate 		return (FRU_INVALPATH);
14837c478bd9Sstevel@tonic-gate 	}
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	if (abs_path_flg == 1) {
14867c478bd9Sstevel@tonic-gate 		if ((err = find_known_element_abs(tags, num_tags, &instance,
14877c478bd9Sstevel@tonic-gate 				*pathDef, *ancestors, correct, tagInstance))
14887c478bd9Sstevel@tonic-gate 				!= FRU_SUCCESS) {
14897c478bd9Sstevel@tonic-gate 			// set up to search next segment for instances left
14907c478bd9Sstevel@tonic-gate 			// over
14917c478bd9Sstevel@tonic-gate 			*instLeft = instance;
14927c478bd9Sstevel@tonic-gate 			free(tags);
14937c478bd9Sstevel@tonic-gate 			delete *ancestors; // linked list
14947c478bd9Sstevel@tonic-gate 			delete *pathDef;
14957c478bd9Sstevel@tonic-gate 			return (err);
14967c478bd9Sstevel@tonic-gate 		}
14977c478bd9Sstevel@tonic-gate 	} else {
14987c478bd9Sstevel@tonic-gate 		if ((err = find_known_element(tags, num_tags, *ancestors,
14997c478bd9Sstevel@tonic-gate 				&instance, correct, tagInstance))
15007c478bd9Sstevel@tonic-gate 				!= FRU_SUCCESS) {
15017c478bd9Sstevel@tonic-gate 			// set up to search next segment for instances left
15027c478bd9Sstevel@tonic-gate 			// over
15037c478bd9Sstevel@tonic-gate 			*instLeft = instance;
15047c478bd9Sstevel@tonic-gate 			free(tags);
15057c478bd9Sstevel@tonic-gate 			delete *ancestors; // linked list
15067c478bd9Sstevel@tonic-gate 			delete *pathDef;
15077c478bd9Sstevel@tonic-gate 			return (err);
15087c478bd9Sstevel@tonic-gate 		}
15097c478bd9Sstevel@tonic-gate 	}
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate 	// if we get here this means the instance number within the payload.
15127c478bd9Sstevel@tonic-gate 	*instLeft = instance;
151335551380Skmohan 	RETRY(err = data_source->get_tag_data(NODEHDL_TO_TREEHDL(container),
151435551380Skmohan 		seg_name, (*correct)->getTag(), (*tagInstance), payload,
151535551380Skmohan 								payloadLen))
151635551380Skmohan 	free(tags);
151735551380Skmohan 	if (err != FRU_SUCCESS) {
15187c478bd9Sstevel@tonic-gate 		delete *ancestors; // linked list
15197c478bd9Sstevel@tonic-gate 		delete *pathDef;
15207c478bd9Sstevel@tonic-gate 	}
152135551380Skmohan 	return (err);
15227c478bd9Sstevel@tonic-gate }
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate /* ========================================================================= */
15257c478bd9Sstevel@tonic-gate /*
15267c478bd9Sstevel@tonic-gate  * Handle decryption if necessary
15277c478bd9Sstevel@tonic-gate  */
15287c478bd9Sstevel@tonic-gate static fru_errno_t
do_decryption(fru_nodehdl_t container,const char * seg_name,uint8_t * payload,size_t payloadLen)15297c478bd9Sstevel@tonic-gate do_decryption(fru_nodehdl_t container, const char *seg_name,
15307c478bd9Sstevel@tonic-gate 		uint8_t *payload, size_t payloadLen)
15317c478bd9Sstevel@tonic-gate {
15327c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
15337c478bd9Sstevel@tonic-gate 	if (segment_is_encrypted(container, seg_name)) {
15347c478bd9Sstevel@tonic-gate 		if (fru_encryption_supported() == FRU_SUCCESS) {
15357c478bd9Sstevel@tonic-gate 			if ((err = encrypt_func(FRU_DECRYPT,
15367c478bd9Sstevel@tonic-gate 				payload, payloadLen)) != FRU_SUCCESS) {
15377c478bd9Sstevel@tonic-gate 				return (err);
15387c478bd9Sstevel@tonic-gate 			}
15397c478bd9Sstevel@tonic-gate 		} else {
15407c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
15417c478bd9Sstevel@tonic-gate 		}
15427c478bd9Sstevel@tonic-gate 	}
15437c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
15447c478bd9Sstevel@tonic-gate }
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate /* ========================================================================= */
15477c478bd9Sstevel@tonic-gate // Same as get_payload except if seg_name is NULL and it will find the one
15487c478bd9Sstevel@tonic-gate // used and return it.
15497c478bd9Sstevel@tonic-gate //
15507c478bd9Sstevel@tonic-gate static fru_errno_t
get_seg_and_payload(fru_nodehdl_t container,char ** seg_name,int instance,const char * field_path,PathDef ** pathDef,Ancestor ** ancestors,Ancestor ** correct,int * tagInstance,int * instLeft,uint8_t ** payload,size_t * payloadLen)15517c478bd9Sstevel@tonic-gate get_seg_and_payload(fru_nodehdl_t container,
15527c478bd9Sstevel@tonic-gate 			char **seg_name,
15537c478bd9Sstevel@tonic-gate 			int instance,
15547c478bd9Sstevel@tonic-gate 			const char *field_path,
15557c478bd9Sstevel@tonic-gate 			// returns the following...
15567c478bd9Sstevel@tonic-gate 			PathDef **pathDef,
15577c478bd9Sstevel@tonic-gate 			Ancestor **ancestors,
15587c478bd9Sstevel@tonic-gate 			Ancestor **correct,
15597c478bd9Sstevel@tonic-gate 			int *tagInstance, // within the segment.
15607c478bd9Sstevel@tonic-gate 			int *instLeft,   // within this payload
15617c478bd9Sstevel@tonic-gate 			uint8_t **payload,
15627c478bd9Sstevel@tonic-gate 			size_t *payloadLen)
15637c478bd9Sstevel@tonic-gate {
15647c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
15657c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
15667c478bd9Sstevel@tonic-gate 		return (err);
15677c478bd9Sstevel@tonic-gate 	}
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 	if (field_path == NULL)
15707c478bd9Sstevel@tonic-gate 		return (FRU_INVALPATH);
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 	if ((*seg_name) != NULL) {
15737c478bd9Sstevel@tonic-gate 
15747c478bd9Sstevel@tonic-gate 		// always check for valid segment names.
15757c478bd9Sstevel@tonic-gate 		if (strlen((const char *)(*seg_name)) > FRU_SEGNAMELEN) {
15767c478bd9Sstevel@tonic-gate 			return (FRU_INVALSEG);
15777c478bd9Sstevel@tonic-gate 		}
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 		if ((err = get_payload(container, (const char *)(*seg_name),
15807c478bd9Sstevel@tonic-gate 			instance, field_path, pathDef, ancestors, correct,
15817c478bd9Sstevel@tonic-gate 			tagInstance, instLeft, payload, payloadLen, READ_MODE))
15827c478bd9Sstevel@tonic-gate 				!= FRU_SUCCESS) {
15837c478bd9Sstevel@tonic-gate 			return (err);
15847c478bd9Sstevel@tonic-gate 		}
15857c478bd9Sstevel@tonic-gate 		return (do_decryption(container, (const char *)(*seg_name),
15867c478bd9Sstevel@tonic-gate 				*payload, *payloadLen));
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate 	} else {
15897c478bd9Sstevel@tonic-gate 		fru_strlist_t seg_list;
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate 		if ((err = get_seg_list_from_ds(container, &seg_list))
15927c478bd9Sstevel@tonic-gate 			!= FRU_SUCCESS) {
15937c478bd9Sstevel@tonic-gate 			return (err);
15947c478bd9Sstevel@tonic-gate 		}
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate 		int found = 0;
15977c478bd9Sstevel@tonic-gate 		for (int i = 0; i < seg_list.num; i++) {
15987c478bd9Sstevel@tonic-gate 			err = get_payload(container,
15997c478bd9Sstevel@tonic-gate 					seg_list.strs[i],
16007c478bd9Sstevel@tonic-gate 					instance, field_path,
16017c478bd9Sstevel@tonic-gate 					pathDef, ancestors, correct,
16027c478bd9Sstevel@tonic-gate 					tagInstance, instLeft,
16037c478bd9Sstevel@tonic-gate 					payload, payloadLen, READ_MODE);
16047c478bd9Sstevel@tonic-gate 			if (err == FRU_SUCCESS) {
16057c478bd9Sstevel@tonic-gate 				(*seg_name) = strdup(seg_list.strs[i]);
16067c478bd9Sstevel@tonic-gate 				fru_destroy_strlist(&seg_list);
16077c478bd9Sstevel@tonic-gate 				return (do_decryption(container,
16087c478bd9Sstevel@tonic-gate 						(const char *)(*seg_name),
16097c478bd9Sstevel@tonic-gate 						*payload, *payloadLen));
16107c478bd9Sstevel@tonic-gate 			} else if (err == FRU_DATANOTFOUND) {
16117c478bd9Sstevel@tonic-gate 				// we may have found some instances or none at
16127c478bd9Sstevel@tonic-gate 				// all but not enough all together.  search
16137c478bd9Sstevel@tonic-gate 				// again with the # of instances left.
16147c478bd9Sstevel@tonic-gate 				instance = *instLeft;
16157c478bd9Sstevel@tonic-gate 			} else {
16167c478bd9Sstevel@tonic-gate 				fru_destroy_strlist(&seg_list);
16177c478bd9Sstevel@tonic-gate 				return (err);
16187c478bd9Sstevel@tonic-gate 			}
16197c478bd9Sstevel@tonic-gate 		}
16207c478bd9Sstevel@tonic-gate 		fru_destroy_strlist(&seg_list);
16217c478bd9Sstevel@tonic-gate 		return (FRU_DATANOTFOUND);
16227c478bd9Sstevel@tonic-gate 	}
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate /* ========================================================================= */
16267c478bd9Sstevel@tonic-gate fru_errno_t
fru_read_field(fru_nodehdl_t container,char ** seg_name,unsigned int instance,const char * field_path,void ** data,size_t * data_len,char ** found_path)16277c478bd9Sstevel@tonic-gate fru_read_field(fru_nodehdl_t container,
16287c478bd9Sstevel@tonic-gate 		char **seg_name, unsigned int instance,
16297c478bd9Sstevel@tonic-gate 		const char *field_path,
16307c478bd9Sstevel@tonic-gate 		void **data, size_t *data_len,
16317c478bd9Sstevel@tonic-gate 		char **found_path)
16327c478bd9Sstevel@tonic-gate {
16337c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
16347c478bd9Sstevel@tonic-gate 	// just init this value for the user
16357c478bd9Sstevel@tonic-gate 	*data = NULL;
16367c478bd9Sstevel@tonic-gate 	*data_len = 0;
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate 	if (lock_container(READ_LOCK, container) != FRU_SUCCESS) {
16397c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
16407c478bd9Sstevel@tonic-gate 	}
16417c478bd9Sstevel@tonic-gate 	PathDef *pathDef;
16427c478bd9Sstevel@tonic-gate 	Ancestor *ancestors;
16437c478bd9Sstevel@tonic-gate 	Ancestor *correctAnt;
16447c478bd9Sstevel@tonic-gate 	int tagInstance = 0;
16457c478bd9Sstevel@tonic-gate 	int instWIPayload = 0;
16467c478bd9Sstevel@tonic-gate 	uint8_t *payload;
16477c478bd9Sstevel@tonic-gate 	size_t payloadLen = 0;
16487c478bd9Sstevel@tonic-gate 	err = get_seg_and_payload(container, seg_name, instance, field_path,
16497c478bd9Sstevel@tonic-gate 			&pathDef, &ancestors, &correctAnt, &tagInstance,
16507c478bd9Sstevel@tonic-gate 			&instWIPayload, &payload, &payloadLen);
16517c478bd9Sstevel@tonic-gate 
16527c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
16557c478bd9Sstevel@tonic-gate 		return (err);
16567c478bd9Sstevel@tonic-gate 	}
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 	if (pathDef == NULL) { // SPECIAL CASE of UNKNOW payload.
16597c478bd9Sstevel@tonic-gate 		delete ancestors;
16607c478bd9Sstevel@tonic-gate 		delete pathDef;
16617c478bd9Sstevel@tonic-gate 		free(payload);
16627c478bd9Sstevel@tonic-gate 
16637c478bd9Sstevel@tonic-gate 		*data = (void *)malloc(payloadLen);
16647c478bd9Sstevel@tonic-gate 		if ((*data) == NULL) {
16657c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
16667c478bd9Sstevel@tonic-gate 		}
16677c478bd9Sstevel@tonic-gate 		memcpy(*data, payload, payloadLen);
16687c478bd9Sstevel@tonic-gate 		*data_len = payloadLen;
16697c478bd9Sstevel@tonic-gate 		if (found_path != NULL) {
16707c478bd9Sstevel@tonic-gate 			*found_path = strdup(UNKNOWN_PATH);
16717c478bd9Sstevel@tonic-gate 		}
16727c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
16737c478bd9Sstevel@tonic-gate 	}
16747c478bd9Sstevel@tonic-gate 
16757c478bd9Sstevel@tonic-gate 	// get the specific data
16767c478bd9Sstevel@tonic-gate 	err = PayloadReader::readData(pathDef, correctAnt,
16777c478bd9Sstevel@tonic-gate 					instWIPayload,
16787c478bd9Sstevel@tonic-gate 					payload, payloadLen,
16797c478bd9Sstevel@tonic-gate 					data, data_len);
16807c478bd9Sstevel@tonic-gate 	delete pathDef;
16817c478bd9Sstevel@tonic-gate 	free(payload);
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate 	if (err == FRU_SUCCESS) {
16847c478bd9Sstevel@tonic-gate 		if (found_path != NULL) {
16857c478bd9Sstevel@tonic-gate 			*found_path = (char *)malloc(
16867c478bd9Sstevel@tonic-gate 				strlen(correctAnt->getPath(instWIPayload))
16877c478bd9Sstevel@tonic-gate 				+ strlen(field_path) + 2);
16887c478bd9Sstevel@tonic-gate 			if ((*found_path) == NULL) {
16897c478bd9Sstevel@tonic-gate 				delete ancestors;
16907c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
16917c478bd9Sstevel@tonic-gate 			}
16927c478bd9Sstevel@tonic-gate 			sprintf(*found_path, "%s%s",
16937c478bd9Sstevel@tonic-gate 				correctAnt->getPath(instWIPayload),
16947c478bd9Sstevel@tonic-gate 					field_path);
16957c478bd9Sstevel@tonic-gate 		}
16967c478bd9Sstevel@tonic-gate 	}
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate 	delete ancestors;
16997c478bd9Sstevel@tonic-gate 	return (err);
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate /* ========================================================================= */
17037c478bd9Sstevel@tonic-gate fru_errno_t
fru_update_field(fru_nodehdl_t container,char * seg_name,unsigned int instance,const char * field_path,void * data,size_t length)17047c478bd9Sstevel@tonic-gate fru_update_field(fru_nodehdl_t container,
17057c478bd9Sstevel@tonic-gate 		char *seg_name, unsigned int instance,
17067c478bd9Sstevel@tonic-gate 		const char *field_path,
17077c478bd9Sstevel@tonic-gate 		void *data, size_t length)
17087c478bd9Sstevel@tonic-gate {
17097c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	if ((field_path == NULL) || IS_UNKNOWN_PATH(field_path)) {
17127c478bd9Sstevel@tonic-gate 		return (FRU_INVALPATH);
17137c478bd9Sstevel@tonic-gate 	} else if (seg_name == NULL) {
17147c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
17157c478bd9Sstevel@tonic-gate 	}
17167c478bd9Sstevel@tonic-gate 
17177c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
17187c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
17197c478bd9Sstevel@tonic-gate 	}
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	if (lock_container(WRITE_LOCK, container) != FRU_SUCCESS) {
17227c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
17237c478bd9Sstevel@tonic-gate 	}
17247c478bd9Sstevel@tonic-gate 	PathDef *pathDef;
17257c478bd9Sstevel@tonic-gate 	Ancestor *ancestors;
17267c478bd9Sstevel@tonic-gate 	Ancestor *correctAnt;
17277c478bd9Sstevel@tonic-gate 	int tagInstance = 0;
17287c478bd9Sstevel@tonic-gate 	int instWIPayload = 0;
17297c478bd9Sstevel@tonic-gate 	uint8_t *payload;
17307c478bd9Sstevel@tonic-gate 	size_t payloadLen = 0;
17317c478bd9Sstevel@tonic-gate 	err = get_payload(container, seg_name, instance, field_path,
17327c478bd9Sstevel@tonic-gate 			&pathDef, &ancestors, &correctAnt, &tagInstance,
17337c478bd9Sstevel@tonic-gate 			&instWIPayload, &payload, &payloadLen, UPDATE_MODE);
17347c478bd9Sstevel@tonic-gate 
17357c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
17367c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
17377c478bd9Sstevel@tonic-gate 		return (err);
17387c478bd9Sstevel@tonic-gate 	}
17397c478bd9Sstevel@tonic-gate 
17407c478bd9Sstevel@tonic-gate 	if ((err = do_decryption(container, (const char *)seg_name,
17417c478bd9Sstevel@tonic-gate 				payload, payloadLen)) != FRU_SUCCESS) {
17427c478bd9Sstevel@tonic-gate 		free(payload);
17437c478bd9Sstevel@tonic-gate 		return (err);
17447c478bd9Sstevel@tonic-gate 	}
17457c478bd9Sstevel@tonic-gate 
17467c478bd9Sstevel@tonic-gate 	// fill in the new data in the payload
17477c478bd9Sstevel@tonic-gate 	err = PayloadReader::updateData(pathDef, correctAnt, instWIPayload,
17487c478bd9Sstevel@tonic-gate 					payload, payloadLen,
17497c478bd9Sstevel@tonic-gate 					data, length);
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
17527c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
17537c478bd9Sstevel@tonic-gate 		delete ancestors; // linked list.
17547c478bd9Sstevel@tonic-gate 		delete pathDef;
17557c478bd9Sstevel@tonic-gate 		free(payload);
17567c478bd9Sstevel@tonic-gate 		return (err);
17577c478bd9Sstevel@tonic-gate 	}
17587c478bd9Sstevel@tonic-gate 
17597c478bd9Sstevel@tonic-gate 	if ((segment_is_encrypted(container, seg_name)) &&
17607c478bd9Sstevel@tonic-gate 		(fru_encryption_supported() == FRU_SUCCESS)) {
17617c478bd9Sstevel@tonic-gate 		if ((err = encrypt_func(FRU_ENCRYPT, payload, payloadLen))
17627c478bd9Sstevel@tonic-gate 			!= FRU_SUCCESS) {
17637c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
17647c478bd9Sstevel@tonic-gate 			delete ancestors; // linked list.
17657c478bd9Sstevel@tonic-gate 			delete pathDef;
17667c478bd9Sstevel@tonic-gate 			free(payload);
17677c478bd9Sstevel@tonic-gate 			return (err);
17687c478bd9Sstevel@tonic-gate 		}
17697c478bd9Sstevel@tonic-gate 	}
17707c478bd9Sstevel@tonic-gate 
177135551380Skmohan 	RETRY(err = data_source->set_tag_data(NODEHDL_TO_TREEHDL(container),
177235551380Skmohan 					seg_name, correctAnt->getTag(),
177335551380Skmohan 					tagInstance, payload, payloadLen))
17747c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
17757c478bd9Sstevel@tonic-gate 	delete ancestors; // linked list.
17767c478bd9Sstevel@tonic-gate 	free(payload);
17777c478bd9Sstevel@tonic-gate 	delete pathDef;
17787c478bd9Sstevel@tonic-gate 	return (err);
17797c478bd9Sstevel@tonic-gate }
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate /* ========================================================================= */
17827c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_num_iterations(fru_nodehdl_t container,char ** seg_name,unsigned int instance,const char * iter_path,int * num_there,char ** found_path)17837c478bd9Sstevel@tonic-gate fru_get_num_iterations(fru_nodehdl_t container,
17847c478bd9Sstevel@tonic-gate 			char **seg_name,
17857c478bd9Sstevel@tonic-gate 			unsigned int instance,
17867c478bd9Sstevel@tonic-gate 			const char *iter_path,
17877c478bd9Sstevel@tonic-gate 			int *num_there,
17887c478bd9Sstevel@tonic-gate 			char **found_path)
17897c478bd9Sstevel@tonic-gate {
17907c478bd9Sstevel@tonic-gate 	// this ensures a more descriptive error message.
17917c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
17927c478bd9Sstevel@tonic-gate 
17937c478bd9Sstevel@tonic-gate 	if (lock_container(READ_LOCK, container) != FRU_SUCCESS) {
17947c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
17957c478bd9Sstevel@tonic-gate 	}
17967c478bd9Sstevel@tonic-gate 	PathDef *pathDef;
17977c478bd9Sstevel@tonic-gate 	Ancestor *ancestors;
17987c478bd9Sstevel@tonic-gate 	Ancestor *correctAnt;
17997c478bd9Sstevel@tonic-gate 	int tagInstance = 0;
18007c478bd9Sstevel@tonic-gate 	int instWIPayload = 0;
18017c478bd9Sstevel@tonic-gate 	uint8_t *payload;
18027c478bd9Sstevel@tonic-gate 	size_t payloadLen = 0;
18037c478bd9Sstevel@tonic-gate 	err = get_seg_and_payload(container, seg_name, instance, iter_path,
18047c478bd9Sstevel@tonic-gate 			&pathDef, &ancestors, &correctAnt, &tagInstance,
18057c478bd9Sstevel@tonic-gate 			&instWIPayload, &payload, &payloadLen);
18067c478bd9Sstevel@tonic-gate 
18077c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
18087c478bd9Sstevel@tonic-gate 
18097c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
18107c478bd9Sstevel@tonic-gate 		return (err);
18117c478bd9Sstevel@tonic-gate 	}
18127c478bd9Sstevel@tonic-gate 
18137c478bd9Sstevel@tonic-gate 	if (pathDef == NULL) { // SPECIAL CASE of UNKNOW payload.
18147c478bd9Sstevel@tonic-gate 		// clean up memory from called functions.
18157c478bd9Sstevel@tonic-gate 		err = FRU_INVALPATH;
18167c478bd9Sstevel@tonic-gate 	} else {
18177c478bd9Sstevel@tonic-gate 		// get the specific data
18187c478bd9Sstevel@tonic-gate 		err = PayloadReader::findIterThere(pathDef, correctAnt,
18197c478bd9Sstevel@tonic-gate 						instWIPayload,
18207c478bd9Sstevel@tonic-gate 						payload, payloadLen,
18217c478bd9Sstevel@tonic-gate 						num_there);
18227c478bd9Sstevel@tonic-gate 	}
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	delete pathDef;
18257c478bd9Sstevel@tonic-gate 	free(payload);
18267c478bd9Sstevel@tonic-gate 
18277c478bd9Sstevel@tonic-gate 	if (err == FRU_SUCCESS) {
18287c478bd9Sstevel@tonic-gate 		if (found_path != NULL) {
18297c478bd9Sstevel@tonic-gate 			*found_path = (char *)malloc(
18307c478bd9Sstevel@tonic-gate 				strlen(correctAnt->getPath(instWIPayload))
18317c478bd9Sstevel@tonic-gate 				+ strlen(iter_path) + 2);
18327c478bd9Sstevel@tonic-gate 			if ((*found_path) == NULL) {
18337c478bd9Sstevel@tonic-gate 				delete ancestors;
18347c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
18357c478bd9Sstevel@tonic-gate 			}
18367c478bd9Sstevel@tonic-gate 			sprintf(*found_path, "%s%s",
18377c478bd9Sstevel@tonic-gate 					correctAnt->getPath(instWIPayload),
18387c478bd9Sstevel@tonic-gate 					iter_path);
18397c478bd9Sstevel@tonic-gate 		}
18407c478bd9Sstevel@tonic-gate 	}
18417c478bd9Sstevel@tonic-gate 
18427c478bd9Sstevel@tonic-gate 	delete ancestors;
18437c478bd9Sstevel@tonic-gate 	return (err);
18447c478bd9Sstevel@tonic-gate }
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate /* ========================================================================= */
18477c478bd9Sstevel@tonic-gate // When adding a new payload with 0 data the iteration control bytes must be
18487c478bd9Sstevel@tonic-gate // filled in with the number possible.
18497c478bd9Sstevel@tonic-gate fru_errno_t
fill_in_iteration_control_bytes(uint8_t * data,const fru_regdef_t * def,int inIteration)18507c478bd9Sstevel@tonic-gate fill_in_iteration_control_bytes(uint8_t *data,
18517c478bd9Sstevel@tonic-gate 				const fru_regdef_t *def,
18527c478bd9Sstevel@tonic-gate 				int inIteration)
18537c478bd9Sstevel@tonic-gate {
18547c478bd9Sstevel@tonic-gate 	fru_errno_t rc = FRU_SUCCESS;
18557c478bd9Sstevel@tonic-gate 
18567c478bd9Sstevel@tonic-gate 	if ((def->iterationType == FRU_NOT_ITERATED) ||
18577c478bd9Sstevel@tonic-gate 		(inIteration)) {
18587c478bd9Sstevel@tonic-gate 
18597c478bd9Sstevel@tonic-gate 		if (def->dataType == FDTYPE_Record) {
18607c478bd9Sstevel@tonic-gate 
18617c478bd9Sstevel@tonic-gate 			int offset = 0;
18627c478bd9Sstevel@tonic-gate 			for (int i = 0; i < def->enumCount; i++) {
18637c478bd9Sstevel@tonic-gate 				const fru_regdef_t *newDef
18647c478bd9Sstevel@tonic-gate 	= fru_reg_lookup_def_by_name((char *)def->enumTable[i].text);
18657c478bd9Sstevel@tonic-gate 				fru_errno_t rc2
18667c478bd9Sstevel@tonic-gate 	= fill_in_iteration_control_bytes(&(data[offset]), newDef, 0);
18677c478bd9Sstevel@tonic-gate 				if (rc2 != FRU_SUCCESS)
18687c478bd9Sstevel@tonic-gate 					return (rc2);
18697c478bd9Sstevel@tonic-gate 				offset += newDef->payloadLen;
18707c478bd9Sstevel@tonic-gate 			}
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate 		} // else field, no sub elements; do nothing...  ;-)
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate 	} else {
18757c478bd9Sstevel@tonic-gate 		data[3] = (char)def->iterationCount;
18767c478bd9Sstevel@tonic-gate 
18777c478bd9Sstevel@tonic-gate 		int offset = 3;
18787c478bd9Sstevel@tonic-gate 		for (int i = 0; i < def->iterationCount; i++) {
18797c478bd9Sstevel@tonic-gate 			fru_errno_t rc3
18807c478bd9Sstevel@tonic-gate 	= fill_in_iteration_control_bytes(&(data[offset]), def, 1);
18817c478bd9Sstevel@tonic-gate 			if (rc3 != FRU_SUCCESS)
18827c478bd9Sstevel@tonic-gate 				return (rc3);
18837c478bd9Sstevel@tonic-gate 			offset += ((def->payloadLen - 4)/(def->iterationCount));
18847c478bd9Sstevel@tonic-gate 		}
18857c478bd9Sstevel@tonic-gate 	}
18867c478bd9Sstevel@tonic-gate 
18877c478bd9Sstevel@tonic-gate 	return (rc);
18887c478bd9Sstevel@tonic-gate }
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate /* ========================================================================= */
18917c478bd9Sstevel@tonic-gate fru_errno_t
fru_add_element(fru_nodehdl_t container,const char * seg_name,const char * element)18927c478bd9Sstevel@tonic-gate fru_add_element(fru_nodehdl_t container,
18937c478bd9Sstevel@tonic-gate 	const char *seg_name,
18947c478bd9Sstevel@tonic-gate 	const char *element)
18957c478bd9Sstevel@tonic-gate {
18967c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate 	if ((seg_name == NULL) || (strlen(seg_name) > FRU_SEGNAMELEN)) {
18997c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
19007c478bd9Sstevel@tonic-gate 	}
19017c478bd9Sstevel@tonic-gate 
19027c478bd9Sstevel@tonic-gate 	const fru_regdef_t *def
19037c478bd9Sstevel@tonic-gate 		= fru_reg_lookup_def_by_name((char *)element);
19047c478bd9Sstevel@tonic-gate 	if (def == NULL) {
19057c478bd9Sstevel@tonic-gate 		return (FRU_NOREGDEF);
19067c478bd9Sstevel@tonic-gate 	}
19077c478bd9Sstevel@tonic-gate 	if (def->tagType == FRU_X) {
19087c478bd9Sstevel@tonic-gate 		return (FRU_ELEMNOTTAGGED);
19097c478bd9Sstevel@tonic-gate 	}
19107c478bd9Sstevel@tonic-gate 
19117c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
19127c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
19137c478bd9Sstevel@tonic-gate 	}
19147c478bd9Sstevel@tonic-gate 
19157c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
19167c478bd9Sstevel@tonic-gate 		return (err);
19177c478bd9Sstevel@tonic-gate 	}
19187c478bd9Sstevel@tonic-gate 
19197c478bd9Sstevel@tonic-gate 	if (lock_container(WRITE_LOCK, container) != FRU_SUCCESS) {
19207c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
19217c478bd9Sstevel@tonic-gate 	}
19227c478bd9Sstevel@tonic-gate 
19237c478bd9Sstevel@tonic-gate 	fru_tag_t tag;
19247c478bd9Sstevel@tonic-gate 	mk_tag(def->tagType, def->tagDense, def->payloadLen, &tag);
19257c478bd9Sstevel@tonic-gate 	uint8_t *data = new uint8_t[def->payloadLen];
19267c478bd9Sstevel@tonic-gate 	memset(data, 0x00, def->payloadLen);
19277c478bd9Sstevel@tonic-gate 
19287c478bd9Sstevel@tonic-gate 	err = fill_in_iteration_control_bytes(data, def, 0);
19297c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
19307c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
19317c478bd9Sstevel@tonic-gate 		delete[] data;
19327c478bd9Sstevel@tonic-gate 		return (err);
19337c478bd9Sstevel@tonic-gate 	}
19347c478bd9Sstevel@tonic-gate 
19357c478bd9Sstevel@tonic-gate 	if (segment_is_encrypted(container, seg_name)) {
19367c478bd9Sstevel@tonic-gate 		if (fru_encryption_supported() == FRU_NOTSUP) {
19377c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
19387c478bd9Sstevel@tonic-gate 			delete[] data;
19397c478bd9Sstevel@tonic-gate 			return (FRU_INVALSEG);
19407c478bd9Sstevel@tonic-gate 		}
19417c478bd9Sstevel@tonic-gate 		if ((err = encrypt_func(FRU_ENCRYPT, data,
19427c478bd9Sstevel@tonic-gate 				def->payloadLen)) != FRU_SUCCESS) {
19437c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
19447c478bd9Sstevel@tonic-gate 			delete[] data;
19457c478bd9Sstevel@tonic-gate 			return (err);
19467c478bd9Sstevel@tonic-gate 		}
19477c478bd9Sstevel@tonic-gate 	}
1948*1da57d55SToomas Soome 
194935551380Skmohan 	RETRY(err = data_source->add_tag_to_seg(NODEHDL_TO_TREEHDL(container),
195035551380Skmohan 					seg_name, tag, data, def->payloadLen))
19517c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
19527c478bd9Sstevel@tonic-gate 	delete[] data;
19537c478bd9Sstevel@tonic-gate 	return (err);
19547c478bd9Sstevel@tonic-gate }
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate /* ========================================================================= */
19577c478bd9Sstevel@tonic-gate fru_errno_t
fru_delete_element(fru_nodehdl_t container,const char * seg_name,unsigned int instance,const char * element)19587c478bd9Sstevel@tonic-gate fru_delete_element(fru_nodehdl_t container,
19597c478bd9Sstevel@tonic-gate 		const char *seg_name,
19607c478bd9Sstevel@tonic-gate 		unsigned int   instance,
19617c478bd9Sstevel@tonic-gate 		const char *element)
19627c478bd9Sstevel@tonic-gate {
19637c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 	if ((seg_name == NULL) || (strlen(seg_name) > FRU_SEGNAMELEN)) {
19667c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
19677c478bd9Sstevel@tonic-gate 	}
19687c478bd9Sstevel@tonic-gate 
19697c478bd9Sstevel@tonic-gate 	if (data_source == NULL) {
19707c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
19717c478bd9Sstevel@tonic-gate 	}
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 	if ((err = is_container(container)) != FRU_SUCCESS) {
19747c478bd9Sstevel@tonic-gate 		return (err);
19757c478bd9Sstevel@tonic-gate 	}
19767c478bd9Sstevel@tonic-gate 
19777c478bd9Sstevel@tonic-gate 	if (lock_container(WRITE_LOCK, container) != FRU_SUCCESS) {
19787c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
19797c478bd9Sstevel@tonic-gate 	}
19807c478bd9Sstevel@tonic-gate 	if ((segment_is_encrypted(container, seg_name)) &&
19817c478bd9Sstevel@tonic-gate 		(fru_encryption_supported() == FRU_NOTSUP)) {
19827c478bd9Sstevel@tonic-gate 		CHK_UNLOCK_CONTAINER(container);
19837c478bd9Sstevel@tonic-gate 		return (FRU_INVALSEG);
19847c478bd9Sstevel@tonic-gate 	}
19857c478bd9Sstevel@tonic-gate 
19867c478bd9Sstevel@tonic-gate 	fru_tag_t tag;
19877c478bd9Sstevel@tonic-gate 	int localInst = instance;
19887c478bd9Sstevel@tonic-gate 	// again the special case of UNKNOWN.  This allows us to delete these
19897c478bd9Sstevel@tonic-gate 	// elements if they are somehow not wanted.
19907c478bd9Sstevel@tonic-gate 	// NOTE: "/UNKNOWN" is not supported just as "/ManR" would not be valid
19917c478bd9Sstevel@tonic-gate 	// either.  Both of these will result in returning FRU_NOREGDEF
19927c478bd9Sstevel@tonic-gate 	if (strcmp(element, "UNKNOWN") == 0) {
19937c478bd9Sstevel@tonic-gate 		fru_tag_t *tags = NULL;
19947c478bd9Sstevel@tonic-gate 		int num_tags = 0;
19957c478bd9Sstevel@tonic-gate 
199635551380Skmohan 		RETRY(err =
199735551380Skmohan 			data_source->get_tag_list(NODEHDL_TO_TREEHDL(container),
199835551380Skmohan 						seg_name, &tags, &num_tags))
1999*1da57d55SToomas Soome 
200035551380Skmohan 		if (err != FRU_SUCCESS) {
20017c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
20027c478bd9Sstevel@tonic-gate 			return (err);
20037c478bd9Sstevel@tonic-gate 		}
20047c478bd9Sstevel@tonic-gate 		if ((err = find_unknown_element(tags, num_tags,
20057c478bd9Sstevel@tonic-gate 			&localInst, &tag)) != FRU_SUCCESS) {
20067c478bd9Sstevel@tonic-gate 			free(tags);
20077c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
20087c478bd9Sstevel@tonic-gate 			return (err);
20097c478bd9Sstevel@tonic-gate 		}
20107c478bd9Sstevel@tonic-gate 		free(tags);
20117c478bd9Sstevel@tonic-gate 	} else {
20127c478bd9Sstevel@tonic-gate 		const fru_regdef_t *def
20137c478bd9Sstevel@tonic-gate 			= fru_reg_lookup_def_by_name((char *)element);
20147c478bd9Sstevel@tonic-gate 		if (def == NULL) {
20157c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
20167c478bd9Sstevel@tonic-gate 			return (FRU_NOREGDEF);
20177c478bd9Sstevel@tonic-gate 		}
20187c478bd9Sstevel@tonic-gate 		if (def->tagType == FRU_X) {
20197c478bd9Sstevel@tonic-gate 			CHK_UNLOCK_CONTAINER(container);
20207c478bd9Sstevel@tonic-gate 			return (FRU_ELEMNOTTAGGED);
20217c478bd9Sstevel@tonic-gate 		}
20227c478bd9Sstevel@tonic-gate 		mk_tag(def->tagType, def->tagDense, def->payloadLen, &tag);
20237c478bd9Sstevel@tonic-gate 	}
2024*1da57d55SToomas Soome 
202535551380Skmohan 	RETRY(err = data_source->delete_tag(NODEHDL_TO_TREEHDL(container),
202635551380Skmohan 						seg_name, tag, instance))
20277c478bd9Sstevel@tonic-gate 	CHK_UNLOCK_CONTAINER(container);
20287c478bd9Sstevel@tonic-gate 	return (err);
20297c478bd9Sstevel@tonic-gate }
20307c478bd9Sstevel@tonic-gate 
20317c478bd9Sstevel@tonic-gate /* General library support */
20327c478bd9Sstevel@tonic-gate /* ========================================================================= */
20337c478bd9Sstevel@tonic-gate static fru_errno_t
make_definition(const fru_regdef_t * def,fru_elemdef_t * definition)20347c478bd9Sstevel@tonic-gate make_definition(const fru_regdef_t *def, fru_elemdef_t *definition)
20357c478bd9Sstevel@tonic-gate {
20367c478bd9Sstevel@tonic-gate 	definition->version = FRU_ELEMDEF_REV;
20377c478bd9Sstevel@tonic-gate 	definition->data_type = def->dataType;
20387c478bd9Sstevel@tonic-gate 	if (def->tagType != FRU_X)
20397c478bd9Sstevel@tonic-gate 		definition->tagged = FRU_Yes;
20407c478bd9Sstevel@tonic-gate 	else
20417c478bd9Sstevel@tonic-gate 		definition->tagged = FRU_No;
20427c478bd9Sstevel@tonic-gate 
20437c478bd9Sstevel@tonic-gate 	// zzz
20447c478bd9Sstevel@tonic-gate 	// This should be the following statement.
20457c478bd9Sstevel@tonic-gate 	// (*definition)->data_length = def->dataLength;
20467c478bd9Sstevel@tonic-gate 	// instead of.
20477c478bd9Sstevel@tonic-gate 	if (def->iterationType != FRU_NOT_ITERATED) {
20487c478bd9Sstevel@tonic-gate 		int elemLen = ((def->dataLength-4)/def->iterationCount);
20497c478bd9Sstevel@tonic-gate 		definition->data_length = elemLen;
20507c478bd9Sstevel@tonic-gate 	} else {
20517c478bd9Sstevel@tonic-gate 		definition->data_length = def->dataLength;
20527c478bd9Sstevel@tonic-gate 	}
20537c478bd9Sstevel@tonic-gate 	// END zzz
20547c478bd9Sstevel@tonic-gate 
20557c478bd9Sstevel@tonic-gate 	definition->disp_type = def->dispType;
20567c478bd9Sstevel@tonic-gate 	definition->purgeable = def->purgeable;
20577c478bd9Sstevel@tonic-gate 	definition->relocatable = def->relocatable;
20587c478bd9Sstevel@tonic-gate 
20597c478bd9Sstevel@tonic-gate 	definition->enum_count = 0;
20607c478bd9Sstevel@tonic-gate 	definition->enum_table = NULL;
20617c478bd9Sstevel@tonic-gate 
20627c478bd9Sstevel@tonic-gate 	unsigned int count = def->enumCount;
20637c478bd9Sstevel@tonic-gate 	if (count != 0) {
20647c478bd9Sstevel@tonic-gate 		definition->enum_table = (fru_enum_t *)malloc(
20657c478bd9Sstevel@tonic-gate 					(sizeof (fru_enum_t)) * count);
20667c478bd9Sstevel@tonic-gate 		if ((definition->enum_table) == NULL) {
20677c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
20687c478bd9Sstevel@tonic-gate 		}
20697c478bd9Sstevel@tonic-gate 		memset(definition->enum_table, 0x00,
20707c478bd9Sstevel@tonic-gate 					((sizeof (fru_enum_t)) * count));
20717c478bd9Sstevel@tonic-gate 	}
20727c478bd9Sstevel@tonic-gate 
20737c478bd9Sstevel@tonic-gate 	for (int i = 0; i < count; i++) {
20747c478bd9Sstevel@tonic-gate 		definition->enum_table[i].value = def->enumTable[i].value;
20757c478bd9Sstevel@tonic-gate 		definition->enum_table[i].text = strdup(def->enumTable[i].text);
20767c478bd9Sstevel@tonic-gate 		if ((definition->enum_table[i].text) == NULL) {
20777c478bd9Sstevel@tonic-gate 			fru_destroy_elemdef(definition);
20787c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
20797c478bd9Sstevel@tonic-gate 		}
20807c478bd9Sstevel@tonic-gate 		(definition->enum_count)++;
20817c478bd9Sstevel@tonic-gate 	}
20827c478bd9Sstevel@tonic-gate 
20837c478bd9Sstevel@tonic-gate 	definition->iteration_count = def->iterationCount;
20847c478bd9Sstevel@tonic-gate 	definition->iteration_type = def->iterationType;
20857c478bd9Sstevel@tonic-gate 
20867c478bd9Sstevel@tonic-gate 	definition->example_string = strdup(def->exampleString);
20877c478bd9Sstevel@tonic-gate 	if ((definition->example_string) == NULL) {
20887c478bd9Sstevel@tonic-gate 		fru_destroy_elemdef(definition);
20897c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
20907c478bd9Sstevel@tonic-gate 	}
20917c478bd9Sstevel@tonic-gate 
20927c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
20937c478bd9Sstevel@tonic-gate }
20947c478bd9Sstevel@tonic-gate 
20957c478bd9Sstevel@tonic-gate /* ========================================================================= */
20967c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_definition(const char * element_name,fru_elemdef_t * definition)20977c478bd9Sstevel@tonic-gate fru_get_definition(const char *element_name,
20987c478bd9Sstevel@tonic-gate 			fru_elemdef_t *definition)
20997c478bd9Sstevel@tonic-gate {
21007c478bd9Sstevel@tonic-gate 	// find the last one in the string...
21017c478bd9Sstevel@tonic-gate 	int abs_path_flg = 0;
21027c478bd9Sstevel@tonic-gate 	Ancestor *ancestors = NULL;
21037c478bd9Sstevel@tonic-gate 	PathDef *pathDef = NULL;
21047c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
21057c478bd9Sstevel@tonic-gate 
21067c478bd9Sstevel@tonic-gate 	err = fru_field_parser(element_name, &ancestors,
21077c478bd9Sstevel@tonic-gate 					&abs_path_flg, &pathDef);
21087c478bd9Sstevel@tonic-gate 	if (err != FRU_SUCCESS) {
21097c478bd9Sstevel@tonic-gate 		return (err);
21107c478bd9Sstevel@tonic-gate 	}
21117c478bd9Sstevel@tonic-gate 
21127c478bd9Sstevel@tonic-gate 	PathDef *last = pathDef;
21137c478bd9Sstevel@tonic-gate 	while (last->next != NULL)
21147c478bd9Sstevel@tonic-gate 		last = last->next;
21157c478bd9Sstevel@tonic-gate 
21167c478bd9Sstevel@tonic-gate 	err = make_definition(last->def, definition);
21177c478bd9Sstevel@tonic-gate 
21187c478bd9Sstevel@tonic-gate 	delete ancestors;
21197c478bd9Sstevel@tonic-gate 	delete pathDef;
21207c478bd9Sstevel@tonic-gate 	return (err);
21217c478bd9Sstevel@tonic-gate }
21227c478bd9Sstevel@tonic-gate 
21237c478bd9Sstevel@tonic-gate /* ========================================================================= */
21247c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_registry(fru_strlist_t * list)21257c478bd9Sstevel@tonic-gate fru_get_registry(fru_strlist_t *list)
21267c478bd9Sstevel@tonic-gate {
21277c478bd9Sstevel@tonic-gate 	fru_errno_t err = FRU_SUCCESS;
21287c478bd9Sstevel@tonic-gate 	unsigned int number = 0;
21297c478bd9Sstevel@tonic-gate 	char **entries = fru_reg_list_entries(&number);
21307c478bd9Sstevel@tonic-gate 	if (entries == NULL) {
21317c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
21327c478bd9Sstevel@tonic-gate 	}
21337c478bd9Sstevel@tonic-gate 	list->strs = entries;
21347c478bd9Sstevel@tonic-gate 	list->num = number;
21357c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
21367c478bd9Sstevel@tonic-gate }
21377c478bd9Sstevel@tonic-gate 
21387c478bd9Sstevel@tonic-gate /* ========================================================================= */
21397c478bd9Sstevel@tonic-gate fru_errno_t
fru_get_tagged_parents(const char * element,fru_strlist_t * parents)21407c478bd9Sstevel@tonic-gate fru_get_tagged_parents(const char *element, fru_strlist_t *parents)
21417c478bd9Sstevel@tonic-gate {
21427c478bd9Sstevel@tonic-gate 	Ancestor *ancestors
21437c478bd9Sstevel@tonic-gate 		= Ancestor::listTaggedAncestors((char *)element);
21447c478bd9Sstevel@tonic-gate 
21457c478bd9Sstevel@tonic-gate 	Ancestor *cur = ancestors;
21467c478bd9Sstevel@tonic-gate 	/* count them */
21477c478bd9Sstevel@tonic-gate 	int number = 0;
21487c478bd9Sstevel@tonic-gate 	while (cur != NULL) {
21497c478bd9Sstevel@tonic-gate 		number++;
21507c478bd9Sstevel@tonic-gate 		cur = cur->next;
21517c478bd9Sstevel@tonic-gate 	}
21527c478bd9Sstevel@tonic-gate 
21537c478bd9Sstevel@tonic-gate 	parents->num = 0;
21547c478bd9Sstevel@tonic-gate 	parents->strs = NULL;
21557c478bd9Sstevel@tonic-gate 	if (number == 0) {
21567c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
21577c478bd9Sstevel@tonic-gate 	}
21587c478bd9Sstevel@tonic-gate 	parents->strs = (char **)malloc(number * sizeof (char *));
21597c478bd9Sstevel@tonic-gate 	if (parents->strs == NULL) {
21607c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
21617c478bd9Sstevel@tonic-gate 	}
21627c478bd9Sstevel@tonic-gate 	memset(parents->strs, 0x00, (number * sizeof (char *)));
21637c478bd9Sstevel@tonic-gate 
21647c478bd9Sstevel@tonic-gate 	cur = ancestors;
21657c478bd9Sstevel@tonic-gate 	for (int i = 0; i < number; i++) {
21667c478bd9Sstevel@tonic-gate 		if (cur == NULL) {
21677c478bd9Sstevel@tonic-gate 			fru_destroy_strlist(parents);
21687c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
21697c478bd9Sstevel@tonic-gate 		}
21707c478bd9Sstevel@tonic-gate 		parents->strs[i] = strdup(cur->getDef()->name);
21717c478bd9Sstevel@tonic-gate 		if (parents->strs[i] == NULL) {
21727c478bd9Sstevel@tonic-gate 			fru_destroy_strlist(parents);
21737c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
21747c478bd9Sstevel@tonic-gate 		}
21757c478bd9Sstevel@tonic-gate 		parents->num++;
21767c478bd9Sstevel@tonic-gate 		cur = cur->next;
21777c478bd9Sstevel@tonic-gate 	}
21787c478bd9Sstevel@tonic-gate 
21797c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
21807c478bd9Sstevel@tonic-gate }
21817c478bd9Sstevel@tonic-gate 
21827c478bd9Sstevel@tonic-gate /*
21837c478bd9Sstevel@tonic-gate  * Enum string converters.
21847c478bd9Sstevel@tonic-gate  */
21857c478bd9Sstevel@tonic-gate /* ========================================================================= */
21867c478bd9Sstevel@tonic-gate const char *
get_displaytype_str(fru_displaytype_t e)21877c478bd9Sstevel@tonic-gate get_displaytype_str(fru_displaytype_t e)
21887c478bd9Sstevel@tonic-gate {
21897c478bd9Sstevel@tonic-gate 	switch (e) {
21907c478bd9Sstevel@tonic-gate 		case FDISP_Binary:
21917c478bd9Sstevel@tonic-gate 			return (gettext("Binary"));
21927c478bd9Sstevel@tonic-gate 		case FDISP_Hex:
21937c478bd9Sstevel@tonic-gate 			return (gettext("Hex"));
21947c478bd9Sstevel@tonic-gate 		case FDISP_Decimal:
21957c478bd9Sstevel@tonic-gate 			return (gettext("Decimal"));
21967c478bd9Sstevel@tonic-gate 		case FDISP_Octal:
21977c478bd9Sstevel@tonic-gate 			return (gettext("Octal"));
21987c478bd9Sstevel@tonic-gate 		case FDISP_String:
21997c478bd9Sstevel@tonic-gate 			return (gettext("String"));
22007c478bd9Sstevel@tonic-gate 		case FDISP_Time:
22017c478bd9Sstevel@tonic-gate 			return (gettext("Time"));
22027c478bd9Sstevel@tonic-gate 		case FDISP_UNDEFINED:
22037c478bd9Sstevel@tonic-gate 			return (gettext("UNDEFINED"));
22047c478bd9Sstevel@tonic-gate 	}
22057c478bd9Sstevel@tonic-gate 	return (gettext("UNDEFINED"));
22067c478bd9Sstevel@tonic-gate }
22077c478bd9Sstevel@tonic-gate 
22087c478bd9Sstevel@tonic-gate /* ========================================================================= */
22097c478bd9Sstevel@tonic-gate const char *
get_datatype_str(fru_datatype_t e)22107c478bd9Sstevel@tonic-gate get_datatype_str(fru_datatype_t e)
22117c478bd9Sstevel@tonic-gate {
22127c478bd9Sstevel@tonic-gate 	switch (e) {
22137c478bd9Sstevel@tonic-gate 		case FDTYPE_Binary:
22147c478bd9Sstevel@tonic-gate 			return (gettext("Binary"));
22157c478bd9Sstevel@tonic-gate 		case FDTYPE_ByteArray:
22167c478bd9Sstevel@tonic-gate 			return (gettext("Byte Array"));
22177c478bd9Sstevel@tonic-gate 		case FDTYPE_ASCII:
22187c478bd9Sstevel@tonic-gate 			return (gettext("ASCII"));
22197c478bd9Sstevel@tonic-gate 		case FDTYPE_Unicode:
22207c478bd9Sstevel@tonic-gate 			return (gettext("Unicode"));
22217c478bd9Sstevel@tonic-gate 		case FDTYPE_Record:
22227c478bd9Sstevel@tonic-gate 			return (gettext("Record"));
22237c478bd9Sstevel@tonic-gate 		case FDTYPE_Enumeration:
22247c478bd9Sstevel@tonic-gate 			return (gettext("Enumeration"));
22257c478bd9Sstevel@tonic-gate 		case FDTYPE_UNDEFINED:
22267c478bd9Sstevel@tonic-gate 			return (gettext("UNDEFINED"));
22277c478bd9Sstevel@tonic-gate 	}
22287c478bd9Sstevel@tonic-gate 	return (gettext("UNDEFINED"));
22297c478bd9Sstevel@tonic-gate }
22307c478bd9Sstevel@tonic-gate /* ========================================================================= */
22317c478bd9Sstevel@tonic-gate const char *
get_which_str(fru_which_t e)22327c478bd9Sstevel@tonic-gate get_which_str(fru_which_t e)
22337c478bd9Sstevel@tonic-gate {
22347c478bd9Sstevel@tonic-gate 	switch (e) {
22357c478bd9Sstevel@tonic-gate 		case FRU_No:
22367c478bd9Sstevel@tonic-gate 			return (gettext("No"));
22377c478bd9Sstevel@tonic-gate 		case FRU_Yes:
22387c478bd9Sstevel@tonic-gate 			return (gettext("Yes"));
22397c478bd9Sstevel@tonic-gate 		case FRU_WHICH_UNDEFINED:
22407c478bd9Sstevel@tonic-gate 			return (gettext("WHICH UNDEFINED"));
22417c478bd9Sstevel@tonic-gate 	}
22427c478bd9Sstevel@tonic-gate 	return (gettext("WHICH UNDEFINED"));
22437c478bd9Sstevel@tonic-gate }
22447c478bd9Sstevel@tonic-gate /* ========================================================================= */
22457c478bd9Sstevel@tonic-gate const char *
get_itertype_str(fru_itertype_t e)22467c478bd9Sstevel@tonic-gate get_itertype_str(fru_itertype_t e)
22477c478bd9Sstevel@tonic-gate {
22487c478bd9Sstevel@tonic-gate 	switch (e) {
22497c478bd9Sstevel@tonic-gate 		case FRU_FIFO:
22507c478bd9Sstevel@tonic-gate 			return (gettext("FIFO"));
22517c478bd9Sstevel@tonic-gate 		case FRU_Circular:
22527c478bd9Sstevel@tonic-gate 			return (gettext("Circular"));
22537c478bd9Sstevel@tonic-gate 		case FRU_Linear:
22547c478bd9Sstevel@tonic-gate 			return (gettext("Linear"));
22557c478bd9Sstevel@tonic-gate 		case FRU_LIFO:
22567c478bd9Sstevel@tonic-gate 			return (gettext("LIFO"));
22577c478bd9Sstevel@tonic-gate 		case FRU_NOT_ITERATED:
22587c478bd9Sstevel@tonic-gate 			return (gettext("NOT ITERATED"));
22597c478bd9Sstevel@tonic-gate 	}
22607c478bd9Sstevel@tonic-gate 	return (gettext("NOT ITERATED"));
22617c478bd9Sstevel@tonic-gate }
2262