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 ((EFI_D_INFO
, "FspNotifyDxe - 2nd entry\n"));
61 DEBUG ((EFI_D_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
);
98 FfsBuffer
= 0xFFFFFFFF;
99 Status
= gBS
->AllocatePages (
105 ASSERT_EFI_ERROR (Status
);
106 ImageContext
.ImageAddress
= (PHYSICAL_ADDRESS
)(UINTN
)FfsBuffer
;
108 // Align buffer on section boundary
110 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
111 ImageContext
.ImageAddress
&= ~((EFI_PHYSICAL_ADDRESS
)ImageContext
.SectionAlignment
- 1);
113 // Load the image to our new buffer
115 Status
= PeCoffLoaderLoadImage (&ImageContext
);
116 ASSERT_EFI_ERROR (Status
);
119 // Relocate the image in our new buffer
121 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
122 ASSERT_EFI_ERROR (Status
);
125 // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
127 gBS
->FreePool (Buffer
);
130 // Flush the instruction cache so the image data is written before we execute it
132 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
134 DEBUG ((EFI_D_INFO
, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.EntryPoint
));
135 Status
= ((EFI_IMAGE_ENTRY_POINT
)(UINTN
)(ImageContext
.EntryPoint
)) (NewImageHandle
, gST
);
136 if (EFI_ERROR (Status
)) {
137 DEBUG ((EFI_D_ERROR
, "Error: Image at 0x%08x start failed: %r\n", ImageContext
.ImageAddress
, Status
));
138 gBS
->FreePages (FfsBuffer
, Pages
);
142 // return error to unload >4G copy, if we already relocate itself to <4G.
144 return EFI_ALREADY_STARTED
;