3 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/UefiDriverEntryPoint.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/PeCoffLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/DxeServicesLib.h>
24 #include <Library/CacheMaintenanceLib.h>
25 #include <Library/UefiLib.h>
28 Relocate this image under 4G memory.
30 @param ImageHandle Handle of driver image.
31 @param SystemTable Pointer to system table.
33 @retval EFI_SUCCESS Image successfully relocated.
34 @retval EFI_ABORTED Failed to relocate image.
38 RelocateImageUnder4GIfNeeded (
39 IN EFI_HANDLE ImageHandle
,
40 IN EFI_SYSTEM_TABLE
*SystemTable
46 EFI_HANDLE NewImageHandle
;
48 EFI_PHYSICAL_ADDRESS FfsBuffer
;
49 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
53 // If it is already <4G, no need do relocate
55 if ((UINTN
)RelocateImageUnder4GIfNeeded
< 0xFFFFFFFF) {
60 // If locate gEfiCallerIdGuid success, it means 2nd entry.
62 Status
= gBS
->LocateProtocol (&gEfiCallerIdGuid
, NULL
, &Interface
);
63 if (!EFI_ERROR (Status
)) {
64 DEBUG ((EFI_D_INFO
, "FspNotifyDxe - 2nd entry\n"));
68 DEBUG ((EFI_D_INFO
, "FspNotifyDxe - 1st entry\n"));
71 // Here we install a dummy handle
73 NewImageHandle
= NULL
;
74 Status
= gBS
->InstallProtocolInterface (
80 ASSERT_EFI_ERROR (Status
);
83 // Reload image itself to <4G mem
85 Status
= GetSectionFromAnyFv (
92 ASSERT_EFI_ERROR (Status
);
93 ImageContext
.Handle
= Buffer
;
94 ImageContext
.ImageRead
= PeCoffLoaderImageReadFromMemory
;
96 // Get information about the image being loaded
98 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
99 ASSERT_EFI_ERROR (Status
);
100 if (ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
101 Pages
= EFI_SIZE_TO_PAGES ((UINTN
) (ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
));
103 Pages
= EFI_SIZE_TO_PAGES ((UINTN
) ImageContext
.ImageSize
);
105 FfsBuffer
= 0xFFFFFFFF;
106 Status
= gBS
->AllocatePages (
112 ASSERT_EFI_ERROR (Status
);
113 ImageContext
.ImageAddress
= (PHYSICAL_ADDRESS
)(UINTN
)FfsBuffer
;
115 // Align buffer on section boundry
117 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
118 ImageContext
.ImageAddress
&= ~((EFI_PHYSICAL_ADDRESS
)(ImageContext
.SectionAlignment
- 1));
120 // Load the image to our new buffer
122 Status
= PeCoffLoaderLoadImage (&ImageContext
);
123 ASSERT_EFI_ERROR (Status
);
126 // Relocate the image in our new buffer
128 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
129 ASSERT_EFI_ERROR (Status
);
132 // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
134 gBS
->FreePool (Buffer
);
137 // Flush the instruction cache so the image data is written before we execute it
139 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
141 DEBUG ((EFI_D_INFO
, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.EntryPoint
));
142 Status
= ((EFI_IMAGE_ENTRY_POINT
)(UINTN
)(ImageContext
.EntryPoint
)) (NewImageHandle
, gST
);
143 if (EFI_ERROR (Status
)) {
144 DEBUG ((EFI_D_ERROR
, "Error: Image at 0x%08x start failed: %r\n", ImageContext
.ImageAddress
, Status
));
145 gBS
->FreePages (FfsBuffer
, Pages
);
149 // return error to unload >4G copy, if we already relocate itself to <4G.
151 return EFI_ALREADY_STARTED
;