123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /** @file
- Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Uefi.h>
- #include <Library/BaseLib.h>
- #include <Library/UefiDriverEntryPoint.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DebugLib.h>
- #include <Library/PeCoffLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/DxeServicesLib.h>
- #include <Library/CacheMaintenanceLib.h>
- #include <Library/UefiLib.h>
- /**
- 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 ((DEBUG_INFO, "FspNotifyDxe - 2nd entry\n"));
- return EFI_SUCCESS;
- }
- DEBUG ((DEBUG_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 boundary
- //
- 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 ((DEBUG_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 ((DEBUG_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;
- }
|