VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c

Last change on this file was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1/** @file
2 FIT Load Image Support
3Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
4SPDX-License-Identifier: BSD-2-Clause-Patent
5**/
6
7#include <PiPei.h>
8#include <UniversalPayload/UniversalPayload.h>
9#include <UniversalPayload/DeviceTree.h>
10#include <Guid/UniversalPayloadBase.h>
11#include <UniversalPayload/ExtraData.h>
12#include <UniversalPayload/DeviceTree.h>
13#include <Ppi/LoadFile.h>
14#include <Library/PciHostBridgeLib.h>
15#include <Protocol/DevicePath.h>
16#include <Library/DebugLib.h>
17#include <Library/HobLib.h>
18#include <Library/MemoryAllocationLib.h>
19#include <Library/BaseMemoryLib.h>
20#include <Library/FdtLib.h>
21#include <Library/PrintLib.h>
22#include <Library/PeiServicesLib.h>
23#include "FitLib.h"
24#define STACK_SIZE 0x20000
25
26CONST EFI_PEI_PPI_DESCRIPTOR gReadyToPayloadSignalPpi = {
27 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
28 &gUplReadyToPayloadPpiGuid,
29 NULL
30};
31
32EFI_PEI_PPI_DESCRIPTOR mEndOfPeiSignalPpi = {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34 &gEfiEndOfPeiSignalPpiGuid,
35 NULL
36};
37
38#if (FixedPcdGetBool (PcdHandOffFdtEnable) == 0)
39
40/**
41 Notify ReadyToPayLoad signal.
42 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
43 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
44 @param[in] Ppi Address of the PPI that was installed.
45 @retval EFI_SUCCESS Hobs data is discovered.
46 @return Others No Hobs data is discovered.
47**/
48EFI_STATUS
49EFIAPI
50EndOfPeiPpiNotifyCallback (
51 IN EFI_PEI_SERVICES **PeiServices,
52 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
53 IN VOID *Ppi
54 )
55{
56 EFI_STATUS Status;
57
58 //
59 // Ready to Payload phase signal
60 //
61 Status = PeiServicesInstallPpi (&gReadyToPayloadSignalPpi);
62
63 return Status;
64}
65
66EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiNotifyList[] = {
67 {
68 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
69 &gEfiEndOfPeiSignalPpiGuid,
70 EndOfPeiPpiNotifyCallback
71 }
72};
73#endif
74
75/**
76 The wrapper function of PeiLoadImageLoadImage().
77 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
78 @param FileHandle - Pointer to the FFS file header of the image.
79 @param ImageAddressArg - Pointer to PE/TE image.
80 @param ImageSizeArg - Size of PE/TE image.
81 @param EntryPoint - Pointer to entry point of specified image file for output.
82 @param AuthenticationState - Pointer to attestation authentication state of image.
83 @return Status of PeiLoadImageLoadImage().
84**/
85EFI_STATUS
86EFIAPI
87PeiLoadFileLoadPayload (
88 IN CONST EFI_PEI_LOAD_FILE_PPI *This,
89 IN EFI_PEI_FILE_HANDLE FileHandle,
90 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
91 OUT UINT64 *ImageSizeArg OPTIONAL,
92 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
93 OUT UINT32 *AuthenticationState
94 )
95{
96 EFI_STATUS Status;
97 FIT_IMAGE_CONTEXT Context;
98 UINTN Instance;
99 VOID *Binary;
100 FIT_RELOCATE_ITEM *RelocateTable;
101 UNIVERSAL_PAYLOAD_BASE *PayloadBase;
102 UINTN Length;
103 UINTN Delta;
104 UINTN Index;
105
106 #if (FixedPcdGetBool (PcdHandOffFdtEnable))
107 VOID *BaseOfStack;
108 VOID *TopOfStack;
109 UNIVERSAL_PAYLOAD_DEVICE_TREE *Fdt;
110 VOID *Hob;
111
112 Fdt = NULL;
113 #endif
114
115 Instance = 0;
116 do {
117 Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState);
118 if (EFI_ERROR (Status)) {
119 return Status;
120 }
121
122 ZeroMem (&Context, sizeof (Context));
123 Status = ParseFitImage (Binary, &Context);
124 } while (EFI_ERROR (Status));
125
126 if (EFI_ERROR (Status)) {
127 ASSERT_EFI_ERROR (Status);
128 return Status;
129 }
130
131 DEBUG (
132 (
133 DEBUG_INFO,
134 "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
135 Context.PayloadBaseAddress,
136 Context.PayloadSize,
137 Context.PayloadEntryPoint
138 )
139 );
140 Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize));
141
142 RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset);
143 CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize);
144
145 if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
146 Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress;
147 Context.PayloadEntryPoint += Delta;
148 for (Index = 0; Index < Context.RelocateTableCount; Index++) {
149 if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
150 *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta;
151 }
152 }
153 } else {
154 Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress;
155 Context.PayloadEntryPoint -= Delta;
156 for (Index = 0; Index < Context.RelocateTableCount; Index++) {
157 if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
158 *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta;
159 }
160 }
161 }
162
163 DEBUG (
164 (
165 DEBUG_INFO,
166 "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
167 Context.PayloadBaseAddress,
168 Context.PayloadSize,
169 Context.PayloadEntryPoint
170 )
171 );
172
173 Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
174 PayloadBase = BuildGuidHob (
175 &gUniversalPayloadBaseGuid,
176 Length
177 );
178 PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
179
180 *ImageAddressArg = Context.PayloadBaseAddress;
181 *ImageSizeArg = Context.PayloadSize;
182 *EntryPoint = Context.PayloadEntryPoint;
183
184 #if (FixedPcdGetBool (PcdHandOffFdtEnable))
185
186 Status = PeiServicesInstallPpi (&mEndOfPeiSignalPpi);
187 ASSERT_EFI_ERROR (Status);
188
189 Status = PeiServicesInstallPpi (&gReadyToPayloadSignalPpi);
190 ASSERT_EFI_ERROR (Status);
191
192 Hob = GetFirstGuidHob (&gUniversalPayloadDeviceTreeGuid);
193 if (Hob != NULL) {
194 Fdt = (UNIVERSAL_PAYLOAD_DEVICE_TREE *)GET_GUID_HOB_DATA (Hob);
195 }
196
197 //
198 // Allocate 128KB for the Stack
199 //
200 BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
201 ASSERT (BaseOfStack != NULL);
202
203 //
204 // Compute the top of the stack we were allocated. Pre-allocate a UINTN
205 // for safety.
206 //
207 TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
208 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
209
210 //
211 // Transfer the control to the entry point of UniveralPayloadEntry.
212 //
213 SwitchStack (
214 (SWITCH_STACK_ENTRY_POINT)(UINTN)Context.PayloadEntryPoint,
215 (VOID *)(Fdt->DeviceTreeAddress),
216 NULL,
217 TopOfStack
218 );
219 #else
220 Status = PeiServicesNotifyPpi (&mEndOfPeiNotifyList[0]);
221 ASSERT_EFI_ERROR (Status);
222 #endif
223
224 return EFI_SUCCESS;
225}
226
227EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
228 PeiLoadFileLoadPayload
229};
230
231EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
232 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
233 &gEfiPeiLoadFilePpiGuid,
234 &mPeiLoadFilePpi
235};
236
237#if (FixedPcdGetBool (PcdHandOffFdtEnable))
238
239/**
240 Discover Hobs data and report data into a FDT.
241 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
242 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
243 @param[in] Ppi Address of the PPI that was installed.
244 @retval EFI_SUCCESS Hobs data is discovered.
245 @return Others No Hobs data is discovered.
246**/
247EFI_STATUS
248EFIAPI
249FdtPpiNotifyCallback (
250 IN EFI_PEI_SERVICES **PeiServices,
251 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
252 IN VOID *Ppi
253 );
254
255EFI_PEI_NOTIFY_DESCRIPTOR mReadyToPayloadNotifyList[] = {
256 {
257 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
258 &gUplReadyToPayloadPpiGuid,
259 FdtPpiNotifyCallback
260 }
261};
262#endif
263
264/**
265 Print FDT data.
266 @param[in] FdtBase Address of the Fdt data.
267**/
268VOID
269PrintFdt (
270 IN VOID *FdtBase
271 )
272{
273 UINT8 *Fdt;
274 UINT32 i;
275
276 Fdt = NULL;
277 i = 0;
278
279 DEBUG ((DEBUG_ERROR, "FDT DTB data:"));
280 for (Fdt = FdtBase, i = 0; i < Fdt32ToCpu (((FDT_HEADER *)FdtBase)->TotalSize); i++, Fdt++) {
281 if (i % 16 == 0) {
282 DEBUG ((DEBUG_ERROR, "\n"));
283 }
284
285 DEBUG ((DEBUG_ERROR, "%02x ", *Fdt));
286 }
287
288 DEBUG ((DEBUG_ERROR, "\n"));
289}
290
291/**
292 It will build FDT for UPL consumed.
293 @param[in] FdtBase Address of the Fdt data.
294 @retval EFI_SUCCESS If it completed successfully.
295 @retval Others If it failed to build required FDT.
296**/
297EFI_STATUS
298BuildFdtForUPL (
299 IN VOID *FdtBase
300 );
301
302#if (FixedPcdGetBool (PcdHandOffFdtEnable))
303
304/**
305 Discover Hobs data and report data into a FDT.
306 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
307 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
308 @param[in] Ppi Address of the PPI that was installed.
309 @retval EFI_SUCCESS Hobs data is discovered.
310 @return Others No Hobs data is discovered.
311**/
312EFI_STATUS
313EFIAPI
314FdtPpiNotifyCallback (
315 IN EFI_PEI_SERVICES **PeiServices,
316 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
317 IN VOID *Ppi
318 )
319{
320 EFI_STATUS Status;
321 UNIVERSAL_PAYLOAD_DEVICE_TREE *Fdt;
322 UINT32 FdtSize;
323 UINTN FdtPages;
324 VOID *FdtBase;
325 UINT32 Data32;
326
327 Fdt = NULL;
328 FdtSize = PcdGet8 (PcdFDTPageSize) * EFI_PAGE_SIZE;
329 FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
330 FdtBase = AllocatePages (FdtPages);
331 if (FdtBase == NULL) {
332 DEBUG ((DEBUG_ERROR, "%a: AllocatePages failed\n", __func__));
333 return EFI_NOT_FOUND;
334 }
335
336 Status = FdtCreateEmptyTree (FdtBase, (UINT32)FdtSize);
337 if (EFI_ERROR (Status)) {
338 DEBUG ((DEBUG_ERROR, "%a: cannot create FDT\n", __func__));
339 }
340
341 // Set cell property of root node
342 Data32 = CpuToFdt32 (2);
343 Status = FdtSetProperty (FdtBase, 0, "#address-cells", &Data32, sizeof (UINT32));
344 Status = FdtSetProperty (FdtBase, 0, "#size-cells", &Data32, sizeof (UINT32));
345
346 Status = BuildFdtForUPL (FdtBase);
347 ASSERT_EFI_ERROR (Status);
348
349 PrintFdt (FdtBase);
350
351 Fdt = BuildGuidHob (&gUniversalPayloadDeviceTreeGuid, sizeof (UNIVERSAL_PAYLOAD_DEVICE_TREE));
352 if (Fdt == NULL) {
353 DEBUG ((DEBUG_ERROR, "%a: Build FDT Hob failed\n", __func__));
354 return EFI_NOT_FOUND;
355 }
356
357 DEBUG ((
358 DEBUG_ERROR,
359 "%a: fdt at 0x%x (size %d)\n",
360 __func__,
361 FdtBase,
362 Fdt32ToCpu (((FDT_HEADER *)FdtBase)->TotalSize)
363 ));
364
365 Fdt->Header.Revision = UNIVERSAL_PAYLOAD_DEVICE_TREE_REVISION;
366 Fdt->Header.Length = sizeof (UNIVERSAL_PAYLOAD_DEVICE_TREE);
367 Fdt->DeviceTreeAddress = (UINT64)FdtBase;
368
369 return Status;
370}
371
372#endif
373
374/**
375 Install Pei Load File PPI.
376 @param FileHandle Handle of the file being invoked.
377 @param PeiServices Describes the list of possible PEI Services.
378 @retval EFI_SUCESS The entry point executes successfully.
379 @retval Others Some error occurs during the execution of this function.
380**/
381EFI_STATUS
382EFIAPI
383InitializeFitPayloadLoaderPeim (
384 IN EFI_PEI_FILE_HANDLE FileHandle,
385 IN CONST EFI_PEI_SERVICES **PeiServices
386 )
387{
388 EFI_STATUS Status;
389
390 Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
391
392 #if (FixedPcdGetBool (PcdHandOffFdtEnable))
393
394 //
395 // Build FDT in end of PEI notify callback.
396 //
397 Status = PeiServicesNotifyPpi (&mReadyToPayloadNotifyList[0]);
398 ASSERT_EFI_ERROR (Status);
399 #endif
400 return Status;
401}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette