]>
Commit | Line | Data |
---|---|---|
2ef2b01e A |
1 | /** @file |
2 | ||
3 | Copyright (c) 2008-2009, Apple Inc. All rights reserved. | |
4 | ||
5 | All rights reserved. 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 | ||
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; | |
118 | ||
119 | ||
120 | Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage); | |
121 | if (EFI_ERROR (Status)) { | |
122 | return Status; | |
123 | } | |
124 | ||
125 | ||
126 | Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); | |
127 | // For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); | |
128 | ASSERT_EFI_ERROR (Status); | |
129 | ||
130 | // | |
131 | // Extract the DxeCore GUID file name. | |
132 | // | |
133 | Status = FfsGetFileInfo (FileHandle, &FvFileInfo); | |
134 | ASSERT_EFI_ERROR (Status); | |
135 | ||
136 | BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint); | |
137 | ||
138 | DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint)); | |
139 | ||
140 | Hob = GetHobList (); | |
141 | if (StackSize == 0) { | |
142 | // User the current stack | |
143 | ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob); | |
144 | } else { | |
145 | ||
146 | // | |
147 | // Allocate 128KB for the Stack | |
148 | // | |
149 | BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize)); | |
150 | ASSERT (BaseOfStack != NULL); | |
151 | ||
152 | // | |
153 | // Compute the top of the stack we were allocated. Pre-allocate a UINTN | |
154 | // for safety. | |
155 | // | |
156 | TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); | |
157 | TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); | |
158 | ||
159 | // | |
160 | // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. | |
161 | // | |
162 | UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize); | |
163 | ||
164 | SwitchStack ( | |
165 | (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint, | |
166 | Hob, | |
167 | NULL, | |
168 | TopOfStack | |
169 | ); | |
170 | ||
171 | } | |
172 | ||
173 | // Should never get here as DXE Core does not return | |
174 | DEBUG ((EFI_D_ERROR, "DxeCore returned\n")); | |
175 | ASSERT (FALSE); | |
176 | ||
177 | return EFI_DEVICE_ERROR; | |
178 | } | |
179 | ||
180 | ||
181 | ||
182 | EFI_STATUS | |
183 | EFIAPI | |
184 | LoadDxeCoreFromFv ( | |
185 | IN UINTN *FvInstance, OPTIONAL | |
186 | IN UINTN StackSize | |
187 | ) | |
188 | { | |
189 | EFI_STATUS Status; | |
190 | EFI_PEI_FV_HANDLE VolumeHandle; | |
191 | EFI_PEI_FILE_HANDLE FileHandle = NULL; | |
192 | ||
193 | if (FvInstance != NULL) { | |
194 | // | |
195 | // Caller passed in a specific FV to try, so only try that one | |
196 | // | |
197 | Status = FfsFindNextVolume (*FvInstance, &VolumeHandle); | |
198 | if (!EFI_ERROR (Status)) { | |
199 | Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle); | |
200 | } | |
201 | } else { | |
202 | Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle); | |
203 | } | |
204 | ||
205 | if (!EFI_ERROR (Status)) { | |
206 | return LoadDxeCoreFromFfsFile (FileHandle, StackSize); | |
207 | } | |
208 | ||
209 | return Status; | |
210 | } | |
211 | ||
212 | ||
213 | EFI_STATUS | |
214 | EFIAPI | |
215 | DecompressFirstFv ( | |
216 | VOID | |
217 | ) | |
218 | { | |
219 | EFI_STATUS Status; | |
220 | EFI_PEI_FV_HANDLE VolumeHandle; | |
221 | EFI_PEI_FILE_HANDLE FileHandle; | |
222 | ||
223 | Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle); | |
224 | if (!EFI_ERROR (Status)) { | |
225 | Status = FfsProcessFvFile (FileHandle); | |
226 | } | |
227 | ||
228 | return Status; | |
229 | } | |
230 | ||
231 |