3 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent
\r
10 #include <Library/BaseLib.h>
\r
11 #include <Library/UefiDriverEntryPoint.h>
\r
12 #include <Library/BaseMemoryLib.h>
\r
13 #include <Library/DebugLib.h>
\r
14 #include <Library/PeCoffLib.h>
\r
15 #include <Library/UefiBootServicesTableLib.h>
\r
16 #include <Library/DxeServicesLib.h>
\r
17 #include <Library/CacheMaintenanceLib.h>
\r
18 #include <Library/UefiLib.h>
\r
21 Relocate this image under 4G memory.
\r
23 @param ImageHandle Handle of driver image.
\r
24 @param SystemTable Pointer to system table.
\r
26 @retval EFI_SUCCESS Image successfully relocated.
\r
27 @retval EFI_ABORTED Failed to relocate image.
\r
31 RelocateImageUnder4GIfNeeded (
\r
32 IN EFI_HANDLE ImageHandle,
\r
33 IN EFI_SYSTEM_TABLE *SystemTable
\r
39 EFI_HANDLE NewImageHandle;
\r
41 EFI_PHYSICAL_ADDRESS FfsBuffer;
\r
42 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
\r
46 // If it is already <4G, no need do relocate
\r
48 if ((UINTN)RelocateImageUnder4GIfNeeded < 0xFFFFFFFF) {
\r
53 // If locate gEfiCallerIdGuid success, it means 2nd entry.
\r
55 Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &Interface);
\r
56 if (!EFI_ERROR (Status)) {
\r
57 DEBUG ((DEBUG_INFO, "FspNotifyDxe - 2nd entry\n"));
\r
61 DEBUG ((DEBUG_INFO, "FspNotifyDxe - 1st entry\n"));
\r
64 // Here we install a dummy handle
\r
66 NewImageHandle = NULL;
\r
67 Status = gBS->InstallProtocolInterface (
\r
70 EFI_NATIVE_INTERFACE,
\r
73 ASSERT_EFI_ERROR (Status);
\r
76 // Reload image itself to <4G mem
\r
78 Status = GetSectionFromAnyFv (
\r
85 ASSERT_EFI_ERROR (Status);
\r
86 ImageContext.Handle = Buffer;
\r
87 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
\r
89 // Get information about the image being loaded
\r
91 Status = PeCoffLoaderGetImageInfo (&ImageContext);
\r
92 ASSERT_EFI_ERROR (Status);
\r
93 if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
\r
94 Pages = EFI_SIZE_TO_PAGES ((UINTN) (ImageContext.ImageSize + ImageContext.SectionAlignment));
\r
96 Pages = EFI_SIZE_TO_PAGES ((UINTN) ImageContext.ImageSize);
\r
98 FfsBuffer = 0xFFFFFFFF;
\r
99 Status = gBS->AllocatePages (
\r
100 AllocateMaxAddress,
\r
101 EfiBootServicesCode,
\r
105 ASSERT_EFI_ERROR (Status);
\r
106 ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
\r
108 // Align buffer on section boundary
\r
110 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
\r
111 ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
\r
113 // Load the image to our new buffer
\r
115 Status = PeCoffLoaderLoadImage (&ImageContext);
\r
116 ASSERT_EFI_ERROR (Status);
\r
119 // Relocate the image in our new buffer
\r
121 Status = PeCoffLoaderRelocateImage (&ImageContext);
\r
122 ASSERT_EFI_ERROR (Status);
\r
125 // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
\r
127 gBS->FreePool (Buffer);
\r
130 // Flush the instruction cache so the image data is written before we execute it
\r
132 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
\r
134 DEBUG ((DEBUG_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint));
\r
135 Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, gST);
\r
136 if (EFI_ERROR (Status)) {
\r
137 DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status));
\r
138 gBS->FreePages (FfsBuffer, Pages);
\r
142 // return error to unload >4G copy, if we already relocate itself to <4G.
\r
144 return EFI_ALREADY_STARTED;
\r