]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
MdeModulePkg Variable: Abstract VariableWriteServiceInitializeDxe/Smm
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index fca8d5380924449533b19572fef040d2d8ec9b60..424f92a537577937ab69deef4339cc406bc05216 100644 (file)
@@ -16,7 +16,7 @@
   VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,\r
   integer overflow. It should also check attribute to avoid authentication bypass.\r
 \r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
 (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
@@ -262,13 +262,12 @@ UpdateVariableStore (
   UINT8                       *CurrBuffer;\r
   EFI_LBA                     LbaNumber;\r
   UINTN                       Size;\r
-  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;\r
   VARIABLE_STORE_HEADER       *VolatileBase;\r
   EFI_PHYSICAL_ADDRESS        FvVolHdr;\r
   EFI_PHYSICAL_ADDRESS        DataPtr;\r
   EFI_STATUS                  Status;\r
 \r
-  FwVolHeader = NULL;\r
+  FvVolHdr    = 0;\r
   DataPtr     = DataPtrIndex;\r
 \r
   //\r
@@ -281,7 +280,6 @@ UpdateVariableStore (
     Status = Fvb->GetPhysicalAddress(Fvb, &FvVolHdr);\r
     ASSERT_EFI_ERROR (Status);\r
 \r
-    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);\r
     //\r
     // Data Pointer should point to the actual Address where data is to be\r
     // written.\r
@@ -290,7 +288,7 @@ UpdateVariableStore (
       DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
     }\r
 \r
-    if ((DataPtr + DataSize) > ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {\r
+    if ((DataPtr + DataSize) > (FvVolHdr + mNvFvHeaderCache->FvLength)) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
   } else {\r
@@ -317,7 +315,7 @@ UpdateVariableStore (
   //\r
   // If we are here we are dealing with Non-Volatile Variables.\r
   //\r
-  LinearOffset  = (UINTN) FwVolHeader;\r
+  LinearOffset  = (UINTN) FvVolHdr;\r
   CurrWritePtr  = (UINTN) DataPtr;\r
   CurrWriteSize = DataSize;\r
   CurrBuffer    = Buffer;\r
@@ -681,7 +679,7 @@ GetStartPointer (
   )\r
 {\r
   //\r
-  // The end of variable store.\r
+  // The start of variable store.\r
   //\r
   return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);\r
 }\r
@@ -2462,6 +2460,8 @@ UpdateVariable (
         if (Variable->CurrPtr != NULL) {\r
           if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) CacheVariable->CurrPtr)->TimeStamp), TimeStamp)) {\r
             CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));\r
+          } else {\r
+            CopyMem (&AuthVariable->TimeStamp, &(((AUTHENTICATED_VARIABLE_HEADER *) CacheVariable->CurrPtr)->TimeStamp), sizeof (EFI_TIME));\r
           }\r
         }\r
       }\r
@@ -2737,7 +2737,7 @@ UpdateVariable (
       }\r
     }\r
 \r
-    State = Variable->CurrPtr->State;\r
+    State = CacheVariable->CurrPtr->State;\r
     State &= VAR_DELETED;\r
 \r
     Status = UpdateVariableStore (\r
@@ -3198,6 +3198,12 @@ VariableServiceSetVariable (
       ((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->AuthInfo.Hdr.dwLength < OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {\r
       return EFI_SECURITY_VIOLATION;\r
     }\r
+    //\r
+    // The VariableSpeculationBarrier() call here is to ensure the above sanity\r
+    // check for the EFI_VARIABLE_AUTHENTICATION_2 descriptor has been completed\r
+    // before the execution of subsequent codes.\r
+    //\r
+    VariableSpeculationBarrier ();\r
     PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
   } else {\r
     PayloadSize = DataSize;\r
@@ -3226,14 +3232,44 @@ VariableServiceSetVariable (
     //\r
     if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
       if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxAuthVariableSize - GetVariableHeaderSize ()) {\r
+        DEBUG ((DEBUG_ERROR,\r
+          "%a: Failed to set variable '%s' with Guid %g\n",\r
+          __FUNCTION__, VariableName, VendorGuid));\r
+        DEBUG ((DEBUG_ERROR,\r
+          "NameSize(0x%x) + PayloadSize(0x%x) > "\r
+          "MaxAuthVariableSize(0x%x) - HeaderSize(0x%x)\n",\r
+          StrSize (VariableName), PayloadSize,\r
+          mVariableModuleGlobal->MaxAuthVariableSize,\r
+          GetVariableHeaderSize ()\r
+          ));\r
         return EFI_INVALID_PARAMETER;\r
       }\r
     } else if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
       if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxVariableSize - GetVariableHeaderSize ()) {\r
+        DEBUG ((DEBUG_ERROR,\r
+          "%a: Failed to set variable '%s' with Guid %g\n",\r
+          __FUNCTION__, VariableName, VendorGuid));\r
+        DEBUG ((DEBUG_ERROR,\r
+          "NameSize(0x%x) + PayloadSize(0x%x) > "\r
+          "MaxVariableSize(0x%x) - HeaderSize(0x%x)\n",\r
+          StrSize (VariableName), PayloadSize,\r
+          mVariableModuleGlobal->MaxVariableSize,\r
+          GetVariableHeaderSize ()\r
+          ));\r
         return EFI_INVALID_PARAMETER;\r
       }\r
     } else {\r
       if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxVolatileVariableSize - GetVariableHeaderSize ()) {\r
+        DEBUG ((DEBUG_ERROR,\r
+          "%a: Failed to set variable '%s' with Guid %g\n",\r
+          __FUNCTION__, VariableName, VendorGuid));\r
+        DEBUG ((DEBUG_ERROR,\r
+          "NameSize(0x%x) + PayloadSize(0x%x) > "\r
+          "MaxVolatileVariableSize(0x%x) - HeaderSize(0x%x)\n",\r
+          StrSize (VariableName), PayloadSize,\r
+          mVariableModuleGlobal->MaxVolatileVariableSize,\r
+          GetVariableHeaderSize ()\r
+          ));\r
         return EFI_INVALID_PARAMETER;\r
       }\r
     }\r
@@ -3692,9 +3728,9 @@ GetMaxVariableSize (
 }\r
 \r
 /**\r
-  Init non-volatile variable store.\r
+  Init real non-volatile variable store.\r
 \r
-  @param[out] NvFvHeader        Output pointer to non-volatile FV header address.\r
+  @param[out] VariableStoreBase Output pointer to real non-volatile variable store base.\r
 \r
   @retval EFI_SUCCESS           Function successfully executed.\r
   @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
@@ -3702,16 +3738,13 @@ GetMaxVariableSize (
 \r
 **/\r
 EFI_STATUS\r
-InitNonVolatileVariableStore (\r
-  OUT EFI_FIRMWARE_VOLUME_HEADER    **NvFvHeader\r
+InitRealNonVolatileVariableStore (\r
+  OUT EFI_PHYSICAL_ADDRESS              *VariableStoreBase\r
   )\r
 {\r
   EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;\r
-  VARIABLE_HEADER                       *Variable;\r
-  VARIABLE_HEADER                       *NextVariable;\r
-  EFI_PHYSICAL_ADDRESS                  VariableStoreBase;\r
-  UINT64                                VariableStoreLength;\r
-  UINTN                                 VariableSize;\r
+  VARIABLE_STORE_HEADER                 *VariableStore;\r
+  UINT32                                VariableStoreLength;\r
   EFI_HOB_GUID_TYPE                     *GuidHob;\r
   EFI_PHYSICAL_ADDRESS                  NvStorageBase;\r
   UINT8                                 *NvStorageData;\r
@@ -3737,10 +3770,9 @@ InitNonVolatileVariableStore (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-  if (NvStorageBase == 0) {\r
-    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  }\r
+  NvStorageBase = NV_STORAGE_VARIABLE_BASE;\r
+  ASSERT (NvStorageBase != 0);\r
+\r
   //\r
   // Copy NV storage data to the memory buffer.\r
   //\r
@@ -3790,24 +3822,23 @@ InitNonVolatileVariableStore (
     return EFI_VOLUME_CORRUPTED;\r
   }\r
 \r
-  VariableStoreBase = (UINTN) FvHeader + FvHeader->HeaderLength;\r
+  VariableStore = (VARIABLE_STORE_HEADER *) ((UINTN) FvHeader + FvHeader->HeaderLength);\r
   VariableStoreLength = NvStorageSize - FvHeader->HeaderLength;\r
+  ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);\r
+  ASSERT (VariableStore->Size == VariableStoreLength);\r
 \r
-  mNvFvHeaderCache = FvHeader;\r
-  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
-  mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;\r
-  if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {\r
+  //\r
+  // Check if the Variable Store header is not corrupted\r
+  //\r
+  if (GetVariableStoreStatus (VariableStore) != EfiValid) {\r
     FreePool (NvStorageData);\r
-    mNvFvHeaderCache = NULL;\r
-    mNvVariableCache = NULL;\r
     DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));\r
     return EFI_VOLUME_CORRUPTED;\r
   }\r
-  ASSERT(mNvVariableCache->Size == VariableStoreLength);\r
 \r
-  ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);\r
+  mNvFvHeaderCache = FvHeader;\r
 \r
-  mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));\r
+  *VariableStoreBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
 \r
   HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);\r
   MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);\r
@@ -3842,14 +3873,45 @@ InitNonVolatileVariableStore (
   //\r
   ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));\r
 \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Init non-volatile variable store.\r
+\r
+  @retval EFI_SUCCESS           Function successfully executed.\r
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
+  @retval EFI_VOLUME_CORRUPTED  Variable Store or Firmware Volume for Variable Store is corrupted.\r
+\r
+**/\r
+EFI_STATUS\r
+InitNonVolatileVariableStore (\r
+  VOID\r
+  )\r
+{\r
+  VARIABLE_HEADER                       *Variable;\r
+  VARIABLE_HEADER                       *NextVariable;\r
+  EFI_PHYSICAL_ADDRESS                  VariableStoreBase;\r
+  UINTN                                 VariableSize;\r
+  EFI_STATUS                            Status;\r
+\r
+  Status = InitRealNonVolatileVariableStore (&VariableStoreBase);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
+  mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;\r
+  mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));\r
+\r
   mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);\r
   mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);\r
 \r
   //\r
   // Parse non-volatile variable data and get last variable offset.\r
   //\r
-  Variable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);\r
-  while (IsValidVariableHeader (Variable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) {\r
+  Variable  = GetStartPointer (mNvVariableCache);\r
+  while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCache))) {\r
     NextVariable = GetNextVariablePtr (Variable);\r
     VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
     if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
@@ -3860,9 +3922,8 @@ InitNonVolatileVariableStore (
 \r
     Variable = NextVariable;\r
   }\r
-  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) Variable - (UINTN) VariableStoreBase;\r
+  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) Variable - (UINTN) mNvVariableCache;\r
 \r
-  *NvFvHeader = FvHeader;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -3963,7 +4024,7 @@ FlushHobVariableToFlash (
 }\r
 \r
 /**\r
-  Initializes variable write service after FTW was ready.\r
+  Initializes variable write service.\r
 \r
   @retval EFI_SUCCESS          Function successfully executed.\r
   @retval Others               Fail to initialize the variable service.\r
@@ -3977,23 +4038,10 @@ VariableWriteServiceInitialize (
   EFI_STATUS                      Status;\r
   UINTN                           Index;\r
   UINT8                           Data;\r
-  EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
-  EFI_PHYSICAL_ADDRESS            NvStorageBase;\r
   VARIABLE_ENTRY_PROPERTY         *VariableEntry;\r
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
-  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-  if (NvStorageBase == 0) {\r
-    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  }\r
-  VariableStoreBase = NvStorageBase + (mNvFvHeaderCache->HeaderLength);\r
-\r
-  //\r
-  // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
-  //\r
-  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
-\r
   //\r
   // Check if the free area is really free.\r
   //\r
@@ -4173,7 +4221,7 @@ ConvertNormalVarStorageToAuthVarStorage (
 /**\r
   Get HOB variable store.\r
 \r
-  @param[out] VariableGuid      NV variable store signature.\r
+  @param[in] VariableGuid       NV variable store signature.\r
 \r
   @retval EFI_SUCCESS           Function successfully executed.\r
   @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
@@ -4189,6 +4237,30 @@ GetHobVariableStore (
   EFI_HOB_GUID_TYPE             *GuidHob;\r
   BOOLEAN                       NeedConvertNormalToAuth;\r
 \r
+  //\r
+  // Make sure there is no more than one Variable HOB.\r
+  //\r
+  DEBUG_CODE (\r
+    GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);\r
+    if (GuidHob != NULL) {\r
+      if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {\r
+        DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));\r
+        ASSERT (FALSE);\r
+      } else if (GetFirstGuidHob (&gEfiVariableGuid) != NULL) {\r
+        DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable HOBs\n"));\r
+        ASSERT (FALSE);\r
+      }\r
+    } else {\r
+      GuidHob = GetFirstGuidHob (&gEfiVariableGuid);\r
+      if (GuidHob != NULL) {\r
+        if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {\r
+          DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"));\r
+          ASSERT (FALSE);\r
+        }\r
+      }\r
+    }\r
+  );\r
+\r
   //\r
   // Combinations supported:\r
   // 1. Normal NV variable store +\r
@@ -4243,7 +4315,6 @@ VariableCommonInitialize (
   VARIABLE_STORE_HEADER           *VolatileVariableStore;\r
   UINTN                           ScratchSize;\r
   EFI_GUID                        *VariableGuid;\r
-  EFI_FIRMWARE_VOLUME_HEADER      *NvFvHeader;\r
 \r
   //\r
   // Allocate runtime memory for variable driver global structure.\r
@@ -4258,8 +4329,7 @@ VariableCommonInitialize (
   //\r
   // Init non-volatile variable store.\r
   //\r
-  NvFvHeader = NULL;\r
-  Status = InitNonVolatileVariableStore (&NvFvHeader);\r
+  Status = InitNonVolatileVariableStore ();\r
   if (EFI_ERROR (Status)) {\r
     FreePool (mVariableModuleGlobal);\r
     return Status;\r
@@ -4287,7 +4357,9 @@ VariableCommonInitialize (
   //\r
   Status = GetHobVariableStore (VariableGuid);\r
   if (EFI_ERROR (Status)) {\r
-    FreePool (NvFvHeader);\r
+    if (mNvFvHeaderCache != NULL) {\r
+      FreePool (mNvFvHeaderCache);\r
+    }\r
     FreePool (mVariableModuleGlobal);\r
     return Status;\r
   }\r
@@ -4306,7 +4378,9 @@ VariableCommonInitialize (
     if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
       FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
     }\r
-    FreePool (NvFvHeader);\r
+    if (mNvFvHeaderCache != NULL) {\r
+      FreePool (mNvFvHeaderCache);\r
+    }\r
     FreePool (mVariableModuleGlobal);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r