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 5*821a83dbSps154918 * Common Development and Distribution License (the "License"). 6*821a83dbSps154918 * 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 /* 22*821a83dbSps154918 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2334e5f34eSkmohan * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <string.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include "PayloadReader.h" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #define ITER_CONT_BYTE_LEN 4 347c478bd9Sstevel@tonic-gate #define IS_ITERATED(pathDef) \ 357c478bd9Sstevel@tonic-gate (pathDef->def->iterationType != FRU_NOT_ITERATED) 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate // functions to place bit data properly. 387c478bd9Sstevel@tonic-gate static fru_errno_t 397c478bd9Sstevel@tonic-gate writeBits(uint64_t bitData, size_t bitLength, 407c478bd9Sstevel@tonic-gate uint8_t *data, size_t dataLength, size_t bitOffset) 417c478bd9Sstevel@tonic-gate { 427c478bd9Sstevel@tonic-gate if ((bitLength > 64) && 437c478bd9Sstevel@tonic-gate (bitOffset > 64) && 447c478bd9Sstevel@tonic-gate (dataLength > 8) && 457c478bd9Sstevel@tonic-gate (bitOffset > (dataLength * 8))) 467c478bd9Sstevel@tonic-gate return (FRU_FAILURE); 477c478bd9Sstevel@tonic-gate // move the bit data into place 487c478bd9Sstevel@tonic-gate bitData = (bitData << (64-bitLength)); 497c478bd9Sstevel@tonic-gate bitData = (bitData >> bitOffset); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate // create a mask to clear the old data. 527c478bd9Sstevel@tonic-gate uint64_t mask = 0; 537c478bd9Sstevel@tonic-gate for (size_t i = 0; i < bitLength; i++) { 547c478bd9Sstevel@tonic-gate mask = ((mask << 1) + 1); 557c478bd9Sstevel@tonic-gate } 567c478bd9Sstevel@tonic-gate mask = (mask << (64-bitLength)); 577c478bd9Sstevel@tonic-gate mask = (mask >> bitOffset); 5834e5f34eSkmohan mask = (mask ^ 0xFFFFFFFFFFFFFFFFULL); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate // get the data out of the byte array. 617c478bd9Sstevel@tonic-gate uint64_t rd = 0; 627c478bd9Sstevel@tonic-gate memcpy((void *)&rd, (void *)data, dataLength); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate // clear the old data 657c478bd9Sstevel@tonic-gate rd = (rd & mask); 667c478bd9Sstevel@tonic-gate // put in the new data. 677c478bd9Sstevel@tonic-gate rd = (rd | bitData); 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate // write the data back to the buffer. 707c478bd9Sstevel@tonic-gate memcpy((void *)data, (void *)&rd, dataLength); 717c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static fru_errno_t 757c478bd9Sstevel@tonic-gate readBits(size_t bitLength, uint8_t *data, 767c478bd9Sstevel@tonic-gate size_t dataLength, int bitOffset, uint64_t *ret) 777c478bd9Sstevel@tonic-gate { 787c478bd9Sstevel@tonic-gate if ((bitLength > 64) || 797c478bd9Sstevel@tonic-gate (bitLength < 0) || 807c478bd9Sstevel@tonic-gate (bitOffset > 64) || 817c478bd9Sstevel@tonic-gate (dataLength > 8) || 827c478bd9Sstevel@tonic-gate (bitOffset > (dataLength * 8))) 837c478bd9Sstevel@tonic-gate return (FRU_FAILURE); 847c478bd9Sstevel@tonic-gate // get the data out of the byte array. 857c478bd9Sstevel@tonic-gate uint64_t rc = 0; 867c478bd9Sstevel@tonic-gate memcpy((void *)&rc, (void *)data, dataLength); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate rc = (rc << bitOffset); 897c478bd9Sstevel@tonic-gate rc = (rc >> (64 - bitLength)); 907c478bd9Sstevel@tonic-gate *ret = rc; 917c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate // =========================================================================== 957c478bd9Sstevel@tonic-gate // caller is to be sure elemDef is contained by recDef. 967c478bd9Sstevel@tonic-gate int 977c478bd9Sstevel@tonic-gate PayloadReader::getOffsetIntoRecord(fru_regdef_t *recDef, 987c478bd9Sstevel@tonic-gate fru_regdef_t *elemDef) 997c478bd9Sstevel@tonic-gate { 1007c478bd9Sstevel@tonic-gate int rc = 0; 1017c478bd9Sstevel@tonic-gate for (int i = 0; i < recDef->enumCount; i++) { 1027c478bd9Sstevel@tonic-gate if (strcmp(recDef->enumTable[i].text, elemDef->name) == 0) 1037c478bd9Sstevel@tonic-gate return (rc); 1047c478bd9Sstevel@tonic-gate const fru_regdef_t *tmpDef = fru_reg_lookup_def_by_name( 1057c478bd9Sstevel@tonic-gate (char *)recDef->enumTable[i].text); 1067c478bd9Sstevel@tonic-gate rc += tmpDef->payloadLen; 1077c478bd9Sstevel@tonic-gate } 108*821a83dbSps154918 return(0); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate // =========================================================================== 1127c478bd9Sstevel@tonic-gate // return -1 on error. 1137c478bd9Sstevel@tonic-gate int 1147c478bd9Sstevel@tonic-gate PayloadReader::calcOffset(int iterType, 1157c478bd9Sstevel@tonic-gate uint8_t head, uint8_t tail, 1167c478bd9Sstevel@tonic-gate uint8_t iterThere, uint8_t iterPoss, 1177c478bd9Sstevel@tonic-gate size_t length, int index, 1187c478bd9Sstevel@tonic-gate fru_errno_t *err) 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate *err = FRU_SUCCESS; 1217c478bd9Sstevel@tonic-gate switch (iterType) { 1227c478bd9Sstevel@tonic-gate case FRU_FIFO: 1237c478bd9Sstevel@tonic-gate case FRU_Linear: 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate if (index == PathDef::lastIteration) 1267c478bd9Sstevel@tonic-gate return (length * tail); 1277c478bd9Sstevel@tonic-gate return (length * index); 1287c478bd9Sstevel@tonic-gate break; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate case FRU_Circular: 1317c478bd9Sstevel@tonic-gate case FRU_LIFO: 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate if (index == PathDef::lastIteration) { 1347c478bd9Sstevel@tonic-gate if (iterType == FRU_LIFO) 1357c478bd9Sstevel@tonic-gate return (length * head); 1367c478bd9Sstevel@tonic-gate return (length * tail); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate // For reading they are oposite. 1407c478bd9Sstevel@tonic-gate if (iterType == FRU_Circular) { 1417c478bd9Sstevel@tonic-gate return (length * ((head + index) % iterPoss)); 1427c478bd9Sstevel@tonic-gate } else { 1437c478bd9Sstevel@tonic-gate int abs = tail - index; 1447c478bd9Sstevel@tonic-gate if (abs < 0) 1457c478bd9Sstevel@tonic-gate // abs is negative here 1467c478bd9Sstevel@tonic-gate abs = iterPoss + abs; 1477c478bd9Sstevel@tonic-gate return (length * abs); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate break; 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate *err = FRU_FAILURE; 1537c478bd9Sstevel@tonic-gate return (-1); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate // =========================================================================== 1577c478bd9Sstevel@tonic-gate // return -1 on error. 1587c478bd9Sstevel@tonic-gate int 1597c478bd9Sstevel@tonic-gate PayloadReader::getIterationOffset(uint8_t *iter, int iterLen, 1607c478bd9Sstevel@tonic-gate PathDef *path, int *rcIterThere, 1617c478bd9Sstevel@tonic-gate fru_errno_t *err, 1627c478bd9Sstevel@tonic-gate int onlyFindingIterThereFlag) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate int rc = 0; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate // read the iteration control bytes first because we may ONLY need 1677c478bd9Sstevel@tonic-gate // them. 1687c478bd9Sstevel@tonic-gate uint8_t head = iter[0]; 1697c478bd9Sstevel@tonic-gate uint8_t tail = iter[1]; 1707c478bd9Sstevel@tonic-gate uint8_t iterThere = iter[2]; 1717c478bd9Sstevel@tonic-gate uint8_t iterPoss = iter[3]; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate // the '+' symbol on anything is an error here 1747c478bd9Sstevel@tonic-gate if (path->iterIndex == PathDef::addIteration) { 1757c478bd9Sstevel@tonic-gate *err = FRU_INVALPATH; 1767c478bd9Sstevel@tonic-gate return (-1); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate // check assumptions for next calls. 1807c478bd9Sstevel@tonic-gate if (iterPoss != path->def->iterationCount) { 1817c478bd9Sstevel@tonic-gate *err = FRU_DATACORRUPT; 1827c478bd9Sstevel@tonic-gate return (-1); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (onlyFindingIterThereFlag == ITER_THERE_ONLY) { 1867c478bd9Sstevel@tonic-gate if (rcIterThere != NULL) { 1877c478bd9Sstevel@tonic-gate *rcIterThere = iterThere; 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate *err = FRU_SUCCESS; 1907c478bd9Sstevel@tonic-gate return (ITER_CONT_BYTE_LEN); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate if ((path->iterIndex != PathDef::addIteration) && 1947c478bd9Sstevel@tonic-gate (path->iterIndex != PathDef::lastIteration) && 1957c478bd9Sstevel@tonic-gate (path->iterIndex >= iterThere)) { 1967c478bd9Sstevel@tonic-gate *err = FRU_DATANOTFOUND; 1977c478bd9Sstevel@tonic-gate return (-1); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate // don't forget to skip the iteration control bytes!!! 2017c478bd9Sstevel@tonic-gate int length = ((path->def->payloadLen - ITER_CONT_BYTE_LEN) 2027c478bd9Sstevel@tonic-gate /path->def->iterationCount); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate rc = calcOffset(path->def->iterationType, 2057c478bd9Sstevel@tonic-gate head, tail, iterThere, iterPoss, 2067c478bd9Sstevel@tonic-gate length, path->iterIndex, err); 2077c478bd9Sstevel@tonic-gate if (rc == -1) { 2087c478bd9Sstevel@tonic-gate // error set by calcOffset 2097c478bd9Sstevel@tonic-gate return (-1); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate *err = FRU_SUCCESS; 2137c478bd9Sstevel@tonic-gate return (ITER_CONT_BYTE_LEN + rc); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate // =========================================================================== 2177c478bd9Sstevel@tonic-gate // Iff onlyFindingIterThereFlag is set data is ignored and dataLen will be set 2187c478bd9Sstevel@tonic-gate // to the number of iterations which are actually in the seeprom. 2197c478bd9Sstevel@tonic-gate fru_errno_t 2207c478bd9Sstevel@tonic-gate PayloadReader::readRecurse(PathDef *path, 2217c478bd9Sstevel@tonic-gate uint8_t *cur, size_t curLen, 2227c478bd9Sstevel@tonic-gate void **data, size_t *dataLen, 2237c478bd9Sstevel@tonic-gate int onlyFindingIterThereFlag) 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate fru_errno_t rc = FRU_SUCCESS; 2267c478bd9Sstevel@tonic-gate size_t calc_data_len = 0; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (path->next == NULL) { 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate // alway go ahead and do the iterated thing. If we are not a 2317c478bd9Sstevel@tonic-gate // field then the onlyFindingIterThereFlag should be set. 2327c478bd9Sstevel@tonic-gate // Check this afterward. 2337c478bd9Sstevel@tonic-gate int offset = 0; 2347c478bd9Sstevel@tonic-gate int iterThere = 0; 2357c478bd9Sstevel@tonic-gate // zzz altering the length things again... 2367c478bd9Sstevel@tonic-gate if (IS_ITERATED(path)) { 2377c478bd9Sstevel@tonic-gate // we are iterated. 2387c478bd9Sstevel@tonic-gate calc_data_len = (path->def->payloadLen 2397c478bd9Sstevel@tonic-gate -ITER_CONT_BYTE_LEN)/ 2407c478bd9Sstevel@tonic-gate path->def->iterationCount; 2417c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets for bit iterations... 2427c478bd9Sstevel@tonic-gate offset = getIterationOffset(cur, curLen, path, 2437c478bd9Sstevel@tonic-gate &iterThere, &rc, 2447c478bd9Sstevel@tonic-gate onlyFindingIterThereFlag); 2457c478bd9Sstevel@tonic-gate if (offset == -1) 2467c478bd9Sstevel@tonic-gate return (rc); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate // done 2497c478bd9Sstevel@tonic-gate if (onlyFindingIterThereFlag) { 2507c478bd9Sstevel@tonic-gate *dataLen = iterThere; 2517c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate } else { 2547c478bd9Sstevel@tonic-gate // done but this thing was not an iteration!!! 2557c478bd9Sstevel@tonic-gate if (onlyFindingIterThereFlag) { 2567c478bd9Sstevel@tonic-gate return (FRU_INVALPATH); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate calc_data_len = path->def->payloadLen; 2607c478bd9Sstevel@tonic-gate offset = 0; 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate // end zzz 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate // now make sure we have a field. 2657c478bd9Sstevel@tonic-gate if (path->def->dataType == FDTYPE_Record) { 2667c478bd9Sstevel@tonic-gate return (FRU_NOTFIELD); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate // allocate and copy. 2707c478bd9Sstevel@tonic-gate if (path->def->dataType == FDTYPE_Binary) { 2717c478bd9Sstevel@tonic-gate uint64_t *eData = (uint64_t *)malloc(sizeof (*eData)); 2727c478bd9Sstevel@tonic-gate if (eData == NULL) { 2737c478bd9Sstevel@tonic-gate return (FRU_FAILURE); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate int bitLength = path->def->dataLength; 2777c478bd9Sstevel@tonic-gate // iterated bit field adjust acordingly. 2787c478bd9Sstevel@tonic-gate if (IS_ITERATED(path)) { 2797c478bd9Sstevel@tonic-gate bitLength = (bitLength-(ITER_CONT_BYTE_LEN*8))/ 2807c478bd9Sstevel@tonic-gate path->def->iterationCount; 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate rc = readBits(bitLength, &(cur[offset]), 2847c478bd9Sstevel@tonic-gate calc_data_len, 0, eData); 2857c478bd9Sstevel@tonic-gate if (rc != FRU_SUCCESS) { 2867c478bd9Sstevel@tonic-gate free(eData); 2877c478bd9Sstevel@tonic-gate return (rc); 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate *data = (void *)eData; 2907c478bd9Sstevel@tonic-gate *dataLen = sizeof (*eData); 2917c478bd9Sstevel@tonic-gate } else if (path->def->dataType == FDTYPE_Enumeration) { 2927c478bd9Sstevel@tonic-gate unsigned char *eData 2937c478bd9Sstevel@tonic-gate = (unsigned char *)malloc(sizeof (uint64_t)); 2947c478bd9Sstevel@tonic-gate if (eData == NULL) { 2957c478bd9Sstevel@tonic-gate return (FRU_FAILURE); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate /* copy the correct number of bytes to eData */ 2987c478bd9Sstevel@tonic-gate memset(eData, 0x00, sizeof (uint64_t)); 2997c478bd9Sstevel@tonic-gate memcpy(&(eData[(sizeof (uint64_t) - (calc_data_len))]), 3007c478bd9Sstevel@tonic-gate &(cur[offset]), 3017c478bd9Sstevel@tonic-gate (calc_data_len)); 3027c478bd9Sstevel@tonic-gate *data = (void*)eData; 3037c478bd9Sstevel@tonic-gate *dataLen = sizeof (uint64_t); 3047c478bd9Sstevel@tonic-gate } else { 3057c478bd9Sstevel@tonic-gate void *rc_data = malloc(calc_data_len); 3067c478bd9Sstevel@tonic-gate if (rc_data == NULL) { 3077c478bd9Sstevel@tonic-gate return (FRU_FAILURE); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate memcpy(rc_data, &(cur[offset]), calc_data_len); 3107c478bd9Sstevel@tonic-gate *data = rc_data; 3117c478bd9Sstevel@tonic-gate *dataLen = calc_data_len; 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate // At this point we know the entry is some sort of record. 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate int newOffset = 0, newLength = 0; 3207c478bd9Sstevel@tonic-gate if (IS_ITERATED(path)) { 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets for bit iterations... 3237c478bd9Sstevel@tonic-gate newOffset = getIterationOffset(cur, curLen, 3247c478bd9Sstevel@tonic-gate path, NULL, &rc, NORMAL_READ); 3257c478bd9Sstevel@tonic-gate if (newOffset == -1) 3267c478bd9Sstevel@tonic-gate return (rc); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate newOffset += getOffsetIntoRecord(path->def, path->next->def); 3307c478bd9Sstevel@tonic-gate newLength = path->next->def->payloadLen; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate return (readRecurse(path->next, &(cur[newOffset]), newLength, 3337c478bd9Sstevel@tonic-gate data, dataLen, onlyFindingIterThereFlag)); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate // =========================================================================== 3377c478bd9Sstevel@tonic-gate // will send the data back in (data,dataLen) 3387c478bd9Sstevel@tonic-gate fru_errno_t 3397c478bd9Sstevel@tonic-gate PayloadReader::readData(PathDef *path, Ancestor *curDef, 3407c478bd9Sstevel@tonic-gate int instWICur, 3417c478bd9Sstevel@tonic-gate uint8_t *payload, size_t payloadLen, 3427c478bd9Sstevel@tonic-gate void **data, size_t *dataLen) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate int offset = curDef->getInstOffset(instWICur); 3457c478bd9Sstevel@tonic-gate return (readRecurse(path, &(payload[offset]), payloadLen-offset, 3467c478bd9Sstevel@tonic-gate data, dataLen, NORMAL_READ)); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate // =========================================================================== 3507c478bd9Sstevel@tonic-gate fru_errno_t 3517c478bd9Sstevel@tonic-gate PayloadReader::findIterThere(PathDef *path, Ancestor *curDef, 3527c478bd9Sstevel@tonic-gate int instWICur, 3537c478bd9Sstevel@tonic-gate uint8_t *payload, size_t payloadLen, 3547c478bd9Sstevel@tonic-gate int *numThere) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate int offset = curDef->getInstOffset(instWICur); 3577c478bd9Sstevel@tonic-gate size_t tmp_num = 0; 3587c478bd9Sstevel@tonic-gate fru_errno_t err = readRecurse(path, &(payload[offset]), 3597c478bd9Sstevel@tonic-gate payloadLen-offset, NULL, &tmp_num, ITER_THERE_ONLY); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (err == FRU_SUCCESS) { 3627c478bd9Sstevel@tonic-gate int tmp_num_there = (int)tmp_num; 3637c478bd9Sstevel@tonic-gate if (tmp_num_there != tmp_num) { 3647c478bd9Sstevel@tonic-gate return (FRU_FAILURE); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate *numThere = tmp_num_there; 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate return (err); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate static fru_errno_t 3727c478bd9Sstevel@tonic-gate update_iter_cont_bytes(PathDef *path, uint8_t *cur, size_t curLen) 3737c478bd9Sstevel@tonic-gate { 3747c478bd9Sstevel@tonic-gate // update the iteration control information 3757c478bd9Sstevel@tonic-gate uint8_t *head = &(cur[0]); 3767c478bd9Sstevel@tonic-gate uint8_t *tail = &(cur[1]); 3777c478bd9Sstevel@tonic-gate uint8_t *numThere = &(cur[2]); 3787c478bd9Sstevel@tonic-gate // This never changes. 3797c478bd9Sstevel@tonic-gate uint8_t numPoss = cur[3]; 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if (numPoss != path->def->iterationCount) { 3827c478bd9Sstevel@tonic-gate return (FRU_DATACORRUPT); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate // Remember that when the iteration is added the head and the tail both 3867c478bd9Sstevel@tonic-gate // equal 0 (ie point to 0). So if we are empty when we are updating 3877c478bd9Sstevel@tonic-gate // then we don't have to alter the head or tail values. We simply add 3887c478bd9Sstevel@tonic-gate // one to the numThere. 3897c478bd9Sstevel@tonic-gate if (*numThere != 0) { 3907c478bd9Sstevel@tonic-gate switch (path->def->iterationType) { 3917c478bd9Sstevel@tonic-gate case FRU_Linear: 3927c478bd9Sstevel@tonic-gate // this will flag an error when Linear can't 3937c478bd9Sstevel@tonic-gate // hold anymore. 3947c478bd9Sstevel@tonic-gate if ((*tail + 1) == numPoss) 3957c478bd9Sstevel@tonic-gate return (FRU_ITERFULL); 3967c478bd9Sstevel@tonic-gate /* Fall through */ 3977c478bd9Sstevel@tonic-gate case FRU_FIFO: 3987c478bd9Sstevel@tonic-gate // if we are not at the end move the tail. 3997c478bd9Sstevel@tonic-gate if (*tail != (numPoss-1)) 4007c478bd9Sstevel@tonic-gate *tail = *tail+1; 4017c478bd9Sstevel@tonic-gate break; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate case FRU_Circular: 4047c478bd9Sstevel@tonic-gate case FRU_LIFO: 4057c478bd9Sstevel@tonic-gate // this is the same except LIFO is read 4067c478bd9Sstevel@tonic-gate // BACKWARDS 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate // move the tail. 4097c478bd9Sstevel@tonic-gate *tail = *tail + 1; 4107c478bd9Sstevel@tonic-gate // if the tail hits the end wrap around. 4117c478bd9Sstevel@tonic-gate if (*tail == numPoss) 4127c478bd9Sstevel@tonic-gate *tail = 0; 4137c478bd9Sstevel@tonic-gate // if tail catches head move the head. 4147c478bd9Sstevel@tonic-gate if (*tail == *head) { 4157c478bd9Sstevel@tonic-gate // if head hits the end wrap around. 4167c478bd9Sstevel@tonic-gate if (++(*head) == numPoss) 4177c478bd9Sstevel@tonic-gate *head = 0; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate break; 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate if ((*numThere) < numPoss) { 4237c478bd9Sstevel@tonic-gate // add one IFF we are not full 4247c478bd9Sstevel@tonic-gate *numThere = *numThere + 1; 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate // =========================================================================== 4317c478bd9Sstevel@tonic-gate fru_errno_t 4327c478bd9Sstevel@tonic-gate PayloadReader::updateRecurse(PathDef *path, 4337c478bd9Sstevel@tonic-gate uint8_t *cur, size_t curLen, 4347c478bd9Sstevel@tonic-gate void *data, size_t dataLen) 4357c478bd9Sstevel@tonic-gate { 4367c478bd9Sstevel@tonic-gate fru_errno_t rc = FRU_SUCCESS; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate if (path->next == NULL) { 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate // Delay checking for Records until after this which will 4417c478bd9Sstevel@tonic-gate // allow for [+] notation for Iterated Records. 4427c478bd9Sstevel@tonic-gate // if this is updating an iteration AND we are adding one... 4437c478bd9Sstevel@tonic-gate if (IS_ITERATED(path) && 4447c478bd9Sstevel@tonic-gate (path->iterIndex == PathDef::addIteration)) { 4457c478bd9Sstevel@tonic-gate return (update_iter_cont_bytes(path, cur, curLen)); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate if (path->def->dataType == FDTYPE_Record) { 4497c478bd9Sstevel@tonic-gate return (FRU_NOTFIELD); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate int offset = 0; 4537c478bd9Sstevel@tonic-gate int calcLen = 0; 4547c478bd9Sstevel@tonic-gate int dummy = 0; 4557c478bd9Sstevel@tonic-gate // zzz altering the length things again... 4567c478bd9Sstevel@tonic-gate if (IS_ITERATED(path)) { 4577c478bd9Sstevel@tonic-gate // we are iterated. 4587c478bd9Sstevel@tonic-gate calcLen = (path->def->payloadLen-ITER_CONT_BYTE_LEN)/ 4597c478bd9Sstevel@tonic-gate path->def->iterationCount; 4607c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets 4617c478bd9Sstevel@tonic-gate offset = getIterationOffset(cur, curLen, 4627c478bd9Sstevel@tonic-gate path, &dummy, &rc, NORMAL_READ); 4637c478bd9Sstevel@tonic-gate if (offset == -1) 4647c478bd9Sstevel@tonic-gate return (rc); 4657c478bd9Sstevel@tonic-gate } else { 4667c478bd9Sstevel@tonic-gate calcLen = path->def->payloadLen; 4677c478bd9Sstevel@tonic-gate offset = 0; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate // end zzz 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate // once again convert enums for the user again. 4727c478bd9Sstevel@tonic-gate if (path->def->dataType == FDTYPE_Binary) { 4737c478bd9Sstevel@tonic-gate int bitLength = path->def->dataLength; 4747c478bd9Sstevel@tonic-gate // iterated bit field adjust acordingly. 4757c478bd9Sstevel@tonic-gate if (path->def->iterationType != FRU_NOT_ITERATED) { 4767c478bd9Sstevel@tonic-gate bitLength = (bitLength - 32)/ 4777c478bd9Sstevel@tonic-gate path->def->iterationCount; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate rc = writeBits (*(uint64_t *)data, bitLength, 4817c478bd9Sstevel@tonic-gate &(cur[offset]), calcLen, 0); 4827c478bd9Sstevel@tonic-gate if (rc != FRU_SUCCESS) 4837c478bd9Sstevel@tonic-gate return (rc); 4847c478bd9Sstevel@tonic-gate } else if (path->def->dataType == FDTYPE_Enumeration) { 4857c478bd9Sstevel@tonic-gate unsigned char *tmp = (unsigned char *)data; 4867c478bd9Sstevel@tonic-gate memcpy(&(cur[offset]), 4877c478bd9Sstevel@tonic-gate &(tmp[(sizeof (uint64_t) - (calcLen))]), 4887c478bd9Sstevel@tonic-gate calcLen); 4897c478bd9Sstevel@tonic-gate } else { 4907c478bd9Sstevel@tonic-gate // copy into and return. 4917c478bd9Sstevel@tonic-gate memcpy(&(cur[offset]), data, dataLen); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate return (FRU_SUCCESS); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate int newOffset = 0, newLength = 0; 4987c478bd9Sstevel@tonic-gate int dummy = 0; 4997c478bd9Sstevel@tonic-gate if (path->def->iterationType != FRU_NOT_ITERATED) { 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate // zzz still have to figure out the bit offsets 5027c478bd9Sstevel@tonic-gate newOffset = getIterationOffset(cur, curLen, path, 5037c478bd9Sstevel@tonic-gate &dummy, &rc, NORMAL_READ); 5047c478bd9Sstevel@tonic-gate if (newOffset == -1) 5057c478bd9Sstevel@tonic-gate return (rc); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate newOffset += getOffsetIntoRecord(path->def, path->next->def); 5087c478bd9Sstevel@tonic-gate newLength = path->next->def->payloadLen; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate return (updateRecurse(path->next, &(cur[newOffset]), newLength, 5117c478bd9Sstevel@tonic-gate data, dataLen)); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate // =========================================================================== 5157c478bd9Sstevel@tonic-gate // will update the data in payload which can then be written back. 5167c478bd9Sstevel@tonic-gate fru_errno_t 5177c478bd9Sstevel@tonic-gate PayloadReader::updateData(PathDef *path, Ancestor *ancestorDef, 5187c478bd9Sstevel@tonic-gate int instWICur, 5197c478bd9Sstevel@tonic-gate uint8_t *payload, size_t payloadLen, 5207c478bd9Sstevel@tonic-gate void *data, size_t dataLen) 5217c478bd9Sstevel@tonic-gate { 5227c478bd9Sstevel@tonic-gate // verify the user data first before doing any major work. 5237c478bd9Sstevel@tonic-gate int calcLen = 0; 5247c478bd9Sstevel@tonic-gate PathDef *prev = path; 5257c478bd9Sstevel@tonic-gate PathDef *cur = path; 5267c478bd9Sstevel@tonic-gate while (cur != NULL) { 5277c478bd9Sstevel@tonic-gate prev = cur; 5287c478bd9Sstevel@tonic-gate cur = cur->next; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate // unless we are updateing with [+] symbol 5327c478bd9Sstevel@tonic-gate // (which means we don't have any data length at all.) 5337c478bd9Sstevel@tonic-gate if (prev->iterIndex != PathDef::addIteration) { 5347c478bd9Sstevel@tonic-gate if (IS_ITERATED(prev)) { 5357c478bd9Sstevel@tonic-gate calcLen = (prev->def->payloadLen-ITER_CONT_BYTE_LEN)/ 5367c478bd9Sstevel@tonic-gate prev->def->iterationCount; 5377c478bd9Sstevel@tonic-gate } else { 5387c478bd9Sstevel@tonic-gate calcLen = prev->def->payloadLen; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate // the sizeof the data for Binary or Enumeration MUST 5417c478bd9Sstevel@tonic-gate // be uint64_t 5427c478bd9Sstevel@tonic-gate if ((prev->def->dataType == FDTYPE_Enumeration) || 5437c478bd9Sstevel@tonic-gate (prev->def->dataType == FDTYPE_Binary)) { 5447c478bd9Sstevel@tonic-gate if (dataLen != sizeof (uint64_t)) 5457c478bd9Sstevel@tonic-gate return (FRU_INVALDATASIZE); 5467c478bd9Sstevel@tonic-gate // all others must be shorter than the space available. 5477c478bd9Sstevel@tonic-gate } else { 5487c478bd9Sstevel@tonic-gate if (dataLen > calcLen) 5497c478bd9Sstevel@tonic-gate return (FRU_INVALDATASIZE); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate int offset = ancestorDef->getInstOffset(instWICur); 5547c478bd9Sstevel@tonic-gate return (updateRecurse(path, &(payload[offset]), payloadLen-offset, 5557c478bd9Sstevel@tonic-gate data, dataLen)); 5567c478bd9Sstevel@tonic-gate } 557