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