]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c
Update DxeCore and FwVolDxe drivers to inherit authentication status for the FV image...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / FwVolDxe / FwVol.c
1 /** @file
2
3 Firmware File System driver that produce full Firmware Volume2 protocol.
4 Layers on top of Firmware Block protocol to produce a file abstraction
5 of FV based files.
6
7 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
8
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions
11 of the BSD License which accompanies this distribution. The
12 full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
14
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17
18 **/
19
20 #include "FwVolDriver.h"
21
22 #define KEYSIZE sizeof (UINTN)
23
24 /**
25 Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
26 copy the real length volume header into it.
27
28 @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to
29 read the volume header
30 @param FwVolHeader Pointer to pointer to allocated buffer in which
31 the volume header is returned.
32
33 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
34 @retval EFI_SUCCESS Successfully read volume header to the allocated
35 buffer.
36 @retval EFI_ACCESS_DENIED Read status of FV is not enabled.
37 **/
38 EFI_STATUS
39 GetFwVolHeader (
40 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
41 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
42 )
43 {
44 EFI_STATUS Status;
45 EFI_FIRMWARE_VOLUME_HEADER TempFvh;
46 EFI_FVB_ATTRIBUTES_2 FvbAttributes;
47 UINTN FvhLength;
48 EFI_PHYSICAL_ADDRESS BaseAddress;
49
50 //
51 // Determine the real length of FV header
52 //
53 Status = Fvb->GetAttributes (
54 Fvb,
55 &FvbAttributes
56 );
57 if (EFI_ERROR (Status)) {
58 return Status;
59 }
60
61 if ((FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {
62 return EFI_ACCESS_DENIED;
63 }
64
65 //
66 // Just avoid compiling warning
67 //
68 BaseAddress = 0;
69 FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
70
71 //
72 // memory-mapped FV and non memory-mapped has different ways to read
73 //
74 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
75 Status = Fvb->GetPhysicalAddress (
76 Fvb,
77 &BaseAddress
78 );
79 if (EFI_ERROR (Status)) {
80 return Status;
81 }
82 CopyMem (&TempFvh, (VOID *) (UINTN) BaseAddress, FvhLength);
83 } else {
84 Status = Fvb->Read (
85 Fvb,
86 0,
87 0,
88 &FvhLength,
89 (UINT8 *) &TempFvh
90 );
91 }
92
93 *FwVolHeader = AllocatePool (TempFvh.HeaderLength);
94 if (*FwVolHeader == NULL) {
95 return EFI_OUT_OF_RESOURCES;
96 }
97 //
98 // Read the whole header
99 //
100 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
101 CopyMem (*FwVolHeader, (VOID *) (UINTN) BaseAddress, TempFvh.HeaderLength);
102 } else {
103 //
104 // Assumed the first block is bigger than the length of Fv headder
105 //
106 FvhLength = TempFvh.HeaderLength;
107 Status = Fvb->Read (
108 Fvb,
109 0,
110 0,
111 &FvhLength,
112 (UINT8 *) *FwVolHeader
113 );
114 //
115 // Check whether Read successes.
116 //
117 if (EFI_ERROR (Status)) {
118 FreePool (*FwVolHeader);
119 *FwVolHeader = NULL;
120 return Status;
121 }
122 }
123
124 return EFI_SUCCESS;
125 }
126
127 /**
128 Free FvDevice resource when error happens.
129
130 @param FvDevice Pointer to the FvDevice to be freed.
131 **/
132 VOID
133 FreeFvDeviceResource (
134 IN FV_DEVICE *FvDevice
135 )
136 {
137 LBA_ENTRY *LbaEntry;
138 FREE_SPACE_ENTRY *FreeSpaceEntry;
139 FFS_FILE_LIST_ENTRY *FfsFileEntry;
140 LIST_ENTRY *NextEntry;
141
142 //
143 // Free LAB Entry
144 //
145 LbaEntry = (LBA_ENTRY *) FvDevice->LbaHeader.ForwardLink;
146 while (&LbaEntry->Link != &FvDevice->LbaHeader) {
147 NextEntry = (&LbaEntry->Link)->ForwardLink;
148 FreePool (LbaEntry);
149 LbaEntry = (LBA_ENTRY *) NextEntry;
150 }
151 //
152 // Free File List Entry
153 //
154 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;
155 while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
156 NextEntry = (&FfsFileEntry->Link)->ForwardLink;
157 FreePool (FfsFileEntry);
158 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
159 }
160 //
161 // Free Space Entry
162 //
163 FreeSpaceEntry = (FREE_SPACE_ENTRY *) FvDevice->FreeSpaceHeader.ForwardLink;
164 while (&FreeSpaceEntry->Link != &FvDevice->FreeSpaceHeader) {
165 NextEntry = (&FreeSpaceEntry->Link)->ForwardLink;
166 FreePool (FreeSpaceEntry);
167 FreeSpaceEntry = (FREE_SPACE_ENTRY *) NextEntry;
168 }
169 //
170 // Free the cache
171 //
172 FreePool ((UINT8 *) (UINTN) FvDevice->CachedFv);
173
174 return ;
175 }
176
177 /**
178
179 Firmware volume inherits authentication status from the FV image file and section(in another firmware volume)
180 where it came from.
181
182 @param FvDevice A pointer to the FvDevice.
183
184 **/
185 VOID
186 FwVolInheritAuthenticationStatus (
187 IN FV_DEVICE *FvDevice
188 )
189 {
190 EFI_STATUS Status;
191 EFI_FIRMWARE_VOLUME_HEADER *CachedFvHeader;
192 EFI_FIRMWARE_VOLUME_EXT_HEADER *CachedFvExtHeader;
193 EFI_FIRMWARE_VOLUME2_PROTOCOL *ParentFvProtocol;
194 UINTN Key;
195 EFI_GUID FileNameGuid;
196 EFI_FV_FILETYPE FileType;
197 EFI_FV_FILE_ATTRIBUTES FileAttributes;
198 UINTN FileSize;
199 EFI_SECTION_TYPE SectionType;
200 UINT32 AuthenticationStatus;
201 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
202 EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
203 UINTN BufferSize;
204
205 CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv;
206
207 if (FvDevice->Fv.ParentHandle != NULL) {
208 //
209 // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from
210 //
211 Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol);
212 if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) {
213 Key = 0;
214 do {
215 FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;
216 Status = ParentFvProtocol->GetNextFile (
217 ParentFvProtocol,
218 &Key,
219 &FileType,
220 &FileNameGuid,
221 &FileAttributes,
222 &FileSize
223 );
224 if (EFI_ERROR (Status)) {
225 return;
226 }
227
228 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
229 FvHeader = NULL;
230 BufferSize = 0;
231 Status = ParentFvProtocol->ReadSection (
232 ParentFvProtocol,
233 &FileNameGuid,
234 SectionType,
235 0,
236 (VOID **) &FvHeader,
237 &BufferSize,
238 &AuthenticationStatus
239 );
240 if (!EFI_ERROR (Status)) {
241 if ((FvHeader->FvLength == CachedFvHeader->FvLength) &&
242 (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) {
243 if (FvHeader->ExtHeaderOffset !=0) {
244 //
245 // Both FVs contain extension header, then compare their FV Name GUID
246 //
247 FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset);
248 CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset);
249 if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) {
250 //
251 // Found the FV image section where the firmware volume came from,
252 // and then inherit authentication status from it.
253 //
254 FvDevice->AuthenticationStatus = AuthenticationStatus;
255 FreePool ((VOID *) FvHeader);
256 return;
257 }
258 } else {
259 //
260 // Both FVs don't contain extension header, then compare their whole FV Image.
261 //
262 if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, FvHeader->FvLength) == 0) {
263 //
264 // Found the FV image section where the firmware volume came from
265 // and then inherit authentication status from it.
266 //
267 FvDevice->AuthenticationStatus = AuthenticationStatus;
268 FreePool ((VOID *) FvHeader);
269 return;
270 }
271 }
272 }
273 FreePool ((VOID *) FvHeader);
274 }
275 } while (TRUE);
276 }
277 }
278 }
279
280 /**
281 Check if an FV is consistent and allocate cache for it.
282
283 @param FvDevice A pointer to the FvDevice to be checked.
284
285 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
286 @retval EFI_VOLUME_CORRUPTED File system is corrupted.
287 @retval EFI_SUCCESS FV is consistent and cache is allocated.
288
289 **/
290 EFI_STATUS
291 FvCheck (
292 IN FV_DEVICE *FvDevice
293 )
294 {
295 EFI_STATUS Status;
296 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
297 EFI_FVB_ATTRIBUTES_2 FvbAttributes;
298 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
299 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
300 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;
301 UINT8 *FwCache;
302 LBA_ENTRY *LbaEntry;
303 FREE_SPACE_ENTRY *FreeSpaceEntry;
304 FFS_FILE_LIST_ENTRY *FfsFileEntry;
305 UINT8 *LbaStart;
306 UINTN Index;
307 EFI_LBA LbaIndex;
308 UINT8 *Ptr;
309 UINTN Size;
310 UINT8 *FreeStart;
311 UINTN FreeSize;
312 UINT8 ErasePolarity;
313 EFI_FFS_FILE_STATE FileState;
314 UINT8 *TopFvAddress;
315 UINTN TestLength;
316 EFI_PHYSICAL_ADDRESS BaseAddress;
317
318 Fvb = FvDevice->Fvb;
319
320 Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
321 if (EFI_ERROR (Status)) {
322 return Status;
323 }
324
325 InitializeListHead (&FvDevice->LbaHeader);
326 InitializeListHead (&FvDevice->FreeSpaceHeader);
327 InitializeListHead (&FvDevice->FfsFileListHeader);
328
329 FwVolHeader = NULL;
330 Status = GetFwVolHeader (Fvb, &FwVolHeader);
331 if (EFI_ERROR (Status)) {
332 return Status;
333 }
334 ASSERT (FwVolHeader != NULL);
335
336 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
337
338 //
339 // Double Check firmware volume header here
340 //
341 if (!VerifyFvHeaderChecksum (FwVolHeader)) {
342 FreePool (FwVolHeader);
343 return EFI_VOLUME_CORRUPTED;
344 }
345
346 BlockMap = FwVolHeader->BlockMap;
347
348 //
349 // FwVolHeader->FvLength is the whole FV length including FV header
350 //
351 FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength);
352 if (FwCache == NULL) {
353 FreePool (FwVolHeader);
354 return EFI_OUT_OF_RESOURCES;
355 }
356
357 FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache;
358
359 //
360 // Copy to memory
361 //
362 LbaStart = FwCache;
363 LbaIndex = 0;
364 Ptr = NULL;
365
366 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
367 //
368 // Get volume base address
369 //
370 Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);
371 if (EFI_ERROR (Status)) {
372 FreePool (FwVolHeader);
373 return Status;
374 }
375
376 Ptr = (UINT8 *) ((UINTN) BaseAddress);
377
378 DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress));
379 }
380 //
381 // Copy whole FV into the memory
382 //
383 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
384
385 for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
386 LbaEntry = AllocatePool (sizeof (LBA_ENTRY));
387 if (LbaEntry == NULL) {
388 FreePool (FwVolHeader);
389 FreeFvDeviceResource (FvDevice);
390 return EFI_OUT_OF_RESOURCES;
391 }
392
393 LbaEntry->LbaIndex = LbaIndex;
394 LbaEntry->StartingAddress = LbaStart;
395 LbaEntry->BlockLength = BlockMap->Length;
396
397 //
398 // Copy each LBA into memory
399 //
400 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
401
402 CopyMem (LbaStart, Ptr, BlockMap->Length);
403 Ptr += BlockMap->Length;
404
405 } else {
406
407 Size = BlockMap->Length;
408 Status = Fvb->Read (
409 Fvb,
410 LbaIndex,
411 0,
412 &Size,
413 LbaStart
414 );
415 //
416 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
417 //
418 if (EFI_ERROR (Status)) {
419 FreePool (FwVolHeader);
420 FreeFvDeviceResource (FvDevice);
421 return Status;
422 }
423
424 }
425
426 LbaIndex++;
427 LbaStart += BlockMap->Length;
428
429 InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link);
430 }
431
432 BlockMap++;
433 }
434
435 FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache;
436
437 //
438 // it is not used any more, so free FwVolHeader
439 //
440 FreePool (FwVolHeader);
441
442 //
443 // Scan to check the free space & File list
444 //
445 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {
446 ErasePolarity = 1;
447 } else {
448 ErasePolarity = 0;
449 }
450
451 FvDevice->ErasePolarity = ErasePolarity;
452
453 //
454 // go through the whole FV cache, check the consistence of the FV
455 //
456 if (FvDevice->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 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset);
461 Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize;
462 Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8);
463 } else {
464 Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);
465 }
466 TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength);
467
468 //
469 // Build FFS list & Free Space List here
470 //
471 while (Ptr < TopFvAddress) {
472 TestLength = TopFvAddress - Ptr;
473
474 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
475 TestLength = sizeof (EFI_FFS_FILE_HEADER);
476 }
477
478 if (IsBufferErased (ErasePolarity, Ptr, TestLength)) {
479 //
480 // We found free space
481 //
482 FreeStart = Ptr;
483 FreeSize = 0;
484
485 do {
486 TestLength = TopFvAddress - Ptr;
487
488 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
489 TestLength = sizeof (EFI_FFS_FILE_HEADER);
490 }
491
492 if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) {
493 break;
494 }
495
496 FreeSize += TestLength;
497 Ptr += TestLength;
498 } while (Ptr < TopFvAddress);
499
500 FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));
501 if (FreeSpaceEntry == NULL) {
502 FreeFvDeviceResource (FvDevice);
503 return EFI_OUT_OF_RESOURCES;
504 }
505 //
506 // Create a Free space entry
507 //
508 FreeSpaceEntry->StartingAddress = FreeStart;
509 FreeSpaceEntry->Length = FreeSize;
510 InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link);
511 continue;
512 }
513 //
514 // double check boundry
515 //
516 if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {
517 break;
518 }
519
520 if (!IsValidFFSHeader (
521 FvDevice->ErasePolarity,
522 (EFI_FFS_FILE_HEADER *) Ptr
523 )) {
524 FileState = GetFileState (
525 FvDevice->ErasePolarity,
526 (EFI_FFS_FILE_HEADER *) Ptr
527 );
528 if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
529 if (IS_FFS_FILE2 (Ptr)) {
530 if (!FvDevice->IsFfs3Fv) {
531 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));
532 }
533 Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2);
534 } else {
535 Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER);
536 }
537
538 continue;
539
540 } else {
541 //
542 // File system is corrputed, return
543 //
544 FreeFvDeviceResource (FvDevice);
545 return EFI_VOLUME_CORRUPTED;
546 }
547 }
548
549 if (IS_FFS_FILE2 (Ptr)) {
550 ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF);
551 if (!FvDevice->IsFfs3Fv) {
552 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));
553 Ptr = Ptr + FFS_FILE2_SIZE (Ptr);
554 //
555 // Adjust Ptr to the next 8-byte aligned boundry.
556 //
557 while (((UINTN) Ptr & 0x07) != 0) {
558 Ptr++;
559 }
560 continue;
561 }
562 }
563
564 if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {
565 FileState = GetFileState (
566 FvDevice->ErasePolarity,
567 (EFI_FFS_FILE_HEADER *) Ptr
568 );
569
570 //
571 // check for non-deleted file
572 //
573 if (FileState != EFI_FILE_DELETED) {
574 //
575 // Create a FFS list entry for each non-deleted file
576 //
577 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
578 if (FfsFileEntry == NULL) {
579 FreeFvDeviceResource (FvDevice);
580 return EFI_OUT_OF_RESOURCES;
581 }
582
583 FfsFileEntry->FfsHeader = Ptr;
584 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
585 }
586
587 if (IS_FFS_FILE2 (Ptr)) {
588 Ptr = Ptr + FFS_FILE2_SIZE (Ptr);
589 } else {
590 Ptr = Ptr + FFS_FILE_SIZE (Ptr);
591 }
592
593 //
594 // Adjust Ptr to the next 8-byte aligned boundry.
595 //
596 while (((UINTN) Ptr & 0x07) != 0) {
597 Ptr++;
598 }
599 } else {
600 //
601 // File system is corrupted, return
602 //
603 FreeFvDeviceResource (FvDevice);
604 return EFI_VOLUME_CORRUPTED;
605 }
606 }
607
608 FvDevice->CurrentFfsFile = NULL;
609
610 return EFI_SUCCESS;
611 }
612
613 /**
614 Entry point function does install/reinstall FV2 protocol with full functionality.
615
616 @param ImageHandle A handle for the image that is initializing this driver
617 @param SystemTable A pointer to the EFI system table
618
619 @retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully.
620 @retval EFI_NOT_FOUND No FV protocol install/reinstall successfully.
621 **/
622 EFI_STATUS
623 EFIAPI
624 FwVolDriverInit (
625 IN EFI_HANDLE ImageHandle,
626 IN EFI_SYSTEM_TABLE *SystemTable
627 )
628 {
629 EFI_STATUS Status;
630 EFI_HANDLE *HandleBuffer;
631 UINTN HandleCount;
632 UINTN Index;
633 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
634 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
635 FV_DEVICE *FvDevice;
636 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
637 BOOLEAN Reinstall;
638 BOOLEAN InstallFlag;
639
640 DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n"));
641 InstallFlag = FALSE;
642 //
643 // Locate all handles of Fvb protocol
644 //
645 Status = gBS->LocateHandleBuffer (
646 ByProtocol,
647 &gEfiFirmwareVolumeBlockProtocolGuid,
648 NULL,
649 &HandleCount,
650 &HandleBuffer
651 );
652 if (EFI_ERROR (Status)) {
653 return EFI_NOT_FOUND;
654 }
655
656 for (Index = 0; Index < HandleCount; Index += 1) {
657 Status = gBS->HandleProtocol (
658 HandleBuffer[Index],
659 &gEfiFirmwareVolumeBlockProtocolGuid,
660 (VOID **) &Fvb
661 );
662 if (EFI_ERROR (Status)) {
663 continue;
664 }
665
666 FwVolHeader = NULL;
667 Status = GetFwVolHeader (Fvb, &FwVolHeader);
668 if (EFI_ERROR (Status)) {
669 continue;
670 }
671 ASSERT (FwVolHeader != NULL);
672 //
673 // Check to see that the file system is indeed formatted in a way we can
674 // understand it...
675 //
676 if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&
677 (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {
678 FreePool (FwVolHeader);
679 continue;
680 }
681 FreePool (FwVolHeader);
682
683 Reinstall = FALSE;
684 //
685 // Check if there is an FV protocol already installed in that handle
686 //
687 Status = gBS->HandleProtocol (
688 HandleBuffer[Index],
689 &gEfiFirmwareVolume2ProtocolGuid,
690 (VOID **) &Fv
691 );
692 if (!EFI_ERROR (Status)) {
693 Reinstall = TRUE;
694 }
695 //
696 // FwVol protocol on the handle so create a new one
697 //
698 FvDevice = AllocateZeroPool (sizeof (FV_DEVICE));
699 if (FvDevice == NULL) {
700 goto Done;
701 }
702
703 FvDevice->Signature = FV_DEVICE_SIGNATURE;
704 FvDevice->Fvb = Fvb;
705
706 //
707 // Firmware Volume Protocol interface
708 //
709 FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes;
710 FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes;
711 FvDevice->Fv.ReadFile = FvReadFile;
712 FvDevice->Fv.ReadSection = FvReadFileSection;
713 FvDevice->Fv.WriteFile = FvWriteFile;
714 FvDevice->Fv.GetNextFile = FvGetNextFile;
715 FvDevice->Fv.KeySize = KEYSIZE;
716 FvDevice->Fv.GetInfo = FvGetVolumeInfo;
717 FvDevice->Fv.SetInfo = FvSetVolumeInfo;
718 FvDevice->Fv.ParentHandle = Fvb->ParentHandle;
719
720 Status = FvCheck (FvDevice);
721 if (EFI_ERROR (Status)) {
722 //
723 // The file system is not consistence
724 //
725 FreePool (FvDevice);
726 continue;
727 }
728
729 FwVolInheritAuthenticationStatus (FvDevice);
730
731 if (Reinstall) {
732 //
733 // Reinstall an New FV protocol
734 //
735 // FvDevice = FV_DEVICE_FROM_THIS (Fv);
736 // FvDevice->Fvb = Fvb;
737 // FreeFvDeviceResource (FvDevice);
738 //
739 Status = gBS->ReinstallProtocolInterface (
740 HandleBuffer[Index],
741 &gEfiFirmwareVolume2ProtocolGuid,
742 Fv,
743 &FvDevice->Fv
744 );
745 if (!EFI_ERROR (Status)) {
746 InstallFlag = TRUE;
747 } else {
748 FreePool (FvDevice);
749 }
750
751 DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status));
752 ASSERT_EFI_ERROR (Status);
753 } else {
754 //
755 // Install an New FV protocol
756 //
757 Status = gBS->InstallProtocolInterface (
758 &FvDevice->Handle,
759 &gEfiFirmwareVolume2ProtocolGuid,
760 EFI_NATIVE_INTERFACE,
761 &FvDevice->Fv
762 );
763 if (!EFI_ERROR (Status)) {
764 InstallFlag = TRUE;
765 } else {
766 FreePool (FvDevice);
767 }
768
769 DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status));
770 ASSERT_EFI_ERROR (Status);
771 }
772 }
773
774 Done:
775 //
776 // As long as one Fv protocol install/reinstall successfully,
777 // success should return to ensure this image will be not unloaded.
778 // Otherwise, new Fv protocols are corrupted by other loaded driver.
779 //
780 if (InstallFlag) {
781 return EFI_SUCCESS;
782 }
783
784 //
785 // No FV protocol install/reinstall successfully.
786 // EFI_NOT_FOUND should return to ensure this image will be unloaded.
787 //
788 return EFI_NOT_FOUND;
789 }