| /****************************************************************************** |
| * |
| * (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; |
| } |