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
75 NULL
// LoadedImageDevicePath
78 // The field is define for Loading modules at fixed address feature to tracker the PEI code
79 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
82 GLOBAL_REMOVE_IF_UNREFERENCED UINT64
*mDxeCodeMemoryRangeUsageBitMap
=NULL
;
86 CHAR16
*MachineTypeName
;
90 // EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.
92 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo
[] = {
93 {EFI_IMAGE_MACHINE_IA32
, L
"IA32"},
94 {EFI_IMAGE_MACHINE_IA64
, L
"IA64"},
95 {EFI_IMAGE_MACHINE_X64
, L
"X64"},
96 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
, L
"ARM"},
97 {EFI_IMAGE_MACHINE_AARCH64
, L
"AARCH64"}
100 UINT16 mDxeCoreImageMachineType
= 0;
103 Return machine type name.
105 @param MachineType The machine type
107 @return machine type name
116 for (Index
= 0; Index
< sizeof(mMachineTypeInfo
)/sizeof(mMachineTypeInfo
[0]); Index
++) {
117 if (mMachineTypeInfo
[Index
].MachineType
== MachineType
) {
118 return mMachineTypeInfo
[Index
].MachineTypeName
;
126 Notification event handler registered by CoreInitializeImageServices () to
127 keep track of which PE/COFF image emulators are available.
129 @param Event The Event that is being processed, not used.
130 @param Context Event Context, not used.
136 PeCoffEmuProtocolNotify (
143 EFI_HANDLE EmuHandle
;
144 EMULATOR_ENTRY
*Entry
;
149 BufferSize
= sizeof (EmuHandle
);
150 Status
= CoreLocateHandle (
153 mPeCoffEmuProtocolNotifyRegistration
,
157 if (EFI_ERROR (Status
)) {
159 // If no more notification events exit
164 Entry
= AllocateZeroPool (sizeof (*Entry
));
165 ASSERT (Entry
!= NULL
);
167 Status
= CoreHandleProtocol (
169 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
170 (VOID
**)&Entry
->Emulator
172 ASSERT_EFI_ERROR (Status
);
174 Entry
->MachineType
= Entry
->Emulator
->MachineType
;
176 InsertTailList (&mAvailableEmulators
, &Entry
->Link
);
181 Add the Image Services to EFI Boot Services Table and install the protocol
182 interfaces for this image.
184 @param HobStart The HOB to initialize
190 CoreInitializeImageServices (
195 LOADED_IMAGE_PRIVATE_DATA
*Image
;
196 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
197 UINT64 DxeCoreImageLength
;
198 VOID
*DxeCoreEntryPoint
;
199 EFI_PEI_HOB_POINTERS DxeCoreHob
;
202 // Searching for image hob
204 DxeCoreHob
.Raw
= HobStart
;
205 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
206 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
212 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
214 ASSERT (DxeCoreHob
.Raw
!= NULL
);
216 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
217 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
218 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
219 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
222 // Initialize the fields for an internal driver
224 Image
= &mCorePrivateImage
;
226 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
227 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
228 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
229 Image
->Tpl
= gEfiCurrentTpl
;
230 Image
->Info
.SystemTable
= gDxeCoreST
;
231 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
232 Image
->Info
.ImageSize
= DxeCoreImageLength
;
235 // Install the protocol interfaces for this image
237 Status
= CoreInstallProtocolInterface (
239 &gEfiLoadedImageProtocolGuid
,
240 EFI_NATIVE_INTERFACE
,
243 ASSERT_EFI_ERROR (Status
);
245 mCurrentImage
= Image
;
248 // Fill in DXE globals
250 mDxeCoreImageMachineType
= PeCoffLoaderGetMachineType (Image
->Info
.ImageBase
);
251 gDxeCoreImageHandle
= Image
->Handle
;
252 gDxeCoreLoadedImage
= &Image
->Info
;
255 // Create the PE/COFF emulator protocol registration event
257 Status
= CoreCreateEvent (
260 PeCoffEmuProtocolNotify
,
262 &mPeCoffEmuProtocolRegistrationEvent
264 ASSERT_EFI_ERROR(Status
);
267 // Register for protocol notifications on this event
269 Status
= CoreRegisterProtocolNotify (
270 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
271 mPeCoffEmuProtocolRegistrationEvent
,
272 &mPeCoffEmuProtocolNotifyRegistration
274 ASSERT_EFI_ERROR(Status
);
276 InitializeListHead (&mAvailableEmulators
);
278 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
280 // Export DXE Core PE Loader functionality for backward compatibility.
282 Status
= CoreInstallProtocolInterface (
283 &mLoadPe32PrivateData
.Handle
,
284 &gEfiLoadPeImageProtocolGuid
,
285 EFI_NATIVE_INTERFACE
,
286 &mLoadPe32PrivateData
.Pe32Image
290 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
296 Read image file (specified by UserHandle) into user specified buffer with specified offset
299 @param UserHandle Image file handle
300 @param Offset Offset to the source file
301 @param ReadSize For input, pointer of size to read; For output,
302 pointer of size actually read.
303 @param Buffer Buffer to write into
305 @retval EFI_SUCCESS Successfully read the specified part of file
314 IN OUT UINTN
*ReadSize
,
319 IMAGE_FILE_HANDLE
*FHand
;
321 if (UserHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
322 return EFI_INVALID_PARAMETER
;
325 if (MAX_ADDRESS
- Offset
< *ReadSize
) {
326 return EFI_INVALID_PARAMETER
;
329 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
330 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
333 // Move data from our local copy of the file
335 EndPosition
= Offset
+ *ReadSize
;
336 if (EndPosition
> FHand
->SourceSize
) {
337 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
339 if (Offset
>= FHand
->SourceSize
) {
343 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
347 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
348 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
349 The function is only invoked when load modules at fixed address feature is enabled.
351 @param ImageBase The base address the image will be loaded at.
352 @param ImageSize The size of the image
354 @retval EFI_SUCCESS The memory range the image will be loaded in is available
355 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
358 CheckAndMarkFixLoadingMemoryUsageBitMap (
359 IN EFI_PHYSICAL_ADDRESS ImageBase
,
363 UINT32 DxeCodePageNumber
;
365 EFI_PHYSICAL_ADDRESS DxeCodeBase
;
366 UINTN BaseOffsetPageNumber
;
367 UINTN TopOffsetPageNumber
;
370 // The DXE code range includes RuntimeCodePage range and Boot time code range.
372 DxeCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
373 DxeCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
374 DxeCodeSize
= EFI_PAGES_TO_SIZE(DxeCodePageNumber
);
375 DxeCodeBase
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
- DxeCodeSize
;
378 // If the memory usage bit map is not initialized, do it. Every bit in the array
379 // indicate the status of the corresponding memory page, available or not
381 if (mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
382 mDxeCodeMemoryRangeUsageBitMap
= AllocateZeroPool(((DxeCodePageNumber
/64) + 1)*sizeof(UINT64
));
385 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
387 if (!gLoadFixedAddressCodeMemoryReady
|| mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
388 return EFI_NOT_FOUND
;
391 // Test the memory range for loading the image in the DXE code range.
393 if (gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
< ImageBase
+ ImageSize
||
394 DxeCodeBase
> ImageBase
) {
395 return EFI_NOT_FOUND
;
398 // Test if the memory is avalaible or not.
400 BaseOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
- DxeCodeBase
));
401 TopOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
+ ImageSize
- DxeCodeBase
));
402 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
403 if ((mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] & LShiftU64(1, (Index
% 64))) != 0) {
405 // This page is already used.
407 return EFI_NOT_FOUND
;
412 // Being here means the memory range is available. So mark the bits for the memory range
414 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
415 mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] |= LShiftU64(1, (Index
% 64));
421 Get the fixed loading address from image header assigned by build tool. This function only be called
422 when Loading module at Fixed address feature enabled.
424 @param ImageContext Pointer to the image context structure that describes the PE/COFF
425 image that needs to be examined by this function.
426 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
427 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
431 GetPeCoffImageFixLoadingAssignedAddress(
432 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
435 UINTN SectionHeaderOffset
;
437 EFI_IMAGE_SECTION_HEADER SectionHeader
;
438 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
441 UINT16 NumberOfSections
;
442 IMAGE_FILE_HANDLE
*Handle
;
443 UINT64 ValueInSectionHeader
;
446 Status
= EFI_NOT_FOUND
;
449 // Get PeHeader pointer
451 Handle
= (IMAGE_FILE_HANDLE
*)ImageContext
->Handle
;
452 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
* )Handle
->Source
+ ImageContext
->PeCoffHeaderOffset
);
453 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+
455 sizeof (EFI_IMAGE_FILE_HEADER
) +
456 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
;
457 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
460 // Get base address from the first section header that doesn't point to code section.
462 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
464 // Read section header from file
466 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
467 Status
= ImageContext
->ImageRead (
468 ImageContext
->Handle
,
473 if (EFI_ERROR (Status
)) {
476 if (Size
!= sizeof (EFI_IMAGE_SECTION_HEADER
)) {
477 return EFI_NOT_FOUND
;
480 Status
= EFI_NOT_FOUND
;
482 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
484 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
485 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
486 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
487 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
489 ValueInSectionHeader
= ReadUnaligned64((UINT64
*)&SectionHeader
.PointerToRelocations
);
490 if (ValueInSectionHeader
!= 0) {
492 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
493 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
494 // relative to top address
496 if ((INT64
)PcdGet64(PcdLoadModuleAtFixAddressEnable
) < 0) {
497 ImageContext
->ImageAddress
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
+ (INT64
)(INTN
)ImageContext
->ImageAddress
;
500 // Check if the memory range is available.
502 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext
->ImageAddress
, (UINTN
)(ImageContext
->ImageSize
+ ImageContext
->SectionAlignment
));
506 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
508 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
));
513 Decides whether a PE/COFF image can execute on this system, either natively
514 or via emulation/interpretation. In the latter case, the PeCoffEmu member
515 of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer
516 to the emulator protocol that supports this image.
518 @param[in, out] Image LOADED_IMAGE_PRIVATE_DATA struct pointer
520 @retval TRUE The image is supported
521 @retval FALSE The image is not supported
526 CoreIsImageTypeSupported (
527 IN OUT LOADED_IMAGE_PRIVATE_DATA
*Image
531 EMULATOR_ENTRY
*Entry
;
533 for (Link
= GetFirstNode (&mAvailableEmulators
);
534 !IsNull (&mAvailableEmulators
, Link
);
535 Link
= GetNextNode (&mAvailableEmulators
, Link
)) {
537 Entry
= BASE_CR (Link
, EMULATOR_ENTRY
, Link
);
538 if (Entry
->MachineType
!= Image
->ImageContext
.Machine
) {
542 if (Entry
->Emulator
->IsImageSupported (Entry
->Emulator
,
543 Image
->ImageContext
.ImageType
,
544 Image
->Info
.FilePath
)) {
545 Image
->PeCoffEmu
= Entry
->Emulator
;
550 return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
) ||
551 EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
);
555 Loads, relocates, and invokes a PE/COFF image
557 @param BootPolicy If TRUE, indicates that the request originates
558 from the boot manager, and that the boot
559 manager is attempting to load FilePath as a
561 @param Pe32Handle The handle of PE32 image
562 @param Image PE image to be loaded
563 @param DstBuffer The buffer to store the image
564 @param EntryPoint A pointer to the entry point
565 @param Attribute The bit mask of attributes to set for the load
568 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
569 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
570 relocate the PE/COFF file
571 @retval EFI_INVALID_PARAMETER Invalid parameter
572 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
577 IN BOOLEAN BootPolicy
,
579 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
580 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
581 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
586 BOOLEAN DstBufAlocated
;
589 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
591 Image
->ImageContext
.Handle
= Pe32Handle
;
592 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
595 // Get information about the image being loaded
597 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
598 if (EFI_ERROR (Status
)) {
602 if (!CoreIsImageTypeSupported (Image
)) {
604 // The PE/COFF loader can support loading image types that can be executed.
605 // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.
607 DEBUG ((DEBUG_ERROR
, "Image type %s can't be loaded on %s UEFI system.\n",
608 GetMachineTypeName (Image
->ImageContext
.Machine
),
609 GetMachineTypeName (mDxeCoreImageMachineType
)));
610 return EFI_UNSUPPORTED
;
614 // Set EFI memory type based on ImageType
616 switch (Image
->ImageContext
.ImageType
) {
617 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
618 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
619 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
621 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
622 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
623 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
625 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
626 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
627 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
628 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
631 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
632 return EFI_UNSUPPORTED
;
636 // Allocate memory of the correct memory type aligned on the required image boundary
638 DstBufAlocated
= FALSE
;
639 if (DstBuffer
== 0) {
641 // Allocate Destination Buffer as caller did not pass it in
644 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
645 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
647 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
650 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
653 // If the image relocations have not been stripped, then load at any address.
654 // Otherwise load at the address at which it was linked.
656 // Memory below 1MB should be treated reserved for CSM and there should be
657 // no modules whose preferred load addresses are below 1MB.
659 Status
= EFI_OUT_OF_RESOURCES
;
661 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
662 // a specified address.
664 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 ) {
665 Status
= GetPeCoffImageFixLoadingAssignedAddress (&(Image
->ImageContext
));
667 if (EFI_ERROR (Status
)) {
669 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
671 DEBUG ((EFI_D_INFO
|EFI_D_LOAD
, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
673 Status
= CoreAllocatePages (
675 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
676 Image
->NumberOfPages
,
677 &Image
->ImageContext
.ImageAddress
681 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
682 Status
= CoreAllocatePages (
684 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
685 Image
->NumberOfPages
,
686 &Image
->ImageContext
.ImageAddress
689 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
690 Status
= CoreAllocatePages (
692 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
693 Image
->NumberOfPages
,
694 &Image
->ImageContext
.ImageAddress
698 if (EFI_ERROR (Status
)) {
701 DstBufAlocated
= TRUE
;
704 // Caller provided the destination buffer
707 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
709 // If the image relocations were stripped, and the caller provided a
710 // destination buffer address that does not match the address that the
711 // image is linked at, then the image cannot be loaded.
713 return EFI_INVALID_PARAMETER
;
716 if (Image
->NumberOfPages
!= 0 &&
717 Image
->NumberOfPages
<
718 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
719 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
720 return EFI_BUFFER_TOO_SMALL
;
723 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
724 Image
->ImageContext
.ImageAddress
= DstBuffer
;
727 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
728 if (!Image
->ImageContext
.IsTeImage
) {
729 Image
->ImageContext
.ImageAddress
=
730 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
731 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
735 // Load the image from the file into the allocated memory
737 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
738 if (EFI_ERROR (Status
)) {
743 // If this is a Runtime Driver, then allocate memory for the FixupData that
744 // is used to relocate the image when SetVirtualAddressMap() is called. The
745 // relocation is done by the Runtime AP.
747 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
748 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
749 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
750 if (Image
->ImageContext
.FixupData
== NULL
) {
751 Status
= EFI_OUT_OF_RESOURCES
;
758 // Relocate the image in memory
760 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
761 if (EFI_ERROR (Status
)) {
766 // Flush the Instruction Cache
768 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
771 // Copy the machine type from the context to the image private data. This
772 // is needed during image unload to know if we should call an EBC protocol
773 // to unload the image.
775 Image
->Machine
= Image
->ImageContext
.Machine
;
778 // Get the image entry point. If it's an EBC image, then call into the
779 // interpreter to create a thunk for the entry point and use the returned
780 // value for the entry point.
782 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
783 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
785 // Locate the EBC interpreter protocol
787 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
788 if (EFI_ERROR(Status
) || Image
->Ebc
== NULL
) {
789 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
794 // Register a callback for flushing the instruction cache so that created
795 // thunks can be flushed.
797 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
798 if (EFI_ERROR(Status
)) {
803 // Create a thunk for the image's entry point. This will be the new
804 // entry point for the image.
806 Status
= Image
->Ebc
->CreateThunk (
809 (VOID
*)(UINTN
) Image
->ImageContext
.EntryPoint
,
810 (VOID
**) &Image
->EntryPoint
812 if (EFI_ERROR(Status
)) {
815 } else if (Image
->PeCoffEmu
!= NULL
) {
816 Status
= Image
->PeCoffEmu
->RegisterImage (Image
->PeCoffEmu
,
817 Image
->ImageBasePage
,
818 EFI_PAGES_TO_SIZE (Image
->NumberOfPages
),
820 if (EFI_ERROR (Status
)) {
821 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
,
822 "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));
828 // Fill in the image information for the Loaded Image Protocol
830 Image
->Type
= Image
->ImageContext
.ImageType
;
831 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
832 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
833 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
834 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
835 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
836 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
838 // Make a list off all the RT images so we can let the RT AP know about them.
840 Image
->RuntimeData
= AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
841 if (Image
->RuntimeData
== NULL
) {
844 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
845 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
846 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
847 Image
->RuntimeData
->Handle
= Image
->Handle
;
848 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
849 InsertImageRecord (Image
->RuntimeData
);
854 // Fill in the entry point of the image if it is available
856 if (EntryPoint
!= NULL
) {
857 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
861 // Print the load address and the PDB file name if it is available
868 CHAR8 EfiFileName
[256];
871 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
,
872 "Loading driver at 0x%11p EntryPoint=0x%11p ",
873 (VOID
*)(UINTN
) Image
->ImageContext
.ImageAddress
,
874 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)));
878 // Print Module Name by Pdb file path.
879 // Windows and Unix style file path are all trimmed correctly.
881 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
883 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
884 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
885 StartIndex
= Index
+ 1;
889 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
890 // The PDB file name is limited in the range of 0~255.
891 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
893 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
894 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
895 if (EfiFileName
[Index
] == 0) {
896 EfiFileName
[Index
] = '.';
898 if (EfiFileName
[Index
] == '.') {
899 EfiFileName
[Index
+ 1] = 'e';
900 EfiFileName
[Index
+ 2] = 'f';
901 EfiFileName
[Index
+ 3] = 'i';
902 EfiFileName
[Index
+ 4] = 0;
907 if (Index
== sizeof (EfiFileName
) - 4) {
908 EfiFileName
[Index
] = 0;
910 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
912 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
924 if (DstBufAlocated
) {
925 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
926 Image
->ImageContext
.ImageAddress
= 0;
927 Image
->ImageBasePage
= 0;
930 if (Image
->ImageContext
.FixupData
!= NULL
) {
931 CoreFreePool (Image
->ImageContext
.FixupData
);
940 Get the image's private data from its handle.
942 @param ImageHandle The image handle
944 @return Return the image private data associated with ImageHandle.
947 LOADED_IMAGE_PRIVATE_DATA
*
948 CoreLoadedImageInfo (
949 IN EFI_HANDLE ImageHandle
953 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
954 LOADED_IMAGE_PRIVATE_DATA
*Image
;
956 Status
= CoreHandleProtocol (
958 &gEfiLoadedImageProtocolGuid
,
959 (VOID
**)&LoadedImage
961 if (!EFI_ERROR (Status
)) {
962 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
964 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
973 Unloads EFI image from memory.
975 @param Image EFI image
976 @param FreePage Free allocated pages
980 CoreUnloadAndCloseImage (
981 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
987 EFI_HANDLE
*HandleBuffer
;
989 EFI_GUID
**ProtocolGuidArray
;
992 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
997 ProtocolGuidArray
= NULL
;
999 if (Image
->Started
) {
1000 UnregisterMemoryProfileImage (Image
);
1003 UnprotectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
1005 if (Image
->Ebc
!= NULL
) {
1007 // If EBC protocol exists we must perform cleanups for this image.
1009 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1012 if (Image
->PeCoffEmu
!= NULL
) {
1014 // If the PE/COFF Emulator protocol exists we must unregister the image.
1016 Image
->PeCoffEmu
->UnregisterImage (Image
->PeCoffEmu
, Image
->ImageBasePage
);
1020 // Unload image, free Image->ImageContext->ModHandle
1022 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1025 // Free our references to the image handle
1027 if (Image
->Handle
!= NULL
) {
1029 Status
= CoreLocateHandleBuffer (
1036 if (!EFI_ERROR (Status
)) {
1037 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1038 Status
= CoreProtocolsPerHandle (
1039 HandleBuffer
[HandleIndex
],
1043 if (!EFI_ERROR (Status
)) {
1044 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1045 Status
= CoreOpenProtocolInformation (
1046 HandleBuffer
[HandleIndex
],
1047 ProtocolGuidArray
[ProtocolIndex
],
1051 if (!EFI_ERROR (Status
)) {
1052 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1053 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1054 Status
= CoreCloseProtocol (
1055 HandleBuffer
[HandleIndex
],
1056 ProtocolGuidArray
[ProtocolIndex
],
1058 OpenInfo
[OpenInfoIndex
].ControllerHandle
1062 if (OpenInfo
!= NULL
) {
1063 CoreFreePool(OpenInfo
);
1067 if (ProtocolGuidArray
!= NULL
) {
1068 CoreFreePool(ProtocolGuidArray
);
1072 if (HandleBuffer
!= NULL
) {
1073 CoreFreePool (HandleBuffer
);
1077 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1079 Status
= CoreUninstallProtocolInterface (
1081 &gEfiLoadedImageDevicePathProtocolGuid
,
1082 Image
->LoadedImageDevicePath
1085 Status
= CoreUninstallProtocolInterface (
1087 &gEfiLoadedImageProtocolGuid
,
1091 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1092 Status
= CoreUninstallProtocolInterface (
1094 &gEfiHiiPackageListProtocolGuid
,
1095 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1101 if (Image
->RuntimeData
!= NULL
) {
1102 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1104 // Remove the Image from the Runtime Image list as we are about to Free it!
1106 RemoveEntryList (&Image
->RuntimeData
->Link
);
1107 RemoveImageRecord (Image
->RuntimeData
);
1109 CoreFreePool (Image
->RuntimeData
);
1113 // Free the Image from memory
1115 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1116 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1120 // Done with the Image structure
1122 if (Image
->Info
.FilePath
!= NULL
) {
1123 CoreFreePool (Image
->Info
.FilePath
);
1126 if (Image
->LoadedImageDevicePath
!= NULL
) {
1127 CoreFreePool (Image
->LoadedImageDevicePath
);
1130 if (Image
->FixupData
!= NULL
) {
1131 CoreFreePool (Image
->FixupData
);
1134 CoreFreePool (Image
);
1139 Loads an EFI image into memory and returns a handle to the image.
1141 @param BootPolicy If TRUE, indicates that the request originates
1142 from the boot manager, and that the boot
1143 manager is attempting to load FilePath as a
1145 @param ParentImageHandle The caller's image handle.
1146 @param FilePath The specific file path from which the image is
1148 @param SourceBuffer If not NULL, a pointer to the memory location
1149 containing a copy of the image to be loaded.
1150 @param SourceSize The size in bytes of SourceBuffer.
1151 @param DstBuffer The buffer to store the image
1152 @param NumberOfPages If not NULL, it inputs a pointer to the page
1153 number of DstBuffer and outputs a pointer to
1154 the page number of the image. If this number is
1155 not enough, return EFI_BUFFER_TOO_SMALL and
1156 this parameter contains the required number.
1157 @param ImageHandle Pointer to the returned image handle that is
1158 created when the image is successfully loaded.
1159 @param EntryPoint A pointer to the entry point
1160 @param Attribute The bit mask of attributes to set for the load
1163 @retval EFI_SUCCESS The image was loaded into memory.
1164 @retval EFI_NOT_FOUND The FilePath was not found.
1165 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1166 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1167 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1168 path cannot be parsed to locate the proper
1169 protocol for loading the file.
1170 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1172 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1174 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1175 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1176 image from being loaded. NULL is returned in *ImageHandle.
1177 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1178 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1179 platform policy specifies that the image should not be started.
1183 CoreLoadImageCommon (
1184 IN BOOLEAN BootPolicy
,
1185 IN EFI_HANDLE ParentImageHandle
,
1186 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1187 IN VOID
*SourceBuffer OPTIONAL
,
1188 IN UINTN SourceSize
,
1189 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1190 IN OUT UINTN
*NumberOfPages OPTIONAL
,
1191 OUT EFI_HANDLE
*ImageHandle
,
1192 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1196 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1197 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
1198 IMAGE_FILE_HANDLE FHand
;
1200 EFI_STATUS SecurityStatus
;
1201 EFI_HANDLE DeviceHandle
;
1202 UINT32 AuthenticationStatus
;
1203 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
1204 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
1205 EFI_DEVICE_PATH_PROTOCOL
*InputFilePath
;
1206 EFI_DEVICE_PATH_PROTOCOL
*Node
;
1208 BOOLEAN ImageIsFromFv
;
1209 BOOLEAN ImageIsFromLoadFile
;
1211 SecurityStatus
= EFI_SUCCESS
;
1213 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
1217 // The caller must pass in a valid ParentImageHandle
1219 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
1220 return EFI_INVALID_PARAMETER
;
1223 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
1224 if (ParentImage
== NULL
) {
1225 DEBUG((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
1226 return EFI_INVALID_PARAMETER
;
1229 ZeroMem (&FHand
, sizeof (IMAGE_FILE_HANDLE
));
1230 FHand
.Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
1231 OriginalFilePath
= FilePath
;
1232 InputFilePath
= FilePath
;
1233 HandleFilePath
= FilePath
;
1234 DeviceHandle
= NULL
;
1235 Status
= EFI_SUCCESS
;
1236 AuthenticationStatus
= 0;
1237 ImageIsFromFv
= FALSE
;
1238 ImageIsFromLoadFile
= FALSE
;
1241 // If the caller passed a copy of the file, then just use it
1243 if (SourceBuffer
!= NULL
) {
1244 FHand
.Source
= SourceBuffer
;
1245 FHand
.SourceSize
= SourceSize
;
1246 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1247 if (EFI_ERROR (Status
)) {
1248 DeviceHandle
= NULL
;
1250 if (SourceSize
> 0) {
1251 Status
= EFI_SUCCESS
;
1253 Status
= EFI_LOAD_ERROR
;
1256 if (FilePath
== NULL
) {
1257 return EFI_INVALID_PARAMETER
;
1261 // Try to get the image device handle by checking the match protocol.
1264 Status
= CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1265 if (!EFI_ERROR (Status
)) {
1266 ImageIsFromFv
= TRUE
;
1268 HandleFilePath
= FilePath
;
1269 Status
= CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1270 if (EFI_ERROR (Status
)) {
1272 HandleFilePath
= FilePath
;
1273 Status
= CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1275 if (EFI_ERROR (Status
)) {
1276 HandleFilePath
= FilePath
;
1277 Status
= CoreLocateDevicePath (&gEfiLoadFileProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1278 if (!EFI_ERROR (Status
)) {
1279 ImageIsFromLoadFile
= TRUE
;
1280 Node
= HandleFilePath
;
1287 // Get the source file buffer by its device path.
1289 FHand
.Source
= GetFileBufferByFilePath (
1293 &AuthenticationStatus
1295 if (FHand
.Source
== NULL
) {
1296 Status
= EFI_NOT_FOUND
;
1298 FHand
.FreeBuffer
= TRUE
;
1299 if (ImageIsFromLoadFile
) {
1301 // LoadFile () may cause the device path of the Handle be updated.
1303 OriginalFilePath
= AppendDevicePath (DevicePathFromHandle (DeviceHandle
), Node
);
1308 if (EFI_ERROR (Status
)) {
1313 if (gSecurity2
!= NULL
) {
1315 // Verify File Authentication through the Security2 Architectural Protocol
1317 SecurityStatus
= gSecurity2
->FileAuthentication (
1324 if (!EFI_ERROR (SecurityStatus
) && ImageIsFromFv
) {
1326 // When Security2 is installed, Security Architectural Protocol must be published.
1328 ASSERT (gSecurity
!= NULL
);
1331 // Verify the Authentication Status through the Security Architectural Protocol
1332 // Only on images that have been read using Firmware Volume protocol.
1334 SecurityStatus
= gSecurity
->FileAuthenticationState (
1336 AuthenticationStatus
,
1340 } else if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
1342 // Verify the Authentication Status through the Security Architectural Protocol
1344 SecurityStatus
= gSecurity
->FileAuthenticationState (
1346 AuthenticationStatus
,
1352 // Check Security Status.
1354 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
1355 if (SecurityStatus
== EFI_ACCESS_DENIED
) {
1357 // Image was not loaded because the platform policy prohibits the image from being loaded.
1358 // It's the only place we could meet EFI_ACCESS_DENIED.
1360 *ImageHandle
= NULL
;
1362 Status
= SecurityStatus
;
1368 // Allocate a new image structure
1370 Image
= AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
1371 if (Image
== NULL
) {
1372 Status
= EFI_OUT_OF_RESOURCES
;
1377 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1379 FilePath
= OriginalFilePath
;
1380 if (DeviceHandle
!= NULL
) {
1381 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
1382 if (!EFI_ERROR (Status
)) {
1383 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
1384 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*)FilePath
) + FilePathSize
);
1388 // Initialize the fields for an internal driver
1390 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
1391 Image
->Info
.SystemTable
= gDxeCoreST
;
1392 Image
->Info
.DeviceHandle
= DeviceHandle
;
1393 Image
->Info
.Revision
= EFI_LOADED_IMAGE_PROTOCOL_REVISION
;
1394 Image
->Info
.FilePath
= DuplicateDevicePath (FilePath
);
1395 Image
->Info
.ParentHandle
= ParentImageHandle
;
1398 if (NumberOfPages
!= NULL
) {
1399 Image
->NumberOfPages
= *NumberOfPages
;
1401 Image
->NumberOfPages
= 0 ;
1405 // Install the protocol interfaces for this image
1406 // don't fire notifications yet
1408 Status
= CoreInstallProtocolInterfaceNotify (
1410 &gEfiLoadedImageProtocolGuid
,
1411 EFI_NATIVE_INTERFACE
,
1415 if (EFI_ERROR (Status
)) {
1420 // Load the image. If EntryPoint is Null, it will not be set.
1422 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
1423 if (EFI_ERROR (Status
)) {
1424 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
1425 if (NumberOfPages
!= NULL
) {
1426 *NumberOfPages
= Image
->NumberOfPages
;
1432 if (NumberOfPages
!= NULL
) {
1433 *NumberOfPages
= Image
->NumberOfPages
;
1437 // Register the image in the Debug Image Info Table if the attribute is set
1439 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) != 0) {
1440 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
1444 //Reinstall loaded image protocol to fire any notifications
1446 Status
= CoreReinstallProtocolInterface (
1448 &gEfiLoadedImageProtocolGuid
,
1452 if (EFI_ERROR (Status
)) {
1457 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1458 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1460 if (OriginalFilePath
!= NULL
) {
1461 Image
->LoadedImageDevicePath
= DuplicateDevicePath (OriginalFilePath
);
1465 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1467 Status
= CoreInstallProtocolInterface (
1469 &gEfiLoadedImageDevicePathProtocolGuid
,
1470 EFI_NATIVE_INTERFACE
,
1471 Image
->LoadedImageDevicePath
1473 if (EFI_ERROR (Status
)) {
1478 // Install HII Package List Protocol onto the image handle
1480 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1481 Status
= CoreInstallProtocolInterface (
1483 &gEfiHiiPackageListProtocolGuid
,
1484 EFI_NATIVE_INTERFACE
,
1485 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1487 if (EFI_ERROR (Status
)) {
1491 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
1494 // Success. Return the image handle
1496 *ImageHandle
= Image
->Handle
;
1500 // All done accessing the source file
1501 // If we allocated the Source buffer, free it
1503 if (FHand
.FreeBuffer
) {
1504 CoreFreePool (FHand
.Source
);
1506 if (OriginalFilePath
!= InputFilePath
) {
1507 CoreFreePool (OriginalFilePath
);
1511 // There was an error. If there's an Image structure, free it
1513 if (EFI_ERROR (Status
)) {
1514 if (Image
!= NULL
) {
1515 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
1518 } else if (EFI_ERROR (SecurityStatus
)) {
1519 Status
= SecurityStatus
;
1523 // Track the return status from LoadImage.
1525 if (Image
!= NULL
) {
1526 Image
->LoadImageStatus
= Status
;
1536 Loads an EFI image into memory and returns a handle to the image.
1538 @param BootPolicy If TRUE, indicates that the request originates
1539 from the boot manager, and that the boot
1540 manager is attempting to load FilePath as a
1542 @param ParentImageHandle The caller's image handle.
1543 @param FilePath The specific file path from which the image is
1545 @param SourceBuffer If not NULL, a pointer to the memory location
1546 containing a copy of the image to be loaded.
1547 @param SourceSize The size in bytes of SourceBuffer.
1548 @param ImageHandle Pointer to the returned image handle that is
1549 created when the image is successfully loaded.
1551 @retval EFI_SUCCESS The image was loaded into memory.
1552 @retval EFI_NOT_FOUND The FilePath was not found.
1553 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1554 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1555 path cannot be parsed to locate the proper
1556 protocol for loading the file.
1557 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1559 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1561 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1562 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1563 image from being loaded. NULL is returned in *ImageHandle.
1564 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1565 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1566 platform policy specifies that the image should not be started.
1572 IN BOOLEAN BootPolicy
,
1573 IN EFI_HANDLE ParentImageHandle
,
1574 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1575 IN VOID
*SourceBuffer OPTIONAL
,
1576 IN UINTN SourceSize
,
1577 OUT EFI_HANDLE
*ImageHandle
1583 PERF_LOAD_IMAGE_BEGIN (NULL
);
1585 Status
= CoreLoadImageCommon (
1591 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
1595 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1599 if (!EFI_ERROR (Status
)) {
1601 // ImageHandle will be valid only Status is success.
1603 Handle
= *ImageHandle
;
1606 PERF_LOAD_IMAGE_END (Handle
);
1614 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1616 @param This Calling context
1617 @param ParentImageHandle The caller's image handle.
1618 @param FilePath The specific file path from which the image is
1620 @param SourceBuffer If not NULL, a pointer to the memory location
1621 containing a copy of the image to be loaded.
1622 @param SourceSize The size in bytes of SourceBuffer.
1623 @param DstBuffer The buffer to store the image.
1624 @param NumberOfPages For input, specifies the space size of the
1625 image by caller if not NULL. For output,
1626 specifies the actual space size needed.
1627 @param ImageHandle Image handle for output.
1628 @param EntryPoint Image entry point for output.
1629 @param Attribute The bit mask of attributes to set for the load
1632 @retval EFI_SUCCESS The image was loaded into memory.
1633 @retval EFI_NOT_FOUND The FilePath was not found.
1634 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1635 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1636 path cannot be parsed to locate the proper
1637 protocol for loading the file.
1638 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1640 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1642 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1643 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1644 image from being loaded. NULL is returned in *ImageHandle.
1645 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1646 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1647 platform policy specifies that the image should not be started.
1653 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1654 IN EFI_HANDLE ParentImageHandle
,
1655 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1656 IN VOID
*SourceBuffer OPTIONAL
,
1657 IN UINTN SourceSize
,
1658 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1659 OUT UINTN
*NumberOfPages OPTIONAL
,
1660 OUT EFI_HANDLE
*ImageHandle
,
1661 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1668 PERF_LOAD_IMAGE_BEGIN (NULL
);
1670 Status
= CoreLoadImageCommon (
1684 if (!EFI_ERROR (Status
)) {
1686 // ImageHandle will be valid only Status is success.
1688 Handle
= *ImageHandle
;
1691 PERF_LOAD_IMAGE_END (Handle
);
1698 Transfer control to a loaded image's entry point.
1700 @param ImageHandle Handle of image to be started.
1701 @param ExitDataSize Pointer of the size to ExitData
1702 @param ExitData Pointer to a pointer to a data buffer that
1703 includes a Null-terminated string,
1704 optionally followed by additional binary data.
1705 The string is a description that the caller may
1706 use to further indicate the reason for the
1709 @retval EFI_INVALID_PARAMETER Invalid parameter
1710 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1711 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1712 @retval EFI_SUCCESS Successfully transfer control to the image's
1719 IN EFI_HANDLE ImageHandle
,
1720 OUT UINTN
*ExitDataSize
,
1721 OUT CHAR16
**ExitData OPTIONAL
1725 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1726 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1727 UINT64 HandleDatabaseKey
;
1731 Handle
= ImageHandle
;
1733 Image
= CoreLoadedImageInfo (ImageHandle
);
1734 if (Image
== NULL
|| Image
->Started
) {
1735 return EFI_INVALID_PARAMETER
;
1737 if (EFI_ERROR (Image
->LoadImageStatus
)) {
1738 return Image
->LoadImageStatus
;
1742 // The image to be started must have the machine type supported by DxeCore.
1744 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->Machine
) &&
1745 Image
->PeCoffEmu
== NULL
) {
1747 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1748 // But it can not be started.
1750 DEBUG ((EFI_D_ERROR
, "Image type %s can't be started ", GetMachineTypeName(Image
->Machine
)));
1751 DEBUG ((EFI_D_ERROR
, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType
)));
1752 return EFI_UNSUPPORTED
;
1755 PERF_START_IMAGE_BEGIN (Handle
);
1759 // Push the current start image context, and
1760 // link the current image to the head. This is the
1761 // only image that can call Exit()
1763 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1764 LastImage
= mCurrentImage
;
1765 mCurrentImage
= Image
;
1766 Image
->Tpl
= gEfiCurrentTpl
;
1769 // Set long jump for Exit() support
1770 // JumpContext must be aligned on a CPU specific boundary.
1771 // Overallocate the buffer and force the required alignment
1773 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1774 if (Image
->JumpBuffer
== NULL
) {
1776 // Image may be unloaded after return with failure,
1777 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1779 PERF_START_IMAGE_END (NULL
);
1782 // Pop the current start image context
1784 mCurrentImage
= LastImage
;
1786 return EFI_OUT_OF_RESOURCES
;
1788 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1790 SetJumpFlag
= SetJump (Image
->JumpContext
);
1792 // The initial call to SetJump() must always return 0.
1793 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1795 if (SetJumpFlag
== 0) {
1796 RegisterMemoryProfileImage (Image
, (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
? EFI_FV_FILETYPE_APPLICATION
: EFI_FV_FILETYPE_DRIVER
));
1798 // Call the image's entry point
1800 Image
->Started
= TRUE
;
1801 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1804 // Add some debug information if the image returned with error.
1805 // This make the user aware and check if the driver image have already released
1806 // all the resource in this situation.
1808 DEBUG_CODE_BEGIN ();
1809 if (EFI_ERROR (Image
->Status
)) {
1810 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1815 // If the image returns, exit it through Exit()
1817 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1821 // Image has completed. Verify the tpl is the same
1823 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1824 CoreRestoreTpl (Image
->Tpl
);
1826 CoreFreePool (Image
->JumpBuffer
);
1829 // Pop the current start image context
1831 mCurrentImage
= LastImage
;
1834 // UEFI Specification - StartImage() - EFI 1.10 Extension
1835 // To maintain compatibility with UEFI drivers that are written to the EFI
1836 // 1.02 Specification, StartImage() must monitor the handle database before
1837 // and after each image is started. If any handles are created or modified
1838 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1839 // be called with the Recursive parameter set to TRUE for each of the newly
1840 // created or modified handles before StartImage() returns.
1842 if (Image
->Type
!= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1843 CoreConnectHandlesByKey (HandleDatabaseKey
);
1847 // Handle the image's returned ExitData
1849 DEBUG_CODE_BEGIN ();
1850 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1852 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1853 if (Image
->ExitData
!= NULL
) {
1854 DEBUG ((DEBUG_LOAD
, " (%hs)", Image
->ExitData
));
1856 DEBUG ((DEBUG_LOAD
, "\n"));
1861 // Return the exit data to the caller
1863 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1864 *ExitDataSize
= Image
->ExitDataSize
;
1865 *ExitData
= Image
->ExitData
;
1868 // Caller doesn't want the exit data, free it
1870 CoreFreePool (Image
->ExitData
);
1871 Image
->ExitData
= NULL
;
1875 // Save the Status because Image will get destroyed if it is unloaded.
1877 Status
= Image
->Status
;
1880 // If the image returned an error, or if the image is an application
1883 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1884 CoreUnloadAndCloseImage (Image
, TRUE
);
1886 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1894 PERF_START_IMAGE_END (Handle
);
1899 Terminates the currently loaded EFI image and returns control to boot services.
1901 @param ImageHandle Handle that identifies the image. This
1902 parameter is passed to the image on entry.
1903 @param Status The image's exit code.
1904 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1905 ExitStatus is EFI_SUCCESS.
1906 @param ExitData Pointer to a data buffer that includes a
1907 Null-terminated Unicode string, optionally
1908 followed by additional binary data. The string
1909 is a description that the caller may use to
1910 further indicate the reason for the image's
1913 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1915 @retval EFI_SUCCESS Successfully terminates the currently loaded
1917 @retval EFI_ACCESS_DENIED Should never reach there.
1918 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1924 IN EFI_HANDLE ImageHandle
,
1925 IN EFI_STATUS Status
,
1926 IN UINTN ExitDataSize
,
1927 IN CHAR16
*ExitData OPTIONAL
1930 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1934 // Prevent possible reentrance to this function
1935 // for the same ImageHandle
1937 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1939 Image
= CoreLoadedImageInfo (ImageHandle
);
1940 if (Image
== NULL
) {
1941 Status
= EFI_INVALID_PARAMETER
;
1945 if (!Image
->Started
) {
1947 // The image has not been started so just free its resources
1949 CoreUnloadAndCloseImage (Image
, TRUE
);
1950 Status
= EFI_SUCCESS
;
1955 // Image has been started, verify this image can exit
1957 if (Image
!= mCurrentImage
) {
1958 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1959 Status
= EFI_INVALID_PARAMETER
;
1966 Image
->Status
= Status
;
1969 // If there's ExitData info, move it
1971 if (ExitData
!= NULL
) {
1972 Image
->ExitDataSize
= ExitDataSize
;
1973 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1974 if (Image
->ExitData
== NULL
) {
1975 Status
= EFI_OUT_OF_RESOURCES
;
1978 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1981 CoreRestoreTpl (OldTpl
);
1983 // return to StartImage
1985 LongJump (Image
->JumpContext
, (UINTN
)-1);
1988 // If we return from LongJump, then it is an error
1991 Status
= EFI_ACCESS_DENIED
;
1993 CoreRestoreTpl (OldTpl
);
2003 @param ImageHandle Handle that identifies the image to be
2006 @retval EFI_SUCCESS The image has been unloaded.
2007 @retval EFI_UNSUPPORTED The image has been started, and does not support
2009 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
2015 IN EFI_HANDLE ImageHandle
2019 LOADED_IMAGE_PRIVATE_DATA
*Image
;
2021 Image
= CoreLoadedImageInfo (ImageHandle
);
2022 if (Image
== NULL
) {
2024 // The image handle is not valid
2026 Status
= EFI_INVALID_PARAMETER
;
2030 if (Image
->Started
) {
2032 // The image has been started, request it to unload.
2034 Status
= EFI_UNSUPPORTED
;
2035 if (Image
->Info
.Unload
!= NULL
) {
2036 Status
= Image
->Info
.Unload (ImageHandle
);
2041 // This Image hasn't been started, thus it can be unloaded
2043 Status
= EFI_SUCCESS
;
2047 if (!EFI_ERROR (Status
)) {
2049 // if the Image was not started or Unloaded O.K. then clean up
2051 CoreUnloadAndCloseImage (Image
, TRUE
);
2061 Unload the specified image.
2063 @param This Indicates the calling context.
2064 @param ImageHandle The specified image handle.
2066 @retval EFI_INVALID_PARAMETER Image handle is NULL.
2067 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
2068 @retval EFI_SUCCESS Image successfully unloaded.
2074 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
2075 IN EFI_HANDLE ImageHandle
2078 return CoreUnloadImage (ImageHandle
);