]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg DxeCore: Handle FFS file with FFS_ATTRIB_CHECKSUM set for not cache...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVol / FwVol.c
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
177 **/
178 EFI_STATUS
179 GetFwVolHeader (
180 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
181 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
182 )
183 {
184 EFI_STATUS Status;
185 EFI_FIRMWARE_VOLUME_HEADER TempFvh;
186 UINTN FvhLength;
187 EFI_LBA StartLba;
188 UINTN Offset;
189 UINT8 *Buffer;
190
191 //
192 // Read the standard FV header
193 //
194 StartLba = 0;
195 Offset = 0;
196 FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
197 Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh);
198 if (EFI_ERROR (Status)) {
199 return Status;
200 }
201
202 //
203 // Allocate a buffer for the caller
204 //
205 *FwVolHeader = AllocatePool (TempFvh.HeaderLength);
206 if (*FwVolHeader == NULL) {
207 return EFI_OUT_OF_RESOURCES;
208 }
209
210 //
211 // Copy the standard header into the buffer
212 //
213 CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
214
215 //
216 // Read the rest of the header
217 //
218 FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);
219 Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);
220 Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer);
221 if (EFI_ERROR (Status)) {
222 //
223 // Read failed so free buffer
224 //
225 CoreFreePool (*FwVolHeader);
226 }
227
228 return Status;
229 }
230
231
232
233 /**
234 Free FvDevice resource when error happens
235
236 @param FvDevice pointer to the FvDevice to be freed.
237
238 **/
239 VOID
240 FreeFvDeviceResource (
241 IN FV_DEVICE *FvDevice
242 )
243 {
244 FFS_FILE_LIST_ENTRY *FfsFileEntry;
245 LIST_ENTRY *NextEntry;
246
247 //
248 // Free File List Entry
249 //
250 FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink;
251 while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
252 NextEntry = (&FfsFileEntry->Link)->ForwardLink;
253
254 if (FfsFileEntry->StreamHandle != 0) {
255 //
256 // Close stream and free resources from SEP
257 //
258 CloseSectionStream (FfsFileEntry->StreamHandle, FALSE);
259 }
260
261 if (FfsFileEntry->FileCached) {
262 //
263 // Free the cached file buffer.
264 //
265 CoreFreePool (FfsFileEntry->FfsHeader);
266 }
267
268 CoreFreePool (FfsFileEntry);
269
270 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
271 }
272
273 if (!FvDevice->IsMemoryMapped) {
274 //
275 // Free the cached FV buffer.
276 //
277 CoreFreePool (FvDevice->CachedFv);
278 }
279
280 //
281 // Free Volume Header
282 //
283 CoreFreePool (FvDevice->FwVolHeader);
284
285 return;
286 }
287
288
289
290 /**
291 Check if an FV is consistent and allocate cache for it.
292
293 @param FvDevice A pointer to the FvDevice to be checked.
294
295 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
296 @retval EFI_SUCCESS FV is consistent and cache is allocated.
297 @retval EFI_VOLUME_CORRUPTED File system is corrupted.
298
299 **/
300 EFI_STATUS
301 FvCheck (
302 IN OUT FV_DEVICE *FvDevice
303 )
304 {
305 EFI_STATUS Status;
306 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
307 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
308 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;
309 EFI_FVB_ATTRIBUTES_2 FvbAttributes;
310 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
311 FFS_FILE_LIST_ENTRY *FfsFileEntry;
312 EFI_FFS_FILE_HEADER *FfsHeader;
313 UINT8 *CacheLocation;
314 UINTN LbaOffset;
315 UINTN HeaderSize;
316 UINTN Index;
317 EFI_LBA LbaIndex;
318 UINTN Size;
319 EFI_FFS_FILE_STATE FileState;
320 UINT8 *TopFvAddress;
321 UINTN TestLength;
322 EFI_PHYSICAL_ADDRESS PhysicalAddress;
323 BOOLEAN FileCached;
324 UINTN WholeFileSize;
325 EFI_FFS_FILE_HEADER *CacheFfsHeader;
326
327 FileCached = FALSE;
328 CacheFfsHeader = NULL;
329
330 Fvb = FvDevice->Fvb;
331 FwVolHeader = FvDevice->FwVolHeader;
332
333 Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
334 if (EFI_ERROR (Status)) {
335 return Status;
336 }
337
338 //
339 // Size is the size of the FV minus the head. We have already allocated
340 // the header to check to make sure the volume is valid
341 //
342 Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);
343 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
344 FvDevice->IsMemoryMapped = TRUE;
345
346 Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress);
347 if (EFI_ERROR (Status)) {
348 return Status;
349 }
350
351 //
352 // Don't cache memory mapped FV really.
353 //
354 FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength);
355 } else {
356 FvDevice->IsMemoryMapped = FALSE;
357 FvDevice->CachedFv = AllocatePool (Size);
358
359 if (FvDevice->CachedFv == NULL) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362 }
363
364 //
365 // Remember a pointer to the end fo the CachedFv
366 //
367 FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;
368
369 if (!FvDevice->IsMemoryMapped) {
370 //
371 // Copy FV minus header into memory using the block map we have all ready
372 // read into memory.
373 //
374 BlockMap = FwVolHeader->BlockMap;
375 CacheLocation = FvDevice->CachedFv;
376 LbaIndex = 0;
377 LbaOffset = 0;
378 HeaderSize = FwVolHeader->HeaderLength;
379 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
380 Index = 0;
381 Size = BlockMap->Length;
382 if (HeaderSize > 0) {
383 //
384 // Skip header size
385 //
386 for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) {
387 HeaderSize -= BlockMap->Length;
388 LbaIndex ++;
389 }
390
391 //
392 // Check whether FvHeader is crossing the multi block range.
393 //
394 if (Index >= BlockMap->NumBlocks) {
395 BlockMap++;
396 continue;
397 } else if (HeaderSize > 0) {
398 LbaOffset = HeaderSize;
399 Size = BlockMap->Length - HeaderSize;
400 HeaderSize = 0;
401 }
402 }
403
404 //
405 // read the FV data
406 //
407 for (; Index < BlockMap->NumBlocks; Index ++) {
408 Status = Fvb->Read (Fvb,
409 LbaIndex,
410 LbaOffset,
411 &Size,
412 CacheLocation
413 );
414
415 //
416 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
417 //
418 if (EFI_ERROR (Status)) {
419 goto Done;
420 }
421
422 LbaIndex++;
423 CacheLocation += Size;
424
425 //
426 // After we skip Fv Header always read from start of block
427 //
428 LbaOffset = 0;
429 Size = BlockMap->Length;
430 }
431
432 BlockMap++;
433 }
434 }
435
436 //
437 // Scan to check the free space & File list
438 //
439 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {
440 FvDevice->ErasePolarity = 1;
441 } else {
442 FvDevice->ErasePolarity = 0;
443 }
444
445
446 //
447 // go through the whole FV cache, check the consistence of the FV.
448 // Make a linked list of all the Ffs file headers
449 //
450 Status = EFI_SUCCESS;
451 InitializeListHead (&FvDevice->FfsFileListHeader);
452
453 //
454 // Build FFS list
455 //
456 if (FwVolHeader->ExtHeaderOffset != 0) {
457 //
458 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
459 //
460 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + (FwVolHeader->ExtHeaderOffset - FwVolHeader->HeaderLength));
461 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);
462 FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8);
463 } else {
464 FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv);
465 }
466 TopFvAddress = FvDevice->EndOfCachedFv;
467 while ((UINT8 *) FfsHeader < TopFvAddress) {
468
469 if (FileCached) {
470 CoreFreePool (CacheFfsHeader);
471 FileCached = FALSE;
472 }
473
474 TestLength = TopFvAddress - ((UINT8 *) FfsHeader);
475 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
476 TestLength = sizeof (EFI_FFS_FILE_HEADER);
477 }
478
479 if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) {
480 //
481 // We have found the free space so we are done!
482 //
483 goto Done;
484 }
485
486 if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {
487 if ((FileState == EFI_FILE_HEADER_INVALID) ||
488 (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
489 if (IS_FFS_FILE2 (FfsHeader)) {
490 if (!FvDevice->IsFfs3Fv) {
491 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name));
492 }
493 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2));
494 } else {
495 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER));
496 }
497 continue;
498 } else {
499 //
500 // File system is corrputed
501 //
502 Status = EFI_VOLUME_CORRUPTED;
503 goto Done;
504 }
505 }
506
507 CacheFfsHeader = FfsHeader;
508 if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {
509 if (FvDevice->IsMemoryMapped) {
510 //
511 // Memory mapped FV has not been cached.
512 // Here is to cache FFS file to memory buffer for following checksum calculating.
513 // And then, the cached file buffer can be also used for FvReadFile.
514 //
515 WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader);
516 CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader);
517 if (CacheFfsHeader == NULL) {
518 Status = EFI_OUT_OF_RESOURCES;
519 goto Done;
520 }
521 FileCached = TRUE;
522 }
523 }
524
525 if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) {
526 //
527 // File system is corrupted
528 //
529 Status = EFI_VOLUME_CORRUPTED;
530 goto Done;
531 }
532
533 if (IS_FFS_FILE2 (CacheFfsHeader)) {
534 ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF);
535 if (!FvDevice->IsFfs3Fv) {
536 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name));
537 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));
538 //
539 // Adjust pointer to the next 8-byte aligned boundry.
540 //
541 FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07);
542 continue;
543 }
544 }
545
546 FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader);
547
548 //
549 // check for non-deleted file
550 //
551 if (FileState != EFI_FILE_DELETED) {
552 //
553 // Create a FFS list entry for each non-deleted file
554 //
555 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
556 if (FfsFileEntry == NULL) {
557 Status = EFI_OUT_OF_RESOURCES;
558 goto Done;
559 }
560
561 FfsFileEntry->FfsHeader = CacheFfsHeader;
562 FfsFileEntry->FileCached = FileCached;
563 FileCached = FALSE;
564 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
565 }
566
567 if (IS_FFS_FILE2 (CacheFfsHeader)) {
568 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));
569 } else {
570 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader));
571 }
572
573 //
574 // Adjust pointer to the next 8-byte aligned boundry.
575 //
576 FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);
577
578 }
579
580 Done:
581 if (EFI_ERROR (Status)) {
582 if (FileCached) {
583 CoreFreePool (CacheFfsHeader);
584 FileCached = FALSE;
585 }
586 FreeFvDeviceResource (FvDevice);
587 }
588
589 return Status;
590 }
591
592
593
594 /**
595 This notification function is invoked when an instance of the
596 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
597 EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where
598 the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.
599
600 @param Event The event that occured
601 @param Context For EFI compatiblity. Not used.
602
603 **/
604 VOID
605 EFIAPI
606 NotifyFwVolBlock (
607 IN EFI_EVENT Event,
608 IN VOID *Context
609 )
610 {
611 EFI_HANDLE Handle;
612 EFI_STATUS Status;
613 UINTN BufferSize;
614 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
615 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
616 FV_DEVICE *FvDevice;
617 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
618 //
619 // Examine all new handles
620 //
621 for (;;) {
622 //
623 // Get the next handle
624 //
625 BufferSize = sizeof (Handle);
626 Status = CoreLocateHandle (
627 ByRegisterNotify,
628 NULL,
629 gEfiFwVolBlockNotifyReg,
630 &BufferSize,
631 &Handle
632 );
633
634 //
635 // If not found, we're done
636 //
637 if (EFI_NOT_FOUND == Status) {
638 break;
639 }
640
641 if (EFI_ERROR (Status)) {
642 continue;
643 }
644
645 //
646 // Get the FirmwareVolumeBlock protocol on that handle
647 //
648 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
649 ASSERT_EFI_ERROR (Status);
650 ASSERT (Fvb != NULL);
651
652 //
653 // Make sure the Fv Header is O.K.
654 //
655 Status = GetFwVolHeader (Fvb, &FwVolHeader);
656 if (EFI_ERROR (Status)) {
657 return;
658 }
659 ASSERT (FwVolHeader != NULL);
660
661 if (!VerifyFvHeaderChecksum (FwVolHeader)) {
662 CoreFreePool (FwVolHeader);
663 continue;
664 }
665
666
667 //
668 // Check to see that the file system is indeed formatted in a way we can
669 // understand it...
670 //
671 if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&
672 (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {
673 continue;
674 }
675
676 //
677 // Check if there is an FV protocol already installed in that handle
678 //
679 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
680 if (!EFI_ERROR (Status)) {
681 //
682 // Update Fv to use a new Fvb
683 //
684 FvDevice = BASE_CR (Fv, FV_DEVICE, Fv);
685 if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) {
686 //
687 // Only write into our device structure if it's our device structure
688 //
689 FvDevice->Fvb = Fvb;
690 }
691
692 } else {
693 //
694 // No FwVol protocol on the handle so create a new one
695 //
696 FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);
697 if (FvDevice == NULL) {
698 return;
699 }
700
701 FvDevice->Fvb = Fvb;
702 FvDevice->Handle = Handle;
703 FvDevice->FwVolHeader = FwVolHeader;
704 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
705 FvDevice->Fv.ParentHandle = Fvb->ParentHandle;
706
707 if (Fvb->ParentHandle != NULL) {
708 //
709 // Inherit the authentication status from FVB.
710 //
711 FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb);
712 }
713
714 if (!EFI_ERROR (FvCheck (FvDevice))) {
715 //
716 // Install an New FV protocol on the existing handle
717 //
718 Status = CoreInstallProtocolInterface (
719 &Handle,
720 &gEfiFirmwareVolume2ProtocolGuid,
721 EFI_NATIVE_INTERFACE,
722 &FvDevice->Fv
723 );
724 ASSERT_EFI_ERROR (Status);
725 } else {
726 //
727 // Free FvDevice Buffer for the corrupt FV image.
728 //
729 CoreFreePool (FvDevice);
730 }
731 }
732 }
733
734 return;
735 }
736
737
738
739 /**
740 This routine is the driver initialization entry point. It registers
741 a notification function. This notification function are responsible
742 for building the FV stack dynamically.
743
744 @param ImageHandle The image handle.
745 @param SystemTable The system table.
746
747 @retval EFI_SUCCESS Function successfully returned.
748
749 **/
750 EFI_STATUS
751 EFIAPI
752 FwVolDriverInit (
753 IN EFI_HANDLE ImageHandle,
754 IN EFI_SYSTEM_TABLE *SystemTable
755 )
756 {
757 gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent (
758 &gEfiFirmwareVolumeBlockProtocolGuid,
759 TPL_CALLBACK,
760 NotifyFwVolBlock,
761 NULL,
762 &gEfiFwVolBlockNotifyReg
763 );
764 return EFI_SUCCESS;
765 }
766
767