diff --git a/board/netmodule/common/bdparser.c b/board/netmodule/common/bdparser.c new file mode 100644 index 0000000000..6a4817feb3 --- /dev/null +++ b/board/netmodule/common/bdparser.c @@ -0,0 +1,2101 @@ +/****************************************************************************** + * (c) COPYRIGHT 2009-2011 by NetModule AG, Switzerland. All rights reserved. + * + * The program(s) may only be used and/or copied with the written permission + * from NetModule AG or in accordance with the terms and conditions stipulated + * in the agreement contract under which the program(s) have been supplied. + * + * PACKAGE : Board descriptor + * + * ABSTRACT: + * This package implements board descriptor manipulation functions. + * + * HISTORY: + * Date Author Description + * 20091106 rb RFE-FB18392: created + * 20091110 rb Added checksum in header + * 20100121 rs Minor cleanup, const arguments specified + * 20100302 sma RFE-FB18392: created (partition) + * 20100322 th Adaptation WinCE and Win32 (includes/warnings) + * Added get bd info (type and name for standard entries) + * Added scan entries (init and get next) + * Added test scan entries (get entry) + * Added uint64 and partition64 + * 20110104 rs General code cleanup (style guide), added new tags/types + * Added bufLen parameter for BD_GetInfo() + * Fixed wrong sizeof type in GetPartition() + * Changed 64 bit type to "long long" from struct + * Added BD_VerifySha1Hmac() function + *****************************************************************************/ + +/*--- includes --------------------------------------------------------------*/ + +#include "bdparser.h" /* own header file */ +#include + + +/* Platform specific include files */ + +#ifdef BD_TARGET_WIN32 + #include /* memcpy, strlen, memset, memcmp */ +#endif + +#ifdef BD_TARGET_WINCE + #pragma warning(push) + #pragma warning(disable: 4115 4201 4204 4214) + #include + #pragma warning(pop) +#endif + +#ifdef BD_TARGET_LINUX + #include /* memcpy, strlen, memset, memcmp */ +#endif + +#ifdef BD_TARGET_UBOOT + #include /* memcpy, etc. */ +#endif + +#ifdef BD_TARGET_VXWORKS + #include "string.h" +// #include "stdlib.h" +// #include "stdio.h" +// #include "ioLib.h" +// #include "vxWorks.h" +#endif + +/* Make sure asserts are enabled when unit tests are required */ +#if defined(BD_CONF_UNIT_TESTS) && !defined (BD_CONF_WANT_ASSERT) + #error BD_CONF_UNIT_TESTS requires assertions +#endif + + +/*--- local variables -------------------------------------------------------*/ + +static const BD_Info bd_info[] = { + { BD_Serial , BD_Type_String , "serial" }, + { BD_Production_Date , BD_Type_Date , "proddate" }, + { BD_Hw_Ver , BD_Type_UInt8 , "hwver" }, + { BD_Hw_Rel , BD_Type_UInt8 , "hwrel" }, + { BD_Prod_Name , BD_Type_String , "prod_name" }, + { BD_Prod_Variant , BD_Type_UInt16 , "prod_variant" }, + { BD_Prod_Compatibility , BD_Type_String , "prod_compatibility" }, + + { BD_Eth_Mac , BD_Type_MAC , "eth_mac" }, + { BD_Ip_Addr , BD_Type_IPV4 , "ip_addr" }, + { BD_Ip_Netmask , BD_Type_IPV4 , "ip_netmask" }, + { BD_Ip_Gateway , BD_Type_IPV4 , "ip_gateway" }, + + { BD_Usb_Device_Id , BD_Type_UInt16 , "usb_device_id" }, + { BD_Usb_Vendor_Id , BD_Type_UInt16 , "usb_vendor_id" }, + + { BD_Ram_Size , BD_Type_UInt32 , "ram_size" }, + { BD_Ram_Size64 , BD_Type_UInt64 , "ram_size64" }, + { BD_Flash_Size , BD_Type_UInt32 , "flash_size" }, + { BD_Flash_Size64 , BD_Type_UInt64 , "flash_size64" }, + { BD_Eeeprom_Size , BD_Type_UInt32 , "eeprom_size" }, + { BD_Nv_Rram_Size , BD_Type_UInt32 , "nv_ram_size" }, + + { BD_Cpu_Base_Clk , BD_Type_UInt32 , "cpu_base_clk" }, + { BD_Cpu_Core_Clk , BD_Type_UInt32 , "cpu_core_clk" }, + { BD_Cpu_Bus_Clk , BD_Type_UInt32 , "cpu_bus_clk" }, + { BD_Ram_Clk , BD_Type_UInt32 , "ram_clk" }, + + { BD_Partition , BD_Type_Partition , "partition" }, + { BD_Partition64 , BD_Type_Partition64, "partition64" }, + + { BD_Lcd_Type , BD_Type_UInt16 , "lcd_type" }, + { BD_Lcd_Backlight , BD_Type_UInt8 , "lcd_backlight" }, + { BD_Lcd_Contrast , BD_Type_UInt8 , "lcd_contrast" }, + { BD_Touch_Type , BD_Type_UInt16 , "touch_type" }, + + { BD_Manufacturer_Id , BD_Type_String , "manufacturer_id" }, + { BD_Hmac_Sha1_4 , BD_Type_HMAC , "hmac-sha1" }, + + { BD_Ui_Adapter_Type , BD_Type_UInt16 , "ui_adapter_type" }, + { PD_Dev_Tree , BD_Type_String , "pd_dev_tree" }, + + /* Guard entry, must be last in array (don't remove) */ + { BD_End , BD_Type_End , 0 }, +}; + + +/*--- local functions -------------------------------------------------------*/ + +static void bd_safeStrCpy( char* pDest, bd_size_t destLen, + const char* pSrc, bd_size_t srcLen ) +{ + bd_size_t bytesToCopy = 0; + + /* Argument check */ + + BD_ASSERT( pDest != 0 ); + BD_ASSERT( destLen >= 1 ); + BD_ASSERT( pSrc != 0 ); + BD_ASSERT( srcLen <= BD_MAX_ENTRY_LEN ); + + /* Copy string, truncate if necessary */ + if ( srcLen <= (destLen - 1) ) + { + /* Whole string fits into supplied buffer */ + bytesToCopy = srcLen; + } + else + { + /* Truncate string to buffer size */ + bytesToCopy = destLen - 1; + } + + if ( bytesToCopy > 0 ) + { + memcpy( pDest, pSrc, bytesToCopy ); + } + pDest[bytesToCopy] = 0; +} + +/*---------------------------------------------------------------------------*/ + +static bd_uint16_t bd_getUInt16( const void* pBuf ) +{ + const bd_uint8_t* pui8Buf = 0; + bd_uint16_t value; + + BD_ASSERT( pBuf != 0 ); + + pui8Buf = (const bd_uint8_t*)pBuf; + value = (pui8Buf[0] << 8) + | (pui8Buf[1] << 0); + + return value; +} + +/*---------------------------------------------------------------------------*/ + +static bd_uint32_t bd_getUInt32( const void* pBuf ) +{ + const bd_uint8_t* pui8Buf = 0; + bd_uint32_t value; + + BD_ASSERT( pBuf != 0 ); + + pui8Buf = (const bd_uint8_t*)pBuf; + value = (pui8Buf[0] << 24) + | (pui8Buf[1] << 16) + | (pui8Buf[2] << 8) + | (pui8Buf[3] << 0); + + return value; +} + +/*---------------------------------------------------------------------------*/ + +static bd_uint64_t bd_getUInt64( const void* pBuf ) +{ + const bd_uint8_t* pui8Buf = 0; + bd_uint64_t value; + int i; + + BD_ASSERT( pBuf != 0 ); + pui8Buf = (const bd_uint8_t*)pBuf; + + value = 0; + for (i=0; i<8; i++) + { + value <<= 8; + value |= pui8Buf[i]; + } + + return value; +} + +/*---------------------------------------------------------------------------*/ + +static bd_bool_t bd_getInfo( bd_uint16_t tag, BD_Type* pType, char* pName, bd_size_t bufLen ) +{ + bd_bool_t rc = BD_FALSE; /* assume error */ + int index; + + for ( index = 0; bd_info[index].tag != BD_End; index++ ) + { + if ( bd_info[index].tag == tag ) + { + BD_ASSERT( bd_info[index].pName != 0 ); + + /* Found desired entry */ + rc = BD_TRUE; + + if( pType != 0 ) + { + /* Fill in type information */ + *pType = bd_info[index].type; + } + + if( pName != 0 ) + { + /* Fill in tag name */ + bd_safeStrCpy( pName, bufLen, bd_info[index].pName, strlen(bd_info[index].pName) ); + } + + break; + } + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +static bd_bool_t bd_getNextEntry( const BD_Context* pCtx, BD_Entry* pEntry ) +{ + bd_bool_t rc = BD_FALSE; /* assume error */ + const bd_uint8_t* pTemp = 0; + bd_uint16_t currTag = 0; + bd_uint16_t currLen = 0; + bd_bool_t first = BD_FALSE; /* assume error */ + + BD_ASSERT( pCtx != 0 ); + BD_ASSERT( pEntry != 0 ); + + /* Make sure we don't read beyond entry is NULL */ + if ( pEntry == 0 ) + { + return rc; + } + + /* Check for last entry*/ + if ( pEntry->entry >= pCtx->entries ) + { + return rc; + } + + /* For the first entry starts with the context buffer else the entry buffer minus header 4 bytes */ + if ( ( pEntry->pData == 0 ) ) + { + pTemp = pCtx->pData; + first = BD_TRUE; + } + else + { + pTemp = pEntry->pData - 4; + first = BD_FALSE; + } + + /* Make sure we don't read beyond data buffer is 0 */ + if ( pTemp == 0 ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + + /* Make sure we don't read beyond data buffer is valid range */ + if ( pTemp < pCtx->pData ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + + /* Make sure we don't read beyond data buffer when getting next tag/len */ + if ( (pTemp + 4) > pCtx->pDataEnd ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + + /* Read tag/length of current entry */ + currTag = bd_getUInt16( pTemp + 0 ); + currLen = bd_getUInt16( pTemp + 2 ); + + /* Validate length field */ + if ( currLen > BD_MAX_ENTRY_LEN ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + + /* Must not exceed data buffer */ + if ( (pTemp + 4 + currLen) > pCtx->pDataEnd ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + + if( first==BD_FALSE ) + { + /* Advance to next entry */ + pTemp += (4 + currLen); + + /* Make sure we don't read beyond data buffer when getting next tag/len */ + if ( (pTemp + 4) > pCtx->pDataEnd ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + + /* Read tag/length of current entry */ + currTag = bd_getUInt16( pTemp + 0 ); + currLen = bd_getUInt16( pTemp + 2 ); + + /* Validate length field */ + if ( currLen > BD_MAX_ENTRY_LEN ) + { + BD_ASSERT(BD_FALSE); + return rc; + } + } + + /* Fill the entry structure */ + pEntry->tag = currTag; + pEntry->len = currLen; + pEntry->entry++; + pEntry->pData = pTemp + 4; + + rc = BD_TRUE; + return rc; +} + +/*---------------------------------------------------------------------------*/ + +static const void* bd_findEntry( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint16_t* pLen ) +{ + const void* pResult = 0; + const bd_uint8_t* pTemp = 0; + bd_uint_t currIndex = 0; + bd_uint_t currEntry = 0; + + + BD_ASSERT( pCtx != 0 ); + BD_ASSERT( pCtx->initialized ); + BD_ASSERT( index < pCtx->entries ); + /* pLen is allowed to be 0, therefore no check is required. */ + + if ( pLen != 0 ) + { + *pLen = 0; + } + + /* Try to find desired entry in data buffer */ + + pTemp = (const bd_uint8_t*)pCtx->pData; + + for (currEntry = 0; currEntry < pCtx->entries; currEntry++) + { + bd_uint16_t currTag = 0; + bd_uint16_t currLen = 0; + + /* Make sure we don't read beyond data buffer when getting next tag/len */ + if ( (pTemp + 4) > pCtx->pDataEnd ) + { + BD_ASSERT(BD_FALSE); + break; + } + + /* Read tag/length of current entry */ + currTag = bd_getUInt16( pTemp + 0 ); + currLen = bd_getUInt16( pTemp + 2 ); + + /* Validate length field */ + if ( currLen > BD_MAX_ENTRY_LEN ) + { + BD_ASSERT(BD_FALSE); + break; + } + + /* Must not exceed data buffer */ + if ( (pTemp + 4 + currLen) > pCtx->pDataEnd ) + { + BD_ASSERT(BD_FALSE); + break; + } + + if ( currTag == tag ) + { + /* Desired entry found */ + if ( currIndex == index ) + { + /* Desired entry found (tag and index match) */ + /* Return pointer to data area of entry */ + pResult = pTemp + 4; + if ( pLen != 0 ) + { + *pLen = currLen; + } + break; + } + else + { + /* Not yet the entry we wanted, look further */ + currIndex++; + } + } + else if ( currTag == 0x0000 ) + { + /* Sorry, entry not found -> aborting */ + break; + } + + /* Advance to next entry */ + pTemp += (4 + currLen); + } + + return pResult; +} + + +/*--- global functions ------------------------------------------------------*/ + +bd_bool_t BD_CheckHeader( BD_Context* pCtx, const void* pHeader ) +{ + const char* pTemp = 0; + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pHeader == 0) + ) + { + return BD_FALSE; + } + + /* Initialize context */ + + pCtx->headerOk = BD_FALSE; + pCtx->initialized = BD_FALSE; + pCtx->size = 0; + pCtx->entries = 0; + pCtx->pData = 0; + pCtx->pDataEnd = 0; + + /* Check Identification */ + + pTemp = (const char*)pHeader; + if ( (pTemp[0] == 'B') && (pTemp[1] == 'D') && (pTemp[2] == 'V') && (pTemp[3] == '1') ) + { + bd_uint16_t payloadLen = 0; + bd_uint16_t checksum = 0; + + /* Valid ID -> Read payload length */ + + payloadLen = bd_getUInt16( pTemp+4 ); + checksum = bd_getUInt16( pTemp+6 ); + + /* Validate length, abort on unreasonable values */ + + if ( payloadLen <= BD_MAX_LENGTH ) + { + pCtx->size = payloadLen; + pCtx->checksum = checksum; + pCtx->headerOk = BD_TRUE; + + rc = BD_TRUE; + } + else + { + /* Invalid length */ + } + } + else + { + /* Unknown identification */ + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_ImportData( BD_Context* pCtx, const void* pData ) +{ + const bd_uint8_t* pTemp = 0; + bd_bool_t rc = BD_FALSE; /* assume error */ + bd_uint16_t tmpChecksum = 0; + size_t i; + + /* Argument check */ + + if ( (pCtx == 0) + || (pData == 0) + || !pCtx->headerOk /* BD_CheckHeader() has not yet been called */ + ) + { + return BD_FALSE; + } + + /* Scan through data, check consistency */ + + BD_ASSERT( pCtx->size <= BD_MAX_LENGTH ); + + pCtx->entries = 0; + pCtx->pData = (const bd_uint8_t*)pData; + pCtx->pDataEnd = pCtx->pData + pCtx->size; + + pTemp = (const bd_uint8_t*)pCtx->pData; + for (;;) + { + bd_uint16_t tag = 0; + bd_uint16_t len = 0; + + /* Make sure we don't read beyond data buffer when getting next tag/len */ + if ( (pTemp + 4) > pCtx->pDataEnd ) + { + /* @@@ RS: This would be an error */ + break; + } + + /* Read tag/length of current entry */ + tag = bd_getUInt16( pTemp + 0 ); + len = bd_getUInt16( pTemp + 2 ); + pTemp += 4; + + /* Validate length field */ + if ( len > BD_MAX_ENTRY_LEN ) + { + /* @@@ RS: This would be an error */ + break; + } + + /* Must not exceed data buffer */ + if ( (pTemp + len) > pCtx->pDataEnd ) + { + /* @@@ RS: This would be an error */ + break; + } + + /* Stop if end tag found */ + if ( tag == 0x0000 ) + { + rc = BD_TRUE; + break; + } + + /* Advance to next entry */ + pTemp += len; + + pCtx->entries++; + } + + /* If parsing was Ok and header contained a checksum, verify it */ + if ( rc && ( pCtx->checksum != 0 ) ) + { + /* Reset pointer to the start of the data/payload buffer */ + pTemp = (const bd_uint8_t*)pCtx->pData; + + /* Compute running byte checksum */ + for (i = 0; i < pCtx->size; i++) + { + tmpChecksum = (bd_uint16_t)( (tmpChecksum + pTemp[i]) & 0xFFFF ); + } + + if ( tmpChecksum != pCtx->checksum ) + { + /* Checksum does not match */ + rc = BD_FALSE; + } + } + + if ( rc ) + { + /* Everything ok */ + pCtx->initialized = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_ExistsEntry( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, 0 ); + if ( pData != 0 ) + { + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetInfo( bd_uint16_t tag, BD_Type* pType, char *pName, bd_size_t bufLen ) +{ + /* + * It is allowed to call this function with either pType or pName + * set to 0. In this case the fields will not be filled out + */ + return bd_getInfo( tag, pType, pName, bufLen ); +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_InitEntry( BD_Entry* pEntry ) +{ + /* Argument check */ + if ( pEntry == 0 ) + { + return BD_FALSE; + } + + memset(pEntry, 0, sizeof(BD_Entry)); + + return BD_TRUE; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetNextEntry( const BD_Context* pCtx, BD_Entry* pEntry ) +{ + /* Argument check */ + + if ( (pCtx == 0) + || !pCtx->initialized + || (pEntry == 0) + ) + { + return BD_FALSE; + } + + return bd_getNextEntry( pCtx, pEntry ); +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetVoid( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_bool_t* pResult ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 2) */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + *pResult = BD_FALSE; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + + /* Void tags necessarily have a length of 0 */ + if ( (pData != 0) && (len == 0) ) + { + *pResult = BD_TRUE; + } + + return BD_TRUE; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetUInt8( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint8_t* pResult ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 2) */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + *pResult = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 1) ) + { + *pResult = *(bd_uint8_t*)pData; + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetUInt16( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint16_t* pResult ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 2) */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + *pResult = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 2) ) + { + *pResult = bd_getUInt16( pData ); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetUInt32( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint32_t* pResult ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 4) */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + *pResult = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 4) ) + { + *pResult = bd_getUInt32( pData ); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetUInt64( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint64_t* pResult ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 4) */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + *pResult = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 8) ) + { + *pResult = bd_getUInt64( pData ); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetIPv4( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint32_t* pResult ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 4) */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + *pResult = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 4) ) + { + *pResult = bd_getUInt32( pData ); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetMAC( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, bd_uint8_t pResult[6] ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry (should be 4) */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + memset( pResult, 0x00, 6 ); + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 6) ) + { + memcpy( pResult, pData, 6 ); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetString( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, char* pResult, bd_size_t bufLen ) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + || (bufLen < 1) + ) + { + return BD_FALSE; + } + + BD_ASSERT( bufLen <= BD_MAX_ENTRY_LEN ); + + /* Clear result */ + pResult[0] = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( pData != 0 ) + { + bd_safeStrCpy( pResult, bufLen, pData, len ); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetBlob( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, + char* pResult, bd_size_t bufLen, bd_size_t* pReadLen) +{ + const void* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || (pReadLen == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + || (bufLen < 1) + ) + { + return BD_FALSE; + } + + BD_ASSERT( bufLen <= BD_MAX_ENTRY_LEN ); + + /* Initialize output value */ + *pReadLen = 0; + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len <= bufLen) ) + { + /* Copy binary data to user provided buffer */ + memcpy( pResult, pData, len ); + *pReadLen = len; + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetPartition( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, BD_PartitionEntry* pResult ) +{ + const bd_uint8_t* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + memset( pResult, 0x00, sizeof(BD_PartitionEntry) ); + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + + /* Size must be at least 10 to make sure we have all mandatory fields */ + if ( ( pData != 0 ) && ( len >= 10 ) ) + { + /* Copy the fix sized fields */ + pResult->flags = *pData; + pData++; + pResult->type = *pData; + pData++; + pResult->offset = bd_getUInt32(pData); + pData+=sizeof(bd_uint32_t); + pResult->size = bd_getUInt32(pData); + pData+=sizeof(bd_uint32_t); + + /* Copy the partition name */ + len -= 10; + bd_safeStrCpy(pResult->name, sizeof(pResult->name), (const char*)pData, len); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +bd_bool_t BD_GetPartition64( const BD_Context* pCtx, bd_uint16_t tag, + bd_uint_t index, BD_PartitionEntry64* pResult ) +{ + const bd_uint8_t* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry */ + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + if (pCtx == 0) { + return BD_FALSE; + } + if ( (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + /* Clear result */ + memset( pResult, 0x00, sizeof(BD_PartitionEntry64) ); + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + + /* Size must be at least 16 to make sure we have all mandatory fields */ + if ( ( pData != 0 ) && (len >= 16) ) + { + /* Copy the fix sized fields */ + pResult->flags = *pData; + pData++; + pResult->type = *pData; + pData++; + pResult->options = *pData; + pData++; + pData+=5; + pResult->offset = bd_getUInt64(pData); + pData+=sizeof(bd_uint64_t); + pResult->size = bd_getUInt64(pData); + pData+=sizeof(bd_uint64_t); + + /* Copy the partition name */ + len -= 16; + bd_safeStrCpy(pResult->name, sizeof(pResult->name), (const char*)pData, len); + + rc = BD_TRUE; + } + + return rc; +} + +/*---------------------------------------------------------------------------*/ + +#ifdef BD_CONF_HAS_HASH + +bd_bool_t BD_VerifySha1Hmac( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, const void* pKey, bd_size_t keyLen ) +{ + const bd_uint8_t* pData = 0; /* pointer to entry data */ + bd_uint16_t len = 0; /* len of entry */ + bd_uint16_t hashDataLen = 0; /* number of bytes to hash */ + const bd_uint8_t* pRefHash; + bd_uint8_t computedHash[160/8]; + bd_bool_t rc = BD_FALSE; /* assume error */ + + /* Argument check */ + + if ( (pCtx == 0) + || (pKey == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { + return BD_FALSE; + } + + BD_ASSERT((keyLen >= 4) && (keyLen <= 256)); + + /* Try to find desired entry */ + pData = bd_findEntry( pCtx, tag, index, &len ); + if ( (pData != 0) && (len == 6) ) + { + /* Determine amount of data to hash */ + hashDataLen = bd_getUInt16(pData); + pData += 2; + BD_ASSERT( hashDataLen < BD_MAX_LENGTH ); + + /* Remember hash value specified in tag */ + pRefHash = pData; + pData += 4; + + /* Compute hash over specified range */ + BD_SHA1_HASH_FUNC(pKey, keyLen, pData, hashDataLen, computedHash); + + /* Compare computed hash value with the one stored in the tag */ + if (memcmp(computedHash, pRefHash, 4) == 0) + { + /* Ok -> Hashes match */ + rc = BD_TRUE; + } + } + + return rc; +} + +#endif /* BD_CONF_HAS_HASH */ + + +/*--- unit test -------------------------------------------------------------*/ + +#ifdef BD_CONF_UNIT_TESTS + +static void bd_testHelpers( void ) +{ + static const bd_uint8_t data[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }; + bd_uint64_t t64; + bd_uint32_t t32; + bd_uint16_t t16; + char tempBuf[4]; + + t16 = bd_getUInt16( data ); + BD_ASSERT( t16 == 0x1234 ); + + t32 = bd_getUInt32( data ); + BD_ASSERT( t32 == 0x12345678 ); + + t64 = bd_getUInt64( data ); + BD_ASSERT( t64 == 0x123456789abcdef0ULL ); + + memset(tempBuf, 0xAA, 4); + bd_safeStrCpy(tempBuf, 4, "xy", 2); + BD_ASSERT(tempBuf[0] == 'x'); + BD_ASSERT(tempBuf[1] == 'y'); + BD_ASSERT(tempBuf[2] == 0); + + memset(tempBuf, 0xAA, 4); + bd_safeStrCpy(tempBuf, 4, "abc", 3); + BD_ASSERT(tempBuf[2] == 'c'); + BD_ASSERT(tempBuf[3] == 0); + + memset(tempBuf, 0xAA, 4); + bd_safeStrCpy(tempBuf, 4, "bcde", 4); + BD_ASSERT(tempBuf[2] == 'd'); + BD_ASSERT(tempBuf[3] == 0); + + memset(tempBuf, 0xAA, 4); + bd_safeStrCpy(tempBuf, 4, "defghi", 6); + BD_ASSERT(tempBuf[2] == 'f'); + BD_ASSERT(tempBuf[3] == 0); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testCheckHeader( void ) +{ + static const bd_uint8_t hdrGood[] = { 'B', 'D', 'V', '1', 0x00, 0x10, 0x00, 0x00 }; + static const bd_uint8_t hdrBad1[] = { 'B', 'X', 'Y', 'Z', 0x00, 0x10, 0x00, 0x00 }; + static const bd_uint8_t hdrBad2[] = { 'B', 'D', 'V', '1', 0x10, 0x01, 0x00, 0x00 }; + + BD_Context bdCtx; + bd_bool_t rc; + + + /* No context, no header */ + rc = BD_CheckHeader( 0, 0 ); + BD_ASSERT( !rc ); + + /* No header */ + rc = BD_CheckHeader( &bdCtx, 0 ); + BD_ASSERT( !rc ); + + /* No context */ + rc = BD_CheckHeader( 0, hdrGood ); + BD_ASSERT( !rc ); + + /* Invalid header (identification) */ + rc = BD_CheckHeader( &bdCtx, hdrBad1 ); + BD_ASSERT( !rc ); + + /* Invalid header (length) */ + rc = BD_CheckHeader( &bdCtx, hdrBad2 ); + BD_ASSERT( !rc ); + + /* Ok */ + rc = BD_CheckHeader( &bdCtx, hdrGood ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.headerOk ); + BD_ASSERT( bdCtx.size == 16 ); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testImport( void ) +{ + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, 0x04, 0x00, 0x00 }; + static const bd_uint8_t data1[] = { 0x00, 0x00, 0x00, 0x00 }; + + static const bd_uint8_t hdr2[] = { 'B', 'D', 'V', '1', 0x00, 13, 0x00, 0x00 }; + static const bd_uint8_t data2[] = { 0x00, 0x01, 0x00, 0x05, 'A', 'B', 'C', 'D', 'E', 0x00, 0x00, 0x00, 0x00 }; + + BD_Context bdCtx; + bd_bool_t rc; + + /* Case 0: End tag only */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 0 ); + + /* Case 1: One string entry, end tag */ + rc = BD_CheckHeader( &bdCtx, hdr2 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data2 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testChecksum( void ) +{ + /* 1 void tag + end tag with valid checksum */ + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, 0x08, 0x00, 0x04 }; + static const bd_uint8_t data1[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + /* 1 void tag + end tag with invalid checksum */ + static const bd_uint8_t hdr2[] = { 'B', 'D', 'V', '1', 0x00, 0x08, 0x00, 0x02 }; + static const bd_uint8_t data2[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + /* 1 void tag + end tag without checksum */ + static const bd_uint8_t hdr3[] = { 'B', 'D', 'V', '1', 0x00, 0x08, 0x00, 0x00 }; + static const bd_uint8_t data3[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + BD_Context bdCtx; + bd_bool_t rc; + + + /* Case 0: valid checksum */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); + BD_ASSERT( bdCtx.checksum == 0x4 ); + + /* Case 1: invalid checksum */ + rc = BD_CheckHeader( &bdCtx, hdr2 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data2 ); + BD_ASSERT( !rc ); + + /* Case 2: no checksum */ + rc = BD_CheckHeader( &bdCtx, hdr3 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data3 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); + BD_ASSERT( bdCtx.checksum == 0 ); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testGetUInt( void ) +{ + static const bd_uint8_t data1[] = { 0x00, 0x01, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, + 0x00, 0x01, 0x00, 0x04, 0xca, 0xfe, 0xba, 0xbe, + 0x00, 0x02, 0x00, 0x02, 0x47, 0x11, + 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data1), 0x00, 0x00 }; + + BD_Context bdCtx; + bd_uint32_t result32; + bd_uint16_t result16; + bd_bool_t rc; + + + /* Initialize */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.entries == 3 ); + + + /* Unknown tag */ + rc = BD_ExistsEntry( &bdCtx, 1001, 0 ); + BD_ASSERT( !rc ); + + /* Unknown index */ + rc = BD_ExistsEntry( &bdCtx, 1, 2 ); + BD_ASSERT( !rc ); + + /* Ok */ + rc = BD_ExistsEntry( &bdCtx, 1, 0 ); + BD_ASSERT( rc ); + + rc = BD_ExistsEntry( &bdCtx, 1, 1 ); + BD_ASSERT( rc ); + + rc = BD_ExistsEntry( &bdCtx, 2, 0 ); + BD_ASSERT( rc ); + + + /* No context */ + rc = BD_GetUInt32( 0, 1, 0, &result32 ); + BD_ASSERT( !rc ); + + /* No result pointer */ + rc = BD_GetUInt32( &bdCtx, 1, 0, 0 ); + BD_ASSERT( !rc ); + + /* Index > number of entries */ + rc = BD_GetUInt32( &bdCtx, 1, 3, &result32 ); + BD_ASSERT( !rc ); + + /* Unknown tag */ + rc = BD_GetUInt32( &bdCtx, 1001, 0, &result32 ); + BD_ASSERT( !rc ); + + /* Entry with wrong size */ + rc = BD_GetUInt32( &bdCtx, 2, 0, &result32 ); + BD_ASSERT( !rc ); + + /* Ok: First entry */ + rc = BD_GetUInt32( &bdCtx, 1, 0, &result32 ); + BD_ASSERT( rc ); + BD_ASSERT( result32 == 0x12345678 ); + + /* Ok: Second entry */ + rc = BD_GetUInt32( &bdCtx, 1, 1, &result32 ); + BD_ASSERT( rc ); + BD_ASSERT( result32 == 0xcafebabe ); + + /* Ok: */ + rc = BD_GetUInt16( &bdCtx, 2, 0, &result16 ); + BD_ASSERT( rc ); + BD_ASSERT( result16 == 0x4711 ); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testGetString( void ) +{ + static const bd_uint8_t data1[] = { 0x00, 0x01, 0x00, 0x05, 'A', 'B', 'C', 'D', 'E', 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data1), 0x00, 0x00 }; + + BD_Context bdCtx; + char buffer[16]; + bd_bool_t rc; + + + /* Initialize */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); + + /* Zero sized buffer */ + rc = BD_GetString( &bdCtx, 1, 0, buffer, 0 ); + BD_ASSERT(!rc); + + /* One byte buffer (terminating 0 only) */ + memset(buffer, 0xCC, sizeof(buffer)); + rc = BD_GetString( &bdCtx, 1, 0, buffer, 1 ); + BD_ASSERT(rc); + BD_ASSERT(buffer[0] == 0); + + /* String exactly fits buffer */ + memset(buffer, 0xCC, sizeof(buffer)); + rc = BD_GetString( &bdCtx, 1, 0, buffer, 6 ); + BD_ASSERT(rc); + BD_ASSERT(buffer[4] == 'E'); + BD_ASSERT(buffer[5] == 0); + + /* Buffer one too short */ + memset(buffer, 0xCC, sizeof(buffer)); + rc = BD_GetString( &bdCtx, 1, 0, buffer, 5 ); + BD_ASSERT(rc); + BD_ASSERT(buffer[3] == 'D'); + BD_ASSERT(buffer[4] == 0); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testGetMAC( void ) +{ + static const bd_uint8_t data1[] = { 0x00, 0x11, 0x00, 0x06, 0x00, 0xA0, 0xBA, 0x12, 0x34, 0x56, + 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data1), 0x00, 0x00 }; + + BD_Context bdCtx; + bd_uint8_t buffer[6]; + bd_bool_t rc; + + + /* Initialize */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); + + /* Non-existing entry */ + memset(buffer, 0xCC, sizeof(buffer)); + rc = BD_GetMAC( &bdCtx, 1017, 0, buffer ); + BD_ASSERT(!rc); + BD_ASSERT(buffer[0] == 0); + BD_ASSERT(buffer[1] == 0); + BD_ASSERT(buffer[2] == 0); + BD_ASSERT(buffer[3] == 0); + BD_ASSERT(buffer[4] == 0); + BD_ASSERT(buffer[5] == 0); + + /* Ok */ + memset(buffer, 0xCC, sizeof(buffer)); + rc = BD_GetMAC( &bdCtx, 17, 0, buffer ); + BD_ASSERT(rc); + BD_ASSERT(buffer[0] == 0x00); + BD_ASSERT(buffer[1] == 0xA0); + BD_ASSERT(buffer[2] == 0xBA); + BD_ASSERT(buffer[3] == 0x12); + BD_ASSERT(buffer[4] == 0x34); + BD_ASSERT(buffer[5] == 0x56); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testGetIPv4( void ) +{ /* IP = 192.168.2.1 = 0xC0A80201 */ + static const bd_uint8_t data1[] = { 0x00, 0x12, 0x00, 0x04, 0xC0, 0xA8, 0x02, 0x01, + 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data1), 0x00, 0x00 }; + + BD_Context bdCtx; + bd_uint32_t ipAddr; + bd_bool_t rc; + + + /* Initialize */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); + + /* Ok */ + ipAddr = 0; + rc = BD_GetIPv4( &bdCtx, 18, 0, &ipAddr ); + BD_ASSERT(rc); + BD_ASSERT(ipAddr == 0xC0A80201); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testGetPartition( void ) +{ + /* Name with length zero */ + static const bd_uint8_t data1[] = { 0x00, 0x18, 0x00, 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data1), 0x00, 0x00 }; + + /* Name with length 5 */ + static const bd_uint8_t data2[] = { 0x00, 0x18, 0x00, 0x0F, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 'N', 'a', 'm', 'e', '5', 0x00, 0x00, 0x00, 0x00}; + static const bd_uint8_t hdr2[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data2), 0x00, 0x00 }; + + /* Name with length 16 */ + static const bd_uint8_t data3[] = { 0x00, 0x18, 0x00, 0x1A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr3[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data3), 0x00, 0x00 }; + + /* Name with length 17 */ + static const bd_uint8_t data4[] = { 0x00, 0x18, 0x00, 0x1B, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'x', 0x00, 0x00, 0x00, 0x00 }; + static const bd_uint8_t hdr4[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data4), 0x00, 0x00 }; + + /* Too short BD */ + static const bd_uint8_t data5[] = { 0x00, 0x18, 0x00, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x00, 0x00 }; + static const bd_uint8_t hdr5[] = { 'B', 'D', 'V', '1', 0x00, sizeof(data5), 0x00, 0x00, 0x00, 0x00 }; + + BD_Context bdCtx; + BD_PartitionEntry bd_partitionEntry; + bd_bool_t rc; + + /* Initialize */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == 1 ); + + /* 0 buffer */ + rc = BD_GetPartition( &bdCtx, BD_Partition, 0, 0 ); + BD_ASSERT(!rc); + + /* Check values */ + rc = BD_GetPartition( &bdCtx, BD_Partition, 0, &bd_partitionEntry ); + BD_ASSERT(rc); + BD_ASSERT(bd_partitionEntry.flags == 0x01); + BD_ASSERT(bd_partitionEntry.type == 0x02); + BD_ASSERT(bd_partitionEntry.size == 0x0708090a); + BD_ASSERT(bd_partitionEntry.offset == 0x03040506); + + /* Check string length is 0 */ + BD_ASSERT(bd_partitionEntry.name[0] == 0); + + /* Check string length in bd 5 */ + rc = BD_CheckHeader( &bdCtx, hdr2 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data2 ); + BD_ASSERT( rc ); + rc = BD_GetPartition( &bdCtx, BD_Partition, 0, &bd_partitionEntry ); + BD_ASSERT(rc); + BD_ASSERT(bd_partitionEntry.name[0] == 'N'); + BD_ASSERT(bd_partitionEntry.name[4] == '5'); + BD_ASSERT(bd_partitionEntry.name[5] == 0); + + /* Check string length in bd 16*/ + rc = BD_CheckHeader( &bdCtx, hdr3 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data3 ); + BD_ASSERT( rc ); + rc = BD_GetPartition( &bdCtx, BD_Partition, 0, &bd_partitionEntry ); + BD_ASSERT(rc); + BD_ASSERT(bd_partitionEntry.name[0] == '0'); + BD_ASSERT(bd_partitionEntry.name[15] == 'f'); + BD_ASSERT(bd_partitionEntry.name[16] == 0); + + /* Check string length in bd 17 */ + rc = BD_CheckHeader( &bdCtx, hdr4 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data4 ); + BD_ASSERT( rc ); + rc = BD_GetPartition( &bdCtx, BD_Partition, 0, &bd_partitionEntry ); + BD_ASSERT(rc); + BD_ASSERT(bd_partitionEntry.name[0] == '0'); + BD_ASSERT(bd_partitionEntry.name[15] == 'F'); + BD_ASSERT(bd_partitionEntry.name[16] == 0); + + /* BD too short */ + rc = BD_CheckHeader( &bdCtx, hdr5 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data5 ); + BD_ASSERT( !rc ); +} + +/*---------------------------------------------------------------------------*/ + +static void bd_testGetEntry( void ) +{ + #define BD16(var) (bd_uint8_t)(((var) >> 8) & 0x00FF), (bd_uint8_t)(((var) >> 0) & 0x00FF) + + typedef struct _BD_IndexTable + { + bd_uint16_t tag; /**< Tag of entry */ + bd_uint_t index; /**< Index of entry */ + } + BD_IndexTable; + + static const bd_uint_t num_entries = 51; // without end tag + static const bd_uint8_t data1[] = + { + // serial[0]: 'Serial' + (bd_uint8_t)(BD_Serial>>8), (bd_uint8_t)(BD_Serial>>0), 0x00, 0x06, + 'S', 'e', 'r', 'i', 'a', 'l', + // date[0]: '01.01.2000' + (bd_uint8_t)(BD_Production_Date>>8), (bd_uint8_t)(BD_Production_Date>>0), 0x00, 0x0A, + '0', '1', '.', '0', '1', '.', '2', '0', '0', '0', + // version[0]: 1 + (bd_uint8_t)(BD_Hw_Ver>>8), (bd_uint8_t)(BD_Hw_Ver>>0), 0x00, sizeof(bd_uint8_t), + 0x01, + // release[0]: 0 + (bd_uint8_t)(BD_Hw_Rel>>8), (bd_uint8_t)(BD_Hw_Rel>>0), 0x00, sizeof(bd_uint8_t), + 0x00, + // name[0]: 'Product' + (bd_uint8_t)(BD_Prod_Name>>8), (bd_uint8_t)(BD_Prod_Name>>0), 0x00, 0x07, + 'P', 'r', 'o', 'd', 'u', 'c', 't', + // variant[0]: 0xF0A5 + (bd_uint8_t)(BD_Prod_Variant>>8), (bd_uint8_t)(BD_Prod_Variant>>0), 0x00, sizeof(bd_uint16_t), + 0xF0, 0xA5, + // compatibility[0]: 'Comp' + (bd_uint8_t)(BD_Prod_Compatibility>>8), (bd_uint8_t)(BD_Prod_Compatibility>>0), 0x00, 0x04, + 'C', 'o', 'm', 'p', + // mac 05:14:23:32:41:50 + (bd_uint8_t)(BD_Eth_Mac>>8), (bd_uint8_t)(BD_Eth_Mac>>0), 0x00, 0x06, + 0x05, 0x14, 0x23, 0x32, 0x41, 0x50, + // ipv4-addr[0]: 192.168.0.2 + (bd_uint8_t)(BD_Ip_Addr>>8), (bd_uint8_t)(BD_Ip_Addr>>0), 0x00, sizeof(bd_uint32_t), + 192, 168, 0, 2, + // ipv4-mask[0]: 255.255.255.0 + (bd_uint8_t)(BD_Ip_Netmask>>8), (bd_uint8_t)(BD_Ip_Netmask>>0), 0x00, sizeof(bd_uint32_t), + 255, 255, 255, 0, + + // ipv4-gateway[0]: 192.168.0.1 + (bd_uint8_t)(BD_Ip_Gateway>>8), (bd_uint8_t)(BD_Ip_Gateway>>0), 0x00, sizeof(bd_uint32_t), + 192, 168, 0, 1, + // ipv4-addr[0]: 172.20.0.2 + (bd_uint8_t)(BD_Ip_Addr>>8), (bd_uint8_t)(BD_Ip_Addr>>0), 0x00, sizeof(bd_uint32_t), + 172, 20, 0, 2, + // ipv4-mask[0]: 255.255.0.0 + (bd_uint8_t)(BD_Ip_Netmask>>8), (bd_uint8_t)(BD_Ip_Netmask>>0), 0x00, sizeof(bd_uint32_t), + 255, 255, 0, 0, + // ipv4-gateway[0]: 172.20.0.1 + (bd_uint8_t)(BD_Ip_Gateway>>8), (bd_uint8_t)(BD_Ip_Gateway>>0), 0x00, sizeof(bd_uint32_t), + 172, 20, 0, 1, + // usbd-pid[0]: 0xAABB + (bd_uint8_t)(BD_Usb_Device_Id>>8), (bd_uint8_t)(BD_Usb_Device_Id>>0), 0x00, sizeof(bd_uint16_t), + 0xAA, 0xBB, + // usbd-vid[0]: 0xCCDD + (bd_uint8_t)(BD_Usb_Vendor_Id>>8), (bd_uint8_t)(BD_Usb_Vendor_Id>>0), 0x00, sizeof(bd_uint16_t), + 0xCC, 0xDD, + // ram-size[0]: 0xA0A1A2A3 + (bd_uint8_t)(BD_Ram_Size>>8), (bd_uint8_t)(BD_Ram_Size>>0), 0x00, sizeof(bd_uint32_t), + 0xA0, 0xA1, 0xA2, 0xA3, + // ram-size64[0]: 0xB0B1B2B3B4B5B6B7 + (bd_uint8_t)(BD_Ram_Size64>>8), (bd_uint8_t)(BD_Ram_Size64>>0), 0x00, sizeof(bd_uint64_t), + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + // flash-size[0]: 0x00000000 + (bd_uint8_t)(BD_Flash_Size>>8), (bd_uint8_t)(BD_Flash_Size>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + // flash-size64[0]: 0x0000000000000000 + (bd_uint8_t)(BD_Flash_Size64>>8), (bd_uint8_t)(BD_Flash_Size64>>0), 0x00, sizeof(bd_uint64_t), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // e2p-size[0]: 0x00000000 + (bd_uint8_t)(BD_Eeeprom_Size>>8), (bd_uint8_t)(BD_Eeeprom_Size>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + // nvram-size64[0]: 0x00000000 + (bd_uint8_t)(BD_Nv_Rram_Size>>8), (bd_uint8_t)(BD_Nv_Rram_Size>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + // cpu-core-clock[0]: 0x00000000 + (bd_uint8_t)(BD_Cpu_Base_Clk>>8), (bd_uint8_t)(BD_Cpu_Base_Clk>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + // cpu-base-clock[0]: 0x00000000 + (bd_uint8_t)(BD_Cpu_Core_Clk>>8), (bd_uint8_t)(BD_Cpu_Core_Clk>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + // cpubus-clock[0]: 0x00000000 + (bd_uint8_t)(BD_Cpu_Bus_Clk>>8), (bd_uint8_t)(BD_Cpu_Bus_Clk>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + // cpuram-clock[0]: 0x00000000 + (bd_uint8_t)(BD_Ram_Clk>>8), (bd_uint8_t)(BD_Ram_Clk>>0), 0x00, sizeof(bd_uint32_t), + 0x00, 0x00, 0x00, 0x00, + + // partition[0]: (len=0x0F) [ACTIVE, BOOTLOADER, offset=0x00010203, size=0x04050607, 'Part0'] + (bd_uint8_t)(BD_Partition>>8), (bd_uint8_t)(BD_Partition>>0), 0x00, 0x0F, + BD_Partition_Flags_Active, + BD_Partition_Type_Raw_BootLoader, + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 'P', 'a', 'r', 't', '0', + // partition[0]: (len=0x0F) [INACTIVE, YAFFS2, offset=0x00112233, size=0x44556677, 'Part1'] + (bd_uint8_t)(BD_Partition>>8), (bd_uint8_t)(BD_Partition>>0), 0x00, 2*sizeof(bd_uint8_t)+2*sizeof(bd_uint32_t)+5, + BD_Partition_Flags_None, + BD_Partition_Type_FS_YAFFS2, + 0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 'P', 'a', 'r', 't', '1', + // partition[0]: (len=0x0F) [ACTIVE, BBT, offset=0xFF00AA55, size=0x00FF55AA, 'Part2'] + (bd_uint8_t)(BD_Partition>>8), (bd_uint8_t)(BD_Partition>>0), 0x00, 2*sizeof(bd_uint8_t)+2*sizeof(bd_uint32_t)+5, + BD_Partition_Flags_Active, + BD_Partition_Type_Raw_BBT, + 0xFF, 0x00, 0xAA, 0x55, + 0x00, 0xFF, 0x55, 0xAA, + 'P', 'a', 'r', 't', '2', + // partition64[0]: (len=0x0F) [ACTIVE, BBT, ReadOnly, offset=0x0000FFFF'FF00AA55, size=0000FFFF'0x00FF55AA, 'Part3'] + (bd_uint8_t)(BD_Partition64>>8), (bd_uint8_t)(BD_Partition64>>0), 0x00, 8*sizeof(bd_uint8_t)+2*sizeof(bd_uint64_t)+5, + BD_Partition_Flags_Active, + BD_Partition_Type_FS_YAFFS2, + BD_Partition_Opts_ReadOnly, + 0,0,0,0,0, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xAA, 0x55, + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x55, 0xAA, + 'P', 'a', 'r', 't', '3', + + // lcd-type[0]: 0x0000 + (bd_uint8_t)(BD_Lcd_Type>>8), (bd_uint8_t)(BD_Lcd_Type>>0), 0x00, sizeof(bd_uint16_t), + 0x00, 0x00, + // lcd-backlight[0]: 0x0000 + (bd_uint8_t)(BD_Lcd_Backlight>>8), (bd_uint8_t)(BD_Lcd_Backlight>>0), 0x00, sizeof(bd_uint8_t), + 0x01, + // lcd-contrast[0]: 0x0000 + (bd_uint8_t)(BD_Lcd_Contrast>>8), (bd_uint8_t)(BD_Lcd_Contrast>>0), 0x00, sizeof(bd_uint8_t), + 0x7F, + // adapter-type[0]: 0x0000 + BD16(BD_Ui_Adapter_Type), 0x00, sizeof(bd_uint16_t), + 0x00, 0x00, + + // user void[0-15]: - + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + + // user row data[0]: 00 01 02 03 04 05 06 07 08 ... 3F + 0x80, 0x01, 0x00, 0x40, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + + // end + (bd_uint8_t)(BD_End>>8), (bd_uint8_t)(BD_End>>0), 0x00, 0x00, + }; + static const bd_uint8_t hdr1[] = { 'B', 'D', 'V', '1', BD16(sizeof(data1)), BD16(0x0000) }; + static BD_IndexTable indexTable[BD_MAX_LENGTH/4]; + + BD_Context bdCtx; + BD_Entry bd_entry; + char name[128]; + unsigned char value[BD_MAX_ENTRY_LEN]; + bd_uint_t num = 0; + bd_uint_t index = 0; + bd_size_t len = 0; + int i = 0; + BD_Type type = BD_Type_None; + bd_bool_t rc = BD_TRUE; + + memset(&bdCtx, 0, sizeof(bdCtx)); + memset(&bd_entry, 0, sizeof(bd_entry)); + memset(indexTable, 0, sizeof(indexTable)); + memset(name, 0, sizeof(name)); + memset(value, 0, sizeof(value)); + + /* initialize */ + rc = BD_CheckHeader( &bdCtx, hdr1 ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, data1 ); + BD_ASSERT( rc ); + BD_ASSERT( bdCtx.initialized ); + BD_ASSERT( bdCtx.entries == num_entries ); + rc = BD_InitEntry(&bd_entry); + BD_ASSERT( rc ); + + /* get all bd entries */ + while(BD_GetNextEntry(&bdCtx, &bd_entry)==BD_TRUE) { + for(i=0;i= 0) && (index < 16)) { + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_UInt8: { + rc = BD_GetUInt8 (&bdCtx, bd_entry.tag, index, (bd_uint8_t *)value); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Hw_Ver) && (index == 0)) { + BD_ASSERT( *((bd_uint8_t *)value) == 0x01 ); + } else if((bd_entry.tag==BD_Hw_Rel) && (index == 0)) { + BD_ASSERT( *((bd_uint8_t *)value) == 0x00 ); + } else if((bd_entry.tag==BD_Lcd_Backlight) && (index == 0)) { + BD_ASSERT( *((bd_uint8_t *)value) == 0x01 ); + } else if((bd_entry.tag==BD_Lcd_Contrast) && (index == 0)) { + BD_ASSERT( *((bd_uint8_t *)value) == 0x7F ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_UInt16: { + rc = BD_GetUInt16(&bdCtx, bd_entry.tag, index, (bd_uint16_t *)value); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Prod_Variant) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0xF0A5 ); + } else if((bd_entry.tag==BD_Prod_Variant) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0xF0A5 ); + } else if((bd_entry.tag==BD_Prod_Variant) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0xF0A5 ); + } else if((bd_entry.tag==BD_Usb_Device_Id) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0xAABB ); + } else if((bd_entry.tag==BD_Usb_Vendor_Id) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0xCCDD ); + } else if((bd_entry.tag==BD_Lcd_Type) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0x0000 ); + } else if((bd_entry.tag==BD_Ui_Adapter_Type) && (index == 0)) { + BD_ASSERT( *((bd_uint16_t *)value) == 0x0000 ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_UInt32: { + rc = BD_GetUInt32(&bdCtx, bd_entry.tag, index, (bd_uint32_t *)value); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Ram_Size) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0xA0A1A2A3 ); + } else if((bd_entry.tag==BD_Flash_Size) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else if((bd_entry.tag==BD_Eeeprom_Size) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else if((bd_entry.tag==BD_Nv_Rram_Size) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else if((bd_entry.tag==BD_Cpu_Base_Clk) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else if((bd_entry.tag==BD_Cpu_Core_Clk) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else if((bd_entry.tag==BD_Cpu_Bus_Clk) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else if((bd_entry.tag==BD_Ram_Clk) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == 0x00000000 ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_UInt64: { + rc = BD_GetUInt64(&bdCtx, bd_entry.tag, index, (bd_uint64_t *)value); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Ram_Size64) && (index == 0)) { + BD_ASSERT( *(bd_uint64_t*)value == 0xB0B1B2B3B4B5B6B7ULL ); + } else if((bd_entry.tag==BD_Flash_Size64) && (index == 0)) { + BD_ASSERT( *(bd_uint64_t*)value == 0x0000000000000000ULL ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_String: { + rc = BD_GetString(&bdCtx, bd_entry.tag, index, (char *)value, bd_entry.len+1); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Prod_Name) && (index == 0)) { + BD_ASSERT( strcmp((char *)value, "Product") == 0 ); + } else if((bd_entry.tag==BD_Prod_Compatibility) && (index == 0)) { + BD_ASSERT( strcmp((char *)value, "Comp") == 0 ); + } else if((bd_entry.tag==BD_Serial) && (index == 0)) { + BD_ASSERT( strcmp((char *)value, "Serial") == 0 ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_Date: { + rc = BD_GetString(&bdCtx, bd_entry.tag, index, (char *)value, bd_entry.len+1); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Production_Date) && (index == 0)) { + BD_ASSERT( strcmp((char *)value, "01.01.2000") == 0 ); + } else { + BD_ASSERT( BD_FALSE ); + } + BD_ASSERT( rc ); + } break; + case BD_Type_MAC: { + rc = BD_GetMAC(&bdCtx, bd_entry.tag, index, (bd_uint8_t *)value); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Eth_Mac) && (index == 0)) { + BD_ASSERT( value[0] == 0x05 ); + BD_ASSERT( value[1] == 0x14 ); + BD_ASSERT( value[2] == 0x23 ); + BD_ASSERT( value[3] == 0x32 ); + BD_ASSERT( value[4] == 0x41 ); + BD_ASSERT( value[5] == 0x50 ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_IPV4: { + rc = BD_GetIPv4(&bdCtx, bd_entry.tag, index, (bd_uint32_t *)value); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Ip_Addr) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == (bd_uint32_t)((192<<24)|(168<<16)|(0<<8)|(2<<0)) ); + } else if((bd_entry.tag==BD_Ip_Netmask) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == (bd_uint32_t)((255<<24)|(255<<16)|(255<<8)|(0<<0)) ); + } else if((bd_entry.tag==BD_Ip_Gateway) && (index == 0)) { + BD_ASSERT( *((bd_uint32_t *)value) == (bd_uint32_t)((192<<24)|(168<<16)|(0<<8)|(1<<0)) ); + } else if((bd_entry.tag==BD_Ip_Addr) && (index == 1)) { + BD_ASSERT( *((bd_uint32_t *)value) == (bd_uint32_t)((172<<24)|(20<<16)|(0<<8)|(2<<0)) ); + } else if((bd_entry.tag==BD_Ip_Netmask) && (index == 1)) { + BD_ASSERT( *((bd_uint32_t *)value) == (bd_uint32_t)((255<<24)|(255<<16)|(0<<8)|(0<<0)) ); + } else if((bd_entry.tag==BD_Ip_Gateway) && (index == 1)) { + BD_ASSERT( *((bd_uint32_t *)value) == (bd_uint32_t)((172<<24)|(20<<16)|(0<<8)|(1<<0)) ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_Partition: { + BD_PartitionEntry *pPartition=(BD_PartitionEntry *)value; + rc = BD_GetPartition(&bdCtx, bd_entry.tag, index, pPartition); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Partition) && (index == 0)) { + BD_ASSERT( pPartition->flags == BD_Partition_Flags_Active ); + BD_ASSERT( pPartition->type == BD_Partition_Type_Raw_BootLoader ); + BD_ASSERT( pPartition->offset == 0x00010203 ); + BD_ASSERT( pPartition->size == 0x04050607 ); + BD_ASSERT( strcmp(pPartition->name, "Part0") == 0 ); + } else if((bd_entry.tag==BD_Partition) && (index == 1)) { + BD_ASSERT( pPartition->flags == BD_Partition_Flags_None ); + BD_ASSERT( pPartition->type == BD_Partition_Type_FS_YAFFS2 ); + BD_ASSERT( pPartition->offset == 0x00112233 ); + BD_ASSERT( pPartition->size == 0x44556677 ); + BD_ASSERT( strcmp(pPartition->name, "Part1") == 0 ); + } else if((bd_entry.tag==BD_Partition) && (index == 2)) { + BD_ASSERT( pPartition->flags == BD_Partition_Flags_Active ); + BD_ASSERT( pPartition->type == BD_Partition_Type_Raw_BBT ); + BD_ASSERT( pPartition->offset == 0xFF00AA55 ); + BD_ASSERT( pPartition->size == 0x00FF55AA ); + BD_ASSERT( strcmp(pPartition->name, "Part2") == 0 ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_Partition64: { + BD_PartitionEntry64 *pPartition64=(BD_PartitionEntry64 *)value; + rc = BD_GetPartition64(&bdCtx, bd_entry.tag, index, pPartition64); + BD_ASSERT( rc ); + if((bd_entry.tag==BD_Partition64) && (index == 0)) { + BD_ASSERT( pPartition64->flags == BD_Partition_Flags_Active ); + BD_ASSERT( pPartition64->type == BD_Partition_Type_FS_YAFFS2 ); + BD_ASSERT( pPartition64->options == BD_Partition_Opts_ReadOnly ); + BD_ASSERT( (pPartition64->offset == 0x0000FFFFFF00AA55ULL) ); + BD_ASSERT( (pPartition64->size == 0x0000FFFF00FF55AAULL) ); + BD_ASSERT( strcmp(pPartition64->name, "Part3") == 0 ); + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + case BD_Type_None: { + rc = BD_GetBlob(&bdCtx, bd_entry.tag, index, (char *)value, bd_entry.len, &len); + BD_ASSERT( rc ); + BD_ASSERT( bd_entry.len == len ); + if((bd_entry.tag==0x8001) && (index == 0)) { + BD_ASSERT( len == 0x40 ); + for(i=0;i<(int)len;i++) { + BD_ASSERT( ((unsigned char)value[i]) == ((unsigned char)i) ); + } + } else { + BD_ASSERT( BD_FALSE ); + } + } break; + default: { + BD_ASSERT( rc ); + } break; + } + if(type != BD_Type_End) { + num++; + } + } + BD_ASSERT( bdCtx.entries == num ); +} + +/*---------------------------------------------------------------------------*/ + +#ifdef BD_CONF_HAS_HASH + +static void bd_testHash( void ) +{ + static bd_uint8_t bdData[] = + { + 0x42, 0x44, 0x56, 0x31, 0x00, 0x20, 0x04, 0xBE, 0x00, 0x1F, 0x00, 0x06, 0x00, 0x12, 0x63, 0x1E, + 0x22, 0x3D, 0x00, 0x08, 0x00, 0x06, 0x00, 0x11, 0x2B, 0x00, 0xAB, 0xCD, 0x00, 0x09, 0x00, 0x04, + 0xAC, 0x1F, 0x0E, 0xFF, 0x00, 0x00, 0x00, 0x00 + }; + const char key[] = "12345"; + const char keyFail[] = "joshua"; + BD_Context bdCtx; + bd_bool_t rc; + + + /* Initialize */ + rc = BD_CheckHeader( &bdCtx, bdData ); + BD_ASSERT( rc ); + rc = BD_ImportData( &bdCtx, bdData+8 ); + BD_ASSERT( rc ); + + /* Verify hashed area of board descriptor */ + rc = BD_VerifySha1Hmac( &bdCtx, BD_Hmac_Sha1_4, 0, key, 5); + BD_ASSERT( rc ); + + /* Try with wrong key -> shall fail */ + rc = BD_VerifySha1Hmac( &bdCtx, BD_Hmac_Sha1_4, 0, keyFail, 6); + BD_ASSERT( !rc ); + + /* Now manipulate a byte in the MAC address .. */ + bdData[23]++; + /* .. and test again. This must fail */ + rc = BD_VerifySha1Hmac( &bdCtx, BD_Hmac_Sha1_4, 0, key, 5); + BD_ASSERT( !rc ); +} + +#endif + +/*---------------------------------------------------------------------------*/ + +void BD_UnitTest(void) +{ + bd_testHelpers( ); + bd_testCheckHeader( ); + bd_testImport(); + bd_testChecksum(); + bd_testGetUInt(); + bd_testGetString(); + bd_testGetMAC(); + bd_testGetIPv4(); + bd_testGetPartition(); + bd_testGetEntry(); +#ifdef BD_CONF_HAS_HASH + bd_testHash(); +#endif +} + +#endif /* BD_CONF_UNIT_TESTS */ + +/*--- eof -------------------------------------------------------------------*/ + diff --git a/board/netmodule/common/bdparser.h b/board/netmodule/common/bdparser.h new file mode 100644 index 0000000000..ae445c2369 --- /dev/null +++ b/board/netmodule/common/bdparser.h @@ -0,0 +1,584 @@ +#ifndef _BDPARSER_H +#define _BDPARSER_H +/****************************************************************************** + * (c) COPYRIGHT 2009-2011 by NetModule AG, Switzerland. All rights reserved. + * + * The program(s) may only be used and/or copied with the written permission + * from NetModule AG or in accordance with the terms and conditions stipulated + * in the agreement contract under which the program(s) have been supplied. + * + * PACKAGE : Board descriptor + * + * ABSTRACT: + * This package implements board descriptor manipulation functions. + * + * HISTORY: + * Date Author Description + * 20091106 rb RFE-FB18392: created + * 20100119 rs Minor cleanup, tags defined + * 20100301 rs Tags redefined + * 20100302 sma RFE-FB18392: created (partition) + * 20100322 th Adaptation WinCE and Win32 (assert) + * Added get bd info (type and name for standard entries) + * Adjusted bd tags + * Added scan entries (init and get next) + * Added partition info (flags and types) + * Added uint64 and partition64 + * Changed boolean value true (BD_TRUE to 1) + * 20110104 rs General code cleanup (style guide), added new tags/types + * Added bufLen parameter for BD_GetInfo() + * Fixed wrong sizeof type in GetPartition() + * Changed 64 bit type to "long long" from struct + * Added BD_VerifySha1Hmac() function + * 20200615 rs Added BD_Hw_Type tag + * + *****************************************************************************/ + +/** + * @file + * Board descriptor parser. + * Get() functions are implemented for all supported basis data types: + * - 8/16/32 bits unsigned integers + * - void + * - string + * - IPv4 addresses + * - Ethernet MAC addresses + */ + +/** + +\mainpage + +\section description Description + +This is the generated documentation for the Board Descriptor utilities. + +For more details see the Board Descriptor Design Description. + +**/ + +/*--- component configuration ------------------------------------------------*/ + +/** Select a target or operating system (just one of course) **/ +#undef BD_TARGET_WIN32 +#undef BD_TARGET_WINCE +#define BD_TARGET_UBOOT +#undef BD_TARGET_LINUX +#undef BD_TARGET_VXWORKS + +#undef BD_CONF_UNIT_TESTS /**< define this to include unit test functions */ + +#undef BD_CONF_WANT_ASSERT /**< define this to use assert functions */ + +#undef BD_CONF_HAS_HASH /**< set to include hash check functions in parser */ + + +/** Define external hmac-sha1 function to use */ +#ifdef BD_CONF_HAS_HASH + extern int hmac_sha1(const void* key, unsigned int keylen, const void* data, unsigned int dataLen, void* hash); + + #define BD_SHA1_HASH_FUNC(key, keylen, data, dataLen, hash) \ + hmac_sha1 (key, keylen, data, dataLen, hash) +#endif + +/** Define desired assert function */ +#ifdef BD_CONF_WANT_ASSERT + #ifdef BD_TARGET_WINCE + #define BD_ASSERT(test) ASSERT(test) + #elif defined(BD_TARGET_WIN32) && !defined(_DEBUG) + /* Win32 Release build */ + #include + #include + #define BD_ASSERT(test) { if(!(test)) { printf("BD_ASSERT(%s)\n- file <%s>\n- line <%d>\n", #test, __FILE__, __LINE__ ); exit(1); } } + #elif defined(BD_TARGET_LINUX) + #include + #define BD_ASSERT(test) { if(!(test)) { printk(KERN_NOTICE "BD_ASSERT(%s) %s:%d\n", #test, __FILE__, __LINE__ ); } } + #else + #include + #define BD_ASSERT(test) assert(test) + #endif +#else + /* No assertions wanted */ + #define BD_ASSERT(test) ((void) 0) +#endif /* BD_CONF_WANT_ASSERT */ + + + +/*--- defines ----------------------------------------------------------------*/ + +#define BD_MAX_LENGTH (4096) /**< Maximum length of a board descriptor's payload */ +#define BD_MAX_ENTRY_LEN (512) /**< Maximum length of a tag value */ +#define BD_HEADER_LENGTH (8) /**< Header is 8 bytes long */ +#define BD_MAX_PARTITION_NAME (16) /**< Name of partition is at most 16 chars long*/ + + +/*--- types ------------------------------------------------------------------*/ + +/** + * Board Descriptor Tags + */ +typedef enum _BD_Tags +{ + BD_End = 0, /**< "Void" -> End tag */ + BD_Serial = 1, /**< "String" -> Serial number of the equipment */ + BD_Production_Date = 2, /**< "Date" -> Production date of the board */ + BD_Hw_Ver = 3, /**< "UInt8" -> Hardware version of the equipment (Major HW changes, potentionally SW relevant) */ + BD_Hw_Rel = 4, /**< "UInt8" -> Hardware release of the equipment (Minor HW changes, not SW relevant) */ + BD_Prod_Name = 5, /**< "String" -> Human readable product name */ + BD_Prod_Variant = 6, /**< "UInt16" -> Product variant */ + BD_Prod_Compatibility = 7, /**< "String" -> Product compatibility name */ + + BD_Eth_Mac = 8, /**< "MAC" -> MAC address of the ethernet interface */ + BD_Ip_Addr = 9, /**< "IPV4" -> IP V4 address (0.0.0.0 = DHCP) */ + BD_Ip_Netmask = 10, /**< "IPV4" -> IP V4 address mask */ + BD_Ip_Gateway = 11, /**< "IPV4" -> IP V4 address of the default gateway */ + + BD_Usb_Device_Id = 12, /**< "UInt16" -> USB device ID */ + BD_Usb_Vendor_Id = 13, /**< "UInt16" -> USB vendor ID */ + + BD_Ram_Size = 14, /**< "UInt32" -> Available RAM size in bytes */ + BD_Ram_Size64 = 15, /**< "UInt64" -> Available RAM size in bytes */ + BD_Flash_Size = 16, /**< "UInt32" -> Available flash size in bytes */ + BD_Flash_Size64 = 17, /**< "UInt64" -> Available flash size in bytes */ + BD_Eeeprom_Size = 18, /**< "UInt32" -> Available EEPROM size in bytes */ + BD_Nv_Rram_Size = 19, /**< "UInt32" -> Available EEPROM size in bytes */ + + BD_Cpu_Base_Clk = 20, /**< "UInt32" -> Base clock of the CPU in Hz = external clock input */ + BD_Cpu_Core_Clk = 21, /**< "UInt32" -> Core clock of the CPU in Hz */ + BD_Cpu_Bus_Clk = 22, /**< "UInt32" -> Bus clock of the CPU in Hz */ + BD_Ram_Clk = 23, /**< "UInt32" -> RAM clock in Hz */ + + BD_Partition = 24, /**< "Partition" -> Offset of 1st Uboot partition in the 1st flash device in bytes */ + BD_Partition64 = 25, /**< "Partition64" -> Offset of 1st Uboot partition in the 1st flash device in bytes */ + + BD_Lcd_Type = 26, /**< "UInt16" -> LCD type -> 0 = not present (interpretation can be project specific) */ + BD_Lcd_Backlight = 27, /**< "UInt8" -> LCD backlight setting (0 = off; 100=max) */ + BD_Lcd_Contrast = 28, /**< "UInt8" -> LCD contrast setting (0 = min; 100=max) */ + BD_Touch_Type = 29, /**< "UInt16" -> Touch Screen type --> 0 = not present/defined */ + + BD_Manufacturer_Id = 30, /**< "String" -> Manufacturer id of the produced equipment (i.e. barcode) */ + BD_Hmac_Sha1_4 = 31, /**< "Hash" -> SHA1 HMAC with 4 byte result */ + BD_Fpga_Info = 32, /**< "UInt32" -> FPGA type/location (0xTTPPRRRR TT=FPGA type, PP=Population location, RRRR=Reserved allways 0000) */ + + BD_BOM_Patch = 33, /**< "UInt8" -> Hardware BOM patch of the equipment (BOM changes, same PCB, not SW relevant) */ + BD_Prod_Variant_Name = 34, /**< "String" -> Product variant */ + BD_Hw_Type = 35, /*<< "UInt16" -> Hardware Type, e.g. 24 for HW24, 26 for HW26 */ + + BD_Ui_Adapter_Type = 4096, /**< "UInt16" -> IV OG2 UI adapterboard type (0 = not present) */ + BD_Voltage = 4098, /**< "UInt8" -> Primary Voltage (1=12-60V, 2=40-160V, 3=24-60V, 4=?, 5=12-24V) */ + + BD_Pd_Module0 = 4100, /**< "String" -> */ + BD_Pd_Module1 = 4101, + BD_Pd_Module2 = 4102, + BD_Pd_Module3 = 4103, + BD_Pd_Module4 = 4104, + BD_Pd_Module5 = 4105, + BD_Pd_Phy0 = 4110, /**< "String" -> */ + BD_Pd_Phy1 = 4111, /**< "String" -> */ + BD_Pd_DIO = 4120, /**< "String" -> */ + BD_Pd_Serial = 4121, /**< "String" -> */ + BD_Pd_Sim = 4122, /**< "String" -> */ + BD_Pd_Led = 4123, /**< "String" -> */ + BD_Pd_UsbHost = 4124, /**< "String" -> */ + PD_Dev_Tree = 4125, /**< "String" -> Devicetree file name */ + BD_Patch = 4126, /**< "UInt8" -> Board patch level (after production) */ + BD_Pd_Phy2 = 4127, /**< "String" -> */ + PD_SerDes = 4128, /**< "UInt16" -> SERDES Configuration (e.g. NB1800) */ + PD_Shield = 4129, /**< "UInt16" -> Assembled Shield (0=COM/IO, 1=DualCAN), 2=CAN/GNSS, 3=DualCAN Passive */ + + /* project specific tags */ + BD_BootPart = 32768, /**< "UInt8" */ + + BD_None_Type = 65535, /**< "Void" -> None */ +} +BD_Tags; + +/** + * Board Descriptor Tag Types + */ +typedef enum _BD_Type +{ + BD_Type_End = 0x00000000, + BD_Type_Void = 0x00000001, + BD_Type_UInt8 = 0x00000002, + BD_Type_UInt16 = 0x00000003, + BD_Type_UInt32 = 0x00000004, + BD_Type_UInt64 = 0x00000005, + BD_Type_String = 0x00000010, + BD_Type_Date = 0x00000020, + BD_Type_MAC = 0x00000030, + BD_Type_IPV4 = 0x00000040, + BD_Type_Partition = 0x00000050, + BD_Type_Partition64 = 0x00000051, + BD_Type_HMAC = 0x00000060, + BD_Type_None = 0xFFFFFFFF, +} +BD_Type; + + +typedef unsigned int bd_uint_t; /**< Generic UInt */ +typedef unsigned int bd_size_t; /**< Size type */ + +typedef unsigned char bd_uint8_t; /**< 8 Bit unsigned integer */ +typedef unsigned short bd_uint16_t; /**< 16 Bit unsigned integer */ +typedef unsigned int bd_uint32_t; /**< 32 Bit unsigned integer */ + +#if defined(BD_TARGET_WIN32) || defined (BD_TARGET_WINCE) + typedef unsigned __int64 bd_uint64_t; /**< 64 Bit unsigned integer */ +#else + typedef unsigned long long bd_uint64_t; /**< 64 Bit unsigned integer */ +#endif + +typedef int bd_bool_t; /**< Boolean */ +#define BD_FALSE 0 /**< Boolean FALSE */ +#define BD_TRUE 1 /**< Boolean TRUE */ + +typedef struct _BD_Info +{ + BD_Tags tag; + BD_Type type; + const char* pName; +} +BD_Info; + +typedef struct _BD_Entry +{ + bd_uint16_t tag; /**< Tag of entry */ + bd_size_t len; /**< Length of entry */ + bd_uint_t entry; /**< Number of entry */ + const bd_uint8_t* pData; /**< Pointer to descriptor data of entry */ +} +BD_Entry; + + +/** + * Board Descriptor Context + * + * This structure is passed to all calls of a Board Descriptor function. + * It stores the required context information. + * The entries are solely used by the Board Descriptor functions. + * They must not be accessed by the user. + */ +typedef struct _BD_Context +{ + bd_bool_t headerOk; /**< True if header check passed else false */ + bd_bool_t initialized; /**< True if data imported (and checked) */ + + bd_uint_t size; /**< Size of descriptor data */ + bd_uint_t entries; /**< Number of entries found */ + + bd_uint16_t checksum; /**< Payload checksum contained in the header */ + const bd_uint8_t* pData; /**< Pointer to descriptor data (not header) */ + const bd_uint8_t* pDataEnd; /**< Pointer to end of data */ +} +BD_Context; + + +/* + * Partition Flags + */ +typedef enum _BD_Partition_Flags +{ + BD_Partition_Flags_None = 0x00, /**< No special flags */ + BD_Partition_Flags_Active = 0x80, /**< Partition is active */ +} +BD_Partition_Flags; + +/* + * Partition Type + */ +typedef enum _BD_Partition_Type +{ + BD_Partition_Type_Raw = 0, /**< Unspecified type */ + BD_Partition_Type_Raw_BootLoader = 1, /**< Linear bootloader image */ + BD_Partition_Type_Raw_BBT = 2, /**< Bad Block Table */ + BD_Partition_Type_FS_YAFFS2 = 3, /**< YAFFS2 Partition */ + BD_Partition_Type_FS_JFFS2 = 4, /**< JFFS2 Partition */ + BD_Partition_Type_FS_FAT16 = 5, /**< FAT16 Partition */ + BD_Partition_Type_FS_FAT32 = 6, /**< FAT32 Partition */ + BD_Partition_Type_FS_EXFAT = 7, /**< EXFAT Partition */ + + BD_Partition_Type_Max = 8, /**< For error checks */ +} +BD_Partition_Type; + +/* + * Partition Options (Partition64 element only) + */ +typedef enum _BD_Partition_Options +{ + BD_Partition_Opts_None = 0x00, /***< No special options */ + BD_Partition_Opts_ReadOnly = 0x01, /***< Partition should be mounted read only */ + BD_Partition_Opts_OS = 0x02, /***< Partition contains operating system (OS) */ +} +BD_Partition_Options; + +/** + * Board descriptor type to describe filesystem partitions + * + * The function BD_GetPartition will directly fill such a structure. + */ +typedef struct _BD_PartitionEntry +{ + BD_Partition_Flags flags; + BD_Partition_Type type; + bd_uint32_t offset; + bd_uint32_t size; + char name[BD_MAX_PARTITION_NAME+1]; +} +BD_PartitionEntry; + +/** + * Board descriptor type to describe filesystem partitions + * + * Extended version with 64 bit addresses and options field. + * The function BD_GetPartition64 will directly fill such a structure. + */ +typedef struct _BD_PartitionEntry64 +{ + BD_Partition_Flags flags; + BD_Partition_Type type; + BD_Partition_Options options; + bd_uint64_t offset; + bd_uint64_t size; + char name[BD_MAX_PARTITION_NAME+1]; +} +BD_PartitionEntry64; + + +/*--- function prototypes ----------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks a BD header's validity and updates the BD context. + * + * @param[in,out] pCtx The context of the BD being checked. + * @param[in] pHeader Pointer to the BD header + * @return True if the header is valid and the context was updated. + * False if the header s not valid. + */ +bd_bool_t BD_CheckHeader( BD_Context* pCtx, const void* pHeader ); + +/** + * Imports BD data from a buffer into a BD context. + * + * @param[in,out] pCtx The context into which data is imported. + * @param[in] pData Pointer to the buffer containing the BD entries. + * @return True if BD entries could be succesfuly imported. + * False if there is an error in the buffer data structure. + */ +bd_bool_t BD_ImportData( BD_Context* pCtx, const void* pData ); + +/** + * Checks the existence of a tag in the BD + * + * @param[in,out] pCtx The context in which the tag is searched. + * @param[in] tag Tag being checked. + * @param[in] index Index of the tag (0=first index). + * @return True if the entry exists in the BD else False. + */ +bd_bool_t BD_ExistsEntry( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index ); + +/** + * Get type and name of a tag in the BD info table + * + * @param[in] tag Tag reference. + * @param[out] pType Type of the tag (0 if not used). + * @param[out] pName Name of the tag (0 if not used). + * @param[in] bufLen Length of the pName buffer. + * If required the returned string for pName will be truncated. + * @return True if the tag in the BD info table exists else False. + */ +bd_bool_t BD_GetInfo( bd_uint16_t tag, BD_Type* pType, char* pName, bd_size_t bufLen ); + +/** + * Initialize the entry before use BD_GetNextEntry + * + * @param[out] pEntry BD entry to be initalized. + * @return True if the entry was initialized, fasle otherwise. + */ +bd_bool_t BD_InitEntry( BD_Entry* pEntry); + +/** + * Get type and name of a tag in the BD info table + * + * @param[in] pCtx The context from which the value is read. + * @param[out] pEntry BD entry (use BD_InitEntry, not 0 for first ). + * @return True if the tag in the BD info table exists else False. + */ +bd_bool_t BD_GetNextEntry( const BD_Context* pCtx, BD_Entry* pEntry ); + + +/** + * Gets a void value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult True if the value could be found else False. + * @return False if something went wrong dring the parsing else True. + */ +bd_bool_t BD_GetVoid( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_bool_t* pResult ); + +/** + * Gets an 8 bits unsigned integer value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read value. + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetUInt8( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_uint8_t* pResult ); + +/** + * Gets a 16 bits unsigned integer value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read value. + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetUInt16( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_uint16_t* pResult ); + +/** + * Gets a 32 bits unsigned integer value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read value. + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetUInt32( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_uint32_t* pResult ); + +/** + * Gets a 64 bits unsigned integer value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read value. + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetUInt64( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_uint64_t* pResult ); + +/** + * Gets a string value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read value. + * @param[in] bufLen Length of the pResult buffer. + * @return True if the value in pResult is valid else False. + * + * @note @li The returned string in pResult is null-terminated. + * @li If the buffer is too.small to hold the value the returned string is truncated. + */ +bd_bool_t BD_GetString( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, char* pResult, bd_size_t bufLen ); + +/** + * Gets a binary large object (blob) value from a BD. + * + * @param[in] pCtx The context from which the value is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read value. + * @param[in] bufLen Length of the pResult buffer. + * @param[out] pReadLen The actual number of bytes read. + * @return True if the complete tag value could be read in pResult else False. + */ +bd_bool_t BD_GetBlob( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, + char* pResult, bd_size_t bufLen, bd_size_t* pReadLen ); + +/** + * Gets an IPv4 address from a BD. + * + * The IP address is returned as a 32 bits unsigned integer with the most + * significant byte first. E.g. 192.168.2.1 is stored as 0xC0A80201 + * + * @param[in] pCtx The context from which the IP address is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read IP address. + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetIPv4( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_uint32_t* pResult ); + +/** + * Gets an Ethernet MAC address from a BD. + * + * @param[in] pCtx The context from which the MAC address is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the read MAC address. + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetMAC( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, bd_uint8_t pResult[6] ); + +/** + * Gets a partition entry from a BD. + * + * @param[in,out] pCtx The context from which the MAC address is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the partition entry + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetPartition( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, BD_PartitionEntry* pResult ); + +/** + * Gets a partition64 entry from a BD. + * + * @param[in,out] pCtx The context from which the MAC address is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[out] pResult Placeholder for the partition entry + * @return True if the value in pResult is valid else False. + */ +bd_bool_t BD_GetPartition64( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, BD_PartitionEntry64* pResult ); + + +#ifdef BD_CONF_HAS_HASH + +/** + * Verifies the SHA1-HMAC checksum. + * + * The checksum is computed with the specified key over the area defined + * by the hash tag. The key must match the one used to generate the descriptor. + * + * @param[in] pCtx The context from which the MAC address is read. + * @param[in] tag Tag Id. + * @param[in] index Index of the tag (0=first occurance). + * @param[in] pKey Pointer to key for HMAC initialization. + * @param[in] keyLen Size of the key. + * @return True if the protected data is unmodified. False in any other case. + */ +bd_bool_t BD_VerifySha1Hmac( const BD_Context* pCtx, bd_uint16_t tag, bd_uint_t index, const void* pKey, bd_size_t keyLen ); + +#endif + + +#ifdef BD_CONF_UNIT_TESTS + +/** + * Runs unit tests + * + * If an error occurs an assert is triggered + */ +void BD_UnitTest(void); + +#endif /* BD_CONF_UNIT_TESTS */ + + +#ifdef __cplusplus +} /*end extern c*/ +#endif + +#endif /* _BDPARSER_H */ + diff --git a/board/netmodule/common/board_descriptor.c b/board/netmodule/common/board_descriptor.c new file mode 100644 index 0000000000..cddade171e --- /dev/null +++ b/board/netmodule/common/board_descriptor.c @@ -0,0 +1,358 @@ +/****************************************************************************** + * (c) COPYRIGHT 2010-2019 by NetModule AG, Switzerland. + * + * The program(s) may only be used and/or copied with the written permission + * from NetModule AG or in accordance with the terms and conditions stipulated + * in the agreement contract under which the program(s) have been supplied. + * + * PACKAGE : NetModule Common Hardware Abstraction + * + * ABSTRACT: + * Board descriptor library + * + * HISTORY: + * Date Author Description + * 20100421 SMA created + * 20100903 rs reading carrier board descriptor from EEPROM at 54. + * code cleanup (tabs/indentation) + * 20110211 rs partition table handling + * 20190330 rs cleanup after years of chaotic development + * 20200615 rs added bd_get_hw_type() + * + *****************************************************************************/ +#include +#include +#include + +#include "board_descriptor.h" /* own header file */ + + +#define MAX_PARTITION_ENTRIES 4 + + +static const BD_Context *bdctx_list; +static size_t bdctx_count = 0; + + +static bd_bool_t _get_string(bd_uint16_t tag, bd_uint_t index, char* pResult, bd_size_t bufLen) +{ + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetString(&bdctx_list[i], tag, index, pResult, bufLen)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + +static bd_bool_t _get_mac(bd_uint16_t tag, bd_uint_t index, bd_uint8_t pResult[6]) +{ + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetMAC(&bdctx_list[i], tag, index, pResult)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + +static bd_bool_t _get_uint8(bd_uint16_t tag, bd_uint_t index, bd_uint8_t* pResult) +{ + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetUInt8(&bdctx_list[i], tag, index, pResult)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + +static bd_bool_t _get_uint16(bd_uint16_t tag, bd_uint_t index, bd_uint16_t* pResult) +{ + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetUInt16(&bdctx_list[i], tag, index, pResult)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + +static bd_bool_t _get_uint32(bd_uint16_t tag, bd_uint_t index, bd_uint32_t* pResult) +{ + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetUInt32(&bdctx_list[i], tag, index, pResult)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + +static bd_bool_t _get_partition64(bd_uint16_t tag, bd_uint_t index, BD_PartitionEntry64 *pResult) +{ + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetPartition64(&bdctx_list[i], tag, index, pResult)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + +static uint8_t _try_partition_read(void) +{ + BD_PartitionEntry64 partition; + int i; + int rc; + int partition_count = 0; + int boot_partition = 0; + + for (i = 0; i < MAX_PARTITION_ENTRIES; i++) + { + rc = _get_partition64(BD_Partition64, i, &partition); + if (rc) { + partition_count++; + if (((partition.flags & BD_Partition_Flags_Active) != 0) && + (i > 0)) { + boot_partition = i; + } + } + } + + if (partition_count < 1) { + printf("ERROR: Too few partitions defined, taking default 0\n"); + } + + return boot_partition; +} + + +void bd_register_context_list(const BD_Context *list, size_t count) +{ + bdctx_list = list; + bdctx_count = count; +} + +int bd_get_context(BD_Context *bdctx, uint32_t i2caddress, uint32_t offset) +{ + bd_bool_t rc; + uint8_t bdHeader[8]; + void* pBdData = NULL; + + /* Read header bytes from beginning of EEPROM */ + if (i2c_read( i2caddress, offset, 2, bdHeader, BD_HEADER_LENGTH )) { + debug("%s() Can't read BD header from EEPROM\n", __func__); + goto exit1; + } + + /* Check whether this is a valid board descriptor (or empty EEPROM) */ + rc = BD_CheckHeader( bdctx, bdHeader ); + if (!rc) { + debug("%s() No valid board descriptor found\n", __func__); + goto exit1; + } + + /* Allocate memory for descriptor data and .. */ + pBdData = malloc( bdctx->size ); + if ( pBdData == NULL ) { + debug("%s() Can't allocate %d bytes\n", __func__, bdctx->size); + goto exit1; + } + + /* .. read data from EEPROM */ + if (i2c_read(i2caddress, offset+BD_HEADER_LENGTH, 2, pBdData, bdctx->size)) { + debug("%s() Can't read data from EEPROM\n", __func__); + goto exit1; + } + + /* + * Import data into board descriptor context + */ + rc = BD_ImportData( bdctx, pBdData ); + if (!rc) { + debug("%s() Invalid board descriptor data\n", __func__); + goto exit1; + } + + return 0; + +exit1: + if (pBdData != NULL) { + free(pBdData); + pBdData = NULL; + } + + return -1; +} + +int bd_get_prodname(char *prodname, size_t len) +{ + if ( !_get_string( BD_Prod_Name, 0, prodname, len) ) { + debug("%s() Product name not found\n", __func__); + return -1; + } + + return 0; +} + +int bd_get_variantname(char *variantname, size_t len) +{ + if ( !_get_string( BD_Prod_Variant_Name, 0, variantname, len) ) { + debug("%s() Variant name not found\n", __func__); + return -1; + } + + return 0; +} + +void bd_get_hw_type(int* type) +{ + uint16_t hwtype = 0; + + if ( !_get_uint16( BD_Hw_Type, 0, &hwtype) ) + debug("%s() no Hw Type found\n", __func__); + + *type = hwtype; +} + +void bd_get_hw_version(int* ver, int* rev) +{ + uint8_t hwver = 0; + uint8_t hwrev = 0; + + if ( !_get_uint8( BD_Hw_Ver, 0, &hwver) ) + debug("%s() no Hw Version found\n", __func__); + + if ( !_get_uint8( BD_Hw_Rel, 0, &hwrev) ) + debug("%s() no Hw Release found\n", __func__); + + *ver = hwver; + *rev = hwrev; +} + +void bd_get_hw_patch(int* patch) +{ + uint8_t hwpatch = 0; + + if ( !_get_uint8( BD_BOM_Patch, 0, &hwpatch) ) + debug("%s() no Hw Patch found\n", __func__); + + *patch = hwpatch; +} + +int bd_get_mac(int index, uint8_t *macaddr, size_t len) +{ + if ( len != 6 ) { + debug("macaddr size must be 6 (is %d)", len); + return -1; + } + + /* MAC address */ + if ( !_get_mac( BD_Eth_Mac, index, macaddr) ) { + debug("%s() MAC addresss %d not found\n", __func__, index); + return -1; + } + + return 0; +} + +uint32_t bd_get_fpgainfo(void) +{ + uint32_t fpgainfo = 0xFFFFFFFF; + + if ( !_get_uint32( BD_Fpga_Info, 0, &fpgainfo) ) + debug("%s() no FGPA Info found\n", __func__); + + return fpgainfo; +} + +int bd_get_pd_dio(char *config, size_t len) +{ + if ( !_get_string(BD_Pd_DIO, 0, config, len) ) { + debug("%s() no DIO info\n", __func__); + return -1; + } + + return 0; +} + +int bd_get_pd_serial(char *config, size_t len) +{ + if ( !_get_string(BD_Pd_Serial, 0, config, len) ) { + debug("%s() no serial port info\n", __func__); + return -1; + } + + return 0; +} + +int bd_get_pd_module(uint32_t slot, char *config, size_t len) +{ + if ( !_get_string(BD_Pd_Module0 + slot, 0, config, len) ) { + debug("%s() could not read module configuration on slot %d\n", + __func__, slot); + return -1; + } + + return 0; +} + +int bd_get_sim_config(char* simconfig, size_t len) +{ + if (!_get_string(BD_Pd_Sim, 0, simconfig, len)) { + debug("%s() no valid SIM config found\n", __func__); + return -1; + } + + return 0; +} + +int bd_get_devicetree(char* devicetreename, size_t len) +{ + if (!_get_string(PD_Dev_Tree, 0, devicetreename, len)) { + debug("%s() no valid devicetree name found\n", __func__); + return -1; + } + + return 0; +} + +int bd_get_shield(uint32_t shieldnr) +{ + bd_uint16_t shield = 0; + + if (!_get_uint16(PD_Shield, shieldnr, &shield) ) { + debug("%s() no shield populated\n", __func__); + return -1; + } + + return shield; +} + +uint8_t bd_get_boot_partition(void) +{ + uint8_t boot_part; + + /* If we have a Bootpartition entry take this as boot part */ + if (_get_uint8( BD_BootPart, 0, &boot_part) ) { + if (boot_part >= 0 && boot_part <= 1) { + return boot_part; + } + } + + /* If we don't have a Bootpartition entry, perhaps we have a partition table */ + return _try_partition_read(); +} diff --git a/board/netmodule/common/board_descriptor.h b/board/netmodule/common/board_descriptor.h new file mode 100644 index 0000000000..89448e229e --- /dev/null +++ b/board/netmodule/common/board_descriptor.h @@ -0,0 +1,33 @@ +/* + * Board descriptor library + * + * (c) COPYRIGHT 2010-2019 by NetModule AG, Switzerland. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __BOARD_DESCRIPTOR_H +#define __BOARD_DESCRIPTOR_H + +#include "bdparser.h" /* BD_Context */ + + +void bd_register_context_list(const BD_Context *list, size_t count); +int bd_get_context(BD_Context *bdctx, uint32_t i2caddress, uint32_t offset); + +int bd_get_prodname(char *prodname, size_t len); +int bd_get_variantname(char *variantname, size_t len); +void bd_get_hw_type(int* type); +void bd_get_hw_version(int* ver, int* rev); +void bd_get_hw_patch(int* patch); +int bd_get_mac(int index, uint8_t *macaddr, size_t len); +uint32_t bd_get_fpgainfo(void); +int bd_get_pd_dio(char *config, size_t len); +int bd_get_pd_serial(char *config, size_t len); +int bd_get_pd_module(uint32_t slot, char *config, size_t len); +int bd_get_sim_config(char* simconfig, size_t len); +int bd_get_devicetree(char* devicetreename, size_t len); +int bd_get_shield(uint32_t shieldnr); +uint8_t bd_get_boot_partition(void); + +#endif /* __BOARD_DESCRIPTOR_H */ diff --git a/board/netmodule/imx8_nmhw23/imx8_nmhw23.c b/board/netmodule/imx8_nmhw23/imx8_nmhw23.c index 57fb0abc1d..1d687e4b1d 100644 --- a/board/netmodule/imx8_nmhw23/imx8_nmhw23.c +++ b/board/netmodule/imx8_nmhw23/imx8_nmhw23.c @@ -15,6 +15,7 @@ #include #include #include +#include "../common/board_descriptor.h" DECLARE_GLOBAL_DATA_PTR; @@ -90,6 +91,26 @@ int board_phy_config(struct phy_device *phydev) } #endif +static void set_mac_address(int index, uchar mac[6]) +{ + /* Then take mac from bd */ + if (is_valid_ethaddr(mac)) { + eth_env_set_enetaddr_by_index("eth", index, mac); + } + else { + printf("Trying to set invalid MAC address"); + } +} + +int board_eth_init(bd_t *bis) +{ + uint8_t mac_addr0[6] = {02,00,00,00,00,01}; + + bd_get_mac(0, mac_addr0, sizeof(mac_addr0)); + set_mac_address(0, mac_addr0); + + return 0; +} void build_info(void) { u32 sc_build = 0, sc_commit = 0;