VirtualBox

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

Last change on this file was 108794, checked in by vboxsync, 3 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: 7.6 KB
Line 
1/** @file
2 ELF Load Image Support
3
4Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <PiPei.h>
10#include <UniversalPayload/UniversalPayload.h>
11#include <UniversalPayload/ExtraData.h>
12
13#include <Ppi/LoadFile.h>
14
15#include <Library/DebugLib.h>
16#include <Library/HobLib.h>
17#include <Library/PeiServicesLib.h>
18#include <Library/MemoryAllocationLib.h>
19#include <Library/BaseMemoryLib.h>
20#include <Guid/UniversalPayloadBase.h>
21#include "ElfLib.h"
22
23CONST EFI_PEI_PPI_DESCRIPTOR gReadyToPayloadSignalPpi = {
24 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
25 &gUplReadyToPayloadPpiGuid,
26 NULL
27};
28
29/**
30 Notify ReadyToPayLoad signal.
31 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
32 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
33 @param[in] Ppi Address of the PPI that was installed.
34 @retval EFI_SUCCESS Hobs data is discovered.
35 @return Others No Hobs data is discovered.
36**/
37EFI_STATUS
38EFIAPI
39EndOfPeiPpiNotifyCallback (
40 IN EFI_PEI_SERVICES **PeiServices,
41 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
42 IN VOID *Ppi
43 )
44{
45 EFI_STATUS Status;
46
47 //
48 // Ready to Payload phase signal
49 //
50 Status = PeiServicesInstallPpi (&gReadyToPayloadSignalPpi);
51
52 return Status;
53}
54
55EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiNotifyList[] = {
56 {
57 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
58 &gEfiEndOfPeiSignalPpiGuid,
59 EndOfPeiPpiNotifyCallback
60 }
61};
62
63/**
64 The wrapper function of PeiLoadImageLoadImage().
65
66 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
67 @param FileHandle - Pointer to the FFS file header of the image.
68 @param ImageAddressArg - Pointer to PE/TE image.
69 @param ImageSizeArg - Size of PE/TE image.
70 @param EntryPoint - Pointer to entry point of specified image file for output.
71 @param AuthenticationState - Pointer to attestation authentication state of image.
72
73 @return Status of PeiLoadImageLoadImage().
74
75**/
76EFI_STATUS
77EFIAPI
78PeiLoadFileLoadPayload (
79 IN CONST EFI_PEI_LOAD_FILE_PPI *This,
80 IN EFI_PEI_FILE_HANDLE FileHandle,
81 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
82 OUT UINT64 *ImageSizeArg OPTIONAL,
83 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
84 OUT UINT32 *AuthenticationState
85 )
86{
87 EFI_STATUS Status;
88 VOID *Elf;
89 UNIVERSAL_PAYLOAD_EXTRA_DATA *ExtraData;
90 UNIVERSAL_PAYLOAD_BASE *PayloadBase;
91 ELF_IMAGE_CONTEXT Context;
92 UINT32 Index;
93 UINT16 ExtraDataIndex;
94 CHAR8 *SectionName;
95 UINTN Offset;
96 UINTN Size;
97 UINT32 ExtraDataCount;
98 UINTN Instance;
99 UINTN Length;
100
101 //
102 // ELF is added to file as RAW section for EDKII bootloader.
103 // But RAW section might be added by build tool before the ELF RAW section when alignment is specified for ELF RAW section.
104 // Below loop skips the RAW section that doesn't contain valid ELF image.
105 //
106 Instance = 0;
107 do {
108 Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Elf, AuthenticationState);
109 if (EFI_ERROR (Status)) {
110 return Status;
111 }
112
113 ZeroMem (&Context, sizeof (Context));
114 Status = ParseElfImage (Elf, &Context);
115 } while (EFI_ERROR (Status));
116
117 Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
118 PayloadBase = BuildGuidHob (
119 &gUniversalPayloadBaseGuid,
120 Length
121 );
122 PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.FileBase;
123
124 DEBUG (
125 (
126 DEBUG_INFO,
127 "Payload File Size: 0x%08X, Mem Size: 0x%08x, Reload: %d\n",
128 Context.FileSize,
129 Context.ImageSize,
130 Context.ReloadRequired
131 )
132 );
133
134 //
135 // Get UNIVERSAL_PAYLOAD_INFO_HEADER and number of additional PLD sections.
136 //
137 ExtraDataCount = 0;
138 for (Index = 0; Index < Context.ShNum; Index++) {
139 Status = GetElfSectionName (&Context, Index, &SectionName);
140 if (EFI_ERROR (Status)) {
141 continue;
142 }
143
144 DEBUG ((DEBUG_INFO, "Payload Section[%d]: %a\n", Index, SectionName));
145 if (AsciiStrCmp (SectionName, UNIVERSAL_PAYLOAD_INFO_SEC_NAME) == 0) {
146 Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
147 } else if (AsciiStrnCmp (SectionName, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH) == 0) {
148 Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
149 if (!EFI_ERROR (Status)) {
150 ExtraDataCount++;
151 }
152 }
153 }
154
155 //
156 // Report the additional PLD sections through HOB.
157 //
158 Length = sizeof (UNIVERSAL_PAYLOAD_EXTRA_DATA) + ExtraDataCount * sizeof (UNIVERSAL_PAYLOAD_EXTRA_DATA_ENTRY);
159 ExtraData = BuildGuidHob (
160 &gUniversalPayloadExtraDataGuid,
161 Length
162 );
163 ExtraData->Count = ExtraDataCount;
164 ExtraData->Header.Revision = UNIVERSAL_PAYLOAD_EXTRA_DATA_REVISION;
165 ExtraData->Header.Length = (UINT16)Length;
166 if (ExtraDataCount != 0) {
167 for (ExtraDataIndex = 0, Index = 0; Index < Context.ShNum; Index++) {
168 Status = GetElfSectionName (&Context, Index, &SectionName);
169 if (EFI_ERROR (Status)) {
170 continue;
171 }
172
173 if (AsciiStrnCmp (SectionName, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH) == 0) {
174 Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
175 if (!EFI_ERROR (Status)) {
176 ASSERT (ExtraDataIndex < ExtraDataCount);
177 AsciiStrCpyS (
178 ExtraData->Entry[ExtraDataIndex].Identifier,
179 sizeof (ExtraData->Entry[ExtraDataIndex].Identifier),
180 SectionName + UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH
181 );
182 ExtraData->Entry[ExtraDataIndex].Base = (UINTN)(Context.FileBase + Offset);
183 ExtraData->Entry[ExtraDataIndex].Size = Size;
184 ExtraDataIndex++;
185 }
186 }
187 }
188 }
189
190 if (Context.ReloadRequired || (Context.PreferredImageAddress != Context.FileBase)) {
191 Context.ImageAddress = AllocatePages (EFI_SIZE_TO_PAGES (Context.ImageSize));
192 } else {
193 Context.ImageAddress = Context.FileBase;
194 }
195
196 //
197 // Load ELF into the required base
198 //
199 Status = LoadElfImage (&Context);
200 if (!EFI_ERROR (Status)) {
201 *ImageAddressArg = (UINTN)Context.ImageAddress;
202 *EntryPoint = Context.EntryPoint;
203 *ImageSizeArg = Context.ImageSize;
204 }
205
206 DEBUG ((DEBUG_INFO, "LoadElfImage :%r, EntryPoint :%x\n", Status, (UINTN)Context.EntryPoint));
207
208 Status = PeiServicesNotifyPpi (&mEndOfPeiNotifyList[0]);
209 ASSERT_EFI_ERROR (Status);
210
211 return Status;
212}
213
214EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
215 PeiLoadFileLoadPayload
216};
217
218EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
219 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
220 &gEfiPeiLoadFilePpiGuid,
221 &mPeiLoadFilePpi
222};
223
224/**
225
226 Install Pei Load File PPI.
227
228 @param FileHandle Handle of the file being invoked.
229 @param PeiServices Describes the list of possible PEI Services.
230
231 @retval EFI_SUCCESS The entry point executes successfully.
232 @retval Others Some error occurs during the execution of this function.
233
234**/
235EFI_STATUS
236EFIAPI
237InitializePayloadLoaderPeim (
238 IN EFI_PEI_FILE_HANDLE FileHandle,
239 IN CONST EFI_PEI_SERVICES **PeiServices
240 )
241{
242 EFI_STATUS Status;
243
244 Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
245
246 return Status;
247}
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