Revision: 14372
          http://edk2.svn.sourceforge.net/edk2/?rev=14372&view=rev
Author:   niruiyu
Date:     2013-05-17 03:49:35 +0000 (Fri, 17 May 2013)
Log Message:
-----------
Add EDKII_VARIABLE_LOCK_PROTOCOL and the implementation in MdeModulePkg 
variable drivers.
Add code in BdsDxe driver to call the protocol to mark the read-only variables 
defined in the UEFI Spec.

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

Modified Paths:
--------------
    trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h
    trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
    trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
    trunk/edk2/MdeModulePkg/Include/Guid/SmmVariableCommon.h
    trunk/edk2/MdeModulePkg/MdeModulePkg.dec
    trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
    trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
    trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
    trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
    trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
    trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
    
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
    
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf

Added Paths:
-----------
    trunk/edk2/MdeModulePkg/Include/Protocol/VariableLock.h

Modified: trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h
===================================================================
--- trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h   2013-05-17 
01:12:34 UTC (rev 14371)
+++ trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h   2013-05-17 
03:49:35 UTC (rev 14372)
@@ -1,7 +1,7 @@
 /** @file
   Head file for BDS Architectural Protocol implementation
 
-Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD 
License
 which accompanies this distribution.  The full text of the license may be 
found at
@@ -47,6 +47,7 @@
 #include <Protocol/SimpleTextInEx.h>
 #include <Protocol/DriverHealth.h>
 #include <Protocol/BootLogo.h>
+#include <Protocol/VariableLock.h>
 
 #include <Library/UefiDriverEntryPoint.h>
 #include <Library/PrintLib.h>

Modified: trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
===================================================================
--- trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf      
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf      
2013-05-17 03:49:35 UTC (rev 14372)
@@ -14,7 +14,7 @@
 #  BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, 
Device Manager" which
 #  is used for user to configure boot option or maintain hardware device.
 #  
-#  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD 
License
 #  which accompanies this distribution.  The full text of the license may be 
found at
@@ -160,6 +160,7 @@
   gEfiDriverHealthProtocolGuid                  ## PROTOCOL SOMETIMES_CONSUMES
   gEfiPciIoProtocolGuid                         ## PROTOCOL CONSUMES
   gEfiBootLogoProtocolGuid                      ## PROTOCOL SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid                ## PROTOCOL CONSUMES
 
 [FeaturePcd]
   gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate

Modified: trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
===================================================================
--- trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c      
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c      
2013-05-17 03:49:35 UTC (rev 14372)
@@ -38,6 +38,17 @@
 
 UINT16                          *mBootNext = NULL;
 
+///
+/// The read-only variables defined in UEFI Spec.
+///
+CHAR16  *mReadOnlyVariables[] = {
+  L"PlatformLangCodes",
+  L"LangCodes",
+  L"BootOptionSupport",
+  L"HwErrRecSupport",
+  L"OsIndicationsSupported"
+  };
+
 /**
 
   Install Boot Device Selection Protocol
@@ -459,6 +470,8 @@
   CHAR16                          *FirmwareVendor;
   EFI_STATUS                      Status;
   UINT16                          BootTimeOut;
+  UINTN                           Index;
+  EDKII_VARIABLE_LOCK_PROTOCOL    *VariableLock;
 
   //
   // Insert the performance probe
@@ -497,6 +510,18 @@
   BdsFormalizeEfiGlobalVariable();
 
   //
+  // Mark the read-only variables if the Variable Lock protocol exists
+  //
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID 
**) &VariableLock);
+  DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", 
Status));
+  if (!EFI_ERROR (Status)) {
+    for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof 
(mReadOnlyVariables[0]); Index++) {
+      Status = VariableLock->RequestToLock (VariableLock, 
mReadOnlyVariables[Index], &gEfiGlobalVariableGuid);
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  //
   // Report Status Code to indicate connecting drivers will happen
   //
   REPORT_STATUS_CODE (
@@ -504,12 +529,6 @@
     (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)
     );
 
-  //
-  // Do the platform init, can be customized by OEM/IBV
-  //
-  PERF_START (NULL, "PlatformBds", "BDS", 0);
-  PlatformBdsInit ();
-
   InitializeHwErrRecSupport();
 
   //
@@ -540,6 +559,12 @@
   InitializeFrontPage (TRUE);
 
   //
+  // Do the platform init, can be customized by OEM/IBV
+  //
+  PERF_START (NULL, "PlatformBds", "BDS", 0);
+  PlatformBdsInit ();
+
+  //
   // Set up the device list based on EFI 1.1 variables
   // process Driver#### and Load the driver's in the
   // driver option list

Modified: trunk/edk2/MdeModulePkg/Include/Guid/SmmVariableCommon.h
===================================================================
--- trunk/edk2/MdeModulePkg/Include/Guid/SmmVariableCommon.h    2013-05-17 
01:12:34 UTC (rev 14371)
+++ trunk/edk2/MdeModulePkg/Include/Guid/SmmVariableCommon.h    2013-05-17 
03:49:35 UTC (rev 14372)
@@ -60,6 +60,10 @@
 // is gEfiSmmVariableProtocolGuid.
 //
 #define SMM_VARIABLE_FUNCTION_GET_STATISTICS          7
+//
+// The payload for this function is SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
+//
+#define SMM_VARIABLE_FUNCTION_LOCK_VARIABLE           8
 
 ///
 /// Size of SMM communicate header, without including the payload.
@@ -101,4 +105,6 @@
   UINT32          Attributes; 
 } SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO;
 
+typedef SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME 
SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE;
+
 #endif // _SMM_VARIABLE_COMMON_H_
\ No newline at end of file

Added: trunk/edk2/MdeModulePkg/Include/Protocol/VariableLock.h
===================================================================
--- trunk/edk2/MdeModulePkg/Include/Protocol/VariableLock.h                     
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Include/Protocol/VariableLock.h     2013-05-17 
03:49:35 UTC (rev 14372)
@@ -0,0 +1,63 @@
+/** @file
+  Variable Lock Protocol is related to EDK II-specific implementation of 
variables
+  and intended for use as a means to mark a variable read-only after the event
+  EFI_END_OF_DXE_EVENT_GUID is signaled.
+
+  Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials                          
+  are licensed and made available under the terms and conditions of the BSD 
License         
+  which accompanies this distribution.  The full text of the license may be 
found at        
+  http://opensource.org/licenses/bsd-license.php                               
             
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,        
             
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.             
+
+**/
+
+#ifndef __VARIABLE_LOCK_H__
+#define __VARIABLE_LOCK_H__
+
+#define EDKII_VARIABLE_LOCK_PROTOCOL_GUID \
+  { \
+    0xcd3d0a05, 0x9e24, 0x437c, { 0xa8, 0x91, 0x1e, 0xe0, 0x53, 0xdb, 0x76, 
0x38 } \
+  }
+
+typedef struct _EDKII_VARIABLE_LOCK_PROTOCOL  EDKII_VARIABLE_LOCK_PROTOCOL;
+
+/**
+  Mark a variable that will become read-only after leaving the DXE phase of 
execution.
+  Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTOCOL 
is allowed.
+
+  @param[in] This          The EDKII_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EDKII_VARIABLE_LOCK_PROTOCOL_REQUEST_TO_LOCK) (
+  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+  IN       CHAR16                       *VariableName,
+  IN       EFI_GUID                     *VendorGuid
+  );
+
+///
+/// Variable Lock Protocol is related to EDK II-specific implementation of 
variables
+/// and intended for use as a means to mark a variable read-only after the 
event
+/// EFI_END_OF_DXE_EVENT_GUID is signaled.
+///
+struct _EDKII_VARIABLE_LOCK_PROTOCOL {
+  EDKII_VARIABLE_LOCK_PROTOCOL_REQUEST_TO_LOCK RequestToLock;
+};
+
+extern EFI_GUID gEdkiiVariableLockProtocolGuid;
+
+#endif  
+

Modified: trunk/edk2/MdeModulePkg/MdeModulePkg.dec
===================================================================
--- trunk/edk2/MdeModulePkg/MdeModulePkg.dec    2013-05-17 01:12:34 UTC (rev 
14371)
+++ trunk/edk2/MdeModulePkg/MdeModulePkg.dec    2013-05-17 03:49:35 UTC (rev 
14372)
@@ -326,6 +326,10 @@
   #  Include/Protocol/SmmVariableProtocol.h
   gEfiSmmVariableProtocolGuid = { 0xed32d533, 0x99e6, 0x4209, { 0x9c, 0xc0, 
0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 }}
 
+  ## This protocol is intended for use as a means to mark a variable read-only 
after the event EFI_END_OF_DXE_EVENT_GUID is signaled.
+  #  Include/Protocol/VariableLock.h
+  gEdkiiVariableLockProtocolGuid = { 0xcd3d0a05, 0x9e24, 0x437c, { 0xa8, 0x91, 
0x1e, 0xe0, 0x53, 0xdb, 0x76, 0x38 }}
+
   ## This protocol is similar with DXE FVB protocol and used in the UEFI SMM 
evvironment.
   #  Include/Protocol/SmmFirmwareVolumeBlock.h
   gEfiSmmFirmwareVolumeBlockProtocolGuid = { 0xd326d041, 0xbd31, 0x4c01, { 
0xb5, 0xa8, 0x62, 0x8b, 0xe8, 0x7f, 0x6, 0x53 }}

Modified: trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
===================================================================
--- trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c    
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c    
2013-05-17 03:49:35 UTC (rev 14372)
@@ -21,14 +21,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.
@@ -1919,7 +1935,59 @@
 }
 
 /**
+  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 finds variable in storage blocks (Volatile or Non-Volatile).
 
   @param VariableName               Name of Variable to be found.
@@ -2192,6 +2260,8 @@
   EFI_STATUS                          Status;
   VARIABLE_HEADER                     *NextVariable;
   EFI_PHYSICAL_ADDRESS                Point;
+  LIST_ENTRY                          *Link;
+  VARIABLE_ENTRY                      *Entry;
 
   //
   // Check input parameters.
@@ -2247,16 +2317,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);
 
   //
@@ -2275,13 +2335,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;
     }
   }
 
@@ -2292,6 +2370,7 @@
 
   Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, 
Attributes, &Variable);
 
+Done:
   InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
   ReleaseLockOnlyAtBootTime 
(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
 

Modified: trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
===================================================================
--- trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h    
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h    
2013-05-17 03:49:35 UTC (rev 14372)
@@ -22,6 +22,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>
@@ -97,6 +98,12 @@
   VOID        *Data;
 } VARIABLE_CACHE_ENTRY;
 
+typedef struct {
+  EFI_GUID    Guid;
+  CHAR16      *Name;
+  LIST_ENTRY  Link;
+} VARIABLE_ENTRY;
+
 /**
   Flush the HOB variable to flash.
 
@@ -456,7 +463,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/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
===================================================================
--- trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c 
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c 
2013-05-17 03:49:35 UTC (rev 14372)
@@ -3,7 +3,7 @@
   Implement all four UEFI Runtime Variable services for the nonvolatile
   and volatile storage space and install variable architecture protocol.
   
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials                          
 are licensed and made available under the terms and conditions of the BSD 
License         
 which accompanies this distribution.  The full text of the license may be 
found at        
@@ -21,6 +21,9 @@
 EFI_HANDLE                     mHandle                    = NULL;
 EFI_EVENT                      mVirtualAddressChangeEvent = NULL;
 EFI_EVENT                      mFtwRegistration           = NULL;
+extern BOOLEAN                 mEndOfDxe;
+extern BOOLEAN                 mEnableLocking;
+EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { 
VariableLockRequestToLock };
 
 /**
   Return TRUE if ExitBootServices () has been called.
@@ -255,13 +258,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 (&gEfiVariableGuid, 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.
 
@@ -375,11 +400,20 @@
   )
 {
   EFI_STATUS                            Status;
-  EFI_EVENT                             ReadyToBootEvent;    
+  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;
@@ -426,7 +460,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/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
===================================================================
--- 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf    
    2013-05-17 01:12:34 UTC (rev 14371)
+++ 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf    
    2013-05-17 03:49:35 UTC (rev 14372)
@@ -2,7 +2,7 @@
 # Component description file for Variable module.
 #
 # This module installs three EFI_RUNTIME_SERVICES: SetVariable, GetVariable, 
GetNextVariableName.
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD 
License
@@ -59,13 +59,15 @@
   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES
   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES
   gEfiFaultTolerantWriteProtocolGuid            ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid                ## ALWAYS_PRODUCES
 
 [Guids]
   gEfiVariableGuid                              ## PRODUCES ## Configuration 
Table Guid 
   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
-  gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event
+  gEfiEventVirtualAddressChangeGuid             ## CONSUMES ## Event
   gEfiSystemNvDataFvGuid                        ## CONSUMES
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES ## Event
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize

Modified: trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
===================================================================
--- trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c 
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c 
2013-05-17 03:49:35 UTC (rev 14372)
@@ -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.
   
@@ -450,6 +497,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;
@@ -635,6 +683,7 @@
       break;
 
     case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
+      mEndOfDxe = TRUE;
       if (AtRuntime()) {
         Status = EFI_UNSUPPORTED;
         break;
@@ -667,6 +716,51 @@
       *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
       break;
 
+    case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:
+      if (CommBufferPayloadSize < 
OFFSET_OF(SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
+        DEBUG ((EFI_D_ERROR, "RequestToLock: SMM communication buffer size 
invalid!\n"));
+        return EFI_SUCCESS;
+      }
+      //
+      // Copy the input communicate buffer payload to pre-allocated SMM 
variable buffer payload.
+      //
+      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, 
CommBufferPayloadSize);
+      VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) 
mVariableBufferPayload;
+
+      if (VariableToLock->NameSize > MAX_ADDRESS - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
+        //
+        // Prevent InfoSize overflow happen
+        //
+        Status = EFI_ACCESS_DENIED;
+        goto EXIT;
+      }
+
+      if (VariableToLock->NameSize < sizeof (CHAR16) || 
VariableToLock->Name[VariableToLock->NameSize/sizeof (CHAR16) - 1] != L'\0') {
+        //
+        // Make sure VariableName is A Null-terminated string.
+        //
+        Status = EFI_ACCESS_DENIED;
+        goto EXIT;
+      }
+      
+      InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + 
VariableToLock->NameSize;
+      
+      //
+      // SMRAM range check already covered before
+      //
+      if (InfoSize > CommBufferPayloadSize) {
+        DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size 
limit!\n"));
+        Status = EFI_ACCESS_DENIED;
+        goto EXIT;
+      }
+
+      Status = VariableLockRequestToLock (
+                 NULL,
+                 VariableToLock->Name,
+                 &VariableToLock->Guid
+                 );
+      break;
+
     default:
       Status = EFI_UNSUPPORTED;
   }
@@ -678,7 +772,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.
 
@@ -774,6 +890,7 @@
   VOID                                    *SmmFtwRegistration;
   EFI_SMM_ACCESS2_PROTOCOL                *SmmAccess;
   UINTN                                   Size;
+  VOID                                    *SmmEndOfDxeRegistration;
 
   //
   // Variable initialize.
@@ -844,6 +961,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/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf       
2013-05-17 01:12:34 UTC (rev 14371)
+++ trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf       
2013-05-17 03:49:35 UTC (rev 14372)
@@ -14,7 +14,7 @@
 #  This external input must be validated carefully to avoid security issue like
 #  buffer overflow, integer overflow.
 #
-# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
 # This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD 
License
 # which accompanies this distribution. The full text of the license may be 
found at
@@ -69,6 +69,7 @@
   gEfiSmmVariableProtocolGuid                   ## ALWAYS_PRODUCES
   gEfiSmmFaultTolerantWriteProtocolGuid         ## SOMETIMES_CONSUMES
   gEfiSmmAccess2ProtocolGuid                    ## ALWAYS_CONSUMES
+  gEfiSmmEndOfDxeProtocolGuid                   ## ALWAYS_CONSUMES
 
 [Guids]
   gEfiVariableGuid                              ## PRODUCES ## Configuration 
Table Guid 

Modified: 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
===================================================================
--- 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   
    2013-05-17 01:12:34 UTC (rev 14371)
+++ 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   
    2013-05-17 03:49:35 UTC (rev 14372)
@@ -19,6 +19,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>
@@ -44,6 +45,7 @@
 UINTN                            mVariableBufferSize;
 UINTN                            mVariableBufferPayloadSize;
 EFI_LOCK                         mVariableServicesLock;
+EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
 
 /**
   Acquires lock only at boot time. Simply returns at runtime.
@@ -160,7 +162,64 @@
   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                                     PayloadSize;
+  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE    *VariableToLock;
+
+  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
+    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) + 
StrSize (VariableName);
+  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 = StrSize (VariableName);
+  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).
 
@@ -722,6 +781,7 @@
   IN EFI_SYSTEM_TABLE                       *SystemTable
   )
 {
+  EFI_STATUS                                Status;
   VOID                                      *SmmVariableRegistration;
   VOID                                      *SmmVariableWriteRegistration;
   EFI_EVENT                                 OnReadyToBootEvent;
@@ -729,6 +789,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/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
===================================================================
--- 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf 
    2013-05-17 01:12:34 UTC (rev 14371)
+++ 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf 
    2013-05-17 03:49:35 UTC (rev 14372)
@@ -4,7 +4,7 @@
 #  This module is the Runtime DXE part correspond to SMM variable module. It 
 #  installs variable arch protocol and variable write arch protocol and works 
 #  with SMM variable module together. 
-# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD 
License
@@ -54,6 +54,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