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