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