]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Library / VarCheckHiiLib / VarCheckHiiGenFromFv.c
1 /** @file
2 Var Check Hii generation from FV.
3
4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "VarCheckHiiGen.h"
10
11 // {d0bc7cb4-6a47-495f-aa11-710746da06a2}
12 #define EFI_VFR_ATTRACT_GUID \
13 { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }
14
15 EFI_GUID gVfrArrayAttractGuid = EFI_VFR_ATTRACT_GUID;
16
17 #define ALL_FF_GUID \
18 { 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }
19
20 EFI_GUID mAllFfGuid = ALL_FF_GUID;
21
22 #define VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('V', 'D', 'R', 'I')
23
24 typedef struct {
25 UINTN Signature;
26 LIST_ENTRY Link;
27 EFI_GUID *DriverGuid;
28 } VAR_CHECK_VFR_DRIVER_INFO;
29
30 LIST_ENTRY mVfrDriverList = INITIALIZE_LIST_HEAD_VARIABLE (mVfrDriverList);
31
32 #define VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK(a) CR (a, VAR_CHECK_VFR_DRIVER_INFO, Link, VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE)
33
34 #define MAX_MATCH_GUID_NUM 100
35
36 /**
37 Get the address by Guid.
38
39 Parse the FFS and find the GUID address.
40 There may be multiple Guids matching the searched Guid.
41
42 @param Ffs Pointer to the FFS.
43 @param Guid Guid to find.
44 @param Length The length of FFS.
45 @param Offset Pointer to pointer to the offset.
46 @param NumOfMatchingGuid The number of matching Guid.
47
48 @retval EFI_SUCCESS One or multiple Guids matching the searched Guid.
49 @retval EFI_NOT_FOUND No Guid matching the searched Guid.
50
51 **/
52 EFI_STATUS
53 GetAddressByGuid (
54 IN VOID *Ffs,
55 IN EFI_GUID *Guid,
56 IN UINTN Length,
57 OUT UINTN **Offset,
58 OUT UINT8 *NumOfMatchingGuid
59 )
60 {
61 UINTN LoopControl;
62 BOOLEAN Found;
63
64 if ((Ffs == NULL) || (Guid == NULL) || (Length == 0)) {
65 return EFI_NOT_FOUND;
66 }
67
68 if (NumOfMatchingGuid != NULL) {
69 *NumOfMatchingGuid = 0;
70 }
71
72 Found = FALSE;
73 for (LoopControl = 0; LoopControl < Length; LoopControl++) {
74 if (CompareGuid (Guid, (EFI_GUID *)((UINT8 *)Ffs + LoopControl))) {
75 Found = TRUE;
76 //
77 // If NumOfMatchGuid or Offset are NULL, means user only want
78 // to check whether current FFS includes this Guid or not.
79 //
80 if ((NumOfMatchingGuid != NULL) && (Offset != NULL)) {
81 if (*NumOfMatchingGuid == 0) {
82 *Offset = InternalVarCheckAllocateZeroPool (sizeof (UINTN) * MAX_MATCH_GUID_NUM);
83 ASSERT (*Offset != NULL);
84 }
85
86 *(*Offset + *NumOfMatchingGuid) = LoopControl + sizeof (EFI_GUID);
87 (*NumOfMatchingGuid)++;
88 } else {
89 break;
90 }
91 }
92 }
93
94 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
95 }
96
97 /**
98 Search the VfrBin Base address.
99
100 According to the known GUID gVfrArrayAttractGuid to get the base address from FFS.
101
102 @param Ffs Pointer to the FFS.
103 @param EfiAddr Pointer to the EFI in FFS
104 @param Length The length of FFS.
105 @param Offset Pointer to pointer to the Addr (Offset).
106 @param NumOfMatchingOffset The number of Addr (Offset).
107
108 @retval EFI_SUCCESS Get the address successfully.
109 @retval EFI_NOT_FOUND No VfrBin found.
110
111 **/
112 EFI_STATUS
113 SearchVfrBinInFfs (
114 IN VOID *Ffs,
115 IN VOID *EfiAddr,
116 IN UINTN Length,
117 OUT UINTN **Offset,
118 OUT UINT8 *NumOfMatchingOffset
119 )
120 {
121 UINTN Index;
122 EFI_STATUS Status;
123 UINTN VirOffValue;
124
125 if ((Ffs == NULL) || (Offset == NULL)) {
126 return EFI_NOT_FOUND;
127 }
128
129 Status = GetAddressByGuid (
130 Ffs,
131 &gVfrArrayAttractGuid,
132 Length,
133 Offset,
134 NumOfMatchingOffset
135 );
136 if (Status != EFI_SUCCESS) {
137 return Status;
138 }
139
140 for (Index = 0; Index < *NumOfMatchingOffset; Index++) {
141 //
142 // Got the virOffset after the GUID
143 //
144 VirOffValue = *(UINTN *)((UINTN)Ffs + *(*Offset + Index));
145 //
146 // Transfer the offset to the VA address. One modules may own multiple VfrBin address.
147 //
148 *(*Offset + Index) = (UINTN)EfiAddr + VirOffValue;
149 }
150
151 return Status;
152 }
153
154 /**
155 Parse FFS.
156
157 @param[in] Fv2 Pointer to Fv2 protocol.
158 @param[in] DriverGuid Pointer to driver GUID.
159
160 @return Found the driver in the FV or not.
161
162 **/
163 BOOLEAN
164 ParseFfs (
165 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2,
166 IN EFI_GUID *DriverGuid
167 )
168 {
169 EFI_STATUS Status;
170 EFI_FV_FILETYPE FoundType;
171 EFI_FV_FILE_ATTRIBUTES FileAttributes;
172 UINT32 AuthenticationStatus;
173 UINTN Size;
174 VOID *Buffer;
175 UINTN SectionSize;
176 VOID *SectionBuffer;
177 UINTN VfrBinIndex;
178 UINT8 NumberofMatchingVfrBin;
179 UINTN *VfrBinBaseAddress;
180
181 Status = Fv2->ReadFile (
182 Fv2,
183 DriverGuid,
184 NULL,
185 &Size,
186 &FoundType,
187 &FileAttributes,
188 &AuthenticationStatus
189 );
190 if (EFI_ERROR (Status)) {
191 return FALSE;
192 }
193
194 Buffer = NULL;
195 Status = Fv2->ReadSection (
196 Fv2,
197 DriverGuid,
198 EFI_SECTION_RAW,
199 0, // Instance
200 &Buffer,
201 &Size,
202 &AuthenticationStatus
203 );
204 if (!EFI_ERROR (Status)) {
205 Status = SearchVfrBinInFfs (Buffer, 0, Size, &VfrBinBaseAddress, &NumberofMatchingVfrBin);
206 if (!EFI_ERROR (Status)) {
207 SectionBuffer = NULL;
208 Status = Fv2->ReadSection (
209 Fv2,
210 DriverGuid,
211 EFI_SECTION_PE32,
212 0, // Instance
213 &SectionBuffer,
214 &SectionSize,
215 &AuthenticationStatus
216 );
217 if (!EFI_ERROR (Status)) {
218 DEBUG ((DEBUG_INFO, "FfsNameGuid - %g\n", DriverGuid));
219 DEBUG ((DEBUG_INFO, "NumberofMatchingVfrBin - 0x%02x\n", NumberofMatchingVfrBin));
220
221 for (VfrBinIndex = 0; VfrBinIndex < NumberofMatchingVfrBin; VfrBinIndex++) {
222 #ifdef DUMP_HII_DATA
223 DEBUG_CODE (
224 DumpHiiPackage ((UINT8 *)(UINTN)SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32));
225 );
226 #endif
227 VarCheckParseHiiPackage ((UINT8 *)(UINTN)SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32), TRUE);
228 }
229
230 FreePool (SectionBuffer);
231 }
232
233 InternalVarCheckFreePool (VfrBinBaseAddress);
234 }
235
236 FreePool (Buffer);
237 }
238
239 return TRUE;
240 }
241
242 /**
243 Parse FVs.
244
245 @param[in] ScanAll Scan all modules in all FVs or not.
246
247 **/
248 VOID
249 ParseFv (
250 IN BOOLEAN ScanAll
251 )
252 {
253 EFI_STATUS Status;
254 EFI_HANDLE *HandleBuffer;
255 UINTN HandleCount;
256 UINTN Index;
257 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2;
258 VOID *Key;
259 EFI_FV_FILETYPE FileType;
260 EFI_GUID NameGuid;
261 EFI_FV_FILE_ATTRIBUTES FileAttributes;
262 UINTN Size;
263 UINTN FfsIndex;
264 VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
265 LIST_ENTRY *VfrDriverLink;
266
267 HandleBuffer = NULL;
268 Status = gBS->LocateHandleBuffer (
269 ByProtocol,
270 &gEfiFirmwareVolume2ProtocolGuid,
271 NULL,
272 &HandleCount,
273 &HandleBuffer
274 );
275 if (EFI_ERROR (Status)) {
276 return;
277 }
278
279 //
280 // Search all FVs
281 //
282 for (Index = 0; Index < HandleCount; Index++) {
283 DEBUG ((DEBUG_INFO, "FvIndex - %x\n", Index));
284 Status = gBS->HandleProtocol (
285 HandleBuffer[Index],
286 &gEfiFirmwareVolume2ProtocolGuid,
287 (VOID **)&Fv2
288 );
289 ASSERT_EFI_ERROR (Status);
290
291 DEBUG_CODE_BEGIN ();
292 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvb2;
293 EFI_PHYSICAL_ADDRESS FvAddress;
294 UINT64 FvSize;
295
296 Status = gBS->HandleProtocol (
297 HandleBuffer[Index],
298 &gEfiFirmwareVolumeBlock2ProtocolGuid,
299 (VOID **)&Fvb2
300 );
301 ASSERT_EFI_ERROR (Status);
302 Status = Fvb2->GetPhysicalAddress (Fvb2, &FvAddress);
303 if (!EFI_ERROR (Status)) {
304 DEBUG ((DEBUG_INFO, "FvAddress - 0x%08x\n", FvAddress));
305 FvSize = ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvAddress)->FvLength;
306 DEBUG ((DEBUG_INFO, "FvSize - 0x%08x\n", FvSize));
307 }
308
309 DEBUG_CODE_END ();
310
311 if (ScanAll) {
312 //
313 // Need to parse all modules in all FVs.
314 //
315 Key = InternalVarCheckAllocateZeroPool (Fv2->KeySize);
316 ASSERT (Key != NULL);
317
318 for (FfsIndex = 0; ; FfsIndex++) {
319 FileType = EFI_FV_FILETYPE_ALL;
320 Status = Fv2->GetNextFile (
321 Fv2,
322 Key,
323 &FileType,
324 &NameGuid,
325 &FileAttributes,
326 &Size
327 );
328 if (EFI_ERROR (Status)) {
329 break;
330 }
331
332 ParseFfs (Fv2, &NameGuid);
333 }
334
335 InternalVarCheckFreePool (Key);
336 } else {
337 //
338 // Only parse drivers in the VFR drivers list.
339 //
340 VfrDriverLink = mVfrDriverList.ForwardLink;
341 while (VfrDriverLink != &mVfrDriverList) {
342 VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);
343 VfrDriverLink = VfrDriverLink->ForwardLink;
344 if (ParseFfs (Fv2, VfrDriverInfo->DriverGuid)) {
345 //
346 // Found the driver in the FV.
347 //
348 RemoveEntryList (&VfrDriverInfo->Link);
349 InternalVarCheckFreePool (VfrDriverInfo);
350 }
351 }
352 }
353 }
354
355 FreePool (HandleBuffer);
356 }
357
358 /**
359 Create Vfr Driver List.
360
361 @param[in] DriverGuidArray Driver Guid Array
362
363 **/
364 VOID
365 CreateVfrDriverList (
366 IN EFI_GUID *DriverGuidArray
367 )
368 {
369 UINTN Index;
370 VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
371
372 for (Index = 0; !IsZeroGuid (&DriverGuidArray[Index]); Index++) {
373 DEBUG ((DEBUG_INFO, "CreateVfrDriverList: %g\n", &DriverGuidArray[Index]));
374 VfrDriverInfo = InternalVarCheckAllocateZeroPool (sizeof (*VfrDriverInfo));
375 ASSERT (VfrDriverInfo != NULL);
376 VfrDriverInfo->Signature = VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE;
377 VfrDriverInfo->DriverGuid = &DriverGuidArray[Index];
378 InsertTailList (&mVfrDriverList, &VfrDriverInfo->Link);
379 }
380 }
381
382 /**
383 Destroy Vfr Driver List.
384
385 **/
386 VOID
387 DestroyVfrDriverList (
388 VOID
389 )
390 {
391 VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
392 LIST_ENTRY *VfrDriverLink;
393
394 while (mVfrDriverList.ForwardLink != &mVfrDriverList) {
395 VfrDriverLink = mVfrDriverList.ForwardLink;
396 VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);
397 RemoveEntryList (&VfrDriverInfo->Link);
398 InternalVarCheckFreePool (VfrDriverInfo);
399 }
400 }
401
402 /**
403 Generate from FV.
404
405 **/
406 VOID
407 VarCheckHiiGenFromFv (
408 VOID
409 )
410 {
411 EFI_GUID *DriverGuidArray;
412 BOOLEAN ScanAll;
413
414 DEBUG ((DEBUG_INFO, "VarCheckHiiGenDxeFromFv\n"));
415
416 //
417 // Get vfr driver guid array from PCD.
418 //
419 DriverGuidArray = (EFI_GUID *)PcdGetPtr (PcdVarCheckVfrDriverGuidArray);
420
421 if (IsZeroGuid (&DriverGuidArray[0])) {
422 //
423 // No VFR driver will be parsed from FVs.
424 //
425 return;
426 }
427
428 if (CompareGuid (&DriverGuidArray[0], &mAllFfGuid)) {
429 ScanAll = TRUE;
430 } else {
431 ScanAll = FALSE;
432 CreateVfrDriverList (DriverGuidArray);
433 }
434
435 ParseFv (ScanAll);
436
437 if (!ScanAll) {
438 DestroyVfrDriverList ();
439 }
440 }