]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
Fix some coding style issues in MdeModulePkg.
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / EmuRuntimeDxe / EmuVariable.c
index 9f372c143710d903c8a151bd60ad908b3a13de47..622fe530b3057485e15969e097087ff3897b528e 100644 (file)
@@ -160,18 +160,21 @@ GetVariableDataPtr (
 }\r
 \r
 /**\r
-  Gets pointer to header of the next variable.\r
+  Gets pointer to header of the next potential variable.\r
 \r
-  This function gets the pointer to the next variable header according\r
-  to the input point to the variable header.\r
+  This function gets the pointer to the next potential variable header\r
+  according to the input point to the variable header.  The return value\r
+  is not a valid variable if the input variable was the last variable\r
+  in the variabl store.\r
 \r
   @param  Variable      Pointer to header of the next variable\r
 \r
   @return Pointer to next variable header.\r
+  @retval NULL  Input was not a valid variable header.\r
 \r
 **/\r
 VARIABLE_HEADER *\r
-GetNextVariablePtr (\r
+GetNextPotentialVariablePtr (\r
   IN  VARIABLE_HEADER   *Variable\r
   )\r
 {\r
@@ -185,13 +188,67 @@ GetNextVariablePtr (
   //\r
   VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
 \r
-  if (VarHeader->StartId != VARIABLE_DATA) {\r
+  return VarHeader;\r
+}\r
+\r
+/**\r
+  Gets pointer to header of the next variable.\r
+\r
+  This function gets the pointer to the next variable header according\r
+  to the input point to the variable header.\r
+\r
+  @param  Variable      Pointer to header of the next variable\r
+\r
+  @return Pointer to next variable header.\r
+\r
+**/\r
+VARIABLE_HEADER *\r
+GetNextVariablePtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+{\r
+  VARIABLE_HEADER *VarHeader;\r
+\r
+  VarHeader = GetNextPotentialVariablePtr (Variable);\r
+\r
+  if ((VarHeader == NULL) || (VarHeader->StartId != VARIABLE_DATA)) {\r
     return NULL;\r
   }\r
 \r
   return VarHeader;\r
 }\r
 \r
+/**\r
+  Updates LastVariableOffset variable for the given variable store.\r
+\r
+  LastVariableOffset points to the offset to use for the next variable\r
+  when updating the variable store.\r
+\r
+  @param[in]   VariableStore       Pointer to the start of the variable store\r
+  @param[out]  LastVariableOffset  Offset to put the next new variable in\r
+\r
+**/\r
+VOID\r
+InitializeLocationForLastVariableOffset (\r
+  IN  VARIABLE_STORE_HEADER *VariableStore,\r
+  OUT UINTN                 *LastVariableOffset\r
+  )\r
+{\r
+  VARIABLE_HEADER *VarHeader;\r
+\r
+  *LastVariableOffset       = sizeof (VARIABLE_STORE_HEADER);\r
+  VarHeader = (VARIABLE_HEADER*) ((UINT8*)VariableStore + *LastVariableOffset);\r
+  while (VarHeader->StartId == VARIABLE_DATA) {\r
+    VarHeader = GetNextPotentialVariablePtr (VarHeader);\r
+\r
+    if (VarHeader != NULL) {\r
+      *LastVariableOffset = (UINTN) VarHeader - (UINTN) VariableStore;\r
+    } else {\r
+      return;\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Gets pointer to the end of the variable storage area.\r
 \r
@@ -263,7 +320,7 @@ UpdateVariableInfo (
       ASSERT (gVariableInfo != NULL);\r
 \r
       CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);\r
-      gVariableInfo->Name = AllocatePool (StrLen (VariableName));\r
+      gVariableInfo->Name = AllocatePool (StrSize (VariableName));\r
       ASSERT (gVariableInfo->Name != NULL);\r
       StrCpy (gVariableInfo->Name, VariableName);\r
       gVariableInfo->Volatile = Volatile;\r
@@ -301,7 +358,7 @@ UpdateVariableInfo (
         ASSERT (Entry->Next != NULL);\r
 \r
         CopyGuid (&Entry->Next->VendorGuid, VendorGuid);\r
-        Entry->Next->Name = AllocatePool (StrLen (VariableName));\r
+        Entry->Next->Name = AllocatePool (StrSize (VariableName));\r
         ASSERT (Entry->Next->Name != NULL);\r
         StrCpy (Entry->Next->Name, VariableName);\r
         Entry->Next->Volatile = Volatile;\r
@@ -315,9 +372,9 @@ UpdateVariableInfo (
   Get index from supported language codes according to language string.\r
 \r
   This code is used to get corresponding index in supported language codes. It can handle\r
-  RFC3066 and ISO639 language tags.\r
+  RFC4646 and ISO639 language tags.\r
   In ISO639 language tags, take 3-characters as a delimitation to find matched string and calculate the index.\r
-  In RFC3066 language tags, take semicolon as a delimitation to find matched string and calculate the index.\r
+  In RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.\r
 \r
   For example:\r
     SupportedLang  = "engfraengfra"\r
@@ -332,7 +389,7 @@ UpdateVariableInfo (
 \r
   @param  SupportedLang               Platform supported language codes.\r
   @param  Lang                        Configured language.\r
-  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC3066.\r
+  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
 \r
   @retval the index of language in the language codes.\r
 \r
@@ -366,7 +423,7 @@ GetIndexFromSupportedLangCodes(
     return 0;\r
   } else {\r
     //\r
-    // Compare RFC3066 language code\r
+    // Compare RFC4646 language code\r
     //\r
     while (*Supported != '\0') {\r
       //\r
@@ -392,9 +449,9 @@ GetIndexFromSupportedLangCodes(
   Get language string from supported language codes according to index.\r
 \r
   This code is used to get corresponding language string in supported language codes. It can handle\r
-  RFC3066 and ISO639 language tags.\r
+  RFC4646 and ISO639 language tags.\r
   In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.\r
-  In RFC3066 language tags, take semicolon as a delimitation. Find language string according to the index.\r
+  In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.\r
 \r
   For example:\r
     SupportedLang  = "engfraengfra"\r
@@ -409,7 +466,7 @@ GetIndexFromSupportedLangCodes(
 \r
   @param  SupportedLang               Platform supported language codes.\r
   @param  Index                       the index in supported language codes.\r
-  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC3066.\r
+  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
 \r
   @retval the language string in the language codes.\r
 \r
@@ -517,7 +574,7 @@ AutoUpdateLangVariable(
     // Therefore, in variable driver, only store the original value for other use.\r
     //\r
     AsciiStrnCpy (mVariableModuleGlobal->LangCodes, Data, DataSize);\r
-  } else if (StrCmp (VariableName, L"PlatformLang") == 0) {\r
+  } else if ((StrCmp (VariableName, L"PlatformLang") == 0) && (DataSize != 0)) {\r
     ASSERT (AsciiStrLen (mVariableModuleGlobal->PlatformLangCodes) != 0);\r
 \r
     //\r
@@ -531,7 +588,7 @@ AutoUpdateLangVariable(
     Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);\r
 \r
     //\r
-    // Get the corresponding ISO639 language tag according to RFC3066 language tag.\r
+    // Get the corresponding ISO639 language tag according to RFC4646 language tag.\r
     //\r
     BestLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, Index, TRUE);\r
 \r
@@ -547,7 +604,7 @@ AutoUpdateLangVariable(
 \r
     ASSERT_EFI_ERROR(Status);\r
 \r
-  } else if (StrCmp (VariableName, L"Lang") == 0) {\r
+  } else if ((StrCmp (VariableName, L"Lang") == 0) && (DataSize != 0)) {\r
     ASSERT (AsciiStrLen (mVariableModuleGlobal->LangCodes) != 0);\r
 \r
     //\r
@@ -561,7 +618,7 @@ AutoUpdateLangVariable(
     Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, BestLang, TRUE);\r
 \r
     //\r
-    // Get the corresponding RFC3066 language tag according to ISO639 language tag.\r
+    // Get the corresponding RFC4646 language tag according to ISO639 language tag.\r
     //\r
     BestPlatformLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);\r
 \r
@@ -571,7 +628,7 @@ AutoUpdateLangVariable(
     FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);\r
 \r
     Status = UpdateVariable(L"PlatformLang", &gEfiGlobalVariableGuid, \r
-                    BestPlatformLang, AsciiStrLen (BestPlatformLang), Attributes, &Variable);\r
+                    BestPlatformLang, AsciiStrSize (BestPlatformLang), Attributes, &Variable);\r
 \r
     DEBUG((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));\r
     ASSERT_EFI_ERROR(Status);\r
@@ -618,7 +675,7 @@ UpdateVariable (
   UINTN                   VarDataOffset;\r
   UINTN                   VarSize;\r
   VARIABLE_GLOBAL         *Global;\r
-  UINTN                               NonVolatileVarableStoreSize;\r
+  UINTN                   NonVolatileVarableStoreSize;\r
 \r
   Global = &mVariableModuleGlobal->VariableGlobal[Physical];\r
 \r
@@ -767,7 +824,9 @@ UpdateVariable (
   //\r
   // Mark the old variable as deleted\r
   //\r
-  Variable->CurrPtr->State &= VAR_DELETED;\r
+  if (Variable->CurrPtr != NULL) {\r
+    Variable->CurrPtr->State &= VAR_DELETED;\r
+  }\r
 \r
   UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);\r
 \r
@@ -811,13 +870,6 @@ FindVariable (
   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(&Global->VariableServicesLock);\r
-\r
   //\r
   // 0: Non-Volatile, 1: Volatile\r
   //\r
@@ -906,6 +958,9 @@ EmuGetVariable (
   if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
+  AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+\r
   //\r
   // Find existing variable\r
   //\r
@@ -979,6 +1034,8 @@ EmuGetNextVariableName (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+\r
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
@@ -1096,6 +1153,11 @@ EmuSetVariable (
   if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }  \r
+\r
+  if (DataSize != 0 && Data == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   //  Make sure if runtime bit is set, boot service bit is set also\r
   //\r
@@ -1129,6 +1191,8 @@ EmuSetVariable (
     }  \r
   }\r
 \r
+  AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+\r
   //\r
   // Check whether the input variable is already existed\r
   //\r
@@ -1299,35 +1363,80 @@ EmuQueryVariableInfo (
 \r
   This function allocates memory space for variable store area and initializes its attributes.\r
 \r
-  @param  VariableBase         Base of the variable store area created\r
-  @param  LastVariableOffset   Size of VARIABLE_STORE_HEADER\r
+  @param  VolatileStore  Indicates if the variable store is volatile.\r
 \r
 **/\r
 EFI_STATUS\r
 InitializeVariableStore (\r
-  OUT EFI_PHYSICAL_ADDRESS  *VariableBase,\r
-  OUT UINTN                 *LastVariableOffset\r
+  IN  BOOLEAN               VolatileStore\r
   )\r
 {\r
   VARIABLE_STORE_HEADER *VariableStore;\r
+  BOOLEAN               FullyInitializeStore;\r
+  EFI_PHYSICAL_ADDRESS  *VariableBase;\r
+  UINTN                 *LastVariableOffset;\r
+\r
+  FullyInitializeStore = TRUE;\r
+\r
+  if (VolatileStore) {\r
+    VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase;\r
+    LastVariableOffset = &mVariableModuleGlobal->VolatileLastVariableOffset;\r
+  } else {\r
+    VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase;\r
+    LastVariableOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;\r
+  }\r
 \r
   //\r
-  // Allocate memory for volatile variable store\r
+  // Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
+  // is stored with common variable in the same NV region. So the platform integrator should\r
+  // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of \r
+  // PcdVariableStoreSize.\r
+  //\r
+  ASSERT (FixedPcdGet32(PcdHwErrStorageSize) <= FixedPcdGet32(PcdVariableStoreSize));\r
+\r
   //\r
-  VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
-                                              FixedPcdGet32(PcdVariableStoreSize)\r
-                                              );\r
+  // Allocate memory for variable store.\r
+  //\r
+  if (VolatileStore || (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0)) {\r
+    VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
+                                                FixedPcdGet32(PcdVariableStoreSize)\r
+                                                );\r
+  } else {\r
+    //\r
+    // A memory location has been reserved for the NV variable store.  Certain\r
+    // platforms may be able to preserve a memory range across system resets,\r
+    // thereby providing better NV variable emulation.\r
+    //\r
+    VariableStore =\r
+      (VARIABLE_STORE_HEADER *)(VOID*)(UINTN)\r
+        PcdGet64 (PcdEmuVariableNvStoreReserved);\r
+    if (\r
+         (VariableStore->Size == FixedPcdGet32(PcdVariableStoreSize)) &&\r
+         (VariableStore->Format == VARIABLE_STORE_FORMATTED) &&\r
+         (VariableStore->State == VARIABLE_STORE_HEALTHY)\r
+       ) {\r
+      DEBUG((\r
+        EFI_D_INFO,\r
+        "Variable Store reserved at %p appears to be valid\n",\r
+        VariableStore\r
+        ));\r
+      FullyInitializeStore = FALSE;\r
+    }\r
+  }\r
+\r
   if (NULL == VariableStore) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  SetMem (VariableStore, FixedPcdGet32(PcdVariableStoreSize), 0xff);\r
+  if (FullyInitializeStore) {\r
+    SetMem (VariableStore, FixedPcdGet32(PcdVariableStoreSize), 0xff);\r
+  }\r
 \r
   //\r
   // Variable Specific Data\r
   //\r
   *VariableBase             = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
-  *LastVariableOffset       = sizeof (VARIABLE_STORE_HEADER);\r
+  InitializeLocationForLastVariableOffset (VariableStore, LastVariableOffset);\r
 \r
   CopyGuid (&VariableStore->Signature, &gEfiVariableGuid);\r
   VariableStore->Size       = FixedPcdGet32(PcdVariableStoreSize);\r
@@ -1376,11 +1485,7 @@ VariableCommonInitialize (
   //\r
   // Intialize volatile variable store\r
   //\r
-  Status = InitializeVariableStore (\r
-            &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,\r
-            &mVariableModuleGlobal->VolatileLastVariableOffset\r
-            );\r
-\r
+  Status = InitializeVariableStore (TRUE);\r
   if (EFI_ERROR (Status)) {\r
     FreePool(mVariableModuleGlobal);\r
     return Status;\r
@@ -1388,10 +1493,7 @@ VariableCommonInitialize (
   //\r
   // Intialize non volatile variable store\r
   //\r
-  Status = InitializeVariableStore (\r
-            &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
-            &mVariableModuleGlobal->NonVolatileLastVariableOffset\r
-            );\r
+  Status = InitializeVariableStore (FALSE);\r
 \r
   return Status;\r
 }\r