Revision: 14378
          http://edk2.svn.sourceforge.net/edk2/?rev=14378&view=rev
Author:   niruiyu
Date:     2013-05-20 07:10:10 +0000 (Mon, 20 May 2013)
Log Message:
-----------
Add the EDKII_VARIABLE_LOCK_PROTOCOL implementation in SecurityPkg variable 
drivers.

Signed-off-by: Ruiyu Ni <[email protected]>
Reviewed-by: Star Zeng <[email protected]>

Modified Paths:
--------------
    trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
    trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
    trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
    
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
    trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
    trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
    
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
    
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf

Modified: trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
===================================================================
--- trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c  
2013-05-20 07:04:56 UTC (rev 14377)
+++ trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c  
2013-05-20 07:10:10 UTC (rev 14378)
@@ -35,14 +35,30 @@
 ///
 /// Define a memory cache that improves the search performance for a variable.
 ///
-VARIABLE_STORE_HEADER  *mNvVariableCache = NULL;
+VARIABLE_STORE_HEADER  *mNvVariableCache      = NULL;
 
 ///
 /// The memory entry used for variable statistics data.
 ///
-VARIABLE_INFO_ENTRY    *gVariableInfo    = NULL;
+VARIABLE_INFO_ENTRY    *gVariableInfo         = NULL;
 
+///
+/// The list to store the variables which cannot be set after the 
EFI_END_OF_DXE_EVENT_GROUP_GUID
+/// or EVT_GROUP_READY_TO_BOOT event.
+///
+LIST_ENTRY             mLockedVariableList    = INITIALIZE_LIST_HEAD_VARIABLE 
(mLockedVariableList);
 
+///
+/// The flag to indicate whether the platform has left the DXE phase of 
execution.
+///
+BOOLEAN                mEndOfDxe              = FALSE;
+
+///
+/// The flag to indicate whether the variable storage locking is enabled.
+///
+BOOLEAN                mEnableLocking         = TRUE;
+
+
 /**
   Routine used to track statistical information about variable usage.
   The data is stored in the EFI system table so it can be accessed later.
@@ -2312,6 +2328,58 @@
 }
 
 /**
+  Mark a variable that will become read-only after leaving the DXE phase of 
execution.
+
+  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
+  @param[in] VariableName  A pointer to the variable name that will be made 
read-only subsequently.
+  @param[in] VendorGuid    A pointer to the vendor GUID that will be made 
read-only subsequently.
+
+  @retval EFI_SUCCESS           The variable specified by the VariableName and 
the VendorGuid was marked
+                                as pending to be read-only.
+  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+                                Or VariableName is an empty string.
+  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or 
EFI_EVENT_GROUP_READY_TO_BOOT has
+                                already been signaled.
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock 
request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+  IN       CHAR16                       *VariableName,
+  IN       EFI_GUID                     *VendorGuid
+  )
+{
+  VARIABLE_ENTRY                  *Entry;
+
+  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (mEndOfDxe) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  Entry = AllocateRuntimePool (sizeof (*Entry) + StrSize (VariableName));
+  if (Entry == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName));
+
+  
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+  Entry->Name = (CHAR16 *) (Entry + 1);
+  StrCpy   (Entry->Name, VariableName);
+  CopyGuid (&Entry->Guid, VendorGuid);
+  InsertTailList (&mLockedVariableList, &Entry->Link);
+
+  ReleaseLockOnlyAtBootTime 
(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+  return EFI_SUCCESS;
+}
+
+/**
   This code checks if variable should be treated as read-only variable.
 
   @param[in]      VariableName            Name of the Variable.
@@ -2627,6 +2695,8 @@
   VARIABLE_HEADER                     *NextVariable;
   EFI_PHYSICAL_ADDRESS                Point;
   UINTN                               PayloadSize;
+  LIST_ENTRY                          *Link;
+  VARIABLE_ENTRY                      *Entry;
 
   //
   // Check input parameters.
@@ -2717,16 +2787,6 @@
     }
   }
 
-  if (AtRuntime ()) {
-    //
-    // HwErrRecSupport Global Variable identifies the level of hardware error 
record persistence
-    // support implemented by the platform. This variable is only modified by 
firmware and is read-only to the OS.
-    //
-    if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp 
(VariableName, L"HwErrRecSupport") == 0)) {
-      return EFI_WRITE_PROTECTED;
-    }
-  }
-
   
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
 
   //
@@ -2745,13 +2805,31 @@
     mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) 
NextVariable - (UINTN) Point;
   }
 
+  if (mEndOfDxe && mEnableLocking) {
+    //
+    // Treat the variables listed in the forbidden variable list as read-only 
after leaving DXE phase.
+    //
+    for ( Link = GetFirstNode (&mLockedVariableList)
+        ; !IsNull (&mLockedVariableList, Link)
+        ; Link = GetNextNode (&mLockedVariableList, Link)
+        ) {
+      Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
+      if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, 
VariableName) == 0)) {
+        Status = EFI_WRITE_PROTECTED;
+        DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after 
leaving DXE phase - %g:%s\n", VendorGuid, VariableName));
+        goto Done;
+      }
+    }
+  }
+
   //
   // Check whether the input variable is already existed.
   //
   Status = FindVariable (VariableName, VendorGuid, &Variable, 
&mVariableModuleGlobal->VariableGlobal, TRUE);
   if (!EFI_ERROR (Status)) {
     if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && 
AtRuntime ()) {
-      return EFI_WRITE_PROTECTED;
+      Status = EFI_WRITE_PROTECTED;
+      goto Done;
     }
   }
   
@@ -2776,6 +2854,7 @@
     Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, 
&Variable, Attributes);
   }
 
+Done:
   InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
   ReleaseLockOnlyAtBootTime 
(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
 

Modified: trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
===================================================================
--- trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h  
2013-05-20 07:04:56 UTC (rev 14377)
+++ trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h  
2013-05-20 07:10:10 UTC (rev 14378)
@@ -21,6 +21,7 @@
 #include <Protocol/FaultTolerantWrite.h>
 #include <Protocol/FirmwareVolumeBlock.h>
 #include <Protocol/Variable.h>
+#include <Protocol/VariableLock.h>
 #include <Library/PcdLib.h>
 #include <Library/HobLib.h>
 #include <Library/UefiDriverEntryPoint.h>
@@ -106,6 +107,12 @@
   VOID        *Data;
 } VARIABLE_CACHE_ENTRY;
 
+typedef struct {
+  EFI_GUID    Guid;
+  CHAR16      *Name;
+  LIST_ENTRY  Link;
+} VARIABLE_ENTRY;
+
 /**
   Flush the HOB variable to flash.
 
@@ -577,7 +584,30 @@
   OUT UINT64                 *RemainingVariableStorageSize,
   OUT UINT64                 *MaximumVariableSize
   );  
-  
+
+/**
+  Mark a variable that will become read-only after leaving the DXE phase of 
execution.
+
+  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
+  @param[in] VariableName  A pointer to the variable name that will be made 
read-only subsequently.
+  @param[in] VendorGuid    A pointer to the vendor GUID that will be made 
read-only subsequently.
+
+  @retval EFI_SUCCESS           The variable specified by the VariableName and 
the VendorGuid was marked
+                                as pending to be read-only.
+  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+                                Or VariableName is an empty string.
+  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or 
EFI_EVENT_GROUP_READY_TO_BOOT has
+                                already been signaled.
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock 
request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+  IN       CHAR16                       *VariableName,
+  IN       EFI_GUID                     *VendorGuid
+  );
+
 extern VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
 
 #endif

Modified: trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
===================================================================
--- trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c       
2013-05-20 07:04:56 UTC (rev 14377)
+++ trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c       
2013-05-20 07:10:10 UTC (rev 14378)
@@ -16,11 +16,13 @@
 #include "Variable.h"
 #include "AuthService.h"
 
-extern VARIABLE_STORE_HEADER        *mNvVariableCache;
-extern VARIABLE_INFO_ENTRY          *gVariableInfo;
-EFI_HANDLE                          mHandle                    = NULL;
-EFI_EVENT                           mVirtualAddressChangeEvent = NULL;
-EFI_EVENT                           mFtwRegistration           = NULL;
+extern VARIABLE_STORE_HEADER   *mNvVariableCache;
+extern VARIABLE_INFO_ENTRY     *gVariableInfo;
+EFI_HANDLE                     mHandle                    = NULL;
+EFI_EVENT                      mVirtualAddressChangeEvent = NULL;
+EFI_EVENT                      mFtwRegistration           = NULL;
+extern BOOLEAN                 mEndOfDxe;
+EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { 
VariableLockRequestToLock };
 
 /**
   Return TRUE if ExitBootServices () has been called.
@@ -257,13 +259,35 @@
   VOID                                    *Context
   )
 {
+  //
+  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event 
is not signaled.
+  //
+  mEndOfDxe = TRUE;
   ReclaimForOS ();
   if (FeaturePcdGet (PcdVariableCollectStatistics)) {
     gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, 
gVariableInfo);
   }
 }
 
+/**
+  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
 
+  This is a notification function registered on 
EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnEndOfDxe (
+  EFI_EVENT                               Event,
+  VOID                                    *Context
+  )
+{
+  mEndOfDxe = TRUE;
+}
+
 /**
   Fault Tolerant Write protocol notification event handler.
 
@@ -378,10 +402,19 @@
 {
   EFI_STATUS                            Status;
   EFI_EVENT                             ReadyToBootEvent;
+  EFI_EVENT                             EndOfDxeEvent;
 
   Status = VariableCommonInitialize ();
   ASSERT_EFI_ERROR (Status);
 
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mHandle,
+                  &gEdkiiVariableLockProtocolGuid,
+                  &mVariableLock,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
   SystemTable->RuntimeServices->GetVariable         = 
VariableServiceGetVariable;
   SystemTable->RuntimeServices->GetNextVariableName = 
VariableServiceGetNextVariableName;
   SystemTable->RuntimeServices->SetVariable         = 
VariableServiceSetVariable;
@@ -428,7 +461,21 @@
              NULL,
              &ReadyToBootEvent
              );
+  ASSERT_EFI_ERROR (Status);
 
+  //
+  // Register the event handling function to set the End Of DXE flag.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  OnEndOfDxe,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
   return EFI_SUCCESS;
 }
 

Modified: 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
===================================================================
--- 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf  
    2013-05-20 07:04:56 UTC (rev 14377)
+++ 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf  
    2013-05-20 07:10:10 UTC (rev 14378)
@@ -67,11 +67,12 @@
   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES
   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES
   gEfiFaultTolerantWriteProtocolGuid            ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid                ## ALWAYS_PRODUCES
 
 [Guids]
   gEfiAuthenticatedVariableGuid                 ## PRODUCES ## Configuration 
Table Guid
   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
-  gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event
+  gEfiEventVirtualAddressChangeGuid             ## CONSUMES ## Event
   gEfiCertTypeRsa2048Sha256Guid
   gEfiImageSecurityDatabaseGuid
   gEfiCertX509Guid
@@ -82,6 +83,7 @@
   gEfiSystemNvDataFvGuid                        ## CONSUMES
   gEfiCertDbGuid
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES ## Event
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize

Modified: trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
===================================================================
--- trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c       
2013-05-20 07:04:56 UTC (rev 14377)
+++ trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c       
2013-05-20 07:10:10 UTC (rev 14378)
@@ -29,6 +29,7 @@
 #include <Protocol/SmmFirmwareVolumeBlock.h>
 #include <Protocol/SmmFaultTolerantWrite.h>
 #include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmEndOfDxe.h>
 
 #include <Library/SmmServicesTableLib.h>
 
@@ -46,15 +47,61 @@
 EFI_GUID                                             mZeroGuid               = 
{0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
 UINT8                                                *mVariableBufferPayload = 
NULL;
 UINTN                                                
mVariableBufferPayloadSize;
+extern BOOLEAN                                       mEndOfDxe;
+extern BOOLEAN                                       mEnableLocking;
 
+/**
+
+  This code sets variable in storage blocks (Volatile or Non-Volatile).
+
+  @param VariableName                     Name of Variable to be found.
+  @param VendorGuid                       Variable vendor GUID.
+  @param Attributes                       Attribute value of the variable found
+  @param DataSize                         Size of Data found. If size is less 
than the
+                                          data, this value contains the 
required size.
+  @param Data                             Data pointer.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SUCCESS                     Set successfully.
+  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
+  @return EFI_NOT_FOUND                   Not found.
+  @return EFI_WRITE_PROTECTED             Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmVariableSetVariable (
+  IN CHAR16                  *VariableName,
+  IN EFI_GUID                *VendorGuid,
+  IN UINT32                  Attributes,
+  IN UINTN                   DataSize,
+  IN VOID                    *Data
+  )
+{
+  EFI_STATUS                 Status;
+
+  //
+  // Disable write protection when the calling SetVariable() through 
EFI_SMM_VARIABLE_PROTOCOL.
+  //
+  mEnableLocking = FALSE;
+  Status         = VariableServiceSetVariable (
+                     VariableName,
+                     VendorGuid,
+                     Attributes,
+                     DataSize,
+                     Data
+                     );
+  mEnableLocking = TRUE;
+  return Status;
+}
+
 EFI_SMM_VARIABLE_PROTOCOL      gSmmVariable = {
   VariableServiceGetVariable,
   VariableServiceGetNextVariableName,
-  VariableServiceSetVariable,
+  SmmVariableSetVariable,
   VariableServiceQueryVariableInfo
 };
 
-
 /**
   Return TRUE if ExitBootServices () has been called.
   
@@ -455,6 +502,7 @@
   SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME  *GetNextVariableName;
   SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO     *QueryVariableInfo;
   VARIABLE_INFO_ENTRY                              *VariableInfo;
+  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE           *VariableToLock;
   UINTN                                            InfoSize;
   UINTN                                            NameBufferSize;
   UINTN                                            CommBufferPayloadSize;
@@ -641,6 +689,7 @@
       break;
 
     case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
+      mEndOfDxe = TRUE;
       if (AtRuntime()) {
         Status = EFI_UNSUPPORTED;
         break;
@@ -673,6 +722,19 @@
       *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
       break;
 
+    case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:
+      if (mEndOfDxe) {
+        Status = EFI_ACCESS_DENIED;
+      } else {
+        VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) 
SmmVariableFunctionHeader->Data;
+        Status = VariableLockRequestToLock (
+                   NULL,
+                   VariableToLock->Name,
+                   &VariableToLock->Guid
+                   );
+      }
+      break;
+
     default:
       Status = EFI_UNSUPPORTED;
   }
@@ -683,7 +745,29 @@
   return EFI_SUCCESS;
 }
 
+/**
+  SMM END_OF_DXE protocol notification event handler.
 
+  @param  Protocol   Points to the protocol's unique identifier
+  @param  Interface  Points to the interface instance
+  @param  Handle     The handle on which the interface was installed
+
+  @retval EFI_SUCCESS   SmmEndOfDxeCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmEndOfDxeCallback (
+  IN CONST EFI_GUID                       *Protocol,
+  IN VOID                                 *Interface,
+  IN EFI_HANDLE                           Handle
+  )
+{
+  DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
+  mEndOfDxe = TRUE;
+  return EFI_SUCCESS;
+}
+
 /**
   SMM Fault Tolerant Write protocol notification event handler.
 
@@ -779,6 +863,7 @@
   VOID                                    *SmmFtwRegistration;
   EFI_SMM_ACCESS2_PROTOCOL                *SmmAccess;
   UINTN                                   Size;
+  VOID                                    *SmmEndOfDxeRegistration;
 
   //
   // Variable initialize.
@@ -849,6 +934,16 @@
   ASSERT_EFI_ERROR (Status);
  
   //
+  // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gEfiSmmEndOfDxeProtocolGuid,
+                    SmmEndOfDxeCallback,
+                    &SmmEndOfDxeRegistration
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
   // Register FtwNotificationEvent () notify function.
   // 
   Status = gSmst->SmmRegisterProtocolNotify (

Modified: 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
===================================================================
--- trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf     
2013-05-20 07:04:56 UTC (rev 14377)
+++ trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf     
2013-05-20 07:10:10 UTC (rev 14378)
@@ -73,6 +73,7 @@
   gEfiSmmVariableProtocolGuid                   ## ALWAYS_PRODUCES
   gEfiSmmFaultTolerantWriteProtocolGuid         ## SOMETIMES_CONSUMES
   gEfiSmmAccess2ProtocolGuid                    ## ALWAYS_CONSUMES
+  gEfiSmmEndOfDxeProtocolGuid                   ## ALWAYS_CONSUMES
 
 [Guids]
   gEfiAuthenticatedVariableGuid                 ## PRODUCES ## Configuration 
Table Guid

Modified: 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
===================================================================
--- 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c 
    2013-05-20 07:04:56 UTC (rev 14377)
+++ 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c 
    2013-05-20 07:10:10 UTC (rev 14378)
@@ -29,6 +29,7 @@
 #include <Protocol/Variable.h>
 #include <Protocol/SmmCommunication.h>
 #include <Protocol/SmmVariable.h>
+#include <Protocol/VariableLock.h>
 
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiRuntimeServicesTableLib.h>
@@ -54,6 +55,7 @@
 UINTN                            mVariableBufferSize;
 UINTN                            mVariableBufferPayloadSize;
 EFI_LOCK                         mVariableServicesLock;
+EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
 
 /**
   Acquires lock only at boot time. Simply returns at runtime.
@@ -173,7 +175,74 @@
   return  SmmVariableFunctionHeader->ReturnStatus;
 }
 
+/**
+  Mark a variable that will become read-only after leaving the DXE phase of 
execution.
 
+  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
+  @param[in] VariableName  A pointer to the variable name that will be made 
read-only subsequently.
+  @param[in] VendorGuid    A pointer to the vendor GUID that will be made 
read-only subsequently.
+
+  @retval EFI_SUCCESS           The variable specified by the VariableName and 
the VendorGuid was marked
+                                as pending to be read-only.
+  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+                                Or VariableName is an empty string.
+  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or 
EFI_EVENT_GROUP_READY_TO_BOOT has
+                                already been signaled.
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock 
request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+  IN       CHAR16                       *VariableName,
+  IN       EFI_GUID                     *VendorGuid
+  )
+{
+  EFI_STATUS                                Status;
+  UINTN                                     VariableNameSize;
+  UINTN                                     PayloadSize;
+  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE    *VariableToLock;
+
+  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  VariableNameSize = StrSize (VariableName);
+
+  //
+  // If VariableName exceeds SMM payload limit. Return failure
+  //
+  if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
+
+  //
+  // Init the communicate buffer. The buffer data size is:
+  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + 
PayloadSize.
+  //
+  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + 
VariableNameSize;
+  Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, 
SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+  ASSERT (VariableToLock != NULL);
+
+  CopyGuid (&VariableToLock->Guid, VendorGuid);
+  VariableToLock->NameSize = VariableNameSize;
+  CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);
+
+  //
+  // Send data to SMM.
+  //
+  Status = SendCommunicateBuffer (PayloadSize);
+
+Done:
+  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
+  return Status;
+}
+
 /**
   This code finds variable in storage blocks (Volatile or Non-Volatile).
 
@@ -740,6 +809,7 @@
   IN EFI_SYSTEM_TABLE                       *SystemTable
   )
 {
+  EFI_STATUS                                Status;
   VOID                                      *SmmVariableRegistration;
   VOID                                      *SmmVariableWriteRegistration;
   EFI_EVENT                                 OnReadyToBootEvent;
@@ -747,6 +817,15 @@
 
   EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
 
+  mVariableLock.RequestToLock = VariableLockRequestToLock;
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mHandle,
+                  &gEdkiiVariableLockProtocolGuid,
+                  &mVariableLock,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
   //
   // Smm variable service is ready
   //

Modified: 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf
===================================================================
--- 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf
   2013-05-20 07:04:56 UTC (rev 14377)
+++ 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf
   2013-05-20 07:10:10 UTC (rev 14378)
@@ -59,6 +59,7 @@
   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES  
   gEfiSmmCommunicationProtocolGuid
   gEfiSmmVariableProtocolGuid
+  gEdkiiVariableLockProtocolGuid                ## ALWAYS_PRODUCES
 
 [Guids]
   gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to