[PATCH v3 05/16] IntelFsp2WrapperPkg/FspWrapperNotifyDxe: Remove an
[mirror_edk2.git] / IntelFsp2WrapperPkg / FspWrapperNotifyDxe / LoadBelow4G.c
CommitLineData
cf1d4549
JY
1/** @file\r
2\r
d953f4f1 3Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
cf1d4549
JY
4\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The\r
8full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <Uefi.h>\r
17#include <Library/BaseLib.h>\r
18#include <Library/UefiDriverEntryPoint.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/PeCoffLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/DxeServicesLib.h>\r
24#include <Library/CacheMaintenanceLib.h>\r
25#include <Library/UefiLib.h>\r
26\r
27/**\r
28 Relocate this image under 4G memory.\r
29\r
30 @param ImageHandle Handle of driver image.\r
31 @param SystemTable Pointer to system table.\r
32\r
33 @retval EFI_SUCCESS Image successfully relocated.\r
34 @retval EFI_ABORTED Failed to relocate image.\r
35\r
36**/\r
37EFI_STATUS\r
38RelocateImageUnder4GIfNeeded (\r
39 IN EFI_HANDLE ImageHandle,\r
40 IN EFI_SYSTEM_TABLE *SystemTable\r
41 )\r
42{\r
43 EFI_STATUS Status;\r
44 UINT8 *Buffer;\r
45 UINTN BufferSize;\r
46 EFI_HANDLE NewImageHandle;\r
47 UINTN Pages;\r
48 EFI_PHYSICAL_ADDRESS FfsBuffer;\r
49 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
50 VOID *Interface;\r
51\r
52 //\r
53 // If it is already <4G, no need do relocate\r
54 //\r
55 if ((UINTN)RelocateImageUnder4GIfNeeded < 0xFFFFFFFF) {\r
56 return EFI_SUCCESS;\r
57 }\r
58\r
59 //\r
60 // If locate gEfiCallerIdGuid success, it means 2nd entry.\r
61 //\r
62 Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &Interface);\r
63 if (!EFI_ERROR (Status)) {\r
64 DEBUG ((DEBUG_INFO, "FspNotifyDxe - 2nd entry\n"));\r
65 return EFI_SUCCESS;\r
66 }\r
67\r
68 DEBUG ((DEBUG_INFO, "FspNotifyDxe - 1st entry\n"));\r
69\r
70 //\r
71 // Here we install a dummy handle\r
72 //\r
73 NewImageHandle = NULL;\r
74 Status = gBS->InstallProtocolInterface (\r
75 &NewImageHandle,\r
76 &gEfiCallerIdGuid,\r
77 EFI_NATIVE_INTERFACE,\r
78 NULL\r
79 );\r
80 ASSERT_EFI_ERROR (Status);\r
81\r
82 //\r
83 // Reload image itself to <4G mem\r
84 //\r
85 Status = GetSectionFromAnyFv (\r
86 &gEfiCallerIdGuid,\r
87 EFI_SECTION_PE32,\r
88 0,\r
89 (VOID **) &Buffer,\r
90 &BufferSize\r
91 );\r
92 ASSERT_EFI_ERROR (Status);\r
93 ImageContext.Handle = Buffer;\r
94 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
95 //\r
96 // Get information about the image being loaded\r
97 //\r
98 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
99 ASSERT_EFI_ERROR (Status);\r
100 if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
101 Pages = EFI_SIZE_TO_PAGES ((UINTN) (ImageContext.ImageSize + ImageContext.SectionAlignment));\r
102 } else {\r
103 Pages = EFI_SIZE_TO_PAGES ((UINTN) ImageContext.ImageSize);\r
104 }\r
105 FfsBuffer = 0xFFFFFFFF;\r
106 Status = gBS->AllocatePages (\r
107 AllocateMaxAddress,\r
108 EfiBootServicesCode,\r
109 Pages,\r
110 &FfsBuffer\r
111 );\r
112 ASSERT_EFI_ERROR (Status);\r
113 ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;\r
114 //\r
0bfb9ee8 115 // Align buffer on section boundary\r
cf1d4549
JY
116 //\r
117 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
d953f4f1 118 ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
cf1d4549
JY
119 //\r
120 // Load the image to our new buffer\r
121 //\r
122 Status = PeCoffLoaderLoadImage (&ImageContext);\r
123 ASSERT_EFI_ERROR (Status);\r
124\r
125 //\r
126 // Relocate the image in our new buffer\r
127 //\r
128 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
129 ASSERT_EFI_ERROR (Status);\r
130\r
131 //\r
132 // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer\r
133 //\r
134 gBS->FreePool (Buffer);\r
135\r
136 //\r
137 // Flush the instruction cache so the image data is written before we execute it\r
138 //\r
139 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
140\r
141 DEBUG ((DEBUG_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint));\r
142 Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, gST);\r
143 if (EFI_ERROR (Status)) {\r
144 DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status));\r
145 gBS->FreePages (FfsBuffer, Pages);\r
146 }\r
147\r
148 //\r
149 // return error to unload >4G copy, if we already relocate itself to <4G.\r
150 //\r
151 return EFI_ALREADY_STARTED;\r
152}\r