]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
Support load 64 bit image from 32 bit core.
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index 645818dfdf25f0f5e03973f35f22cb06c4674e50..5f128e9d6135b5b0a73e27d86ab0c63dce9b79a8 100644 (file)
@@ -3,7 +3,7 @@
   The common variable operation routines shared by DXE_RUNTIME variable \r
   module and DXE_SMM variable module.\r
   \r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials                          \r
 are licensed and made available under the terms and conditions of the BSD License         \r
 which accompanies this distribution.  The full text of the license may be found at        \r
@@ -615,40 +615,49 @@ Reclaim (
   CommonVariableTotalSize = 0;\r
   HwErrVariableTotalSize  = 0;\r
 \r
-  //\r
-  // Start Pointers for the variable.\r
-  //\r
-  Variable          = GetStartPointer (VariableStoreHeader);\r
-  MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
+  if (IsVolatile) {\r
+    //\r
+    // Start Pointers for the variable.\r
+    //\r
+    Variable          = GetStartPointer (VariableStoreHeader);\r
+    MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
 \r
-  while (IsValidVariableHeader (Variable)) {\r
-    NextVariable = GetNextVariablePtr (Variable);\r
-    if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&\r
-        Variable != UpdatingVariable &&\r
-        Variable != UpdatingInDeletedTransition\r
-       ) {\r
-      VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
-      MaximumBufferSize += VariableSize;\r
+    while (IsValidVariableHeader (Variable)) {\r
+      NextVariable = GetNextVariablePtr (Variable);\r
+      if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&\r
+          Variable != UpdatingVariable &&\r
+          Variable != UpdatingInDeletedTransition\r
+         ) {\r
+        VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+        MaximumBufferSize += VariableSize;\r
+      }\r
+\r
+      Variable = NextVariable;\r
     }\r
 \r
-    Variable = NextVariable;\r
-  }\r
+    if (NewVariable != NULL) {\r
+      //\r
+      // Add the new variable size.\r
+      //\r
+      MaximumBufferSize += NewVariableSize;\r
+    }\r
 \r
-  if (NewVariable != NULL) {\r
     //\r
-    // Add the new variable size.\r
+    // Reserve the 1 Bytes with Oxff to identify the\r
+    // end of the variable buffer.\r
     //\r
-    MaximumBufferSize += NewVariableSize;\r
-  }\r
-\r
-  //\r
-  // Reserve the 1 Bytes with Oxff to identify the \r
-  // end of the variable buffer. \r
-  // \r
-  MaximumBufferSize += 1;\r
-  ValidBuffer = AllocatePool (MaximumBufferSize);\r
-  if (ValidBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    MaximumBufferSize += 1;\r
+    ValidBuffer = AllocatePool (MaximumBufferSize);\r
+    if (ValidBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    //\r
+    // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache\r
+    // as the buffer to reduce SMRAM consumption for SMM variable driver.\r
+    //\r
+    MaximumBufferSize = mNvVariableCache->Size;\r
+    ValidBuffer = (UINT8 *) mNvVariableCache;\r
   }\r
 \r
   SetMem (ValidBuffer, MaximumBufferSize, 0xff);\r
@@ -770,6 +779,7 @@ Reclaim (
     //\r
     SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
     CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));\r
+    *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
     Status  = EFI_SUCCESS;\r
   } else {\r
     //\r
@@ -777,34 +787,37 @@ Reclaim (
     //\r
     Status = FtwVariableSpace (\r
               VariableBase,\r
-              ValidBuffer,\r
-              (UINTN) (CurrPtr - ValidBuffer)\r
+              (VARIABLE_STORE_HEADER *) ValidBuffer\r
               );\r
-    CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
-  }\r
-  if (!EFI_ERROR (Status)) {\r
-    *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
-    if (!IsVolatile) {\r
+    if (!EFI_ERROR (Status)) {\r
+      *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
       mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;\r
       mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;\r
-    }\r
-  } else {\r
-    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
-    while (IsValidVariableHeader (NextVariable)) {\r
-      VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
-      if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
-      } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
-      }\r
+    } else {\r
+      NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
+      while (IsValidVariableHeader (NextVariable)) {\r
+        VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
+        if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+          mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+        } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+          mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+        }\r
 \r
-      NextVariable = GetNextVariablePtr (NextVariable);\r
+        NextVariable = GetNextVariablePtr (NextVariable);\r
+      }\r
+      *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
     }\r
-    *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
   }\r
 \r
 Done:\r
-  FreePool (ValidBuffer);\r
+  if (IsVolatile) {\r
+    FreePool (ValidBuffer);\r
+  } else {\r
+    //\r
+    // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.\r
+    //\r
+    CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -1259,8 +1272,13 @@ VariableGetBestLanguage (
 \r
   @param[in] DataSize           Size of data. 0 means delete.\r
 \r
+  @retval EFI_SUCCESS           The update operation is successful or ignored.\r
+  @retval EFI_WRITE_PROTECTED   Update PlatformLangCodes/LangCodes at runtime.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough variable space to do the update operation.\r
+  @retval Others                Other errors happened during the update operation.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 AutoUpdateLangVariable (\r
   IN  CHAR16             *VariableName,\r
   IN  VOID               *Data,\r
@@ -1279,7 +1297,7 @@ AutoUpdateLangVariable (
   // Don't do updates for delete operation\r
   //\r
   if (DataSize == 0) {\r
-    return;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   SetLanguageCodes = FALSE;\r
@@ -1289,7 +1307,7 @@ AutoUpdateLangVariable (
     // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.\r
     //\r
     if (AtRuntime ()) {\r
-      return;\r
+      return EFI_WRITE_PROTECTED;\r
     }\r
 \r
     SetLanguageCodes = TRUE;\r
@@ -1319,7 +1337,7 @@ AutoUpdateLangVariable (
     // LangCodes is a volatile variable, so it can not be updated at runtime.\r
     //\r
     if (AtRuntime ()) {\r
-      return;\r
+      return EFI_WRITE_PROTECTED;\r
     }\r
 \r
     SetLanguageCodes = TRUE;\r
@@ -1363,11 +1381,13 @@ AutoUpdateLangVariable (
         //\r
         // Neither PlatformLang nor Lang is set, directly return\r
         //\r
-        return;\r
+        return EFI_SUCCESS;\r
       }\r
     }\r
   }\r
-  \r
+\r
+  Status = EFI_SUCCESS;\r
+\r
   //\r
   // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.\r
   //\r
@@ -1401,9 +1421,7 @@ AutoUpdateLangVariable (
         Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,\r
                                  ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
 \r
-        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));\r
-\r
-        ASSERT_EFI_ERROR(Status);\r
+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a: Status: %r\n", BestPlatformLang, BestLang, Status));\r
       }\r
     }\r
 \r
@@ -1435,11 +1453,12 @@ AutoUpdateLangVariable (
         Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang, \r
                                  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
+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));\r
       }\r
     }\r
   }\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -2476,7 +2495,13 @@ VariableServiceSetVariable (
   //\r
   // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
   //\r
-  AutoUpdateLangVariable (VariableName, Data, DataSize);\r
+  Status = AutoUpdateLangVariable (VariableName, Data, DataSize);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.\r
+    //\r
+    goto Done;\r
+  }\r
 \r
   Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);\r
 \r