## Maximum PPI count is supported by PeiCore's PPI database.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported|64|UINT32|0x00010033\r
\r
- ## Size of the NV variable range.\r
+ ## Size of the NV variable range. Note that this value should less than or equal to PcdFlashNvStorageFtwSpareSize\r
+ # The root cause is that variable driver will use FTW protocol to reclaim variable region.\r
+ # If the length of variable region is larger than FTW spare size, it means the whole variable region can not\r
+ # be reflushed through the manner of fault tolerant write. \r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x0|UINT32|0x30000002\r
\r
- ## Maximum allowable size of a common type variable, that is, non-hardware error type variable.\r
+ ## The maximum size of single common variable, that is non-HwErr type varible.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x400|UINT32|0x30000003\r
\r
- ## Maximum allowable size of a single hardware error record variable.\r
+ ## The maximum size of single hardware error record variable.\r
+ # In IA32/X64 platforms, this value should be larger than 1KB.\r
+ # In IA64 platforms, this value should be larger than 128KB.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000|UINT32|0x30000004\r
\r
- ## Size of allocated memory for volatile variable store. Variables are stored in such region and \r
- # total length of all variables should not larger than this value.\r
- ##\r
+ ## The size of reserved HwErr variable space. This space is located at NV variable range.\r
+ # HwErr type variable is stored with common non-volatile variables in NV region.\r
+ # this value is used to guarantee the space of HwErr type variable and not populated by common variable.\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x8000|UINT32|0x30000006\r
+\r
+ ## The size of volatile buffer. This buffer is used to store VOLATILE attribute variable.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000|UINT32|0x30000005\r
- \r
- ## Size of the FTW spare block range.\r
+\r
+ ## Size of the FTW spare block range. Note that this value should larger than PcdFlashNvStorageVariableSize\r
+ # The root cause is that variable driver will use FTW protocol to reclaim variable region.\r
+ # If the length of variable region is larger than FTW spare size, it means the whole variable region can not\r
+ # be reflushed through the manner of fault tolerant write.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
\r
## Size of the FTW working block range.\r
CHAR16 *UpdatingVariableNamePtr;\r
\r
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
+ //\r
+ // recaluate the total size of Common/HwErr type variables in non-volatile area.\r
+ //\r
+ if (!IsVolatile) {\r
+ mVariableModuleGlobal->CommonVariableTotalSize = 0;\r
+ mVariableModuleGlobal->HwErrVariableTotalSize = 0;\r
+ }\r
\r
//\r
// Start Pointers for the variable.\r
VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
CurrPtr += VariableSize;\r
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;\r
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;\r
+ }\r
}\r
Variable = NextVariable;\r
}\r
VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;\r
CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);\r
CurrPtr += VariableSize;\r
+ if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;\r
+ } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;\r
+ }\r
}\r
\r
//\r
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;\r
CurrPtr += VariableSize;\r
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;\r
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;\r
+ }\r
}\r
}\r
\r
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
BOOLEAN Volatile;\r
EFI_PHYSICAL_ADDRESS Point;\r
+ UINTN ScratchSize;\r
+ UINTN NonVolatileVarableStoreSize;\r
\r
//\r
// Check input parameters\r
// as a temporary storage.\r
//\r
NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));\r
+ ScratchSize = MAX(FixedPcdGet32(PcdMaxVariableSize), FixedPcdGet32(PcdMaxHardwareErrorVariableSize));\r
\r
- SetMem (NextVariable, FixedPcdGet32(PcdMaxVariableSize), 0xff);\r
+ SetMem (NextVariable, ScratchSize, 0xff);\r
\r
NextVariable->StartId = VARIABLE_DATA;\r
NextVariable->Attributes = Attributes;\r
// Create a nonvolatile variable\r
//\r
Volatile = FALSE;\r
- \r
- if ((UINT32) (VarSize +*NonVolatileOffset) >\r
- ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size\r
- ) {\r
+ NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;\r
+ if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) \r
+ && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > FixedPcdGet32(PcdHwErrStorageSize)))\r
+ || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) \r
+ && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - FixedPcdGet32(PcdHwErrStorageSize)))) {\r
if (EfiAtRuntime ()) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
//\r
// If still no enough space, return out of resources\r
//\r
- if ((UINT32) (VarSize +*NonVolatileOffset) >\r
- ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size\r
- ) {\r
+ if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) \r
+ && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > FixedPcdGet32(PcdHwErrStorageSize)))\r
+ || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) \r
+ && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - FixedPcdGet32(PcdHwErrStorageSize)))) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
\r
*NonVolatileOffset = HEADER_ALIGN (*NonVolatileOffset + VarSize);\r
\r
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VarSize);\r
+ } else {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);\r
+ }\r
} else {\r
//\r
// Create a volatile variable\r
VARIABLE_HEADER *NextVariable;\r
UINT64 VariableSize;\r
VARIABLE_STORE_HEADER *VariableStoreHeader;\r
+ UINT64 CommonVariableTotalSize;\r
+ UINT64 HwErrVariableTotalSize;\r
+\r
+ CommonVariableTotalSize = 0;\r
+ HwErrVariableTotalSize = 0;\r
\r
if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {\r
//\r
// Make sure the Attributes combination is supported by the platform.\r
// Make sure RT Attribute is set if we are in Runtime phase.\r
//\r
return EFI_INVALID_PARAMETER;\r
+ } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ //\r
+ // Make sure Hw Attribute is set with NV.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
// with the storage size (excluding the storage header size).\r
//\r
*MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
- *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
-\r
- //\r
- // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.\r
- //\r
- *MaximumVariableSize = FixedPcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);\r
\r
//\r
// Harware error record variable needs larger size.\r
//\r
- if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ *MaximumVariableStorageSize = FixedPcdGet32(PcdHwErrStorageSize);\r
*MaximumVariableSize = FixedPcdGet32(PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);\r
+ } else {\r
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
+ ASSERT (FixedPcdGet32(PcdHwErrStorageSize) < VariableStoreHeader->Size);\r
+ *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - FixedPcdGet32(PcdHwErrStorageSize);\r
+ }\r
+\r
+ //\r
+ // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.\r
+ //\r
+ *MaximumVariableSize = FixedPcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);\r
}\r
\r
//\r
// since the space occupied by variables not marked with\r
// VAR_ADDED is not allowed to be reclaimed in Runtime.\r
//\r
- *RemainingVariableStorageSize -= VariableSize;\r
+ if ((NextVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ HwErrVariableTotalSize += VariableSize;\r
+ } else {\r
+ CommonVariableTotalSize += VariableSize;\r
+ }\r
} else {\r
//\r
// Only care about Variables with State VAR_ADDED,because\r
// the space not marked as VAR_ADDED is reclaimable now.\r
//\r
if (Variable->State == VAR_ADDED) {\r
- *RemainingVariableStorageSize -= VariableSize;\r
+ if ((NextVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ HwErrVariableTotalSize += VariableSize;\r
+ } else {\r
+ CommonVariableTotalSize += VariableSize;\r
+ }\r
}\r
}\r
\r
Variable = NextVariable;\r
}\r
\r
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD){\r
+ *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;\r
+ }else {\r
+ *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;\r
+ }\r
+\r
if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {\r
*MaximumVariableSize = 0;\r
} else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {\r
VOID *Context\r
)\r
{\r
- UINT32 VarSize;\r
EFI_STATUS Status;\r
+ UINTN CommonVariableSpace;\r
+ UINTN RemainingCommonVariableSpace;\r
+ UINTN RemainingHwErrVariableSpace;\r
\r
- VarSize = ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;\r
Status = EFI_SUCCESS; \r
\r
+ CommonVariableSpace = ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32(PcdHwErrStorageSize); //Allowable max size of common variable storage space\r
+\r
+ RemainingCommonVariableSpace = CommonVariableSpace - mVariableModuleGlobal->CommonVariableTotalSize;\r
+\r
+ RemainingHwErrVariableSpace = PcdGet32 (PcdHwErrStorageSize) - mVariableModuleGlobal->HwErrVariableTotalSize;\r
//\r
// Check if the free area is blow a threshold\r
//\r
- if ((VarSize - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {\r
+ if ((RemainingCommonVariableSpace < PcdGet32 (PcdMaxVariableSize))\r
+ || (RemainingHwErrVariableSpace < PcdGet32 (PcdMaxHardwareErrorVariableSize))){\r
Status = Reclaim (\r
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
- &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
- FALSE,\r
- NULL\r
- );\r
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+ FALSE,\r
+ NULL\r
+ );\r
ASSERT_EFI_ERROR (Status);\r
}\r
}\r
EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
UINT64 VariableStoreLength;\r
EFI_EVENT ReadyToBootEvent;\r
+ UINTN ScratchSize;\r
\r
Status = EFI_SUCCESS;\r
//\r
\r
EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
mVariableModuleGlobal->VariableGlobal.ReentrantState = 0;\r
+ mVariableModuleGlobal->CommonVariableTotalSize = 0;\r
+ mVariableModuleGlobal->HwErrVariableTotalSize = 0;\r
\r
//\r
- // Allocate memory for volatile variable store\r
+ // Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.\r
//\r
- VolatileVariableStore = AllocateRuntimePool (FixedPcdGet32(PcdVariableStoreSize) + FixedPcdGet32(PcdMaxVariableSize));\r
+ ScratchSize = MAX(FixedPcdGet32(PcdMaxVariableSize), FixedPcdGet32(PcdMaxHardwareErrorVariableSize));\r
+ VolatileVariableStore = AllocateRuntimePool (FixedPcdGet32(PcdVariableStoreSize) + ScratchSize);\r
if (VolatileVariableStore == NULL) {\r
FreePool (mVariableModuleGlobal);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- SetMem (VolatileVariableStore, FixedPcdGet32(PcdVariableStoreSize) + FixedPcdGet32(PcdMaxVariableSize), 0xff);\r
+ SetMem (VolatileVariableStore, FixedPcdGet32(PcdVariableStoreSize) + ScratchSize, 0xff);\r
\r
//\r
// Variable Specific Data\r
Status = EFI_SUCCESS;\r
\r
while (IsValidVariableHeader (NextVariable)) {\r
+ UINTN VariableSize = 0;\r
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
+ if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+ } else {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+ }\r
+\r
NextVariable = GetNextVariablePtr (NextVariable);\r
}\r
\r