brdbootldr/ubootldr/inflate2.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // base\omap_hrp\h4_bootloader\inflate2.cpp
       
    15 // For inflate image which is compressed by Deflate algortihm instead of ZIP
       
    16 // (The ROM header un-compressed, the rest part of the image is compressed.)
       
    17 // 
       
    18 //
       
    19 
       
    20 #define FILE_ID	0x4C5A4955
       
    21 
       
    22 #include <e32def.h>
       
    23 #include <e32def_private.h>
       
    24 #include <e32cmn.h>
       
    25 #include <e32rom.h>
       
    26 
       
    27 #include "inflate2.h"
       
    28 
       
    29 #include <e32std.h>
       
    30 #include <e32std_private.h>
       
    31 #include "bootldr.h"
       
    32 #include "unzip.h"
       
    33 
       
    34 #include <f32file.h>
       
    35 #include <e32svr.h>
       
    36 
       
    37 
       
    38 #define PTRADD(T,p,x)	((T*)((char*)(p)+(x)))
       
    39 #define MIN(a,b)		(((a)<(b))?(a):(b))
       
    40 
       
    41 
       
    42 // bit-stream input class
       
    43 inline TUint reverse(TUint aVal)
       
    44 //
       
    45 // Reverse the byte-order of a 32 bit value
       
    46 // This generates optimal ARM code (4 instructions)
       
    47 //
       
    48 	{
       
    49 	TUint v=(aVal<<16)|(aVal>>16);
       
    50 	v^=aVal;
       
    51 	v&=0xff00ffff;
       
    52 	aVal=(aVal>>8)|(aVal<<24);
       
    53 	return aVal^(v>>8);
       
    54 	}
       
    55 
       
    56 
       
    57 
       
    58 void HexDump(TUint8 * aStartAddress, TUint aLength)
       
    59     {
       
    60     TUint index;
       
    61     for( index = 0; index != aLength; ++index)
       
    62         {
       
    63         if( index % 16 == 0)
       
    64             {
       
    65             PrintToScreen(_L("\r\n0x%08x: "),aStartAddress + index);   
       
    66             }
       
    67             
       
    68         PrintToScreen(_L("%02x "), *(aStartAddress+index));
       
    69         
       
    70         }
       
    71     PrintToScreen(_L("\r\n\r\n"));
       
    72     }
       
    73 
       
    74 
       
    75 
       
    76 /******************************************************************************************************
       
    77 	Bit input Stream code
       
    78  *****************************************************************************************************/
       
    79 
       
    80 
       
    81 
       
    82 /** Construct a bit stream input object
       
    83 
       
    84 	Following construction the bit stream is ready for reading bits, but will
       
    85 	immediately call UnderflowL() as the input buffer is empty.
       
    86 */
       
    87 TBitInput::TBitInput()
       
    88     :iCount(0)
       
    89 	,iRemain(0)
       
    90 	{}
       
    91 
       
    92 /** Construct a bit stream input object over a buffer
       
    93 
       
    94 	Following construction the bit stream is ready for reading bits from
       
    95 	the specified buffer.
       
    96 
       
    97 	@param aPtr The address of the buffer containing the bit stream
       
    98 	@param aLength The length of the bitstream in bits
       
    99 	@param aOffset The bit offset from the start of the buffer to the bit stream (defaults to zero)
       
   100 */
       
   101 TBitInput::TBitInput(const TUint8* aPtr, TInt aLength, TInt aOffset)
       
   102 	{
       
   103 	Set(aPtr,aLength,aOffset);
       
   104 	}
       
   105 
       
   106 /** Set the memory buffer to use for input
       
   107 
       
   108 	Bits will be read from this buffer until it is empty, at which point
       
   109 	UnderflowL() will be called.
       
   110 	
       
   111 	@param aPtr The address of the buffer containing the bit stream
       
   112 	@param aLength The length of the bitstream in bits
       
   113 	@param aOffset The bit offset from the start of the buffer to the bit stream (defaults to zero)
       
   114 */
       
   115 void TBitInput::Set(const TUint8* aPtr, TInt aLength, TInt aOffset)
       
   116 	{
       
   117 	TUint p=(TUint)aPtr;
       
   118 	p+=aOffset>>3;			// nearest byte to the specified bit offset
       
   119 	aOffset&=7;				// bit offset within the byte
       
   120 	const TUint32* ptr=(const TUint32*)(p&~3);	// word containing this byte
       
   121 	aOffset+=(p&3)<<3;		// bit offset within the word
       
   122 	if (aLength==0)
       
   123 		iCount=0;
       
   124 	else
       
   125 		{
       
   126 		// read the first few bits of the stream
       
   127 		iBits=reverse(*ptr++)<<aOffset;
       
   128 		aOffset=32-aOffset;
       
   129 		aLength-=aOffset;
       
   130 		if (aLength<0)
       
   131 			aOffset+=aLength;
       
   132 		iCount=aOffset;
       
   133 		}
       
   134 	iRemain=aLength;
       
   135 	iPtr=ptr;
       
   136 	}
       
   137 
       
   138 //#define __HUFFMAN_MACHINE_CODED__
       
   139 
       
   140 #ifndef __HUFFMAN_MACHINE_CODED__
       
   141 /** Read a single bit from the input
       
   142 
       
   143 	Return the next bit in the input stream. This will call UnderflowL() if
       
   144 	there are no more bits available.
       
   145 
       
   146 	@return The next bit in the stream
       
   147 
       
   148 	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
       
   149 		to get more data
       
   150 */
       
   151 TUint TBitInput::ReadL()
       
   152 	{
       
   153 	TInt c=iCount;
       
   154 	TUint bits=iBits;
       
   155 	if (--c<0)
       
   156 		return ReadL(1);
       
   157 	iCount=c;
       
   158 	iBits=bits<<1;
       
   159 	return bits>>31;
       
   160 	}
       
   161 
       
   162 /** Read a multi-bit value from the input
       
   163 
       
   164 	Return the next few bits as an unsigned integer. The last bit read is
       
   165 	the least significant bit of the returned value, and the value is
       
   166 	zero extended to return a 32-bit result.
       
   167 
       
   168 	A read of zero bits will always reaturn zero.
       
   169 	
       
   170 	This will call UnderflowL() if there are not enough bits available.
       
   171 
       
   172 	@param aSize The number of bits to read
       
   173 
       
   174 	@return The bits read from the stream
       
   175 
       
   176 	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
       
   177 		to get more data
       
   178 */
       
   179 TUint TBitInput::ReadL(TInt aSize)
       
   180 	{
       
   181 	if (!aSize)
       
   182 		return 0;
       
   183 	TUint val=0;
       
   184 	TUint bits=iBits;
       
   185 	iCount-=aSize;
       
   186 	while (iCount<0)
       
   187 		{
       
   188 		// need more bits
       
   189 		val|=bits>>(32-(iCount+aSize))<<(-iCount);	// scrub low order bits
       
   190 
       
   191 		aSize=-iCount;	// bits still required
       
   192 		if (iRemain>0)
       
   193 			{
       
   194 			bits=reverse(*iPtr++);
       
   195 			iCount+=32;
       
   196 			iRemain-=32;
       
   197 			if (iRemain<0)
       
   198 				iCount+=iRemain;
       
   199 			}
       
   200 		else
       
   201 			{
       
   202 			UnderflowL();
       
   203 			bits=iBits;
       
   204 			iCount-=aSize;
       
   205 			}
       
   206 		}
       
   207 //#ifdef __CPU_X86
       
   208 	// X86 does not allow shift-by-32
       
   209 //	iBits=aSize==32?0:bits<<aSize;
       
   210 //#else
       
   211 	iBits=bits<<aSize;
       
   212 //#endif
       
   213 	return val|(bits>>(32-aSize));
       
   214 	}
       
   215 
       
   216 /** Read and decode a Huffman Code
       
   217 
       
   218 	Interpret the next bits in the input as a Huffman code in the specified
       
   219 	decoding. The decoding tree should be the output from Huffman::Decoding().
       
   220 
       
   221 	@param aTree The huffman decoding tree
       
   222 
       
   223 	@return The symbol that was decoded
       
   224 	
       
   225 	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
       
   226 		to get more data
       
   227 */
       
   228 TUint TBitInput::HuffmanL(const TUint32* aTree)
       
   229 	{
       
   230 	TUint huff=0;
       
   231 	do
       
   232 		{
       
   233 		aTree=PTRADD(TUint32,aTree,huff>>16);
       
   234 		huff=*aTree;
       
   235 		if (ReadL()==0)
       
   236 			huff<<=16;
       
   237 		} while ((huff&0x10000u)==0);
       
   238 	return huff>>17;
       
   239 	}
       
   240 
       
   241 #endif
       
   242 
       
   243 
       
   244 /** Handle an empty input buffer
       
   245 
       
   246 	This virtual function is called when the input buffer is empty and
       
   247 	more bits are required. It should reset the input buffer with more
       
   248 	data using Set().
       
   249 
       
   250 	A derived class can replace this to read the data from a file
       
   251 	(for example) before reseting the input buffer.
       
   252 
       
   253 	@leave KErrUnderflow The default implementation leaves
       
   254 */
       
   255 void TBitInput::UnderflowL()
       
   256 	{
       
   257 	
       
   258 	}
       
   259 
       
   260 
       
   261 
       
   262 /******************************************************************************************************
       
   263 	Huffman Code
       
   264  *****************************************************************************************************/
       
   265 
       
   266 TUint32* HuffmanSubTree(TUint32* aPtr,const TUint32* aValue,TUint32** aLevel)
       
   267 //
       
   268 // write the subtree below aPtr and return the head
       
   269 //
       
   270 	{
       
   271 	TUint32* l=*aLevel++;
       
   272 	if (l>aValue)
       
   273 		{
       
   274 		TUint32* sub0=HuffmanSubTree(aPtr,aValue,aLevel);	// 0-tree first
       
   275 		aPtr=HuffmanSubTree(sub0,aValue-(aPtr-sub0)-1,aLevel);			// 1-tree
       
   276 		TInt branch0=(TUint8*)sub0-(TUint8*)(aPtr-1);
       
   277 		*--aPtr=KBranch1|branch0;
       
   278 		}
       
   279 	else if (l==aValue)
       
   280 		{
       
   281 		TUint term0=*aValue--;						// 0-term
       
   282 		aPtr=HuffmanSubTree(aPtr,aValue,aLevel);			// 1-tree
       
   283 		*--aPtr=KBranch1|(term0>>16);
       
   284 		}
       
   285 	else	// l<iNext
       
   286 		{
       
   287 		TUint term0=*aValue--;						// 0-term
       
   288 		TUint term1=*aValue--;
       
   289 		*--aPtr=(term1>>16<<16)|(term0>>16);
       
   290 		}
       
   291 	return aPtr;
       
   292 	}
       
   293 
       
   294 
       
   295 
       
   296 /** Create a canonical Huffman decoding tree
       
   297 
       
   298 	This generates the huffman decoding tree used by TBitInput::HuffmanL() to read huffman
       
   299 	encoded data. The input is table of code lengths, as generated by Huffman::HuffmanL()
       
   300 	and must represent a valid huffman code.
       
   301 	
       
   302 	@param aHuffman The table of code lengths as generated by Huffman::HuffmanL()
       
   303 	@param aNumCodes The number of codes in the table
       
   304 	@param aDecodeTree The space for the decoding tree. This must be the same
       
   305 		size as the code-length table, and can safely be the same memory
       
   306 	@param  aSymbolBase the base value for the output 'symbols' from the decoding tree, by default
       
   307 		this is zero.
       
   308 
       
   309 	@panic "USER ???" If the provided code is not a valid Huffman coding
       
   310 
       
   311 	@see IsValid()
       
   312 	@see HuffmanL()
       
   313 */
       
   314 void Huffman::Decoding(const TUint32 aHuffman[],TInt aNumCodes,TUint32 aDecodeTree[],TInt aSymbolBase)
       
   315 	{
       
   316 #ifdef _DEBUG
       
   317 	if(!IsValid(aHuffman,aNumCodes))
       
   318 		{
       
   319 #ifdef __LED__
       
   320 		leds(0xBAD00006); 	
       
   321 #endif
       
   322 
       
   323 		}
       
   324 #endif
       
   325 	TInt counts[KMaxCodeLength];
       
   326 	memset1(counts, 0, (sizeof(TInt)*KMaxCodeLength));
       
   327 	
       
   328 	TInt codes=0;
       
   329 	TInt ii;
       
   330 	for (ii=0;ii<aNumCodes;++ii)
       
   331 		{
       
   332 		TInt len=aHuffman[ii];
       
   333 		aDecodeTree[ii]=len;
       
   334 		if (--len>=0)
       
   335 			{
       
   336 			++counts[len];
       
   337 			++codes;
       
   338 			}
       
   339 		}
       
   340 		
       
   341 	TUint32* level[KMaxCodeLength];
       
   342 
       
   343 	TUint32* lit=aDecodeTree+codes;
       
   344 	for (ii=0;ii<KMaxCodeLength;++ii)
       
   345 		{
       
   346 		level[ii]=lit;
       
   347 		lit-=counts[ii];
       
   348 		}
       
   349 	aSymbolBase=(aSymbolBase<<17)+(KHuffTerminate<<16);
       
   350 	for (ii=0;ii<aNumCodes;++ii)
       
   351 		{
       
   352 		TUint len=TUint8(aDecodeTree[ii]);
       
   353 		if (len)
       
   354 			*--level[len-1]|=(ii<<17)+aSymbolBase;
       
   355 		}
       
   356 	if (codes==1)	// codes==1 special case: incomplete tree
       
   357 		{
       
   358 		TUint term=aDecodeTree[0]>>16;
       
   359 		aDecodeTree[0]=term|(term<<16); // 0- and 1-terminate at root
       
   360 		}
       
   361 	else if (codes>1)
       
   362 		HuffmanSubTree(aDecodeTree+codes-1,aDecodeTree+codes-1,&level[0]);
       
   363 	}
       
   364 
       
   365 // The decoding tree for the externalised code
       
   366 const TUint32 HuffmanDecoding[]=
       
   367 	{
       
   368 	0x0004006c,
       
   369 	0x00040064,
       
   370 	0x0004005c,
       
   371 	0x00040050,
       
   372 	0x00040044,
       
   373 	0x0004003c,
       
   374 	0x00040034,
       
   375 	0x00040021,
       
   376 	0x00040023,
       
   377 	0x00040025,
       
   378 	0x00040027,
       
   379 	0x00040029,
       
   380 	0x00040014,
       
   381 	0x0004000c,
       
   382 	0x00040035,
       
   383 	0x00390037,
       
   384 	0x00330031,
       
   385 	0x0004002b,
       
   386 	0x002f002d,
       
   387 	0x001f001d,
       
   388 	0x001b0019,
       
   389 	0x00040013,
       
   390 	0x00170015,
       
   391 	0x0004000d,
       
   392 	0x0011000f,
       
   393 	0x000b0009,
       
   394 	0x00070003,
       
   395 	0x00050001
       
   396 	};
       
   397 
       
   398 /** Restore a canonical huffman encoding from a bit stream
       
   399 
       
   400 	The encoding must have been stored using Huffman::ExternalizeL(). The resulting
       
   401 	code-length table can be used to create an encoding table using Huffman::Encoding()
       
   402 	or a decoding tree using Huffman::Decoding().
       
   403 	
       
   404 	@param aInput The input stream with the encoding
       
   405 	@param aHuffman The internalized code-length table is placed here
       
   406 	@param aNumCodes The number of huffman codes in the table
       
   407 
       
   408 	@leave TBitInput::HuffmanL()
       
   409 
       
   410 	@see ExternalizeL()
       
   411 */
       
   412 void Huffman::InternalizeL(TBitInput& aInput,TUint32 aHuffman[],TInt aNumCodes)
       
   413 // See ExternalizeL for a description of the format
       
   414 	{
       
   415 
       
   416 	// initialise move-to-front list
       
   417 	TUint8 list[Huffman::KMetaCodes];
       
   418 	for (TInt i=0;i<Huffman::KMetaCodes;++i)	
       
   419 		list[i]=TUint8(i);
       
   420 
       
   421 	TInt last=0;
       
   422 	// extract codes, reverse rle-0 and mtf encoding in one pass
       
   423 	TUint32* p=aHuffman;
       
   424 	const TUint32* end=aHuffman+aNumCodes;
       
   425 	TInt rl=0;
       
   426 	while (p+rl<end)
       
   427 		{
       
   428 		TInt c=aInput.HuffmanL(HuffmanDecoding);
       
   429 		if (c<2)
       
   430 			{
       
   431 			// one of the zero codes used by RLE-0
       
   432 			// update he run-length
       
   433 			rl+=rl+c+1;
       
   434 			}
       
   435 		else
       
   436 			{
       
   437 			while (rl>0)
       
   438 				{
       
   439 				*p++=last;
       
   440 				--rl;
       
   441 				}
       
   442 			--c;
       
   443 			list[0]=TUint8(last);
       
   444 			last=list[c];
       
   445 			memcpy1(&list[1],&list[0],c);
       
   446 			*p++=last;
       
   447 			}
       
   448 		}
       
   449 	while (rl>0)
       
   450 		{
       
   451 		*p++=last;
       
   452 		--rl;
       
   453 		}
       
   454 	}
       
   455 
       
   456 
       
   457 
       
   458 
       
   459 /** Validate a Huffman encoding
       
   460 
       
   461 	This verifies that a Huffman coding described by the code lengths is valid.
       
   462 	In particular, it ensures that no code exceeds the maximum length and
       
   463 	that it is possible to generate a canonical coding for the specified lengths.
       
   464 	
       
   465 	@param aHuffman The table of code lengths as generated by Huffman::HuffmanL()
       
   466 	@param aNumCodes The number of codes in the table
       
   467 
       
   468 	@return True if the code is valid, otherwise false
       
   469 */
       
   470 TBool Huffman::IsValid(const TUint32 aHuffman[],TInt aNumCodes)
       
   471 	{
       
   472 	// The code is valid if one of the following holds:
       
   473 	// (a) the code exactly fills the 'code space'
       
   474 	// (b) there is only a single symbol with code length 1
       
   475 	// (c) there are no encoded symbols
       
   476 	//
       
   477 	TUint remain=1<<KMaxCodeLength;
       
   478 	TInt totlen=0;
       
   479 	for (const TUint32* p=aHuffman+aNumCodes; p>aHuffman;)
       
   480 		{
       
   481 		TInt len=*--p;
       
   482 		if (len>0)
       
   483 			{
       
   484 			totlen+=len;
       
   485 			if (len>KMaxCodeLength)
       
   486 				return 0;
       
   487 			TUint c=1<<(KMaxCodeLength-len);
       
   488 			if (c>remain)
       
   489 				return 0;
       
   490 			remain-=c;
       
   491 			}
       
   492 		}
       
   493 
       
   494 	return remain==0 || totlen<=1;
       
   495 	}
       
   496 
       
   497 
       
   498 
       
   499 TInt Inflater::Inflate(TBitInput& aBits, TUint8* aBuffer, TInt aSize)
       
   500 	{
       
   501 	TEncoding encoding;
       
   502 	TInt r = Init(aBits, encoding);
       
   503 	if (r==KErrNone)
       
   504 		r = DoInflate(aBits, encoding, aBuffer, aSize);
       
   505 	return r;
       
   506 	}
       
   507 
       
   508 TInt Inflater::Init(TBitInput& aBits, TEncoding& aEncoding)
       
   509 	{
       
   510 // read the encoding
       
   511 	Huffman::InternalizeL(aBits,aEncoding.iLitLen,KDeflationCodes);
       
   512 // validate the encoding
       
   513 	if (!Huffman::IsValid(aEncoding.iLitLen,TEncoding::ELitLens) ||
       
   514 		!Huffman::IsValid(aEncoding.iDistance,TEncoding::EDistances))
       
   515 		return KErrCorrupt;
       
   516 // convert the length tables into huffman decoding trees
       
   517 	Huffman::Decoding(aEncoding.iLitLen,TEncoding::ELitLens,aEncoding.iLitLen);
       
   518 	Huffman::Decoding(aEncoding.iDistance,TEncoding::EDistances,aEncoding.iDistance);
       
   519 	return KErrNone;
       
   520 	}
       
   521 
       
   522 
       
   523  
       
   524 TInt Inflater::DoInflate(TBitInput& aBits, TEncoding& aEncoding, TUint8* aBuffer, TInt aSize)
       
   525 	{
       
   526 	TUint8* out=aBuffer;
       
   527 	TUint8* const end=out+aSize;
       
   528 //
       
   529 	while (out<end)
       
   530 		{
       
   531 		// get a huffman code
       
   532 		TInt code=aBits.HuffmanL(aEncoding.iLitLen)-TEncoding::ELiterals;
       
   533 		if (code<0)
       
   534 			{
       
   535 			*out++=TUint8(code);
       
   536 			continue;			// another literal/length combo
       
   537 			}
       
   538 		if (code==TEncoding::EEos-TEncoding::ELiterals)
       
   539 			{	// eos marker. we're done
       
   540 			break;
       
   541 			}
       
   542 		// get the extra bits for the length code
       
   543 		if (code>=8)
       
   544 			{
       
   545 			TInt xtra=(code>>2)-1;
       
   546 			code-=xtra<<2;
       
   547 			code<<=xtra;
       
   548 			code|=aBits.ReadL(xtra);
       
   549 			}
       
   550 		TInt len=code+KDeflateMinLength;
       
   551 		// get the distance code
       
   552 		code=aBits.HuffmanL(aEncoding.iDistance);
       
   553 		if (code>=8)
       
   554 			{
       
   555 			TInt xtra=(code>>2)-1;
       
   556 			code-=xtra<<2;
       
   557 			code<<=xtra;
       
   558 			code|=aBits.ReadL(xtra);
       
   559 			}
       
   560 		TUint8* dptr = out-(code+1);
       
   561 		TInt wlen = MIN(end-out,len);
       
   562 		for(TInt i=0;i<wlen;i++)	//this byte by byte copy is required in stead of a memcpy as over lap required. memcopy does
       
   563 		    {
       
   564 		    *out++=*dptr++;			//not do much better as the length of copies are short ie over the 16 byte threshold    
       
   565 		    }
       
   566 			
       
   567 		};
       
   568 	return out-aBuffer;
       
   569 	}
       
   570 
       
   571 
       
   572 TFileInput::TFileInput(TInt aBlockLen, TInt aFileSize)
       
   573     :iReadBuf(iBuf1)
       
   574     ,iPtr(iBuf1,KBufSize)
       
   575     ,iBlockLen(aBlockLen)
       
   576     ,iFileSize(aFileSize)
       
   577     ,iImageReadProgress(0)
       
   578 	{
       
   579 	// Avoid buffer overrrun
       
   580 	if( aBlockLen > KBufSize)
       
   581 	    iBlockLen = KBufSize;
       
   582 	
       
   583 	// issue first read
       
   584 	iState=ReadInputData(iReadBuf,iBlockLen);
       
   585 	iImageReadProgress += iBlockLen;
       
   586 	}
       
   587 
       
   588 void TFileInput::Init()
       
   589     {
       
   590     Set(iReadBuf, iBlockLen*8);
       
   591     InitProgressBar(0,(TUint)iFileSize,_L("LOAD"));        
       
   592     }
       
   593 
       
   594 void TFileInput::UnderflowL()
       
   595 	{
       
   596 	TUint8* b=iReadBuf;
       
   597 	ASSERT(b!=NULL);
       
   598 	Set(b, iBlockLen*8);
       
   599 	
       
   600 	// start reading to the next buffer
       
   601 	b = iBuf1;
       
   602 	iState=ReadInputData(b,iBlockLen);
       
   603 	Set(b, iBlockLen*8);
       
   604 	iReadBuf=b;
       
   605 
       
   606 	// Update progress
       
   607 	iImageReadProgress += iBlockLen;
       
   608 	UpdateProgressBar(0,(TUint)iImageReadProgress);
       
   609 
       
   610 #ifdef __SUPPORT_FLASH_REPRO__	
       
   611 	NotifyDataAvailable(iImageReadProgress);
       
   612 #endif	
       
   613 	}
       
   614 
       
   615 
       
   616 void memcpy1(TAny* aTrg, const TAny* aSrc, unsigned int aLength)
       
   617 //
       
   618 // Copy from the aSrc to aTrg for aLength bytes.
       
   619 //
       
   620 	{
       
   621 	TInt aLen32=0;
       
   622 	TUint32* pT32=(TUint32*)aTrg;
       
   623 	const TUint32* pS32=(TUint32 *)aSrc;
       
   624 	TInt aLen8;
       
   625 	TUint32* pE32;
       
   626 	TUint8* pT;
       
   627     TUint8* pE;
       
   628     TUint8* pS;
       
   629 	
       
   630 	if (aLength==0)
       
   631 		return;//((TUint8*)aTrg);
       
   632 	
       
   633 	if (((TInt)pT32&3)==0 && ((TInt)pS32&3)==0)
       
   634 		aLen32=aLength>>2;
       
   635 	aLen8=aLength-(aLen32<<2);
       
   636 	pE32=pT32+aLen32;
       
   637 	if (aTrg<aSrc)
       
   638 		{
       
   639 		pS32=(TUint32*)aSrc;
       
   640 		while (pT32<pE32)
       
   641 			*pT32++=(*pS32++);
       
   642 		pT=(TUint8*)pT32;
       
   643 		pS=(TUint8*)pS32;
       
   644 		pE=(TUint8*)aTrg+aLength;
       
   645 		while (pT<pE)
       
   646 			*pT++=(*pS++);
       
   647 		}
       
   648 	else if (aTrg>aSrc)
       
   649 		{
       
   650 		pT=(TUint8*)(pT32+aLen32);
       
   651 		pE=pT+aLen8;
       
   652 		pS=(TUint8*)aSrc+aLength;
       
   653 		while (pE>pT)
       
   654 			*--pE=(*--pS);
       
   655 		pS32=(TUint32*)pS;
       
   656 		while (pE32>pT32)
       
   657 			*--pE32=(*--pS32);
       
   658 		}
       
   659 	}
       
   660 
       
   661 
       
   662 void memset1(void* aTrg, int aValue, unsigned int aLength)
       
   663 //
       
   664 // Fill memory with aLength aChars.
       
   665 //
       
   666 	{
       
   667 	TInt aLen32=0;
       
   668 	TUint32 *pM32=(TUint32 *)aTrg;
       
   669 	TUint32 *pE32;
       
   670 	TUint c;
       
   671 	TUint32 fillChar;
       
   672 	TInt aLen8;
       
   673 	TUint8 *pM;
       
   674 	TUint8 *pE;
       
   675 	
       
   676 	if (((TInt)aTrg&3)==0)
       
   677 		{
       
   678 		aLen32=aLength>>2;
       
   679 		pE32=pM32+aLen32;
       
   680 		c = aValue & 0xff;
       
   681 		fillChar=c+(c<<8)+(c<<16)+(c<<24);
       
   682 		while (pM32<pE32)
       
   683 			*pM32++=fillChar;
       
   684 		}
       
   685 	aLen8=aLength-(aLen32<<2);
       
   686 	pM=(TUint8 *)pM32;
       
   687 	pE=pM+aLen8;
       
   688 	while (pM<pE)
       
   689 		*pM++=(TUint8)(aValue);
       
   690 	}
       
   691 
       
   692 
       
   693 TInt memcmp1(const TUint8* aTrg, const TUint8* aSrc, TInt aLength)
       
   694 //
       
   695 // Compare aSrc with aTrg
       
   696 //
       
   697 	{
       
   698 	for (TInt n=0; n<aLength; n++)
       
   699 		{
       
   700 		if (aTrg[n] != aSrc[n])
       
   701 			return -1;
       
   702 		}
       
   703 	return 0;
       
   704 	}
       
   705 
       
   706 
       
   707 #ifdef SYMBIAN_CHECK_ROM_CHECKSUM
       
   708 TUint Check(const TUint32* aPtr, TInt aSize)
       
   709 	{
       
   710 	TUint sum=0;
       
   711 	aSize/=4;
       
   712 	while (aSize-->0)
       
   713 		sum+=*aPtr++;
       
   714 	return sum;
       
   715 	}
       
   716 
       
   717 TInt CheckRomChecksum(TRomHeader& aRomHeader)
       
   718 	{
       
   719 
       
   720 	TInt size = aRomHeader.iUnpagedUncompressedSize;
       
   721 	const TUint32* addr = (TUint32*) &aRomHeader;
       
   722 #ifdef _DEBUG_CORELDR_
       
   723 	PrintVal("ROM addr = ", (TUint32) addr);
       
   724 	PrintVal("ROM size = ", (TUint32) size);
       
   725 #endif
       
   726 
       
   727 	TUint checkSum = Check(addr, size);
       
   728 
       
   729 	// modify the checksum because ROMBUILD is broken...
       
   730 	checkSum -= (aRomHeader.iRomSize-size)/4; // adjust for missing 0xffffffff
       
   731 	checkSum -= aRomHeader.iCompressionType;
       
   732 	checkSum -= aRomHeader.iUnpagedCompressedSize;
       
   733 	checkSum -= aRomHeader.iUnpagedUncompressedSize;
       
   734 
       
   735 	TUint expectedChecksum = 0x12345678;
       
   736 #ifdef _DEBUG_CORELDR_
       
   737 	PrintVal("Checksum = ", checkSum);
       
   738 	PrintVal("expectedChecksum = ", expectedChecksum);
       
   739 #endif
       
   740 
       
   741 	return (checkSum==expectedChecksum)?0:-2;
       
   742 	}
       
   743 #endif 
       
   744 
       
   745 
       
   746 int DoDeflateDownload()
       
   747     {    
       
   748     // Read ROM Loader Header
       
   749     TInt r = KErrNone;
       
   750     TInt headerSize = TROM_LOADER_HEADER_SIZE;
       
   751     
       
   752     if(RomLoaderHeaderExists)
       
   753         {
       
   754         TUint8 romLoaderHeader[TROM_LOADER_HEADER_SIZE];
       
   755     	FileSize -= headerSize;
       
   756     	r = ReadInputData((TUint8*)&romLoaderHeader, headerSize);
       
   757     	if( KErrNone!=r)
       
   758     		{
       
   759     		PrintToScreen(_L("Unable to read loader header... (size:%d)\r\n"), headerSize);
       
   760     		BOOT_FAULT();    
       
   761     		}
       
   762         }
       
   763     
       
   764 	
       
   765 	// Read ROM Header
       
   766 	TRomHeader* romHeader;
       
   767 	romHeader = (TRomHeader*)DestinationAddress();
       
   768 	
       
   769 	headerSize = sizeof(TRomHeader);
       
   770 	r = ReadInputData((TUint8*)romHeader, headerSize);
       
   771 	if( KErrNone!=r)
       
   772 		{
       
   773         PrintToScreen(_L("Unable to read ROM header... (size:%d)\r\n"), headerSize);
       
   774 		BOOT_FAULT();
       
   775 		}
       
   776 		
       
   777 	DEBUG_PRINT((_L("headerSize       :%d\r\n"), headerSize));	
       
   778 	DEBUG_PRINT((_L("iRomHeaderSize   :0x%08x\r\n"), romHeader->iRomHeaderSize));
       
   779 	DEBUG_PRINT((_L("iDebugPort       :0x%08x\r\n"), romHeader->iDebugPort));
       
   780 	DEBUG_PRINT((_L("iVersion         :%d.%d %d\r\n"), romHeader->iVersion.iMajor, romHeader->iVersion.iMinor, romHeader->iVersion.iBuild));
       
   781 	DEBUG_PRINT((_L("iCompressionType :0x%08x\r\n"), romHeader->iCompressionType));
       
   782 	DEBUG_PRINT((_L("iCompressedSize  :0x%08x\r\n"), romHeader->iCompressedSize));
       
   783 	DEBUG_PRINT((_L("iUncompressedSize:0x%08x\r\n"), romHeader->iUncompressedSize));
       
   784 	
       
   785 	DEBUG_PRINT((_L("iCompressedUnpagedStart:0x%08x\r\n"), romHeader->iCompressedUnpagedStart));
       
   786 	DEBUG_PRINT((_L("iUnpagedCompressedSize:0x%08x\r\n"), romHeader->iUnpagedCompressedSize));
       
   787 	DEBUG_PRINT((_L("iUnpagedUncompressedSize:0x%08x\r\n"), romHeader->iUnpagedUncompressedSize));
       
   788 	
       
   789 	if( romHeader->iCompressionType != KUidCompressionDeflate )
       
   790 		{
       
   791 		PrintToScreen(_L("Not supported compression method:0x%08x\r\n"), romHeader->iCompressionType);
       
   792 	    BOOT_FAULT();   
       
   793     	}
       
   794 
       
   795     TUint8 * pScr = (TUint8 *)DestinationAddress();
       
   796 
       
   797     DEBUG_PRINT((_L("Load address:0x%08x.\r\n"), pScr));
       
   798 
       
   799     if( romHeader->iCompressedUnpagedStart > (TUint)headerSize )
       
   800     	{
       
   801        	// Copy uncompressed un-paged part (bootstrap + Page Index Table) to the proper place if it longer than the romHeader
       
   802     	TInt unpagedSize = (romHeader->iCompressedUnpagedStart - headerSize);
       
   803     	
       
   804        	DEBUG_PRINT((_L("Copy uncompressed un-paged part ...\r\n")));         
       
   805        	DEBUG_PRINT((_L("to   :0x%08x.\r\n"),((TUint8 *)DestinationAddress()+headerSize) ));
       
   806        	DEBUG_PRINT((_L("len  :0x%08x.\r\n"),unpagedSize ));
       
   807        	
       
   808    		r = ReadInputData(((TUint8 *)DestinationAddress()+headerSize), unpagedSize);
       
   809    	  	// Modify header size to include the un-paged part such that the inflate code will not need to be modified
       
   810        	headerSize = unpagedSize;
       
   811    		if( KErrNone!=r)
       
   812    			{
       
   813    			PrintToScreen(_L("uncompressed un-paged part... (size:%d)\r\n"), headerSize);
       
   814    			BOOT_FAULT();
       
   815    			}
       
   816        }
       
   817     
       
   818     pScr += (headerSize + romHeader->iUnpagedUncompressedSize);    
       
   819     DEBUG_PRINT((_L("Compressed image load address:0x%08x.\r\n"), pScr));
       
   820     
       
   821     FileSize = romHeader->iUnpagedCompressedSize;
       
   822     
       
   823 #ifdef __SUPPORT_FLASH_REPRO__
       
   824 	if (LoadToFlash)
       
   825 		ImageSize = ((romHeader->iUnpagedUncompressedSize | 0x3ff) + 1);  // Round it to 0x400 for flashing
       
   826 #endif
       
   827         
       
   828     ImageReadProgress=0;
       
   829     TInt block_size = Max(0x1000,FileSize>>8);
       
   830     
       
   831 	DEBUG_PRINT((_L("Compressed image loaded into the RAM for decompress.\r\n")));		
       
   832    
       
   833     pScr = (TUint8 *)DestinationAddress();
       
   834     pScr += (headerSize + romHeader->iUnpagedUncompressedSize);
       
   835     
       
   836     TFileInput image(block_size, FileSize);
       
   837     image.Init();
       
   838     
       
   839 #ifdef __SUPPORT_FLASH_REPRO__
       
   840 	if (LoadToFlash)
       
   841 		{
       
   842 
       
   843 		DEBUG_PRINT((_L("InitFlashWrite. ImageSize:%d (0x%08x).\r\n"), ImageSize, ImageSize));	
       
   844 
       
   845 		r=InitFlashWrite();
       
   846 		if (r!=KErrNone)
       
   847 			{
       
   848 			PrintToScreen(_L("FAULT due to InitFlashWrite return %d\r\n"), r);
       
   849 			BOOT_FAULT();
       
   850 			}
       
   851 		}
       
   852 #endif  // __SUPPORT_FLASH_REPRO__
       
   853     
       
   854     
       
   855 	DEBUG_PRINT((_L("(TUint8 *)(DestinationAddress() + headerSize):0x%08x, size:%d.\r\n"),(TUint8 *)(DestinationAddress() + headerSize), romHeader->iUnpagedUncompressedSize));
       
   856 
       
   857     
       
   858     TUint nChars = Inflater::Inflate(
       
   859         image,
       
   860         (TUint8 *)(DestinationAddress() + headerSize),
       
   861         romHeader->iUnpagedUncompressedSize
       
   862         );
       
   863     
       
   864     
       
   865     DEBUG_PRINT((_L("Decompressed %d bytes.\r\n"), nChars));	
       
   866 
       
   867 
       
   868     if( 0 > (TInt)nChars)
       
   869         {
       
   870         PrintToScreen(_L("Error in decompression, return code: %d.\r\n"), nChars);
       
   871         BOOT_FAULT();
       
   872         }
       
   873     
       
   874 #ifdef __SUPPORT_FLASH_REPRO__
       
   875 	if (LoadToFlash)
       
   876         {
       
   877 
       
   878 	    DEBUG_PRINT((_L("NotifyDataAvailable. ImageSize:%d (0x%08x).\r\n"), ImageSize, ImageSize));	
       
   879 	    
       
   880 		NotifyDataAvailable(ImageSize);
       
   881 
       
   882     	DEBUG_PRINT((_L("NotifyDownloadComplete.\r\n")));
       
   883 
       
   884     	NotifyDownloadComplete();
       
   885         }
       
   886 #else
       
   887 
       
   888 	DELAY(20000);
       
   889 
       
   890 #endif   //  __SUPPORT_FLASH_REPRO__
       
   891     
       
   892     return KErrNone;
       
   893     }
       
   894