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