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