X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FImage%2FImage.c;h=5b441f03fbbf089edb78a32a83d3fe63eb661d2a;hp=56d93ade805d863a246260013c4b774ab1af0139;hb=84edd20bd0756ef5719835498d4283435d6b5e77;hpb=31222776dbf72d2953445ce4bcc735bf196e6b4f diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index 56d93ade80..5b441f03fb 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -1,7 +1,7 @@ /** @file Core image handling services to load and unload PeImage. -Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -77,6 +77,46 @@ LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = { // GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mDxeCodeMemoryRangeUsageBitMap=NULL; +typedef struct { + UINT16 MachineType; + CHAR16 *MachineTypeName; +} MACHINE_TYPE_INFO; + +// +// EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type. +// +GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo[] = { + {EFI_IMAGE_MACHINE_IA32, L"IA32"}, + {EFI_IMAGE_MACHINE_IA64, L"IA64"}, + {EFI_IMAGE_MACHINE_X64, L"X64"}, + {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"} +}; + +UINT16 mDxeCoreImageMachineType = 0; + +/** + Return machine type name. + + @param MachineType The machine type + + @return machine type name +**/ +CHAR16 * +GetMachineTypeName ( + UINT16 MachineType + ) +{ + UINTN Index; + + for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) { + if (mMachineTypeInfo[Index].MachineType == MachineType) { + return mMachineTypeInfo[Index].MachineTypeName; + } + } + + return L""; +} + /** Add the Image Services to EFI Boot Services Table and install the protocol interfaces for this image. @@ -147,6 +187,7 @@ CoreInitializeImageServices ( // // Fill in DXE globals // + mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase); gDxeCoreImageHandle = Image->Handle; gDxeCoreLoadedImage = &Image->Info; @@ -191,6 +232,14 @@ CoreReadImageFile ( UINTN EndPosition; IMAGE_FILE_HANDLE *FHand; + if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (MAX_ADDRESS - Offset < *ReadSize) { + return EFI_INVALID_PARAMETER; + } + FHand = (IMAGE_FILE_HANDLE *)UserHandle; ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE); @@ -340,7 +389,10 @@ GetPeCoffImageFixLoadingAssignedAddress( if (EFI_ERROR (Status)) { return Status; } - + if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) { + return EFI_NOT_FOUND; + } + Status = EFI_NOT_FOUND; if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { @@ -426,6 +478,8 @@ CoreLoadPeImage ( // The PE/COFF loader can support loading image types that can be executed. // If we loaded an image type that we can not execute return EFI_UNSUPORTED. // + DEBUG ((EFI_D_ERROR, "Image type %s can't be loaded ", GetMachineTypeName(Image->ImageContext.Machine))); + DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType))); return EFI_UNSUPPORTED; } } @@ -800,6 +854,9 @@ CoreUnloadAndCloseImage ( UINTN OpenInfoCount; UINTN OpenInfoIndex; + HandleBuffer = NULL; + ProtocolGuidArray = NULL; + if (Image->Ebc != NULL) { // // If EBC protocol exists we must perform cleanups for this image. @@ -993,6 +1050,7 @@ CoreLoadImageCommon ( EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath; EFI_DEVICE_PATH_PROTOCOL *HandleFilePath; UINTN FilePathSize; + BOOLEAN ImageIsFromFv; SecurityStatus = EFI_SUCCESS; @@ -1019,13 +1077,18 @@ CoreLoadImageCommon ( DeviceHandle = NULL; Status = EFI_SUCCESS; AuthenticationStatus = 0; + ImageIsFromFv = FALSE; + // // If the caller passed a copy of the file, then just use it // if (SourceBuffer != NULL) { FHand.Source = SourceBuffer; FHand.SourceSize = SourceSize; - CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle); + Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle); + if (EFI_ERROR (Status)) { + DeviceHandle = NULL; + } if (SourceSize > 0) { Status = EFI_SUCCESS; } else { @@ -1052,7 +1115,9 @@ CoreLoadImageCommon ( // FHand.FreeBuffer = TRUE; Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle); - if (EFI_ERROR (Status)) { + if (!EFI_ERROR (Status)) { + ImageIsFromFv = TRUE; + } else { HandleFilePath = FilePath; Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle); if (EFI_ERROR (Status)) { @@ -1069,43 +1134,72 @@ CoreLoadImageCommon ( } } - if (Status == EFI_ALREADY_STARTED) { + if (EFI_ERROR (Status)) { Image = NULL; goto Done; - } else if (EFI_ERROR (Status)) { - return Status; } - // - // Verify the Authentication Status through the Security Architectural Protocol - // - if ((gSecurity != NULL) && (OriginalFilePath != NULL)) { + if (gSecurity2 != NULL) { + // + // Verify File Authentication through the Security2 Architectural Protocol + // + SecurityStatus = gSecurity2->FileAuthentication ( + gSecurity2, + OriginalFilePath, + FHand.Source, + FHand.SourceSize, + BootPolicy + ); + if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) { + // + // When Security2 is installed, Security Architectural Protocol must be published. + // + ASSERT (gSecurity != NULL); + + // + // Verify the Authentication Status through the Security Architectural Protocol + // Only on images that have been read using Firmware Volume protocol. + // + SecurityStatus = gSecurity->FileAuthenticationState ( + gSecurity, + AuthenticationStatus, + OriginalFilePath + ); + } + } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) { + // + // Verify the Authentication Status through the Security Architectural Protocol + // SecurityStatus = gSecurity->FileAuthenticationState ( gSecurity, AuthenticationStatus, OriginalFilePath ); - if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) { - if (SecurityStatus == EFI_ACCESS_DENIED) { - // - // Image was not loaded because the platform policy prohibits the image from being loaded. - // It's the only place we could meet EFI_ACCESS_DENIED. - // - *ImageHandle = NULL; - } - Status = SecurityStatus; - Image = NULL; - goto Done; - } } + // + // Check Security Status. + // + if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) { + if (SecurityStatus == EFI_ACCESS_DENIED) { + // + // Image was not loaded because the platform policy prohibits the image from being loaded. + // It's the only place we could meet EFI_ACCESS_DENIED. + // + *ImageHandle = NULL; + } + Status = SecurityStatus; + Image = NULL; + goto Done; + } // // Allocate a new image structure // Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA)); if (Image == NULL) { - return EFI_OUT_OF_RESOURCES; + Status = EFI_OUT_OF_RESOURCES; + goto Done; } // @@ -1244,11 +1338,19 @@ Done: if (EFI_ERROR (Status)) { if (Image != NULL) { CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0)); + Image = NULL; } } else if (EFI_ERROR (SecurityStatus)) { Status = SecurityStatus; } + // + // Track the return status from LoadImage. + // + if (Image != NULL) { + Image->LoadImageStatus = Status; + } + return Status; } @@ -1302,6 +1404,7 @@ CoreLoadImage ( { EFI_STATUS Status; UINT64 Tick; + EFI_HANDLE Handle; Tick = 0; PERF_CODE ( @@ -1321,8 +1424,16 @@ CoreLoadImage ( EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION ); - PERF_START (*ImageHandle, "LoadImage:", NULL, Tick); - PERF_END (*ImageHandle, "LoadImage:", NULL, 0); + Handle = NULL; + if (!EFI_ERROR (Status)) { + // + // ImageHandle will be valid only Status is success. + // + Handle = *ImageHandle; + } + + PERF_START (Handle, "LoadImage:", NULL, Tick); + PERF_END (Handle, "LoadImage:", NULL, 0); return Status; } @@ -1381,7 +1492,16 @@ CoreLoadImageEx ( IN UINT32 Attribute ) { - return CoreLoadImageCommon ( + EFI_STATUS Status; + UINT64 Tick; + EFI_HANDLE Handle; + + Tick = 0; + PERF_CODE ( + Tick = GetPerformanceCounter (); + ); + + Status = CoreLoadImageCommon ( TRUE, ParentImageHandle, FilePath, @@ -1393,6 +1513,19 @@ CoreLoadImageEx ( EntryPoint, Attribute ); + + Handle = NULL; + if (!EFI_ERROR (Status)) { + // + // ImageHandle will be valid only Status is success. + // + Handle = *ImageHandle; + } + + PERF_START (Handle, "LoadImage:", NULL, Tick); + PERF_END (Handle, "LoadImage:", NULL, 0); + + return Status; } @@ -1410,6 +1543,7 @@ CoreLoadImageEx ( @retval EFI_INVALID_PARAMETER Invalid parameter @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started. @retval EFI_SUCCESS Successfully transfer control to the image's entry point. @@ -1427,24 +1561,36 @@ CoreStartImage ( LOADED_IMAGE_PRIVATE_DATA *LastImage; UINT64 HandleDatabaseKey; UINTN SetJumpFlag; + UINT64 Tick; + EFI_HANDLE Handle; + + Tick = 0; + Handle = ImageHandle; Image = CoreLoadedImageInfo (ImageHandle); if (Image == NULL || Image->Started) { return EFI_INVALID_PARAMETER; } + if (EFI_ERROR (Image->LoadImageStatus)) { + return Image->LoadImageStatus; + } // // The image to be started must have the machine type supported by DxeCore. // - ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)); if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) { + // + // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED + // But it can not be started. + // + DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine))); + DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType))); return EFI_UNSUPPORTED; } - // - // Don't profile Objects or invalid start requests - // - PERF_START (ImageHandle, "StartImage:", NULL, 0); + PERF_CODE ( + Tick = GetPerformanceCounter (); + ); // @@ -1464,7 +1610,12 @@ CoreStartImage ( // Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT); if (Image->JumpBuffer == NULL) { - PERF_END (ImageHandle, "StartImage:", NULL, 0); + // + // Image may be unloaded after return with failure, + // then ImageHandle may be invalid, so use NULL handle to record perf log. + // + PERF_START (NULL, "StartImage:", NULL, Tick); + PERF_END (NULL, "StartImage:", NULL, 0); return EFI_OUT_OF_RESOURCES; } Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT); @@ -1475,6 +1626,7 @@ CoreStartImage ( // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump(). // if (SetJumpFlag == 0) { + RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER)); // // Call the image's entry point // @@ -1555,12 +1707,17 @@ CoreStartImage ( // if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { CoreUnloadAndCloseImage (Image, TRUE); + // + // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log. + // + Handle = NULL; } // // Done // - PERF_END (ImageHandle, "StartImage:", NULL, 0); + PERF_START (Handle, "StartImage:", NULL, Tick); + PERF_END (Handle, "StartImage:", NULL, 0); return Status; } @@ -1695,6 +1852,7 @@ CoreUnloadImage ( Status = EFI_INVALID_PARAMETER; goto Done; } + UnregisterMemoryProfileImage (Image); if (Image->Started) { //