1/** @file 2 Var Check Hii generation from FV. 3 4Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT 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 21EFI_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 26EFI_GUID mAllFfGuid = ALL_FF_GUID; 27 28#define VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('V', 'D', 'R', 'I') 29 30typedef struct { 31 UINTN Signature; 32 LIST_ENTRY Link; 33 EFI_GUID *DriverGuid; 34} VAR_CHECK_VFR_DRIVER_INFO; 35 36LIST_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**/ 58EFI_STATUS 59GetAddressByGuid ( 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**/ 117EFI_STATUS 118SearchVfrBinInFfs ( 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**/ 167BOOLEAN 168ParseFfs ( 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**/ 252VOID 253ParseFv ( 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**/ 367VOID 368CreateVfrDriverList ( 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**/ 389VOID 390DestroyVfrDriverList ( 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**/ 409VOID 410VarCheckHiiGenFromFv ( 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