]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c
Change the TPL lock level to EFI_TPL_NOTIFY. Variable Service is called in ResetSyste...
[mirror_edk2.git] / EdkModulePkg / Universal / EmuVariable / RuntimeDxe / EmuVariable.c
index 093705c60dd60c00a4989be47909ce6be1e6260f..8695b7526a699d734d8faa8dfbec9b0632861744 100644 (file)
@@ -1,6 +1,6 @@
 /*++\r
 \r
-Copyright (c) 2006, Intel Corporation\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
 All rights reserved. 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
@@ -26,83 +26,39 @@ Revision History
 //\r
 ESAL_VARIABLE_GLOBAL  *mVariableModuleGlobal;\r
 \r
-UINT32\r
-EFIAPI\r
-ArrayLength (\r
-  IN CHAR16 *String\r
+//\r
+// This is a temperary function which will be removed \r
+// when EfiAcquireLock in UefiLib can handle the\r
+// the call in UEFI Runtimer driver in RT phase.\r
+//\r
+STATIC\r
+VOID\r
+AcquireLockOnlyAtBootTime (\r
+  IN EFI_LOCK  *Lock\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Determine the length of null terminated char16 array.\r
-\r
-Arguments:\r
-\r
-  String    Null-terminated CHAR16 array pointer.\r
-\r
-Returns:\r
-\r
-  UINT32    Number of bytes in the string, including the double NULL at the end;\r
-\r
---*/\r
 {\r
-  UINT32  Count;\r
-\r
-  if (NULL == String) {\r
-    return 0;\r
+  if (!EfiAtRuntime ()) {\r
+    EfiAcquireLock (Lock);\r
   }\r
-\r
-  Count = 0;\r
-\r
-  while (0 != String[Count]) {\r
-    Count++;\r
-  }\r
-\r
-  return (Count * 2) + 2;\r
 }\r
 \r
-VARIABLE_STORE_STATUS\r
-EFIAPI\r
-GetVariableStoreStatus (\r
-  IN VARIABLE_STORE_HEADER *VarStoreHeader\r
+//\r
+// This is a temperary function which will be removed \r
+// when EfiAcquireLock in UefiLib can handle the\r
+// the call in UEFI Runtimer driver in RT phase.\r
+//\r
+STATIC\r
+VOID\r
+ReleaseLockOnlyAtBootTime (\r
+  IN EFI_LOCK  *Lock\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This code gets the pointer to the variable name.\r
-\r
-Arguments:\r
-\r
-  VarStoreHeader  Pointer to the Variable Store Header.\r
-\r
-Returns:\r
-\r
-  EfiHealthy    Variable store is healthy\r
-  EfiRaw        Variable store is raw\r
-  EfiInvalid    Variable store is invalid\r
-\r
---*/\r
 {\r
-  if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
-      VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
-      VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
-      ) {\r
-\r
-    return EfiValid;\r
-  } else if (VarStoreHeader->Signature == 0xffffffff &&\r
-           VarStoreHeader->Size == 0xffffffff &&\r
-           VarStoreHeader->Format == 0xff &&\r
-           VarStoreHeader->State == 0xff\r
-          ) {\r
-\r
-    return EfiRaw;\r
-  } else {\r
-    return EfiInvalid;\r
+  if (!EfiAtRuntime ()) {\r
+    EfiReleaseLock (Lock);\r
   }\r
 }\r
 \r
+STATIC\r
 UINT8 *\r
 EFIAPI\r
 GetVariableDataPtr (\r
@@ -133,6 +89,7 @@ Returns:
   return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
 }\r
 \r
+STATIC\r
 VARIABLE_HEADER *\r
 EFIAPI\r
 GetNextVariablePtr (\r
@@ -173,6 +130,7 @@ Returns:
   return VarHeader;\r
 }\r
 \r
+STATIC\r
 VARIABLE_HEADER *\r
 EFIAPI\r
 GetEndPointer (\r
@@ -200,6 +158,7 @@ Returns:
   return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size);\r
 }\r
 \r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 FindVariable (\r
@@ -233,6 +192,13 @@ 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(&Global->VariableServicesLock);\r
+\r
   //\r
   // 0: Non-Volatile, 1: Volatile\r
   //\r
@@ -265,7 +231,7 @@ Returns:
             return EFI_SUCCESS;\r
           } else {\r
             if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
-              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) {\r
+              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {\r
                 PtrTrack->CurrPtr   = Variable[Index];\r
                 PtrTrack->Volatile  = (BOOLEAN) Index;\r
                 return EFI_SUCCESS;\r
@@ -329,24 +295,35 @@ Returns:
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Done;\r
   }\r
   //\r
   // Get data size\r
   //\r
   VarDataSize = Variable.CurrPtr->DataSize;\r
   if (*DataSize >= VarDataSize) {\r
+    if (Data == NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
     CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
-    if (Attributes) {\r
+    if (Attributes != NULL) {\r
       *Attributes = Variable.CurrPtr->Attributes;\r
     }\r
 \r
     *DataSize = VarDataSize;\r
-    return EFI_SUCCESS;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
   } else {\r
     *DataSize = VarDataSize;\r
-    return EFI_BUFFER_TOO_SMALL;\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Done;\r
   }\r
+\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -389,7 +366,7 @@ Returns:
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Done;\r
   }\r
 \r
   while (TRUE) {\r
@@ -409,7 +386,8 @@ Returns:
         Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
         Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
       } else {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Variable.CurrPtr = Variable.StartPtr;\r
@@ -440,12 +418,15 @@ Returns:
         }\r
 \r
         *VariableNameSize = VarNameSize;\r
-        return Status;\r
+        goto Done;\r
       }\r
     }\r
   }\r
 \r
-  return EFI_NOT_FOUND;\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  return Status;\r
\r
 }\r
 \r
 EFI_STATUS\r
@@ -501,45 +482,54 @@ Returns:
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Status == EFI_INVALID_PARAMETER) {\r
-    return Status;\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_VARIABLE_SIZE (1024) bytes.\r
-  //\r
-  else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  //  Make sure if runtime bit is set, boot service bit is set also\r
-  //\r
-  else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS\r
+    goto Done;\r
+  } else if (!EFI_ERROR (Status) && Variable.Volatile && EfiAtRuntime()) {\r
+    //\r
+    // If EfiAtRuntime and the variable is Volatile and Runtime Access,  \r
+    // the volatile is ReadOnly, and SetVariable should be aborted and \r
+    // return EFI_WRITE_PROTECTED.\r
+    //\r
+    Status = EFI_WRITE_PROTECTED;\r
+    goto Done;\r
+  } else if (sizeof (VARIABLE_HEADER) + (StrSize (VariableName) + DataSize) > MAX_VARIABLE_SIZE) {\r
+    //\r
+    //  The size of the VariableName, including the Unicode Null in bytes plus\r
+    //  the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS\r
           ) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Runtime but Attribute is not Runtime\r
-  //\r
-  else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Cannot set volatile variable in Runtime\r
-  //\r
-  else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Setting a data variable with no access, or zero DataSize attributes\r
-  // specified causes it to be deleted.\r
-  //\r
-  else if (DataSize == 0 || Attributes == 0) {\r
+    //\r
+    //  Make sure if runtime bit is set, boot service bit is set also\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+    //\r
+    // Runtime but Attribute is not Runtime\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
+    //\r
+    // Cannot set volatile variable in Runtime\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
+    //\r
+    // Setting a data variable with no access, or zero DataSize attributes\r
+    // specified causes it to be deleted.\r
+    //\r
     if (!EFI_ERROR (Status)) {\r
       Variable.CurrPtr->State &= VAR_DELETED;\r
-      return EFI_SUCCESS;\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
     }\r
 \r
-    return EFI_NOT_FOUND;\r
+    Status = EFI_NOT_FOUND;\r
+    goto Done;\r
   } else {\r
     if (!EFI_ERROR (Status)) {\r
       //\r
@@ -549,7 +539,8 @@ Returns:
       if (Variable.CurrPtr->DataSize == DataSize &&\r
           !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)\r
             ) {\r
-        return EFI_SUCCESS;\r
+        Status = EFI_SUCCESS;\r
+        goto Done;\r
       } else if (Variable.CurrPtr->State == VAR_ADDED) {\r
         //\r
         // Mark the old variable as in delete transition\r
@@ -561,7 +552,7 @@ Returns:
     // Create a new variable and copy the data.\r
     //\r
     VarNameOffset = sizeof (VARIABLE_HEADER);\r
-    VarNameSize   = ArrayLength (VariableName);\r
+    VarNameSize   = StrSize (VariableName);\r
     VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
     VarSize       = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
 \r
@@ -569,20 +560,23 @@ Returns:
       if ((UINT32) (VarSize +*NonVolatileOffset) >\r
             ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
             ) {\r
-        return EFI_OUT_OF_RESOURCES;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
       }\r
 \r
       NextVariable        = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);\r
       *NonVolatileOffset  = *NonVolatileOffset + VarSize;\r
     } else {\r
       if (EfiAtRuntime ()) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       if ((UINT32) (VarSize +*VolatileOffset) >\r
             ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
             ) {\r
-        return EFI_OUT_OF_RESOURCES;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
       }\r
 \r
       NextVariable    = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);\r
@@ -622,7 +616,10 @@ Returns:
     }\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  Status = EFI_SUCCESS;\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  return Status;\r
 }\r
 \r
 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
@@ -688,8 +685,15 @@ Returns:
     //   Make sure RT Attribute is set if we are in Runtime phase.\r
     //\r
     return EFI_INVALID_PARAMETER;\r
+  } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
+    //\r
+    // Cannot Query volatile variable in Runtime\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+  \r
   if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
     //\r
     // Query is Volatile related.\r
@@ -740,10 +744,12 @@ Returns:
     Variable = NextVariable;\r
   }\r
 \r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
   return EFI_SUCCESS;\r
 }\r
 #endif\r
 \r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 InitializeVariableStore (\r
@@ -819,11 +825,14 @@ Returns:
   if (NULL == mVariableModuleGlobal) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
+  EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, EFI_TPL_NOTIFY);\r
+  \r
   //\r
   // Intialize volatile variable store\r
   //\r
   Status = InitializeVariableStore (\r
-            &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase,\r
+            &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,\r
             &mVariableModuleGlobal->VolatileLastVariableOffset\r
             );\r
 \r
@@ -834,7 +843,7 @@ Returns:
   // Intialize non volatile variable store\r
   //\r
   Status = InitializeVariableStore (\r
-            &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,\r
+            &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
             &mVariableModuleGlobal->NonVolatileLastVariableOffset\r
             );\r
 \r