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
, // DeviceHandleDevicePath
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
173 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
174 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
175 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
182 Loads, relocates, and invokes a PE/COFF image
186 Pe32Handle - The handle of PE32 image
187 Image - PE image to be loaded
188 DstBuffer - The buffer to store the image
189 EntryPoint - A pointer to the entry point
190 Attribute - The bit mask of attributes to set for the load PE image
194 EFI_SUCCESS - The file was loaded, relocated, and invoked
196 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
198 EFI_INVALID_PARAMETER - Invalid parameter
200 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
205 BOOLEAN DstBufAlocated
;
208 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
210 Image
->ImageContext
.Handle
= Pe32Handle
;
211 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
214 // Get information about the image being loaded
216 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
217 if (EFI_ERROR (Status
)) {
221 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
223 // The PE/COFF loader can support loading image types that can be executed.
224 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
226 return EFI_UNSUPPORTED
;
230 // Set EFI memory type based on ImageType
232 switch (Image
->ImageContext
.ImageType
) {
233 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
234 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
235 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
237 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
238 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
239 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
241 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
242 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
243 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
244 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
247 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
248 return EFI_UNSUPPORTED
;
252 // Allocate memory of the correct memory type aligned on the required image boundry
254 DstBufAlocated
= FALSE
;
255 if (DstBuffer
== 0) {
257 // Allocate Destination Buffer as caller did not pass it in
260 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
261 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
263 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
266 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
269 // If the image relocations have not been stripped, then load at any address.
270 // Otherwise load at the address at which it was linked.
272 // Memory below 1MB should be treated reserved for CSM and there should be
273 // no modules whose preferred load addresses are below 1MB.
275 Status
= EFI_OUT_OF_RESOURCES
;
276 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
277 Status
= CoreAllocatePages (
279 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
280 Image
->NumberOfPages
,
281 &Image
->ImageContext
.ImageAddress
284 if (EFI_ERROR (Status
) && !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
)) {
295 DstBufAlocated
= TRUE
;
298 // Caller provided the destination buffer
301 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
303 // If the image relocations were stripped, and the caller provided a
304 // destination buffer address that does not match the address that the
305 // image is linked at, then the image cannot be loaded.
307 return EFI_INVALID_PARAMETER
;
310 if (Image
->NumberOfPages
!= 0 &&
311 Image
->NumberOfPages
<
312 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
313 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
314 return EFI_BUFFER_TOO_SMALL
;
317 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
318 Image
->ImageContext
.ImageAddress
= DstBuffer
;
321 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
322 Image
->ImageContext
.ImageAddress
=
323 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
324 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
327 // Load the image from the file into the allocated memory
329 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
330 if (EFI_ERROR (Status
)) {
335 // If this is a Runtime Driver, then allocate memory for the FixupData that
336 // is used to relocate the image when SetVirtualAddressMap() is called. The
337 // relocation is done by the Runtime AP.
339 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
340 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
341 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
342 if (Image
->ImageContext
.FixupData
== NULL
) {
343 Status
= EFI_OUT_OF_RESOURCES
;
350 // Relocate the image in memory
352 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
353 if (EFI_ERROR (Status
)) {
358 // Flush the Instruction Cache
360 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
363 // Copy the machine type from the context to the image private data. This
364 // is needed during image unload to know if we should call an EBC protocol
365 // to unload the image.
367 Image
->Machine
= Image
->ImageContext
.Machine
;
370 // Get the image entry point. If it's an EBC image, then call into the
371 // interpreter to create a thunk for the entry point and use the returned
372 // value for the entry point.
374 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
375 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
377 // Locate the EBC interpreter protocol
379 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
380 if (EFI_ERROR(Status
)) {
385 // Register a callback for flushing the instruction cache so that created
386 // thunks can be flushed.
388 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
389 if (EFI_ERROR(Status
)) {
394 // Create a thunk for the image's entry point. This will be the new
395 // entry point for the image.
397 Status
= Image
->Ebc
->CreateThunk (
400 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
401 (VOID
**)&Image
->EntryPoint
403 if (EFI_ERROR(Status
)) {
409 // Fill in the image information for the Loaded Image Protocol
411 Image
->Type
= Image
->ImageContext
.ImageType
;
412 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
413 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
414 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
415 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
416 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
417 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
419 // Make a list off all the RT images so we can let the RT AP know about them.
421 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
422 if (Image
->RuntimeData
== NULL
) {
425 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
426 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
427 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
428 Image
->RuntimeData
->Handle
= Image
->Handle
;
429 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
434 // Fill in the entry point of the image if it is available
436 if (EntryPoint
!= NULL
) {
437 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
441 // Print the load address and the PDB file name if it is available
448 CHAR8 EfiFileName
[256];
450 if (Image
->ImageContext
.Machine
!= IMAGE_FILE_MACHINE_IA64
) {
451 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
452 "Loading driver at 0x%10p EntryPoint=0x%10p ",
453 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
454 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
));
457 // For IPF Image, the real entry point should be print.
459 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
460 "Loading driver at 0x%10p EntryPoint=0x%10p ",
461 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
462 (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)Image
->ImageContext
.EntryPoint
)));
466 // Print Module Name by Pdb file path
468 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
470 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
471 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
472 StartIndex
= Index
+ 1;
476 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
478 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
479 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
480 if (EfiFileName
[Index
] == 0) {
481 EfiFileName
[Index
] = '.';
483 if (EfiFileName
[Index
] == '.') {
484 EfiFileName
[Index
+ 1] = 'e';
485 EfiFileName
[Index
+ 2] = 'f';
486 EfiFileName
[Index
+ 3] = 'i';
487 EfiFileName
[Index
+ 4] = 0;
491 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
493 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
505 if (DstBufAlocated
) {
506 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
509 if (Image
->ImageContext
.FixupData
!= NULL
) {
510 CoreFreePool (Image
->ImageContext
.FixupData
);
517 LOADED_IMAGE_PRIVATE_DATA
*
518 CoreLoadedImageInfo (
519 IN EFI_HANDLE ImageHandle
525 Get the image's private data from its handle.
529 ImageHandle - The image handle
533 Return the image private data associated with ImageHandle.
538 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
539 LOADED_IMAGE_PRIVATE_DATA
*Image
;
541 Status
= CoreHandleProtocol (
543 &gEfiLoadedImageProtocolGuid
,
544 (VOID
**)&LoadedImage
546 if (!EFI_ERROR (Status
)) {
547 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
549 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
558 CoreLoadImageCommon (
559 IN BOOLEAN BootPolicy
,
560 IN EFI_HANDLE ParentImageHandle
,
561 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
562 IN VOID
*SourceBuffer OPTIONAL
,
564 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
565 IN OUT UINTN
*NumberOfPages OPTIONAL
,
566 OUT EFI_HANDLE
*ImageHandle
,
567 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
574 Loads an EFI image into memory and returns a handle to the image.
578 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
579 and that the boot manager is attempting to load FilePath as a boot selection.
580 ParentImageHandle - The caller's image handle.
581 FilePath - The specific file path from which the image is loaded.
582 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
583 the image to be loaded.
584 SourceSize - The size in bytes of SourceBuffer.
585 DstBuffer - The buffer to store the image
586 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
587 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
589 ImageHandle - Pointer to the returned image handle that is created when the image
590 is successfully loaded.
591 EntryPoint - A pointer to the entry point
592 Attribute - The bit mask of attributes to set for the load PE image
596 EFI_SUCCESS - The image was loaded into memory.
597 EFI_NOT_FOUND - The FilePath was not found.
598 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
599 EFI_BUFFER_TOO_SMALL - The buffer is too small
600 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
601 parsed to locate the proper protocol for loading the file.
602 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
605 LOADED_IMAGE_PRIVATE_DATA
*Image
;
606 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
607 IMAGE_FILE_HANDLE FHand
;
609 EFI_STATUS SecurityStatus
;
610 EFI_HANDLE DeviceHandle
;
611 UINT32 AuthenticationStatus
;
612 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
613 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
616 SecurityStatus
= EFI_SUCCESS
;
618 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
622 // The caller must pass in a valid ParentImageHandle
624 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
625 return EFI_INVALID_PARAMETER
;
628 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
629 if (ParentImage
== NULL
) {
630 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
631 return EFI_INVALID_PARAMETER
;
635 // Get simple read access to the source file
637 OriginalFilePath
= FilePath
;
638 Status
= CoreOpenImageFile (
645 &AuthenticationStatus
647 if (Status
== EFI_ALREADY_STARTED
) {
650 } else if (EFI_ERROR (Status
)) {
655 // Verify the Authentication Status through the Security Architectural Protocol
657 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
658 SecurityStatus
= gSecurity
->FileAuthenticationState (
660 AuthenticationStatus
,
663 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
664 Status
= SecurityStatus
;
672 // Allocate a new image structure
674 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
676 return EFI_OUT_OF_RESOURCES
;
680 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
682 FilePath
= OriginalFilePath
;
683 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
684 if (!EFI_ERROR (Status
)) {
685 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
686 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
687 Image
->DeviceHandleDevicePath
= CoreDuplicateDevicePath (HandleFilePath
);
691 // Initialize the fields for an internal driver
693 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
694 Image
->Info
.SystemTable
= gDxeCoreST
;
695 Image
->Info
.DeviceHandle
= DeviceHandle
;
696 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
697 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
698 Image
->Info
.ParentHandle
= ParentImageHandle
;
701 if (NumberOfPages
!= NULL
) {
702 Image
->NumberOfPages
= *NumberOfPages
;
704 Image
->NumberOfPages
= 0 ;
708 // Install the protocol interfaces for this image
709 // don't fire notifications yet
711 Status
= CoreInstallProtocolInterfaceNotify (
713 &gEfiLoadedImageProtocolGuid
,
714 EFI_NATIVE_INTERFACE
,
718 if (EFI_ERROR (Status
)) {
723 // Load the image. If EntryPoint is Null, it will not be set.
725 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
726 if (EFI_ERROR (Status
)) {
727 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
728 if (NumberOfPages
!= NULL
) {
729 *NumberOfPages
= Image
->NumberOfPages
;
736 // Register the image in the Debug Image Info Table if the attribute is set
738 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
739 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
743 //Reinstall loaded image protocol to fire any notifications
745 Status
= CoreReinstallProtocolInterface (
747 &gEfiLoadedImageProtocolGuid
,
751 if (EFI_ERROR (Status
)) {
757 // Success. Return the image handle
759 *ImageHandle
= Image
->Handle
;
763 // All done accessing the source file
764 // If we allocated the Source buffer, free it
766 if (FHand
.FreeBuffer
) {
767 CoreFreePool (FHand
.Source
);
771 // There was an error. If there's an Image structure, free it
773 if (EFI_ERROR (Status
)) {
775 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
778 } else if (EFI_ERROR (SecurityStatus
)) {
779 Status
= SecurityStatus
;
790 IN BOOLEAN BootPolicy
,
791 IN EFI_HANDLE ParentImageHandle
,
792 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
793 IN VOID
*SourceBuffer OPTIONAL
,
795 OUT EFI_HANDLE
*ImageHandle
801 Loads an EFI image into memory and returns a handle to the image.
805 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
806 and that the boot manager is attempting to load FilePath as a boot selection.
807 ParentImageHandle - The caller's image handle.
808 FilePath - The specific file path from which the image is loaded.
809 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
810 the image to be loaded.
811 SourceSize - The size in bytes of SourceBuffer.
812 ImageHandle - Pointer to the returned image handle that is created when the image
813 is successfully loaded.
817 EFI_SUCCESS - The image was loaded into memory.
818 EFI_NOT_FOUND - The FilePath was not found.
819 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
820 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
821 parsed to locate the proper protocol for loading the file.
822 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
827 PERF_START (NULL
, "LoadImage", NULL
, 0);
829 Status
= CoreLoadImageCommon (
835 (EFI_PHYSICAL_ADDRESS
)NULL
,
839 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
842 PERF_END (NULL
, "LoadImage", NULL
, 0);
851 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
852 IN EFI_HANDLE ParentImageHandle
,
853 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
854 IN VOID
*SourceBuffer OPTIONAL
,
856 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
857 OUT UINTN
*NumberOfPages OPTIONAL
,
858 OUT EFI_HANDLE
*ImageHandle
,
859 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
866 Loads an EFI image into memory and returns a handle to the image with extended parameters.
870 This - Calling context
871 ParentImageHandle - The caller's image handle.
872 FilePath - The specific file path from which the image is loaded.
873 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
874 the image to be loaded.
875 SourceSize - The size in bytes of SourceBuffer.
876 DstBuffer - The buffer to store the image.
877 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
878 For output, specifies the actual space size needed.
879 ImageHandle - Image handle for output.
880 EntryPoint - Image entry point for output.
881 Attribute - The bit mask of attributes to set for the load PE image.
885 EFI_SUCCESS - The image was loaded into memory.
886 EFI_NOT_FOUND - The FilePath was not found.
887 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
888 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
889 parsed to locate the proper protocol for loading the file.
890 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
893 return CoreLoadImageCommon (
913 IN EFI_HANDLE ImageHandle
,
914 OUT UINTN
*ExitDataSize
,
915 OUT CHAR16
**ExitData OPTIONAL
921 Transfer control to a loaded image's entry point.
925 ImageHandle - Handle of image to be started.
927 ExitDataSize - Pointer of the size to ExitData
929 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
930 Unicode string, optionally followed by additional binary data. The string
931 is a description that the caller may use to further indicate the reason for
936 EFI_INVALID_PARAMETER - Invalid parameter
938 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
940 EFI_SUCCESS - Successfully transfer control to the image's entry point.
945 LOADED_IMAGE_PRIVATE_DATA
*Image
;
946 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
947 UINT64 HandleDatabaseKey
;
950 Image
= CoreLoadedImageInfo (ImageHandle
);
951 if (Image
== NULL_HANDLE
|| Image
->Started
) {
952 return EFI_INVALID_PARAMETER
;
956 // Don't profile Objects or invalid start requests
958 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
962 // Push the current start image context, and
963 // link the current image to the head. This is the
964 // only image that can call Exit()
966 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
967 LastImage
= mCurrentImage
;
968 mCurrentImage
= Image
;
969 Image
->Tpl
= gEfiCurrentTpl
;
972 // Set long jump for Exit() support
973 // JumpContext must be aligned on a CPU specific boundary.
974 // Overallocate the buffer and force the required alignment
976 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
977 if (Image
->JumpBuffer
== NULL
) {
978 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
979 return EFI_OUT_OF_RESOURCES
;
981 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
983 SetJumpFlag
= SetJump (Image
->JumpContext
);
985 // The initial call to SetJump() must always return 0.
986 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
990 // Call the image's entry point
992 Image
->Started
= TRUE
;
993 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
996 // Add some debug information if the image returned with error.
997 // This make the user aware and check if the driver image have already released
998 // all the resource in this situation.
1000 DEBUG_CODE_BEGIN ();
1001 if (EFI_ERROR (Image
->Status
)) {
1002 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1007 // If the image returns, exit it through Exit()
1009 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1013 // Image has completed. Verify the tpl is the same
1015 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1016 CoreRestoreTpl (Image
->Tpl
);
1018 CoreFreePool (Image
->JumpBuffer
);
1021 // Pop the current start image context
1023 mCurrentImage
= LastImage
;
1026 // Go connect any handles that were created or modified while the image executed.
1028 CoreConnectHandlesByKey (HandleDatabaseKey
);
1031 // Handle the image's returned ExitData
1033 DEBUG_CODE_BEGIN ();
1034 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1038 "StartImage: ExitDataSize %d, ExitData %x",
1039 Image
->ExitDataSize
,
1042 if (Image
->ExitData
!= NULL
) {
1043 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1045 DEBUG ((EFI_D_LOAD
, "\n"));
1050 // Return the exit data to the caller
1052 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1053 *ExitDataSize
= Image
->ExitDataSize
;
1054 *ExitData
= Image
->ExitData
;
1057 // Caller doesn't want the exit data, free it
1059 CoreFreePool (Image
->ExitData
);
1060 Image
->ExitData
= NULL
;
1064 // Save the Status because Image will get destroyed if it is unloaded.
1066 Status
= Image
->Status
;
1069 // If the image returned an error, or if the image is an application
1072 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1073 CoreUnloadAndCloseImage (Image
, TRUE
);
1079 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1085 CoreUnloadAndCloseImage (
1086 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1091 Routine Description:
1093 Unloads EFI image from memory.
1098 FreePage - Free allocated pages
1108 EFI_HANDLE
*HandleBuffer
;
1110 EFI_GUID
**ProtocolGuidArray
;
1112 UINTN ProtocolIndex
;
1113 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1114 UINTN OpenInfoCount
;
1115 UINTN OpenInfoIndex
;
1117 if (Image
->Ebc
!= NULL
) {
1119 // If EBC protocol exists we must perform cleanups for this image.
1121 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1125 // Unload image, free Image->ImageContext->ModHandle
1127 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1130 // Free our references to the image handle
1132 if (Image
->Handle
!= NULL_HANDLE
) {
1134 Status
= CoreLocateHandleBuffer (
1141 if (!EFI_ERROR (Status
)) {
1142 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1143 Status
= CoreProtocolsPerHandle (
1144 HandleBuffer
[HandleIndex
],
1148 if (!EFI_ERROR (Status
)) {
1149 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1150 Status
= CoreOpenProtocolInformation (
1151 HandleBuffer
[HandleIndex
],
1152 ProtocolGuidArray
[ProtocolIndex
],
1156 if (!EFI_ERROR (Status
)) {
1157 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1158 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1159 Status
= CoreCloseProtocol (
1160 HandleBuffer
[HandleIndex
],
1161 ProtocolGuidArray
[ProtocolIndex
],
1163 OpenInfo
[OpenInfoIndex
].ControllerHandle
1167 if (OpenInfo
!= NULL
) {
1168 CoreFreePool(OpenInfo
);
1172 if (ProtocolGuidArray
!= NULL
) {
1173 CoreFreePool(ProtocolGuidArray
);
1177 if (HandleBuffer
!= NULL
) {
1178 CoreFreePool (HandleBuffer
);
1182 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1184 Status
= CoreUninstallProtocolInterface (
1186 &gEfiLoadedImageProtocolGuid
,
1191 if (Image
->RuntimeData
!= NULL
) {
1192 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1194 // Remove the Image from the Runtime Image list as we are about to Free it!
1196 RemoveEntryList (&Image
->RuntimeData
->Link
);
1198 CoreFreePool (Image
->RuntimeData
);
1202 // Free the Image from memory
1204 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1205 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1209 // Done with the Image structure
1211 if (Image
->Info
.FilePath
!= NULL
) {
1212 CoreFreePool (Image
->Info
.FilePath
);
1215 if (Image
->DeviceHandleDevicePath
!= NULL
) {
1216 CoreFreePool (Image
->DeviceHandleDevicePath
);
1219 if (Image
->FixupData
!= NULL
) {
1220 CoreFreePool (Image
->FixupData
);
1223 CoreFreePool (Image
);
1231 IN EFI_HANDLE ImageHandle
,
1232 IN EFI_STATUS Status
,
1233 IN UINTN ExitDataSize
,
1234 IN CHAR16
*ExitData OPTIONAL
1238 Routine Description:
1240 Terminates the currently loaded EFI image and returns control to boot services.
1244 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1246 Status - The image's exit code.
1247 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1249 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1250 optionally followed by additional binary data. The string is a
1251 description that the caller may use to further indicate the reason for
1256 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1258 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1260 EFI_ACCESS_DENIED - Should never reach there.
1262 EFI_OUT_OF_RESOURCES - Could not allocate pool
1266 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1270 // Prevent possible reentrance to this function
1271 // for the same ImageHandle
1273 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1275 Image
= CoreLoadedImageInfo (ImageHandle
);
1276 if (Image
== NULL_HANDLE
) {
1277 Status
= EFI_INVALID_PARAMETER
;
1281 if (!Image
->Started
) {
1283 // The image has not been started so just free its resources
1285 CoreUnloadAndCloseImage (Image
, TRUE
);
1286 Status
= EFI_SUCCESS
;
1291 // Image has been started, verify this image can exit
1293 if (Image
!= mCurrentImage
) {
1294 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1295 Status
= EFI_INVALID_PARAMETER
;
1302 Image
->Status
= Status
;
1305 // If there's ExitData info, move it
1307 if (ExitData
!= NULL
) {
1308 Image
->ExitDataSize
= ExitDataSize
;
1309 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1310 if (Image
->ExitData
== NULL
) {
1311 Status
= EFI_OUT_OF_RESOURCES
;
1314 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1317 CoreRestoreTpl (OldTpl
);
1319 // return to StartImage
1321 LongJump (Image
->JumpContext
, (UINTN
)-1);
1324 // If we return from LongJump, then it is an error
1327 Status
= EFI_ACCESS_DENIED
;
1329 CoreRestoreTpl (OldTpl
);
1338 IN EFI_HANDLE ImageHandle
1342 Routine Description:
1348 ImageHandle - Handle that identifies the image to be unloaded.
1352 EFI_SUCCESS - The image has been unloaded.
1353 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1354 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1359 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1363 // Prevent possible reentrance to this function
1364 // for the same ImageHandle
1366 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1368 Image
= CoreLoadedImageInfo (ImageHandle
);
1369 if (Image
== NULL
) {
1371 // The image handle is not valid
1373 Status
= EFI_INVALID_PARAMETER
;
1377 if (Image
->Started
) {
1379 // The image has been started, request it to unload.
1381 Status
= EFI_UNSUPPORTED
;
1382 if (Image
->Info
.Unload
!= NULL
) {
1383 Status
= Image
->Info
.Unload (ImageHandle
);
1388 // This Image hasn't been started, thus it can be unloaded
1390 Status
= EFI_SUCCESS
;
1394 if (!EFI_ERROR (Status
)) {
1396 // if the Image was not started or Unloaded O.K. then clean up
1398 CoreUnloadAndCloseImage (Image
, TRUE
);
1402 CoreRestoreTpl (OldTpl
);
1410 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1411 IN EFI_HANDLE ImageHandle
1415 Routine Description:
1417 Unload the specified image.
1421 This - Indicates the calling context.
1423 ImageHandle - The specified image handle.
1427 EFI_INVALID_PARAMETER - Image handle is NULL.
1429 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1431 EFI_SUCCESS - Image successfully unloaded.
1435 return CoreUnloadImage (ImageHandle
);