|
1 /* |
|
2 * Copyright (c) 1996-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 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32std.h> |
|
20 #include <e32std_private.h> |
|
21 #include <e32uid.h> |
|
22 #include "h_utl.h" |
|
23 #include <string.h> |
|
24 #include <stdlib.h> |
|
25 |
|
26 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) |
|
27 #include <iomanip> |
|
28 #else //!__MSVCDOTNET__ |
|
29 #include <iomanip.h> |
|
30 #endif //__MSVCDOTNET__ |
|
31 |
|
32 #include "r_global.h" |
|
33 #include "r_obey.h" |
|
34 #include "r_rom.h" |
|
35 #include "r_dir.h" |
|
36 #include "patchdataprocessor.h" |
|
37 #include "memmap.h" |
|
38 #include "byte_pair.h" |
|
39 |
|
40 const TInt KSpareExports=16; |
|
41 extern TInt gThreadNum; |
|
42 extern char* gDepInfoFile; |
|
43 extern TBool gGenDepGraph; |
|
44 |
|
45 TUint32 DeflateCompressCheck(char *bytes,TInt size,ostream &os); |
|
46 void DeflateCompress(char *bytes,TInt size,ostream &os); |
|
47 void InflateUnCompress(unsigned char* source, int sourcesize,unsigned char* dest, int destsize); |
|
48 |
|
49 EntryQueue* LoadImageWorker::m_queue = NULL; |
|
50 TInt LoadImageWorker::m_errors = 0; |
|
51 TMemModel LoadImageWorker::m_memmodel; |
|
52 boost::mutex LoadImageWorker::m_mutex; |
|
53 LoadImageWorker::LoadImageWorker(EntryQueue* aQueue, TMemModel aMemModel) |
|
54 { |
|
55 m_queue = aQueue; |
|
56 m_memmodel = aMemModel; |
|
57 } |
|
58 void LoadImageWorker::operator()() |
|
59 { |
|
60 while(1) |
|
61 { |
|
62 m_mutex.lock(); |
|
63 if(m_queue->size() > 0) |
|
64 { |
|
65 TRomBuilderEntry * current = m_queue->front(); |
|
66 m_queue->pop(); |
|
67 m_mutex.unlock(); |
|
68 TInt err = current->OpenImageFile(); |
|
69 if(err) |
|
70 { |
|
71 m_mutex.lock(); |
|
72 ++m_errors; |
|
73 m_mutex.unlock(); |
|
74 continue; |
|
75 } |
|
76 if(current->iOverrideFlags&KOverrideAddress || current->iHdr->iFlags & KImageFixedAddressExe) |
|
77 { |
|
78 if(m_memmodel != E_MM_Multiple && m_memmodel != E_MM_Flexible && !current->IsDll()) |
|
79 current->iRomImageFlags |=KRomImageFlagFixedAddressExe; |
|
80 } |
|
81 if(gPagedRom) |
|
82 { |
|
83 if(current->iHdr->iFlags&KImageCodePaged) |
|
84 { |
|
85 current->iRomImageFlags&=~KRomImageFlagCodeUnpaged; |
|
86 current->iRomImageFlags|=KRomImageFlagCodePaged; |
|
87 } |
|
88 if(current->iHdr->iFlags&KImageCodeUnpaged) |
|
89 { |
|
90 current->iRomImageFlags|=KRomImageFlagCodeUnpaged; |
|
91 current->iRomImageFlags&=~KRomImageFlagCodePaged; |
|
92 } |
|
93 } |
|
94 if(current->iHdr->iFlags&KImageDataPaged) |
|
95 { |
|
96 current->iRomImageFlags&=~KRomImageFlagDataUnpaged; |
|
97 current->iRomImageFlags|=KRomImageFlagDataPaged; |
|
98 } |
|
99 if(current->iHdr->iFlags&KImageDataUnpaged) |
|
100 { |
|
101 current->iRomImageFlags|=KRomImageFlagDataUnpaged; |
|
102 current->iRomImageFlags&=~KRomImageFlagDataPaged; |
|
103 } |
|
104 if(current->iHdr->iFlags&KImageDebuggable) |
|
105 { |
|
106 current->iRomImageFlags|=KRomImageDebuggable; |
|
107 } |
|
108 else |
|
109 { |
|
110 current->iRomImageFlags&=~KRomImageDebuggable; |
|
111 } |
|
112 } |
|
113 else |
|
114 { |
|
115 m_mutex.unlock(); |
|
116 break; |
|
117 } |
|
118 } |
|
119 } |
|
120 E32Rom* CompressPageWorker::m_rom = NULL; |
|
121 TInt CompressPageWorker::m_nextpage = 0; |
|
122 TInt CompressPageWorker::m_totalpages = 0; |
|
123 TInt CompressPageWorker::m_pagesize = 0; |
|
124 boost::mutex CompressPageWorker::m_mutex; |
|
125 TInt CompressPageWorker::m_error = 0; |
|
126 CompressPageWorker::CompressPageWorker(E32Rom* aRom, TInt aPageSize, TInt aTotalPages, TInt aNextPage) |
|
127 { |
|
128 m_rom = aRom; |
|
129 m_pagesize = aPageSize; |
|
130 m_totalpages = aTotalPages; |
|
131 m_nextpage = aNextPage; |
|
132 } |
|
133 void CompressPageWorker::operator()() |
|
134 { |
|
135 SRomPageInfo* pPageBase = (SRomPageInfo*)((TInt)m_rom->iHeader + m_rom->iHeader->iRomPageIndex); |
|
136 CBytePair bpe(gFastCompress); |
|
137 while(1) |
|
138 { |
|
139 m_mutex.lock(); |
|
140 TInt currentPageIndex = m_nextpage++; |
|
141 m_mutex.unlock(); |
|
142 if(currentPageIndex < m_totalpages) |
|
143 { |
|
144 TInt inOffset = m_pagesize * currentPageIndex; |
|
145 TUint8 attrib = (TUint8)SRomPageInfo::EPageable; |
|
146 SRomPageInfo info ={ (TUint32)inOffset, (TUint16)m_pagesize, (TUint8)SRomPageInfo::EBytePair, attrib }; |
|
147 TUint8* in = (TUint8*) m_rom->iHeader + inOffset; |
|
148 TUint8* out = in; |
|
149 TInt outSize = BytePairCompress(out, in, m_pagesize, &bpe); |
|
150 if(outSize == KErrTooBig) |
|
151 { |
|
152 info.iCompressionType = SRomPageInfo::ENoCompression; |
|
153 memcpy(out, in, m_pagesize); |
|
154 outSize = m_pagesize; |
|
155 } |
|
156 if(outSize < 0 ) |
|
157 { |
|
158 m_mutex.lock(); |
|
159 m_error = outSize; |
|
160 m_mutex.unlock(); |
|
161 break; |
|
162 } |
|
163 info.iDataSize = (TUint16) outSize; |
|
164 *(pPageBase + currentPageIndex) = info; |
|
165 if((currentPageIndex & 255) == 255) |
|
166 { |
|
167 m_mutex.lock(); |
|
168 Print(EAlways, ".\n"); |
|
169 m_mutex.unlock(); |
|
170 } |
|
171 } |
|
172 else |
|
173 { |
|
174 break; |
|
175 } |
|
176 } |
|
177 } |
|
178 |
|
179 //////////////////////////////////////////////////////////////////////// |
|
180 |
|
181 TAddressRange::TAddressRange() |
|
182 : iImagePtr(0), iImageAddr(0), iRunAddr(0), iSize(0) |
|
183 { |
|
184 } |
|
185 |
|
186 void TAddressRange::Append(TAddressRange& aRange) |
|
187 { |
|
188 if(aRange.iSize) |
|
189 { |
|
190 aRange.iImagePtr = iImagePtr; |
|
191 aRange.iImageAddr = iImageAddr; |
|
192 aRange.iRunAddr = iRunAddr; |
|
193 Extend(aRange.iSize); |
|
194 } |
|
195 } |
|
196 |
|
197 void TAddressRange::Move(TInt aOffset) |
|
198 { |
|
199 iImagePtr = static_cast<char*>(iImagePtr) + aOffset; |
|
200 iImageAddr += aOffset; |
|
201 iRunAddr += aOffset; |
|
202 } |
|
203 |
|
204 void TAddressRange::Extend(TInt aOffset) |
|
205 { |
|
206 Move(aOffset); |
|
207 iSize += aOffset; |
|
208 } |
|
209 |
|
210 //////////////////////////////////////////////////////////////////////// |
|
211 |
|
212 inline TUint32 AlignData(TUint32 anAddr) |
|
213 { |
|
214 return ((anAddr+0x0f)&~0x0f); |
|
215 } |
|
216 |
|
217 TUint32 E32Rom::AlignToPage(TUint32 anAddr) |
|
218 { |
|
219 TUint a=(TUint)iObey->iPageSize-1; |
|
220 return ((anAddr+a)&~a); |
|
221 } |
|
222 |
|
223 /* |
|
224 Allocate virtual memory for static data in rom. |
|
225 @param aAddr Base address of last allocated memory. |
|
226 @param aSize Size of memory to allocate. |
|
227 @return Address allocated. This is below aAddr. |
|
228 */ |
|
229 TUint32 E32Rom::AllocVirtual(TUint32 aAddr,TUint aSize) |
|
230 { |
|
231 TInt align = iObey->iVirtualAllocSize; |
|
232 if(align<0) |
|
233 { |
|
234 align = -align; // get correct sign |
|
235 // -ve align means also align to next power-of-two >= aSize... |
|
236 while(aSize>(TUint)align) |
|
237 align <<=1; |
|
238 } |
|
239 |
|
240 TUint mask = (TUint)align-1; |
|
241 aSize = (aSize+mask)&~mask; // round up |
|
242 aAddr &= ~mask; // round down |
|
243 return aAddr-aSize; |
|
244 } |
|
245 |
|
246 TUint32 E32Rom::AlignToChunk(TUint32 anAddr) |
|
247 { |
|
248 TUint a=(TUint)iObey->iChunkSize-1; |
|
249 return ((anAddr+a)&~a); |
|
250 } |
|
251 |
|
252 COrderedFileList::COrderedFileList(TInt aMaxFiles) |
|
253 : iCount(0), iMaxFiles(aMaxFiles), iOrderedFiles(NULL) |
|
254 {} |
|
255 |
|
256 COrderedFileList::~COrderedFileList() |
|
257 { |
|
258 iCount=0; |
|
259 delete[] iOrderedFiles; |
|
260 } |
|
261 |
|
262 COrderedFileList* COrderedFileList::New(TInt aMaxFiles) |
|
263 { |
|
264 COrderedFileList *pL=new COrderedFileList(aMaxFiles); |
|
265 pL->iOrderedFiles=new TRomBuilderEntry*[aMaxFiles]; |
|
266 return pL; |
|
267 } |
|
268 |
|
269 void COrderedFileList::Add(TRomBuilderEntry* anEntry) |
|
270 { |
|
271 // note: this routine assumes that the set of kernel-mode files |
|
272 // (primary/extension/device) required by a given variant is linearly ordered by <= |
|
273 // e.g. can't have three variants {A,B,V1} {A,B,C,V2} {A,C,V3} because B and C |
|
274 // are unordered with respect to <=, since neither of |
|
275 // {n | Vn requires B} and {n | Vn requires C} is a subset of the other. |
|
276 // In a case like this, ROMBUILD may fail to resolve the addresses of some global data |
|
277 THardwareVariant& v=anEntry->iHardwareVariant; |
|
278 TInt i=0; |
|
279 while(i<iCount && v<=iOrderedFiles[i]->iHardwareVariant) i++; |
|
280 TInt j=iCount; |
|
281 while(j>i) |
|
282 { |
|
283 iOrderedFiles[j]=iOrderedFiles[j-1]; |
|
284 j--; |
|
285 } |
|
286 iOrderedFiles[i]=anEntry; |
|
287 iCount++; |
|
288 } |
|
289 |
|
290 void GetFileNameAndUid(char *aDllName, TUid &aDllUid, char *aExportName) |
|
291 { |
|
292 strcpy(aDllName, aExportName); |
|
293 aDllUid=KNullUid; |
|
294 TInt start; |
|
295 for (start=0; start<(TInt)strlen(aExportName) && aExportName[start]!='['; start++) |
|
296 ; |
|
297 if (start==(TInt)strlen(aExportName)) |
|
298 start=KErrNotFound; |
|
299 TInt end=strlen(aExportName)-1; |
|
300 while (end>=0) |
|
301 { |
|
302 if (aExportName[end]==']') |
|
303 break; |
|
304 --end; |
|
305 } |
|
306 if (end<0) |
|
307 end=KErrNotFound; |
|
308 |
|
309 if ((start!=KErrNotFound) && (end!=KErrNotFound) && (end>start)) |
|
310 { |
|
311 // Importing from DLL with Uid |
|
312 char uidStr[0x100]; |
|
313 strcpy(uidStr, "0x"); |
|
314 strncat(uidStr, aExportName+start+1, end-start-1); |
|
315 #ifdef __TOOLS2__ |
|
316 istringstream val(uidStr); |
|
317 #else |
|
318 istrstream val(uidStr,strlen(uidStr)); |
|
319 #endif |
|
320 |
|
321 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) |
|
322 val >> setbase(0); |
|
323 #endif //__MSVCDOTNET__ |
|
324 |
|
325 TUint32 u; |
|
326 val >> u; |
|
327 val.peek(); |
|
328 if (val.eof()) |
|
329 { |
|
330 aDllUid=TUid::Uid(u); |
|
331 char *dot=aExportName+strlen(aExportName)-1; |
|
332 while (dot>=aExportName) |
|
333 { |
|
334 if (*dot=='.') |
|
335 break; |
|
336 dot--; |
|
337 } |
|
338 if (dot<aExportName) // no dot |
|
339 aDllName[start]=0; |
|
340 else |
|
341 { |
|
342 aDllName[start]=0; |
|
343 strcat(aDllName, dot); |
|
344 } |
|
345 } |
|
346 } |
|
347 } |
|
348 |
|
349 E32Rom::E32Rom(CObeyFile *aObey) |
|
350 // |
|
351 // Constructor |
|
352 // |
|
353 { |
|
354 |
|
355 iSize=sizeof(TRomLoaderHeader)+aObey->iRomSize; |
|
356 iObey=aObey; |
|
357 iPeFiles=NULL; |
|
358 |
|
359 if(gLowMem) |
|
360 { |
|
361 iImageMap = new Memmap(); |
|
362 |
|
363 if(iImageMap == NULL) |
|
364 { |
|
365 iSize = 0; |
|
366 Print(EError, "Out of memory.\n"); |
|
367 } |
|
368 else |
|
369 { |
|
370 iImageMap->SetMaxMapSize(iSize); |
|
371 if(iImageMap->CreateMemoryMap(0, 0xff) == EFalse) |
|
372 { |
|
373 iSize = 0; |
|
374 Print(EError, "Failed to create image map object"); |
|
375 |
|
376 iImageMap->CloseMemoryMap(ETrue); |
|
377 delete iImageMap; |
|
378 iImageMap = NULL; |
|
379 } |
|
380 else |
|
381 { |
|
382 iData = iImageMap->GetMemoryMapPointer(); |
|
383 } |
|
384 } |
|
385 } |
|
386 else |
|
387 { |
|
388 iData=new char [iSize]; |
|
389 if (iData==NULL) |
|
390 { |
|
391 iSize=0; |
|
392 Print(EError, "Out of memory.\n"); |
|
393 } |
|
394 HMem::Set(iData, 0xff, iSize); |
|
395 } |
|
396 iHeader=(TRomHeader *)(iData+sizeof(TRomLoaderHeader)); |
|
397 iExtensionRomHeader=NULL; |
|
398 iLoaderHeader=(TRomLoaderHeader *)iData; |
|
399 iSectionPtr=(char *)iHeader+aObey->iSectionStart-aObey->iRomLinearBase+sizeof(TRomSectionHeader); |
|
400 TheRomHeader=(ImpTRomHeader *)iHeader; |
|
401 TheRomMem=(TUint32)iHeader; |
|
402 iNextDataChunkBase=aObey->iKernDataRunAddress; |
|
403 iTotalSvDataSize=0; |
|
404 iNextDllDataAddr=aObey->iDllDataTop; |
|
405 iPrevPrimaryAddress=NULL; |
|
406 iPrevVariantAddress=NULL; |
|
407 iVariantFileLists=NULL; |
|
408 iImportsFixedUp=0; |
|
409 iBranchesFixedUp=0; |
|
410 iVtableEntriesFixedUp=0; |
|
411 iOverhead=0; |
|
412 } |
|
413 |
|
414 E32Rom::~E32Rom() |
|
415 // |
|
416 // Destructor |
|
417 // |
|
418 { |
|
419 |
|
420 if(gLowMem) |
|
421 { |
|
422 iImageMap->CloseMemoryMap(ETrue); |
|
423 delete iImageMap; |
|
424 } |
|
425 else |
|
426 delete iData; |
|
427 delete [] iPeFiles; |
|
428 if (iVariantFileLists) |
|
429 { |
|
430 TInt i; |
|
431 for (i=0; i<iObey->iNumberOfVariants; i++) |
|
432 delete iVariantFileLists[i]; |
|
433 delete [] iVariantFileLists; |
|
434 } |
|
435 } |
|
436 |
|
437 TInt E32Rom::Align(TInt aVal) |
|
438 // |
|
439 // Align to romalign |
|
440 // |
|
441 { |
|
442 |
|
443 return ((aVal+iObey->iRomAlign-1)/iObey->iRomAlign)*iObey->iRomAlign; |
|
444 } |
|
445 |
|
446 TInt E32Rom::LoadContents(char*& anAddr, TRomHeader* aHeader) |
|
447 { |
|
448 // Load all the PE/E32Image files |
|
449 TInt nfiles=iObey->iNumberOfPeFiles; |
|
450 iPeFiles=new TRomBuilderEntry* [nfiles]; |
|
451 if (!iPeFiles) |
|
452 return Print(EError, "Out of memory.\n"); |
|
453 |
|
454 TInt r=TranslateFiles(); |
|
455 if (r!=KErrNone) |
|
456 return r; |
|
457 |
|
458 ProcessDllData(); |
|
459 |
|
460 EnumerateVariants(); |
|
461 |
|
462 r=BuildDependenceGraph(); |
|
463 if (r!=KErrNone) |
|
464 return r; |
|
465 |
|
466 // Update the ROM image headers with SMP information. |
|
467 SetSmpFlags(); |
|
468 |
|
469 r=ProcessDependencies(); |
|
470 if (r!=KErrNone) |
|
471 return r; |
|
472 |
|
473 char* addr = anAddr; |
|
474 TRomExceptionSearchTable* exceptionSearchTable = 0; |
|
475 |
|
476 if(gPagedRom) |
|
477 { |
|
478 gDepInfoFile = (char* )malloc(strlen((char *)iObey->iRomFileName) + 1); |
|
479 strcpy(gDepInfoFile, (char *)iObey->iRomFileName); |
|
480 iObey->SetArea().DefaultArea()->SortFilesForPagedRom(); |
|
481 // exception search table needs to go at start of ROM to make it not demand paged... |
|
482 addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable); |
|
483 } |
|
484 else if(gGenDepGraph) |
|
485 { |
|
486 Print(EWarning, "Not dependence information in an unpaged ROM."); |
|
487 } |
|
488 |
|
489 addr=WriteDirectory(addr, aHeader); |
|
490 // Aligned |
|
491 |
|
492 TRACE(TSCRATCH,Print(EAlways,"Directory written\n")); |
|
493 |
|
494 // Stick all the files in ROM |
|
495 |
|
496 TReloc* relocationTable; |
|
497 addr = AllocateRelocationTable(addr, relocationTable); |
|
498 aHeader->iRelocInfo = relocationTable ? ActualToRomAddress(relocationTable) : 0; |
|
499 // Aligned |
|
500 |
|
501 TRACE(TSCRATCH,Print(EAlways,"Done AllocateRelocationTable\n")); |
|
502 |
|
503 CalculateDataAddresses(); |
|
504 addr = LayoutRom(addr); |
|
505 |
|
506 TRACE(TSCRATCH,Print(EAlways,"Done LayoutRom\n")); |
|
507 |
|
508 FillInRelocationTable(relocationTable); |
|
509 |
|
510 TRACE(TSCRATCH,Print(EAlways,"Done FillInRelocationTable\n")); |
|
511 |
|
512 if(!exceptionSearchTable) |
|
513 addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable); |
|
514 ConstructRomExceptionSearchTable(exceptionSearchTable); |
|
515 |
|
516 TRACE(TSCRATCH,Print(EAlways,"Done ConstructRomExceptionSearchTable\n")); |
|
517 |
|
518 LinkKernelExtensions(iObey->iExtensions, iObey->iNumberOfExtensions); |
|
519 |
|
520 TRACE(TSCRATCH,Print(EAlways,"Done LinkKernelExtensions\n")); |
|
521 |
|
522 r=ResolveDllRefTables(); |
|
523 if (r!=KErrNone) |
|
524 return r; |
|
525 r=ResolveImports(); |
|
526 if (r!=KErrNone) |
|
527 return r; |
|
528 if (iObey->iCollapseMode>ECollapseNone) |
|
529 { |
|
530 r=CollapseImportThunks(); |
|
531 if (r!=KErrNone) |
|
532 return r; |
|
533 if (iObey->iCollapseMode>ECollapseImportThunksOnly) |
|
534 { |
|
535 r=CollapseBranches(); |
|
536 if (r!=KErrNone) |
|
537 return r; |
|
538 } |
|
539 Print(ELog,"%d imports, %d branches, %d vtable entries fixed up\n", |
|
540 iImportsFixedUp,iBranchesFixedUp,iVtableEntriesFixedUp); |
|
541 } |
|
542 |
|
543 iSizeUsed=(TInt)addr-(TInt)iHeader; |
|
544 Print(ELog, "\n%08x of %08x bytes used.\n", iSizeUsed, iSize-sizeof(TRomLoaderHeader)); |
|
545 |
|
546 // round the rom size in the header to a multiple of 1 Megabyte |
|
547 TInt rounded = ((iSizeUsed+0xfffff)&0xfff00000); |
|
548 if (rounded < iObey->iRomSize) |
|
549 iObey->iRomSize = rounded; |
|
550 iUncompressedSize = iSizeUsed; |
|
551 |
|
552 anAddr = addr; |
|
553 |
|
554 return KErrNone; |
|
555 } |
|
556 |
|
557 |
|
558 void E32Rom::CreatePageIndex(char*& aAddr) |
|
559 { |
|
560 iHeader->iRomPageIndex = 0; |
|
561 if(gPagedRom==0 || gEnableCompress==0) |
|
562 return; |
|
563 |
|
564 // Insert space for Rom Page Info table... |
|
565 iHeader->iRomPageIndex = (TInt)aAddr-(TInt)iHeader; |
|
566 TInt pageSize = iObey->iPageSize; |
|
567 TInt numPages = iSize/pageSize+1; |
|
568 TInt pageInfoSize = numPages*sizeof(SRomPageInfo); |
|
569 |
|
570 gPageIndexTableSize = pageInfoSize; // For accumulate uncompressed un-paged size added Page Index Table |
|
571 |
|
572 Print(ELog, "Inserting %d bytes for RomPageInfo at ROM offset 0x%08x\n", pageInfoSize, iHeader->iRomPageIndex); |
|
573 memset(aAddr,0,pageInfoSize); |
|
574 iOverhead += pageInfoSize; |
|
575 aAddr += pageInfoSize; |
|
576 } |
|
577 |
|
578 TInt E32Rom::SetupPages() |
|
579 { |
|
580 iHeader->iPageableRomStart = 0; |
|
581 iHeader->iPageableRomSize = 0; |
|
582 iHeader->iDemandPagingConfig = gDemandPagingConfig; |
|
583 |
|
584 if(!gPagedRom) |
|
585 return KErrNone; |
|
586 |
|
587 // Initialise the Rom Page Info for each page which indicates it is uncompressed... |
|
588 TInt pageSize = iObey->iPageSize; |
|
589 |
|
590 TInt pagedStartOffset = 0x7fffffff; |
|
591 TRomBuilderEntry* e = iObey->SetArea().DefaultArea()->iFirstPagedCode; |
|
592 if(e) |
|
593 { |
|
594 // we have paged code... |
|
595 pagedStartOffset = e->RomEntry()->iAddressLin-iObey->iRomLinearBase; |
|
596 pagedStartOffset = (pagedStartOffset+pageSize-1)&~(pageSize-1); // round up to next page; |
|
597 iHeader->iPageableRomStart = pagedStartOffset; |
|
598 TInt pageableSize = iSizeUsed-pagedStartOffset; |
|
599 if(pageableSize>0) |
|
600 iHeader->iPageableRomSize = pageableSize; |
|
601 } |
|
602 |
|
603 return KErrNone; |
|
604 } |
|
605 |
|
606 TInt E32Rom::CompressPages() |
|
607 { |
|
608 |
|
609 if(!gPagedRom || !gEnableCompress) |
|
610 return KErrNone; |
|
611 |
|
612 // Initialise the Rom Page Info for each page which indicates it is uncompressed... |
|
613 TInt pageSize = iObey->iPageSize; |
|
614 TInt numPages = (iSizeUsed+pageSize-1)/pageSize; |
|
615 |
|
616 TInt pagedStartOffset = iHeader->iPageableRomStart; |
|
617 |
|
618 Print(EAlways, "\nCompressing pages...\n"); |
|
619 TInt inOffset = 0; |
|
620 SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex); |
|
621 TInt currentIndex = 0; |
|
622 while(inOffset < pagedStartOffset) |
|
623 { |
|
624 |
|
625 TUint8 attrib = (TUint8)0; |
|
626 SRomPageInfo info = {(TUint32)inOffset,(TUint16)pageSize,(TUint8)SRomPageInfo::EBytePair,(TUint8)attrib}; |
|
627 info.iDataSize = (TUint16) pageSize; |
|
628 *pi++ = info; |
|
629 inOffset += pageSize; |
|
630 if((currentIndex & 255) == 255) |
|
631 Print(EAlways, ".\n"); |
|
632 currentIndex++; |
|
633 } |
|
634 CompressPageWorker compressworker(this, pageSize, numPages, currentIndex); |
|
635 |
|
636 boost::thread_group threads; |
|
637 for(int i = 0; i < gThreadNum; i++) |
|
638 { |
|
639 threads.create_thread(compressworker); |
|
640 } |
|
641 threads.join_all(); |
|
642 if(compressworker.m_error < 0) |
|
643 return compressworker.m_error; |
|
644 for(;currentIndex < numPages - 1; currentIndex++) |
|
645 { |
|
646 pi++; |
|
647 SRomPageInfo* prev = pi - 1; |
|
648 TUint8* dest = (TUint8*) iHeader + prev->iDataStart + prev->iDataSize; |
|
649 TUint8* src = (TUint8*) iHeader + pi->iDataStart; |
|
650 memcpy(dest, src, pi->iDataSize); |
|
651 pi->iDataStart = prev->iDataStart + prev->iDataSize; |
|
652 } |
|
653 TInt relSize = pi->iDataStart + pi->iDataSize; |
|
654 |
|
655 memset((TUint8*)iHeader + relSize, 0xff, iSizeUsed - relSize); |
|
656 TInt compression = (iSizeUsed >= 1000) ? (relSize*10)/(iSizeUsed/1000) : (relSize*10000)/iSizeUsed; |
|
657 Print(EAlways, "%d.%02d%%\n", compression/100, compression%100); |
|
658 iSizeUsed = relSize; |
|
659 return KErrNone; |
|
660 } |
|
661 |
|
662 TInt E32Rom::CompressPage(SRomPageInfo& aPageInfo, TInt aOutOffset, CBytePair * aBPE) |
|
663 { |
|
664 TUint8* in = (TUint8*)iHeader+aPageInfo.iDataStart; |
|
665 TInt inSize = aPageInfo.iDataSize; |
|
666 TUint8* out = (TUint8*)iHeader+aOutOffset; |
|
667 switch(aPageInfo.iCompressionType) |
|
668 { |
|
669 case SRomPageInfo::ENoCompression: |
|
670 memcpy(out,in,inSize); |
|
671 return inSize; |
|
672 |
|
673 case SRomPageInfo::EBytePair: |
|
674 { |
|
675 TInt r = BytePairCompress(out, in, inSize, aBPE); |
|
676 if(r!=KErrTooBig) |
|
677 return r; |
|
678 // data can't be compressed... |
|
679 aPageInfo.iCompressionType = SRomPageInfo::ENoCompression; |
|
680 memcpy(out,in,inSize); |
|
681 return inSize; |
|
682 } |
|
683 |
|
684 default: |
|
685 Print(EError, "Unsupported page compression type (%d)\n", aPageInfo.iCompressionType); |
|
686 return KErrNotSupported; |
|
687 } |
|
688 } |
|
689 |
|
690 |
|
691 // Avoid "warning" about constant expression |
|
692 static void checksize(const char* aTypeName, int aSize, int aCorrectSize) |
|
693 { |
|
694 if (aSize != aCorrectSize) |
|
695 Print(EError, "sizeof(%s) = %d, should be %d\n", aTypeName, aSize, aCorrectSize); |
|
696 } |
|
697 |
|
698 TInt E32Rom::CreateExtension(MRomImage* aKernelRom) |
|
699 { |
|
700 |
|
701 // sanity check |
|
702 checksize("TExtensionRomHeader", sizeof(TExtensionRomHeader), 128); |
|
703 |
|
704 char *addr=(char *)iHeader; |
|
705 iExtensionRomHeader=(TExtensionRomHeader*)addr; |
|
706 addr += sizeof(TExtensionRomHeader); |
|
707 // Aligned |
|
708 |
|
709 TRomHeader dummy; |
|
710 TInt r=LoadContents(addr, &dummy); |
|
711 if (r!=KErrNone) |
|
712 { |
|
713 Print(EError, "LoadContents failed - return code %d\n", r); |
|
714 return r; |
|
715 } |
|
716 iExtensionRomHeader->iRomRootDirectoryList = dummy.iRomRootDirectoryList; |
|
717 |
|
718 iLoaderHeader->SetUp(iObey); |
|
719 FinaliseExtensionHeader(aKernelRom); |
|
720 DisplayExtensionHeader(); |
|
721 |
|
722 return KErrNone; |
|
723 } |
|
724 |
|
725 TInt E32Rom::Create() |
|
726 { |
|
727 |
|
728 TVariantList::Setup(iObey); |
|
729 char *addr=(char *)iHeader; |
|
730 // Aligned |
|
731 |
|
732 // Put the bootstrap in rom - it contains a hole at offset 0x80 where the |
|
733 // TRomHeader information will be placed later |
|
734 |
|
735 gBootstrapSize = HFile::Read(iObey->iBootFileName, iHeader); |
|
736 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
737 Print(ELog, "bootstrapSize: 0x%08x, (%d)\n", gBootstrapSize, gBootstrapSize); |
|
738 |
|
739 if (gBootstrapSize==0) |
|
740 return Print(EError, "Cannot open the bootstrap file '%s'.\n", iObey->iBootFileName); |
|
741 gBootstrapSize=Align(gBootstrapSize); |
|
742 addr+=gBootstrapSize; |
|
743 iOverhead=gBootstrapSize; |
|
744 // Aligned |
|
745 |
|
746 CreatePageIndex(addr); |
|
747 |
|
748 TInt r=LoadContents(addr, iHeader); |
|
749 if (r!=KErrNone) |
|
750 { |
|
751 Print(EError, "LoadContents failed - return code %d\n", r); |
|
752 return r; |
|
753 } |
|
754 |
|
755 r = SetupPages(); // initialize ROM paging info... |
|
756 if(r!=KErrNone) |
|
757 { |
|
758 Print(EError, "Setup pages information failed - return code %d\n", r); |
|
759 return r; |
|
760 } |
|
761 |
|
762 r = CheckUnpagedMemSize(); // check for unpaged memory overflow |
|
763 if(r!=KErrNone) |
|
764 { |
|
765 return r; |
|
766 } |
|
767 |
|
768 r = CompressPages(); // setup ROM paging info... |
|
769 if(r!=KErrNone) |
|
770 { |
|
771 Print(EError, "CompressPages failed - return code %d\n", r); |
|
772 return r; |
|
773 } |
|
774 |
|
775 iLoaderHeader->SetUp(iObey); |
|
776 ImpTRomHeader* header = (ImpTRomHeader *)iHeader; |
|
777 header->SetUp(iObey); |
|
778 header->iTotalSvDataSize=iTotalSvDataSize; |
|
779 if (iObey->iMemModel==E_MM_Direct) |
|
780 { |
|
781 header->iUserDataAddress=iObey->iDataRunAddress; |
|
782 header->iTotalUserDataSize=iNextDataChunkBase-iObey->iDataRunAddress; |
|
783 } |
|
784 else |
|
785 { |
|
786 header->iUserDataAddress=iObey->iDllDataTop; |
|
787 header->iTotalUserDataSize=iObey->iDllDataTop-iNextDllDataAddr; |
|
788 } |
|
789 if (header->iRomSectionHeader) |
|
790 FinaliseSectionHeader(); // sorts out the second section checksum |
|
791 |
|
792 header->CheckSum(iObey->iCheckSum); // finally, sort out the overall checksum |
|
793 |
|
794 header->Display(); |
|
795 |
|
796 TUint testCheckSum = HMem::CheckSum((TUint *)iHeader, iHeader->iRomSize); |
|
797 Print(ELog, "Rom 32bit words sum to %08x\n", testCheckSum); |
|
798 if (testCheckSum != iObey->iCheckSum) |
|
799 return Print(EError, "Rom checksum is incorrect: %08x should be %08x\n", |
|
800 testCheckSum, iObey->iCheckSum); |
|
801 |
|
802 // 8bit checksum = sum of bytes |
|
803 // odd/even checksum = checksum of the odd and even halfwords of the image |
|
804 |
|
805 Print(ELog, "Rom 8bit checksum %08x\n", HMem::CheckSum8((TUint8 *)iHeader, iHeader->iRomSize)); |
|
806 Print(ELog, "Rom 8bit odd checksum %08x\n", HMem::CheckSumOdd8((TUint8 *)iHeader, iHeader->iRomSize)); |
|
807 Print(ELog, "Rom 8bit even checksum %08x\n", HMem::CheckSumEven8((TUint8 *)iHeader, iHeader->iRomSize)); |
|
808 |
|
809 if (iHeader->iPrimaryFile) |
|
810 { |
|
811 if (iObey->iKernelModel==ESingleKernel) |
|
812 { |
|
813 Print(ELog,"\nPrimary details (Single Kernel):\n"); |
|
814 TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader); |
|
815 TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader); |
|
816 Display(hdr); |
|
817 Print(ELog,"\n"); |
|
818 } |
|
819 else if (iObey->iKernelModel==EMultipleKernels) |
|
820 { |
|
821 Print(ELog,"\nPrimary details (Multiple Kernels):\n"); |
|
822 TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader); |
|
823 TInt n=1; |
|
824 FOREVER |
|
825 { |
|
826 Print(ELog,"\nKernel %d:\n",n); |
|
827 TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader); |
|
828 Display(hdr); |
|
829 Print(ELog,"\n"); |
|
830 if (!hdr->iNextExtension) |
|
831 break; |
|
832 r=(TRomEntry*)(hdr->iNextExtension-iObey->iRomLinearBase+(char*)iHeader); |
|
833 n++; |
|
834 } |
|
835 } |
|
836 } |
|
837 |
|
838 return KErrNone; |
|
839 } |
|
840 |
|
841 char *E32Rom::WriteDirectory(char *aAddr, TRomHeader* aHeader) |
|
842 // |
|
843 // Write the directory structure where appropriate |
|
844 // |
|
845 { |
|
846 |
|
847 TLinAddr dirptr=ActualToRomAddress(aAddr); |
|
848 if (iObey->iSectionPosition==-1) |
|
849 { |
|
850 // Just the one rom. Put the directory structure at aAddr |
|
851 iDirectorySize=WriteHeadersToRom(aAddr); |
|
852 aAddr+=Align(iDirectorySize); |
|
853 } |
|
854 else |
|
855 { |
|
856 // Put the directory structure in the second ROM, after the SectionHeader |
|
857 // and the second section information for first section files |
|
858 TInt size=0; |
|
859 TInt i; |
|
860 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
861 { |
|
862 TRomBuilderEntry *file=iPeFiles[i]; |
|
863 if (file->iRomSectionNumber!=0) |
|
864 break; |
|
865 TInt size1, size2; |
|
866 file->SizeInSections(size1,size2); |
|
867 size+=size2; |
|
868 } |
|
869 dirptr=ActualToRomAddress(iSectionPtr)+size; |
|
870 iDirectorySize=WriteHeadersToRom(RomToActualAddress(dirptr)); |
|
871 } |
|
872 aHeader->iRomRootDirectoryList=dirptr; |
|
873 return aAddr; |
|
874 } |
|
875 |
|
876 void E32Rom::Display(TRomImageHeader *aHdr) |
|
877 // |
|
878 // Print info on a file |
|
879 // |
|
880 { |
|
881 TRACE(TAREA, Print(ELog, "+Display header %08x\n", aHdr)); |
|
882 Print(ELog, "Uids: %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum); |
|
883 Print(ELog, "Entry point: %08x\n", aHdr->iEntryPoint); |
|
884 Print(ELog, "Code start addr: %08x\n", aHdr->iCodeAddress); |
|
885 Print(ELog, "Data start addr: %08x\n", aHdr->iDataAddress); |
|
886 Print(ELog, "DataBssLinearBase: %08x\n", aHdr->iDataBssLinearBase); |
|
887 Print(ELog, "Text size: %08x\n", aHdr->iTextSize); |
|
888 Print(ELog, "Code size: %08x\n", aHdr->iCodeSize); |
|
889 Print(ELog, "Data size: %08x\n", aHdr->iDataSize); |
|
890 Print(ELog, "BssSize: %08x\n", aHdr->iBssSize); |
|
891 Print(ELog, "Total data size: %08x\n", aHdr->iTotalDataSize); |
|
892 Print(ELog, "Heap min: %08x\n", aHdr->iHeapSizeMin); |
|
893 Print(ELog, "Heap max: %08x\n", aHdr->iHeapSizeMax); |
|
894 Print(ELog, "Stack size: %08x\n", aHdr->iStackSize); |
|
895 Print(ELog, "Dll ref table: %08x\n", aHdr->iDllRefTable); |
|
896 Print(ELog, "Export directory: %08x\n", aHdr->iExportDir); |
|
897 Print(ELog, "Export dir count: %08x\n", aHdr->iExportDirCount); |
|
898 Print(ELog, "Hardware variant: %08x\n", aHdr->iHardwareVariant); |
|
899 Print(ELog, "Flags: %08x\n", aHdr->iFlags); |
|
900 Print(ELog, "Secure ID: %08x\n", aHdr->iS.iSecureId); |
|
901 Print(ELog, "Vendor ID: %08x\n", aHdr->iS.iVendorId); |
|
902 Print(ELog, "Capability: %08x %08x\n", aHdr->iS.iCaps[1], aHdr->iS.iCaps[0]); |
|
903 Print(ELog, "Tools Version: %d.%02d(%d)\n", aHdr->iToolsVersion.iMajor, aHdr->iToolsVersion.iMinor, aHdr->iToolsVersion.iBuild); |
|
904 Print(ELog, "Module Version: %d.%d\n", aHdr->iModuleVersion>>16, aHdr->iModuleVersion&0x0000ffffu); |
|
905 Print(ELog, "Exception Descriptor: %08x\n", aHdr->iExceptionDescriptor); |
|
906 Print(ELog, "Priority: %d\n", aHdr->iPriority); |
|
907 } |
|
908 |
|
909 void E32Rom::DisplaySizes(TPrintType aWhere) |
|
910 { |
|
911 |
|
912 Print(aWhere, "Summary of file sizes in rom:\n"); |
|
913 Print(aWhere, "Overhead (bootstrap+gaps+sectioning)\t%d\n", iOverhead); |
|
914 Print(aWhere, "Overhead (directory size)\t%d\n", iDirectorySize); |
|
915 TRomBuilderEntry *file=iObey->FirstFile(); |
|
916 while (file) |
|
917 { |
|
918 file->DisplaySize(aWhere); |
|
919 file=iObey->NextFile(); |
|
920 } |
|
921 Print(aWhere, "\nTotal used\t%d\n", iSizeUsed); |
|
922 Print(aWhere, "Free\t%d\n", iObey->iRomSize-iSizeUsed); |
|
923 |
|
924 if (iObey->SetArea().Count() > 1) |
|
925 { |
|
926 Print(aWhere, "\nArea summary:\n"); |
|
927 for (NonDefaultAreasIterator it(iObey->SetArea()); |
|
928 ! it.IsDone(); |
|
929 it.GoToNext()) |
|
930 { |
|
931 const Area& a = it.Current(); |
|
932 Print(aWhere, "%s\t used: %d bytes / free: %d bytes\n", |
|
933 a.Name(), a.UsedSize(), a.MaxSize()-a.UsedSize()); |
|
934 } |
|
935 } |
|
936 } |
|
937 |
|
938 TInt E32Rom::RequiredSize() |
|
939 // |
|
940 // Get the (approximate) required size of the Rom |
|
941 // |
|
942 { |
|
943 |
|
944 TInt sum=0; |
|
945 TRomBuilderEntry *current=iObey->FirstFile(); |
|
946 while (current) |
|
947 { |
|
948 if (current->iResource || current->HCRDataFile()) |
|
949 sum+=Align(HFile::GetLength((TText*)current->iFileName)); |
|
950 else |
|
951 sum+=Align(current->SizeInRom()); |
|
952 current=iObey->NextFile(); |
|
953 } |
|
954 return sum+iOverhead+Align(iDirectorySize); |
|
955 } |
|
956 |
|
957 TInt E32Rom::TranslateFiles() |
|
958 // |
|
959 // Load and translate all PE/E32 image files |
|
960 // |
|
961 { |
|
962 |
|
963 TInt i=0; |
|
964 TInt total_errors = 0; |
|
965 TRomBuilderEntry* current = 0; |
|
966 EntryQueue imagesQueue; |
|
967 for (current = iObey->FirstFile(); current; current = iObey->NextFile() ) |
|
968 { |
|
969 if ((!current->iResource) && (!current->HCRDataFile())) |
|
970 { |
|
971 iPeFiles[i++]=current; |
|
972 imagesQueue.push(current); |
|
973 } |
|
974 } |
|
975 LoadImageWorker loadworker(&imagesQueue, iObey->iMemModel); |
|
976 boost::thread_group threads; |
|
977 for(int i = 0; i < gThreadNum; i++) |
|
978 { |
|
979 threads.create_thread(loadworker); |
|
980 } |
|
981 threads.join_all(); |
|
982 |
|
983 total_errors = loadworker.m_errors; |
|
984 if (total_errors) |
|
985 return KErrGeneral; |
|
986 for (current = iObey->FirstFile(); current; current = iObey->NextFile() ) |
|
987 { |
|
988 if ((!current->iResource) && (!current->HCRDataFile())) |
|
989 { |
|
990 TInt err = CheckForVersionConflicts(current); |
|
991 total_errors += err; |
|
992 } |
|
993 } |
|
994 return total_errors ? KErrGeneral : KErrNone; |
|
995 } |
|
996 |
|
997 const TText FileTypeFile[]= "File "; |
|
998 const TText FileTypePrimary[]= "Primary "; |
|
999 const TText FileTypeVariant[]= "Variant "; |
|
1000 const TText FileTypeExtension[]="Extension"; |
|
1001 const TText FileTypeDevice[]= "Device "; |
|
1002 |
|
1003 void E32Rom::EnumerateVariants() |
|
1004 { |
|
1005 TInt vIndex; |
|
1006 TInt nFiles=iObey->iNumberOfExtensions+iObey->iNumberOfDevices+3; |
|
1007 iVariantFileLists=new COrderedFileList*[iObey->iNumberOfVariants]; |
|
1008 for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++) |
|
1009 iVariantFileLists[vIndex]=COrderedFileList::New(nFiles); |
|
1010 for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++) |
|
1011 { |
|
1012 TRomBuilderEntry *variant=iObey->iVariants[vIndex]; |
|
1013 THardwareVariant& v=variant->iHardwareVariant; |
|
1014 TInt i; |
|
1015 for (i=0; i<iObey->iNumberOfPrimaries; i++) |
|
1016 { |
|
1017 TRomBuilderEntry *primary=iObey->iPrimaries[i]; |
|
1018 if (v<=primary->iHardwareVariant) |
|
1019 { |
|
1020 iVariantFileLists[vIndex]->Add(primary); |
|
1021 break; |
|
1022 } |
|
1023 } |
|
1024 iVariantFileLists[vIndex]->Add(variant); |
|
1025 for (i=0; i<iObey->iNumberOfExtensions; i++) |
|
1026 { |
|
1027 TRomBuilderEntry *ext=iObey->iExtensions[i]; |
|
1028 if (v<=ext->iHardwareVariant) |
|
1029 { |
|
1030 iVariantFileLists[vIndex]->Add(ext); |
|
1031 } |
|
1032 } |
|
1033 for (i=0; i<iObey->iNumberOfDevices; i++) |
|
1034 { |
|
1035 TRomBuilderEntry *dev=iObey->iDevices[i]; |
|
1036 if (v<=dev->iHardwareVariant) |
|
1037 { |
|
1038 iVariantFileLists[vIndex]->Add(dev); |
|
1039 } |
|
1040 } |
|
1041 } |
|
1042 TUint totalDataBss=0; |
|
1043 for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++) |
|
1044 { |
|
1045 TRomBuilderEntry *variant=iObey->iVariants[vIndex]; |
|
1046 THardwareVariant& v=variant->iHardwareVariant; |
|
1047 COrderedFileList& files=*iVariantFileLists[vIndex]; |
|
1048 TInt count=files.Count(); |
|
1049 Print(ELog,"\nVariant %08x, %d Files:\n",v.ReturnVariant(),count); |
|
1050 TInt i; |
|
1051 TUint dataOffset=0; |
|
1052 for (i=0; i<count; i++) |
|
1053 { |
|
1054 TRomBuilderEntry *pF=files[i]; |
|
1055 TUint gap=0; |
|
1056 if (pF->iDataAlignment>0) |
|
1057 { |
|
1058 gap=(pF->iDataAlignment-dataOffset)%(pF->iDataAlignment); |
|
1059 dataOffset+=gap; |
|
1060 } |
|
1061 E32ImageHeader *pH=pF->iHdr; |
|
1062 if (pF->iDataBssOffset!=0xffffffff && pF->iDataBssOffset!=dataOffset) |
|
1063 Print(EError,"Conflicting DataBss addresses\n"); |
|
1064 pF->iDataBssOffset=dataOffset; |
|
1065 TInt dataSize=AlignData(pH->iDataSize+pH->iBssSize); |
|
1066 const TText* pT=FileTypeFile; |
|
1067 if (pF->Primary()) |
|
1068 pT=FileTypePrimary; |
|
1069 if (pF->Variant()) |
|
1070 pT=FileTypeVariant; |
|
1071 if (pF->Extension()) |
|
1072 pT=FileTypeExtension; |
|
1073 if (pF->Device()) |
|
1074 pT=FileTypeDevice; |
|
1075 Print(ELog,"%s %12s[%08x] DataSize=%6x DataOffset=%6x",pT,pF->iName,pF->iHardwareVariant.ReturnVariant(),dataSize,dataOffset); |
|
1076 if (gap) |
|
1077 Print(ELog, " (gap %x for %x alignment)\n", gap, pF->iDataAlignment); |
|
1078 Print(ELog, "\n"); |
|
1079 dataOffset+=dataSize; |
|
1080 } |
|
1081 if (dataOffset>totalDataBss) |
|
1082 totalDataBss=dataOffset; |
|
1083 } |
|
1084 Print(ELog,"\nTotal SvData size=%6x\n",totalDataBss); |
|
1085 iTotalSvDataSize=totalDataBss; |
|
1086 } |
|
1087 |
|
1088 TInt E32Rom::LoadDataToRom(TRomBuilderEntry *aFile, TAddressRange& aAddress, CBytePair* aBPE) |
|
1089 // |
|
1090 // Load a data file to rom |
|
1091 // |
|
1092 { |
|
1093 const char* tn = "resource"; |
|
1094 if (aFile->iNonXIP) |
|
1095 tn = (aFile->iCompression) ? "compressed executable" : "uncompressed executable"; |
|
1096 Print(ELog,"Reading %s %s to rom linear address %08x\n", tn, aFile->iFileName, aAddress.iImageAddr); |
|
1097 |
|
1098 TUint32 size=HFile::GetLength((TText*)aFile->iFileName); |
|
1099 if (size==0) |
|
1100 { |
|
1101 Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",aFile->iFileName); |
|
1102 return size; |
|
1103 } |
|
1104 |
|
1105 aFile->iHeaderRange=aAddress; |
|
1106 char* addr = (char*)aFile->iHeaderRange.iImagePtr; |
|
1107 const char* src = NULL; |
|
1108 #ifdef __TOOLS2__ |
|
1109 ostringstream os; |
|
1110 #else |
|
1111 ostrstream os; |
|
1112 #endif |
|
1113 if (aFile->iNonXIP) |
|
1114 { |
|
1115 E32ImageFile f(aBPE); |
|
1116 TInt r = f.Open(aFile->iFileName); |
|
1117 // is it really a valid E32ImageFile? |
|
1118 if (r != KErrNone) |
|
1119 { |
|
1120 Print(EWarning, "File '%s' is not a valid executable. Loading file as data.\n", aFile->iFileName); |
|
1121 aFile->iNonXIP = EFalse; |
|
1122 } |
|
1123 else |
|
1124 { |
|
1125 TUint compression = f.iHdr->CompressionType(); |
|
1126 if (compression != aFile->iCompression || aFile->iPreferred) |
|
1127 { |
|
1128 if (compression == 0) |
|
1129 Print(ELog, "Compressing file %s\n", aFile->iFileName); |
|
1130 else if (aFile->iCompression == 0) |
|
1131 Print(ELog, "Decompressing file %s\n", aFile->iFileName); |
|
1132 f.iHdr->iCompressionType = aFile->iCompression; |
|
1133 if (aFile->iPreferred) |
|
1134 { |
|
1135 f.iHdr->iModuleVersion &= ~0xffffu; |
|
1136 f.iHdr->iModuleVersion |= 0x8000u; |
|
1137 } |
|
1138 f.UpdateHeaderCrc(); |
|
1139 } |
|
1140 Print(ELog, "Compression Method:0x%08x/0x%08x \n", f.iHdr->CompressionType(), aFile->iCompression); |
|
1141 os << f; |
|
1142 #ifdef __TOOLS2__ |
|
1143 size = (os.str()).length(); |
|
1144 src = (os.str()).c_str(); |
|
1145 #else |
|
1146 size = os.pcount(); |
|
1147 src = os.str(); |
|
1148 #endif |
|
1149 } |
|
1150 } |
|
1151 if (addr+size>iData+iSize) |
|
1152 { |
|
1153 Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName); |
|
1154 Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize); |
|
1155 exit(667); |
|
1156 } |
|
1157 if (src) |
|
1158 memcpy(addr, src, size); |
|
1159 else |
|
1160 size = HFile::Read((TText*)aFile->iFileName, (TAny *)addr); |
|
1161 Print(ELog,"Size: %08x\n", size); |
|
1162 |
|
1163 aFile->iHeaderRange.iSize=size; |
|
1164 aAddress.Extend(aFile->iHeaderRange.iSize); |
|
1165 return size; |
|
1166 } |
|
1167 |
|
1168 |
|
1169 void E32Rom::CalculateDataAddresses() |
|
1170 // |
|
1171 // |
|
1172 // |
|
1173 { |
|
1174 |
|
1175 TInt i; |
|
1176 TUint32 maxkern = 0; |
|
1177 Print(ELog, "\nCalculating kernel limit.\n"); |
|
1178 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1179 { |
|
1180 TRomBuilderEntry* e = iPeFiles[i]; |
|
1181 if (e->Primary()) |
|
1182 { |
|
1183 // this is a kernel |
|
1184 TUint32 stack = AlignToPage(e->iHdr->iStackSize); |
|
1185 TUint32 heap = AlignToPage(e->iHdr->iHeapSizeMax); |
|
1186 if (stack + heap > maxkern) |
|
1187 maxkern = stack + heap; |
|
1188 } |
|
1189 } |
|
1190 iObey->iKernelLimit = AlignToChunk(maxkern + iTotalSvDataSize) + iObey->iKernDataRunAddress; |
|
1191 if (iObey->iMemModel==E_MM_Direct) |
|
1192 iNextDataChunkBase=iObey->iDataRunAddress; |
|
1193 else |
|
1194 iNextDataChunkBase = iObey->iKernelLimit; |
|
1195 Print(ELog, "\nCalculating data addresses.\n"); |
|
1196 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1197 { |
|
1198 TRACE(TAREA,Print(ELog,"CalculateDataAddresses %d %s\n",i,iPeFiles[i]->iFileName)); |
|
1199 CalculateDataAddress(iPeFiles[i]); |
|
1200 } |
|
1201 TRACE(TIMPORT,Print(ELog,"CalculateDataAddresses complete\n")); |
|
1202 |
|
1203 // On moving model, advance kernel limit past fixed process data areas |
|
1204 if (iObey->iMemModel==E_MM_Moving) |
|
1205 iObey->iKernelLimit = iNextDataChunkBase; |
|
1206 } |
|
1207 |
|
1208 void E32Rom::CalculateDataAddress(TRomBuilderEntry *aFile) |
|
1209 // |
|
1210 // Work out where the .data/.bss will be |
|
1211 // |
|
1212 { |
|
1213 TUint32 dataBssSize=aFile->iRomNode->iRomFile->iTotalDataBss; |
|
1214 TUint32 dataRunAddr; |
|
1215 if (aFile->Primary()) |
|
1216 { |
|
1217 dataRunAddr = iObey->iKernDataRunAddress; |
|
1218 CPU = aFile->iHdr->CpuIdentifier(); |
|
1219 } |
|
1220 else |
|
1221 { |
|
1222 dataRunAddr = iObey->iDataRunAddress; |
|
1223 if (iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible && (aFile->iHdr->iFlags & KImageFixedAddressExe)) // propagate 'fixed' from PETRAN |
|
1224 { |
|
1225 dataRunAddr=0xffffffff; |
|
1226 } |
|
1227 } |
|
1228 if (aFile->iOverrideFlags&KOverrideAddress) |
|
1229 { |
|
1230 if ((iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible) || aFile->iRelocationAddress!=0xffffffff) |
|
1231 dataRunAddr=aFile->iRelocationAddress; |
|
1232 if (aFile->Extension() || aFile->Variant() || aFile->Device()) |
|
1233 Print(EError, "reloc not permitted with extension/variant/device\n"); |
|
1234 } |
|
1235 if (!aFile->IsDll() && !aFile->Primary() && (dataRunAddr==0xffffffff || iObey->iMemModel==E_MM_Direct)) |
|
1236 { |
|
1237 dataRunAddr=iNextDataChunkBase; |
|
1238 TInt stackreserve=iObey->iDefaultStackReserve; |
|
1239 if (aFile->iOverrideFlags & KOverrideStackReserve) |
|
1240 stackreserve=aFile->iStackReserve; |
|
1241 TInt datsize=AlignToChunk(dataBssSize+stackreserve); |
|
1242 // Move target data address to next free chunk |
|
1243 iNextDataChunkBase+=datsize; |
|
1244 } |
|
1245 if (aFile->Extension() || aFile->Device() || aFile->Variant()) |
|
1246 { |
|
1247 dataRunAddr=iObey->iKernDataRunAddress+aFile->iDataBssOffset; |
|
1248 } |
|
1249 else if (aFile->IsDll() && dataBssSize!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe<0) |
|
1250 { |
|
1251 iNextDllDataAddr = AllocVirtual(iNextDllDataAddr,dataBssSize); |
|
1252 dataRunAddr=iNextDllDataAddr; |
|
1253 } |
|
1254 if (iObey->iMemModel==E_MM_Moving && dataRunAddr==iObey->iDataRunAddress && aFile->Secondary()) |
|
1255 { |
|
1256 Print(EWarning,"Secondary not fixed\n"); |
|
1257 } |
|
1258 |
|
1259 TRACE(TAREA, Print(ELog, "Data run address %08x\n", dataRunAddr)); |
|
1260 aFile->iDataBssLinearBase=dataRunAddr; |
|
1261 } |
|
1262 |
|
1263 void E32Rom::LoadFileToRom(TRomBuilderEntry *aFile) |
|
1264 // |
|
1265 // Load an E32Image/PE file to rom |
|
1266 // |
|
1267 { |
|
1268 |
|
1269 char* addr = (char*)aFile->iHeaderRange.iImagePtr; |
|
1270 TRACE(TAREA, Print(ELog,"+LoadFileToRom addr %08x %08x %08x\n", addr, |
|
1271 aFile->iHeaderRange.iImageAddr, aFile->iHeaderRange.iRunAddr)); |
|
1272 |
|
1273 if (addr+aFile->SizeInRom()>iData+iSize) // check this |
|
1274 { |
|
1275 Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName); |
|
1276 Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize); |
|
1277 exit(666); |
|
1278 } |
|
1279 |
|
1280 // check file will not overflow into next ROM |
|
1281 if (aFile->Primary()) |
|
1282 { |
|
1283 if (!iPrevPrimaryAddress) |
|
1284 iHeader->iPrimaryFile=ActualToRomAddress(aFile->RomEntry()); |
|
1285 else if (iObey->iKernelModel==EMultipleKernels) |
|
1286 { |
|
1287 ((TRomImageHeader*)iPrevPrimaryAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry()); |
|
1288 } |
|
1289 iPrevPrimaryAddress=addr; |
|
1290 TRACE(TAREA, Print(ELog, "iHeader->iPrimaryFile = %08x\n", iHeader->iPrimaryFile)); |
|
1291 } |
|
1292 |
|
1293 // Place the file in rom |
|
1294 if (aFile->Variant()) |
|
1295 { |
|
1296 if (iPrevVariantAddress) |
|
1297 ((TRomImageHeader*)iPrevVariantAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry()); |
|
1298 else |
|
1299 iHeader->iVariantFile=ActualToRomAddress(aFile->RomEntry()); |
|
1300 iPrevVariantAddress=addr; |
|
1301 } |
|
1302 if (aFile->IsDll() && aFile->iRomNode->iRomFile->iTotalDataBss!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe>=0) |
|
1303 { |
|
1304 TRomFile* f=aFile->iRomNode->iRomFile->iPDeps[0]; // attach process |
|
1305 aFile->iDataBssLinearBase = f->DataBssLinearBase() + aFile->iRomNode->iRomFile->iDataBssOffsetInExe; |
|
1306 } |
|
1307 |
|
1308 aFile->LoadToRom(); |
|
1309 } |
|
1310 |
|
1311 char *E32Rom::LayoutRom(char *romaddr) |
|
1312 // |
|
1313 // Layout the files from the obey file starting at romaddr in the image |
|
1314 // dealing correctly with areas |
|
1315 // Also deals with two section ROMs |
|
1316 // |
|
1317 { |
|
1318 |
|
1319 TAddressRange main; |
|
1320 TAddressRange* mainptr=&main; |
|
1321 SetImageAddr(main, romaddr); |
|
1322 |
|
1323 TAddressRange second; |
|
1324 TAddressRange* secondptr=0; |
|
1325 if (iObey->iSectionStart != 0) |
|
1326 { |
|
1327 SetImageAddr(second,iSectionPtr); |
|
1328 secondptr = &second; |
|
1329 } |
|
1330 |
|
1331 TInt fileCount=0; |
|
1332 |
|
1333 // |
|
1334 // Process files in non default areas |
|
1335 // |
|
1336 |
|
1337 CBytePair bpe(gFastCompress); |
|
1338 for (NonDefaultAreasIterator areaIt(iObey->SetArea()); |
|
1339 ! areaIt.IsDone(); |
|
1340 areaIt.GoToNext()) |
|
1341 { |
|
1342 Area& currentArea = areaIt.Current(); |
|
1343 currentArea.SetSrcBaseAddr(mainptr->iImageAddr); |
|
1344 |
|
1345 mainptr->iRunAddr = currentArea.DestBaseAddr(); |
|
1346 |
|
1347 for (FilesInAreaIterator fileIt(currentArea); |
|
1348 ! fileIt.IsDone(); |
|
1349 fileIt.GoToNext()) |
|
1350 { |
|
1351 TRomBuilderEntry* currentFile = fileIt.Current(); |
|
1352 |
|
1353 LayoutFile(currentFile, *mainptr, secondptr, &bpe); |
|
1354 |
|
1355 TUint overflow; |
|
1356 if (! currentArea.ExtendSrcLimitAddr(mainptr->iImageAddr, overflow)) |
|
1357 { |
|
1358 Print(EError, "Can't fit '%s' in area '%s'\n", currentFile->iFileName, currentArea.Name()); |
|
1359 Print(EError, "Area overflowed by 0x%x bytes.\n", overflow); |
|
1360 exit(666); |
|
1361 } |
|
1362 |
|
1363 ++fileCount; |
|
1364 assert(iObey->iSectionPosition == -1 || fileCount < iObey->iSectionPosition); |
|
1365 } |
|
1366 |
|
1367 TInt offset=(char*)mainptr->iImagePtr-romaddr; |
|
1368 mainptr->Extend(Align(offset)-offset); |
|
1369 } // for every non default area |
|
1370 |
|
1371 |
|
1372 // |
|
1373 // Process files in default area |
|
1374 // |
|
1375 |
|
1376 mainptr->iRunAddr = mainptr->iImageAddr; |
|
1377 |
|
1378 for (FilesInAreaIterator fileIt(*(iObey->SetArea().DefaultArea())); |
|
1379 ! fileIt.IsDone(); |
|
1380 fileIt.GoToNext()) |
|
1381 { |
|
1382 if (fileCount==iObey->iSectionPosition) |
|
1383 { |
|
1384 // skip rest of first section and pick up after the |
|
1385 // information already accumulated in the second section |
|
1386 NextRom(mainptr, secondptr); |
|
1387 mainptr = secondptr; |
|
1388 secondptr = 0; |
|
1389 } |
|
1390 |
|
1391 LayoutFile(fileIt.Current(), *mainptr, secondptr, &bpe); |
|
1392 |
|
1393 ++fileCount; |
|
1394 } |
|
1395 |
|
1396 // align to likely position of next file |
|
1397 TInt offset=(char*)mainptr->iImagePtr-romaddr; |
|
1398 offset = Align(offset)-offset; |
|
1399 mainptr->Extend(offset); |
|
1400 iOverhead +=offset; |
|
1401 |
|
1402 return (char*)mainptr->iImagePtr; |
|
1403 } |
|
1404 |
|
1405 void E32Rom::LayoutFile(TRomBuilderEntry* current, TAddressRange& aMain, TAddressRange* aSecond, CBytePair * aBPE) |
|
1406 // |
|
1407 // Work out where to place a file in ROM and set up the |
|
1408 // appropriate TAddressRange information |
|
1409 // |
|
1410 { |
|
1411 TInt alignment = iObey->iRomAlign; |
|
1412 if (current->iAlignment > alignment) |
|
1413 alignment = current->iAlignment; |
|
1414 |
|
1415 if (alignment) |
|
1416 { |
|
1417 // Align this file on a boundary |
|
1418 TUint32 romaddr=aMain.iRunAddr; |
|
1419 TInt i=romaddr & (alignment-1); |
|
1420 TInt gap=0; |
|
1421 if (i!=0) |
|
1422 gap=alignment-i; |
|
1423 if (current->iAlignment) |
|
1424 Print(ELog, "\nAlign to %08x. Skipped %d bytes\n", romaddr+gap, gap); |
|
1425 aMain.Extend(gap); |
|
1426 iOverhead += gap; |
|
1427 } |
|
1428 |
|
1429 if (current->iCodeAlignment != 0) |
|
1430 { |
|
1431 TUint32 runaddr=aMain.iRunAddr + sizeof(TRomImageHeader); |
|
1432 TInt i=runaddr & (current->iCodeAlignment-1); |
|
1433 TInt gap=0; |
|
1434 if (i!=0) |
|
1435 gap=current->iCodeAlignment-i; |
|
1436 Print(ELog, "\nCode Align to %08x. Skipped %d bytes\n", runaddr+gap, gap); |
|
1437 aMain.Extend(gap); |
|
1438 iOverhead += gap; |
|
1439 } |
|
1440 |
|
1441 Print(ELog,"\n********************************************************************\n"); |
|
1442 |
|
1443 if (current->iPatched) |
|
1444 Print(ELog, "[Patched file]\n"); |
|
1445 |
|
1446 if (current->iResource) |
|
1447 { |
|
1448 TInt size=LoadDataToRom(current, aMain, aBPE); |
|
1449 if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart) |
|
1450 return; // first section has overflowed |
|
1451 current->FixupRomEntries(size); |
|
1452 return; |
|
1453 } |
|
1454 if(current->HCRDataFile()){ |
|
1455 TInt size=LoadDataToRom(current, aMain, aBPE); |
|
1456 if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart) |
|
1457 return; // first section has overflowed |
|
1458 current->FixupRomEntries(size); |
|
1459 iHeader->iHcrFileAddress = current->iHeaderRange.iImageAddr ; |
|
1460 TRACE(TAREA, Print(ELog, "iHeader->iHcrFileAddress = %08x\n", iHeader->iHcrFileAddress)); |
|
1461 return ; |
|
1462 } |
|
1463 Print(ELog,"Processing file %s\n",current->iFileName); |
|
1464 |
|
1465 if (current->Primary()) |
|
1466 { |
|
1467 Print(ELog, "[Primary]\n"); |
|
1468 } |
|
1469 |
|
1470 if (current->Secondary()) |
|
1471 { |
|
1472 iHeader->iSecondaryFile=ActualToRomAddress(current->RomEntry()); |
|
1473 Print(ELog, "[Secondary]\n"); |
|
1474 } |
|
1475 |
|
1476 // Section 1 things |
|
1477 // |
|
1478 // TRomImageHeader, text, export directory, data |
|
1479 |
|
1480 aMain.Append(current->iHeaderRange); |
|
1481 aMain.Append(current->iCodeSection); |
|
1482 aMain.Append(current->iDataSection); |
|
1483 |
|
1484 // section 2 things |
|
1485 // |
|
1486 // dll ref table |
|
1487 |
|
1488 if (aSecond != 0) |
|
1489 { |
|
1490 // two section ROM - split image between both sections |
|
1491 aSecond->Append(current->iExportDirSection); |
|
1492 aSecond->Append(current->iDllRefTableRange); |
|
1493 } |
|
1494 else |
|
1495 { |
|
1496 // default placement in first section |
|
1497 aMain.Append(current->iExportDirSection); |
|
1498 aMain.Append(current->iDllRefTableRange); |
|
1499 } |
|
1500 |
|
1501 TInt section1size = aMain.iRunAddr-current->iCodeSection.iRunAddr; |
|
1502 |
|
1503 if (aMain.iRunAddr == aMain.iImageAddr) |
|
1504 { |
|
1505 Print(ELog, "Load Address: %08x\n", current->iHeaderRange.iImageAddr); |
|
1506 } |
|
1507 else |
|
1508 { |
|
1509 Print(ELog, "Rom Address: %08x\n", current->iHeaderRange.iImageAddr); |
|
1510 Print(ELog, "Area Address: %08x\n", current->iHeaderRange.iRunAddr); |
|
1511 } |
|
1512 Print(ELog, "Size: %08x\n", section1size); |
|
1513 |
|
1514 if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart) |
|
1515 return; // first section has overflowed |
|
1516 |
|
1517 LoadFileToRom(current); |
|
1518 Display(current->iRomImageHeader); |
|
1519 Print(ELog, "Dll ref table size: %08x\n", current->iDllRefTableRange.iSize); |
|
1520 Print(ELog, "Compression: %08x\n", current->iCompression); |
|
1521 Print(ELog, "\n"); |
|
1522 |
|
1523 current->FixupRomEntries(section1size); |
|
1524 } |
|
1525 |
|
1526 static int CompareAddresses(const void * arg1, const void * arg2) |
|
1527 { |
|
1528 return (* (TUint32 *)arg1) < (* (TUint32 *)arg2) ? -1: 1; |
|
1529 } |
|
1530 |
|
1531 char *E32Rom::ReserveRomExceptionSearchTable(char *anAddr, TRomExceptionSearchTable*& exceptionSearchTable) |
|
1532 { |
|
1533 TRomExceptionSearchTable *pT = (TRomExceptionSearchTable *)anAddr; |
|
1534 exceptionSearchTable = pT; |
|
1535 if (iExtensionRomHeader) |
|
1536 { |
|
1537 iExtensionRomHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr); |
|
1538 } |
|
1539 else |
|
1540 { |
|
1541 iHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr); |
|
1542 } |
|
1543 TLinAddr * addr = &pT->iEntries[0]; |
|
1544 int numEntries = 0; |
|
1545 int errors = 0; |
|
1546 // Count number of entries needed |
|
1547 for (int i = 0; i < iObey->iNumberOfPeFiles; i++) |
|
1548 { |
|
1549 TUint32 xd = iPeFiles[i]->iHdr->iExceptionDescriptor; |
|
1550 if ((xd & 1) && (xd != 0xffffffffu)) |
|
1551 { |
|
1552 numEntries++; |
|
1553 } |
|
1554 else if (!iPeFiles[i]->iHdr->iExceptionDescriptor) |
|
1555 { |
|
1556 #ifdef __REJECT_NON_EXCEPTION_AWARE_BINARIES__ |
|
1557 Print(EError, "Executable not exception aware: %s\n", iPeFiles[i]->iName); |
|
1558 errors++; |
|
1559 #else |
|
1560 Print(ELog, "Executable not exception aware: %s\n", iPeFiles[i]->iName); |
|
1561 #endif |
|
1562 } |
|
1563 } |
|
1564 if (errors > 0) exit(666); |
|
1565 // NB we add one to numEntries to allow space for a fencepost value (see below for more) |
|
1566 int spaceNeeded = sizeof(pT->iNumEntries) + sizeof(pT->iEntries[0])*(numEntries+1); |
|
1567 int delta = (int)(addr+spaceNeeded) - (int)(iData+iSize); |
|
1568 // Check we've got enough room |
|
1569 if (delta > 0) |
|
1570 { |
|
1571 Print(EError, "Can't fit Rom Exception Search Table in Rom.\n"); |
|
1572 Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", delta); |
|
1573 exit(666); |
|
1574 } |
|
1575 pT->iNumEntries = numEntries; |
|
1576 return anAddr+spaceNeeded; |
|
1577 } |
|
1578 |
|
1579 void E32Rom::ConstructRomExceptionSearchTable(TRomExceptionSearchTable* exceptionSearchTable) |
|
1580 { |
|
1581 TRomExceptionSearchTable *pT = exceptionSearchTable; |
|
1582 TLinAddr * addr = &pT->iEntries[0]; |
|
1583 // Initialize the table |
|
1584 int numEntries = pT->iNumEntries; |
|
1585 TLinAddr fencepost = 0xffffffff; |
|
1586 if (numEntries) |
|
1587 { |
|
1588 TLinAddr fp = 0; |
|
1589 for (int j = 0; j < iObey->iNumberOfPeFiles; j++) |
|
1590 { |
|
1591 TUint32 xd = iPeFiles[j]->iHdr->iExceptionDescriptor; |
|
1592 if ((xd & 1) && (xd != 0xffffffff)) |
|
1593 { |
|
1594 // mask out bottom bit set by ELFTRAN. |
|
1595 xd &= ~1; |
|
1596 *addr++ = iPeFiles[j]->iHdr->iCodeBase; |
|
1597 TLinAddr aEDAddr = iPeFiles[j]->iHdr->iCodeBase + xd; |
|
1598 // Keep track of greatest code limit so we can use it as the fencepost value |
|
1599 TExceptionDescriptor * aEDp = (TExceptionDescriptor *)RomToActualAddress(aEDAddr); |
|
1600 TLinAddr codeLimit = aEDp->iROSegmentLimit; |
|
1601 if (codeLimit>fp) fp=codeLimit; |
|
1602 } |
|
1603 } |
|
1604 if (fp) fencepost=fp; |
|
1605 // now check they're in order (they should be). |
|
1606 int inOrder = 1; |
|
1607 for (int k=numEntries-1;inOrder && k; k--) |
|
1608 { |
|
1609 inOrder = pT->iEntries[k]>pT->iEntries[k-1]?1:0; |
|
1610 } |
|
1611 |
|
1612 if (!inOrder) |
|
1613 { |
|
1614 Print(ELog, "Sorting Rom Exception Table.\n"); |
|
1615 qsort(&pT->iEntries[0],numEntries,sizeof(pT->iEntries[0]), CompareAddresses); |
|
1616 } |
|
1617 } |
|
1618 /* |
|
1619 Add the fencepost value at the end of the table. This is used to optimize the comparison |
|
1620 function passed to bsearch when retrieving values from the search table. It also allows a certain |
|
1621 amount of error checking on lookup keys. |
|
1622 */ |
|
1623 *addr++ = fencepost; |
|
1624 } |
|
1625 |
|
1626 void TRomBuilderEntry::SizeInSections(TInt& aSize1, TInt& aSize2) |
|
1627 // |
|
1628 // Exact size of the upper & lower section information |
|
1629 // lower = text + data |
|
1630 // upper = export directory + dllref table |
|
1631 // |
|
1632 { |
|
1633 aSize1 = iHeaderRange.iSize; |
|
1634 aSize1 += iCodeSection.iSize; // text (including rdata) |
|
1635 aSize1 += iDataSection.iSize; // static data |
|
1636 |
|
1637 aSize2 = iExportDirSection.iSize; // export directory |
|
1638 aSize2 += iDllRefTableRange.iSize; // DLL ref table |
|
1639 } |
|
1640 |
|
1641 |
|
1642 void E32Rom::NextRom(TAddressRange* aFirst, TAddressRange* aSecond) |
|
1643 // |
|
1644 // Move on to the next Rom bank, taking the IATs with us |
|
1645 // |
|
1646 { |
|
1647 |
|
1648 Print(ELog,"\n####################################################################\n"); |
|
1649 TInt gap=iObey->iSectionStart-aFirst->iImageAddr; |
|
1650 if (gap<0) |
|
1651 { |
|
1652 Print(EError, "First section overflowed by %08x bytes\n", -gap); |
|
1653 exit(669); |
|
1654 } |
|
1655 iOverhead+=gap+sizeof(TRomSectionHeader); |
|
1656 Print(ELog, "[Next rom section]\n"); |
|
1657 Print(ELog, "Skipping %08x bytes\n", gap); |
|
1658 Print(ELog, "LinAddr: %08x\n", iObey->iSectionStart); |
|
1659 Print(ELog, "First section tables: %08x\n", iObey->iSectionStart+sizeof(TRomSectionHeader)); |
|
1660 TInt size=aSecond->iImageAddr-iObey->iSectionStart; |
|
1661 Print(ELog, "Tables size: %08x\n", size-sizeof(TRomSectionHeader)); |
|
1662 Print(ELog, "Rom Directory %08x\n", iHeader->iRomRootDirectoryList); |
|
1663 Print(ELog, "Rom Directory size %08x\n", iDirectorySize); |
|
1664 |
|
1665 if (aSecond->iImageAddr != iHeader->iRomRootDirectoryList) |
|
1666 { |
|
1667 Print(EError, "Second section has overwritten the Rom directory\n"); |
|
1668 exit(669); |
|
1669 } |
|
1670 aSecond->Extend(iDirectorySize); |
|
1671 |
|
1672 Print(ELog, "\n"); |
|
1673 } |
|
1674 |
|
1675 TInt E32Rom::ResolveDllRefTables() |
|
1676 // |
|
1677 // |
|
1678 // |
|
1679 { |
|
1680 |
|
1681 Print(ELog, "\nResolving Dll reference tables.\n"); |
|
1682 TInt i; |
|
1683 TInt err = KErrNone; |
|
1684 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1685 { |
|
1686 TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables %d\n",i)); |
|
1687 TInt r=iPeFiles[i]->ResolveDllRefTable(*this); |
|
1688 if (r!=KErrNone) |
|
1689 err=r; |
|
1690 } |
|
1691 TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables complete\n")); |
|
1692 return err; |
|
1693 } |
|
1694 |
|
1695 |
|
1696 TInt E32Rom::BuildDependenceGraph() |
|
1697 { |
|
1698 Print(ELog, "\nBuilding dependence graph.\n"); |
|
1699 TInt i; |
|
1700 TInt err = KErrNone; |
|
1701 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1702 { |
|
1703 TRACE(TIMPORT,Print(ELog,"BuildDep %d\n",i)); |
|
1704 TRomBuilderEntry* e=iPeFiles[i]; |
|
1705 TInt r=e->BuildDependenceGraph(*this); |
|
1706 if (r!=KErrNone) |
|
1707 err=r; |
|
1708 if (!e->IsDll()) |
|
1709 { |
|
1710 if (e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0) |
|
1711 e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataPresent); // EXE with static data |
|
1712 } |
|
1713 else if ((e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0) && !e->Variant() && !e->Extension()) |
|
1714 { |
|
1715 // requires normal case DLL data initialisation |
|
1716 e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent); |
|
1717 } |
|
1718 } |
|
1719 TRACE(TIMPORT,Print(ELog,"BuildDep complete\n")); |
|
1720 |
|
1721 if(!gPagedRom) |
|
1722 return err; |
|
1723 |
|
1724 Print(ELog,"\n"); |
|
1725 |
|
1726 return err; |
|
1727 } |
|
1728 |
|
1729 #define MARK_BEEN_HERE 1 |
|
1730 #define MARK_KEEP 2 |
|
1731 #define MARK_EXE 4 |
|
1732 #define MARK_CHECKED 8 |
|
1733 void E32Rom::UnmarkGraph(TInt aMark) |
|
1734 { |
|
1735 TRomNode* x = 0; |
|
1736 for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable) |
|
1737 x->iRomFile->iMark &= ~aMark; |
|
1738 } |
|
1739 |
|
1740 void E32Rom::FindMarked(TInt aMarkMask, TInt aMark, TRomFile**& aList) |
|
1741 { |
|
1742 UnmarkGraph(MARK_CHECKED); |
|
1743 TRomNode* x = 0; |
|
1744 aMarkMask |= MARK_CHECKED; |
|
1745 aMark &= ~MARK_CHECKED; |
|
1746 for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable) |
|
1747 { |
|
1748 TRomFile* e = x->iRomFile; |
|
1749 if ((e->iMark&aMarkMask)==aMark) |
|
1750 { |
|
1751 *aList++=e; |
|
1752 e->iMark |= MARK_CHECKED; |
|
1753 } |
|
1754 } |
|
1755 } |
|
1756 |
|
1757 TInt TRomFile::MarkDeps() |
|
1758 { |
|
1759 TInt n=0; |
|
1760 TInt i; |
|
1761 for (i=0; i<iNumDeps; ++i) |
|
1762 { |
|
1763 TRomFile* e=iDeps[i]; |
|
1764 if (!(e->iMark & MARK_BEEN_HERE)) |
|
1765 { |
|
1766 e->iMark|=MARK_BEEN_HERE; |
|
1767 ++n; |
|
1768 n+=e->MarkDeps(); |
|
1769 TUint32 flg = RomImageFlags(); |
|
1770 TUint32 eflg = e->RomImageFlags(); |
|
1771 if (eflg & KRomImageFlagDataPresent) |
|
1772 iRbEntry->iRomImageFlags |= KRomImageFlagDataPresent; |
|
1773 TBool e_is_dll = eflg & KImageDll; |
|
1774 if ((flg & KImageDll) && e_is_dll && (eflg & KRomImageFlagDataInit)) |
|
1775 iRbEntry->iRomImageFlags |= KRomImageFlagDataInit; |
|
1776 if (!e_is_dll) |
|
1777 e->iMark|=MARK_EXE; |
|
1778 if (eflg&KRomImageFlagData) |
|
1779 e->iMark|=MARK_KEEP; |
|
1780 } |
|
1781 } |
|
1782 return n; |
|
1783 } |
|
1784 |
|
1785 TInt TRomFile::FindRouteTo(TRomFile* aDest, TRomFile** aStack, TInt aIndex) |
|
1786 { |
|
1787 TInt i; |
|
1788 for (i=0; i<iNumDeps; ++i) |
|
1789 { |
|
1790 TRomFile* e=iDeps[i]; |
|
1791 if (e == aDest) |
|
1792 return aIndex; |
|
1793 if (!(e->iMark & MARK_BEEN_HERE)) |
|
1794 { |
|
1795 e->iMark|=MARK_BEEN_HERE; |
|
1796 aStack[aIndex] = e; |
|
1797 TInt r = e->FindRouteTo(aDest, aStack, aIndex+1); |
|
1798 if (r >= 0) |
|
1799 return r; |
|
1800 } |
|
1801 } |
|
1802 return KErrNotFound; |
|
1803 } |
|
1804 |
|
1805 void E32Rom::ListRouteTo(TRomFile* aStart, TRomFile* aDest, TInt aNDeps) |
|
1806 { |
|
1807 TRomNode* rootdir = iObey->iRootDirectory; |
|
1808 TRomFile** stack = new TRomFile*[aNDeps]; |
|
1809 UnmarkGraph(); |
|
1810 TInt depth = aStart->FindRouteTo(aDest, stack, 0); |
|
1811 assert(depth >= 0); |
|
1812 Print(EAlways, "\t--->%s\n", (const char*)TModuleName(*aDest, rootdir)); |
|
1813 while(--depth >= 0) |
|
1814 Print(EAlways, "\tvia %s\n", (const char*)TModuleName(*stack[depth], rootdir)); |
|
1815 delete[] stack; |
|
1816 } |
|
1817 |
|
1818 TInt E32Rom::ProcessDependencies() |
|
1819 { |
|
1820 TInt i; |
|
1821 TInt errors = 0; |
|
1822 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1823 { |
|
1824 TRomBuilderEntry* e=iPeFiles[i]; |
|
1825 TRomNode* rn = e->iRomNode; |
|
1826 TRomFile* rf = rn->iRomFile; |
|
1827 UnmarkGraph(); |
|
1828 TInt n=rf->MarkDeps(); |
|
1829 rf->iNumPDeps=n; |
|
1830 if (n) |
|
1831 { |
|
1832 rf->iPDeps=new TRomFile* [n]; |
|
1833 if (!rf->iPDeps) |
|
1834 return KErrNoMemory; |
|
1835 TRomFile** l=rf->iPDeps; |
|
1836 FindMarked(MARK_EXE, MARK_EXE, l); |
|
1837 TInt nx=l-rf->iPDeps; |
|
1838 if (!e->IsDll() && (nx>1 || nx==1 && l[-1]!=rf)) |
|
1839 { |
|
1840 Print(EError,"EXE %s links to the following other EXEs:\n", e->iFileName); |
|
1841 TInt j; |
|
1842 for (j=0; j<nx; ++j) |
|
1843 { |
|
1844 if (rf->iPDeps[j] != rf) |
|
1845 ListRouteTo(rf, rf->iPDeps[j], n); |
|
1846 } |
|
1847 ++errors; |
|
1848 continue; |
|
1849 } |
|
1850 else if (nx>1) |
|
1851 { |
|
1852 Print(EError,"DLL %s links to more than one EXE:\n",e->iFileName); |
|
1853 TInt j; |
|
1854 for (j=0; j<nx; ++j) |
|
1855 ListRouteTo(rf, rf->iPDeps[j], n); |
|
1856 ++errors; |
|
1857 continue; |
|
1858 } |
|
1859 if (nx) |
|
1860 e->iRomImageFlags|=KRomImageFlagExeInTree; |
|
1861 FindMarked(MARK_KEEP|MARK_EXE, MARK_KEEP, l); |
|
1862 rf->iNumPDeps=l-rf->iPDeps; |
|
1863 if (rf->iNumPDeps) |
|
1864 { |
|
1865 e->iDllRefTableRange.iSize=(rf->iNumPDeps-1)*sizeof(TRomImageHeader*)+sizeof(TDllRefTable); |
|
1866 if (e->IsDll() && rf->iTotalDataBss) |
|
1867 { |
|
1868 TRomFile* f=rf->iPDeps[0]; // first dependency, EXE if there is one |
|
1869 TUint fflg = f->RomImageFlags(); |
|
1870 TBool f_is_dll = fflg & KImageDll; |
|
1871 if (!f_is_dll) |
|
1872 { |
|
1873 // DLL with data/bss depends on EXE |
|
1874 if ((fflg & KRomImageFlagFixedAddressExe) || iObey->iMemModel==E_MM_Direct) |
|
1875 { |
|
1876 // assign the DLL data address in the EXE bss section |
|
1877 rf->iDataBssOffsetInExe=f->iTotalDataBss; |
|
1878 f->iTotalDataBss+=rf->iTotalDataBss; |
|
1879 } |
|
1880 } |
|
1881 else if (iObey->iMemModel==E_MM_Direct) |
|
1882 { |
|
1883 Print(EError, "DLL with data/bss must have attach process specified\n"); |
|
1884 return KErrGeneral; |
|
1885 } |
|
1886 } |
|
1887 } |
|
1888 else |
|
1889 { |
|
1890 delete[] rf->iPDeps; |
|
1891 rf->iPDeps=NULL; |
|
1892 } |
|
1893 } |
|
1894 if (!rf->iNumPDeps) |
|
1895 e->iDllRefTableRange.iSize=0; |
|
1896 } |
|
1897 if (iObey->iMemModel == E_MM_Moving) |
|
1898 { |
|
1899 // On moving model only, we must verify that no fixed process links to a |
|
1900 // DLL with data/bss which is attached to a fixed process. |
|
1901 // On multiple model there is no restriction. |
|
1902 // On direct model all DLLs with data/bss must specify an attach process |
|
1903 // and the error will show up as one EXE depending on another. |
|
1904 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1905 { |
|
1906 TRomBuilderEntry* e=iPeFiles[i]; |
|
1907 TRomNode* rn = e->iRomNode; |
|
1908 TRomFile* rf = rn->iRomFile; |
|
1909 TUint rif = rf->RomImageFlags(); |
|
1910 if (e->IsDll() || e->Primary() || !(rif & KRomImageFlagFixedAddressExe)) |
|
1911 continue; // only need to check fixed address user mode EXEs |
|
1912 TInt n = rf->iNumPDeps; |
|
1913 TInt j; |
|
1914 for (j=0; j<n; ++j) |
|
1915 { |
|
1916 TRomFile* f = rf->iPDeps[j]; |
|
1917 TUint fflg = f->RomImageFlags(); |
|
1918 if ((fflg & KImageDll) && (f->iDataBssOffsetInExe < 0)) |
|
1919 { |
|
1920 // fixed user EXE links to DLL with data/bss and no attach process |
|
1921 Print(EError,"Fixed EXE %s links to DLL with data/bss and no attach process:\n", e->iFileName); |
|
1922 ListRouteTo(rf, rf->iPDeps[j], n); |
|
1923 ++errors; |
|
1924 } |
|
1925 } |
|
1926 } |
|
1927 } |
|
1928 if (errors) |
|
1929 return KErrGeneral; |
|
1930 |
|
1931 STRACE(TIMPORT, |
|
1932 { |
|
1933 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1934 { |
|
1935 TRomBuilderEntry* e=iPeFiles[i]; |
|
1936 TRomNode* rn = e->iRomNode; |
|
1937 TRomFile* rf = rn->iRomFile; |
|
1938 Print(ELog,"File %s: PN=%d\n",e->iFileName,rf->iNumPDeps); |
|
1939 TInt j; |
|
1940 for (j=0; j<rf->iNumPDeps; ++j) |
|
1941 { |
|
1942 TRomFile* f=rf->iPDeps[j]; |
|
1943 Print(ELog,"\t%s\n", (const char*)TModuleName(*f, iObey->iRootDirectory)); |
|
1944 } |
|
1945 } |
|
1946 }) |
|
1947 return KErrNone; |
|
1948 } |
|
1949 |
|
1950 void E32Rom::SetSmpFlags() |
|
1951 { |
|
1952 if (gLogLevel & LOG_LEVEL_SMP_INFO) |
|
1953 { |
|
1954 Print(ELog,"\nComputing SMP properties. The following components are SMP-unsafe:\n"); |
|
1955 } |
|
1956 |
|
1957 bool is_all_safe = 1; |
|
1958 |
|
1959 for (int i = 0; i < iObey->iNumberOfPeFiles; i++) |
|
1960 { |
|
1961 TRomBuilderEntry* e = iPeFiles[i]; |
|
1962 |
|
1963 if ( e->iRomNode->iRomFile->ComputeSmpSafe(e) ) |
|
1964 { |
|
1965 e->iRomImageFlags |= KRomImageSMPSafe; |
|
1966 } |
|
1967 else |
|
1968 { |
|
1969 is_all_safe = 0; |
|
1970 e->iRomImageFlags &= ~KRomImageSMPSafe; |
|
1971 } |
|
1972 } |
|
1973 |
|
1974 if ( (gLogLevel & LOG_LEVEL_SMP_INFO) && is_all_safe) |
|
1975 { |
|
1976 Print(ELog,"There are no unsafe components."); |
|
1977 } |
|
1978 } |
|
1979 |
|
1980 TInt E32Rom::ResolveImports() |
|
1981 // |
|
1982 // Fix the import address table for each of the files in rom |
|
1983 // |
|
1984 { |
|
1985 |
|
1986 Print(ELog, "Resolving Imports.\n"); |
|
1987 TInt i; |
|
1988 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
1989 { |
|
1990 TInt r=iPeFiles[i]->FixupImports(*this); |
|
1991 if (r!=KErrNone) |
|
1992 return r; |
|
1993 } |
|
1994 return KErrNone; |
|
1995 } |
|
1996 |
|
1997 char *E32Rom::RomToActualAddress(TUint aPtr) |
|
1998 { |
|
1999 return (char *)(aPtr-iObey->iRomLinearBase+(TUint)iHeader); |
|
2000 } |
|
2001 |
|
2002 TUint E32Rom::ActualToRomAddress(TAny *aPtr) |
|
2003 { |
|
2004 return ((TUint)aPtr)-(TUint32)iHeader+iObey->iRomLinearBase; |
|
2005 } |
|
2006 |
|
2007 void E32Rom::SetImageAddr(TAddressRange& aRange, TAny* aPtr, TUint32 aRunOffset) |
|
2008 { |
|
2009 aRange.iImagePtr=aPtr; |
|
2010 aRange.iImageAddr=ActualToRomAddress(aPtr); |
|
2011 aRange.iRunAddr=aRange.iImageAddr+aRunOffset; |
|
2012 } |
|
2013 |
|
2014 void E32Rom::SetImageAddr(TAddressRange& aRange, TUint aAddr, TUint32 aRunOffset) |
|
2015 { |
|
2016 aRange.iImagePtr=RomToActualAddress(aAddr); |
|
2017 aRange.iImageAddr=aAddr; |
|
2018 aRange.iRunAddr=aAddr+aRunOffset; |
|
2019 } |
|
2020 |
|
2021 TRomNode* E32Rom::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack) |
|
2022 // |
|
2023 // return the file with the name aName |
|
2024 // |
|
2025 { |
|
2026 return iObey->iRootDirectory->FindImageFileByName(aInfo, aPrintDiag, aFallBack); |
|
2027 } |
|
2028 |
|
2029 TInt E32Rom::CheckForVersionConflicts(const TRomBuilderEntry* a) |
|
2030 { |
|
2031 return iObey->iRootDirectory->CheckForVersionConflicts(a); |
|
2032 } |
|
2033 |
|
2034 TRomNode* E32Rom::CopyDirectory(TRomNode*& aLastExecutable) |
|
2035 { |
|
2036 return iObey->iRootDirectory->CopyDirectory(aLastExecutable, 0); |
|
2037 } |
|
2038 |
|
2039 TInt E32Rom::CollapseImportThunks() |
|
2040 // |
|
2041 // Collapse 3-word import thunks into a single branch |
|
2042 // |
|
2043 { |
|
2044 |
|
2045 Print(ELog, "\nCollapsing Import Thunks.\n"); |
|
2046 TInt i; |
|
2047 for (i=0; i<iObey->iNumberOfPeFiles; i++) |
|
2048 { |
|
2049 if (iPeFiles[i]->iHdr->iImportOffset) |
|
2050 { |
|
2051 TInt r=CollapseImportThunks(iPeFiles[i]); |
|
2052 if (r!=KErrNone) |
|
2053 return r; |
|
2054 } |
|
2055 } |
|
2056 return KErrNone; |
|
2057 } |
|
2058 |
|
2059 TInt E32Rom::WriteImages(TInt aHeaderType) |
|
2060 { |
|
2061 if (aHeaderType < 0) |
|
2062 aHeaderType = 1; |
|
2063 ofstream romFile((const char *)iObey->iRomFileName,ios::binary); |
|
2064 if (!romFile) |
|
2065 return Print(EError,"Cannot open ROM file %s for output\n",iObey->iRomFileName); |
|
2066 Write(romFile, aHeaderType); |
|
2067 romFile.close(); |
|
2068 |
|
2069 // Write out the odd/even 16-bits of the images |
|
2070 |
|
2071 char sname[256]; |
|
2072 if (iObey->iRomOddFileName) |
|
2073 { |
|
2074 strcpy(sname, (const char*)iObey->iRomOddFileName); |
|
2075 if (strcmp(sname, "*")==0) |
|
2076 { |
|
2077 // use romname with ".odd" appended. |
|
2078 sprintf(sname,"%s.odd",(const char *)iObey->iRomFileName); |
|
2079 } |
|
2080 ofstream oFile(sname,ios::binary); |
|
2081 if (!oFile) |
|
2082 return Print(EError,"Cannot open file %s for output\n",sname); |
|
2083 Print(EAlways, "Writing odd half words to file %s\n",sname); |
|
2084 WriteOdd(oFile); |
|
2085 oFile.close(); |
|
2086 } |
|
2087 if (iObey->iRomEvenFileName) |
|
2088 { |
|
2089 strcpy(sname, (const char*)iObey->iRomEvenFileName); |
|
2090 if (strcmp(sname, "*")==0) |
|
2091 { |
|
2092 // use romname with ".even" appended. |
|
2093 sprintf(sname,"%s.even",(const char *)iObey->iRomFileName); |
|
2094 } |
|
2095 ofstream oFile(sname,ios::binary); |
|
2096 if (!oFile) |
|
2097 return Print(EError,"Cannot open file %s for output\n",sname); |
|
2098 Print(EAlways, "Writing even half words to file %s\n",sname); |
|
2099 WriteEven(oFile); |
|
2100 oFile.close(); |
|
2101 } |
|
2102 |
|
2103 // Write out the ROM in the SREC or S19 format |
|
2104 |
|
2105 if (iObey->iSRecordFileName) |
|
2106 { |
|
2107 strcpy(sname, (const char*)iObey->iSRecordFileName); |
|
2108 if (strcmp(sname, "*")==0) |
|
2109 { |
|
2110 // use romname with ".srec" appended. |
|
2111 sprintf(sname,"%s.srec",(const char *)iObey->iRomFileName); |
|
2112 } |
|
2113 ofstream sFile(sname,ios::binary); |
|
2114 if (!romFile) |
|
2115 return Print(EError,"Cannot open file %s for output\n",sname); |
|
2116 Print(EAlways, "Writing S record format to file %s\n",sname); |
|
2117 WriteSRecord(sFile); |
|
2118 sFile.close(); |
|
2119 } |
|
2120 return KErrNone; |
|
2121 } |
|
2122 |
|
2123 void E32Rom::WriteOdd(ofstream &os) |
|
2124 { |
|
2125 char *ptr=(char *)iHeader+2; |
|
2126 TInt i; |
|
2127 for (i=2; i<iObey->iRomSize; i+=4, ptr+=4) |
|
2128 os.write(ptr, 2); |
|
2129 } |
|
2130 |
|
2131 void E32Rom::WriteEven(ofstream &os) |
|
2132 { |
|
2133 char *ptr=(char *)iHeader; |
|
2134 TInt i; |
|
2135 for (i=0; i<iObey->iRomSize; i+=4, ptr+=4) |
|
2136 os.write(ptr, 2); |
|
2137 } |
|
2138 |
|
2139 void E32Rom::SetCompressionInfo(TUint aCompressionType, TUint aCompressedSize, TUint aUncompressedSize) |
|
2140 { |
|
2141 |
|
2142 if (iExtensionRomHeader) |
|
2143 { |
|
2144 iExtensionRomHeader->iCompressionType=aCompressionType; |
|
2145 iExtensionRomHeader->iCompressedSize=aCompressedSize; |
|
2146 iExtensionRomHeader->iUncompressedSize=aUncompressedSize; |
|
2147 } |
|
2148 else |
|
2149 { |
|
2150 iHeader->iCompressionType=aCompressionType; |
|
2151 iHeader->iCompressedSize=aCompressedSize; |
|
2152 iHeader->iUncompressedSize=aUncompressedSize; |
|
2153 } |
|
2154 } |
|
2155 |
|
2156 void E32Rom::Write(ofstream &os, TInt aHeaderType) |
|
2157 // |
|
2158 // Output a rom image |
|
2159 // |
|
2160 { |
|
2161 |
|
2162 const char *compressed=gEnableCompress ? " compressed" : " uncompressed"; |
|
2163 |
|
2164 switch (aHeaderType) |
|
2165 { |
|
2166 case 0: |
|
2167 Print(EAlways, "\nWriting%s Rom image without",compressed); |
|
2168 break; |
|
2169 case 1: |
|
2170 default: |
|
2171 Print(EAlways, "\nWriting%sRom image with repro",compressed); |
|
2172 os.write(iData, sizeof(TRomLoaderHeader)); |
|
2173 break; |
|
2174 case 2: |
|
2175 Print(EAlways, "\nWriting%s Rom image with PE-COFF",compressed); |
|
2176 { |
|
2177 unsigned char coffhead[0x58] = {0}; // zero all the elements |
|
2178 |
|
2179 // fill in the constant bits |
|
2180 // this is supposed to be simple, remember |
|
2181 coffhead[1] = 0x0a; |
|
2182 coffhead[2] = 0x01; |
|
2183 coffhead[0x10] = 0x1c; |
|
2184 coffhead[0x12] = 0x0f; |
|
2185 coffhead[0x13] = 0xa1; |
|
2186 coffhead[0x14] = 0x0b; |
|
2187 coffhead[0x15] = 0x01; |
|
2188 coffhead[0x26] = 0x40; |
|
2189 coffhead[0x2a] = 0x40; |
|
2190 coffhead[0x30] = 0x2e; |
|
2191 coffhead[0x31] = 0x74; |
|
2192 coffhead[0x32] = 0x65; |
|
2193 coffhead[0x33] = 0x78; |
|
2194 coffhead[0x34] = 0x74; |
|
2195 coffhead[0x3a] = 0x40; |
|
2196 coffhead[0x3e] = 0x40; |
|
2197 coffhead[0x44] = 0x58; |
|
2198 coffhead[0x54] = 0x20; |
|
2199 |
|
2200 // now fill in the text segment size |
|
2201 *(TUint32 *) (&coffhead[0x18]) = ALIGN4K(iSizeUsed); |
|
2202 *(TUint32 *) (&coffhead[0x40]) = ALIGN4K(iSizeUsed); |
|
2203 |
|
2204 os.write(reinterpret_cast<char *>(coffhead), sizeof(coffhead)); |
|
2205 } |
|
2206 break; |
|
2207 } |
|
2208 Print(EAlways, " header to file %s\n", iObey->iRomFileName); |
|
2209 |
|
2210 iHeader->iUnpagedCompressedSize = 0; |
|
2211 iHeader->iUnpagedUncompressedSize = iHeader->iPageableRomStart; |
|
2212 iHeader->iCompressedUnpagedStart = gBootstrapSize + gPageIndexTableSize; // AttilaV calculate uncompressed un-paged size |
|
2213 |
|
2214 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2215 { |
|
2216 Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize); |
|
2217 Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize); |
|
2218 |
|
2219 Print(ELog, "iExtensionRomHeader :%d\n", iExtensionRomHeader); |
|
2220 Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType )); |
|
2221 Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize )); |
|
2222 Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize )); |
|
2223 |
|
2224 Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart ); |
|
2225 Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize ); |
|
2226 Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex ); |
|
2227 |
|
2228 Print(ELog, "iSizeUsed :0x%08x (%d)\n", iSizeUsed, iSizeUsed ); |
|
2229 Print(ELog, "Linear base address :0x%08x\n",iHeader->iRomBase); |
|
2230 Print(ELog, "Size: 0x%08x\n",iHeader->iRomSize); |
|
2231 } |
|
2232 |
|
2233 if ( gPagedRom && gCompressUnpaged) |
|
2234 { |
|
2235 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2236 Print(ELog, "Write out compressed un-paged and paged sections\n\n"); |
|
2237 ImpTRomHeader* header = (ImpTRomHeader *)iHeader; |
|
2238 |
|
2239 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2240 { |
|
2241 Print(ELog, "Header:\n"); |
|
2242 header->Display(); |
|
2243 } |
|
2244 |
|
2245 streampos headerpos=os.tellp(); |
|
2246 |
|
2247 // Write out uncompressed un-paged part (bootstrap + Page Index Table) |
|
2248 os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart); |
|
2249 |
|
2250 // write out the compressed unpaged part |
|
2251 int srcsize=iHeader->iPageableRomStart - iHeader->iCompressedUnpagedStart; |
|
2252 |
|
2253 int rawimagelen=DeflateCompressCheck(((char *)iHeader)+iHeader->iCompressedUnpagedStart,srcsize,os); |
|
2254 iHeader->iUnpagedCompressedSize = rawimagelen; |
|
2255 iHeader->iUnpagedUncompressedSize = srcsize ; |
|
2256 |
|
2257 // align to 4kbyte boundary if neccessary |
|
2258 TUint32 distanceFrom4kBoundary = ((~(iHeader->iCompressedUnpagedStart + rawimagelen /*+ sizeof(TRomLoaderHeader)*/ )) & 0xfff) + 1; |
|
2259 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2260 Print(ELog, "distanceFrom4kBoundary :0x%08x (%d)\n", distanceFrom4kBoundary, distanceFrom4kBoundary); |
|
2261 char filer[0x1000]; |
|
2262 memset( filer, 0, 0x1000); |
|
2263 os.write((char *)filer, distanceFrom4kBoundary); |
|
2264 |
|
2265 |
|
2266 // write out the paged part |
|
2267 os.write((char *)iHeader + iHeader->iPageableRomStart, ALIGN4K(iSizeUsed - iHeader->iPageableRomStart)); |
|
2268 |
|
2269 // update size and compression information of paged-part |
|
2270 SetCompressionInfo(KUidCompressionDeflate, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize)); |
|
2271 |
|
2272 // Calculate starting index of the Pageable Rom Start |
|
2273 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2274 { |
|
2275 Print(ELog, "iPageableRomStart : %d (0x%08x)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart); |
|
2276 Print(ELog, "iCompressedUnpagedStart : %d (0x%08x)\n", iHeader->iCompressedUnpagedStart, iHeader->iCompressedUnpagedStart); |
|
2277 Print(ELog, "rawimagelen : %d (0x%08x)\n", rawimagelen, rawimagelen); |
|
2278 } |
|
2279 |
|
2280 TInt displacement = iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary; |
|
2281 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2282 Print(ELog, "new iPageableRomStart : %d (0x%08x)\n", (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary), (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary)); |
|
2283 displacement = iHeader->iPageableRomStart-displacement; |
|
2284 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2285 Print(ELog, "displacement : %d (0x%08x)\n", displacement, displacement); |
|
2286 |
|
2287 SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex); |
|
2288 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2289 Print(ELog, "First Pageable page info[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize); |
|
2290 |
|
2291 TInt startPageableIndex = (iHeader->iPageableRomStart) / (iObey->iPageSize); |
|
2292 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2293 { |
|
2294 Print(ELog, "iObey->iPageSize : %d (0x%08x)\n", iObey->iPageSize, iObey->iPageSize); |
|
2295 Print(ELog, "startPageableIndex : %d (0x%08x)\n", startPageableIndex, startPageableIndex); |
|
2296 } |
|
2297 pi += startPageableIndex; |
|
2298 |
|
2299 |
|
2300 while ( 0 != pi->iDataStart) |
|
2301 { |
|
2302 if (H.iVerbose) Print(ELog, "\t\tinfo[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize); |
|
2303 |
|
2304 pi->iDataStart -= displacement; |
|
2305 |
|
2306 if (H.iVerbose) Print(ELog, "\t\tinfo[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize); |
|
2307 |
|
2308 ++pi; |
|
2309 } |
|
2310 |
|
2311 |
|
2312 |
|
2313 // Rewrite the header with updated info |
|
2314 #ifdef __TOOLS2__ |
|
2315 os.seekp(headerpos); |
|
2316 #else |
|
2317 os.seekp(headerpos,ios::beg); |
|
2318 #endif |
|
2319 |
|
2320 // Rewrite uncompressed un-paged part (bootstrap + Page Index Table) |
|
2321 os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart); |
|
2322 |
|
2323 |
|
2324 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2325 { |
|
2326 Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize, iHeader->iUnpagedCompressedSize); |
|
2327 Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize, iHeader->iUnpagedUncompressedSize); |
|
2328 |
|
2329 Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType )); |
|
2330 Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize )); |
|
2331 Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize )); |
|
2332 |
|
2333 Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart ); |
|
2334 Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize ); |
|
2335 Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex ); |
|
2336 Print(ELog, "\t\tinfo(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi->iDataStart, pi->iDataSize, pi->iDataSize); |
|
2337 |
|
2338 Print(ELog, "Linear base address: %08x\n",iHeader->iRomBase); |
|
2339 Print(ELog, "Size: %08x\n",iHeader->iRomSize); |
|
2340 } |
|
2341 |
|
2342 return; |
|
2343 } |
|
2344 |
|
2345 if (!gEnableCompress || gPagedRom || !gCompressUnpaged) |
|
2346 { |
|
2347 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2348 Print(ELog, "Writeout uncompressed un-paged and paged sections2\n"); |
|
2349 SetCompressionInfo(KFormatNotCompressed, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize)); |
|
2350 iHeader->iUnpagedCompressedSize = ALIGN4K(iSizeUsed); |
|
2351 iHeader->iUnpagedUncompressedSize = ALIGN4K(iUncompressedSize); |
|
2352 |
|
2353 os.write((char *)iHeader, ALIGN4K(iSizeUsed)); |
|
2354 |
|
2355 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2356 { |
|
2357 Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize); |
|
2358 Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize); |
|
2359 |
|
2360 Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType )); |
|
2361 Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize )); |
|
2362 Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize )); |
|
2363 |
|
2364 Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart ); |
|
2365 Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize ); |
|
2366 Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex ); |
|
2367 } |
|
2368 |
|
2369 return; |
|
2370 } |
|
2371 |
|
2372 // compressed image without paging section |
|
2373 streampos headerpos=os.tellp(); |
|
2374 int headersize=iExtensionRomHeader ? sizeof(TExtensionRomHeader) : sizeof(TRomHeader); |
|
2375 |
|
2376 os.write(reinterpret_cast<char*>(iHeader), headersize); // write a dummy header |
|
2377 // compress the rest of the image |
|
2378 int srcsize=iSizeUsed - headersize; |
|
2379 int rawimagelen=DeflateCompressCheck(((char *)iHeader)+headersize,srcsize,os); |
|
2380 // write the compression info into the header |
|
2381 SetCompressionInfo(KUidCompressionDeflate, rawimagelen, iUncompressedSize); // doesn't need to be 4K aligned |
|
2382 iHeader->iCompressedUnpagedStart = headersize; |
|
2383 iHeader->iUnpagedCompressedSize = rawimagelen; |
|
2384 iHeader->iUnpagedUncompressedSize = srcsize; |
|
2385 |
|
2386 #ifdef __TOOLS2__ |
|
2387 os.seekp(headerpos); |
|
2388 #else |
|
2389 os.seekp(headerpos,ios::beg); |
|
2390 #endif |
|
2391 os.write(reinterpret_cast<char*>(iHeader), headersize); // write header again with (compressed) size info |
|
2392 |
|
2393 if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO) |
|
2394 Print(ELog, "\tiSizeUsed:%d, iUncompressedSize:%d, headersize:%d, srcsize:%d, rawimagelen:%d \n",iSizeUsed, iUncompressedSize, headersize, srcsize, rawimagelen); |
|
2395 } |
|
2396 |
|
2397 TInt E32Rom::Compare(char *anImage, TInt aHeaderType) |
|
2398 { |
|
2399 if (aHeaderType < 0) |
|
2400 aHeaderType = 1; |
|
2401 ifstream file(anImage, ios::binary); |
|
2402 if (!file) |
|
2403 return Print(EError, "Cannot open Rom image '%s' for verification\n", anImage); |
|
2404 Print(ELog, "\nVerifying ROM against image in %s\n", anImage); |
|
2405 switch (aHeaderType) |
|
2406 { |
|
2407 case 0: |
|
2408 break; |
|
2409 case 1: |
|
2410 default: |
|
2411 Print(ELog, "Skipping repro header\n"); |
|
2412 file.seekg(sizeof(TRomLoaderHeader)); |
|
2413 break; |
|
2414 case 2: |
|
2415 Print(ELog, "Skipping coff header\n"); |
|
2416 file.seekg(0x58); |
|
2417 break; |
|
2418 } |
|
2419 TInt length=ALIGN4K(iSizeUsed); |
|
2420 if (iObey->iSectionStart != 0) |
|
2421 { |
|
2422 length = iObey->iSectionStart-iObey->iRomLinearBase; |
|
2423 Print(ELog, "Verifying first section (%08x bytes)... ", length); |
|
2424 } |
|
2425 |
|
2426 TRomHeader compareHeader; |
|
2427 file.read((char *)&compareHeader, sizeof(TRomHeader)); |
|
2428 // Arrange different settings for TRomHeader and |
|
2429 // TRomSectionHeader in the obey file |
|
2430 // For now just copy across the things that'll change |
|
2431 compareHeader.iVersion=iHeader->iVersion; |
|
2432 compareHeader.iTime=iHeader->iTime; |
|
2433 compareHeader.iTimeHi=(TUint32)(iHeader->iTime >> 32); |
|
2434 compareHeader.iCheckSum=iHeader->iCheckSum; |
|
2435 compareHeader.iLanguage=iHeader->iLanguage; |
|
2436 |
|
2437 if (memcmp(&compareHeader, iHeader, sizeof(TRomHeader))!=0) |
|
2438 return Print(EError, "Verify failed.\nRom headers are different\n"); |
|
2439 |
|
2440 // Now compare the rest of the image (or first section) |
|
2441 |
|
2442 TUint *ptr=(TUint *)(iHeader+1); |
|
2443 TInt i; |
|
2444 for (i=sizeof(TRomHeader); i<length; i+=4) |
|
2445 { |
|
2446 TUint a; |
|
2447 file.read((char *)&a, sizeof(TUint)); |
|
2448 if (file.eof()) |
|
2449 return Print(EError, "Verify failed.\nDifferent Rom sizes\n"); |
|
2450 if (a!=*ptr) |
|
2451 return Print(EError, "Verify failed.\nContents differ at Rom address %08x\n", i+iObey->iRomLinearBase); |
|
2452 ptr++; |
|
2453 } |
|
2454 file.close(); |
|
2455 Print(EAlways, "Verify OK\n"); |
|
2456 return KErrNone; |
|
2457 } |
|
2458 |
|
2459 |
|
2460 char* E32Rom::AllocateRelocationTable(char* aAddr, TReloc*& aRelocTable) |
|
2461 { |
|
2462 if(iObey->SetArea().Count() > 1) |
|
2463 { |
|
2464 aRelocTable = reinterpret_cast<TReloc*>(aAddr); |
|
2465 |
|
2466 // Allocate one entry per non default area + 1 sentinel |
|
2467 // (Count() returns number of non default areas + 1 (the |
|
2468 // default area)) |
|
2469 TInt size = iObey->SetArea().Count() * sizeof(TReloc); |
|
2470 aAddr += Align(size); |
|
2471 } |
|
2472 else |
|
2473 { |
|
2474 aRelocTable = 0; |
|
2475 } |
|
2476 |
|
2477 return aAddr; |
|
2478 } |
|
2479 |
|
2480 |
|
2481 void E32Rom::FillInRelocationTable(TReloc* aRelocTable) |
|
2482 { |
|
2483 TReloc* p = aRelocTable; |
|
2484 TInt wastedBytes = 0; |
|
2485 |
|
2486 for (NonDefaultAreasIterator areaIt(iObey->SetArea()); |
|
2487 ! areaIt.IsDone(); |
|
2488 areaIt.GoToNext()) |
|
2489 { |
|
2490 Area& currentArea = areaIt.Current(); |
|
2491 |
|
2492 if (currentArea.UsedSize() > 0) |
|
2493 { |
|
2494 p->iLength = currentArea.UsedSize(); |
|
2495 p->iSrc = currentArea.SrcBaseAddr(); |
|
2496 p->iDest = currentArea.DestBaseAddr(); |
|
2497 ++p; |
|
2498 } |
|
2499 else |
|
2500 { |
|
2501 wastedBytes += sizeof(TReloc); |
|
2502 } |
|
2503 } |
|
2504 |
|
2505 if (aRelocTable != 0) |
|
2506 { |
|
2507 // Last entry acts as a sentinel |
|
2508 memset(p, 0, sizeof(*p)); |
|
2509 } |
|
2510 |
|
2511 if (wastedBytes > 0) |
|
2512 { |
|
2513 Print(EWarning, "Some areas are declared but not used\n"); |
|
2514 Print(EWarning, "%d bytes wasted in relocation table\n", wastedBytes); |
|
2515 } |
|
2516 } |
|
2517 |
|
2518 |
|
2519 /** |
|
2520 Link together the kernel extensions. |
|
2521 |
|
2522 Must be called only after space has been allocated in the ROM image |
|
2523 for the kernel extension. |
|
2524 */ |
|
2525 |
|
2526 void E32Rom::LinkKernelExtensions(TRomBuilderEntry* aExtArray[], TInt aExtCount) |
|
2527 { |
|
2528 /** |
|
2529 * The kernel extensions should never be linked together as part of extension ROMs. |
|
2530 */ |
|
2531 if (!iExtensionRomHeader) |
|
2532 { |
|
2533 TLinAddr* pLastNextExtAddr = &(iHeader->iExtensionFile); |
|
2534 |
|
2535 for (TInt i=0; i<aExtCount; ++i) |
|
2536 { |
|
2537 TRomBuilderEntry* curExt = aExtArray[i]; |
|
2538 *pLastNextExtAddr = ActualToRomAddress(curExt->RomEntry()); |
|
2539 pLastNextExtAddr = &(curExt->iRomImageHeader->iNextExtension); |
|
2540 } |
|
2541 |
|
2542 *pLastNextExtAddr = 0; |
|
2543 } |
|
2544 } |
|
2545 |
|
2546 void E32Rom::ProcessDllData() |
|
2547 { |
|
2548 DllDataEntry *entry = iObey->GetFirstDllDataEntry(); |
|
2549 TRomBuilderEntry *romEntry; |
|
2550 TLinAddr* aExportTbl; |
|
2551 void *aLocation; |
|
2552 TUint aDataAddr; |
|
2553 while(entry){ |
|
2554 // A Dll data may be patched either via the ordinal number (as in ABIv2), or via |
|
2555 // the address of the data field (as in ABIv1). |
|
2556 romEntry = entry->iRomNode->iRomFile->iRbEntry; |
|
2557 if((TInt)entry->iOrdinal != -1) { |
|
2558 |
|
2559 // const data symbol may belong in the Code section. Get the address of the data field via the |
|
2560 // export table. If the address lies within the Code or data section limits, |
|
2561 // get the corresponding location and update it.While considering the Data section limits don't |
|
2562 // include the Bss section, as it doesn't exist as yet in the image. |
|
2563 if(entry->iOrdinal < 1 || entry->iOrdinal > (TUint32)romEntry->iOrigHdr->iExportDirCount) |
|
2564 { |
|
2565 Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", entry->iOrdinal, romEntry->iName); |
|
2566 entry = entry->NextDllDataEntry(); |
|
2567 continue; |
|
2568 } |
|
2569 aExportTbl = (TLinAddr*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iExportDirOffset); |
|
2570 aDataAddr = (TInt32)(aExportTbl[entry->iOrdinal - 1] + entry->iOffset); |
|
2571 |
|
2572 if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) && |
|
2573 (aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \ |
|
2574 romEntry->iOrigHdr->iCodeSize)) ) |
|
2575 { |
|
2576 char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset); |
|
2577 aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase)); |
|
2578 memcpy(aLocation, &(entry->iNewValue), entry->iSize); |
|
2579 } |
|
2580 else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) && |
|
2581 (aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \ |
|
2582 romEntry->iOrigHdr->iDataSize )) ) |
|
2583 { |
|
2584 char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset); |
|
2585 aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase)); |
|
2586 memcpy(aLocation, &(entry->iNewValue), entry->iSize); |
|
2587 } |
|
2588 else |
|
2589 { |
|
2590 Print(EWarning, "Patchdata failed as address pointed by ordinal %d of DLL %s doesn't lie within Code or Data section limits\n", entry->iOrdinal, romEntry->iName); |
|
2591 } |
|
2592 |
|
2593 } |
|
2594 else if((TInt)entry->iDataAddress != -1) { |
|
2595 // const data symbol may belong in the Code section. If the address lies within the Code |
|
2596 // or data section limits, get the corresponding location and update it.While considering |
|
2597 // the Data section limits don't include the Bss section, as it doesn't exist as yet in the image. |
|
2598 aDataAddr = (TUint)(entry->iDataAddress + entry->iOffset); |
|
2599 if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) && |
|
2600 (aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \ |
|
2601 romEntry->iOrigHdr->iCodeSize )) ) |
|
2602 { |
|
2603 char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset); |
|
2604 aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase)); |
|
2605 memcpy(aLocation, &(entry->iNewValue), entry->iSize); |
|
2606 } |
|
2607 else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) && |
|
2608 (aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \ |
|
2609 romEntry->iOrigHdr->iDataSize )) ) |
|
2610 { |
|
2611 char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset); |
|
2612 aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase)); |
|
2613 memcpy(aLocation, &(entry->iNewValue), entry->iSize); |
|
2614 } |
|
2615 else |
|
2616 { |
|
2617 Print(EWarning, "Patchdata failed as address 0x%x specified for DLL %s doesn't lie within Code or Data section limits\n", entry->iOrdinal, romEntry->iName); |
|
2618 } |
|
2619 } |
|
2620 else { |
|
2621 } |
|
2622 entry = entry->NextDllDataEntry(); |
|
2623 } |
|
2624 } |
|
2625 |
|
2626 TInt E32Rom::CheckUnpagedMemSize() |
|
2627 { |
|
2628 |
|
2629 if (H.iVerbose && gPagedRom) |
|
2630 { |
|
2631 Print(EDiagnostic, "iMaxUnpagedMemSize 0x%08x (%d)\n", iObey->iMaxUnpagedMemSize, iObey->iMaxUnpagedMemSize); |
|
2632 } |
|
2633 |
|
2634 // Only check if the iMaxUnpagedMemSize is set |
|
2635 if (iObey->iMaxUnpagedMemSize <= 0) return KErrNone; |
|
2636 |
|
2637 // Only for paged rom |
|
2638 if (!gPagedRom) |
|
2639 { |
|
2640 Print(EWarning, "The unpaged size overflow check is skipped.\n"); |
|
2641 return KErrNone; |
|
2642 } |
|
2643 |
|
2644 if (iHeader->iPageableRomStart > 0) |
|
2645 { |
|
2646 if (iHeader->iPageableRomStart > iObey->iMaxUnpagedMemSize) |
|
2647 { |
|
2648 Print(EError, "Unpaged memory size overflow: require 0x%08x (%d) bytes while the maximum size is 0x%08x (%d) bytes\n", |
|
2649 iHeader->iPageableRomStart, |
|
2650 iHeader->iPageableRomStart, |
|
2651 iObey->iMaxUnpagedMemSize, |
|
2652 iObey->iMaxUnpagedMemSize); |
|
2653 |
|
2654 return KErrNoMemory; |
|
2655 } |
|
2656 } |
|
2657 else |
|
2658 { |
|
2659 Print(EWarning, "The size of unpaged memory is not available. The unpaged memory overflow checking is skipped.\n"); |
|
2660 } |
|
2661 |
|
2662 return KErrNone; |
|
2663 } |
|
2664 |
|
2665 TRomNode* E32Rom::RootDirectory() |
|
2666 { |
|
2667 return iObey->iRootDirectory; |
|
2668 } |
|
2669 |
|
2670 TText* E32Rom::RomFileName() |
|
2671 { |
|
2672 return iObey->iRomFileName; |
|
2673 } |
|
2674 |
|
2675 TUint32 E32Rom::RomBase() |
|
2676 { |
|
2677 return iHeader->iRomBase; |
|
2678 } |
|
2679 |
|
2680 TUint32 E32Rom::RomSize() |
|
2681 { |
|
2682 return iHeader->iRomSize; |
|
2683 } |
|
2684 |
|
2685 TVersion E32Rom::Version() |
|
2686 { |
|
2687 return iHeader->iVersion; |
|
2688 } |
|
2689 |
|
2690 TInt64 E32Rom::Time() |
|
2691 { |
|
2692 return iHeader->iTime; |
|
2693 } |
|
2694 |
|
2695 TUint32 E32Rom::CheckSum() |
|
2696 { |
|
2697 return iHeader->iCheckSum; |
|
2698 } |
|
2699 |
|
2700 TUint32 E32Rom::DataRunAddress() |
|
2701 { |
|
2702 return iObey->iDataRunAddress; |
|
2703 } |
|
2704 |
|
2705 TUint32 E32Rom::RomAlign() |
|
2706 { |
|
2707 return iObey->iRomAlign; |
|
2708 } |