]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Library/PrePiLib/PrePiLib.c
a359d5bdb0bc426757309889ca270dda6f3b5d56
[mirror_edk2.git] / EmbeddedPkg / Library / PrePiLib / PrePiLib.c
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 UINT64 Tick;
119
120 Tick = 0;
121 PERF_START (NULL, "SEC", NULL, 1);
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
146
147
148 if (PerformanceMeasurementEnabled ()) {
149 Tick = GetPerformanceCounter ();
150 }
151 PERF_END (NULL, "SEC", NULL, Tick);
152
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
174
175 if (PerformanceMeasurementEnabled ()) {
176 Tick = GetPerformanceCounter ();
177 }
178 PERF_END (NULL, "SEC", NULL, Tick);
179
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