]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
MdeModulePkg: Change complex DEBUG_CODE() to DEBUG_CODE_BEGIN/END()
[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 *(*Offset + *NumOfMatchingGuid) = LoopControl + sizeof (EFI_GUID);
86 (*NumOfMatchingGuid)++;
87 } else {
88 break;
89 }
90 }
91 }
92
93 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
94 }
95
96 /**
97 Search the VfrBin Base address.
98
99 According to the known GUID gVfrArrayAttractGuid to get the base address from FFS.
100
101 @param Ffs Pointer to the FFS.
102 @param EfiAddr Pointer to the EFI in FFS
103 @param Length The length of FFS.
104 @param Offset Pointer to pointer to the Addr (Offset).
105 @param NumOfMatchingOffset The number of Addr (Offset).
106
107 @retval EFI_SUCCESS Get the address successfully.
108 @retval EFI_NOT_FOUND No VfrBin found.
109
110 **/
111 EFI_STATUS
112 SearchVfrBinInFfs (
113 IN VOID *Ffs,
114 IN VOID *EfiAddr,
115 IN UINTN Length,
116 OUT UINTN **Offset,
117 OUT UINT8 *NumOfMatchingOffset
118 )
119 {
120 UINTN Index;
121 EFI_STATUS Status;
122 UINTN VirOffValue;
123
124 if ((Ffs == NULL) || (Offset == NULL)) {
125 return EFI_NOT_FOUND;
126 }
127 Status = GetAddressByGuid (
128 Ffs,
129 &gVfrArrayAttractGuid,
130 Length,
131 Offset,
132 NumOfMatchingOffset
133 );
134 if (Status != EFI_SUCCESS) {
135 return Status;
136 }
137
138 for (Index = 0; Index < *NumOfMatchingOffset; Index++) {
139 //
140 // Got the virOffset after the GUID
141 //
142 VirOffValue = *(UINTN *) ((UINTN) Ffs + *(*Offset + Index));
143 //
144 // Transfer the offset to the VA address. One modules may own multiple VfrBin address.
145 //
146 *(*Offset + Index) = (UINTN) EfiAddr + VirOffValue;
147 }
148
149 return Status;
150 }
151
152 /**
153 Parse FFS.
154
155 @param[in] Fv2 Pointer to Fv2 protocol.
156 @param[in] DriverGuid Pointer to driver GUID.
157
158 @return Found the driver in the FV or not.
159
160 **/
161 BOOLEAN
162 ParseFfs (
163 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2,
164 IN EFI_GUID *DriverGuid
165 )
166 {
167 EFI_STATUS Status;
168 EFI_FV_FILETYPE FoundType;
169 EFI_FV_FILE_ATTRIBUTES FileAttributes;
170 UINT32 AuthenticationStatus;
171 UINTN Size;
172 VOID *Buffer;
173 UINTN SectionSize;
174 VOID *SectionBuffer;
175 UINTN VfrBinIndex;
176 UINT8 NumberofMatchingVfrBin;
177 UINTN *VfrBinBaseAddress;
178
179 Status = Fv2->ReadFile (
180 Fv2,
181 DriverGuid,
182 NULL,
183 &Size,
184 &FoundType,
185 &FileAttributes,
186 &AuthenticationStatus
187 );
188 if (EFI_ERROR (Status)) {
189 return FALSE;
190 }
191
192 Buffer = NULL;
193 Status = Fv2->ReadSection (
194 Fv2,
195 DriverGuid,
196 EFI_SECTION_RAW,
197 0, // Instance
198 &Buffer,
199 &Size,
200 &AuthenticationStatus
201 );
202 if (!EFI_ERROR (Status)) {
203 Status = SearchVfrBinInFfs (Buffer, 0, Size, &VfrBinBaseAddress, &NumberofMatchingVfrBin);
204 if (!EFI_ERROR (Status)) {
205 SectionBuffer = NULL;
206 Status = Fv2->ReadSection (
207 Fv2,
208 DriverGuid,
209 EFI_SECTION_PE32,
210 0, // Instance
211 &SectionBuffer,
212 &SectionSize,
213 &AuthenticationStatus
214 );
215 if (!EFI_ERROR (Status)) {
216 DEBUG ((DEBUG_INFO , "FfsNameGuid - %g\n", DriverGuid));
217 DEBUG ((DEBUG_INFO , "NumberofMatchingVfrBin - 0x%02x\n", NumberofMatchingVfrBin));
218
219 for (VfrBinIndex = 0; VfrBinIndex < NumberofMatchingVfrBin; VfrBinIndex++) {
220 #ifdef DUMP_HII_DATA
221 DEBUG_CODE (
222 DumpHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32));
223 );
224 #endif
225 VarCheckParseHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32), TRUE);
226 }
227
228 FreePool (SectionBuffer);
229 }
230
231 InternalVarCheckFreePool (VfrBinBaseAddress);
232 }
233
234 FreePool (Buffer);
235 }
236
237 return TRUE;
238 }
239
240 /**
241 Parse FVs.
242
243 @param[in] ScanAll Scan all modules in all FVs or not.
244
245 **/
246 VOID
247 ParseFv (
248 IN BOOLEAN ScanAll
249 )
250 {
251 EFI_STATUS Status;
252 EFI_HANDLE *HandleBuffer;
253 UINTN HandleCount;
254 UINTN Index;
255 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2;
256 VOID *Key;
257 EFI_FV_FILETYPE FileType;
258 EFI_GUID NameGuid;
259 EFI_FV_FILE_ATTRIBUTES FileAttributes;
260 UINTN Size;
261 UINTN FfsIndex;
262 VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
263 LIST_ENTRY *VfrDriverLink;
264
265 HandleBuffer = NULL;
266 Status = gBS->LocateHandleBuffer (
267 ByProtocol,
268 &gEfiFirmwareVolume2ProtocolGuid,
269 NULL,
270 &HandleCount,
271 &HandleBuffer
272 );
273 if (EFI_ERROR (Status)) {
274 return;
275 }
276
277 //
278 // Search all FVs
279 //
280 for (Index = 0; Index < HandleCount; Index++) {
281 DEBUG ((DEBUG_INFO , "FvIndex - %x\n", Index));
282 Status = gBS->HandleProtocol (
283 HandleBuffer[Index],
284 &gEfiFirmwareVolume2ProtocolGuid,
285 (VOID **) &Fv2
286 );
287 ASSERT_EFI_ERROR (Status);
288
289 DEBUG_CODE_BEGIN ();
290 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvb2;
291 EFI_PHYSICAL_ADDRESS FvAddress;
292 UINT64 FvSize;
293
294 Status = gBS->HandleProtocol (
295 HandleBuffer[Index],
296 &gEfiFirmwareVolumeBlock2ProtocolGuid,
297 (VOID **) &Fvb2
298 );
299 ASSERT_EFI_ERROR (Status);
300 Status = Fvb2->GetPhysicalAddress (Fvb2, &FvAddress);
301 if (!EFI_ERROR (Status)) {
302 DEBUG ((DEBUG_INFO , "FvAddress - 0x%08x\n", FvAddress));
303 FvSize = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvAddress)->FvLength;
304 DEBUG ((DEBUG_INFO , "FvSize - 0x%08x\n", FvSize));
305 }
306 DEBUG_CODE_END ();
307
308 if (ScanAll) {
309 //
310 // Need to parse all modules in all FVs.
311 //
312 Key = InternalVarCheckAllocateZeroPool (Fv2->KeySize);
313 ASSERT (Key != NULL);
314
315 for (FfsIndex = 0; ; FfsIndex++) {
316 FileType = EFI_FV_FILETYPE_ALL;
317 Status = Fv2->GetNextFile (
318 Fv2,
319 Key,
320 &FileType,
321 &NameGuid,
322 &FileAttributes,
323 &Size
324 );
325 if (EFI_ERROR (Status)) {
326 break;
327 }
328
329 ParseFfs (Fv2, &NameGuid);
330 }
331
332 InternalVarCheckFreePool (Key);
333 } else {
334 //
335 // Only parse drivers in the VFR drivers list.
336 //
337 VfrDriverLink = mVfrDriverList.ForwardLink;
338 while (VfrDriverLink != &mVfrDriverList) {
339 VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);
340 VfrDriverLink = VfrDriverLink->ForwardLink;
341 if (ParseFfs (Fv2, VfrDriverInfo->DriverGuid)) {
342 //
343 // Found the driver in the FV.
344 //
345 RemoveEntryList (&VfrDriverInfo->Link);
346 InternalVarCheckFreePool (VfrDriverInfo);
347 }
348 }
349 }
350 }
351
352 FreePool (HandleBuffer);
353 }
354
355 /**
356 Create Vfr Driver List.
357
358 @param[in] DriverGuidArray Driver Guid Array
359
360 **/
361 VOID
362 CreateVfrDriverList (
363 IN EFI_GUID *DriverGuidArray
364 )
365 {
366 UINTN Index;
367 VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
368
369 for (Index = 0; !IsZeroGuid (&DriverGuidArray[Index]); Index++) {
370 DEBUG ((DEBUG_INFO , "CreateVfrDriverList: %g\n", &DriverGuidArray[Index]));
371 VfrDriverInfo = InternalVarCheckAllocateZeroPool (sizeof (*VfrDriverInfo));
372 ASSERT (VfrDriverInfo != NULL);
373 VfrDriverInfo->Signature = VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE;
374 VfrDriverInfo->DriverGuid = &DriverGuidArray[Index];
375 InsertTailList (&mVfrDriverList, &VfrDriverInfo->Link);
376 }
377 }
378
379 /**
380 Destroy Vfr Driver List.
381
382 **/
383 VOID
384 DestroyVfrDriverList (
385 VOID
386 )
387 {
388 VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
389 LIST_ENTRY *VfrDriverLink;
390
391 while (mVfrDriverList.ForwardLink != &mVfrDriverList) {
392 VfrDriverLink = mVfrDriverList.ForwardLink;
393 VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);
394 RemoveEntryList (&VfrDriverInfo->Link);
395 InternalVarCheckFreePool (VfrDriverInfo);
396 }
397 }
398
399 /**
400 Generate from FV.
401
402 **/
403 VOID
404 VarCheckHiiGenFromFv (
405 VOID
406 )
407 {
408 EFI_GUID *DriverGuidArray;
409 BOOLEAN ScanAll;
410
411 DEBUG ((DEBUG_INFO , "VarCheckHiiGenDxeFromFv\n"));
412
413 //
414 // Get vfr driver guid array from PCD.
415 //
416 DriverGuidArray = (EFI_GUID *) PcdGetPtr (PcdVarCheckVfrDriverGuidArray);
417
418 if (IsZeroGuid (&DriverGuidArray[0])) {
419 //
420 // No VFR driver will be parsed from FVs.
421 //
422 return;
423 }
424
425 if (CompareGuid (&DriverGuidArray[0], &mAllFfGuid)) {
426 ScanAll = TRUE;
427 } else {
428 ScanAll = FALSE;
429 CreateVfrDriverList (DriverGuidArray);
430 }
431
432 ParseFv (ScanAll);
433
434 if (!ScanAll) {
435 DestroyVfrDriverList ();
436 }
437 }