TianoCore EDK2 master
Loading...
Searching...
No Matches
FitPayloadLoaderPeim.c
Go to the documentation of this file.
1
7#include <PiPei.h>
13#include <Ppi/LoadFile.h>
15#include <Protocol/DevicePath.h>
16#include <Library/DebugLib.h>
17#include <Library/HobLib.h>
20#include <Library/FdtLib.h>
21#include <Library/PrintLib.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
49EFIAPI
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,
71 }
72};
73#endif
74
86EFIAPI
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;
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 //
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 = {
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
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
268VOID
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
299 IN VOID *FdtBase
300 );
301
302#if (FixedPcdGetBool (PcdHandOffFdtEnable))
303
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;
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
382EFIAPI
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}
UINT64 UINTN
#define CPU_STACK_ALIGNMENT
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID *EFIAPI BuildGuidHob(IN CONST EFI_GUID *Guid, IN UINTN DataLength)
Definition: HobLib.c:336
VOID EFIAPI SwitchStack(IN SWITCH_STACK_ENTRY_POINT EntryPoint, IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL, IN VOID *NewStack,...)
Definition: SwitchStack.c:42
VOID(EFIAPI * SWITCH_STACK_ENTRY_POINT)(IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL)
Definition: BaseLib.h:5019
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI PeiServicesNotifyPpi(IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList)
EFI_STATUS EFIAPI PeiServicesInstallPpi(IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList)
INT32 EFIAPI FdtSetProperty(IN VOID *Fdt, IN INT32 NodeOffset, IN CONST CHAR8 *Name, IN CONST VOID *Value, IN UINT32 Length)
Definition: FdtLib.c:593
UINT32 EFIAPI CpuToFdt32(IN UINT32 Value)
Definition: FdtLib.c:74
UINT32 EFIAPI Fdt32ToCpu(IN UINT32 Value)
Definition: FdtLib.c:57
INT32 EFIAPI FdtCreateEmptyTree(IN VOID *Buffer, IN UINT32 BufferSize)
Definition: FdtLib.c:143
EFI_STATUS EFIAPI ParseFitImage(IN VOID *ImageBase, OUT FIT_IMAGE_CONTEXT *Context)
Definition: FitLib.c:82
EFI_STATUS EFIAPI PeiLoadFileLoadPayload(IN CONST EFI_PEI_LOAD_FILE_PPI *This, IN EFI_PEI_FILE_HANDLE FileHandle, OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, OUT UINT64 *ImageSizeArg OPTIONAL, OUT EFI_PHYSICAL_ADDRESS *EntryPoint, OUT UINT32 *AuthenticationState)
EFI_STATUS EFIAPI EndOfPeiPpiNotifyCallback(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi)
VOID PrintFdt(IN VOID *FdtBase)
EFI_STATUS EFIAPI InitializeFitPayloadLoaderPeim(IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices)
EFI_STATUS BuildFdtForUPL(IN VOID *FdtBase)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define ALIGN_POINTER(Pointer, Alignment)
Definition: Base.h:963
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define FixedPcdGetBool(TokenName)
Definition: PcdLib.h:120
EFI_STATUS EFIAPI PeiServicesFfsFindSectionData3(IN EFI_SECTION_TYPE SectionType, IN UINTN SectionInstance, IN EFI_PEI_FILE_HANDLE FileHandle, OUT VOID **SectionData, OUT UINT32 *AuthenticationStatus)
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
VOID *EFIAPI AllocatePages(IN UINTN Pages)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112