[edk2-devel] [edk2-platforms] [PATCH v3 2/4] MinPlatformPkg: Add VariableWriteLib

Nate DeSimone posted 4 patches 1 month ago

[edk2-devel] [edk2-platforms] [PATCH v3 2/4] MinPlatformPkg: Add VariableWriteLib

Posted by Nate DeSimone 1 month ago
VariableWriteLib is a phase agnostic library for writing
to UEFI Variables. This library provides the MinSetVariable(),
MinQueryVariableInfo(), MinIsVariableRequestToLockSupported(),
and MinVariableRequestToLock() APIs which are usable in DXE
and SMM.

Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Michael Kubacki <michael.kubacki@microsoft.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Signed-off-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
Reviewed-by: Isaac Oram <isaac.w.oram@intel.com>
---
 .../MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc |   2 +
 .../Include/Library/VariableWriteLib.h        | 129 +++++++++
 .../DxeRuntimeVariableWriteLib.c              | 256 ++++++++++++++++++
 .../DxeRuntimeVariableWriteLib.inf            |  49 ++++
 .../SmmVariableWriteCommon.c                  | 167 ++++++++++++
 .../StandaloneMmVariableWriteLib.inf          |  45 +++
 .../StandaloneMmVariableWriteLibConstructor.c |  48 ++++
 .../TraditionalMmVariableWriteLib.inf         |  44 +++
 ...TraditionalMmVariableWriteLibConstructor.c |  48 ++++
 .../Intel/MinPlatformPkg/MinPlatformPkg.dsc   |   1 +
 10 files changed, 789 insertions(+)
 create mode 100644 Platform/Intel/MinPlatformPkg/Include/Library/VariableWriteLib.h
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.c
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.inf
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/SmmVariableWriteCommon.c
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLib.inf
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLibConstructor.c
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLib.inf
 create mode 100644 Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLibConstructor.c

diff --git a/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc b/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc
index 0db1250ab7..57847e6a4d 100644
--- a/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc
+++ b/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc
@@ -48,6 +48,7 @@
 
 [LibraryClasses.common.DXE_CORE, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION]
   VariableReadLib|MinPlatformPkg/Library/DxeRuntimeVariableReadLib/DxeRuntimeVariableReadLib.inf
+  VariableWriteLib|MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.inf
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
@@ -93,6 +94,7 @@
   Tcg2PhysicalPresenceLib|SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
   VariableReadLib|MinPlatformPkg/Library/SmmVariableReadLib/TraditionalMmVariableReadLib.inf
+  VariableWriteLib|MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLib.inf
 
 [LibraryClasses.common.SMM_CORE]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
diff --git a/Platform/Intel/MinPlatformPkg/Include/Library/VariableWriteLib.h b/Platform/Intel/MinPlatformPkg/Include/Library/VariableWriteLib.h
new file mode 100644
index 0000000000..c52aec93ec
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Include/Library/VariableWriteLib.h
@@ -0,0 +1,129 @@
+/** @file
+  Variable Write Lib
+
+  This library provides phase agnostic access to the UEFI Variable Services.
+  This is done by implementing a wrapper on top of the phase specific mechanism
+  for writing to UEFI variables. For example, the DXE implementation accesses
+  the UEFI Runtime Services Table, and the SMM implementation uses
+  EFI_SMM_VARIABLE_PROTOCOL.
+
+  Using this library allows code to be written in a generic manner that can be
+  used in DXE or SMM without modification.
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+
+/**
+  Sets the value of a variable.
+
+  @param[in]  VariableName       A Null-terminated string that is the name of the vendor's variable.
+                                 Each VariableName is unique for each VendorGuid. VariableName must
+                                 contain 1 or more characters. If VariableName is an empty string,
+                                 then EFI_INVALID_PARAMETER is returned.
+  @param[in]  VendorGuid         A unique identifier for the vendor.
+  @param[in]  Attributes         Attributes bitmask to set for the variable.
+  @param[in]  DataSize           The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE or
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to
+                                 the variable value (the timestamp associated with the variable may be updated however
+                                 even if no new data value is provided,see the description of the
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
+  @param[in]  Data               The contents for the variable.
+
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
+                                 defined by the Attributes.
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
+                                 DataSize exceeds the maximum allowed.
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set,
+                                 but the AuthInfo does NOT pass the validation check carried out by the firmware.
+
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+VarLibSetVariable (
+  IN  CHAR16                        *VariableName,
+  IN  EFI_GUID                      *VendorGuid,
+  IN  UINT32                        Attributes,
+  IN  UINTN                         DataSize,
+  IN  VOID                          *Data
+  );
+
+/**
+  Returns information about the EFI variables.
+
+  @param[in]   Attributes                   Attributes bitmask to specify the type of variables on
+                                            which to return information.
+  @param[out]  MaximumVariableStorageSize   On output the maximum size of the storage space
+                                            available for the EFI variables associated with the
+                                            attributes specified.
+  @param[out]  RemainingVariableStorageSize Returns the remaining size of the storage space
+                                            available for the EFI variables associated with the
+                                            attributes specified.
+  @param[out]  MaximumVariableSize          Returns the maximum size of the individual EFI
+                                            variables associated with the attributes specified.
+
+  @retval EFI_SUCCESS                  Valid answer returned.
+  @retval EFI_INVALID_PARAMETER        An invalid combination of attribute bits was supplied
+  @retval EFI_UNSUPPORTED              The attribute is not supported on this platform, and the
+                                       MaximumVariableStorageSize,
+                                       RemainingVariableStorageSize, MaximumVariableSize
+                                       are undefined.
+**/
+EFI_STATUS
+EFIAPI
+VarLibQueryVariableInfo (
+  IN  UINT32                        Attributes,
+  OUT UINT64                        *MaximumVariableStorageSize,
+  OUT UINT64                        *RemainingVariableStorageSize,
+  OUT UINT64                        *MaximumVariableSize
+  );
+
+/**
+  Indicates if the VarLibVariableRequestToLock() API is supported by the current
+  VariableWriteLib implementation. At time of writting, this API is not
+  available in SMM or after ExitBootServices.
+
+  @retval TRUE                  The VarLibVariableRequestToLock() API is supported
+  @retval FALSE                 The VarLibVariableRequestToLock() API is not supported
+**/
+BOOLEAN
+EFIAPI
+VarLibIsVariableRequestToLockSupported (
+  VOID
+  );
+
+/**
+  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.
+**/
+EFI_STATUS
+EFIAPI
+VarLibVariableRequestToLock (
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid
+  );
diff --git a/Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.c b/Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.c
new file mode 100644
index 0000000000..3b7f377bc2
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.c
@@ -0,0 +1,256 @@
+/** @file
+  DXE Variable Write Lib
+
+  This library provides phase agnostic access to the UEFI Variable Services.
+  This is done by implementing a wrapper on top of the phase specific mechanism
+  for writing to UEFI variables. For example, the DXE implementation accesses
+  the UEFI Runtime Services Table, and the SMM implementation uses
+  EFI_SMM_VARIABLE_PROTOCOL.
+
+  Using this library allows code to be written in a generic manner that can be
+  used in DXE or SMM without modification.
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/EventGroup.h>
+#include <Protocol/VariableLock.h>
+
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+STATIC EDKII_VARIABLE_LOCK_PROTOCOL  *mVariableWriteLibVariableLock = NULL;
+
+/**
+  Sets the value of a variable.
+
+  @param[in]  VariableName       A Null-terminated string that is the name of the vendor's variable.
+                                 Each VariableName is unique for each VendorGuid. VariableName must
+                                 contain 1 or more characters. If VariableName is an empty string,
+                                 then EFI_INVALID_PARAMETER is returned.
+  @param[in]  VendorGuid         A unique identifier for the vendor.
+  @param[in]  Attributes         Attributes bitmask to set for the variable.
+  @param[in]  DataSize           The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE or
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to
+                                 the variable value (the timestamp associated with the variable may be updated however
+                                 even if no new data value is provided,see the description of the
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
+  @param[in]  Data               The contents for the variable.
+
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
+                                 defined by the Attributes.
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
+                                 DataSize exceeds the maximum allowed.
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set,
+                                 but the AuthInfo does NOT pass the validation check carried out by the firmware.
+
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+VarLibSetVariable (
+  IN  CHAR16                        *VariableName,
+  IN  EFI_GUID                      *VendorGuid,
+  IN  UINT32                        Attributes,
+  IN  UINTN                         DataSize,
+  IN  VOID                          *Data
+  )
+{
+  EFI_STATUS    Status = EFI_UNSUPPORTED;
+
+  if (gRT != NULL) {
+    Status = gRT->SetVariable (
+                    VariableName,
+                    VendorGuid,
+                    Attributes,
+                    DataSize,
+                    Data
+                    );
+  }
+  return Status;
+}
+
+/**
+  Returns information about the EFI variables.
+
+  @param[in]   Attributes                   Attributes bitmask to specify the type of variables on
+                                            which to return information.
+  @param[out]  MaximumVariableStorageSize   On output the maximum size of the storage space
+                                            available for the EFI variables associated with the
+                                            attributes specified.
+  @param[out]  RemainingVariableStorageSize Returns the remaining size of the storage space
+                                            available for the EFI variables associated with the
+                                            attributes specified.
+  @param[out]  MaximumVariableSize          Returns the maximum size of the individual EFI
+                                            variables associated with the attributes specified.
+
+  @retval EFI_SUCCESS                  Valid answer returned.
+  @retval EFI_INVALID_PARAMETER        An invalid combination of attribute bits was supplied
+  @retval EFI_UNSUPPORTED              The attribute is not supported on this platform, and the
+                                       MaximumVariableStorageSize,
+                                       RemainingVariableStorageSize, MaximumVariableSize
+                                       are undefined.
+**/
+EFI_STATUS
+EFIAPI
+VarLibQueryVariableInfo (
+  IN  UINT32                        Attributes,
+  OUT UINT64                        *MaximumVariableStorageSize,
+  OUT UINT64                        *RemainingVariableStorageSize,
+  OUT UINT64                        *MaximumVariableSize
+  )
+{
+  EFI_STATUS    Status = EFI_UNSUPPORTED;
+
+  if (gRT != NULL) {
+    Status = gRT->QueryVariableInfo (
+                    Attributes,
+                    MaximumVariableStorageSize,
+                    RemainingVariableStorageSize,
+                    MaximumVariableSize
+                    );
+  }
+  return Status;
+}
+
+/**
+  Indicates if the VarLibVariableRequestToLock() API is supported by the current
+  VariableWriteLib implementation. At time of writting, this API is not
+  available in SMM or after ExitBootServices.
+
+  @retval TRUE                  The VarLibVariableRequestToLock() API is supported
+  @retval FALSE                 The VarLibVariableRequestToLock() API is not supported
+**/
+BOOLEAN
+EFIAPI
+VarLibIsVariableRequestToLockSupported (
+  VOID
+  )
+{
+  if (mVariableWriteLibVariableLock != NULL) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  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.
+**/
+EFI_STATUS
+EFIAPI
+VarLibVariableRequestToLock (
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid
+  )
+{
+  EFI_STATUS    Status = EFI_UNSUPPORTED;
+
+  if (mVariableWriteLibVariableLock != NULL) {
+    Status = mVariableWriteLibVariableLock->RequestToLock (
+                                              mVariableWriteLibVariableLock,
+                                              VariableName,
+                                              VendorGuid
+                                              );
+  }
+  return Status;
+}
+
+/**
+  Exit Boot Services Event notification handler.
+
+  @param[in]  Event     Event whose notification function is being invoked.
+  @param[in]  Context   Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+DxeRuntimeVariableWriteLibOnExitBootServices (
+  IN  EFI_EVENT                    Event,
+  IN  VOID                         *Context
+  )
+{
+  mVariableWriteLibVariableLock = NULL;
+}
+
+/**
+  The constructor function acquires the Variable Lock Protocol
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeVariableWriteLibConstructor (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+  EFI_EVENT     ExitBootServiceEvent;
+  EFI_EVENT     LegacyBootEvent;
+
+  //
+  // Locate VariableLockProtocol.
+  //
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&mVariableWriteLibVariableLock);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register the event to inform SMM variable that it is at runtime.
+  //
+  Status = gBS->CreateEventEx (
+             EVT_NOTIFY_SIGNAL,
+             TPL_NOTIFY,
+             DxeRuntimeVariableWriteLibOnExitBootServices,
+             NULL,
+             &gEfiEventExitBootServicesGuid,
+             &ExitBootServiceEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register the event to inform SMM variable that it is at runtime for legacy boot.
+  // Reuse OnExitBootServices() here.
+  //
+  Status = EfiCreateEventLegacyBootEx (
+             TPL_NOTIFY,
+             DxeRuntimeVariableWriteLibOnExitBootServices,
+             NULL,
+             &LegacyBootEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.inf b/Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.inf
new file mode 100644
index 0000000000..704a8ac7cc
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/DxeRuntimeVariableWriteLib/DxeRuntimeVariableWriteLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for DXE Variable Write Lib
+#
+# This library provides phase agnostic access to the UEFI Variable Services.
+# This is done by implementing a wrapper on top of the phase specific mechanism
+# for writing to UEFI variables. For example, the DXE implementation accesses
+# the UEFI Runtime Services Table, and the SMM implementation uses
+# EFI_SMM_VARIABLE_PROTOCOL.
+#
+# Using this library allows code to be written in a generic manner that can be
+# used in DXE or SMM without modification.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeRuntimeVariableWriteLib
+  FILE_GUID                      = 9681E383-5FD4-47A4-B4F8-6651EE603E4E
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  LIBRARY_CLASS                  = VariableWriteLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+  CONSTRUCTOR                    = DxeRuntimeVariableWriteLibConstructor
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+  DxeRuntimeVariableWriteLib.c
+
+[LibraryClasses]
+  DebugLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+
+[Guids]
+  gEfiEventExitBootServicesGuid       ## CONSUMES ## Event
+
+[Protocols]
+  gEfiVariableWriteArchProtocolGuid   ## CONSUMES
+  gEdkiiVariableLockProtocolGuid      ## CONSUMES
+
+[Depex]
+  gEfiVariableWriteArchProtocolGuid AND gEdkiiVariableLockProtocolGuid
diff --git a/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/SmmVariableWriteCommon.c b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/SmmVariableWriteCommon.c
new file mode 100644
index 0000000000..e8d7d19ed1
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/SmmVariableWriteCommon.c
@@ -0,0 +1,167 @@
+/** @file
+  SMM Variable Write Lib
+
+  This library provides phase agnostic access to the UEFI Variable Services.
+  This is done by implementing a wrapper on top of the phase specific mechanism
+  for writing to UEFI variables.
+
+  This is the common implementation pieces that are shared between
+  traditional SMM and standalone MM.
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+
+#include <Protocol/SmmVariable.h>
+
+EFI_SMM_VARIABLE_PROTOCOL  *mVariableWriteLibSmmVariable = NULL;
+
+/**
+  Sets the value of a variable.
+
+  @param[in]  VariableName       A Null-terminated string that is the name of the vendor's variable.
+                                 Each VariableName is unique for each VendorGuid. VariableName must
+                                 contain 1 or more characters. If VariableName is an empty string,
+                                 then EFI_INVALID_PARAMETER is returned.
+  @param[in]  VendorGuid         A unique identifier for the vendor.
+  @param[in]  Attributes         Attributes bitmask to set for the variable.
+  @param[in]  DataSize           The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE or
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to
+                                 the variable value (the timestamp associated with the variable may be updated however
+                                 even if no new data value is provided,see the description of the
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
+  @param[in]  Data               The contents for the variable.
+
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
+                                 defined by the Attributes.
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
+                                 DataSize exceeds the maximum allowed.
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set,
+                                 but the AuthInfo does NOT pass the validation check carried out by the firmware.
+
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+VarLibSetVariable (
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid,
+  IN  UINT32                       Attributes,
+  IN  UINTN                        DataSize,
+  IN  VOID                         *Data
+  )
+{
+  EFI_STATUS    Status = EFI_UNSUPPORTED;
+
+  if (mVariableWriteLibSmmVariable != NULL) {
+    Status = mVariableWriteLibSmmVariable->SmmSetVariable (
+                                            VariableName,
+                                            VendorGuid,
+                                            Attributes,
+                                            DataSize,
+                                            Data
+                                            );
+  }
+  return Status;
+}
+
+/**
+  Returns information about the EFI variables.
+
+  @param[in]   Attributes                   Attributes bitmask to specify the type of variables on
+                                            which to return information.
+  @param[out]  MaximumVariableStorageSize   On output the maximum size of the storage space
+                                            available for the EFI variables associated with the
+                                            attributes specified.
+  @param[out]  RemainingVariableStorageSize Returns the remaining size of the storage space
+                                            available for the EFI variables associated with the
+                                            attributes specified.
+  @param[out]  MaximumVariableSize          Returns the maximum size of the individual EFI
+                                            variables associated with the attributes specified.
+
+  @retval EFI_SUCCESS                  Valid answer returned.
+  @retval EFI_INVALID_PARAMETER        An invalid combination of attribute bits was supplied
+  @retval EFI_UNSUPPORTED              The attribute is not supported on this platform, and the
+                                       MaximumVariableStorageSize,
+                                       RemainingVariableStorageSize, MaximumVariableSize
+                                       are undefined.
+**/
+EFI_STATUS
+EFIAPI
+VarLibQueryVariableInfo (
+  IN  UINT32            Attributes,
+  OUT UINT64            *MaximumVariableStorageSize,
+  OUT UINT64            *RemainingVariableStorageSize,
+  OUT UINT64            *MaximumVariableSize
+  )
+{
+  EFI_STATUS    Status = EFI_UNSUPPORTED;
+
+  if (mVariableWriteLibSmmVariable != NULL) {
+    Status = mVariableWriteLibSmmVariable->SmmQueryVariableInfo (
+                                             Attributes,
+                                             MaximumVariableStorageSize,
+                                             RemainingVariableStorageSize,
+                                             MaximumVariableSize
+                                             );
+  }
+  return Status;
+}
+
+/**
+  Indicates if the VarLibVariableRequestToLock() API is supported by the current
+  VariableWriteLib implementation. At time of writting, this API is not
+  available in SMM or after ExitBootServices.
+
+  @retval TRUE                  The VarLibVariableRequestToLock() API is supported
+  @retval FALSE                 The VarLibVariableRequestToLock() API is not supported
+**/
+BOOLEAN
+EFIAPI
+VarLibIsVariableRequestToLockSupported (
+  VOID
+  )
+{
+  return FALSE;
+}
+
+/**
+  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.
+**/
+EFI_STATUS
+EFIAPI
+VarLibVariableRequestToLock (
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid
+  )
+{
+  //
+  // Variable lock protocol is not accessible from SMM
+  //
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLib.inf b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLib.inf
new file mode 100644
index 0000000000..4cafc421c4
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLib.inf
@@ -0,0 +1,45 @@
+## @file
+# Component description file for Standalone MM Variable Write Lib
+#
+# This library provides phase agnostic access to the UEFI Variable Services.
+# This is done by implementing a wrapper on top of the phase specific mechanism
+# for writing to UEFI variables. For example, the DXE implementation accesses
+# the UEFI Runtime Services Table, and the SMM implementation uses
+# EFI_SMM_VARIABLE_PROTOCOL.
+#
+# Using this library allows code to be written in a generic manner that can be
+# used in DXE or SMM without modification.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = SmmVariableWriteLib
+  FILE_GUID                      = 62A023A6-DEBA-4407-A617-18963090DAFD
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = MM_STANDALONE
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  LIBRARY_CLASS                  = VariableWriteLib|MM_STANDALONE
+  CONSTRUCTOR                    = StandaloneMmVariableWriteLibConstructor
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+  SmmVariableWriteCommon.c
+  StandaloneMmVariableWriteLibConstructor.c
+
+[LibraryClasses]
+  DebugLib
+  MmServicesTableLib
+
+[Protocols]
+  gEfiSmmVariableProtocolGuid   ## CONSUMES
+
+[Depex]
+  gEfiSmmVariableProtocolGuid
diff --git a/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLibConstructor.c b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLibConstructor.c
new file mode 100644
index 0000000000..4493929328
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLibConstructor.c
@@ -0,0 +1,48 @@
+/** @file
+  Standalone MM Variable Write Lib
+
+  This library provides phase agnostic access to the UEFI Variable Services.
+  This is done by implementing a wrapper on top of the phase specific mechanism
+  for reading from UEFI variables.
+
+  This is the standalone MM specific LibraryClass constructor.
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+
+#include <Protocol/SmmVariable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/MmServicesTableLib.h>
+
+extern EFI_SMM_VARIABLE_PROTOCOL  *mVariableWriteLibSmmVariable;
+
+/**
+  The constructor function acquires the EFI SMM Variable Services
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the MM System Table.
+
+  @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmVariableWriteLibConstructor (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_MM_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+
+  //
+  // Locate SmmVariableProtocol.
+  //
+  Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &mVariableWriteLibSmmVariable);
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLib.inf b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLib.inf
new file mode 100644
index 0000000000..5d833b7e0f
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for Traditional MM Variable Write Lib
+#
+# This library provides phase agnostic access to the UEFI Variable Services.
+# This is done by implementing a wrapper on top of the phase specific mechanism
+# for writing to UEFI variables. For example, the DXE implementation accesses
+# the UEFI Runtime Services Table, and the SMM implementation uses
+# EFI_SMM_VARIABLE_PROTOCOL.
+#
+# Using this library allows code to be written in a generic manner that can be
+# used in DXE or SMM without modification.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = TraditionalMmVariableWriteLib
+  FILE_GUID                      = 8C385E9B-C260-466C-91D2-43D839712680
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = VariableWriteLib|DXE_SMM_DRIVER SMM_CORE
+  CONSTRUCTOR                    = TraditionalMmVariableWriteLibConstructor
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+  SmmVariableWriteCommon.c
+  TraditionalMmVariableWriteLibConstructor.c
+
+[LibraryClasses]
+  DebugLib
+  SmmServicesTableLib
+
+[Protocols]
+  gEfiSmmVariableProtocolGuid   ## CONSUMES
+
+[Depex]
+  gEfiSmmVariableProtocolGuid
diff --git a/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLibConstructor.c b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLibConstructor.c
new file mode 100644
index 0000000000..472ccc5aad
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/SmmVariableWriteLib/TraditionalMmVariableWriteLibConstructor.c
@@ -0,0 +1,48 @@
+/** @file
+  Traditional MM Variable Write Lib
+
+  This library provides phase agnostic access to the UEFI Variable Services.
+  This is done by implementing a wrapper on top of the phase specific mechanism
+  for reading from UEFI variables.
+
+  This is the traditional SMM specific LibraryClass constructor.
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/SmmVariable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+
+extern EFI_SMM_VARIABLE_PROTOCOL  *mVariableWriteLibSmmVariable;
+
+/**
+  The constructor function acquires the EFI SMM Variable Services
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+TraditionalMmVariableWriteLibConstructor (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+
+  //
+  // Locate SmmVariableProtocol.
+  //
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &mVariableWriteLibSmmVariable);
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dsc b/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dsc
index 18b5c6f5b1..e968ec4cb2 100644
--- a/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dsc
+++ b/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dsc
@@ -121,6 +121,7 @@
   SpiFlashCommonLib|MinPlatformPkg/Flash/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf
   StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
   VariableReadLib|MinPlatformPkg/Library/SmmVariableReadLib/StandaloneMmVariableReadLib.inf
+  VariableWriteLib|MinPlatformPkg/Library/SmmVariableWriteLib/StandaloneMmVariableWriteLib.inf
 
 ###################################################################################################
 #
-- 
2.27.0.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#73738): https://edk2.groups.io/g/devel/message/73738
Mute This Topic: https://groups.io/mt/81898860/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-