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
;
211 IMAGE_FILE_HANDLE
*FHandle
;
214 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
216 Image
->ImageContext
.Handle
= Pe32Handle
;
217 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
220 // Get information about the image being loaded
222 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
223 if (EFI_ERROR (Status
)) {
227 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
228 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
230 // The PE/COFF loader can support loading image types that can be executed.
231 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
233 return EFI_UNSUPPORTED
;
238 // Set EFI memory type based on ImageType
240 switch (Image
->ImageContext
.ImageType
) {
241 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
242 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
243 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
245 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
246 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
247 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
249 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
250 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
251 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
252 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
255 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
256 return EFI_UNSUPPORTED
;
259 // Get the image base address in the original PeImage.
261 LinkTimeBase
= (UINTN
) Image
->ImageContext
.ImageAddress
;
264 // Allocate memory of the correct memory type aligned on the required image boundry
266 DstBufAlocated
= FALSE
;
267 if (DstBuffer
== 0) {
269 // Allocate Destination Buffer as caller did not pass it in
272 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
273 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
275 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
278 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
281 // If the image relocations have not been stripped, then load at any address.
282 // Otherwise load at the address at which it was linked.
284 // Memory below 1MB should be treated reserved for CSM and there should be
285 // no modules whose preferred load addresses are below 1MB.
287 Status
= EFI_OUT_OF_RESOURCES
;
288 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
289 Status
= CoreAllocatePages (
291 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
292 Image
->NumberOfPages
,
293 &Image
->ImageContext
.ImageAddress
296 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
297 Status
= CoreAllocatePages (
299 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
300 Image
->NumberOfPages
,
301 &Image
->ImageContext
.ImageAddress
304 if (EFI_ERROR (Status
)) {
307 DstBufAlocated
= TRUE
;
310 // Caller provided the destination buffer
313 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
315 // If the image relocations were stripped, and the caller provided a
316 // destination buffer address that does not match the address that the
317 // image is linked at, then the image cannot be loaded.
319 return EFI_INVALID_PARAMETER
;
322 if (Image
->NumberOfPages
!= 0 &&
323 Image
->NumberOfPages
<
324 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
325 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
326 return EFI_BUFFER_TOO_SMALL
;
329 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
330 Image
->ImageContext
.ImageAddress
= DstBuffer
;
333 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
334 Image
->ImageContext
.ImageAddress
=
335 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
336 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
339 // Load the image from the file into the allocated memory
341 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
342 if (EFI_ERROR (Status
)) {
347 // If this is a Runtime Driver, then allocate memory for the FixupData that
348 // is used to relocate the image when SetVirtualAddressMap() is called. The
349 // relocation is done by the Runtime AP.
351 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
352 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
353 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
354 if (Image
->ImageContext
.FixupData
== NULL
) {
355 Status
= EFI_OUT_OF_RESOURCES
;
362 // Measure the image before applying fixup
364 Status
= CoreLocateProtocol (
365 &gEfiTcgPlatformProtocolGuid
,
367 (VOID
**) &TcgPlatformProtocol
369 if (!EFI_ERROR (Status
)) {
370 FHandle
= (IMAGE_FILE_HANDLE
*) Image
->ImageContext
.Handle
;
371 Status
= TcgPlatformProtocol
->MeasurePeImage (
373 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FHandle
->Source
,
376 Image
->ImageContext
.ImageType
,
377 Image
->Info
.DeviceHandle
,
381 ASSERT_EFI_ERROR (Status
);
385 // Relocate the image in memory
387 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
388 if (EFI_ERROR (Status
)) {
393 // Flush the Instruction Cache
395 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
398 // Copy the machine type from the context to the image private data. This
399 // is needed during image unload to know if we should call an EBC protocol
400 // to unload the image.
402 Image
->Machine
= Image
->ImageContext
.Machine
;
405 // Get the image entry point. If it's an EBC image, then call into the
406 // interpreter to create a thunk for the entry point and use the returned
407 // value for the entry point.
409 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
410 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
412 // Locate the EBC interpreter protocol
414 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
415 if (EFI_ERROR(Status
)) {
420 // Register a callback for flushing the instruction cache so that created
421 // thunks can be flushed.
423 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
424 if (EFI_ERROR(Status
)) {
429 // Create a thunk for the image's entry point. This will be the new
430 // entry point for the image.
432 Status
= Image
->Ebc
->CreateThunk (
435 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
436 (VOID
**)&Image
->EntryPoint
438 if (EFI_ERROR(Status
)) {
444 // Fill in the image information for the Loaded Image Protocol
446 Image
->Type
= Image
->ImageContext
.ImageType
;
447 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
448 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
449 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
450 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
451 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
452 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
454 // Make a list off all the RT images so we can let the RT AP know about them.
456 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
457 if (Image
->RuntimeData
== NULL
) {
460 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
461 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
462 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
463 Image
->RuntimeData
->Handle
= Image
->Handle
;
464 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
469 // Fill in the entry point of the image if it is available
471 if (EntryPoint
!= NULL
) {
472 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
476 // Print the load address and the PDB file name if it is available
483 CHAR8 EfiFileName
[256];
485 if (Image
->ImageContext
.Machine
!= IMAGE_FILE_MACHINE_IA64
) {
486 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
487 "Loading driver at 0x%10p EntryPoint=0x%10p ",
488 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
489 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
));
492 // For IPF Image, the real entry point should be print.
494 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
495 "Loading driver at 0x%10p EntryPoint=0x%10p ",
496 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
497 (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)Image
->ImageContext
.EntryPoint
)));
501 // Print Module Name by Pdb file path
503 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
505 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
506 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
507 StartIndex
= Index
+ 1;
511 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
513 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
514 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
515 if (EfiFileName
[Index
] == 0) {
516 EfiFileName
[Index
] = '.';
518 if (EfiFileName
[Index
] == '.') {
519 EfiFileName
[Index
+ 1] = 'e';
520 EfiFileName
[Index
+ 2] = 'f';
521 EfiFileName
[Index
+ 3] = 'i';
522 EfiFileName
[Index
+ 4] = 0;
526 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
528 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
540 if (DstBufAlocated
) {
541 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
544 if (Image
->ImageContext
.FixupData
!= NULL
) {
545 CoreFreePool (Image
->ImageContext
.FixupData
);
552 LOADED_IMAGE_PRIVATE_DATA
*
553 CoreLoadedImageInfo (
554 IN EFI_HANDLE ImageHandle
560 Get the image's private data from its handle.
564 ImageHandle - The image handle
568 Return the image private data associated with ImageHandle.
573 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
574 LOADED_IMAGE_PRIVATE_DATA
*Image
;
576 Status
= CoreHandleProtocol (
578 &gEfiLoadedImageProtocolGuid
,
579 (VOID
**)&LoadedImage
581 if (!EFI_ERROR (Status
)) {
582 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
584 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
593 CoreLoadImageCommon (
594 IN BOOLEAN BootPolicy
,
595 IN EFI_HANDLE ParentImageHandle
,
596 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
597 IN VOID
*SourceBuffer OPTIONAL
,
599 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
600 IN OUT UINTN
*NumberOfPages OPTIONAL
,
601 OUT EFI_HANDLE
*ImageHandle
,
602 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
609 Loads an EFI image into memory and returns a handle to the image.
613 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
614 and that the boot manager is attempting to load FilePath as a boot selection.
615 ParentImageHandle - The caller's image handle.
616 FilePath - The specific file path from which the image is loaded.
617 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
618 the image to be loaded.
619 SourceSize - The size in bytes of SourceBuffer.
620 DstBuffer - The buffer to store the image
621 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
622 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
624 ImageHandle - Pointer to the returned image handle that is created when the image
625 is successfully loaded.
626 EntryPoint - A pointer to the entry point
627 Attribute - The bit mask of attributes to set for the load PE image
631 EFI_SUCCESS - The image was loaded into memory.
632 EFI_NOT_FOUND - The FilePath was not found.
633 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
634 EFI_BUFFER_TOO_SMALL - The buffer is too small
635 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
636 parsed to locate the proper protocol for loading the file.
637 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
640 LOADED_IMAGE_PRIVATE_DATA
*Image
;
641 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
642 IMAGE_FILE_HANDLE FHand
;
644 EFI_STATUS SecurityStatus
;
645 EFI_HANDLE DeviceHandle
;
646 UINT32 AuthenticationStatus
;
647 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
648 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
651 SecurityStatus
= EFI_SUCCESS
;
653 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
657 // The caller must pass in a valid ParentImageHandle
659 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
660 return EFI_INVALID_PARAMETER
;
663 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
664 if (ParentImage
== NULL
) {
665 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
666 return EFI_INVALID_PARAMETER
;
670 // Get simple read access to the source file
672 OriginalFilePath
= FilePath
;
673 Status
= CoreOpenImageFile (
680 &AuthenticationStatus
682 if (Status
== EFI_ALREADY_STARTED
) {
685 } else if (EFI_ERROR (Status
)) {
690 // Verify the Authentication Status through the Security Architectural Protocol
692 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
693 SecurityStatus
= gSecurity
->FileAuthenticationState (
695 AuthenticationStatus
,
698 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
699 Status
= SecurityStatus
;
707 // Allocate a new image structure
709 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
711 return EFI_OUT_OF_RESOURCES
;
715 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
717 FilePath
= OriginalFilePath
;
718 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
719 if (!EFI_ERROR (Status
)) {
720 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
721 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
725 // Initialize the fields for an internal driver
727 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
728 Image
->Info
.SystemTable
= gDxeCoreST
;
729 Image
->Info
.DeviceHandle
= DeviceHandle
;
730 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
731 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
732 Image
->Info
.ParentHandle
= ParentImageHandle
;
735 if (NumberOfPages
!= NULL
) {
736 Image
->NumberOfPages
= *NumberOfPages
;
738 Image
->NumberOfPages
= 0 ;
742 // Install the protocol interfaces for this image
743 // don't fire notifications yet
745 Status
= CoreInstallProtocolInterfaceNotify (
747 &gEfiLoadedImageProtocolGuid
,
748 EFI_NATIVE_INTERFACE
,
752 if (EFI_ERROR (Status
)) {
757 // Load the image. If EntryPoint is Null, it will not be set.
759 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
760 if (EFI_ERROR (Status
)) {
761 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
762 if (NumberOfPages
!= NULL
) {
763 *NumberOfPages
= Image
->NumberOfPages
;
770 // Register the image in the Debug Image Info Table if the attribute is set
772 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
773 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
777 //Reinstall loaded image protocol to fire any notifications
779 Status
= CoreReinstallProtocolInterface (
781 &gEfiLoadedImageProtocolGuid
,
785 if (EFI_ERROR (Status
)) {
790 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
791 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
793 if (OriginalFilePath
!= NULL
) {
794 Image
->LoadedImageDevicePath
= CoreDuplicateDevicePath (OriginalFilePath
);
798 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
800 Status
= CoreInstallProtocolInterface (
802 &gEfiLoadedImageDevicePathProtocolGuid
,
803 EFI_NATIVE_INTERFACE
,
804 Image
->LoadedImageDevicePath
806 if (EFI_ERROR (Status
)) {
811 // Success. Return the image handle
813 *ImageHandle
= Image
->Handle
;
817 // All done accessing the source file
818 // If we allocated the Source buffer, free it
820 if (FHand
.FreeBuffer
) {
821 CoreFreePool (FHand
.Source
);
825 // There was an error. If there's an Image structure, free it
827 if (EFI_ERROR (Status
)) {
829 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
832 } else if (EFI_ERROR (SecurityStatus
)) {
833 Status
= SecurityStatus
;
844 IN BOOLEAN BootPolicy
,
845 IN EFI_HANDLE ParentImageHandle
,
846 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
847 IN VOID
*SourceBuffer OPTIONAL
,
849 OUT EFI_HANDLE
*ImageHandle
855 Loads an EFI image into memory and returns a handle to the image.
859 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
860 and that the boot manager is attempting to load FilePath as a boot selection.
861 ParentImageHandle - The caller's image handle.
862 FilePath - The specific file path from which the image is loaded.
863 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
864 the image to be loaded.
865 SourceSize - The size in bytes of SourceBuffer.
866 ImageHandle - Pointer to the returned image handle that is created when the image
867 is successfully loaded.
871 EFI_SUCCESS - The image was loaded into memory.
872 EFI_NOT_FOUND - The FilePath was not found.
873 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
874 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
875 parsed to locate the proper protocol for loading the file.
876 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
881 PERF_START (NULL
, "LoadImage", NULL
, 0);
883 Status
= CoreLoadImageCommon (
889 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
893 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
896 PERF_END (NULL
, "LoadImage", NULL
, 0);
905 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
906 IN EFI_HANDLE ParentImageHandle
,
907 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
908 IN VOID
*SourceBuffer OPTIONAL
,
910 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
911 OUT UINTN
*NumberOfPages OPTIONAL
,
912 OUT EFI_HANDLE
*ImageHandle
,
913 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
920 Loads an EFI image into memory and returns a handle to the image with extended parameters.
924 This - Calling context
925 ParentImageHandle - The caller's image handle.
926 FilePath - The specific file path from which the image is loaded.
927 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
928 the image to be loaded.
929 SourceSize - The size in bytes of SourceBuffer.
930 DstBuffer - The buffer to store the image.
931 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
932 For output, specifies the actual space size needed.
933 ImageHandle - Image handle for output.
934 EntryPoint - Image entry point for output.
935 Attribute - The bit mask of attributes to set for the load PE image.
939 EFI_SUCCESS - The image was loaded into memory.
940 EFI_NOT_FOUND - The FilePath was not found.
941 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
942 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
943 parsed to locate the proper protocol for loading the file.
944 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
947 return CoreLoadImageCommon (
964 IN EFI_HANDLE ImageHandle
,
965 OUT UINTN
*ExitDataSize
,
966 OUT CHAR16
**ExitData OPTIONAL
972 Transfer control to a loaded image's entry point.
976 ImageHandle - Handle of image to be started.
978 ExitDataSize - Pointer of the size to ExitData
980 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
981 Unicode string, optionally followed by additional binary data. The string
982 is a description that the caller may use to further indicate the reason for
987 EFI_INVALID_PARAMETER - Invalid parameter
989 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
991 EFI_SUCCESS - Successfully transfer control to the image's entry point.
996 LOADED_IMAGE_PRIVATE_DATA
*Image
;
997 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
998 UINT64 HandleDatabaseKey
;
1001 Image
= CoreLoadedImageInfo (ImageHandle
);
1002 if (Image
== NULL_HANDLE
|| Image
->Started
) {
1003 return EFI_INVALID_PARAMETER
;
1007 // Don't profile Objects or invalid start requests
1009 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1013 // Push the current start image context, and
1014 // link the current image to the head. This is the
1015 // only image that can call Exit()
1017 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1018 LastImage
= mCurrentImage
;
1019 mCurrentImage
= Image
;
1020 Image
->Tpl
= gEfiCurrentTpl
;
1023 // Set long jump for Exit() support
1024 // JumpContext must be aligned on a CPU specific boundary.
1025 // Overallocate the buffer and force the required alignment
1027 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1028 if (Image
->JumpBuffer
== NULL
) {
1029 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1030 return EFI_OUT_OF_RESOURCES
;
1032 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1034 SetJumpFlag
= SetJump (Image
->JumpContext
);
1036 // The initial call to SetJump() must always return 0.
1037 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1041 // Call the image's entry point
1043 Image
->Started
= TRUE
;
1044 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1047 // Add some debug information if the image returned with error.
1048 // This make the user aware and check if the driver image have already released
1049 // all the resource in this situation.
1051 DEBUG_CODE_BEGIN ();
1052 if (EFI_ERROR (Image
->Status
)) {
1053 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1058 // If the image returns, exit it through Exit()
1060 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1064 // Image has completed. Verify the tpl is the same
1066 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1067 CoreRestoreTpl (Image
->Tpl
);
1069 CoreFreePool (Image
->JumpBuffer
);
1072 // Pop the current start image context
1074 mCurrentImage
= LastImage
;
1077 // Go connect any handles that were created or modified while the image executed.
1079 CoreConnectHandlesByKey (HandleDatabaseKey
);
1082 // Handle the image's returned ExitData
1084 DEBUG_CODE_BEGIN ();
1085 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1089 "StartImage: ExitDataSize %d, ExitData %x",
1090 Image
->ExitDataSize
,
1093 if (Image
->ExitData
!= NULL
) {
1094 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1096 DEBUG ((EFI_D_LOAD
, "\n"));
1101 // Return the exit data to the caller
1103 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1104 *ExitDataSize
= Image
->ExitDataSize
;
1105 *ExitData
= Image
->ExitData
;
1108 // Caller doesn't want the exit data, free it
1110 CoreFreePool (Image
->ExitData
);
1111 Image
->ExitData
= NULL
;
1115 // Save the Status because Image will get destroyed if it is unloaded.
1117 Status
= Image
->Status
;
1120 // If the image returned an error, or if the image is an application
1123 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1124 CoreUnloadAndCloseImage (Image
, TRUE
);
1130 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1136 CoreUnloadAndCloseImage (
1137 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1142 Routine Description:
1144 Unloads EFI image from memory.
1149 FreePage - Free allocated pages
1159 EFI_HANDLE
*HandleBuffer
;
1161 EFI_GUID
**ProtocolGuidArray
;
1163 UINTN ProtocolIndex
;
1164 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1165 UINTN OpenInfoCount
;
1166 UINTN OpenInfoIndex
;
1168 if (Image
->Ebc
!= NULL
) {
1170 // If EBC protocol exists we must perform cleanups for this image.
1172 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1176 // Unload image, free Image->ImageContext->ModHandle
1178 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1181 // Free our references to the image handle
1183 if (Image
->Handle
!= NULL_HANDLE
) {
1185 Status
= CoreLocateHandleBuffer (
1192 if (!EFI_ERROR (Status
)) {
1193 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1194 Status
= CoreProtocolsPerHandle (
1195 HandleBuffer
[HandleIndex
],
1199 if (!EFI_ERROR (Status
)) {
1200 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1201 Status
= CoreOpenProtocolInformation (
1202 HandleBuffer
[HandleIndex
],
1203 ProtocolGuidArray
[ProtocolIndex
],
1207 if (!EFI_ERROR (Status
)) {
1208 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1209 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1210 Status
= CoreCloseProtocol (
1211 HandleBuffer
[HandleIndex
],
1212 ProtocolGuidArray
[ProtocolIndex
],
1214 OpenInfo
[OpenInfoIndex
].ControllerHandle
1218 if (OpenInfo
!= NULL
) {
1219 CoreFreePool(OpenInfo
);
1223 if (ProtocolGuidArray
!= NULL
) {
1224 CoreFreePool(ProtocolGuidArray
);
1228 if (HandleBuffer
!= NULL
) {
1229 CoreFreePool (HandleBuffer
);
1233 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1235 Status
= CoreUninstallProtocolInterface (
1237 &gEfiLoadedImageDevicePathProtocolGuid
,
1238 Image
->LoadedImageDevicePath
1241 Status
= CoreUninstallProtocolInterface (
1243 &gEfiLoadedImageProtocolGuid
,
1249 if (Image
->RuntimeData
!= NULL
) {
1250 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1252 // Remove the Image from the Runtime Image list as we are about to Free it!
1254 RemoveEntryList (&Image
->RuntimeData
->Link
);
1256 CoreFreePool (Image
->RuntimeData
);
1260 // Free the Image from memory
1262 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1263 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1267 // Done with the Image structure
1269 if (Image
->Info
.FilePath
!= NULL
) {
1270 CoreFreePool (Image
->Info
.FilePath
);
1273 if (Image
->LoadedImageDevicePath
!= NULL
) {
1274 CoreFreePool (Image
->LoadedImageDevicePath
);
1277 if (Image
->FixupData
!= NULL
) {
1278 CoreFreePool (Image
->FixupData
);
1281 CoreFreePool (Image
);
1289 IN EFI_HANDLE ImageHandle
,
1290 IN EFI_STATUS Status
,
1291 IN UINTN ExitDataSize
,
1292 IN CHAR16
*ExitData OPTIONAL
1296 Routine Description:
1298 Terminates the currently loaded EFI image and returns control to boot services.
1302 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1304 Status - The image's exit code.
1305 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1307 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1308 optionally followed by additional binary data. The string is a
1309 description that the caller may use to further indicate the reason for
1314 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1316 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1318 EFI_ACCESS_DENIED - Should never reach there.
1320 EFI_OUT_OF_RESOURCES - Could not allocate pool
1324 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1328 // Prevent possible reentrance to this function
1329 // for the same ImageHandle
1331 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1333 Image
= CoreLoadedImageInfo (ImageHandle
);
1334 if (Image
== NULL_HANDLE
) {
1335 Status
= EFI_INVALID_PARAMETER
;
1339 if (!Image
->Started
) {
1341 // The image has not been started so just free its resources
1343 CoreUnloadAndCloseImage (Image
, TRUE
);
1344 Status
= EFI_SUCCESS
;
1349 // Image has been started, verify this image can exit
1351 if (Image
!= mCurrentImage
) {
1352 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1353 Status
= EFI_INVALID_PARAMETER
;
1360 Image
->Status
= Status
;
1363 // If there's ExitData info, move it
1365 if (ExitData
!= NULL
) {
1366 Image
->ExitDataSize
= ExitDataSize
;
1367 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1368 if (Image
->ExitData
== NULL
) {
1369 Status
= EFI_OUT_OF_RESOURCES
;
1372 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1375 CoreRestoreTpl (OldTpl
);
1377 // return to StartImage
1379 LongJump (Image
->JumpContext
, (UINTN
)-1);
1382 // If we return from LongJump, then it is an error
1385 Status
= EFI_ACCESS_DENIED
;
1387 CoreRestoreTpl (OldTpl
);
1396 IN EFI_HANDLE ImageHandle
1400 Routine Description:
1406 ImageHandle - Handle that identifies the image to be unloaded.
1410 EFI_SUCCESS - The image has been unloaded.
1411 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1412 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1417 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1421 // Prevent possible reentrance to this function
1422 // for the same ImageHandle
1424 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1426 Image
= CoreLoadedImageInfo (ImageHandle
);
1427 if (Image
== NULL
) {
1429 // The image handle is not valid
1431 Status
= EFI_INVALID_PARAMETER
;
1435 if (Image
->Started
) {
1437 // The image has been started, request it to unload.
1439 Status
= EFI_UNSUPPORTED
;
1440 if (Image
->Info
.Unload
!= NULL
) {
1441 Status
= Image
->Info
.Unload (ImageHandle
);
1446 // This Image hasn't been started, thus it can be unloaded
1448 Status
= EFI_SUCCESS
;
1452 if (!EFI_ERROR (Status
)) {
1454 // if the Image was not started or Unloaded O.K. then clean up
1456 CoreUnloadAndCloseImage (Image
, TRUE
);
1460 CoreRestoreTpl (OldTpl
);
1468 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1469 IN EFI_HANDLE ImageHandle
1473 Routine Description:
1475 Unload the specified image.
1479 This - Indicates the calling context.
1481 ImageHandle - The specified image handle.
1485 EFI_INVALID_PARAMETER - Image handle is NULL.
1487 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1489 EFI_SUCCESS - Image successfully unloaded.
1493 return CoreUnloadImage (ImageHandle
);