]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
UefiPayloadPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiPayloadPkg / UefiPayloadEntry / LoadDxeCore.c
1 /** @file
2
3 Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "UefiPayloadEntry.h"
10
11 /**
12 Allocate pages for code.
13
14 @param[in] Pages Number of pages to be allocated.
15
16 @return Allocated memory.
17 **/
18 VOID *
19 AllocateCodePages (
20 IN UINTN Pages
21 )
22 {
23 VOID *Alloc;
24 EFI_PEI_HOB_POINTERS Hob;
25
26 Alloc = AllocatePages (Pages);
27 if (Alloc == NULL) {
28 return NULL;
29 }
30
31 // find the HOB we just created, and change the type to EfiBootServicesCode
32 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
33 while (Hob.Raw != NULL) {
34 if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == (UINTN)Alloc) {
35 Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiBootServicesCode;
36 return Alloc;
37 }
38
39 Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (Hob));
40 }
41
42 ASSERT (FALSE);
43
44 FreePages (Alloc, Pages);
45 return NULL;
46 }
47
48 /**
49 Loads and relocates a PE/COFF image
50
51 @param[in] PeCoffImage Point to a Pe/Coff image.
52 @param[out] ImageAddress The image memory address after relocation.
53 @param[out] ImageSize The image size.
54 @param[out] EntryPoint The image entry point.
55
56 @return EFI_SUCCESS If the image is loaded and relocated successfully.
57 @return Others If the image failed to load or relocate.
58 **/
59 EFI_STATUS
60 LoadPeCoffImage (
61 IN VOID *PeCoffImage,
62 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
63 OUT UINT64 *ImageSize,
64 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
65 )
66 {
67 RETURN_STATUS Status;
68 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
69 VOID *Buffer;
70
71 ZeroMem (&ImageContext, sizeof (ImageContext));
72
73 ImageContext.Handle = PeCoffImage;
74 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
75
76 Status = PeCoffLoaderGetImageInfo (&ImageContext);
77 if (EFI_ERROR (Status)) {
78 ASSERT_EFI_ERROR (Status);
79 return Status;
80 }
81
82 //
83 // Allocate Memory for the image
84 //
85 Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES ((UINT32)ImageContext.ImageSize));
86 if (Buffer == NULL) {
87 return EFI_OUT_OF_RESOURCES;
88 }
89
90 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
91
92 //
93 // Load the image to our new buffer
94 //
95 Status = PeCoffLoaderLoadImage (&ImageContext);
96 if (EFI_ERROR (Status)) {
97 ASSERT_EFI_ERROR (Status);
98 return Status;
99 }
100
101 //
102 // Relocate the image in our new buffer
103 //
104 Status = PeCoffLoaderRelocateImage (&ImageContext);
105 if (EFI_ERROR (Status)) {
106 ASSERT_EFI_ERROR (Status);
107 return Status;
108 }
109
110 *ImageAddress = ImageContext.ImageAddress;
111 *ImageSize = ImageContext.ImageSize;
112 *EntryPoint = ImageContext.EntryPoint;
113
114 return EFI_SUCCESS;
115 }
116
117 /**
118 This function searchs a given file type with a given Guid within a valid FV.
119 If input Guid is NULL, will locate the first section having the given file type
120
121 @param FvHeader A pointer to firmware volume header that contains the set of files
122 to be searched.
123 @param FileType File type to be searched.
124 @param Guid Will ignore if it is NULL.
125 @param FileHeader A pointer to the discovered file, if successful.
126
127 @retval EFI_SUCCESS Successfully found FileType
128 @retval EFI_NOT_FOUND File type can't be found.
129 **/
130 EFI_STATUS
131 FvFindFileByTypeGuid (
132 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
133 IN EFI_FV_FILETYPE FileType,
134 IN EFI_GUID *Guid OPTIONAL,
135 OUT EFI_FFS_FILE_HEADER **FileHeader
136 )
137 {
138 EFI_PHYSICAL_ADDRESS CurrentAddress;
139 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
140 EFI_FFS_FILE_HEADER *File;
141 UINT32 Size;
142 EFI_PHYSICAL_ADDRESS EndOfFile;
143
144 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader;
145 EndOfFirmwareVolume = CurrentAddress + FvHeader->FvLength;
146
147 //
148 // Loop through the FFS files
149 //
150 for (EndOfFile = CurrentAddress + FvHeader->HeaderLength; ; ) {
151 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
152 if (CurrentAddress > EndOfFirmwareVolume) {
153 break;
154 }
155
156 File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
157 if (IS_FFS_FILE2 (File)) {
158 Size = FFS_FILE2_SIZE (File);
159 if (Size <= 0x00FFFFFF) {
160 break;
161 }
162 } else {
163 Size = FFS_FILE_SIZE (File);
164 if (Size < sizeof (EFI_FFS_FILE_HEADER)) {
165 break;
166 }
167 }
168
169 EndOfFile = CurrentAddress + Size;
170 if (EndOfFile > EndOfFirmwareVolume) {
171 break;
172 }
173
174 //
175 // Look for file type
176 //
177 if (File->Type == FileType) {
178 if ((Guid == NULL) || CompareGuid (&File->Name, Guid)) {
179 *FileHeader = File;
180 return EFI_SUCCESS;
181 }
182 }
183 }
184
185 return EFI_NOT_FOUND;
186 }
187
188 /**
189 This function searchs a given section type within a valid FFS file.
190
191 @param FileHeader A pointer to the file header that contains the set of sections to
192 be searched.
193 @param SectionType The value of the section type to search.
194 @param SectionData A pointer to the discovered section, if successful.
195
196 @retval EFI_SUCCESS The section was found.
197 @retval EFI_NOT_FOUND The section was not found.
198
199 **/
200 EFI_STATUS
201 FileFindSection (
202 IN EFI_FFS_FILE_HEADER *FileHeader,
203 IN EFI_SECTION_TYPE SectionType,
204 OUT VOID **SectionData
205 )
206 {
207 UINT32 FileSize;
208 EFI_COMMON_SECTION_HEADER *Section;
209 UINT32 SectionSize;
210 UINT32 Index;
211
212 if (IS_FFS_FILE2 (FileHeader)) {
213 FileSize = FFS_FILE2_SIZE (FileHeader);
214 } else {
215 FileSize = FFS_FILE_SIZE (FileHeader);
216 }
217
218 FileSize -= sizeof (EFI_FFS_FILE_HEADER);
219
220 Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1);
221 Index = 0;
222 while (Index < FileSize) {
223 if (Section->Type == SectionType) {
224 if (IS_SECTION2 (Section)) {
225 *SectionData = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2));
226 } else {
227 *SectionData = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER));
228 }
229
230 return EFI_SUCCESS;
231 }
232
233 if (IS_SECTION2 (Section)) {
234 SectionSize = SECTION2_SIZE (Section);
235 } else {
236 SectionSize = SECTION_SIZE (Section);
237 }
238
239 SectionSize = GET_OCCUPIED_SIZE (SectionSize, 4);
240 ASSERT (SectionSize != 0);
241 Index += SectionSize;
242
243 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionSize);
244 }
245
246 return EFI_NOT_FOUND;
247 }
248
249 /**
250 Find DXE core from FV and build DXE core HOBs.
251
252 @param[out] DxeCoreEntryPoint DXE core entry point
253
254 @retval EFI_SUCCESS If it completed successfully.
255 @retval EFI_NOT_FOUND If it failed to load DXE FV.
256 **/
257 EFI_STATUS
258 LoadDxeCore (
259 OUT PHYSICAL_ADDRESS *DxeCoreEntryPoint
260 )
261 {
262 EFI_STATUS Status;
263 EFI_FIRMWARE_VOLUME_HEADER *PayloadFv;
264 EFI_FIRMWARE_VOLUME_HEADER *DxeCoreFv;
265 EFI_FFS_FILE_HEADER *FileHeader;
266 VOID *PeCoffImage;
267 EFI_PHYSICAL_ADDRESS ImageAddress;
268 UINT64 ImageSize;
269
270 PayloadFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdPayloadFdMemBase);
271
272 //
273 // DXE FV is inside Payload FV. Here find DXE FV from Payload FV
274 //
275 Status = FvFindFileByTypeGuid (PayloadFv, EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, NULL, &FileHeader);
276 if (EFI_ERROR (Status)) {
277 return Status;
278 }
279
280 Status = FileFindSection (FileHeader, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, (VOID **)&DxeCoreFv);
281 if (EFI_ERROR (Status)) {
282 return Status;
283 }
284
285 //
286 // Report DXE FV to DXE core
287 //
288 BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreFv, DxeCoreFv->FvLength);
289
290 //
291 // Find DXE core file from DXE FV
292 //
293 Status = FvFindFileByTypeGuid (DxeCoreFv, EFI_FV_FILETYPE_DXE_CORE, NULL, &FileHeader);
294 if (EFI_ERROR (Status)) {
295 return Status;
296 }
297
298 Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&PeCoffImage);
299 if (EFI_ERROR (Status)) {
300 return Status;
301 }
302
303 //
304 // Get DXE core info
305 //
306 Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, DxeCoreEntryPoint);
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 BuildModuleHob (&FileHeader->Name, ImageAddress, EFI_SIZE_TO_PAGES ((UINT32)ImageSize) * EFI_PAGE_SIZE, *DxeCoreEntryPoint);
312
313 return EFI_SUCCESS;
314 }
315
316 /**
317 Find DXE core from FV and build DXE core HOBs.
318
319 @param[in] DxeFv The FV where to find the DXE core.
320 @param[out] DxeCoreEntryPoint DXE core entry point
321
322 @retval EFI_SUCCESS If it completed successfully.
323 @retval EFI_NOT_FOUND If it failed to load DXE FV.
324 **/
325 EFI_STATUS
326 UniversalLoadDxeCore (
327 IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv,
328 OUT PHYSICAL_ADDRESS *DxeCoreEntryPoint
329 )
330 {
331 EFI_STATUS Status;
332 EFI_FFS_FILE_HEADER *FileHeader;
333 VOID *PeCoffImage;
334 EFI_PHYSICAL_ADDRESS ImageAddress;
335 UINT64 ImageSize;
336
337 //
338 // Find DXE core file from DXE FV
339 //
340 Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DXE_CORE, NULL, &FileHeader);
341 if (EFI_ERROR (Status)) {
342 return Status;
343 }
344
345 Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&PeCoffImage);
346 if (EFI_ERROR (Status)) {
347 return Status;
348 }
349
350 //
351 // Get DXE core info
352 //
353 Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, DxeCoreEntryPoint);
354 if (EFI_ERROR (Status)) {
355 return Status;
356 }
357
358 BuildModuleHob (&FileHeader->Name, ImageAddress, EFI_SIZE_TO_PAGES ((UINT32)ImageSize) * EFI_PAGE_SIZE, *DxeCoreEntryPoint);
359
360 return EFI_SUCCESS;
361 }