2 Core image handling services to load and unload PeImage.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
15 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
17 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
18 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
28 // This code is needed to build the Image handle for the DXE Core
30 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
31 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
33 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
34 TRUE
, // If entrypoint has been called
37 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
38 NULL
, // Parent handle
39 NULL
, // System handle
41 NULL
, // Device handle
50 EfiBootServicesCode
, // ImageCodeType
51 EfiBootServicesData
// ImageDataType
53 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
57 EFI_SUCCESS
, // Status
65 NULL
// LoadedImageDevicePath
68 // The field is define for Loading modules at fixed address feature to tracker the PEI code
69 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
72 GLOBAL_REMOVE_IF_UNREFERENCED UINT64
*mDxeCodeMemoryRangeUsageBitMap
=NULL
;
76 CHAR16
*MachineTypeName
;
80 // EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.
82 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo
[] = {
83 {EFI_IMAGE_MACHINE_IA32
, L
"IA32"},
84 {EFI_IMAGE_MACHINE_IA64
, L
"IA64"},
85 {EFI_IMAGE_MACHINE_X64
, L
"X64"},
86 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
, L
"ARM"},
87 {EFI_IMAGE_MACHINE_AARCH64
, L
"AARCH64"}
90 UINT16 mDxeCoreImageMachineType
= 0;
93 Return machine type name.
95 @param MachineType The machine type
97 @return machine type name
106 for (Index
= 0; Index
< sizeof(mMachineTypeInfo
)/sizeof(mMachineTypeInfo
[0]); Index
++) {
107 if (mMachineTypeInfo
[Index
].MachineType
== MachineType
) {
108 return mMachineTypeInfo
[Index
].MachineTypeName
;
116 Add the Image Services to EFI Boot Services Table and install the protocol
117 interfaces for this image.
119 @param HobStart The HOB to initialize
125 CoreInitializeImageServices (
130 LOADED_IMAGE_PRIVATE_DATA
*Image
;
131 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
132 UINT64 DxeCoreImageLength
;
133 VOID
*DxeCoreEntryPoint
;
134 EFI_PEI_HOB_POINTERS DxeCoreHob
;
137 // Searching for image hob
139 DxeCoreHob
.Raw
= HobStart
;
140 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
141 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
147 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
149 ASSERT (DxeCoreHob
.Raw
!= NULL
);
151 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
152 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
153 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
154 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
157 // Initialize the fields for an internal driver
159 Image
= &mCorePrivateImage
;
161 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
162 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
163 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
164 Image
->Tpl
= gEfiCurrentTpl
;
165 Image
->Info
.SystemTable
= gDxeCoreST
;
166 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
167 Image
->Info
.ImageSize
= DxeCoreImageLength
;
170 // Install the protocol interfaces for this image
172 Status
= CoreInstallProtocolInterface (
174 &gEfiLoadedImageProtocolGuid
,
175 EFI_NATIVE_INTERFACE
,
178 ASSERT_EFI_ERROR (Status
);
180 mCurrentImage
= Image
;
183 // Fill in DXE globals
185 mDxeCoreImageMachineType
= PeCoffLoaderGetMachineType (Image
->Info
.ImageBase
);
186 gDxeCoreImageHandle
= Image
->Handle
;
187 gDxeCoreLoadedImage
= &Image
->Info
;
189 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
191 // Export DXE Core PE Loader functionality for backward compatibility.
193 Status
= CoreInstallProtocolInterface (
194 &mLoadPe32PrivateData
.Handle
,
195 &gEfiLoadPeImageProtocolGuid
,
196 EFI_NATIVE_INTERFACE
,
197 &mLoadPe32PrivateData
.Pe32Image
201 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
207 Read image file (specified by UserHandle) into user specified buffer with specified offset
210 @param UserHandle Image file handle
211 @param Offset Offset to the source file
212 @param ReadSize For input, pointer of size to read; For output,
213 pointer of size actually read.
214 @param Buffer Buffer to write into
216 @retval EFI_SUCCESS Successfully read the specified part of file
225 IN OUT UINTN
*ReadSize
,
230 IMAGE_FILE_HANDLE
*FHand
;
232 if (UserHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
233 return EFI_INVALID_PARAMETER
;
236 if (MAX_ADDRESS
- Offset
< *ReadSize
) {
237 return EFI_INVALID_PARAMETER
;
240 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
241 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
244 // Move data from our local copy of the file
246 EndPosition
= Offset
+ *ReadSize
;
247 if (EndPosition
> FHand
->SourceSize
) {
248 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
250 if (Offset
>= FHand
->SourceSize
) {
254 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
258 To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If
259 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
260 The function is only invoked when load modules at fixed address feature is enabled.
262 @param ImageBase The base address the image will be loaded at.
263 @param ImageSize The size of the image
265 @retval EFI_SUCCESS The memory range the image will be loaded in is available
266 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
269 CheckAndMarkFixLoadingMemoryUsageBitMap (
270 IN EFI_PHYSICAL_ADDRESS ImageBase
,
274 UINT32 DxeCodePageNumber
;
276 EFI_PHYSICAL_ADDRESS DxeCodeBase
;
277 UINTN BaseOffsetPageNumber
;
278 UINTN TopOffsetPageNumber
;
281 // The DXE code range includes RuntimeCodePage range and Boot time code range.
283 DxeCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
284 DxeCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
285 DxeCodeSize
= EFI_PAGES_TO_SIZE(DxeCodePageNumber
);
286 DxeCodeBase
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
- DxeCodeSize
;
289 // If the memory usage bit map is not initialized, do it. Every bit in the array
290 // indicate the status of the corresponding memory page, available or not
292 if (mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
293 mDxeCodeMemoryRangeUsageBitMap
= AllocateZeroPool(((DxeCodePageNumber
/64) + 1)*sizeof(UINT64
));
296 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
298 if (!gLoadFixedAddressCodeMemoryReady
|| mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
299 return EFI_NOT_FOUND
;
302 // Test the memory range for loading the image in the DXE code range.
304 if (gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
< ImageBase
+ ImageSize
||
305 DxeCodeBase
> ImageBase
) {
306 return EFI_NOT_FOUND
;
309 // Test if the memory is avalaible or not.
311 BaseOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
- DxeCodeBase
));
312 TopOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
+ ImageSize
- DxeCodeBase
));
313 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
314 if ((mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] & LShiftU64(1, (Index
% 64))) != 0) {
316 // This page is already used.
318 return EFI_NOT_FOUND
;
323 // Being here means the memory range is available. So mark the bits for the memory range
325 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
326 mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] |= LShiftU64(1, (Index
% 64));
332 Get the fixed loading address from image header assigned by build tool. This function only be called
333 when Loading module at Fixed address feature enabled.
335 @param ImageContext Pointer to the image context structure that describes the PE/COFF
336 image that needs to be examined by this function.
337 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
338 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
342 GetPeCoffImageFixLoadingAssignedAddress(
343 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
346 UINTN SectionHeaderOffset
;
348 EFI_IMAGE_SECTION_HEADER SectionHeader
;
349 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
352 UINT16 NumberOfSections
;
353 IMAGE_FILE_HANDLE
*Handle
;
354 UINT64 ValueInSectionHeader
;
357 Status
= EFI_NOT_FOUND
;
360 // Get PeHeader pointer
362 Handle
= (IMAGE_FILE_HANDLE
*)ImageContext
->Handle
;
363 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
* )Handle
->Source
+ ImageContext
->PeCoffHeaderOffset
);
364 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+
366 sizeof (EFI_IMAGE_FILE_HEADER
) +
367 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
;
368 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
371 // Get base address from the first section header that doesn't point to code section.
373 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
375 // Read section header from file
377 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
378 Status
= ImageContext
->ImageRead (
379 ImageContext
->Handle
,
384 if (EFI_ERROR (Status
)) {
387 if (Size
!= sizeof (EFI_IMAGE_SECTION_HEADER
)) {
388 return EFI_NOT_FOUND
;
391 Status
= EFI_NOT_FOUND
;
393 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
395 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
396 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
397 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
398 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
400 ValueInSectionHeader
= ReadUnaligned64((UINT64
*)&SectionHeader
.PointerToRelocations
);
401 if (ValueInSectionHeader
!= 0) {
403 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
404 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
405 // relative to top address
407 if ((INT64
)PcdGet64(PcdLoadModuleAtFixAddressEnable
) < 0) {
408 ImageContext
->ImageAddress
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
+ (INT64
)(INTN
)ImageContext
->ImageAddress
;
411 // Check if the memory range is available.
413 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext
->ImageAddress
, (UINTN
)(ImageContext
->ImageSize
+ ImageContext
->SectionAlignment
));
417 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
419 DEBUG ((EFI_D_INFO
|EFI_D_LOAD
, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID
*)(UINTN
)(ImageContext
->ImageAddress
), Status
));
423 Loads, relocates, and invokes a PE/COFF image
425 @param BootPolicy If TRUE, indicates that the request originates
426 from the boot manager, and that the boot
427 manager is attempting to load FilePath as a
429 @param Pe32Handle The handle of PE32 image
430 @param Image PE image to be loaded
431 @param DstBuffer The buffer to store the image
432 @param EntryPoint A pointer to the entry point
433 @param Attribute The bit mask of attributes to set for the load
436 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
437 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
438 relocate the PE/COFF file
439 @retval EFI_INVALID_PARAMETER Invalid parameter
440 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
445 IN BOOLEAN BootPolicy
,
447 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
448 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
449 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
454 BOOLEAN DstBufAlocated
;
457 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
459 Image
->ImageContext
.Handle
= Pe32Handle
;
460 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
463 // Get information about the image being loaded
465 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
466 if (EFI_ERROR (Status
)) {
470 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
471 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
473 // The PE/COFF loader can support loading image types that can be executed.
474 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
476 DEBUG ((EFI_D_ERROR
, "Image type %s can't be loaded ", GetMachineTypeName(Image
->ImageContext
.Machine
)));
477 DEBUG ((EFI_D_ERROR
, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType
)));
478 return EFI_UNSUPPORTED
;
483 // Set EFI memory type based on ImageType
485 switch (Image
->ImageContext
.ImageType
) {
486 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
487 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
488 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
490 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
491 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
492 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
494 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
495 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
496 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
497 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
500 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
501 return EFI_UNSUPPORTED
;
505 // Allocate memory of the correct memory type aligned on the required image boundary
507 DstBufAlocated
= FALSE
;
508 if (DstBuffer
== 0) {
510 // Allocate Destination Buffer as caller did not pass it in
513 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
514 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
516 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
519 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
522 // If the image relocations have not been stripped, then load at any address.
523 // Otherwise load at the address at which it was linked.
525 // Memory below 1MB should be treated reserved for CSM and there should be
526 // no modules whose preferred load addresses are below 1MB.
528 Status
= EFI_OUT_OF_RESOURCES
;
530 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
531 // a specified address.
533 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 ) {
534 Status
= GetPeCoffImageFixLoadingAssignedAddress (&(Image
->ImageContext
));
536 if (EFI_ERROR (Status
)) {
538 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
540 DEBUG ((EFI_D_INFO
|EFI_D_LOAD
, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
542 Status
= CoreAllocatePages (
544 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
545 Image
->NumberOfPages
,
546 &Image
->ImageContext
.ImageAddress
550 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
551 Status
= CoreAllocatePages (
553 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
554 Image
->NumberOfPages
,
555 &Image
->ImageContext
.ImageAddress
558 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
559 Status
= CoreAllocatePages (
561 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
562 Image
->NumberOfPages
,
563 &Image
->ImageContext
.ImageAddress
567 if (EFI_ERROR (Status
)) {
570 DstBufAlocated
= TRUE
;
573 // Caller provided the destination buffer
576 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
578 // If the image relocations were stripped, and the caller provided a
579 // destination buffer address that does not match the address that the
580 // image is linked at, then the image cannot be loaded.
582 return EFI_INVALID_PARAMETER
;
585 if (Image
->NumberOfPages
!= 0 &&
586 Image
->NumberOfPages
<
587 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
588 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
589 return EFI_BUFFER_TOO_SMALL
;
592 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
593 Image
->ImageContext
.ImageAddress
= DstBuffer
;
596 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
597 if (!Image
->ImageContext
.IsTeImage
) {
598 Image
->ImageContext
.ImageAddress
=
599 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
600 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
604 // Load the image from the file into the allocated memory
606 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
607 if (EFI_ERROR (Status
)) {
612 // If this is a Runtime Driver, then allocate memory for the FixupData that
613 // is used to relocate the image when SetVirtualAddressMap() is called. The
614 // relocation is done by the Runtime AP.
616 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
617 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
618 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
619 if (Image
->ImageContext
.FixupData
== NULL
) {
620 Status
= EFI_OUT_OF_RESOURCES
;
627 // Relocate the image in memory
629 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
630 if (EFI_ERROR (Status
)) {
635 // Flush the Instruction Cache
637 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
640 // Copy the machine type from the context to the image private data. This
641 // is needed during image unload to know if we should call an EBC protocol
642 // to unload the image.
644 Image
->Machine
= Image
->ImageContext
.Machine
;
647 // Get the image entry point. If it's an EBC image, then call into the
648 // interpreter to create a thunk for the entry point and use the returned
649 // value for the entry point.
651 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
652 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
654 // Locate the EBC interpreter protocol
656 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
657 if (EFI_ERROR(Status
) || Image
->Ebc
== NULL
) {
658 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
663 // Register a callback for flushing the instruction cache so that created
664 // thunks can be flushed.
666 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
667 if (EFI_ERROR(Status
)) {
672 // Create a thunk for the image's entry point. This will be the new
673 // entry point for the image.
675 Status
= Image
->Ebc
->CreateThunk (
678 (VOID
*)(UINTN
) Image
->ImageContext
.EntryPoint
,
679 (VOID
**) &Image
->EntryPoint
681 if (EFI_ERROR(Status
)) {
687 // Fill in the image information for the Loaded Image Protocol
689 Image
->Type
= Image
->ImageContext
.ImageType
;
690 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
691 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
692 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
693 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
694 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
695 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
697 // Make a list off all the RT images so we can let the RT AP know about them.
699 Image
->RuntimeData
= AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
700 if (Image
->RuntimeData
== NULL
) {
703 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
704 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
705 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
706 Image
->RuntimeData
->Handle
= Image
->Handle
;
707 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
708 InsertImageRecord (Image
->RuntimeData
);
713 // Fill in the entry point of the image if it is available
715 if (EntryPoint
!= NULL
) {
716 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
720 // Print the load address and the PDB file name if it is available
727 CHAR8 EfiFileName
[256];
730 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
,
731 "Loading driver at 0x%11p EntryPoint=0x%11p ",
732 (VOID
*)(UINTN
) Image
->ImageContext
.ImageAddress
,
733 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)));
737 // Print Module Name by Pdb file path.
738 // Windows and Unix style file path are all trimmed correctly.
740 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
742 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
743 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
744 StartIndex
= Index
+ 1;
748 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
749 // The PDB file name is limited in the range of 0~255.
750 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
752 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
753 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
754 if (EfiFileName
[Index
] == 0) {
755 EfiFileName
[Index
] = '.';
757 if (EfiFileName
[Index
] == '.') {
758 EfiFileName
[Index
+ 1] = 'e';
759 EfiFileName
[Index
+ 2] = 'f';
760 EfiFileName
[Index
+ 3] = 'i';
761 EfiFileName
[Index
+ 4] = 0;
766 if (Index
== sizeof (EfiFileName
) - 4) {
767 EfiFileName
[Index
] = 0;
769 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
771 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
783 if (DstBufAlocated
) {
784 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
785 Image
->ImageContext
.ImageAddress
= 0;
786 Image
->ImageBasePage
= 0;
789 if (Image
->ImageContext
.FixupData
!= NULL
) {
790 CoreFreePool (Image
->ImageContext
.FixupData
);
799 Get the image's private data from its handle.
801 @param ImageHandle The image handle
803 @return Return the image private data associated with ImageHandle.
806 LOADED_IMAGE_PRIVATE_DATA
*
807 CoreLoadedImageInfo (
808 IN EFI_HANDLE ImageHandle
812 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
813 LOADED_IMAGE_PRIVATE_DATA
*Image
;
815 Status
= CoreHandleProtocol (
817 &gEfiLoadedImageProtocolGuid
,
818 (VOID
**)&LoadedImage
820 if (!EFI_ERROR (Status
)) {
821 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
823 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
832 Unloads EFI image from memory.
834 @param Image EFI image
835 @param FreePage Free allocated pages
839 CoreUnloadAndCloseImage (
840 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
846 EFI_HANDLE
*HandleBuffer
;
848 EFI_GUID
**ProtocolGuidArray
;
851 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
856 ProtocolGuidArray
= NULL
;
858 if (Image
->Started
) {
859 UnregisterMemoryProfileImage (Image
);
862 UnprotectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
864 if (Image
->Ebc
!= NULL
) {
866 // If EBC protocol exists we must perform cleanups for this image.
868 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
872 // Unload image, free Image->ImageContext->ModHandle
874 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
877 // Free our references to the image handle
879 if (Image
->Handle
!= NULL
) {
881 Status
= CoreLocateHandleBuffer (
888 if (!EFI_ERROR (Status
)) {
889 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
890 Status
= CoreProtocolsPerHandle (
891 HandleBuffer
[HandleIndex
],
895 if (!EFI_ERROR (Status
)) {
896 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
897 Status
= CoreOpenProtocolInformation (
898 HandleBuffer
[HandleIndex
],
899 ProtocolGuidArray
[ProtocolIndex
],
903 if (!EFI_ERROR (Status
)) {
904 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
905 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
906 Status
= CoreCloseProtocol (
907 HandleBuffer
[HandleIndex
],
908 ProtocolGuidArray
[ProtocolIndex
],
910 OpenInfo
[OpenInfoIndex
].ControllerHandle
914 if (OpenInfo
!= NULL
) {
915 CoreFreePool(OpenInfo
);
919 if (ProtocolGuidArray
!= NULL
) {
920 CoreFreePool(ProtocolGuidArray
);
924 if (HandleBuffer
!= NULL
) {
925 CoreFreePool (HandleBuffer
);
929 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
931 Status
= CoreUninstallProtocolInterface (
933 &gEfiLoadedImageDevicePathProtocolGuid
,
934 Image
->LoadedImageDevicePath
937 Status
= CoreUninstallProtocolInterface (
939 &gEfiLoadedImageProtocolGuid
,
943 if (Image
->ImageContext
.HiiResourceData
!= 0) {
944 Status
= CoreUninstallProtocolInterface (
946 &gEfiHiiPackageListProtocolGuid
,
947 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
953 if (Image
->RuntimeData
!= NULL
) {
954 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
956 // Remove the Image from the Runtime Image list as we are about to Free it!
958 RemoveEntryList (&Image
->RuntimeData
->Link
);
959 RemoveImageRecord (Image
->RuntimeData
);
961 CoreFreePool (Image
->RuntimeData
);
965 // Free the Image from memory
967 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
968 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
972 // Done with the Image structure
974 if (Image
->Info
.FilePath
!= NULL
) {
975 CoreFreePool (Image
->Info
.FilePath
);
978 if (Image
->LoadedImageDevicePath
!= NULL
) {
979 CoreFreePool (Image
->LoadedImageDevicePath
);
982 if (Image
->FixupData
!= NULL
) {
983 CoreFreePool (Image
->FixupData
);
986 CoreFreePool (Image
);
991 Loads an EFI image into memory and returns a handle to the image.
993 @param BootPolicy If TRUE, indicates that the request originates
994 from the boot manager, and that the boot
995 manager is attempting to load FilePath as a
997 @param ParentImageHandle The caller's image handle.
998 @param FilePath The specific file path from which the image is
1000 @param SourceBuffer If not NULL, a pointer to the memory location
1001 containing a copy of the image to be loaded.
1002 @param SourceSize The size in bytes of SourceBuffer.
1003 @param DstBuffer The buffer to store the image
1004 @param NumberOfPages If not NULL, it inputs a pointer to the page
1005 number of DstBuffer and outputs a pointer to
1006 the page number of the image. If this number is
1007 not enough, return EFI_BUFFER_TOO_SMALL and
1008 this parameter contains the required number.
1009 @param ImageHandle Pointer to the returned image handle that is
1010 created when the image is successfully loaded.
1011 @param EntryPoint A pointer to the entry point
1012 @param Attribute The bit mask of attributes to set for the load
1015 @retval EFI_SUCCESS The image was loaded into memory.
1016 @retval EFI_NOT_FOUND The FilePath was not found.
1017 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1018 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1019 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1020 path cannot be parsed to locate the proper
1021 protocol for loading the file.
1022 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1024 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1026 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1027 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1028 image from being loaded. NULL is returned in *ImageHandle.
1029 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1030 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1031 platform policy specifies that the image should not be started.
1035 CoreLoadImageCommon (
1036 IN BOOLEAN BootPolicy
,
1037 IN EFI_HANDLE ParentImageHandle
,
1038 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1039 IN VOID
*SourceBuffer OPTIONAL
,
1040 IN UINTN SourceSize
,
1041 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1042 IN OUT UINTN
*NumberOfPages OPTIONAL
,
1043 OUT EFI_HANDLE
*ImageHandle
,
1044 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1048 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1049 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
1050 IMAGE_FILE_HANDLE FHand
;
1052 EFI_STATUS SecurityStatus
;
1053 EFI_HANDLE DeviceHandle
;
1054 UINT32 AuthenticationStatus
;
1055 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
1056 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
1057 EFI_DEVICE_PATH_PROTOCOL
*InputFilePath
;
1058 EFI_DEVICE_PATH_PROTOCOL
*Node
;
1060 BOOLEAN ImageIsFromFv
;
1061 BOOLEAN ImageIsFromLoadFile
;
1063 SecurityStatus
= EFI_SUCCESS
;
1065 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
1069 // The caller must pass in a valid ParentImageHandle
1071 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
1072 return EFI_INVALID_PARAMETER
;
1075 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
1076 if (ParentImage
== NULL
) {
1077 DEBUG((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
1078 return EFI_INVALID_PARAMETER
;
1081 ZeroMem (&FHand
, sizeof (IMAGE_FILE_HANDLE
));
1082 FHand
.Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
1083 OriginalFilePath
= FilePath
;
1084 InputFilePath
= FilePath
;
1085 HandleFilePath
= FilePath
;
1086 DeviceHandle
= NULL
;
1087 Status
= EFI_SUCCESS
;
1088 AuthenticationStatus
= 0;
1089 ImageIsFromFv
= FALSE
;
1090 ImageIsFromLoadFile
= FALSE
;
1093 // If the caller passed a copy of the file, then just use it
1095 if (SourceBuffer
!= NULL
) {
1096 FHand
.Source
= SourceBuffer
;
1097 FHand
.SourceSize
= SourceSize
;
1098 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1099 if (EFI_ERROR (Status
)) {
1100 DeviceHandle
= NULL
;
1102 if (SourceSize
> 0) {
1103 Status
= EFI_SUCCESS
;
1105 Status
= EFI_LOAD_ERROR
;
1108 if (FilePath
== NULL
) {
1109 return EFI_INVALID_PARAMETER
;
1113 // Try to get the image device handle by checking the match protocol.
1116 Status
= CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1117 if (!EFI_ERROR (Status
)) {
1118 ImageIsFromFv
= TRUE
;
1120 HandleFilePath
= FilePath
;
1121 Status
= CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1122 if (EFI_ERROR (Status
)) {
1124 HandleFilePath
= FilePath
;
1125 Status
= CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1127 if (EFI_ERROR (Status
)) {
1128 HandleFilePath
= FilePath
;
1129 Status
= CoreLocateDevicePath (&gEfiLoadFileProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1130 if (!EFI_ERROR (Status
)) {
1131 ImageIsFromLoadFile
= TRUE
;
1132 Node
= HandleFilePath
;
1139 // Get the source file buffer by its device path.
1141 FHand
.Source
= GetFileBufferByFilePath (
1145 &AuthenticationStatus
1147 if (FHand
.Source
== NULL
) {
1148 Status
= EFI_NOT_FOUND
;
1150 FHand
.FreeBuffer
= TRUE
;
1151 if (ImageIsFromLoadFile
) {
1153 // LoadFile () may cause the device path of the Handle be updated.
1155 OriginalFilePath
= AppendDevicePath (DevicePathFromHandle (DeviceHandle
), Node
);
1160 if (EFI_ERROR (Status
)) {
1165 if (gSecurity2
!= NULL
) {
1167 // Verify File Authentication through the Security2 Architectural Protocol
1169 SecurityStatus
= gSecurity2
->FileAuthentication (
1176 if (!EFI_ERROR (SecurityStatus
) && ImageIsFromFv
) {
1178 // When Security2 is installed, Security Architectural Protocol must be published.
1180 ASSERT (gSecurity
!= NULL
);
1183 // Verify the Authentication Status through the Security Architectural Protocol
1184 // Only on images that have been read using Firmware Volume protocol.
1186 SecurityStatus
= gSecurity
->FileAuthenticationState (
1188 AuthenticationStatus
,
1192 } else if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
1194 // Verify the Authentication Status through the Security Architectural Protocol
1196 SecurityStatus
= gSecurity
->FileAuthenticationState (
1198 AuthenticationStatus
,
1204 // Check Security Status.
1206 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
1207 if (SecurityStatus
== EFI_ACCESS_DENIED
) {
1209 // Image was not loaded because the platform policy prohibits the image from being loaded.
1210 // It's the only place we could meet EFI_ACCESS_DENIED.
1212 *ImageHandle
= NULL
;
1214 Status
= SecurityStatus
;
1220 // Allocate a new image structure
1222 Image
= AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
1223 if (Image
== NULL
) {
1224 Status
= EFI_OUT_OF_RESOURCES
;
1229 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1231 FilePath
= OriginalFilePath
;
1232 if (DeviceHandle
!= NULL
) {
1233 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
1234 if (!EFI_ERROR (Status
)) {
1235 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
1236 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*)FilePath
) + FilePathSize
);
1240 // Initialize the fields for an internal driver
1242 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
1243 Image
->Info
.SystemTable
= gDxeCoreST
;
1244 Image
->Info
.DeviceHandle
= DeviceHandle
;
1245 Image
->Info
.Revision
= EFI_LOADED_IMAGE_PROTOCOL_REVISION
;
1246 Image
->Info
.FilePath
= DuplicateDevicePath (FilePath
);
1247 Image
->Info
.ParentHandle
= ParentImageHandle
;
1250 if (NumberOfPages
!= NULL
) {
1251 Image
->NumberOfPages
= *NumberOfPages
;
1253 Image
->NumberOfPages
= 0 ;
1257 // Install the protocol interfaces for this image
1258 // don't fire notifications yet
1260 Status
= CoreInstallProtocolInterfaceNotify (
1262 &gEfiLoadedImageProtocolGuid
,
1263 EFI_NATIVE_INTERFACE
,
1267 if (EFI_ERROR (Status
)) {
1272 // Load the image. If EntryPoint is Null, it will not be set.
1274 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
1275 if (EFI_ERROR (Status
)) {
1276 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
1277 if (NumberOfPages
!= NULL
) {
1278 *NumberOfPages
= Image
->NumberOfPages
;
1284 if (NumberOfPages
!= NULL
) {
1285 *NumberOfPages
= Image
->NumberOfPages
;
1289 // Register the image in the Debug Image Info Table if the attribute is set
1291 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) != 0) {
1292 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
1296 //Reinstall loaded image protocol to fire any notifications
1298 Status
= CoreReinstallProtocolInterface (
1300 &gEfiLoadedImageProtocolGuid
,
1304 if (EFI_ERROR (Status
)) {
1309 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1310 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1312 if (OriginalFilePath
!= NULL
) {
1313 Image
->LoadedImageDevicePath
= DuplicateDevicePath (OriginalFilePath
);
1317 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1319 Status
= CoreInstallProtocolInterface (
1321 &gEfiLoadedImageDevicePathProtocolGuid
,
1322 EFI_NATIVE_INTERFACE
,
1323 Image
->LoadedImageDevicePath
1325 if (EFI_ERROR (Status
)) {
1330 // Install HII Package List Protocol onto the image handle
1332 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1333 Status
= CoreInstallProtocolInterface (
1335 &gEfiHiiPackageListProtocolGuid
,
1336 EFI_NATIVE_INTERFACE
,
1337 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1339 if (EFI_ERROR (Status
)) {
1343 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
1346 // Success. Return the image handle
1348 *ImageHandle
= Image
->Handle
;
1352 // All done accessing the source file
1353 // If we allocated the Source buffer, free it
1355 if (FHand
.FreeBuffer
) {
1356 CoreFreePool (FHand
.Source
);
1358 if (OriginalFilePath
!= InputFilePath
) {
1359 CoreFreePool (OriginalFilePath
);
1363 // There was an error. If there's an Image structure, free it
1365 if (EFI_ERROR (Status
)) {
1366 if (Image
!= NULL
) {
1367 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
1370 } else if (EFI_ERROR (SecurityStatus
)) {
1371 Status
= SecurityStatus
;
1375 // Track the return status from LoadImage.
1377 if (Image
!= NULL
) {
1378 Image
->LoadImageStatus
= Status
;
1388 Loads an EFI image into memory and returns a handle to the image.
1390 @param BootPolicy If TRUE, indicates that the request originates
1391 from the boot manager, and that the boot
1392 manager is attempting to load FilePath as a
1394 @param ParentImageHandle The caller's image handle.
1395 @param FilePath The specific file path from which the image is
1397 @param SourceBuffer If not NULL, a pointer to the memory location
1398 containing a copy of the image to be loaded.
1399 @param SourceSize The size in bytes of SourceBuffer.
1400 @param ImageHandle Pointer to the returned image handle that is
1401 created when the image is successfully loaded.
1403 @retval EFI_SUCCESS The image was loaded into memory.
1404 @retval EFI_NOT_FOUND The FilePath was not found.
1405 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1406 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1407 path cannot be parsed to locate the proper
1408 protocol for loading the file.
1409 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1411 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1413 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1414 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1415 image from being loaded. NULL is returned in *ImageHandle.
1416 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1417 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1418 platform policy specifies that the image should not be started.
1424 IN BOOLEAN BootPolicy
,
1425 IN EFI_HANDLE ParentImageHandle
,
1426 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1427 IN VOID
*SourceBuffer OPTIONAL
,
1428 IN UINTN SourceSize
,
1429 OUT EFI_HANDLE
*ImageHandle
1435 PERF_LOAD_IMAGE_BEGIN (NULL
);
1437 Status
= CoreLoadImageCommon (
1443 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
1447 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1451 if (!EFI_ERROR (Status
)) {
1453 // ImageHandle will be valid only Status is success.
1455 Handle
= *ImageHandle
;
1458 PERF_LOAD_IMAGE_END (Handle
);
1466 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1468 @param This Calling context
1469 @param ParentImageHandle The caller's image handle.
1470 @param FilePath The specific file path from which the image is
1472 @param SourceBuffer If not NULL, a pointer to the memory location
1473 containing a copy of the image to be loaded.
1474 @param SourceSize The size in bytes of SourceBuffer.
1475 @param DstBuffer The buffer to store the image.
1476 @param NumberOfPages For input, specifies the space size of the
1477 image by caller if not NULL. For output,
1478 specifies the actual space size needed.
1479 @param ImageHandle Image handle for output.
1480 @param EntryPoint Image entry point for output.
1481 @param Attribute The bit mask of attributes to set for the load
1484 @retval EFI_SUCCESS The image was loaded into memory.
1485 @retval EFI_NOT_FOUND The FilePath was not found.
1486 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1487 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1488 path cannot be parsed to locate the proper
1489 protocol for loading the file.
1490 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1492 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1494 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1495 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1496 image from being loaded. NULL is returned in *ImageHandle.
1497 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1498 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1499 platform policy specifies that the image should not be started.
1505 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1506 IN EFI_HANDLE ParentImageHandle
,
1507 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1508 IN VOID
*SourceBuffer OPTIONAL
,
1509 IN UINTN SourceSize
,
1510 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1511 OUT UINTN
*NumberOfPages OPTIONAL
,
1512 OUT EFI_HANDLE
*ImageHandle
,
1513 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1520 PERF_LOAD_IMAGE_BEGIN (NULL
);
1522 Status
= CoreLoadImageCommon (
1536 if (!EFI_ERROR (Status
)) {
1538 // ImageHandle will be valid only Status is success.
1540 Handle
= *ImageHandle
;
1543 PERF_LOAD_IMAGE_END (Handle
);
1550 Transfer control to a loaded image's entry point.
1552 @param ImageHandle Handle of image to be started.
1553 @param ExitDataSize Pointer of the size to ExitData
1554 @param ExitData Pointer to a pointer to a data buffer that
1555 includes a Null-terminated string,
1556 optionally followed by additional binary data.
1557 The string is a description that the caller may
1558 use to further indicate the reason for the
1561 @retval EFI_INVALID_PARAMETER Invalid parameter
1562 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1563 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1564 @retval EFI_SUCCESS Successfully transfer control to the image's
1571 IN EFI_HANDLE ImageHandle
,
1572 OUT UINTN
*ExitDataSize
,
1573 OUT CHAR16
**ExitData OPTIONAL
1577 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1578 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1579 UINT64 HandleDatabaseKey
;
1583 Handle
= ImageHandle
;
1585 Image
= CoreLoadedImageInfo (ImageHandle
);
1586 if (Image
== NULL
|| Image
->Started
) {
1587 return EFI_INVALID_PARAMETER
;
1589 if (EFI_ERROR (Image
->LoadImageStatus
)) {
1590 return Image
->LoadImageStatus
;
1594 // The image to be started must have the machine type supported by DxeCore.
1596 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->Machine
)) {
1598 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1599 // But it can not be started.
1601 DEBUG ((EFI_D_ERROR
, "Image type %s can't be started ", GetMachineTypeName(Image
->Machine
)));
1602 DEBUG ((EFI_D_ERROR
, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType
)));
1603 return EFI_UNSUPPORTED
;
1606 PERF_START_IMAGE_BEGIN (Handle
);
1610 // Push the current start image context, and
1611 // link the current image to the head. This is the
1612 // only image that can call Exit()
1614 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1615 LastImage
= mCurrentImage
;
1616 mCurrentImage
= Image
;
1617 Image
->Tpl
= gEfiCurrentTpl
;
1620 // Set long jump for Exit() support
1621 // JumpContext must be aligned on a CPU specific boundary.
1622 // Overallocate the buffer and force the required alignment
1624 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1625 if (Image
->JumpBuffer
== NULL
) {
1627 // Image may be unloaded after return with failure,
1628 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1630 PERF_START_IMAGE_END (NULL
);
1633 // Pop the current start image context
1635 mCurrentImage
= LastImage
;
1637 return EFI_OUT_OF_RESOURCES
;
1639 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1641 SetJumpFlag
= SetJump (Image
->JumpContext
);
1643 // The initial call to SetJump() must always return 0.
1644 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1646 if (SetJumpFlag
== 0) {
1647 RegisterMemoryProfileImage (Image
, (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
? EFI_FV_FILETYPE_APPLICATION
: EFI_FV_FILETYPE_DRIVER
));
1649 // Call the image's entry point
1651 Image
->Started
= TRUE
;
1652 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1655 // Add some debug information if the image returned with error.
1656 // This make the user aware and check if the driver image have already released
1657 // all the resource in this situation.
1659 DEBUG_CODE_BEGIN ();
1660 if (EFI_ERROR (Image
->Status
)) {
1661 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1666 // If the image returns, exit it through Exit()
1668 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1672 // Image has completed. Verify the tpl is the same
1674 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1675 CoreRestoreTpl (Image
->Tpl
);
1677 CoreFreePool (Image
->JumpBuffer
);
1680 // Pop the current start image context
1682 mCurrentImage
= LastImage
;
1685 // UEFI Specification - StartImage() - EFI 1.10 Extension
1686 // To maintain compatibility with UEFI drivers that are written to the EFI
1687 // 1.02 Specification, StartImage() must monitor the handle database before
1688 // and after each image is started. If any handles are created or modified
1689 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1690 // be called with the Recursive parameter set to TRUE for each of the newly
1691 // created or modified handles before StartImage() returns.
1693 if (Image
->Type
!= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1694 CoreConnectHandlesByKey (HandleDatabaseKey
);
1698 // Handle the image's returned ExitData
1700 DEBUG_CODE_BEGIN ();
1701 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1703 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1704 if (Image
->ExitData
!= NULL
) {
1705 DEBUG ((DEBUG_LOAD
, " (%hs)", Image
->ExitData
));
1707 DEBUG ((DEBUG_LOAD
, "\n"));
1712 // Return the exit data to the caller
1714 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1715 *ExitDataSize
= Image
->ExitDataSize
;
1716 *ExitData
= Image
->ExitData
;
1719 // Caller doesn't want the exit data, free it
1721 CoreFreePool (Image
->ExitData
);
1722 Image
->ExitData
= NULL
;
1726 // Save the Status because Image will get destroyed if it is unloaded.
1728 Status
= Image
->Status
;
1731 // If the image returned an error, or if the image is an application
1734 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1735 CoreUnloadAndCloseImage (Image
, TRUE
);
1737 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1745 PERF_START_IMAGE_END (Handle
);
1750 Terminates the currently loaded EFI image and returns control to boot services.
1752 @param ImageHandle Handle that identifies the image. This
1753 parameter is passed to the image on entry.
1754 @param Status The image's exit code.
1755 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1756 ExitStatus is EFI_SUCCESS.
1757 @param ExitData Pointer to a data buffer that includes a
1758 Null-terminated Unicode string, optionally
1759 followed by additional binary data. The string
1760 is a description that the caller may use to
1761 further indicate the reason for the image's
1764 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1766 @retval EFI_SUCCESS Successfully terminates the currently loaded
1768 @retval EFI_ACCESS_DENIED Should never reach there.
1769 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1775 IN EFI_HANDLE ImageHandle
,
1776 IN EFI_STATUS Status
,
1777 IN UINTN ExitDataSize
,
1778 IN CHAR16
*ExitData OPTIONAL
1781 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1785 // Prevent possible reentrance to this function
1786 // for the same ImageHandle
1788 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1790 Image
= CoreLoadedImageInfo (ImageHandle
);
1791 if (Image
== NULL
) {
1792 Status
= EFI_INVALID_PARAMETER
;
1796 if (!Image
->Started
) {
1798 // The image has not been started so just free its resources
1800 CoreUnloadAndCloseImage (Image
, TRUE
);
1801 Status
= EFI_SUCCESS
;
1806 // Image has been started, verify this image can exit
1808 if (Image
!= mCurrentImage
) {
1809 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1810 Status
= EFI_INVALID_PARAMETER
;
1817 Image
->Status
= Status
;
1820 // If there's ExitData info, move it
1822 if (ExitData
!= NULL
) {
1823 Image
->ExitDataSize
= ExitDataSize
;
1824 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1825 if (Image
->ExitData
== NULL
) {
1826 Status
= EFI_OUT_OF_RESOURCES
;
1829 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1832 CoreRestoreTpl (OldTpl
);
1834 // return to StartImage
1836 LongJump (Image
->JumpContext
, (UINTN
)-1);
1839 // If we return from LongJump, then it is an error
1842 Status
= EFI_ACCESS_DENIED
;
1844 CoreRestoreTpl (OldTpl
);
1854 @param ImageHandle Handle that identifies the image to be
1857 @retval EFI_SUCCESS The image has been unloaded.
1858 @retval EFI_UNSUPPORTED The image has been started, and does not support
1860 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1866 IN EFI_HANDLE ImageHandle
1870 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1872 Image
= CoreLoadedImageInfo (ImageHandle
);
1873 if (Image
== NULL
) {
1875 // The image handle is not valid
1877 Status
= EFI_INVALID_PARAMETER
;
1881 if (Image
->Started
) {
1883 // The image has been started, request it to unload.
1885 Status
= EFI_UNSUPPORTED
;
1886 if (Image
->Info
.Unload
!= NULL
) {
1887 Status
= Image
->Info
.Unload (ImageHandle
);
1892 // This Image hasn't been started, thus it can be unloaded
1894 Status
= EFI_SUCCESS
;
1898 if (!EFI_ERROR (Status
)) {
1900 // if the Image was not started or Unloaded O.K. then clean up
1902 CoreUnloadAndCloseImage (Image
, TRUE
);
1912 Unload the specified image.
1914 @param This Indicates the calling context.
1915 @param ImageHandle The specified image handle.
1917 @retval EFI_INVALID_PARAMETER Image handle is NULL.
1918 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
1919 @retval EFI_SUCCESS Image successfully unloaded.
1925 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1926 IN EFI_HANDLE ImageHandle
1929 return CoreUnloadImage (ImageHandle
);