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