TianoCore EDK2 master
Loading...
Searching...
No Matches
Fvb.c
Go to the documentation of this file.
1
10#include "PiDxe.h"
11#include <Guid/EventGroup.h>
13#include <Guid/VariableFormat.h>
14
16#include <Protocol/DevicePath.h>
17
18#include <Library/UefiLib.h>
20#include <Library/BaseLib.h>
22#include <Library/DebugLib.h>
27#include <Library/PcdLib.h>
29#include "Fvb.h"
30
31#define EFI_AUTHENTICATED_VARIABLE_GUID \
32{ 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
33
34//
35// Virtual Address Change Event
36//
37// This is needed for runtime variable access.
38//
39EFI_EVENT mEmuVarsFvbAddrChangeEvent = NULL;
40
41//
42// This is the single instance supported by this driver. It
43// supports the FVB and Device Path protocols.
44//
45EFI_FW_VOL_BLOCK_DEVICE mEmuVarsFvb = {
46 FVB_DEVICE_SIGNATURE,
47 { // DevicePath
48 {
49 {
52 {
53 sizeof (MEMMAP_DEVICE_PATH),
54 0
55 }
56 },
58 0,
59 0,
60 },
61 {
62 END_DEVICE_PATH_TYPE,
63 END_ENTIRE_DEVICE_PATH_SUBTYPE,
64 {
66 0
67 }
68 }
69 },
70 NULL, // BufferPtr
71 EMU_FVB_BLOCK_SIZE, // BlockSize
72 EMU_FVB_SIZE, // Size
73 { // FwVolBlockInstance
81 NULL
82 },
83};
84
95VOID
96EFIAPI
98 IN EFI_EVENT Event,
99 IN VOID *Context
100 )
101{
102 EfiConvertPointer (0x0, &mEmuVarsFvb.BufferPtr);
103}
104
105//
106// FVB protocol APIs
107//
108
127EFIAPI
131 )
132{
133 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
134
135 FvbDevice = FVB_DEVICE_FROM_THIS (This);
136
137 *Address = (EFI_PHYSICAL_ADDRESS)(UINTN)FvbDevice->BufferPtr;
138
139 return EFI_SUCCESS;
140}
141
169EFIAPI
172 IN EFI_LBA Lba,
173 OUT UINTN *BlockSize,
174 OUT UINTN *NumberOfBlocks
175 )
176{
177 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
178
179 if (Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 FvbDevice = FVB_DEVICE_FROM_THIS (This);
184
185 *BlockSize = FvbDevice->BlockSize;
186 *NumberOfBlocks = (UINTN)(EMU_FVB_NUM_TOTAL_BLOCKS - Lba);
187
188 return EFI_SUCCESS;
189}
190
207EFIAPI
210 OUT EFI_FVB_ATTRIBUTES_2 *Attributes
211 )
212{
213 *Attributes =
215 EFI_FVB2_READ_ENABLED_CAP |
216 EFI_FVB2_READ_STATUS |
217 EFI_FVB2_WRITE_ENABLED_CAP |
218 EFI_FVB2_WRITE_STATUS |
219 EFI_FVB2_ERASE_POLARITY
220 );
221
222 return EFI_SUCCESS;
223}
224
248EFIAPI
251 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
252 )
253{
254 return EFI_ACCESS_DENIED;
255}
256
306EFIAPI
309 ...
310 )
311{
312 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
313 VA_LIST Args;
314 EFI_LBA StartingLba;
315 UINTN NumOfLba;
316 UINT8 *ErasePtr;
317 UINTN EraseSize;
318
319 FvbDevice = FVB_DEVICE_FROM_THIS (This);
320
321 //
322 // Check input parameters
323 //
324 VA_START (Args, This);
325 do {
326 StartingLba = VA_ARG (Args, EFI_LBA);
327 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
328 break;
329 }
330
331 NumOfLba = VA_ARG (Args, UINTN);
332
333 if ((StartingLba > EMU_FVB_NUM_TOTAL_BLOCKS) ||
334 (NumOfLba > EMU_FVB_NUM_TOTAL_BLOCKS - StartingLba))
335 {
336 VA_END (Args);
337 return EFI_INVALID_PARAMETER;
338 }
339 } while (1);
340
341 VA_END (Args);
342
343 //
344 // Erase blocks
345 //
346 VA_START (Args, This);
347 do {
348 StartingLba = VA_ARG (Args, EFI_LBA);
349 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
350 break;
351 }
352
353 NumOfLba = VA_ARG (Args, UINTN);
354
355 ErasePtr = FvbDevice->BufferPtr;
356 ErasePtr += (UINTN)StartingLba * FvbDevice->BlockSize;
357 EraseSize = NumOfLba * FvbDevice->BlockSize;
358
359 SetMem (ErasePtr, EraseSize, ERASED_UINT8);
360 } while (1);
361
362 VA_END (Args);
363
364 //
365 // Call platform hook
366 //
367 VA_START (Args, This);
368 PlatformFvbBlocksErased (This, Args);
369 VA_END (Args);
370
371 return EFI_SUCCESS;
372}
373
434EFIAPI
437 IN EFI_LBA Lba,
438 IN UINTN Offset,
439 IN OUT UINTN *NumBytes,
440 IN UINT8 *Buffer
441 )
442{
443 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
444 UINT8 *FvbDataPtr;
445 EFI_STATUS Status;
446
447 FvbDevice = FVB_DEVICE_FROM_THIS (This);
448
449 if ((Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) ||
450 (Offset > FvbDevice->BlockSize))
451 {
452 return EFI_INVALID_PARAMETER;
453 }
454
455 Status = EFI_SUCCESS;
456 if (*NumBytes > FvbDevice->BlockSize - Offset) {
457 *NumBytes = FvbDevice->BlockSize - Offset;
458 Status = EFI_BAD_BUFFER_SIZE;
459 }
460
461 FvbDataPtr = FvbDevice->BufferPtr;
462 FvbDataPtr += (UINTN)Lba * FvbDevice->BlockSize;
463 FvbDataPtr += Offset;
464
465 CopyMem (FvbDataPtr, Buffer, *NumBytes);
466 PlatformFvbDataWritten (This, Lba, Offset, *NumBytes, Buffer);
467 return Status;
468}
469
518EFIAPI
521 IN EFI_LBA Lba,
522 IN UINTN Offset,
523 IN OUT UINTN *NumBytes,
524 IN OUT UINT8 *Buffer
525 )
526{
527 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
528 UINT8 *FvbDataPtr;
529 EFI_STATUS Status;
530
531 FvbDevice = FVB_DEVICE_FROM_THIS (This);
532
533 if ((Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) ||
534 (Offset > FvbDevice->BlockSize))
535 {
536 return EFI_INVALID_PARAMETER;
537 }
538
539 Status = EFI_SUCCESS;
540 if (*NumBytes > FvbDevice->BlockSize - Offset) {
541 *NumBytes = FvbDevice->BlockSize - Offset;
542 Status = EFI_BAD_BUFFER_SIZE;
543 }
544
545 FvbDataPtr = FvbDevice->BufferPtr;
546 FvbDataPtr += (UINTN)Lba * FvbDevice->BlockSize;
547 FvbDataPtr += Offset;
548
549 CopyMem (Buffer, FvbDataPtr, *NumBytes);
550 PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer);
551 return Status;
552}
553
565 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
566 )
567{
568 UINT16 Checksum;
569
570 //
571 // Verify the header revision, header signature, length
572 // Length of FvBlock cannot be 2**64-1
573 // HeaderLength cannot be an odd number
574 //
575 if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
576 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
577 (FwVolHeader->FvLength != EMU_FVB_SIZE) ||
578 (FwVolHeader->HeaderLength != EMU_FV_HEADER_LENGTH)
579 )
580 {
581 DEBUG ((DEBUG_INFO, "EMU Variable FVB: Basic FV headers were invalid\n"));
582 return EFI_NOT_FOUND;
583 }
584
585 //
586 // Verify the header checksum
587 //
588 Checksum = CalculateSum16 ((VOID *)FwVolHeader, FwVolHeader->HeaderLength);
589
590 if (Checksum != 0) {
591 DEBUG ((DEBUG_INFO, "EMU Variable FVB: FV checksum was invalid\n"));
592 return EFI_NOT_FOUND;
593 }
594
595 return EFI_SUCCESS;
596}
597
605VOID
607 IN VOID *Ptr
608 )
609{
610 //
611 // Templates for authenticated variable FV header
612 //
613 STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate = {
614 { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
615 // UINT8 ZeroVector[16];
616 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
617
618 // EFI_GUID FileSystemGuid;
619 EFI_SYSTEM_NV_DATA_FV_GUID,
620
621 // UINT64 FvLength;
622 EMU_FVB_SIZE,
623
624 // UINT32 Signature;
625 EFI_FVH_SIGNATURE,
626
627 // EFI_FVB_ATTRIBUTES_2 Attributes;
628 0x4feff,
629
630 // UINT16 HeaderLength;
631 EMU_FV_HEADER_LENGTH,
632
633 // UINT16 Checksum;
634 0,
635
636 // UINT16 ExtHeaderOffset;
637 0,
638
639 // UINT8 Reserved[1];
640 { 0 },
641
642 // UINT8 Revision;
644
645 // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
646 {
647 {
648 EMU_FVB_NUM_TOTAL_BLOCKS, // UINT32 NumBlocks;
649 EMU_FVB_BLOCK_SIZE // UINT32 Length;
650 }
651 }
652 },
653 // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
654 { 0, 0 }, // End of block map
655 { // VARIABLE_STORE_HEADER VarHdr;
656 // EFI_GUID Signature; // need authenticated variables for secure boot
657 EFI_AUTHENTICATED_VARIABLE_GUID,
658
659 // UINT32 Size;
660 (
661 FixedPcdGet32 (PcdFlashNvStorageVariableSize) -
663 ),
664
665 // UINT8 Format;
667
668 // UINT8 State;
669 VARIABLE_STORE_HEALTHY,
670
671 // UINT16 Reserved;
672 0,
673
674 // UINT32 Reserved1;
675 0
676 }
677 };
678
680
681 //
682 // Copy the template structure into the location
683 //
684 CopyMem (
685 Ptr,
686 &FvAndAuthenticatedVarTemplate,
687 sizeof FvAndAuthenticatedVarTemplate
688 );
689
690 //
691 // Update the checksum for the FV header
692 //
693 Fv = (EFI_FIRMWARE_VOLUME_HEADER *)Ptr;
695}
696
707EFIAPI
709 IN EFI_HANDLE ImageHandle,
710 IN EFI_SYSTEM_TABLE *SystemTable
711 )
712{
713 EFI_STATUS Status;
714 VOID *Ptr;
715 VOID *SubPtr;
716 BOOLEAN Initialize;
717 EFI_HANDLE Handle;
718 EFI_PHYSICAL_ADDRESS Address;
719 RETURN_STATUS PcdStatus;
720
721 DEBUG ((DEBUG_INFO, "EMU Variable FVB Started\n"));
722
723 //
724 // Verify that the PCD's are set correctly.
725 //
726 ASSERT (
727 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) %
728 EMU_FVB_BLOCK_SIZE == 0
729 );
730 if (
731 (PcdGet32 (PcdFlashNvStorageVariableSize) +
732 PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
733 ) >
734 EMU_FVB_NUM_SPARE_BLOCKS * EMU_FVB_BLOCK_SIZE
735 )
736 {
737 DEBUG ((DEBUG_ERROR, "EMU Variable invalid PCD sizes\n"));
738 return EFI_INVALID_PARAMETER;
739 }
740
741 if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
742 DEBUG ((
743 DEBUG_INFO,
744 "Disabling EMU Variable FVB since "
745 "flash variables appear to be supported.\n"
746 ));
747 return EFI_ABORTED;
748 }
749
750 //
751 // By default we will initialize the FV contents. But, if
752 // PcdEmuVariableNvStoreReserved is non-zero, then we will
753 // use this location for our buffer.
754 //
755 // If this location does not have a proper FV header, then
756 // we will initialize it.
757 //
759 if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {
760 Ptr = (VOID *)(UINTN)PcdGet64 (PcdEmuVariableNvStoreReserved);
761 DEBUG ((
762 DEBUG_INFO,
763 "EMU Variable FVB: Using pre-reserved block at %p\n",
764 Ptr
765 ));
766 Status = ValidateFvHeader (Ptr);
767 if (!EFI_ERROR (Status)) {
768 DEBUG ((DEBUG_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));
770 }
771 } else {
772 Ptr = AllocateRuntimePages (EFI_SIZE_TO_PAGES (EMU_FVB_SIZE));
773 }
774
775 mEmuVarsFvb.BufferPtr = Ptr;
776
777 //
778 // Initialize the main FV header and variable store header
779 //
780 if (Initialize) {
781 SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
783 }
784
785 PcdStatus = PcdSet64S (PcdFlashNvStorageVariableBase64, (UINTN)Ptr);
786 ASSERT_RETURN_ERROR (PcdStatus);
787
788 //
789 // Initialize the Fault Tolerant Write data area
790 //
791 SubPtr = (VOID *)((UINT8 *)Ptr + PcdGet32 (PcdFlashNvStorageVariableSize));
792 PcdStatus = PcdSet64S (
793 PcdFlashNvStorageFtwWorkingBase64,
794 (UINTN)SubPtr
795 );
796 ASSERT_RETURN_ERROR (PcdStatus);
797
798 //
799 // Initialize the Fault Tolerant Write spare block
800 //
801 SubPtr = (VOID *)((UINT8 *)Ptr +
802 EMU_FVB_NUM_SPARE_BLOCKS * EMU_FVB_BLOCK_SIZE);
803 PcdStatus = PcdSet64S (
804 PcdFlashNvStorageFtwSpareBase64,
805 (UINTN)SubPtr
806 );
807 ASSERT_RETURN_ERROR (PcdStatus);
808
809 //
810 // Setup FVB device path
811 //
812 Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Ptr;
813 mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;
814 mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;
815
816 //
817 // Install the protocols
818 //
819 DEBUG ((DEBUG_INFO, "Installing FVB for EMU Variable support\n"));
820 Handle = 0;
821 Status = gBS->InstallMultipleProtocolInterfaces (
822 &Handle,
823 &gEfiFirmwareVolumeBlock2ProtocolGuid,
824 &mEmuVarsFvb.FwVolBlockInstance,
825 &gEfiDevicePathProtocolGuid,
826 &mEmuVarsFvb.DevicePath,
827 NULL
828 );
829 ASSERT_EFI_ERROR (Status);
830
831 //
832 // Register for the virtual address change event
833 //
834 Status = gBS->CreateEventEx (
835 EVT_NOTIFY_SIGNAL,
836 TPL_NOTIFY,
838 NULL,
839 &gEfiEventVirtualAddressChangeGuid,
840 &mEmuVarsFvbAddrChangeEvent
841 );
842 ASSERT_EFI_ERROR (Status);
843
844 return EFI_SUCCESS;
845}
UINT64 UINTN
UINT16 EFIAPI CalculateSum16(IN CONST UINT16 *Buffer, IN UINTN Length)
Definition: CheckSum.c:107
UINT16 EFIAPI CalculateCheckSum16(IN CONST UINT16 *Buffer, IN UINTN Length)
Definition: CheckSum.c:151
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define HW_MEMMAP_DP
Definition: DevicePath.h:109
#define EFI_LBA_LIST_TERMINATOR
EFI_STATUS ValidateFvHeader(IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader)
Definition: Fvb.c:564
EFI_STATUS EFIAPI FvbProtocolGetPhysicalAddress(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address)
Definition: Fvb.c:128
VOID EFIAPI FvbVirtualAddressChangeEvent(IN EFI_EVENT Event, IN VOID *Context)
Definition: Fvb.c:97
EFI_STATUS EFIAPI FvbProtocolGetBlockSize(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, OUT UINTN *BlockSize, OUT UINTN *NumberOfBlocks)
Definition: Fvb.c:170
EFI_STATUS EFIAPI FvbInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Fvb.c:708
EFI_STATUS EFIAPI FvbProtocolGetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, OUT EFI_FVB_ATTRIBUTES_2 *Attributes)
Definition: Fvb.c:208
EFI_STATUS EFIAPI FvbProtocolSetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes)
Definition: Fvb.c:249
VOID InitializeFvAndVariableStoreHeaders(IN VOID *Ptr)
Definition: Fvb.c:606
EFI_STATUS EFIAPI FvbProtocolRead(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN OUT UINT8 *Buffer)
Definition: Fvb.c:519
EFI_STATUS EFIAPI FvbProtocolEraseBlocks(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,...)
Definition: Fvb.c:307
EFI_STATUS EFIAPI FvbProtocolWrite(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer)
Definition: Fvb.c:435
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define VA_ARG(Marker, TYPE)
Definition: Base.h:679
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define VA_END(Marker)
Definition: Base.h:691
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define ASSERT_RETURN_ERROR(StatusParameter)
Definition: DebugLib.h:493
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define FixedPcdGet32(TokenName)
Definition: PcdLib.h:92
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdSet64S(TokenName, Value)
Definition: PcdLib.h:511
UINT32 EFI_FVB_ATTRIBUTES_2
#define EFI_FVH_REVISION
VOID EFIAPI PlatformFvbBlocksErased(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN VA_LIST List)
VOID EFIAPI PlatformFvbDataRead(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN UINTN NumBytes, IN UINT8 *Buffer)
VOID EFIAPI PlatformFvbDataWritten(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN UINTN NumBytes, IN UINT8 *Buffer)
VOID *EFIAPI AllocateRuntimePages(IN UINTN Pages)
STATIC RETURN_STATUS Initialize(VOID)
Definition: Ram.c:29
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EfiMemoryMappedIO
EFI_STATUS EFIAPI EfiConvertPointer(IN UINTN DebugDisposition, IN OUT VOID **Address)
Definition: RuntimeLib.c:561
#define VARIABLE_STORE_FORMATTED
EFI_PHYSICAL_ADDRESS StartingAddress
Definition: DevicePath.h:123
EFI_PHYSICAL_ADDRESS EndingAddress
Definition: DevicePath.h:127