blob: 51e2f3c396b162066379bd60d19412891885e026 [file] [log] [blame]
/******************************************************************************
*
* (C)Copyright 2005 - 2011 Marvell. All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
* The copyright notice above does not evidence any actual or intended
* publication of such source code.
* This Module contains Proprietary Information of Marvell and should be
* treated as Confidential.
* The information in this file is provided for the exclusive use of the
* licensees of Marvell.
* Such users have the right to use, modify, and incorporate this code into
* products for purposes authorized by the license agreement provided they
* include this notice and the associated copyright notice with any such
* product.
* The information in this file is provided "AS IS" without warranty.
*
*
* FILENAME: Misc.c
*
* PURPOSE: Contain helpful misc. functions
*
******************************************************************************/
#include "misc.h"
static unsigned char* StrPtr8;
static unsigned int DataWidth;
// Very simple routine to reverse bytes on up to a 512 byte buffer.
UINT_T ReverseBytes (UINT8_T* Address, UINT_T Size)
{
UINT8_T Buffer[512];
UINT_T i;
if (Size > 512)
return InvalidSizeError;
// First copy to a Buffer
for (i=0; (i < Size); i++)
Buffer[i] = Address[i];
// Next copy to Address in reverse order
for (i=0; (i < Size); i++)
Address[Size - 1 - i] = Buffer[i];
return NoError;
}
//endian conversion function: self explanatory
unsigned int Endian_Convert (unsigned int in)
{
unsigned int out;
out = in << 24;
out |= (in & 0xFF00) << 8;
out |= (in & 0xFF0000) >> 8;
out |= (in & 0xFF000000) >> 24;
return out;
}
// return 1 if majority of right-most numBits in Word are 1
// return 0 if majority of right-most numBits in Word are 0
// return 0 if 1s are equal to 0s (this means numBits is even)
unsigned int MajorityVote (unsigned int Word, unsigned int numBits)
{
int i;
int numOnes = 0;
int numZeros = 0;
for (i=1; i<=numBits; i++)
{
if ( (Word & 1) == 1 ) numOnes++;
else numZeros++;
Word = Word>>1;
}
if (numOnes > numZeros) return 1;
else return 0; // If majority voting is requested for even number of bits and numOnes == numZeros, zero wins
}
/**
* Memory set function
**/
void memset(void *Addr, unsigned char Val, unsigned long Size)
{
unsigned long i;
for(i=0; i < Size; i++ )
{
((unsigned char*)Addr)[i] = Val;
}
}
void *memcpy(void *dest, const void *src, unsigned int n)
{
const unsigned char *s = (const unsigned char*)src;
unsigned char *d = (unsigned char *)dest;
//don't copy if we don't need to
if(dest == src)
return dest;
//smart copy, in case of overlap:
while(n-- > 0)
if(s > d) //copy 'forwards'
*d++ = *s++;
else //copy 'in reverse'
d[n] = s[n];
return dest;
}
void *memmove(void *dest, const void *src, unsigned int n)
{
return memcpy(dest, src, n);
}
int memcmp( const void *buffer1, const void *buffer2, int count)
{
UINT8_T* buf1 = (UINT8_T*)buffer1;
UINT8_T* buf2 = (UINT8_T*)buffer2;
while(count)
{
if( *(buf1) != *(buf2) )
return( (*buf1 < *buf2) ? -1 : 1 );
buf1 += sizeof(UINT8_T);
buf2 += sizeof(UINT8_T);
count--;
}
return 0;
}
int ConvertStringToInteger8(const unsigned char* StringPtr, unsigned int Count)
{
int Output = 0;
unsigned char c;
while (*StringPtr)
{
Output *= Count;
c = *StringPtr++;
if (c >= '0' && c <= '9')
Output += (c-'0');
else
Output += ((c|' ')-'a'+10);
}
return (Output);
}
int DivideTwoNumbers(int Numerator,int Denominator)
{
int Tmp = 0;
int Output = 0;
int Count;
if(!Denominator)
return Numerator;
for (Count = 28; Count >= 0; Count -= 4)
{
Tmp <<= 4;
Output <<= 4;
Tmp |= (Numerator >> Count)&0xf;
while(Tmp >= 0)
{
Tmp -= Denominator;
Output++;
}
Tmp += Denominator;
Output--;
}
return(Output);
}
int ModOfTwoNumbers(int Numerator, int Denominator)
{
//return(Numerator - (Denominator * DivideTwoNumbers(Numerator, Denominator)));
int Tmp;
Tmp = DivideTwoNumbers(Numerator, Denominator);
Tmp = Tmp * Denominator;
Tmp = Numerator - Tmp;
#if LINUX_BUILD
// The GCC compiler assigns the value in R1(Quotient) to variable on the left side of the "="
// in the calling code. So we need to move the Remainder (in Tmp) to R1 so we get the Remainder
// returned and not the quotient.
// Syntax below informs the compiler we modified R1 intentionally and don't mess with it.
asm("mov r1, %[value]" :: [value] "r" (Tmp): "r1"); // this move the contents of temp into r1
#endif
return Tmp;
}
void ConvertLongIntToBuf8(int DataValue, int Count)
{
if (DataValue >= Count)
{
ConvertLongIntToBuf8(DivideTwoNumbers(DataValue, Count), Count);
StrPtr8++;
DataWidth--;
DataValue = ModOfTwoNumbers(DataValue, Count);
}
if (DataWidth > 0)
*StrPtr8 = (unsigned char)(DataValue + (DataValue < 10 ? '0' : ('a'-10)));
}
void ConvertIntToBuf8(unsigned char* StringPtr,unsigned int Value, int Width,unsigned int Count)
{
int i;
StrPtr8 = StringPtr;
DataWidth = Width;
if (Value >= Count)
{
ConvertLongIntToBuf8(DivideTwoNumbers(Value,Count),Count);
StrPtr8++;
DataWidth--;
Value=ModOfTwoNumbers(Value,Count);
}
if (DataWidth-->0)
*StrPtr8=(unsigned char)(Value + (Value < 10 ? '0' : ('a'-10)));
// If DataWidth=0, the following will do nothing, so just return here
if (DataWidth == 0) return;
// Shift the contents of the buffer to right by DataWidth to achieve right alignment
for (i=Width; i > DataWidth; i--)
{
*(StrPtr8+DataWidth) = *(StrPtr8);
StrPtr8--;
}
// Prepend leading zeros if necessary
while (DataWidth-- > 0)
*++StrPtr8 = '0';
}
void __aeabi_idiv0( void ){
//dummy function for the compiler
// need to investigate the in32t_divide.o and x0_a000.o libraries from XDB
return;
}
//The below functions are pulled in from a library when built by RVCT or SDT compiler (NDT flag)
//When built by the linux compiler, we need to define the calls ourselves
#if LINUX_BUILD
void __aeabi_idiv(void){
//void __divsi3(void){
asm("b DivideTwoNumbers");
return;
}
void __aeabi_uidiv(void){
//void __udivsi3(void){
asm("b DivideTwoNumbers");
return;
}
void __aeabi_uidivmod(void){
asm("b ModOfTwoNumbers");
return;
}
long long __aeabi_llsr(long long a, int b)
{
}
#endif
/*
String Compare function - case sensitive
Will compare str1 to str2, character to character, until a NULL character is hit
or until maxlength is reached
If no NULL character is present, there could be serious issues
Return values:
-1 = str1 < str2
0 = Match
1 = str1 > str2
*/
int strcmpl( char* str1, char* str2, int maxlength )
{
int length = maxlength;
while((*str1 != NULL) && (*str2 != NULL) && --length)
{
if (*str1 != *str2)
{
// check the char that was different to determine results
if ( *str1 > *str2 )
return 1;
else
return -1;
}
str1++; str2++;
}
// strings compared so far, but did we reach the end of both?
if ( *str1 != NULL && *str2 != NULL )
// did not find the NULLs but have reached the maxlength to compare
return 0;
if ( *str1 == NULL && *str2 == NULL )
return 0;
if ( *str1 != NULL && *str2 == NULL )
// "abcde" > "abcd"
return 1;
else
// "abcd" < "abcde"
return -1;
}
/*
String Compare function - case insensitive
Will compare str1 to str2 ignoring case, character to character, until a NULL character is hit
or until maxlength is reached
If no NULL character is present, there could be serious issues
Return values:
-1 = str1 < str2
0 = Match
1 = str1 > str2
*/
int stricmpl( char* str1, char* str2, int maxlength)
{
int length = maxlength;
while((*str1 != NULL) && (*str2 != NULL) && --length)
{
if ( ((*str1) & 0xDF) != ((*str2) & 0xDF) )
{
// check the char that was different to determine results
if ( ((*str1) & 0xDF) > ((*str2) & 0xDF) )
return 1;
else
return -1;
}
str1++; str2++;
}
// strings compared so far, but did we reach the end of both?
if ( *str1 != NULL && *str2 != NULL )
// did not find the NULLs but have reached the maxlength to compare
return 0;
if ( *str1 == NULL && *str2 == NULL )
return 0;
if ( *str1 != NULL && *str2 == NULL )
// "abcde" > "abcd"
return 1;
else
// "abcd" < "abcde"
return -1;
}
INT_T strlen (const char * str)
{
int i = 0;
while(str[i++] != '\0')
if(i > 1000)
break;
return --i;
}
INT_T memcmpFF( const void *buffer, INT_T count)
{
UINT8_T* buf = (UINT8_T*)buffer;
while(count--)
{
if( *(buf) != 0xFF )
return -1;
buf += sizeof(UINT8_T);
}
return 0;
}
//Aligns the pointer on ALIGN boundary
unsigned long Align_Ptr (unsigned long Address, unsigned long Align)
{
Address = (Address+Align-1) & ~(Align - 1);
return Address;
}
void bubble(UINT16_T * ptr, UINT_T n)
{
UINT_T i, j, temp;
for (i = 0; i < n-1; i++)
for (j = i + 1; j < n; j++)
if (ptr[i] > ptr[j])
{
temp = ptr[j];
ptr[j] = ptr[i];
ptr[i] = temp;
}
}
UINT CalcImageChecksum( UINT_T* DownloadArea, UINT_T ImageLength)
{
UINT ImageChecksum = 0;
UINT32* ptr32 = DownloadArea;
UINT32* pEnd = ptr32 + (ImageLength / sizeof(UINT32));
UINT BytesSummed = 0;
while ( ptr32 < pEnd )
{
// checksum format version 2 algorithm as defined by flasher
ImageChecksum ^= (*ptr32);
ptr32++;
BytesSummed += sizeof(UINT32);
}
return ImageChecksum;
}
UINT_T CalcMRDChecksum( UINT_T* start, UINT_T length)
{
UINT8_T *pRD_DDR_end = NULL;
UINT_T check_sum = 0, num = 0;
UINT_T a = 0x0001, b = 0x0000, index = 0;
UINT8_T * pRAMbuf;
pRAMbuf = (UINT8_T *)start;
pRD_DDR_end = pRAMbuf + length;
do
{
num = (UINT_T)(*pRAMbuf++);
a += num;
index++;
b += a;
/*
Algorithm is defined as mod MOD_ADLER at every modification to a and b.
For efficiency reasons this mod can be done once in a while to keep (a) and (b) in range (32-bit signed)
The result is invariant of MOD_LOOPS value.
a<5550*256; b<(5551*256/2)*5550=3943430400 (in range)
*/
if(index == MOD_LOOPS)
{
index =0;
a %= MOD_ADLER;
b %= MOD_ADLER;
}
// TBD: MISALIGNED 32-BIT ACCESS HERE AT EVERY BYTE ADDRESS, VERY INEFFICIENT & REDUNDANT
// Kept here for now for compatibility with old version of the tool that produces RDA with DADADADA at misaligned offset
} while( pRAMbuf < (UINT8_T *)pRD_DDR_end );
if(index)
{
a %= MOD_ADLER;
b %= MOD_ADLER;
}
check_sum = (b << 16) | a;
return check_sum;
}
const UINT32 crc32_table[] =
{
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
UINT32 CalcCRC32 (const unsigned char *buf, int len, unsigned int init)
{
UINT32 crc = init;
while (len--)
{
crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
buf++;
}
return crc;
}
UINT16_T from32to16(UINT x)
{
/* add up 16-bit and 16-bit for 16+c bit */
x = (x & 0xffff) + (x >> 16);
/* add up carry.. */
x = (x & 0xffff) + (x >> 16);
return x;
}
UINT malbrain_crc32(UINT crcu32, const BYTE *ptr, UINT buf_len)
{
static const UINT s_crc32[16] = {
0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
if (!ptr)
return 0;
crcu32 = ~crcu32;
while (buf_len--)
{
BYTE b = *ptr++;
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
}
return ~crcu32;
}
CHAR *HexToSwdObmVersion(UINT32 VerHex)
{
static CHAR VerStr[8];
memset(VerStr, 0, 8);
VerStr[0] = (VerHex >> 24) & 0xFF ;
VerStr[1] = '.';
VerStr[2] = (VerHex >> 16) & 0xFF;
VerStr[3] = '.';
VerStr[4] = (VerHex >> 8) & 0xFF;
VerStr[5] = '.';
VerStr[6] = (VerHex >> 0) & 0xFF;
return VerStr;
}
char *ImageID2String(UINT_T id)
{
static char str[5];
memset(str, 0, sizeof(str));
str[0] = (id >> 24) & 0xff;
str[1] = (id >> 16) & 0xff;
str[2] = (id >> 8) & 0xff;
str[3] = id & 0xff;
return str;
}