2 Core image handling services to load and unload PeImage.
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
23 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
24 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
34 // This code is needed to build the Image handle for the DXE Core
36 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
37 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
39 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
40 TRUE
, // If entrypoint has been called
43 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
44 NULL
, // Parent handle
45 NULL
, // System handle
47 NULL
, // Device handle
56 EfiBootServicesCode
, // ImageCodeType
57 EfiBootServicesData
// ImageDataType
59 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
63 EFI_SUCCESS
, // Status
71 NULL
// LoadedImageDevicePath
74 // The field is define for Loading modules at fixed address feature to tracker the PEI code
75 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
78 GLOBAL_REMOVE_IF_UNREFERENCED UINT64
*mDxeCodeMemoryRangeUsageBitMap
=NULL
;
82 CHAR16
*MachineTypeName
;
86 // EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.
88 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo
[] = {
89 {EFI_IMAGE_MACHINE_IA32
, L
"IA32"},
90 {EFI_IMAGE_MACHINE_IA64
, L
"IA64"},
91 {EFI_IMAGE_MACHINE_X64
, L
"X64"},
92 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
, L
"ARM"}
95 UINT16 mDxeCoreImageMachineType
= 0;
98 Return machine type name.
100 @param MachineType The machine type
102 @return machine type name
111 for (Index
= 0; Index
< sizeof(mMachineTypeInfo
)/sizeof(mMachineTypeInfo
[0]); Index
++) {
112 if (mMachineTypeInfo
[Index
].MachineType
== MachineType
) {
113 return mMachineTypeInfo
[Index
].MachineTypeName
;
121 Add the Image Services to EFI Boot Services Table and install the protocol
122 interfaces for this image.
124 @param HobStart The HOB to initialize
130 CoreInitializeImageServices (
135 LOADED_IMAGE_PRIVATE_DATA
*Image
;
136 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
137 UINT64 DxeCoreImageLength
;
138 VOID
*DxeCoreEntryPoint
;
139 EFI_PEI_HOB_POINTERS DxeCoreHob
;
142 // Searching for image hob
144 DxeCoreHob
.Raw
= HobStart
;
145 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
146 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
152 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
154 ASSERT (DxeCoreHob
.Raw
!= NULL
);
156 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
157 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
158 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
159 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
162 // Initialize the fields for an internal driver
164 Image
= &mCorePrivateImage
;
166 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
167 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
168 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
169 Image
->Tpl
= gEfiCurrentTpl
;
170 Image
->Info
.SystemTable
= gDxeCoreST
;
171 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
172 Image
->Info
.ImageSize
= DxeCoreImageLength
;
175 // Install the protocol interfaces for this image
177 Status
= CoreInstallProtocolInterface (
179 &gEfiLoadedImageProtocolGuid
,
180 EFI_NATIVE_INTERFACE
,
183 ASSERT_EFI_ERROR (Status
);
185 mCurrentImage
= Image
;
188 // Fill in DXE globals
190 mDxeCoreImageMachineType
= PeCoffLoaderGetMachineType (Image
->Info
.ImageBase
);
191 gDxeCoreImageHandle
= Image
->Handle
;
192 gDxeCoreLoadedImage
= &Image
->Info
;
194 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
196 // Export DXE Core PE Loader functionality for backward compatibility.
198 Status
= CoreInstallProtocolInterface (
199 &mLoadPe32PrivateData
.Handle
,
200 &gEfiLoadPeImageProtocolGuid
,
201 EFI_NATIVE_INTERFACE
,
202 &mLoadPe32PrivateData
.Pe32Image
210 Read image file (specified by UserHandle) into user specified buffer with specified offset
213 @param UserHandle Image file handle
214 @param Offset Offset to the source file
215 @param ReadSize For input, pointer of size to read; For output,
216 pointer of size actually read.
217 @param Buffer Buffer to write into
219 @retval EFI_SUCCESS Successfully read the specified part of file
228 IN OUT UINTN
*ReadSize
,
233 IMAGE_FILE_HANDLE
*FHand
;
235 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
236 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
239 // Move data from our local copy of the file
241 EndPosition
= Offset
+ *ReadSize
;
242 if (EndPosition
> FHand
->SourceSize
) {
243 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
245 if (Offset
>= FHand
->SourceSize
) {
249 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
253 To check memory usage bit map arry to figure out if the memory range the image will be loaded in is available or not. If
254 memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.
255 The function is only invoked when load modules at fixed address feature is enabled.
257 @param ImageBase The base addres the image will be loaded at.
258 @param ImageSize The size of the image
260 @retval EFI_SUCCESS The memory range the image will be loaded in is available
261 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
264 CheckAndMarkFixLoadingMemoryUsageBitMap (
265 IN EFI_PHYSICAL_ADDRESS ImageBase
,
269 UINT32 DxeCodePageNumber
;
271 EFI_PHYSICAL_ADDRESS DxeCodeBase
;
272 UINTN BaseOffsetPageNumber
;
273 UINTN TopOffsetPageNumber
;
276 // The DXE code range includes RuntimeCodePage range and Boot time code range.
278 DxeCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
279 DxeCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
280 DxeCodeSize
= EFI_PAGES_TO_SIZE(DxeCodePageNumber
);
281 DxeCodeBase
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
- DxeCodeSize
;
284 // If the memory usage bit map is not initialized, do it. Every bit in the array
285 // indicate the status of the corresponding memory page, available or not
287 if (mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
288 mDxeCodeMemoryRangeUsageBitMap
= AllocateZeroPool(((DxeCodePageNumber
/64) + 1)*sizeof(UINT64
));
291 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
293 if (!gLoadFixedAddressCodeMemoryReady
|| mDxeCodeMemoryRangeUsageBitMap
== NULL
) {
294 return EFI_NOT_FOUND
;
297 // Test the memory range for loading the image in the DXE code range.
299 if (gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
< ImageBase
+ ImageSize
||
300 DxeCodeBase
> ImageBase
) {
301 return EFI_NOT_FOUND
;
304 // Test if the memory is avalaible or not.
306 BaseOffsetPageNumber
= (UINTN
)EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
- DxeCodeBase
));
307 TopOffsetPageNumber
= (UINTN
)EFI_SIZE_TO_PAGES((UINT32
)(ImageBase
+ ImageSize
- DxeCodeBase
));
308 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
309 if ((mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] & LShiftU64(1, (Index
% 64))) != 0) {
311 // This page is already used.
313 return EFI_NOT_FOUND
;
318 // Being here means the memory range is available. So mark the bits for the memory range
320 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
321 mDxeCodeMemoryRangeUsageBitMap
[Index
/ 64] |= LShiftU64(1, (Index
% 64));
327 Get the fixed loadding address from image header assigned by build tool. This function only be called
328 when Loading module at Fixed address feature enabled.
330 @param ImageContext Pointer to the image context structure that describes the PE/COFF
331 image that needs to be examined by this function.
332 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
333 @retval EFI_NOT_FOUND The image has no assigned fixed loadding address.
337 GetPeCoffImageFixLoadingAssignedAddress(
338 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
341 UINTN SectionHeaderOffset
;
343 EFI_IMAGE_SECTION_HEADER SectionHeader
;
344 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
347 UINT16 NumberOfSections
;
348 IMAGE_FILE_HANDLE
*Handle
;
349 UINT64 ValueInSectionHeader
;
352 Status
= EFI_NOT_FOUND
;
355 // Get PeHeader pointer
357 Handle
= (IMAGE_FILE_HANDLE
*)ImageContext
->Handle
;
358 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
* )Handle
->Source
+ ImageContext
->PeCoffHeaderOffset
);
359 SectionHeaderOffset
= (UINTN
)(
360 ImageContext
->PeCoffHeaderOffset
+
362 sizeof (EFI_IMAGE_FILE_HEADER
) +
363 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
365 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
368 // Get base address from the first section header that doesn't point to code section.
370 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
372 // Read section header from file
374 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
375 Status
= ImageContext
->ImageRead (
376 ImageContext
->Handle
,
381 if (EFI_ERROR (Status
)) {
385 Status
= EFI_NOT_FOUND
;
387 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
389 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
390 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
391 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
392 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fileds should be set to Zero
394 ValueInSectionHeader
= ReadUnaligned64((UINT64
*)&SectionHeader
.PointerToRelocations
);
395 if (ValueInSectionHeader
!= 0) {
397 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
398 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
399 // relative to top address
401 if ((INT64
)PcdGet64(PcdLoadModuleAtFixAddressEnable
) < 0) {
402 ImageContext
->ImageAddress
= gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
+ (INT64
)(INTN
)ImageContext
->ImageAddress
;
405 // Check if the memory range is avaliable.
407 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext
->ImageAddress
, (UINTN
)(ImageContext
->ImageSize
+ ImageContext
->SectionAlignment
));
411 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
413 DEBUG ((EFI_D_INFO
|EFI_D_LOAD
, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID
*)(UINTN
)(ImageContext
->ImageAddress
), Status
));
417 Loads, relocates, and invokes a PE/COFF image
419 @param BootPolicy If TRUE, indicates that the request originates
420 from the boot manager, and that the boot
421 manager is attempting to load FilePath as a
423 @param Pe32Handle The handle of PE32 image
424 @param Image PE image to be loaded
425 @param DstBuffer The buffer to store the image
426 @param EntryPoint A pointer to the entry point
427 @param Attribute The bit mask of attributes to set for the load
430 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
431 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
432 relocate the PE/COFF file
433 @retval EFI_INVALID_PARAMETER Invalid parameter
434 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
439 IN BOOLEAN BootPolicy
,
441 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
442 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
443 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
448 BOOLEAN DstBufAlocated
;
451 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
453 Image
->ImageContext
.Handle
= Pe32Handle
;
454 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
457 // Get information about the image being loaded
459 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
460 if (EFI_ERROR (Status
)) {
464 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
465 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
467 // The PE/COFF loader can support loading image types that can be executed.
468 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
470 DEBUG ((EFI_D_ERROR
, "Image type %s can't be loaded on %s UEFI system.\n", GetMachineTypeName(Image
->ImageContext
.Machine
), GetMachineTypeName(mDxeCoreImageMachineType
)));
471 return EFI_UNSUPPORTED
;
476 // Set EFI memory type based on ImageType
478 switch (Image
->ImageContext
.ImageType
) {
479 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
480 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
481 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
483 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
484 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
485 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
487 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
488 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
489 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
490 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
493 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
494 return EFI_UNSUPPORTED
;
498 // Allocate memory of the correct memory type aligned on the required image boundry
500 DstBufAlocated
= FALSE
;
501 if (DstBuffer
== 0) {
503 // Allocate Destination Buffer as caller did not pass it in
506 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
507 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
509 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
512 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
515 // If the image relocations have not been stripped, then load at any address.
516 // Otherwise load at the address at which it was linked.
518 // Memory below 1MB should be treated reserved for CSM and there should be
519 // no modules whose preferred load addresses are below 1MB.
521 Status
= EFI_OUT_OF_RESOURCES
;
523 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
524 // a specified address.
526 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 ) {
527 Status
= GetPeCoffImageFixLoadingAssignedAddress (&(Image
->ImageContext
));
529 if (EFI_ERROR (Status
)) {
531 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
533 DEBUG ((EFI_D_INFO
|EFI_D_LOAD
, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
535 Status
= CoreAllocatePages (
537 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
538 Image
->NumberOfPages
,
539 &Image
->ImageContext
.ImageAddress
543 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
544 Status
= CoreAllocatePages (
546 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
547 Image
->NumberOfPages
,
548 &Image
->ImageContext
.ImageAddress
551 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
552 Status
= CoreAllocatePages (
554 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
555 Image
->NumberOfPages
,
556 &Image
->ImageContext
.ImageAddress
560 if (EFI_ERROR (Status
)) {
563 DstBufAlocated
= TRUE
;
566 // Caller provided the destination buffer
569 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
571 // If the image relocations were stripped, and the caller provided a
572 // destination buffer address that does not match the address that the
573 // image is linked at, then the image cannot be loaded.
575 return EFI_INVALID_PARAMETER
;
578 if (Image
->NumberOfPages
!= 0 &&
579 Image
->NumberOfPages
<
580 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
581 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
582 return EFI_BUFFER_TOO_SMALL
;
585 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
586 Image
->ImageContext
.ImageAddress
= DstBuffer
;
589 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
590 if (!Image
->ImageContext
.IsTeImage
) {
591 Image
->ImageContext
.ImageAddress
=
592 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
593 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
597 // Load the image from the file into the allocated memory
599 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
600 if (EFI_ERROR (Status
)) {
605 // If this is a Runtime Driver, then allocate memory for the FixupData that
606 // is used to relocate the image when SetVirtualAddressMap() is called. The
607 // relocation is done by the Runtime AP.
609 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
610 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
611 Image
->ImageContext
.FixupData
= AllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
612 if (Image
->ImageContext
.FixupData
== NULL
) {
613 Status
= EFI_OUT_OF_RESOURCES
;
620 // Relocate the image in memory
622 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
623 if (EFI_ERROR (Status
)) {
628 // Flush the Instruction Cache
630 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
633 // Copy the machine type from the context to the image private data. This
634 // is needed during image unload to know if we should call an EBC protocol
635 // to unload the image.
637 Image
->Machine
= Image
->ImageContext
.Machine
;
640 // Get the image entry point. If it's an EBC image, then call into the
641 // interpreter to create a thunk for the entry point and use the returned
642 // value for the entry point.
644 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
645 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
647 // Locate the EBC interpreter protocol
649 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
650 if (EFI_ERROR(Status
) || Image
->Ebc
== NULL
) {
651 DEBUG ((DEBUG_LOAD
| DEBUG_ERROR
, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
656 // Register a callback for flushing the instruction cache so that created
657 // thunks can be flushed.
659 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
660 if (EFI_ERROR(Status
)) {
665 // Create a thunk for the image's entry point. This will be the new
666 // entry point for the image.
668 Status
= Image
->Ebc
->CreateThunk (
671 (VOID
*)(UINTN
) Image
->ImageContext
.EntryPoint
,
672 (VOID
**) &Image
->EntryPoint
674 if (EFI_ERROR(Status
)) {
680 // Fill in the image information for the Loaded Image Protocol
682 Image
->Type
= Image
->ImageContext
.ImageType
;
683 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
684 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
685 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
686 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
687 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) != 0) {
688 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
690 // Make a list off all the RT images so we can let the RT AP know about them.
692 Image
->RuntimeData
= AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
693 if (Image
->RuntimeData
== NULL
) {
696 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
697 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
698 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
699 Image
->RuntimeData
->Handle
= Image
->Handle
;
700 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
705 // Fill in the entry point of the image if it is available
707 if (EntryPoint
!= NULL
) {
708 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
712 // Print the load address and the PDB file name if it is available
719 CHAR8 EfiFileName
[256];
722 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
,
723 "Loading driver at 0x%11p EntryPoint=0x%11p ",
724 (VOID
*)(UINTN
) Image
->ImageContext
.ImageAddress
,
725 FUNCTION_ENTRY_POINT (Image
->ImageContext
.EntryPoint
)));
729 // Print Module Name by Pdb file path.
730 // Windows and Unix style file path are all trimmed correctly.
732 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
734 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
735 if ((Image
->ImageContext
.PdbPointer
[Index
] == '\\') || (Image
->ImageContext
.PdbPointer
[Index
] == '/')) {
736 StartIndex
= Index
+ 1;
740 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
741 // The PDB file name is limited in the range of 0~255.
742 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
744 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
745 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
746 if (EfiFileName
[Index
] == 0) {
747 EfiFileName
[Index
] = '.';
749 if (EfiFileName
[Index
] == '.') {
750 EfiFileName
[Index
+ 1] = 'e';
751 EfiFileName
[Index
+ 2] = 'f';
752 EfiFileName
[Index
+ 3] = 'i';
753 EfiFileName
[Index
+ 4] = 0;
758 if (Index
== sizeof (EfiFileName
) - 4) {
759 EfiFileName
[Index
] = 0;
761 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
763 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
775 if (DstBufAlocated
) {
776 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
779 if (Image
->ImageContext
.FixupData
!= NULL
) {
780 CoreFreePool (Image
->ImageContext
.FixupData
);
789 Get the image's private data from its handle.
791 @param ImageHandle The image handle
793 @return Return the image private data associated with ImageHandle.
796 LOADED_IMAGE_PRIVATE_DATA
*
797 CoreLoadedImageInfo (
798 IN EFI_HANDLE ImageHandle
802 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
803 LOADED_IMAGE_PRIVATE_DATA
*Image
;
805 Status
= CoreHandleProtocol (
807 &gEfiLoadedImageProtocolGuid
,
808 (VOID
**)&LoadedImage
810 if (!EFI_ERROR (Status
)) {
811 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
813 DEBUG ((DEBUG_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle
));
822 Unloads EFI image from memory.
824 @param Image EFI image
825 @param FreePage Free allocated pages
829 CoreUnloadAndCloseImage (
830 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
836 EFI_HANDLE
*HandleBuffer
;
838 EFI_GUID
**ProtocolGuidArray
;
841 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
845 if (Image
->Ebc
!= NULL
) {
847 // If EBC protocol exists we must perform cleanups for this image.
849 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
853 // Unload image, free Image->ImageContext->ModHandle
855 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
858 // Free our references to the image handle
860 if (Image
->Handle
!= NULL
) {
862 Status
= CoreLocateHandleBuffer (
869 if (!EFI_ERROR (Status
)) {
870 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
871 Status
= CoreProtocolsPerHandle (
872 HandleBuffer
[HandleIndex
],
876 if (!EFI_ERROR (Status
)) {
877 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
878 Status
= CoreOpenProtocolInformation (
879 HandleBuffer
[HandleIndex
],
880 ProtocolGuidArray
[ProtocolIndex
],
884 if (!EFI_ERROR (Status
)) {
885 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
886 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
887 Status
= CoreCloseProtocol (
888 HandleBuffer
[HandleIndex
],
889 ProtocolGuidArray
[ProtocolIndex
],
891 OpenInfo
[OpenInfoIndex
].ControllerHandle
895 if (OpenInfo
!= NULL
) {
896 CoreFreePool(OpenInfo
);
900 if (ProtocolGuidArray
!= NULL
) {
901 CoreFreePool(ProtocolGuidArray
);
905 if (HandleBuffer
!= NULL
) {
906 CoreFreePool (HandleBuffer
);
910 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
912 Status
= CoreUninstallProtocolInterface (
914 &gEfiLoadedImageDevicePathProtocolGuid
,
915 Image
->LoadedImageDevicePath
918 Status
= CoreUninstallProtocolInterface (
920 &gEfiLoadedImageProtocolGuid
,
924 if (Image
->ImageContext
.HiiResourceData
!= 0) {
925 Status
= CoreUninstallProtocolInterface (
927 &gEfiHiiPackageListProtocolGuid
,
928 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
934 if (Image
->RuntimeData
!= NULL
) {
935 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
937 // Remove the Image from the Runtime Image list as we are about to Free it!
939 RemoveEntryList (&Image
->RuntimeData
->Link
);
941 CoreFreePool (Image
->RuntimeData
);
945 // Free the Image from memory
947 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
948 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
952 // Done with the Image structure
954 if (Image
->Info
.FilePath
!= NULL
) {
955 CoreFreePool (Image
->Info
.FilePath
);
958 if (Image
->LoadedImageDevicePath
!= NULL
) {
959 CoreFreePool (Image
->LoadedImageDevicePath
);
962 if (Image
->FixupData
!= NULL
) {
963 CoreFreePool (Image
->FixupData
);
966 CoreFreePool (Image
);
971 Loads an EFI image into memory and returns a handle to the image.
973 @param BootPolicy If TRUE, indicates that the request originates
974 from the boot manager, and that the boot
975 manager is attempting to load FilePath as a
977 @param ParentImageHandle The caller's image handle.
978 @param FilePath The specific file path from which the image is
980 @param SourceBuffer If not NULL, a pointer to the memory location
981 containing a copy of the image to be loaded.
982 @param SourceSize The size in bytes of SourceBuffer.
983 @param DstBuffer The buffer to store the image
984 @param NumberOfPages If not NULL, it inputs a pointer to the page
985 number of DstBuffer and outputs a pointer to
986 the page number of the image. If this number is
987 not enough, return EFI_BUFFER_TOO_SMALL and
988 this parameter contains the required number.
989 @param ImageHandle Pointer to the returned image handle that is
990 created when the image is successfully loaded.
991 @param EntryPoint A pointer to the entry point
992 @param Attribute The bit mask of attributes to set for the load
995 @retval EFI_SUCCESS The image was loaded into memory.
996 @retval EFI_NOT_FOUND The FilePath was not found.
997 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
998 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
999 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1000 path cannot be parsed to locate the proper
1001 protocol for loading the file.
1002 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1004 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1006 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1007 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1008 image from being loaded. NULL is returned in *ImageHandle.
1009 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1010 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1011 platform policy specifies that the image should not be started.
1015 CoreLoadImageCommon (
1016 IN BOOLEAN BootPolicy
,
1017 IN EFI_HANDLE ParentImageHandle
,
1018 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1019 IN VOID
*SourceBuffer OPTIONAL
,
1020 IN UINTN SourceSize
,
1021 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1022 IN OUT UINTN
*NumberOfPages OPTIONAL
,
1023 OUT EFI_HANDLE
*ImageHandle
,
1024 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1028 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1029 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
1030 IMAGE_FILE_HANDLE FHand
;
1032 EFI_STATUS SecurityStatus
;
1033 EFI_HANDLE DeviceHandle
;
1034 UINT32 AuthenticationStatus
;
1035 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
1036 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
1039 SecurityStatus
= EFI_SUCCESS
;
1041 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
1045 // The caller must pass in a valid ParentImageHandle
1047 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
1048 return EFI_INVALID_PARAMETER
;
1051 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
1052 if (ParentImage
== NULL
) {
1053 DEBUG((DEBUG_LOAD
|DEBUG_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
1054 return EFI_INVALID_PARAMETER
;
1057 ZeroMem (&FHand
, sizeof (IMAGE_FILE_HANDLE
));
1058 FHand
.Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
1059 OriginalFilePath
= FilePath
;
1060 HandleFilePath
= FilePath
;
1061 DeviceHandle
= NULL
;
1062 Status
= EFI_SUCCESS
;
1063 AuthenticationStatus
= 0;
1065 // If the caller passed a copy of the file, then just use it
1067 if (SourceBuffer
!= NULL
) {
1068 FHand
.Source
= SourceBuffer
;
1069 FHand
.SourceSize
= SourceSize
;
1070 CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1071 if (SourceSize
> 0) {
1072 Status
= EFI_SUCCESS
;
1074 Status
= EFI_LOAD_ERROR
;
1077 if (FilePath
== NULL
) {
1078 return EFI_INVALID_PARAMETER
;
1081 // Get the source file buffer by its device path.
1083 FHand
.Source
= GetFileBufferByFilePath (
1087 &AuthenticationStatus
1089 if (FHand
.Source
== NULL
) {
1090 Status
= EFI_NOT_FOUND
;
1093 // Try to get the image device handle by checking the match protocol.
1095 FHand
.FreeBuffer
= TRUE
;
1096 Status
= CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1097 if (EFI_ERROR (Status
)) {
1098 HandleFilePath
= FilePath
;
1099 Status
= CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1100 if (EFI_ERROR (Status
)) {
1102 HandleFilePath
= FilePath
;
1103 Status
= CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1105 if (EFI_ERROR (Status
)) {
1106 HandleFilePath
= FilePath
;
1107 Status
= CoreLocateDevicePath (&gEfiLoadFileProtocolGuid
, &HandleFilePath
, &DeviceHandle
);
1114 if (Status
== EFI_ALREADY_STARTED
) {
1117 } else if (EFI_ERROR (Status
)) {
1122 // Verify the Authentication Status through the Security Architectural Protocol
1124 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
1125 SecurityStatus
= gSecurity
->FileAuthenticationState (
1127 AuthenticationStatus
,
1130 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
1131 if (SecurityStatus
== EFI_ACCESS_DENIED
) {
1133 // Image was not loaded because the platform policy prohibits the image from being loaded.
1134 // It's the only place we could meet EFI_ACCESS_DENIED.
1136 *ImageHandle
= NULL
;
1138 Status
= SecurityStatus
;
1146 // Allocate a new image structure
1148 Image
= AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
1149 if (Image
== NULL
) {
1150 return EFI_OUT_OF_RESOURCES
;
1154 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1156 FilePath
= OriginalFilePath
;
1157 if (DeviceHandle
!= NULL
) {
1158 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
1159 if (!EFI_ERROR (Status
)) {
1160 FilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
1161 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*)FilePath
) + FilePathSize
);
1165 // Initialize the fields for an internal driver
1167 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
1168 Image
->Info
.SystemTable
= gDxeCoreST
;
1169 Image
->Info
.DeviceHandle
= DeviceHandle
;
1170 Image
->Info
.Revision
= EFI_LOADED_IMAGE_PROTOCOL_REVISION
;
1171 Image
->Info
.FilePath
= DuplicateDevicePath (FilePath
);
1172 Image
->Info
.ParentHandle
= ParentImageHandle
;
1175 if (NumberOfPages
!= NULL
) {
1176 Image
->NumberOfPages
= *NumberOfPages
;
1178 Image
->NumberOfPages
= 0 ;
1182 // Install the protocol interfaces for this image
1183 // don't fire notifications yet
1185 Status
= CoreInstallProtocolInterfaceNotify (
1187 &gEfiLoadedImageProtocolGuid
,
1188 EFI_NATIVE_INTERFACE
,
1192 if (EFI_ERROR (Status
)) {
1197 // Load the image. If EntryPoint is Null, it will not be set.
1199 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
1200 if (EFI_ERROR (Status
)) {
1201 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
1202 if (NumberOfPages
!= NULL
) {
1203 *NumberOfPages
= Image
->NumberOfPages
;
1209 if (NumberOfPages
!= NULL
) {
1210 *NumberOfPages
= Image
->NumberOfPages
;
1214 // Register the image in the Debug Image Info Table if the attribute is set
1216 if ((Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) != 0) {
1217 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
1221 //Reinstall loaded image protocol to fire any notifications
1223 Status
= CoreReinstallProtocolInterface (
1225 &gEfiLoadedImageProtocolGuid
,
1229 if (EFI_ERROR (Status
)) {
1234 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1235 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1237 if (OriginalFilePath
!= NULL
) {
1238 Image
->LoadedImageDevicePath
= DuplicateDevicePath (OriginalFilePath
);
1242 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1244 Status
= CoreInstallProtocolInterface (
1246 &gEfiLoadedImageDevicePathProtocolGuid
,
1247 EFI_NATIVE_INTERFACE
,
1248 Image
->LoadedImageDevicePath
1250 if (EFI_ERROR (Status
)) {
1255 // Install HII Package List Protocol onto the image handle
1257 if (Image
->ImageContext
.HiiResourceData
!= 0) {
1258 Status
= CoreInstallProtocolInterface (
1260 &gEfiHiiPackageListProtocolGuid
,
1261 EFI_NATIVE_INTERFACE
,
1262 (VOID
*) (UINTN
) Image
->ImageContext
.HiiResourceData
1264 if (EFI_ERROR (Status
)) {
1270 // Success. Return the image handle
1272 *ImageHandle
= Image
->Handle
;
1276 // All done accessing the source file
1277 // If we allocated the Source buffer, free it
1279 if (FHand
.FreeBuffer
) {
1280 CoreFreePool (FHand
.Source
);
1284 // There was an error. If there's an Image structure, free it
1286 if (EFI_ERROR (Status
)) {
1287 if (Image
!= NULL
) {
1288 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
1290 } else if (EFI_ERROR (SecurityStatus
)) {
1291 Status
= SecurityStatus
;
1301 Loads an EFI image into memory and returns a handle to the image.
1303 @param BootPolicy If TRUE, indicates that the request originates
1304 from the boot manager, and that the boot
1305 manager is attempting to load FilePath as a
1307 @param ParentImageHandle The caller's image handle.
1308 @param FilePath The specific file path from which the image is
1310 @param SourceBuffer If not NULL, a pointer to the memory location
1311 containing a copy of the image to be loaded.
1312 @param SourceSize The size in bytes of SourceBuffer.
1313 @param ImageHandle Pointer to the returned image handle that is
1314 created when the image is successfully loaded.
1316 @retval EFI_SUCCESS The image was loaded into memory.
1317 @retval EFI_NOT_FOUND The FilePath was not found.
1318 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1319 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1320 path cannot be parsed to locate the proper
1321 protocol for loading the file.
1322 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1324 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1326 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1327 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1328 image from being loaded. NULL is returned in *ImageHandle.
1329 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1330 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1331 platform policy specifies that the image should not be started.
1337 IN BOOLEAN BootPolicy
,
1338 IN EFI_HANDLE ParentImageHandle
,
1339 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1340 IN VOID
*SourceBuffer OPTIONAL
,
1341 IN UINTN SourceSize
,
1342 OUT EFI_HANDLE
*ImageHandle
1350 Tick
= GetPerformanceCounter ();
1353 Status
= CoreLoadImageCommon (
1359 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
1363 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1366 PERF_START (*ImageHandle
, "LoadImage:", NULL
, Tick
);
1367 PERF_END (*ImageHandle
, "LoadImage:", NULL
, 0);
1375 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1377 @param This Calling context
1378 @param ParentImageHandle The caller's image handle.
1379 @param FilePath The specific file path from which the image is
1381 @param SourceBuffer If not NULL, a pointer to the memory location
1382 containing a copy of the image to be loaded.
1383 @param SourceSize The size in bytes of SourceBuffer.
1384 @param DstBuffer The buffer to store the image.
1385 @param NumberOfPages For input, specifies the space size of the
1386 image by caller if not NULL. For output,
1387 specifies the actual space size needed.
1388 @param ImageHandle Image handle for output.
1389 @param EntryPoint Image entry point for output.
1390 @param Attribute The bit mask of attributes to set for the load
1393 @retval EFI_SUCCESS The image was loaded into memory.
1394 @retval EFI_NOT_FOUND The FilePath was not found.
1395 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1396 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1397 path cannot be parsed to locate the proper
1398 protocol for loading the file.
1399 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1401 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1403 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1404 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1405 image from being loaded. NULL is returned in *ImageHandle.
1406 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1407 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1408 platform policy specifies that the image should not be started.
1414 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1415 IN EFI_HANDLE ParentImageHandle
,
1416 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1417 IN VOID
*SourceBuffer OPTIONAL
,
1418 IN UINTN SourceSize
,
1419 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
1420 OUT UINTN
*NumberOfPages OPTIONAL
,
1421 OUT EFI_HANDLE
*ImageHandle
,
1422 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
1426 return CoreLoadImageCommon (
1442 Transfer control to a loaded image's entry point.
1444 @param ImageHandle Handle of image to be started.
1445 @param ExitDataSize Pointer of the size to ExitData
1446 @param ExitData Pointer to a pointer to a data buffer that
1447 includes a Null-terminated string,
1448 optionally followed by additional binary data.
1449 The string is a description that the caller may
1450 use to further indicate the reason for the
1453 @retval EFI_INVALID_PARAMETER Invalid parameter
1454 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1455 @retval EFI_SUCCESS Successfully transfer control to the image's
1462 IN EFI_HANDLE ImageHandle
,
1463 OUT UINTN
*ExitDataSize
,
1464 OUT CHAR16
**ExitData OPTIONAL
1468 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1469 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
1470 UINT64 HandleDatabaseKey
;
1473 Image
= CoreLoadedImageInfo (ImageHandle
);
1474 if (Image
== NULL
|| Image
->Started
) {
1475 return EFI_INVALID_PARAMETER
;
1479 // The image to be started must have the machine type supported by DxeCore.
1481 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->Machine
)) {
1483 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1484 // But it can not be started.
1486 DEBUG ((EFI_D_ERROR
, "Image type %s can't be started on %s UEFI system.\n", GetMachineTypeName(Image
->Machine
), GetMachineTypeName(mDxeCoreImageMachineType
)));
1487 return EFI_UNSUPPORTED
;
1491 // Don't profile Objects or invalid start requests
1493 PERF_START (ImageHandle
, "StartImage:", NULL
, 0);
1497 // Push the current start image context, and
1498 // link the current image to the head. This is the
1499 // only image that can call Exit()
1501 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1502 LastImage
= mCurrentImage
;
1503 mCurrentImage
= Image
;
1504 Image
->Tpl
= gEfiCurrentTpl
;
1507 // Set long jump for Exit() support
1508 // JumpContext must be aligned on a CPU specific boundary.
1509 // Overallocate the buffer and force the required alignment
1511 Image
->JumpBuffer
= AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1512 if (Image
->JumpBuffer
== NULL
) {
1513 PERF_END (ImageHandle
, "StartImage:", NULL
, 0);
1514 return EFI_OUT_OF_RESOURCES
;
1516 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1518 SetJumpFlag
= SetJump (Image
->JumpContext
);
1520 // The initial call to SetJump() must always return 0.
1521 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1523 if (SetJumpFlag
== 0) {
1525 // Call the image's entry point
1527 Image
->Started
= TRUE
;
1528 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1531 // Add some debug information if the image returned with error.
1532 // This make the user aware and check if the driver image have already released
1533 // all the resource in this situation.
1535 DEBUG_CODE_BEGIN ();
1536 if (EFI_ERROR (Image
->Status
)) {
1537 DEBUG ((DEBUG_ERROR
, "Error: Image at %11p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1542 // If the image returns, exit it through Exit()
1544 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1548 // Image has completed. Verify the tpl is the same
1550 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1551 CoreRestoreTpl (Image
->Tpl
);
1553 CoreFreePool (Image
->JumpBuffer
);
1556 // Pop the current start image context
1558 mCurrentImage
= LastImage
;
1561 // Go connect any handles that were created or modified while the image executed.
1563 CoreConnectHandlesByKey (HandleDatabaseKey
);
1566 // Handle the image's returned ExitData
1568 DEBUG_CODE_BEGIN ();
1569 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1571 DEBUG ((DEBUG_LOAD
, "StartImage: ExitDataSize %d, ExitData %p", (UINT32
)Image
->ExitDataSize
, Image
->ExitData
));
1572 if (Image
->ExitData
!= NULL
) {
1573 DEBUG ((DEBUG_LOAD
, " (%hs)", Image
->ExitData
));
1575 DEBUG ((DEBUG_LOAD
, "\n"));
1580 // Return the exit data to the caller
1582 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1583 *ExitDataSize
= Image
->ExitDataSize
;
1584 *ExitData
= Image
->ExitData
;
1587 // Caller doesn't want the exit data, free it
1589 CoreFreePool (Image
->ExitData
);
1590 Image
->ExitData
= NULL
;
1594 // Save the Status because Image will get destroyed if it is unloaded.
1596 Status
= Image
->Status
;
1599 // If the image returned an error, or if the image is an application
1602 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1603 CoreUnloadAndCloseImage (Image
, TRUE
);
1609 PERF_END (ImageHandle
, "StartImage:", NULL
, 0);
1614 Terminates the currently loaded EFI image and returns control to boot services.
1616 @param ImageHandle Handle that identifies the image. This
1617 parameter is passed to the image on entry.
1618 @param Status The image's exit code.
1619 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1620 ExitStatus is EFI_SUCCESS.
1621 @param ExitData Pointer to a data buffer that includes a
1622 Null-terminated Unicode string, optionally
1623 followed by additional binary data. The string
1624 is a description that the caller may use to
1625 further indicate the reason for the image's
1628 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1630 @retval EFI_SUCCESS Successfully terminates the currently loaded
1632 @retval EFI_ACCESS_DENIED Should never reach there.
1633 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1639 IN EFI_HANDLE ImageHandle
,
1640 IN EFI_STATUS Status
,
1641 IN UINTN ExitDataSize
,
1642 IN CHAR16
*ExitData OPTIONAL
1645 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1649 // Prevent possible reentrance to this function
1650 // for the same ImageHandle
1652 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1654 Image
= CoreLoadedImageInfo (ImageHandle
);
1655 if (Image
== NULL
) {
1656 Status
= EFI_INVALID_PARAMETER
;
1660 if (!Image
->Started
) {
1662 // The image has not been started so just free its resources
1664 CoreUnloadAndCloseImage (Image
, TRUE
);
1665 Status
= EFI_SUCCESS
;
1670 // Image has been started, verify this image can exit
1672 if (Image
!= mCurrentImage
) {
1673 DEBUG ((DEBUG_LOAD
|DEBUG_ERROR
, "Exit: Image is not exitable image\n"));
1674 Status
= EFI_INVALID_PARAMETER
;
1681 Image
->Status
= Status
;
1684 // If there's ExitData info, move it
1686 if (ExitData
!= NULL
) {
1687 Image
->ExitDataSize
= ExitDataSize
;
1688 Image
->ExitData
= AllocatePool (Image
->ExitDataSize
);
1689 if (Image
->ExitData
== NULL
) {
1690 Status
= EFI_OUT_OF_RESOURCES
;
1693 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1696 CoreRestoreTpl (OldTpl
);
1698 // return to StartImage
1700 LongJump (Image
->JumpContext
, (UINTN
)-1);
1703 // If we return from LongJump, then it is an error
1706 Status
= EFI_ACCESS_DENIED
;
1708 CoreRestoreTpl (OldTpl
);
1718 @param ImageHandle Handle that identifies the image to be
1721 @retval EFI_SUCCESS The image has been unloaded.
1722 @retval EFI_UNSUPPORTED The image has been sarted, and does not support
1724 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1730 IN EFI_HANDLE ImageHandle
1734 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1736 Image
= CoreLoadedImageInfo (ImageHandle
);
1737 if (Image
== NULL
) {
1739 // The image handle is not valid
1741 Status
= EFI_INVALID_PARAMETER
;
1745 if (Image
->Started
) {
1747 // The image has been started, request it to unload.
1749 Status
= EFI_UNSUPPORTED
;
1750 if (Image
->Info
.Unload
!= NULL
) {
1751 Status
= Image
->Info
.Unload (ImageHandle
);
1756 // This Image hasn't been started, thus it can be unloaded
1758 Status
= EFI_SUCCESS
;
1762 if (!EFI_ERROR (Status
)) {
1764 // if the Image was not started or Unloaded O.K. then clean up
1766 CoreUnloadAndCloseImage (Image
, TRUE
);
1776 Unload the specified image.
1778 @param This Indicates the calling context.
1779 @param ImageHandle The specified image handle.
1781 @retval EFI_INVALID_PARAMETER Image handle is NULL.
1782 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
1783 @retval EFI_SUCCESS Image successfully unloaded.
1789 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1790 IN EFI_HANDLE ImageHandle
1793 return CoreUnloadImage (ImageHandle
);