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