From 5590a82b6d8bfe192c2b9b8f14cd4139f633e97a Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 14 Dec 2016 15:02:53 +0100 Subject: [PATCH] netbird: add netbird version 2 Add the netbird version 2 configuration, this is the prototype release of the final NB800 product. --- arch/arm/Kconfig | 9 + board/nm/netbird_v2/Kconfig | 26 + board/nm/netbird_v2/Makefile | 13 + board/nm/netbird_v2/bdparser.c | 2106 ++++++++++++++++++++++++ board/nm/netbird_v2/bdparser.h | 558 +++++++ board/nm/netbird_v2/board.c | 515 ++++++ board/nm/netbird_v2/board.h | 27 + board/nm/netbird_v2/board_descriptor.c | 240 +++ board/nm/netbird_v2/board_descriptor.h | 17 + board/nm/netbird_v2/mux.c | 217 +++ board/nm/netbird_v2/u-boot.lds | 158 ++ configs/am335x_netbird_v2_defconfig | 44 + include/configs/am335x_netbird_v2.h | 217 +++ 13 files changed, 4147 insertions(+) create mode 100644 board/nm/netbird_v2/Kconfig create mode 100644 board/nm/netbird_v2/Makefile create mode 100644 board/nm/netbird_v2/bdparser.c create mode 100644 board/nm/netbird_v2/bdparser.h create mode 100644 board/nm/netbird_v2/board.c create mode 100644 board/nm/netbird_v2/board.h create mode 100644 board/nm/netbird_v2/board_descriptor.c create mode 100644 board/nm/netbird_v2/board_descriptor.h create mode 100644 board/nm/netbird_v2/mux.c create mode 100644 board/nm/netbird_v2/u-boot.lds create mode 100644 configs/am335x_netbird_v2_defconfig create mode 100644 include/configs/am335x_netbird_v2.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7c0e8d4276..c865dfab99 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -382,6 +382,14 @@ config TARGET_AM335X_NETBIRD select DM_SERIAL select DM_GPIO +config TARGET_AM335X_NETBIRD_V2 + bool "Support am335x_netbird_v2" + select CPU_V7 + select SUPPORT_SPL + select DM + select DM_SERIAL + select DM_GPIO + config TARGET_AM335X_SL50 bool "Support am335x_sl50" select CPU_V7 @@ -879,6 +887,7 @@ source "board/imx31_phycore/Kconfig" source "board/isee/igep0033/Kconfig" source "board/mpl/vcma9/Kconfig" source "board/nm/netbird/Kconfig" +source "board/nm/netbird_v2/Kconfig" source "board/olimex/mx23_olinuxino/Kconfig" source "board/phytec/pcm051/Kconfig" source "board/phytec/pcm052/Kconfig" diff --git a/board/nm/netbird_v2/Kconfig b/board/nm/netbird_v2/Kconfig new file mode 100644 index 0000000000..4196a42dda --- /dev/null +++ b/board/nm/netbird_v2/Kconfig @@ -0,0 +1,26 @@ +if TARGET_AM335X_NETBIRD_V2 + +config SYS_BOARD + default "netbird_v2" + +config SYS_VENDOR + default "nm" + +config SYS_SOC + default "am33xx" + +config SYS_CONFIG_NAME + default "am335x_netbird_v2" + +config CONS_INDEX + int "UART used for console" + range 1 6 + default 2 + help + The AM335x SoC has a total of 6 UARTs (UART0 to UART5 as referenced + in documentation, etc) available to it. Depending on your specific + board you may want something other than UART0 as for example the IDK + uses UART3 so enter 4 here. + +endif + diff --git a/board/nm/netbird_v2/Makefile b/board/nm/netbird_v2/Makefile new file mode 100644 index 0000000000..1aad33e609 --- /dev/null +++ b/board/nm/netbird_v2/Makefile @@ -0,0 +1,13 @@ +# +# Makefile +# +# Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),) +obj-y := mux.o +endif + +obj-y += board.o bdparser.o board_descriptor.o diff --git a/board/nm/netbird_v2/bdparser.c b/board/nm/netbird_v2/bdparser.c new file mode 100644 index 0000000000..36d4094f41 --- /dev/null +++ b/board/nm/netbird_v2/bdparser.c @@ -0,0 +1,2106 @@ +/****************************************************************************** + * (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" }, + + /* 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; + } + writel(1<<14, 0x4804c13c); /* set gpio out */ + if ( (pResult == 0) + || !pCtx->initialized + || (index >= pCtx->entries) + ) + { +mdelay(1000); +writel(1<<14, 0x4804c190); /* set gpio out */ + return BD_FALSE; + } + +mdelay(1000); +writel(1<<14, 0x4804c190); /* set gpio out */ + /* 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/nm/netbird_v2/bdparser.h b/board/nm/netbird_v2/bdparser.h new file mode 100644 index 0000000000..f1d469c366 --- /dev/null +++ b/board/nm/netbird_v2/bdparser.h @@ -0,0 +1,558 @@ +#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 + *****************************************************************************/ + +/** + * @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_Ui_Adapter_Type = 4096, /**< "UInt16" -> IV OG2 UI adapterboard type (0 = not present) */ + + /* 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/nm/netbird_v2/board.c b/board/nm/netbird_v2/board.c new file mode 100644 index 0000000000..694c241a9c --- /dev/null +++ b/board/nm/netbird_v2/board.c @@ -0,0 +1,515 @@ +/* + * board.c + * + * Board functions for TI AM335X based boards + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "board_descriptor.h" +#include "board.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* GPIO that controls power to DDR on EVM-SK */ +#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) +#define GPIO_DDR_VTT_EN GPIO_TO_PIN(0, 7) +#define ICE_GPIO_DDR_VTT_EN GPIO_TO_PIN(0, 18) +#define GPIO_PR1_MII_CTRL GPIO_TO_PIN(3, 4) +#define GPIO_MUX_MII_CTRL GPIO_TO_PIN(3, 10) +#define GPIO_FET_SWITCH_CTRL GPIO_TO_PIN(0, 7) +#define GPIO_PHY_RESET GPIO_TO_PIN(2, 5) + +#define NETBIRD_GPIO_RST_PHY_N GPIO_TO_PIN(0, 16) +#define NETBIRD_GPIO_PWR_GSM GPIO_TO_PIN(1, 22) +#define NETBIRD_GPIO_SUPPLY_GSM GPIO_TO_PIN(0, 31) +#define NETBIRD_GPIO_RST_GSM GPIO_TO_PIN(1, 25) +#define NETBIRD_GPIO_WLAN_EN GPIO_TO_PIN(3, 10) +#define NETBIRD_GPIO_BT_EN GPIO_TO_PIN(3, 4) +#define NETBIRD_GPIO_EN_GPS_ANT GPIO_TO_PIN(2, 24) +#define NETBIRD_GPIO_LED_A GPIO_TO_PIN(1, 14) +#define NETBIRD_GPIO_LED_B GPIO_TO_PIN(1, 15) +#define NETBIRD_GPIO_RESET_BUTTON GPIO_TO_PIN(1, 13) + +#define DDR3_CLOCK_FREQUENCY (400) + +#if defined(CONFIG_SPL_BUILD) || \ + (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_DM_ETH)) +static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; +#endif + +/* + * Read header information from EEPROM into global structure. + */ +static inline int __maybe_unused read_eeprom(void) +{ + return bd_read(-1, CONFIG_SYS_I2C_EEPROM_ADDR); +} + +struct serial_device *default_serial_console(void) +{ + return &eserial1_device; +} + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + +static const struct ddr_data ddr3_netbird_data = { + /* Ratios were optimized by DDR3 training software from TI */ + .datardsratio0 = 0x37, + .datawdsratio0 = 0x42, + .datafwsratio0 = 0x98, + .datawrsratio0 = 0x7a, +}; + +static const struct cmd_control ddr3_netbird_cmd_ctrl_data = { + .cmd0csratio = MT41K256M16HA125E_RATIO, + .cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT, + + .cmd1csratio = MT41K256M16HA125E_RATIO, + .cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT, + + .cmd2csratio = MT41K256M16HA125E_RATIO, + .cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_netbird_emif_reg_data = { + .sdram_config = MT41K256M16HA125E_EMIF_SDCFG, + .ref_ctrl = 0x61A, /* 32ms > 85°C */ + .sdram_tim1 = 0x0AAAE51B, + .sdram_tim2 = 0x246B7FDA, + .sdram_tim3 = 0x50FFE67F, + .zq_config = MT41K256M16HA125E_ZQ_CFG, + .emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY, +}; + + +#ifdef CONFIG_SPL_OS_BOOT +int spl_start_uboot(void) +{ + /* break into full u-boot on 'c' */ + if (serial_tstc() && serial_getc() == 'c') + return 1; + +#ifdef CONFIG_SPL_ENV_SUPPORT + env_init(); + env_relocate_spec(); + if (getenv_yesno("boot_os") != 1) + return 1; +#endif + + return 0; +} +#endif + +#define OSC (V_OSCK/1000000) +struct dpll_params dpll_ddr_nbhw16= { + DDR3_CLOCK_FREQUENCY, OSC-1, 1, -1, -1, -1, -1}; + +void am33xx_spl_board_init(void) +{ + /* Get the frequency */ + dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev); + + /* Set CPU speed to 600 MHZ */ + dpll_mpu_opp100.m = MPUPLL_M_600; + + /* Set CORE Frequencies to OPP100 */ + do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); + + /* Clear th PFM Flag on DCDC4 */ + if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_DCDC4, 0x00, 0x80)) { + puts ("tps65218_reg_write failure (DCDC4 clear PFM Flag)\n"); + }; + + /* Disable DCDC2 because it is not used and could make noise */ + if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_ENABLE1, 0, 0x02)) { + puts ("tps65218_reg_write failure (DCDC2 disable)\n"); + }; + + + /* Set MPU Frequency to what we detected now that voltages are set */ + do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); + + if (read_eeprom() < 0) + puts("Could not get board ID.\n"); +} + +const struct dpll_params *get_dpll_ddr_params(void) +{ + dpll_ddr_nbhw16.n = (get_osclk() / 1000000) - 1; + return &dpll_ddr_nbhw16; +} + +void set_uart_mux_conf(void) +{ + enable_uart0_pin_mux(); + enable_uart1_pin_mux(); +} + +void set_mux_conf_regs(void) +{ + enable_board_pin_mux(); +} + + +const struct ctrl_ioregs ioregs_netbird = { + .cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, +}; + + +void sdram_init(void) +{ + config_ddr(DDR3_CLOCK_FREQUENCY, &ioregs_netbird, + &ddr3_netbird_data, + &ddr3_netbird_cmd_ctrl_data, + &ddr3_netbird_emif_reg_data, 0); +} + +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +static void request_and_set_gpio(int gpio, char *name, int value) +{ + int ret; + + ret = gpio_request(gpio, name); + if (ret < 0) { + printf("%s: Unable to request %s\n", __func__, name); + return; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + printf("%s: Unable to set %s as output\n", __func__, name); + goto err_free_gpio; + } + + gpio_set_value(gpio, value); + + return; + +err_free_gpio: + gpio_free(gpio); +} + +#define REQUEST_AND_SET_GPIO(N) request_and_set_gpio(N, #N, 1); +#define REQUEST_AND_CLEAR_GPIO(N) request_and_set_gpio(N, #N, 0); + + +int check_reset_button(void) +{ + int counter = 0; + int ret; + + ret = gpio_request(NETBIRD_GPIO_RESET_BUTTON, "reset button"); + if (ret < 0) { + printf("Unable to request reset button gpio\n"); + return -1; + } + + ret = gpio_direction_input(NETBIRD_GPIO_RESET_BUTTON); + if (ret < 0) { + printf("Unable to set reset button as input\n"); + return -1; + } + + /* Check if reset button is pressed for at least 3 seconds */ + do { + if (gpio_get_value(NETBIRD_GPIO_RESET_BUTTON) != 0) break; + udelay(100000); /* 100ms */ + counter++; + + if (counter==30) {/* Indicate factory reset threshold */ + /* let LED blink up once */ + gpio_set_value(NETBIRD_GPIO_LED_B, 1); + udelay(400000); /* 400ms */ + gpio_set_value(NETBIRD_GPIO_LED_B, 0); + } else if (counter==150) { /* Indicate recovery boot threshold */ + /* let LED blink up twice */ + gpio_set_value(NETBIRD_GPIO_LED_B, 1); + udelay(400000); /* 400ms */ + gpio_set_value(NETBIRD_GPIO_LED_B, 0); + udelay(400000); /* 400ms */ + gpio_set_value(NETBIRD_GPIO_LED_B, 1); + udelay(400000); /* 400ms */ + gpio_set_value(NETBIRD_GPIO_LED_B, 0); + } + } while (counter<150); + + if (counter < 30) return 0; /* Don't do anything for duration < 3s */ + + if (counter < 150) /* Do factory reset for duration between 3s and 15s */ + { + char new_bootargs[512]; + char *bootargs = getenv("bootargs"); + + if (bootargs==0) bootargs=""; + + printf("Do factory reset during boot...\n"); + + strncpy(new_bootargs, bootargs, sizeof(new_bootargs)); + strncat(new_bootargs, " factory-reset", sizeof(new_bootargs)); + + setenv("bootargs", new_bootargs); + + printf("bootargs = %s\n", new_bootargs); + + return 1; + } else { /* Boot into recovery for duration > 15s */ + + /* set consoledev to external port */ + setenv("consoledev", "ttyO0"); + + printf("Booting recovery image...\n"); + + /* Set bootcmd to run recovery */ + setenv("bootcmd", "run recovery"); + + return 0; + } + return 0; +} + +/* + * Basic board specific setup. Pinmux has been handled already. + */ +int board_init(void) +{ +#if defined(CONFIG_HW_WATCHDOG) + hw_watchdog_init(); +#endif + + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; +#if defined(CONFIG_NOR) || defined(CONFIG_NAND) + gpmc_init(); +#endif + + /* Power on the supply of the gsm modem */ + REQUEST_AND_SET_GPIO(NETBIRD_GPIO_SUPPLY_GSM); + mdelay(100); + /* Take modem out of reset */ + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_RST_GSM); + udelay(10000); + /* Do power up sequence, this modem has a special power up sequence + * where we have to pull PWR for > 1s but < 7s (see manual) */ + REQUEST_AND_SET_GPIO(NETBIRD_GPIO_PWR_GSM); + mdelay(1200); + gpio_set_value(NETBIRD_GPIO_PWR_GSM, 0); + /* Enable debug LED to troubleshoot hw problems */ + REQUEST_AND_SET_GPIO(NETBIRD_GPIO_LED_A); + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_LED_B); + REQUEST_AND_SET_GPIO(NETBIRD_GPIO_RST_PHY_N); + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_WLAN_EN); + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_BT_EN); + /* There are two funcions on the same mux mode for MMC2_DAT7 we want + * to use RMII2_CRS_DV so we need to set SMA2 Register to 1 + * See SPRS717J site 49 (10)*/ + #define SMA2_REGISTER (CTRL_BASE + 0x1320) + writel(0x01, SMA2_REGISTER); /* Select RMII2_CRS_DV instead of MMC2_DAT7 */ + + printf("OSC: %lu Hz\n", get_osclk()); + + return 0; +} + +#ifdef CONFIG_BOARD_LATE_INIT +int board_late_init(void) +{ +#if !defined(CONFIG_SPL_BUILD) + int hw_ver, hw_rev; + int boot_partition; + + if (read_eeprom() < 0) + puts("Could not get board ID.\n"); + + /* add active root partition to environment */ + boot_partition = bd_get_boot_partition(); + if (boot_partition > 1) { + boot_partition = 0; + } + + /* mmcblk0p1 => root0, mmcblk0p2 => root1 so +1 */ + setenv_ulong("root_part", boot_partition + 1); + + /* add hardware versions to environment */ + if (bd_get_hw_version(&hw_ver, &hw_rev)==0) { + char hw_versions[128]; + char new_env[256]; + snprintf(hw_versions, sizeof(hw_versions), "CP=%d.%d", hw_ver, hw_rev); + snprintf(new_env, sizeof(new_env), "setenv bootargs $bootargs %s", hw_versions); + setenv("add_version_bootargs", new_env); + } + + check_reset_button(); + +#endif + +#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG + int rc; + char *name = NULL; + + set_board_info_env(name); +#endif + + return 0; +} +#endif + +#ifndef CONFIG_DM_ETH + +#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ + (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) +static void cpsw_control(int enabled) +{ + /* VTP can be added here */ + + return; +} + +static struct cpsw_slave_data cpsw_slaves[] = { + { + .slave_reg_ofs = 0x208, + .sliver_reg_ofs = 0xd80, + .phy_addr = 0, + }, + { + .slave_reg_ofs = 0x308, + .sliver_reg_ofs = 0xdc0, + .phy_addr = 1, + }, +}; + +static struct cpsw_platform_data cpsw_data = { + .mdio_base = CPSW_MDIO_BASE, + .cpsw_base = CPSW_BASE, + .mdio_div = 0xff, + .channels = 8, + .cpdma_reg_ofs = 0x800, + .slaves = 1, + .slave_data = cpsw_slaves, + .ale_reg_ofs = 0xd00, + .ale_entries = 1024, + .host_port_reg_ofs = 0x108, + .hw_stats_reg_ofs = 0x900, + .bd_ram_ofs = 0x2000, + .mac_control = (1 << 5), + .control = cpsw_control, + .host_port_num = 0, + .version = CPSW_CTRL_VERSION_2, +}; +#endif + +#if ((defined(CONFIG_SPL_ETH_SUPPORT) || defined(CONFIG_SPL_USBETH_SUPPORT)) &&\ + defined(CONFIG_SPL_BUILD)) || \ + ((defined(CONFIG_DRIVER_TI_CPSW) || \ + defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)) && \ + !defined(CONFIG_SPL_BUILD)) + +static void set_mac_address(int index, uchar mac[6]) +{ + /* Then take mac from bd */ + if (is_valid_ethaddr(mac)) { + eth_setenv_enetaddr_by_index("eth", index, mac); + } + else { + printf("Trying to set invalid MAC address"); + } +} + +/* + * This function will: + * Read the eFuse for MAC addresses, and set ethaddr/eth1addr/usbnet_devaddr + * in the environment + * Perform fixups to the PHY present on certain boards. We only need this + * function in: + * - SPL with either CPSW or USB ethernet support + * - Full U-Boot, with either CPSW or USB ethernet + * Build in only these cases to avoid warnings about unused variables + * when we build an SPL that has neither option but full U-Boot will. + */ +int board_eth_init(bd_t *bis) +{ + int rv, n = 0; + uint8_t mac_addr0[6] = {02,00,00,00,00,01}; + uint8_t mac_addr1[6] = {02,00,00,00,00,02}; + __maybe_unused struct ti_am_eeprom *header; + +#if !defined(CONFIG_SPL_BUILD) +#ifdef CONFIG_DRIVER_TI_CPSW + + cpsw_data.mdio_div = 0x3E; + + bd_get_mac_address(0, mac_addr0, sizeof(mac_addr0)); + set_mac_address(0, mac_addr0); + + bd_get_mac_address(1, mac_addr1, sizeof(mac_addr1)); + set_mac_address(1, mac_addr1); + + writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE, &cdev->miisel); + cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RMII; + cpsw_slaves[1].phy_if = PHY_INTERFACE_MODE_RMII; + cpsw_slaves[0].phy_addr = 0; + cpsw_slaves[1].phy_addr = 1; + + rv = cpsw_register(&cpsw_data); + if (rv < 0) + printf("Error %d registering CPSW switch\n", rv); + else + n += rv; +#endif + +#endif +#if defined(CONFIG_USB_ETHER) && \ + (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT)) + if (is_valid_ethaddr(mac_addr0)) + eth_setenv_enetaddr("usbnet_devaddr", mac_addr0); + + rv = usb_eth_initialize(bis); + if (rv < 0) + printf("Error %d registering USB_ETHER\n", rv); + else + n += rv; +#endif + return n; +} +#endif + +#endif /* CONFIG_DM_ETH */ + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + return 0; +} +#endif diff --git a/board/nm/netbird_v2/board.h b/board/nm/netbird_v2/board.h new file mode 100644 index 0000000000..8083c7d0d2 --- /dev/null +++ b/board/nm/netbird_v2/board.h @@ -0,0 +1,27 @@ +/* + * board.h + * + * TI AM335x boards information header + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ +/* + * We have three pin mux functions that must exist. We must be able to enable + * uart0, for initial output and i2c0 to read the main EEPROM. We then have a + * main pinmux function that can be overridden to enable all other pinmux that + * is required on the board. + */ +void enable_uart0_pin_mux(void); +void enable_uart1_pin_mux(void); +void enable_uart2_pin_mux(void); +void enable_uart3_pin_mux(void); +void enable_uart4_pin_mux(void); +void enable_uart5_pin_mux(void); +void enable_i2c0_pin_mux(void); +void enable_board_pin_mux(void); +#endif diff --git a/board/nm/netbird_v2/board_descriptor.c b/board/nm/netbird_v2/board_descriptor.c new file mode 100644 index 0000000000..ee05c0c8c8 --- /dev/null +++ b/board/nm/netbird_v2/board_descriptor.c @@ -0,0 +1,240 @@ +/* + * Library to support early TI EVM EEPROM handling + * + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla + * Steve Kipisz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include "board_descriptor.h" +#include "bdparser.h" + +#define SYSINFO_ADDRESS 0x0000 /* Board descriptor at beginning of EEPROM */ +#define SYSCONFIG_ADDRESS 0x0600 /* Board descriptor at beginning of EEPROM */ +#define MAX_PARTITION_ENTRIES 4 + +static BD_Context *bd_board_info = 0; +static BD_Context *bd_system_config = 0; + +static int i2c_eeprom_init(int i2c_bus, int dev_addr) +{ + int rc; + + if (i2c_bus >= 0) { + rc = i2c_set_bus_num(i2c_bus); + if (rc) + return rc; + } + + return i2c_probe(dev_addr); +} + +static int i2c_eeprom_read(int offset, void *data, size_t len) +{ + return i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, + offset, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, + data, + len); +} + +static int boardinfo_read(BD_Context **context, size_t start_addr) +{ + char bd_header_buffer[8]; + void *bd_data = NULL; + + if(*context) + return 0; + + *context = calloc(sizeof(BD_Context), 1); + if(!*context) + { + printf("Couldn't allocate memory for board information\n"); + goto failed; + } + + if (i2c_eeprom_read(start_addr, bd_header_buffer, sizeof(bd_header_buffer))) { + printf("%s() Can't read BD header from EEPROM\n", __FUNCTION__); + goto failed; + } + + if (!BD_CheckHeader(*context, bd_header_buffer)) + { + printf("Invalid board information header\n"); + goto failed; + } + + bd_data = malloc((*context)->size); + if (bd_data == NULL) + { + printf("Can not allocate memory for board info"); + goto failed; + } + + if (i2c_eeprom_read(start_addr + sizeof(bd_header_buffer), bd_data, (*context)->size)) + { + printf("Can not read board information data"); + goto failed; + } + + if (!BD_ImportData(*context, bd_data)) + { + printf("Invalid board information!\n"); + goto failed; + } + + return 0; + +failed: + if (bd_data != NULL) + { + free(bd_data); + bd_data = NULL; + } + + if (*context != NULL) + { + free(*context); + *context = NULL; + } + + return -1; +} + +static void read_sysinfo(void) +{ + int err; + + err = boardinfo_read(&bd_board_info, SYSINFO_ADDRESS); + if (err ) { + printf("Could not read sysinf boarddescriptor\n"); + return; + } + + return; +} + +static void read_sysconfig(void) +{ + int err; + + err = boardinfo_read(&bd_system_config, SYSCONFIG_ADDRESS); + if (err ) { + printf("Could not read sysconfig boarddescriptor\n"); + return; + } +} + +int bd_read (int bus_addr, int dev_addr) +{ + if (i2c_eeprom_init(bus_addr, dev_addr)) { + return -1; + } + + read_sysinfo(); + read_sysconfig(); + + return 0; +} + +static u8 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 = BD_GetPartition64( bd_system_config, 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; + +} + +u8 bd_get_boot_partition(void) +{ + u8 boot_part; + + if ((bd_system_config == 0)) { + puts("System config not valid, can not get boot partition\n"); + return 0; + } + + /* If we have a new Bootpartition entry take this as boot part */ + if ( BD_GetUInt8( bd_system_config, BD_BootPart, 0, &boot_part) ) { + if (boot_part >= 0 && boot_part <= 1) { + return boot_part; + } + } + + /* If we not have a Bootpartition entry, perhaps we have a partition table */ + return try_partition_read(); + +} + +int bd_get_mac_address(uint index, u8 *mac, u32 len) +{ + if (bd_board_info == 0) { + puts("Board info not valid, can not get mac address\n"); + return -1; + } + + if (len != 6) { + return -1; + } + + if (BD_GetMAC( bd_board_info, BD_Eth_Mac, index, mac)) + return 0; + else + return -1; +} + +int bd_get_hw_version(int* pVer, int* pRev) +{ + u8 bdCpHwVer = 0; + u8 bdCpHwRev = 0; + + if (bd_board_info == 0) { + puts("Board info not valid, can not get hw version\n"); + return -1; + } + /* Hardware version/revision */ + if ( !BD_GetUInt8( bd_board_info, BD_Hw_Ver, 0, &bdCpHwVer) ) { + printf("no Hw version found\n"); + return -1; + } + /* Hardware version/revision */ + if ( !BD_GetUInt8( bd_board_info, BD_Hw_Rel, 0, &bdCpHwRev) ) { + printf("no Hw release found\n"); + return -1; + } + + *pVer = bdCpHwVer; + *pRev = bdCpHwRev; + + return 0; +} + diff --git a/board/nm/netbird_v2/board_descriptor.h b/board/nm/netbird_v2/board_descriptor.h new file mode 100644 index 0000000000..a62b1a9567 --- /dev/null +++ b/board/nm/netbird_v2/board_descriptor.h @@ -0,0 +1,17 @@ +/* + * Library to support early TI EVM EEPROM handling + * + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __BOARD_DESCRIPTOR_H +#define __BOARD_DESCRIPTOR_H + +int bd_read(int bus_addr, int dev_addr); +u8 bd_get_boot_partition(void); +int bd_get_mac_address(uint index, u8 *mac_address, u32 len); +int bd_get_hw_version(int* pVer, int* pRev); + +#endif /* __BOARD_DESCRIPTOR_H */ diff --git a/board/nm/netbird_v2/mux.c b/board/nm/netbird_v2/mux.c new file mode 100644 index 0000000000..f829ca5927 --- /dev/null +++ b/board/nm/netbird_v2/mux.c @@ -0,0 +1,217 @@ +/* + * mux.c + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include "board.h" + +static struct module_pin_mux uart2_pin_mux[] = { + {OFFSET(spi0_sclk), (MODE(1) | PULLUP_EN | RXACTIVE)}, /* UART2_RXD */ + {OFFSET(spi0_d0), (MODE(1) | PULLUDEN)}, /* UART2_TXD */ + {-1}, +}; + +static struct module_pin_mux uart3_pin_mux[] = { + {OFFSET(spi0_cs1), (MODE(1) | PULLUP_EN | RXACTIVE)}, /* UART3_RXD */ + {OFFSET(ecap0_in_pwm0_out), (MODE(1) | PULLUDEN)}, /* UART3_TXD */ + {-1}, +}; + +static struct module_pin_mux uart4_pin_mux[] = { + {OFFSET(gpmc_wait0), (MODE(6) | PULLUP_EN | RXACTIVE)}, /* UART4_RXD */ + {OFFSET(gpmc_wpn), (MODE(6) | PULLUDEN)}, /* UART4_TXD */ + {-1}, +}; + +static struct module_pin_mux uart5_pin_mux[] = { + {OFFSET(lcd_data9), (MODE(4) | PULLUP_EN | RXACTIVE)}, /* UART5_RXD */ + {OFFSET(lcd_data8), (MODE(4) | PULLUDEN)}, /* UART5_TXD */ + {-1}, +}; + +static struct module_pin_mux i2c0_pin_mux[] = { + {OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | + PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* I2C_DATA */ + {OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | + PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* I2C_SCLK */ + {-1}, +}; + +/* V2OK */ +static struct module_pin_mux uart0_netbird_pin_mux[] = { + {OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (E15) UART0_RXD */ + {OFFSET(uart0_txd), (MODE(0) | PULLUDEN | PULLUP_EN)}, /* (E16) UART0_TXD */ + {OFFSET(uart0_ctsn), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (E18) UART0_CTSN */ + {OFFSET(uart0_rtsn), (MODE(0) | PULLUDEN | PULLUP_EN)}, /* (E17) UART0_RTSN */ + {-1}, +}; + +/* V2OK */ +static struct module_pin_mux uart1_netbird_pin_mux[] = { + {OFFSET(uart1_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (D16) uart1_rxd.uart1_rxd */ + {OFFSET(uart1_txd), (MODE(0) | PULLUDEN | PULLUP_EN)}, /* (D15) uart1_txd.uart1_txd */ + {-1}, +}; + +/* V2OK */ +static struct module_pin_mux rmii1_netbird_pin_mux[] = { + {OFFSET(mii1_crs), MODE(1) | PULLUDDIS | RXACTIVE}, /* (H17) mii1_crs.rmii1_crs */ + {OFFSET(mii1_rxerr), MODE(1) | PULLUDDIS | RXACTIVE}, /* (J15) mii1_rxerr.rmii1_rxerr */ + {OFFSET(mii1_txen), MODE(1) | PULLUDDIS }, /* (J16) mii1_txen.rmii1_txen */ + {OFFSET(mii1_txd0), MODE(1) | PULLUDDIS }, /* (K17) mii1_txd0.rmii1_txd0 */ + {OFFSET(mii1_txd1), MODE(1) | PULLUDDIS }, /* (K16) mii1_txd1.rmii1_txd1 */ + {OFFSET(mii1_rxd0), MODE(1) | PULLUDDIS | RXACTIVE }, /* (M16) mii1_rxd0.rmii1_rxd0 */ + {OFFSET(mii1_rxd1), MODE(1) | PULLUDDIS | RXACTIVE }, /* (L15) mii1_rxd1.rmii1_rxd1 */ + {OFFSET(rmii1_refclk), MODE(0) | PULLUDDIS | RXACTIVE}, /* (H18) rmii1_refclk.rmii1_refclk */ + {OFFSET(mdio_clk), MODE(0) | PULLUDDIS }, /* (M18) mdio_clk.mdio_clk */ + {OFFSET(mdio_data), MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE }, /* (M17) mido_data.mdio_data */ + {OFFSET(xdma_event_intr0), MODE(3) }, /* (A15) xdma_event_intr0.clkout1 (25 MHz clk for MDIO) */ + {-1}, +}; + +static struct module_pin_mux mmc0_sdio_netbird_pin_mux[] = { + {OFFSET(mmc0_clk), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_CLK */ + {OFFSET(mmc0_cmd), (MODE(0) | PULLUDEN | PULLUP_EN)}, /* MMC0_CMD */ + {OFFSET(mmc0_dat0), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC0_DAT0 */ + {OFFSET(mmc0_dat1), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC0_DAT1 */ + {OFFSET(mmc0_dat2), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC0_DAT2 */ + {OFFSET(mmc0_dat3), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC0_DAT3 */ + {-1}, +}; + +static struct module_pin_mux mmc1_emmc_netbird_pin_mux[] = { + {OFFSET(gpmc_csn1), (MODE(2) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_CLK */ + {OFFSET(gpmc_csn2), (MODE(2) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_CMD */ + {OFFSET(gpmc_ad0), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT0 */ + {OFFSET(gpmc_ad1), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT1 */ + {OFFSET(gpmc_ad2), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT2 */ + {OFFSET(gpmc_ad3), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT3 */ + {OFFSET(gpmc_ad4), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT3 */ + {OFFSET(gpmc_ad5), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT3 */ + {OFFSET(gpmc_ad6), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT3 */ + {OFFSET(gpmc_ad7), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE )}, /* MMC1_DAT3 */ + {-1}, +}; + +static struct module_pin_mux gpio_netbird_pin_mux[] = { + /* Bank 0 */ + {OFFSET(spi0_sclk), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (A17) spi0_sclk.gpio0[2] */ /* BUTTON */ + {OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (C18) eCAP0_in_PWM0_out.gpio0[7] */ /* PWM */ + {OFFSET(mii1_txd3), (MODE(7) | PULLUDDIS)}, /* (J18) gmii1_txd3.gpio0[16] */ /* RST_PHY~ */ + {OFFSET(gpmc_ad11), (MODE(7) | PULLUDDIS)}, /* (U12) gpmc_ad11.gpio0[27] */ /* RST_EXT~ */ + /* Bank 1 */ + {OFFSET(gpmc_ad14), (MODE(7) | PULLUDDIS)}, /* (V13) gpmc_ad14.gpio1[14] */ /* LED_A */ + {OFFSET(gpmc_ad15), (MODE(7) | PULLUDDIS)}, /* (U13) gpmc_ad15.gpio1[15] */ /* LED_B */ + {OFFSET(gpmc_a11), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (V17) gpmc_a11.gpio1[27] */ /* USB_PWR_EN */ + {OFFSET(gpmc_a9), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (U16) gpmc_a9.gpio1[25] */ /* RST_GSM */ + {OFFSET(gpmc_csn3), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (U17) gpmc_csn3.gpio0[31] */ /* GSM_SUPP_EN */ + {OFFSET(gpmc_a5), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (V15) gpmc_a5.gpio1[21] */ /* GSM_PWR_EN */ + /* Bank 2 */ + {OFFSET(lcd_data3), (MODE(7) | PULLUDEN| PULLUP_EN)}, /* (V5) lcd_pclk.gpio2[9] */ /* SYSBOOT */ + {OFFSET(lcd_data4), (MODE(7) | PULLUDEN| PULLUP_EN)}, /* (V5) lcd_pclk.gpio2[10] */ /* SYSBOOT */ + /* Bank 3 */ + {OFFSET(mii1_rxdv), (MODE(7) | PULLUDDIS)}, /* (J17) gmii1_rxdv.gpio3[4] */ /* BT_EN */ + {OFFSET(mii1_rxdv), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (K18) gmii1_txclk.gpio3[9] */ /* WLAN_IRQ */ + {OFFSET(mii1_rxdv), (MODE(7) | PULLUDDIS)}, /* (L18) gmii1_rxclk.gpio3[10] */ /* WLAN_EN */ + {OFFSET(mcasp0_ahclkr), (MODE(7) | PULLUDDIS)}, /* (C12) mcasp0_ahclkr.gpio3[17] */ /* WLAN_CLK (32k Linux only) */ + {-1}, +}; + +static struct module_pin_mux usb_netbird_pin_mux[] = { + {OFFSET(usb0_drvvbus), (MODE(0) | PULLUDEN | PULLDOWN_EN)}, /* (F16) USB0_DRVVBUS.USB0_DRVVBUS */ /* PWM */ + {OFFSET(usb1_drvvbus), (MODE(0) | PULLUDDIS | PULLDOWN_EN)}, /* (F15) USB1_DRVVBUS.USB1_DRVVBUS */ /* RST_PHY~ */ + {-1}, +}; + +static struct module_pin_mux unused_netbird_pin_mux[] = { + {OFFSET(lcd_data6), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, /* SYSBOOT6 is not used bulldown active, receiver disabled */ + {OFFSET(lcd_data7), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, /* SYSBOOT7 is not used bulldown active, receiver disabled */ + {OFFSET(lcd_data10), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, /* SYSBOOT10 is not used bulldown active, receiver disabled */ + {OFFSET(lcd_data11), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, /* SYSBOOT11 is not used bulldown active, receiver disabled */ + {-1}, +}; + +void enable_uart0_pin_mux(void) +{ + configure_module_pin_mux(uart0_netbird_pin_mux); +} + +void enable_uart1_pin_mux(void) +{ + configure_module_pin_mux(uart1_netbird_pin_mux); +} + +void enable_uart2_pin_mux(void) +{ + configure_module_pin_mux(uart2_pin_mux); +} + +void enable_uart3_pin_mux(void) +{ + configure_module_pin_mux(uart3_pin_mux); +} + +void enable_uart4_pin_mux(void) +{ + configure_module_pin_mux(uart4_pin_mux); +} + +void enable_uart5_pin_mux(void) +{ + configure_module_pin_mux(uart5_pin_mux); +} + +void enable_i2c0_pin_mux(void) +{ + configure_module_pin_mux(i2c0_pin_mux); +} + +/* + * The AM335x GP EVM, if daughter card(s) are connected, can have 8 + * different profiles. These profiles determine what peripherals are + * valid and need pinmux to be configured. + */ +#define PROFILE_NONE 0x0 +#define PROFILE_0 (1 << 0) +#define PROFILE_1 (1 << 1) +#define PROFILE_2 (1 << 2) +#define PROFILE_3 (1 << 3) +#define PROFILE_4 (1 << 4) +#define PROFILE_5 (1 << 5) +#define PROFILE_6 (1 << 6) +#define PROFILE_7 (1 << 7) +#define PROFILE_MASK 0x7 +#define PROFILE_ALL 0xFF + +/* CPLD registers */ +#define I2C_CPLD_ADDR 0x35 +#define CFG_REG 0x10 + +void enable_board_pin_mux(void) +{ + /* Netbird board */ + configure_module_pin_mux(gpio_netbird_pin_mux); + configure_module_pin_mux(rmii1_netbird_pin_mux); + configure_module_pin_mux(mmc0_sdio_netbird_pin_mux); + configure_module_pin_mux(mmc1_emmc_netbird_pin_mux); + configure_module_pin_mux(usb_netbird_pin_mux); + configure_module_pin_mux(usb_netbird_pin_mux); + configure_module_pin_mux(i2c0_pin_mux); + configure_module_pin_mux(unused_netbird_pin_mux); +} diff --git a/board/nm/netbird_v2/u-boot.lds b/board/nm/netbird_v2/u-boot.lds new file mode 100644 index 0000000000..dad7e09c65 --- /dev/null +++ b/board/nm/netbird_v2/u-boot.lds @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + *(.vectors) + CPUDIR/start.o (.text*) + board/nm/netbird_v2/built-in.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .__efi_runtime_start : { + *(.__efi_runtime_start) + } + + .efi_runtime : { + *(efi_runtime_text) + *(efi_runtime_data) + } + + .__efi_runtime_stop : { + *(.__efi_runtime_stop) + } + + .efi_runtime_rel_start : + { + *(.__efi_runtime_rel_start) + } + + .efi_runtime_rel : { + *(.relefi_runtime_text) + *(.relefi_runtime_data) + } + + .efi_runtime_rel_stop : + { + *(.__efi_runtime_rel_stop) + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rel.dyn : { + *(.rel*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + .hash : { *(.hash*) } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + /* + * Deprecated: this MMU section is used by pxa at present but + * should not be used by new boards/CPUs. + */ + . = ALIGN(4096); + .mmutable : { + *(.mmutable) + } + +/* + * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c + * __bss_base and __bss_limit are for linker only (overlay ordering) + */ + + .bss_start __rel_dyn_start (OVERLAY) : { + KEEP(*(.__bss_start)); + __bss_base = .; + } + + .bss __bss_base (OVERLAY) : { + *(.bss*) + . = ALIGN(4); + __bss_limit = .; + } + + .bss_end __bss_limit (OVERLAY) : { + KEEP(*(.__bss_end)); + } + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .gnu.hash : { *(.gnu.hash) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +} diff --git a/configs/am335x_netbird_v2_defconfig b/configs/am335x_netbird_v2_defconfig new file mode 100644 index 0000000000..813074d0d2 --- /dev/null +++ b/configs/am335x_netbird_v2_defconfig @@ -0,0 +1,44 @@ +CONFIG_ARM=y +CONFIG_TARGET_AM335X_NETBIRD_V2=y +CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_SPL=y +CONFIG_SPL_STACK_R=y +CONFIG_FIT=y +CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT" +CONFIG_HUSH_PARSER=y +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Press s to abort autoboot in %d seconds\n" +CONFIG_AUTOBOOT_STOP_STR="s" +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_ASKENV=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +CONFIG_CMD_DFU=y +CONFIG_CMD_GPIO=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_DFU_TFTP=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_USB_MUSB_HOST=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Texas Instruments" +CONFIG_G_DNL_VENDOR_NUM=0x0451 +CONFIG_G_DNL_PRODUCT_NUM=0xd022 +CONFIG_OF_LIBFDT=y diff --git a/include/configs/am335x_netbird_v2.h b/include/configs/am335x_netbird_v2.h new file mode 100644 index 0000000000..d958f545a1 --- /dev/null +++ b/include/configs/am335x_netbird_v2.h @@ -0,0 +1,217 @@ +/* + * am335x_evm.h + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __CONFIG_AM335X_NETBIRD_V2_H +#define __CONFIG_AM335X_NETBIRD_V2_H + +#include + +#undef CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC +#undef CONFIG_HW_WATCHDOG +#undef CONFIG_OMPAP_WATCHDOG +#undef CONFIG_SPL_WATCHDOG_SUPPORT + +#ifndef CONFIG_SPL_BUILD +# define CONFIG_TIMESTAMP +# define CONFIG_LZO +#endif + +#define CONFIG_SYS_BOOTM_LEN (16 << 20) + +#define MACH_TYPE_TIAM335EVM 3589 /* Until the next sync */ +#define CONFIG_MACH_TYPE MACH_TYPE_TIAM335EVM +#define CONFIG_BOARD_LATE_INIT + +/* Clock Defines */ +#define V_OSCK 0 /* 0 means detect from sysboot1 config */ +#define V_SCLK (V_OSCK) + +#include + +#ifndef CONFIG_SPL_BUILD +#define CONFIG_EXTRA_ENV_SETTINGS \ + "kernel_image=kernel.bin\0" \ + "fdt_image=openwrt-nbhw16.dtb\0" \ + "modeboot=sdboot\0" \ + "fdt_addr=0x82000000\0" \ + "kernel_addr=0x80000000\0" \ + "load_addr=0x83000000\0" \ + "root_part=1\0" /* Default root partition, overwritte in board/mv_ebu/a38x/nbhw14_env.c */ \ + "add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 console=ttyO1,115200 rootwait earlyprintk\0" \ + "add_version_bootargs=setenv bootargs $bootargs\0" \ + "fdt_skip_update=yes\0" \ + "ethprime=cpsw\0" \ + "sdbringup=echo Try bringup boot && ext4load mmc 1:$root_part $kernel_addr /boot/zImage && " \ + "ext4load mmc 1:$root_part $fdt_addr /boot/am335x-netbird-v2.dtb && setenv bootargs $bootargs rw;\0" \ + "sdprod=ext4load mmc 1:$root_part $kernel_addr /boot/$kernel_image && " \ + "ext4load mmc 1:$root_part $fdt_addr /boot/$fdt_image && setenv bootargs $bootargs ro;\0" \ + "sdboot=if mmc dev 1; then echo Copying Linux from SD to RAM...; "\ + "if test -e mmc 1:$root_part /boot/$kernel_image; then run sdprod; " \ + "else run sdbringup; fi; " \ + "run add_sd_bootargs; run add_version_bootargs; " \ + "bootz $kernel_addr - $fdt_addr; fi\0" \ + "bootcmd=run sdboot\0" \ + "ipaddr=192.168.1.1\0" \ + "serverip=192.168.1.254\0" \ + "recovery=tftpboot $kernel_addr recovery-image; tftpboot $fdt_addr recovery-dtb; setenv bootargs rdinit=/etc/preinit console=ttyO0,115200 debug; bootz $kernel_addr - $fdt_addr\0" +#endif + +/* NS16550 Configuration */ +#define CONFIG_SYS_NS16550_COM1 0x44e09000 /* Base EVM has UART0 */ +#define CONFIG_SYS_NS16550_COM2 0x48022000 /* UART1 */ +#define CONFIG_SYS_NS16550_COM3 0x48024000 /* UART2 */ +#define CONFIG_SYS_NS16550_COM4 0x481a6000 /* UART3 */ +#define CONFIG_SYS_NS16550_COM5 0x481a8000 /* UART4 */ +#define CONFIG_SYS_NS16550_COM6 0x481aa000 /* UART5 */ +#define CONFIG_BAUDRATE 115200 +#define CONFIG_CONS_INDEX 2 /* Use UART1 as standard UART (1 = UART0) */ + +#define CONFIG_CMD_EEPROM +#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 /* Main EEPROM */ +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 50 + +#define CONFIG_ENV_IS_IN_EEPROM +#define CONFIG_ENV_OFFSET 0x1000 /* The Environment is located at 4k */ +#define CONFIG_ENV_SIZE 0x800 /* The maximum size is 2k */ +#undef CONFIG_SPL_ENV_SUPPORT +#undef CONFIG_SPL_NAND_SUPPORT +#undef CONFIG_SPL_ONENAND_SUPPORT + + +/* We need to disable SPI to not confuse the eeprom env driver */ +#undef CONFIG_SPI +#undef CONFIG_SPI_BOOT +#undef CONFIG_SPL_OS_BOOT + +#define CONFIG_SPL_POWER_SUPPORT +#define CONFIG_SPL_YMODEM_SUPPORT + +#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds" + +#define CONFIG_SUPPORT_EMMC_BOOT + +/* + * USB configuration. We enable MUSB support, both for host and for + * gadget. We set USB0 as peripheral and USB1 as host, based on the + * board schematic and physical port wired to each. Then for host we + * add mass storage support and for gadget we add both RNDIS ethernet + * and DFU. + */ +#define CONFIG_USB_MUSB_DSPS +#define CONFIG_ARCH_MISC_INIT +#define CONFIG_USB_MUSB_PIO_ONLY +#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT +#define CONFIG_AM335X_USB0 +#define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL +#define CONFIG_AM335X_USB1 +#define CONFIG_AM335X_USB1_MODE MUSB_HOST + +/* Fastboot */ +#define CONFIG_USB_FUNCTION_FASTBOOT +#define CONFIG_CMD_FASTBOOT +#define CONFIG_ANDROID_BOOT_IMAGE +#define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR +#define CONFIG_FASTBOOT_BUF_SIZE 0x07000000 + +/* To support eMMC booting */ +#define CONFIG_STORAGE_EMMC +#define CONFIG_FASTBOOT_FLASH_MMC_DEV 1 + +#ifdef CONFIG_USB_MUSB_HOST +#define CONFIG_USB_STORAGE +#endif + +#ifdef CONFIG_USB_MUSB_GADGET +/* Removing USB gadget and can be enabled adter adding support usb DM */ +#ifndef CONFIG_DM_ETH +#define CONFIG_USB_ETHER +#define CONFIG_USB_ETH_RNDIS +#define CONFIG_USBNET_HOST_ADDR "de:ad:be:af:00:00" +#endif /* CONFIG_DM_ETH */ +#endif /* CONFIG_USB_MUSB_GADGET */ + +/* + * Disable MMC DM for SPL build and can be re-enabled after adding + * DM support in SPL + */ +#ifdef CONFIG_SPL_BUILD +#undef CONFIG_DM_MMC +#undef CONFIG_TIMER +#endif + +#if defined(CONFIG_SPL_BUILD) +/* Remove other SPL modes. */ +#undef CONFIG_SPL_NAND_SUPPORT +#define CONFIG_ENV_IS_NOWHERE +#undef CONFIG_PARTITION_UUIDS +#undef CONFIG_EFI_PARTITION +#endif + +/* USB Device Firmware Update support */ +#ifndef CONFIG_SPL_BUILD +#define CONFIG_USB_FUNCTION_DFU +#define CONFIG_DFU_MMC +#define DFU_ALT_INFO_MMC \ + "dfu_alt_info_mmc=" \ + "boot part 0 1;" \ + "rootfs part 0 2;" \ + "MLO fat 0 1;" \ + "MLO.raw raw 0x100 0x100;" \ + "u-boot.img.raw raw 0x300 0x400;" \ + "spl-os-args.raw raw 0x80 0x80;" \ + "spl-os-image.raw raw 0x900 0x2000;" \ + "spl-os-args fat 0 1;" \ + "spl-os-image fat 0 1;" \ + "u-boot.img fat 0 1;" \ + "uEnv.txt fat 0 1\0" +#define DFU_ALT_INFO_NAND "" +#define CONFIG_DFU_RAM +#define DFU_ALT_INFO_RAM \ + "dfu_alt_info_ram=" \ + "kernel ram 0x80200000 0xD80000;" \ + "fdt ram 0x80F80000 0x80000;" \ + "ramdisk ram 0x81000000 0x4000000\0" +#define DFUARGS \ + "dfu_alt_info_emmc=rawemmc raw 0 3751936\0" \ + DFU_ALT_INFO_MMC \ + DFU_ALT_INFO_RAM \ + DFU_ALT_INFO_NAND +#endif + +/* Network. */ +#define CONFIG_PHY_GIGE +#define CONFIG_PHYLIB +#define CONFIG_PHY_SMSC + +#ifdef CONFIG_DRIVER_TI_CPSW +#define CONFIG_CLOCK_SYNTHESIZER +#define CLK_SYNTHESIZER_I2C_ADDR 0x65 +#endif + +#define CONFIG_SYS_MEMTEST_START 0x80000000 +#define CONFIG_SYS_MEMTEST_END 0x87900000 + +/* Enable support for TPS 65218 */ +#define CONFIG_POWER +#define CONFIG_POWER_I2C +#define CONFIG_POWER_TPS65218 +/* For compatibility reasons (BeagleBone) */ +#define CONFIG_POWER_TPS65217 +#define CONFIG_POWER_TPS62362 + +#endif /* ! __CONFIG_AM335X_NETBIRD_V2_H */