| /* |
| * Copyright (c) 2014 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /*=========================================================================== |
| EDIT HISTORY FOR FILE |
| |
| This section contains comments describing changes made to the module. |
| Notice that changes are listed in reverse chronological order. |
| |
| $Header:$ $DateTime: $ $Author: $ |
| |
| when who what, where, why |
| -------- --- ----------------------------------------------------- |
| 04/10/13 kumarpra nv parser creation |
| ===========================================================================*/ |
| |
| #include <linux/string.h> |
| #include "wlan_nv.h" |
| |
| /* |
| * NV stream layer service |
| */ |
| #include "wlan_nv_stream.h" |
| #include "wlan_nv_template_internal.h" |
| #include "wlan_nv_parser_internal.h" |
| #include "wlan_nv_template_api.h" |
| #include "wlan_nv_template_builtin.h" |
| |
| extern void vos_mem_copy( void *pDst, const void *pSrc, unsigned int numBytes ); |
| |
| #define _RECURSIVE_DATA_TABLE_PARSING |
| // Recursive/iterative switch !! Default iterative |
| #define _RECURSIVE_VERSION |
| |
| /* |
| * Build process should have created the built-in templates in |
| * "wlan_nv_templateBuiltIn.c" |
| * Include its auto-generated companion header file |
| * "wlan_nv_templateBuiltIn.h" |
| * |
| * The main definitions are |
| * _NV_TEMPLATE_TABLE NvTablesBuiltIn[]; |
| * |
| */ |
| |
| /* |
| * Parsing control bitmap |
| */ |
| tANI_U32 gNVParsingControlLo; |
| static int subTableSize; |
| static int fieldSize; |
| static sHalNv *gpnvData_t; |
| /* store enum comparison results*/ |
| static _ENUM_META_DATA enumMetaDataFromBin[INDEX_ENUM_MAX]; |
| |
| |
| /* |
| * This data copy logic ignores the enum or int data types, |
| * but simply copy the whole chunk to the NV data structure |
| */ |
| typedef struct { |
| int idxSubFromBin; |
| int idxSubBuiltin; |
| } _SUBTABLES_QUEUE; |
| |
| pF_NumElemBasedOnStorageType numElemBasedOnStorageType[] = { |
| numElemSingular, // SINGULAR=0 |
| numElemArray1, // ARRAY_1=1 |
| numElemArray2, // ARRAY_2=2 |
| numElemArray3, // ARRAY_3=3 |
| }; |
| |
| static int sizeOneElemBasedOnFieldIdBasicDataType[] = { |
| 1, // _FIELD_ID_DATA_TYPE_U8 =0 |
| 4, // _FIELD_ID_DATA_TYPE_U32 |
| 1, // _FIELD_ID_DATA_TYPE_S8 |
| 4, // _FIELD_ID_DATA_TYPE_S32 |
| 2, // _FIELD_ID_DATA_TYPE_U16 |
| 2, // _FIELD_ID_DATA_TYPE_S16 |
| }; |
| |
| static _NV_STREAM_BUF nvStream[_NV_STREAM_LEN_MAX]; |
| static int subTableRd, subTableWr; |
| |
| #if !defined(_RECURSIVE_VERSION) |
| #define _SUBTABLES_MAX 32 |
| static _SUBTABLES_QUEUE subTablesQueue[_SUBTABLES_MAX]; |
| #endif |
| |
| /*============================================================================== |
| * |
| * Storage for NvTablesFromBin |
| * |
| *=============================================================================== |
| */ |
| |
| /* |
| * Init NvTablesFromBin |
| * All entries are initialized to 0, pointers to NULL |
| */ |
| |
| _NV_TEMPLATE_TABLE NvTablesFromBin[TABLES_MAX][TABLE_ENTRIES_MAX] = { |
| { /* TABLE_LAST*/ |
| {{nul}, 0, 0, 0, 0, 0, 0, {nul}}, |
| }, |
| }; |
| |
| static void initNvTablesFromBin(void) |
| { |
| int i, j; |
| |
| for (i = 0; i < TABLES_MAX; i++) { |
| for (j = 0; j < TABLE_ENTRIES_MAX; j++) { |
| NvTablesFromBin[i][j].fieldName[0] = nul; |
| NvTablesFromBin[i][j].fieldName[1] = nul; |
| NvTablesFromBin[i][j].fieldName[2] = nul; |
| NvTablesFromBin[i][j].fieldId = 0; |
| NvTablesFromBin[i][j].fieldStorageType = 0; |
| NvTablesFromBin[i][j].fieldStorageSize1 = 0; |
| NvTablesFromBin[i][j].fieldStorageSize2 = 0; |
| NvTablesFromBin[i][j].fieldStorageSize3 = 0; |
| NvTablesFromBin[i][j].offset = 0; |
| NvTablesFromBin[i][j].fieldFullName[0] = nul; |
| NvTablesFromBin[i][j].fieldFullName[1] = nul; |
| NvTablesFromBin[i][j].fieldFullName[2] = nul; |
| } |
| } |
| |
| return; |
| } |
| |
| /*============================================================================== |
| * |
| * Storage for NvEnumsFromBin |
| * |
| * ============================================================================== |
| */ |
| |
| /* |
| * Prepare the NV enum templates storage parsed from nv.bin |
| * They are used later for parsing the nv.bin data |
| * All entries are initialized to 0, pointers to NULL |
| */ |
| |
| _NV_TEMPLATE_ENUM NvEnumsFromBin[INDEX_ENUM_MAX][ENUM_ENTRIES_MAX] = { |
| { /* INDEX_ENUM_LAST */ |
| {{nul}, 0, 0, {nul}}, |
| }, |
| }; |
| |
| static void initNvEnumsFromBin(void) |
| { |
| int i, j; |
| |
| for(i = 0; i < INDEX_ENUM_MAX; i++) { |
| for(j = 0; j < ENUM_ENTRIES_MAX; j++) { |
| NvEnumsFromBin[i][j].enumName[0] = nul; |
| NvEnumsFromBin[i][j].enumName[1] = nul; |
| NvEnumsFromBin[i][j].enumName[2] = nul; |
| NvEnumsFromBin[i][j].enumValue = 0; |
| NvEnumsFromBin[i][j].enumValuePeer = 0xFF; |
| NvEnumsFromBin[i][j].enumFullName[0] = nul; |
| } |
| } |
| return; |
| } |
| |
| |
| // ============================================================================= |
| // |
| // Parse template streams |
| // |
| // ============================================================================= |
| |
| /* |
| * Read nv.bin to extract the template info |
| * _NV_TEMPLATE_TABLE NvTablesFromBin[]; |
| */ |
| |
| /* |
| * Parse nv.bin data and extract to the build-in data storage |
| * |
| * There are two outcomes from earlier templates comparison operation. |
| * different or identical |
| * If identical, this operation will most likely take place. |
| * If different, |
| * One is to simply indicate to the user and abort reading the nv.bin data |
| * The other is to continue this operation, and extract the matching entries |
| * in nv.bin |
| */ |
| |
| /* |
| * The template based NV logic: |
| * - the s/w module has the built-in templates |
| * - nv.bin is read one stream at a time, sequentially from beginning to end |
| * - if the stream is an enum stream, |
| * - add to nv.bin template data structure |
| * - compare with the built in template, by the string ID |
| * - if two match, move on |
| * - if not match, indicate mismatch, act based on the global logic |
| * _ selection |
| * - if abort, exit here |
| * - if extract-matching-ones, |
| * - copy the enum from the built-in template over to a separate |
| * _ column |
| * - when the enum comparison is done, all correlated enums have |
| * - a built-in enum value |
| * - all mismtached ones have 0xff |
| * - else if the stream is a table |
| * - add to nv.bin template data structure |
| * - compare with the built-in template, by the field string ID |
| * - if two tables match, move on |
| * - if not match, indicate mismatch and proceed based on the global |
| * - logic selection |
| * - if abort, exit here |
| * - if extract-matching-ones, |
| * - copy the built-in template offset to a separate column |
| * - eles if the stream is a data stream |
| * - parse the data stream based on the accumulated NV templates so far, |
| * - note at this point, |
| * - 1. the accumulated templates may be incomplete, to make up the |
| * - whole NV structure |
| * - 2. some will be "overwritten" by later templates definitions |
| * - that change the earlier templates) |
| * - how to parse? |
| * - based on the nv.bin accumulated templates so far, |
| * - select the table definition from the data stream, |
| * - find the corresponding table template, |
| * - start parsing data based on the template's field string IDs, |
| * - field by field sequentially. |
| * - if the field is a nested table, |
| * - go inside to the next level |
| * - if the field is a basic type, |
| * - copy data of the given size to the offset which is the |
| * - offset in the built-in nv data storage |
| * - end of the logic |
| */ |
| |
| /*---------------------------------------------------------------------------- |
| \brief nvParser() - parse nv data provided in input buffer and store |
| \ output in sHalNv |
| \param inputEncodedbuffer, length, sHalNv - ptr to input stream, |
| \param length, sHalNv |
| \return success when successfully decode and copy to sHalNv structure |
| \sa |
| -----------------------------------------------------------------------------*/ |
| |
| VOS_STATUS nvParser(tANI_U8 *pnvEncodedBuf, tANI_U32 nvReadBufSize, |
| sHalNv *hal_nv) |
| { |
| _STREAM_RC streamRc; |
| _NV_STREAM_BUF *pStream = &nvStream[0]; |
| tANI_U32 len; |
| _ErrorCode errCode = _OK; |
| VOS_STATUS ret = VOS_STATUS_SUCCESS; |
| gpnvData_t = hal_nv; |
| |
| // prepare storages for parsing nv.bin |
| initNvTablesFromBin(); |
| initNvEnumsFromBin(); |
| |
| // init stream read pointer |
| initReadStream(pnvEncodedBuf, nvReadBufSize); |
| |
| // get and process streams one by one |
| while (RC_FAIL != (streamRc = NEXT_STREAM(&len, &nvStream[0])) ) { |
| // need to copy, stream layer is freeing it |
| if (len > _NV_STREAM_LEN_MAX) { |
| errCode = _STREAM_NOT_FIT_BUF; |
| goto _error; |
| } |
| // template or data |
| if (IsStreamTemplate(pStream[_NV_BIN_STREAM_HEADER_BYTE])) { |
| if (_MIS_MATCH == processNvTemplate(pStream, len)) { |
| if (_FLAG_AND_ABORT(gNVParsingControlLo) ) { |
| errCode = _SW_BIN_MISMATCH; |
| break; |
| } |
| } |
| } |
| else { |
| processNvData(pStream, len); |
| } |
| } |
| |
| _error: |
| if (_OK != errCode) { |
| ret = VOS_STATUS_E_INVAL; |
| } |
| |
| // all done |
| return ret; |
| } |
| |
| static _NV_TEMPLATE_PROCESS_RC processNvTemplate(_NV_STREAM_BUF *pStream, |
| int len) |
| { |
| // Table or enum |
| if (IsTemplateStreamTable(pStream[_NV_BIN_STREAM_HEADER_BYTE])) { |
| return processNvTemplateTable(pStream, len); |
| } |
| else { |
| return processNvTemplateEnum(pStream, len); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * |
| * Parse one table template stream in nv.bin |
| * The length of table templates varies, based on the field ID class, |
| * field size type |
| */ |
| |
| static _NV_TEMPLATE_PROCESS_RC processNvTemplateTable(_NV_STREAM_BUF *pStream, |
| int len) |
| { |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| char tableNameFromBin[_TABLE_NAME_LEN +1]; |
| int tableIdxFromBin; |
| |
| // construct the template table in the NvTablesFromBin |
| memset((void*)tableNameFromBin, '\0', (size_t) (_TABLE_NAME_LEN +1)); |
| tableIdxFromBin = constructATemplateTable(pStream, len, tableNameFromBin); |
| |
| // fetch the table name from the first entry, the Table of all tables |
| // search for the corresponding table in NvDataBuiltIn |
| if (tableIdxFromBin) { |
| rc = compareWithBuiltinTable(tableIdxFromBin, tableNameFromBin); |
| } |
| // done |
| return rc; |
| } |
| |
| static int getOffsetFromBuiltIn(char *tableNameFromBin) |
| { |
| int offset = _OFFSET_NOT_SET; |
| int i; |
| |
| _NV_TEMPLATE_TABLE (*pTableBuiltin)[TABLE_ENTRIES_MAX] = NvTablesBuiltIn; |
| // search NvTablesBuiltIn for the same string named table, and its idx |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTableBuiltin[0][i].fieldName[0]) { |
| break; |
| } |
| if (!strcmp(tableNameFromBin, pTableBuiltin[0][i].fieldName)) { |
| offset = pTableBuiltin[0][i].offset; |
| break; |
| } |
| } |
| return offset; |
| } |
| |
| /* |
| * Construct a table template in the NvTablesFromBin |
| * it returns the newly constructed table, for comparison with NvTablesBuiltIn |
| */ |
| static int constructATemplateTable(_NV_STREAM_BUF *pStream, int len, |
| char *tableStrName) |
| { |
| int pos = 0; |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| int tableIdx, entryIdx; |
| int i; |
| _ErrorCode errCode = _OK; |
| |
| tableIdx = (pStream[_NV_BIN_STREAM_TABLE_ID_BYTE] & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| |
| if (IsIdxTableOfAllTables(tableIdx)) { |
| } |
| else { |
| // find the string name of the table |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[0][i].fieldName[0]) { |
| break; |
| } |
| if ((pTable[0][i].fieldId & FIELD_ID_TABLE_OR_ENUM_IDX_MASK) == |
| tableIdx) { |
| strlcpy(tableStrName, pTable[0][i].fieldName, (_TABLE_NAME_LEN +1)); |
| break; |
| } |
| } |
| if (TABLE_ENTRIES_MAX == i) { |
| // if string name not found, don't know what to do |
| errCode = _TABLE_NON_EXIST_IN_TABLE_OF_ALL_TABLES; |
| goto _error; |
| } |
| } |
| |
| // check if the table is already populated |
| if (nul != pTable[tableIdx][0].fieldName[0]) { // there is data in that enty |
| // tbd: decision logic based on Parsing Control (bitmap) |
| } |
| |
| // overwrite table entry, tableIdx |
| pos = _TABLE_FIELDS_POS; |
| entryIdx = 0; |
| while (pos < len) { |
| if (!(pos <= (len - _TABLE_FIELD_MIN_LEN))) { |
| // error condition |
| errCode = _INSUFFICIENT_FOR_FIELD_PARSER_ERROR; |
| break; |
| } |
| |
| // populate the entry |
| memset(pTable[tableIdx][entryIdx].fieldName, '\0', |
| (size_t) (_TABLE_NAME_LEN + 1)); |
| memset(pTable[tableIdx][entryIdx].fieldFullName, '\0', |
| (size_t) (_TABLE_FIELD_FULL_NAME_LEN + 1)); |
| pTable[tableIdx][entryIdx].fieldName[0] = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldName[1] = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldId = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldStorageType = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldStorageSize1 = 0; |
| pTable[tableIdx][entryIdx].fieldStorageSize2 = 0; |
| pTable[tableIdx][entryIdx].fieldStorageSize3 = 0; |
| pTable[tableIdx][entryIdx].offset = |
| getOffsetFromBuiltIn(pTable[tableIdx][entryIdx].fieldName); |
| |
| if (SINGULAR == |
| _STORAGE_TYPE(pTable[tableIdx][entryIdx].fieldStorageType)) { |
| } |
| else if (ARRAY_1 == |
| _STORAGE_TYPE(pTable[tableIdx][entryIdx].fieldStorageType)) { |
| pTable[tableIdx][entryIdx].fieldStorageSize1 = pStream[pos++]; |
| } |
| else if (ARRAY_2 == |
| _STORAGE_TYPE(pTable[tableIdx][entryIdx].fieldStorageType)) { |
| pTable[tableIdx][entryIdx].fieldStorageSize1 = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldStorageSize2 = pStream[pos++]; |
| } |
| else if (ARRAY_3 == |
| _STORAGE_TYPE(pTable[tableIdx][entryIdx].fieldStorageType)) { |
| pTable[tableIdx][entryIdx].fieldStorageSize1 = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldStorageSize2 = pStream[pos++]; |
| pTable[tableIdx][entryIdx].fieldStorageSize3 = pStream[pos++]; |
| } |
| // |
| entryIdx++; |
| } |
| |
| _error: |
| if (_OK != errCode) { |
| } |
| |
| // all done |
| return tableIdx; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * |
| * Table Compare logic: |
| * |
| * 1. the fields need to be in the same order. Looping through fields doesn't |
| * guarantee order. |
| * 2. whenever mismatch occurs in this "same-order" comparison, flag. |
| * 3. If extract matching entries' option is selected, proceed to nv.bin table |
| * and extract data. |
| * |
| * Note |
| * "compareWithBuiltinTable" is the initiating point. |
| * "compare2Tables" is the top level compare logic. |
| * it is naturally implemented as a recursive call, but out of stack |
| * overflow concern, |
| * it is also implemented as an iterative loop. |
| * |
| */ |
| |
| static _NV_TEMPLATE_PROCESS_RC compareWithBuiltinTable(int idxFromBin, |
| char *tableNameFromBin) |
| { |
| int i; |
| _NV_TEMPLATE_TABLE (*pTableBuiltin)[TABLE_ENTRIES_MAX] = NvTablesBuiltIn; |
| int tableIdxBuiltin = 0; |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| _ErrorCode errCode = _OK; |
| |
| // search NvTablesBuiltIn for the same string named table, and its idx |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTableBuiltin[0][i].fieldName[0]) { |
| break; |
| } |
| if (!strcmp(tableNameFromBin, pTableBuiltin[0][i].fieldName)) { |
| tableIdxBuiltin = (pTableBuiltin[0][i].fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| break; |
| } |
| } |
| |
| // compare and copy values |
| if (!tableIdxBuiltin) { |
| errCode = _TABLE_NON_EXIST_IN_TABLE_OF_ALL_TABLES; |
| rc = _MIS_MATCH; |
| } |
| else { |
| subTableRd = 0; |
| subTableWr = 0; |
| |
| // fire the comparison logic |
| if (_MIS_MATCH == compare2Tables(idxFromBin, tableIdxBuiltin)) { |
| rc = _MIS_MATCH; |
| } |
| |
| // for iterative version |
| // return code (rc) should only be set to _MIS_MATCH when it happens at |
| // least once |
| #if !defined(_RECURSIVE_VERSION) |
| { |
| int idxSubFromBin, idxSubBuiltin; |
| while (subTableRd != subTableWr) { |
| idxSubFromBin = subTablesQueue[subTableRd].idxSubFromBin; |
| idxSubBuiltin = subTablesQueue[subTableRd].idxSubBuiltin; |
| if (_MIS_MATCH == compare2Tables(idxSubFromBin, idxSubBuiltin)) { |
| rc = _MIS_MATCH; |
| } |
| // increment read pointer |
| subTableRd = (subTableRd+1) % _SUBTABLES_MAX; |
| } |
| } |
| #endif //#if !defined(_RECURSIVE_VERSION) |
| } |
| |
| //_error: |
| if (_OK != errCode) { |
| //printf("Error %d \n", errCode); |
| } |
| |
| // |
| return rc; |
| } |
| |
| static _NV_TEMPLATE_PROCESS_RC compare2Tables(int idxFromBin, int idxBuiltin) |
| { |
| int i, j; |
| _NV_TEMPLATE_TABLE (*pTableBuiltIn)[TABLE_ENTRIES_MAX]; |
| _NV_TEMPLATE_TABLE (*pTableFromBin)[TABLE_ENTRIES_MAX]; |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| |
| pTableBuiltIn = NvTablesBuiltIn; |
| pTableFromBin = NvTablesFromBin; |
| |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if ((nul == pTableBuiltIn[idxBuiltin][i].fieldName[0]) || |
| // end of table occurs in either table |
| (nul == pTableFromBin[idxFromBin][i].fieldName[0])) { |
| // end of table occurs in either table |
| if ((nul == pTableBuiltIn[idxBuiltin][i].fieldName[0]) && |
| (nul == pTableFromBin[idxFromBin][i].fieldName[0])) { |
| rc = _MATCH; |
| } |
| else { |
| rc = _MIS_MATCH; |
| |
| for (j=0; j<TABLE_ENTRIES_MAX; j++) { |
| if (nul == pTableBuiltIn[idxBuiltin][j].fieldName[0]) { |
| // end of bin table |
| break; |
| } |
| if (!strcmp( |
| (const char*) pTableBuiltIn[idxBuiltin][j].fieldName, |
| (const char*) pTableFromBin[idxFromBin][i].fieldName)) { |
| // found matching field in bin table |
| // DO NOT check return code, it's already a mismatch |
| compare2FieldsAndCopyFromBin( |
| &(pTableBuiltIn[idxBuiltin][j]), |
| &(pTableFromBin[idxFromBin][i]), idxBuiltin, |
| idxFromBin); |
| break; |
| } |
| } |
| } |
| break; // end of table, either table, condition |
| } |
| else { |
| if (!strcmp(pTableBuiltIn[idxBuiltin][i].fieldName, |
| pTableFromBin[idxFromBin][i].fieldName)) { |
| // two field names match |
| if (_MATCH == compare2FieldsAndCopyFromBin( |
| &(pTableBuiltIn[idxBuiltin][i]), |
| &(pTableFromBin[idxFromBin][i]), |
| idxBuiltin, idxFromBin)) { |
| rc = _MATCH; |
| } |
| else { |
| rc = _MIS_MATCH; |
| if ( _FLAG_AND_ABORT(gNVParsingControlLo) ) { |
| break; |
| } |
| } |
| } |
| else { |
| rc = _MIS_MATCH; |
| if ( _FLAG_AND_ABORT(gNVParsingControlLo) ) { |
| break; |
| } |
| // else |
| // loop through the WHOLE bin tables, looking for a matching field. |
| // this would take care of both cases where bin table field is |
| // either "ahead" or "behind" |
| for (j = 0; j < TABLE_ENTRIES_MAX; j++) { |
| // end of bin table |
| if (nul == pTableFromBin[idxBuiltin][j].fieldName[0]) { |
| break; |
| } |
| if (!strcmp(pTableBuiltIn[idxBuiltin][j].fieldName, |
| pTableFromBin[idxFromBin][i].fieldName)) { |
| // found matching field in bin table |
| // DO NOT check return code, it's already a mismatch |
| compare2FieldsAndCopyFromBin(&(pTableBuiltIn[idxBuiltin][j]), |
| &(pTableFromBin[idxFromBin][i]), idxBuiltin, idxFromBin); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| return rc; |
| } |
| |
| static _NV_TEMPLATE_PROCESS_RC compare2FieldsAndCopyFromBin( |
| _NV_TEMPLATE_TABLE*pTableBuiltIn, |
| _NV_TEMPLATE_TABLE *pTableFromBin, int idxBuiltin, int idxFromBin) |
| { |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| |
| // Verified already the fieldNames match |
| // fieldId type matching? |
| /* |
| * If it's a simple type, simple comparison, ==,after mask out the data type |
| * else if it's a table, need to compare 2 tables, don't call recursively |
| */ |
| if (_MIS_MATCH == compare2FieldIDType(pTableBuiltIn, pTableFromBin, |
| idxBuiltin, idxFromBin)) { |
| rc = _MIS_MATCH; |
| goto _end; |
| } |
| // storage type matching? |
| // If it's SINGULAR, simple == comparison |
| // else if it's ARRAY_n, besides check ARRAY_n equal, check sizes |
| // if sizes are Index_int, simple comparison |
| // else if sizes are INDEX_ENUM, need to loop through enums |
| // |
| if (_MIS_MATCH == compare2FieldStorageTypeAndSizes(pTableBuiltIn, |
| pTableFromBin, idxBuiltin, idxFromBin)) { |
| rc = _MIS_MATCH; |
| goto _end; |
| } |
| |
| // all matched, copy offset over |
| rc = _MATCH; |
| pTableFromBin->offset = pTableBuiltIn->offset; |
| |
| _end: |
| return rc; |
| } |
| |
| static _NV_TEMPLATE_PROCESS_RC compare2FieldIDType( |
| _NV_TEMPLATE_TABLE *pTableBuiltIn, |
| _NV_TEMPLATE_TABLE *pTableFromBin, int idxBuiltin, int idxFromBin) |
| { |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| |
| if (IsFieldTypeBasicData(pTableBuiltIn->fieldId)) { |
| if (pTableBuiltIn->fieldId == pTableFromBin->fieldId) { |
| rc = _MATCH; |
| } |
| else { |
| rc = _MIS_MATCH; |
| } |
| } |
| else { // field is a table |
| int idxSubBuiltin = pTableBuiltIn->fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK; |
| int idxSubFromBin = pTableFromBin->fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK; |
| #if defined(_RECURSIVE_VERSION) |
| rc = compare2Tables(idxSubFromBin, idxSubBuiltin); |
| #else |
| { |
| subTablesQueue[subTableWr].idxSubFromBin = idxSubFromBin; |
| subTablesQueue[subTableWr].idxSubBuiltin = idxSubBuiltin; |
| subTableWr = (subTableWr +1) % _SUBTABLES_MAX; |
| } |
| #endif //#if defined(_RECURSIVE_VERSION) |
| } |
| |
| return rc; |
| } |
| |
| |
| static _NV_TEMPLATE_PROCESS_RC compare2FieldStorageTypeAndSizes( |
| _NV_TEMPLATE_TABLE *pTableBuiltIn, |
| _NV_TEMPLATE_TABLE *pTableFromBin, int idxBuiltIn, int idxFromBin) |
| { |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| |
| if (_STORAGE_TYPE(pTableBuiltIn->fieldStorageType) == |
| _STORAGE_TYPE(pTableFromBin->fieldStorageType)) { |
| if (SINGULAR == _STORAGE_TYPE(pTableBuiltIn->fieldStorageType)) { |
| rc = _MATCH; |
| } |
| else if (ARRAY_1 == _STORAGE_TYPE(pTableBuiltIn->fieldStorageType)) { |
| if ((_MATCH == compare2StorageSize(idxBuiltIn, idxFromBin, |
| _STORAGE_SIZE1(pTableBuiltIn->fieldStorageSize1, |
| pTableBuiltIn->fieldStorageType), |
| _STORAGE_SIZE1(pTableFromBin->fieldStorageSize1, |
| pTableFromBin->fieldStorageType), |
| pTableBuiltIn->fieldStorageSize1, |
| pTableFromBin->fieldStorageSize1)) ) { |
| |
| rc = _MATCH; |
| } |
| } |
| else if (ARRAY_2 == _STORAGE_TYPE(pTableBuiltIn->fieldStorageType)) { |
| if ((_MATCH == compare2StorageSize(idxBuiltIn, idxFromBin, |
| _STORAGE_SIZE1(pTableBuiltIn->fieldStorageSize1, |
| pTableBuiltIn->fieldStorageType), |
| _STORAGE_SIZE1(pTableFromBin->fieldStorageSize1, |
| pTableFromBin->fieldStorageType), |
| pTableBuiltIn->fieldStorageSize1, |
| pTableFromBin->fieldStorageSize1)) && |
| (_MATCH == compare2StorageSize(idxBuiltIn, idxFromBin, |
| _STORAGE_SIZE2(pTableBuiltIn->fieldStorageSize2, |
| pTableBuiltIn->fieldStorageType), |
| _STORAGE_SIZE2(pTableFromBin->fieldStorageSize2, |
| pTableFromBin->fieldStorageType), |
| pTableBuiltIn->fieldStorageSize2, |
| pTableFromBin->fieldStorageSize2)) ) { |
| rc = _MATCH; |
| } |
| } |
| else if (ARRAY_3 == _STORAGE_TYPE(pTableBuiltIn->fieldStorageType)) { |
| if ((_MATCH == compare2StorageSize(idxBuiltIn, idxFromBin, |
| _STORAGE_SIZE1(pTableBuiltIn->fieldStorageSize1, |
| pTableBuiltIn->fieldStorageType), |
| _STORAGE_SIZE1(pTableFromBin->fieldStorageSize1, |
| pTableFromBin->fieldStorageType), |
| pTableBuiltIn->fieldStorageSize1, |
| pTableFromBin->fieldStorageSize1)) && |
| (_MATCH == compare2StorageSize(idxBuiltIn, idxFromBin, |
| _STORAGE_SIZE2(pTableBuiltIn->fieldStorageSize2, |
| pTableBuiltIn->fieldStorageType), |
| _STORAGE_SIZE2(pTableFromBin->fieldStorageSize2, |
| pTableFromBin->fieldStorageType), |
| pTableBuiltIn->fieldStorageSize2, |
| pTableFromBin->fieldStorageSize2)) && |
| (_MATCH == compare2StorageSize(idxBuiltIn, idxFromBin, |
| _STORAGE_SIZE3(pTableBuiltIn->fieldStorageSize3, |
| pTableBuiltIn->fieldStorageType), |
| _STORAGE_SIZE3(pTableFromBin->fieldStorageSize3, |
| pTableFromBin->fieldStorageType), |
| pTableBuiltIn->fieldStorageSize3, |
| pTableFromBin->fieldStorageSize3)) ) { |
| rc = _MATCH; |
| } |
| } |
| } |
| else { |
| rc = _MIS_MATCH; |
| } |
| return rc; |
| } |
| |
| static _NV_TEMPLATE_PROCESS_RC compare2StorageSize(int idxBuiltIn, |
| int idxFromBin, int sizeBuiltIn, |
| int sizeFromBin, tANI_U8 sizeBuiltInLowByte, tANI_U8 sizeFromBinLowByte) |
| { |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| |
| if (IsFieldSizeInt(sizeBuiltInLowByte) && |
| IsFieldSizeInt(sizeFromBinLowByte)) { |
| if (sizeBuiltIn == sizeFromBin) { |
| rc = _MATCH; |
| } |
| else { |
| rc = _MIS_MATCH; |
| } |
| } |
| else if (!IsFieldSizeInt(sizeBuiltInLowByte) && |
| !IsFieldSizeInt(sizeFromBinLowByte)) { |
| // enums should have been compared when enum streams are parsed |
| // The implication is that the enum streams should go before tables' |
| rc = enumMetaDataFromBin[idxFromBin].match; |
| } |
| else { |
| rc = _MIS_MATCH; |
| } |
| |
| return rc; |
| } |
| |
| /* |
| * ---------------------------------------------------------------------------- |
| * |
| * Parse one enum template stream in nv.bin |
| */ |
| static _NV_TEMPLATE_PROCESS_RC processNvTemplateEnum(_NV_STREAM_BUF *pStream, |
| int len) |
| { |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| char enumStr[_ENUM_NAME_LEN + 1]; |
| //_NV_TEMPLATE_ENUM *pEnum; |
| int enumIdx; |
| |
| // construct the enum template in the NvEnumsFromBin |
| memset((void*)enumStr, '\0', (size_t) (_ENUM_NAME_LEN + 1)); |
| enumIdx = constructATemplateEnum(pStream, len, enumStr); |
| |
| // Compare the enum template |
| // also record compare results for later use in the table |
| // templates parsing where |
| // the fields may be indexed by enums |
| // if enumIdx ==0, didn't construct any entry, |
| // (or only the first entry) |
| if (enumIdx) { |
| compareEnumWithBuiltin(enumStr, enumIdx); |
| } |
| |
| return rc; |
| } |
| |
| static void compareEnumWithBuiltin(char *enumStr, int enumIdxFromBin) |
| { |
| int i; |
| int enumIdxBuiltin = 0; |
| _NV_TEMPLATE_ENUM (*pEnumBuiltin)[ENUM_ENTRIES_MAX] = NvEnumsBuiltIn; |
| _ErrorCode errCode = _OK; |
| |
| for (i = 0; i < ENUM_ENTRIES_MAX; i++) { |
| if (nul == pEnumBuiltin[0][i].enumName[0]) { |
| break; |
| } |
| if (!strcmp(enumStr, pEnumBuiltin[0][i].enumName)) { |
| enumIdxBuiltin = pEnumBuiltin[0][i].enumValue; |
| break; |
| } |
| } |
| if (!enumIdxBuiltin) { |
| errCode = _ENUM_NOT_FOUND_IN_BUILT_IN; |
| return; |
| } |
| else { |
| compare2EnumEntriesAndCopy(enumIdxFromBin, enumIdxBuiltin); |
| } |
| |
| //_error: |
| if (_OK != errCode) { |
| //printf("Error %d\n", errCode); |
| } |
| |
| return; |
| } |
| |
| static _NV_TEMPLATE_PROCESS_RC compare2EnumEntriesAndCopy(int idxFromBin, |
| int idxBuiltin) |
| { |
| int i,j; |
| _NV_TEMPLATE_PROCESS_RC rc = _MATCH; |
| _NV_TEMPLATE_ENUM (*enumsFromBin)[ENUM_ENTRIES_MAX] = NvEnumsFromBin; |
| _NV_TEMPLATE_ENUM (*enumsBuiltin)[ENUM_ENTRIES_MAX] = NvEnumsBuiltIn; |
| |
| // need to go through all enums |
| for (i = 0; i < ENUM_ENTRIES_MAX; i++) { |
| // end conditions: either both reach the end (match), |
| // or one of them reaching the end (mismatch) |
| if ((nul == enumsBuiltin[idxBuiltin][i].enumName[0]) || |
| (nul == enumsFromBin[idxFromBin][i].enumName[0])) { |
| if ((nul == enumsBuiltin[idxBuiltin][i].enumName[0]) && |
| (nul == enumsFromBin[idxFromBin][i].enumName[0])) { |
| // fully matched |
| rc = _MATCH; |
| break; |
| } |
| else { |
| rc = _MIS_MATCH; |
| for (j = 0; j < ENUM_ENTRIES_MAX; j++) { |
| if (nul == enumsBuiltin[idxBuiltin][j].enumName[0]) { |
| break; |
| } |
| if (!strcmp((const char*)enumsFromBin[idxFromBin][i].enumName, |
| (const char*)enumsBuiltin[idxBuiltin][j].enumName)) { |
| enumsFromBin[idxFromBin][i].enumValuePeer = |
| enumsBuiltin[idxBuiltin][j].enumValue; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| else { |
| if (!strcmp(enumsBuiltin[idxBuiltin][i].enumName, |
| enumsFromBin[idxFromBin][i].enumName)) { |
| // copy builtIn enum value to fromBin |
| enumsFromBin[idxFromBin][i].enumValuePeer = |
| enumsBuiltin[idxBuiltin][i].enumValue; |
| } |
| else { |
| // mismatch, but still loop through the whole enum list |
| // for the "ahead" and "behind" scenarios |
| rc = _MIS_MATCH; |
| for (j = 0; j < ENUM_ENTRIES_MAX; j++) { |
| if (nul == enumsBuiltin[idxBuiltin][j].enumName[0]) { |
| break; |
| } |
| if (!strcmp(enumsFromBin[idxFromBin][i].enumName, |
| enumsBuiltin[idxBuiltin][j].enumName)) { |
| enumsFromBin[idxFromBin][i].enumValuePeer = |
| enumsBuiltin[idxBuiltin][j].enumValue; |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| // record match or mismatch for later data parsing use |
| enumMetaDataFromBin[idxFromBin].match = rc; |
| |
| // all done |
| return rc; |
| } |
| |
| static int constructATemplateEnum(_NV_STREAM_BUF *pStream, int len, |
| char *enumStr) |
| { |
| int pos = 0; |
| _NV_TEMPLATE_ENUM (*pEnum)[ENUM_ENTRIES_MAX]; |
| int enumIdx = 0; |
| int i; |
| int entryIdx; |
| _ErrorCode errCode = _OK; |
| |
| enumIdx = (pStream[_NV_BIN_STREAM_ENUM_ID_BYTE] & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| pEnum = NvEnumsFromBin; |
| |
| // find its string name |
| // the logic: |
| // since the nv.bin doesn't encode the enum string name in the actual enum |
| // stream, only the first "enum of all enums" |
| // has the names of all enums. |
| if (IsIdxEnumOfAllEnums(enumIdx)) { |
| } |
| else { |
| for (i = 0; i < ENUM_ENTRIES_MAX; i++) { |
| if (nul == pEnum[0][i].enumName[0]) { |
| break; |
| } |
| if (pEnum[0][i].enumValue == enumIdx) { |
| strlcpy(enumStr, pEnum[0][i].enumName,(_ENUM_NAME_LEN + 1)); |
| break; |
| } |
| } |
| if (ENUM_ENTRIES_MAX == i) { |
| // without a string name, don't know what to do with the enum indexed |
| errCode = _ENUM_NOT_FOUND_IN_BUILT_IN; |
| goto _error; |
| } |
| } |
| |
| // Found the enum string name, now parsing decision time ... |
| // Is the entry already populated? |
| if (nul != pEnum[enumIdx][0].enumName[0]) { // there is data in that entry |
| // TBD: |
| // the logic here depends on how we support "parsing data based on the |
| // latest template". |
| // one way is to overwrite the template, so the subsequent parsing will |
| // be based on the "latest". |
| // the second way is to "append" the template, and the parsing should |
| // always be based on the "last" of the same name |
| // for simplicity, support the first approach for now. |
| // |
| // the logic: |
| // based on the parsing control (bitmap), we may proceed on overwriting |
| // enums with blind faith that the writing logic is correct, |
| // or ignore the appended. |
| // |
| } |
| |
| // overwrite entry, enumIdx |
| pos = _ENUM_START_POS; |
| entryIdx = 0; |
| while (pos < len) { |
| if (!(pos <= (len - _ENUM_MIN_LEN))) { |
| // error condition |
| errCode = _INSUFFICIENT_FOR_FIELD_PARSER_ERROR; |
| break; |
| } |
| |
| // populate the entry |
| memset(pEnum[enumIdx][entryIdx].enumName, '\0', |
| (size_t) (_ENUM_NAME_LEN +1)); |
| memset(pEnum[enumIdx][entryIdx].enumFullName, '\0', |
| (size_t) (_ENUM_FULL_NAME_LEN +1)); |
| pEnum[enumIdx][entryIdx].enumName[0] = pStream[pos++]; |
| pEnum[enumIdx][entryIdx].enumName[1] = pStream[pos++]; |
| pEnum[enumIdx][entryIdx].enumValue = pStream[pos++]; |
| entryIdx++; |
| } |
| |
| _error: |
| if (_OK != errCode) { |
| //printf("Error %d\n", errCode); |
| } |
| |
| // all done |
| return enumIdx; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * |
| * Process data stream |
| * The purpose is to copy nv.bin data into built in NV data structure. |
| * This is the parser function. |
| * |
| * Next phase: |
| * With NV data in the s/w module data structure, nv.bin conforming |
| * to the new format can be generated. That is the nv.bin generation logic.) |
| * |
| * Data stream has the following format |
| * |
| * delimiter|streamHeader|tableID|data....|CRC|delimiter |
| * Note |
| * 1. delimiters are not present in the stream data, pStream. |
| * 2. nested tables do NOT have table IDs with them. |
| * |
| */ |
| // NV data, per built in templates |
| // Recursive table parsing, which is naturally depth-first |
| // If iterative, a bit hard to implement |
| |
| static void parseSubDataTable4Size(int tableIdx, int numElem) |
| { |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| int idxSubTable; |
| int i; |
| int numSubElem = 0, idx=0; |
| |
| // "apply" template to data -- parsing the actual NV data, |
| // so far we have been parsing and building templates |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[tableIdx][i].fieldName[0]) { |
| // data parsing done for this stream |
| break; |
| } |
| if (IsFieldTypeBasicData(pTable[tableIdx][i].fieldId)) { |
| getBasicDataSize(&(pTable[tableIdx][i])); |
| } |
| else { |
| // number of element |
| idx = |
| _STORAGE_TYPE(pTable[tableIdx][i].fieldStorageType); |
| numSubElem = numElemBasedOnStorageType[idx]( |
| &(pTable[tableIdx][i]), 1); |
| // get size of the sub-table |
| idxSubTable = (pTable[tableIdx][i].fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| // recursive calls for the total size of the subtable |
| parseSubDataTable4Size(idxSubTable, numSubElem); |
| } |
| } |
| // update subTableSize for the number of elements |
| subTableSize *= numElem; |
| |
| return; |
| } |
| |
| static void copyDataToBuiltInFromBin(int tableIdx,int fieldId, |
| _NV_STREAM_BUF *pStream, int *pos, int addOffset, int tableBaseOffset) |
| { |
| int i,j,k,storageType; |
| int idx=0, size1=0, size2=0, size3=0; |
| int enumIdx1=0, enumIdx2=0, enumIdx3=0, sizeOneElem=0; |
| int isFirstFieldEnum=0,isSecondFieldEnum=0,isThirdFieldEnum=0; |
| int index,index1,index2; |
| int dindex,dindex1,dindex2,totalSize; |
| int offset=0,sizeBuiltIn,tableIdxBuiltIn,fieldIdBuiltIn; |
| int idxBuiltIn=0, size1BuiltIn=0, size2BuiltIn=0, size3BuiltIn=0; |
| int size1Bin=0, size2Bin=0, size3Bin=0, numElemBuiltIn; |
| int sizeOneElemBuiltIn=0, field; |
| unsigned char *ptr, *dptr; |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| _NV_TEMPLATE_TABLE (*pTableBuiltIn)[TABLE_ENTRIES_MAX] = NvTablesBuiltIn; |
| |
| storageType = _STORAGE_TYPE(pTable[tableIdx][fieldId].fieldStorageType); |
| field = pTable[tableIdx][fieldId].fieldId; |
| sizeOneElem = sizeOneElemBasedOnFieldIdBasicDataType[field & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK]; |
| sizeBuiltIn = getBuiltInFieldCount(tableIdx, |
| pTable[tableIdx][fieldId].fieldName, |
| &tableIdxBuiltIn,&fieldIdBuiltIn,&numElemBuiltIn); |
| |
| field = pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldId; |
| sizeOneElemBuiltIn = sizeOneElemBasedOnFieldIdBasicDataType[field & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK]; |
| |
| if (storageType == SINGULAR ) { |
| ptr = ((unsigned char*)gpnvData_t) + tableBaseOffset + addOffset; |
| dptr = (unsigned char *)&pStream[*pos]; |
| |
| if (IsFieldTypeBasicData(pTable[tableIdx][fieldId].fieldId)) { |
| idx = _STORAGE_TYPE(pTable[tableIdx][fieldId].fieldStorageType); |
| size1Bin = numElemBasedOnStorageType[idx]( |
| &(pTable[tableIdx][fieldId]), 1); |
| field = pTable[tableIdx][fieldId].fieldId; |
| sizeOneElem = sizeOneElemBasedOnFieldIdBasicDataType[field & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK]; |
| |
| idxBuiltIn = _STORAGE_TYPE( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| size1BuiltIn = numElemBasedOnStorageType[idx]( |
| &(pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn]), 0); |
| |
| size1 = size1Bin; |
| if (size1 > size1BuiltIn) { |
| size1 = size1BuiltIn; |
| } |
| } |
| totalSize = size1 * sizeOneElem; |
| |
| offset = 0; |
| for (i = 0; i < size1; i++) { |
| vos_mem_copy(&ptr[offset], &dptr[offset], sizeOneElem); |
| offset = offset + sizeOneElem; |
| } |
| |
| *pos = *pos + (size1Bin * sizeOneElem); |
| } |
| else { |
| if (ARRAY_1 == storageType) { |
| ptr = ((unsigned char*)gpnvData_t) + tableBaseOffset + addOffset; |
| dptr = (unsigned char *)&pStream[*pos]; |
| |
| idx = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1Bin = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize1, 1); |
| |
| idx = _STORAGE_SIZE1( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size1BuiltIn = getNumElemOutOfStorageSize(idx, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, 0); |
| |
| size1 = size1Bin; |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx1 = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| isFirstFieldEnum = 1; |
| } |
| else { |
| isFirstFieldEnum = 0; |
| if (size1 > size1BuiltIn) { |
| size1 = size1BuiltIn; |
| } |
| } |
| |
| offset = 0; |
| for (i = 0; i < size1; i++) { |
| if (isFirstFieldEnum) { |
| if (NvEnumsFromBin[enumIdx1][i].enumValuePeer != 0xFF) { |
| index = NvEnumsFromBin[enumIdx1][i].enumValuePeer; |
| dindex = NvEnumsFromBin[enumIdx1][i].enumValue; |
| |
| index = index * sizeOneElem; |
| dindex = dindex * sizeOneElem; |
| |
| vos_mem_copy(&ptr[index], &dptr[dindex], sizeOneElem); |
| } |
| } |
| else { |
| vos_mem_copy(&ptr[offset], &dptr[offset], sizeOneElem); |
| offset = offset + sizeOneElem; |
| } |
| } |
| |
| *pos = *pos + (size1Bin * sizeOneElem); |
| } |
| else if (ARRAY_2 == storageType) { |
| ptr = ((unsigned char*)gpnvData_t) + tableBaseOffset + addOffset; |
| dptr = (unsigned char *)&pStream[*pos]; |
| |
| idx = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1Bin = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize1, 1); |
| |
| idx = _STORAGE_SIZE2(pTable[tableIdx][fieldId].fieldStorageSize2, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| |
| size2Bin = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize2, 1); |
| |
| idx = _STORAGE_SIZE1( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size1BuiltIn = getNumElemOutOfStorageSize(idx, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, 0); |
| |
| idx = _STORAGE_SIZE2( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize2, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size2BuiltIn = getNumElemOutOfStorageSize(idx, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize2, 0); |
| |
| size1 = size1Bin; |
| size2 = size2Bin; |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx1 = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| isFirstFieldEnum = 1; |
| } |
| else { |
| isFirstFieldEnum = 0; |
| if (size1 > size1BuiltIn) { |
| size1 = size1BuiltIn; |
| } |
| } |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize2)) { |
| enumIdx2 = ((pTable[tableIdx][fieldId].fieldStorageSize2 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| isSecondFieldEnum = 1; |
| } |
| else { |
| isSecondFieldEnum = 0; |
| if (size2 > size2BuiltIn) { |
| size2 = size2BuiltIn; |
| } |
| } |
| |
| offset = 0; |
| |
| for (i = 0; i < size1; i++) { |
| if (isFirstFieldEnum) { |
| if (NvEnumsFromBin[enumIdx1][i].enumValuePeer == 0xFF) { |
| continue; |
| } |
| |
| index = NvEnumsFromBin[enumIdx1][i].enumValuePeer; |
| dindex = NvEnumsFromBin[enumIdx1][i].enumValue; |
| } |
| else { |
| index = dindex = i; |
| } |
| |
| for (j = 0; j < size2; j++) { |
| if (isSecondFieldEnum) { |
| if (NvEnumsFromBin[enumIdx2][j].enumValuePeer == 0xFF) { |
| continue; |
| } |
| |
| index1 = NvEnumsFromBin[enumIdx2][j].enumValuePeer; |
| dindex1 = NvEnumsFromBin[enumIdx2][j].enumValue; |
| } |
| else { |
| index1 = dindex1 = j; |
| } |
| |
| vos_mem_copy(&ptr[(index1 + index * size2BuiltIn)*sizeOneElem], |
| &dptr[(dindex1+dindex*size2Bin)*sizeOneElem], sizeOneElem); |
| offset = offset + sizeOneElem; |
| } |
| } |
| |
| *pos = *pos + size2Bin * size1Bin * sizeOneElem; |
| } |
| else if (ARRAY_3 == storageType) { |
| ptr = ((unsigned char*)gpnvData_t) + tableBaseOffset + addOffset; |
| dptr = (unsigned char *)&pStream[*pos]; |
| |
| idx = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1Bin = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize1, 1); |
| |
| idx = _STORAGE_SIZE2(pTable[tableIdx][fieldId].fieldStorageSize2, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size2Bin = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize2, 1); |
| |
| idx = _STORAGE_SIZE3(pTable[tableIdx][fieldId].fieldStorageSize3, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size3Bin = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize3, 1); |
| |
| idx = _STORAGE_SIZE1( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size1BuiltIn = getNumElemOutOfStorageSize(idx, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, |
| 0); |
| |
| idx = _STORAGE_SIZE2( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize2, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size2BuiltIn = getNumElemOutOfStorageSize(idx, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize2, |
| 0); |
| |
| idx = _STORAGE_SIZE3( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize3, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size3BuiltIn = getNumElemOutOfStorageSize(idx, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize3, |
| 0); |
| |
| size1 = size1Bin; |
| size2 = size2Bin; |
| size3 = size3Bin; |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx1 = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| isFirstFieldEnum = 1; |
| } |
| else { |
| isFirstFieldEnum = 0; |
| if (size1 > size1BuiltIn) { |
| size1 = size1BuiltIn; |
| } |
| } |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize2)) { |
| enumIdx2 = ((pTable[tableIdx][fieldId].fieldStorageSize2 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| isSecondFieldEnum = 1; |
| } |
| else { |
| isSecondFieldEnum = 0; |
| if (size2 > size2BuiltIn) { |
| size2 = size2BuiltIn; |
| } |
| } |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize3)) { |
| enumIdx3 = ((pTable[tableIdx][fieldId].fieldStorageSize3 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| isThirdFieldEnum = 1; |
| } |
| else { |
| isThirdFieldEnum = 0; |
| if (size3 > size3BuiltIn) { |
| size3 = size3BuiltIn; |
| } |
| } |
| |
| offset = 0; |
| for (i = 0; i < size1; i++) { |
| if (isFirstFieldEnum) { |
| if (NvEnumsFromBin[enumIdx1][i].enumValuePeer == 0xFF) { |
| continue; |
| } |
| |
| index = NvEnumsFromBin[enumIdx1][i].enumValuePeer; |
| dindex = NvEnumsFromBin[enumIdx1][i].enumValue; |
| } |
| else { |
| index = dindex = i; |
| } |
| |
| for (j = 0; j < size2; j++) { |
| if (isSecondFieldEnum) { |
| if (NvEnumsFromBin[enumIdx2][j].enumValuePeer == 0xFF) { |
| continue; |
| } |
| |
| index1 = NvEnumsFromBin[enumIdx2][j].enumValuePeer; |
| dindex1 = NvEnumsFromBin[enumIdx2][j].enumValue; |
| } |
| else { |
| index1 = dindex1 = j; |
| } |
| |
| for (k = 0; k < size3; k++) { |
| if (isThirdFieldEnum) { |
| if (NvEnumsFromBin[enumIdx2][j].enumValuePeer == 0xFF) { |
| continue; |
| } |
| |
| index2 = NvEnumsFromBin[enumIdx3][k].enumValuePeer; |
| dindex2 = NvEnumsFromBin[enumIdx3][k].enumValue; |
| } |
| else { |
| index2 = dindex2 = k; |
| } |
| |
| vos_mem_copy(&ptr[(index2 + (index1 * size2BuiltIn) + |
| (index * size3BuiltIn * size2BuiltIn)) * sizeOneElem], |
| &dptr[(dindex2 + (dindex1 * size2Bin) + |
| (dindex * size3Bin * size2Bin))*sizeOneElem], |
| sizeOneElem); |
| |
| offset = offset + sizeOneElem; |
| } |
| } |
| } |
| |
| *pos = *pos + size1Bin * size2Bin * size3Bin * sizeOneElem; |
| } |
| else { |
| } |
| } |
| } |
| |
| // search NvTablesBuiltIn for the same string named table, and its idx |
| static int getBuiltInFieldCount (int tableIdxBin, char *tableNameFromBin, |
| int *tblIdBuiltIn, int *fieldIdBuitIn, int *numElements) |
| { |
| int i,idx,numElem,tableIdxBuiltin=0,fieldCnt; |
| _NV_TEMPLATE_TABLE (*pTableBin)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesBuiltIn; |
| int found=0, fieldIndex = 0; |
| |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTableBin[0][i].fieldName[0]) { |
| break; |
| } |
| |
| if ((pTableBin[0][i].fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK) == tableIdxBin) { |
| found = 1; |
| break; |
| } |
| } |
| |
| if (!found) { |
| return -1; |
| } |
| |
| //fieldName index got from tableId from Bin |
| fieldIndex = i; |
| found = 0; |
| |
| for (i=0;i<TABLE_ENTRIES_MAX;i++) { |
| if (nul == pTable[0][i].fieldName[0]) { |
| break; |
| } |
| |
| if (!strcmp((const char*)pTableBin[0][fieldIndex].fieldName, |
| (const char*)pTable[0][i].fieldName)) { |
| found = 1; |
| break; |
| } |
| } |
| |
| if (!found) { |
| return -1; |
| } |
| |
| //found tableId of builtIn |
| tableIdxBuiltin = *tblIdBuiltIn = |
| (pTable[0][i].fieldId & FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| found = 0; |
| |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[tableIdxBuiltin][i].fieldName[0]) { |
| break; |
| } |
| |
| if (!strcmp((const char*)tableNameFromBin, |
| (const char*)pTable[tableIdxBuiltin][i].fieldName)) { |
| found = 1; |
| break; |
| } |
| } |
| |
| if (!found) { |
| return -1; |
| } |
| |
| *fieldIdBuitIn = i; |
| |
| idx = _STORAGE_TYPE(pTable[tableIdxBuiltin][i].fieldStorageType); |
| numElem = numElemBasedOnStorageType[idx](&(pTable[tableIdxBuiltin][i]), 0); |
| |
| fieldSize = 0; |
| fieldCnt = getFieldCount (tableIdxBuiltin, i, numElem, 0); |
| |
| *numElements = numElem; |
| |
| return fieldCnt; |
| } |
| |
| static int getFieldCount(int tableIdx, int fieldId, int numElem, int nvBin) |
| { |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX]; |
| int idxSubTable; |
| int i, j, storageType, field; |
| int numSubElem=0, idx =0, size1=0, size2=0, size3=0, sizeOneElem=0; |
| int enumIdx1=0, enumIdx2=0, enumIdx3=0; |
| |
| if ( nvBin ) { |
| pTable = NvTablesFromBin; |
| } |
| else { |
| pTable = NvTablesBuiltIn; |
| } |
| |
| storageType = _STORAGE_TYPE(pTable[tableIdx][fieldId].fieldStorageType); |
| |
| if (SINGULAR == storageType) { |
| if (IsFieldTypeBasicData(pTable[tableIdx][fieldId].fieldId)) { |
| idx = _STORAGE_TYPE(pTable[tableIdx][fieldId].fieldStorageType); |
| size1 = numElemBasedOnStorageType[idx](&(pTable[tableIdx][fieldId]), |
| nvBin); |
| } |
| else { |
| } |
| } |
| else { |
| if (ARRAY_1 == storageType) { |
| idx = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1 = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize1,nvBin); |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx1 = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| } |
| } |
| else if (ARRAY_2 == storageType) { |
| idx = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1 = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize1,nvBin); |
| |
| idx = _STORAGE_SIZE2(pTable[tableIdx][fieldId].fieldStorageSize2, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| |
| size2 = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize2,nvBin); |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx1 = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| } |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize2)) { |
| enumIdx2 = ((pTable[tableIdx][fieldId].fieldStorageSize2 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| } |
| } |
| else if (ARRAY_3 == storageType) { |
| idx = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1 = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize1,nvBin); |
| |
| idx = _STORAGE_SIZE2(pTable[tableIdx][fieldId].fieldStorageSize2, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size2 = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize2,nvBin); |
| |
| idx = _STORAGE_SIZE3(pTable[tableIdx][fieldId].fieldStorageSize3, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size3 = getNumElemOutOfStorageSize(idx, |
| pTable[tableIdx][fieldId].fieldStorageSize3,nvBin); |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx1 = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| } |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize2)) { |
| enumIdx2 = ((pTable[tableIdx][fieldId].fieldStorageSize2 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| } |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize3)) { |
| enumIdx3 = ((pTable[tableIdx][fieldId].fieldStorageSize3 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| } |
| } |
| else { |
| } |
| } |
| |
| if (IsFieldTypeBasicData(pTable[tableIdx][fieldId].fieldId)) { |
| field = pTable[tableIdx][fieldId].fieldId; |
| sizeOneElem = sizeOneElemBasedOnFieldIdBasicDataType[field & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK]; |
| if ( size3 ) { |
| fieldSize = fieldSize + size3 * size2 * size1 * sizeOneElem; |
| } |
| else if ( size2 ) { |
| fieldSize = fieldSize + size2 * size1 * sizeOneElem; |
| } |
| else if ( size1 ) { |
| fieldSize = fieldSize + size1 * sizeOneElem; |
| } |
| else { |
| } |
| } |
| else { |
| idxSubTable = (pTable[tableIdx][fieldId].fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| |
| for (j=0; j<numElem; j++) { |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[idxSubTable][i].fieldName[0]) { |
| // data parsing done for this stream |
| break; |
| } |
| |
| idx = _STORAGE_TYPE(pTable[idxSubTable][i].fieldStorageType); |
| numSubElem = numElemBasedOnStorageType[idx]( |
| &(pTable[idxSubTable][i]),nvBin); |
| |
| getFieldCount(idxSubTable, i, numSubElem, nvBin); |
| } |
| } |
| } |
| |
| return fieldSize; |
| } |
| |
| static void parseSubDataTableAndCopy(int tableIdx, int numElem, int numElem2, |
| int numElem3, int fieldId, _NV_STREAM_BUF *pStream, int *pos, int addOffset, |
| int tableBaseOffset, int localAddOffset) |
| { |
| int idxSubTable, i, j, l, m, idx1, storageType, fieldCount=0; |
| int size1BuiltIn, size2BuiltIn, size3BuiltIn; |
| int tableIdxBuiltIn, fieldIdBuiltIn, numElemBuiltIn, incAddOffset=0; |
| int totalOffset=0, enumIdx, size1Bin, size2Bin, size3Bin; |
| int numSubElem, numSubElem2, numSubElem3, sizeBuiltIn=0, idx=0; |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| _NV_TEMPLATE_TABLE (*pTableBuiltIn)[TABLE_ENTRIES_MAX] = NvTablesBuiltIn; |
| |
| // "apply" template to data -- parsing the actual NV data, |
| // so far we have been parsing and building templates |
| if (IsFieldTypeBasicData(pTable[tableIdx][fieldId].fieldId)) { |
| // First Entry, same as off addOffset just increment localOffset |
| if (pTable[tableIdx][fieldId].offset == addOffset) { |
| totalOffset = localAddOffset + pTable[tableIdx][fieldId].offset; |
| } |
| else { |
| // Multiple Entry next index array, addOffset and localOffset |
| totalOffset = localAddOffset + pTable[tableIdx][fieldId].offset + |
| addOffset; |
| } |
| copyDataToBuiltInFromBin(tableIdx, fieldId, pStream, pos, totalOffset, |
| tableBaseOffset); |
| } |
| else { |
| // number of element |
| // get size of the sub-table |
| idxSubTable = (pTable[tableIdx][fieldId].fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| |
| fieldSize = 0; |
| sizeBuiltIn = getBuiltInFieldCount(tableIdx, |
| pTable[tableIdx][fieldId].fieldName, |
| &tableIdxBuiltIn, &fieldIdBuiltIn, &numElemBuiltIn); |
| incAddOffset = 0; |
| |
| if (numElemBuiltIn) { |
| incAddOffset = sizeBuiltIn/numElemBuiltIn; |
| } |
| |
| storageType = _STORAGE_TYPE(pTable[tableIdx][fieldId].fieldStorageType); |
| |
| fieldSize = 0; |
| fieldCount = getFieldCount(tableIdx, fieldId, numElem, 1); |
| |
| idx1 = _STORAGE_SIZE1(pTable[tableIdx][fieldId].fieldStorageSize1, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size1Bin = getNumElemOutOfStorageSize(idx1, |
| pTable[tableIdx][fieldId].fieldStorageSize1, 1); |
| |
| for (l=0; l < numElem3; l++) { |
| if (storageType == ARRAY_3) { |
| idx1 = _STORAGE_SIZE3(pTable[tableIdx][fieldId].fieldStorageSize3, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| |
| size3Bin = getNumElemOutOfStorageSize(idx1, |
| pTable[tableIdx][fieldId].fieldStorageSize3, 1); |
| |
| fieldSize = 0; |
| getBuiltInFieldCount(tableIdx, |
| pTable[tableIdx][fieldId].fieldName, &tableIdxBuiltIn, |
| &fieldIdBuiltIn, &numElemBuiltIn); |
| |
| idx1 = _STORAGE_SIZE3( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize3, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| size3BuiltIn = getNumElemOutOfStorageSize(idx1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize3, |
| 0); |
| |
| if (!IsFieldSizeInt(pTable[tableIdx][fieldId].fieldStorageSize3)) { |
| enumIdx = ((pTable[tableIdx][fieldId].fieldStorageSize3 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| if (NvEnumsFromBin[enumIdx][l].enumValuePeer == 0xFF) { |
| *pos = *pos + (fieldCount/size1Bin) * numElem * numElem2; |
| continue; |
| } |
| } |
| else { |
| if ((l+1) > size3BuiltIn) { |
| *pos = *pos + (fieldCount/size1Bin) * numElem * numElem2; |
| continue; |
| } |
| } |
| } |
| for (m=0; m < numElem2; m++) { |
| if (storageType == ARRAY_2) { |
| idx1 = _STORAGE_SIZE2( |
| pTable[tableIdx][fieldId].fieldStorageSize2, |
| pTable[tableIdx][fieldId].fieldStorageType); |
| size2Bin = getNumElemOutOfStorageSize(idx1, |
| pTable[tableIdx][fieldId].fieldStorageSize2, 1); |
| |
| fieldSize = 0; |
| getBuiltInFieldCount(tableIdx, |
| pTable[tableIdx][fieldId].fieldName, &tableIdxBuiltIn, |
| &fieldIdBuiltIn, &numElemBuiltIn); |
| |
| idx1 = _STORAGE_SIZE2( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize2, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size2BuiltIn = getNumElemOutOfStorageSize(idx1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize2, |
| 0); |
| |
| if (!IsFieldSizeInt( |
| pTable[tableIdx][fieldId].fieldStorageSize2)) { |
| enumIdx = ((pTable[tableIdx][fieldId].fieldStorageSize2 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| if (NvEnumsFromBin[enumIdx][m].enumValuePeer == 0xFF) { |
| *pos = *pos + (fieldCount/size1Bin) * numElem; |
| continue; |
| } |
| } |
| else { |
| if ((m+1) > size2BuiltIn) { |
| *pos = *pos + (fieldCount/size1Bin) * numElem; |
| continue; |
| } |
| } |
| } |
| for (j=0; j < numElem; j++) { |
| if (storageType == ARRAY_1) { |
| fieldSize = 0; |
| getBuiltInFieldCount(tableIdx, |
| pTable[tableIdx][fieldId].fieldName, &tableIdxBuiltIn, |
| &fieldIdBuiltIn, &numElemBuiltIn); |
| |
| idx1 = _STORAGE_SIZE1( |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageType); |
| |
| size1BuiltIn = getNumElemOutOfStorageSize(idx1, |
| pTableBuiltIn[tableIdxBuiltIn][fieldIdBuiltIn].fieldStorageSize1, |
| 0); |
| |
| if (!IsFieldSizeInt( |
| pTable[tableIdx][fieldId].fieldStorageSize1)) { |
| enumIdx = ((pTable[tableIdx][fieldId].fieldStorageSize1 & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| if (NvEnumsFromBin[enumIdx][j].enumValuePeer == 0xFF) { |
| *pos = *pos + (fieldCount/size1Bin); |
| continue; |
| } |
| } |
| else { |
| if ((j+1) > size1BuiltIn) { |
| *pos = *pos + (fieldCount/size1Bin); |
| continue; |
| } |
| } |
| } |
| |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[idxSubTable][i].fieldName[0]) { |
| // data parsing done for this stream |
| break; |
| } |
| |
| idx = _STORAGE_TYPE(pTable[idxSubTable][i].fieldStorageType); |
| numSubElem = numElemBasedOnStorageType[idx]( |
| &(pTable[idxSubTable][i]),1); |
| numSubElem2 = numSubElem3 = 1; |
| |
| if (idx == ARRAY_1) { |
| idx1 = _STORAGE_SIZE1( |
| pTable[idxSubTable][i].fieldStorageSize1, |
| pTable[idxSubTable][i].fieldStorageType); |
| numSubElem = getNumElemOutOfStorageSize(idx1, |
| pTable[idxSubTable][i].fieldStorageSize1, 1); |
| } |
| else if (idx == ARRAY_2) { |
| idx1 = _STORAGE_SIZE1( |
| pTable[idxSubTable][i].fieldStorageSize1, |
| pTable[idxSubTable][i].fieldStorageType); |
| numSubElem = getNumElemOutOfStorageSize(idx1, |
| pTable[idxSubTable][i].fieldStorageSize1, 1); |
| |
| idx1 = _STORAGE_SIZE2( |
| pTable[idxSubTable][i].fieldStorageSize2, |
| pTable[idxSubTable][i].fieldStorageType); |
| numSubElem2 = getNumElemOutOfStorageSize(idx1, |
| pTable[idxSubTable][i].fieldStorageSize2, 1); |
| } |
| else if (idx == ARRAY_3) { |
| idx1 = _STORAGE_SIZE1( |
| pTable[idxSubTable][i].fieldStorageSize1, |
| pTable[idxSubTable][i].fieldStorageType); |
| numSubElem = getNumElemOutOfStorageSize(idx1, |
| pTable[idxSubTable][i].fieldStorageSize1, 1); |
| |
| idx1 = _STORAGE_SIZE2( |
| pTable[idxSubTable][i].fieldStorageSize2, |
| pTable[idxSubTable][i].fieldStorageType); |
| numSubElem2 = getNumElemOutOfStorageSize(idx1, |
| pTable[idxSubTable][i].fieldStorageSize2, 1); |
| |
| idx1 = _STORAGE_SIZE3( |
| pTable[idxSubTable][i].fieldStorageSize3, |
| pTable[idxSubTable][i].fieldStorageType); |
| numSubElem3 = getNumElemOutOfStorageSize(idx1, |
| pTable[idxSubTable][i].fieldStorageSize3, 1); |
| } |
| |
| if (_OFFSET_NOT_SET != pTable[idxSubTable][i].offset) { |
| if ( pTable[tableIdx][fieldId].offset == addOffset ) { |
| parseSubDataTableAndCopy(idxSubTable, numSubElem, |
| numSubElem2, numSubElem3, i, pStream, pos, |
| addOffset, tableBaseOffset, localAddOffset); |
| } |
| else { |
| // NOT the first Entry in the table.. |
| if ( !pTable[tableIdx][fieldId].offset ) { |
| parseSubDataTableAndCopy(idxSubTable, numSubElem, |
| numSubElem2, numSubElem3, i, pStream, pos, |
| addOffset, tableBaseOffset, localAddOffset); |
| } |
| else { |
| //First Entry in the the table.. |
| //(Sending parent offset..) |
| parseSubDataTableAndCopy(idxSubTable, numSubElem, |
| numSubElem2, numSubElem3, i, pStream, pos, |
| addOffset, tableBaseOffset, |
| pTable[tableIdx][fieldId].offset); |
| } |
| } |
| } |
| else { |
| fieldSize = 0; |
| fieldCount = getFieldCount(idxSubTable, i, numSubElem, 1); |
| *pos += fieldCount; |
| } |
| } |
| |
| localAddOffset = localAddOffset + incAddOffset; |
| } |
| } |
| } |
| } |
| |
| return; |
| } |
| |
| static void processNvData(_NV_STREAM_BUF *pStream, int len) |
| { |
| int tableIdx, pos, idx = 0, addOffset = 0, i; |
| int numElem = 0, additionalOffset = 0, tableBaseOffset = 0; |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| |
| // fetch the table template |
| pos = 0; // stream header byte is already checked, that's why we are here |
| pos += _NV_BIN_DATA_STREAM_TABLEID_BYTE; |
| tableIdx = (pStream[_NV_BIN_DATA_STREAM_TABLEID_BYTE] & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| pos++; |
| |
| // call the table parsing |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[0][i].fieldName[0]) { |
| break; |
| } |
| if (tableIdx == _TABLE_IDX(pTable[0][i].fieldId)) { |
| // Table base offset, stored in the "table of all tables" (index 0), |
| // will be added to |
| // fields relative offset in all tables. |
| tableBaseOffset = pTable[0][i].offset; |
| |
| idx = _STORAGE_TYPE(pTable[0][i].fieldStorageType); |
| |
| // number of element |
| numElem = numElemBasedOnStorageType[idx](&(pTable[0][i]),1); |
| |
| // recursive calls for the total size of the subtable, which may |
| // contain nested tables |
| subTableSize = 0; |
| parseSubDataTable4Size(tableIdx, numElem); |
| |
| // additional offset for EACH subsequent table element |
| additionalOffset = subTableSize/numElem; |
| |
| break; |
| } |
| } |
| |
| if (numElem) { |
| for (i = 0; i < numElem; i++) { |
| addOffset = (i * additionalOffset); |
| parseDataTable_new(pStream, &pos, tableIdx, addOffset, |
| tableBaseOffset); |
| } |
| } |
| |
| // the above recursive data table parser takes care of the nested tables |
| // all done |
| return; |
| } |
| |
| static void parseDataTable_new(_NV_STREAM_BUF *pStream, int* pos, int tableIdx, |
| int addOffset, int tableBaseOffset) |
| { |
| _NV_TEMPLATE_TABLE (*pTable)[TABLE_ENTRIES_MAX] = NvTablesFromBin; |
| int i, idx, fieldCount; |
| int numElem, numElem2, numElem3, storageType, idxSubTable; |
| |
| // "apply" template to data -- parsing the actual NV data, |
| // so far we have been parsing and building templates |
| for (i = 0; i < TABLE_ENTRIES_MAX; i++) { |
| if (nul == pTable[tableIdx][i].fieldName[0]) { |
| // data parsing done for this stream |
| break; |
| } |
| |
| // get size of the sub-table |
| idxSubTable = (pTable[tableIdx][i].fieldId & |
| FIELD_ID_TABLE_OR_ENUM_IDX_MASK); |
| |
| idx = _STORAGE_TYPE(pTable[tableIdx][i].fieldStorageType); |
| |
| numElem = numElemBasedOnStorageType[idx](&(pTable[tableIdx][i]),1); |
| |
| addOffset = pTable[tableIdx][i].offset; |
| |
| fieldSize = 0; |
| fieldCount = getFieldCount(tableIdx, i, numElem, 1); |
| |
| numElem2 = numElem3 = 1; |
| |
| if (idx == ARRAY_1 ) { |
| storageType = _STORAGE_SIZE1(pTable[tableIdx][i].fieldStorageSize1, |
| pTable[tableIdx][i].fieldStorageType); |
| numElem = getNumElemOutOfStorageSize(storageType, |
| pTable[tableIdx][i].fieldStorageSize1, 1); |
| } |
| else if (idx == ARRAY_2) { |
| storageType = _STORAGE_SIZE1(pTable[tableIdx][i].fieldStorageSize1, |
| pTable[tableIdx][i].fieldStorageType); |
| |
| numElem = getNumElemOutOfStorageSize(storageType, |
| pTable[tableIdx][i].fieldStorageSize1, 1); |
| |
| storageType = _STORAGE_SIZE2(pTable[tableIdx][i].fieldStorageSize2, |
| pTable[tableIdx][i].fieldStorageType); |
| |
| numElem2 = getNumElemOutOfStorageSize(storageType, |
| pTable[tableIdx][i].fieldStorageSize2, 1); |
| } |
| else if (idx == ARRAY_3) { |
| storageType = _STORAGE_SIZE1(pTable[tableIdx][i].fieldStorageSize1, |
| pTable[tableIdx][i].fieldStorageType); |
| |
| numElem = getNumElemOutOfStorageSize(storageType, |
| pTable[tableIdx][i].fieldStorageSize1, 1); |
| |
| storageType = _STORAGE_SIZE2(pTable[tableIdx][i].fieldStorageSize2, |
| pTable[tableIdx][i].fieldStorageType); |
| |
| numElem2 = getNumElemOutOfStorageSize(storageType, |
| pTable[tableIdx][i].fieldStorageSize2, 1); |
| |
| storageType = _STORAGE_SIZE3(pTable[tableIdx][i].fieldStorageSize3, |
| pTable[tableIdx][i].fieldStorageType); |
| |
| numElem3 = getNumElemOutOfStorageSize(storageType, |
| pTable[tableIdx][i].fieldStorageSize3, 1); |
| } |
| |
| if (_OFFSET_NOT_SET != pTable[tableIdx][i].offset) { |
| parseSubDataTableAndCopy(tableIdx, numElem, numElem2, numElem3, i, |
| pStream, pos, addOffset, tableBaseOffset, 0); |
| } |
| else { |
| *pos += fieldCount; |
| } |
| } |
| } |
| |
| static void getBasicDataSize(_NV_TEMPLATE_TABLE *pTableEntry) |
| { |
| int numElem, sizeOneElem, totalSize; |
| int idx, idx1; |
| |
| // number of element |
| idx = _STORAGE_TYPE(pTableEntry->fieldStorageType); |
| numElem = numElemBasedOnStorageType[idx](pTableEntry, 1); |
| |
| // size of each element |
| idx1 = pTableEntry->fieldId & FIELD_ID_TABLE_OR_ENUM_IDX_MASK; |
| sizeOneElem = sizeOneElemBasedOnFieldIdBasicDataType[idx1]; |
| |
| // total size in bytes |
| totalSize = numElem * sizeOneElem; |
| |
| // all done, update global |
| subTableSize += totalSize; |
| |
| return; |
| } |
| |
| static int numElemSingular(_NV_TEMPLATE_TABLE *pTableEntry, int unused) |
| { |
| return 1; |
| } |
| |
| static int getNumElemOutOfStorageSize(int fieldStorageSize, |
| uint8 fieldStorageSizeLowByte, int nvBin) |
| { |
| int ret = 0; |
| if (IsFieldSizeInt(fieldStorageSizeLowByte)) { |
| return fieldStorageSize; |
| } |
| else { |
| int maxEnumVal=0, i; |
| _NV_TEMPLATE_ENUM (*pEnum)[ENUM_ENTRIES_MAX]; |
| int enumIdx = ((fieldStorageSizeLowByte & |
| FIELD_SIZE_VALUE_MASK) >> FIELD_SIZE_VALUE_LSB); |
| |
| if (nvBin) { |
| pEnum = NvEnumsFromBin; |
| } |
| else { |
| pEnum = NvEnumsBuiltIn; |
| } |
| |
| for (i = 0; i < ENUM_ENTRIES_MAX; i++) { |
| if (nul == pEnum[enumIdx][i].enumName[0]) { |
| if ( i == 0 ) { |
| maxEnumVal = 0; |
| } |
| else { |
| maxEnumVal = pEnum[enumIdx][i-1].enumValue; |
| } |
| break; |
| } |
| } |
| ret = (maxEnumVal + 1); |
| return ret; // +1 to count for 0 to maxEnumVal |
| } |
| } |
| |
| static int numElemArray1(_NV_TEMPLATE_TABLE *pTableEntry, int nvBin) |
| { |
| int fieldStorageSize = 0; |
| |
| fieldStorageSize = getNumElemOutOfStorageSize(_STORAGE_SIZE1( |
| pTableEntry->fieldStorageSize1, pTableEntry->fieldStorageType), |
| pTableEntry->fieldStorageSize1, nvBin); |
| |
| return fieldStorageSize; |
| } |
| |
| static int numElemArray2(_NV_TEMPLATE_TABLE *pTableEntry, int nvBin) |
| { |
| int fieldStorageSize1,fieldStorageSize2,fieldStorageSize; |
| |
| fieldStorageSize1 = getNumElemOutOfStorageSize(_STORAGE_SIZE1( |
| pTableEntry->fieldStorageSize1, |
| pTableEntry->fieldStorageType), |
| pTableEntry->fieldStorageSize1, nvBin); |
| |
| fieldStorageSize2 = getNumElemOutOfStorageSize(_STORAGE_SIZE2( |
| pTableEntry->fieldStorageSize2, |
| pTableEntry->fieldStorageType), |
| pTableEntry->fieldStorageSize2, nvBin); |
| |
| fieldStorageSize = fieldStorageSize1 * fieldStorageSize2; |
| |
| return fieldStorageSize; |
| } |
| |
| static int numElemArray3(_NV_TEMPLATE_TABLE *pTableEntry, int nvBin) |
| { |
| int fieldStorageSize1,fieldStorageSize2,fieldStorageSize3,fieldStorageSize; |
| |
| fieldStorageSize1 = getNumElemOutOfStorageSize(_STORAGE_SIZE1( |
| pTableEntry->fieldStorageSize1, |
| pTableEntry->fieldStorageType), |
| pTableEntry->fieldStorageSize1, nvBin); |
| |
| fieldStorageSize2 = getNumElemOutOfStorageSize(_STORAGE_SIZE2( |
| pTableEntry->fieldStorageSize2, |
| pTableEntry->fieldStorageType), |
| pTableEntry->fieldStorageSize2, nvBin); |
| |
| fieldStorageSize3 = getNumElemOutOfStorageSize(_STORAGE_SIZE3( |
| pTableEntry->fieldStorageSize3, |
| pTableEntry->fieldStorageType), |
| pTableEntry->fieldStorageSize3, nvBin); |
| |
| fieldStorageSize = fieldStorageSize1 * fieldStorageSize2 * fieldStorageSize3; |
| |
| return fieldStorageSize; |
| } |