]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
1. The original code has a bug on calculate the size of SCRATCH_SIZE. It should be...
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index 0e5735e941a644d85cc6698592cea15a74c19726..62025c9ee1dc0471f09ff7ccd9121c0aef3b29ad 100644 (file)
@@ -596,6 +596,13 @@ Reclaim (
   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
@@ -661,6 +668,11 @@ Reclaim (
       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
@@ -672,6 +684,11 @@ Reclaim (
     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
@@ -713,6 +730,11 @@ Reclaim (
         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
@@ -1216,6 +1238,8 @@ RuntimeServiceSetVariable (
   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
@@ -1397,8 +1421,9 @@ RuntimeServiceSetVariable (
   // 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
@@ -1438,10 +1463,11 @@ RuntimeServiceSetVariable (
     // 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
@@ -1456,9 +1482,10 @@ RuntimeServiceSetVariable (
       //\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
@@ -1542,6 +1569,11 @@ RuntimeServiceSetVariable (
 \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
@@ -1653,11 +1685,16 @@ RuntimeServiceQueryVariableInfo (
   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
@@ -1673,6 +1710,11 @@ RuntimeServiceQueryVariableInfo (
     // 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
@@ -1694,18 +1736,23 @@ RuntimeServiceQueryVariableInfo (
   // 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
@@ -1727,14 +1774,22 @@ RuntimeServiceQueryVariableInfo (
       // 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
@@ -1744,6 +1799,12 @@ RuntimeServiceQueryVariableInfo (
     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
@@ -1773,22 +1834,29 @@ ReclaimForOS(
   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
@@ -1820,6 +1888,7 @@ VariableCommonInitialize (
   EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
   UINT64                          VariableStoreLength;\r
   EFI_EVENT                       ReadyToBootEvent;\r
+  UINTN                           ScratchSize;\r
 \r
   Status = EFI_SUCCESS;\r
   //\r
@@ -1832,17 +1901,20 @@ VariableCommonInitialize (
 \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
@@ -1925,6 +1997,14 @@ VariableCommonInitialize (
     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