-/*++\r
+/** @file\r
+ Core image handling services to load and unload PeImage.\r
\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\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
+**/\r
\r
-Module Name:\r
+#include "DxeMain.h"\r
+#include "Image.h"\r
\r
- Image.c\r
-\r
-Abstract:\r
-\r
- Core image handling services\r
-\r
---*/\r
-\r
-#include <DxeMain.h>\r
//\r
// Module Globals\r
//\r
-\r
LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;\r
\r
LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {\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
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mDxeCodeMemoryRangeUsageBitMap=NULL;\r
+\r
+typedef struct {\r
+ UINT16 MachineType;\r
+ CHAR16 *MachineTypeName;\r
+} MACHINE_TYPE_INFO;\r
+\r
+//\r
+// EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo[] = {\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_AARCH64, L"AARCH64"}\r
+};\r
\r
+UINT16 mDxeCoreImageMachineType = 0;\r
\r
-EFI_STATUS\r
-CoreInitializeImageServices (\r
- IN VOID *HobStart\r
+/**\r
+ Return machine type name.\r
+\r
+ @param MachineType The machine type\r
+\r
+ @return machine type name\r
+**/\r
+CHAR16 *\r
+GetMachineTypeName (\r
+ UINT16 MachineType\r
)\r
-/*++\r
+{\r
+ UINTN Index;\r
\r
-Routine Description:\r
+ for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {\r
+ if (mMachineTypeInfo[Index].MachineType == MachineType) {\r
+ return mMachineTypeInfo[Index].MachineTypeName;\r
+ }\r
+ }\r
\r
- Add the Image Services to EFI Boot Services Table and install the protocol\r
- interfaces for this image.\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
-Arguments:\r
+ EmuHandle = NULL;\r
\r
- HobStart - The HOB to initialize\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
\r
-Returns:\r
+ @param HobStart The HOB to initialize\r
\r
- Status code.\r
+ @return Status code.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+CoreInitializeImageServices (\r
+ IN VOID *HobStart\r
+ )\r
{\r
EFI_STATUS Status;\r
LOADED_IMAGE_PRIVATE_DATA *Image;\r
UINT64 DxeCoreImageLength;\r
VOID *DxeCoreEntryPoint;\r
EFI_PEI_HOB_POINTERS DxeCoreHob;\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
// Initialize the fields for an internal driver\r
//\r
//\r
// Fill in DXE globals\r
//\r
+ mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);\r
gDxeCoreImageHandle = Image->Handle;\r
gDxeCoreLoadedImage = &Image->Info;\r
\r
//\r
- // Export DXE Core PE Loader functionality\r
+ // Create the PE/COFF emulator protocol registration event\r
//\r
- return CoreInstallProtocolInterface (\r
- &mLoadPe32PrivateData.Handle,\r
- &gEfiLoadPeImageProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &mLoadPe32PrivateData.Pe32Image\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
+ Status = CoreInstallProtocolInterface (\r
+ &mLoadPe32PrivateData.Handle,\r
+ &gEfiLoadPeImageProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mLoadPe32PrivateData.Pe32Image\r
+ );\r
+ }\r
+\r
+ ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
+ return Status;\r
}\r
\r
+/**\r
+ Read image file (specified by UserHandle) into user specified buffer with specified offset\r
+ and length.\r
+\r
+ @param UserHandle Image file handle\r
+ @param Offset Offset to the source file\r
+ @param ReadSize For input, pointer of size to read; For output,\r
+ pointer of size actually read.\r
+ @param Buffer Buffer to write into\r
+\r
+ @retval EFI_SUCCESS Successfully read the specified part of file\r
+ into buffer.\r
+\r
+**/\r
EFI_STATUS\r
-CoreLoadPeImage (\r
- IN BOOLEAN BootPolicy, \r
- IN VOID *Pe32Handle,\r
- IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
- IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
- IN UINT32 Attribute\r
+EFIAPI\r
+CoreReadImageFile (\r
+ IN VOID *UserHandle,\r
+ IN UINTN Offset,\r
+ IN OUT UINTN *ReadSize,\r
+ OUT VOID *Buffer\r
)\r
-/*++\r
+{\r
+ UINTN EndPosition;\r
+ IMAGE_FILE_HANDLE *FHand;\r
+\r
+ if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
-Routine Description:\r
+ if (MAX_ADDRESS - Offset < *ReadSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- Loads, relocates, and invokes a PE/COFF image\r
+ FHand = (IMAGE_FILE_HANDLE *)UserHandle;\r
+ ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
+\r
+ //\r
+ // Move data from our local copy of the file\r
+ //\r
+ EndPosition = Offset + *ReadSize;\r
+ if (EndPosition > FHand->SourceSize) {\r
+ *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
+ }\r
+ if (Offset >= FHand->SourceSize) {\r
+ *ReadSize = 0;\r
+ }\r
+\r
+ CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
+ return EFI_SUCCESS;\r
+}\r
+/**\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
-Arguments:\r
- BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
- and that the boot manager is attempting to load FilePath as a boot selection.\r
- Pe32Handle - The handle of PE32 image\r
- Image - PE image to be loaded\r
- DstBuffer - The buffer to store the image\r
- EntryPoint - A pointer to the entry point\r
- Attribute - The bit mask of attributes to set for the load PE image\r
+ @param ImageBase The base address the image will be loaded at.\r
+ @param ImageSize The size of the image\r
\r
-Returns:\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
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase,\r
+ IN UINTN ImageSize\r
+ )\r
+{\r
+ UINT32 DxeCodePageNumber;\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
+ DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+ DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+ DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);\r
+ DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;\r
+\r
+ //\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
+ if (mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+ mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));\r
+ }\r
+ //\r
+ // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
+ //\r
+ if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Test the memory range for loading the image in the DXE code range.\r
+ //\r
+ if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||\r
+ DxeCodeBase > ImageBase) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Test if the memory is avalaible or not.\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
+ }\r
+ }\r
+\r
+ //\r
+ // Being here means the memory range is available. So mark the bits for the memory range\r
+ //\r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+/**\r
+\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 loading address.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ )\r
+{\r
+ UINTN SectionHeaderOffset;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
+ UINT16 Index;\r
+ UINTN Size;\r
+ UINT16 NumberOfSections;\r
+ IMAGE_FILE_HANDLE *Handle;\r
+ UINT64 ValueInSectionHeader;\r
+\r
+\r
+ Status = EFI_NOT_FOUND;\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 = 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
+ // Get base address from the first section header that doesn't point to code section.\r
+ //\r
+ for (Index = 0; Index < NumberOfSections; Index++) {\r
+ //\r
+ // Read section header from file\r
+ //\r
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ SectionHeaderOffset,\r
+ &Size,\r
+ &SectionHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\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 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
+ // 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
+ }\r
+ //\r
+ // Check if the memory range is available.\r
+ //\r
+ Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
+ }\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
- EFI_SUCCESS - The file was loaded, relocated, and invoked\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
- EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\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
- EFI_INVALID_PARAMETER - Invalid parameter\r
+ return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine) ||\r
+ EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine);\r
+}\r
\r
- EFI_BUFFER_TOO_SMALL - Buffer for image is too small\r
+/**\r
+ Loads, relocates, and invokes a PE/COFF image\r
\r
---*/\r
+ @param BootPolicy If TRUE, indicates that the request originates\r
+ from the boot manager, and that the boot\r
+ manager is attempting to load FilePath as a\r
+ boot selection.\r
+ @param Pe32Handle The handle of PE32 image\r
+ @param Image PE image to be loaded\r
+ @param DstBuffer The buffer to store the image\r
+ @param EntryPoint A pointer to the entry point\r
+ @param Attribute The bit mask of attributes to set for the load\r
+ PE image\r
+\r
+ @retval EFI_SUCCESS The file was loaded, relocated, and invoked\r
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and\r
+ relocate the PE/COFF file\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small\r
+\r
+**/\r
+EFI_STATUS\r
+CoreLoadPeImage (\r
+ IN BOOLEAN BootPolicy,\r
+ IN VOID *Pe32Handle,\r
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
+ IN UINT32 Attribute\r
+ )\r
{\r
EFI_STATUS Status;\r
BOOLEAN DstBufAlocated;\r
UINTN Size;\r
- UINTN LinkTimeBase;\r
- EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;\r
- IMAGE_FILE_HANDLE *FHandle;\r
\r
- FHandle = NULL;\r
ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
\r
Image->ImageContext.Handle = Pe32Handle;\r
return Status;\r
}\r
\r
- if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\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_UNSUPORTED.\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
// Set EFI memory type based on ImageType\r
//\r
Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
return EFI_UNSUPPORTED;\r
}\r
- //\r
- // Get the image base address in the original PeImage.\r
- //\r
- LinkTimeBase = (UINTN) Image->ImageContext.ImageAddress;\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
// no modules whose preferred load addresses are below 1MB.\r
//\r
Status = EFI_OUT_OF_RESOURCES;\r
- if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
- Status = CoreAllocatePages (\r
- AllocateAddress,\r
- (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
- Image->NumberOfPages,\r
- &Image->ImageContext.ImageAddress\r
- );\r
- }\r
- if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
- Status = CoreAllocatePages (\r
- AllocateAnyPages,\r
- (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
- Image->NumberOfPages,\r
- &Image->ImageContext.ImageAddress\r
- );\r
+ //\r
+ // If Loading Module At Fixed Address feature is enabled, the module should be loaded to\r
+ // a specified address.\r
+ //\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {\r
+ Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));\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
+ 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
+ Status = CoreAllocatePages (\r
+ AllocateAnyPages,\r
+ (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+ Image->NumberOfPages,\r
+ &Image->ImageContext.ImageAddress\r
+ );\r
+ }\r
+ } else {\r
+ if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
+ Status = CoreAllocatePages (\r
+ AllocateAddress,\r
+ (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+ Image->NumberOfPages,\r
+ &Image->ImageContext.ImageAddress\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
+ Status = CoreAllocatePages (\r
+ AllocateAnyPages,\r
+ (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+ Image->NumberOfPages,\r
+ &Image->ImageContext.ImageAddress\r
+ );\r
+ }\r
}\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
- Image->ImageContext.ImageAddress =\r
- (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
- ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
+ if (!Image->ImageContext.IsTeImage) {\r
+ Image->ImageContext.ImageAddress =\r
+ (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
+ ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
+ }\r
\r
//\r
// Load the image from the file into the allocated memory\r
// is used to relocate the image when SetVirtualAddressMap() is called. The\r
// relocation is done by the Runtime AP.\r
//\r
- if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
+ if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
- Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
+ Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
if (Image->ImageContext.FixupData == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
}\r
\r
- //\r
- // Measure the image before applying fixup\r
- //\r
- Status = CoreLocateProtocol (\r
- &gEfiTcgPlatformProtocolGuid,\r
- NULL,\r
- (VOID **) &TcgPlatformProtocol\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- FHandle = (IMAGE_FILE_HANDLE *) Image->ImageContext.Handle;\r
- Status = TcgPlatformProtocol->MeasurePeImage (\r
- BootPolicy,\r
- (EFI_PHYSICAL_ADDRESS) (UINTN) FHandle->Source,\r
- FHandle->SourceSize,\r
- LinkTimeBase,\r
- Image->ImageContext.ImageType,\r
- Image->Info.DeviceHandle,\r
- Image->Info.FilePath\r
- );\r
-\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
//\r
// Relocate the image in memory\r
//\r
// Locate the EBC interpreter protocol\r
//\r
Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
- if (EFI_ERROR(Status)) {\r
+ if (EFI_ERROR(Status) || Image->Ebc == NULL) {\r
+ DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));\r
goto Done;\r
}\r
\r
Status = Image->Ebc->CreateThunk (\r
Image->Ebc,\r
Image->Handle,\r
- (VOID *)(UINTN)Image->ImageContext.EntryPoint,\r
- (VOID **)&Image->EntryPoint\r
+ (VOID *)(UINTN) Image->ImageContext.EntryPoint,\r
+ (VOID **) &Image->EntryPoint\r
);\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
Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
- if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
+ if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
//\r
// Make a list off all the RT images so we can let the RT AP know about them.\r
//\r
- Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
+ Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
if (Image->RuntimeData == NULL) {\r
goto Done;\r
}\r
Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
Image->RuntimeData->Handle = Image->Handle;\r
InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
+ InsertImageRecord (Image->RuntimeData);\r
}\r
}\r
\r
UINTN Index;\r
UINTN StartIndex;\r
CHAR8 EfiFileName[256];\r
- \r
- if (Image->ImageContext.Machine != IMAGE_FILE_MACHINE_IA64) {\r
- DEBUG ((EFI_D_INFO | EFI_D_LOAD, \r
- "Loading driver at 0x%10p EntryPoint=0x%10p ", \r
- (VOID *)(UINTN)Image->ImageContext.ImageAddress, \r
- (VOID *)(UINTN)Image->ImageContext.EntryPoint));\r
- } else {\r
- //\r
- // For IPF Image, the real entry point should be print.\r
- // \r
- DEBUG ((EFI_D_INFO | EFI_D_LOAD, \r
- "Loading driver at 0x%10p EntryPoint=0x%10p ", \r
- (VOID *)(UINTN)Image->ImageContext.ImageAddress, \r
- (VOID *)(UINTN)(*(UINT64 *)(UINTN)Image->ImageContext.EntryPoint)));\r
- }\r
- \r
+\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD,\r
+ "Loading driver at 0x%11p EntryPoint=0x%11p ",\r
+ (VOID *)(UINTN) Image->ImageContext.ImageAddress,\r
+ FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));\r
+\r
+\r
//\r
- // Print Module Name by Pdb file path\r
+ // Print Module Name by Pdb file path.\r
+ // Windows and Unix style file path are all trimmed correctly.\r
//\r
if (Image->ImageContext.PdbPointer != NULL) {\r
StartIndex = 0;\r
for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
- if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
+ if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {\r
StartIndex = Index + 1;\r
}\r
}\r
//\r
// Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
+ // The PDB file name is limited in the range of 0~255.\r
+ // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.\r
//\r
- for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
+ for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
if (EfiFileName[Index] == 0) {\r
EfiFileName[Index] = '.';\r
break;\r
}\r
}\r
- DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
+\r
+ if (Index == sizeof (EfiFileName) - 4) {\r
+ EfiFileName[Index] = 0;\r
+ }\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
}\r
- DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
\r
DEBUG_CODE_END ();\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
}\r
\r
\r
-LOADED_IMAGE_PRIVATE_DATA *\r
-CoreLoadedImageInfo (\r
- IN EFI_HANDLE ImageHandle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
\r
+/**\r
Get the image's private data from its handle.\r
\r
-Arguments:\r
-\r
- ImageHandle - The image handle\r
+ @param ImageHandle The image handle\r
\r
-Returns:\r
+ @return Return the image private data associated with ImageHandle.\r
\r
- Return the image private data associated with ImageHandle.\r
-\r
---*/\r
+**/\r
+LOADED_IMAGE_PRIVATE_DATA *\r
+CoreLoadedImageInfo (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
{\r
EFI_STATUS Status;\r
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
if (!EFI_ERROR (Status)) {\r
Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
} else {\r
- DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));\r
+ DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));\r
Image = NULL;\r
}\r
\r
return Image;\r
}\r
\r
-STATIC\r
-EFI_STATUS\r
-CoreLoadImageCommon (\r
- IN BOOLEAN BootPolicy,\r
- IN EFI_HANDLE ParentImageHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- IN VOID *SourceBuffer OPTIONAL,\r
- IN UINTN SourceSize,\r
- IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
- IN OUT UINTN *NumberOfPages OPTIONAL,\r
- OUT EFI_HANDLE *ImageHandle,\r
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
- IN UINT32 Attribute\r
- )\r
-/*++\r
\r
-Routine Description:\r
+/**\r
+ Unloads EFI image from memory.\r
\r
- Loads an EFI image into memory and returns a handle to the image.\r
+ @param Image EFI image\r
+ @param FreePage Free allocated pages\r
\r
-Arguments:\r
-\r
- BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
- and that the boot manager is attempting to load FilePath as a boot selection.\r
- ParentImageHandle - The caller's image handle.\r
- FilePath - The specific file path from which the image is loaded.\r
- SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
- the image to be loaded.\r
- SourceSize - The size in bytes of SourceBuffer.\r
- DstBuffer - The buffer to store the image\r
- NumberOfPages - If not NULL, a pointer to the image's page number, if this number\r
- is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain\r
- the required number.\r
- ImageHandle - Pointer to the returned image handle that is created when the image\r
- is successfully loaded.\r
- EntryPoint - A pointer to the entry point\r
- Attribute - The bit mask of attributes to set for the load PE image\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The image was loaded into memory.\r
- EFI_NOT_FOUND - The FilePath was not found.\r
- EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
- EFI_BUFFER_TOO_SMALL - The buffer is too small\r
- EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
- parsed to locate the proper protocol for loading the file.\r
- EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
---*/\r
+**/\r
+VOID\r
+CoreUnloadAndCloseImage (\r
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
+ IN BOOLEAN FreePage\r
+ )\r
{\r
- LOADED_IMAGE_PRIVATE_DATA *Image;\r
- LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
- IMAGE_FILE_HANDLE FHand;\r
- EFI_STATUS Status;\r
- EFI_STATUS SecurityStatus;\r
- EFI_HANDLE DeviceHandle;\r
- UINT32 AuthenticationStatus;\r
- EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
- EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
- UINTN FilePathSize;\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleIndex;\r
+ EFI_GUID **ProtocolGuidArray;\r
+ UINTN ArrayCount;\r
+ UINTN ProtocolIndex;\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
+ UINTN OpenInfoCount;\r
+ UINTN OpenInfoIndex;\r
\r
- SecurityStatus = EFI_SUCCESS;\r
+ HandleBuffer = NULL;\r
+ ProtocolGuidArray = NULL;\r
\r
- ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
- ParentImage = NULL;\r
+ if (Image->Started) {\r
+ UnregisterMemoryProfileImage (Image);\r
+ }\r
\r
- //\r
- // The caller must pass in a valid ParentImageHandle\r
- //\r
- if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
- return EFI_INVALID_PARAMETER;\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
+ //\r
+ Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
}\r
\r
- ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
- if (ParentImage == NULL) {\r
- DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
- return EFI_INVALID_PARAMETER;\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
- // Get simple read access to the source file\r
+ // Unload image, free Image->ImageContext->ModHandle\r
//\r
- OriginalFilePath = FilePath;\r
- Status = CoreOpenImageFile (\r
- BootPolicy,\r
- SourceBuffer,\r
- SourceSize,\r
- &FilePath,\r
- &DeviceHandle,\r
- &FHand,\r
- &AuthenticationStatus\r
- );\r
- if (Status == EFI_ALREADY_STARTED) {\r
- Image = NULL;\r
- goto Done;\r
- } else if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ PeCoffLoaderUnloadImage (&Image->ImageContext);\r
\r
//\r
- // Verify the Authentication Status through the Security Architectural Protocol\r
+ // Free our references to the image handle\r
//\r
- if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
- SecurityStatus = gSecurity->FileAuthenticationState (\r
- gSecurity,\r
- AuthenticationStatus,\r
- OriginalFilePath\r
- );\r
- if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
- Status = SecurityStatus;\r
- Image = NULL;\r
- goto Done;\r
+ if (Image->Handle != NULL) {\r
+\r
+ Status = CoreLocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
+ Status = CoreProtocolsPerHandle (\r
+ HandleBuffer[HandleIndex],\r
+ &ProtocolGuidArray,\r
+ &ArrayCount\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
+ Status = CoreOpenProtocolInformation (\r
+ HandleBuffer[HandleIndex],\r
+ ProtocolGuidArray[ProtocolIndex],\r
+ &OpenInfo,\r
+ &OpenInfoCount\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
+ if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
+ Status = CoreCloseProtocol (\r
+ HandleBuffer[HandleIndex],\r
+ ProtocolGuidArray[ProtocolIndex],\r
+ Image->Handle,\r
+ OpenInfo[OpenInfoIndex].ControllerHandle\r
+ );\r
+ }\r
+ }\r
+ if (OpenInfo != NULL) {\r
+ CoreFreePool(OpenInfo);\r
+ }\r
+ }\r
+ }\r
+ if (ProtocolGuidArray != NULL) {\r
+ CoreFreePool(ProtocolGuidArray);\r
+ }\r
+ }\r
+ }\r
+ if (HandleBuffer != NULL) {\r
+ CoreFreePool (HandleBuffer);\r
+ }\r
+ }\r
+\r
+ CoreRemoveDebugImageInfoEntry (Image->Handle);\r
+\r
+ Status = CoreUninstallProtocolInterface (\r
+ Image->Handle,\r
+ &gEfiLoadedImageDevicePathProtocolGuid,\r
+ Image->LoadedImageDevicePath\r
+ );\r
+\r
+ Status = CoreUninstallProtocolInterface (\r
+ Image->Handle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ &Image->Info\r
+ );\r
+\r
+ if (Image->ImageContext.HiiResourceData != 0) {\r
+ Status = CoreUninstallProtocolInterface (\r
+ Image->Handle,\r
+ &gEfiHiiPackageListProtocolGuid,\r
+ (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
+ );\r
+ }\r
+\r
+ }\r
+\r
+ if (Image->RuntimeData != NULL) {\r
+ if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
+ //\r
+ // Remove the Image from the Runtime Image list as we are about to Free it!\r
+ //\r
+ RemoveEntryList (&Image->RuntimeData->Link);\r
+ RemoveImageRecord (Image->RuntimeData);\r
+ }\r
+ CoreFreePool (Image->RuntimeData);\r
+ }\r
+\r
+ //\r
+ // Free the Image from memory\r
+ //\r
+ if ((Image->ImageBasePage != 0) && FreePage) {\r
+ CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
+ }\r
+\r
+ //\r
+ // Done with the Image structure\r
+ //\r
+ if (Image->Info.FilePath != NULL) {\r
+ CoreFreePool (Image->Info.FilePath);\r
+ }\r
+\r
+ if (Image->LoadedImageDevicePath != NULL) {\r
+ CoreFreePool (Image->LoadedImageDevicePath);\r
+ }\r
+\r
+ if (Image->FixupData != NULL) {\r
+ CoreFreePool (Image->FixupData);\r
+ }\r
+\r
+ CoreFreePool (Image);\r
+}\r
+\r
+\r
+/**\r
+ Loads an EFI image into memory and returns a handle to the image.\r
+\r
+ @param BootPolicy If TRUE, indicates that the request originates\r
+ from the boot manager, and that the boot\r
+ manager is attempting to load FilePath as a\r
+ boot selection.\r
+ @param ParentImageHandle The caller's image handle.\r
+ @param FilePath The specific file path from which the image is\r
+ loaded.\r
+ @param SourceBuffer If not NULL, a pointer to the memory location\r
+ containing a copy of the image to be loaded.\r
+ @param SourceSize The size in bytes of SourceBuffer.\r
+ @param DstBuffer The buffer to store the image\r
+ @param NumberOfPages If not NULL, it inputs a pointer to the page\r
+ number of DstBuffer and outputs a pointer to\r
+ the page number of the image. If this number is\r
+ not enough, return EFI_BUFFER_TOO_SMALL and\r
+ this parameter contains the required number.\r
+ @param ImageHandle Pointer to the returned image handle that is\r
+ created when the image is successfully loaded.\r
+ @param EntryPoint A pointer to the entry point\r
+ @param Attribute The bit mask of attributes to set for the load\r
+ PE image\r
+\r
+ @retval EFI_SUCCESS The image was loaded into memory.\r
+ @retval EFI_NOT_FOUND The FilePath was not found.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small\r
+ @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
+ path cannot be parsed to locate the proper\r
+ protocol for loading the file.\r
+ @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
+ resources.\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
+ 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
+ platform policy specifies that the image should not be started.\r
+\r
+**/\r
+EFI_STATUS\r
+CoreLoadImageCommon (\r
+ IN BOOLEAN BootPolicy,\r
+ IN EFI_HANDLE ParentImageHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN VOID *SourceBuffer OPTIONAL,\r
+ IN UINTN SourceSize,\r
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
+ IN OUT UINTN *NumberOfPages OPTIONAL,\r
+ OUT EFI_HANDLE *ImageHandle,\r
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
+ IN UINT32 Attribute\r
+ )\r
+{\r
+ LOADED_IMAGE_PRIVATE_DATA *Image;\r
+ LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
+ IMAGE_FILE_HANDLE FHand;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS SecurityStatus;\r
+ EFI_HANDLE DeviceHandle;\r
+ UINT32 AuthenticationStatus;\r
+ EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *InputFilePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ UINTN FilePathSize;\r
+ BOOLEAN ImageIsFromFv;\r
+ BOOLEAN ImageIsFromLoadFile;\r
+\r
+ SecurityStatus = EFI_SUCCESS;\r
+\r
+ ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
+ ParentImage = NULL;\r
+\r
+ //\r
+ // The caller must pass in a valid ParentImageHandle\r
+ //\r
+ if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
+ if (ParentImage == NULL) {\r
+ DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));\r
+ FHand.Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
+ OriginalFilePath = FilePath;\r
+ InputFilePath = FilePath;\r
+ HandleFilePath = FilePath;\r
+ DeviceHandle = NULL;\r
+ Status = EFI_SUCCESS;\r
+ AuthenticationStatus = 0;\r
+ ImageIsFromFv = FALSE;\r
+ ImageIsFromLoadFile = FALSE;\r
+\r
+ //\r
+ // If the caller passed a copy of the file, then just use it\r
+ //\r
+ if (SourceBuffer != NULL) {\r
+ FHand.Source = SourceBuffer;\r
+ FHand.SourceSize = SourceSize;\r
+ Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ DeviceHandle = NULL;\r
+ }\r
+ if (SourceSize > 0) {\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_LOAD_ERROR;\r
+ }\r
+ } else {\r
+ if (FilePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Try to get the image device handle by checking the match protocol.\r
+ //\r
+ Node = NULL;\r
+ Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ ImageIsFromFv = TRUE;\r
+ } else {\r
+ HandleFilePath = FilePath;\r
+ Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ if (!BootPolicy) {\r
+ HandleFilePath = FilePath;\r
+ Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ HandleFilePath = FilePath;\r
+ Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ ImageIsFromLoadFile = TRUE;\r
+ Node = HandleFilePath;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the source file buffer by its device path.\r
+ //\r
+ FHand.Source = GetFileBufferByFilePath (\r
+ BootPolicy,\r
+ FilePath,\r
+ &FHand.SourceSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (FHand.Source == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ } else {\r
+ FHand.FreeBuffer = TRUE;\r
+ if (ImageIsFromLoadFile) {\r
+ //\r
+ // LoadFile () may cause the device path of the Handle be updated.\r
+ //\r
+ OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Image = NULL;\r
+ goto Done;\r
+ }\r
+\r
+ if (gSecurity2 != NULL) {\r
+ //\r
+ // Verify File Authentication through the Security2 Architectural Protocol\r
+ //\r
+ SecurityStatus = gSecurity2->FileAuthentication (\r
+ gSecurity2,\r
+ OriginalFilePath,\r
+ FHand.Source,\r
+ FHand.SourceSize,\r
+ BootPolicy\r
+ );\r
+ if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {\r
+ //\r
+ // When Security2 is installed, Security Architectural Protocol must be published.\r
+ //\r
+ ASSERT (gSecurity != NULL);\r
+\r
+ //\r
+ // Verify the Authentication Status through the Security Architectural Protocol\r
+ // Only on images that have been read using Firmware Volume protocol.\r
+ //\r
+ SecurityStatus = gSecurity->FileAuthenticationState (\r
+ gSecurity,\r
+ AuthenticationStatus,\r
+ OriginalFilePath\r
+ );\r
}\r
+ } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
+ //\r
+ // Verify the Authentication Status through the Security Architectural Protocol\r
+ //\r
+ SecurityStatus = gSecurity->FileAuthenticationState (\r
+ gSecurity,\r
+ AuthenticationStatus,\r
+ OriginalFilePath\r
+ );\r
}\r
\r
+ //\r
+ // Check Security Status.\r
+ //\r
+ if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
+ if (SecurityStatus == EFI_ACCESS_DENIED) {\r
+ //\r
+ // Image was not loaded because the platform policy prohibits the image from being loaded.\r
+ // It's the only place we could meet EFI_ACCESS_DENIED.\r
+ //\r
+ *ImageHandle = NULL;\r
+ }\r
+ Status = SecurityStatus;\r
+ Image = NULL;\r
+ goto Done;\r
+ }\r
\r
//\r
// Allocate a new image structure\r
//\r
- Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
+ Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
if (Image == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
\r
//\r
// Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
//\r
FilePath = OriginalFilePath;\r
- Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
- if (!EFI_ERROR (Status)) {\r
- FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
- FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );\r
+ if (DeviceHandle != NULL) {\r
+ Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
+ if (!EFI_ERROR (Status)) {\r
+ FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
+ FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );\r
+ }\r
}\r
-\r
//\r
// Initialize the fields for an internal driver\r
//\r
Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
Image->Info.SystemTable = gDxeCoreST;\r
Image->Info.DeviceHandle = DeviceHandle;\r
- Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;\r
- Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);\r
+ Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
+ Image->Info.FilePath = DuplicateDevicePath (FilePath);\r
Image->Info.ParentHandle = ParentImageHandle;\r
\r
\r
goto Done;\r
}\r
\r
+ if (NumberOfPages != NULL) {\r
+ *NumberOfPages = Image->NumberOfPages;\r
+ }\r
+\r
//\r
// Register the image in the Debug Image Info Table if the attribute is set\r
//\r
- if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {\r
+ if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {\r
CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
}\r
\r
// otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.\r
//\r
if (OriginalFilePath != NULL) {\r
- Image->LoadedImageDevicePath = CoreDuplicateDevicePath (OriginalFilePath);\r
+ Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);\r
}\r
\r
//\r
goto Done;\r
}\r
\r
+ //\r
+ // Install HII Package List Protocol onto the image handle\r
+ //\r
+ if (Image->ImageContext.HiiResourceData != 0) {\r
+ Status = CoreInstallProtocolInterface (\r
+ &Image->Handle,\r
+ &gEfiHiiPackageListProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+ ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
//\r
// Success. Return the image handle\r
//\r
if (FHand.FreeBuffer) {\r
CoreFreePool (FHand.Source);\r
}\r
+ if (OriginalFilePath != InputFilePath) {\r
+ CoreFreePool (OriginalFilePath);\r
+ }\r
\r
//\r
// There was an error. If there's an Image structure, free it\r
if (EFI_ERROR (Status)) {\r
if (Image != NULL) {\r
CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
- *ImageHandle = NULL;\r
+ Image = NULL;\r
}\r
} else if (EFI_ERROR (SecurityStatus)) {\r
Status = SecurityStatus;\r
}\r
\r
+ //\r
+ // Track the return status from LoadImage.\r
+ //\r
+ if (Image != NULL) {\r
+ Image->LoadImageStatus = Status;\r
+ }\r
+\r
return Status;\r
}\r
\r
\r
\r
+\r
+/**\r
+ Loads an EFI image into memory and returns a handle to the image.\r
+\r
+ @param BootPolicy If TRUE, indicates that the request originates\r
+ from the boot manager, and that the boot\r
+ manager is attempting to load FilePath as a\r
+ boot selection.\r
+ @param ParentImageHandle The caller's image handle.\r
+ @param FilePath The specific file path from which the image is\r
+ loaded.\r
+ @param SourceBuffer If not NULL, a pointer to the memory location\r
+ containing a copy of the image to be loaded.\r
+ @param SourceSize The size in bytes of SourceBuffer.\r
+ @param ImageHandle Pointer to the returned image handle that is\r
+ created when the image is successfully loaded.\r
+\r
+ @retval EFI_SUCCESS The image was loaded into memory.\r
+ @retval EFI_NOT_FOUND The FilePath was not found.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
+ path cannot be parsed to locate the proper\r
+ protocol for loading the file.\r
+ @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
+ resources.\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
+ 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
+ platform policy specifies that the image should not be started.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CoreLoadImage (\r
IN UINTN SourceSize,\r
OUT EFI_HANDLE *ImageHandle\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Loads an EFI image into memory and returns a handle to the image.\r
-\r
-Arguments:\r
-\r
- BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
- and that the boot manager is attempting to load FilePath as a boot selection.\r
- ParentImageHandle - The caller's image handle.\r
- FilePath - The specific file path from which the image is loaded.\r
- SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
- the image to be loaded.\r
- SourceSize - The size in bytes of SourceBuffer.\r
- ImageHandle - Pointer to the returned image handle that is created when the image\r
- is successfully loaded.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The image was loaded into memory.\r
- EFI_NOT_FOUND - The FilePath was not found.\r
- EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
- EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
- parsed to locate the proper protocol for loading the file.\r
- EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
---*/\r
{\r
EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
\r
- PERF_START (NULL, "LoadImage", NULL, 0);\r
+ PERF_LOAD_IMAGE_BEGIN (NULL);\r
\r
Status = CoreLoadImageCommon (\r
BootPolicy,\r
FilePath,\r
SourceBuffer,\r
SourceSize,\r
- (EFI_PHYSICAL_ADDRESS)NULL,\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,\r
NULL,\r
ImageHandle,\r
NULL,\r
EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
);\r
\r
- PERF_END (NULL, "LoadImage", NULL, 0);\r
+ Handle = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // ImageHandle will be valid only Status is success.\r
+ //\r
+ Handle = *ImageHandle;\r
+ }\r
+\r
+ PERF_LOAD_IMAGE_END (Handle);\r
\r
return Status;\r
}\r
\r
\r
+\r
+/**\r
+ Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
+\r
+ @param This Calling context\r
+ @param ParentImageHandle The caller's image handle.\r
+ @param FilePath The specific file path from which the image is\r
+ loaded.\r
+ @param SourceBuffer If not NULL, a pointer to the memory location\r
+ containing a copy of the image to be loaded.\r
+ @param SourceSize The size in bytes of SourceBuffer.\r
+ @param DstBuffer The buffer to store the image.\r
+ @param NumberOfPages For input, specifies the space size of the\r
+ image by caller if not NULL. For output,\r
+ specifies the actual space size needed.\r
+ @param ImageHandle Image handle for output.\r
+ @param EntryPoint Image entry point for output.\r
+ @param Attribute The bit mask of attributes to set for the load\r
+ PE image.\r
+\r
+ @retval EFI_SUCCESS The image was loaded into memory.\r
+ @retval EFI_NOT_FOUND The FilePath was not found.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
+ path cannot be parsed to locate the proper\r
+ protocol for loading the file.\r
+ @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
+ resources.\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
+ 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
+ platform policy specifies that the image should not be started.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CoreLoadImageEx (\r
OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
IN UINT32 Attribute\r
)\r
-/*++\r
-\r
-Routine Description:\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
\r
- Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
+ PERF_LOAD_IMAGE_BEGIN (NULL);\r
\r
-Arguments:\r
-\r
- This - Calling context\r
- ParentImageHandle - The caller's image handle.\r
- FilePath - The specific file path from which the image is loaded.\r
- SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
- the image to be loaded.\r
- SourceSize - The size in bytes of SourceBuffer.\r
- DstBuffer - The buffer to store the image.\r
- NumberOfPages - For input, specifies the space size of the image by caller if not NULL.\r
- For output, specifies the actual space size needed.\r
- ImageHandle - Image handle for output.\r
- EntryPoint - Image entry point for output.\r
- Attribute - The bit mask of attributes to set for the load PE image.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The image was loaded into memory.\r
- EFI_NOT_FOUND - The FilePath was not found.\r
- EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
- EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
- parsed to locate the proper protocol for loading the file.\r
- EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
---*/\r
-{\r
- return CoreLoadImageCommon (\r
+ Status = CoreLoadImageCommon (\r
TRUE,\r
ParentImageHandle,\r
FilePath,\r
EntryPoint,\r
Attribute\r
);\r
+\r
+ Handle = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // ImageHandle will be valid only Status is success.\r
+ //\r
+ Handle = *ImageHandle;\r
+ }\r
+\r
+ PERF_LOAD_IMAGE_END (Handle);\r
+\r
+ return Status;\r
}\r
\r
+\r
+/**\r
+ Transfer control to a loaded image's entry point.\r
+\r
+ @param ImageHandle Handle of image to be started.\r
+ @param ExitDataSize Pointer of the size to ExitData\r
+ @param ExitData Pointer to a pointer to a data buffer that\r
+ includes a Null-terminated string,\r
+ optionally followed by additional binary data.\r
+ The string is a description that the caller may\r
+ use to further indicate the reason for the\r
+ image's exit.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
+ @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.\r
+ @retval EFI_SUCCESS Successfully transfer control to the image's\r
+ entry point.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CoreStartImage (\r
OUT UINTN *ExitDataSize,\r
OUT CHAR16 **ExitData OPTIONAL\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Transfer control to a loaded image's entry point.\r
-\r
-Arguments:\r
-\r
- ImageHandle - Handle of image to be started.\r
-\r
- ExitDataSize - Pointer of the size to ExitData\r
-\r
- ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated\r
- Unicode string, optionally followed by additional binary data. The string\r
- is a description that the caller may use to further indicate the reason for\r
- the image's exit.\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - Invalid parameter\r
-\r
- EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
-\r
- EFI_SUCCESS - Successfully transfer control to the image's entry point.\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
LOADED_IMAGE_PRIVATE_DATA *Image;\r
LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
UINT64 HandleDatabaseKey;\r
UINTN SetJumpFlag;\r
+ EFI_HANDLE Handle;\r
+\r
+ Handle = ImageHandle;\r
\r
Image = CoreLoadedImageInfo (ImageHandle);\r
- if (Image == NULL_HANDLE || Image->Started) {\r
+ if (Image == NULL || Image->Started) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+ if (EFI_ERROR (Image->LoadImageStatus)) {\r
+ return Image->LoadImageStatus;\r
+ }\r
\r
//\r
- // Don't profile Objects or invalid start requests\r
+ // The image to be started must have the machine type supported by DxeCore.\r
//\r
- PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);\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
+ //\r
+ DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));\r
+ DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ PERF_START_IMAGE_BEGIN (Handle);\r
\r
\r
//\r
// JumpContext must be aligned on a CPU specific boundary.\r
// Overallocate the buffer and force the required alignment\r
//\r
- Image->JumpBuffer = CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
+ Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
if (Image->JumpBuffer == NULL) {\r
- PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\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_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
// The initial call to SetJump() must always return 0.\r
// Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
//\r
- if (!SetJumpFlag) {\r
+ if (SetJumpFlag == 0) {\r
+ RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));\r
//\r
// Call the image's entry point\r
//\r
//\r
DEBUG_CODE_BEGIN ();\r
if (EFI_ERROR (Image->Status)) {\r
- DEBUG ((EFI_D_ERROR, "Error: Image at %10p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
+ DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
}\r
DEBUG_CODE_END ();\r
\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
DEBUG_CODE_BEGIN ();\r
if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
\r
- DEBUG (\r
- (EFI_D_LOAD,\r
- "StartImage: ExitDataSize %d, ExitData %x",\r
- Image->ExitDataSize,\r
- Image->ExitData)\r
- );\r
+ DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));\r
if (Image->ExitData != NULL) {\r
- DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));\r
+ DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));\r
}\r
- DEBUG ((EFI_D_LOAD, "\n"));\r
+ DEBUG ((DEBUG_LOAD, "\n"));\r
}\r
DEBUG_CODE_END ();\r
\r
//\r
if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
CoreUnloadAndCloseImage (Image, TRUE);\r
- }\r
-\r
- //\r
- // Done\r
- //\r
- PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
- return Status;\r
-}\r
-\r
-\r
-VOID\r
-CoreUnloadAndCloseImage (\r
- IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
- IN BOOLEAN FreePage\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unloads EFI image from memory.\r
-\r
-Arguments:\r
-\r
- Image - EFI image\r
- FreePage - Free allocated pages\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN HandleIndex;\r
- EFI_GUID **ProtocolGuidArray;\r
- UINTN ArrayCount;\r
- UINTN ProtocolIndex;\r
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
- UINTN OpenInfoCount;\r
- UINTN OpenInfoIndex;\r
-\r
- if (Image->Ebc != NULL) {\r
//\r
- // If EBC protocol exists we must perform cleanups for this image.\r
+ // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.\r
//\r
- Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
- }\r
-\r
- //\r
- // Unload image, free Image->ImageContext->ModHandle\r
- //\r
- PeCoffLoaderUnloadImage (&Image->ImageContext);\r
-\r
- //\r
- // Free our references to the image handle\r
- //\r
- if (Image->Handle != NULL_HANDLE) {\r
-\r
- Status = CoreLocateHandleBuffer (\r
- AllHandles,\r
- NULL,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
- Status = CoreProtocolsPerHandle (\r
- HandleBuffer[HandleIndex],\r
- &ProtocolGuidArray,\r
- &ArrayCount\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
- Status = CoreOpenProtocolInformation (\r
- HandleBuffer[HandleIndex],\r
- ProtocolGuidArray[ProtocolIndex],\r
- &OpenInfo,\r
- &OpenInfoCount\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
- if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
- Status = CoreCloseProtocol (\r
- HandleBuffer[HandleIndex],\r
- ProtocolGuidArray[ProtocolIndex],\r
- Image->Handle,\r
- OpenInfo[OpenInfoIndex].ControllerHandle\r
- );\r
- }\r
- }\r
- if (OpenInfo != NULL) {\r
- CoreFreePool(OpenInfo);\r
- }\r
- }\r
- }\r
- if (ProtocolGuidArray != NULL) {\r
- CoreFreePool(ProtocolGuidArray);\r
- }\r
- }\r
- }\r
- if (HandleBuffer != NULL) {\r
- CoreFreePool (HandleBuffer);\r
- }\r
- }\r
-\r
- CoreRemoveDebugImageInfoEntry (Image->Handle);\r
-\r
- Status = CoreUninstallProtocolInterface (\r
- Image->Handle,\r
- &gEfiLoadedImageDevicePathProtocolGuid,\r
- Image->LoadedImageDevicePath\r
- );\r
-\r
- Status = CoreUninstallProtocolInterface (\r
- Image->Handle,\r
- &gEfiLoadedImageProtocolGuid,\r
- &Image->Info\r
- );\r
-\r
- }\r
-\r
- if (Image->RuntimeData != NULL) {\r
- if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
- //\r
- // Remove the Image from the Runtime Image list as we are about to Free it!\r
- //\r
- RemoveEntryList (&Image->RuntimeData->Link);\r
- }\r
- CoreFreePool (Image->RuntimeData);\r
- }\r
-\r
- //\r
- // Free the Image from memory\r
- //\r
- if ((Image->ImageBasePage != 0) && FreePage) {\r
- CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
+ Handle = NULL;\r
}\r
\r
//\r
- // Done with the Image structure\r
+ // Done\r
//\r
- if (Image->Info.FilePath != NULL) {\r
- CoreFreePool (Image->Info.FilePath);\r
- }\r
-\r
- if (Image->LoadedImageDevicePath != NULL) {\r
- CoreFreePool (Image->LoadedImageDevicePath);\r
- }\r
-\r
- if (Image->FixupData != NULL) {\r
- CoreFreePool (Image->FixupData);\r
- }\r
-\r
- CoreFreePool (Image);\r
+ PERF_START_IMAGE_END (Handle);\r
+ return Status;\r
}\r
\r
+/**\r
+ Terminates the currently loaded EFI image and returns control to boot services.\r
\r
-\r
+ @param ImageHandle Handle that identifies the image. This\r
+ parameter is passed to the image on entry.\r
+ @param Status The image's exit code.\r
+ @param ExitDataSize The size, in bytes, of ExitData. Ignored if\r
+ ExitStatus is EFI_SUCCESS.\r
+ @param ExitData Pointer to a data buffer that includes a\r
+ Null-terminated Unicode string, optionally\r
+ followed by additional binary data. The string\r
+ is a description that the caller may use to\r
+ further indicate the reason for the image's\r
+ exit.\r
+\r
+ @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current\r
+ image.\r
+ @retval EFI_SUCCESS Successfully terminates the currently loaded\r
+ EFI image.\r
+ @retval EFI_ACCESS_DENIED Should never reach there.\r
+ @retval EFI_OUT_OF_RESOURCES Could not allocate pool\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CoreExit (\r
IN UINTN ExitDataSize,\r
IN CHAR16 *ExitData OPTIONAL\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Terminates the currently loaded EFI image and returns control to boot services.\r
-\r
-Arguments:\r
-\r
- ImageHandle - Handle that identifies the image. This parameter is passed to the image\r
- on entry.\r
- Status - The image's exit code.\r
- ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is\r
- EFI_SUCCESS.\r
- ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,\r
- optionally followed by additional binary data. The string is a\r
- description that the caller may use to further indicate the reason for\r
- the image's exit.\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.\r
-\r
- EFI_SUCCESS - Successfully terminates the currently loaded EFI image.\r
-\r
- EFI_ACCESS_DENIED - Should never reach there.\r
-\r
- EFI_OUT_OF_RESOURCES - Could not allocate pool\r
-\r
---*/\r
{\r
LOADED_IMAGE_PRIVATE_DATA *Image;\r
EFI_TPL OldTpl;\r
//\r
// Prevent possible reentrance to this function\r
// for the same ImageHandle\r
- // \r
- OldTpl = CoreRaiseTpl (TPL_NOTIFY); \r
- \r
+ //\r
+ OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
+\r
Image = CoreLoadedImageInfo (ImageHandle);\r
- if (Image == NULL_HANDLE) {\r
+ if (Image == NULL) {\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
// Image has been started, verify this image can exit\r
//\r
if (Image != mCurrentImage) {\r
- DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));\r
+ DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
//\r
if (ExitData != NULL) {\r
Image->ExitDataSize = ExitDataSize;\r
- Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);\r
+ Image->ExitData = AllocatePool (Image->ExitDataSize);\r
if (Image->ExitData == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
\r
\r
\r
-EFI_STATUS\r
-EFIAPI\r
-CoreUnloadImage (\r
- IN EFI_HANDLE ImageHandle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
\r
+/**\r
Unloads an image.\r
\r
-Arguments:\r
-\r
- ImageHandle - Handle that identifies the image to be unloaded.\r
+ @param ImageHandle Handle that identifies the image to be\r
+ unloaded.\r
\r
-Returns:\r
+ @retval EFI_SUCCESS The image has been unloaded.\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
- EFI_SUCCESS - The image has been unloaded.\r
- EFI_UNSUPPORTED - The image has been sarted, and does not support unload.\r
- EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.\r
-\r
---*/\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreUnloadImage (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
{\r
EFI_STATUS Status;\r
LOADED_IMAGE_PRIVATE_DATA *Image;\r
- EFI_TPL OldTpl;\r
\r
- //\r
- // Prevent possible reentrance to this function\r
- // for the same ImageHandle\r
- // \r
- OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
- \r
Image = CoreLoadedImageInfo (ImageHandle);\r
if (Image == NULL ) {\r
//\r
}\r
\r
Done:\r
- CoreRestoreTpl (OldTpl);\r
return Status;\r
}\r
\r
\r
+\r
+/**\r
+ Unload the specified image.\r
+\r
+ @param This Indicates the calling context.\r
+ @param ImageHandle The specified image handle.\r
+\r
+ @retval EFI_INVALID_PARAMETER Image handle is NULL.\r
+ @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.\r
+ @retval EFI_SUCCESS Image successfully unloaded.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CoreUnloadImageEx (\r
IN EFI_PE32_IMAGE_PROTOCOL *This,\r
IN EFI_HANDLE ImageHandle\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unload the specified image.\r
-\r
-Arguments:\r
-\r
- This - Indicates the calling context.\r
-\r
- ImageHandle - The specified image handle.\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - Image handle is NULL.\r
-\r
- EFI_UNSUPPORTED - Attempt to unload an unsupported image.\r
-\r
- EFI_SUCCESS - Image successfully unloaded.\r
-\r
---*/\r
{\r
return CoreUnloadImage (ImageHandle);\r
}\r