2 Core image handling services to load and unload PeImage.
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
23 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
24 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
34 // This code is needed to build the Image handle for the DXE Core
36 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
37 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
39 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
40 TRUE
, // If entrypoint has been called
43 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
44 NULL
, // Parent handle
45 NULL
, // System handle
47 NULL
, // Device handle
56 EfiBootServicesCode
, // ImageCodeType
57 EfiBootServicesData
// ImageDataType
59 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
63 EFI_SUCCESS
, // Status
71 NULL
// LoadedImageDevicePath
77 Add the Image Services to EFI Boot Services Table and install the protocol
78 interfaces for this image.
80 @param HobStart The HOB to initialize
86 CoreInitializeImageServices (
91 LOADED_IMAGE_PRIVATE_DATA
*Image
;
92 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
93 UINT64 DxeCoreImageLength
;
94 VOID
*DxeCoreEntryPoint
;
95 EFI_PEI_HOB_POINTERS DxeCoreHob
;
97 // Searching for image hob
99 DxeCoreHob
.Raw
= HobStart
;
100 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
101 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
107 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
109 ASSERT (DxeCoreHob
.Raw
!= NULL
);
111 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
112 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
113 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
114 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
116 // Initialize the fields for an internal driver
118 Image
= &mCorePrivateImage
;
120 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
121 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
122 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
123 Image
->Tpl
= gEfiCurrentTpl
;
124 Image
->Info
.SystemTable
= gDxeCoreST
;
125 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
126 Image
->Info
.ImageSize
= DxeCoreImageLength
;
129 // Install the protocol interfaces for this image
131 Status
= CoreInstallProtocolInterface (
133 &gEfiLoadedImageProtocolGuid
,
134 EFI_NATIVE_INTERFACE
,
137 ASSERT_EFI_ERROR (Status
);
139 mCurrentImage
= Image
;
142 // Fill in DXE globals
144 gDxeCoreImageHandle
= Image
->Handle
;
145 gDxeCoreLoadedImage
= &Image
->Info
;
148 // Export DXE Core PE Loader functionality
150 return CoreInstallProtocolInterface (
151 &mLoadPe32PrivateData
.Handle
,
152 &gEfiLoadPeImageProtocolGuid
,
153 EFI_NATIVE_INTERFACE
,
154 &mLoadPe32PrivateData
.Pe32Image
160 Loads, relocates, and invokes a PE/COFF image
162 @param BootPolicy If TRUE, indicates that the request originates
163 from the boot manager, and that the boot
164 manager is attempting to load FilePath as a
166 @param Pe32Handle The handle of PE32 image
167 @param Image PE image to be loaded
168 @param DstBuffer The buffer to store the image
169 @param EntryPoint A pointer to the entry point
170 @param Attribute The bit mask of attributes to set for the load
173 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
174 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
175 relocate the PE/COFF file
176 @retval EFI_INVALID_PARAMETER Invalid parameter
177 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
182 IN BOOLEAN BootPolicy
,
184 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
185 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
186 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
191 BOOLEAN DstBufAlocated
;
194 EFI_TCG_PLATFORM_PROTOCOL
*TcgPlatformProtocol
;
195 IMAGE_FILE_HANDLE
*FHandle
;
198 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
200 Image
->ImageContext
.Handle
= Pe32Handle
;
201 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
204 // Get information about the image being loaded
206 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
207 if (EFI_ERROR (Status
)) {
211 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
212 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
214 // The PE/COFF loader can support loading image types that can be executed.
215 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
217 return EFI_UNSUPPORTED
;
222 // Set EFI memory type based on ImageType
224 switch (Image
->ImageContext
.ImageType
) {
225 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
226 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
227 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
229 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
230 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
231 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
233 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
234 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
235 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
236 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
239 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
240 return EFI_UNSUPPORTED
;
243 // Get the image base address in the original PeImage.
245 LinkTimeBase
= (UINTN
) Image
->ImageContext
.ImageAddress
;
248 // Allocate memory of the correct memory type aligned on the required image boundry
250 DstBufAlocated
= FALSE
;
251 if (DstBuffer
== 0) {
253 // Allocate Destination Buffer as caller did not pass it in
256 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
257 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
259 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
262 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
265 // If the image relocations have not been stripped, then load at any address.
266 // Otherwise load at the address at which it was linked.
268 // Memory below 1MB should be treated reserved for CSM and there should be
269 // no modules whose preferred load addresses are below 1MB.
271 Status
= EFI_OUT_OF_RESOURCES
;
272 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
273 Status
= CoreAllocatePages (
275 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
276 Image
->NumberOfPages
,
277 &Image
->ImageContext
.ImageAddress
280 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
281 Status
= CoreAllocatePages (
283 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
284 Image
->NumberOfPages
,
285 &Image
->ImageContext
.ImageAddress
288 if (EFI_ERROR (Status
)) {
291 DstBufAlocated
= TRUE
;
294 // Caller provided the destination buffer
297 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
299 // If the image relocations were stripped, and the caller provided a
300 // destination buffer address that does not match the address that the
301 // image is linked at, then the image cannot be loaded.
303 return EFI_INVALID_PARAMETER
;
306 if (Image
->NumberOfPages
!= 0 &&
307 Image
->NumberOfPages
<
308 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
309 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
310 return EFI_BUFFER_TOO_SMALL
;
313 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
314 Image
->ImageContext
.ImageAddress
= DstBuffer
;
317 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
318 if (!Image
->ImageContext
.IsTeImage
) {
319 Image
->ImageContext
.ImageAddress
=
320 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
321 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
325 // Load the image from the file into the allocated memory
327 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
328 if (EFI_ERROR (Status
)) {
333 // If this is a Runtime Driver, then allocate memory for the FixupData that
334 // is used to relocate the image when SetVirtualAddressMap() is called. The
335 // relocation is done by the Runtime AP.
337 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
338 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
339 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
340 if (Image
->ImageContext
.FixupData
== NULL
) {
341 Status
= EFI_OUT_OF_RESOURCES
;
348 // Measure the image before applying fixup
350 Status
= CoreLocateProtocol (
351 &gEfiTcgPlatformProtocolGuid
,
353 (VOID
**) &TcgPlatformProtocol
355 if (!EFI_ERROR (Status
)) {
356 FHandle
= (IMAGE_FILE_HANDLE
*) Image
->ImageContext
.Handle
;
357 Status
= TcgPlatformProtocol
->MeasurePeImage (
359 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FHandle
->Source
,
362 Image
->ImageContext
.ImageType
,
363 Image
->Info
.DeviceHandle
,
367 ASSERT_EFI_ERROR (Status
);
371 // Relocate the image in memory
373 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
374 if (EFI_ERROR (Status
)) {
379 // Flush the Instruction Cache
381 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
384 // Copy the machine type from the context to the image private data. This
385 // is needed during image unload to know if we should call an EBC protocol
386 // to unload the image.
388 Image
->Machine
= Image
->ImageContext
.Machine
;
391 // Get the image entry point. If it's an EBC image, then call into the
392 // interpreter to create a thunk for the entry point and use the returned
393 // value for the entry point.
395 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
396 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
398 // Locate the EBC interpreter protocol
400 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
401 if (EFI_ERROR(Status
)) {
402 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
407 // Register a callback for flushing the instruction cache so that created
408 // thunks can be flushed.
410 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
411 if (EFI_ERROR(Status
)) {
416 // Create a thunk for the image's entry point. This will be the new
417 // entry point for the image.
419 Status
= Image
->Ebc
->CreateThunk (
422 (VOID
*)(UINTN
) Image
->ImageContext
.EntryPoint
,
423 (VOID
**) &Image
->EntryPoint
425 if (EFI_ERROR(Status
)) {
431 // Fill in the image information for the Loaded Image Protocol
433 Image
->Type
= Image
->ImageContext
.ImageType
;
434 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
435 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
436 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
437 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
438 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
439 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
441 // Make a list off all the RT images so we can let the RT AP know about them.
443 Image
->RuntimeData
= AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
444 if (Image
->RuntimeData
== NULL
) {
447 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
448 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
449 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
450 Image
->RuntimeData
->Handle
= Image
->Handle
;
451 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
456 // Fill in the entry point of the image if it is available
458 if (EntryPoint
!= NULL
) {
459 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
463 // Print the load address and the PDB file name if it is available
470 CHAR8 EfiFileName
[256];
473 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
,
474 "Loading driver at 0x%11p EntryPoint=0x%11p ",
475 (VOID
*)(UINTN
) Image
->ImageContext
.ImageAddress
,
476 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)));
480 // Print Module Name by Pdb file path.
481 // Windows and Unix style file path are all trimmed correctly.
483 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
485 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
486 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
487 StartIndex
= Index
+ 1;
491 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
492 // The PDB file name is limited in the range of 0~255.
493 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
495 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
496 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
497 if (EfiFileName
[Index
] == 0) {
498 EfiFileName
[Index
] = '.';
500 if (EfiFileName
[Index
] == '.') {
501 EfiFileName
[Index
+ 1] = 'e';
502 EfiFileName
[Index
+ 2] = 'f';
503 EfiFileName
[Index
+ 3] = 'i';
504 EfiFileName
[Index
+ 4] = 0;
509 if (Index
== sizeof (EfiFileName
) - 4) {
510 EfiFileName
[Index
] = 0;
512 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
514 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
526 if (DstBufAlocated
) {
527 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
530 if (Image
->ImageContext
.FixupData
!= NULL
) {
531 CoreFreePool (Image
->ImageContext
.FixupData
);
540 Get the image's private data from its handle.
542 @param ImageHandle The image handle
544 @return Return the image private data associated with ImageHandle.
547 LOADED_IMAGE_PRIVATE_DATA
*
548 CoreLoadedImageInfo (
549 IN EFI_HANDLE ImageHandle
553 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
554 LOADED_IMAGE_PRIVATE_DATA
*Image
;
556 Status
= CoreHandleProtocol (
558 &gEfiLoadedImageProtocolGuid
,
559 (VOID
**)&LoadedImage
561 if (!EFI_ERROR (Status
)) {
562 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
564 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
573 Unloads EFI image from memory.
575 @param Image EFI image
576 @param FreePage Free allocated pages
580 CoreUnloadAndCloseImage (
581 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
587 EFI_HANDLE
*HandleBuffer
;
589 EFI_GUID
**ProtocolGuidArray
;
592 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
596 if (Image
->Ebc
!= NULL
) {
598 // If EBC protocol exists we must perform cleanups for this image.
600 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
604 // Unload image, free Image->ImageContext->ModHandle
606 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
609 // Free our references to the image handle
611 if (Image
->Handle
!= NULL
) {
613 Status
= CoreLocateHandleBuffer (
620 if (!EFI_ERROR (Status
)) {
621 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
622 Status
= CoreProtocolsPerHandle (
623 HandleBuffer
[HandleIndex
],
627 if (!EFI_ERROR (Status
)) {
628 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
629 Status
= CoreOpenProtocolInformation (
630 HandleBuffer
[HandleIndex
],
631 ProtocolGuidArray
[ProtocolIndex
],
635 if (!EFI_ERROR (Status
)) {
636 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
637 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
638 Status
= CoreCloseProtocol (
639 HandleBuffer
[HandleIndex
],
640 ProtocolGuidArray
[ProtocolIndex
],
642 OpenInfo
[OpenInfoIndex
].ControllerHandle
646 if (OpenInfo
!= NULL
) {
647 CoreFreePool(OpenInfo
);
651 if (ProtocolGuidArray
!= NULL
) {
652 CoreFreePool(ProtocolGuidArray
);
656 if (HandleBuffer
!= NULL
) {
657 CoreFreePool (HandleBuffer
);
661 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
663 Status
= CoreUninstallProtocolInterface (
665 &gEfiLoadedImageDevicePathProtocolGuid
,
666 Image
->LoadedImageDevicePath
669 Status
= CoreUninstallProtocolInterface (
671 &gEfiLoadedImageProtocolGuid
,
677 if (Image
->RuntimeData
!= NULL
) {
678 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
680 // Remove the Image from the Runtime Image list as we are about to Free it!
682 RemoveEntryList (&Image
->RuntimeData
->Link
);
684 CoreFreePool (Image
->RuntimeData
);
688 // Free the Image from memory
690 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
691 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
695 // Done with the Image structure
697 if (Image
->Info
.FilePath
!= NULL
) {
698 CoreFreePool (Image
->Info
.FilePath
);
701 if (Image
->LoadedImageDevicePath
!= NULL
) {
702 CoreFreePool (Image
->LoadedImageDevicePath
);
705 if (Image
->FixupData
!= NULL
) {
706 CoreFreePool (Image
->FixupData
);
709 CoreFreePool (Image
);
714 Loads an EFI image into memory and returns a handle to the image.
716 @param BootPolicy If TRUE, indicates that the request originates
717 from the boot manager, and that the boot
718 manager is attempting to load FilePath as a
720 @param ParentImageHandle The caller's image handle.
721 @param FilePath The specific file path from which the image is
723 @param SourceBuffer If not NULL, a pointer to the memory location
724 containing a copy of the image to be loaded.
725 @param SourceSize The size in bytes of SourceBuffer.
726 @param DstBuffer The buffer to store the image
727 @param NumberOfPages If not NULL, it inputs a pointer to the page
728 number of DstBuffer and outputs a pointer to
729 the page number of the image. If this number is
730 not enough, return EFI_BUFFER_TOO_SMALL and
731 this parameter contains the required number.
732 @param ImageHandle Pointer to the returned image handle that is
733 created when the image is successfully loaded.
734 @param EntryPoint A pointer to the entry point
735 @param Attribute The bit mask of attributes to set for the load
738 @retval EFI_SUCCESS The image was loaded into memory.
739 @retval EFI_NOT_FOUND The FilePath was not found.
740 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
741 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
742 @retval EFI_UNSUPPORTED The image type is not supported, or the device
743 path cannot be parsed to locate the proper
744 protocol for loading the file.
745 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
750 CoreLoadImageCommon (
751 IN BOOLEAN BootPolicy
,
752 IN EFI_HANDLE ParentImageHandle
,
753 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
754 IN VOID
*SourceBuffer OPTIONAL
,
756 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
757 IN OUT UINTN
*NumberOfPages OPTIONAL
,
758 OUT EFI_HANDLE
*ImageHandle
,
759 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
763 LOADED_IMAGE_PRIVATE_DATA
*Image
;
764 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
765 IMAGE_FILE_HANDLE FHand
;
767 EFI_STATUS SecurityStatus
;
768 EFI_HANDLE DeviceHandle
;
769 UINT32 AuthenticationStatus
;
770 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
771 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
774 SecurityStatus
= EFI_SUCCESS
;
776 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
780 // The caller must pass in a valid ParentImageHandle
782 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
783 return EFI_INVALID_PARAMETER
;
786 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
787 if (ParentImage
== NULL
) {
788 DEBUG((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
789 return EFI_INVALID_PARAMETER
;
793 // Get simple read access to the source file
795 OriginalFilePath
= FilePath
;
796 Status
= CoreOpenImageFile (
803 &AuthenticationStatus
805 if (Status
== EFI_ALREADY_STARTED
) {
808 } else if (EFI_ERROR (Status
)) {
813 // Verify the Authentication Status through the Security Architectural Protocol
815 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
816 SecurityStatus
= gSecurity
->FileAuthenticationState (
818 AuthenticationStatus
,
821 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
822 Status
= SecurityStatus
;
830 // Allocate a new image structure
832 Image
= AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
834 return EFI_OUT_OF_RESOURCES
;
838 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
840 FilePath
= OriginalFilePath
;
841 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
842 if (!EFI_ERROR (Status
)) {
843 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
844 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*)FilePath
) + FilePathSize
);
848 // Initialize the fields for an internal driver
850 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
851 Image
->Info
.SystemTable
= gDxeCoreST
;
852 Image
->Info
.DeviceHandle
= DeviceHandle
;
853 Image
->Info
.Revision
= EFI_LOADED_IMAGE_PROTOCOL_REVISION
;
854 Image
->Info
.FilePath
= DuplicateDevicePath (FilePath
);
855 Image
->Info
.ParentHandle
= ParentImageHandle
;
858 if (NumberOfPages
!= NULL
) {
859 Image
->NumberOfPages
= *NumberOfPages
;
861 Image
->NumberOfPages
= 0 ;
865 // Install the protocol interfaces for this image
866 // don't fire notifications yet
868 Status
= CoreInstallProtocolInterfaceNotify (
870 &gEfiLoadedImageProtocolGuid
,
871 EFI_NATIVE_INTERFACE
,
875 if (EFI_ERROR (Status
)) {
880 // Load the image. If EntryPoint is Null, it will not be set.
882 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
883 if (EFI_ERROR (Status
)) {
884 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
885 if (NumberOfPages
!= NULL
) {
886 *NumberOfPages
= Image
->NumberOfPages
;
892 if (NumberOfPages
!= NULL
) {
893 *NumberOfPages
= Image
->NumberOfPages
;
897 // Register the image in the Debug Image Info Table if the attribute is set
899 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) != 0) {
900 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
904 //Reinstall loaded image protocol to fire any notifications
906 Status
= CoreReinstallProtocolInterface (
908 &gEfiLoadedImageProtocolGuid
,
912 if (EFI_ERROR (Status
)) {
917 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
918 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
920 if (OriginalFilePath
!= NULL
) {
921 Image
->LoadedImageDevicePath
= DuplicateDevicePath (OriginalFilePath
);
925 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
927 Status
= CoreInstallProtocolInterface (
929 &gEfiLoadedImageDevicePathProtocolGuid
,
930 EFI_NATIVE_INTERFACE
,
931 Image
->LoadedImageDevicePath
933 if (EFI_ERROR (Status
)) {
938 // Success. Return the image handle
940 *ImageHandle
= Image
->Handle
;
944 // All done accessing the source file
945 // If we allocated the Source buffer, free it
947 if (FHand
.FreeBuffer
) {
948 CoreFreePool (FHand
.Source
);
952 // There was an error. If there's an Image structure, free it
954 if (EFI_ERROR (Status
)) {
956 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
959 } else if (EFI_ERROR (SecurityStatus
)) {
960 Status
= SecurityStatus
;
970 Loads an EFI image into memory and returns a handle to the image.
972 @param BootPolicy If TRUE, indicates that the request originates
973 from the boot manager, and that the boot
974 manager is attempting to load FilePath as a
976 @param ParentImageHandle The caller's image handle.
977 @param FilePath The specific file path from which the image is
979 @param SourceBuffer If not NULL, a pointer to the memory location
980 containing a copy of the image to be loaded.
981 @param SourceSize The size in bytes of SourceBuffer.
982 @param ImageHandle Pointer to the returned image handle that is
983 created when the image is successfully loaded.
985 @retval EFI_SUCCESS The image was loaded into memory.
986 @retval EFI_NOT_FOUND The FilePath was not found.
987 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
988 @retval EFI_UNSUPPORTED The image type is not supported, or the device
989 path cannot be parsed to locate the proper
990 protocol for loading the file.
991 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
998 IN BOOLEAN BootPolicy
,
999 IN EFI_HANDLE ParentImageHandle
,
1000 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1001 IN VOID
*SourceBuffer OPTIONAL
,
1002 IN UINTN SourceSize
,
1003 OUT EFI_HANDLE
*ImageHandle
1011 Tick
= GetPerformanceCounter ();
1014 Status
= CoreLoadImageCommon (
1020 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
1024 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1027 PERF_START (*ImageHandle
, LOAD_IMAGE_TOK
, NULL
, Tick
);
1028 PERF_END (*ImageHandle
, LOAD_IMAGE_TOK
, NULL
, 0);
1036 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1038 @param This Calling context
1039 @param ParentImageHandle The caller's image handle.
1040 @param FilePath The specific file path from which the image is
1042 @param SourceBuffer If not NULL, a pointer to the memory location
1043 containing a copy of the image to be loaded.
1044 @param SourceSize The size in bytes of SourceBuffer.
1045 @param DstBuffer The buffer to store the image.
1046 @param NumberOfPages For input, specifies the space size of the
1047 image by caller if not NULL. For output,
1048 specifies the actual space size needed.
1049 @param ImageHandle Image handle for output.
1050 @param EntryPoint Image entry point for output.
1051 @param Attribute The bit mask of attributes to set for the load
1054 @retval EFI_SUCCESS The image was loaded into memory.
1055 @retval EFI_NOT_FOUND The FilePath was not found.
1056 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1057 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1058 path cannot be parsed to locate the proper
1059 protocol for loading the file.
1060 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1067 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1068 IN EFI_HANDLE ParentImageHandle
,
1069 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1070 IN VOID
*SourceBuffer OPTIONAL
,
1071 IN UINTN SourceSize
,
1072 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1073 OUT UINTN
*NumberOfPages OPTIONAL
,
1074 OUT EFI_HANDLE
*ImageHandle
,
1075 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1079 return CoreLoadImageCommon (
1095 Transfer control to a loaded image's entry point.
1097 @param ImageHandle Handle of image to be started.
1098 @param ExitDataSize Pointer of the size to ExitData
1099 @param ExitData Pointer to a pointer to a data buffer that
1100 includes a Null-terminated Unicode string,
1101 optionally followed by additional binary data.
1102 The string is a description that the caller may
1103 use to further indicate the reason for the
1106 @retval EFI_INVALID_PARAMETER Invalid parameter
1107 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1108 @retval EFI_SUCCESS Successfully transfer control to the image's
1115 IN EFI_HANDLE ImageHandle
,
1116 OUT UINTN
*ExitDataSize
,
1117 OUT CHAR16
**ExitData OPTIONAL
1121 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1122 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1123 UINT64 HandleDatabaseKey
;
1126 Image
= CoreLoadedImageInfo (ImageHandle
);
1127 if (Image
== NULL
|| Image
->Started
) {
1128 return EFI_INVALID_PARAMETER
;
1132 // Don't profile Objects or invalid start requests
1134 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1138 // Push the current start image context, and
1139 // link the current image to the head. This is the
1140 // only image that can call Exit()
1142 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1143 LastImage
= mCurrentImage
;
1144 mCurrentImage
= Image
;
1145 Image
->Tpl
= gEfiCurrentTpl
;
1148 // Set long jump for Exit() support
1149 // JumpContext must be aligned on a CPU specific boundary.
1150 // Overallocate the buffer and force the required alignment
1152 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1153 if (Image
->JumpBuffer
== NULL
) {
1154 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1155 return EFI_OUT_OF_RESOURCES
;
1157 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1159 SetJumpFlag
= SetJump (Image
->JumpContext
);
1161 // The initial call to SetJump() must always return 0.
1162 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1164 if (SetJumpFlag
== 0) {
1166 // Call the image's entry point
1168 Image
->Started
= TRUE
;
1169 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1172 // Add some debug information if the image returned with error.
1173 // This make the user aware and check if the driver image have already released
1174 // all the resource in this situation.
1176 DEBUG_CODE_BEGIN ();
1177 if (EFI_ERROR (Image
->Status
)) {
1178 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1183 // If the image returns, exit it through Exit()
1185 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1189 // Image has completed. Verify the tpl is the same
1191 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1192 CoreRestoreTpl (Image
->Tpl
);
1194 CoreFreePool (Image
->JumpBuffer
);
1197 // Pop the current start image context
1199 mCurrentImage
= LastImage
;
1202 // Go connect any handles that were created or modified while the image executed.
1204 CoreConnectHandlesByKey (HandleDatabaseKey
);
1207 // Handle the image's returned ExitData
1209 DEBUG_CODE_BEGIN ();
1210 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1212 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1213 if (Image
->ExitData
!= NULL
) {
1214 DEBUG ((DEBUG_LOAD
, " (%hs)", Image
->ExitData
));
1216 DEBUG ((DEBUG_LOAD
, "\n"));
1221 // Return the exit data to the caller
1223 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1224 *ExitDataSize
= Image
->ExitDataSize
;
1225 *ExitData
= Image
->ExitData
;
1228 // Caller doesn't want the exit data, free it
1230 CoreFreePool (Image
->ExitData
);
1231 Image
->ExitData
= NULL
;
1235 // Save the Status because Image will get destroyed if it is unloaded.
1237 Status
= Image
->Status
;
1240 // If the image returned an error, or if the image is an application
1243 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1244 CoreUnloadAndCloseImage (Image
, TRUE
);
1250 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1255 Terminates the currently loaded EFI image and returns control to boot services.
1257 @param ImageHandle Handle that identifies the image. This
1258 parameter is passed to the image on entry.
1259 @param Status The image's exit code.
1260 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1261 ExitStatus is EFI_SUCCESS.
1262 @param ExitData Pointer to a data buffer that includes a
1263 Null-terminated Unicode string, optionally
1264 followed by additional binary data. The string
1265 is a description that the caller may use to
1266 further indicate the reason for the image's
1269 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1271 @retval EFI_SUCCESS Successfully terminates the currently loaded
1273 @retval EFI_ACCESS_DENIED Should never reach there.
1274 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1280 IN EFI_HANDLE ImageHandle
,
1281 IN EFI_STATUS Status
,
1282 IN UINTN ExitDataSize
,
1283 IN CHAR16
*ExitData OPTIONAL
1286 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1290 // Prevent possible reentrance to this function
1291 // for the same ImageHandle
1293 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1295 Image
= CoreLoadedImageInfo (ImageHandle
);
1296 if (Image
== NULL
) {
1297 Status
= EFI_INVALID_PARAMETER
;
1301 if (!Image
->Started
) {
1303 // The image has not been started so just free its resources
1305 CoreUnloadAndCloseImage (Image
, TRUE
);
1306 Status
= EFI_SUCCESS
;
1311 // Image has been started, verify this image can exit
1313 if (Image
!= mCurrentImage
) {
1314 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1315 Status
= EFI_INVALID_PARAMETER
;
1322 Image
->Status
= Status
;
1325 // If there's ExitData info, move it
1327 if (ExitData
!= NULL
) {
1328 Image
->ExitDataSize
= ExitDataSize
;
1329 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1330 if (Image
->ExitData
== NULL
) {
1331 Status
= EFI_OUT_OF_RESOURCES
;
1334 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1337 CoreRestoreTpl (OldTpl
);
1339 // return to StartImage
1341 LongJump (Image
->JumpContext
, (UINTN
)-1);
1344 // If we return from LongJump, then it is an error
1347 Status
= EFI_ACCESS_DENIED
;
1349 CoreRestoreTpl (OldTpl
);
1359 @param ImageHandle Handle that identifies the image to be
1362 @retval EFI_SUCCESS The image has been unloaded.
1363 @retval EFI_UNSUPPORTED The image has been sarted, and does not support
1365 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1371 IN EFI_HANDLE ImageHandle
1375 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1377 Image
= CoreLoadedImageInfo (ImageHandle
);
1378 if (Image
== NULL
) {
1380 // The image handle is not valid
1382 Status
= EFI_INVALID_PARAMETER
;
1386 if (Image
->Started
) {
1388 // The image has been started, request it to unload.
1390 Status
= EFI_UNSUPPORTED
;
1391 if (Image
->Info
.Unload
!= NULL
) {
1392 Status
= Image
->Info
.Unload (ImageHandle
);
1397 // This Image hasn't been started, thus it can be unloaded
1399 Status
= EFI_SUCCESS
;
1403 if (!EFI_ERROR (Status
)) {
1405 // if the Image was not started or Unloaded O.K. then clean up
1407 CoreUnloadAndCloseImage (Image
, TRUE
);
1417 Unload the specified image.
1419 @param This Indicates the calling context.
1420 @param ImageHandle The specified image handle.
1422 @retval EFI_INVALID_PARAMETER Image handle is NULL.
1423 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
1424 @retval EFI_SUCCESS Image successfully unloaded.
1430 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1431 IN EFI_HANDLE ImageHandle
1434 return CoreUnloadImage (ImageHandle
);