3 Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 #include "PeCoffLoaderEx.h"
29 #ifdef EFI_NT_EMULATOR
31 #include "EfiHobLib.h"
32 #include EFI_PPI_DEFINITION (NtLoadAsDll)
37 PeCoffLoaderGetPeHeader (
38 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
39 OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
44 PeCoffLoaderImageAddress (
45 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
51 PeCoffLoaderGetImageInfo (
52 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
53 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
58 PeCoffLoaderRelocateImage (
59 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
60 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
65 PeCoffLoaderLoadImage (
66 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
67 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
72 PeCoffLoaderUnloadImage (
73 IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
76 #if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE)
78 AsmEfiSetBreakSupport (
83 EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader
= {
84 PeCoffLoaderGetImageInfo
,
85 PeCoffLoaderLoadImage
,
86 PeCoffLoaderRelocateImage
,
87 PeCoffLoaderUnloadImage
90 #ifdef EFI_NT_EMULATOR
91 EFI_NT_LOAD_AS_DLL_PPI
*mPeCoffLoaderWinNtLoadAsDll
= NULL
;
95 InstallEfiPeiPeCoffLoader (
96 IN EFI_PEI_SERVICES
**PeiServices
,
97 IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL
**This
,
98 IN EFI_PEI_PPI_DESCRIPTOR
*ThisPpi
104 Install PE/COFF loader PPI
108 PeiServices - General purpose services available to every PEIM
110 This - Pointer to get Pei PE coff loader protocol as output
112 ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform
122 Status
= EFI_SUCCESS
;
124 #ifdef EFI_NT_EMULATOR
126 // For use by PEI Core and Modules
128 if (NULL
!= PeiServices
) {
129 Status
= (**PeiServices
).LocatePpi (
131 &gEfiNtLoadAsDllPpiGuid
,
134 &mPeCoffLoaderWinNtLoadAsDll
138 // Now in SecMain or ERM usage, bind appropriately
140 PEI_ASSERT (PeiServices
, (NULL
!= ThisPpi
));
142 mPeCoffLoaderWinNtLoadAsDll
= (EFI_NT_LOAD_AS_DLL_PPI
*) ThisPpi
;
143 PEI_ASSERT (PeiServices
, (NULL
!= mPeCoffLoaderWinNtLoadAsDll
));
148 *This
= &mPeCoffLoader
;
156 PeCoffLoaderGetPeHeader (
157 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
158 OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
164 Retrieves the PE or TE Header from a PE/COFF or TE image
168 ImageContext - The context of the image being loaded
170 PeHdr - The buffer in which to return the PE32, PE32+, or TE header
174 EFI_SUCCESS if the PE or TE Header is read,
175 Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
180 EFI_IMAGE_DOS_HEADER DosHdr
;
185 // Read the DOS image header to check for it's existance
187 Size
= sizeof (EFI_IMAGE_DOS_HEADER
);
188 Status
= ImageContext
->ImageRead (
189 ImageContext
->Handle
,
194 if (EFI_ERROR (Status
)) {
195 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
199 ImageContext
->PeCoffHeaderOffset
= 0;
200 if (DosHdr
.e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
202 // DOS image header is present, so read the PE header after the DOS image
205 ImageContext
->PeCoffHeaderOffset
= DosHdr
.e_lfanew
;
209 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
210 // data, but that should not hurt anythine. Hdr.Pe32->OptionalHeader.Magic
211 // determins if this is a PE32 or PE32+ image. The magic is in the same
212 // location in both images.
214 Size
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
215 Status
= ImageContext
->ImageRead (
216 ImageContext
->Handle
,
217 ImageContext
->PeCoffHeaderOffset
,
221 if (EFI_ERROR (Status
)) {
222 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
227 // Use Signature to figure out if we understand the image format
229 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
230 ImageContext
->IsTeImage
= TRUE
;
231 ImageContext
->Machine
= Hdr
.Te
->Machine
;
232 ImageContext
->ImageType
= (UINT16
)(Hdr
.Te
->Subsystem
);
233 ImageContext
->ImageSize
= 0;
234 ImageContext
->SectionAlignment
= 4096;
235 ImageContext
->SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
237 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
238 ImageContext
->IsTeImage
= FALSE
;
239 ImageContext
->Machine
= Hdr
.Pe32
->FileHeader
.Machine
;
242 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
243 // It is for backward-compatibility consideration, because
244 // some system will generate PE32+ image with PE32 Magic.
246 if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
247 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
248 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
249 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
250 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
) {
251 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
253 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
256 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
||
257 Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
259 // PE32 and PE32+ have the same offset for these fields.
260 // We use PE32 for both PE32 and PE32+ headers here.
262 ImageContext
->ImageType
= Hdr
.Pe32
->OptionalHeader
.Subsystem
;
263 ImageContext
->ImageSize
= (UINT64
)Hdr
.Pe32
->OptionalHeader
.SizeOfImage
;
264 ImageContext
->SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
265 ImageContext
->SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
268 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE
;
269 return EFI_UNSUPPORTED
;
272 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE
;
273 return EFI_UNSUPPORTED
;
276 if (!PeCoffLoaderImageFormatSupported (ImageContext
->Machine
)) {
278 // If the PE/COFF loader does not support the image type return
279 // unsupported. This library can suport lots of types of images
280 // this does not mean the user of this library can call the entry
281 // point of the image.
283 return EFI_UNSUPPORTED
;
291 PeCoffLoaderCheckImageType (
292 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
298 Checks the PE or TE header of a PE/COFF or TE image to determine if it supported
302 ImageContext - The context of the image being loaded
306 EFI_SUCCESS if the PE/COFF or TE image is supported
307 EFI_UNSUPPORTED of the PE/COFF or TE image is not supported.
311 switch (ImageContext
->ImageType
) {
313 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
314 ImageContext
->ImageCodeMemoryType
= EfiLoaderCode
;
315 ImageContext
->ImageDataMemoryType
= EfiLoaderData
;
318 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
319 ImageContext
->ImageCodeMemoryType
= EfiBootServicesCode
;
320 ImageContext
->ImageDataMemoryType
= EfiBootServicesData
;
323 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
324 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
325 ImageContext
->ImageCodeMemoryType
= EfiRuntimeServicesCode
;
326 ImageContext
->ImageDataMemoryType
= EfiRuntimeServicesData
;
330 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_SUBSYSTEM
;
331 return EFI_UNSUPPORTED
;
339 PeCoffLoaderGetImageInfo (
340 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
341 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
347 Retrieves information on a PE/COFF image
351 This - Calling context
353 ImageContext - The context of the image being loaded
357 EFI_SUCCESS if the information on the PE/COFF image was collected.
358 EFI_UNSUPPORTED of the PE/COFF image is not supported.
359 Otherwise, the error status from reading the PE/COFF image using the
360 ImageContext->ImageRead() function
362 EFI_INVALID_PARAMETER - ImageContext is NULL.
367 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData
;
368 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
369 EFI_IMAGE_DATA_DIRECTORY
*DebugDirectoryEntry
;
372 UINTN DebugDirectoryEntryRva
;
373 UINTN DebugDirectoryEntryFileOffset
;
374 UINTN SectionHeaderOffset
;
375 EFI_IMAGE_SECTION_HEADER SectionHeader
;
376 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry
;
377 UINT32 NumberOfRvaAndSizes
;
380 if (NULL
== ImageContext
) {
381 return EFI_INVALID_PARAMETER
;
387 ImageContext
->ImageError
= EFI_IMAGE_ERROR_SUCCESS
;
389 Hdr
.Union
= &HdrData
;
390 Status
= PeCoffLoaderGetPeHeader (ImageContext
, Hdr
);
391 if (EFI_ERROR (Status
)) {
396 // Verify machine type
398 Status
= PeCoffLoaderCheckImageType (ImageContext
);
399 if (EFI_ERROR (Status
)) {
403 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
406 // Retrieve the base address of the image
408 if (!(ImageContext
->IsTeImage
)) {
411 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
412 // It is for backward-compatibility consideration, because
413 // some system will generate PE32+ image with PE32 Magic.
415 if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
416 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
417 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
418 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
419 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
) {
420 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
422 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
425 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
429 ImageContext
->ImageAddress
= Hdr
.Pe32
->OptionalHeader
.ImageBase
;
434 ImageContext
->ImageAddress
= Hdr
.Pe32Plus
->OptionalHeader
.ImageBase
;
437 ImageContext
->ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(Hdr
.Te
->ImageBase
+ Hdr
.Te
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
));
441 // Initialize the alternate destination address to 0 indicating that it
442 // should not be used.
444 ImageContext
->DestinationAddress
= 0;
447 // Initialize the codeview pointer.
449 ImageContext
->CodeView
= NULL
;
450 ImageContext
->PdbPointer
= NULL
;
453 // Three cases with regards to relocations:
454 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
455 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
456 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
457 // has no base relocs to apply
458 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
460 // Look at the file header to determine if relocations have been stripped, and
461 // save this info in the image context for later use.
463 if ((!(ImageContext
->IsTeImage
)) && ((Hdr
.Pe32
->FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0)) {
464 ImageContext
->RelocationsStripped
= TRUE
;
466 ImageContext
->RelocationsStripped
= FALSE
;
469 if (!(ImageContext
->IsTeImage
)) {
471 // Use PE32 to access fields that have same offset in PE32 and PE32+
473 ImageContext
->ImageSize
= (UINT64
) Hdr
.Pe32
->OptionalHeader
.SizeOfImage
;
474 ImageContext
->SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
475 ImageContext
->SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
476 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
480 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
481 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
486 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
487 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
490 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
492 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
495 // Determine the file offset of the debug directory... This means we walk
496 // the sections to find which section contains the RVA of the debug
499 DebugDirectoryEntryFileOffset
= 0;
501 SectionHeaderOffset
= (UINTN
)(
502 ImageContext
->PeCoffHeaderOffset
+
504 sizeof (EFI_IMAGE_FILE_HEADER
) +
505 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
508 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
510 // Read section header from file
512 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
513 Status
= ImageContext
->ImageRead (
514 ImageContext
->Handle
,
519 if (EFI_ERROR (Status
)) {
520 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
524 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
525 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
527 DebugDirectoryEntryFileOffset
= DebugDirectoryEntryRva
- SectionHeader
.VirtualAddress
+ SectionHeader
.PointerToRawData
;
531 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
534 if (DebugDirectoryEntryFileOffset
!= 0) {
535 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
++) {
537 // Read next debug directory entry
539 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
540 Status
= ImageContext
->ImageRead (
541 ImageContext
->Handle
,
542 DebugDirectoryEntryFileOffset
,
546 if (EFI_ERROR (Status
)) {
547 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
551 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
552 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
* sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
553 if (DebugEntry
.RVA
== 0 && DebugEntry
.FileOffset
!= 0) {
554 ImageContext
->ImageSize
+= DebugEntry
.SizeOfData
;
564 // Because Te image only extracts base relocations and debug directory entries from
565 // Pe image and in Te image header there is not a field to describe the imagesize,
566 // we use the largest VirtualAddress plus Size in each directory entry to describe the imagesize
568 ImageContext
->ImageSize
= (UINT64
) (Hdr
.Te
->DataDirectory
[0].VirtualAddress
+ Hdr
.Te
->DataDirectory
[0].Size
);
569 if(Hdr
.Te
->DataDirectory
[1].VirtualAddress
> Hdr
.Te
->DataDirectory
[0].VirtualAddress
) {
570 ImageContext
->ImageSize
= (UINT64
) (Hdr
.Te
->DataDirectory
[1].VirtualAddress
+ Hdr
.Te
->DataDirectory
[1].Size
);
572 ImageContext
->SectionAlignment
= 4096;
573 ImageContext
->SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
) Hdr
.Te
->BaseOfCode
- (UINTN
) Hdr
.Te
->StrippedSize
;
575 DebugDirectoryEntry
= &Hdr
.Te
->DataDirectory
[1];
576 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
577 SectionHeaderOffset
= (UINTN
)(sizeof (EFI_TE_IMAGE_HEADER
));
579 DebugDirectoryEntryFileOffset
= 0;
581 for (Index
= 0; Index
< Hdr
.Te
->NumberOfSections
; Index
++) {
583 // Read section header from file
585 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
586 Status
= ImageContext
->ImageRead (
587 ImageContext
->Handle
,
592 if (EFI_ERROR (Status
)) {
593 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
597 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
598 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
599 DebugDirectoryEntryFileOffset
= DebugDirectoryEntryRva
-
600 SectionHeader
.VirtualAddress
+
601 SectionHeader
.PointerToRawData
+
602 sizeof (EFI_TE_IMAGE_HEADER
) -
603 Hdr
.Te
->StrippedSize
;
607 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
610 if (DebugDirectoryEntryFileOffset
!= 0) {
611 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
++) {
613 // Read next debug directory entry
615 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
616 Status
= ImageContext
->ImageRead (
617 ImageContext
->Handle
,
618 DebugDirectoryEntryFileOffset
,
622 if (EFI_ERROR (Status
)) {
623 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
627 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
628 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
* sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
640 PeCoffLoaderImageAddress (
641 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
648 Converts an image address to the loaded address
652 ImageContext - The context of the image being loaded
654 Address - The address to be converted to the loaded address
658 NULL if the address can not be converted, otherwise, the converted address
662 if (Address
>= ImageContext
->ImageSize
) {
663 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
667 return (CHAR8
*) ((UINTN
) ImageContext
->ImageAddress
+ Address
);
672 PeCoffLoaderRelocateImage (
673 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
674 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
680 Relocates a PE/COFF image in memory
684 This - Calling context
686 ImageContext - Contains information on the loaded image to relocate
690 EFI_SUCCESS if the PE/COFF image was relocated
691 EFI_LOAD_ERROR if the image is not a valid PE/COFF image
692 EFI_UNSUPPORTED not support
697 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
698 EFI_IMAGE_DATA_DIRECTORY
*RelocDir
;
700 EFI_IMAGE_BASE_RELOCATION
*RelocBase
;
701 EFI_IMAGE_BASE_RELOCATION
*RelocBaseEnd
;
710 EFI_PHYSICAL_ADDRESS BaseAddress
;
711 UINT32 NumberOfRvaAndSizes
;
713 #ifdef EFI_NT_EMULATOR
720 if (NULL
== ImageContext
) {
721 return EFI_INVALID_PARAMETER
;
727 ImageContext
->ImageError
= EFI_IMAGE_ERROR_SUCCESS
;
730 // If there are no relocation entries, then we are done
732 if (ImageContext
->RelocationsStripped
) {
737 // If the destination address is not 0, use that rather than the
738 // image address as the relocation target.
740 if (ImageContext
->DestinationAddress
!= 0) {
741 BaseAddress
= ImageContext
->DestinationAddress
;
743 BaseAddress
= ImageContext
->ImageAddress
;
746 if (!(ImageContext
->IsTeImage
)) {
747 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)ImageContext
->ImageAddress
+ ImageContext
->PeCoffHeaderOffset
);
750 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
751 // It is for backward-compatibility consideration, because
752 // some system will generate PE32+ image with PE32 Magic.
754 if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
755 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
756 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
757 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
758 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
) {
759 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
761 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
764 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
768 Adjust
= (UINT64
)BaseAddress
- Hdr
.Pe32
->OptionalHeader
.ImageBase
;
769 Hdr
.Pe32
->OptionalHeader
.ImageBase
= (UINT32
)BaseAddress
;
771 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
772 RelocDir
= &Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
777 Adjust
= (UINT64
) BaseAddress
- Hdr
.Pe32Plus
->OptionalHeader
.ImageBase
;
778 Hdr
.Pe32Plus
->OptionalHeader
.ImageBase
= (UINT64
)BaseAddress
;
780 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
781 RelocDir
= &Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
785 // Find the relocation block
786 // Per the PE/COFF spec, you can't assume that a given data directory
787 // is present in the image. You have to check the NumberOfRvaAndSizes in
788 // the optional header to verify a desired directory entry is there.
791 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
&& RelocDir
->Size
> 0) {
792 RelocBase
= PeCoffLoaderImageAddress (ImageContext
, RelocDir
->VirtualAddress
);
793 RelocBaseEnd
= PeCoffLoaderImageAddress (
795 RelocDir
->VirtualAddress
+ RelocDir
->Size
- 1
797 if ((RelocBase
== NULL
) || (RelocBaseEnd
== NULL
)) {
799 // If the base start or end address resolved to 0, then fail.
801 return EFI_LOAD_ERROR
;
805 // Set base and end to bypass processing below.
807 RelocBase
= RelocBaseEnd
= 0;
810 Hdr
.Te
= (EFI_TE_IMAGE_HEADER
*)(UINTN
)(ImageContext
->ImageAddress
);
811 Adjust
= (UINT64
) (BaseAddress
- Hdr
.Te
->StrippedSize
+ sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->ImageBase
);
812 Hdr
.Te
->ImageBase
= (UINT64
) (BaseAddress
- Hdr
.Te
->StrippedSize
+ sizeof (EFI_TE_IMAGE_HEADER
));
815 // Find the relocation block
817 RelocDir
= &Hdr
.Te
->DataDirectory
[0];
818 if (RelocDir
->Size
> 0) {
819 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*)(UINTN
)(
820 ImageContext
->ImageAddress
+
821 RelocDir
->VirtualAddress
+
822 sizeof(EFI_TE_IMAGE_HEADER
) -
825 RelocBaseEnd
= (EFI_IMAGE_BASE_RELOCATION
*) ((UINTN
) RelocBase
+ (UINTN
) RelocDir
->Size
- 1);
828 // Set base and end to bypass processing below.
836 // Run the relocation information and apply the fixups
838 FixupData
= ImageContext
->FixupData
;
839 while (RelocBase
< RelocBaseEnd
) {
841 Reloc
= (UINT16
*) ((CHAR8
*) RelocBase
+ sizeof (EFI_IMAGE_BASE_RELOCATION
));
842 RelocEnd
= (UINT16
*) ((CHAR8
*) RelocBase
+ RelocBase
->SizeOfBlock
);
843 if (!(ImageContext
->IsTeImage
)) {
844 FixupBase
= PeCoffLoaderImageAddress (ImageContext
, RelocBase
->VirtualAddress
);
846 if (FixupBase
== NULL
) {
848 // If the FixupBase address resolved to 0, then fail.
850 return EFI_LOAD_ERROR
;
853 FixupBase
= (CHAR8
*)(UINTN
)(ImageContext
->ImageAddress
+
854 RelocBase
->VirtualAddress
+
855 sizeof(EFI_TE_IMAGE_HEADER
) -
860 if ((CHAR8
*) RelocEnd
< (CHAR8
*) ((UINTN
) ImageContext
->ImageAddress
) ||
861 (CHAR8
*) RelocEnd
> (CHAR8
*)((UINTN
)ImageContext
->ImageAddress
+
862 (UINTN
)ImageContext
->ImageSize
)) {
863 ImageContext
->ImageError
= EFI_IMAGE_ERROR_FAILED_RELOCATION
;
864 return EFI_LOAD_ERROR
;
868 // Run this relocation record
870 while (Reloc
< RelocEnd
) {
872 Fixup
= FixupBase
+ (*Reloc
& 0xFFF);
873 switch ((*Reloc
) >> 12) {
874 case EFI_IMAGE_REL_BASED_ABSOLUTE
:
877 case EFI_IMAGE_REL_BASED_HIGH
:
878 F16
= (UINT16
*) Fixup
;
879 *F16
= (UINT16
) (*F16
+ (UINT16
)(((UINT32
)Adjust
) >> 16));
880 if (FixupData
!= NULL
) {
881 *(UINT16
*) FixupData
= *F16
;
882 FixupData
= FixupData
+ sizeof (UINT16
);
886 case EFI_IMAGE_REL_BASED_LOW
:
887 F16
= (UINT16
*) Fixup
;
888 *F16
= (UINT16
) (*F16
+ (UINT16
) Adjust
);
889 if (FixupData
!= NULL
) {
890 *(UINT16
*) FixupData
= *F16
;
891 FixupData
= FixupData
+ sizeof (UINT16
);
895 case EFI_IMAGE_REL_BASED_HIGHLOW
:
896 F32
= (UINT32
*) Fixup
;
897 *F32
= *F32
+ (UINT32
) Adjust
;
898 if (FixupData
!= NULL
) {
899 FixupData
= ALIGN_POINTER (FixupData
, sizeof (UINT32
));
900 *(UINT32
*) FixupData
= *F32
;
901 FixupData
= FixupData
+ sizeof (UINT32
);
905 case EFI_IMAGE_REL_BASED_DIR64
:
909 F64
= (UINT64
*) Fixup
;
910 *F64
= *F64
+ (UINT64
) Adjust
;
911 if (FixupData
!= NULL
) {
912 FixupData
= ALIGN_POINTER (FixupData
, sizeof(UINT64
));
913 *(UINT64
*)(FixupData
) = *F64
;
914 FixupData
= FixupData
+ sizeof(UINT64
);
918 case EFI_IMAGE_REL_BASED_HIGHADJ
:
920 // Return the same EFI_UNSUPPORTED return code as
921 // PeCoffLoaderRelocateImageEx() returns if it does not recognize
922 // the relocation type.
924 ImageContext
->ImageError
= EFI_IMAGE_ERROR_FAILED_RELOCATION
;
925 return EFI_UNSUPPORTED
;
929 // The common code does not handle some of the stranger IPF relocations
930 // PeCoffLoaderRelocateImageEx () addes support for these complex fixups
931 // on IPF and is a No-Op on other archtiectures.
933 Status
= PeCoffLoaderRelocateImageEx (Reloc
, Fixup
, &FixupData
, Adjust
);
934 if (EFI_ERROR (Status
)) {
935 ImageContext
->ImageError
= EFI_IMAGE_ERROR_FAILED_RELOCATION
;
941 // Next relocation record
949 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*) RelocEnd
;
952 #ifdef EFI_NT_EMULATOR
953 DllEntryPoint
= NULL
;
954 ImageContext
->ModHandle
= NULL
;
956 // Load the DLL if it's not an EBC image.
958 if ((ImageContext
->PdbPointer
!= NULL
) &&
959 (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
)) {
960 Status
= mPeCoffLoaderWinNtLoadAsDll
->Entry (
961 ImageContext
->PdbPointer
,
966 if (!EFI_ERROR (Status
) && DllEntryPoint
!= NULL
) {
967 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) DllEntryPoint
;
968 ImageContext
->ModHandle
= ModHandle
;
978 PeCoffLoaderLoadImage (
979 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
980 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
986 Loads a PE/COFF image into memory
990 This - Calling context
992 ImageContext - Contains information on image to load into memory
996 EFI_SUCCESS if the PE/COFF image was loaded
997 EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
998 EFI_LOAD_ERROR if the image is a runtime driver with no relocations
999 EFI_INVALID_PARAMETER if the image address is invalid
1004 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1005 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT CheckContext
;
1006 EFI_IMAGE_SECTION_HEADER
*FirstSection
;
1007 EFI_IMAGE_SECTION_HEADER
*Section
;
1008 UINTN NumberOfSections
;
1013 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
1014 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
1016 UINT32 TempDebugEntryRva
;
1017 UINT32 NumberOfRvaAndSizes
;
1019 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
1020 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
1021 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
1022 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
1023 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
1026 if (NULL
== ImageContext
) {
1027 return EFI_INVALID_PARAMETER
;
1033 ImageContext
->ImageError
= EFI_IMAGE_ERROR_SUCCESS
;
1036 // Copy the provided context info into our local version, get what we
1037 // can from the original image, and then use that to make sure everything
1040 CopyMem (&CheckContext
, ImageContext
, sizeof (EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
));
1042 Status
= PeCoffLoaderGetImageInfo (This
, &CheckContext
);
1043 if (EFI_ERROR (Status
)) {
1048 // Make sure there is enough allocated space for the image being loaded
1050 if (ImageContext
->ImageSize
< CheckContext
.ImageSize
) {
1051 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_IMAGE_SIZE
;
1052 return EFI_BUFFER_TOO_SMALL
;
1054 if (ImageContext
->ImageAddress
== 0) {
1056 // Image cannot be loaded into 0 address.
1058 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
1059 return EFI_INVALID_PARAMETER
;
1062 // If there's no relocations, then make sure it's not a runtime driver,
1063 // and that it's being loaded at the linked address.
1065 if (CheckContext
.RelocationsStripped
) {
1067 // If the image does not contain relocations and it is a runtime driver
1068 // then return an error.
1070 if (CheckContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
1071 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_SUBSYSTEM
;
1072 return EFI_LOAD_ERROR
;
1075 // If the image does not contain relocations, and the requested load address
1076 // is not the linked address, then return an error.
1078 if (CheckContext
.ImageAddress
!= ImageContext
->ImageAddress
) {
1079 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
1080 return EFI_INVALID_PARAMETER
;
1084 // Make sure the allocated space has the proper section alignment
1086 if (!(ImageContext
->IsTeImage
)) {
1087 if ((ImageContext
->ImageAddress
& (CheckContext
.SectionAlignment
- 1)) != 0) {
1088 ImageContext
->ImageError
= EFI_IMAGE_ERROR_INVALID_SECTION_ALIGNMENT
;
1089 return EFI_INVALID_PARAMETER
;
1093 // Read the entire PE/COFF or TE header into memory
1095 if (!(ImageContext
->IsTeImage
)) {
1096 Status
= ImageContext
->ImageRead (
1097 ImageContext
->Handle
,
1099 &ImageContext
->SizeOfHeaders
,
1100 (VOID
*) (UINTN
) ImageContext
->ImageAddress
1103 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)ImageContext
->ImageAddress
+ ImageContext
->PeCoffHeaderOffset
);
1105 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
1106 (UINTN
)ImageContext
->ImageAddress
+
1107 ImageContext
->PeCoffHeaderOffset
+
1109 sizeof(EFI_IMAGE_FILE_HEADER
) +
1110 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1112 NumberOfSections
= (UINTN
) (Hdr
.Pe32
->FileHeader
.NumberOfSections
);
1114 Status
= ImageContext
->ImageRead (
1115 ImageContext
->Handle
,
1117 &ImageContext
->SizeOfHeaders
,
1118 (VOID
*)(UINTN
)ImageContext
->ImageAddress
1121 Hdr
.Te
= (EFI_TE_IMAGE_HEADER
*)(UINTN
)(ImageContext
->ImageAddress
);
1123 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
1124 (UINTN
)ImageContext
->ImageAddress
+
1125 sizeof(EFI_TE_IMAGE_HEADER
)
1127 NumberOfSections
= (UINTN
) (Hdr
.Te
->NumberOfSections
);
1131 if (EFI_ERROR (Status
)) {
1132 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
1133 return EFI_LOAD_ERROR
;
1137 // Load each section of the image
1139 Section
= FirstSection
;
1140 for (Index
= 0, MaxEnd
= NULL
; Index
< NumberOfSections
; Index
++) {
1143 // Compute sections address
1145 Base
= PeCoffLoaderImageAddress (ImageContext
, Section
->VirtualAddress
);
1146 End
= PeCoffLoaderImageAddress (
1148 Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
- 1
1150 if (ImageContext
->IsTeImage
) {
1151 Base
= (CHAR8
*)((UINTN
) Base
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
)Hdr
.Te
->StrippedSize
);
1152 End
= (CHAR8
*)((UINTN
) End
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
)Hdr
.Te
->StrippedSize
);
1159 // If the base start or end address resolved to 0, then fail.
1161 if ((Base
== NULL
) || (End
== NULL
)) {
1162 ImageContext
->ImageError
= EFI_IMAGE_ERROR_SECTION_NOT_LOADED
;
1163 return EFI_LOAD_ERROR
;
1169 Size
= (UINTN
) Section
->Misc
.VirtualSize
;
1170 if ((Size
== 0) || (Size
> Section
->SizeOfRawData
)) {
1171 Size
= (UINTN
) Section
->SizeOfRawData
;
1174 if (Section
->SizeOfRawData
) {
1175 if (!(ImageContext
->IsTeImage
)) {
1176 Status
= ImageContext
->ImageRead (
1177 ImageContext
->Handle
,
1178 Section
->PointerToRawData
,
1183 Status
= ImageContext
->ImageRead (
1184 ImageContext
->Handle
,
1185 Section
->PointerToRawData
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
)Hdr
.Te
->StrippedSize
,
1191 if (EFI_ERROR (Status
)) {
1192 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
1198 // If raw size is less then virt size, zero fill the remaining
1201 if (Size
< Section
->Misc
.VirtualSize
) {
1202 ZeroMem (Base
+ Size
, Section
->Misc
.VirtualSize
- Size
);
1211 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
1214 // Get image's entry point
1216 if (!(ImageContext
->IsTeImage
)) {
1219 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
1220 // It is for backward-compatibility consideration, because
1221 // some system will generate PE32+ image with PE32 Magic.
1223 if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
1224 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
1225 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
1226 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1227 } else if (Hdr
.Pe32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
) {
1228 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1230 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1234 // Sizes of AddressOfEntryPoint are different so we need to do this safely
1236 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PeCoffLoaderImageAddress (
1238 (UINTN
)Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
1242 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (
1243 (UINTN
)ImageContext
->ImageAddress
+
1244 (UINTN
)Hdr
.Te
->AddressOfEntryPoint
+
1245 (UINTN
)sizeof(EFI_TE_IMAGE_HEADER
) -
1246 (UINTN
)Hdr
.Te
->StrippedSize
1251 // Determine the size of the fixup data
1253 // Per the PE/COFF spec, you can't assume that a given data directory
1254 // is present in the image. You have to check the NumberOfRvaAndSizes in
1255 // the optional header to verify a desired directory entry is there.
1257 if (!(ImageContext
->IsTeImage
)) {
1258 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1262 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1263 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1268 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1269 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1272 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
1273 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1275 ImageContext
->FixupDataSize
= 0;
1278 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[0];
1279 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1282 // Consumer must allocate a buffer for the relocation fixup log.
1283 // Only used for runtime drivers.
1285 ImageContext
->FixupData
= NULL
;
1288 // Load the Codeview info if present
1290 if (ImageContext
->DebugDirectoryEntryRva
!= 0) {
1291 if (!(ImageContext
->IsTeImage
)) {
1292 DebugEntry
= PeCoffLoaderImageAddress (
1294 ImageContext
->DebugDirectoryEntryRva
1297 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(UINTN
)(
1298 ImageContext
->ImageAddress
+
1299 ImageContext
->DebugDirectoryEntryRva
+
1300 sizeof(EFI_TE_IMAGE_HEADER
) -
1301 Hdr
.Te
->StrippedSize
1305 if (DebugEntry
!= NULL
) {
1306 TempDebugEntryRva
= DebugEntry
->RVA
;
1307 if (DebugEntry
->RVA
== 0 && DebugEntry
->FileOffset
!= 0) {
1309 if ((UINTN
)Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
1310 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
;
1312 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->SizeOfRawData
;
1316 if (TempDebugEntryRva
!= 0) {
1317 if (!(ImageContext
->IsTeImage
)) {
1318 ImageContext
->CodeView
= PeCoffLoaderImageAddress (ImageContext
, TempDebugEntryRva
);
1320 ImageContext
->CodeView
= (VOID
*)(
1321 (UINTN
)ImageContext
->ImageAddress
+
1322 (UINTN
)TempDebugEntryRva
+
1323 (UINTN
)sizeof (EFI_TE_IMAGE_HEADER
) -
1324 (UINTN
) Hdr
.Te
->StrippedSize
1328 if (ImageContext
->CodeView
== NULL
) {
1329 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
1330 return EFI_LOAD_ERROR
;
1333 if (DebugEntry
->RVA
== 0) {
1334 Size
= DebugEntry
->SizeOfData
;
1335 if (!(ImageContext
->IsTeImage
)) {
1336 Status
= ImageContext
->ImageRead (
1337 ImageContext
->Handle
,
1338 DebugEntry
->FileOffset
,
1340 ImageContext
->CodeView
1343 Status
= ImageContext
->ImageRead (
1344 ImageContext
->Handle
,
1345 DebugEntry
->FileOffset
+ sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
,
1347 ImageContext
->CodeView
1350 // Should we apply fix up to this field according to the size difference between PE and TE?
1351 // Because now we maintain TE header fields unfixed, this field will also remain as they are
1352 // in original PE image.
1356 if (EFI_ERROR (Status
)) {
1357 ImageContext
->ImageError
= EFI_IMAGE_ERROR_IMAGE_READ
;
1358 return EFI_LOAD_ERROR
;
1361 DebugEntry
->RVA
= TempDebugEntryRva
;
1364 switch (*(UINT32
*) ImageContext
->CodeView
) {
1365 case CODEVIEW_SIGNATURE_NB10
:
1366 ImageContext
->PdbPointer
= (CHAR8
*)ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
1369 case CODEVIEW_SIGNATURE_RSDS
:
1370 ImageContext
->PdbPointer
= (CHAR8
*)ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
1380 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
1382 // Get Image's HII resource section
1384 if (!(ImageContext
->IsTeImage
)) {
1385 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1389 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
];
1394 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
];
1397 if (DirectoryEntry
->Size
!= 0) {
1398 Base
= PeCoffLoaderImageAddress (ImageContext
, DirectoryEntry
->VirtualAddress
);
1400 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) Base
;
1401 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
1403 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
1404 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
1405 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (Base
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
1407 if (ResourceDirectoryString
->Length
== 3 &&
1408 ResourceDirectoryString
->String
[0] == L
'H' &&
1409 ResourceDirectoryString
->String
[1] == L
'I' &&
1410 ResourceDirectoryString
->String
[2] == L
'I') {
1412 // Resource Type "HII" found
1414 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
1416 // Move to next level - resource Name
1418 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (Base
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
1419 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
1421 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
1423 // Move to next level - resource Language
1425 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (Base
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
1426 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
1431 // Now it ought to be resource Data
1433 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
1434 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (Base
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
1435 ImageContext
->HiiResourceData
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) PeCoffLoaderImageAddress (ImageContext
, ResourceDataEntry
->OffsetToData
);
1441 ResourceDirectoryEntry
++;
1447 #if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE)
1448 AsmEfiSetBreakSupport ((UINTN
)(ImageContext
->ImageAddress
));
1456 PeCoffLoaderUnloadImage (
1457 IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1461 Routine Description:
1463 Unload a PE/COFF image from memory
1467 ImageContext - Contains information on image to load into memory
1475 #ifdef EFI_NT_EMULATOR
1477 // Calling Win32 API free library
1479 mPeCoffLoaderWinNtLoadAsDll
->FreeLibrary (ImageContext
->ModHandle
);