]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg/Core: Fix typos in comments
[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 @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 boundary.
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 boundary.
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