/** @file\r
Core image handling services to load and unload PeImage.\r
\r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
}\r
};\r
\r
+typedef struct {\r
+ LIST_ENTRY Link;\r
+ EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *Emulator;\r
+ UINT16 MachineType;\r
+} EMULATOR_ENTRY;\r
+\r
+STATIC LIST_ENTRY mAvailableEmulators;\r
+STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent;\r
+STATIC VOID *mPeCoffEmuProtocolNotifyRegistration;\r
\r
//\r
// This code is needed to build the Image handle for the DXE Core\r
NULL, // JumpContext\r
0, // Machine\r
NULL, // Ebc\r
+ NULL, // PeCoffEmu\r
NULL, // RuntimeData\r
NULL // LoadedImageDevicePath\r
};\r
//\r
// The field is define for Loading modules at fixed address feature to tracker the PEI code\r
// memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page\r
-// available or not. \r
+// available or not.\r
//\r
GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mDxeCodeMemoryRangeUsageBitMap=NULL;\r
\r
{EFI_IMAGE_MACHINE_IA32, L"IA32"},\r
{EFI_IMAGE_MACHINE_IA64, L"IA64"},\r
{EFI_IMAGE_MACHINE_X64, L"X64"},\r
- {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"}\r
+ {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"},\r
+ {EFI_IMAGE_MACHINE_AARCH64, L"AARCH64"}\r
};\r
\r
UINT16 mDxeCoreImageMachineType = 0;\r
)\r
{\r
UINTN Index;\r
- \r
+\r
for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {\r
if (mMachineTypeInfo[Index].MachineType == MachineType) {\r
return mMachineTypeInfo[Index].MachineTypeName;\r
return L"<Unknown>";\r
}\r
\r
+/**\r
+ Notification event handler registered by CoreInitializeImageServices () to\r
+ keep track of which PE/COFF image emulators are available.\r
+\r
+ @param Event The Event that is being processed, not used.\r
+ @param Context Event Context, not used.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+PeCoffEmuProtocolNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ EFI_HANDLE EmuHandle;\r
+ EMULATOR_ENTRY *Entry;\r
+\r
+ EmuHandle = NULL;\r
+\r
+ while (TRUE) {\r
+ BufferSize = sizeof (EmuHandle);\r
+ Status = CoreLocateHandle (\r
+ ByRegisterNotify,\r
+ NULL,\r
+ mPeCoffEmuProtocolNotifyRegistration,\r
+ &BufferSize,\r
+ &EmuHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no more notification events exit\r
+ //\r
+ return;\r
+ }\r
+\r
+ Entry = AllocateZeroPool (sizeof (*Entry));\r
+ ASSERT (Entry != NULL);\r
+\r
+ Status = CoreHandleProtocol (\r
+ EmuHandle,\r
+ &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
+ (VOID **)&Entry->Emulator\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Entry->MachineType = Entry->Emulator->MachineType;\r
+\r
+ InsertTailList (&mAvailableEmulators, &Entry->Link);\r
+ }\r
+}\r
+\r
/**\r
Add the Image Services to EFI Boot Services Table and install the protocol\r
interfaces for this image.\r
UINT64 DxeCoreImageLength;\r
VOID *DxeCoreEntryPoint;\r
EFI_PEI_HOB_POINTERS DxeCoreHob;\r
- \r
+\r
//\r
// Searching for image hob\r
//\r
DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;\r
DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;\r
gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;\r
- \r
+\r
//\r
// Initialize the fields for an internal driver\r
//\r
gDxeCoreImageHandle = Image->Handle;\r
gDxeCoreLoadedImage = &Image->Info;\r
\r
+ //\r
+ // Create the PE/COFF emulator protocol registration event\r
+ //\r
+ Status = CoreCreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ PeCoffEmuProtocolNotify,\r
+ NULL,\r
+ &mPeCoffEmuProtocolRegistrationEvent\r
+ );\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ //\r
+ // Register for protocol notifications on this event\r
+ //\r
+ Status = CoreRegisterProtocolNotify (\r
+ &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
+ mPeCoffEmuProtocolRegistrationEvent,\r
+ &mPeCoffEmuProtocolNotifyRegistration\r
+ );\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ InitializeListHead (&mAvailableEmulators);\r
+\r
if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
//\r
// Export DXE Core PE Loader functionality for backward compatibility.\r
);\r
}\r
\r
+ ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
return Status;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
/**\r
- 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 \r
- memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.\r
- The function is only invoked when load modules at fixed address feature is enabled. \r
- \r
- @param ImageBase The base addres the image will be loaded at.\r
+ To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If\r
+ memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
+ The function is only invoked when load modules at fixed address feature is enabled.\r
+\r
+ @param ImageBase The base address the image will be loaded at.\r
@param ImageSize The size of the image\r
- \r
+\r
@retval EFI_SUCCESS The memory range the image will be loaded in is available\r
@retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
**/\r
)\r
{\r
UINT32 DxeCodePageNumber;\r
- UINT64 DxeCodeSize; \r
+ UINT64 DxeCodeSize;\r
EFI_PHYSICAL_ADDRESS DxeCodeBase;\r
UINTN BaseOffsetPageNumber;\r
UINTN TopOffsetPageNumber;\r
UINTN Index;\r
//\r
// The DXE code range includes RuntimeCodePage range and Boot time code range.\r
- // \r
+ //\r
DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);\r
DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;\r
- \r
+\r
//\r
- // If the memory usage bit map is not initialized, do it. Every bit in the array \r
+ // If the memory usage bit map is not initialized, do it. Every bit in the array\r
// indicate the status of the corresponding memory page, available or not\r
- // \r
+ //\r
if (mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));\r
}\r
//\r
if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||\r
DxeCodeBase > ImageBase) {\r
- return EFI_NOT_FOUND; \r
- } \r
+ return EFI_NOT_FOUND;\r
+ }\r
//\r
// Test if the memory is avalaible or not.\r
- // \r
- BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));\r
- TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));\r
+ //\r
+ BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));\r
+ TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));\r
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
//\r
// This page is already used.\r
//\r
- return EFI_NOT_FOUND; \r
+ return EFI_NOT_FOUND;\r
}\r
}\r
- \r
+\r
//\r
// Being here means the memory range is available. So mark the bits for the memory range\r
- // \r
+ //\r
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
}\r
- return EFI_SUCCESS; \r
+ return EFI_SUCCESS;\r
}\r
/**\r
\r
- Get the fixed loadding address from image header assigned by build tool. This function only be called\r
+ Get the fixed loading address from image header assigned by build tool. This function only be called\r
when Loading module at Fixed address feature enabled.\r
\r
@param ImageContext Pointer to the image context structure that describes the PE/COFF\r
image that needs to be examined by this function.\r
@retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
- @retval EFI_NOT_FOUND The image has no assigned fixed loadding address.\r
+ @retval EFI_NOT_FOUND The image has no assigned fixed loading address.\r
\r
**/\r
EFI_STATUS\r
UINT16 NumberOfSections;\r
IMAGE_FILE_HANDLE *Handle;\r
UINT64 ValueInSectionHeader;\r
- \r
+\r
\r
Status = EFI_NOT_FOUND;\r
- \r
+\r
//\r
// Get PeHeader pointer\r
//\r
Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;\r
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);\r
- SectionHeaderOffset = (UINTN)(\r
- ImageContext->PeCoffHeaderOffset +\r
- sizeof (UINT32) +\r
- sizeof (EFI_IMAGE_FILE_HEADER) +\r
- ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
- );\r
+ SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
\r
//\r
}\r
\r
Status = EFI_NOT_FOUND;\r
- \r
+\r
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
//\r
// Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
- // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an \r
- // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations \r
- // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fileds should be set to Zero\r
+ // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an\r
+ // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations\r
+ // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero\r
//\r
ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
if (ValueInSectionHeader != 0) {\r
//\r
- // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext \r
+ // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext\r
// hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset\r
// relative to top address\r
//\r
if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {\r
- ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;\r
+ ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;\r
}\r
//\r
- // Check if the memory range is avaliable.\r
+ // Check if the memory range is available.\r
//\r
Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
}\r
- break; \r
+ break;\r
}\r
SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
}\r
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));\r
return Status;\r
}\r
+\r
+/**\r
+ Decides whether a PE/COFF image can execute on this system, either natively\r
+ or via emulation/interpretation. In the latter case, the PeCoffEmu member\r
+ of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer\r
+ to the emulator protocol that supports this image.\r
+\r
+ @param[in, out] Image LOADED_IMAGE_PRIVATE_DATA struct pointer\r
+\r
+ @retval TRUE The image is supported\r
+ @retval FALSE The image is not supported\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+CoreIsImageTypeSupported (\r
+ IN OUT LOADED_IMAGE_PRIVATE_DATA *Image\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ EMULATOR_ENTRY *Entry;\r
+\r
+ for (Link = GetFirstNode (&mAvailableEmulators);\r
+ !IsNull (&mAvailableEmulators, Link);\r
+ Link = GetNextNode (&mAvailableEmulators, Link)) {\r
+\r
+ Entry = BASE_CR (Link, EMULATOR_ENTRY, Link);\r
+ if (Entry->MachineType != Image->ImageContext.Machine) {\r
+ continue;\r
+ }\r
+\r
+ if (Entry->Emulator->IsImageSupported (Entry->Emulator,\r
+ Image->ImageContext.ImageType,\r
+ Image->Info.FilePath)) {\r
+ Image->PeCoffEmu = Entry->Emulator;\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine) ||\r
+ EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine);\r
+}\r
+\r
/**\r
Loads, relocates, and invokes a PE/COFF image\r
\r
return Status;\r
}\r
\r
- if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
- if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
- //\r
- // The PE/COFF loader can support loading image types that can be executed.\r
- // If we loaded an image type that we can not execute return EFI_UNSUPORTED.\r
- //\r
- DEBUG ((EFI_D_ERROR, "Image type %s can't be loaded ", GetMachineTypeName(Image->ImageContext.Machine)));\r
- DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));\r
- return EFI_UNSUPPORTED;\r
- }\r
+ if (!CoreIsImageTypeSupported (Image)) {\r
+ //\r
+ // The PE/COFF loader can support loading image types that can be executed.\r
+ // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "Image type %s can't be loaded on %s UEFI system.\n",\r
+ GetMachineTypeName (Image->ImageContext.Machine),\r
+ GetMachineTypeName (mDxeCoreImageMachineType)));\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
//\r
}\r
\r
//\r
- // Allocate memory of the correct memory type aligned on the required image boundry\r
+ // Allocate memory of the correct memory type aligned on the required image boundary\r
//\r
DstBufAlocated = FALSE;\r
if (DstBuffer == 0) {\r
\r
if (EFI_ERROR (Status)) {\r
//\r
- // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.\r
- //\r
+ // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.\r
+ //\r
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));\r
- \r
+\r
Status = CoreAllocatePages (\r
AllocateAnyPages,\r
(EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
Image->NumberOfPages,\r
&Image->ImageContext.ImageAddress\r
- ); \r
- } \r
+ );\r
+ }\r
} else {\r
if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
Status = CoreAllocatePages (\r
if (EFI_ERROR(Status)) {\r
goto Done;\r
}\r
+ } else if (Image->PeCoffEmu != NULL) {\r
+ Status = Image->PeCoffEmu->RegisterImage (Image->PeCoffEmu,\r
+ Image->ImageBasePage,\r
+ EFI_PAGES_TO_SIZE (Image->NumberOfPages),\r
+ &Image->EntryPoint);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_LOAD | DEBUG_ERROR,\r
+ "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));\r
+ goto Done;\r
+ }\r
}\r
\r
//\r
\r
if (DstBufAlocated) {\r
CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
+ Image->ImageContext.ImageAddress = 0;\r
+ Image->ImageBasePage = 0;\r
}\r
\r
if (Image->ImageContext.FixupData != NULL) {\r
UnregisterMemoryProfileImage (Image);\r
}\r
\r
+ UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
if (Image->Ebc != NULL) {\r
//\r
// If EBC protocol exists we must perform cleanups for this image.\r
Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
}\r
\r
+ if (Image->PeCoffEmu != NULL) {\r
+ //\r
+ // If the PE/COFF Emulator protocol exists we must unregister the image.\r
+ //\r
+ Image->PeCoffEmu->UnregisterImage (Image->PeCoffEmu, Image->ImageBasePage);\r
+ }\r
+\r
//\r
// Unload image, free Image->ImageContext->ModHandle\r
//\r
@retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not\r
understood.\r
@retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.\r
- @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the \r
+ @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the\r
image from being loaded. NULL is returned in *ImageHandle.\r
- @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a \r
- valid EFI_LOADED_IMAGE_PROTOCOL. However, the current \r
+ @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a\r
+ valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
platform policy specifies that the image should not be started.\r
\r
**/\r
// Get the source file buffer by its device path.\r
//\r
FHand.Source = GetFileBufferByFilePath (\r
- BootPolicy, \r
+ BootPolicy,\r
FilePath,\r
&FHand.SourceSize,\r
&AuthenticationStatus\r
goto Done;\r
}\r
}\r
+ ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
\r
//\r
// Success. Return the image handle\r
@retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not\r
understood.\r
@retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.\r
- @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the \r
+ @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the\r
image from being loaded. NULL is returned in *ImageHandle.\r
- @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a \r
- valid EFI_LOADED_IMAGE_PROTOCOL. However, the current \r
+ @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a\r
+ valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
platform policy specifies that the image should not be started.\r
\r
**/\r
)\r
{\r
EFI_STATUS Status;\r
- UINT64 Tick;\r
EFI_HANDLE Handle;\r
\r
- Tick = 0;\r
- PERF_CODE (\r
- Tick = GetPerformanceCounter ();\r
- );\r
+ PERF_LOAD_IMAGE_BEGIN (NULL);\r
\r
Status = CoreLoadImageCommon (\r
BootPolicy,\r
EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
);\r
\r
- Handle = NULL; \r
+ Handle = NULL;\r
if (!EFI_ERROR (Status)) {\r
//\r
- // ImageHandle will be valid only Status is success. \r
+ // ImageHandle will be valid only Status is success.\r
//\r
Handle = *ImageHandle;\r
}\r
\r
- PERF_START (Handle, "LoadImage:", NULL, Tick);\r
- PERF_END (Handle, "LoadImage:", NULL, 0);\r
+ PERF_LOAD_IMAGE_END (Handle);\r
\r
return Status;\r
}\r
@retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not\r
understood.\r
@retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.\r
- @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the \r
+ @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the\r
image from being loaded. NULL is returned in *ImageHandle.\r
- @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a \r
- valid EFI_LOADED_IMAGE_PROTOCOL. However, the current \r
+ @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a\r
+ valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
platform policy specifies that the image should not be started.\r
\r
**/\r
)\r
{\r
EFI_STATUS Status;\r
- UINT64 Tick;\r
EFI_HANDLE Handle;\r
\r
- Tick = 0;\r
- PERF_CODE (\r
- Tick = GetPerformanceCounter ();\r
- );\r
+ PERF_LOAD_IMAGE_BEGIN (NULL);\r
\r
Status = CoreLoadImageCommon (\r
TRUE,\r
Attribute\r
);\r
\r
- Handle = NULL; \r
+ Handle = NULL;\r
if (!EFI_ERROR (Status)) {\r
//\r
- // ImageHandle will be valid only Status is success. \r
+ // ImageHandle will be valid only Status is success.\r
//\r
Handle = *ImageHandle;\r
}\r
\r
- PERF_START (Handle, "LoadImage:", NULL, Tick);\r
- PERF_END (Handle, "LoadImage:", NULL, 0);\r
+ PERF_LOAD_IMAGE_END (Handle);\r
\r
return Status;\r
}\r
LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
UINT64 HandleDatabaseKey;\r
UINTN SetJumpFlag;\r
- UINT64 Tick;\r
EFI_HANDLE Handle;\r
\r
- Tick = 0;\r
Handle = ImageHandle;\r
\r
Image = CoreLoadedImageInfo (ImageHandle);\r
//\r
// The image to be started must have the machine type supported by DxeCore.\r
//\r
- if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) {\r
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine) &&\r
+ Image->PeCoffEmu == NULL) {\r
//\r
// Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED\r
// But it can not be started.\r
return EFI_UNSUPPORTED;\r
}\r
\r
- PERF_CODE (\r
- Tick = GetPerformanceCounter ();\r
- );\r
+ PERF_START_IMAGE_BEGIN (Handle);\r
\r
\r
//\r
// Image may be unloaded after return with failure,\r
// then ImageHandle may be invalid, so use NULL handle to record perf log.\r
//\r
- PERF_START (NULL, "StartImage:", NULL, Tick);\r
- PERF_END (NULL, "StartImage:", NULL, 0);\r
+ PERF_START_IMAGE_END (NULL);\r
+\r
+ //\r
+ // Pop the current start image context\r
+ //\r
+ mCurrentImage = LastImage;\r
+\r
return EFI_OUT_OF_RESOURCES;\r
}\r
Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
mCurrentImage = LastImage;\r
\r
//\r
- // Go connect any handles that were created or modified while the image executed.\r
+ // UEFI Specification - StartImage() - EFI 1.10 Extension\r
+ // To maintain compatibility with UEFI drivers that are written to the EFI\r
+ // 1.02 Specification, StartImage() must monitor the handle database before\r
+ // and after each image is started. If any handles are created or modified\r
+ // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must\r
+ // be called with the Recursive parameter set to TRUE for each of the newly\r
+ // created or modified handles before StartImage() returns.\r
//\r
- CoreConnectHandlesByKey (HandleDatabaseKey);\r
+ if (Image->Type != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ CoreConnectHandlesByKey (HandleDatabaseKey);\r
+ }\r
\r
//\r
// Handle the image's returned ExitData\r
//\r
// Done\r
//\r
- PERF_START (Handle, "StartImage:", NULL, Tick);\r
- PERF_END (Handle, "StartImage:", NULL, 0);\r
+ PERF_START_IMAGE_END (Handle);\r
return Status;\r
}\r
\r
unloaded.\r
\r
@retval EFI_SUCCESS The image has been unloaded.\r
- @retval EFI_UNSUPPORTED The image has been sarted, and does not support\r
+ @retval EFI_UNSUPPORTED The image has been started, and does not support\r
unload.\r
@retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.\r
\r