3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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.
18 Wrap the Base PE/COFF loader with the PE COFF Protocol
23 #define IMAGE_64_MACHINE_TYPE_SUPPORTED(Machine) \
24 ((Machine) == EFI_IMAGE_MACHINE_IA32 || \
25 (Machine) == EFI_IMAGE_MACHINE_X64 || \
26 (Machine) == EFI_IMAGE_MACHINE_EBC)
30 PeCoffLoader64GetPeHeader (
31 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
32 OUT EFI_IMAGE_NT_HEADERS64
*PeHdr
37 PeCoffLoader64CheckImageType (
38 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
39 IN EFI_IMAGE_NT_HEADERS64
*PeHdr
44 PeCoffLoader64ImageAddress (
45 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
51 PeCoffLoader64GetImageInfo (
52 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
53 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
58 PeCoffLoader64RelocateImage (
59 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
60 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
65 PeCoffLoader64LoadImage (
66 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
67 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
72 PeCoffLoader64UnloadImage (
73 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
74 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
78 PeCoffLoader64RelocateImageEx (
81 IN OUT CHAR8
**FixupData
,
85 EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoaderX64
= {
86 PeCoffLoader64GetImageInfo
,
87 PeCoffLoader64LoadImage
,
88 PeCoffLoader64RelocateImage
,
89 PeCoffLoader64UnloadImage
94 PeCoffLoader64GetPeHeader (
95 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
96 OUT EFI_IMAGE_NT_HEADERS64
*PeHdr
101 Retrieves the PE Header from a PE/COFF image
104 ImageContext - The context of the image being loaded
105 PeHdr - The buffer in which to return the PE header
108 EFI_SUCCESS if the PE Header is read,
109 Otherwise, the error status from reading the PE/COFF image using the ImageRead function.
114 EFI_IMAGE_DOS_HEADER DosHdr
;
118 // Read the DOS image headers
120 Size
= sizeof (EFI_IMAGE_DOS_HEADER
);
121 Status
= ImageContext
->ImageRead (
122 ImageContext
->Handle
,
127 if (EFI_ERROR (Status
)) {
128 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
132 ImageContext
->PeCoffHeaderOffset
= 0;
133 if (DosHdr
.e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
135 // DOS image header is present, so read the PE header after the DOS image header
137 ImageContext
->PeCoffHeaderOffset
= DosHdr
.e_lfanew
;
141 // Read the PE/COFF Header
143 Size
= sizeof (EFI_IMAGE_NT_HEADERS64
);
144 Status
= ImageContext
->ImageRead (
145 ImageContext
->Handle
,
146 ImageContext
->PeCoffHeaderOffset
,
150 if (EFI_ERROR (Status
)) {
151 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
160 PeCoffLoader64CheckImageType (
161 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
162 IN EFI_IMAGE_NT_HEADERS64
*PeHdr
167 Checks the PE header of a PE/COFF image to determine if it supported
170 ImageContext - The context of the image being loaded
171 PeHdr - The buffer in which to return the PE header
174 EFI_SUCCESS if the PE/COFF image is supported
175 EFI_UNSUPPORTED of the PE/COFF image is not supported.
180 // Check the PE/COFF Header SIgnature
182 if (PeHdr
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
183 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE
;
184 return EFI_UNSUPPORTED
;
188 // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based)
189 // and the machine type for the Virtual Machine.
191 ImageContext
->Machine
= PeHdr
->FileHeader
.Machine
;
192 if (!(IMAGE_64_MACHINE_TYPE_SUPPORTED (ImageContext
->Machine
))) {
193 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_MACHINE_TYPE
;
194 return EFI_UNSUPPORTED
;
198 // See if the image type is supported. We support EFI Applications,
199 // EFI Boot Service Drivers, and EFI Runtime Drivers.
201 ImageContext
->ImageType
= PeHdr
->OptionalHeader
.Subsystem
;
202 switch (ImageContext
->ImageType
) {
204 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
205 ImageContext
->ImageCodeMemoryType
= EfiLoaderCode
;
206 ImageContext
->ImageDataMemoryType
= EfiLoaderData
;
209 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
210 ImageContext
->ImageCodeMemoryType
= EfiBootServicesCode
;
211 ImageContext
->ImageDataMemoryType
= EfiBootServicesData
;
214 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
215 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
216 ImageContext
->ImageCodeMemoryType
= EfiRuntimeServicesCode
;
217 ImageContext
->ImageDataMemoryType
= EfiRuntimeServicesData
;
221 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
222 return EFI_UNSUPPORTED
;
230 PeCoffLoader64GetImageInfo (
231 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
232 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
237 Retrieves information on a PE/COFF image
240 ImageContext - The context of the image being loaded
241 PeHdr - The buffer in which to return the PE header
244 EFI_SUCCESS if the information on the PE/COFF image was collected.
245 EFI_UNSUPPORTED of the PE/COFF image is not supported.
246 Otherwise, the error status from reading the PE/COFF image using the
247 ImageContext->ImageRead() function
252 EFI_IMAGE_NT_HEADERS64 PeHdr
;
253 EFI_IMAGE_DATA_DIRECTORY
*DebugDirectoryEntry
;
256 UINTN DebugDirectoryEntryRva
;
257 UINTN DebugDirectoryEntryFileOffset
;
258 UINTN SectionHeaderOffset
;
259 EFI_IMAGE_SECTION_HEADER SectionHeader
;
260 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry
;
262 if (NULL
== ImageContext
) {
263 return EFI_INVALID_PARAMETER
;
269 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
271 Status
= PeCoffLoader64GetPeHeader (ImageContext
, &PeHdr
);
272 if (EFI_ERROR (Status
)) {
277 // Verify machine type
279 Status
= PeCoffLoader64CheckImageType (ImageContext
, &PeHdr
);
280 if (EFI_ERROR(Status
)) {
285 // Retrieve the base address of the image
287 ImageContext
->ImageAddress
= PeHdr
.OptionalHeader
.ImageBase
;
290 // Initialize the alternate destination address to 0 indicating that it
291 // should not be used.
293 ImageContext
->DestinationAddress
= 0;
296 // Initialize the codeview pointer.
298 ImageContext
->CodeView
= NULL
;
299 ImageContext
->PdbPointer
= NULL
;
302 // Three cases with regards to relocations:
303 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
304 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
305 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
306 // has no base relocs to apply
307 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
309 // Look at the file header to determine if relocations have been stripped, and
310 // save this info in the image context for later use.
312 if (PeHdr
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) {
313 ImageContext
->RelocationsStripped
= TRUE
;
315 ImageContext
->RelocationsStripped
= FALSE
;
318 ImageContext
->ImageSize
= (UINT64
)PeHdr
.OptionalHeader
.SizeOfImage
;
319 ImageContext
->SectionAlignment
= PeHdr
.OptionalHeader
.SectionAlignment
;
320 ImageContext
->SizeOfHeaders
= PeHdr
.OptionalHeader
.SizeOfHeaders
;
323 // Modify ImageSize to contain .PDB file name if required and initialize
327 if (PeHdr
.OptionalHeader
.NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
328 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)
329 &(PeHdr
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
331 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
334 // Determine the file offset of the debug directory... This means we walk
335 // the sections to find which section contains the RVA of the debug
339 DebugDirectoryEntryFileOffset
= 0;
341 SectionHeaderOffset
= (UINTN
) (
342 ImageContext
->PeCoffHeaderOffset
+
344 sizeof (EFI_IMAGE_FILE_HEADER
) +
345 PeHdr
.FileHeader
.SizeOfOptionalHeader
348 for (Index
= 0; Index
< PeHdr
.FileHeader
.NumberOfSections
; Index
+= 1) {
350 // Read section header from file
352 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
353 Status
= ImageContext
->ImageRead (
354 ImageContext
->Handle
,
359 if (EFI_ERROR (Status
)) {
360 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
364 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
365 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
366 DebugDirectoryEntryFileOffset
= DebugDirectoryEntryRva
- SectionHeader
.VirtualAddress
+ SectionHeader
.PointerToRawData
;
370 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
373 if (DebugDirectoryEntryFileOffset
!= 0) {
374 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
++) {
376 // Read next debug directory entry
378 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
379 Status
= ImageContext
->ImageRead (
380 ImageContext
->Handle
,
381 DebugDirectoryEntryFileOffset
,
385 if (EFI_ERROR (Status
)) {
386 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
389 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
390 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
* sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
391 if (DebugEntry
.RVA
== 0 && DebugEntry
.FileOffset
!= 0) {
392 ImageContext
->ImageSize
+= DebugEntry
.SizeOfData
;
404 PeCoffLoader64ImageAddress (
405 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
411 Converts an image address to the loaded address
414 ImageContext - The context of the image being loaded
415 Address - The address to be converted to the loaded address
418 NULL if the address can not be converted, otherwise, the converted address
422 if (Address
>= ImageContext
->ImageSize
) {
423 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
426 return (CHAR8
*)((UINTN
)ImageContext
->ImageAddress
+ Address
);
431 PeCoffLoader64RelocateImage (
432 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
433 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
438 Relocates a PE/COFF image in memory
441 ImageContext - Contains information on the loaded image to relocate
444 EFI_SUCCESS if the PE/COFF image was relocated
445 EFI_LOAD_ERROR if the image is not a valid PE/COFF image
450 EFI_IMAGE_NT_HEADERS64
*PeHdr
;
451 EFI_IMAGE_DATA_DIRECTORY
*RelocDir
;
453 EFI_IMAGE_BASE_RELOCATION
*RelocBase
;
454 EFI_IMAGE_BASE_RELOCATION
*RelocBaseEnd
;
462 EFI_PHYSICAL_ADDRESS BaseAddress
;
468 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
471 // If there are no relocation entries, then we are done
473 if (ImageContext
->RelocationsStripped
) {
478 // If the destination address is not 0, use that rather than the
479 // image address as the relocation target.
481 if (ImageContext
->DestinationAddress
) {
482 BaseAddress
= ImageContext
->DestinationAddress
;
484 BaseAddress
= ImageContext
->ImageAddress
;
486 PeHdr
= (EFI_IMAGE_NT_HEADERS64
*)((UINTN
)ImageContext
->ImageAddress
+
487 ImageContext
->PeCoffHeaderOffset
);
488 Adjust
= (UINT64
) BaseAddress
- PeHdr
->OptionalHeader
.ImageBase
;
490 PeHdr
->OptionalHeader
.ImageBase
= (UINTN
) BaseAddress
;
493 // Find the relocation block
495 // Per the PE/COFF spec, you can't assume that a given data directory
496 // is present in the image. You have to check the NumberOfRvaAndSizes in
497 // the optional header to verify a desired directory entry is there.
499 if (PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
500 RelocDir
= &PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
501 RelocBase
= PeCoffLoader64ImageAddress (ImageContext
, RelocDir
->VirtualAddress
);
502 RelocBaseEnd
= PeCoffLoader64ImageAddress (
504 RelocDir
->VirtualAddress
+ RelocDir
->Size
- 1
508 // Set base and end to bypass processing below.
510 RelocBase
= RelocBaseEnd
= 0;
513 // Run the relocation information and apply the fixups
515 FixupData
= ImageContext
->FixupData
;
516 while (RelocBase
< RelocBaseEnd
) {
518 Reloc
= (UINT16
*) ((CHAR8
*) RelocBase
+ sizeof(EFI_IMAGE_BASE_RELOCATION
));
519 RelocEnd
= (UINT16
*) ((CHAR8
*) RelocBase
+ RelocBase
->SizeOfBlock
);
520 FixupBase
= PeCoffLoader64ImageAddress (ImageContext
, RelocBase
->VirtualAddress
);
521 if ((CHAR8
*) RelocEnd
< (CHAR8
*)((UINTN
)ImageContext
->ImageAddress
) ||
522 (CHAR8
*) RelocEnd
> (CHAR8
*)((UINTN
)ImageContext
->ImageAddress
+
523 (UINTN
)ImageContext
->ImageSize
)) {
524 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
525 return EFI_LOAD_ERROR
;
529 // Run this relocation record
531 while (Reloc
< RelocEnd
) {
533 Fixup
= FixupBase
+ (*Reloc
& 0xFFF);
534 switch ((*Reloc
) >> 12) {
535 case EFI_IMAGE_REL_BASED_ABSOLUTE
:
537 case EFI_IMAGE_REL_BASED_HIGH
:
538 F16
= (UINT16
*) Fixup
;
539 *F16
= (UINT16
) (*F16
+ ((UINT16
) ((UINT32
) Adjust
>> 16)));
540 if (FixupData
!= NULL
) {
541 *(UINT16
*) FixupData
= *F16
;
542 FixupData
= FixupData
+ sizeof(UINT16
);
545 case EFI_IMAGE_REL_BASED_LOW
:
546 F16
= (UINT16
*) Fixup
;
547 *F16
= (UINT16
)(*F16
+ (UINT16
) Adjust
);
548 if (FixupData
!= NULL
) {
549 *(UINT16
*) FixupData
= *F16
;
550 FixupData
= FixupData
+ sizeof(UINT16
);
553 case EFI_IMAGE_REL_BASED_HIGHLOW
:
554 F32
= (UINT32
*) Fixup
;
555 *F32
= *F32
+ (UINT32
) Adjust
;
556 if (FixupData
!= NULL
) {
557 FixupData
= ALIGN_POINTER(FixupData
, sizeof(UINT32
));
558 *(UINT32
*) FixupData
= *F32
;
559 FixupData
= FixupData
+ sizeof(UINT32
);
562 case EFI_IMAGE_REL_BASED_HIGHADJ
:
563 // Return the same EFI_UNSUPPORTED return code as
564 // PeCoffLoader64RelocateImageEx() returns if it does not recognize
565 // the relocation type.
567 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
568 return EFI_UNSUPPORTED
;
570 Status
= PeCoffLoader64RelocateImageEx (Reloc
, Fixup
, &FixupData
, Adjust
);
571 if (EFI_ERROR (Status
)) {
572 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
578 // Next relocation record
586 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*) RelocEnd
;
594 PeCoffLoader64RelocateImageEx (
597 IN OUT CHAR8
**FixupData
,
603 Performs an IA-32 specific relocation fixup
606 Reloc - Pointer to the relocation record
607 Fixup - Pointer to the address to fix up
608 FixupData - Pointer to a buffer to log the fixups
609 Adjust - The offset to adjust the fixup
618 switch ((*Reloc
) >> 12) {
620 case EFI_IMAGE_REL_BASED_DIR64
:
621 F64
= (UINT64
*) Fixup
;
622 *F64
= *F64
+ (UINT64
) Adjust
;
623 if (*FixupData
!= NULL
) {
624 *FixupData
= ALIGN_POINTER(*FixupData
, sizeof(UINT64
));
625 *(UINT64
*)(*FixupData
) = *F64
;
626 *FixupData
= *FixupData
+ sizeof(UINT64
);
631 return EFI_UNSUPPORTED
;
641 PeCoffLoader64LoadImage (
642 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
643 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
648 Loads a PE/COFF image into memory
651 ImageContext - Contains information on image to load into memory
654 EFI_SUCCESS if the PE/COFF image was loaded
655 EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
656 EFI_LOAD_ERROR if the image is a runtime driver with no relocations
657 EFI_INVALID_PARAMETER if the image address is invalid
662 EFI_IMAGE_NT_HEADERS64
*PeHdr
;
663 PE_COFF_LOADER_IMAGE_CONTEXT CheckContext
;
664 EFI_IMAGE_SECTION_HEADER
*FirstSection
;
665 EFI_IMAGE_SECTION_HEADER
*Section
;
670 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
671 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
673 UINT32 TempDebugEntryRva
;
678 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
681 // Copy the provided context info into our local version, get what we
682 // can from the original image, and then use that to make sure everything
688 sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
)
691 Status
= PeCoffLoader64GetImageInfo (
695 if (EFI_ERROR (Status
)) {
700 // Make sure there is enough allocated space for the image being loaded
702 if (ImageContext
->ImageSize
< CheckContext
.ImageSize
) {
703 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_SIZE
;
704 return EFI_BUFFER_TOO_SMALL
;
708 // If there's no relocations, then make sure it's not a runtime driver,
709 // and that it's being loaded at the linked address.
711 if (CheckContext
.RelocationsStripped
== TRUE
) {
713 // If the image does not contain relocations and it is a runtime driver
714 // then return an error.
716 if (CheckContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
717 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
718 return EFI_LOAD_ERROR
;
721 // If the image does not contain relocations, and the requested load address
722 // is not the linked address, then return an error.
724 if (CheckContext
.ImageAddress
!= ImageContext
->ImageAddress
) {
725 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
726 return EFI_INVALID_PARAMETER
;
731 // Make sure the allocated space has the proper section alignment
733 if ((ImageContext
->ImageAddress
& (CheckContext
.SectionAlignment
- 1)) != 0) {
734 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SECTION_ALIGNMENT
;
735 return EFI_INVALID_PARAMETER
;
739 // Read the entire PE/COFF header into memory
741 Status
= ImageContext
->ImageRead (
742 ImageContext
->Handle
,
744 &ImageContext
->SizeOfHeaders
,
745 (VOID
*)(UINTN
)ImageContext
->ImageAddress
747 if (EFI_ERROR(Status
)) {
748 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
749 return EFI_LOAD_ERROR
;
752 PeHdr
= (EFI_IMAGE_NT_HEADERS64
*)
753 ((UINTN
)ImageContext
->ImageAddress
+ ImageContext
->PeCoffHeaderOffset
);
756 // Load each section of the image
758 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
759 (UINTN
)ImageContext
->ImageAddress
+
760 ImageContext
->PeCoffHeaderOffset
+
762 sizeof(EFI_IMAGE_FILE_HEADER
) +
763 PeHdr
->FileHeader
.SizeOfOptionalHeader
766 Section
= FirstSection
;
767 for ( Index
=0, MaxEnd
= NULL
;
768 Index
< PeHdr
->FileHeader
.NumberOfSections
;
772 // Compute sections address
774 Base
= PeCoffLoader64ImageAddress (ImageContext
, Section
->VirtualAddress
);
775 End
= PeCoffLoader64ImageAddress (
777 Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
- 1);
782 // If the base start or end address resolved to 0, then fail.
785 ImageContext
->ImageError
= IMAGE_ERROR_SECTION_NOT_LOADED
;
786 return EFI_LOAD_ERROR
;
790 // Read the section, we can resume the length of PE image can't
791 // exceed the max 32bit integer
793 Size
= (UINTN
) Section
->Misc
.VirtualSize
;
794 if ((Size
== 0) || (Size
> Section
->SizeOfRawData
)) {
795 Size
= (UINTN
) Section
->SizeOfRawData
;
797 if (Section
->SizeOfRawData
) {
798 Status
= ImageContext
->ImageRead (
799 ImageContext
->Handle
,
800 Section
->PointerToRawData
,
803 if (EFI_ERROR(Status
)) {
804 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
810 // If raw size is less then virt size, zero fill the remaining
813 if (Size
< Section
->Misc
.VirtualSize
) {
814 ZeroMem (Base
+ Size
, Section
->Misc
.VirtualSize
- (UINTN
)Size
);
824 // Get image's entry point
826 ImageContext
->EntryPoint
=
827 (EFI_PHYSICAL_ADDRESS
) (UINTN
) PeCoffLoader64ImageAddress (
829 PeHdr
->OptionalHeader
.AddressOfEntryPoint
833 // Determine the size of the fixup data
835 // Per the PE/COFF spec, you can't assume that a given data directory
836 // is present in the image. You have to check the NumberOfRvaAndSizes in
837 // the optional header to verify a desired directory entry is there.
839 if (PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
840 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)
841 &PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
842 ImageContext
->FixupDataSize
=
843 DirectoryEntry
->Size
/ sizeof(UINT16
) * sizeof(UINTN
);
845 ImageContext
->FixupDataSize
= 0;
848 // Consumer must allocate a buffer for the relocation fixup log.
849 // Only used for runtime drivers.
851 ImageContext
->FixupData
= NULL
;
854 // Load the Codeview info if present
856 if (ImageContext
->DebugDirectoryEntryRva
!= 0) {
857 DebugEntry
= PeCoffLoader64ImageAddress (
859 ImageContext
->DebugDirectoryEntryRva
861 if (DebugEntry
!= NULL
) {
862 TempDebugEntryRva
= DebugEntry
->RVA
;
863 if (DebugEntry
->RVA
== 0 && DebugEntry
->FileOffset
!= 0) {
865 if ((UINTN
) Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
866 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
;
868 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->SizeOfRawData
;
871 if (TempDebugEntryRva
!= 0) {
872 ImageContext
->CodeView
= PeCoffLoader64ImageAddress (ImageContext
, TempDebugEntryRva
);
873 if (ImageContext
->CodeView
== NULL
) {
874 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
875 return EFI_LOAD_ERROR
;
878 if (DebugEntry
->RVA
== 0) {
879 Size
= (UINTN
) DebugEntry
->SizeOfData
;
880 Status
= ImageContext
->ImageRead (
881 ImageContext
->Handle
,
882 DebugEntry
->FileOffset
,
884 ImageContext
->CodeView
886 if (EFI_ERROR(Status
)) {
887 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
888 return EFI_LOAD_ERROR
;
890 DebugEntry
->RVA
= TempDebugEntryRva
;
893 switch (* (UINT32
*) ImageContext
->CodeView
) {
894 case CODEVIEW_SIGNATURE_NB10
:
895 ImageContext
->PdbPointer
= (CHAR8
*) ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
897 case CODEVIEW_SIGNATURE_RSDS
:
898 ImageContext
->PdbPointer
= (CHAR8
*) ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
912 PeCoffLoader64UnloadImage (
913 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
914 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
919 Unload of images is not supported
922 ImageContext - The image to unload
932 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*
934 GetPeCoffLoaderX64Protocol (
937 return &mPeCoffLoaderX64
;