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