|
1 /* |
|
2 * Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * @internalComponent * @released |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include <stdlib.h> |
|
21 #include <string.h> |
|
22 #include <ctype.h> |
|
23 #include <e32std.h> |
|
24 #include <e32std_private.h> |
|
25 #include <e32rom.h> |
|
26 #include <u32std.h> |
|
27 #include <e32uid.h> |
|
28 #include <f32file.h> |
|
29 |
|
30 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) |
|
31 #include <iomanip> |
|
32 #include <strstream> |
|
33 #else //!__MSVCDOTNET__ |
|
34 #include <iomanip.h> |
|
35 #endif //__MSVCDOTNET__ |
|
36 |
|
37 #ifdef _L |
|
38 #undef _L |
|
39 #endif |
|
40 |
|
41 #include "h_utl.h" |
|
42 #include "r_obey.h" |
|
43 #include "rofs.h" |
|
44 #include "e32image.h" |
|
45 #include "patchdataprocessor.h" |
|
46 |
|
47 extern TUint checkSum(const void* aPtr); |
|
48 |
|
49 extern ECompression gCompress; |
|
50 extern TUint gCompressionMethod; |
|
51 extern TInt gCodePagingOverride; |
|
52 extern TInt gDataPagingOverride; |
|
53 extern TInt gLogLevel; |
|
54 TBool gDriveImage=EFalse; // for drive image support. |
|
55 |
|
56 |
|
57 TInt TRomNode::Count=0; |
|
58 TRomNode* TRomNode::TheFirstNode = NULL; |
|
59 TRomNode* TRomNode::TheLastNode = NULL; |
|
60 |
|
61 // introduced for data drive files' attribute |
|
62 TUint8 TRomNode::sDefaultInitialAttr = (TUint8)KEntryAttReadOnly; |
|
63 |
|
64 struct SortableEntry |
|
65 { |
|
66 TRofsEntry* iEntry; |
|
67 TBool iIsDir; |
|
68 TUint16 iOffset; |
|
69 }; |
|
70 |
|
71 int compare(const void* l, const void* r) |
|
72 { |
|
73 const SortableEntry* left = (const SortableEntry*)l; |
|
74 const SortableEntry* right = (const SortableEntry*)r; |
|
75 if (left->iIsDir) |
|
76 { |
|
77 if (!right->iIsDir) |
|
78 return -1; // dir < file |
|
79 } |
|
80 else |
|
81 { |
|
82 if (right->iIsDir) |
|
83 return +1; // file > dir |
|
84 } |
|
85 |
|
86 // both the same type of entry, sort by name |
|
87 // must first convert to an 8 bit string |
|
88 // array and NULL terminate it. |
|
89 char temp1[500]; |
|
90 char temp2[500]; |
|
91 |
|
92 |
|
93 TInt i=0; |
|
94 for (i = 0; i < left->iEntry->iNameLength; i++) |
|
95 { |
|
96 temp1[i]=(char) left->iEntry->iName[i]; |
|
97 } |
|
98 temp1[i]=0; |
|
99 |
|
100 for (i = 0; i < right->iEntry->iNameLength; i++) |
|
101 { |
|
102 temp2[i]=(char) right->iEntry->iName[i]; |
|
103 } |
|
104 temp2[i]=0; |
|
105 |
|
106 return stricmp((const char*)&temp1[0], (const char*)&temp2[0]); |
|
107 } |
|
108 |
|
109 TRomNode::TRomNode(TText* aName, TRomBuilderEntry* aEntry) |
|
110 // |
|
111 // Constructor |
|
112 // |
|
113 : |
|
114 iNextNode(NULL), |
|
115 iParent(NULL), iSibling(0), iChild(0), iNextNodeForSameFile(0), |
|
116 iTotalDirectoryBlockSize(0), |
|
117 iTotalFileBlockSize(0), |
|
118 iImagePosition(0), |
|
119 iFileBlockPosition(0), |
|
120 iAtt(sDefaultInitialAttr), |
|
121 iAttExtra(0xFF), |
|
122 iHidden(EFalse), |
|
123 iEntry(aEntry), |
|
124 iFileStartOffset(0), |
|
125 iSize(0), |
|
126 iOverride(0), |
|
127 iFileUpdate(EFalse), |
|
128 iAlias(false) |
|
129 { |
|
130 iName = (TText*)NormaliseFileName((const char*)aName); |
|
131 iIdentifier=TRomNode::Count++; |
|
132 |
|
133 // Add this node to the flat linked list |
|
134 if( !TheFirstNode ) |
|
135 { |
|
136 TheFirstNode = this; |
|
137 } |
|
138 else |
|
139 { |
|
140 TheLastNode->iNextNode = this; |
|
141 } |
|
142 TheLastNode = this; |
|
143 |
|
144 if (iEntry) |
|
145 { |
|
146 iEntry->SetRomNode(this); |
|
147 } |
|
148 else |
|
149 { |
|
150 iAtt = (TUint8)KEntryAttDir; |
|
151 } |
|
152 } |
|
153 |
|
154 TRomNode::~TRomNode() |
|
155 { |
|
156 if (iEntry && !iAlias) |
|
157 { |
|
158 delete iEntry; |
|
159 } |
|
160 iEntry = 0; |
|
161 if(iName) |
|
162 free(iName); |
|
163 iName = 0; |
|
164 } |
|
165 |
|
166 TRomNode *TRomNode::FindInDirectory(TText *aName) |
|
167 // |
|
168 // Check if the TRomNode for aName exists in aDir, and if so, return it. |
|
169 // |
|
170 { |
|
171 |
|
172 TRomNode *entry=iChild; // first subdirectory or file |
|
173 while (entry) |
|
174 { |
|
175 if ((stricmp((const char *)aName, (const char *)entry->iName))==0) |
|
176 return entry; |
|
177 else |
|
178 entry=entry->iSibling; |
|
179 } |
|
180 return 0; |
|
181 } |
|
182 |
|
183 |
|
184 |
|
185 TInt indend = 0; |
|
186 |
|
187 void indendStructure(TInt i) |
|
188 { |
|
189 while(i > 0) |
|
190 { |
|
191 cout << " "; |
|
192 i--; |
|
193 } |
|
194 }; |
|
195 |
|
196 // displays the directory structure |
|
197 void TRomNode::DisplayStructure(ostream* aOut) |
|
198 { |
|
199 indendStructure(indend); |
|
200 *aOut << iName << "\n"; |
|
201 if (iChild) |
|
202 { |
|
203 indend++; |
|
204 iChild->DisplayStructure(aOut); |
|
205 indend--; |
|
206 } |
|
207 if (iSibling) |
|
208 iSibling->DisplayStructure(aOut); |
|
209 } |
|
210 |
|
211 |
|
212 void TRomNode::deleteTheFirstNode() |
|
213 { |
|
214 |
|
215 TheFirstNode = NULL; |
|
216 } |
|
217 |
|
218 |
|
219 void TRomNode::InitializeCount() |
|
220 { |
|
221 Count = 0; |
|
222 } |
|
223 void TRomNode::displayFlatList() |
|
224 { |
|
225 TRomNode* current = TheFirstNode; |
|
226 TInt i = 0; |
|
227 while(current) |
|
228 { |
|
229 i++; |
|
230 cout << "\n" << i <<": " << current->iName << endl; |
|
231 current = current->NextNode(); |
|
232 } |
|
233 |
|
234 } |
|
235 |
|
236 |
|
237 |
|
238 void TRomNode::AddFile(TRomNode* aChild) |
|
239 { |
|
240 if (iEntry) |
|
241 { |
|
242 Print(EError, "Adding subdirectory to a file!!!\n"); |
|
243 return; |
|
244 } |
|
245 Add(aChild); |
|
246 } |
|
247 |
|
248 TRomNode* TRomNode::NewSubDir(TText *aName) |
|
249 { |
|
250 if (iEntry) |
|
251 { |
|
252 Print(EError, "Adding subdirectory to a file!!!\n"); |
|
253 return 0; |
|
254 } |
|
255 |
|
256 TRomNode* node = new TRomNode(aName ); |
|
257 if (node==0) |
|
258 { |
|
259 Print(EError, "TRomNode::NewNode: Out of memory\n"); |
|
260 return 0; |
|
261 } |
|
262 node->iParent = this; |
|
263 Add(node); |
|
264 return node; |
|
265 } |
|
266 |
|
267 void TRomNode::Add(TRomNode* aChild) |
|
268 { |
|
269 if (iChild) // this node is a non-empty directory |
|
270 { |
|
271 TRomNode* dir = iChild; // find where to link in the new node |
|
272 while (dir->iSibling) |
|
273 dir = dir->iSibling; |
|
274 dir->iSibling = aChild; |
|
275 } |
|
276 else |
|
277 iChild = aChild; // else just set it up as the child of the dir |
|
278 aChild->iSibling = 0; |
|
279 aChild->iParent = this; |
|
280 } |
|
281 |
|
282 TInt TRomNode::SetAttExtra(TText *anAttWord, TRomBuilderEntry* aFile, enum EKeyword aKeyword) |
|
283 // |
|
284 // Set the file extra attribute byte from the letters passed |
|
285 // Note: The iAttExtra bits are inverted. '0' represent enabled |
|
286 // |
|
287 { |
|
288 iAttExtra=0xFF; |
|
289 if (anAttWord==0 || anAttWord[0]=='\0') |
|
290 return Print(EError, "Missing argument for keyword 'exattrib'.\n"); |
|
291 for (TText *letter=anAttWord;*letter!=0;letter++) |
|
292 { |
|
293 switch (*letter) |
|
294 { |
|
295 case 'u': |
|
296 iAttExtra |= (KEntryAttUnique >> 23); // '1' represents disabled in iAttExtra |
|
297 break; |
|
298 case 'U': |
|
299 iAttExtra &= ~(KEntryAttUnique >> 23); // '0' represent enabled in iAttExtra |
|
300 break; |
|
301 default: |
|
302 return Print(EError, "Unrecognised exattrib - '%c'.\n", *letter); |
|
303 break; |
|
304 } |
|
305 } |
|
306 |
|
307 if((~iAttExtra & (KEntryAttUnique >> 23))!=0) // If the unique file attribute is set |
|
308 { |
|
309 if(aKeyword==EKeywordFile || aKeyword==EKeywordData) // If the Keyword is File or Data |
|
310 { |
|
311 if(strlen(aFile->iFileName) > (KMaxFileName-KRofsMangleNameLength)) // check whether we have enough space to add the mangle tage |
|
312 return Print(EError, "Lengthy filename with unique attribute to name mangle.\n"); |
|
313 } |
|
314 else // for all other keywords |
|
315 return Print(EError, "exattrib field not allowed for entries except data and file.\n"); |
|
316 } |
|
317 return KErrNone; |
|
318 } |
|
319 |
|
320 |
|
321 TInt TRomNode::SetAtt(TText *anAttWord) |
|
322 // |
|
323 // Set the file attribute byte from the letters passed |
|
324 // |
|
325 { |
|
326 iAtt=0; |
|
327 if (anAttWord==0 || anAttWord[0]=='\0') |
|
328 return Print(EError, "Missing argument for keyword 'attrib'.\n"); |
|
329 for (TText *letter=anAttWord;*letter!=0;letter++) |
|
330 { |
|
331 switch (*letter) |
|
332 { |
|
333 case 'R': |
|
334 case 'w': |
|
335 iAtt |= KEntryAttReadOnly; |
|
336 break; |
|
337 case 'r': |
|
338 case 'W': |
|
339 iAtt &= ~KEntryAttReadOnly; |
|
340 break; |
|
341 case 'H': |
|
342 iAtt |= KEntryAttHidden; |
|
343 break; |
|
344 case 'h': |
|
345 iAtt &= ~KEntryAttHidden; |
|
346 break; |
|
347 case 'S': |
|
348 iAtt |= KEntryAttSystem; |
|
349 break; |
|
350 case 's': |
|
351 iAtt &= ~KEntryAttSystem; |
|
352 break; |
|
353 default: |
|
354 return Print(EError, "Unrecognised attrib - '%c'.\n", *letter); |
|
355 break; |
|
356 } |
|
357 } |
|
358 return KErrNone; |
|
359 } |
|
360 |
|
361 |
|
362 |
|
363 TInt TRomNode::CalculateEntrySize() const |
|
364 // Calculates the amount of ROM space required to hold |
|
365 // this entry. The return is the actual size of the TRofsEntry |
|
366 // structure, not rounded up |
|
367 { |
|
368 TInt requiredSizeBytes = KRofsEntryHeaderSize + NameLengthUnicode(); |
|
369 return requiredSizeBytes; |
|
370 } |
|
371 |
|
372 TInt TRomNode::CalculateDirectoryEntrySize( TInt& aDirectoryBlockSize, |
|
373 TInt& aFileBlockSize ) |
|
374 // Calculates the total size of the TRofsDir structure required |
|
375 // for this directory and the size of the files block. Traverses all the |
|
376 // children adding their entry sizes. The result is not rounded up. |
|
377 // |
|
378 // On return aDirectoryBlockSize is the number of bytes required for the |
|
379 // main directory structure. aFileBlockSize is the number of bytes |
|
380 // required to hold the list of files. |
|
381 // |
|
382 // Returns KErrNone on success |
|
383 { |
|
384 |
|
385 TInt offsetBytes=0; |
|
386 TInt padBytes=0; |
|
387 if( 0 == iTotalDirectoryBlockSize ) |
|
388 { |
|
389 // need to calculate by walking children |
|
390 if( !iChild ) |
|
391 { |
|
392 return Print(EError, "TRomNode structure corrupt\n"); |
|
393 } |
|
394 |
|
395 TInt dirBlockSize = KRofsDirHeaderSize; |
|
396 TInt fileBlockSize = 0; |
|
397 TInt fileCount=0; |
|
398 TInt dirCount=0; |
|
399 |
|
400 TRomNode* node = iChild; |
|
401 while (node) |
|
402 { |
|
403 TInt entrySize = node->CalculateEntrySize(); |
|
404 if( node->IsDirectory() ) |
|
405 { |
|
406 dirBlockSize += (4 - dirBlockSize) & 3; // pad to next word boundary |
|
407 dirBlockSize += entrySize; |
|
408 dirCount++; |
|
409 } |
|
410 else |
|
411 { |
|
412 fileBlockSize += (4 - fileBlockSize) & 3; // pad to next word boundary |
|
413 fileBlockSize += entrySize; |
|
414 fileCount++; |
|
415 } |
|
416 node = node->iSibling; |
|
417 } |
|
418 |
|
419 offsetBytes = ((fileCount + dirCount) * 2) + 4; //the +4 are the two offset counts, |
|
420 padBytes = offsetBytes % 4; |
|
421 |
|
422 iTotalDirectoryBlockSize = dirBlockSize; |
|
423 iTotalFileBlockSize = fileBlockSize; |
|
424 } |
|
425 |
|
426 aDirectoryBlockSize = iTotalDirectoryBlockSize + offsetBytes + padBytes; |
|
427 aFileBlockSize = iTotalFileBlockSize; |
|
428 return KErrNone; |
|
429 } |
|
430 |
|
431 /** |
|
432 Place the files and it's attributes (incase of executables) |
|
433 Called for both rofs and datadrive creation. |
|
434 |
|
435 @param aDest - Destination buffer. |
|
436 @param aOffset - offset value, used for rofs only. |
|
437 @param aMaxSize- Maximum size required for rofs. |
|
438 |
|
439 @return - Returns the number of bytes placed or a -ve error code. |
|
440 */ |
|
441 TInt TRomNode::PlaceFile( TUint8* &aDest, TUint aOffset, TUint aMaxSize, CBytePair *aBPE ) |
|
442 // |
|
443 // Place the file into the ROM image, making any necessary conversions |
|
444 // along the way. |
|
445 // |
|
446 // Returns the number of bytes placed or a -ve error code. |
|
447 { |
|
448 |
|
449 TInt size=0; |
|
450 |
|
451 // file hasn't been placed for drive image. |
|
452 if(gDriveImage) |
|
453 { |
|
454 size = iEntry->PlaceFile(aDest,aMaxSize,aBPE); |
|
455 iSize = size; |
|
456 } |
|
457 else |
|
458 { |
|
459 if (iEntry->iHidden) |
|
460 iFileStartOffset = KFileHidden; |
|
461 else |
|
462 { |
|
463 if (iEntry->iFileOffset==0) |
|
464 { |
|
465 // file hasn't been placed |
|
466 size = iEntry->PlaceFile( aDest, aMaxSize, aBPE ); |
|
467 if (size>=0) |
|
468 iEntry->iFileOffset = aOffset; |
|
469 } |
|
470 else { |
|
471 iFileStartOffset = (TInt)iEntry; |
|
472 } |
|
473 } |
|
474 } |
|
475 |
|
476 // Deal with any override attributes |
|
477 // (omit paging overrides as these are dealt with in TRomBuilderEntry::PlaceFile |
|
478 // and may also be legitimately specified for non-executable files in ROM) |
|
479 if( iOverride&~(KOverrideCodeUnpaged|KOverrideCodePaged|KOverrideDataUnpaged|KOverrideDataPaged) ) |
|
480 { |
|
481 E32ImageHeaderV* hdr = (E32ImageHeaderV*)aDest; |
|
482 |
|
483 TUint hdrfmt = hdr->HeaderFormat(); |
|
484 if (hdrfmt != KImageHdrFmt_V) |
|
485 { |
|
486 Print(EError,"%s: Can't load old format binary\n", iEntry->iFileName); |
|
487 return KErrNotSupported; |
|
488 } |
|
489 |
|
490 // First need to check that it's a real image header |
|
491 if( (TUint)size > sizeof(E32ImageHeader) ) |
|
492 { |
|
493 if( ((TInt)hdr->iSignature == 0x434f5045u) && ((TInt)hdr->iUid1 == KExecutableImageUidValue || (TInt)hdr->iUid1 == KDynamicLibraryUidValue) ) |
|
494 { |
|
495 // Should check the CRC as well here... |
|
496 // Something for later |
|
497 |
|
498 // Ok, it looks like an image header |
|
499 if( iOverride & KOverrideStack ) |
|
500 { |
|
501 hdr->iStackSize = iStackSize; |
|
502 } |
|
503 if( iOverride & KOverrideHeapMin ) |
|
504 { |
|
505 hdr->iHeapSizeMin = iHeapSizeMin; |
|
506 } |
|
507 if( iOverride & KOverrideHeapMax ) |
|
508 { |
|
509 hdr->iHeapSizeMax = iHeapSizeMax; |
|
510 } |
|
511 if( iOverride & KOverrideFixed ) |
|
512 { |
|
513 if( hdr->iFlags & KImageDll ) |
|
514 { |
|
515 Print(EError,"%s: Can't used FIXED keyword on a DLL\n", iEntry->iFileName); |
|
516 return KErrNotSupported; |
|
517 } |
|
518 hdr->iFlags |= KImageFixedAddressExe; |
|
519 } |
|
520 if( iOverride & (KOverrideUid1|KOverrideUid2|KOverrideUid3)) |
|
521 { |
|
522 if (iOverride & KOverrideUid1) |
|
523 { |
|
524 hdr->iUid1 = iUid1; |
|
525 } |
|
526 if (iOverride & KOverrideUid2) |
|
527 { |
|
528 hdr->iUid2 = iUid2; |
|
529 } |
|
530 if (iOverride & KOverrideUid3) |
|
531 { |
|
532 hdr->iUid3 = iUid3; |
|
533 } |
|
534 // Need to re-checksum the UIDs |
|
535 TUidType ut(TUidType(TUid::Uid(hdr->iUid1), TUid::Uid(hdr->iUid2), TUid::Uid(hdr->iUid3))); |
|
536 hdr->iUidChecksum = (checkSum(((TUint8*)&ut)+1)<<16)|checkSum(&ut); |
|
537 } |
|
538 if( iOverride & KOverridePriority ) |
|
539 { |
|
540 hdr->iProcessPriority = (TUint16)iPriority; |
|
541 } |
|
542 if( iOverride & KOverrideCapability ) |
|
543 { |
|
544 hdr->iS.iCaps = iCapability; |
|
545 } |
|
546 |
|
547 // Need to re-CRC the header |
|
548 hdr->iHeaderCrc = KImageCrcInitialiser; |
|
549 TUint32 crc = 0; |
|
550 TInt hdrsz = hdr->TotalSize(); |
|
551 HMem::Crc32(crc, hdr, hdrsz); |
|
552 hdr->iHeaderCrc = crc; |
|
553 } |
|
554 } |
|
555 } |
|
556 |
|
557 return size; |
|
558 } |
|
559 |
|
560 TInt TRomNode::CountFileAndDir(TInt& aFileCount, TInt& aDirCount) |
|
561 { |
|
562 // |
|
563 // Count the number of file and directory entries for this node |
|
564 // |
|
565 TRomNode* node = iChild; |
|
566 |
|
567 aFileCount=0; |
|
568 aDirCount=0; |
|
569 while( node ) |
|
570 { |
|
571 if( node->IsFile() ) |
|
572 { |
|
573 aFileCount++; |
|
574 } |
|
575 else |
|
576 { |
|
577 aDirCount++; |
|
578 } |
|
579 |
|
580 node = node->iSibling; |
|
581 } |
|
582 return KErrNone; |
|
583 } |
|
584 |
|
585 TInt TRomNode::Place( TUint8* aDestBase ) |
|
586 // |
|
587 // Writes this directory entry out to the image. |
|
588 // The image starts at aDestBase. |
|
589 // The position in the image must already have been set with SetImagePosition() |
|
590 // and SetFileBlockPosition(). |
|
591 // Returns KErrNone on success |
|
592 // |
|
593 { |
|
594 TUint8* dirBlockBase = aDestBase + iImagePosition; |
|
595 TUint8* fileBlockBase = aDestBase + iFileBlockPosition; |
|
596 |
|
597 TRofsDir* pDir = (TRofsDir*)dirBlockBase; |
|
598 pDir->iFirstEntryOffset = KRofsDirFirstEntryOffset; |
|
599 pDir->iFileBlockAddress = iFileBlockPosition; |
|
600 pDir->iFileBlockSize = iTotalFileBlockSize; |
|
601 pDir->iStructSize = (TUint16)iTotalDirectoryBlockSize; |
|
602 |
|
603 TRofsEntry* pDirEntry = &(pDir->iSubDir); |
|
604 TRofsEntry* pFileEntry = (TRofsEntry*)fileBlockBase; |
|
605 |
|
606 TInt dirCount; |
|
607 TInt fileCount; |
|
608 TInt index = 0; |
|
609 CountFileAndDir(fileCount, dirCount); |
|
610 |
|
611 SortableEntry* array = new SortableEntry[fileCount + dirCount]; |
|
612 TRomNode* node = iChild; |
|
613 |
|
614 while( node ) |
|
615 { |
|
616 TRofsEntry* entry; |
|
617 |
|
618 if( node->IsFile() ) |
|
619 { |
|
620 entry = pFileEntry; |
|
621 |
|
622 //Offset in 32bit words from start of file block |
|
623 array[index].iOffset = (TUint16) ((((TUint8*) entry) - fileBlockBase) >> 2); |
|
624 array[index].iIsDir = EFalse; |
|
625 } |
|
626 else |
|
627 { |
|
628 entry = pDirEntry; |
|
629 |
|
630 //Offset in 32bit words from start of directory block |
|
631 array[index].iOffset = (TUint16) ((((TUint8*) entry) - dirBlockBase) >> 2); |
|
632 array[index].iIsDir = ETrue; |
|
633 } |
|
634 array[index].iEntry = entry; |
|
635 index++; |
|
636 |
|
637 entry->iNameOffset = KRofsEntryNameOffset; |
|
638 entry->iAtt = node->iAtt; |
|
639 entry->iAttExtra = node->iAttExtra; |
|
640 |
|
641 TInt entryLen = KRofsEntryHeaderSize; |
|
642 entryLen += node->NameCpy( (char*)&entry->iName, entry->iNameLength ); |
|
643 entryLen += (4 - entryLen) & 3; // round up to nearest word |
|
644 entry->iStructSize = (TUint16)entryLen; |
|
645 |
|
646 |
|
647 if( node->IsFile() ) |
|
648 { |
|
649 // node is a file, entry points to the file |
|
650 // write an entry out into the file block |
|
651 pFileEntry->iFileAddress = node->iFileStartOffset; |
|
652 node->iAtt &= ~KEntryAttDir; |
|
653 pFileEntry->iFileSize = node->iEntry->RealFileSize(); |
|
654 memcpy(&pFileEntry->iUids[0], &node->iEntry->iUids[0], sizeof(pFileEntry->iUids)); |
|
655 pFileEntry = (TRofsEntry*)( (TUint8*)pFileEntry + entryLen ); |
|
656 } |
|
657 else |
|
658 { |
|
659 // node is a subdirectory, entry points to directory |
|
660 pDirEntry->iFileAddress = node->iImagePosition; |
|
661 node->iAtt |= KEntryAttDir; |
|
662 |
|
663 // the size is just the size of the directory block |
|
664 pDirEntry->iFileSize = node->iTotalDirectoryBlockSize; |
|
665 pDirEntry = (TRofsEntry*)( (TUint8*)pDirEntry + entryLen ); |
|
666 } |
|
667 |
|
668 node = node->iSibling; |
|
669 } |
|
670 |
|
671 qsort(array,fileCount + dirCount,sizeof(SortableEntry),&compare); |
|
672 |
|
673 //Now copy the contents of sorted array to the image |
|
674 TUint16* currentPtr = (TUint16*) (dirBlockBase + iTotalDirectoryBlockSize); |
|
675 |
|
676 *currentPtr=(TUint16)dirCount; |
|
677 currentPtr++; |
|
678 *currentPtr=(TUint16)fileCount; |
|
679 currentPtr++; |
|
680 |
|
681 for (index = 0; index < (fileCount + dirCount); index++) |
|
682 { |
|
683 *currentPtr = array[index].iOffset; |
|
684 currentPtr++; |
|
685 } |
|
686 delete[] array; |
|
687 return KErrNone; |
|
688 } |
|
689 |
|
690 |
|
691 |
|
692 void TRomNode::Remove(TRomNode* aChild) |
|
693 { |
|
694 if (iChild==0) |
|
695 { |
|
696 Print(EError, "Removing file from a file!!!\n"); |
|
697 return; |
|
698 } |
|
699 if (iChild==aChild) // first child in this directory |
|
700 { |
|
701 iChild = aChild->iSibling; |
|
702 aChild->iSibling = 0; |
|
703 if(iChild==0) |
|
704 { |
|
705 iParent->Remove(this); |
|
706 TRomNode * current = TheFirstNode; |
|
707 TRomNode * prev = current; |
|
708 while(current != this) |
|
709 { |
|
710 prev = current; |
|
711 current = current->NextNode(); |
|
712 } |
|
713 prev->SetNextNode(current->NextNode()); |
|
714 delete this; |
|
715 } |
|
716 return; |
|
717 } |
|
718 TRomNode* prev = iChild; |
|
719 while (prev->iSibling && prev->iSibling != aChild) |
|
720 prev = prev->iSibling; |
|
721 if (prev==0) |
|
722 { |
|
723 Print(EError, "Attempting to remove file not in this directory!!!\n"); |
|
724 return; |
|
725 } |
|
726 prev->iSibling = aChild->iSibling; |
|
727 aChild->iSibling = 0; |
|
728 } |
|
729 |
|
730 void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount) |
|
731 { |
|
732 TRomNode *current=iChild; |
|
733 while(current) |
|
734 { |
|
735 if (current->iChild) |
|
736 aDirCount++; |
|
737 else |
|
738 aFileCount++; |
|
739 current=current->iSibling; |
|
740 } |
|
741 } |
|
742 |
|
743 void TRomNode::Destroy() |
|
744 // |
|
745 // Follow the TRomNode tree, destroying it |
|
746 // |
|
747 { |
|
748 |
|
749 TRomNode *current = this; // root has no siblings |
|
750 while (current) |
|
751 { |
|
752 if (current->iChild) |
|
753 current->iChild->Destroy(); |
|
754 TRomNode* prev=current; |
|
755 current=current->iSibling; |
|
756 delete prev; |
|
757 prev = 0; |
|
758 } |
|
759 } |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 TInt TRomNode::NameCpy(char* aDest, TUint8& aUnicodeLength ) |
|
765 // |
|
766 // Safely copy a file name in the rom entry |
|
767 // Returns the number of bytes used. Write the length in unicode characters |
|
768 // into aUnicodeLength. |
|
769 // |
|
770 { |
|
771 |
|
772 if ((aDest==NULL) || (iName==NULL)) |
|
773 return 0; |
|
774 const unsigned char* pSourceByte = (const unsigned char*)iName; |
|
775 unsigned char* pTargetByte=(unsigned char*)aDest; |
|
776 for (;;) |
|
777 { |
|
778 const TUint sourceByte=*pSourceByte; |
|
779 if (sourceByte==0) |
|
780 { |
|
781 break; |
|
782 } |
|
783 if ((sourceByte&0x80)==0) |
|
784 { |
|
785 *pTargetByte=(unsigned char)sourceByte; |
|
786 ++pTargetByte; |
|
787 *pTargetByte=0; |
|
788 ++pTargetByte; |
|
789 ++pSourceByte; |
|
790 } |
|
791 else if ((sourceByte&0xe0)==0xc0) |
|
792 { |
|
793 ++pSourceByte; |
|
794 const TUint secondSourceByte=*pSourceByte; |
|
795 if ((secondSourceByte&0xc0)!=0x80) |
|
796 { |
|
797 Print(EError, "Bad UTF-8 '%s'", iName); |
|
798 exit(671); |
|
799 } |
|
800 *pTargetByte=(unsigned char)((secondSourceByte&0x3f)|((sourceByte&0x03)<<6)); |
|
801 ++pTargetByte; |
|
802 *pTargetByte=(unsigned char)((sourceByte>>2)&0x07); |
|
803 ++pTargetByte; |
|
804 ++pSourceByte; |
|
805 } |
|
806 else if ((sourceByte&0xf0)==0xe0) |
|
807 { |
|
808 ++pSourceByte; |
|
809 const TUint secondSourceByte=*pSourceByte; |
|
810 if ((secondSourceByte&0xc0)!=0x80) |
|
811 { |
|
812 Print(EError, "Bad UTF-8 '%s'", iName); |
|
813 exit(672); |
|
814 } |
|
815 ++pSourceByte; |
|
816 const TUint thirdSourceByte=*pSourceByte; |
|
817 if ((thirdSourceByte&0xc0)!=0x80) |
|
818 { |
|
819 Print(EError, "Bad UTF-8 '%s'", iName); |
|
820 exit(673); |
|
821 } |
|
822 *pTargetByte=(unsigned char)((thirdSourceByte&0x3f)|((secondSourceByte&0x03)<<6)); |
|
823 ++pTargetByte; |
|
824 *pTargetByte=(unsigned char)(((secondSourceByte>>2)&0x0f)|((sourceByte&0x0f)<<4)); |
|
825 ++pTargetByte; |
|
826 ++pSourceByte; |
|
827 } |
|
828 else |
|
829 { |
|
830 Print(EError, "Bad UTF-8 '%s'", iName); |
|
831 exit(674); |
|
832 } |
|
833 } |
|
834 const TInt numberOfBytesInTarget=(pTargetByte-(unsigned char*)aDest); // this number excludes the trailing null-terminator |
|
835 if (numberOfBytesInTarget%2!=0) |
|
836 { |
|
837 Print(EError, "Internal error"); |
|
838 exit(675); |
|
839 } |
|
840 aUnicodeLength = (TUint8)(numberOfBytesInTarget/2); // returns the length of aDest (in UTF-16 characters for Unicode, not bytes) |
|
841 return numberOfBytesInTarget; |
|
842 } |
|
843 |
|
844 |
|
845 TInt TRomNode::NameLengthUnicode() const |
|
846 // |
|
847 // Find the unicode lenght of the name |
|
848 // |
|
849 { |
|
850 |
|
851 if (iName==NULL) |
|
852 return 0; |
|
853 |
|
854 const unsigned char* pSourceByte = (const unsigned char*)iName; |
|
855 TInt len = 0; |
|
856 for (;;) |
|
857 { |
|
858 const TUint sourceByte=*pSourceByte; |
|
859 if (sourceByte==0) |
|
860 { |
|
861 break; |
|
862 } |
|
863 if ((sourceByte&0x80)==0) |
|
864 { |
|
865 len += 2; |
|
866 ++pSourceByte; |
|
867 } |
|
868 else if ((sourceByte&0xe0)==0xc0) |
|
869 { |
|
870 ++pSourceByte; |
|
871 const TUint secondSourceByte=*pSourceByte; |
|
872 if ((secondSourceByte&0xc0)!=0x80) |
|
873 { |
|
874 Print(EError, "Bad UTF-8 '%s'", iName); |
|
875 exit(671); |
|
876 } |
|
877 len += 2; |
|
878 ++pSourceByte; |
|
879 } |
|
880 else if ((sourceByte&0xf0)==0xe0) |
|
881 { |
|
882 ++pSourceByte; |
|
883 const TUint secondSourceByte=*pSourceByte; |
|
884 if ((secondSourceByte&0xc0)!=0x80) |
|
885 { |
|
886 Print(EError, "Bad UTF-8 '%s'", iName); |
|
887 exit(672); |
|
888 } |
|
889 ++pSourceByte; |
|
890 const TUint thirdSourceByte=*pSourceByte; |
|
891 if ((thirdSourceByte&0xc0)!=0x80) |
|
892 { |
|
893 Print(EError, "Bad UTF-8 '%s'", iName); |
|
894 exit(673); |
|
895 } |
|
896 len += 2; |
|
897 ++pSourceByte; |
|
898 } |
|
899 else |
|
900 { |
|
901 Print(EError, "Bad UTF-8 '%s'", iName); |
|
902 exit(674); |
|
903 } |
|
904 } |
|
905 return len; |
|
906 } |
|
907 |
|
908 |
|
909 void TRomNode::AddNodeForSameFile(TRomNode* aPreviousNode, TRomBuilderEntry* aFile) |
|
910 { |
|
911 // sanity checking |
|
912 if (iNextNodeForSameFile != 0 || iEntry != aFile || (aPreviousNode && aPreviousNode->iEntry != iEntry)) |
|
913 { |
|
914 Print(EError, "Adding Node for same file: TRomNode structure corrupted\n"); |
|
915 exit(666); |
|
916 } |
|
917 iNextNodeForSameFile = aPreviousNode; |
|
918 } |
|
919 |
|
920 |
|
921 |
|
922 |
|
923 |
|
924 //************************************** |
|
925 // TRomBuilderEntry |
|
926 //************************************** |
|
927 |
|
928 |
|
929 |
|
930 TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,TText *aName) |
|
931 // |
|
932 // Constructor |
|
933 // |
|
934 :iFirstDllDataEntry(0), iName(0),iFileName(0),iNext(0), iNextInArea(0), |
|
935 iExecutable(EFalse), iFileOffset(EFalse), iCompressEnabled(0), |
|
936 iHidden(0), iRomNode(0), iRealFileSize(0) |
|
937 { |
|
938 if (aFileName) |
|
939 iFileName = NormaliseFileName(aFileName); |
|
940 if (aName) |
|
941 iName = (TText*)NormaliseFileName((const char*)aName); |
|
942 memset(iUids,0 ,sizeof(TCheckedUid)); |
|
943 } |
|
944 |
|
945 TRomBuilderEntry::~TRomBuilderEntry() |
|
946 // |
|
947 // Destructor |
|
948 // |
|
949 { |
|
950 if(iFileName) |
|
951 { |
|
952 free(iFileName); |
|
953 } |
|
954 iFileName = 0; |
|
955 if(iName) |
|
956 { |
|
957 free(iName); |
|
958 } |
|
959 } |
|
960 |
|
961 void TRomBuilderEntry::SetRomNode(TRomNode* aNode) |
|
962 { |
|
963 aNode->AddNodeForSameFile(iRomNode, this); |
|
964 iRomNode = aNode; |
|
965 } |
|
966 |
|
967 |
|
968 TInt isNumber(TText *aString) |
|
969 { |
|
970 if (aString==NULL) |
|
971 return 0; |
|
972 if (strlen((char *)aString)==0) |
|
973 return 0; |
|
974 return isdigit(aString[0]); |
|
975 } |
|
976 |
|
977 TInt getNumber(TText *aStr) |
|
978 { |
|
979 TUint a; |
|
980 #ifdef __TOOLS2__ |
|
981 istringstream val((char *)aStr); |
|
982 #else |
|
983 istrstream val((char *)aStr,strlen((char *)aStr)); |
|
984 #endif |
|
985 |
|
986 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) |
|
987 val >> setbase(0); |
|
988 #endif //__MSVCDOTNET__ |
|
989 |
|
990 val >> a; |
|
991 return a; |
|
992 } |
|
993 |
|
994 |
|
995 TInt TRomBuilderEntry::PlaceFile( TUint8* &aDest,TUint aMaxSize, CBytePair *aBPE ) |
|
996 // |
|
997 // Place the file in ROM. Since we don't support compression yet all |
|
998 // we have to do is read the file into memory |
|
999 // compress it, if it isn't already compressed. |
|
1000 // |
|
1001 // Returns the number of bytes used, or -ve error code |
|
1002 { |
|
1003 TUint compression = 0; |
|
1004 TBool executable = iExecutable; |
|
1005 Print(ELog,"Reading file %s to image\n", iFileName ); |
|
1006 TUint32 size=HFile::GetLength((TText*)iFileName); |
|
1007 if (size==0) |
|
1008 Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",iFileName); |
|
1009 if (aDest == NULL) { |
|
1010 aMaxSize = size*2; |
|
1011 aMaxSize = (aMaxSize>0) ? aMaxSize : 2; |
|
1012 aDest = new TUint8[aMaxSize]; |
|
1013 } |
|
1014 |
|
1015 if (executable) |
|
1016 { |
|
1017 // indicate if the image will overflow without compression |
|
1018 TBool overflow; |
|
1019 if(size>aMaxSize) |
|
1020 overflow = ETrue; |
|
1021 else |
|
1022 overflow = EFalse; |
|
1023 |
|
1024 // try to compress this executable |
|
1025 E32ImageFile f(aBPE); |
|
1026 TInt r = f.Open(iFileName); |
|
1027 // is it really a valid E32ImageFile? |
|
1028 if (r != KErrNone) |
|
1029 { |
|
1030 Print(EWarning, "File '%s' is not a valid executable. Placing file as data.\n", iFileName); |
|
1031 executable = EFalse; |
|
1032 } |
|
1033 else |
|
1034 { |
|
1035 |
|
1036 if(iRomNode->iOverride & KOverrideDllData) |
|
1037 { |
|
1038 DllDataEntry *aDllEntry = iRomNode->iEntry->GetFirstDllDataEntry(); |
|
1039 TLinAddr* aExportTbl; |
|
1040 void *aLocation; |
|
1041 TUint aDataAddr; |
|
1042 char *aCodeSeg, *aDataSeg; |
|
1043 |
|
1044 aExportTbl = (TLinAddr*)((char*)f.iData + f.iOrigHdr->iExportDirOffset); |
|
1045 |
|
1046 // const data symbol may belong in the Code section. If the address lies within the Code or data section limits, |
|
1047 // get the corresponding location and update it.While considering the Data section limits |
|
1048 // don't include the Bss section, as it doesn't exist as yet in the image. |
|
1049 while( aDllEntry ){ |
|
1050 if(aDllEntry->iOrdinal != (TUint32)-1){ |
|
1051 if(aDllEntry->iOrdinal < 1 || aDllEntry->iOrdinal > (TUint)f.iOrigHdr->iExportDirCount){ |
|
1052 Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", aDllEntry->iOrdinal, iRomNode->iName); |
|
1053 aDllEntry = aDllEntry->NextDllDataEntry(); |
|
1054 continue; |
|
1055 } |
|
1056 |
|
1057 // Get the address of the data field via the export table. |
|
1058 aDataAddr = (TInt32)(aExportTbl[aDllEntry->iOrdinal - 1] + aDllEntry->iOffset); |
|
1059 if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){ |
|
1060 aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset); |
|
1061 aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase ); |
|
1062 memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize); |
|
1063 } |
|
1064 else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){ |
|
1065 aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset); |
|
1066 aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase ); |
|
1067 memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize); |
|
1068 } |
|
1069 else |
|
1070 { |
|
1071 Print(EWarning, "Patchdata failed as address pointed by ordinal %d of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName); |
|
1072 } |
|
1073 } |
|
1074 else if(aDllEntry->iDataAddress != (TLinAddr)-1){ |
|
1075 aDataAddr = aDllEntry->iDataAddress + aDllEntry->iOffset; |
|
1076 if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){ |
|
1077 aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset); |
|
1078 aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase ); |
|
1079 memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize); |
|
1080 } |
|
1081 else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){ |
|
1082 aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset); |
|
1083 aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase ); |
|
1084 memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize); |
|
1085 } |
|
1086 else |
|
1087 { |
|
1088 Print(EWarning, "Patchdata failed as address 0x%x of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName); |
|
1089 } |
|
1090 } |
|
1091 aDllEntry = aDllEntry->NextDllDataEntry(); |
|
1092 } |
|
1093 } |
|
1094 |
|
1095 compression = f.iHdr->CompressionType(); |
|
1096 Print(ELog,"Original file:'%s' is compressed by method:%08x\n", iFileName, compression); |
|
1097 |
|
1098 |
|
1099 TUint32 oldFileComp; |
|
1100 TUint32 newFileComp; |
|
1101 |
|
1102 if(compression) |
|
1103 { |
|
1104 // The E32 image in release directory is compressed |
|
1105 oldFileComp = compression; |
|
1106 } |
|
1107 else |
|
1108 { |
|
1109 // The E32 image in release directory is uncompressed |
|
1110 oldFileComp = 0; |
|
1111 } |
|
1112 |
|
1113 if( iCompressEnabled != ECompressionUnknown) |
|
1114 { |
|
1115 // The new state would be as stated in obey file, i.e. |
|
1116 // filecompress or fileuncompress |
|
1117 newFileComp = gCompressionMethod; |
|
1118 } |
|
1119 else if (gCompress != ECompressionUnknown) |
|
1120 { |
|
1121 // The new state would be as stated set globally |
|
1122 newFileComp = gCompressionMethod; |
|
1123 } |
|
1124 else |
|
1125 { |
|
1126 // When not known if compression is to be applied or not, |
|
1127 // set it same as that of the E32 image in release directory |
|
1128 newFileComp = oldFileComp; |
|
1129 } |
|
1130 |
|
1131 if(!gDriveImage) |
|
1132 { |
|
1133 // overide paging flags... |
|
1134 E32ImageHeaderV* h=f.iHdr; |
|
1135 if (iRomNode->iOverride & KOverrideCodePaged) |
|
1136 { |
|
1137 h->iFlags &= ~KImageCodeUnpaged; |
|
1138 h->iFlags |= KImageCodePaged; |
|
1139 } |
|
1140 if (iRomNode->iOverride & KOverrideCodeUnpaged) |
|
1141 { |
|
1142 h->iFlags |= KImageCodeUnpaged; |
|
1143 h->iFlags &= ~KImageCodePaged; |
|
1144 } |
|
1145 if (iRomNode->iOverride & KOverrideDataPaged) |
|
1146 { |
|
1147 h->iFlags &= ~KImageDataUnpaged; |
|
1148 h->iFlags |= KImageDataPaged; |
|
1149 } |
|
1150 if (iRomNode->iOverride & KOverrideDataUnpaged) |
|
1151 { |
|
1152 h->iFlags |= KImageDataUnpaged; |
|
1153 h->iFlags &= ~KImageDataPaged; |
|
1154 } |
|
1155 |
|
1156 // apply global paging override... |
|
1157 switch(gCodePagingOverride) |
|
1158 { |
|
1159 case EKernelConfigPagingPolicyNoPaging: |
|
1160 h->iFlags |= KImageCodeUnpaged; |
|
1161 h->iFlags &= ~KImageCodePaged; |
|
1162 break; |
|
1163 case EKernelConfigPagingPolicyAlwaysPage: |
|
1164 h->iFlags |= KImageCodePaged; |
|
1165 h->iFlags &= ~KImageCodeUnpaged; |
|
1166 break; |
|
1167 case EKernelConfigPagingPolicyDefaultUnpaged: |
|
1168 if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged))) |
|
1169 h->iFlags |= KImageCodeUnpaged; |
|
1170 break; |
|
1171 case EKernelConfigPagingPolicyDefaultPaged: |
|
1172 if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged))) |
|
1173 h->iFlags |= KImageCodePaged; |
|
1174 break; |
|
1175 } |
|
1176 switch(gDataPagingOverride) |
|
1177 { |
|
1178 case EKernelConfigPagingPolicyNoPaging: |
|
1179 h->iFlags |= KImageDataUnpaged; |
|
1180 h->iFlags &= ~KImageDataPaged; |
|
1181 break; |
|
1182 case EKernelConfigPagingPolicyAlwaysPage: |
|
1183 h->iFlags |= KImageDataPaged; |
|
1184 h->iFlags &= ~KImageDataUnpaged; |
|
1185 break; |
|
1186 case EKernelConfigPagingPolicyDefaultUnpaged: |
|
1187 if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged))) |
|
1188 h->iFlags |= KImageDataUnpaged; |
|
1189 break; |
|
1190 case EKernelConfigPagingPolicyDefaultPaged: |
|
1191 if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged))) |
|
1192 h->iFlags |= KImageDataPaged; |
|
1193 break; |
|
1194 } |
|
1195 f.UpdateHeaderCrc(); |
|
1196 |
|
1197 // make sure paged code has correct compression type... |
|
1198 if(h->iFlags&KImageCodePaged) |
|
1199 { |
|
1200 if(newFileComp!=0) |
|
1201 newFileComp = KUidCompressionBytePair; |
|
1202 } |
|
1203 } |
|
1204 |
|
1205 if ( oldFileComp != newFileComp ) |
|
1206 { |
|
1207 |
|
1208 if( newFileComp == 0) |
|
1209 { |
|
1210 Print(ELog,"Decompressing executable '%s'\n", iFileName); |
|
1211 f.iHdr->iCompressionType = 0; |
|
1212 } |
|
1213 else |
|
1214 { |
|
1215 Print(ELog,"Compressing executable '%s' with method:%08x\n", iFileName, newFileComp); |
|
1216 f.iHdr->iCompressionType = newFileComp; |
|
1217 } |
|
1218 f.UpdateHeaderCrc(); |
|
1219 if (overflow) |
|
1220 { |
|
1221 char * buffer = new char [size]; |
|
1222 // need to check if the compressed file will fit in the image |
|
1223 #if defined(__LINUX__) |
|
1224 ostrstream os((char*)aDest, aMaxSize, (ios::openmode)(ios::out+ios::binary)); |
|
1225 #elif defined(__TOOLS2__) && defined (_STLP_THREADS) |
|
1226 ostrstream os((char*)buffer, size,(ios::out+ios::binary)); |
|
1227 #elif defined( __TOOLS2__) |
|
1228 ostrstream os((char*)buffer, size,(ios::out+ios::binary)); |
|
1229 #else |
|
1230 ostrstream os( (char*)buffer, size, (ios::out+ios::binary)); |
|
1231 #endif |
|
1232 os << f; |
|
1233 TUint compressedSize = os.pcount(); |
|
1234 if (compressedSize <= aMaxSize) |
|
1235 overflow = EFalse; |
|
1236 delete[] buffer; |
|
1237 } |
|
1238 } |
|
1239 if (overflow) |
|
1240 { |
|
1241 Print(EError, "Can't fit '%s' in image\n", iFileName); |
|
1242 Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize); |
|
1243 exit(667); |
|
1244 } |
|
1245 #if defined(__TOOLS2__) && defined (_STLP_THREADS) |
|
1246 ostrstream os((char*)aDest, aMaxSize,(ios::out+ios::binary)); |
|
1247 #elif __TOOLS2__ |
|
1248 ostrstream os((char*)aDest, aMaxSize, (std::_Ios_Openmode)(ios::out+ios::binary)); |
|
1249 #else |
|
1250 ostrstream os((char*)aDest, aMaxSize, (ios::out+ios::binary)); |
|
1251 #endif |
|
1252 os << f; |
|
1253 size = os.pcount(); |
|
1254 compression = f.iHdr->CompressionType(); |
|
1255 memcpy(&iUids[0], aDest, sizeof(iUids)); |
|
1256 } |
|
1257 } |
|
1258 if (!executable) |
|
1259 { |
|
1260 if ( size > aMaxSize ) |
|
1261 { |
|
1262 Print(EError, "Can't fit '%s' in image\n", iFileName); |
|
1263 Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize); |
|
1264 exit(667); |
|
1265 } |
|
1266 size = HFile::Read((TText*)iFileName, (TAny *)aDest); |
|
1267 TUint32 Uidslen = (size > sizeof(iUids)) ? sizeof(iUids) : size; |
|
1268 memcpy(&iUids[0], aDest, Uidslen); |
|
1269 } |
|
1270 |
|
1271 if (compression) |
|
1272 Print(ELog,"Compressed executable File '%s' size: %08x, mode:%08x\n", iFileName, size, compression); |
|
1273 else if (iExecutable) |
|
1274 Print(ELog,"Executable File '%s' size: %08x\n", iFileName, size); |
|
1275 else |
|
1276 Print(ELog,"File '%s' size: %08x\n", iFileName, size); |
|
1277 iRealFileSize = size; // required later when directory is written |
|
1278 |
|
1279 return size; |
|
1280 } |
|
1281 |
|
1282 |
|
1283 TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable) |
|
1284 { |
|
1285 |
|
1286 if (iHidden && iChild==0) |
|
1287 { |
|
1288 // Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure) |
|
1289 if (iSibling) |
|
1290 return iSibling->CopyDirectory(aLastExecutable); |
|
1291 else |
|
1292 return 0; |
|
1293 } |
|
1294 |
|
1295 TRomNode* copy = new TRomNode(iName); |
|
1296 if(aLastExecutable==0) |
|
1297 aLastExecutable = copy; // this must be the root of the structure |
|
1298 // recursively copy the sub-structures |
|
1299 if (iChild) |
|
1300 copy->iChild = iChild->CopyDirectory(aLastExecutable); |
|
1301 if (iSibling) |
|
1302 copy->iSibling = iSibling->CopyDirectory(aLastExecutable); |
|
1303 copy->Clone(this); |
|
1304 return copy; |
|
1305 } |
|
1306 |
|
1307 |
|
1308 |
|
1309 |
|
1310 void TRomNode::Clone(TRomNode* aOriginal) |
|
1311 { |
|
1312 iAtt = aOriginal->iAtt; |
|
1313 iAttExtra = aOriginal->iAttExtra; |
|
1314 iEntry = aOriginal->iEntry; |
|
1315 iHidden = aOriginal->iHidden; |
|
1316 iFileStartOffset = aOriginal->iFileStartOffset; |
|
1317 iSize = aOriginal->iSize; |
|
1318 iParent = aOriginal->iParent; |
|
1319 iAlias = aOriginal->iAlias; |
|
1320 } |
|
1321 |
|
1322 |
|
1323 void TRomNode::Alias(TRomNode* aNode) |
|
1324 { |
|
1325 // sanity checking |
|
1326 if (aNode->iEntry == 0) |
|
1327 { |
|
1328 Print(EError, "Aliasing: TRomNode structure corrupted\n"); |
|
1329 exit(666); |
|
1330 } |
|
1331 Clone(aNode); |
|
1332 iEntry = aNode->iEntry; |
|
1333 if (iEntry) |
|
1334 { |
|
1335 iEntry->SetRomNode(this); |
|
1336 } |
|
1337 iAlias = true; |
|
1338 } |
|
1339 |
|
1340 |
|
1341 void TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, TText* aNewName) |
|
1342 { |
|
1343 aOldParent->Remove(this); |
|
1344 aNewParent->Add(this); |
|
1345 delete [] iName; |
|
1346 iName = new TText[strlen((const char *)aNewName)+1]; |
|
1347 strcpy ((char *)iName, (const char *)aNewName); |
|
1348 } |
|
1349 |
|
1350 TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const |
|
1351 { |
|
1352 TInt l = 0; |
|
1353 // aIgnoreHiddenAttrib is used to find the complete file name length as |
|
1354 // in ROM of a hidden file. |
|
1355 if (iParent && ( !iHidden || aIgnoreHiddenAttrib)) |
|
1356 l = iParent->FullNameLength() + 1; |
|
1357 l += strlen((const char*)iName); |
|
1358 return l; |
|
1359 } |
|
1360 |
|
1361 TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const |
|
1362 { |
|
1363 TInt l = 0; |
|
1364 TInt nl = strlen((const char*)iName); |
|
1365 // aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file. |
|
1366 if (iParent && ( !iHidden || aIgnoreHiddenAttrib)) |
|
1367 l = iParent->GetFullName(aBuf); |
|
1368 char* b = aBuf + l; |
|
1369 if (l) |
|
1370 *b++ = '\\', ++l; |
|
1371 memcpy(b, iName, nl); |
|
1372 b += nl; |
|
1373 *b = 0; |
|
1374 l += nl; |
|
1375 return l; |
|
1376 } |
|
1377 |
|
1378 // Fuction to return first node in the patchdata linked list |
|
1379 DllDataEntry *TRomBuilderEntry::GetFirstDllDataEntry() const |
|
1380 { |
|
1381 if (iFirstDllDataEntry) |
|
1382 { |
|
1383 return iFirstDllDataEntry; |
|
1384 } |
|
1385 else |
|
1386 { |
|
1387 return NULL; |
|
1388 } |
|
1389 } |
|
1390 |
|
1391 // Fuction to set first node in the patchdata linked list |
|
1392 void TRomBuilderEntry::SetFirstDllDataEntry(DllDataEntry *aDllDataEntry) |
|
1393 { |
|
1394 iFirstDllDataEntry = aDllDataEntry; |
|
1395 } |
|
1396 void TRomBuilderEntry::DisplaySize(TPrintType aWhere) |
|
1397 { |
|
1398 TBool aIgnoreHiddenAttrib = ETrue; |
|
1399 TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib); |
|
1400 char *aBuf = new char[aLen+1]; |
|
1401 if(gLogLevel & LOG_LEVEL_FILE_DETAILS) |
|
1402 { |
|
1403 iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib); |
|
1404 if(iFileName) |
|
1405 Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, RealFileSize(), (iRomNode->iHidden || iHidden)?"hidden":"", aBuf); |
|
1406 else |
|
1407 Print(aWhere, "%s\t%s\n", (iRomNode->iHidden || iHidden)?"hidden":"", aBuf); |
|
1408 } |
|
1409 else |
|
1410 { |
|
1411 if(iFileName) |
|
1412 Print(aWhere, "%s\t%d\n", iFileName, RealFileSize()); |
|
1413 } |
|
1414 |
|
1415 } |