0
|
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 |
|