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