]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf32Convert.c
ArmLib/ArmV7Mmu: use 64-bit type for mapping region size
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf32Convert.c
CommitLineData
f51461c8 1/** @file\r
97fa0ee9 2Elf32 Convert solution\r
f51461c8 3\r
97fa0ee9 4Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
f51461c8
LG
5Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>\r
6\r
7This program and the accompanying materials are licensed and made available\r
8under the terms and conditions of the BSD License which accompanies this\r
9distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "WinNtInclude.h"\r
18\r
19#ifndef __GNUC__\r
20#include <windows.h>\r
21#include <io.h>\r
22#endif\r
23#include <assert.h>\r
24#include <stdio.h>\r
25#include <stdlib.h>\r
26#include <string.h>\r
27#include <time.h>\r
28#include <ctype.h>\r
29\r
30#include <Common/UefiBaseTypes.h>\r
31#include <IndustryStandard/PeImage.h>\r
32\r
33#include "PeCoffLib.h"\r
34#include "EfiUtilityMsgs.h"\r
35\r
36#include "GenFw.h"\r
37#include "ElfConvert.h"\r
38#include "Elf32Convert.h"\r
39\r
40STATIC\r
41VOID\r
42ScanSections32 (\r
43 VOID\r
44 );\r
45\r
46STATIC\r
47BOOLEAN\r
48WriteSections32 (\r
49 SECTION_FILTER_TYPES FilterType\r
50 );\r
51\r
52STATIC\r
53VOID\r
54WriteRelocations32 (\r
55 VOID\r
56 );\r
57\r
58STATIC\r
59VOID\r
60WriteDebug32 (\r
61 VOID\r
62 );\r
63\r
64STATIC\r
65VOID\r
66SetImageSize32 (\r
67 VOID\r
68 );\r
69\r
70STATIC\r
71VOID\r
72CleanUp32 (\r
73 VOID\r
74 );\r
75\r
76//\r
77// Rename ELF32 strucutres to common names to help when porting to ELF64.\r
78//\r
79typedef Elf32_Shdr Elf_Shdr;\r
80typedef Elf32_Ehdr Elf_Ehdr;\r
81typedef Elf32_Rel Elf_Rel;\r
82typedef Elf32_Sym Elf_Sym;\r
83typedef Elf32_Phdr Elf_Phdr;\r
84typedef Elf32_Dyn Elf_Dyn;\r
85#define ELFCLASS ELFCLASS32\r
86#define ELF_R_TYPE(r) ELF32_R_TYPE(r)\r
87#define ELF_R_SYM(r) ELF32_R_SYM(r)\r
88\r
89//\r
90// Well known ELF structures.\r
91//\r
92STATIC Elf_Ehdr *mEhdr;\r
93STATIC Elf_Shdr *mShdrBase;\r
94STATIC Elf_Phdr *mPhdrBase;\r
95\r
96//\r
97// Coff information\r
98//\r
54b1b57a 99STATIC UINT32 mCoffAlignment = 0x20;\r
f51461c8
LG
100\r
101//\r
102// PE section alignment.\r
103//\r
0192b71c 104STATIC const UINT16 mCoffNbrSections = 4;\r
f51461c8
LG
105\r
106//\r
107// ELF sections to offset in Coff file.\r
108//\r
109STATIC UINT32 *mCoffSectionsOffset = NULL;\r
110\r
111//\r
112// Offsets in COFF file\r
113//\r
114STATIC UINT32 mNtHdrOffset;\r
115STATIC UINT32 mTextOffset;\r
116STATIC UINT32 mDataOffset;\r
117STATIC UINT32 mHiiRsrcOffset;\r
118STATIC UINT32 mRelocOffset;\r
0192b71c 119STATIC UINT32 mDebugOffset;\r
f51461c8
LG
120\r
121//\r
122// Initialization Function\r
123//\r
124BOOLEAN\r
125InitializeElf32 (\r
126 UINT8 *FileBuffer,\r
127 ELF_FUNCTION_TABLE *ElfFunctions\r
128 )\r
129{\r
130 //\r
131 // Initialize data pointer and structures.\r
132 //\r
133 mEhdr = (Elf_Ehdr*) FileBuffer; \r
134\r
135 //\r
136 // Check the ELF32 specific header information.\r
137 //\r
138 if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) {\r
139 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32");\r
140 return FALSE;\r
141 }\r
142 if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
143 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
144 return FALSE;\r
145 } \r
146 if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {\r
147 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
148 return FALSE;\r
149 }\r
150 if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM))) { \r
151 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
152 return FALSE;\r
153 }\r
154 if (mEhdr->e_version != EV_CURRENT) {\r
155 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);\r
156 return FALSE;\r
157 }\r
158 \r
159 //\r
160 // Update section header pointers\r
161 //\r
162 mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff);\r
163 mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff);\r
164 \r
165 //\r
166 // Create COFF Section offset buffer and zero.\r
167 //\r
168 mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32));\r
169 memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32));\r
170\r
171 //\r
172 // Fill in function pointers.\r
173 //\r
174 ElfFunctions->ScanSections = ScanSections32;\r
175 ElfFunctions->WriteSections = WriteSections32;\r
176 ElfFunctions->WriteRelocations = WriteRelocations32;\r
177 ElfFunctions->WriteDebug = WriteDebug32;\r
178 ElfFunctions->SetImageSize = SetImageSize32;\r
179 ElfFunctions->CleanUp = CleanUp32;\r
180\r
181 return TRUE;\r
182}\r
183\r
184\r
185//\r
186// Header by Index functions\r
187//\r
188STATIC\r
189Elf_Shdr*\r
190GetShdrByIndex (\r
191 UINT32 Num\r
192 )\r
193{\r
194 if (Num >= mEhdr->e_shnum)\r
195 return NULL;\r
196 return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize);\r
197}\r
198\r
199STATIC\r
200Elf_Phdr*\r
201GetPhdrByIndex (\r
202 UINT32 num\r
203 )\r
204{\r
205 if (num >= mEhdr->e_phnum) {\r
206 return NULL;\r
207 }\r
208\r
209 return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize);\r
210}\r
211\r
212STATIC\r
213UINT32\r
214CoffAlign (\r
215 UINT32 Offset\r
216 )\r
217{\r
218 return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
219}\r
220\r
4f7d5c67
AB
221STATIC\r
222UINT32\r
223DebugRvaAlign (\r
224 UINT32 Offset\r
225 )\r
226{\r
227 return (Offset + 3) & ~3;\r
228}\r
229\r
f51461c8
LG
230//\r
231// filter functions\r
232//\r
233STATIC\r
234BOOLEAN\r
235IsTextShdr (\r
236 Elf_Shdr *Shdr\r
237 )\r
238{\r
239 return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC);\r
240}\r
241\r
242STATIC\r
243BOOLEAN\r
244IsHiiRsrcShdr (\r
245 Elf_Shdr *Shdr\r
246 )\r
247{\r
248 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
249\r
250 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);\r
251}\r
252\r
253STATIC\r
254BOOLEAN\r
255IsDataShdr (\r
256 Elf_Shdr *Shdr\r
257 )\r
258{\r
259 if (IsHiiRsrcShdr(Shdr)) {\r
260 return FALSE;\r
261 }\r
262 return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
263}\r
264\r
265//\r
266// Elf functions interface implementation\r
267//\r
268\r
269STATIC\r
270VOID\r
271ScanSections32 (\r
272 VOID\r
273 )\r
274{\r
275 UINT32 i;\r
276 EFI_IMAGE_DOS_HEADER *DosHdr;\r
277 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
278 UINT32 CoffEntry;\r
279 UINT32 SectionCount;\r
234f9ff9 280 BOOLEAN FoundSection;\r
f51461c8
LG
281\r
282 CoffEntry = 0;\r
283 mCoffOffset = 0;\r
f51461c8
LG
284\r
285 //\r
286 // Coff file start with a DOS header.\r
287 //\r
288 mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
289 mNtHdrOffset = mCoffOffset;\r
290 switch (mEhdr->e_machine) {\r
291 case EM_386:\r
292 case EM_ARM:\r
293 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
294 break;\r
295 default:\r
296 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
297 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
298 break;\r
299 }\r
300\r
301 mTableOffset = mCoffOffset;\r
302 mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
303\r
54b1b57a
AB
304 //\r
305 // Set mCoffAlignment to the maximum alignment of the input sections\r
306 // we care about\r
307 //\r
308 for (i = 0; i < mEhdr->e_shnum; i++) {\r
309 Elf_Shdr *shdr = GetShdrByIndex(i);\r
310 if (shdr->sh_addralign <= mCoffAlignment) {\r
311 continue;\r
312 }\r
313 if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {\r
314 mCoffAlignment = (UINT32)shdr->sh_addralign;\r
315 }\r
316 }\r
317\r
02a5421f
AB
318 //\r
319 // Move the PE/COFF header right before the first section. This will help us\r
320 // save space when converting to TE.\r
321 //\r
322 if (mCoffAlignment > mCoffOffset) {\r
323 mNtHdrOffset += mCoffAlignment - mCoffOffset;\r
324 mTableOffset += mCoffAlignment - mCoffOffset;\r
325 mCoffOffset = mCoffAlignment;\r
326 }\r
327\r
f51461c8
LG
328 //\r
329 // First text sections.\r
330 //\r
331 mCoffOffset = CoffAlign(mCoffOffset);\r
234f9ff9
EB
332 mTextOffset = mCoffOffset;\r
333 FoundSection = FALSE;\r
f51461c8
LG
334 SectionCount = 0;\r
335 for (i = 0; i < mEhdr->e_shnum; i++) {\r
336 Elf_Shdr *shdr = GetShdrByIndex(i);\r
337 if (IsTextShdr(shdr)) {\r
338 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
339 // the alignment field is valid\r
340 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
341 // if the section address is aligned we must align PE/COFF\r
342 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
343 } else {\r
344 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
345 }\r
346 }\r
347\r
348 /* Relocate entry. */\r
349 if ((mEhdr->e_entry >= shdr->sh_addr) &&\r
350 (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
351 CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr;\r
352 }\r
353\r
354 //\r
355 // Set mTextOffset with the offset of the first '.text' section\r
356 //\r
234f9ff9 357 if (!FoundSection) {\r
f51461c8 358 mTextOffset = mCoffOffset;\r
234f9ff9 359 FoundSection = TRUE;\r
f51461c8
LG
360 }\r
361\r
362 mCoffSectionsOffset[i] = mCoffOffset;\r
363 mCoffOffset += shdr->sh_size;\r
364 SectionCount ++;\r
365 }\r
366 }\r
367\r
234f9ff9 368 if (!FoundSection) {\r
f51461c8
LG
369 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
370 assert (FALSE);\r
371 }\r
372\r
4f7d5c67 373 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0bd0d6df 374 mCoffOffset = CoffAlign(mCoffOffset);\r
f51461c8
LG
375\r
376 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
377 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
378 }\r
379\r
380 //\r
381 // Then data sections.\r
382 //\r
383 mDataOffset = mCoffOffset;\r
234f9ff9 384 FoundSection = FALSE;\r
f51461c8
LG
385 SectionCount = 0;\r
386 for (i = 0; i < mEhdr->e_shnum; i++) {\r
387 Elf_Shdr *shdr = GetShdrByIndex(i);\r
388 if (IsDataShdr(shdr)) {\r
389 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
390 // the alignment field is valid\r
391 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
392 // if the section address is aligned we must align PE/COFF\r
393 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
394 } else {\r
395 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
396 }\r
397 }\r
234f9ff9
EB
398\r
399 //\r
400 // Set mDataOffset with the offset of the first '.data' section\r
401 //\r
402 if (!FoundSection) {\r
403 mDataOffset = mCoffOffset;\r
404 FoundSection = TRUE;\r
405 }\r
406\r
f51461c8
LG
407 mCoffSectionsOffset[i] = mCoffOffset;\r
408 mCoffOffset += shdr->sh_size;\r
409 SectionCount ++;\r
410 }\r
411 }\r
f51461c8
LG
412\r
413 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
414 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
415 }\r
416\r
0192b71c
AB
417 //\r
418 // Make room for .debug data in .data (or .text if .data is empty) instead of\r
419 // putting it in a section of its own. This is explicitly allowed by the\r
420 // PE/COFF spec, and prevents bloat in the binary when using large values for\r
421 // section alignment.\r
422 //\r
423 if (SectionCount > 0) {\r
4f7d5c67 424 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0192b71c
AB
425 }\r
426 mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
427 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
428 strlen(mInImageName) + 1;\r
429\r
430 mCoffOffset = CoffAlign(mCoffOffset);\r
431 if (SectionCount == 0) {\r
432 mDataOffset = mCoffOffset;\r
433 }\r
434\r
f51461c8
LG
435 //\r
436 // The HII resource sections.\r
437 //\r
438 mHiiRsrcOffset = mCoffOffset;\r
439 for (i = 0; i < mEhdr->e_shnum; i++) {\r
440 Elf_Shdr *shdr = GetShdrByIndex(i);\r
441 if (IsHiiRsrcShdr(shdr)) {\r
442 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
443 // the alignment field is valid\r
444 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
445 // if the section address is aligned we must align PE/COFF\r
446 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
447 } else {\r
448 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
449 }\r
450 }\r
451 if (shdr->sh_size != 0) {\r
234f9ff9 452 mHiiRsrcOffset = mCoffOffset;\r
f51461c8
LG
453 mCoffSectionsOffset[i] = mCoffOffset;\r
454 mCoffOffset += shdr->sh_size;\r
455 mCoffOffset = CoffAlign(mCoffOffset);\r
456 SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);\r
457 }\r
458 break;\r
459 }\r
460 }\r
461\r
462 mRelocOffset = mCoffOffset;\r
463\r
464 //\r
465 // Allocate base Coff file. Will be expanded later for relocations.\r
466 //\r
467 mCoffFile = (UINT8 *)malloc(mCoffOffset);\r
468 memset(mCoffFile, 0, mCoffOffset);\r
469\r
470 //\r
471 // Fill headers.\r
472 //\r
473 DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;\r
474 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
475 DosHdr->e_lfanew = mNtHdrOffset;\r
476\r
477 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);\r
478\r
479 NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
480\r
481 switch (mEhdr->e_machine) {\r
482 case EM_386:\r
483 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
484 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
485 break;\r
486 case EM_ARM:\r
487 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
488 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
489 break;\r
490 default:\r
491 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
492 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
493 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
494 }\r
495\r
496 NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections;\r
497 NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
498 mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;\r
499 NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
500 NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
501 NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
502 NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
503 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
504 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
505 | EFI_IMAGE_FILE_32BIT_MACHINE;\r
506\r
507 NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;\r
508 NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;\r
509 NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
510 NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
511\r
512 NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset;\r
513\r
514 NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset;\r
515 NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
516 NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment;\r
517 NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment;\r
518 NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
519\r
520 NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset;\r
521 NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
522\r
523 //\r
524 // Section headers.\r
525 //\r
526 if ((mDataOffset - mTextOffset) > 0) {\r
527 CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,\r
528 EFI_IMAGE_SCN_CNT_CODE\r
529 | EFI_IMAGE_SCN_MEM_EXECUTE\r
530 | EFI_IMAGE_SCN_MEM_READ);\r
531 } else {\r
532 // Don't make a section of size 0.\r
533 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
534 }\r
535\r
536 if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
537 CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
538 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
539 | EFI_IMAGE_SCN_MEM_WRITE\r
540 | EFI_IMAGE_SCN_MEM_READ);\r
541 } else {\r
542 // Don't make a section of size 0.\r
543 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
544 }\r
545\r
546 if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
547 CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
548 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
549 | EFI_IMAGE_SCN_MEM_READ);\r
550\r
551 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;\r
552 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;\r
553 } else {\r
554 // Don't make a section of size 0.\r
555 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
556 }\r
557\r
558}\r
559\r
560STATIC\r
561BOOLEAN\r
562WriteSections32 (\r
563 SECTION_FILTER_TYPES FilterType\r
564 )\r
565{\r
566 UINT32 Idx;\r
567 Elf_Shdr *SecShdr;\r
568 UINT32 SecOffset;\r
569 BOOLEAN (*Filter)(Elf_Shdr *);\r
570\r
571 //\r
572 // Initialize filter pointer\r
573 //\r
574 switch (FilterType) {\r
575 case SECTION_TEXT:\r
576 Filter = IsTextShdr;\r
577 break;\r
578 case SECTION_HII:\r
579 Filter = IsHiiRsrcShdr;\r
580 break;\r
581 case SECTION_DATA:\r
582 Filter = IsDataShdr;\r
583 break;\r
584 default:\r
585 return FALSE;\r
586 }\r
587\r
588 //\r
589 // First: copy sections.\r
590 //\r
591 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
592 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
593 if ((*Filter)(Shdr)) {\r
594 switch (Shdr->sh_type) {\r
595 case SHT_PROGBITS:\r
596 /* Copy. */\r
597 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
598 (UINT8*)mEhdr + Shdr->sh_offset,\r
599 Shdr->sh_size);\r
600 break;\r
601\r
602 case SHT_NOBITS:\r
603 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
604 break;\r
605\r
606 default:\r
607 //\r
608 // Ignore for unkown section type.\r
609 //\r
610 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
611 break;\r
612 }\r
613 }\r
614 }\r
615\r
616 //\r
617 // Second: apply relocations.\r
618 //\r
619 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
620 //\r
621 // Determine if this is a relocation section.\r
622 //\r
623 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
624 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
625 continue;\r
626 }\r
627 \r
628 //\r
629 // Relocation section found. Now extract section information that the relocations\r
630 // apply to in the ELF data and the new COFF data.\r
631 //\r
632 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
633 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
634 \r
635 //\r
636 // Only process relocations for the current filter type.\r
637 //\r
638 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
639 UINT32 RelOffset;\r
640 \r
641 //\r
642 // Determine the symbol table referenced by the relocation data.\r
643 //\r
644 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
645 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
646\r
647 //\r
648 // Process all relocation entries for this section.\r
649 //\r
650 for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) {\r
651 //\r
652 // Set pointer to relocation entry\r
653 //\r
654 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset);\r
655 \r
656 //\r
657 // Set pointer to symbol table entry associated with the relocation entry.\r
658 //\r
659 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
660 \r
661 Elf_Shdr *SymShdr;\r
662 UINT8 *Targ;\r
663 UINT16 Address;\r
664\r
665 //\r
666 // Check section header index found in symbol table and get the section \r
667 // header location.\r
668 //\r
669 if (Sym->st_shndx == SHN_UNDEF\r
670 || Sym->st_shndx == SHN_ABS\r
671 || Sym->st_shndx > mEhdr->e_shnum) {\r
672 Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
673 }\r
674 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
675\r
676 //\r
677 // Convert the relocation data to a pointer into the coff file.\r
678 //\r
679 // Note: \r
680 // r_offset is the virtual address of the storage unit to be relocated.\r
681 // sh_addr is the virtual address for the base of the section.\r
682 //\r
683 Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
684\r
685 //\r
686 // Determine how to handle each relocation type based on the machine type.\r
687 //\r
688 if (mEhdr->e_machine == EM_386) {\r
689 switch (ELF_R_TYPE(Rel->r_info)) {\r
690 case R_386_NONE:\r
691 break;\r
692 case R_386_32:\r
693 //\r
694 // Absolute relocation.\r
695 // Converts Targ from a absolute virtual address to the absolute\r
696 // COFF address.\r
697 //\r
698 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
699 + mCoffSectionsOffset[Sym->st_shndx];\r
700 break;\r
701 case R_386_PC32:\r
702 //\r
703 // Relative relocation: Symbol - Ip + Addend\r
704 //\r
705 *(UINT32 *)Targ = *(UINT32 *)Targ\r
706 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
707 - (SecOffset - SecShdr->sh_addr);\r
708 break;\r
709 default:\r
710 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
711 }\r
712 } else if (mEhdr->e_machine == EM_ARM) {\r
713 switch (ELF32_R_TYPE(Rel->r_info)) {\r
714 case R_ARM_RBASE:\r
715 // No relocation - no action required\r
716 // break skipped\r
717\r
718 case R_ARM_PC24:\r
719 case R_ARM_XPC25:\r
720 case R_ARM_THM_PC22:\r
721 case R_ARM_THM_JUMP19:\r
722 case R_ARM_CALL:\r
723 case R_ARM_JMP24:\r
724 case R_ARM_THM_JUMP24: \r
725 case R_ARM_PREL31: \r
726 case R_ARM_MOVW_PREL_NC: \r
727 case R_ARM_MOVT_PREL:\r
728 case R_ARM_THM_MOVW_PREL_NC:\r
729 case R_ARM_THM_MOVT_PREL:\r
730 case R_ARM_THM_JMP6:\r
731 case R_ARM_THM_ALU_PREL_11_0:\r
732 case R_ARM_THM_PC12:\r
733 case R_ARM_REL32_NOI:\r
734 case R_ARM_ALU_PC_G0_NC:\r
735 case R_ARM_ALU_PC_G0:\r
736 case R_ARM_ALU_PC_G1_NC:\r
737 case R_ARM_ALU_PC_G1:\r
738 case R_ARM_ALU_PC_G2:\r
739 case R_ARM_LDR_PC_G1:\r
740 case R_ARM_LDR_PC_G2:\r
741 case R_ARM_LDRS_PC_G0:\r
742 case R_ARM_LDRS_PC_G1:\r
743 case R_ARM_LDRS_PC_G2:\r
744 case R_ARM_LDC_PC_G0:\r
745 case R_ARM_LDC_PC_G1:\r
746 case R_ARM_LDC_PC_G2:\r
747 case R_ARM_GOT_PREL:\r
748 case R_ARM_THM_JUMP11:\r
749 case R_ARM_THM_JUMP8:\r
750 case R_ARM_TLS_GD32:\r
751 case R_ARM_TLS_LDM32:\r
752 case R_ARM_TLS_IE32:\r
753 // Thease are all PC-relative relocations and don't require modification\r
754 // GCC does not seem to have the concept of a application that just needs to get relocated.\r
755 break;\r
756\r
757 case R_ARM_THM_MOVW_ABS_NC:\r
758 // MOVW is only lower 16-bits of the addres\r
759 Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
760 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
761 break;\r
762\r
763 case R_ARM_THM_MOVT_ABS:\r
764 // MOVT is only upper 16-bits of the addres\r
765 Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);\r
766 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
767 break;\r
768\r
769 case R_ARM_ABS32:\r
770 case R_ARM_RABS32:\r
771 //\r
772 // Absolute relocation.\r
773 //\r
774 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
775 break;\r
776\r
777 default:\r
778 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
779 }\r
780 }\r
781 }\r
782 }\r
783 }\r
784\r
785 return TRUE;\r
786}\r
787\r
788UINTN gMovwOffset = 0;\r
789\r
790STATIC\r
791VOID\r
792WriteRelocations32 (\r
793 VOID\r
794 )\r
795{\r
796 UINT32 Index;\r
797 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
798 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
799 BOOLEAN FoundRelocations;\r
800 Elf_Dyn *Dyn;\r
801 Elf_Rel *Rel;\r
802 UINTN RelElementSize;\r
803 UINTN RelSize;\r
804 UINTN RelOffset;\r
805 UINTN K;\r
806 UINT8 *Targ;\r
807 Elf32_Phdr *DynamicSegment;\r
808 Elf32_Phdr *TargetSegment;\r
809\r
810 for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
811 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
812 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
813 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
814 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
815 UINT32 RelIdx;\r
816\r
817 FoundRelocations = TRUE;\r
818 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
819 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
820\r
821 if (mEhdr->e_machine == EM_386) { \r
822 switch (ELF_R_TYPE(Rel->r_info)) {\r
823 case R_386_NONE:\r
824 case R_386_PC32:\r
825 //\r
826 // No fixup entry required.\r
827 //\r
828 break;\r
829 case R_386_32:\r
830 //\r
831 // Creates a relative relocation entry from the absolute entry.\r
832 //\r
833 CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]\r
834 + (Rel->r_offset - SecShdr->sh_addr),\r
835 EFI_IMAGE_REL_BASED_HIGHLOW);\r
836 break;\r
837 default:\r
838 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
839 }\r
840 } else if (mEhdr->e_machine == EM_ARM) {\r
841 switch (ELF32_R_TYPE(Rel->r_info)) {\r
842 case R_ARM_RBASE:\r
843 // No relocation - no action required\r
844 // break skipped\r
845\r
846 case R_ARM_PC24:\r
847 case R_ARM_XPC25:\r
848 case R_ARM_THM_PC22:\r
849 case R_ARM_THM_JUMP19:\r
850 case R_ARM_CALL:\r
851 case R_ARM_JMP24:\r
852 case R_ARM_THM_JUMP24: \r
853 case R_ARM_PREL31: \r
854 case R_ARM_MOVW_PREL_NC: \r
855 case R_ARM_MOVT_PREL:\r
856 case R_ARM_THM_MOVW_PREL_NC:\r
857 case R_ARM_THM_MOVT_PREL:\r
858 case R_ARM_THM_JMP6:\r
859 case R_ARM_THM_ALU_PREL_11_0:\r
860 case R_ARM_THM_PC12:\r
861 case R_ARM_REL32_NOI:\r
862 case R_ARM_ALU_PC_G0_NC:\r
863 case R_ARM_ALU_PC_G0:\r
864 case R_ARM_ALU_PC_G1_NC:\r
865 case R_ARM_ALU_PC_G1:\r
866 case R_ARM_ALU_PC_G2:\r
867 case R_ARM_LDR_PC_G1:\r
868 case R_ARM_LDR_PC_G2:\r
869 case R_ARM_LDRS_PC_G0:\r
870 case R_ARM_LDRS_PC_G1:\r
871 case R_ARM_LDRS_PC_G2:\r
872 case R_ARM_LDC_PC_G0:\r
873 case R_ARM_LDC_PC_G1:\r
874 case R_ARM_LDC_PC_G2:\r
875 case R_ARM_GOT_PREL:\r
876 case R_ARM_THM_JUMP11:\r
877 case R_ARM_THM_JUMP8:\r
878 case R_ARM_TLS_GD32:\r
879 case R_ARM_TLS_LDM32:\r
880 case R_ARM_TLS_IE32:\r
881 // Thease are all PC-relative relocations and don't require modification\r
882 break;\r
883\r
884 case R_ARM_THM_MOVW_ABS_NC:\r
885 CoffAddFixup (\r
886 mCoffSectionsOffset[RelShdr->sh_info]\r
887 + (Rel->r_offset - SecShdr->sh_addr),\r
888 EFI_IMAGE_REL_BASED_ARM_MOV32T\r
889 );\r
890\r
891 // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction\r
892 // Track this address so we can log an error for unsupported sequence of MOVW/MOVT\r
893 gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);\r
894 break;\r
895\r
896 case R_ARM_THM_MOVT_ABS:\r
897 if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {\r
898 Error (NULL, 0, 3000, "Not Supported", "PE/COFF requires MOVW+MOVT instruction sequence %x +4 != %x.", gMovwOffset, mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));\r
899 }\r
900 break;\r
901\r
902 case R_ARM_ABS32:\r
903 case R_ARM_RABS32:\r
904 CoffAddFixup (\r
905 mCoffSectionsOffset[RelShdr->sh_info]\r
906 + (Rel->r_offset - SecShdr->sh_addr),\r
907 EFI_IMAGE_REL_BASED_HIGHLOW\r
908 );\r
909 break;\r
910\r
911 default:\r
912 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
913 }\r
914 } else {\r
915 Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine);\r
916 }\r
917 }\r
918 }\r
919 }\r
920 }\r
921\r
922 if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {\r
923 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
924\r
925 for (Index = 0; Index < mEhdr->e_phnum; Index++) {\r
926 RelElementSize = 0;\r
927 RelSize = 0;\r
928 RelOffset = 0;\r
929\r
930 DynamicSegment = GetPhdrByIndex (Index);\r
931\r
932 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
933 Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);\r
934\r
935 while (Dyn->d_tag != DT_NULL) {\r
936 switch (Dyn->d_tag) {\r
937 case DT_REL:\r
938 RelOffset = Dyn->d_un.d_val;\r
939 break;\r
940\r
941 case DT_RELSZ:\r
942 RelSize = Dyn->d_un.d_val;\r
943 break;\r
944\r
945 case DT_RELENT:\r
946 RelElementSize = Dyn->d_un.d_val;\r
947 break;\r
948\r
949 default:\r
950 break;\r
951 }\r
952 Dyn++;\r
953 }\r
954 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
955 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
956 }\r
957\r
958 for (K = 0; K < RelSize; K += RelElementSize) {\r
959\r
960 if (DynamicSegment->p_paddr == 0) {\r
961 // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL\r
962 // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools\r
963 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);\r
964 } else {\r
965 // This is how it reads in the generic ELF specification\r
966 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);\r
967 }\r
968\r
969 switch (ELF32_R_TYPE (Rel->r_info)) {\r
970 case R_ARM_RBASE:\r
971 break;\r
972\r
973 case R_ARM_RABS32:\r
974 TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
975\r
976 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.\r
977 Targ = mCoffFile + mCoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
978\r
979 *(UINT32 *)Targ = *(UINT32 *)Targ + mCoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
980\r
981 CoffAddFixup (mCoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
982 break;\r
983 \r
984 default:\r
985 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
986 break;\r
987 }\r
988 }\r
989 break;\r
990 }\r
991 }\r
992 }\r
993\r
994 //\r
995 // Pad by adding empty entries.\r
996 //\r
997 while (mCoffOffset & (mCoffAlignment - 1)) {\r
998 CoffAddFixupEntry(0);\r
999 }\r
1000\r
1001 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1002 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1003 Dir->Size = mCoffOffset - mRelocOffset;\r
1004 if (Dir->Size == 0) {\r
1005 // If no relocations, null out the directory entry and don't add the .reloc section\r
1006 Dir->VirtualAddress = 0;\r
1007 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1008 } else {\r
1009 Dir->VirtualAddress = mRelocOffset;\r
1010 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1011 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1012 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1013 | EFI_IMAGE_SCN_MEM_READ);\r
1014 }\r
1015\r
1016}\r
1017\r
1018STATIC\r
1019VOID\r
1020WriteDebug32 (\r
1021 VOID\r
1022 )\r
1023{\r
1024 UINT32 Len;\r
f51461c8
LG
1025 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1026 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1027 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1028 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1029\r
1030 Len = strlen(mInImageName) + 1;\r
f51461c8 1031\r
0192b71c 1032 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1033 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1034 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1035 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1036 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1037\r
1038 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1039 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1040 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1041\r
1042\r
1043 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1044 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c
AB
1045 DataDir->VirtualAddress = mDebugOffset;\r
1046 DataDir->Size = Dir->SizeOfData + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1047}\r
1048\r
1049STATIC\r
1050VOID\r
1051SetImageSize32 (\r
1052 VOID\r
1053 )\r
1054{\r
1055 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1056 \r
1057 //\r
1058 // Set image size\r
1059 //\r
1060 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1061 NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;\r
1062}\r
1063\r
1064STATIC\r
1065VOID\r
1066CleanUp32 (\r
1067 VOID\r
1068 )\r
1069{\r
1070 if (mCoffSectionsOffset != NULL) {\r
1071 free (mCoffSectionsOffset);\r
1072 }\r
1073}\r
1074\r
1075\r