22#include "VirtNorFlash.h"
24extern UINTN mFlashNvStorageVariableBase;
52 UINT32 NvStorageFtwSpareSize;
53 UINT32 NvStorageFtwWorkingSize;
54 UINT32 NvStorageVariableSize;
55 UINT64 NvStorageFtwSpareBase;
56 UINT64 NvStorageFtwWorkingBase;
57 UINT64 NvStorageVariableBase;
62 NvStorageFtwWorkingSize =
PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
63 NvStorageFtwSpareSize =
PcdGet32 (PcdFlashNvStorageFtwSpareSize);
64 NvStorageVariableSize =
PcdGet32 (PcdFlashNvStorageVariableSize);
66 NvStorageFtwSpareBase = (
PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ?
67 PcdGet64 (PcdFlashNvStorageFtwSpareBase64) :
PcdGet32 (PcdFlashNvStorageFtwSpareBase);
68 NvStorageFtwWorkingBase = (
PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ?
69 PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) :
PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
70 NvStorageVariableBase = (
PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
71 PcdGet64 (PcdFlashNvStorageVariableBase64) :
PcdGet32 (PcdFlashNvStorageVariableBase);
74 if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) {
77 "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n",
80 return EFI_INVALID_PARAMETER;
83 if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) {
86 "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n",
89 return EFI_INVALID_PARAMETER;
93 if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->BlockSize <= 0)) {
96 "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n",
100 return EFI_INVALID_PARAMETER;
103 if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->BlockSize <= 0)) {
106 "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n",
108 NvStorageFtwWorkingSize
110 return EFI_INVALID_PARAMETER;
113 if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->BlockSize <= 0)) {
116 "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n",
118 NvStorageFtwSpareSize
120 return EFI_INVALID_PARAMETER;
124 if ((NvStorageVariableBase % Instance->BlockSize != 0) ||
125 (NvStorageFtwWorkingBase % Instance->BlockSize != 0) ||
126 (NvStorageFtwSpareBase % Instance->BlockSize != 0))
128 DEBUG ((DEBUG_ERROR,
"%a: NvStorage Base addresses must be aligned to block size boundaries", __func__));
129 return EFI_INVALID_PARAMETER;
138 PcdGet32 (PcdFlashNvStorageVariableSize) +
139 PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
140 PcdGet32 (PcdFlashNvStorageFtwSpareSize);
141 FirmwareVolumeHeader->
Signature = EFI_FVH_SIGNATURE;
143 EFI_FVB2_READ_ENABLED_CAP |
144 EFI_FVB2_READ_STATUS |
145 EFI_FVB2_STICKY_WRITE |
146 EFI_FVB2_MEMORY_MAPPED |
147 EFI_FVB2_ERASE_POLARITY |
148 EFI_FVB2_WRITE_STATUS |
149 EFI_FVB2_WRITE_ENABLED_CAP
166 VariableStoreHeader->
State = VARIABLE_STORE_HEALTHY;
169 Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
193 UINTN VariableStoreLength;
198 FvLength =
PcdGet32 (PcdFlashNvStorageVariableSize) +
PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
199 PcdGet32 (PcdFlashNvStorageFtwSpareSize);
207 || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
208 || (FwVolHeader->FvLength != FvLength)
213 "%a: No Firmware Volume header present\n",
216 return EFI_NOT_FOUND;
220 if (
CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) ==
FALSE ) {
223 "%a: Firmware Volume Guid non-compatible\n",
226 return EFI_NOT_FOUND;
230 Checksum =
CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
234 "%a: FV checksum is invalid (Checksum:0x%X)\n",
238 return EFI_NOT_FOUND;
244 if (!
CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
247 "%a: Variable Store Guid non-compatible\n",
250 return EFI_NOT_FOUND;
253 VariableStoreLength =
PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
254 if (VariableStoreHeader->Size != VariableStoreLength) {
257 "%a: Variable Store Length does not match\n",
260 return EFI_NOT_FOUND;
266 DEBUG ((DEBUG_INFO,
"%a: checking variables\n", __func__));
267 VarOffset =
sizeof (*VariableStoreHeader);
274 CONST CHAR16 *VarName;
275 CONST CHAR8 *VarState;
276 RETURN_STATUS Status;
278 Status =
SafeUintnAdd (VarOffset,
sizeof (*VarHeader), &VarHeaderEnd);
280 DEBUG ((DEBUG_ERROR,
"%a: integer overflow\n", __func__));
281 return EFI_NOT_FOUND;
284 if (VarHeaderEnd >= VariableStoreHeader->Size) {
285 if (VarOffset <= VariableStoreHeader->Size -
sizeof (UINT16)) {
286 CONST UINT16 *StartId;
288 StartId = (VOID *)((
UINTN)VariableStoreHeader + VarOffset);
289 if (*StartId == 0x55aa) {
290 DEBUG ((DEBUG_ERROR,
"%a: startid at invalid location\n", __func__));
291 return EFI_NOT_FOUND;
295 DEBUG ((DEBUG_INFO,
"%a: end of var list (no space left)\n", __func__));
299 VarHeader = (VOID *)((
UINTN)VariableStoreHeader + VarOffset);
300 if (VarHeader->StartId != 0x55aa) {
301 DEBUG ((DEBUG_INFO,
"%a: end of var list (no startid)\n", __func__));
305 if (VarHeader->State == 0xff) {
306 DEBUG ((DEBUG_INFO,
"%a: end of var list (unwritten state)\n", __func__));
311 switch (VarHeader->State) {
314 VarState =
"header-ok";
315 VarName = L
"<unknown>";
325 VarState =
"del-in-transition";
331 VarState =
"deleted";
337 "%a: invalid variable state: 0x%x\n",
341 return EFI_NOT_FOUND;
344 Status =
SafeUintnAdd (VarHeaderEnd, VarHeader->NameSize, &VarNameEnd);
346 DEBUG ((DEBUG_ERROR,
"%a: integer overflow\n", __func__));
347 return EFI_NOT_FOUND;
350 Status =
SafeUintnAdd (VarNameEnd, VarHeader->DataSize, &VarEnd);
352 DEBUG ((DEBUG_ERROR,
"%a: integer overflow\n", __func__));
353 return EFI_NOT_FOUND;
356 if (VarEnd > VariableStoreHeader->Size) {
359 "%a: invalid variable size: 0x%Lx + 0x%Lx + 0x%x + 0x%x > 0x%x\n",
362 (UINT64)(
sizeof (*VarHeader)),
365 VariableStoreHeader->Size
367 return EFI_NOT_FOUND;
370 if (((VarHeader->NameSize & 1) != 0) ||
371 (VarHeader->NameSize < 4))
373 DEBUG ((DEBUG_ERROR,
"%a: invalid name size\n", __func__));
374 return EFI_NOT_FOUND;
377 if (VarName ==
NULL) {
378 VarName = (VOID *)((
UINTN)VariableStoreHeader + VarHeaderEnd);
379 if (VarName[VarHeader->NameSize / 2 - 1] != L
'\0') {
380 DEBUG ((DEBUG_ERROR,
"%a: name is not null terminated\n", __func__));
381 return EFI_NOT_FOUND;
387 "%a: +0x%04Lx: name=0x%x data=0x%x guid=%g '%s' (%a)\n",
392 &VarHeader->VendorGuid,
397 VarPadding = (4 - (VarEnd & 3)) & 3;
400 DEBUG ((DEBUG_ERROR,
"%a: integer overflow\n", __func__));
401 return EFI_NOT_FOUND;
432 EFI_FVB2_READ_ENABLED_CAP |
433 EFI_FVB2_READ_STATUS |
434 EFI_FVB2_STICKY_WRITE |
435 EFI_FVB2_MEMORY_MAPPED |
436 EFI_FVB2_ERASE_POLARITY |
437 EFI_FVB2_WRITE_STATUS |
438 EFI_FVB2_WRITE_ENABLED_CAP
442 *Attributes = FlashFvbAttributes;
444 DEBUG ((DEBUG_BLKIO,
"FvbGetAttributes(0x%X)\n", *Attributes));
475 DEBUG ((DEBUG_BLKIO,
"FvbSetAttributes(0x%X) is not supported\n", *Attributes));
476 return EFI_UNSUPPORTED;
498FvbGetPhysicalAddress (
505 Instance = INSTANCE_FROM_FVB_THIS (This);
507 DEBUG ((DEBUG_BLKIO,
"FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress));
509 ASSERT (Address !=
NULL);
511 *Address = mFlashNvStorageVariableBase;
553 Instance = INSTANCE_FROM_FVB_THIS (This);
555 DEBUG ((DEBUG_BLKIO,
"FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->BlockSize, Instance->LastBlock));
557 if (Lba > Instance->LastBlock) {
558 DEBUG ((DEBUG_ERROR,
"FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->LastBlock));
559 Status = EFI_INVALID_PARAMETER;
562 *BlockSize = (
UINTN)Instance->BlockSize;
563 *NumberOfBlocks = (
UINTN)(Instance->LastBlock - Lba + 1);
565 DEBUG ((DEBUG_BLKIO,
"FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
628 Instance = INSTANCE_FROM_FVB_THIS (This);
630 DEBUG ((DEBUG_BLKIO,
"FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
635 BlockSize = Instance->BlockSize;
637 DEBUG ((DEBUG_BLKIO,
"FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
641 if ((Offset >= BlockSize) ||
642 (*NumBytes > BlockSize) ||
643 ((Offset + *NumBytes) > BlockSize))
645 DEBUG ((DEBUG_ERROR,
"FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
646 return EFI_BAD_BUFFER_SIZE;
650 if (*NumBytes == 0) {
651 return EFI_BAD_BUFFER_SIZE;
655 if (*NumBytes % BlockSize != 0) {
656 TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
657 if (EFI_ERROR (TempStatus)) {
658 return EFI_DEVICE_ERROR;
662 TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
663 if (EFI_ERROR (TempStatus)) {
665 return EFI_DEVICE_ERROR;
738 Instance = INSTANCE_FROM_FVB_THIS (This);
740 return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
800 Instance = INSTANCE_FROM_FVB_THIS (This);
802 DEBUG ((DEBUG_BLKIO,
"FvbEraseBlocks()\n"));
825 "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
826 Instance->StartLba + StartingLba,
830 if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->LastBlock)) {
832 DEBUG ((DEBUG_ERROR,
"FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
833 Status = EFI_INVALID_PARAMETER;
858 while (NumOfLba > 0) {
860 BlockAddress = GET_NOR_BLOCK_ADDRESS (
861 Instance->RegionBaseAddress,
862 Instance->StartLba + StartingLba,
867 DEBUG ((DEBUG_BLKIO,
"FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
868 Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
869 if (EFI_ERROR (Status)) {
871 Status = EFI_DEVICE_ERROR;
897FvbVirtualNotifyEvent (
UINT16 EFIAPI CalculateSum16(IN CONST UINT16 *Buffer, IN UINTN Length)
UINT16 EFIAPI CalculateCheckSum16(IN CONST UINT16 *Buffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define EFI_LBA_LIST_TERMINATOR
VOID InitializeFvAndVariableStoreHeaders(IN VOID *Ptr)
#define RETURN_ERROR(StatusCode)
#define VA_ARG(Marker, TYPE)
#define VA_START(Marker, Parameter)
#define DEBUG(Expression)
#define PcdGet64(TokenName)
#define PcdGet32(TokenName)
UINT32 EFI_FVB_ATTRIBUTES_2
RETURN_STATUS EFIAPI SafeUintnAdd(IN UINTN Augend, IN UINTN Addend, OUT UINTN *Result)
UINT64 EFI_PHYSICAL_ADDRESS
EFI_STATUS EFIAPI EfiConvertPointer(IN UINTN DebugDisposition, IN OUT VOID **Address)
EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]
EFI_FVB_ATTRIBUTES_2 Attributes