]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
Align the header of variable from 1 to 4, which can avoid the size of variable conten...
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index 34bc4a8e1522e5d9ce88694491192802d492a195..e1fec9d62c6e31a3828ddc9bd68ca29e99dcfa8f 100644 (file)
@@ -152,7 +152,6 @@ UpdateVariableInfo (
 }\r
 \r
 \r
-\r
 BOOLEAN\r
 IsValidVariableHeader (\r
   IN  VARIABLE_HEADER   *Variable\r
@@ -172,10 +171,7 @@ Returns:
 \r
 --*/\r
 {\r
-  if (Variable == NULL ||\r
-      Variable->StartId != VARIABLE_DATA ||\r
-      (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE\r
-      ) {\r
+  if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {\r
     return FALSE;\r
   }\r
 \r
@@ -372,6 +368,59 @@ Returns:
 }\r
 \r
 \r
+UINT32\r
+NameSizeOfVariable (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+{\r
+  //\r
+  // Check whether the header is valid fully;\r
+  // Tricky: The unprogramed data in FLASH equals 0xff.\r
+  // \r
+  if (Variable->DataSize == (UINT32) -1 || \r
+      Variable->Attributes == (UINT32) -1 || \r
+      Variable->NameSize == (UINT32) -1) {\r
+    return 0;\r
+  }\r
+  return Variable->NameSize;\r
+}\r
+\r
+UINT32\r
+DataSizeOfVariable (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+{\r
+  //\r
+  // Check whether the header is valid fully;\r
+  // Tricky: The unprogramed data in FLASH equals 0xff.\r
+  // \r
+  if (Variable->DataSize == (UINT32) -1 || \r
+      Variable->Attributes == (UINT32) -1 || \r
+      Variable->NameSize == (UINT32) -1) {\r
+    return 0;\r
+  }\r
+  return Variable->DataSize;\r
+}\r
+\r
+UINT32\r
+AttributesOfVariable (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+{\r
+\r
+  //\r
+  // Check whether the header is valid fully;\r
+  // Tricky: The unprogramed data in FLASH equals 0xff.\r
+  // \r
+  if (Variable->DataSize == (UINT32) -1 || \r
+      Variable->Attributes == (UINT32) -1 || \r
+      Variable->NameSize == (UINT32) -1) {\r
+    return 0;\r
+  }\r
+  return Variable->Attributes;\r
+}\r
+\r
+\r
 UINT8 *\r
 GetVariableDataPtr (\r
   IN  VARIABLE_HEADER   *Variable\r
@@ -395,7 +444,7 @@ Returns:
   //\r
   // Be careful about pad size for alignment\r
   //\r
-  return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
+  return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + NameSizeOfVariable (Variable) + GET_PAD_SIZE (NameSizeOfVariable (Variable)));\r
 }\r
 \r
 \r
@@ -425,9 +474,34 @@ Returns:
   //\r
   // Be careful about pad size for alignment\r
   //\r
-  return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
+  return (VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) GetVariableDataPtr (Variable) + DataSizeOfVariable (Variable) + GET_PAD_SIZE (DataSizeOfVariable (Variable))));\r
 }\r
 \r
+VARIABLE_HEADER *\r
+GetStartPointer (\r
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This code gets the pointer to the first variable memory pointer byte\r
+\r
+Arguments:\r
+\r
+  VarStoreHeader        Pointer to the Variable Store Header.\r
+\r
+Returns:\r
+\r
+  VARIABLE_HEADER*      Pointer to last unavailable Variable Header\r
+\r
+--*/\r
+{\r
+  //\r
+  // The end of variable store\r
+  //\r
+  return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);\r
+}\r
 \r
 VARIABLE_HEADER *\r
 GetEndPointer (\r
@@ -452,7 +526,7 @@ Returns:
   //\r
   // The end of variable store\r
   //\r
-  return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
+  return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
 }\r
 \r
 \r
@@ -495,8 +569,7 @@ Returns:
   //\r
   // Start Pointers for the variable.\r
   //\r
-  Variable        = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
-\r
+  Variable        = GetStartPointer (VariableStoreHeader);\r
   ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
 \r
   while (IsValidVariableHeader (Variable)) {\r
@@ -522,12 +595,12 @@ Returns:
   // Copy variable store header\r
   //\r
   CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
-  CurrPtr += sizeof (VARIABLE_STORE_HEADER);\r
+  CurrPtr = (UINT8 *) GetStartPointer (VariableStoreHeader);\r
 \r
   //\r
   // Start Pointers for the variable.\r
   //\r
-  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+  Variable = GetStartPointer (VariableStoreHeader);\r
 \r
   while (IsValidVariableHeader (Variable)) {\r
     NextVariable = GetNextVariablePtr (Variable);\r
@@ -676,11 +749,12 @@ FindVariableInCache (
         if (Entry->DataSize == 0) {\r
           // Variable was deleted so return not found\r
           return EFI_NOT_FOUND;\r
-        } else if (Entry->DataSize != *DataSize) {\r
+        } else if (Entry->DataSize > *DataSize) {\r
           // If the buffer is too small return correct size\r
           *DataSize = Entry->DataSize;\r
           return EFI_BUFFER_TOO_SMALL;\r
         } else {\r
+          *DataSize = Entry->DataSize;\r
           // Return the data\r
           CopyMem (Data, Entry->Data, Entry->DataSize);\r
           if (Attributes != NULL) {\r
@@ -728,13 +802,6 @@ Returns:
   VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
   UINTN                 Index;\r
 \r
-  //\r
-  // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName\r
-  // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to\r
-  // the correct places if this assumption does not hold TRUE anymore.\r
-  //\r
-  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
-\r
   //\r
   // 0: Volatile, 1: Non-Volatile\r
   // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName\r
@@ -747,8 +814,8 @@ Returns:
   // Start Pointers for the variable.\r
   // Actual Data Pointer where data can be written.\r
   //\r
-  Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);\r
-  Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);\r
+  Variable[0] = GetStartPointer (VariableStoreHeader[0]);\r
+  Variable[1] = GetStartPointer (VariableStoreHeader[1]);\r
 \r
   if (VariableName[0] != 0 && VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -757,7 +824,7 @@ Returns:
   // Find the variable by walk through volatile and then non-volatile variable store\r
   //\r
   for (Index = 0; Index < 2; Index++) {\r
-    PtrTrack->StartPtr  = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);\r
+    PtrTrack->StartPtr  = GetStartPointer (VariableStoreHeader[Index]);\r
     PtrTrack->EndPtr    = GetEndPointer (VariableStoreHeader[Index]);\r
 \r
     while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {\r
@@ -769,7 +836,8 @@ Returns:
             return EFI_SUCCESS;\r
           } else {\r
             if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
-              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {\r
+              ASSERT (NameSizeOfVariable (Variable[Index]) != 0);\r
+              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), NameSizeOfVariable (Variable[Index]))) {\r
                 PtrTrack->CurrPtr   = Variable[Index];\r
                 PtrTrack->Volatile  = (BOOLEAN)(Index == 0);\r
                 return EFI_SUCCESS;\r
@@ -832,6 +900,8 @@ RuntimeServiceGetVariable (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
   //\r
   // Find existing variable\r
   //\r
@@ -839,7 +909,7 @@ RuntimeServiceGetVariable (
   if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_SUCCESS)){\r
     // Hit in the Cache\r
     UpdateVariableInfo (VariableName, VendorGuid, FALSE, TRUE, FALSE, FALSE, TRUE);\r
-    return Status;\r
+    goto Done;\r
   }\r
   \r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
@@ -850,7 +920,9 @@ RuntimeServiceGetVariable (
   //\r
   // Get data size\r
   //\r
-  VarDataSize = Variable.CurrPtr->DataSize;\r
+  VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
+  ASSERT (VarDataSize != 0);\r
+\r
   if (*DataSize >= VarDataSize) {\r
     if (Data == NULL) {\r
       Status = EFI_INVALID_PARAMETER;\r
@@ -916,6 +988,8 @@ RuntimeServiceGetNextVariableName (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
@@ -936,8 +1010,8 @@ RuntimeServiceGetNextVariableName (
     if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
       Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));\r
       if (!Variable.Volatile) {\r
-        Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
-        Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase));\r
+        Variable.StartPtr = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
+        Variable.EndPtr   = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase));\r
       } else {\r
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
@@ -953,7 +1027,9 @@ RuntimeServiceGetNextVariableName (
     //\r
     if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {\r
       if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
-        VarNameSize = Variable.CurrPtr->NameSize;\r
+        VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
+        ASSERT (VarNameSize != 0);\r
+\r
         if (VarNameSize <= *VariableNameSize) {\r
           CopyMem (\r
             VariableName,\r
@@ -1036,11 +1112,7 @@ RuntimeServiceSetVariable (
   UINTN                   *NonVolatileOffset;\r
   UINT32                  Instance;\r
   BOOLEAN                 Volatile;\r
-\r
-  Reclaimed         = FALSE;\r
-  VolatileOffset    = &mVariableModuleGlobal->VolatileLastVariableOffset;\r
-  NonVolatileOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;\r
-  Instance          = mVariableModuleGlobal->FvbInstance;\r
+  EFI_PHYSICAL_ADDRESS    Point;\r
 \r
   //\r
   // Check input parameters\r
@@ -1054,6 +1126,7 @@ RuntimeServiceSetVariable (
   if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   //\r
   //  The size of the VariableName, including the Unicode Null in bytes plus\r
   //  the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)\r
@@ -1074,6 +1147,31 @@ RuntimeServiceSetVariable (
       return EFI_INVALID_PARAMETER;\r
     }  \r
   }  \r
+\r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+  Reclaimed         = FALSE;\r
+  Instance          = mVariableModuleGlobal->FvbInstance;\r
+  VolatileOffset    = &mVariableModuleGlobal->VolatileLastVariableOffset;\r
+\r
+  //\r
+  // Consider reentrant in MCA/INIT/NMI. It needs be reupdated;\r
+  //\r
+  if (1 < InterlockedIncrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState)) {\r
+    Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;;\r
+    //\r
+    // Parse non-volatile variable data and get last variable offset\r
+    //\r
+    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);\r
+    while (IsValidVariableHeader (NextVariable)) {\r
+      NextVariable = GetNextVariablePtr (NextVariable);\r
+    }\r
+    mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;\r
+  }\r
+\r
+  NonVolatileOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;\r
+  \r
+\r
   //\r
   // Check whether the input variable is already existed\r
   //\r
@@ -1130,7 +1228,7 @@ RuntimeServiceSetVariable (
     // If the variable is marked valid and the same data has been passed in\r
     // then return to the caller immediately.\r
     //\r
-    if (Variable.CurrPtr->DataSize == DataSize &&\r
+    if (DataSizeOfVariable (Variable.CurrPtr) == DataSize &&\r
         (CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) == 0)) {\r
       \r
       UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
@@ -1319,7 +1417,7 @@ RuntimeServiceSetVariable (
       goto Done;\r
     }\r
 \r
-    *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
+    *NonVolatileOffset = HEADER_ALIGN (*NonVolatileOffset + VarSize);\r
 \r
   } else {\r
     //\r
@@ -1364,7 +1462,7 @@ RuntimeServiceSetVariable (
       goto Done;\r
     }\r
 \r
-    *VolatileOffset = *VolatileOffset + VarSize;\r
+    *VolatileOffset = HEADER_ALIGN (*VolatileOffset + VarSize);\r
   }\r
   //\r
   // Mark the old variable as deleted\r
@@ -1395,7 +1493,9 @@ RuntimeServiceSetVariable (
   UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
 \r
 Done:\r
+  InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);\r
   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
   return Status;\r
 }\r
 \r
@@ -1498,7 +1598,7 @@ RuntimeServiceQueryVariableInfo (
   //\r
   // Point to the starting address of the variables.\r
   //\r
-  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+  Variable = GetStartPointer (VariableStoreHeader);\r
 \r
   //\r
   // Now walk through the related variable store.\r
@@ -1585,6 +1685,7 @@ Returns:
 \r
 \r
   EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
+  mVariableModuleGlobal->VariableGlobal.ReentrantState = 0;\r
 \r
   //\r
   // Allocate memory for volatile variable store\r
@@ -1601,7 +1702,7 @@ Returns:
   //  Variable Specific Data\r
   //\r
   mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
-  mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
+  mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;\r
 \r
   VolatileVariableStore->Signature                  = VARIABLE_STORE_SIGNATURE;\r
   VolatileVariableStore->Size                       = VARIABLE_STORE_SIZE;\r
@@ -1697,7 +1798,7 @@ Returns:
     //\r
     // Parse non-volatile variable data and get last variable offset\r
     //\r
-    NextVariable  = (VARIABLE_HEADER *) (CurrPtr + sizeof (VARIABLE_STORE_HEADER));\r
+    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) CurrPtr);\r
     Status        = EFI_SUCCESS;\r
 \r
     while (IsValidVariableHeader (NextVariable)) {\r