1 /** @file
2 
3   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PrePi.h>
10 
11 //
12 // Hack to work in NT32
13 //
14 EFI_STATUS
15 
16 EFIAPI
17 
18 SecWinNtPeiLoadFile (
19   IN  VOID                    *Pe32Data,
20   IN  EFI_PHYSICAL_ADDRESS    *ImageAddress,
21   IN  UINT64                  *ImageSize,
22   IN  EFI_PHYSICAL_ADDRESS    *EntryPoint
23   );
24 
25 STATIC
26 VOID*
27 EFIAPI
AllocateCodePages(IN UINTN Pages)28 AllocateCodePages (
29   IN  UINTN     Pages
30   )
31 {
32   VOID                    *Alloc;
33   EFI_PEI_HOB_POINTERS    Hob;
34 
35   Alloc = AllocatePages (Pages);
36   if (Alloc == NULL) {
37     return NULL;
38   }
39 
40   // find the HOB we just created, and change the type to EfiBootServicesCode
41   Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
42   while (Hob.Raw != NULL) {
43     if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == (UINTN)Alloc) {
44       Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiBootServicesCode;
45       return Alloc;
46     }
47     Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (Hob));
48   }
49 
50   ASSERT (FALSE);
51 
52   FreePages (Alloc, Pages);
53   return NULL;
54 }
55 
56 
57 EFI_STATUS
58 EFIAPI
LoadPeCoffImage(IN VOID * PeCoffImage,OUT EFI_PHYSICAL_ADDRESS * ImageAddress,OUT UINT64 * ImageSize,OUT EFI_PHYSICAL_ADDRESS * EntryPoint)59 LoadPeCoffImage (
60   IN  VOID                                      *PeCoffImage,
61   OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress,
62   OUT UINT64                                    *ImageSize,
63   OUT EFI_PHYSICAL_ADDRESS                      *EntryPoint
64   )
65 {
66   RETURN_STATUS                 Status;
67   PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
68   VOID                           *Buffer;
69 
70   ZeroMem (&ImageContext, sizeof (ImageContext));
71 
72   ImageContext.Handle    = PeCoffImage;
73   ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
74 
75   Status = PeCoffLoaderGetImageInfo (&ImageContext);
76   ASSERT_EFI_ERROR (Status);
77 
78 
79   //
80   // Allocate Memory for the image
81   //
82   Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize));
83   ASSERT (Buffer != 0);
84 
85 
86   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
87 
88   //
89   // Load the image to our new buffer
90   //
91   Status = PeCoffLoaderLoadImage (&ImageContext);
92   ASSERT_EFI_ERROR (Status);
93 
94   //
95   // Relocate the image in our new buffer
96   //
97   Status = PeCoffLoaderRelocateImage (&ImageContext);
98   ASSERT_EFI_ERROR (Status);
99 
100 
101   *ImageAddress = ImageContext.ImageAddress;
102   *ImageSize    = ImageContext.ImageSize;
103   *EntryPoint   = ImageContext.EntryPoint;
104 
105   //
106   // Flush not needed for all architectures. We could have a processor specific
107   // function in this library that does the no-op if needed.
108   //
109   InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize);
110 
111   return Status;
112 }
113 
114 
115 
116 typedef
117 VOID
118 (EFIAPI *DXE_CORE_ENTRY_POINT) (
119   IN  VOID *HobStart
120   );
121 
122 EFI_STATUS
123 EFIAPI
LoadDxeCoreFromFfsFile(IN EFI_PEI_FILE_HANDLE FileHandle,IN UINTN StackSize)124 LoadDxeCoreFromFfsFile (
125   IN EFI_PEI_FILE_HANDLE  FileHandle,
126   IN UINTN                StackSize
127   )
128 {
129   EFI_STATUS              Status;
130   VOID                    *PeCoffImage;
131   EFI_PHYSICAL_ADDRESS    ImageAddress;
132   UINT64                  ImageSize;
133   EFI_PHYSICAL_ADDRESS    EntryPoint;
134   VOID                    *BaseOfStack;
135   VOID                    *TopOfStack;
136   VOID                    *Hob;
137   EFI_FV_FILE_INFO        FvFileInfo;
138 
139   Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);
140   if (EFI_ERROR  (Status)) {
141     return Status;
142   }
143 
144 
145   Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
146 // For NT32 Debug  Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
147   ASSERT_EFI_ERROR (Status);
148 
149   //
150   // Extract the DxeCore GUID file name.
151   //
152   Status = FfsGetFileInfo (FileHandle, &FvFileInfo);
153   ASSERT_EFI_ERROR (Status);
154 
155   BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint);
156 
157   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint));
158 
159   Hob = GetHobList ();
160   if (StackSize == 0) {
161     // User the current stack
162 
163     ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob);
164   } else {
165 
166     //
167     // Allocate 128KB for the Stack
168     //
169     BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
170     ASSERT (BaseOfStack != NULL);
171 
172     //
173     // Compute the top of the stack we were allocated. Pre-allocate a UINTN
174     // for safety.
175     //
176     TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
177     TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
178 
179     //
180     // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
181     //
182     UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize);
183 
184     SwitchStack (
185       (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint,
186       Hob,
187       NULL,
188       TopOfStack
189       );
190 
191   }
192 
193   // Should never get here as DXE Core does not return
194   DEBUG ((EFI_D_ERROR, "DxeCore returned\n"));
195   ASSERT (FALSE);
196 
197   return EFI_DEVICE_ERROR;
198 }
199 
200 
201 
202 EFI_STATUS
203 EFIAPI
LoadDxeCoreFromFv(IN UINTN * FvInstance,OPTIONAL IN UINTN StackSize)204 LoadDxeCoreFromFv (
205   IN UINTN  *FvInstance,   OPTIONAL
206   IN UINTN  StackSize
207   )
208 {
209   EFI_STATUS          Status;
210   EFI_PEI_FV_HANDLE   VolumeHandle;
211   EFI_PEI_FILE_HANDLE FileHandle = NULL;
212 
213   if (FvInstance != NULL) {
214     //
215     // Caller passed in a specific FV to try, so only try that one
216     //
217     Status = FfsFindNextVolume (*FvInstance, &VolumeHandle);
218     if (!EFI_ERROR (Status)) {
219       Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
220     }
221   } else {
222     Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
223   }
224 
225   if (!EFI_ERROR (Status)) {
226     return LoadDxeCoreFromFfsFile (FileHandle, StackSize);
227   }
228 
229   return Status;
230 }
231 
232 
233 EFI_STATUS
234 EFIAPI
DecompressFirstFv(VOID)235 DecompressFirstFv (
236   VOID
237   )
238 {
239   EFI_STATUS          Status;
240   EFI_PEI_FV_HANDLE   VolumeHandle;
241   EFI_PEI_FILE_HANDLE FileHandle;
242 
243   Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle);
244   if (!EFI_ERROR (Status)) {
245     Status = FfsProcessFvFile (FileHandle);
246   }
247 
248   return Status;
249 }
250 
251 
252