]>
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 ( | |
2ef2b01e | 25 | IN VOID *Pe32Data, |
2ef2b01e | 26 | IN EFI_PHYSICAL_ADDRESS *ImageAddress, |
2ef2b01e | 27 | IN UINT64 *ImageSize, |
2ef2b01e | 28 | IN EFI_PHYSICAL_ADDRESS *EntryPoint |
2ef2b01e A |
29 | ); |
30 | ||
31 | ||
32 | EFI_STATUS | |
33 | EFIAPI | |
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 | |
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; | |
2ef2b01e A |
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 | |
65568970 | 137 | |
2ef2b01e A |
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); | |
65568970 | 158 | |
2ef2b01e A |
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 | |
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 | |
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 |