2 Core image handling services to load and unload PeImage.
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
15 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
19 EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*Emulator
;
23 STATIC LIST_ENTRY mAvailableEmulators
;
24 STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent
;
25 STATIC VOID
*mPeCoffEmuProtocolNotifyRegistration
;
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
;
79 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo
[] = {
80 { EFI_IMAGE_MACHINE_IA32
, L
"IA32" },
81 { EFI_IMAGE_MACHINE_IA64
, L
"IA64" },
82 { EFI_IMAGE_MACHINE_X64
, L
"X64" },
83 { EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
, L
"ARM" },
84 { EFI_IMAGE_MACHINE_AARCH64
, L
"AARCH64" }
87 UINT16 mDxeCoreImageMachineType
= 0;
90 Return machine type name.
92 @param MachineType The machine type
94 @return machine type name
103 for (Index
= 0; Index
< sizeof (mMachineTypeInfo
)/sizeof (mMachineTypeInfo
[0]); Index
++) {
104 if (mMachineTypeInfo
[Index
].MachineType
== MachineType
) {
105 return mMachineTypeInfo
[Index
].MachineTypeName
;
113 Notification event handler registered by CoreInitializeImageServices () to
114 keep track of which PE/COFF image emulators are available.
116 @param Event The Event that is being processed, not used.
117 @param Context Event Context, not used.
123 PeCoffEmuProtocolNotify (
130 EFI_HANDLE EmuHandle
;
131 EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*Emulator
;
132 EMULATOR_ENTRY
*Entry
;
138 BufferSize
= sizeof (EmuHandle
);
139 Status
= CoreLocateHandle (
142 mPeCoffEmuProtocolNotifyRegistration
,
146 if (EFI_ERROR (Status
)) {
148 // If no more notification events exit
153 Status
= CoreHandleProtocol (
155 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
158 if (EFI_ERROR (Status
) || (Emulator
== NULL
)) {
162 Entry
= AllocateZeroPool (sizeof (*Entry
));
163 ASSERT (Entry
!= NULL
);
165 Entry
->Emulator
= Emulator
;
166 Entry
->MachineType
= Entry
->Emulator
->MachineType
;
168 InsertTailList (&mAvailableEmulators
, &Entry
->Link
);
173 Add the Image Services to EFI Boot Services Table and install the protocol
174 interfaces for this image.
176 @param HobStart The HOB to initialize
182 CoreInitializeImageServices (
187 LOADED_IMAGE_PRIVATE_DATA
*Image
;
188 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
189 UINT64 DxeCoreImageLength
;
190 VOID
*DxeCoreEntryPoint
;
191 EFI_PEI_HOB_POINTERS DxeCoreHob
;
194 // Searching for image hob
196 DxeCoreHob
.Raw
= HobStart
;
197 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
198 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
205 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
208 ASSERT (DxeCoreHob
.Raw
!= NULL
);
210 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
211 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
212 DxeCoreEntryPoint
= (VOID
*)(UINTN
)DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
213 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
216 // Initialize the fields for an internal driver
218 Image
= &mCorePrivateImage
;
220 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
221 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
222 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES ((UINTN
)(DxeCoreImageLength
)));
223 Image
->Tpl
= gEfiCurrentTpl
;
224 Image
->Info
.SystemTable
= gDxeCoreST
;
225 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
226 Image
->Info
.ImageSize
= DxeCoreImageLength
;
229 // Install the protocol interfaces for this image
231 Status
= CoreInstallProtocolInterface (
233 &gEfiLoadedImageProtocolGuid
,
234 EFI_NATIVE_INTERFACE
,
237 ASSERT_EFI_ERROR (Status
);
239 mCurrentImage
= Image
;
242 // Fill in DXE globals
244 mDxeCoreImageMachineType
= PeCoffLoaderGetMachineType (Image
->Info
.ImageBase
);
245 gDxeCoreImageHandle
= Image
->Handle
;
246 gDxeCoreLoadedImage
= &Image
->Info
;
249 // Create the PE/COFF emulator protocol registration event
251 Status
= CoreCreateEvent (
254 PeCoffEmuProtocolNotify
,
256 &mPeCoffEmuProtocolRegistrationEvent
258 ASSERT_EFI_ERROR (Status
);
261 // Register for protocol notifications on this event
263 Status
= CoreRegisterProtocolNotify (
264 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
265 mPeCoffEmuProtocolRegistrationEvent
,
266 &mPeCoffEmuProtocolNotifyRegistration
268 ASSERT_EFI_ERROR (Status
);
270 InitializeListHead (&mAvailableEmulators
);
272 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
278 Read image file (specified by UserHandle) into user specified buffer with specified offset
281 @param UserHandle Image file handle
282 @param Offset Offset to the source file
283 @param ReadSize For input, pointer of size to read; For output,
284 pointer of size actually read.
285 @param Buffer Buffer to write into
287 @retval EFI_SUCCESS Successfully read the specified part of file
296 IN OUT UINTN
*ReadSize
,
301 IMAGE_FILE_HANDLE
*FHand
;
303 if ((UserHandle
== NULL
) || (ReadSize
== NULL
) || (Buffer
== NULL
)) {
304 return EFI_INVALID_PARAMETER
;
307 if (MAX_ADDRESS
- Offset
< *ReadSize
) {
308 return EFI_INVALID_PARAMETER
;
311 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
312 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
315 // Move data from our local copy of the file
317 EndPosition
= Offset
+ *ReadSize
;
318 if (EndPosition
> FHand
->SourceSize
) {
319 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
322 if (Offset
>= FHand
->SourceSize
) {
326 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
331 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
332 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
333 The function is only invoked when load modules at fixed address feature is enabled.
335 @param ImageBase The base address the image will be loaded at.
336 @param ImageSize The size of the image
338 @retval EFI_SUCCESS The memory range the image will be loaded in is available
339 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
342 CheckAndMarkFixLoadingMemoryUsageBitMap (
343 IN EFI_PHYSICAL_ADDRESS ImageBase
,
347 UINT32 DxeCodePageNumber
;
349 EFI_PHYSICAL_ADDRESS DxeCodeBase
;
350 UINTN BaseOffsetPageNumber
;
351 UINTN TopOffsetPageNumber
;
355 // The DXE code range includes RuntimeCodePage range and Boot time code range.
357 DxeCodePageNumber
= PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber
);
358 DxeCodePageNumber
+= PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber
);
359 DxeCodeSize
= EFI_PAGES_TO_SIZE (DxeCodePageNumber
);
360 DxeCodeBase
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
- DxeCodeSize
;
363 // If the memory usage bit map is not initialized, do it. Every bit in the array
364 // indicate the status of the corresponding memory page, available or not
366 if (mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
367 mDxeCodeMemoryRangeUsageBitMap
= AllocateZeroPool (((DxeCodePageNumber
/64) + 1)*sizeof (UINT64
));
371 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
373 if (!gLoadFixedAddressCodeMemoryReady
|| (mDxeCodeMemoryRangeUsageBitMap
== NULL
)) {
374 return EFI_NOT_FOUND
;
378 // Test the memory range for loading the image in the DXE code range.
380 if ((gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
< ImageBase
+ ImageSize
) ||
381 (DxeCodeBase
> ImageBase
))
383 return EFI_NOT_FOUND
;
387 // Test if the memory is avalaible or not.
389 BaseOffsetPageNumber
= EFI_SIZE_TO_PAGES ((UINT32
)(ImageBase
- DxeCodeBase
));
390 TopOffsetPageNumber
= EFI_SIZE_TO_PAGES ((UINT32
)(ImageBase
+ ImageSize
- DxeCodeBase
));
391 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
392 if ((mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] & LShiftU64 (1, (Index
% 64))) != 0) {
394 // This page is already used.
396 return EFI_NOT_FOUND
;
401 // Being here means the memory range is available. So mark the bits for the memory range
403 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
404 mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] |= LShiftU64 (1, (Index
% 64));
412 Get the fixed loading address from image header assigned by build tool. This function only be called
413 when Loading module at Fixed address feature enabled.
415 @param ImageContext Pointer to the image context structure that describes the PE/COFF
416 image that needs to be examined by this function.
417 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
418 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
422 GetPeCoffImageFixLoadingAssignedAddress (
423 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
426 UINTN SectionHeaderOffset
;
428 EFI_IMAGE_SECTION_HEADER SectionHeader
;
429 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
432 UINT16 NumberOfSections
;
433 IMAGE_FILE_HANDLE
*Handle
;
434 UINT64 ValueInSectionHeader
;
436 Status
= EFI_NOT_FOUND
;
439 // Get PeHeader pointer
441 Handle
= (IMAGE_FILE_HANDLE
*)ImageContext
->Handle
;
442 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
*)Handle
->Source
+ ImageContext
->PeCoffHeaderOffset
);
443 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+
445 sizeof (EFI_IMAGE_FILE_HEADER
) +
446 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
;
447 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
450 // Get base address from the first section header that doesn't point to code section.
452 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
454 // Read section header from file
456 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
457 Status
= ImageContext
->ImageRead (
458 ImageContext
->Handle
,
463 if (EFI_ERROR (Status
)) {
467 if (Size
!= sizeof (EFI_IMAGE_SECTION_HEADER
)) {
468 return EFI_NOT_FOUND
;
471 Status
= EFI_NOT_FOUND
;
473 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
475 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
476 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
477 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
478 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
480 ValueInSectionHeader
= ReadUnaligned64 ((UINT64
*)&SectionHeader
.PointerToRelocations
);
481 if (ValueInSectionHeader
!= 0) {
483 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
484 // hold the specified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
485 // relative to top address
487 if ((INT64
)PcdGet64 (PcdLoadModuleAtFixAddressEnable
) < 0) {
488 ImageContext
->ImageAddress
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
+ (INT64
)(INTN
)ImageContext
->ImageAddress
;
492 // Check if the memory range is available.
494 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext
->ImageAddress
, (UINTN
)(ImageContext
->ImageSize
+ ImageContext
->SectionAlignment
));
500 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
503 DEBUG ((DEBUG_INFO
|DEBUG_LOAD
, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID
*)(UINTN
)(ImageContext
->ImageAddress
), Status
));
508 Decides whether a PE/COFF image can execute on this system, either natively
509 or via emulation/interpretation. In the latter case, the PeCoffEmu member
510 of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer
511 to the emulator protocol that supports this image.
513 @param[in, out] Image LOADED_IMAGE_PRIVATE_DATA struct pointer
515 @retval TRUE The image is supported
516 @retval FALSE The image is not supported
521 CoreIsImageTypeSupported (
522 IN OUT LOADED_IMAGE_PRIVATE_DATA
*Image
526 EMULATOR_ENTRY
*Entry
;
528 for (Link
= GetFirstNode (&mAvailableEmulators
);
529 !IsNull (&mAvailableEmulators
, Link
);
530 Link
= GetNextNode (&mAvailableEmulators
, Link
))
532 Entry
= BASE_CR (Link
, EMULATOR_ENTRY
, Link
);
533 if (Entry
->MachineType
!= Image
->ImageContext
.Machine
) {
537 if (Entry
->Emulator
->IsImageSupported (
539 Image
->ImageContext
.ImageType
,
543 Image
->PeCoffEmu
= Entry
->Emulator
;
548 return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
) ||
549 EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
);
553 Loads, relocates, and invokes a PE/COFF image
555 @param BootPolicy If TRUE, indicates that the request originates
556 from the boot manager, and that the boot
557 manager is attempting to load FilePath as a
559 @param Pe32Handle The handle of PE32 image
560 @param Image PE image to be loaded
561 @param DstBuffer The buffer to store the image
562 @param EntryPoint A pointer to the entry point
563 @param Attribute The bit mask of attributes to set for the load
566 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
567 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
568 relocate the PE/COFF file
569 @retval EFI_INVALID_PARAMETER Invalid parameter
570 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
575 IN BOOLEAN BootPolicy
,
577 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
578 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
579 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
584 BOOLEAN DstBufAlocated
;
587 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
589 Image
->ImageContext
.Handle
= Pe32Handle
;
590 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
593 // Get information about the image being loaded
595 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
596 if (EFI_ERROR (Status
)) {
600 if (!CoreIsImageTypeSupported (Image
)) {
602 // The PE/COFF loader can support loading image types that can be executed.
603 // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.
607 "Image type %s can't be loaded on %s UEFI system.\n",
608 GetMachineTypeName (Image
->ImageContext
.Machine
),
609 GetMachineTypeName (mDxeCoreImageMachineType
)
611 return EFI_UNSUPPORTED
;
615 // Set EFI memory type based on ImageType
617 switch (Image
->ImageContext
.ImageType
) {
618 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
619 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
620 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
622 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
623 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
624 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
626 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
627 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
628 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
629 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
632 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
633 return EFI_UNSUPPORTED
;
637 // Allocate memory of the correct memory type aligned on the required image boundary
639 DstBufAlocated
= FALSE
;
640 if (DstBuffer
== 0) {
642 // Allocate Destination Buffer as caller did not pass it in
645 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
646 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
648 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
651 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
654 // If the image relocations have not been stripped, then load at any address.
655 // Otherwise load at the address at which it was linked.
657 // Memory below 1MB should be treated reserved for CSM and there should be
658 // no modules whose preferred load addresses are below 1MB.
660 Status
= EFI_OUT_OF_RESOURCES
;
662 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
663 // a specified address.
665 if (PcdGet64 (PcdLoadModuleAtFixAddressEnable
) != 0 ) {
666 Status
= GetPeCoffImageFixLoadingAssignedAddress (&(Image
->ImageContext
));
668 if (EFI_ERROR (Status
)) {
670 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
672 DEBUG ((DEBUG_INFO
|DEBUG_LOAD
, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
674 Status
= CoreAllocatePages (
676 (EFI_MEMORY_TYPE
)(Image
->ImageContext
.ImageCodeMemoryType
),
677 Image
->NumberOfPages
,
678 &Image
->ImageContext
.ImageAddress
682 if ((Image
->ImageContext
.ImageAddress
>= 0x100000) || Image
->ImageContext
.RelocationsStripped
) {
683 Status
= CoreAllocatePages (
685 (EFI_MEMORY_TYPE
)(Image
->ImageContext
.ImageCodeMemoryType
),
686 Image
->NumberOfPages
,
687 &Image
->ImageContext
.ImageAddress
691 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
692 Status
= CoreAllocatePages (
694 (EFI_MEMORY_TYPE
)(Image
->ImageContext
.ImageCodeMemoryType
),
695 Image
->NumberOfPages
,
696 &Image
->ImageContext
.ImageAddress
701 if (EFI_ERROR (Status
)) {
705 DstBufAlocated
= TRUE
;
708 // Caller provided the destination buffer
711 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
713 // If the image relocations were stripped, and the caller provided a
714 // destination buffer address that does not match the address that the
715 // image is linked at, then the image cannot be loaded.
717 return EFI_INVALID_PARAMETER
;
720 if ((Image
->NumberOfPages
!= 0) &&
721 (Image
->NumberOfPages
<
722 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))))
724 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
725 return EFI_BUFFER_TOO_SMALL
;
728 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
729 Image
->ImageContext
.ImageAddress
= DstBuffer
;
732 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
733 if (!Image
->ImageContext
.IsTeImage
) {
734 Image
->ImageContext
.ImageAddress
=
735 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
736 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
740 // Load the image from the file into the allocated memory
742 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
743 if (EFI_ERROR (Status
)) {
748 // If this is a Runtime Driver, then allocate memory for the FixupData that
749 // is used to relocate the image when SetVirtualAddressMap() is called. The
750 // relocation is done by the Runtime AP.
752 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
753 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
754 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
755 if (Image
->ImageContext
.FixupData
== NULL
) {
756 Status
= EFI_OUT_OF_RESOURCES
;
763 // Relocate the image in memory
765 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
766 if (EFI_ERROR (Status
)) {
771 // Flush the Instruction Cache
773 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
776 // Copy the machine type from the context to the image private data.
778 Image
->Machine
= Image
->ImageContext
.Machine
;
781 // Get the image entry point.
783 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
786 // Fill in the image information for the Loaded Image Protocol
788 Image
->Type
= Image
->ImageContext
.ImageType
;
789 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
790 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
791 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
)(Image
->ImageContext
.ImageCodeMemoryType
);
792 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
)(Image
->ImageContext
.ImageDataMemoryType
);
793 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
794 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
796 // Make a list off all the RT images so we can let the RT AP know about them.
798 Image
->RuntimeData
= AllocateRuntimePool (sizeof (EFI_RUNTIME_IMAGE_ENTRY
));
799 if (Image
->RuntimeData
== NULL
) {
803 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
804 Image
->RuntimeData
->ImageSize
= (UINT64
)(Image
->Info
.ImageSize
);
805 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
806 Image
->RuntimeData
->Handle
= Image
->Handle
;
807 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
808 InsertImageRecord (Image
->RuntimeData
);
813 // Fill in the entry point of the image if it is available
815 if (EntryPoint
!= NULL
) {
816 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
820 // Print the load address and the PDB file name if it is available
827 CHAR8 EfiFileName
[256];
830 DEBUG_INFO
| DEBUG_LOAD
,
831 "Loading driver at 0x%11p EntryPoint=0x%11p ",
832 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
833 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)
837 // Print Module Name by Pdb file path.
838 // Windows and Unix style file path are all trimmed correctly.
840 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
842 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
843 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
844 StartIndex
= Index
+ 1;
849 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
850 // The PDB file name is limited in the range of 0~255.
851 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
853 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
854 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
855 if (EfiFileName
[Index
] == 0) {
856 EfiFileName
[Index
] = '.';
859 if (EfiFileName
[Index
] == '.') {
860 EfiFileName
[Index
+ 1] = 'e';
861 EfiFileName
[Index
+ 2] = 'f';
862 EfiFileName
[Index
+ 3] = 'i';
863 EfiFileName
[Index
+ 4] = 0;
868 if (Index
== sizeof (EfiFileName
) - 4) {
869 EfiFileName
[Index
] = 0;
872 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
875 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
887 if (DstBufAlocated
) {
888 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
889 Image
->ImageContext
.ImageAddress
= 0;
890 Image
->ImageBasePage
= 0;
893 if (Image
->ImageContext
.FixupData
!= NULL
) {
894 CoreFreePool (Image
->ImageContext
.FixupData
);
901 Get the image's private data from its handle.
903 @param ImageHandle The image handle
905 @return Return the image private data associated with ImageHandle.
908 LOADED_IMAGE_PRIVATE_DATA
*
909 CoreLoadedImageInfo (
910 IN EFI_HANDLE ImageHandle
914 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
915 LOADED_IMAGE_PRIVATE_DATA
*Image
;
917 Status
= CoreHandleProtocol (
919 &gEfiLoadedImageProtocolGuid
,
920 (VOID
**)&LoadedImage
922 if (!EFI_ERROR (Status
)) {
923 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
925 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
933 Unloads EFI image from memory.
935 @param Image EFI image
936 @param FreePage Free allocated pages
940 CoreUnloadAndCloseImage (
941 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
947 EFI_HANDLE
*HandleBuffer
;
949 EFI_GUID
**ProtocolGuidArray
;
952 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
957 ProtocolGuidArray
= NULL
;
959 if (Image
->Started
) {
960 UnregisterMemoryProfileImage (Image
);
963 UnprotectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
965 if (Image
->PeCoffEmu
!= NULL
) {
967 // If the PE/COFF Emulator protocol exists we must unregister the image.
969 Image
->PeCoffEmu
->UnregisterImage (Image
->PeCoffEmu
, Image
->ImageBasePage
);
973 // Unload image, free Image->ImageContext->ModHandle
975 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
978 // Free our references to the image handle
980 if (Image
->Handle
!= NULL
) {
981 Status
= CoreLocateHandleBuffer (
988 if (!EFI_ERROR (Status
)) {
989 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
990 Status
= CoreProtocolsPerHandle (
991 HandleBuffer
[HandleIndex
],
995 if (!EFI_ERROR (Status
)) {
996 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
997 Status
= CoreOpenProtocolInformation (
998 HandleBuffer
[HandleIndex
],
999 ProtocolGuidArray
[ProtocolIndex
],
1003 if (!EFI_ERROR (Status
)) {
1004 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1005 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1006 Status
= CoreCloseProtocol (
1007 HandleBuffer
[HandleIndex
],
1008 ProtocolGuidArray
[ProtocolIndex
],
1010 OpenInfo
[OpenInfoIndex
].ControllerHandle
1015 if (OpenInfo
!= NULL
) {
1016 CoreFreePool (OpenInfo
);
1021 if (ProtocolGuidArray
!= NULL
) {
1022 CoreFreePool (ProtocolGuidArray
);
1027 if (HandleBuffer
!= NULL
) {
1028 CoreFreePool (HandleBuffer
);
1032 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1034 Status
= CoreUninstallProtocolInterface (
1036 &gEfiLoadedImageDevicePathProtocolGuid
,
1037 Image
->LoadedImageDevicePath
1040 Status
= CoreUninstallProtocolInterface (
1042 &gEfiLoadedImageProtocolGuid
,
1046 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1047 Status
= CoreUninstallProtocolInterface (
1049 &gEfiHiiPackageListProtocolGuid
,
1050 (VOID
*)(UINTN
)Image
->ImageContext
.HiiResourceData
1055 if (Image
->RuntimeData
!= NULL
) {
1056 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1058 // Remove the Image from the Runtime Image list as we are about to Free it!
1060 RemoveEntryList (&Image
->RuntimeData
->Link
);
1061 RemoveImageRecord (Image
->RuntimeData
);
1064 CoreFreePool (Image
->RuntimeData
);
1068 // Free the Image from memory
1070 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1071 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1075 // Done with the Image structure
1077 if (Image
->Info
.FilePath
!= NULL
) {
1078 CoreFreePool (Image
->Info
.FilePath
);
1081 if (Image
->LoadedImageDevicePath
!= NULL
) {
1082 CoreFreePool (Image
->LoadedImageDevicePath
);
1085 if (Image
->FixupData
!= NULL
) {
1086 CoreFreePool (Image
->FixupData
);
1089 CoreFreePool (Image
);
1093 Loads an EFI image into memory and returns a handle to the image.
1095 @param BootPolicy If TRUE, indicates that the request originates
1096 from the boot manager, and that the boot
1097 manager is attempting to load FilePath as a
1099 @param ParentImageHandle The caller's image handle.
1100 @param FilePath The specific file path from which the image is
1102 @param SourceBuffer If not NULL, a pointer to the memory location
1103 containing a copy of the image to be loaded.
1104 @param SourceSize The size in bytes of SourceBuffer.
1105 @param DstBuffer The buffer to store the image
1106 @param NumberOfPages If not NULL, it inputs a pointer to the page
1107 number of DstBuffer and outputs a pointer to
1108 the page number of the image. If this number is
1109 not enough, return EFI_BUFFER_TOO_SMALL and
1110 this parameter contains the required number.
1111 @param ImageHandle Pointer to the returned image handle that is
1112 created when the image is successfully loaded.
1113 @param EntryPoint A pointer to the entry point
1114 @param Attribute The bit mask of attributes to set for the load
1117 @retval EFI_SUCCESS The image was loaded into memory.
1118 @retval EFI_NOT_FOUND The FilePath was not found.
1119 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1120 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1121 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1122 path cannot be parsed to locate the proper
1123 protocol for loading the file.
1124 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1126 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1128 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1129 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1130 image from being loaded. NULL is returned in *ImageHandle.
1131 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1132 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1133 platform policy specifies that the image should not be started.
1137 CoreLoadImageCommon (
1138 IN BOOLEAN BootPolicy
,
1139 IN EFI_HANDLE ParentImageHandle
,
1140 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1141 IN VOID
*SourceBuffer OPTIONAL
,
1142 IN UINTN SourceSize
,
1143 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1144 IN OUT UINTN
*NumberOfPages OPTIONAL
,
1145 OUT EFI_HANDLE
*ImageHandle
,
1146 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1150 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1151 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
1152 IMAGE_FILE_HANDLE FHand
;
1154 EFI_STATUS SecurityStatus
;
1155 EFI_HANDLE DeviceHandle
;
1156 UINT32 AuthenticationStatus
;
1157 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
1158 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
1159 EFI_DEVICE_PATH_PROTOCOL
*InputFilePath
;
1160 EFI_DEVICE_PATH_PROTOCOL
*Node
;
1162 BOOLEAN ImageIsFromFv
;
1163 BOOLEAN ImageIsFromLoadFile
;
1165 SecurityStatus
= EFI_SUCCESS
;
1167 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
1171 // The caller must pass in a valid ParentImageHandle
1173 if ((ImageHandle
== NULL
) || (ParentImageHandle
== NULL
)) {
1174 return EFI_INVALID_PARAMETER
;
1177 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
1178 if (ParentImage
== NULL
) {
1179 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
1180 return EFI_INVALID_PARAMETER
;
1183 ZeroMem (&FHand
, sizeof (IMAGE_FILE_HANDLE
));
1184 FHand
.Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
1185 OriginalFilePath
= FilePath
;
1186 InputFilePath
= FilePath
;
1187 HandleFilePath
= FilePath
;
1188 DeviceHandle
= NULL
;
1189 Status
= EFI_SUCCESS
;
1190 AuthenticationStatus
= 0;
1191 ImageIsFromFv
= FALSE
;
1192 ImageIsFromLoadFile
= FALSE
;
1195 // If the caller passed a copy of the file, then just use it
1197 if (SourceBuffer
!= NULL
) {
1198 FHand
.Source
= SourceBuffer
;
1199 FHand
.SourceSize
= SourceSize
;
1200 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1201 if (EFI_ERROR (Status
)) {
1202 DeviceHandle
= NULL
;
1205 if (SourceSize
> 0) {
1206 Status
= EFI_SUCCESS
;
1208 Status
= EFI_LOAD_ERROR
;
1211 if (FilePath
== NULL
) {
1212 return EFI_INVALID_PARAMETER
;
1216 // Try to get the image device handle by checking the match protocol.
1219 Status
= CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1220 if (!EFI_ERROR (Status
)) {
1221 ImageIsFromFv
= TRUE
;
1223 HandleFilePath
= FilePath
;
1224 Status
= CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1225 if (EFI_ERROR (Status
)) {
1227 HandleFilePath
= FilePath
;
1228 Status
= CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1231 if (EFI_ERROR (Status
)) {
1232 HandleFilePath
= FilePath
;
1233 Status
= CoreLocateDevicePath (&gEfiLoadFileProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1234 if (!EFI_ERROR (Status
)) {
1235 ImageIsFromLoadFile
= TRUE
;
1236 Node
= HandleFilePath
;
1243 // Get the source file buffer by its device path.
1245 FHand
.Source
= GetFileBufferByFilePath (
1249 &AuthenticationStatus
1251 if (FHand
.Source
== NULL
) {
1252 Status
= EFI_NOT_FOUND
;
1254 FHand
.FreeBuffer
= TRUE
;
1255 if (ImageIsFromLoadFile
) {
1257 // LoadFile () may cause the device path of the Handle be updated.
1259 OriginalFilePath
= AppendDevicePath (DevicePathFromHandle (DeviceHandle
), Node
);
1264 if (EFI_ERROR (Status
)) {
1269 if (gSecurity2
!= NULL
) {
1271 // Verify File Authentication through the Security2 Architectural Protocol
1273 SecurityStatus
= gSecurity2
->FileAuthentication (
1280 if (!EFI_ERROR (SecurityStatus
) && ImageIsFromFv
) {
1282 // When Security2 is installed, Security Architectural Protocol must be published.
1284 ASSERT (gSecurity
!= NULL
);
1287 // Verify the Authentication Status through the Security Architectural Protocol
1288 // Only on images that have been read using Firmware Volume protocol.
1290 SecurityStatus
= gSecurity
->FileAuthenticationState (
1292 AuthenticationStatus
,
1296 } else if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
1298 // Verify the Authentication Status through the Security Architectural Protocol
1300 SecurityStatus
= gSecurity
->FileAuthenticationState (
1302 AuthenticationStatus
,
1308 // Check Security Status.
1310 if (EFI_ERROR (SecurityStatus
) && (SecurityStatus
!= EFI_SECURITY_VIOLATION
)) {
1311 if (SecurityStatus
== EFI_ACCESS_DENIED
) {
1313 // Image was not loaded because the platform policy prohibits the image from being loaded.
1314 // It's the only place we could meet EFI_ACCESS_DENIED.
1316 *ImageHandle
= NULL
;
1319 Status
= SecurityStatus
;
1325 // Allocate a new image structure
1327 Image
= AllocateZeroPool (sizeof (LOADED_IMAGE_PRIVATE_DATA
));
1328 if (Image
== NULL
) {
1329 Status
= EFI_OUT_OF_RESOURCES
;
1334 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1336 FilePath
= OriginalFilePath
;
1337 if (DeviceHandle
!= NULL
) {
1338 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
1339 if (!EFI_ERROR (Status
)) {
1340 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
);
1341 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*)(((UINT8
*)FilePath
) + FilePathSize
);
1346 // Initialize the fields for an internal driver
1348 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
1349 Image
->Info
.SystemTable
= gDxeCoreST
;
1350 Image
->Info
.DeviceHandle
= DeviceHandle
;
1351 Image
->Info
.Revision
= EFI_LOADED_IMAGE_PROTOCOL_REVISION
;
1352 Image
->Info
.FilePath
= DuplicateDevicePath (FilePath
);
1353 Image
->Info
.ParentHandle
= ParentImageHandle
;
1355 if (NumberOfPages
!= NULL
) {
1356 Image
->NumberOfPages
= *NumberOfPages
;
1358 Image
->NumberOfPages
= 0;
1362 // Install the protocol interfaces for this image
1363 // don't fire notifications yet
1365 Status
= CoreInstallProtocolInterfaceNotify (
1367 &gEfiLoadedImageProtocolGuid
,
1368 EFI_NATIVE_INTERFACE
,
1372 if (EFI_ERROR (Status
)) {
1377 // Load the image. If EntryPoint is Null, it will not be set.
1379 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
1380 if (EFI_ERROR (Status
)) {
1381 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
1382 if (NumberOfPages
!= NULL
) {
1383 *NumberOfPages
= Image
->NumberOfPages
;
1390 if (NumberOfPages
!= NULL
) {
1391 *NumberOfPages
= Image
->NumberOfPages
;
1395 // Register the image in the Debug Image Info Table if the attribute is set
1397 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) != 0) {
1398 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
1402 // Reinstall loaded image protocol to fire any notifications
1404 Status
= CoreReinstallProtocolInterface (
1406 &gEfiLoadedImageProtocolGuid
,
1410 if (EFI_ERROR (Status
)) {
1415 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1416 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1418 if (OriginalFilePath
!= NULL
) {
1419 Image
->LoadedImageDevicePath
= DuplicateDevicePath (OriginalFilePath
);
1423 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1425 Status
= CoreInstallProtocolInterface (
1427 &gEfiLoadedImageDevicePathProtocolGuid
,
1428 EFI_NATIVE_INTERFACE
,
1429 Image
->LoadedImageDevicePath
1431 if (EFI_ERROR (Status
)) {
1436 // Install HII Package List Protocol onto the image handle
1438 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1439 Status
= CoreInstallProtocolInterface (
1441 &gEfiHiiPackageListProtocolGuid
,
1442 EFI_NATIVE_INTERFACE
,
1443 (VOID
*)(UINTN
)Image
->ImageContext
.HiiResourceData
1445 if (EFI_ERROR (Status
)) {
1450 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
1453 // Success. Return the image handle
1455 *ImageHandle
= Image
->Handle
;
1459 // All done accessing the source file
1460 // If we allocated the Source buffer, free it
1462 if (FHand
.FreeBuffer
) {
1463 CoreFreePool (FHand
.Source
);
1466 if (OriginalFilePath
!= InputFilePath
) {
1467 CoreFreePool (OriginalFilePath
);
1471 // There was an error. If there's an Image structure, free it
1473 if (EFI_ERROR (Status
)) {
1474 if (Image
!= NULL
) {
1475 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
1478 } else if (EFI_ERROR (SecurityStatus
)) {
1479 Status
= SecurityStatus
;
1483 // Track the return status from LoadImage.
1485 if (Image
!= NULL
) {
1486 Image
->LoadImageStatus
= Status
;
1493 Loads an EFI image into memory and returns a handle to the image.
1495 @param BootPolicy If TRUE, indicates that the request originates
1496 from the boot manager, and that the boot
1497 manager is attempting to load FilePath as a
1499 @param ParentImageHandle The caller's image handle.
1500 @param FilePath The specific file path from which the image is
1502 @param SourceBuffer If not NULL, a pointer to the memory location
1503 containing a copy of the image to be loaded.
1504 @param SourceSize The size in bytes of SourceBuffer.
1505 @param ImageHandle Pointer to the returned image handle that is
1506 created when the image is successfully loaded.
1508 @retval EFI_SUCCESS The image was loaded into memory.
1509 @retval EFI_NOT_FOUND The FilePath was not found.
1510 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1511 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1512 path cannot be parsed to locate the proper
1513 protocol for loading the file.
1514 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1516 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1518 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1519 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1520 image from being loaded. NULL is returned in *ImageHandle.
1521 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1522 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1523 platform policy specifies that the image should not be started.
1529 IN BOOLEAN BootPolicy
,
1530 IN EFI_HANDLE ParentImageHandle
,
1531 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1532 IN VOID
*SourceBuffer OPTIONAL
,
1533 IN UINTN SourceSize
,
1534 OUT EFI_HANDLE
*ImageHandle
1540 PERF_LOAD_IMAGE_BEGIN (NULL
);
1542 Status
= CoreLoadImageCommon (
1548 (EFI_PHYSICAL_ADDRESS
)(UINTN
)NULL
,
1552 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1556 if (!EFI_ERROR (Status
)) {
1558 // ImageHandle will be valid only Status is success.
1560 Handle
= *ImageHandle
;
1563 PERF_LOAD_IMAGE_END (Handle
);
1569 Transfer control to a loaded image's entry point.
1571 @param ImageHandle Handle of image to be started.
1572 @param ExitDataSize Pointer of the size to ExitData
1573 @param ExitData Pointer to a pointer to a data buffer that
1574 includes a Null-terminated string,
1575 optionally followed by additional binary data.
1576 The string is a description that the caller may
1577 use to further indicate the reason for the
1580 @retval EFI_INVALID_PARAMETER Invalid parameter
1581 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1582 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1583 @retval EFI_SUCCESS Successfully transfer control to the image's
1590 IN EFI_HANDLE ImageHandle
,
1591 OUT UINTN
*ExitDataSize
,
1592 OUT CHAR16
**ExitData OPTIONAL
1596 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1597 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1598 UINT64 HandleDatabaseKey
;
1602 Handle
= ImageHandle
;
1604 Image
= CoreLoadedImageInfo (ImageHandle
);
1605 if ((Image
== NULL
) || Image
->Started
) {
1606 return EFI_INVALID_PARAMETER
;
1609 if (EFI_ERROR (Image
->LoadImageStatus
)) {
1610 return Image
->LoadImageStatus
;
1614 // The image to be started must have the machine type supported by DxeCore.
1616 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->Machine
) &&
1617 (Image
->PeCoffEmu
== NULL
))
1620 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1621 // But it can not be started.
1623 DEBUG ((DEBUG_ERROR
, "Image type %s can't be started ", GetMachineTypeName (Image
->Machine
)));
1624 DEBUG ((DEBUG_ERROR
, "on %s UEFI system.\n", GetMachineTypeName (mDxeCoreImageMachineType
)));
1625 return EFI_UNSUPPORTED
;
1628 if (Image
->PeCoffEmu
!= NULL
) {
1629 Status
= Image
->PeCoffEmu
->RegisterImage (
1631 Image
->ImageBasePage
,
1632 EFI_PAGES_TO_SIZE (Image
->NumberOfPages
),
1635 if (EFI_ERROR (Status
)) {
1637 DEBUG_LOAD
| DEBUG_ERROR
,
1638 "CoreLoadPeImage: Failed to register foreign image with emulator - %r\n",
1645 PERF_START_IMAGE_BEGIN (Handle
);
1648 // Push the current start image context, and
1649 // link the current image to the head. This is the
1650 // only image that can call Exit()
1652 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1653 LastImage
= mCurrentImage
;
1654 mCurrentImage
= Image
;
1655 Image
->Tpl
= gEfiCurrentTpl
;
1658 // Set long jump for Exit() support
1659 // JumpContext must be aligned on a CPU specific boundary.
1660 // Overallocate the buffer and force the required alignment
1662 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1663 if (Image
->JumpBuffer
== NULL
) {
1665 // Image may be unloaded after return with failure,
1666 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1668 PERF_START_IMAGE_END (NULL
);
1671 // Pop the current start image context
1673 mCurrentImage
= LastImage
;
1675 return EFI_OUT_OF_RESOURCES
;
1678 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1680 SetJumpFlag
= SetJump (Image
->JumpContext
);
1682 // The initial call to SetJump() must always return 0.
1683 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1685 if (SetJumpFlag
== 0) {
1686 RegisterMemoryProfileImage (Image
, (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
? EFI_FV_FILETYPE_APPLICATION
: EFI_FV_FILETYPE_DRIVER
));
1688 // Call the image's entry point
1690 Image
->Started
= TRUE
;
1691 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1694 // Add some debug information if the image returned with error.
1695 // This make the user aware and check if the driver image have already released
1696 // all the resource in this situation.
1698 DEBUG_CODE_BEGIN ();
1699 if (EFI_ERROR (Image
->Status
)) {
1700 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1706 // If the image returns, exit it through Exit()
1708 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1712 // Image has completed. Verify the tpl is the same
1714 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1715 CoreRestoreTpl (Image
->Tpl
);
1717 CoreFreePool (Image
->JumpBuffer
);
1720 // Pop the current start image context
1722 mCurrentImage
= LastImage
;
1725 // UEFI Specification - StartImage() - EFI 1.10 Extension
1726 // To maintain compatibility with UEFI drivers that are written to the EFI
1727 // 1.02 Specification, StartImage() must monitor the handle database before
1728 // and after each image is started. If any handles are created or modified
1729 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1730 // be called with the Recursive parameter set to TRUE for each of the newly
1731 // created or modified handles before StartImage() returns.
1733 if (Image
->Type
!= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1734 CoreConnectHandlesByKey (HandleDatabaseKey
);
1738 // Handle the image's returned ExitData
1740 DEBUG_CODE_BEGIN ();
1741 if ((Image
->ExitDataSize
!= 0) || (Image
->ExitData
!= NULL
)) {
1742 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1743 if (Image
->ExitData
!= NULL
) {
1744 DEBUG ((DEBUG_LOAD
, " (%s)", Image
->ExitData
));
1747 DEBUG ((DEBUG_LOAD
, "\n"));
1753 // Return the exit data to the caller
1755 if ((ExitData
!= NULL
) && (ExitDataSize
!= NULL
)) {
1756 *ExitDataSize
= Image
->ExitDataSize
;
1757 *ExitData
= Image
->ExitData
;
1760 // Caller doesn't want the exit data, free it
1762 CoreFreePool (Image
->ExitData
);
1763 Image
->ExitData
= NULL
;
1767 // Save the Status because Image will get destroyed if it is unloaded.
1769 Status
= Image
->Status
;
1772 // If the image returned an error, or if the image is an application
1775 if (EFI_ERROR (Image
->Status
) || (Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
)) {
1776 CoreUnloadAndCloseImage (Image
, TRUE
);
1778 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1786 PERF_START_IMAGE_END (Handle
);
1791 Terminates the currently loaded EFI image and returns control to boot services.
1793 @param ImageHandle Handle that identifies the image. This
1794 parameter is passed to the image on entry.
1795 @param Status The image's exit code.
1796 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1797 ExitStatus is EFI_SUCCESS.
1798 @param ExitData Pointer to a data buffer that includes a
1799 Null-terminated Unicode string, optionally
1800 followed by additional binary data. The string
1801 is a description that the caller may use to
1802 further indicate the reason for the image's
1805 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1807 @retval EFI_SUCCESS Successfully terminates the currently loaded
1809 @retval EFI_ACCESS_DENIED Should never reach there.
1810 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1816 IN EFI_HANDLE ImageHandle
,
1817 IN EFI_STATUS Status
,
1818 IN UINTN ExitDataSize
,
1819 IN CHAR16
*ExitData OPTIONAL
1822 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1826 // Prevent possible reentrance to this function
1827 // for the same ImageHandle
1829 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1831 Image
= CoreLoadedImageInfo (ImageHandle
);
1832 if (Image
== NULL
) {
1833 Status
= EFI_INVALID_PARAMETER
;
1837 if (!Image
->Started
) {
1839 // The image has not been started so just free its resources
1841 CoreUnloadAndCloseImage (Image
, TRUE
);
1842 Status
= EFI_SUCCESS
;
1847 // Image has been started, verify this image can exit
1849 if (Image
!= mCurrentImage
) {
1850 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1851 Status
= EFI_INVALID_PARAMETER
;
1858 Image
->Status
= Status
;
1861 // If there's ExitData info, move it
1863 if (ExitData
!= NULL
) {
1864 Image
->ExitDataSize
= ExitDataSize
;
1865 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1866 if (Image
->ExitData
== NULL
) {
1867 Status
= EFI_OUT_OF_RESOURCES
;
1871 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1874 CoreRestoreTpl (OldTpl
);
1876 // return to StartImage
1878 LongJump (Image
->JumpContext
, (UINTN
)-1);
1881 // If we return from LongJump, then it is an error
1884 Status
= EFI_ACCESS_DENIED
;
1886 CoreRestoreTpl (OldTpl
);
1893 @param ImageHandle Handle that identifies the image to be
1896 @retval EFI_SUCCESS The image has been unloaded.
1897 @retval EFI_UNSUPPORTED The image has been started, and does not support
1899 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1905 IN EFI_HANDLE ImageHandle
1909 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1911 Image
= CoreLoadedImageInfo (ImageHandle
);
1912 if (Image
== NULL
) {
1914 // The image handle is not valid
1916 Status
= EFI_INVALID_PARAMETER
;
1920 if (Image
->Started
) {
1922 // The image has been started, request it to unload.
1924 Status
= EFI_UNSUPPORTED
;
1925 if (Image
->Info
.Unload
!= NULL
) {
1926 Status
= Image
->Info
.Unload (ImageHandle
);
1930 // This Image hasn't been started, thus it can be unloaded
1932 Status
= EFI_SUCCESS
;
1935 if (!EFI_ERROR (Status
)) {
1937 // if the Image was not started or Unloaded O.K. then clean up
1939 CoreUnloadAndCloseImage (Image
, TRUE
);