1 /** @file 2 Firmware File System driver that produce Firmware Volume protocol. 3 Layers on top of Firmware Block protocol to produce a file abstraction 4 of FV based files. 5 6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include "DxeMain.h" 18 #include "FwVolDriver.h" 19 20 21 // 22 // Protocol notify related globals 23 // 24 VOID *gEfiFwVolBlockNotifyReg; 25 EFI_EVENT gEfiFwVolBlockEvent; 26 27 FV_DEVICE mFvDevice = { 28 FV2_DEVICE_SIGNATURE, 29 NULL, 30 NULL, 31 { 32 FvGetVolumeAttributes, 33 FvSetVolumeAttributes, 34 FvReadFile, 35 FvReadFileSection, 36 FvWriteFile, 37 FvGetNextFile, 38 sizeof (UINTN), 39 NULL, 40 FvGetVolumeInfo, 41 FvSetVolumeInfo 42 }, 43 NULL, 44 NULL, 45 NULL, 46 NULL, 47 { NULL, NULL }, 48 0, 49 0, 50 FALSE, 51 FALSE 52 }; 53 54 55 // 56 // FFS helper functions 57 // 58 /** 59 Read data from Firmware Block by FVB protocol Read. 60 The data may cross the multi block ranges. 61 62 @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data. 63 @param StartLba Pointer to StartLba. 64 On input, the start logical block index from which to read. 65 On output,the end logical block index after reading. 66 @param Offset Pointer to Offset 67 On input, offset into the block at which to begin reading. 68 On output, offset into the end block after reading. 69 @param DataSize Size of data to be read. 70 @param Data Pointer to Buffer that the data will be read into. 71 72 @retval EFI_SUCCESS Successfully read data from firmware block. 73 @retval others 74 **/ 75 EFI_STATUS 76 ReadFvbData ( 77 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, 78 IN OUT EFI_LBA *StartLba, 79 IN OUT UINTN *Offset, 80 IN UINTN DataSize, 81 OUT UINT8 *Data 82 ) 83 { 84 UINTN BlockSize; 85 UINTN NumberOfBlocks; 86 UINTN BlockIndex; 87 UINTN ReadDataSize; 88 EFI_STATUS Status; 89 90 // 91 // Try read data in current block 92 // 93 BlockIndex = 0; 94 ReadDataSize = DataSize; 95 Status = Fvb->Read (Fvb, *StartLba, *Offset, &ReadDataSize, Data); 96 if (Status == EFI_SUCCESS) { 97 *Offset += DataSize; 98 return EFI_SUCCESS; 99 } else if (Status != EFI_BAD_BUFFER_SIZE) { 100 // 101 // other error will direct return 102 // 103 return Status; 104 } 105 106 // 107 // Data crosses the blocks, read data from next block 108 // 109 DataSize -= ReadDataSize; 110 Data += ReadDataSize; 111 *StartLba = *StartLba + 1; 112 while (DataSize > 0) { 113 Status = Fvb->GetBlockSize (Fvb, *StartLba, &BlockSize, &NumberOfBlocks); 114 if (EFI_ERROR (Status)) { 115 return Status; 116 } 117 118 // 119 // Read data from the crossing blocks 120 // 121 BlockIndex = 0; 122 while (BlockIndex < NumberOfBlocks && DataSize >= BlockSize) { 123 Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &BlockSize, Data); 124 if (EFI_ERROR (Status)) { 125 return Status; 126 } 127 Data += BlockSize; 128 DataSize -= BlockSize; 129 BlockIndex ++; 130 } 131 132 // 133 // Data doesn't exceed the current block range. 134 // 135 if (DataSize < BlockSize) { 136 break; 137 } 138 139 // 140 // Data must be got from the next block range. 141 // 142 *StartLba += NumberOfBlocks; 143 } 144 145 // 146 // read the remaining data 147 // 148 if (DataSize > 0) { 149 Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &DataSize, Data); 150 if (EFI_ERROR (Status)) { 151 return Status; 152 } 153 } 154 155 // 156 // Update Lba and Offset used by the following read. 157 // 158 *StartLba += BlockIndex; 159 *Offset = DataSize; 160 161 return EFI_SUCCESS; 162 } 163 164 /** 165 Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and 166 copy the real length volume header into it. 167 168 @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to 169 read the volume header 170 @param FwVolHeader Pointer to pointer to allocated buffer in which 171 the volume header is returned. 172 173 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. 174 @retval EFI_SUCCESS Successfully read volume header to the allocated 175 buffer. 176 @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or 177 the file system could not be understood. 178 179 **/ 180 EFI_STATUS 181 GetFwVolHeader ( 182 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, 183 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader 184 ) 185 { 186 EFI_STATUS Status; 187 EFI_FIRMWARE_VOLUME_HEADER TempFvh; 188 UINTN FvhLength; 189 EFI_LBA StartLba; 190 UINTN Offset; 191 UINT8 *Buffer; 192 193 // 194 // Read the standard FV header 195 // 196 StartLba = 0; 197 Offset = 0; 198 FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER); 199 Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh); 200 if (EFI_ERROR (Status)) { 201 return Status; 202 } 203 204 // 205 // Validate FV Header signature, if not as expected, continue. 206 // 207 if (TempFvh.Signature != EFI_FVH_SIGNATURE) { 208 return EFI_INVALID_PARAMETER; 209 } 210 211 // 212 // Check to see that the file system is indeed formatted in a way we can 213 // understand it... 214 // 215 if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) && 216 (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) { 217 return EFI_INVALID_PARAMETER; 218 } 219 220 // 221 // Allocate a buffer for the caller 222 // 223 *FwVolHeader = AllocatePool (TempFvh.HeaderLength); 224 if (*FwVolHeader == NULL) { 225 return EFI_OUT_OF_RESOURCES; 226 } 227 228 // 229 // Copy the standard header into the buffer 230 // 231 CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); 232 233 // 234 // Read the rest of the header 235 // 236 FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER); 237 Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER); 238 Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer); 239 if (EFI_ERROR (Status)) { 240 // 241 // Read failed so free buffer 242 // 243 CoreFreePool (*FwVolHeader); 244 } 245 246 return Status; 247 } 248 249 250 251 /** 252 Free FvDevice resource when error happens 253 254 @param FvDevice pointer to the FvDevice to be freed. 255 256 **/ 257 VOID 258 FreeFvDeviceResource ( 259 IN FV_DEVICE *FvDevice 260 ) 261 { 262 FFS_FILE_LIST_ENTRY *FfsFileEntry; 263 LIST_ENTRY *NextEntry; 264 265 // 266 // Free File List Entry 267 // 268 FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink; 269 while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) { 270 NextEntry = (&FfsFileEntry->Link)->ForwardLink; 271 272 if (FfsFileEntry->StreamHandle != 0) { 273 // 274 // Close stream and free resources from SEP 275 // 276 CloseSectionStream (FfsFileEntry->StreamHandle, FALSE); 277 } 278 279 if (FfsFileEntry->FileCached) { 280 // 281 // Free the cached file buffer. 282 // 283 CoreFreePool (FfsFileEntry->FfsHeader); 284 } 285 286 CoreFreePool (FfsFileEntry); 287 288 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry; 289 } 290 291 if (!FvDevice->IsMemoryMapped) { 292 // 293 // Free the cached FV buffer. 294 // 295 CoreFreePool (FvDevice->CachedFv); 296 } 297 298 // 299 // Free Volume Header 300 // 301 CoreFreePool (FvDevice->FwVolHeader); 302 303 return; 304 } 305 306 307 308 /** 309 Check if an FV is consistent and allocate cache for it. 310 311 @param FvDevice A pointer to the FvDevice to be checked. 312 313 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. 314 @retval EFI_SUCCESS FV is consistent and cache is allocated. 315 @retval EFI_VOLUME_CORRUPTED File system is corrupted. 316 317 **/ 318 EFI_STATUS 319 FvCheck ( 320 IN OUT FV_DEVICE *FvDevice 321 ) 322 { 323 EFI_STATUS Status; 324 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; 325 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; 326 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; 327 EFI_FVB_ATTRIBUTES_2 FvbAttributes; 328 EFI_FV_BLOCK_MAP_ENTRY *BlockMap; 329 FFS_FILE_LIST_ENTRY *FfsFileEntry; 330 EFI_FFS_FILE_HEADER *FfsHeader; 331 UINT8 *CacheLocation; 332 UINTN LbaOffset; 333 UINTN HeaderSize; 334 UINTN Index; 335 EFI_LBA LbaIndex; 336 UINTN Size; 337 EFI_FFS_FILE_STATE FileState; 338 UINT8 *TopFvAddress; 339 UINTN TestLength; 340 EFI_PHYSICAL_ADDRESS PhysicalAddress; 341 BOOLEAN FileCached; 342 UINTN WholeFileSize; 343 EFI_FFS_FILE_HEADER *CacheFfsHeader; 344 345 FileCached = FALSE; 346 CacheFfsHeader = NULL; 347 348 Fvb = FvDevice->Fvb; 349 FwVolHeader = FvDevice->FwVolHeader; 350 351 Status = Fvb->GetAttributes (Fvb, &FvbAttributes); 352 if (EFI_ERROR (Status)) { 353 return Status; 354 } 355 356 // 357 // Size is the size of the FV minus the head. We have already allocated 358 // the header to check to make sure the volume is valid 359 // 360 Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength); 361 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { 362 FvDevice->IsMemoryMapped = TRUE; 363 364 Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress); 365 if (EFI_ERROR (Status)) { 366 return Status; 367 } 368 369 // 370 // Don't cache memory mapped FV really. 371 // 372 FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength); 373 } else { 374 FvDevice->IsMemoryMapped = FALSE; 375 FvDevice->CachedFv = AllocatePool (Size); 376 377 if (FvDevice->CachedFv == NULL) { 378 return EFI_OUT_OF_RESOURCES; 379 } 380 } 381 382 // 383 // Remember a pointer to the end fo the CachedFv 384 // 385 FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; 386 387 if (!FvDevice->IsMemoryMapped) { 388 // 389 // Copy FV minus header into memory using the block map we have all ready 390 // read into memory. 391 // 392 BlockMap = FwVolHeader->BlockMap; 393 CacheLocation = FvDevice->CachedFv; 394 LbaIndex = 0; 395 LbaOffset = 0; 396 HeaderSize = FwVolHeader->HeaderLength; 397 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { 398 Index = 0; 399 Size = BlockMap->Length; 400 if (HeaderSize > 0) { 401 // 402 // Skip header size 403 // 404 for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) { 405 HeaderSize -= BlockMap->Length; 406 LbaIndex ++; 407 } 408 409 // 410 // Check whether FvHeader is crossing the multi block range. 411 // 412 if (Index >= BlockMap->NumBlocks) { 413 BlockMap++; 414 continue; 415 } else if (HeaderSize > 0) { 416 LbaOffset = HeaderSize; 417 Size = BlockMap->Length - HeaderSize; 418 HeaderSize = 0; 419 } 420 } 421 422 // 423 // read the FV data 424 // 425 for (; Index < BlockMap->NumBlocks; Index ++) { 426 Status = Fvb->Read (Fvb, 427 LbaIndex, 428 LbaOffset, 429 &Size, 430 CacheLocation 431 ); 432 433 // 434 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length 435 // 436 if (EFI_ERROR (Status)) { 437 goto Done; 438 } 439 440 LbaIndex++; 441 CacheLocation += Size; 442 443 // 444 // After we skip Fv Header always read from start of block 445 // 446 LbaOffset = 0; 447 Size = BlockMap->Length; 448 } 449 450 BlockMap++; 451 } 452 } 453 454 // 455 // Scan to check the free space & File list 456 // 457 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { 458 FvDevice->ErasePolarity = 1; 459 } else { 460 FvDevice->ErasePolarity = 0; 461 } 462 463 464 // 465 // go through the whole FV cache, check the consistence of the FV. 466 // Make a linked list of all the Ffs file headers 467 // 468 Status = EFI_SUCCESS; 469 InitializeListHead (&FvDevice->FfsFileListHeader); 470 471 // 472 // Build FFS list 473 // 474 if (FwVolHeader->ExtHeaderOffset != 0) { 475 // 476 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. 477 // 478 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + (FwVolHeader->ExtHeaderOffset - FwVolHeader->HeaderLength)); 479 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize); 480 FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8); 481 } else { 482 FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv); 483 } 484 TopFvAddress = FvDevice->EndOfCachedFv; 485 while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) { 486 487 if (FileCached) { 488 CoreFreePool (CacheFfsHeader); 489 FileCached = FALSE; 490 } 491 492 TestLength = TopFvAddress - ((UINT8 *) FfsHeader); 493 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { 494 TestLength = sizeof (EFI_FFS_FILE_HEADER); 495 } 496 497 if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) { 498 // 499 // We have found the free space so we are done! 500 // 501 goto Done; 502 } 503 504 if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) { 505 if ((FileState == EFI_FILE_HEADER_INVALID) || 506 (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { 507 if (IS_FFS_FILE2 (FfsHeader)) { 508 if (!FvDevice->IsFfs3Fv) { 509 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name)); 510 } 511 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2)); 512 } else { 513 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER)); 514 } 515 continue; 516 } else { 517 // 518 // File system is corrputed 519 // 520 Status = EFI_VOLUME_CORRUPTED; 521 goto Done; 522 } 523 } 524 525 CacheFfsHeader = FfsHeader; 526 if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { 527 if (FvDevice->IsMemoryMapped) { 528 // 529 // Memory mapped FV has not been cached. 530 // Here is to cache FFS file to memory buffer for following checksum calculating. 531 // And then, the cached file buffer can be also used for FvReadFile. 532 // 533 WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader); 534 CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader); 535 if (CacheFfsHeader == NULL) { 536 Status = EFI_OUT_OF_RESOURCES; 537 goto Done; 538 } 539 FileCached = TRUE; 540 } 541 } 542 543 if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) { 544 // 545 // File system is corrupted 546 // 547 Status = EFI_VOLUME_CORRUPTED; 548 goto Done; 549 } 550 551 if (IS_FFS_FILE2 (CacheFfsHeader)) { 552 ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF); 553 if (!FvDevice->IsFfs3Fv) { 554 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name)); 555 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); 556 // 557 // Adjust pointer to the next 8-byte aligned boundry. 558 // 559 FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07); 560 continue; 561 } 562 } 563 564 FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader); 565 566 // 567 // check for non-deleted file 568 // 569 if (FileState != EFI_FILE_DELETED) { 570 // 571 // Create a FFS list entry for each non-deleted file 572 // 573 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); 574 if (FfsFileEntry == NULL) { 575 Status = EFI_OUT_OF_RESOURCES; 576 goto Done; 577 } 578 579 FfsFileEntry->FfsHeader = CacheFfsHeader; 580 FfsFileEntry->FileCached = FileCached; 581 FileCached = FALSE; 582 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); 583 } 584 585 if (IS_FFS_FILE2 (CacheFfsHeader)) { 586 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); 587 } else { 588 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader)); 589 } 590 591 // 592 // Adjust pointer to the next 8-byte aligned boundry. 593 // 594 FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07); 595 596 } 597 598 Done: 599 if (EFI_ERROR (Status)) { 600 if (FileCached) { 601 CoreFreePool (CacheFfsHeader); 602 FileCached = FALSE; 603 } 604 FreeFvDeviceResource (FvDevice); 605 } 606 607 return Status; 608 } 609 610 611 612 /** 613 This notification function is invoked when an instance of the 614 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the 615 EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where 616 the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done. 617 618 @param Event The event that occured 619 @param Context For EFI compatiblity. Not used. 620 621 **/ 622 VOID 623 EFIAPI 624 NotifyFwVolBlock ( 625 IN EFI_EVENT Event, 626 IN VOID *Context 627 ) 628 { 629 EFI_HANDLE Handle; 630 EFI_STATUS Status; 631 UINTN BufferSize; 632 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; 633 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; 634 FV_DEVICE *FvDevice; 635 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; 636 // 637 // Examine all new handles 638 // 639 for (;;) { 640 // 641 // Get the next handle 642 // 643 BufferSize = sizeof (Handle); 644 Status = CoreLocateHandle ( 645 ByRegisterNotify, 646 NULL, 647 gEfiFwVolBlockNotifyReg, 648 &BufferSize, 649 &Handle 650 ); 651 652 // 653 // If not found, we're done 654 // 655 if (EFI_NOT_FOUND == Status) { 656 break; 657 } 658 659 if (EFI_ERROR (Status)) { 660 continue; 661 } 662 663 // 664 // Get the FirmwareVolumeBlock protocol on that handle 665 // 666 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); 667 ASSERT_EFI_ERROR (Status); 668 ASSERT (Fvb != NULL); 669 670 // 671 // Make sure the Fv Header is O.K. 672 // 673 Status = GetFwVolHeader (Fvb, &FwVolHeader); 674 if (EFI_ERROR (Status)) { 675 continue; 676 } 677 ASSERT (FwVolHeader != NULL); 678 679 if (!VerifyFvHeaderChecksum (FwVolHeader)) { 680 CoreFreePool (FwVolHeader); 681 continue; 682 } 683 684 // 685 // Check if there is an FV protocol already installed in that handle 686 // 687 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); 688 if (!EFI_ERROR (Status)) { 689 // 690 // Update Fv to use a new Fvb 691 // 692 FvDevice = BASE_CR (Fv, FV_DEVICE, Fv); 693 if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) { 694 // 695 // Only write into our device structure if it's our device structure 696 // 697 FvDevice->Fvb = Fvb; 698 } 699 700 } else { 701 // 702 // No FwVol protocol on the handle so create a new one 703 // 704 FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice); 705 if (FvDevice == NULL) { 706 return; 707 } 708 709 FvDevice->Fvb = Fvb; 710 FvDevice->Handle = Handle; 711 FvDevice->FwVolHeader = FwVolHeader; 712 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); 713 FvDevice->Fv.ParentHandle = Fvb->ParentHandle; 714 715 if (Fvb->ParentHandle != NULL) { 716 // 717 // Inherit the authentication status from FVB. 718 // 719 FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb); 720 } 721 722 if (!EFI_ERROR (FvCheck (FvDevice))) { 723 // 724 // Install an New FV protocol on the existing handle 725 // 726 Status = CoreInstallProtocolInterface ( 727 &Handle, 728 &gEfiFirmwareVolume2ProtocolGuid, 729 EFI_NATIVE_INTERFACE, 730 &FvDevice->Fv 731 ); 732 ASSERT_EFI_ERROR (Status); 733 } else { 734 // 735 // Free FvDevice Buffer for the corrupt FV image. 736 // 737 CoreFreePool (FvDevice); 738 } 739 } 740 } 741 742 return; 743 } 744 745 746 747 /** 748 This routine is the driver initialization entry point. It registers 749 a notification function. This notification function are responsible 750 for building the FV stack dynamically. 751 752 @param ImageHandle The image handle. 753 @param SystemTable The system table. 754 755 @retval EFI_SUCCESS Function successfully returned. 756 757 **/ 758 EFI_STATUS 759 EFIAPI 760 FwVolDriverInit ( 761 IN EFI_HANDLE ImageHandle, 762 IN EFI_SYSTEM_TABLE *SystemTable 763 ) 764 { 765 gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent ( 766 &gEfiFirmwareVolumeBlockProtocolGuid, 767 TPL_CALLBACK, 768 NotifyFwVolBlock, 769 NULL, 770 &gEfiFwVolBlockNotifyReg 771 ); 772 return EFI_SUCCESS; 773 } 774 775 776