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