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 EMULATOR_ENTRY
*Entry
;
145 BufferSize
= sizeof (EmuHandle
);
146 Status
= CoreLocateHandle (
149 mPeCoffEmuProtocolNotifyRegistration
,
153 if (EFI_ERROR (Status
)) {
155 // If no more notification events exit
160 Entry
= AllocateZeroPool (sizeof (*Entry
));
161 ASSERT (Entry
!= NULL
);
163 Status
= CoreHandleProtocol (
165 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
166 (VOID
**)&Entry
->Emulator
168 ASSERT_EFI_ERROR (Status
);
170 Entry
->MachineType
= Entry
->Emulator
->MachineType
;
172 InsertTailList (&mAvailableEmulators
, &Entry
->Link
);
177 Add the Image Services to EFI Boot Services Table and install the protocol
178 interfaces for this image.
180 @param HobStart The HOB to initialize
186 CoreInitializeImageServices (
191 LOADED_IMAGE_PRIVATE_DATA
*Image
;
192 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
193 UINT64 DxeCoreImageLength
;
194 VOID
*DxeCoreEntryPoint
;
195 EFI_PEI_HOB_POINTERS DxeCoreHob
;
198 // Searching for image hob
200 DxeCoreHob
.Raw
= HobStart
;
201 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
202 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
208 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
210 ASSERT (DxeCoreHob
.Raw
!= NULL
);
212 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
213 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
214 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
215 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
218 // Initialize the fields for an internal driver
220 Image
= &mCorePrivateImage
;
222 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
223 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
224 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
225 Image
->Tpl
= gEfiCurrentTpl
;
226 Image
->Info
.SystemTable
= gDxeCoreST
;
227 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
228 Image
->Info
.ImageSize
= DxeCoreImageLength
;
231 // Install the protocol interfaces for this image
233 Status
= CoreInstallProtocolInterface (
235 &gEfiLoadedImageProtocolGuid
,
236 EFI_NATIVE_INTERFACE
,
239 ASSERT_EFI_ERROR (Status
);
241 mCurrentImage
= Image
;
244 // Fill in DXE globals
246 mDxeCoreImageMachineType
= PeCoffLoaderGetMachineType (Image
->Info
.ImageBase
);
247 gDxeCoreImageHandle
= Image
->Handle
;
248 gDxeCoreLoadedImage
= &Image
->Info
;
251 // Create the PE/COFF emulator protocol registration event
253 Status
= CoreCreateEvent (
256 PeCoffEmuProtocolNotify
,
258 &mPeCoffEmuProtocolRegistrationEvent
260 ASSERT_EFI_ERROR(Status
);
263 // Register for protocol notifications on this event
265 Status
= CoreRegisterProtocolNotify (
266 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
267 mPeCoffEmuProtocolRegistrationEvent
,
268 &mPeCoffEmuProtocolNotifyRegistration
270 ASSERT_EFI_ERROR(Status
);
272 InitializeListHead (&mAvailableEmulators
);
274 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
276 // Export DXE Core PE Loader functionality for backward compatibility.
278 Status
= CoreInstallProtocolInterface (
279 &mLoadPe32PrivateData
.Handle
,
280 &gEfiLoadPeImageProtocolGuid
,
281 EFI_NATIVE_INTERFACE
,
282 &mLoadPe32PrivateData
.Pe32Image
286 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
292 Read image file (specified by UserHandle) into user specified buffer with specified offset
295 @param UserHandle Image file handle
296 @param Offset Offset to the source file
297 @param ReadSize For input, pointer of size to read; For output,
298 pointer of size actually read.
299 @param Buffer Buffer to write into
301 @retval EFI_SUCCESS Successfully read the specified part of file
310 IN OUT UINTN
*ReadSize
,
315 IMAGE_FILE_HANDLE
*FHand
;
317 if (UserHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
318 return EFI_INVALID_PARAMETER
;
321 if (MAX_ADDRESS
- Offset
< *ReadSize
) {
322 return EFI_INVALID_PARAMETER
;
325 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
326 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
329 // Move data from our local copy of the file
331 EndPosition
= Offset
+ *ReadSize
;
332 if (EndPosition
> FHand
->SourceSize
) {
333 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
335 if (Offset
>= FHand
->SourceSize
) {
339 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
343 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
344 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
345 The function is only invoked when load modules at fixed address feature is enabled.
347 @param ImageBase The base address the image will be loaded at.
348 @param ImageSize The size of the image
350 @retval EFI_SUCCESS The memory range the image will be loaded in is available
351 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
354 CheckAndMarkFixLoadingMemoryUsageBitMap (
355 IN EFI_PHYSICAL_ADDRESS ImageBase
,
359 UINT32 DxeCodePageNumber
;
361 EFI_PHYSICAL_ADDRESS DxeCodeBase
;
362 UINTN BaseOffsetPageNumber
;
363 UINTN TopOffsetPageNumber
;
366 // The DXE code range includes RuntimeCodePage range and Boot time code range.
368 DxeCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
369 DxeCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
370 DxeCodeSize
= EFI_PAGES_TO_SIZE(DxeCodePageNumber
);
371 DxeCodeBase
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
- DxeCodeSize
;
374 // If the memory usage bit map is not initialized, do it. Every bit in the array
375 // indicate the status of the corresponding memory page, available or not
377 if (mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
378 mDxeCodeMemoryRangeUsageBitMap
= AllocateZeroPool(((DxeCodePageNumber
/64) + 1)*sizeof(UINT64
));
381 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
383 if (!gLoadFixedAddressCodeMemoryReady
|| mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
384 return EFI_NOT_FOUND
;
387 // Test the memory range for loading the image in the DXE code range.
389 if (gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
< ImageBase
+ ImageSize
||
390 DxeCodeBase
> ImageBase
) {
391 return EFI_NOT_FOUND
;
394 // Test if the memory is avalaible or not.
396 BaseOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
- DxeCodeBase
));
397 TopOffsetPageNumber
= EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
+ ImageSize
- DxeCodeBase
));
398 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
399 if ((mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] & LShiftU64(1, (Index
% 64))) != 0) {
401 // This page is already used.
403 return EFI_NOT_FOUND
;
408 // Being here means the memory range is available. So mark the bits for the memory range
410 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
411 mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] |= LShiftU64(1, (Index
% 64));
417 Get the fixed loading address from image header assigned by build tool. This function only be called
418 when Loading module at Fixed address feature enabled.
420 @param ImageContext Pointer to the image context structure that describes the PE/COFF
421 image that needs to be examined by this function.
422 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
423 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
427 GetPeCoffImageFixLoadingAssignedAddress(
428 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
431 UINTN SectionHeaderOffset
;
433 EFI_IMAGE_SECTION_HEADER SectionHeader
;
434 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
437 UINT16 NumberOfSections
;
438 IMAGE_FILE_HANDLE
*Handle
;
439 UINT64 ValueInSectionHeader
;
442 Status
= EFI_NOT_FOUND
;
445 // Get PeHeader pointer
447 Handle
= (IMAGE_FILE_HANDLE
*)ImageContext
->Handle
;
448 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
* )Handle
->Source
+ ImageContext
->PeCoffHeaderOffset
);
449 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+
451 sizeof (EFI_IMAGE_FILE_HEADER
) +
452 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
;
453 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
456 // Get base address from the first section header that doesn't point to code section.
458 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
460 // Read section header from file
462 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
463 Status
= ImageContext
->ImageRead (
464 ImageContext
->Handle
,
469 if (EFI_ERROR (Status
)) {
472 if (Size
!= sizeof (EFI_IMAGE_SECTION_HEADER
)) {
473 return EFI_NOT_FOUND
;
476 Status
= EFI_NOT_FOUND
;
478 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
480 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
481 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
482 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
483 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
485 ValueInSectionHeader
= ReadUnaligned64((UINT64
*)&SectionHeader
.PointerToRelocations
);
486 if (ValueInSectionHeader
!= 0) {
488 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
489 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
490 // relative to top address
492 if ((INT64
)PcdGet64(PcdLoadModuleAtFixAddressEnable
) < 0) {
493 ImageContext
->ImageAddress
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
+ (INT64
)(INTN
)ImageContext
->ImageAddress
;
496 // Check if the memory range is available.
498 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext
->ImageAddress
, (UINTN
)(ImageContext
->ImageSize
+ ImageContext
->SectionAlignment
));
502 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
504 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
));
509 Decides whether a PE/COFF image can execute on this system, either natively
510 or via emulation/interpretation. In the latter case, the PeCoffEmu member
511 of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer
512 to the emulator protocol that supports this image.
514 @param[in, out] Image LOADED_IMAGE_PRIVATE_DATA struct pointer
516 @retval TRUE The image is supported
517 @retval FALSE The image is not supported
522 CoreIsImageTypeSupported (
523 IN OUT LOADED_IMAGE_PRIVATE_DATA
*Image
527 EMULATOR_ENTRY
*Entry
;
529 for (Link
= GetFirstNode (&mAvailableEmulators
);
530 !IsNull (&mAvailableEmulators
, Link
);
531 Link
= GetNextNode (&mAvailableEmulators
, Link
)) {
533 Entry
= BASE_CR (Link
, EMULATOR_ENTRY
, Link
);
534 if (Entry
->MachineType
!= Image
->ImageContext
.Machine
) {
538 if (Entry
->Emulator
->IsImageSupported (Entry
->Emulator
,
539 Image
->ImageContext
.ImageType
,
540 Image
->Info
.FilePath
)) {
541 Image
->PeCoffEmu
= Entry
->Emulator
;
546 return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
) ||
547 EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
);
551 Loads, relocates, and invokes a PE/COFF image
553 @param BootPolicy If TRUE, indicates that the request originates
554 from the boot manager, and that the boot
555 manager is attempting to load FilePath as a
557 @param Pe32Handle The handle of PE32 image
558 @param Image PE image to be loaded
559 @param DstBuffer The buffer to store the image
560 @param EntryPoint A pointer to the entry point
561 @param Attribute The bit mask of attributes to set for the load
564 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
565 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
566 relocate the PE/COFF file
567 @retval EFI_INVALID_PARAMETER Invalid parameter
568 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
573 IN BOOLEAN BootPolicy
,
575 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
576 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
577 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
582 BOOLEAN DstBufAlocated
;
585 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
587 Image
->ImageContext
.Handle
= Pe32Handle
;
588 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
591 // Get information about the image being loaded
593 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
594 if (EFI_ERROR (Status
)) {
598 if (!CoreIsImageTypeSupported (Image
)) {
600 // The PE/COFF loader can support loading image types that can be executed.
601 // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.
603 DEBUG ((DEBUG_ERROR
, "Image type %s can't be loaded on %s UEFI system.\n",
604 GetMachineTypeName (Image
->ImageContext
.Machine
),
605 GetMachineTypeName (mDxeCoreImageMachineType
)));
606 return EFI_UNSUPPORTED
;
610 // Set EFI memory type based on ImageType
612 switch (Image
->ImageContext
.ImageType
) {
613 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
614 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
615 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
617 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
618 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
619 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
621 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
622 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
623 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
624 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
627 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
628 return EFI_UNSUPPORTED
;
632 // Allocate memory of the correct memory type aligned on the required image boundary
634 DstBufAlocated
= FALSE
;
635 if (DstBuffer
== 0) {
637 // Allocate Destination Buffer as caller did not pass it in
640 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
641 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
643 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
646 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
649 // If the image relocations have not been stripped, then load at any address.
650 // Otherwise load at the address at which it was linked.
652 // Memory below 1MB should be treated reserved for CSM and there should be
653 // no modules whose preferred load addresses are below 1MB.
655 Status
= EFI_OUT_OF_RESOURCES
;
657 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
658 // a specified address.
660 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 ) {
661 Status
= GetPeCoffImageFixLoadingAssignedAddress (&(Image
->ImageContext
));
663 if (EFI_ERROR (Status
)) {
665 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
667 DEBUG ((EFI_D_INFO
|EFI_D_LOAD
, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
669 Status
= CoreAllocatePages (
671 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
672 Image
->NumberOfPages
,
673 &Image
->ImageContext
.ImageAddress
677 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
678 Status
= CoreAllocatePages (
680 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
681 Image
->NumberOfPages
,
682 &Image
->ImageContext
.ImageAddress
685 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
686 Status
= CoreAllocatePages (
688 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
689 Image
->NumberOfPages
,
690 &Image
->ImageContext
.ImageAddress
694 if (EFI_ERROR (Status
)) {
697 DstBufAlocated
= TRUE
;
700 // Caller provided the destination buffer
703 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
705 // If the image relocations were stripped, and the caller provided a
706 // destination buffer address that does not match the address that the
707 // image is linked at, then the image cannot be loaded.
709 return EFI_INVALID_PARAMETER
;
712 if (Image
->NumberOfPages
!= 0 &&
713 Image
->NumberOfPages
<
714 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
715 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
716 return EFI_BUFFER_TOO_SMALL
;
719 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
720 Image
->ImageContext
.ImageAddress
= DstBuffer
;
723 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
724 if (!Image
->ImageContext
.IsTeImage
) {
725 Image
->ImageContext
.ImageAddress
=
726 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
727 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
731 // Load the image from the file into the allocated memory
733 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
734 if (EFI_ERROR (Status
)) {
739 // If this is a Runtime Driver, then allocate memory for the FixupData that
740 // is used to relocate the image when SetVirtualAddressMap() is called. The
741 // relocation is done by the Runtime AP.
743 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
744 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
745 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
746 if (Image
->ImageContext
.FixupData
== NULL
) {
747 Status
= EFI_OUT_OF_RESOURCES
;
754 // Relocate the image in memory
756 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
757 if (EFI_ERROR (Status
)) {
762 // Flush the Instruction Cache
764 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
767 // Copy the machine type from the context to the image private data.
769 Image
->Machine
= Image
->ImageContext
.Machine
;
772 // Get the image entry point.
774 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
775 if (Image
->PeCoffEmu
!= NULL
) {
776 Status
= Image
->PeCoffEmu
->RegisterImage (Image
->PeCoffEmu
,
777 Image
->ImageBasePage
,
778 EFI_PAGES_TO_SIZE (Image
->NumberOfPages
),
780 if (EFI_ERROR (Status
)) {
781 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
,
782 "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));
788 // Fill in the image information for the Loaded Image Protocol
790 Image
->Type
= Image
->ImageContext
.ImageType
;
791 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
792 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
793 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
794 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
795 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
796 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
798 // Make a list off all the RT images so we can let the RT AP know about them.
800 Image
->RuntimeData
= AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
801 if (Image
->RuntimeData
== NULL
) {
804 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
805 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
806 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
807 Image
->RuntimeData
->Handle
= Image
->Handle
;
808 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
809 InsertImageRecord (Image
->RuntimeData
);
814 // Fill in the entry point of the image if it is available
816 if (EntryPoint
!= NULL
) {
817 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
821 // Print the load address and the PDB file name if it is available
828 CHAR8 EfiFileName
[256];
831 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
,
832 "Loading driver at 0x%11p EntryPoint=0x%11p ",
833 (VOID
*)(UINTN
) Image
->ImageContext
.ImageAddress
,
834 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)));
838 // Print Module Name by Pdb file path.
839 // Windows and Unix style file path are all trimmed correctly.
841 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
843 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
844 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
845 StartIndex
= Index
+ 1;
849 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
850 // The PDB file name is limited in the range of 0~255.
851 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
853 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
854 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
855 if (EfiFileName
[Index
] == 0) {
856 EfiFileName
[Index
] = '.';
858 if (EfiFileName
[Index
] == '.') {
859 EfiFileName
[Index
+ 1] = 'e';
860 EfiFileName
[Index
+ 2] = 'f';
861 EfiFileName
[Index
+ 3] = 'i';
862 EfiFileName
[Index
+ 4] = 0;
867 if (Index
== sizeof (EfiFileName
) - 4) {
868 EfiFileName
[Index
] = 0;
870 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
872 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
884 if (DstBufAlocated
) {
885 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
886 Image
->ImageContext
.ImageAddress
= 0;
887 Image
->ImageBasePage
= 0;
890 if (Image
->ImageContext
.FixupData
!= NULL
) {
891 CoreFreePool (Image
->ImageContext
.FixupData
);
900 Get the image's private data from its handle.
902 @param ImageHandle The image handle
904 @return Return the image private data associated with ImageHandle.
907 LOADED_IMAGE_PRIVATE_DATA
*
908 CoreLoadedImageInfo (
909 IN EFI_HANDLE ImageHandle
913 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
914 LOADED_IMAGE_PRIVATE_DATA
*Image
;
916 Status
= CoreHandleProtocol (
918 &gEfiLoadedImageProtocolGuid
,
919 (VOID
**)&LoadedImage
921 if (!EFI_ERROR (Status
)) {
922 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
924 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
933 Unloads EFI image from memory.
935 @param Image EFI image
936 @param FreePage Free allocated pages
940 CoreUnloadAndCloseImage (
941 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
947 EFI_HANDLE
*HandleBuffer
;
949 EFI_GUID
**ProtocolGuidArray
;
952 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
957 ProtocolGuidArray
= NULL
;
959 if (Image
->Started
) {
960 UnregisterMemoryProfileImage (Image
);
963 UnprotectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
965 if (Image
->PeCoffEmu
!= NULL
) {
967 // If the PE/COFF Emulator protocol exists we must unregister the image.
969 Image
->PeCoffEmu
->UnregisterImage (Image
->PeCoffEmu
, Image
->ImageBasePage
);
973 // Unload image, free Image->ImageContext->ModHandle
975 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
978 // Free our references to the image handle
980 if (Image
->Handle
!= NULL
) {
982 Status
= CoreLocateHandleBuffer (
989 if (!EFI_ERROR (Status
)) {
990 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
991 Status
= CoreProtocolsPerHandle (
992 HandleBuffer
[HandleIndex
],
996 if (!EFI_ERROR (Status
)) {
997 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
998 Status
= CoreOpenProtocolInformation (
999 HandleBuffer
[HandleIndex
],
1000 ProtocolGuidArray
[ProtocolIndex
],
1004 if (!EFI_ERROR (Status
)) {
1005 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1006 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1007 Status
= CoreCloseProtocol (
1008 HandleBuffer
[HandleIndex
],
1009 ProtocolGuidArray
[ProtocolIndex
],
1011 OpenInfo
[OpenInfoIndex
].ControllerHandle
1015 if (OpenInfo
!= NULL
) {
1016 CoreFreePool(OpenInfo
);
1020 if (ProtocolGuidArray
!= NULL
) {
1021 CoreFreePool(ProtocolGuidArray
);
1025 if (HandleBuffer
!= NULL
) {
1026 CoreFreePool (HandleBuffer
);
1030 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1032 Status
= CoreUninstallProtocolInterface (
1034 &gEfiLoadedImageDevicePathProtocolGuid
,
1035 Image
->LoadedImageDevicePath
1038 Status
= CoreUninstallProtocolInterface (
1040 &gEfiLoadedImageProtocolGuid
,
1044 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1045 Status
= CoreUninstallProtocolInterface (
1047 &gEfiHiiPackageListProtocolGuid
,
1048 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1054 if (Image
->RuntimeData
!= NULL
) {
1055 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1057 // Remove the Image from the Runtime Image list as we are about to Free it!
1059 RemoveEntryList (&Image
->RuntimeData
->Link
);
1060 RemoveImageRecord (Image
->RuntimeData
);
1062 CoreFreePool (Image
->RuntimeData
);
1066 // Free the Image from memory
1068 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1069 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1073 // Done with the Image structure
1075 if (Image
->Info
.FilePath
!= NULL
) {
1076 CoreFreePool (Image
->Info
.FilePath
);
1079 if (Image
->LoadedImageDevicePath
!= NULL
) {
1080 CoreFreePool (Image
->LoadedImageDevicePath
);
1083 if (Image
->FixupData
!= NULL
) {
1084 CoreFreePool (Image
->FixupData
);
1087 CoreFreePool (Image
);
1092 Loads an EFI image into memory and returns a handle to the image.
1094 @param BootPolicy If TRUE, indicates that the request originates
1095 from the boot manager, and that the boot
1096 manager is attempting to load FilePath as a
1098 @param ParentImageHandle The caller's image handle.
1099 @param FilePath The specific file path from which the image is
1101 @param SourceBuffer If not NULL, a pointer to the memory location
1102 containing a copy of the image to be loaded.
1103 @param SourceSize The size in bytes of SourceBuffer.
1104 @param DstBuffer The buffer to store the image
1105 @param NumberOfPages If not NULL, it inputs a pointer to the page
1106 number of DstBuffer and outputs a pointer to
1107 the page number of the image. If this number is
1108 not enough, return EFI_BUFFER_TOO_SMALL and
1109 this parameter contains the required number.
1110 @param ImageHandle Pointer to the returned image handle that is
1111 created when the image is successfully loaded.
1112 @param EntryPoint A pointer to the entry point
1113 @param Attribute The bit mask of attributes to set for the load
1116 @retval EFI_SUCCESS The image was loaded into memory.
1117 @retval EFI_NOT_FOUND The FilePath was not found.
1118 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1119 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1120 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1121 path cannot be parsed to locate the proper
1122 protocol for loading the file.
1123 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1125 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1127 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1128 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1129 image from being loaded. NULL is returned in *ImageHandle.
1130 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1131 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1132 platform policy specifies that the image should not be started.
1136 CoreLoadImageCommon (
1137 IN BOOLEAN BootPolicy
,
1138 IN EFI_HANDLE ParentImageHandle
,
1139 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1140 IN VOID
*SourceBuffer OPTIONAL
,
1141 IN UINTN SourceSize
,
1142 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1143 IN OUT UINTN
*NumberOfPages OPTIONAL
,
1144 OUT EFI_HANDLE
*ImageHandle
,
1145 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1149 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1150 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
1151 IMAGE_FILE_HANDLE FHand
;
1153 EFI_STATUS SecurityStatus
;
1154 EFI_HANDLE DeviceHandle
;
1155 UINT32 AuthenticationStatus
;
1156 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
1157 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
1158 EFI_DEVICE_PATH_PROTOCOL
*InputFilePath
;
1159 EFI_DEVICE_PATH_PROTOCOL
*Node
;
1161 BOOLEAN ImageIsFromFv
;
1162 BOOLEAN ImageIsFromLoadFile
;
1164 SecurityStatus
= EFI_SUCCESS
;
1166 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
1170 // The caller must pass in a valid ParentImageHandle
1172 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
1173 return EFI_INVALID_PARAMETER
;
1176 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
1177 if (ParentImage
== NULL
) {
1178 DEBUG((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
1179 return EFI_INVALID_PARAMETER
;
1182 ZeroMem (&FHand
, sizeof (IMAGE_FILE_HANDLE
));
1183 FHand
.Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
1184 OriginalFilePath
= FilePath
;
1185 InputFilePath
= FilePath
;
1186 HandleFilePath
= FilePath
;
1187 DeviceHandle
= NULL
;
1188 Status
= EFI_SUCCESS
;
1189 AuthenticationStatus
= 0;
1190 ImageIsFromFv
= FALSE
;
1191 ImageIsFromLoadFile
= FALSE
;
1194 // If the caller passed a copy of the file, then just use it
1196 if (SourceBuffer
!= NULL
) {
1197 FHand
.Source
= SourceBuffer
;
1198 FHand
.SourceSize
= SourceSize
;
1199 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1200 if (EFI_ERROR (Status
)) {
1201 DeviceHandle
= NULL
;
1203 if (SourceSize
> 0) {
1204 Status
= EFI_SUCCESS
;
1206 Status
= EFI_LOAD_ERROR
;
1209 if (FilePath
== NULL
) {
1210 return EFI_INVALID_PARAMETER
;
1214 // Try to get the image device handle by checking the match protocol.
1217 Status
= CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1218 if (!EFI_ERROR (Status
)) {
1219 ImageIsFromFv
= TRUE
;
1221 HandleFilePath
= FilePath
;
1222 Status
= CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1223 if (EFI_ERROR (Status
)) {
1225 HandleFilePath
= FilePath
;
1226 Status
= CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1228 if (EFI_ERROR (Status
)) {
1229 HandleFilePath
= FilePath
;
1230 Status
= CoreLocateDevicePath (&gEfiLoadFileProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1231 if (!EFI_ERROR (Status
)) {
1232 ImageIsFromLoadFile
= TRUE
;
1233 Node
= HandleFilePath
;
1240 // Get the source file buffer by its device path.
1242 FHand
.Source
= GetFileBufferByFilePath (
1246 &AuthenticationStatus
1248 if (FHand
.Source
== NULL
) {
1249 Status
= EFI_NOT_FOUND
;
1251 FHand
.FreeBuffer
= TRUE
;
1252 if (ImageIsFromLoadFile
) {
1254 // LoadFile () may cause the device path of the Handle be updated.
1256 OriginalFilePath
= AppendDevicePath (DevicePathFromHandle (DeviceHandle
), Node
);
1261 if (EFI_ERROR (Status
)) {
1266 if (gSecurity2
!= NULL
) {
1268 // Verify File Authentication through the Security2 Architectural Protocol
1270 SecurityStatus
= gSecurity2
->FileAuthentication (
1277 if (!EFI_ERROR (SecurityStatus
) && ImageIsFromFv
) {
1279 // When Security2 is installed, Security Architectural Protocol must be published.
1281 ASSERT (gSecurity
!= NULL
);
1284 // Verify the Authentication Status through the Security Architectural Protocol
1285 // Only on images that have been read using Firmware Volume protocol.
1287 SecurityStatus
= gSecurity
->FileAuthenticationState (
1289 AuthenticationStatus
,
1293 } else if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
1295 // Verify the Authentication Status through the Security Architectural Protocol
1297 SecurityStatus
= gSecurity
->FileAuthenticationState (
1299 AuthenticationStatus
,
1305 // Check Security Status.
1307 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
1308 if (SecurityStatus
== EFI_ACCESS_DENIED
) {
1310 // Image was not loaded because the platform policy prohibits the image from being loaded.
1311 // It's the only place we could meet EFI_ACCESS_DENIED.
1313 *ImageHandle
= NULL
;
1315 Status
= SecurityStatus
;
1321 // Allocate a new image structure
1323 Image
= AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
1324 if (Image
== NULL
) {
1325 Status
= EFI_OUT_OF_RESOURCES
;
1330 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1332 FilePath
= OriginalFilePath
;
1333 if (DeviceHandle
!= NULL
) {
1334 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
1335 if (!EFI_ERROR (Status
)) {
1336 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
1337 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*)FilePath
) + FilePathSize
);
1341 // Initialize the fields for an internal driver
1343 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
1344 Image
->Info
.SystemTable
= gDxeCoreST
;
1345 Image
->Info
.DeviceHandle
= DeviceHandle
;
1346 Image
->Info
.Revision
= EFI_LOADED_IMAGE_PROTOCOL_REVISION
;
1347 Image
->Info
.FilePath
= DuplicateDevicePath (FilePath
);
1348 Image
->Info
.ParentHandle
= ParentImageHandle
;
1351 if (NumberOfPages
!= NULL
) {
1352 Image
->NumberOfPages
= *NumberOfPages
;
1354 Image
->NumberOfPages
= 0 ;
1358 // Install the protocol interfaces for this image
1359 // don't fire notifications yet
1361 Status
= CoreInstallProtocolInterfaceNotify (
1363 &gEfiLoadedImageProtocolGuid
,
1364 EFI_NATIVE_INTERFACE
,
1368 if (EFI_ERROR (Status
)) {
1373 // Load the image. If EntryPoint is Null, it will not be set.
1375 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
1376 if (EFI_ERROR (Status
)) {
1377 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
1378 if (NumberOfPages
!= NULL
) {
1379 *NumberOfPages
= Image
->NumberOfPages
;
1385 if (NumberOfPages
!= NULL
) {
1386 *NumberOfPages
= Image
->NumberOfPages
;
1390 // Register the image in the Debug Image Info Table if the attribute is set
1392 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) != 0) {
1393 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
1397 //Reinstall loaded image protocol to fire any notifications
1399 Status
= CoreReinstallProtocolInterface (
1401 &gEfiLoadedImageProtocolGuid
,
1405 if (EFI_ERROR (Status
)) {
1410 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1411 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1413 if (OriginalFilePath
!= NULL
) {
1414 Image
->LoadedImageDevicePath
= DuplicateDevicePath (OriginalFilePath
);
1418 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1420 Status
= CoreInstallProtocolInterface (
1422 &gEfiLoadedImageDevicePathProtocolGuid
,
1423 EFI_NATIVE_INTERFACE
,
1424 Image
->LoadedImageDevicePath
1426 if (EFI_ERROR (Status
)) {
1431 // Install HII Package List Protocol onto the image handle
1433 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1434 Status
= CoreInstallProtocolInterface (
1436 &gEfiHiiPackageListProtocolGuid
,
1437 EFI_NATIVE_INTERFACE
,
1438 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1440 if (EFI_ERROR (Status
)) {
1444 ProtectUefiImage (&Image
->Info
, Image
->LoadedImageDevicePath
);
1447 // Success. Return the image handle
1449 *ImageHandle
= Image
->Handle
;
1453 // All done accessing the source file
1454 // If we allocated the Source buffer, free it
1456 if (FHand
.FreeBuffer
) {
1457 CoreFreePool (FHand
.Source
);
1459 if (OriginalFilePath
!= InputFilePath
) {
1460 CoreFreePool (OriginalFilePath
);
1464 // There was an error. If there's an Image structure, free it
1466 if (EFI_ERROR (Status
)) {
1467 if (Image
!= NULL
) {
1468 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
1471 } else if (EFI_ERROR (SecurityStatus
)) {
1472 Status
= SecurityStatus
;
1476 // Track the return status from LoadImage.
1478 if (Image
!= NULL
) {
1479 Image
->LoadImageStatus
= Status
;
1489 Loads an EFI image into memory and returns a handle to the image.
1491 @param BootPolicy If TRUE, indicates that the request originates
1492 from the boot manager, and that the boot
1493 manager is attempting to load FilePath as a
1495 @param ParentImageHandle The caller's image handle.
1496 @param FilePath The specific file path from which the image is
1498 @param SourceBuffer If not NULL, a pointer to the memory location
1499 containing a copy of the image to be loaded.
1500 @param SourceSize The size in bytes of SourceBuffer.
1501 @param ImageHandle Pointer to the returned image handle that is
1502 created when the image is successfully loaded.
1504 @retval EFI_SUCCESS The image was loaded into memory.
1505 @retval EFI_NOT_FOUND The FilePath was not found.
1506 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1507 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1508 path cannot be parsed to locate the proper
1509 protocol for loading the file.
1510 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1512 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1514 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1515 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1516 image from being loaded. NULL is returned in *ImageHandle.
1517 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1518 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1519 platform policy specifies that the image should not be started.
1525 IN BOOLEAN BootPolicy
,
1526 IN EFI_HANDLE ParentImageHandle
,
1527 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1528 IN VOID
*SourceBuffer OPTIONAL
,
1529 IN UINTN SourceSize
,
1530 OUT EFI_HANDLE
*ImageHandle
1536 PERF_LOAD_IMAGE_BEGIN (NULL
);
1538 Status
= CoreLoadImageCommon (
1544 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
1548 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1552 if (!EFI_ERROR (Status
)) {
1554 // ImageHandle will be valid only Status is success.
1556 Handle
= *ImageHandle
;
1559 PERF_LOAD_IMAGE_END (Handle
);
1567 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1569 @param This Calling context
1570 @param ParentImageHandle The caller's image handle.
1571 @param FilePath The specific file path from which the image is
1573 @param SourceBuffer If not NULL, a pointer to the memory location
1574 containing a copy of the image to be loaded.
1575 @param SourceSize The size in bytes of SourceBuffer.
1576 @param DstBuffer The buffer to store the image.
1577 @param NumberOfPages For input, specifies the space size of the
1578 image by caller if not NULL. For output,
1579 specifies the actual space size needed.
1580 @param ImageHandle Image handle for output.
1581 @param EntryPoint Image entry point for output.
1582 @param Attribute The bit mask of attributes to set for the load
1585 @retval EFI_SUCCESS The image was loaded into memory.
1586 @retval EFI_NOT_FOUND The FilePath was not found.
1587 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1588 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1589 path cannot be parsed to locate the proper
1590 protocol for loading the file.
1591 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1593 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1595 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1596 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1597 image from being loaded. NULL is returned in *ImageHandle.
1598 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1599 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1600 platform policy specifies that the image should not be started.
1606 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1607 IN EFI_HANDLE ParentImageHandle
,
1608 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1609 IN VOID
*SourceBuffer OPTIONAL
,
1610 IN UINTN SourceSize
,
1611 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1612 OUT UINTN
*NumberOfPages OPTIONAL
,
1613 OUT EFI_HANDLE
*ImageHandle
,
1614 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1621 PERF_LOAD_IMAGE_BEGIN (NULL
);
1623 Status
= CoreLoadImageCommon (
1637 if (!EFI_ERROR (Status
)) {
1639 // ImageHandle will be valid only Status is success.
1641 Handle
= *ImageHandle
;
1644 PERF_LOAD_IMAGE_END (Handle
);
1651 Transfer control to a loaded image's entry point.
1653 @param ImageHandle Handle of image to be started.
1654 @param ExitDataSize Pointer of the size to ExitData
1655 @param ExitData Pointer to a pointer to a data buffer that
1656 includes a Null-terminated string,
1657 optionally followed by additional binary data.
1658 The string is a description that the caller may
1659 use to further indicate the reason for the
1662 @retval EFI_INVALID_PARAMETER Invalid parameter
1663 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1664 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1665 @retval EFI_SUCCESS Successfully transfer control to the image's
1672 IN EFI_HANDLE ImageHandle
,
1673 OUT UINTN
*ExitDataSize
,
1674 OUT CHAR16
**ExitData OPTIONAL
1678 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1679 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1680 UINT64 HandleDatabaseKey
;
1684 Handle
= ImageHandle
;
1686 Image
= CoreLoadedImageInfo (ImageHandle
);
1687 if (Image
== NULL
|| Image
->Started
) {
1688 return EFI_INVALID_PARAMETER
;
1690 if (EFI_ERROR (Image
->LoadImageStatus
)) {
1691 return Image
->LoadImageStatus
;
1695 // The image to be started must have the machine type supported by DxeCore.
1697 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->Machine
) &&
1698 Image
->PeCoffEmu
== NULL
) {
1700 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1701 // But it can not be started.
1703 DEBUG ((EFI_D_ERROR
, "Image type %s can't be started ", GetMachineTypeName(Image
->Machine
)));
1704 DEBUG ((EFI_D_ERROR
, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType
)));
1705 return EFI_UNSUPPORTED
;
1708 PERF_START_IMAGE_BEGIN (Handle
);
1712 // Push the current start image context, and
1713 // link the current image to the head. This is the
1714 // only image that can call Exit()
1716 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1717 LastImage
= mCurrentImage
;
1718 mCurrentImage
= Image
;
1719 Image
->Tpl
= gEfiCurrentTpl
;
1722 // Set long jump for Exit() support
1723 // JumpContext must be aligned on a CPU specific boundary.
1724 // Overallocate the buffer and force the required alignment
1726 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1727 if (Image
->JumpBuffer
== NULL
) {
1729 // Image may be unloaded after return with failure,
1730 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1732 PERF_START_IMAGE_END (NULL
);
1735 // Pop the current start image context
1737 mCurrentImage
= LastImage
;
1739 return EFI_OUT_OF_RESOURCES
;
1741 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1743 SetJumpFlag
= SetJump (Image
->JumpContext
);
1745 // The initial call to SetJump() must always return 0.
1746 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1748 if (SetJumpFlag
== 0) {
1749 RegisterMemoryProfileImage (Image
, (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
? EFI_FV_FILETYPE_APPLICATION
: EFI_FV_FILETYPE_DRIVER
));
1751 // Call the image's entry point
1753 Image
->Started
= TRUE
;
1754 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1757 // Add some debug information if the image returned with error.
1758 // This make the user aware and check if the driver image have already released
1759 // all the resource in this situation.
1761 DEBUG_CODE_BEGIN ();
1762 if (EFI_ERROR (Image
->Status
)) {
1763 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1768 // If the image returns, exit it through Exit()
1770 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1774 // Image has completed. Verify the tpl is the same
1776 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1777 CoreRestoreTpl (Image
->Tpl
);
1779 CoreFreePool (Image
->JumpBuffer
);
1782 // Pop the current start image context
1784 mCurrentImage
= LastImage
;
1787 // UEFI Specification - StartImage() - EFI 1.10 Extension
1788 // To maintain compatibility with UEFI drivers that are written to the EFI
1789 // 1.02 Specification, StartImage() must monitor the handle database before
1790 // and after each image is started. If any handles are created or modified
1791 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1792 // be called with the Recursive parameter set to TRUE for each of the newly
1793 // created or modified handles before StartImage() returns.
1795 if (Image
->Type
!= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1796 CoreConnectHandlesByKey (HandleDatabaseKey
);
1800 // Handle the image's returned ExitData
1802 DEBUG_CODE_BEGIN ();
1803 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1805 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1806 if (Image
->ExitData
!= NULL
) {
1807 DEBUG ((DEBUG_LOAD
, " (%hs)", Image
->ExitData
));
1809 DEBUG ((DEBUG_LOAD
, "\n"));
1814 // Return the exit data to the caller
1816 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1817 *ExitDataSize
= Image
->ExitDataSize
;
1818 *ExitData
= Image
->ExitData
;
1821 // Caller doesn't want the exit data, free it
1823 CoreFreePool (Image
->ExitData
);
1824 Image
->ExitData
= NULL
;
1828 // Save the Status because Image will get destroyed if it is unloaded.
1830 Status
= Image
->Status
;
1833 // If the image returned an error, or if the image is an application
1836 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1837 CoreUnloadAndCloseImage (Image
, TRUE
);
1839 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1847 PERF_START_IMAGE_END (Handle
);
1852 Terminates the currently loaded EFI image and returns control to boot services.
1854 @param ImageHandle Handle that identifies the image. This
1855 parameter is passed to the image on entry.
1856 @param Status The image's exit code.
1857 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1858 ExitStatus is EFI_SUCCESS.
1859 @param ExitData Pointer to a data buffer that includes a
1860 Null-terminated Unicode string, optionally
1861 followed by additional binary data. The string
1862 is a description that the caller may use to
1863 further indicate the reason for the image's
1866 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1868 @retval EFI_SUCCESS Successfully terminates the currently loaded
1870 @retval EFI_ACCESS_DENIED Should never reach there.
1871 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1877 IN EFI_HANDLE ImageHandle
,
1878 IN EFI_STATUS Status
,
1879 IN UINTN ExitDataSize
,
1880 IN CHAR16
*ExitData OPTIONAL
1883 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1887 // Prevent possible reentrance to this function
1888 // for the same ImageHandle
1890 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1892 Image
= CoreLoadedImageInfo (ImageHandle
);
1893 if (Image
== NULL
) {
1894 Status
= EFI_INVALID_PARAMETER
;
1898 if (!Image
->Started
) {
1900 // The image has not been started so just free its resources
1902 CoreUnloadAndCloseImage (Image
, TRUE
);
1903 Status
= EFI_SUCCESS
;
1908 // Image has been started, verify this image can exit
1910 if (Image
!= mCurrentImage
) {
1911 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1912 Status
= EFI_INVALID_PARAMETER
;
1919 Image
->Status
= Status
;
1922 // If there's ExitData info, move it
1924 if (ExitData
!= NULL
) {
1925 Image
->ExitDataSize
= ExitDataSize
;
1926 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1927 if (Image
->ExitData
== NULL
) {
1928 Status
= EFI_OUT_OF_RESOURCES
;
1931 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1934 CoreRestoreTpl (OldTpl
);
1936 // return to StartImage
1938 LongJump (Image
->JumpContext
, (UINTN
)-1);
1941 // If we return from LongJump, then it is an error
1944 Status
= EFI_ACCESS_DENIED
;
1946 CoreRestoreTpl (OldTpl
);
1956 @param ImageHandle Handle that identifies the image to be
1959 @retval EFI_SUCCESS The image has been unloaded.
1960 @retval EFI_UNSUPPORTED The image has been started, and does not support
1962 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1968 IN EFI_HANDLE ImageHandle
1972 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1974 Image
= CoreLoadedImageInfo (ImageHandle
);
1975 if (Image
== NULL
) {
1977 // The image handle is not valid
1979 Status
= EFI_INVALID_PARAMETER
;
1983 if (Image
->Started
) {
1985 // The image has been started, request it to unload.
1987 Status
= EFI_UNSUPPORTED
;
1988 if (Image
->Info
.Unload
!= NULL
) {
1989 Status
= Image
->Info
.Unload (ImageHandle
);
1994 // This Image hasn't been started, thus it can be unloaded
1996 Status
= EFI_SUCCESS
;
2000 if (!EFI_ERROR (Status
)) {
2002 // if the Image was not started or Unloaded O.K. then clean up
2004 CoreUnloadAndCloseImage (Image
, TRUE
);
2014 Unload the specified image.
2016 @param This Indicates the calling context.
2017 @param ImageHandle The specified image handle.
2019 @retval EFI_INVALID_PARAMETER Image handle is NULL.
2020 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
2021 @retval EFI_SUCCESS Image successfully unloaded.
2027 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
2028 IN EFI_HANDLE ImageHandle
2031 return CoreUnloadImage (ImageHandle
);