From 00899456b809b7a0809e92d3e020435eece0effd Mon Sep 17 00:00:00 2001 From: "Yao, Jiewen" Date: Tue, 28 Jul 2015 07:26:57 +0000 Subject: [PATCH] FspNotifyDxe need handle >4G memory. The FSP API is always 32bit, but FspNotifyDxe might load to >4G memory. In order to make thunk work, we need reload FspNotifyDxe to <4G memory. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Yao, Jiewen" Reviewed-by: "Mudusuru, Giri P" git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18094 6f19259b-4bc3-4df7-8a09-765794883524 --- .../FspNotifyDxe/FspNotifyDxe.c | 24 +++ .../FspNotifyDxe/FspNotifyDxe.inf | 4 + IntelFspWrapperPkg/FspNotifyDxe/LoadBelow4G.c | 152 ++++++++++++++++++ IntelFspWrapperPkg/IntelFspWrapperPkg.dsc | 2 + 4 files changed, 182 insertions(+) create mode 100644 IntelFspWrapperPkg/FspNotifyDxe/LoadBelow4G.c diff --git a/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.c b/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.c index f8e8e826f1..1a1e4e6258 100644 --- a/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.c +++ b/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.c @@ -23,6 +23,22 @@ #include #include +/** + Relocate this image under 4G memory. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + FSP_INFO_HEADER *mFspHeader = NULL; /** @@ -120,6 +136,14 @@ FspDxeEntryPoint ( VOID *Registration; EFI_EVENT ProtocolNotifyEvent; + // + // Load this driver's image to memory + // + Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + if (PcdGet32 (PcdFlashFvSecondFspBase) == 0) { mFspHeader = FspFindFspHeader (PcdGet32 (PcdFlashFvFspBase)); } else { diff --git a/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf b/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf index 8175dbd324..66970cc380 100644 --- a/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf +++ b/IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf @@ -30,6 +30,7 @@ [Sources] FspNotifyDxe.c + LoadBelow4G.c [Packages] MdePkg/MdePkg.dec @@ -43,6 +44,9 @@ BaseMemoryLib UefiLib FspApiLib + PeCoffLib + CacheMaintenanceLib + DxeServicesLib [Protocols] gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES diff --git a/IntelFspWrapperPkg/FspNotifyDxe/LoadBelow4G.c b/IntelFspWrapperPkg/FspNotifyDxe/LoadBelow4G.c new file mode 100644 index 0000000000..d39164e1fe --- /dev/null +++ b/IntelFspWrapperPkg/FspNotifyDxe/LoadBelow4G.c @@ -0,0 +1,152 @@ +/** @file + +Copyright (c) 2015, 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 +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Relocate this image under 4G memory. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + EFI_HANDLE NewImageHandle; + UINTN Pages; + EFI_PHYSICAL_ADDRESS FfsBuffer; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + VOID *Interface; + + // + // If it is already <4G, no need do relocate + // + if ((UINTN)RelocateImageUnder4GIfNeeded < 0xFFFFFFFF) { + return EFI_SUCCESS; + } + + // + // If locate gEfiCallerIdGuid success, it means 2nd entry. + // + Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &Interface); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "FspNotifyDxe - 2nd entry\n")); + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_INFO, "FspNotifyDxe - 1st entry\n")); + + // + // Here we install a dummy handle + // + NewImageHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &NewImageHandle, + &gEfiCallerIdGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Reload image itself to <4G mem + // + Status = GetSectionFromAnyFv ( + &gEfiCallerIdGuid, + EFI_SECTION_PE32, + 0, + (VOID **) &Buffer, + &BufferSize + ); + ASSERT_EFI_ERROR (Status); + ImageContext.Handle = Buffer; + ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; + // + // Get information about the image being loaded + // + Status = PeCoffLoaderGetImageInfo (&ImageContext); + ASSERT_EFI_ERROR (Status); + if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) { + Pages = EFI_SIZE_TO_PAGES ((UINTN) (ImageContext.ImageSize + ImageContext.SectionAlignment)); + } else { + Pages = EFI_SIZE_TO_PAGES ((UINTN) ImageContext.ImageSize); + } + FfsBuffer = 0xFFFFFFFF; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesCode, + Pages, + &FfsBuffer + ); + ASSERT_EFI_ERROR (Status); + ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer; + // + // Align buffer on section boundry + // + ImageContext.ImageAddress += ImageContext.SectionAlignment - 1; + ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1)); + // + // Load the image to our new buffer + // + Status = PeCoffLoaderLoadImage (&ImageContext); + ASSERT_EFI_ERROR (Status); + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoaderRelocateImage (&ImageContext); + ASSERT_EFI_ERROR (Status); + + // + // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer + // + gBS->FreePool (Buffer); + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + DEBUG ((EFI_D_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint)); + Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, gST); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status)); + gBS->FreePages (FfsBuffer, Pages); + } + + // + // return error to unload >4G copy, if we already relocate itself to <4G. + // + return EFI_ALREADY_STARTED; +} diff --git a/IntelFspWrapperPkg/IntelFspWrapperPkg.dsc b/IntelFspWrapperPkg/IntelFspWrapperPkg.dsc index dbd05a1272..04677c3231 100644 --- a/IntelFspWrapperPkg/IntelFspWrapperPkg.dsc +++ b/IntelFspWrapperPkg/IntelFspWrapperPkg.dsc @@ -34,6 +34,7 @@ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf # Dummy - test build only SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf @@ -66,6 +67,7 @@ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf UefiLib|MdePkg/Library/UefiLib/UefiLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf