2 Base PE/COFF loader supports loading any PE32/PE32+ or TE image, but
3 only supports relocating IA32, x64, IPF, and EBC images.
5 Caution: This file requires additional review when modified.
6 This library will have external input - PE/COFF image.
7 This external input must be validated carefully to avoid security issue like
8 buffer overflow, integer overflow.
10 The basic guideline is that caller need provide ImageContext->ImageRead () with the
11 necessary data range check, to make sure when this library reads PE/COFF image, the
12 PE image buffer is always in valid range.
13 This library will also do some additional check for PE header fields.
15 PeCoffLoaderGetPeHeader() routine will do basic check for PE/COFF header.
16 PeCoffLoaderGetImageInfo() routine will do basic check for whole PE/COFF image.
18 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
19 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
20 This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php.
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 #include "BasePeCoffLibInternals.h"
33 Retrieves the magic value from the PE/COFF header.
35 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
37 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
38 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
42 PeCoffLoaderGetPeHeaderMagicValue (
43 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
47 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
48 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
49 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
50 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
52 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
53 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
56 // Return the magic value from the PC/COFF Optional Header
58 return Hdr
.Pe32
->OptionalHeader
.Magic
;
63 Retrieves the PE or TE Header from a PE/COFF or TE image.
65 Caution: This function may receive untrusted input.
66 PE/COFF image is external input, so this routine will
67 also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader,
68 SizeOfHeader, Section Data Region and Security Data Region be in PE image range.
70 @param ImageContext The context of the image being loaded.
71 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
73 @retval RETURN_SUCCESS The PE or TE Header is read.
74 @retval Other The error status from reading the PE/COFF or TE image using the ImageRead function.
78 PeCoffLoaderGetPeHeader (
79 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
80 OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
84 EFI_IMAGE_DOS_HEADER DosHdr
;
88 UINT32 SectionHeaderOffset
;
91 UINTN NumberOfSections
;
92 EFI_IMAGE_SECTION_HEADER SectionHeader
;
95 // Read the DOS image header to check for its existence
97 Size
= sizeof (EFI_IMAGE_DOS_HEADER
);
99 Status
= ImageContext
->ImageRead (
100 ImageContext
->Handle
,
105 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
106 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
107 if (Size
!= ReadSize
) {
108 Status
= RETURN_UNSUPPORTED
;
113 ImageContext
->PeCoffHeaderOffset
= 0;
114 if (DosHdr
.e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
116 // DOS image header is present, so read the PE header after the DOS image
119 ImageContext
->PeCoffHeaderOffset
= DosHdr
.e_lfanew
;
123 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
124 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
125 // determines if this is a PE32 or PE32+ image. The magic is in the same
126 // location in both images.
128 Size
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
130 Status
= ImageContext
->ImageRead (
131 ImageContext
->Handle
,
132 ImageContext
->PeCoffHeaderOffset
,
136 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
137 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
138 if (Size
!= ReadSize
) {
139 Status
= RETURN_UNSUPPORTED
;
145 // Use Signature to figure out if we understand the image format
147 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
148 ImageContext
->IsTeImage
= TRUE
;
149 ImageContext
->Machine
= Hdr
.Te
->Machine
;
150 ImageContext
->ImageType
= (UINT16
)(Hdr
.Te
->Subsystem
);
152 // For TeImage, SectionAlignment is undefined to be set to Zero
153 // ImageSize can be calculated.
155 ImageContext
->ImageSize
= 0;
156 ImageContext
->SectionAlignment
= 0;
157 ImageContext
->SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
159 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
160 ImageContext
->IsTeImage
= FALSE
;
161 ImageContext
->Machine
= Hdr
.Pe32
->FileHeader
.Machine
;
163 Magic
= PeCoffLoaderGetPeHeaderMagicValue (Hdr
);
165 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
167 // 1. Check FileHeader.SizeOfOptionalHeader filed.
169 if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
< Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
) {
170 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
171 return RETURN_UNSUPPORTED
;
175 // 2. Check the OptionalHeader.SizeOfHeaders field.
176 // This field will be use like the following mode, so just compare the result.
177 // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.
179 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1 < Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
) {
180 if (Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
< (UINT32
)((UINT8
*)(&Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINT8
*) &Hdr
)) {
181 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
182 return RETURN_UNSUPPORTED
;
187 // 2.2 Read last byte of Hdr.Pe32.OptionalHeader.SizeOfHeaders from the file.
191 Status
= ImageContext
->ImageRead (
192 ImageContext
->Handle
,
193 Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
- 1,
197 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
198 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
199 if (Size
!= ReadSize
) {
200 Status
= RETURN_UNSUPPORTED
;
206 // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data.
207 // Read the last byte to make sure the data is in the image region.
208 // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.
210 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
< Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
) {
211 if (Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
!= 0) {
213 // Check the member data to avoid overflow.
215 if ((UINT32
) (~0) - Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
<
216 Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
) {
217 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
218 return RETURN_UNSUPPORTED
;
222 // Read last byte of section header from file
226 Status
= ImageContext
->ImageRead (
227 ImageContext
->Handle
,
228 Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
+
229 Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
- 1,
233 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
234 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
235 if (Size
!= ReadSize
) {
236 Status
= RETURN_UNSUPPORTED
;
246 ImageContext
->ImageType
= Hdr
.Pe32
->OptionalHeader
.Subsystem
;
247 ImageContext
->ImageSize
= (UINT64
)Hdr
.Pe32
->OptionalHeader
.SizeOfImage
;
248 ImageContext
->SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
249 ImageContext
->SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
251 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
253 // 1. Check FileHeader.SizeOfOptionalHeader filed.
255 if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
< Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
) {
256 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
257 return RETURN_UNSUPPORTED
;
261 // 2. Check the OptionalHeader.SizeOfHeaders field.
262 // This field will be use like the following mode, so just compare the result.
263 // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.
265 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1 < Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
) {
266 if (Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
< (UINT32
)((UINT8
*)(&Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - (UINT8
*) &Hdr
)) {
267 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
268 return RETURN_UNSUPPORTED
;
273 // 2.2 Read last byte of Hdr.Pe32Plus.OptionalHeader.SizeOfHeaders from the file.
277 Status
= ImageContext
->ImageRead (
278 ImageContext
->Handle
,
279 Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- 1,
283 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
284 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
285 if (Size
!= ReadSize
) {
286 Status
= RETURN_UNSUPPORTED
;
292 // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data.
293 // Read the last byte to make sure the data is in the image region.
294 // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.
296 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
< Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
) {
297 if (Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
!= 0) {
299 // Check the member data to avoid overflow.
301 if ((UINT32
) (~0) - Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
<
302 Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
) {
303 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
304 return RETURN_UNSUPPORTED
;
308 // Read last byte of section header from file
312 Status
= ImageContext
->ImageRead (
313 ImageContext
->Handle
,
314 Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
+
315 Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
- 1,
319 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
320 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
321 if (Size
!= ReadSize
) {
322 Status
= RETURN_UNSUPPORTED
;
332 ImageContext
->ImageType
= Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
333 ImageContext
->ImageSize
= (UINT64
) Hdr
.Pe32Plus
->OptionalHeader
.SizeOfImage
;
334 ImageContext
->SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
335 ImageContext
->SizeOfHeaders
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
337 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_MACHINE_TYPE
;
338 return RETURN_UNSUPPORTED
;
341 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_MACHINE_TYPE
;
342 return RETURN_UNSUPPORTED
;
345 if (!PeCoffLoaderImageFormatSupported (ImageContext
->Machine
)) {
347 // If the PE/COFF loader does not support the image type return
348 // unsupported. This library can support lots of types of images
349 // this does not mean the user of this library can call the entry
350 // point of the image.
352 return RETURN_UNSUPPORTED
;
356 // Check each section field.
358 if (ImageContext
->IsTeImage
) {
359 SectionHeaderOffset
= sizeof(EFI_TE_IMAGE_HEADER
);
360 NumberOfSections
= (UINTN
) (Hdr
.Te
->NumberOfSections
);
362 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+ sizeof (UINT32
) + sizeof (EFI_IMAGE_FILE_HEADER
) + Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
;
363 NumberOfSections
= (UINTN
) (Hdr
.Pe32
->FileHeader
.NumberOfSections
);
366 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
368 // Read section header from file
370 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
372 Status
= ImageContext
->ImageRead (
373 ImageContext
->Handle
,
378 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
379 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
380 if (Size
!= ReadSize
) {
381 Status
= RETURN_UNSUPPORTED
;
386 if (SectionHeader
.SizeOfRawData
> 0) {
388 // Check the member data to avoid overflow.
390 if ((UINT32
) (~0) - SectionHeader
.PointerToRawData
< SectionHeader
.SizeOfRawData
) {
391 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
392 return RETURN_UNSUPPORTED
;
396 // Base on the ImageRead function to check the section data field.
397 // Read the last byte to make sure the data is in the image region.
401 Status
= ImageContext
->ImageRead (
402 ImageContext
->Handle
,
403 SectionHeader
.PointerToRawData
+ SectionHeader
.SizeOfRawData
- 1,
407 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
408 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
409 if (Size
!= ReadSize
) {
410 Status
= RETURN_UNSUPPORTED
;
417 // Check next section.
419 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
422 return RETURN_SUCCESS
;
427 Retrieves information about a PE/COFF image.
429 Computes the PeCoffHeaderOffset, IsTeImage, ImageType, ImageAddress, ImageSize,
430 DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and
431 DebugDirectoryEntryRva fields of the ImageContext structure.
432 If ImageContext is NULL, then return RETURN_INVALID_PARAMETER.
433 If the PE/COFF image accessed through the ImageRead service in the ImageContext
434 structure is not a supported PE/COFF image type, then return RETURN_UNSUPPORTED.
435 If any errors occur while computing the fields of ImageContext,
436 then the error status is returned in the ImageError field of ImageContext.
437 If the image is a TE image, then SectionAlignment is set to 0.
438 The ImageRead and Handle fields of ImageContext structure must be valid prior
439 to invoking this service.
441 Caution: This function may receive untrusted input.
442 PE/COFF image is external input, so this routine will
443 also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader,
444 SizeOfHeader, Section Data Region and Security Data Region be in PE image range.
446 @param ImageContext The pointer to the image context structure that describes the PE/COFF
447 image that needs to be examined by this function.
449 @retval RETURN_SUCCESS The information on the PE/COFF image was collected.
450 @retval RETURN_INVALID_PARAMETER ImageContext is NULL.
451 @retval RETURN_UNSUPPORTED The PE/COFF image is not supported.
456 PeCoffLoaderGetImageInfo (
457 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
460 RETURN_STATUS Status
;
461 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData
;
462 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
463 EFI_IMAGE_DATA_DIRECTORY
*DebugDirectoryEntry
;
467 UINTN DebugDirectoryEntryRva
;
468 UINTN DebugDirectoryEntryFileOffset
;
469 UINTN SectionHeaderOffset
;
470 EFI_IMAGE_SECTION_HEADER SectionHeader
;
471 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry
;
472 UINT32 NumberOfRvaAndSizes
;
475 if (ImageContext
== NULL
) {
476 return RETURN_INVALID_PARAMETER
;
481 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
483 Hdr
.Union
= &HdrData
;
484 Status
= PeCoffLoaderGetPeHeader (ImageContext
, Hdr
);
485 if (RETURN_ERROR (Status
)) {
489 Magic
= PeCoffLoaderGetPeHeaderMagicValue (Hdr
);
492 // Retrieve the base address of the image
494 if (!(ImageContext
->IsTeImage
)) {
495 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
499 ImageContext
->ImageAddress
= Hdr
.Pe32
->OptionalHeader
.ImageBase
;
504 ImageContext
->ImageAddress
= Hdr
.Pe32Plus
->OptionalHeader
.ImageBase
;
507 ImageContext
->ImageAddress
= (PHYSICAL_ADDRESS
)(Hdr
.Te
->ImageBase
+ Hdr
.Te
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
));
511 // Initialize the alternate destination address to 0 indicating that it
512 // should not be used.
514 ImageContext
->DestinationAddress
= 0;
517 // Initialize the debug codeview pointer.
519 ImageContext
->DebugDirectoryEntryRva
= 0;
520 ImageContext
->CodeView
= NULL
;
521 ImageContext
->PdbPointer
= NULL
;
524 // Three cases with regards to relocations:
525 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
526 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
527 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
528 // has no base relocs to apply
529 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
531 // Look at the file header to determine if relocations have been stripped, and
532 // save this information in the image context for later use.
534 if ((!(ImageContext
->IsTeImage
)) && ((Hdr
.Pe32
->FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0)) {
535 ImageContext
->RelocationsStripped
= TRUE
;
536 } else if ((ImageContext
->IsTeImage
) && (Hdr
.Te
->DataDirectory
[0].Size
== 0) && (Hdr
.Te
->DataDirectory
[0].VirtualAddress
== 0)) {
537 ImageContext
->RelocationsStripped
= TRUE
;
539 ImageContext
->RelocationsStripped
= FALSE
;
543 // TE Image Relocation Data Directory Entry size is non-zero, but the Relocation Data Directory Virtual Address is zero.
544 // This case is not a valid TE image.
546 if ((ImageContext
->IsTeImage
) && (Hdr
.Te
->DataDirectory
[0].Size
!= 0) && (Hdr
.Te
->DataDirectory
[0].VirtualAddress
== 0)) {
547 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
548 return RETURN_UNSUPPORTED
;
551 if (!(ImageContext
->IsTeImage
)) {
552 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
556 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
557 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
562 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
563 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
566 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
568 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
571 // Determine the file offset of the debug directory... This means we walk
572 // the sections to find which section contains the RVA of the debug
575 DebugDirectoryEntryFileOffset
= 0;
577 SectionHeaderOffset
= (UINTN
)(
578 ImageContext
->PeCoffHeaderOffset
+
580 sizeof (EFI_IMAGE_FILE_HEADER
) +
581 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
584 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
586 // Read section header from file
588 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
590 Status
= ImageContext
->ImageRead (
591 ImageContext
->Handle
,
596 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
597 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
598 if (Size
!= ReadSize
) {
599 Status
= RETURN_UNSUPPORTED
;
604 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
605 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
607 DebugDirectoryEntryFileOffset
= DebugDirectoryEntryRva
- SectionHeader
.VirtualAddress
+ SectionHeader
.PointerToRawData
;
611 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
614 if (DebugDirectoryEntryFileOffset
!= 0) {
615 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) {
617 // Read next debug directory entry
619 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
621 Status
= ImageContext
->ImageRead (
622 ImageContext
->Handle
,
623 DebugDirectoryEntryFileOffset
+ Index
,
627 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
628 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
629 if (Size
!= ReadSize
) {
630 Status
= RETURN_UNSUPPORTED
;
636 // From PeCoff spec, when DebugEntry.RVA == 0 means this debug info will not load into memory.
637 // Here we will always load EFI_IMAGE_DEBUG_TYPE_CODEVIEW type debug info. so need adjust the
638 // ImageContext->ImageSize when DebugEntry.RVA == 0.
640 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
641 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
);
642 if (DebugEntry
.RVA
== 0 && DebugEntry
.FileOffset
!= 0) {
643 ImageContext
->ImageSize
+= DebugEntry
.SizeOfData
;
646 return RETURN_SUCCESS
;
653 DebugDirectoryEntry
= &Hdr
.Te
->DataDirectory
[1];
654 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
655 SectionHeaderOffset
= (UINTN
)(sizeof (EFI_TE_IMAGE_HEADER
));
657 DebugDirectoryEntryFileOffset
= 0;
659 for (Index
= 0; Index
< Hdr
.Te
->NumberOfSections
;) {
661 // Read section header from file
663 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
665 Status
= ImageContext
->ImageRead (
666 ImageContext
->Handle
,
671 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
672 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
673 if (Size
!= ReadSize
) {
674 Status
= RETURN_UNSUPPORTED
;
679 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
680 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
681 DebugDirectoryEntryFileOffset
= DebugDirectoryEntryRva
-
682 SectionHeader
.VirtualAddress
+
683 SectionHeader
.PointerToRawData
+
684 sizeof (EFI_TE_IMAGE_HEADER
) -
685 Hdr
.Te
->StrippedSize
;
688 // File offset of the debug directory was found, if this is not the last
689 // section, then skip to the last section for calculating the image size.
691 if (Index
< (UINTN
) Hdr
.Te
->NumberOfSections
- 1) {
692 SectionHeaderOffset
+= (Hdr
.Te
->NumberOfSections
- 1 - Index
) * sizeof (EFI_IMAGE_SECTION_HEADER
);
693 Index
= Hdr
.Te
->NumberOfSections
- 1;
699 // In Te image header there is not a field to describe the ImageSize.
700 // Actually, the ImageSize equals the RVA plus the VirtualSize of
701 // the last section mapped into memory (Must be rounded up to
702 // a multiple of Section Alignment). Per the PE/COFF specification, the
703 // section headers in the Section Table must appear in order of the RVA
704 // values for the corresponding sections. So the ImageSize can be determined
705 // by the RVA and the VirtualSize of the last section header in the
708 if ((++Index
) == (UINTN
)Hdr
.Te
->NumberOfSections
) {
709 ImageContext
->ImageSize
= (SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
);
712 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
715 if (DebugDirectoryEntryFileOffset
!= 0) {
716 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) {
718 // Read next debug directory entry
720 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
722 Status
= ImageContext
->ImageRead (
723 ImageContext
->Handle
,
724 DebugDirectoryEntryFileOffset
+ Index
,
728 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
729 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
730 if (Size
!= ReadSize
) {
731 Status
= RETURN_UNSUPPORTED
;
736 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
737 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
);
738 return RETURN_SUCCESS
;
744 return RETURN_SUCCESS
;
749 Converts an image address to the loaded address.
751 @param ImageContext The context of the image being loaded.
752 @param Address The relative virtual address to be converted to the loaded address.
754 @return The converted address or NULL if the address can not be converted.
758 PeCoffLoaderImageAddress (
759 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
764 // Make sure that Address and ImageSize is correct for the loaded image.
766 if (Address
>= ImageContext
->ImageSize
) {
767 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
771 return (CHAR8
*)((UINTN
) ImageContext
->ImageAddress
+ Address
);
775 Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage().
777 If the DestinationAddress field of ImageContext is 0, then use the ImageAddress field of
778 ImageContext as the relocation base address. Otherwise, use the DestinationAddress field
779 of ImageContext as the relocation base address. The caller must allocate the relocation
780 fixup log buffer and fill in the FixupData field of ImageContext prior to calling this function.
782 The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress,
783 ImageSize, DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders,
784 DebugDirectoryEntryRva, EntryPoint, FixupDataSize, CodeView, PdbPointer, and FixupData of
785 the ImageContext structure must be valid prior to invoking this service.
787 If ImageContext is NULL, then ASSERT().
789 Note that if the platform does not maintain coherency between the instruction cache(s) and the data
790 cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
791 prior to transferring control to a PE/COFF image that is loaded using this library.
793 @param ImageContext The pointer to the image context structure that describes the PE/COFF
794 image that is being relocated.
796 @retval RETURN_SUCCESS The PE/COFF image was relocated.
797 Extended status information is in the ImageError field of ImageContext.
798 @retval RETURN_LOAD_ERROR The image in not a valid PE/COFF image.
799 Extended status information is in the ImageError field of ImageContext.
800 @retval RETURN_UNSUPPORTED A relocation record type is not supported.
801 Extended status information is in the ImageError field of ImageContext.
806 PeCoffLoaderRelocateImage (
807 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
810 RETURN_STATUS Status
;
811 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
812 EFI_IMAGE_DATA_DIRECTORY
*RelocDir
;
814 EFI_IMAGE_BASE_RELOCATION
*RelocBase
;
815 EFI_IMAGE_BASE_RELOCATION
*RelocBaseEnd
;
824 PHYSICAL_ADDRESS BaseAddress
;
825 UINT32 NumberOfRvaAndSizes
;
828 ASSERT (ImageContext
!= NULL
);
833 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
836 // If there are no relocation entries, then we are done
838 if (ImageContext
->RelocationsStripped
) {
839 // Applies additional environment specific actions to relocate fixups
840 // to a PE/COFF image if needed
841 PeCoffLoaderRelocateImageExtraAction (ImageContext
);
842 return RETURN_SUCCESS
;
846 // If the destination address is not 0, use that rather than the
847 // image address as the relocation target.
849 if (ImageContext
->DestinationAddress
!= 0) {
850 BaseAddress
= ImageContext
->DestinationAddress
;
852 BaseAddress
= ImageContext
->ImageAddress
;
855 if (!(ImageContext
->IsTeImage
)) {
856 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)ImageContext
->ImageAddress
+ ImageContext
->PeCoffHeaderOffset
);
858 Magic
= PeCoffLoaderGetPeHeaderMagicValue (Hdr
);
860 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
864 Adjust
= (UINT64
)BaseAddress
- Hdr
.Pe32
->OptionalHeader
.ImageBase
;
866 Hdr
.Pe32
->OptionalHeader
.ImageBase
= (UINT32
)BaseAddress
;
869 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
870 RelocDir
= &Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
875 Adjust
= (UINT64
) BaseAddress
- Hdr
.Pe32Plus
->OptionalHeader
.ImageBase
;
877 Hdr
.Pe32Plus
->OptionalHeader
.ImageBase
= (UINT64
)BaseAddress
;
880 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
881 RelocDir
= &Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
885 // Find the relocation block
886 // Per the PE/COFF spec, you can't assume that a given data directory
887 // is present in the image. You have to check the NumberOfRvaAndSizes in
888 // the optional header to verify a desired directory entry is there.
891 if ((NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) && (RelocDir
->Size
> 0)) {
892 RelocBase
= PeCoffLoaderImageAddress (ImageContext
, RelocDir
->VirtualAddress
);
893 RelocBaseEnd
= PeCoffLoaderImageAddress (
895 RelocDir
->VirtualAddress
+ RelocDir
->Size
- 1
897 if (RelocBase
== NULL
|| RelocBaseEnd
== NULL
) {
898 return RETURN_LOAD_ERROR
;
902 // Set base and end to bypass processing below.
904 RelocBase
= RelocBaseEnd
= NULL
;
907 Hdr
.Te
= (EFI_TE_IMAGE_HEADER
*)(UINTN
)(ImageContext
->ImageAddress
);
908 Adjust
= (UINT64
) (BaseAddress
- Hdr
.Te
->StrippedSize
+ sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->ImageBase
);
910 Hdr
.Te
->ImageBase
= (UINT64
) (BaseAddress
- Hdr
.Te
->StrippedSize
+ sizeof (EFI_TE_IMAGE_HEADER
));
914 // Find the relocation block
916 RelocDir
= &Hdr
.Te
->DataDirectory
[0];
917 if (RelocDir
->Size
> 0) {
918 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*)(UINTN
)(
919 ImageContext
->ImageAddress
+
920 RelocDir
->VirtualAddress
+
921 sizeof(EFI_TE_IMAGE_HEADER
) -
924 RelocBaseEnd
= (EFI_IMAGE_BASE_RELOCATION
*) ((UINTN
) RelocBase
+ (UINTN
) RelocDir
->Size
- 1);
927 // Set base and end to bypass processing below.
929 RelocBase
= RelocBaseEnd
= NULL
;
934 // If Adjust is not zero, then apply fix ups to the image
938 // Run the relocation information and apply the fixups
940 FixupData
= ImageContext
->FixupData
;
941 while (RelocBase
< RelocBaseEnd
) {
943 Reloc
= (UINT16
*) ((CHAR8
*) RelocBase
+ sizeof (EFI_IMAGE_BASE_RELOCATION
));
944 RelocEnd
= (UINT16
*) ((CHAR8
*) RelocBase
+ RelocBase
->SizeOfBlock
);
947 // Make sure RelocEnd is in the Image range.
949 if ((CHAR8
*) RelocEnd
< (CHAR8
*)((UINTN
) ImageContext
->ImageAddress
) ||
950 (CHAR8
*) RelocEnd
> (CHAR8
*)((UINTN
)ImageContext
->ImageAddress
+ (UINTN
)ImageContext
->ImageSize
)) {
951 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
952 return RETURN_LOAD_ERROR
;
955 if (!(ImageContext
->IsTeImage
)) {
956 FixupBase
= PeCoffLoaderImageAddress (ImageContext
, RelocBase
->VirtualAddress
);
957 if (FixupBase
== NULL
) {
958 return RETURN_LOAD_ERROR
;
961 FixupBase
= (CHAR8
*)(UINTN
)(ImageContext
->ImageAddress
+
962 RelocBase
->VirtualAddress
+
963 sizeof(EFI_TE_IMAGE_HEADER
) -
969 // Run this relocation record
971 while (Reloc
< RelocEnd
) {
973 Fixup
= FixupBase
+ (*Reloc
& 0xFFF);
974 switch ((*Reloc
) >> 12) {
975 case EFI_IMAGE_REL_BASED_ABSOLUTE
:
978 case EFI_IMAGE_REL_BASED_HIGH
:
979 Fixup16
= (UINT16
*) Fixup
;
980 *Fixup16
= (UINT16
) (*Fixup16
+ ((UINT16
) ((UINT32
) Adjust
>> 16)));
981 if (FixupData
!= NULL
) {
982 *(UINT16
*) FixupData
= *Fixup16
;
983 FixupData
= FixupData
+ sizeof (UINT16
);
987 case EFI_IMAGE_REL_BASED_LOW
:
988 Fixup16
= (UINT16
*) Fixup
;
989 *Fixup16
= (UINT16
) (*Fixup16
+ (UINT16
) Adjust
);
990 if (FixupData
!= NULL
) {
991 *(UINT16
*) FixupData
= *Fixup16
;
992 FixupData
= FixupData
+ sizeof (UINT16
);
996 case EFI_IMAGE_REL_BASED_HIGHLOW
:
997 Fixup32
= (UINT32
*) Fixup
;
998 *Fixup32
= *Fixup32
+ (UINT32
) Adjust
;
999 if (FixupData
!= NULL
) {
1000 FixupData
= ALIGN_POINTER (FixupData
, sizeof (UINT32
));
1001 *(UINT32
*)FixupData
= *Fixup32
;
1002 FixupData
= FixupData
+ sizeof (UINT32
);
1006 case EFI_IMAGE_REL_BASED_DIR64
:
1007 Fixup64
= (UINT64
*) Fixup
;
1008 *Fixup64
= *Fixup64
+ (UINT64
) Adjust
;
1009 if (FixupData
!= NULL
) {
1010 FixupData
= ALIGN_POINTER (FixupData
, sizeof(UINT64
));
1011 *(UINT64
*)(FixupData
) = *Fixup64
;
1012 FixupData
= FixupData
+ sizeof(UINT64
);
1018 // The common code does not handle some of the stranger IPF relocations
1019 // PeCoffLoaderRelocateImageEx () adds support for these complex fixups
1020 // on IPF and is a No-Op on other architectures.
1022 Status
= PeCoffLoaderRelocateImageEx (Reloc
, Fixup
, &FixupData
, Adjust
);
1023 if (RETURN_ERROR (Status
)) {
1024 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
1030 // Next relocation record
1038 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*) RelocEnd
;
1042 // Adjust the EntryPoint to match the linked-to address
1044 if (ImageContext
->DestinationAddress
!= 0) {
1045 ImageContext
->EntryPoint
-= (UINT64
) ImageContext
->ImageAddress
;
1046 ImageContext
->EntryPoint
+= (UINT64
) ImageContext
->DestinationAddress
;
1050 // Applies additional environment specific actions to relocate fixups
1051 // to a PE/COFF image if needed
1052 PeCoffLoaderRelocateImageExtraAction (ImageContext
);
1054 return RETURN_SUCCESS
;
1058 Loads a PE/COFF image into memory.
1060 Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer
1061 specified by the ImageAddress and ImageSize fields of ImageContext. The caller must allocate
1062 the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function.
1063 The EntryPoint, FixupDataSize, CodeView, PdbPointer and HiiResourceData fields of ImageContext are computed.
1064 The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress, ImageSize,
1065 DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva
1066 fields of the ImageContext structure must be valid prior to invoking this service.
1068 If ImageContext is NULL, then ASSERT().
1070 Note that if the platform does not maintain coherency between the instruction cache(s) and the data
1071 cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
1072 prior to transferring control to a PE/COFF image that is loaded using this library.
1074 @param ImageContext The pointer to the image context structure that describes the PE/COFF
1075 image that is being loaded.
1077 @retval RETURN_SUCCESS The PE/COFF image was loaded into the buffer specified by
1078 the ImageAddress and ImageSize fields of ImageContext.
1079 Extended status information is in the ImageError field of ImageContext.
1080 @retval RETURN_BUFFER_TOO_SMALL The caller did not provide a large enough buffer.
1081 Extended status information is in the ImageError field of ImageContext.
1082 @retval RETURN_LOAD_ERROR The PE/COFF image is an EFI Runtime image with no relocations.
1083 Extended status information is in the ImageError field of ImageContext.
1084 @retval RETURN_INVALID_PARAMETER The image address is invalid.
1085 Extended status information is in the ImageError field of ImageContext.
1090 PeCoffLoaderLoadImage (
1091 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1094 RETURN_STATUS Status
;
1095 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1096 PE_COFF_LOADER_IMAGE_CONTEXT CheckContext
;
1097 EFI_IMAGE_SECTION_HEADER
*FirstSection
;
1098 EFI_IMAGE_SECTION_HEADER
*Section
;
1099 UINTN NumberOfSections
;
1103 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
1104 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
1106 UINT32 TempDebugEntryRva
;
1107 UINT32 NumberOfRvaAndSizes
;
1109 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
1110 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
1111 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
1112 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
1116 ASSERT (ImageContext
!= NULL
);
1121 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
1124 // Copy the provided context information into our local version, get what we
1125 // can from the original image, and then use that to make sure everything
1128 CopyMem (&CheckContext
, ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
1130 Status
= PeCoffLoaderGetImageInfo (&CheckContext
);
1131 if (RETURN_ERROR (Status
)) {
1136 // Make sure there is enough allocated space for the image being loaded
1138 if (ImageContext
->ImageSize
< CheckContext
.ImageSize
) {
1139 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_SIZE
;
1140 return RETURN_BUFFER_TOO_SMALL
;
1142 if (ImageContext
->ImageAddress
== 0) {
1144 // Image cannot be loaded into 0 address.
1146 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
1147 return RETURN_INVALID_PARAMETER
;
1150 // If there's no relocations, then make sure it's not a runtime driver,
1151 // and that it's being loaded at the linked address.
1153 if (CheckContext
.RelocationsStripped
) {
1155 // If the image does not contain relocations and it is a runtime driver
1156 // then return an error.
1158 if (CheckContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
1159 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
1160 return RETURN_LOAD_ERROR
;
1163 // If the image does not contain relocations, and the requested load address
1164 // is not the linked address, then return an error.
1166 if (CheckContext
.ImageAddress
!= ImageContext
->ImageAddress
) {
1167 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
1168 return RETURN_INVALID_PARAMETER
;
1172 // Make sure the allocated space has the proper section alignment
1174 if (!(ImageContext
->IsTeImage
)) {
1175 if ((ImageContext
->ImageAddress
& (CheckContext
.SectionAlignment
- 1)) != 0) {
1176 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SECTION_ALIGNMENT
;
1177 return RETURN_INVALID_PARAMETER
;
1181 // Read the entire PE/COFF or TE header into memory
1183 if (!(ImageContext
->IsTeImage
)) {
1184 Status
= ImageContext
->ImageRead (
1185 ImageContext
->Handle
,
1187 &ImageContext
->SizeOfHeaders
,
1188 (VOID
*) (UINTN
) ImageContext
->ImageAddress
1191 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)ImageContext
->ImageAddress
+ ImageContext
->PeCoffHeaderOffset
);
1193 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
1194 (UINTN
)ImageContext
->ImageAddress
+
1195 ImageContext
->PeCoffHeaderOffset
+
1197 sizeof(EFI_IMAGE_FILE_HEADER
) +
1198 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1200 NumberOfSections
= (UINTN
) (Hdr
.Pe32
->FileHeader
.NumberOfSections
);
1202 Status
= ImageContext
->ImageRead (
1203 ImageContext
->Handle
,
1205 &ImageContext
->SizeOfHeaders
,
1206 (void *)(UINTN
)ImageContext
->ImageAddress
1209 Hdr
.Te
= (EFI_TE_IMAGE_HEADER
*)(UINTN
)(ImageContext
->ImageAddress
);
1211 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
1212 (UINTN
)ImageContext
->ImageAddress
+
1213 sizeof(EFI_TE_IMAGE_HEADER
)
1215 NumberOfSections
= (UINTN
) (Hdr
.Te
->NumberOfSections
);
1219 if (RETURN_ERROR (Status
)) {
1220 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1221 return RETURN_LOAD_ERROR
;
1225 // Load each section of the image
1227 Section
= FirstSection
;
1228 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
1232 Size
= (UINTN
) Section
->Misc
.VirtualSize
;
1233 if ((Size
== 0) || (Size
> Section
->SizeOfRawData
)) {
1234 Size
= (UINTN
) Section
->SizeOfRawData
;
1238 // Compute sections address
1240 Base
= PeCoffLoaderImageAddress (ImageContext
, Section
->VirtualAddress
);
1241 End
= PeCoffLoaderImageAddress (
1243 Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
- 1
1247 // If the size of the section is non-zero and the base address or end address resolved to 0, then fail.
1249 if ((Size
> 0) && ((Base
== NULL
) || (End
== NULL
))) {
1250 ImageContext
->ImageError
= IMAGE_ERROR_SECTION_NOT_LOADED
;
1251 return RETURN_LOAD_ERROR
;
1254 if (ImageContext
->IsTeImage
) {
1255 Base
= (CHAR8
*)((UINTN
) Base
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
)Hdr
.Te
->StrippedSize
);
1256 End
= (CHAR8
*)((UINTN
) End
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
)Hdr
.Te
->StrippedSize
);
1259 if (Section
->SizeOfRawData
> 0) {
1260 if (!(ImageContext
->IsTeImage
)) {
1261 Status
= ImageContext
->ImageRead (
1262 ImageContext
->Handle
,
1263 Section
->PointerToRawData
,
1268 Status
= ImageContext
->ImageRead (
1269 ImageContext
->Handle
,
1270 Section
->PointerToRawData
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
)Hdr
.Te
->StrippedSize
,
1276 if (RETURN_ERROR (Status
)) {
1277 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1283 // If raw size is less then virtual size, zero fill the remaining
1286 if (Size
< Section
->Misc
.VirtualSize
) {
1287 ZeroMem (Base
+ Size
, Section
->Misc
.VirtualSize
- Size
);
1297 // Get image's entry point
1299 Magic
= PeCoffLoaderGetPeHeaderMagicValue (Hdr
);
1300 if (!(ImageContext
->IsTeImage
)) {
1302 // Sizes of AddressOfEntryPoint are different so we need to do this safely
1304 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1308 ImageContext
->EntryPoint
= (PHYSICAL_ADDRESS
)(UINTN
)PeCoffLoaderImageAddress (
1310 (UINTN
)Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
1316 ImageContext
->EntryPoint
= (PHYSICAL_ADDRESS
)(UINTN
)PeCoffLoaderImageAddress (
1318 (UINTN
)Hdr
.Pe32Plus
->OptionalHeader
.AddressOfEntryPoint
1322 ImageContext
->EntryPoint
= (PHYSICAL_ADDRESS
) (
1323 (UINTN
)ImageContext
->ImageAddress
+
1324 (UINTN
)Hdr
.Te
->AddressOfEntryPoint
+
1325 (UINTN
)sizeof(EFI_TE_IMAGE_HEADER
) -
1326 (UINTN
)Hdr
.Te
->StrippedSize
1331 // Determine the size of the fixup data
1333 // Per the PE/COFF spec, you can't assume that a given data directory
1334 // is present in the image. You have to check the NumberOfRvaAndSizes in
1335 // the optional header to verify a desired directory entry is there.
1337 if (!(ImageContext
->IsTeImage
)) {
1338 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1342 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1343 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1348 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1349 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1352 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
1353 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1355 ImageContext
->FixupDataSize
= 0;
1358 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[0];
1359 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1362 // Consumer must allocate a buffer for the relocation fixup log.
1363 // Only used for runtime drivers.
1365 ImageContext
->FixupData
= NULL
;
1368 // Load the Codeview information if present
1370 if (ImageContext
->DebugDirectoryEntryRva
!= 0) {
1371 if (!(ImageContext
->IsTeImage
)) {
1372 DebugEntry
= PeCoffLoaderImageAddress (
1374 ImageContext
->DebugDirectoryEntryRva
1377 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(UINTN
)(
1378 ImageContext
->ImageAddress
+
1379 ImageContext
->DebugDirectoryEntryRva
+
1380 sizeof(EFI_TE_IMAGE_HEADER
) -
1381 Hdr
.Te
->StrippedSize
1385 if (DebugEntry
!= NULL
) {
1386 TempDebugEntryRva
= DebugEntry
->RVA
;
1387 if (DebugEntry
->RVA
== 0 && DebugEntry
->FileOffset
!= 0) {
1389 if ((UINTN
)Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
1390 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
;
1392 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->SizeOfRawData
;
1396 if (TempDebugEntryRva
!= 0) {
1397 if (!(ImageContext
->IsTeImage
)) {
1398 ImageContext
->CodeView
= PeCoffLoaderImageAddress (ImageContext
, TempDebugEntryRva
);
1400 ImageContext
->CodeView
= (VOID
*)(
1401 (UINTN
)ImageContext
->ImageAddress
+
1402 (UINTN
)TempDebugEntryRva
+
1403 (UINTN
)sizeof (EFI_TE_IMAGE_HEADER
) -
1404 (UINTN
) Hdr
.Te
->StrippedSize
1408 if (ImageContext
->CodeView
== NULL
) {
1409 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1410 return RETURN_LOAD_ERROR
;
1413 if (DebugEntry
->RVA
== 0) {
1414 Size
= DebugEntry
->SizeOfData
;
1415 if (!(ImageContext
->IsTeImage
)) {
1416 Status
= ImageContext
->ImageRead (
1417 ImageContext
->Handle
,
1418 DebugEntry
->FileOffset
,
1420 ImageContext
->CodeView
1423 Status
= ImageContext
->ImageRead (
1424 ImageContext
->Handle
,
1425 DebugEntry
->FileOffset
+ sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
,
1427 ImageContext
->CodeView
1430 // Should we apply fix up to this field according to the size difference between PE and TE?
1431 // Because now we maintain TE header fields unfixed, this field will also remain as they are
1432 // in original PE image.
1436 if (RETURN_ERROR (Status
)) {
1437 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1438 return RETURN_LOAD_ERROR
;
1441 DebugEntry
->RVA
= TempDebugEntryRva
;
1444 switch (*(UINT32
*) ImageContext
->CodeView
) {
1445 case CODEVIEW_SIGNATURE_NB10
:
1446 if (DebugEntry
->SizeOfData
< sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)) {
1447 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
1448 return RETURN_UNSUPPORTED
;
1450 ImageContext
->PdbPointer
= (CHAR8
*)ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
1453 case CODEVIEW_SIGNATURE_RSDS
:
1454 if (DebugEntry
->SizeOfData
< sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
)) {
1455 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
1456 return RETURN_UNSUPPORTED
;
1458 ImageContext
->PdbPointer
= (CHAR8
*)ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
1461 case CODEVIEW_SIGNATURE_MTOC
:
1462 if (DebugEntry
->SizeOfData
< sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
)) {
1463 ImageContext
->ImageError
= IMAGE_ERROR_UNSUPPORTED
;
1464 return RETURN_UNSUPPORTED
;
1466 ImageContext
->PdbPointer
= (CHAR8
*)ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
);
1477 // Get Image's HII resource section
1479 ImageContext
->HiiResourceData
= 0;
1480 if (!(ImageContext
->IsTeImage
)) {
1481 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1485 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
];
1490 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
];
1493 if (DirectoryEntry
->Size
!= 0) {
1494 Base
= PeCoffLoaderImageAddress (ImageContext
, DirectoryEntry
->VirtualAddress
);
1496 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) Base
;
1497 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
1499 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
1500 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
1502 // Check the ResourceDirectoryEntry->u1.s.NameOffset before use it.
1504 if (ResourceDirectoryEntry
->u1
.s
.NameOffset
>= DirectoryEntry
->Size
) {
1507 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (Base
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
1508 String
= &ResourceDirectoryString
->String
[0];
1510 if (ResourceDirectoryString
->Length
== 3 &&
1511 String
[0] == L
'H' &&
1512 String
[1] == L
'I' &&
1513 String
[2] == L
'I') {
1515 // Resource Type "HII" found
1517 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
1519 // Move to next level - resource Name
1521 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (Base
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
1522 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
1524 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
1526 // Move to next level - resource Language
1528 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (Base
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
1529 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
1534 // Now it ought to be resource Data
1536 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
1537 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (Base
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
1538 ImageContext
->HiiResourceData
= (PHYSICAL_ADDRESS
) (UINTN
) PeCoffLoaderImageAddress (ImageContext
, ResourceDataEntry
->OffsetToData
);
1543 ResourceDirectoryEntry
++;
1554 Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI
1557 This function reapplies relocation fixups to the PE/COFF image specified by ImageBase
1558 and ImageSize so the image will execute correctly when the PE/COFF image is mapped
1559 to the address specified by VirtualImageBase. RelocationData must be identical
1560 to the FiuxupData buffer from the PE_COFF_LOADER_IMAGE_CONTEXT structure
1561 after this PE/COFF image was relocated with PeCoffLoaderRelocateImage().
1563 Note that if the platform does not maintain coherency between the instruction cache(s) and the data
1564 cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
1565 prior to transferring control to a PE/COFF image that is loaded using this library.
1567 @param ImageBase The base address of a PE/COFF image that has been loaded
1568 and relocated into system memory.
1569 @param VirtImageBase The request virtual address that the PE/COFF image is to
1571 @param ImageSize The size, in bytes, of the PE/COFF image.
1572 @param RelocationData A pointer to the relocation data that was collected when the PE/COFF
1573 image was relocated using PeCoffLoaderRelocateImage().
1578 PeCoffLoaderRelocateImageForRuntime (
1579 IN PHYSICAL_ADDRESS ImageBase
,
1580 IN PHYSICAL_ADDRESS VirtImageBase
,
1582 IN VOID
*RelocationData
1587 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1588 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1589 UINT32 NumberOfRvaAndSizes
;
1590 EFI_IMAGE_DATA_DIRECTORY
*DataDirectory
;
1591 EFI_IMAGE_DATA_DIRECTORY
*RelocDir
;
1592 EFI_IMAGE_BASE_RELOCATION
*RelocBase
;
1593 EFI_IMAGE_BASE_RELOCATION
*RelocBaseEnd
;
1603 RETURN_STATUS Status
;
1606 OldBase
= (CHAR8
*)((UINTN
)ImageBase
);
1607 NewBase
= (CHAR8
*)((UINTN
)VirtImageBase
);
1608 Adjust
= (UINTN
) NewBase
- (UINTN
) OldBase
;
1611 // Find the image's relocate dir info
1613 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)OldBase
;
1614 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1616 // Valid DOS header so get address of PE header
1618 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)(((CHAR8
*)DosHdr
) + DosHdr
->e_lfanew
);
1621 // No Dos header so assume image starts with PE header.
1623 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)OldBase
;
1626 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1628 // Not a valid PE image so Exit
1633 Magic
= PeCoffLoaderGetPeHeaderMagicValue (Hdr
);
1635 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1639 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1640 DataDirectory
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[0]);
1645 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1646 DataDirectory
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[0]);
1650 // Find the relocation block
1652 // Per the PE/COFF spec, you can't assume that a given data directory
1653 // is present in the image. You have to check the NumberOfRvaAndSizes in
1654 // the optional header to verify a desired directory entry is there.
1656 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
1657 RelocDir
= DataDirectory
+ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
;
1658 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*)(UINTN
)(ImageBase
+ RelocDir
->VirtualAddress
);
1659 RelocBaseEnd
= (EFI_IMAGE_BASE_RELOCATION
*)(UINTN
)(ImageBase
+ RelocDir
->VirtualAddress
+ RelocDir
->Size
);
1662 // Cannot find relocations, cannot continue to relocate the image, ASSERT for this invalid image.
1669 // ASSERT for the invalid image when RelocBase and RelocBaseEnd are both NULL.
1671 ASSERT (RelocBase
!= NULL
&& RelocBaseEnd
!= NULL
);
1674 // Run the whole relocation block. And re-fixup data that has not been
1675 // modified. The FixupData is used to see if the image has been modified
1676 // since it was relocated. This is so data sections that have been updated
1677 // by code will not be fixed up, since that would set them back to
1680 FixupData
= RelocationData
;
1681 while (RelocBase
< RelocBaseEnd
) {
1683 // Add check for RelocBase->SizeOfBlock field.
1685 if ((RelocBase
->SizeOfBlock
== 0) || (RelocBase
->SizeOfBlock
> RelocDir
->Size
)) {
1687 // Data invalid, cannot continue to relocate the image, just return.
1692 Reloc
= (UINT16
*) ((UINT8
*) RelocBase
+ sizeof (EFI_IMAGE_BASE_RELOCATION
));
1693 RelocEnd
= (UINT16
*) ((UINT8
*) RelocBase
+ RelocBase
->SizeOfBlock
);
1694 FixupBase
= (CHAR8
*) ((UINTN
)ImageBase
) + RelocBase
->VirtualAddress
;
1697 // Run this relocation record
1699 while (Reloc
< RelocEnd
) {
1701 Fixup
= FixupBase
+ (*Reloc
& 0xFFF);
1702 switch ((*Reloc
) >> 12) {
1704 case EFI_IMAGE_REL_BASED_ABSOLUTE
:
1707 case EFI_IMAGE_REL_BASED_HIGH
:
1708 Fixup16
= (UINT16
*) Fixup
;
1709 if (*(UINT16
*) FixupData
== *Fixup16
) {
1710 *Fixup16
= (UINT16
) (*Fixup16
+ ((UINT16
) ((UINT32
) Adjust
>> 16)));
1713 FixupData
= FixupData
+ sizeof (UINT16
);
1716 case EFI_IMAGE_REL_BASED_LOW
:
1717 Fixup16
= (UINT16
*) Fixup
;
1718 if (*(UINT16
*) FixupData
== *Fixup16
) {
1719 *Fixup16
= (UINT16
) (*Fixup16
+ ((UINT16
) Adjust
& 0xffff));
1722 FixupData
= FixupData
+ sizeof (UINT16
);
1725 case EFI_IMAGE_REL_BASED_HIGHLOW
:
1726 Fixup32
= (UINT32
*) Fixup
;
1727 FixupData
= ALIGN_POINTER (FixupData
, sizeof (UINT32
));
1728 if (*(UINT32
*) FixupData
== *Fixup32
) {
1729 *Fixup32
= *Fixup32
+ (UINT32
) Adjust
;
1732 FixupData
= FixupData
+ sizeof (UINT32
);
1735 case EFI_IMAGE_REL_BASED_DIR64
:
1736 Fixup64
= (UINT64
*)Fixup
;
1737 FixupData
= ALIGN_POINTER (FixupData
, sizeof (UINT64
));
1738 if (*(UINT64
*) FixupData
== *Fixup64
) {
1739 *Fixup64
= *Fixup64
+ (UINT64
)Adjust
;
1742 FixupData
= FixupData
+ sizeof (UINT64
);
1745 case EFI_IMAGE_REL_BASED_HIGHADJ
:
1747 // Not valid Relocation type for UEFI image, ASSERT
1754 // Only Itanium requires ConvertPeImage_Ex
1756 Status
= PeHotRelocateImageEx (Reloc
, Fixup
, &FixupData
, Adjust
);
1757 if (RETURN_ERROR (Status
)) {
1762 // Next relocation record
1769 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*) RelocEnd
;
1775 Reads contents of a PE/COFF image from a buffer in system memory.
1777 This is the default implementation of a PE_COFF_LOADER_READ_FILE function
1778 that assumes FileHandle pointer to the beginning of a PE/COFF image.
1779 This function reads contents of the PE/COFF image that starts at the system memory
1780 address specified by FileHandle. The read operation copies ReadSize bytes from the
1781 PE/COFF image starting at byte offset FileOffset into the buffer specified by Buffer.
1782 The size of the buffer actually read is returned in ReadSize.
1784 The caller must make sure the FileOffset and ReadSize within the file scope.
1786 If FileHandle is NULL, then ASSERT().
1787 If ReadSize is NULL, then ASSERT().
1788 If Buffer is NULL, then ASSERT().
1790 @param FileHandle The pointer to base of the input stream
1791 @param FileOffset Offset into the PE/COFF image to begin the read operation.
1792 @param ReadSize On input, the size in bytes of the requested read operation.
1793 On output, the number of bytes actually read.
1794 @param Buffer Output buffer that contains the data read from the PE/COFF image.
1796 @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into
1801 PeCoffLoaderImageReadFromMemory (
1802 IN VOID
*FileHandle
,
1803 IN UINTN FileOffset
,
1804 IN OUT UINTN
*ReadSize
,
1808 ASSERT (ReadSize
!= NULL
);
1809 ASSERT (FileHandle
!= NULL
);
1810 ASSERT (Buffer
!= NULL
);
1812 CopyMem (Buffer
, ((UINT8
*)FileHandle
) + FileOffset
, *ReadSize
);
1813 return RETURN_SUCCESS
;
1817 Unloads a loaded PE/COFF image from memory and releases its taken resource.
1818 Releases any environment specific resources that were allocated when the image
1819 specified by ImageContext was loaded using PeCoffLoaderLoadImage().
1821 For NT32 emulator, the PE/COFF image loaded by system needs to release.
1822 For real platform, the PE/COFF image loaded by Core doesn't needs to be unloaded,
1823 this function can simply return RETURN_SUCCESS.
1825 If ImageContext is NULL, then ASSERT().
1827 @param ImageContext The pointer to the image context structure that describes the PE/COFF
1828 image to be unloaded.
1830 @retval RETURN_SUCCESS The PE/COFF image was unloaded successfully.
1834 PeCoffLoaderUnloadImage (
1835 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1839 // Applies additional environment specific actions to unload a
1840 // PE/COFF image if needed
1842 PeCoffLoaderUnloadImageExtraAction (ImageContext
);
1843 return RETURN_SUCCESS
;