EmbeddedPkg/PrePiLib: Correct function name
[mirror_edk2.git] / IntelFsp2WrapperPkg / FspWrapperNotifyDxe / LoadBelow4G.c
1 /** @file\r
2 \r
3 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
4 \r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions\r
7 of the BSD License which accompanies this distribution.  The\r
8 full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT 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
37 EFI_STATUS\r
38 RelocateImageUnder4GIfNeeded (\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
115   // Align buffer on section boundary\r
116   //\r
117   ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
118   ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
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