]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg/DxeCore: Ensure FfsFileHeader 8 bytes aligned
[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 - 2019, 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 Index;
333 EFI_LBA LbaIndex;
334 UINTN Size;
335 EFI_FFS_FILE_STATE FileState;
336 UINT8 *TopFvAddress;
337 UINTN TestLength;
338 EFI_PHYSICAL_ADDRESS PhysicalAddress;
339 BOOLEAN FileCached;
340 UINTN WholeFileSize;
341 EFI_FFS_FILE_HEADER *CacheFfsHeader;
342
343 FileCached = FALSE;
344 CacheFfsHeader = NULL;
345
346 Fvb = FvDevice->Fvb;
347 FwVolHeader = FvDevice->FwVolHeader;
348
349 Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353
354 Size = (UINTN) FwVolHeader->FvLength;
355 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
356 FvDevice->IsMemoryMapped = TRUE;
357
358 Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress);
359 if (EFI_ERROR (Status)) {
360 return Status;
361 }
362
363 //
364 // Don't cache memory mapped FV really.
365 //
366 FvDevice->CachedFv = (UINT8 *) (UINTN) PhysicalAddress;
367 } else {
368 FvDevice->IsMemoryMapped = FALSE;
369 FvDevice->CachedFv = AllocatePool (Size);
370
371 if (FvDevice->CachedFv == NULL) {
372 return EFI_OUT_OF_RESOURCES;
373 }
374 }
375
376 //
377 // Remember a pointer to the end of the CachedFv
378 //
379 FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;
380
381 if (!FvDevice->IsMemoryMapped) {
382 //
383 // Copy FV into memory using the block map.
384 //
385 BlockMap = FwVolHeader->BlockMap;
386 CacheLocation = FvDevice->CachedFv;
387 LbaIndex = 0;
388 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
389 //
390 // read the FV data
391 //
392 Size = BlockMap->Length;
393 for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
394 Status = Fvb->Read (
395 Fvb,
396 LbaIndex,
397 0,
398 &Size,
399 CacheLocation
400 );
401
402 //
403 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
404 //
405 if (EFI_ERROR (Status)) {
406 goto Done;
407 }
408
409 LbaIndex++;
410 CacheLocation += BlockMap->Length;
411 }
412
413 BlockMap++;
414 }
415 }
416
417 //
418 // Scan to check the free space & File list
419 //
420 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {
421 FvDevice->ErasePolarity = 1;
422 } else {
423 FvDevice->ErasePolarity = 0;
424 }
425
426
427 //
428 // go through the whole FV cache, check the consistence of the FV.
429 // Make a linked list of all the Ffs file headers
430 //
431 Status = EFI_SUCCESS;
432 InitializeListHead (&FvDevice->FfsFileListHeader);
433
434 //
435 // Build FFS list
436 //
437 if (FwVolHeader->ExtHeaderOffset != 0) {
438 //
439 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
440 //
441 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + FwVolHeader->ExtHeaderOffset);
442 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);
443 } else {
444 FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv + FwVolHeader->HeaderLength);
445 }
446 FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8);
447 TopFvAddress = FvDevice->EndOfCachedFv;
448 while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) {
449
450 if (FileCached) {
451 CoreFreePool (CacheFfsHeader);
452 FileCached = FALSE;
453 }
454
455 TestLength = TopFvAddress - ((UINT8 *) FfsHeader);
456 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
457 TestLength = sizeof (EFI_FFS_FILE_HEADER);
458 }
459
460 if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) {
461 //
462 // We have found the free space so we are done!
463 //
464 goto Done;
465 }
466
467 if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {
468 if ((FileState == EFI_FILE_HEADER_INVALID) ||
469 (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
470 if (IS_FFS_FILE2 (FfsHeader)) {
471 if (!FvDevice->IsFfs3Fv) {
472 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name));
473 }
474 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2));
475 } else {
476 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER));
477 }
478 continue;
479 } else {
480 //
481 // File system is corrputed
482 //
483 Status = EFI_VOLUME_CORRUPTED;
484 goto Done;
485 }
486 }
487
488 CacheFfsHeader = FfsHeader;
489 if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {
490 if (FvDevice->IsMemoryMapped) {
491 //
492 // Memory mapped FV has not been cached.
493 // Here is to cache FFS file to memory buffer for following checksum calculating.
494 // And then, the cached file buffer can be also used for FvReadFile.
495 //
496 WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader);
497 CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader);
498 if (CacheFfsHeader == NULL) {
499 Status = EFI_OUT_OF_RESOURCES;
500 goto Done;
501 }
502 FileCached = TRUE;
503 }
504 }
505
506 if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) {
507 //
508 // File system is corrupted
509 //
510 Status = EFI_VOLUME_CORRUPTED;
511 goto Done;
512 }
513
514 if (IS_FFS_FILE2 (CacheFfsHeader)) {
515 ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF);
516 if (!FvDevice->IsFfs3Fv) {
517 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name));
518 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));
519 //
520 // Adjust pointer to the next 8-byte aligned boundary.
521 //
522 FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07);
523 continue;
524 }
525 }
526
527 FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader);
528
529 //
530 // check for non-deleted file
531 //
532 if (FileState != EFI_FILE_DELETED) {
533 //
534 // Create a FFS list entry for each non-deleted file
535 //
536 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
537 if (FfsFileEntry == NULL) {
538 Status = EFI_OUT_OF_RESOURCES;
539 goto Done;
540 }
541
542 FfsFileEntry->FfsHeader = CacheFfsHeader;
543 FfsFileEntry->FileCached = FileCached;
544 FileCached = FALSE;
545 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
546 }
547
548 if (IS_FFS_FILE2 (CacheFfsHeader)) {
549 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));
550 } else {
551 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader));
552 }
553
554 //
555 // Adjust pointer to the next 8-byte aligned boundary.
556 //
557 FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);
558
559 }
560
561 Done:
562 if (EFI_ERROR (Status)) {
563 if (FileCached) {
564 CoreFreePool (CacheFfsHeader);
565 FileCached = FALSE;
566 }
567 FreeFvDeviceResource (FvDevice);
568 }
569
570 return Status;
571 }
572
573
574
575 /**
576 This notification function is invoked when an instance of the
577 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
578 EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where
579 the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.
580
581 @param Event The event that occured
582 @param Context For EFI compatiblity. Not used.
583
584 **/
585 VOID
586 EFIAPI
587 NotifyFwVolBlock (
588 IN EFI_EVENT Event,
589 IN VOID *Context
590 )
591 {
592 EFI_HANDLE Handle;
593 EFI_STATUS Status;
594 UINTN BufferSize;
595 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
596 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
597 FV_DEVICE *FvDevice;
598 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
599 //
600 // Examine all new handles
601 //
602 for (;;) {
603 //
604 // Get the next handle
605 //
606 BufferSize = sizeof (Handle);
607 Status = CoreLocateHandle (
608 ByRegisterNotify,
609 NULL,
610 gEfiFwVolBlockNotifyReg,
611 &BufferSize,
612 &Handle
613 );
614
615 //
616 // If not found, we're done
617 //
618 if (EFI_NOT_FOUND == Status) {
619 break;
620 }
621
622 if (EFI_ERROR (Status)) {
623 continue;
624 }
625
626 //
627 // Get the FirmwareVolumeBlock protocol on that handle
628 //
629 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
630 ASSERT_EFI_ERROR (Status);
631 ASSERT (Fvb != NULL);
632
633 //
634 // Make sure the Fv Header is O.K.
635 //
636 Status = GetFwVolHeader (Fvb, &FwVolHeader);
637 if (EFI_ERROR (Status)) {
638 continue;
639 }
640 ASSERT (FwVolHeader != NULL);
641
642 if (!VerifyFvHeaderChecksum (FwVolHeader)) {
643 CoreFreePool (FwVolHeader);
644 continue;
645 }
646
647 //
648 // Check if there is an FV protocol already installed in that handle
649 //
650 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
651 if (!EFI_ERROR (Status)) {
652 //
653 // Update Fv to use a new Fvb
654 //
655 FvDevice = BASE_CR (Fv, FV_DEVICE, Fv);
656 if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) {
657 //
658 // Only write into our device structure if it's our device structure
659 //
660 FvDevice->Fvb = Fvb;
661 }
662
663 } else {
664 //
665 // No FwVol protocol on the handle so create a new one
666 //
667 FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);
668 if (FvDevice == NULL) {
669 return;
670 }
671
672 FvDevice->Fvb = Fvb;
673 FvDevice->Handle = Handle;
674 FvDevice->FwVolHeader = FwVolHeader;
675 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
676 FvDevice->Fv.ParentHandle = Fvb->ParentHandle;
677 //
678 // Inherit the authentication status from FVB.
679 //
680 FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb);
681
682 if (!EFI_ERROR (FvCheck (FvDevice))) {
683 //
684 // Install an New FV protocol on the existing handle
685 //
686 Status = CoreInstallProtocolInterface (
687 &Handle,
688 &gEfiFirmwareVolume2ProtocolGuid,
689 EFI_NATIVE_INTERFACE,
690 &FvDevice->Fv
691 );
692 ASSERT_EFI_ERROR (Status);
693 } else {
694 //
695 // Free FvDevice Buffer for the corrupt FV image.
696 //
697 CoreFreePool (FvDevice);
698 }
699 }
700 }
701
702 return;
703 }
704
705
706
707 /**
708 This routine is the driver initialization entry point. It registers
709 a notification function. This notification function are responsible
710 for building the FV stack dynamically.
711
712 @param ImageHandle The image handle.
713 @param SystemTable The system table.
714
715 @retval EFI_SUCCESS Function successfully returned.
716
717 **/
718 EFI_STATUS
719 EFIAPI
720 FwVolDriverInit (
721 IN EFI_HANDLE ImageHandle,
722 IN EFI_SYSTEM_TABLE *SystemTable
723 )
724 {
725 gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent (
726 &gEfiFirmwareVolumeBlockProtocolGuid,
727 TPL_CALLBACK,
728 NotifyFwVolBlock,
729 NULL,
730 &gEfiFwVolBlockNotifyReg
731 );
732 return EFI_SUCCESS;
733 }
734
735