ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/obm/Common/Misc/misc.c b/marvell/obm/Common/Misc/misc.c
new file mode 100644
index 0000000..51e2f3c
--- /dev/null
+++ b/marvell/obm/Common/Misc/misc.c
@@ -0,0 +1,601 @@
+/******************************************************************************
+ *
+ * (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;
+}