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 EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*Emulator
;
32 STATIC LIST_ENTRY mAvailableEmulators
;
33 STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent
;
34 STATIC VOID
*mPeCoffEmuProtocolNotifyRegistration
;
37 // This code is needed to build the Image handle for the DXE Core
39 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
40 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
42 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
43 TRUE
, // If entrypoint has been called
46 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
47 NULL
, // Parent handle
48 NULL
, // System handle
50 NULL
, // Device handle
59 EfiBootServicesCode
, // ImageCodeType
60 EfiBootServicesData
// ImageDataType
62 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
66 EFI_SUCCESS
, // Status
74 NULL
// LoadedImageDevicePath
77 // The field is define for Loading modules at fixed address feature to tracker the PEI code
78 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
81 GLOBAL_REMOVE_IF_UNREFERENCED UINT64
*mDxeCodeMemoryRangeUsageBitMap
=NULL
;
85 CHAR16
*MachineTypeName
;
88 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo
[] = {
89 {EFI_IMAGE_MACHINE_IA32
, L
"IA32"},
90 {EFI_IMAGE_MACHINE_IA64
, L
"IA64"},
91 {EFI_IMAGE_MACHINE_X64
, L
"X64"},
92 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
, L
"ARM"},
93 {EFI_IMAGE_MACHINE_AARCH64
, L
"AARCH64"}
96 UINT16 mDxeCoreImageMachineType
= 0;
99 Return machine type name.
101 @param MachineType The machine type
103 @return machine type name
112 for (Index
= 0; Index
< sizeof(mMachineTypeInfo
)/sizeof(mMachineTypeInfo
[0]); Index
++) {
113 if (mMachineTypeInfo
[Index
].MachineType
== MachineType
) {
114 return mMachineTypeInfo
[Index
].MachineTypeName
;
122 Notification event handler registered by CoreInitializeImageServices () to
123 keep track of which PE/COFF image emulators are available.
125 @param Event The Event that is being processed, not used.
126 @param Context Event Context, not used.
132 PeCoffEmuProtocolNotify (
139 EFI_HANDLE EmuHandle
;
140 EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*Emulator
;
141 EMULATOR_ENTRY
*Entry
;
147 BufferSize
= sizeof (EmuHandle
);
148 Status
= CoreLocateHandle (
151 mPeCoffEmuProtocolNotifyRegistration
,
155 if (EFI_ERROR (Status
)) {
157 // If no more notification events exit
162 Status
= CoreHandleProtocol (
164 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
167 if (EFI_ERROR (Status
) || Emulator
== NULL
) {
171 Entry
= AllocateZeroPool (sizeof (*Entry
));
172 ASSERT (Entry
!= NULL
);
174 Entry
->Emulator
= Emulator
;
175 Entry
->MachineType
= Entry
->Emulator
->MachineType
;
177 InsertTailList (&mAvailableEmulators
, &Entry
->Link
);
182 Add the Image Services to EFI Boot Services Table and install the protocol
183 interfaces for this image.
185 @param HobStart The HOB to initialize
191 CoreInitializeImageServices (
196 LOADED_IMAGE_PRIVATE_DATA
*Image
;
197 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
198 UINT64 DxeCoreImageLength
;
199 VOID
*DxeCoreEntryPoint
;
200 EFI_PEI_HOB_POINTERS DxeCoreHob
;
203 // Searching for image hob
205 DxeCoreHob
.Raw
= HobStart
;
206 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
207 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
213 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
215 ASSERT (DxeCoreHob
.Raw
!= NULL
);
217 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
218 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
219 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
220 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
223 // Initialize the fields for an internal driver
225 Image
= &mCorePrivateImage
;
227 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
228 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
229 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
230 Image
->Tpl
= gEfiCurrentTpl
;
231 Image
->Info
.SystemTable
= gDxeCoreST
;
232 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
233 Image
->Info
.ImageSize
= DxeCoreImageLength
;
236 // Install the protocol interfaces for this image
238 Status
= CoreInstallProtocolInterface (
240 &gEfiLoadedImageProtocolGuid
,
241 EFI_NATIVE_INTERFACE
,
244 ASSERT_EFI_ERROR (Status
);
246 mCurrentImage
= Image
;
249 // Fill in DXE globals
251 mDxeCoreImageMachineType
= PeCoffLoaderGetMachineType (Image
->Info
.ImageBase
);
252 gDxeCoreImageHandle
= Image
->Handle
;
253 gDxeCoreLoadedImage
= &Image
->Info
;
256 // Create the PE/COFF emulator protocol registration event
258 Status
= CoreCreateEvent (
261 PeCoffEmuProtocolNotify
,
263 &mPeCoffEmuProtocolRegistrationEvent
265 ASSERT_EFI_ERROR(Status
);
268 // Register for protocol notifications on this event
270 Status
= CoreRegisterProtocolNotify (
271 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
272 mPeCoffEmuProtocolRegistrationEvent
,
273 &mPeCoffEmuProtocolNotifyRegistration
275 ASSERT_EFI_ERROR(Status
);
277 InitializeListHead (&mAvailableEmulators
);
279 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
281 // Export DXE Core PE Loader functionality for backward compatibility.
283 Status
= CoreInstallProtocolInterface (
284 &mLoadPe32PrivateData
.Handle
,
285 &gEfiLoadPeImageProtocolGuid
,
286 EFI_NATIVE_INTERFACE
,
287 &mLoadPe32PrivateData
.Pe32Image
291 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
297 Read image file (specified by UserHandle) into user specified buffer with specified offset
300 @param UserHandle Image file handle
301 @param Offset Offset to the source file
302 @param ReadSize For input, pointer of size to read; For output,
303 pointer of size actually read.
304 @param Buffer Buffer to write into
306 @retval EFI_SUCCESS Successfully read the specified part of file
315 IN OUT UINTN
*ReadSize
,
320 IMAGE_FILE_HANDLE
*FHand
;
322 if (UserHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
323 return EFI_INVALID_PARAMETER
;
326 if (MAX_ADDRESS
- Offset
< *ReadSize
) {
327 return EFI_INVALID_PARAMETER
;
330 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
331 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
334 // Move data from our local copy of the file
336 EndPosition
= Offset
+ *ReadSize
;
337 if (EndPosition
> FHand
->SourceSize
) {
338 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
340 if (Offset
>= FHand
->SourceSize
) {
344 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
348 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
349 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
350 The function is only invoked when load modules at fixed address feature is enabled.
352 @param ImageBase The base address the image will be loaded at.
353 @param ImageSize The size of the image
355 @retval EFI_SUCCESS The memory range the image will be loaded in is available
356 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
359 CheckAndMarkFixLoadingMemoryUsageBitMap (
360 IN EFI_PHYSICAL_ADDRESS ImageBase
,
364 UINT32 DxeCodePageNumber
;
366 EFI_PHYSICAL_ADDRESS DxeCodeBase
;
367 UINTN BaseOffsetPageNumber
;
368 UINTN TopOffsetPageNumber
;
371 // The DXE code range includes RuntimeCodePage range and Boot time code range.
373 DxeCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
374 DxeCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
375 DxeCodeSize
= EFI_PAGES_TO_SIZE(DxeCodePageNumber
);
376 DxeCodeBase
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
- DxeCodeSize
;
379 // If the memory usage bit map is not initialized, do it. Every bit in the array
380 // indicate the status of the corresponding memory page, available or not
382 if (mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
383 mDxeCodeMemoryRangeUsageBitMap
= AllocateZeroPool(((DxeCodePageNumber
/64) + 1)*sizeof(UINT64
));
386 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
388 if (!gLoadFixedAddressCodeMemoryReady
|| mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
389 return EFI_NOT_FOUND
;
392 // Test the memory range for loading the image in the DXE code range.
394 if (gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
< ImageBase
+ ImageSize
||
395 DxeCodeBase
> ImageBase
) {
396 return EFI_NOT_FOUND
;
399 // Test if the memory is avalaible or not.
401 BaseOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
- DxeCodeBase
));
402 TopOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
+ ImageSize
- DxeCodeBase
));
403 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
404 if ((mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] & LShiftU64(1, (Index
% 64))) != 0) {
406 // This page is already used.
408 return EFI_NOT_FOUND
;
413 // Being here means the memory range is available. So mark the bits for the memory range
415 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
416 mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] |= LShiftU64(1, (Index
% 64));
422 Get the fixed loading address from image header assigned by build tool. This function only be called
423 when Loading module at Fixed address feature enabled.
425 @param ImageContext Pointer to the image context structure that describes the PE/COFF
426 image that needs to be examined by this function.
427 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
428 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
432 GetPeCoffImageFixLoadingAssignedAddress(
433 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
436 UINTN SectionHeaderOffset
;
438 EFI_IMAGE_SECTION_HEADER SectionHeader
;
439 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
442 UINT16 NumberOfSections
;
443 IMAGE_FILE_HANDLE
*Handle
;
444 UINT64 ValueInSectionHeader
;
447 Status
= EFI_NOT_FOUND
;
450 // Get PeHeader pointer
452 Handle
= (IMAGE_FILE_HANDLE
*)ImageContext
->Handle
;
453 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
* )Handle
->Source
+ ImageContext
->PeCoffHeaderOffset
);
454 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+
456 sizeof (EFI_IMAGE_FILE_HEADER
) +
457 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
;
458 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
461 // Get base address from the first section header that doesn't point to code section.
463 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
465 // Read section header from file
467 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
468 Status
= ImageContext
->ImageRead (
469 ImageContext
->Handle
,
474 if (EFI_ERROR (Status
)) {
477 if (Size
!= sizeof (EFI_IMAGE_SECTION_HEADER
)) {
478 return EFI_NOT_FOUND
;
481 Status
= EFI_NOT_FOUND
;
483 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
485 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
486 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
487 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
488 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
490 ValueInSectionHeader
= ReadUnaligned64((UINT64
*)&SectionHeader
.PointerToRelocations
);
491 if (ValueInSectionHeader
!= 0) {
493 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
494 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
495 // relative to top address
497 if ((INT64
)PcdGet64(PcdLoadModuleAtFixAddressEnable
) < 0) {
498 ImageContext
->ImageAddress
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
+ (INT64
)(INTN
)ImageContext
->ImageAddress
;
501 // Check if the memory range is available.
503 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext
->ImageAddress
, (UINTN
)(ImageContext
->ImageSize
+ ImageContext
->SectionAlignment
));
507 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
509 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
));
514 Decides whether a PE/COFF image can execute on this system, either natively
515 or via emulation/interpretation. In the latter case, the PeCoffEmu member
516 of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer
517 to the emulator protocol that supports this image.
519 @param[in, out] Image LOADED_IMAGE_PRIVATE_DATA struct pointer
521 @retval TRUE The image is supported
522 @retval FALSE The image is not supported
527 CoreIsImageTypeSupported (
528 IN OUT LOADED_IMAGE_PRIVATE_DATA
*Image
532 EMULATOR_ENTRY
*Entry
;
534 for (Link
= GetFirstNode (&mAvailableEmulators
);
535 !IsNull (&mAvailableEmulators
, Link
);
536 Link
= GetNextNode (&mAvailableEmulators
, Link
)) {
538 Entry
= BASE_CR (Link
, EMULATOR_ENTRY
, Link
);
539 if (Entry
->MachineType
!= Image
->ImageContext
.Machine
) {
543 if (Entry
->Emulator
->IsImageSupported (Entry
->Emulator
,
544 Image
->ImageContext
.ImageType
,
545 Image
->Info
.FilePath
)) {
546 Image
->PeCoffEmu
= Entry
->Emulator
;
551 return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
) ||
552 EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
);
556 Loads, relocates, and invokes a PE/COFF image
558 @param BootPolicy If TRUE, indicates that the request originates
559 from the boot manager, and that the boot
560 manager is attempting to load FilePath as a
562 @param Pe32Handle The handle of PE32 image
563 @param Image PE image to be loaded
564 @param DstBuffer The buffer to store the image
565 @param EntryPoint A pointer to the entry point
566 @param Attribute The bit mask of attributes to set for the load
569 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
570 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
571 relocate the PE/COFF file
572 @retval EFI_INVALID_PARAMETER Invalid parameter
573 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
578 IN BOOLEAN BootPolicy
,
580 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
581 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
582 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
587 BOOLEAN DstBufAlocated
;
590 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
592 Image
->ImageContext
.Handle
= Pe32Handle
;
593 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
596 // Get information about the image being loaded
598 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
599 if (EFI_ERROR (Status
)) {
603 if (!CoreIsImageTypeSupported (Image
)) {
605 // The PE/COFF loader can support loading image types that can be executed.
606 // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.
608 DEBUG ((DEBUG_ERROR
, "Image type %s can't be loaded on %s UEFI system.\n",
609 GetMachineTypeName (Image
->ImageContext
.Machine
),
610 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 ((EFI_D_INFO
|EFI_D_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
690 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
691 Status
= CoreAllocatePages (
693 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
694 Image
->NumberOfPages
,
695 &Image
->ImageContext
.ImageAddress
699 if (EFI_ERROR (Status
)) {
702 DstBufAlocated
= TRUE
;
705 // Caller provided the destination buffer
708 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
710 // If the image relocations were stripped, and the caller provided a
711 // destination buffer address that does not match the address that the
712 // image is linked at, then the image cannot be loaded.
714 return EFI_INVALID_PARAMETER
;
717 if (Image
->NumberOfPages
!= 0 &&
718 Image
->NumberOfPages
<
719 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
720 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
721 return EFI_BUFFER_TOO_SMALL
;
724 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
725 Image
->ImageContext
.ImageAddress
= DstBuffer
;
728 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
729 if (!Image
->ImageContext
.IsTeImage
) {
730 Image
->ImageContext
.ImageAddress
=
731 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
732 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
736 // Load the image from the file into the allocated memory
738 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
739 if (EFI_ERROR (Status
)) {
744 // If this is a Runtime Driver, then allocate memory for the FixupData that
745 // is used to relocate the image when SetVirtualAddressMap() is called. The
746 // relocation is done by the Runtime AP.
748 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
749 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
750 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
751 if (Image
->ImageContext
.FixupData
== NULL
) {
752 Status
= EFI_OUT_OF_RESOURCES
;
759 // Relocate the image in memory
761 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
762 if (EFI_ERROR (Status
)) {
767 // Flush the Instruction Cache
769 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
772 // Copy the machine type from the context to the image private data.
774 Image
->Machine
= Image
->ImageContext
.Machine
;
777 // Get the image entry point.
779 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
780 if (Image
->PeCoffEmu
!= NULL
) {
781 Status
= Image
->PeCoffEmu
->RegisterImage (Image
->PeCoffEmu
,
782 Image
->ImageBasePage
,
783 EFI_PAGES_TO_SIZE (Image
->NumberOfPages
),
785 if (EFI_ERROR (Status
)) {
786 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
,
787 "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));
793 // Fill in the image information for the Loaded Image Protocol
795 Image
->Type
= Image
->ImageContext
.ImageType
;
796 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
797 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
798 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
799 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
800 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
801 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
803 // Make a list off all the RT images so we can let the RT AP know about them.
805 Image
->RuntimeData
= AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
806 if (Image
->RuntimeData
== NULL
) {
809 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
810 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
811 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
812 Image
->RuntimeData
->Handle
= Image
->Handle
;
813 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
814 InsertImageRecord (Image
->RuntimeData
);
819 // Fill in the entry point of the image if it is available
821 if (EntryPoint
!= NULL
) {
822 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
826 // Print the load address and the PDB file name if it is available
833 CHAR8 EfiFileName
[256];
836 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
,
837 "Loading driver at 0x%11p EntryPoint=0x%11p ",
838 (VOID
*)(UINTN
) Image
->ImageContext
.ImageAddress
,
839 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)));
843 // Print Module Name by Pdb file path.
844 // Windows and Unix style file path are all trimmed correctly.
846 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
848 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
849 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
850 StartIndex
= Index
+ 1;
854 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
855 // The PDB file name is limited in the range of 0~255.
856 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
858 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
859 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
860 if (EfiFileName
[Index
] == 0) {
861 EfiFileName
[Index
] = '.';
863 if (EfiFileName
[Index
] == '.') {
864 EfiFileName
[Index
+ 1] = 'e';
865 EfiFileName
[Index
+ 2] = 'f';
866 EfiFileName
[Index
+ 3] = 'i';
867 EfiFileName
[Index
+ 4] = 0;
872 if (Index
== sizeof (EfiFileName
) - 4) {
873 EfiFileName
[Index
] = 0;
875 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
877 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
889 if (DstBufAlocated
) {
890 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
891 Image
->ImageContext
.ImageAddress
= 0;
892 Image
->ImageBasePage
= 0;
895 if (Image
->ImageContext
.FixupData
!= NULL
) {
896 CoreFreePool (Image
->ImageContext
.FixupData
);
905 Get the image's private data from its handle.
907 @param ImageHandle The image handle
909 @return Return the image private data associated with ImageHandle.
912 LOADED_IMAGE_PRIVATE_DATA
*
913 CoreLoadedImageInfo (
914 IN EFI_HANDLE ImageHandle
918 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
919 LOADED_IMAGE_PRIVATE_DATA
*Image
;
921 Status
= CoreHandleProtocol (
923 &gEfiLoadedImageProtocolGuid
,
924 (VOID
**)&LoadedImage
926 if (!EFI_ERROR (Status
)) {
927 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
929 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
938 Unloads EFI image from memory.
940 @param Image EFI image
941 @param FreePage Free allocated pages
945 CoreUnloadAndCloseImage (
946 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
952 EFI_HANDLE
*HandleBuffer
;
954 EFI_GUID
**ProtocolGuidArray
;
957 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
962 ProtocolGuidArray
= NULL
;
964 if (Image
->Started
) {
965 UnregisterMemoryProfileImage (Image
);
968 UnprotectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
970 if (Image
->PeCoffEmu
!= NULL
) {
972 // If the PE/COFF Emulator protocol exists we must unregister the image.
974 Image
->PeCoffEmu
->UnregisterImage (Image
->PeCoffEmu
, Image
->ImageBasePage
);
978 // Unload image, free Image->ImageContext->ModHandle
980 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
983 // Free our references to the image handle
985 if (Image
->Handle
!= NULL
) {
987 Status
= CoreLocateHandleBuffer (
994 if (!EFI_ERROR (Status
)) {
995 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
996 Status
= CoreProtocolsPerHandle (
997 HandleBuffer
[HandleIndex
],
1001 if (!EFI_ERROR (Status
)) {
1002 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1003 Status
= CoreOpenProtocolInformation (
1004 HandleBuffer
[HandleIndex
],
1005 ProtocolGuidArray
[ProtocolIndex
],
1009 if (!EFI_ERROR (Status
)) {
1010 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1011 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1012 Status
= CoreCloseProtocol (
1013 HandleBuffer
[HandleIndex
],
1014 ProtocolGuidArray
[ProtocolIndex
],
1016 OpenInfo
[OpenInfoIndex
].ControllerHandle
1020 if (OpenInfo
!= NULL
) {
1021 CoreFreePool(OpenInfo
);
1025 if (ProtocolGuidArray
!= NULL
) {
1026 CoreFreePool(ProtocolGuidArray
);
1030 if (HandleBuffer
!= NULL
) {
1031 CoreFreePool (HandleBuffer
);
1035 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1037 Status
= CoreUninstallProtocolInterface (
1039 &gEfiLoadedImageDevicePathProtocolGuid
,
1040 Image
->LoadedImageDevicePath
1043 Status
= CoreUninstallProtocolInterface (
1045 &gEfiLoadedImageProtocolGuid
,
1049 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1050 Status
= CoreUninstallProtocolInterface (
1052 &gEfiHiiPackageListProtocolGuid
,
1053 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1059 if (Image
->RuntimeData
!= NULL
) {
1060 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1062 // Remove the Image from the Runtime Image list as we are about to Free it!
1064 RemoveEntryList (&Image
->RuntimeData
->Link
);
1065 RemoveImageRecord (Image
->RuntimeData
);
1067 CoreFreePool (Image
->RuntimeData
);
1071 // Free the Image from memory
1073 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1074 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1078 // Done with the Image structure
1080 if (Image
->Info
.FilePath
!= NULL
) {
1081 CoreFreePool (Image
->Info
.FilePath
);
1084 if (Image
->LoadedImageDevicePath
!= NULL
) {
1085 CoreFreePool (Image
->LoadedImageDevicePath
);
1088 if (Image
->FixupData
!= NULL
) {
1089 CoreFreePool (Image
->FixupData
);
1092 CoreFreePool (Image
);
1097 Loads an EFI image into memory and returns a handle to the image.
1099 @param BootPolicy If TRUE, indicates that the request originates
1100 from the boot manager, and that the boot
1101 manager is attempting to load FilePath as a
1103 @param ParentImageHandle The caller's image handle.
1104 @param FilePath The specific file path from which the image is
1106 @param SourceBuffer If not NULL, a pointer to the memory location
1107 containing a copy of the image to be loaded.
1108 @param SourceSize The size in bytes of SourceBuffer.
1109 @param DstBuffer The buffer to store the image
1110 @param NumberOfPages If not NULL, it inputs a pointer to the page
1111 number of DstBuffer and outputs a pointer to
1112 the page number of the image. If this number is
1113 not enough, return EFI_BUFFER_TOO_SMALL and
1114 this parameter contains the required number.
1115 @param ImageHandle Pointer to the returned image handle that is
1116 created when the image is successfully loaded.
1117 @param EntryPoint A pointer to the entry point
1118 @param Attribute The bit mask of attributes to set for the load
1121 @retval EFI_SUCCESS The image was loaded into memory.
1122 @retval EFI_NOT_FOUND The FilePath was not found.
1123 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1124 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1125 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1126 path cannot be parsed to locate the proper
1127 protocol for loading the file.
1128 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1130 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1132 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1133 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1134 image from being loaded. NULL is returned in *ImageHandle.
1135 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1136 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1137 platform policy specifies that the image should not be started.
1141 CoreLoadImageCommon (
1142 IN BOOLEAN BootPolicy
,
1143 IN EFI_HANDLE ParentImageHandle
,
1144 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1145 IN VOID
*SourceBuffer OPTIONAL
,
1146 IN UINTN SourceSize
,
1147 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1148 IN OUT UINTN
*NumberOfPages OPTIONAL
,
1149 OUT EFI_HANDLE
*ImageHandle
,
1150 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1154 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1155 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
1156 IMAGE_FILE_HANDLE FHand
;
1158 EFI_STATUS SecurityStatus
;
1159 EFI_HANDLE DeviceHandle
;
1160 UINT32 AuthenticationStatus
;
1161 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
1162 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
1163 EFI_DEVICE_PATH_PROTOCOL
*InputFilePath
;
1164 EFI_DEVICE_PATH_PROTOCOL
*Node
;
1166 BOOLEAN ImageIsFromFv
;
1167 BOOLEAN ImageIsFromLoadFile
;
1169 SecurityStatus
= EFI_SUCCESS
;
1171 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
1175 // The caller must pass in a valid ParentImageHandle
1177 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
1178 return EFI_INVALID_PARAMETER
;
1181 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
1182 if (ParentImage
== NULL
) {
1183 DEBUG((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
1184 return EFI_INVALID_PARAMETER
;
1187 ZeroMem (&FHand
, sizeof (IMAGE_FILE_HANDLE
));
1188 FHand
.Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
1189 OriginalFilePath
= FilePath
;
1190 InputFilePath
= FilePath
;
1191 HandleFilePath
= FilePath
;
1192 DeviceHandle
= NULL
;
1193 Status
= EFI_SUCCESS
;
1194 AuthenticationStatus
= 0;
1195 ImageIsFromFv
= FALSE
;
1196 ImageIsFromLoadFile
= FALSE
;
1199 // If the caller passed a copy of the file, then just use it
1201 if (SourceBuffer
!= NULL
) {
1202 FHand
.Source
= SourceBuffer
;
1203 FHand
.SourceSize
= SourceSize
;
1204 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1205 if (EFI_ERROR (Status
)) {
1206 DeviceHandle
= NULL
;
1208 if (SourceSize
> 0) {
1209 Status
= EFI_SUCCESS
;
1211 Status
= EFI_LOAD_ERROR
;
1214 if (FilePath
== NULL
) {
1215 return EFI_INVALID_PARAMETER
;
1219 // Try to get the image device handle by checking the match protocol.
1222 Status
= CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1223 if (!EFI_ERROR (Status
)) {
1224 ImageIsFromFv
= TRUE
;
1226 HandleFilePath
= FilePath
;
1227 Status
= CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1228 if (EFI_ERROR (Status
)) {
1230 HandleFilePath
= FilePath
;
1231 Status
= CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1233 if (EFI_ERROR (Status
)) {
1234 HandleFilePath
= FilePath
;
1235 Status
= CoreLocateDevicePath (&gEfiLoadFileProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1236 if (!EFI_ERROR (Status
)) {
1237 ImageIsFromLoadFile
= TRUE
;
1238 Node
= HandleFilePath
;
1245 // Get the source file buffer by its device path.
1247 FHand
.Source
= GetFileBufferByFilePath (
1251 &AuthenticationStatus
1253 if (FHand
.Source
== NULL
) {
1254 Status
= EFI_NOT_FOUND
;
1256 FHand
.FreeBuffer
= TRUE
;
1257 if (ImageIsFromLoadFile
) {
1259 // LoadFile () may cause the device path of the Handle be updated.
1261 OriginalFilePath
= AppendDevicePath (DevicePathFromHandle (DeviceHandle
), Node
);
1266 if (EFI_ERROR (Status
)) {
1271 if (gSecurity2
!= NULL
) {
1273 // Verify File Authentication through the Security2 Architectural Protocol
1275 SecurityStatus
= gSecurity2
->FileAuthentication (
1282 if (!EFI_ERROR (SecurityStatus
) && ImageIsFromFv
) {
1284 // When Security2 is installed, Security Architectural Protocol must be published.
1286 ASSERT (gSecurity
!= NULL
);
1289 // Verify the Authentication Status through the Security Architectural Protocol
1290 // Only on images that have been read using Firmware Volume protocol.
1292 SecurityStatus
= gSecurity
->FileAuthenticationState (
1294 AuthenticationStatus
,
1298 } else if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
1300 // Verify the Authentication Status through the Security Architectural Protocol
1302 SecurityStatus
= gSecurity
->FileAuthenticationState (
1304 AuthenticationStatus
,
1310 // Check Security Status.
1312 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
1313 if (SecurityStatus
== EFI_ACCESS_DENIED
) {
1315 // Image was not loaded because the platform policy prohibits the image from being loaded.
1316 // It's the only place we could meet EFI_ACCESS_DENIED.
1318 *ImageHandle
= NULL
;
1320 Status
= SecurityStatus
;
1326 // Allocate a new image structure
1328 Image
= AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
1329 if (Image
== NULL
) {
1330 Status
= EFI_OUT_OF_RESOURCES
;
1335 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1337 FilePath
= OriginalFilePath
;
1338 if (DeviceHandle
!= NULL
) {
1339 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
1340 if (!EFI_ERROR (Status
)) {
1341 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
1342 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
;
1356 if (NumberOfPages
!= NULL
) {
1357 Image
->NumberOfPages
= *NumberOfPages
;
1359 Image
->NumberOfPages
= 0 ;
1363 // Install the protocol interfaces for this image
1364 // don't fire notifications yet
1366 Status
= CoreInstallProtocolInterfaceNotify (
1368 &gEfiLoadedImageProtocolGuid
,
1369 EFI_NATIVE_INTERFACE
,
1373 if (EFI_ERROR (Status
)) {
1378 // Load the image. If EntryPoint is Null, it will not be set.
1380 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
1381 if (EFI_ERROR (Status
)) {
1382 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
1383 if (NumberOfPages
!= NULL
) {
1384 *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
)) {
1449 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
1452 // Success. Return the image handle
1454 *ImageHandle
= Image
->Handle
;
1458 // All done accessing the source file
1459 // If we allocated the Source buffer, free it
1461 if (FHand
.FreeBuffer
) {
1462 CoreFreePool (FHand
.Source
);
1464 if (OriginalFilePath
!= InputFilePath
) {
1465 CoreFreePool (OriginalFilePath
);
1469 // There was an error. If there's an Image structure, free it
1471 if (EFI_ERROR (Status
)) {
1472 if (Image
!= NULL
) {
1473 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
1476 } else if (EFI_ERROR (SecurityStatus
)) {
1477 Status
= SecurityStatus
;
1481 // Track the return status from LoadImage.
1483 if (Image
!= NULL
) {
1484 Image
->LoadImageStatus
= Status
;
1494 Loads an EFI image into memory and returns a handle to the image.
1496 @param BootPolicy If TRUE, indicates that the request originates
1497 from the boot manager, and that the boot
1498 manager is attempting to load FilePath as a
1500 @param ParentImageHandle The caller's image handle.
1501 @param FilePath The specific file path from which the image is
1503 @param SourceBuffer If not NULL, a pointer to the memory location
1504 containing a copy of the image to be loaded.
1505 @param SourceSize The size in bytes of SourceBuffer.
1506 @param ImageHandle Pointer to the returned image handle that is
1507 created when the image is successfully loaded.
1509 @retval EFI_SUCCESS The image was loaded into memory.
1510 @retval EFI_NOT_FOUND The FilePath was not found.
1511 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1512 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1513 path cannot be parsed to locate the proper
1514 protocol for loading the file.
1515 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1517 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1519 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1520 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1521 image from being loaded. NULL is returned in *ImageHandle.
1522 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1523 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1524 platform policy specifies that the image should not be started.
1530 IN BOOLEAN BootPolicy
,
1531 IN EFI_HANDLE ParentImageHandle
,
1532 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1533 IN VOID
*SourceBuffer OPTIONAL
,
1534 IN UINTN SourceSize
,
1535 OUT EFI_HANDLE
*ImageHandle
1541 PERF_LOAD_IMAGE_BEGIN (NULL
);
1543 Status
= CoreLoadImageCommon (
1549 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
1553 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1557 if (!EFI_ERROR (Status
)) {
1559 // ImageHandle will be valid only Status is success.
1561 Handle
= *ImageHandle
;
1564 PERF_LOAD_IMAGE_END (Handle
);
1572 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1574 @param This Calling context
1575 @param ParentImageHandle The caller's image handle.
1576 @param FilePath The specific file path from which the image is
1578 @param SourceBuffer If not NULL, a pointer to the memory location
1579 containing a copy of the image to be loaded.
1580 @param SourceSize The size in bytes of SourceBuffer.
1581 @param DstBuffer The buffer to store the image.
1582 @param NumberOfPages For input, specifies the space size of the
1583 image by caller if not NULL. For output,
1584 specifies the actual space size needed.
1585 @param ImageHandle Image handle for output.
1586 @param EntryPoint Image entry point for output.
1587 @param Attribute The bit mask of attributes to set for the load
1590 @retval EFI_SUCCESS The image was loaded into memory.
1591 @retval EFI_NOT_FOUND The FilePath was not found.
1592 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1593 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1594 path cannot be parsed to locate the proper
1595 protocol for loading the file.
1596 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1598 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1600 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1601 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1602 image from being loaded. NULL is returned in *ImageHandle.
1603 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1604 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1605 platform policy specifies that the image should not be started.
1611 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1612 IN EFI_HANDLE ParentImageHandle
,
1613 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1614 IN VOID
*SourceBuffer OPTIONAL
,
1615 IN UINTN SourceSize
,
1616 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1617 OUT UINTN
*NumberOfPages OPTIONAL
,
1618 OUT EFI_HANDLE
*ImageHandle
,
1619 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1626 PERF_LOAD_IMAGE_BEGIN (NULL
);
1628 Status
= CoreLoadImageCommon (
1642 if (!EFI_ERROR (Status
)) {
1644 // ImageHandle will be valid only Status is success.
1646 Handle
= *ImageHandle
;
1649 PERF_LOAD_IMAGE_END (Handle
);
1656 Transfer control to a loaded image's entry point.
1658 @param ImageHandle Handle of image to be started.
1659 @param ExitDataSize Pointer of the size to ExitData
1660 @param ExitData Pointer to a pointer to a data buffer that
1661 includes a Null-terminated string,
1662 optionally followed by additional binary data.
1663 The string is a description that the caller may
1664 use to further indicate the reason for the
1667 @retval EFI_INVALID_PARAMETER Invalid parameter
1668 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1669 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1670 @retval EFI_SUCCESS Successfully transfer control to the image's
1677 IN EFI_HANDLE ImageHandle
,
1678 OUT UINTN
*ExitDataSize
,
1679 OUT CHAR16
**ExitData OPTIONAL
1683 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1684 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1685 UINT64 HandleDatabaseKey
;
1689 Handle
= ImageHandle
;
1691 Image
= CoreLoadedImageInfo (ImageHandle
);
1692 if (Image
== NULL
|| Image
->Started
) {
1693 return EFI_INVALID_PARAMETER
;
1695 if (EFI_ERROR (Image
->LoadImageStatus
)) {
1696 return Image
->LoadImageStatus
;
1700 // The image to be started must have the machine type supported by DxeCore.
1702 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->Machine
) &&
1703 Image
->PeCoffEmu
== NULL
) {
1705 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1706 // But it can not be started.
1708 DEBUG ((EFI_D_ERROR
, "Image type %s can't be started ", GetMachineTypeName(Image
->Machine
)));
1709 DEBUG ((EFI_D_ERROR
, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType
)));
1710 return EFI_UNSUPPORTED
;
1713 PERF_START_IMAGE_BEGIN (Handle
);
1717 // Push the current start image context, and
1718 // link the current image to the head. This is the
1719 // only image that can call Exit()
1721 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1722 LastImage
= mCurrentImage
;
1723 mCurrentImage
= Image
;
1724 Image
->Tpl
= gEfiCurrentTpl
;
1727 // Set long jump for Exit() support
1728 // JumpContext must be aligned on a CPU specific boundary.
1729 // Overallocate the buffer and force the required alignment
1731 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1732 if (Image
->JumpBuffer
== NULL
) {
1734 // Image may be unloaded after return with failure,
1735 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1737 PERF_START_IMAGE_END (NULL
);
1740 // Pop the current start image context
1742 mCurrentImage
= LastImage
;
1744 return EFI_OUT_OF_RESOURCES
;
1746 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1748 SetJumpFlag
= SetJump (Image
->JumpContext
);
1750 // The initial call to SetJump() must always return 0.
1751 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1753 if (SetJumpFlag
== 0) {
1754 RegisterMemoryProfileImage (Image
, (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
? EFI_FV_FILETYPE_APPLICATION
: EFI_FV_FILETYPE_DRIVER
));
1756 // Call the image's entry point
1758 Image
->Started
= TRUE
;
1759 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1762 // Add some debug information if the image returned with error.
1763 // This make the user aware and check if the driver image have already released
1764 // all the resource in this situation.
1766 DEBUG_CODE_BEGIN ();
1767 if (EFI_ERROR (Image
->Status
)) {
1768 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1773 // If the image returns, exit it through Exit()
1775 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1779 // Image has completed. Verify the tpl is the same
1781 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1782 CoreRestoreTpl (Image
->Tpl
);
1784 CoreFreePool (Image
->JumpBuffer
);
1787 // Pop the current start image context
1789 mCurrentImage
= LastImage
;
1792 // UEFI Specification - StartImage() - EFI 1.10 Extension
1793 // To maintain compatibility with UEFI drivers that are written to the EFI
1794 // 1.02 Specification, StartImage() must monitor the handle database before
1795 // and after each image is started. If any handles are created or modified
1796 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1797 // be called with the Recursive parameter set to TRUE for each of the newly
1798 // created or modified handles before StartImage() returns.
1800 if (Image
->Type
!= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1801 CoreConnectHandlesByKey (HandleDatabaseKey
);
1805 // Handle the image's returned ExitData
1807 DEBUG_CODE_BEGIN ();
1808 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1810 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1811 if (Image
->ExitData
!= NULL
) {
1812 DEBUG ((DEBUG_LOAD
, " (%hs)", Image
->ExitData
));
1814 DEBUG ((DEBUG_LOAD
, "\n"));
1819 // Return the exit data to the caller
1821 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1822 *ExitDataSize
= Image
->ExitDataSize
;
1823 *ExitData
= Image
->ExitData
;
1826 // Caller doesn't want the exit data, free it
1828 CoreFreePool (Image
->ExitData
);
1829 Image
->ExitData
= NULL
;
1833 // Save the Status because Image will get destroyed if it is unloaded.
1835 Status
= Image
->Status
;
1838 // If the image returned an error, or if the image is an application
1841 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1842 CoreUnloadAndCloseImage (Image
, TRUE
);
1844 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1852 PERF_START_IMAGE_END (Handle
);
1857 Terminates the currently loaded EFI image and returns control to boot services.
1859 @param ImageHandle Handle that identifies the image. This
1860 parameter is passed to the image on entry.
1861 @param Status The image's exit code.
1862 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1863 ExitStatus is EFI_SUCCESS.
1864 @param ExitData Pointer to a data buffer that includes a
1865 Null-terminated Unicode string, optionally
1866 followed by additional binary data. The string
1867 is a description that the caller may use to
1868 further indicate the reason for the image's
1871 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1873 @retval EFI_SUCCESS Successfully terminates the currently loaded
1875 @retval EFI_ACCESS_DENIED Should never reach there.
1876 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1882 IN EFI_HANDLE ImageHandle
,
1883 IN EFI_STATUS Status
,
1884 IN UINTN ExitDataSize
,
1885 IN CHAR16
*ExitData OPTIONAL
1888 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1892 // Prevent possible reentrance to this function
1893 // for the same ImageHandle
1895 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1897 Image
= CoreLoadedImageInfo (ImageHandle
);
1898 if (Image
== NULL
) {
1899 Status
= EFI_INVALID_PARAMETER
;
1903 if (!Image
->Started
) {
1905 // The image has not been started so just free its resources
1907 CoreUnloadAndCloseImage (Image
, TRUE
);
1908 Status
= EFI_SUCCESS
;
1913 // Image has been started, verify this image can exit
1915 if (Image
!= mCurrentImage
) {
1916 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1917 Status
= EFI_INVALID_PARAMETER
;
1924 Image
->Status
= Status
;
1927 // If there's ExitData info, move it
1929 if (ExitData
!= NULL
) {
1930 Image
->ExitDataSize
= ExitDataSize
;
1931 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1932 if (Image
->ExitData
== NULL
) {
1933 Status
= EFI_OUT_OF_RESOURCES
;
1936 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1939 CoreRestoreTpl (OldTpl
);
1941 // return to StartImage
1943 LongJump (Image
->JumpContext
, (UINTN
)-1);
1946 // If we return from LongJump, then it is an error
1949 Status
= EFI_ACCESS_DENIED
;
1951 CoreRestoreTpl (OldTpl
);
1961 @param ImageHandle Handle that identifies the image to be
1964 @retval EFI_SUCCESS The image has been unloaded.
1965 @retval EFI_UNSUPPORTED The image has been started, and does not support
1967 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1973 IN EFI_HANDLE ImageHandle
1977 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1979 Image
= CoreLoadedImageInfo (ImageHandle
);
1980 if (Image
== NULL
) {
1982 // The image handle is not valid
1984 Status
= EFI_INVALID_PARAMETER
;
1988 if (Image
->Started
) {
1990 // The image has been started, request it to unload.
1992 Status
= EFI_UNSUPPORTED
;
1993 if (Image
->Info
.Unload
!= NULL
) {
1994 Status
= Image
->Info
.Unload (ImageHandle
);
1999 // This Image hasn't been started, thus it can be unloaded
2001 Status
= EFI_SUCCESS
;
2005 if (!EFI_ERROR (Status
)) {
2007 // if the Image was not started or Unloaded O.K. then clean up
2009 CoreUnloadAndCloseImage (Image
, TRUE
);
2019 Unload the specified image.
2021 @param This Indicates the calling context.
2022 @param ImageHandle The specified image handle.
2024 @retval EFI_INVALID_PARAMETER Image handle is NULL.
2025 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
2026 @retval EFI_SUCCESS Image successfully unloaded.
2032 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
2033 IN EFI_HANDLE ImageHandle
2036 return CoreUnloadImage (ImageHandle
);