xref: /titanic_41/usr/src/lib/libfru/libfru/PayloadReader.cc (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <string.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #include "PayloadReader.h"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #define	ITER_CONT_BYTE_LEN 4
35*7c478bd9Sstevel@tonic-gate #define	IS_ITERATED(pathDef) \
36*7c478bd9Sstevel@tonic-gate (pathDef->def->iterationType != FRU_NOT_ITERATED)
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate // functions to place bit data properly.
39*7c478bd9Sstevel@tonic-gate static fru_errno_t
40*7c478bd9Sstevel@tonic-gate writeBits(uint64_t bitData, size_t bitLength,
41*7c478bd9Sstevel@tonic-gate 	uint8_t *data, size_t dataLength, size_t bitOffset)
42*7c478bd9Sstevel@tonic-gate {
43*7c478bd9Sstevel@tonic-gate 	if ((bitLength > 64) &&
44*7c478bd9Sstevel@tonic-gate 		(bitOffset > 64) &&
45*7c478bd9Sstevel@tonic-gate 		(dataLength > 8) &&
46*7c478bd9Sstevel@tonic-gate 		(bitOffset > (dataLength * 8)))
47*7c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
48*7c478bd9Sstevel@tonic-gate 	// move the bit data into place
49*7c478bd9Sstevel@tonic-gate 	bitData = (bitData << (64-bitLength));
50*7c478bd9Sstevel@tonic-gate 	bitData = (bitData >> bitOffset);
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate 	// create a mask to clear the old data.
53*7c478bd9Sstevel@tonic-gate 	uint64_t mask = 0;
54*7c478bd9Sstevel@tonic-gate 	for (size_t i = 0; i < bitLength; i++) {
55*7c478bd9Sstevel@tonic-gate 		mask = ((mask << 1) + 1);
56*7c478bd9Sstevel@tonic-gate 	}
57*7c478bd9Sstevel@tonic-gate 	mask = (mask << (64-bitLength));
58*7c478bd9Sstevel@tonic-gate 	mask = (mask >> bitOffset);
59*7c478bd9Sstevel@tonic-gate 	mask = (mask ^ 0xFFFFFFFFFFFFFFFF);
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	// get the data out of the byte array.
62*7c478bd9Sstevel@tonic-gate 	uint64_t rd = 0;
63*7c478bd9Sstevel@tonic-gate 	memcpy((void *)&rd, (void *)data, dataLength);
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 	// clear the old data
66*7c478bd9Sstevel@tonic-gate 	rd = (rd & mask);
67*7c478bd9Sstevel@tonic-gate 	// put in the new data.
68*7c478bd9Sstevel@tonic-gate 	rd = (rd | bitData);
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate 	// write the data back to the buffer.
71*7c478bd9Sstevel@tonic-gate 	memcpy((void *)data, (void *)&rd, dataLength);
72*7c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate static fru_errno_t
76*7c478bd9Sstevel@tonic-gate readBits(size_t bitLength, uint8_t *data,
77*7c478bd9Sstevel@tonic-gate 	size_t dataLength, int bitOffset, uint64_t *ret)
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate 	if ((bitLength > 64) ||
80*7c478bd9Sstevel@tonic-gate 		(bitLength < 0) ||
81*7c478bd9Sstevel@tonic-gate 		(bitOffset > 64) ||
82*7c478bd9Sstevel@tonic-gate 		(dataLength > 8) ||
83*7c478bd9Sstevel@tonic-gate 		(bitOffset > (dataLength * 8)))
84*7c478bd9Sstevel@tonic-gate 		return (FRU_FAILURE);
85*7c478bd9Sstevel@tonic-gate 	// get the data out of the byte array.
86*7c478bd9Sstevel@tonic-gate 	uint64_t rc = 0;
87*7c478bd9Sstevel@tonic-gate 	memcpy((void *)&rc, (void *)data, dataLength);
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	rc = (rc << bitOffset);
90*7c478bd9Sstevel@tonic-gate 	rc = (rc >> (64 - bitLength));
91*7c478bd9Sstevel@tonic-gate 	*ret = rc;
92*7c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
93*7c478bd9Sstevel@tonic-gate }
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate // ===========================================================================
96*7c478bd9Sstevel@tonic-gate // caller is to be sure elemDef is contained by recDef.
97*7c478bd9Sstevel@tonic-gate int
98*7c478bd9Sstevel@tonic-gate PayloadReader::getOffsetIntoRecord(fru_regdef_t *recDef,
99*7c478bd9Sstevel@tonic-gate 				fru_regdef_t *elemDef)
100*7c478bd9Sstevel@tonic-gate {
101*7c478bd9Sstevel@tonic-gate 	int rc = 0;
102*7c478bd9Sstevel@tonic-gate 	for (int i = 0; i < recDef->enumCount; i++) {
103*7c478bd9Sstevel@tonic-gate 		if (strcmp(recDef->enumTable[i].text, elemDef->name) == 0)
104*7c478bd9Sstevel@tonic-gate 			return (rc);
105*7c478bd9Sstevel@tonic-gate 		const fru_regdef_t *tmpDef = fru_reg_lookup_def_by_name(
106*7c478bd9Sstevel@tonic-gate 					(char *)recDef->enumTable[i].text);
107*7c478bd9Sstevel@tonic-gate 		rc += tmpDef->payloadLen;
108*7c478bd9Sstevel@tonic-gate 	}
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate }
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate // ===========================================================================
113*7c478bd9Sstevel@tonic-gate // return -1 on error.
114*7c478bd9Sstevel@tonic-gate int
115*7c478bd9Sstevel@tonic-gate PayloadReader::calcOffset(int iterType,
116*7c478bd9Sstevel@tonic-gate 			uint8_t head, uint8_t tail,
117*7c478bd9Sstevel@tonic-gate 			uint8_t iterThere, uint8_t iterPoss,
118*7c478bd9Sstevel@tonic-gate 			size_t length, int index,
119*7c478bd9Sstevel@tonic-gate 			fru_errno_t *err)
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate 	*err = FRU_SUCCESS;
122*7c478bd9Sstevel@tonic-gate 	switch (iterType) {
123*7c478bd9Sstevel@tonic-gate 		case FRU_FIFO:
124*7c478bd9Sstevel@tonic-gate 		case FRU_Linear:
125*7c478bd9Sstevel@tonic-gate 		{
126*7c478bd9Sstevel@tonic-gate 			if (index == PathDef::lastIteration)
127*7c478bd9Sstevel@tonic-gate 				return (length * tail);
128*7c478bd9Sstevel@tonic-gate 			return (length * index);
129*7c478bd9Sstevel@tonic-gate 		break;
130*7c478bd9Sstevel@tonic-gate 		}
131*7c478bd9Sstevel@tonic-gate 		case FRU_Circular:
132*7c478bd9Sstevel@tonic-gate 		case FRU_LIFO:
133*7c478bd9Sstevel@tonic-gate 		{
134*7c478bd9Sstevel@tonic-gate 			if (index == PathDef::lastIteration) {
135*7c478bd9Sstevel@tonic-gate 				if (iterType == FRU_LIFO)
136*7c478bd9Sstevel@tonic-gate 					return (length * head);
137*7c478bd9Sstevel@tonic-gate 				return (length * tail);
138*7c478bd9Sstevel@tonic-gate 			}
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 			// For reading they are oposite.
141*7c478bd9Sstevel@tonic-gate 			if (iterType == FRU_Circular) {
142*7c478bd9Sstevel@tonic-gate 				return (length * ((head + index) % iterPoss));
143*7c478bd9Sstevel@tonic-gate 			} else {
144*7c478bd9Sstevel@tonic-gate 				int abs = tail - index;
145*7c478bd9Sstevel@tonic-gate 				if (abs < 0)
146*7c478bd9Sstevel@tonic-gate 					// abs is negative here
147*7c478bd9Sstevel@tonic-gate 					abs = iterPoss + abs;
148*7c478bd9Sstevel@tonic-gate 				return (length * abs);
149*7c478bd9Sstevel@tonic-gate 			}
150*7c478bd9Sstevel@tonic-gate 		break;
151*7c478bd9Sstevel@tonic-gate 		}
152*7c478bd9Sstevel@tonic-gate 	}
153*7c478bd9Sstevel@tonic-gate 	*err = FRU_FAILURE;
154*7c478bd9Sstevel@tonic-gate 	return (-1);
155*7c478bd9Sstevel@tonic-gate }
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate // ===========================================================================
158*7c478bd9Sstevel@tonic-gate // return -1 on error.
159*7c478bd9Sstevel@tonic-gate int
160*7c478bd9Sstevel@tonic-gate PayloadReader::getIterationOffset(uint8_t *iter, int iterLen,
161*7c478bd9Sstevel@tonic-gate 				PathDef *path, int *rcIterThere,
162*7c478bd9Sstevel@tonic-gate 				fru_errno_t *err,
163*7c478bd9Sstevel@tonic-gate 				int onlyFindingIterThereFlag)
164*7c478bd9Sstevel@tonic-gate {
165*7c478bd9Sstevel@tonic-gate 	int rc = 0;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	// read the iteration control bytes first because we may ONLY need
168*7c478bd9Sstevel@tonic-gate 	// them.
169*7c478bd9Sstevel@tonic-gate 	uint8_t head = iter[0];
170*7c478bd9Sstevel@tonic-gate 	uint8_t tail = iter[1];
171*7c478bd9Sstevel@tonic-gate 	uint8_t iterThere = iter[2];
172*7c478bd9Sstevel@tonic-gate 	uint8_t iterPoss = iter[3];
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	// the '+' symbol on anything is an error here
175*7c478bd9Sstevel@tonic-gate 	if (path->iterIndex == PathDef::addIteration) {
176*7c478bd9Sstevel@tonic-gate 		*err = FRU_INVALPATH;
177*7c478bd9Sstevel@tonic-gate 		return (-1);
178*7c478bd9Sstevel@tonic-gate 	}
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	// check assumptions for next calls.
181*7c478bd9Sstevel@tonic-gate 	if (iterPoss != path->def->iterationCount) {
182*7c478bd9Sstevel@tonic-gate 		*err = FRU_DATACORRUPT;
183*7c478bd9Sstevel@tonic-gate 		return (-1);
184*7c478bd9Sstevel@tonic-gate 	}
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	if (onlyFindingIterThereFlag == ITER_THERE_ONLY) {
187*7c478bd9Sstevel@tonic-gate 		if (rcIterThere != NULL) {
188*7c478bd9Sstevel@tonic-gate 			*rcIterThere = iterThere;
189*7c478bd9Sstevel@tonic-gate 		}
190*7c478bd9Sstevel@tonic-gate 		*err = FRU_SUCCESS;
191*7c478bd9Sstevel@tonic-gate 		return (ITER_CONT_BYTE_LEN);
192*7c478bd9Sstevel@tonic-gate 	}
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	if ((path->iterIndex != PathDef::addIteration) &&
195*7c478bd9Sstevel@tonic-gate 		(path->iterIndex != PathDef::lastIteration) &&
196*7c478bd9Sstevel@tonic-gate 		(path->iterIndex >= iterThere)) {
197*7c478bd9Sstevel@tonic-gate 		*err = FRU_DATANOTFOUND;
198*7c478bd9Sstevel@tonic-gate 		return (-1);
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	// don't forget to skip the iteration control bytes!!!
202*7c478bd9Sstevel@tonic-gate 	int length = ((path->def->payloadLen - ITER_CONT_BYTE_LEN)
203*7c478bd9Sstevel@tonic-gate 			/path->def->iterationCount);
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	rc = calcOffset(path->def->iterationType,
206*7c478bd9Sstevel@tonic-gate 			head, tail, iterThere, iterPoss,
207*7c478bd9Sstevel@tonic-gate 			length, path->iterIndex, err);
208*7c478bd9Sstevel@tonic-gate 	if (rc == -1) {
209*7c478bd9Sstevel@tonic-gate 		// error set by calcOffset
210*7c478bd9Sstevel@tonic-gate 		return (-1);
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	*err = FRU_SUCCESS;
214*7c478bd9Sstevel@tonic-gate 	return (ITER_CONT_BYTE_LEN + rc);
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate // ===========================================================================
218*7c478bd9Sstevel@tonic-gate // Iff onlyFindingIterThereFlag is set data is ignored and dataLen will be set
219*7c478bd9Sstevel@tonic-gate // to the number of iterations which are actually in the seeprom.
220*7c478bd9Sstevel@tonic-gate fru_errno_t
221*7c478bd9Sstevel@tonic-gate PayloadReader::readRecurse(PathDef *path,
222*7c478bd9Sstevel@tonic-gate 			uint8_t *cur, size_t curLen,
223*7c478bd9Sstevel@tonic-gate 			void **data, size_t *dataLen,
224*7c478bd9Sstevel@tonic-gate 			int onlyFindingIterThereFlag)
225*7c478bd9Sstevel@tonic-gate {
226*7c478bd9Sstevel@tonic-gate 	fru_errno_t rc = FRU_SUCCESS;
227*7c478bd9Sstevel@tonic-gate 	size_t calc_data_len = 0;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	if (path->next == NULL) {
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 		// alway go ahead and do the iterated thing.  If we are not a
232*7c478bd9Sstevel@tonic-gate 		// field then the onlyFindingIterThereFlag should be set.
233*7c478bd9Sstevel@tonic-gate 		// Check this afterward.
234*7c478bd9Sstevel@tonic-gate 		int offset = 0;
235*7c478bd9Sstevel@tonic-gate 		int iterThere = 0;
236*7c478bd9Sstevel@tonic-gate 		// zzz altering the length things again...
237*7c478bd9Sstevel@tonic-gate 		if (IS_ITERATED(path)) {
238*7c478bd9Sstevel@tonic-gate 			// we are iterated.
239*7c478bd9Sstevel@tonic-gate 			calc_data_len = (path->def->payloadLen
240*7c478bd9Sstevel@tonic-gate 						-ITER_CONT_BYTE_LEN)/
241*7c478bd9Sstevel@tonic-gate 					path->def->iterationCount;
242*7c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets for bit iterations...
243*7c478bd9Sstevel@tonic-gate 			offset = getIterationOffset(cur, curLen, path,
244*7c478bd9Sstevel@tonic-gate 				&iterThere, &rc,
245*7c478bd9Sstevel@tonic-gate 				onlyFindingIterThereFlag);
246*7c478bd9Sstevel@tonic-gate 			if (offset == -1)
247*7c478bd9Sstevel@tonic-gate 				return (rc);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 			// done
250*7c478bd9Sstevel@tonic-gate 			if (onlyFindingIterThereFlag) {
251*7c478bd9Sstevel@tonic-gate 				*dataLen = iterThere;
252*7c478bd9Sstevel@tonic-gate 				return (FRU_SUCCESS);
253*7c478bd9Sstevel@tonic-gate 			}
254*7c478bd9Sstevel@tonic-gate 		} else {
255*7c478bd9Sstevel@tonic-gate 			// done but this thing was not an iteration!!!
256*7c478bd9Sstevel@tonic-gate 			if (onlyFindingIterThereFlag) {
257*7c478bd9Sstevel@tonic-gate 				return (FRU_INVALPATH);
258*7c478bd9Sstevel@tonic-gate 			}
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 			calc_data_len = path->def->payloadLen;
261*7c478bd9Sstevel@tonic-gate 			offset = 0;
262*7c478bd9Sstevel@tonic-gate 		}
263*7c478bd9Sstevel@tonic-gate 		// end zzz
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 		// now make sure we have a field.
266*7c478bd9Sstevel@tonic-gate 		if (path->def->dataType == FDTYPE_Record) {
267*7c478bd9Sstevel@tonic-gate 			return (FRU_NOTFIELD);
268*7c478bd9Sstevel@tonic-gate 		}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 		// allocate and copy.
271*7c478bd9Sstevel@tonic-gate 		if (path->def->dataType == FDTYPE_Binary) {
272*7c478bd9Sstevel@tonic-gate 			uint64_t *eData = (uint64_t *)malloc(sizeof (*eData));
273*7c478bd9Sstevel@tonic-gate 			if (eData == NULL) {
274*7c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
275*7c478bd9Sstevel@tonic-gate 			}
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 			int bitLength = path->def->dataLength;
278*7c478bd9Sstevel@tonic-gate 			// iterated bit field adjust acordingly.
279*7c478bd9Sstevel@tonic-gate 			if (IS_ITERATED(path)) {
280*7c478bd9Sstevel@tonic-gate 				bitLength = (bitLength-(ITER_CONT_BYTE_LEN*8))/
281*7c478bd9Sstevel@tonic-gate 					path->def->iterationCount;
282*7c478bd9Sstevel@tonic-gate 			}
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 			rc = readBits(bitLength, &(cur[offset]),
285*7c478bd9Sstevel@tonic-gate 					calc_data_len, 0, eData);
286*7c478bd9Sstevel@tonic-gate 			if (rc != FRU_SUCCESS) {
287*7c478bd9Sstevel@tonic-gate 				free(eData);
288*7c478bd9Sstevel@tonic-gate 				return (rc);
289*7c478bd9Sstevel@tonic-gate 			}
290*7c478bd9Sstevel@tonic-gate 			*data = (void *)eData;
291*7c478bd9Sstevel@tonic-gate 			*dataLen = sizeof (*eData);
292*7c478bd9Sstevel@tonic-gate 		} else if (path->def->dataType == FDTYPE_Enumeration) {
293*7c478bd9Sstevel@tonic-gate 			unsigned char *eData
294*7c478bd9Sstevel@tonic-gate 				= (unsigned char *)malloc(sizeof (uint64_t));
295*7c478bd9Sstevel@tonic-gate 			if (eData == NULL) {
296*7c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
297*7c478bd9Sstevel@tonic-gate 			}
298*7c478bd9Sstevel@tonic-gate 			/* copy the correct number of bytes to eData */
299*7c478bd9Sstevel@tonic-gate 			memset(eData, 0x00, sizeof (uint64_t));
300*7c478bd9Sstevel@tonic-gate 			memcpy(&(eData[(sizeof (uint64_t) - (calc_data_len))]),
301*7c478bd9Sstevel@tonic-gate 				&(cur[offset]),
302*7c478bd9Sstevel@tonic-gate 				(calc_data_len));
303*7c478bd9Sstevel@tonic-gate 			*data = (void*)eData;
304*7c478bd9Sstevel@tonic-gate 			*dataLen = sizeof (uint64_t);
305*7c478bd9Sstevel@tonic-gate 		} else {
306*7c478bd9Sstevel@tonic-gate 			void *rc_data = malloc(calc_data_len);
307*7c478bd9Sstevel@tonic-gate 			if (rc_data == NULL) {
308*7c478bd9Sstevel@tonic-gate 				return (FRU_FAILURE);
309*7c478bd9Sstevel@tonic-gate 			}
310*7c478bd9Sstevel@tonic-gate 			memcpy(rc_data, &(cur[offset]), calc_data_len);
311*7c478bd9Sstevel@tonic-gate 			*data = rc_data;
312*7c478bd9Sstevel@tonic-gate 			*dataLen = calc_data_len;
313*7c478bd9Sstevel@tonic-gate 		}
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	// At this point we know the entry is some sort of record.
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	int newOffset = 0, newLength = 0;
321*7c478bd9Sstevel@tonic-gate 	if (IS_ITERATED(path)) {
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets for bit iterations...
324*7c478bd9Sstevel@tonic-gate 		newOffset = getIterationOffset(cur, curLen,
325*7c478bd9Sstevel@tonic-gate 				path, NULL, &rc, NORMAL_READ);
326*7c478bd9Sstevel@tonic-gate 		if (newOffset == -1)
327*7c478bd9Sstevel@tonic-gate 			return (rc);
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	newOffset += getOffsetIntoRecord(path->def, path->next->def);
331*7c478bd9Sstevel@tonic-gate 	newLength = path->next->def->payloadLen;
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	return (readRecurse(path->next, &(cur[newOffset]), newLength,
334*7c478bd9Sstevel@tonic-gate 		data, dataLen, onlyFindingIterThereFlag));
335*7c478bd9Sstevel@tonic-gate }
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate // ===========================================================================
338*7c478bd9Sstevel@tonic-gate // will send the data back in (data,dataLen)
339*7c478bd9Sstevel@tonic-gate fru_errno_t
340*7c478bd9Sstevel@tonic-gate PayloadReader::readData(PathDef *path, Ancestor *curDef,
341*7c478bd9Sstevel@tonic-gate 			int instWICur,
342*7c478bd9Sstevel@tonic-gate 			uint8_t *payload, size_t payloadLen,
343*7c478bd9Sstevel@tonic-gate 			void **data, size_t *dataLen)
344*7c478bd9Sstevel@tonic-gate {
345*7c478bd9Sstevel@tonic-gate 	int offset = curDef->getInstOffset(instWICur);
346*7c478bd9Sstevel@tonic-gate 	return (readRecurse(path, &(payload[offset]), payloadLen-offset,
347*7c478bd9Sstevel@tonic-gate 		data, dataLen, NORMAL_READ));
348*7c478bd9Sstevel@tonic-gate }
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate // ===========================================================================
351*7c478bd9Sstevel@tonic-gate fru_errno_t
352*7c478bd9Sstevel@tonic-gate PayloadReader::findIterThere(PathDef *path, Ancestor *curDef,
353*7c478bd9Sstevel@tonic-gate 				int instWICur,
354*7c478bd9Sstevel@tonic-gate 				uint8_t *payload, size_t payloadLen,
355*7c478bd9Sstevel@tonic-gate 				int *numThere)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	int offset = curDef->getInstOffset(instWICur);
358*7c478bd9Sstevel@tonic-gate 	size_t tmp_num = 0;
359*7c478bd9Sstevel@tonic-gate 	fru_errno_t err = readRecurse(path, &(payload[offset]),
360*7c478bd9Sstevel@tonic-gate 		payloadLen-offset, NULL, &tmp_num, ITER_THERE_ONLY);
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	if (err == FRU_SUCCESS) {
363*7c478bd9Sstevel@tonic-gate 		int tmp_num_there = (int)tmp_num;
364*7c478bd9Sstevel@tonic-gate 		if (tmp_num_there != tmp_num) {
365*7c478bd9Sstevel@tonic-gate 			return (FRU_FAILURE);
366*7c478bd9Sstevel@tonic-gate 		}
367*7c478bd9Sstevel@tonic-gate 		*numThere = tmp_num_there;
368*7c478bd9Sstevel@tonic-gate 	}
369*7c478bd9Sstevel@tonic-gate 	return (err);
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate static fru_errno_t
373*7c478bd9Sstevel@tonic-gate update_iter_cont_bytes(PathDef *path, uint8_t *cur, size_t curLen)
374*7c478bd9Sstevel@tonic-gate {
375*7c478bd9Sstevel@tonic-gate 	// update the iteration control information
376*7c478bd9Sstevel@tonic-gate 	uint8_t *head = &(cur[0]);
377*7c478bd9Sstevel@tonic-gate 	uint8_t *tail = &(cur[1]);
378*7c478bd9Sstevel@tonic-gate 	uint8_t *numThere = &(cur[2]);
379*7c478bd9Sstevel@tonic-gate 	// This never changes.
380*7c478bd9Sstevel@tonic-gate 	uint8_t numPoss = cur[3];
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	if (numPoss != path->def->iterationCount) {
383*7c478bd9Sstevel@tonic-gate 		return (FRU_DATACORRUPT);
384*7c478bd9Sstevel@tonic-gate 	}
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	// Remember that when the iteration is added the head and the tail both
387*7c478bd9Sstevel@tonic-gate 	// equal 0 (ie point to 0).  So if we are empty when we are updating
388*7c478bd9Sstevel@tonic-gate 	// then we don't have to alter the head or tail values.  We simply add
389*7c478bd9Sstevel@tonic-gate 	// one to the numThere.
390*7c478bd9Sstevel@tonic-gate 	if (*numThere != 0) {
391*7c478bd9Sstevel@tonic-gate 		switch (path->def->iterationType) {
392*7c478bd9Sstevel@tonic-gate 			case FRU_Linear:
393*7c478bd9Sstevel@tonic-gate 				// this will flag an error when Linear can't
394*7c478bd9Sstevel@tonic-gate 				// hold anymore.
395*7c478bd9Sstevel@tonic-gate 				if ((*tail + 1) == numPoss)
396*7c478bd9Sstevel@tonic-gate 					return (FRU_ITERFULL);
397*7c478bd9Sstevel@tonic-gate 			/* Fall through */
398*7c478bd9Sstevel@tonic-gate 			case FRU_FIFO:
399*7c478bd9Sstevel@tonic-gate 				// if we are not at the end move the tail.
400*7c478bd9Sstevel@tonic-gate 				if (*tail != (numPoss-1))
401*7c478bd9Sstevel@tonic-gate 					*tail = *tail+1;
402*7c478bd9Sstevel@tonic-gate 			break;
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 			case FRU_Circular:
405*7c478bd9Sstevel@tonic-gate 			case FRU_LIFO:
406*7c478bd9Sstevel@tonic-gate 				// this is the same except LIFO is read
407*7c478bd9Sstevel@tonic-gate 				// BACKWARDS
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 				// move the tail.
410*7c478bd9Sstevel@tonic-gate 				*tail = *tail + 1;
411*7c478bd9Sstevel@tonic-gate 				// if the tail hits the end wrap around.
412*7c478bd9Sstevel@tonic-gate 				if (*tail == numPoss)
413*7c478bd9Sstevel@tonic-gate 					*tail = 0;
414*7c478bd9Sstevel@tonic-gate 				// if tail catches head move the head.
415*7c478bd9Sstevel@tonic-gate 				if (*tail == *head) {
416*7c478bd9Sstevel@tonic-gate 					// if head hits the end wrap around.
417*7c478bd9Sstevel@tonic-gate 					if (++(*head) == numPoss)
418*7c478bd9Sstevel@tonic-gate 						*head = 0;
419*7c478bd9Sstevel@tonic-gate 				}
420*7c478bd9Sstevel@tonic-gate 			break;
421*7c478bd9Sstevel@tonic-gate 		}
422*7c478bd9Sstevel@tonic-gate 	}
423*7c478bd9Sstevel@tonic-gate 	if ((*numThere) < numPoss) {
424*7c478bd9Sstevel@tonic-gate 		// add one IFF we are not full
425*7c478bd9Sstevel@tonic-gate 		*numThere = *numThere + 1;
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 	return (FRU_SUCCESS);
429*7c478bd9Sstevel@tonic-gate }
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate // ===========================================================================
432*7c478bd9Sstevel@tonic-gate fru_errno_t
433*7c478bd9Sstevel@tonic-gate PayloadReader::updateRecurse(PathDef *path,
434*7c478bd9Sstevel@tonic-gate 				uint8_t *cur, size_t curLen,
435*7c478bd9Sstevel@tonic-gate 				void *data, size_t dataLen)
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate 	fru_errno_t rc = FRU_SUCCESS;
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 	if (path->next == NULL) {
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 		// Delay checking for Records until after this which will
442*7c478bd9Sstevel@tonic-gate 		// allow for [+] notation for Iterated Records.
443*7c478bd9Sstevel@tonic-gate 		// if this is updating an iteration AND we are adding one...
444*7c478bd9Sstevel@tonic-gate 		if (IS_ITERATED(path) &&
445*7c478bd9Sstevel@tonic-gate 			(path->iterIndex == PathDef::addIteration)) {
446*7c478bd9Sstevel@tonic-gate 			return (update_iter_cont_bytes(path, cur, curLen));
447*7c478bd9Sstevel@tonic-gate 		}
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 		if (path->def->dataType == FDTYPE_Record) {
450*7c478bd9Sstevel@tonic-gate 			return (FRU_NOTFIELD);
451*7c478bd9Sstevel@tonic-gate 		}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		int offset = 0;
454*7c478bd9Sstevel@tonic-gate 		int calcLen = 0;
455*7c478bd9Sstevel@tonic-gate 		int dummy = 0;
456*7c478bd9Sstevel@tonic-gate 		// zzz altering the length things again...
457*7c478bd9Sstevel@tonic-gate 		if (IS_ITERATED(path)) {
458*7c478bd9Sstevel@tonic-gate 			// we are iterated.
459*7c478bd9Sstevel@tonic-gate 			calcLen = (path->def->payloadLen-ITER_CONT_BYTE_LEN)/
460*7c478bd9Sstevel@tonic-gate 				path->def->iterationCount;
461*7c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets
462*7c478bd9Sstevel@tonic-gate 			offset = getIterationOffset(cur, curLen,
463*7c478bd9Sstevel@tonic-gate 				path, &dummy, &rc, NORMAL_READ);
464*7c478bd9Sstevel@tonic-gate 			if (offset == -1)
465*7c478bd9Sstevel@tonic-gate 				return (rc);
466*7c478bd9Sstevel@tonic-gate 		} else {
467*7c478bd9Sstevel@tonic-gate 			calcLen = path->def->payloadLen;
468*7c478bd9Sstevel@tonic-gate 			offset = 0;
469*7c478bd9Sstevel@tonic-gate 		}
470*7c478bd9Sstevel@tonic-gate 		// end zzz
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 		// once again convert enums for the user again.
473*7c478bd9Sstevel@tonic-gate 		if (path->def->dataType == FDTYPE_Binary) {
474*7c478bd9Sstevel@tonic-gate 			int bitLength = path->def->dataLength;
475*7c478bd9Sstevel@tonic-gate 			// iterated bit field adjust acordingly.
476*7c478bd9Sstevel@tonic-gate 			if (path->def->iterationType != FRU_NOT_ITERATED) {
477*7c478bd9Sstevel@tonic-gate 				bitLength = (bitLength - 32)/
478*7c478bd9Sstevel@tonic-gate 					path->def->iterationCount;
479*7c478bd9Sstevel@tonic-gate 			}
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 			rc = writeBits (*(uint64_t *)data, bitLength,
482*7c478bd9Sstevel@tonic-gate 					&(cur[offset]), calcLen, 0);
483*7c478bd9Sstevel@tonic-gate 			if (rc != FRU_SUCCESS)
484*7c478bd9Sstevel@tonic-gate 				return (rc);
485*7c478bd9Sstevel@tonic-gate 		} else if (path->def->dataType == FDTYPE_Enumeration) {
486*7c478bd9Sstevel@tonic-gate 			unsigned char *tmp = (unsigned char *)data;
487*7c478bd9Sstevel@tonic-gate 			memcpy(&(cur[offset]),
488*7c478bd9Sstevel@tonic-gate 				&(tmp[(sizeof (uint64_t) - (calcLen))]),
489*7c478bd9Sstevel@tonic-gate 				calcLen);
490*7c478bd9Sstevel@tonic-gate 		} else {
491*7c478bd9Sstevel@tonic-gate 			// copy into and return.
492*7c478bd9Sstevel@tonic-gate 			memcpy(&(cur[offset]), data, dataLen);
493*7c478bd9Sstevel@tonic-gate 		}
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 		return (FRU_SUCCESS);
496*7c478bd9Sstevel@tonic-gate 	}
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 	int newOffset = 0, newLength = 0;
499*7c478bd9Sstevel@tonic-gate 	int dummy = 0;
500*7c478bd9Sstevel@tonic-gate 	if (path->def->iterationType != FRU_NOT_ITERATED) {
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets
503*7c478bd9Sstevel@tonic-gate 		newOffset = getIterationOffset(cur, curLen, path,
504*7c478bd9Sstevel@tonic-gate 					&dummy, &rc, NORMAL_READ);
505*7c478bd9Sstevel@tonic-gate 		if (newOffset == -1)
506*7c478bd9Sstevel@tonic-gate 			return (rc);
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate 	newOffset += getOffsetIntoRecord(path->def, path->next->def);
509*7c478bd9Sstevel@tonic-gate 	newLength = path->next->def->payloadLen;
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	return (updateRecurse(path->next, &(cur[newOffset]), newLength,
512*7c478bd9Sstevel@tonic-gate 		data, dataLen));
513*7c478bd9Sstevel@tonic-gate }
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate // ===========================================================================
516*7c478bd9Sstevel@tonic-gate // will update the data in payload which can then be written back.
517*7c478bd9Sstevel@tonic-gate fru_errno_t
518*7c478bd9Sstevel@tonic-gate PayloadReader::updateData(PathDef *path, Ancestor *ancestorDef,
519*7c478bd9Sstevel@tonic-gate 			int instWICur,
520*7c478bd9Sstevel@tonic-gate 			uint8_t *payload, size_t payloadLen,
521*7c478bd9Sstevel@tonic-gate 			void *data, size_t dataLen)
522*7c478bd9Sstevel@tonic-gate {
523*7c478bd9Sstevel@tonic-gate 	// verify the user data first before doing any major work.
524*7c478bd9Sstevel@tonic-gate 	int calcLen = 0;
525*7c478bd9Sstevel@tonic-gate 	PathDef *prev = path;
526*7c478bd9Sstevel@tonic-gate 	PathDef *cur = path;
527*7c478bd9Sstevel@tonic-gate 	while (cur != NULL) {
528*7c478bd9Sstevel@tonic-gate 		prev = cur;
529*7c478bd9Sstevel@tonic-gate 		cur = cur->next;
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	// unless we are updateing with [+] symbol
533*7c478bd9Sstevel@tonic-gate 	// (which means we don't have any data length at all.)
534*7c478bd9Sstevel@tonic-gate 	if (prev->iterIndex != PathDef::addIteration) {
535*7c478bd9Sstevel@tonic-gate 		if (IS_ITERATED(prev)) {
536*7c478bd9Sstevel@tonic-gate 			calcLen = (prev->def->payloadLen-ITER_CONT_BYTE_LEN)/
537*7c478bd9Sstevel@tonic-gate 				prev->def->iterationCount;
538*7c478bd9Sstevel@tonic-gate 		} else {
539*7c478bd9Sstevel@tonic-gate 				calcLen = prev->def->payloadLen;
540*7c478bd9Sstevel@tonic-gate 		}
541*7c478bd9Sstevel@tonic-gate 		// the sizeof the data for Binary or Enumeration MUST
542*7c478bd9Sstevel@tonic-gate 		// be uint64_t
543*7c478bd9Sstevel@tonic-gate 		if ((prev->def->dataType == FDTYPE_Enumeration) ||
544*7c478bd9Sstevel@tonic-gate 			(prev->def->dataType == FDTYPE_Binary)) {
545*7c478bd9Sstevel@tonic-gate 			if (dataLen != sizeof (uint64_t))
546*7c478bd9Sstevel@tonic-gate 				return (FRU_INVALDATASIZE);
547*7c478bd9Sstevel@tonic-gate 		// all others must be shorter than the space available.
548*7c478bd9Sstevel@tonic-gate 		} else {
549*7c478bd9Sstevel@tonic-gate 			if (dataLen > calcLen)
550*7c478bd9Sstevel@tonic-gate 				return (FRU_INVALDATASIZE);
551*7c478bd9Sstevel@tonic-gate 		}
552*7c478bd9Sstevel@tonic-gate 	}
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	int offset = ancestorDef->getInstOffset(instWICur);
555*7c478bd9Sstevel@tonic-gate 	return (updateRecurse(path, &(payload[offset]), payloadLen-offset,
556*7c478bd9Sstevel@tonic-gate 		data, dataLen));
557*7c478bd9Sstevel@tonic-gate }
558