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