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