3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Core image handling services
27 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
29 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
30 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
40 // This code is needed to build the Image handle for the DXE Core
42 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
43 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
45 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
46 TRUE
, // If entrypoint has been called
49 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
50 NULL
, // Parent handle
51 NULL
, // System handle
53 NULL
, // Device handle
62 EfiBootServicesCode
, // ImageCodeType
63 EfiBootServicesData
// ImageDataType
65 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
69 EFI_SUCCESS
, // Status
77 NULL
// LoadedImageDevicePath
82 CoreInitializeImageServices (
89 Add the Image Services to EFI Boot Services Table and install the protocol
90 interfaces for this image.
94 HobStart - The HOB to initialize
103 LOADED_IMAGE_PRIVATE_DATA
*Image
;
104 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
105 UINT64 DxeCoreImageLength
;
106 VOID
*DxeCoreEntryPoint
;
107 EFI_PEI_HOB_POINTERS DxeCoreHob
;
109 // Searching for image hob
111 DxeCoreHob
.Raw
= HobStart
;
112 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
113 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
119 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
121 ASSERT (DxeCoreHob
.Raw
!= NULL
);
123 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
124 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
125 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
126 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
128 // Initialize the fields for an internal driver
130 Image
= &mCorePrivateImage
;
132 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
133 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
134 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
135 Image
->Tpl
= gEfiCurrentTpl
;
136 Image
->Info
.SystemTable
= gDxeCoreST
;
137 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
138 Image
->Info
.ImageSize
= DxeCoreImageLength
;
141 // Install the protocol interfaces for this image
143 Status
= CoreInstallProtocolInterface (
145 &gEfiLoadedImageProtocolGuid
,
146 EFI_NATIVE_INTERFACE
,
149 ASSERT_EFI_ERROR (Status
);
151 mCurrentImage
= Image
;
154 // Fill in DXE globals
156 gDxeCoreImageHandle
= Image
->Handle
;
157 gDxeCoreLoadedImage
= &Image
->Info
;
160 // Export DXE Core PE Loader functionality
162 return CoreInstallProtocolInterface (
163 &mLoadPe32PrivateData
.Handle
,
164 &gEfiLoadPeImageProtocolGuid
,
165 EFI_NATIVE_INTERFACE
,
166 &mLoadPe32PrivateData
.Pe32Image
172 IN BOOLEAN BootPolicy
,
174 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
175 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
176 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
183 Loads, relocates, and invokes a PE/COFF image
186 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
187 and that the boot manager is attempting to load FilePath as a boot selection.
188 Pe32Handle - The handle of PE32 image
189 Image - PE image to be loaded
190 DstBuffer - The buffer to store the image
191 EntryPoint - A pointer to the entry point
192 Attribute - The bit mask of attributes to set for the load PE image
196 EFI_SUCCESS - The file was loaded, relocated, and invoked
198 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
200 EFI_INVALID_PARAMETER - Invalid parameter
202 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
207 BOOLEAN DstBufAlocated
;
210 EFI_TCG_PLATFORM_PROTOCOL
*TcgPlatformProtocol
;
212 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
214 Image
->ImageContext
.Handle
= Pe32Handle
;
215 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
218 // Get information about the image being loaded
220 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
221 if (EFI_ERROR (Status
)) {
225 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
227 // The PE/COFF loader can support loading image types that can be executed.
228 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
230 return EFI_UNSUPPORTED
;
234 // Set EFI memory type based on ImageType
236 switch (Image
->ImageContext
.ImageType
) {
237 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
238 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
239 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
241 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
242 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
243 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
245 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
246 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
247 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
248 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
251 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
252 return EFI_UNSUPPORTED
;
255 // Get the image base address in the original PeImage.
257 LinkTimeBase
= (UINTN
) Image
->ImageContext
.ImageAddress
;
260 // Allocate memory of the correct memory type aligned on the required image boundry
262 DstBufAlocated
= FALSE
;
263 if (DstBuffer
== 0) {
265 // Allocate Destination Buffer as caller did not pass it in
268 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
269 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
271 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
274 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
277 // If the image relocations have not been stripped, then load at any address.
278 // Otherwise load at the address at which it was linked.
280 // Memory below 1MB should be treated reserved for CSM and there should be
281 // no modules whose preferred load addresses are below 1MB.
283 Status
= EFI_OUT_OF_RESOURCES
;
284 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
285 Status
= CoreAllocatePages (
287 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
288 Image
->NumberOfPages
,
289 &Image
->ImageContext
.ImageAddress
292 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
293 Status
= CoreAllocatePages (
295 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
296 Image
->NumberOfPages
,
297 &Image
->ImageContext
.ImageAddress
300 if (EFI_ERROR (Status
)) {
303 DstBufAlocated
= TRUE
;
306 // Caller provided the destination buffer
309 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
311 // If the image relocations were stripped, and the caller provided a
312 // destination buffer address that does not match the address that the
313 // image is linked at, then the image cannot be loaded.
315 return EFI_INVALID_PARAMETER
;
318 if (Image
->NumberOfPages
!= 0 &&
319 Image
->NumberOfPages
<
320 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
321 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
322 return EFI_BUFFER_TOO_SMALL
;
325 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
326 Image
->ImageContext
.ImageAddress
= DstBuffer
;
329 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
330 Image
->ImageContext
.ImageAddress
=
331 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
332 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
335 // Load the image from the file into the allocated memory
337 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
338 if (EFI_ERROR (Status
)) {
343 // If this is a Runtime Driver, then allocate memory for the FixupData that
344 // is used to relocate the image when SetVirtualAddressMap() is called. The
345 // relocation is done by the Runtime AP.
347 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
348 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
349 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
350 if (Image
->ImageContext
.FixupData
== NULL
) {
351 Status
= EFI_OUT_OF_RESOURCES
;
358 // Measure the image before applying fixup
360 Status
= CoreLocateProtocol (
361 &gEfiTcgPlatformProtocolGuid
,
363 (VOID
**) &TcgPlatformProtocol
365 if (!EFI_ERROR (Status
)) {
366 Status
= TcgPlatformProtocol
->MeasurePeImage (
368 Image
->ImageContext
.ImageAddress
,
369 (UINTN
) Image
->ImageContext
.ImageSize
,
371 Image
->ImageContext
.ImageType
,
372 Image
->Info
.DeviceHandle
,
376 ASSERT_EFI_ERROR (Status
);
380 // Relocate the image in memory
382 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
383 if (EFI_ERROR (Status
)) {
388 // Flush the Instruction Cache
390 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
393 // Copy the machine type from the context to the image private data. This
394 // is needed during image unload to know if we should call an EBC protocol
395 // to unload the image.
397 Image
->Machine
= Image
->ImageContext
.Machine
;
400 // Get the image entry point. If it's an EBC image, then call into the
401 // interpreter to create a thunk for the entry point and use the returned
402 // value for the entry point.
404 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
405 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
407 // Locate the EBC interpreter protocol
409 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
410 if (EFI_ERROR(Status
)) {
415 // Register a callback for flushing the instruction cache so that created
416 // thunks can be flushed.
418 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
419 if (EFI_ERROR(Status
)) {
424 // Create a thunk for the image's entry point. This will be the new
425 // entry point for the image.
427 Status
= Image
->Ebc
->CreateThunk (
430 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
431 (VOID
**)&Image
->EntryPoint
433 if (EFI_ERROR(Status
)) {
439 // Fill in the image information for the Loaded Image Protocol
441 Image
->Type
= Image
->ImageContext
.ImageType
;
442 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
443 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
444 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
445 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
446 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
447 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
449 // Make a list off all the RT images so we can let the RT AP know about them.
451 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
452 if (Image
->RuntimeData
== NULL
) {
455 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
456 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
457 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
458 Image
->RuntimeData
->Handle
= Image
->Handle
;
459 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
464 // Fill in the entry point of the image if it is available
466 if (EntryPoint
!= NULL
) {
467 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
471 // Print the load address and the PDB file name if it is available
478 CHAR8 EfiFileName
[256];
480 if (Image
->ImageContext
.Machine
!= IMAGE_FILE_MACHINE_IA64
) {
481 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
482 "Loading driver at 0x%10p EntryPoint=0x%10p ",
483 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
484 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
));
487 // For IPF Image, the real entry point should be print.
489 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
490 "Loading driver at 0x%10p EntryPoint=0x%10p ",
491 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
492 (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)Image
->ImageContext
.EntryPoint
)));
496 // Print Module Name by Pdb file path
498 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
500 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
501 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
502 StartIndex
= Index
+ 1;
506 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
508 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
509 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
510 if (EfiFileName
[Index
] == 0) {
511 EfiFileName
[Index
] = '.';
513 if (EfiFileName
[Index
] == '.') {
514 EfiFileName
[Index
+ 1] = 'e';
515 EfiFileName
[Index
+ 2] = 'f';
516 EfiFileName
[Index
+ 3] = 'i';
517 EfiFileName
[Index
+ 4] = 0;
521 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
523 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
535 if (DstBufAlocated
) {
536 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
539 if (Image
->ImageContext
.FixupData
!= NULL
) {
540 CoreFreePool (Image
->ImageContext
.FixupData
);
547 LOADED_IMAGE_PRIVATE_DATA
*
548 CoreLoadedImageInfo (
549 IN EFI_HANDLE ImageHandle
555 Get the image's private data from its handle.
559 ImageHandle - The image handle
563 Return the image private data associated with ImageHandle.
568 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
569 LOADED_IMAGE_PRIVATE_DATA
*Image
;
571 Status
= CoreHandleProtocol (
573 &gEfiLoadedImageProtocolGuid
,
574 (VOID
**)&LoadedImage
576 if (!EFI_ERROR (Status
)) {
577 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
579 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
588 CoreLoadImageCommon (
589 IN BOOLEAN BootPolicy
,
590 IN EFI_HANDLE ParentImageHandle
,
591 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
592 IN VOID
*SourceBuffer OPTIONAL
,
594 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
595 IN OUT UINTN
*NumberOfPages OPTIONAL
,
596 OUT EFI_HANDLE
*ImageHandle
,
597 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
604 Loads an EFI image into memory and returns a handle to the image.
608 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
609 and that the boot manager is attempting to load FilePath as a boot selection.
610 ParentImageHandle - The caller's image handle.
611 FilePath - The specific file path from which the image is loaded.
612 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
613 the image to be loaded.
614 SourceSize - The size in bytes of SourceBuffer.
615 DstBuffer - The buffer to store the image
616 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
617 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
619 ImageHandle - Pointer to the returned image handle that is created when the image
620 is successfully loaded.
621 EntryPoint - A pointer to the entry point
622 Attribute - The bit mask of attributes to set for the load PE image
626 EFI_SUCCESS - The image was loaded into memory.
627 EFI_NOT_FOUND - The FilePath was not found.
628 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
629 EFI_BUFFER_TOO_SMALL - The buffer is too small
630 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
631 parsed to locate the proper protocol for loading the file.
632 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
635 LOADED_IMAGE_PRIVATE_DATA
*Image
;
636 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
637 IMAGE_FILE_HANDLE FHand
;
639 EFI_STATUS SecurityStatus
;
640 EFI_HANDLE DeviceHandle
;
641 UINT32 AuthenticationStatus
;
642 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
643 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
646 SecurityStatus
= EFI_SUCCESS
;
648 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
652 // The caller must pass in a valid ParentImageHandle
654 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
655 return EFI_INVALID_PARAMETER
;
658 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
659 if (ParentImage
== NULL
) {
660 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
661 return EFI_INVALID_PARAMETER
;
665 // Get simple read access to the source file
667 OriginalFilePath
= FilePath
;
668 Status
= CoreOpenImageFile (
675 &AuthenticationStatus
677 if (Status
== EFI_ALREADY_STARTED
) {
680 } else if (EFI_ERROR (Status
)) {
685 // Verify the Authentication Status through the Security Architectural Protocol
687 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
688 SecurityStatus
= gSecurity
->FileAuthenticationState (
690 AuthenticationStatus
,
693 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
694 Status
= SecurityStatus
;
702 // Allocate a new image structure
704 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
706 return EFI_OUT_OF_RESOURCES
;
710 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
712 FilePath
= OriginalFilePath
;
713 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
714 if (!EFI_ERROR (Status
)) {
715 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
716 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
720 // Initialize the fields for an internal driver
722 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
723 Image
->Info
.SystemTable
= gDxeCoreST
;
724 Image
->Info
.DeviceHandle
= DeviceHandle
;
725 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
726 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
727 Image
->Info
.ParentHandle
= ParentImageHandle
;
730 if (NumberOfPages
!= NULL
) {
731 Image
->NumberOfPages
= *NumberOfPages
;
733 Image
->NumberOfPages
= 0 ;
737 // Install the protocol interfaces for this image
738 // don't fire notifications yet
740 Status
= CoreInstallProtocolInterfaceNotify (
742 &gEfiLoadedImageProtocolGuid
,
743 EFI_NATIVE_INTERFACE
,
747 if (EFI_ERROR (Status
)) {
752 // Load the image. If EntryPoint is Null, it will not be set.
754 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
755 if (EFI_ERROR (Status
)) {
756 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
757 if (NumberOfPages
!= NULL
) {
758 *NumberOfPages
= Image
->NumberOfPages
;
765 // Register the image in the Debug Image Info Table if the attribute is set
767 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
768 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
772 //Reinstall loaded image protocol to fire any notifications
774 Status
= CoreReinstallProtocolInterface (
776 &gEfiLoadedImageProtocolGuid
,
780 if (EFI_ERROR (Status
)) {
785 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
786 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
788 if (OriginalFilePath
!= NULL
) {
789 Image
->LoadedImageDevicePath
= CoreDuplicateDevicePath (OriginalFilePath
);
793 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
795 Status
= CoreInstallProtocolInterface (
797 &gEfiLoadedImageDevicePathProtocolGuid
,
798 EFI_NATIVE_INTERFACE
,
799 Image
->LoadedImageDevicePath
801 if (EFI_ERROR (Status
)) {
806 // Success. Return the image handle
808 *ImageHandle
= Image
->Handle
;
812 // All done accessing the source file
813 // If we allocated the Source buffer, free it
815 if (FHand
.FreeBuffer
) {
816 CoreFreePool (FHand
.Source
);
820 // There was an error. If there's an Image structure, free it
822 if (EFI_ERROR (Status
)) {
824 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
827 } else if (EFI_ERROR (SecurityStatus
)) {
828 Status
= SecurityStatus
;
839 IN BOOLEAN BootPolicy
,
840 IN EFI_HANDLE ParentImageHandle
,
841 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
842 IN VOID
*SourceBuffer OPTIONAL
,
844 OUT EFI_HANDLE
*ImageHandle
850 Loads an EFI image into memory and returns a handle to the image.
854 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
855 and that the boot manager is attempting to load FilePath as a boot selection.
856 ParentImageHandle - The caller's image handle.
857 FilePath - The specific file path from which the image is loaded.
858 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
859 the image to be loaded.
860 SourceSize - The size in bytes of SourceBuffer.
861 ImageHandle - Pointer to the returned image handle that is created when the image
862 is successfully loaded.
866 EFI_SUCCESS - The image was loaded into memory.
867 EFI_NOT_FOUND - The FilePath was not found.
868 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
869 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
870 parsed to locate the proper protocol for loading the file.
871 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
876 PERF_START (NULL
, "LoadImage", NULL
, 0);
878 Status
= CoreLoadImageCommon (
884 (EFI_PHYSICAL_ADDRESS
)NULL
,
888 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
891 PERF_END (NULL
, "LoadImage", NULL
, 0);
900 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
901 IN EFI_HANDLE ParentImageHandle
,
902 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
903 IN VOID
*SourceBuffer OPTIONAL
,
905 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
906 OUT UINTN
*NumberOfPages OPTIONAL
,
907 OUT EFI_HANDLE
*ImageHandle
,
908 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
915 Loads an EFI image into memory and returns a handle to the image with extended parameters.
919 This - Calling context
920 ParentImageHandle - The caller's image handle.
921 FilePath - The specific file path from which the image is loaded.
922 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
923 the image to be loaded.
924 SourceSize - The size in bytes of SourceBuffer.
925 DstBuffer - The buffer to store the image.
926 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
927 For output, specifies the actual space size needed.
928 ImageHandle - Image handle for output.
929 EntryPoint - Image entry point for output.
930 Attribute - The bit mask of attributes to set for the load PE image.
934 EFI_SUCCESS - The image was loaded into memory.
935 EFI_NOT_FOUND - The FilePath was not found.
936 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
937 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
938 parsed to locate the proper protocol for loading the file.
939 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
942 return CoreLoadImageCommon (
959 IN EFI_HANDLE ImageHandle
,
960 OUT UINTN
*ExitDataSize
,
961 OUT CHAR16
**ExitData OPTIONAL
967 Transfer control to a loaded image's entry point.
971 ImageHandle - Handle of image to be started.
973 ExitDataSize - Pointer of the size to ExitData
975 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
976 Unicode string, optionally followed by additional binary data. The string
977 is a description that the caller may use to further indicate the reason for
982 EFI_INVALID_PARAMETER - Invalid parameter
984 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
986 EFI_SUCCESS - Successfully transfer control to the image's entry point.
991 LOADED_IMAGE_PRIVATE_DATA
*Image
;
992 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
993 UINT64 HandleDatabaseKey
;
996 Image
= CoreLoadedImageInfo (ImageHandle
);
997 if (Image
== NULL_HANDLE
|| Image
->Started
) {
998 return EFI_INVALID_PARAMETER
;
1002 // Don't profile Objects or invalid start requests
1004 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1008 // Push the current start image context, and
1009 // link the current image to the head. This is the
1010 // only image that can call Exit()
1012 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1013 LastImage
= mCurrentImage
;
1014 mCurrentImage
= Image
;
1015 Image
->Tpl
= gEfiCurrentTpl
;
1018 // Set long jump for Exit() support
1019 // JumpContext must be aligned on a CPU specific boundary.
1020 // Overallocate the buffer and force the required alignment
1022 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1023 if (Image
->JumpBuffer
== NULL
) {
1024 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1025 return EFI_OUT_OF_RESOURCES
;
1027 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1029 SetJumpFlag
= SetJump (Image
->JumpContext
);
1031 // The initial call to SetJump() must always return 0.
1032 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1036 // Call the image's entry point
1038 Image
->Started
= TRUE
;
1039 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1042 // Add some debug information if the image returned with error.
1043 // This make the user aware and check if the driver image have already released
1044 // all the resource in this situation.
1046 DEBUG_CODE_BEGIN ();
1047 if (EFI_ERROR (Image
->Status
)) {
1048 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1053 // If the image returns, exit it through Exit()
1055 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1059 // Image has completed. Verify the tpl is the same
1061 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1062 CoreRestoreTpl (Image
->Tpl
);
1064 CoreFreePool (Image
->JumpBuffer
);
1067 // Pop the current start image context
1069 mCurrentImage
= LastImage
;
1072 // Go connect any handles that were created or modified while the image executed.
1074 CoreConnectHandlesByKey (HandleDatabaseKey
);
1077 // Handle the image's returned ExitData
1079 DEBUG_CODE_BEGIN ();
1080 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1084 "StartImage: ExitDataSize %d, ExitData %x",
1085 Image
->ExitDataSize
,
1088 if (Image
->ExitData
!= NULL
) {
1089 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1091 DEBUG ((EFI_D_LOAD
, "\n"));
1096 // Return the exit data to the caller
1098 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1099 *ExitDataSize
= Image
->ExitDataSize
;
1100 *ExitData
= Image
->ExitData
;
1103 // Caller doesn't want the exit data, free it
1105 CoreFreePool (Image
->ExitData
);
1106 Image
->ExitData
= NULL
;
1110 // Save the Status because Image will get destroyed if it is unloaded.
1112 Status
= Image
->Status
;
1115 // If the image returned an error, or if the image is an application
1118 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1119 CoreUnloadAndCloseImage (Image
, TRUE
);
1125 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1131 CoreUnloadAndCloseImage (
1132 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1137 Routine Description:
1139 Unloads EFI image from memory.
1144 FreePage - Free allocated pages
1154 EFI_HANDLE
*HandleBuffer
;
1156 EFI_GUID
**ProtocolGuidArray
;
1158 UINTN ProtocolIndex
;
1159 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1160 UINTN OpenInfoCount
;
1161 UINTN OpenInfoIndex
;
1163 if (Image
->Ebc
!= NULL
) {
1165 // If EBC protocol exists we must perform cleanups for this image.
1167 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1171 // Unload image, free Image->ImageContext->ModHandle
1173 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1176 // Free our references to the image handle
1178 if (Image
->Handle
!= NULL_HANDLE
) {
1180 Status
= CoreLocateHandleBuffer (
1187 if (!EFI_ERROR (Status
)) {
1188 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1189 Status
= CoreProtocolsPerHandle (
1190 HandleBuffer
[HandleIndex
],
1194 if (!EFI_ERROR (Status
)) {
1195 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1196 Status
= CoreOpenProtocolInformation (
1197 HandleBuffer
[HandleIndex
],
1198 ProtocolGuidArray
[ProtocolIndex
],
1202 if (!EFI_ERROR (Status
)) {
1203 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1204 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1205 Status
= CoreCloseProtocol (
1206 HandleBuffer
[HandleIndex
],
1207 ProtocolGuidArray
[ProtocolIndex
],
1209 OpenInfo
[OpenInfoIndex
].ControllerHandle
1213 if (OpenInfo
!= NULL
) {
1214 CoreFreePool(OpenInfo
);
1218 if (ProtocolGuidArray
!= NULL
) {
1219 CoreFreePool(ProtocolGuidArray
);
1223 if (HandleBuffer
!= NULL
) {
1224 CoreFreePool (HandleBuffer
);
1228 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1230 Status
= CoreUninstallProtocolInterface (
1232 &gEfiLoadedImageDevicePathProtocolGuid
,
1233 Image
->LoadedImageDevicePath
1236 Status
= CoreUninstallProtocolInterface (
1238 &gEfiLoadedImageProtocolGuid
,
1244 if (Image
->RuntimeData
!= NULL
) {
1245 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1247 // Remove the Image from the Runtime Image list as we are about to Free it!
1249 RemoveEntryList (&Image
->RuntimeData
->Link
);
1251 CoreFreePool (Image
->RuntimeData
);
1255 // Free the Image from memory
1257 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1258 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1262 // Done with the Image structure
1264 if (Image
->Info
.FilePath
!= NULL
) {
1265 CoreFreePool (Image
->Info
.FilePath
);
1268 if (Image
->LoadedImageDevicePath
!= NULL
) {
1269 CoreFreePool (Image
->LoadedImageDevicePath
);
1272 if (Image
->FixupData
!= NULL
) {
1273 CoreFreePool (Image
->FixupData
);
1276 CoreFreePool (Image
);
1284 IN EFI_HANDLE ImageHandle
,
1285 IN EFI_STATUS Status
,
1286 IN UINTN ExitDataSize
,
1287 IN CHAR16
*ExitData OPTIONAL
1291 Routine Description:
1293 Terminates the currently loaded EFI image and returns control to boot services.
1297 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1299 Status - The image's exit code.
1300 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1302 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1303 optionally followed by additional binary data. The string is a
1304 description that the caller may use to further indicate the reason for
1309 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1311 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1313 EFI_ACCESS_DENIED - Should never reach there.
1315 EFI_OUT_OF_RESOURCES - Could not allocate pool
1319 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1323 // Prevent possible reentrance to this function
1324 // for the same ImageHandle
1326 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1328 Image
= CoreLoadedImageInfo (ImageHandle
);
1329 if (Image
== NULL_HANDLE
) {
1330 Status
= EFI_INVALID_PARAMETER
;
1334 if (!Image
->Started
) {
1336 // The image has not been started so just free its resources
1338 CoreUnloadAndCloseImage (Image
, TRUE
);
1339 Status
= EFI_SUCCESS
;
1344 // Image has been started, verify this image can exit
1346 if (Image
!= mCurrentImage
) {
1347 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1348 Status
= EFI_INVALID_PARAMETER
;
1355 Image
->Status
= Status
;
1358 // If there's ExitData info, move it
1360 if (ExitData
!= NULL
) {
1361 Image
->ExitDataSize
= ExitDataSize
;
1362 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1363 if (Image
->ExitData
== NULL
) {
1364 Status
= EFI_OUT_OF_RESOURCES
;
1367 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1370 CoreRestoreTpl (OldTpl
);
1372 // return to StartImage
1374 LongJump (Image
->JumpContext
, (UINTN
)-1);
1377 // If we return from LongJump, then it is an error
1380 Status
= EFI_ACCESS_DENIED
;
1382 CoreRestoreTpl (OldTpl
);
1391 IN EFI_HANDLE ImageHandle
1395 Routine Description:
1401 ImageHandle - Handle that identifies the image to be unloaded.
1405 EFI_SUCCESS - The image has been unloaded.
1406 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1407 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1412 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1416 // Prevent possible reentrance to this function
1417 // for the same ImageHandle
1419 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1421 Image
= CoreLoadedImageInfo (ImageHandle
);
1422 if (Image
== NULL
) {
1424 // The image handle is not valid
1426 Status
= EFI_INVALID_PARAMETER
;
1430 if (Image
->Started
) {
1432 // The image has been started, request it to unload.
1434 Status
= EFI_UNSUPPORTED
;
1435 if (Image
->Info
.Unload
!= NULL
) {
1436 Status
= Image
->Info
.Unload (ImageHandle
);
1441 // This Image hasn't been started, thus it can be unloaded
1443 Status
= EFI_SUCCESS
;
1447 if (!EFI_ERROR (Status
)) {
1449 // if the Image was not started or Unloaded O.K. then clean up
1451 CoreUnloadAndCloseImage (Image
, TRUE
);
1455 CoreRestoreTpl (OldTpl
);
1463 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1464 IN EFI_HANDLE ImageHandle
1468 Routine Description:
1470 Unload the specified image.
1474 This - Indicates the calling context.
1476 ImageHandle - The specified image handle.
1480 EFI_INVALID_PARAMETER - Image handle is NULL.
1482 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1484 EFI_SUCCESS - Image successfully unloaded.
1488 return CoreUnloadImage (ImageHandle
);