public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM
@ 2019-01-02 13:13 Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 01/11] StandaloneMmPkg: Remove MM_STANDALONE LIBRARY_CLASS from StandaloneMmCoreHobLib Jagadeesh Ujja
                   ` (10 more replies)
  0 siblings, 11 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

In-Reply-To: 

Changes since v1:
-Addressed the comments from Liming Gao
 - StandaloneMmServicesTableLib library implemented in MdePkg.
- Addressed all the comments from Ard Biesheuvel.
- For comment from Jian Wang about avoiding if..else, this
  requires a bit more clarity and so this comment has not
  been addressed.
- All the patches in this series can be pulled from
  https://github.com/jagadeeshujja/edk2.git branch: topics/aarch64_secure_vars


Changes since RFC v4:
- Addressed all the comments from Liming Gao
  - Added an additional PCD 'PcdStandaloneMmCodeEnabled' to indicate
    presence of StandaloneMM support.
  - MdePkg.dec file updated to include StandaloneMmServiceTableLib and
    StandaloneMmRuntimeDxe library.
  - Platform specific changes will be posted in a seperate patchset.
  - AsmLfence wrapper function is supported for AArch64 platforms.
  - All the patches in this series can be pulled from
    https://github.com/jagadeeshujja/edk2 (branch: topics/aarch64_secure_vars)

Changes since RFC v3:
- Addressed all the comments from Liming Gao
  - Added a AArch64 implementation of AsmLfence which is a wrapper for
    MemoryFence. The changes in variable service driver in v3 of this
    patchset that used MemoryFence instead of AsmLfence have been removed.
  - Added StandaloneMmServicesTableLib.h and StandaloneMmRuntimeDxe
    library into MdePkg.
  - Renamed PcdStandaloneMmEnable as PcdStandaloneMmVariableEnabled and
    added to in to MdePkg.
  - Now with above changes, edk2 packages don't need to depend on
    StandaloneMmPkg/StandaloneMmPkg.dec
- Addressed comments from Ting Ye
  - Removed the hacks in the v3 version.
  - Will relook into the “TimerWrapp.c” file and add a appropriate
    implementation of this for MM Standalone mode code.

Changes since RFC v2:
- Added 'Contributed-under' tag, removed Change-ID tag and
  maintained a single signed-off-by for the all the patches.

Changes since RFC v1:
- Addressed all the comments from Liming Gao
  - Removed the use of #ifdef/#else/#endif and used a Pcd instead to
    select between MM and non-MM paths.
  - Removed all dependencies on edk2-platforms.
  - Dropped the use of mMmst and used gSmst instead.
  - Added a dummy implementation UefiRuntimeServiceTableLib for
    MM_STANDALONE usage
- Replaced all uses of AsmLfence with MemoryFence from variable
  service code.
- Add a new StandaloneMmRuntimeDxe library to for use by non-MM code.

This patch series extends the existing secure variable service support for
use with Standalone MM. This is applicable to paltforms that use Standalone
Management Mode to protect access to non-volatile memory (NOR flash in case
of these patches) used to store the secure EFI variables.

The first patch pulls in additional libraries from the staging branch of
StandaloneMmPkg into the edk2's StandaloneMmPkg. The existing secure variable
service implementation supports only the traditional MM mode and so the rest
of the patches extends the existing secure variable service support to be
useable with Standalone MM mode as well.

Jagadeesh Ujja (11):
  StandaloneMmPkg: Remove MM_STANDALONE LIBRARY_CLASS from
    StandaloneMmCoreHobLib
  StandaloneMmPkg: Adding the library packages used by MM_STANDALONE
    drivers
  MdeModulePkg: Add a PCD to indicate Standalone MM supports secure
    variable
  MdePkg/Include: Add StandaloneMmServicesTableLib library
  MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver
  MdeModulePkg/Variable/RuntimeDxe: adapt for usability with MM
    Standalone
  MdeModulePkg/Variable/RuntimeDxe: adapt as a MM Standalone driver
  MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this
    library
  ArmPlatformPkg/NorFlashDxe: allow reusability as a MM driver
  SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this
    library
  CryptoPkg/BaseCryptLib: allow MM_STANDALONE drivers to use this
    library

 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h                                            |    4 +-
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf                                          |    2 +
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c                                         |   96 +-
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c                                   | 1339 ++++++++++++++++++++
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf                                 |   76 ++
 CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                                              |    2 +-
 MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf                                            |    5 +-
 MdeModulePkg/MdeModulePkg.dec                                                               |    5 +
 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf                      |    1 +
 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c                        |  203 ++-
 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf             |  101 ++
 MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c                           |   27 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c                                       |   37 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf                           |    1 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c                                    |  201 ++-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c                          |   31 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf                        |    3 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf                         |  132 ++
 MdePkg/Include/Library/StandaloneMmServicesTableLib.h                                       |   43 +
 MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c                  |   39 +
 MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf                |   36 +
 MdePkg/MdePkg.dec                                                                           |    4 +
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                     |    5 +-
 StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf                   |    2 +-
 StandaloneMmPkg/Library/StandaloneMmHobLib/AArch64/StandaloneMmCoreHobLibInternal.c         |   64 +
 StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.c                             |  651 ++++++++++
 StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf                           |   48 +
 StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c   |  823 ++++++++++++
 StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf |   45 +
 StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c         |   64 +
 StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf       |   36 +
 31 files changed, 3943 insertions(+), 183 deletions(-)
 create mode 100644 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c
 create mode 100644 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf
 create mode 100644 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
 create mode 100644 MdePkg/Include/Library/StandaloneMmServicesTableLib.h
 create mode 100644 MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
 create mode 100644 MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmHobLib/AArch64/StandaloneMmCoreHobLibInternal.c
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.c
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
 create mode 100644 StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf

-- 
2.7.4



^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v2 01/11] StandaloneMmPkg: Remove MM_STANDALONE LIBRARY_CLASS from StandaloneMmCoreHobLib
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 02/11] StandaloneMmPkg: Adding the library packages used by MM_STANDALONE drivers Jagadeesh Ujja
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

For MM_STANDALONE drivers hoblib information will be retrieved from
StandaloneMmHobLib, hence removing from StandaloneMmCoreHobLib
library class.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
index db19d3c..ac036e3 100644
--- a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
+++ b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
@@ -24,7 +24,7 @@
   MODULE_TYPE                    = MM_CORE_STANDALONE
   VERSION_STRING                 = 1.0
   PI_SPECIFICATION_VERSION       = 0x00010032
-  LIBRARY_CLASS                  = HobLib|MM_CORE_STANDALONE MM_STANDALONE
+  LIBRARY_CLASS                  = HobLib|MM_CORE_STANDALONE
 
 #
 #  VALID_ARCHITECTURES           = AARCH64
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 02/11] StandaloneMmPkg: Adding the library packages used by MM_STANDALONE drivers
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 01/11] StandaloneMmPkg: Remove MM_STANDALONE LIBRARY_CLASS from StandaloneMmCoreHobLib Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 03/11] MdeModulePkg: Add a PCD to indicate Standalone MM supports secure variable Jagadeesh Ujja
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Drivers of type MM_STANDALONE uses these libraries for accessing the
hoblib and memory allocation.

The Library being added are
  - StandaloneMmHobLib
  - StandaloneMmMemoryAllocationLib
  - StandaloneMmServicesTableLib

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 StandaloneMmPkg/Library/StandaloneMmHobLib/AArch64/StandaloneMmCoreHobLibInternal.c         |  64 ++
 StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.c                             | 651 ++++++++++++++++
 StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf                           |  48 ++
 StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c   | 823 ++++++++++++++++++++
 StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf |  45 ++
 StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c         |  64 ++
 StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf       |  36 +
 7 files changed, 1731 insertions(+)

diff --git a/StandaloneMmPkg/Library/StandaloneMmHobLib/AArch64/StandaloneMmCoreHobLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmHobLib/AArch64/StandaloneMmCoreHobLibInternal.c
new file mode 100644
index 0000000..ac5a1c0
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmHobLib/AArch64/StandaloneMmCoreHobLibInternal.c
@@ -0,0 +1,64 @@
+/** @file
+  HOB Library implementation for Standalone MM Core.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2018, ARM Limited. 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.
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Guid/MemoryAllocationHob.h>
+
+//
+// Cache copy of HobList pointer.
+//
+extern VOID *gHobList;
+
+EFI_HOB_HANDOFF_INFO_TABLE*
+HobConstructor (
+  IN VOID   *EfiMemoryBegin,
+  IN UINTN  EfiMemoryLength,
+  IN VOID   *EfiFreeMemoryBottom,
+  IN VOID   *EfiFreeMemoryTop
+  )
+{
+  EFI_HOB_HANDOFF_INFO_TABLE  *Hob;
+  EFI_HOB_GENERIC_HEADER      *HobEnd;
+
+  Hob    = EfiFreeMemoryBottom;
+  HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1);
+
+  Hob->Header.HobType     = EFI_HOB_TYPE_HANDOFF;
+  Hob->Header.HobLength   = sizeof(EFI_HOB_HANDOFF_INFO_TABLE);
+  Hob->Header.Reserved    = 0;
+
+  HobEnd->HobType     = EFI_HOB_TYPE_END_OF_HOB_LIST;
+  HobEnd->HobLength   = sizeof(EFI_HOB_GENERIC_HEADER);
+  HobEnd->Reserved    = 0;
+
+  Hob->Version             = EFI_HOB_HANDOFF_TABLE_VERSION;
+  Hob->BootMode            = BOOT_WITH_FULL_CONFIGURATION;
+
+  Hob->EfiMemoryTop        = (UINTN)EfiMemoryBegin + EfiMemoryLength;
+  Hob->EfiMemoryBottom     = (UINTN)EfiMemoryBegin;
+  Hob->EfiFreeMemoryTop    = (UINTN)EfiFreeMemoryTop;
+  Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1);
+  Hob->EfiEndOfHobList     = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
+
+  gHobList = Hob;
+
+  return Hob;
+}
diff --git a/StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.c b/StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.c
new file mode 100644
index 0000000..e399058
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.c
@@ -0,0 +1,651 @@
+/** @file
+  HOB Library implementation for Standalone MM Core.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2018, ARM Limited. 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.
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Guid/MemoryAllocationHob.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+EFI_MM_SYSTEM_TABLE   *gMmst = NULL;
+
+/**
+  The constructor function caches the pointer to HOB list.
+
+  The constructor function gets the start address of HOB list from system configuration table.
+  It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor successfully gets HobList.
+  @retval Other value   The constructor can't get HobList.
+
+**/
+EFI_STATUS
+EFIAPI
+HobLibConstructor (
+  IN EFI_HANDLE             ImageHandle,
+  IN EFI_MM_SYSTEM_TABLE  *SmmSystemTable
+  )
+{
+  UINTN       Index;
+
+  for (Index = 0; Index < gMmst->NumberOfTableEntries; Index++) {
+    if (CompareGuid (&gEfiHobListGuid, &gMmst->MmConfigurationTable[Index].VendorGuid)) {
+      gHobList = gMmst->MmConfigurationTable[Index].VendorTable;
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+/**
+  Returns the pointer to the HOB list.
+
+  This function returns the pointer to first HOB in the list.
+  If the pointer to the HOB list is NULL, then ASSERT().
+
+  @return The pointer to the HOB list.
+
+**/
+VOID *
+EFIAPI
+GetHobList (
+  VOID
+  )
+{
+  UINTN       Index;
+
+  if (gHobList == NULL) {
+    for (Index = 0; Index < gMmst->NumberOfTableEntries; Index++) {
+      if (CompareGuid (&gEfiHobListGuid, &gMmst->MmConfigurationTable[Index].VendorGuid)) {
+        gHobList = gMmst->MmConfigurationTable[Index].VendorTable;
+        break;
+      }
+    }
+  }
+  ASSERT (gHobList != NULL);
+  return gHobList;
+}
+
+/**
+  Returns the next instance of a HOB type from the starting HOB.
+
+  This function searches the first instance of a HOB type from the starting HOB pointer.
+  If there does not exist such HOB type from the starting HOB pointer, it will return NULL.
+  In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
+  unconditionally: it returns HobStart back if HobStart itself meets the requirement;
+  caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+
+  If HobStart is NULL, then ASSERT().
+
+  @param  Type          The HOB type to return.
+  @param  HobStart      The starting HOB pointer to search from.
+
+  @return The next instance of a HOB type from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetNextHob (
+  IN UINT16                 Type,
+  IN CONST VOID             *HobStart
+  )
+{
+  EFI_PEI_HOB_POINTERS  Hob;
+
+  ASSERT (HobStart != NULL);
+
+  Hob.Raw = (UINT8 *) HobStart;
+  //
+  // Parse the HOB list until end of list or matching type is found.
+  //
+  while (!END_OF_HOB_LIST (Hob)) {
+    if (Hob.Header->HobType == Type) {
+      return Hob.Raw;
+    }
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+  return NULL;
+}
+
+/**
+  Returns the first instance of a HOB type among the whole HOB list.
+
+  This function searches the first instance of a HOB type among the whole HOB list.
+  If there does not exist such HOB type in the HOB list, it will return NULL.
+
+  If the pointer to the HOB list is NULL, then ASSERT().
+
+  @param  Type          The HOB type to return.
+
+  @return The next instance of a HOB type from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetFirstHob (
+  IN UINT16                 Type
+  )
+{
+  VOID      *HobList;
+
+  HobList = GetHobList ();
+  return GetNextHob (Type, HobList);
+}
+
+/**
+  Returns the next instance of the matched GUID HOB from the starting HOB.
+
+  This function searches the first instance of a HOB from the starting HOB pointer.
+  Such HOB should satisfy two conditions:
+  its HOB type is EFI_HOB_TYPE_GUID_EXTENSION, and its GUID Name equals to the input Guid.
+  If such a HOB from the starting HOB pointer does not exist, it will return NULL.
+  Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
+  to extract the data section and its size information, respectively.
+  In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
+  unconditionally: it returns HobStart back if HobStart itself meets the requirement;
+  caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+
+  If Guid is NULL, then ASSERT().
+  If HobStart is NULL, then ASSERT().
+
+  @param  Guid          The GUID to match with in the HOB list.
+  @param  HobStart      A pointer to a Guid.
+
+  @return The next instance of the matched GUID HOB from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetNextGuidHob (
+  IN CONST EFI_GUID         *Guid,
+  IN CONST VOID             *HobStart
+  )
+{
+  EFI_PEI_HOB_POINTERS  GuidHob;
+
+  GuidHob.Raw = (UINT8 *) HobStart;
+  while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) {
+    if (CompareGuid (Guid, &GuidHob.Guid->Name)) {
+      break;
+    }
+    GuidHob.Raw = GET_NEXT_HOB (GuidHob);
+  }
+  return GuidHob.Raw;
+}
+
+/**
+  Returns the first instance of the matched GUID HOB among the whole HOB list.
+
+  This function searches the first instance of a HOB among the whole HOB list.
+  Such HOB should satisfy two conditions:
+  its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
+  If such a HOB from the starting HOB pointer does not exist, it will return NULL.
+  Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
+  to extract the data section and its size information, respectively.
+
+  If the pointer to the HOB list is NULL, then ASSERT().
+  If Guid is NULL, then ASSERT().
+
+  @param  Guid          The GUID to match with in the HOB list.
+
+  @return The first instance of the matched GUID HOB among the whole HOB list.
+
+**/
+VOID *
+EFIAPI
+GetFirstGuidHob (
+  IN CONST EFI_GUID         *Guid
+  )
+{
+  VOID      *HobList;
+
+  HobList = GetHobList ();
+  return GetNextGuidHob (Guid, HobList);
+}
+
+/**
+  Get the system boot mode from the HOB list.
+
+  This function returns the system boot mode information from the
+  PHIT HOB in HOB list.
+
+  If the pointer to the HOB list is NULL, then ASSERT().
+
+  @param  VOID
+
+  @return The Boot Mode.
+
+**/
+EFI_BOOT_MODE
+EFIAPI
+GetBootModeHob (
+  VOID
+  )
+{
+  EFI_HOB_HANDOFF_INFO_TABLE    *HandOffHob;
+
+  HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList ();
+
+  return HandOffHob->BootMode;
+}
+
+VOID *
+CreateHob (
+  IN  UINT16    HobType,
+  IN  UINT16    HobLength
+  )
+{
+  EFI_HOB_HANDOFF_INFO_TABLE  *HandOffHob;
+  EFI_HOB_GENERIC_HEADER      *HobEnd;
+  EFI_PHYSICAL_ADDRESS        FreeMemory;
+  VOID                        *Hob;
+
+  HandOffHob = GetHobList ();
+
+  HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+
+  FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
+
+  if (FreeMemory < HobLength) {
+    return NULL;
+  }
+
+  Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
+  ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType;
+  ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength;
+  ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0;
+
+  HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength);
+  HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+  HobEnd->HobType   = EFI_HOB_TYPE_END_OF_HOB_LIST;
+  HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER);
+  HobEnd->Reserved  = 0;
+  HobEnd++;
+  HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+  return Hob;
+}
+
+/**
+  Builds a HOB for a loaded PE32 module.
+
+  This function builds a HOB for a loaded PE32 module.
+  If ModuleName is NULL, then ASSERT().
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  ModuleName              The GUID File Name of the module.
+  @param  MemoryAllocationModule  The 64 bit physical address of the module.
+  @param  ModuleLength            The length of the module in bytes.
+  @param  EntryPoint              The 64 bit physical address of the module entry point.
+
+**/
+VOID
+EFIAPI
+BuildModuleHob (
+  IN CONST EFI_GUID         *ModuleName,
+  IN EFI_PHYSICAL_ADDRESS   MemoryAllocationModule,
+  IN UINT64                 ModuleLength,
+  IN EFI_PHYSICAL_ADDRESS   EntryPoint
+  )
+{
+  EFI_HOB_MEMORY_ALLOCATION_MODULE  *Hob;
+
+  ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) &&
+          ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0));
+
+  Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
+
+  CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
+  Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
+  Hob->MemoryAllocationHeader.MemoryLength      = ModuleLength;
+  Hob->MemoryAllocationHeader.MemoryType        = EfiBootServicesCode;
+
+  //
+  // Zero the reserved space to match HOB spec
+  //
+  ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved));
+
+  CopyGuid (&Hob->ModuleName, ModuleName);
+  Hob->EntryPoint = EntryPoint;
+}
+
+/**
+  Builds a HOB that describes a chunk of system memory.
+
+  This function builds a HOB that describes a chunk of system memory.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  ResourceType        The type of resource described by this HOB.
+  @param  ResourceAttribute   The resource attributes of the memory described by this HOB.
+  @param  PhysicalStart       The 64 bit physical address of memory described by this HOB.
+  @param  NumberOfBytes       The length of the memory described by this HOB in bytes.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorHob (
+  IN EFI_RESOURCE_TYPE            ResourceType,
+  IN EFI_RESOURCE_ATTRIBUTE_TYPE  ResourceAttribute,
+  IN EFI_PHYSICAL_ADDRESS         PhysicalStart,
+  IN UINT64                       NumberOfBytes
+  )
+{
+  EFI_HOB_RESOURCE_DESCRIPTOR  *Hob;
+
+  Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
+  ASSERT (Hob != NULL);
+
+  Hob->ResourceType      = ResourceType;
+  Hob->ResourceAttribute = ResourceAttribute;
+  Hob->PhysicalStart     = PhysicalStart;
+  Hob->ResourceLength    = NumberOfBytes;
+}
+
+/**
+  Builds a GUID HOB with a certain data length.
+
+  This function builds a customized HOB tagged with a GUID for identification
+  and returns the start address of GUID HOB data so that caller can fill the customized data.
+  The HOB Header and Name field is already stripped.
+  If Guid is NULL, then ASSERT().
+  If there is no additional space for HOB creation, then ASSERT().
+  If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+
+  @param  Guid          The GUID to tag the customized HOB.
+  @param  DataLength    The size of the data payload for the GUID HOB.
+
+  @return The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidHob (
+  IN CONST EFI_GUID              *Guid,
+  IN UINTN                       DataLength
+  )
+{
+  EFI_HOB_GUID_TYPE *Hob;
+
+  //
+  // Make sure that data length is not too long.
+  //
+  ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
+
+  Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
+  CopyGuid (&Hob->Name, Guid);
+  return Hob + 1;
+}
+
+
+/**
+  Copies a data buffer to a newly-built HOB.
+
+  This function builds a customized HOB tagged with a GUID for identification,
+  copies the input data to the HOB data field and returns the start address of the GUID HOB data.
+  The HOB Header and Name field is already stripped.
+  If Guid is NULL, then ASSERT().
+  If Data is NULL and DataLength > 0, then ASSERT().
+  If there is no additional space for HOB creation, then ASSERT().
+  If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+
+  @param  Guid          The GUID to tag the customized HOB.
+  @param  Data          The data to be copied into the data field of the GUID HOB.
+  @param  DataLength    The size of the data payload for the GUID HOB.
+
+  @return The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidDataHob (
+  IN CONST EFI_GUID              *Guid,
+  IN VOID                        *Data,
+  IN UINTN                       DataLength
+  )
+{
+  VOID  *HobData;
+
+  ASSERT (Data != NULL || DataLength == 0);
+
+  HobData = BuildGuidHob (Guid, DataLength);
+
+  return CopyMem (HobData, Data, DataLength);
+}
+
+/**
+  Builds a Firmware Volume HOB.
+
+  This function builds a Firmware Volume HOB.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  BaseAddress   The base address of the Firmware Volume.
+  @param  Length        The size of the Firmware Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildFvHob (
+  IN EFI_PHYSICAL_ADDRESS        BaseAddress,
+  IN UINT64                      Length
+  )
+{
+  EFI_HOB_FIRMWARE_VOLUME  *Hob;
+
+  Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
+
+  Hob->BaseAddress = BaseAddress;
+  Hob->Length      = Length;
+}
+
+
+/**
+  Builds a EFI_HOB_TYPE_FV2 HOB.
+
+  This function builds a EFI_HOB_TYPE_FV2 HOB.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  BaseAddress   The base address of the Firmware Volume.
+  @param  Length        The size of the Firmware Volume in bytes.
+  @param  FvName       The name of the Firmware Volume.
+  @param  FileName      The name of the file.
+
+**/
+VOID
+EFIAPI
+BuildFv2Hob (
+  IN          EFI_PHYSICAL_ADDRESS        BaseAddress,
+  IN          UINT64                      Length,
+  IN CONST    EFI_GUID                    *FvName,
+  IN CONST    EFI_GUID                    *FileName
+  )
+{
+  EFI_HOB_FIRMWARE_VOLUME2  *Hob;
+
+  Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
+
+  Hob->BaseAddress = BaseAddress;
+  Hob->Length      = Length;
+  CopyGuid (&Hob->FvName, FvName);
+  CopyGuid (&Hob->FileName, FileName);
+}
+
+
+/**
+  Builds a HOB for the CPU.
+
+  This function builds a HOB for the CPU.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  SizeOfMemorySpace   The maximum physical memory addressability of the processor.
+  @param  SizeOfIoSpace       The maximum physical I/O addressability of the processor.
+
+**/
+VOID
+EFIAPI
+BuildCpuHob (
+  IN UINT8                       SizeOfMemorySpace,
+  IN UINT8                       SizeOfIoSpace
+  )
+{
+  EFI_HOB_CPU  *Hob;
+
+  Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
+
+  Hob->SizeOfMemorySpace = SizeOfMemorySpace;
+  Hob->SizeOfIoSpace     = SizeOfIoSpace;
+
+  //
+  // Zero the reserved space to match HOB spec
+  //
+  ZeroMem (Hob->Reserved, sizeof (Hob->Reserved));
+}
+
+/**
+  Builds a HOB for the memory allocation.
+
+  This function builds a HOB for the memory allocation.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  BaseAddress   The 64 bit physical address of the memory.
+  @param  Length        The length of the memory allocation in bytes.
+  @param  MemoryType    Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildMemoryAllocationHob (
+  IN EFI_PHYSICAL_ADDRESS        BaseAddress,
+  IN UINT64                      Length,
+  IN EFI_MEMORY_TYPE             MemoryType
+  )
+{
+  EFI_HOB_MEMORY_ALLOCATION  *Hob;
+
+  ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
+          ((Length & (EFI_PAGE_SIZE - 1)) == 0));
+
+  Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
+
+  ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+  Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+  Hob->AllocDescriptor.MemoryLength      = Length;
+  Hob->AllocDescriptor.MemoryType        = MemoryType;
+  //
+  // Zero the reserved space to match HOB spec
+  //
+  ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
+}
+
+/**
+  Builds a HOB that describes a chunk of system memory with Owner GUID.
+
+  This function builds a HOB that describes a chunk of system memory.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  ResourceType        The type of resource described by this HOB.
+  @param  ResourceAttribute   The resource attributes of the memory described by this HOB.
+  @param  PhysicalStart       The 64 bit physical address of memory described by this HOB.
+  @param  NumberOfBytes       The length of the memory described by this HOB in bytes.
+  @param  OwnerGUID           GUID for the owner of this resource.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorWithOwnerHob (
+  IN EFI_RESOURCE_TYPE            ResourceType,
+  IN EFI_RESOURCE_ATTRIBUTE_TYPE  ResourceAttribute,
+  IN EFI_PHYSICAL_ADDRESS         PhysicalStart,
+  IN UINT64                       NumberOfBytes,
+  IN EFI_GUID                     *OwnerGUID
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Builds a Capsule Volume HOB.
+
+  This function builds a Capsule Volume HOB.
+  If the platform does not support Capsule Volume HOBs, then ASSERT().
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  BaseAddress   The base address of the Capsule Volume.
+  @param  Length        The size of the Capsule Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildCvHob (
+  IN EFI_PHYSICAL_ADDRESS        BaseAddress,
+  IN UINT64                      Length
+  )
+{
+  ASSERT (FALSE);
+}
+
+
+/**
+  Builds a HOB for the BSP store.
+
+  This function builds a HOB for BSP store.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  BaseAddress   The 64 bit physical address of the BSP.
+  @param  Length        The length of the BSP store in bytes.
+  @param  MemoryType    Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildBspStoreHob (
+  IN EFI_PHYSICAL_ADDRESS        BaseAddress,
+  IN UINT64                      Length,
+  IN EFI_MEMORY_TYPE             MemoryType
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Builds a HOB for the Stack.
+
+  This function builds a HOB for the stack.
+  If there is no additional space for HOB creation, then ASSERT().
+
+  @param  BaseAddress   The 64 bit physical address of the Stack.
+  @param  Length        The length of the stack in bytes.
+
+**/
+VOID
+EFIAPI
+BuildStackHob (
+  IN EFI_PHYSICAL_ADDRESS        BaseAddress,
+  IN UINT64                      Length
+  )
+{
+  ASSERT (FALSE);
+}
diff --git a/StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf b/StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf
new file mode 100644
index 0000000..d73188e
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Instance of HOB Library for Standalone MM Core.
+#
+# HOB Library implementation for the Standalone MM Core. Does not have a constructor.
+#  Uses gHobList defined in the Standalone MM Core Entry Point Library.
+#
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2018, ARM Limited. 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.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = HobLib
+  FILE_GUID                      = 8262551B-AB2D-4E76-99FC-5EBB83F4988E
+  MODULE_TYPE                    = MM_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  LIBRARY_CLASS                  = HobLib|MM_STANDALONE
+  CONSTRUCTOR                    = HobLibConstructor
+#
+#  VALID_ARCHITECTURES           = AARCH64
+#
+[Sources.Common]
+  StandaloneMmHobLib.c
+
+[Sources.AARCH64]
+  AArch64/StandaloneMmCoreHobLibInternal.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  MmServicesTableLib
+
+[Guids]
+  gEfiHobListGuid                               ## CONSUMES  ## SystemTable
diff --git a/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c
new file mode 100644
index 0000000..1efdc94
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c
@@ -0,0 +1,823 @@
+/** @file
+  Support routines for memory allocation routines based on Standalone MM Core internal functions.
+
+  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, ARM Limited. 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.
+
+**/
+
+#include <PiMm.h>
+
+#include <Guid/MmramMemoryReserve.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+extern EFI_MM_SYSTEM_TABLE   *gMmst;
+
+/**
+  Allocates one or more 4KB pages of a certain memory type.
+
+  Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
+  buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL is returned.
+  If there is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  @param  MemoryType            The type of memory to allocate.
+  @param  Pages                 The number of 4 KB pages to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+InternalAllocatePages (
+  IN EFI_MEMORY_TYPE  MemoryType,
+  IN UINTN            Pages
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  Memory;
+
+  if (Pages == 0) {
+    return NULL;
+  }
+
+  Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+  return (VOID *) (UINTN) Memory;
+}
+
+/**
+  Allocates one or more 4KB pages of type EfiBootServicesData.
+
+  Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
+  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
+  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
+  returned.
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocatePages (
+  IN UINTN  Pages
+  )
+{
+  return InternalAllocatePages (EfiRuntimeServicesData, Pages);
+}
+
+/**
+  Allocates one or more 4KB pages of type EfiRuntimeServicesData.
+
+  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
+  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
+  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
+  returned.
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateRuntimePages (
+  IN UINTN  Pages
+  )
+{
+  return InternalAllocatePages (EfiRuntimeServicesData, Pages);
+}
+
+/**
+  Allocates one or more 4KB pages of type EfiReservedMemoryType.
+
+  Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
+  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
+  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
+  returned.
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateReservedPages (
+  IN UINTN  Pages
+  )
+{
+  return NULL;
+}
+
+/**
+  Frees one or more 4KB pages that were previously allocated with one of the page allocation
+  functions in the Memory Allocation Library.
+
+  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
+  must have been allocated on a previous call to the page allocation services of the Memory
+  Allocation Library.  If it is not possible to free allocated pages, then this function will
+  perform no actions.
+
+  If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
+  then ASSERT().
+  If Pages is zero, then ASSERT().
+
+  @param  Buffer                Pointer to the buffer of pages to free.
+  @param  Pages                 The number of 4 KB pages to free.
+
+**/
+VOID
+EFIAPI
+FreePages (
+  IN VOID   *Buffer,
+  IN UINTN  Pages
+  )
+{
+  EFI_STATUS  Status;
+
+  ASSERT (Pages != 0);
+  Status = gMmst->MmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Allocates one or more 4KB pages of a certain memory type at a specified alignment.
+
+  Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
+  specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is returned.
+  If there is not enough memory at the specified alignment remaining to satisfy the request, then
+  NULL is returned.
+  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
+
+  @param  MemoryType            The type of memory to allocate.
+  @param  Pages                 The number of 4 KB pages to allocate.
+  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
+                                If Alignment is zero, then byte alignment is used.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+InternalAllocateAlignedPages (
+  IN EFI_MEMORY_TYPE  MemoryType,
+  IN UINTN            Pages,
+  IN UINTN            Alignment
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  Memory;
+  UINTN                 AlignedMemory;
+  UINTN                 AlignmentMask;
+  UINTN                 UnalignedPages;
+  UINTN                 RealPages;
+
+  //
+  // Alignment must be a power of two or zero.
+  //
+  ASSERT ((Alignment & (Alignment - 1)) == 0);
+
+  if (Pages == 0) {
+    return NULL;
+  }
+  if (Alignment > EFI_PAGE_SIZE) {
+    //
+    // Calculate the total number of pages since alignment is larger than page size.
+    //
+    AlignmentMask  = Alignment - 1;
+    RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);
+    //
+    // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
+    //
+    ASSERT (RealPages > Pages);
+
+    Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
+    if (EFI_ERROR (Status)) {
+      return NULL;
+    }
+    AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
+    UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
+    if (UnalignedPages > 0) {
+      //
+      // Free first unaligned page(s).
+      //
+      Status = gMmst->MmFreePages (Memory, UnalignedPages);
+      ASSERT_EFI_ERROR (Status);
+    }
+    Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
+    UnalignedPages = RealPages - Pages - UnalignedPages;
+    if (UnalignedPages > 0) {
+      //
+      // Free last unaligned page(s).
+      //
+      Status = gMmst->MmFreePages (Memory, UnalignedPages);
+      ASSERT_EFI_ERROR (Status);
+    }
+  } else {
+    //
+    // Do not over-allocate pages in this case.
+    //
+    Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
+    if (EFI_ERROR (Status)) {
+      return NULL;
+    }
+    AlignedMemory  = (UINTN) Memory;
+  }
+  return (VOID *) AlignedMemory;
+}
+
+/**
+  Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
+
+  Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
+  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
+  returned.  If there is not enough memory at the specified alignment remaining to satisfy the
+  request, then NULL is returned.
+
+  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
+                                If Alignment is zero, then byte alignment is used.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateAlignedPages (
+  IN UINTN  Pages,
+  IN UINTN  Alignment
+  )
+{
+  return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
+}
+
+/**
+  Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
+
+  Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
+  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
+  returned.  If there is not enough memory at the specified alignment remaining to satisfy the
+  request, then NULL is returned.
+
+  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
+                                If Alignment is zero, then byte alignment is used.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateAlignedRuntimePages (
+  IN UINTN  Pages,
+  IN UINTN  Alignment
+  )
+{
+  return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
+}
+
+/**
+  Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
+
+  Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
+  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
+  returned.  If there is not enough memory at the specified alignment remaining to satisfy the
+  request, then NULL is returned.
+
+  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
+                                If Alignment is zero, then byte alignment is used.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateAlignedReservedPages (
+  IN UINTN  Pages,
+  IN UINTN  Alignment
+  )
+{
+  return NULL;
+}
+
+/**
+  Frees one or more 4KB pages that were previously allocated with one of the aligned page
+  allocation functions in the Memory Allocation Library.
+
+  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
+  must have been allocated on a previous call to the aligned page allocation services of the Memory
+  Allocation Library.  If it is not possible to free allocated pages, then this function will
+  perform no actions.
+
+  If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
+  Library, then ASSERT().
+  If Pages is zero, then ASSERT().
+
+  @param  Buffer                Pointer to the buffer of pages to free.
+  @param  Pages                 The number of 4 KB pages to free.
+
+**/
+VOID
+EFIAPI
+FreeAlignedPages (
+  IN VOID   *Buffer,
+  IN UINTN  Pages
+  )
+{
+  EFI_STATUS  Status;
+
+  ASSERT (Pages != 0);
+  Status = gMmst->MmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Allocates a buffer of a certain pool type.
+
+  Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
+  pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
+  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  @param  MemoryType            The type of memory to allocate.
+  @param  AllocationSize        The number of bytes to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+InternalAllocatePool (
+  IN EFI_MEMORY_TYPE  MemoryType,
+  IN UINTN            AllocationSize
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *Memory;
+
+  Memory = NULL;
+
+  Status = gMmst->MmAllocatePool (MemoryType, AllocationSize, &Memory);
+  if (EFI_ERROR (Status)) {
+    Memory = NULL;
+  }
+  return Memory;
+}
+
+/**
+  Allocates a buffer of type EfiBootServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
+  pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
+  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocatePool (
+  IN UINTN  AllocationSize
+  )
+{
+  return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
+}
+
+/**
+  Allocates a buffer of type EfiRuntimeServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
+  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
+  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateRuntimePool (
+  IN UINTN  AllocationSize
+  )
+{
+  return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
+}
+
+/**
+  Allocates a buffer of type EfiReservedMemoryType.
+
+  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
+  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
+  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateReservedPool (
+  IN UINTN  AllocationSize
+  )
+{
+  return NULL;
+}
+
+/**
+  Allocates and zeros a buffer of a certain pool type.
+
+  Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
+  with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a valid
+  buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the request,
+  then NULL is returned.
+
+  @param  PoolType              The type of memory to allocate.
+  @param  AllocationSize        The number of bytes to allocate and zero.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+InternalAllocateZeroPool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            AllocationSize
+  )
+{
+  VOID  *Memory;
+
+  Memory = InternalAllocatePool (PoolType, AllocationSize);
+  if (Memory != NULL) {
+    Memory = ZeroMem (Memory, AllocationSize);
+  }
+  return Memory;
+}
+
+/**
+  Allocates and zeros a buffer of type EfiBootServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
+  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
+  request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateZeroPool (
+  IN UINTN  AllocationSize
+  )
+{
+  return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
+}
+
+/**
+  Allocates and zeros a buffer of type EfiRuntimeServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
+  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
+  request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateRuntimeZeroPool (
+  IN UINTN  AllocationSize
+  )
+{
+  return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
+}
+
+/**
+  Allocates and zeros a buffer of type EfiReservedMemoryType.
+
+  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
+  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
+  request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateReservedZeroPool (
+  IN UINTN  AllocationSize
+  )
+{
+  return NULL;
+}
+
+/**
+  Copies a buffer to an allocated buffer of a certain pool type.
+
+  Allocates the number bytes specified by AllocationSize of a certain pool type, copies
+  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
+  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
+  is not enough memory remaining to satisfy the request, then NULL is returned.
+  If Buffer is NULL, then ASSERT().
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  PoolType              The type of pool to allocate.
+  @param  AllocationSize        The number of bytes to allocate and zero.
+  @param  Buffer                The buffer to copy to the allocated buffer.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+InternalAllocateCopyPool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            AllocationSize,
+  IN CONST VOID       *Buffer
+  )
+{
+  VOID  *Memory;
+
+  ASSERT (Buffer != NULL);
+  ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
+
+  Memory = InternalAllocatePool (PoolType, AllocationSize);
+  if (Memory != NULL) {
+    Memory = CopyMem (Memory, Buffer, AllocationSize);
+  }
+  return Memory;
+}
+
+/**
+  Copies a buffer to an allocated buffer of type EfiBootServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
+  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
+  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
+  is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  If Buffer is NULL, then ASSERT().
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+  @param  Buffer                The buffer to copy to the allocated buffer.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateCopyPool (
+  IN UINTN       AllocationSize,
+  IN CONST VOID  *Buffer
+  )
+{
+  return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
+}
+
+/**
+  Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
+  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
+  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
+  is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  If Buffer is NULL, then ASSERT().
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+  @param  Buffer                The buffer to copy to the allocated buffer.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateRuntimeCopyPool (
+  IN UINTN       AllocationSize,
+  IN CONST VOID  *Buffer
+  )
+{
+  return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
+}
+
+/**
+  Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
+
+  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
+  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
+  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
+  is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  If Buffer is NULL, then ASSERT().
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+  @param  Buffer                The buffer to copy to the allocated buffer.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateReservedCopyPool (
+  IN UINTN       AllocationSize,
+  IN CONST VOID  *Buffer
+  )
+{
+  return NULL;
+}
+
+/**
+  Reallocates a buffer of a specified memory type.
+
+  Allocates and zeros the number bytes specified by NewSize from memory of the type
+  specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
+  enough memory remaining to satisfy the request, then NULL is returned.
+
+  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
+  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
+
+  @param  PoolType       The type of pool to allocate.
+  @param  OldSize        The size, in bytes, of OldBuffer.
+  @param  NewSize        The size, in bytes, of the buffer to reallocate.
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
+                         parameter that may be NULL.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+InternalReallocatePool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            OldSize,
+  IN UINTN            NewSize,
+  IN VOID             *OldBuffer  OPTIONAL
+  )
+{
+  VOID  *NewBuffer;
+
+  NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
+  if (NewBuffer != NULL && OldBuffer != NULL) {
+    CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
+    FreePool (OldBuffer);
+  }
+  return NewBuffer;
+}
+
+/**
+  Reallocates a buffer of type EfiBootServicesData.
+
+  Allocates and zeros the number bytes specified by NewSize from memory of type
+  EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
+  enough memory remaining to satisfy the request, then NULL is returned.
+
+  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
+  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
+
+  @param  OldSize        The size, in bytes, of OldBuffer.
+  @param  NewSize        The size, in bytes, of the buffer to reallocate.
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
+                         parameter that may be NULL.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+ReallocatePool (
+  IN UINTN  OldSize,
+  IN UINTN  NewSize,
+  IN VOID   *OldBuffer  OPTIONAL
+  )
+{
+  return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
+}
+
+/**
+  Reallocates a buffer of type EfiRuntimeServicesData.
+
+  Allocates and zeros the number bytes specified by NewSize from memory of type
+  EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
+  enough memory remaining to satisfy the request, then NULL is returned.
+
+  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
+  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
+
+  @param  OldSize        The size, in bytes, of OldBuffer.
+  @param  NewSize        The size, in bytes, of the buffer to reallocate.
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
+                         parameter that may be NULL.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+ReallocateRuntimePool (
+  IN UINTN  OldSize,
+  IN UINTN  NewSize,
+  IN VOID   *OldBuffer  OPTIONAL
+  )
+{
+  return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
+}
+
+/**
+  Reallocates a buffer of type EfiReservedMemoryType.
+
+  Allocates and zeros the number bytes specified by NewSize from memory of type
+  EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize and
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
+  enough memory remaining to satisfy the request, then NULL is returned.
+
+  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
+  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
+
+  @param  OldSize        The size, in bytes, of OldBuffer.
+  @param  NewSize        The size, in bytes, of the buffer to reallocate.
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
+                         parameter that may be NULL.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+ReallocateReservedPool (
+  IN UINTN  OldSize,
+  IN UINTN  NewSize,
+  IN VOID   *OldBuffer  OPTIONAL
+  )
+{
+  return NULL;
+}
+
+/**
+  Frees a buffer that was previously allocated with one of the pool allocation functions in the
+  Memory Allocation Library.
+
+  Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
+  pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
+  resources, then this function will perform no actions.
+
+  If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
+  then ASSERT().
+
+  @param  Buffer                Pointer to the buffer to free.
+
+**/
+VOID
+EFIAPI
+FreePool (
+  IN VOID   *Buffer
+  )
+{
+  EFI_STATUS    Status;
+
+  Status = gMmst->MmFreePool (Buffer);
+  ASSERT_EFI_ERROR (Status);
+}
diff --git a/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
new file mode 100644
index 0000000..9ac03df
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
@@ -0,0 +1,45 @@
+## @file
+# Memory Allocation Library instance dedicated to MM Core.
+# The implementation borrows the MM Core Memory Allocation services as the primitive
+# for memory allocation instead of using MM System Table servces in an indirect way.
+# It is assumed that this library instance must be linked with MM Core in this package.
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2018, ARM Limited. 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = MemoryAllocationLib
+  FILE_GUID                      = 54646378-A9DC-473F-9BE1-BD027C4C76DE
+  MODULE_TYPE                    = MM_CORE_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  LIBRARY_CLASS                  = MemoryAllocationLib|MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
+#
+
+[Sources]
+  StandaloneMmMemoryAllocationLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  MmServicesTableLib
+  HobLib
diff --git a/StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c b/StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
new file mode 100644
index 0000000..e0e0044
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
@@ -0,0 +1,64 @@
+/** @file
+  MM Core MM Services Table Library.
+
+  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, ARM Limited. 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.
+
+**/
+
+#include <PiMm.h>
+#include <Library/DebugLib.h>
+
+extern EFI_MM_SYSTEM_TABLE         *gMmst;
+
+/**
+  The constructor function caches the pointer of MM Services Table.
+
+  @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 EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmServicesTableLibConstructor (
+  IN EFI_HANDLE             ImageHandle,
+  IN EFI_MM_SYSTEM_TABLE  *MmSystemTable
+  )
+{
+  gMmst = MmSystemTable;
+  return EFI_SUCCESS;
+}
+
+/**
+  This function allows the caller to determine if the driver is executing in
+  Standalone Management Mode(SMM).
+
+  This function returns TRUE if the driver is executing in SMM and FALSE if the
+  driver is not executing in SMM.
+
+  @retval  TRUE  The driver is executing in Standalone Management Mode (SMM).
+  @retval  FALSE The driver is not executing in Standalone Management Mode (SMM).
+
+**/
+BOOLEAN
+EFIAPI
+InMm (
+  VOID
+  )
+{
+  //
+  // We are already in Standalone MM
+  //
+  return TRUE;
+}
+
diff --git a/StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf b/StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
new file mode 100644
index 0000000..c362429
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
@@ -0,0 +1,36 @@
+## @file
+# MM Core MM Services Table Library.
+#
+# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2018, ARM Limited. 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.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = StandaloneMmServicesTableLib
+  FILE_GUID                      = BEE33A2F-F49D-4B71-AF3E-FFCCB9885DEA
+  MODULE_TYPE                    = MM_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  LIBRARY_CLASS                  = MmServicesTableLib|MM_STANDALONE
+  CONSTRUCTOR                    = StandaloneMmServicesTableLibConstructor
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
+#
+
+[Sources]
+  StandaloneMmServicesTableLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 03/11] MdeModulePkg: Add a PCD to indicate Standalone MM supports secure variable
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 01/11] StandaloneMmPkg: Remove MM_STANDALONE LIBRARY_CLASS from StandaloneMmCoreHobLib Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 02/11] StandaloneMmPkg: Adding the library packages used by MM_STANDALONE drivers Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library Jagadeesh Ujja
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Add a flag that indicates whether Standalone MM mode supports
secure storage of variables.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 MdeModulePkg/MdeModulePkg.dec | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 41d2b04..badea4a 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -1041,6 +1041,11 @@
   # @Prompt Enable UEFI Stack Guard.
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0x30001055
 
+  ## This flag indicates secure variable functionality is implemented by Standalone MM
+  #  TRUE  - Secure variable storage supported by Standalone MM code.
+  #  FALSE - Standalone MM code does not support secure storage of variables
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled|FALSE|BOOLEAN|0x30001056
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## Dynamic type PCD can be registered callback function for Pcd setting action.
   #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (2 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 03/11] MdeModulePkg: Add a PCD to indicate Standalone MM supports secure variable Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-03 11:03   ` Ard Biesheuvel
  2019-01-02 13:13 ` [PATCH v2 05/11] MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver Jagadeesh Ujja
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Some of the existing DXE drivers can be refactored to execute within
the Standalone MM execution environment as well. Allow such drivers to
get access to the Standalone MM services tables.

Add a mechanism to determine the execution mode is required.
i.e, in MM or non-MM

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
 MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
 MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
 MdePkg/MdePkg.dec                                                            |  4 ++
 4 files changed, 122 insertions(+)

diff --git a/MdePkg/Include/Library/StandaloneMmServicesTableLib.h b/MdePkg/Include/Library/StandaloneMmServicesTableLib.h
new file mode 100644
index 0000000..3a27ac4
--- /dev/null
+++ b/MdePkg/Include/Library/StandaloneMmServicesTableLib.h
@@ -0,0 +1,43 @@
+/** @file
+  Provides a service to retrieve a pointer to the Standalone MM Services Table.
+  Provides a InMm implementation for RUNTIME DXE drivers
+
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2016 - 2018, ARM Limited. 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 __MM_SERVICES_TABLE_LIB_H__
+#define __MM_SERVICES_TABLE_LIB_H__
+
+#include <PiMm.h>
+#include <PiDxe.h>
+
+extern EFI_MM_SYSTEM_TABLE         *gMmst;
+
+/**
+  This function allows the caller to determine if the driver is executing in
+  Standalone Management Mode(SMM).
+
+  This function returns TRUE if the driver is executing in SMM and FALSE if the
+  driver is not executing in SMM.
+
+  @retval  TRUE  The driver is executing in Standalone Management Mode (SMM).
+  @retval  FALSE The driver is not executing in Standalone Management Mode (SMM).
+
+**/
+BOOLEAN
+EFIAPI
+InMm (
+  VOID
+  );
+
+#endif
diff --git a/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
new file mode 100644
index 0000000..6f37cd8
--- /dev/null
+++ b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
@@ -0,0 +1,39 @@
+/** @file
+  Standalone MM Services Table Library.
+
+  Copyright (c) 2018, ARM Limited. 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.
+
+**/
+
+#include <PiDxe.h>
+#include <PiMm.h>
+
+EFI_MM_SYSTEM_TABLE         *gMmst = NULL;
+
+/**
+  This function allows the caller to determine if the driver is executing in
+  Standalone Management Mode(SMM).
+
+  This function returns TRUE if the driver is executing in SMM and FALSE if the
+  driver is not executing in SMM.
+
+  @retval  TRUE  The driver is executing in Standalone Management Mode (SMM).
+  @retval  FALSE The driver is not executing in Standalone Management Mode (SMM).
+
+**/
+BOOLEAN
+EFIAPI
+InMm (
+  VOID
+  )
+{
+  return FALSE;
+}
diff --git a/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
new file mode 100644
index 0000000..c94b605
--- /dev/null
+++ b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  Provides StandaloneMmServicesTableLib.
+#
+#  Copyright (c) 2018, ARM Limited. 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = StandaloneMmServicesTableLib
+  FILE_GUID                      = 8099cfbf-9564-4c9b-9052-e66b1da88930
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = StandaloneMmServicesTableLib |DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
+#
+
+[Sources]
+  StandaloneMmServicesTableLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 712bd46..ec9b266 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -243,6 +243,10 @@
   ##
   SafeIntLib|Include/Library/SafeIntLib.h
 
+  ## @libraryclass Provides a service to retrieve a pointer to the Standalone MM Services Table.
+  #                 Only available to MM_STANDALONE module types.
+  MmServicesTableLib|Include/Library/StandaloneMmServicesTableLib.h
+
 [LibraryClasses.IA32, LibraryClasses.X64]
   ##  @libraryclass  Abstracts both S/W SMI generation and detection.
   ##
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 05/11] MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (3 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 17:15   ` Ard Biesheuvel
  2019-01-02 13:13 ` [PATCH v2 06/11] MdeModulePkg/Variable/RuntimeDxe: adapt for usability with MM Standalone Jagadeesh Ujja
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Adapt the FaultTolerantWriteDxe driver to be used as a MM_STANDALONE
driver to provide UEFI fault tolerant write protocol functionality
for variable reclaim operation on EFI variables stored on a NOR flash
that is only accessible to code executing in MM Standalone mode.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf          |   1 +
 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c            | 203 +++++++++++++++-----
 MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf | 101 ++++++++++
 MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c               |  27 +--
 4 files changed, 271 insertions(+), 61 deletions(-)

diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
index dcde58d..026bc60 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
@@ -77,6 +77,7 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase      ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64    ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize      ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
 
 #
 # gBS->CalculateCrc32() is consumed in EntryPoint.
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
index 481fea3..33f99e6 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
@@ -44,6 +44,7 @@
   This driver need to make sure the CommBuffer is not in the SMRAM range.
 
 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2018, ARM Limited. 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
@@ -55,13 +56,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 
 #include <PiSmm.h>
+#include <PiMm.h>
 #include <Library/SmmServicesTableLib.h>
 #include <Library/SmmMemLib.h>
+#include <Library/StandaloneMmMemLib.h>
 #include <Library/BaseLib.h>
 #include <Protocol/SmmSwapAddressRange.h>
 #include "FaultTolerantWrite.h"
 #include "FaultTolerantWriteSmmCommon.h"
 #include <Protocol/SmmEndOfDxe.h>
+#include <Library/StandaloneMmServicesTableLib.h>
 
 EFI_EVENT                                 mFvbRegistration = NULL;
 EFI_FTW_DEVICE                            *mFtwDevice      = NULL;
@@ -92,11 +96,19 @@ FtwGetFvbByHandle (
   //
   // To get the SMM FVB protocol interface on the handle
   //
-  return gSmst->SmmHandleProtocol (
-                  FvBlockHandle,
-                  &gEfiSmmFirmwareVolumeBlockProtocolGuid,
-                  (VOID **) FvBlock
-                  );
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    return gSmst->SmmHandleProtocol (
+                    FvBlockHandle,
+                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                    (VOID **) FvBlock
+                    );
+  } else {
+    return gMmst->MmHandleProtocol (
+                    FvBlockHandle,
+                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                    (VOID **) FvBlock
+                    );
+  }
 }
 
 /**
@@ -119,11 +131,19 @@ FtwGetSarProtocol (
   //
   // Locate Smm Swap Address Range protocol
   //
-  Status = gSmst->SmmLocateProtocol (
-                    &gEfiSmmSwapAddressRangeProtocolGuid,
-                    NULL,
-                    SarProtocol
-                    );
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gSmst->SmmLocateProtocol (
+                      &gEfiSmmSwapAddressRangeProtocolGuid,
+                      NULL,
+                      SarProtocol
+                      );
+  } else {
+    Status = gMmst->MmLocateProtocol (
+                      &gEfiSmmSwapAddressRangeProtocolGuid,
+                      NULL,
+                      SarProtocol
+                      );
+  }
   return Status;
 }
 
@@ -158,13 +178,23 @@ GetFvbCountAndBuffer (
   BufferSize     = 0;
   *NumberHandles = 0;
   *Buffer        = NULL;
-  Status = gSmst->SmmLocateHandle (
-                    ByProtocol,
-                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
-                    NULL,
-                    &BufferSize,
-                    *Buffer
-                    );
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gSmst->SmmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  } else {
+    Status = gMmst->MmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  }
   if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
     return EFI_NOT_FOUND;
   }
@@ -173,15 +203,23 @@ GetFvbCountAndBuffer (
   if (*Buffer == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
-
-  Status = gSmst->SmmLocateHandle (
-                    ByProtocol,
-                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
-                    NULL,
-                    &BufferSize,
-                    *Buffer
-                    );
-
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gSmst->SmmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  } else {
+    Status = gMmst->MmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  }
   *NumberHandles = BufferSize / sizeof(EFI_HANDLE);
   if (EFI_ERROR(Status)) {
     *NumberHandles = 0;
@@ -335,10 +373,16 @@ SmmFaultTolerantWriteHandler (
     return EFI_SUCCESS;
   }
   CommBufferPayloadSize = TempCommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE;
-
-  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
-    DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
-    return EFI_SUCCESS;
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+      DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
+      return EFI_SUCCESS;
+    }
+  } else {
+    if (!MmIsBufferOutsideMmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+      DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
+      return EFI_SUCCESS;
+    }
   }
 
   SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)CommBuffer;
@@ -531,11 +575,19 @@ FvbNotificationEvent (
   // Just return to avoid install SMM FaultTolerantWriteProtocol again
   // if SMM Fault Tolerant Write protocol had been installed.
   //
-  Status = gSmst->SmmLocateProtocol (
-                    &gEfiSmmFaultTolerantWriteProtocolGuid,
-                    NULL,
-                    (VOID **) &FtwProtocol
-                    );
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gSmst->SmmLocateProtocol (
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,
+                      NULL,
+                      (VOID **) &FtwProtocol
+                      );
+  } else {
+    Status = gMmst->MmLocateProtocol (
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,
+                      NULL,
+                      (VOID **) &FtwProtocol
+                      );
+  }
   if (!EFI_ERROR (Status)) {
     return EFI_SUCCESS;
   }
@@ -551,31 +603,45 @@ FvbNotificationEvent (
   //
   // Install protocol interface
   //
-  Status = gSmst->SmmInstallProtocolInterface (
-                    &mFtwDevice->Handle,
-                    &gEfiSmmFaultTolerantWriteProtocolGuid,
-                    EFI_NATIVE_INTERFACE,
-                    &mFtwDevice->FtwInstance
-                    );
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gSmst->SmmInstallProtocolInterface (
+                      &mFtwDevice->Handle,
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &mFtwDevice->FtwInstance
+                      );
+  } else {
+    Status = gMmst->MmInstallProtocolInterface (
+                      &mFtwDevice->Handle,
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &mFtwDevice->FtwInstance
+                      );
+  }
   ASSERT_EFI_ERROR (Status);
 
   ///
   /// Register SMM FTW SMI handler
   ///
-  Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
-  ASSERT_EFI_ERROR (Status);
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
+    ASSERT_EFI_ERROR (Status);
 
-  //
-  // Notify the Ftw wrapper driver SMM Ftw is ready
-  //
-  FtwHandle = NULL;
-  Status = gBS->InstallProtocolInterface (
+    //
+    // Notify the Ftw wrapper driver SMM Ftw is ready
+    //
+    FtwHandle = NULL;
+    Status = gBS->InstallProtocolInterface (
                   &FtwHandle,
                   &gEfiSmmFaultTolerantWriteProtocolGuid,
                   EFI_NATIVE_INTERFACE,
                   NULL
                   );
-  ASSERT_EFI_ERROR (Status);
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    Status = gMmst->MmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
 
   return EFI_SUCCESS;
 }
@@ -655,3 +721,42 @@ SmmFaultTolerantWriteInitialize (
 
   return EFI_SUCCESS;
 }
+
+/**
+  This function is the entry point of the Fault Tolerant Write driver.
+
+  @param[in] ImageHandle        A handle for the image that is initializing this driver
+  @param[in] SystemTable        A pointer to the EFI system table
+
+  @retval EFI_SUCCESS           The initialization finished successfully.
+  @retval EFI_OUT_OF_RESOURCES  Allocate memory error
+  @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmFaultTolerantWriteInitialize (
+  IN EFI_HANDLE                           ImageHandle,
+  IN EFI_MM_SYSTEM_TABLE                  *SystemTable
+  )
+{
+  EFI_STATUS                              Status;
+
+  //
+  // Allocate private data structure for SMM FTW protocol and do some initialization
+  //
+  Status = InitFtwDevice (&mFtwDevice);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+  Status = gMmst->MmRegisterProtocolNotify (
+                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                    FvbNotificationEvent,
+                    &mFvbRegistration
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  FvbNotificationEvent (NULL, NULL, NULL);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
new file mode 100644
index 0000000..615f688
--- /dev/null
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
@@ -0,0 +1,101 @@
+## @file
+#   Fault Tolerant Write Smm Driver.
+#
+#   This driver installs SMM Fault Tolerant Write (FTW) protocol, which provides fault
+#   tolerant write capability in SMM environment for block devices. Its implementation
+#   depends on the full functionality SMM FVB protocol that support read, write/erase
+#   flash access.
+#
+# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018, ARM Limited. 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = FaultTolerantWriteMmStandalone
+  MODULE_UNI_FILE                = SmmFaultTolerantWriteDxe.uni
+  FILE_GUID                      = 470CB248-E8AC-473c-BB4F-81069A1FE6FD
+  MODULE_TYPE                    = MM_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  ENTRY_POINT                    = StandaloneMmFaultTolerantWriteInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
+#
+
+[Sources]
+  FtwMisc.c
+  UpdateWorkingBlock.c
+  FaultTolerantWrite.c
+  FaultTolerantWriteSmm.c
+  FaultTolerantWrite.h
+  FaultTolerantWriteSmmCommon.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+  MemoryAllocationLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  ReportStatusCodeLib
+  MemLib
+  StandaloneMmDriverEntryPoint
+  BaseLib
+  MmServicesTableLib
+
+[Guids]
+  #
+  # Signature in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
+  #
+  ## CONSUMES           ## GUID
+  ## PRODUCES           ## GUID
+  gEdkiiWorkingBlockSignatureGuid
+
+[Protocols]
+  gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable  ## SOMETIMES_CONSUMES
+  ## NOTIFY
+  ## CONSUMES
+  gEfiSmmFirmwareVolumeBlockProtocolGuid
+  ## PRODUCES
+  ## UNDEFINED # SmiHandlerRegister
+  gEfiSmmFaultTolerantWriteProtocolGuid
+  gEfiSmmEndOfDxeProtocolGuid                      ## CONSUMES
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable    ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase    ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize    ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase      ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64    ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize      ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
+#
+# gBS->CalculateCrc32() is consumed in EntryPoint.
+# PI spec said: When the DXE Foundation is notified that the EFI_RUNTIME_ARCH_PROTOCOL
+# has been installed, then the Boot Service CalculateCrc32() is available.
+# So add gEfiRuntimeArchProtocolGuid Depex here.
+#
+[Depex]
+  TRUE
+  #gEfiSmmFirmwareVolumeBlockProtocolGuid AND gEfiRuntimeArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SmmFaultTolerantWriteDxeExtra.uni
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
index 50d3421..9c98e57 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
@@ -3,6 +3,7 @@
    Internal functions to operate Working Block Space.
 
 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2018, ARM Limited. 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
@@ -57,19 +58,21 @@ InitializeLocalWorkSpaceHeader (
     );
   mWorkingBlockHeader.WriteQueueSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
 
-  //
-  // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
-  //
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    //
+    // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
+    //
 
-  //
-  // Calculate the Crc of woking block header
-  //
-  Status = gBS->CalculateCrc32 (
-                  &mWorkingBlockHeader,
-                  sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
-                  &mWorkingBlockHeader.Crc
-                  );
-  ASSERT_EFI_ERROR (Status);
+    //
+    // Calculate the Crc of woking block header
+    //
+    Status = gBS->CalculateCrc32 (
+                    &mWorkingBlockHeader,
+                    sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+                    &mWorkingBlockHeader.Crc
+                    );
+    ASSERT_EFI_ERROR (Status);
+  }
 
   mWorkingBlockHeader.WorkingBlockValid    = FTW_VALID_STATE;
   mWorkingBlockHeader.WorkingBlockInvalid  = FTW_INVALID_STATE;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 06/11] MdeModulePkg/Variable/RuntimeDxe: adapt for usability with MM Standalone
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (4 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 05/11] MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 07/11] MdeModulePkg/Variable/RuntimeDxe: adapt as a MM Standalone driver Jagadeesh Ujja
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Adapt the VariableSmmRuntimeDxe driver to communicate with a VariableSmm
driver that is implemented as a MM Standalone driver.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf    |  1 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   | 31 +++++++++++++-------
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf |  3 ++
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 7ef8a97..6bb35bb 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -131,6 +131,7 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxUserNvVariableSpaceSize           ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdBoottimeReservedNvVariableSpaceSize  ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## CONSUMES # statistic the information of variable.
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 85d655d..1902348 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -14,6 +14,8 @@
   InitCommunicateBuffer() is really function to check the variable data size.
 
 Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2018, ARM Limited. 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
@@ -179,7 +181,11 @@ SendCommunicateBuffer (
   SMM_VARIABLE_COMMUNICATE_HEADER           *SmmVariableFunctionHeader;
 
   CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
-  Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBuffer, &CommSize);
+  } else {
+    Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);
+  }
   ASSERT_EFI_ERROR (Status);
 
   SmmCommunicateHeader      = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
@@ -991,9 +997,11 @@ SmmVariableReady (
 {
   EFI_STATUS                                Status;
 
-  Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
-  if (EFI_ERROR (Status)) {
-    return;
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
+    if (EFI_ERROR (Status)) {
+      return;
+    }
   }
 
   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
@@ -1069,13 +1077,14 @@ SmmVariableWriteReady (
 {
   EFI_STATUS                                Status;
   VOID                                      *ProtocolOps;
-
-  //
-  // Check whether the protocol is installed or not.
-  //
-  Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);
-  if (EFI_ERROR (Status)) {
-    return;
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    //
+    // Check whether the protocol is installed or not.
+    //
+    Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);
+    if (EFI_ERROR (Status)) {
+      return;
+    }
   }
 
   //
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index bd73f7a..c84dd2d 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -87,6 +87,9 @@
   ## SOMETIMES_CONSUMES   ## Variable:L"dbt"
   gEfiImageSecurityDatabaseGuid
 
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
+
 [Depex]
   gEfiSmmCommunicationProtocolGuid
 
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 07/11] MdeModulePkg/Variable/RuntimeDxe: adapt as a MM Standalone driver
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (5 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 06/11] MdeModulePkg/Variable/RuntimeDxe: adapt for usability with MM Standalone Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 08/11] MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Adapt the variable runtime dxe driver to be used as a MM_STANDALONE
driver to provide variable storage service in MM Standalone mode.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c               |  37 ++--
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c            | 201 ++++++++++++++++----
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf | 132 +++++++++++++
 3 files changed, 312 insertions(+), 58 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index 443cf07..ff30c98 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -18,6 +18,7 @@
 
 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) 2018, ARM Limited. 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
@@ -3277,19 +3278,21 @@ VariableServiceSetVariable (
     }
   }
 
-  //
-  // Special Handling for MOR Lock variable.
-  //
-  Status = SetVariableCheckHandlerMor (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *) ((UINTN) Data + DataSize - PayloadSize));
-  if (Status == EFI_ALREADY_STARTED) {
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
     //
-    // EFI_ALREADY_STARTED means the SetVariable() action is handled inside of SetVariableCheckHandlerMor().
-    // Variable driver can just return SUCCESS.
+    // Special Handling for MOR Lock variable.
     //
-    return EFI_SUCCESS;
-  }
-  if (EFI_ERROR (Status)) {
-    return Status;
+    Status = SetVariableCheckHandlerMor (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *) ((UINTN) Data + DataSize - PayloadSize));
+    if (Status == EFI_ALREADY_STARTED) {
+      //
+      // EFI_ALREADY_STARTED means the SetVariable() action is handled inside of SetVariableCheckHandlerMor().
+      // Variable driver can just return SUCCESS.
+      //
+      return EFI_SUCCESS;
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
   }
 
   Status = VarCheckLibSetVariableCheck (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *) ((UINTN) Data + DataSize - PayloadSize), mRequestSource);
@@ -4098,12 +4101,14 @@ VariableWriteServiceInitialize (
     }
   }
 
-  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
 
-  //
-  // Initialize MOR Lock variable.
-  //
-  MorLockInit ();
+    //
+    // Initialize MOR Lock variable.
+    //
+    MorLockInit ();
+  }
 
   return Status;
 }
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
index 8c53f84..02b6638 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
@@ -15,6 +15,7 @@
   SmmVariableGetStatistics() should also do validation based on its own knowledge.
 
 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2018, ARM Limited. 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
@@ -34,6 +35,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/SmmServicesTableLib.h>
 #include <Library/SmmMemLib.h>
 
+#include <Library/StandaloneMmMemLib.h>
+#include <Library/StandaloneMmServicesTableLib.h>
 #include <Guid/SmmVariableCommon.h>
 #include "Variable.h"
 
@@ -218,11 +221,19 @@ GetFtwProtocol (
   //
   // Locate Smm Fault Tolerent Write protocol
   //
-  Status = gSmst->SmmLocateProtocol (
-                    &gEfiSmmFaultTolerantWriteProtocolGuid,
-                    NULL,
-                    FtwProtocol
-                    );
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gMmst->MmLocateProtocol (
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,
+                      NULL,
+                      FtwProtocol
+                      );
+  } else {
+    Status = gSmst->SmmLocateProtocol (
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,
+                      NULL,
+                      FtwProtocol
+                      );
+  }
   return Status;
 }
 
@@ -248,11 +259,19 @@ GetFvbByHandle (
   //
   // To get the SMM FVB protocol interface on the handle
   //
-  return gSmst->SmmHandleProtocol (
-                  FvBlockHandle,
-                  &gEfiSmmFirmwareVolumeBlockProtocolGuid,
-                  (VOID **) FvBlock
-                  );
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    return gMmst->MmHandleProtocol (
+                    FvBlockHandle,
+                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                    (VOID **) FvBlock
+                    );
+  } else {
+    return gSmst->SmmHandleProtocol (
+                    FvBlockHandle,
+                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                    (VOID **) FvBlock
+                    );
+  }
 }
 
 
@@ -287,13 +306,23 @@ GetFvbCountAndBuffer (
   BufferSize     = 0;
   *NumberHandles = 0;
   *Buffer        = NULL;
-  Status = gSmst->SmmLocateHandle (
-                    ByProtocol,
-                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
-                    NULL,
-                    &BufferSize,
-                    *Buffer
-                    );
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gMmst->MmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  } else {
+    Status = gSmst->SmmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  }
   if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
     return EFI_NOT_FOUND;
   }
@@ -303,14 +332,23 @@ GetFvbCountAndBuffer (
     return EFI_OUT_OF_RESOURCES;
   }
 
-  Status = gSmst->SmmLocateHandle (
-                    ByProtocol,
-                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
-                    NULL,
-                    &BufferSize,
-                    *Buffer
-                    );
-
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+     Status = gMmst->MmLocateHandle (
+                       ByProtocol,
+                       &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                       NULL,
+                       &BufferSize,
+                       *Buffer
+                       );
+  } else {
+    Status = gSmst->SmmLocateHandle (
+                      ByProtocol,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      NULL,
+                      &BufferSize,
+                      *Buffer
+                      );
+  }
   *NumberHandles = BufferSize / sizeof(EFI_HANDLE);
   if (EFI_ERROR(Status)) {
     *NumberHandles = 0;
@@ -499,10 +537,16 @@ SmmVariableHandler (
     DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));
     return EFI_SUCCESS;
   }
-
-  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
-    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));
-    return EFI_SUCCESS;
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    if (!MmIsBufferOutsideMmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+      DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));
+      return EFI_SUCCESS;
+    }
+  } else {
+    if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+      DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));
+      return EFI_SUCCESS;
+    }
   }
 
   SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;
@@ -691,13 +735,17 @@ SmmVariableHandler (
         break;
       }
       if (!mEndOfDxe) {
-        MorLockInitAtEndOfDxe ();
-        mEndOfDxe = TRUE;
-        VarCheckLibInitializeAtEndOfDxe (NULL);
-        //
-        // The initialization for variable quota.
-        //
-        InitializeVariableQuota ();
+        if (!PcdGetBool (PcdStandaloneMmVariableEnabled)){
+          MorLockInitAtEndOfDxe ();
+          mEndOfDxe = TRUE;
+          VarCheckLibInitializeAtEndOfDxe (NULL);
+          //
+          // The initialization for variable quota.
+          //
+          InitializeVariableQuota ();
+        } else {
+          mEndOfDxe = TRUE;
+        }
       }
       ReclaimForOS ();
       Status = EFI_SUCCESS;
@@ -911,12 +959,22 @@ SmmFtwNotificationEvent (
   //
   // Notify the variable wrapper driver the variable write service is ready
   //
-  Status = gBS->InstallProtocolInterface (
-                  &mSmmVariableHandle,
-                  &gSmmVariableWriteGuid,
-                  EFI_NATIVE_INTERFACE,
-                  NULL
-                  );
+  if (PcdGetBool (PcdStandaloneMmVariableEnabled)) {
+    Status = gMmst->MmInstallProtocolInterface (
+                      &mSmmVariableHandle,
+                      &gSmmVariableWriteGuid,
+                      EFI_NATIVE_INTERFACE,
+                      NULL
+                      );
+  } else {
+    Status = gBS->InstallProtocolInterface (
+                    &mSmmVariableHandle,
+                    &gSmmVariableWriteGuid,
+                    EFI_NATIVE_INTERFACE,
+                    NULL
+                    );
+  }
+
   ASSERT_EFI_ERROR (Status);
 
   return EFI_SUCCESS;
@@ -1026,4 +1084,63 @@ VariableServiceInitialize (
   return EFI_SUCCESS;
 }
 
+/**
+  Variable Driver main entry point. The Variable driver places the 4 EFI
+  runtime services in the EFI System Table and installs arch protocols
+  for variable read and write services being available. It also registers
+  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       Variable service successfully initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmVariableServiceInitialize (
+  IN EFI_HANDLE                           ImageHandle,
+  IN EFI_MM_SYSTEM_TABLE                     *SystemTable
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_HANDLE                              VariableHandle;
+  VOID                                    *SmmFtwRegistration;
+
+  //
+  // Variable initialize.
+  //
+  Status = VariableCommonInitialize ();
+  ASSERT_EFI_ERROR (Status);
+
+  mVariableBufferPayloadSize = GetMaxVariableSize () +
+                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();
+
+  Status = gMmst->MmAllocatePool (
+                    EfiRuntimeServicesData,
+                    mVariableBufferPayloadSize,
+                    (VOID **)&mVariableBufferPayload
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  ///
+  /// Register SMM variable SMI handler
+  ///
+  VariableHandle = NULL;
+  Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Register FtwNotificationEvent () notify function.
+  //
+  Status = gMmst->MmRegisterProtocolNotify (
+                    &gEfiSmmFaultTolerantWriteProtocolGuid,
+                    SmmFtwNotificationEvent,
+                    &SmmFtwRegistration
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  SmmFtwNotificationEvent (NULL, NULL, NULL);
+
+  return EFI_SUCCESS;
+}
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
new file mode 100644
index 0000000..89ecc14
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -0,0 +1,132 @@
+## @file
+#  Provides MM variable service.
+#
+#  The whole MM authentication variable design relies on the integrity of flash part and MM.
+#  which is assumed to be protected by platform.  All variable code and metadata in flash/MM Memory
+#  may not be modified without authorization. If platform fails to protect these resources,
+#  the authentication service provided in this driver will be broken, and the behavior is undefined.
+#
+# Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018, ARM Limited. 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001000A
+  BASE_NAME                      = VariableSmm
+  MODULE_UNI_FILE                = VariableSmm.uni
+  FILE_GUID                      = 23A089B3-EED5-4ac5-B2AB-43E3298C2343
+  MODULE_TYPE                    = MM_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  ENTRY_POINT                    = StandaloneMmVariableServiceInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
+#
+
+[Sources]
+  Reclaim.c
+  Variable.c
+  VariableSmm.c
+  VarCheck.c
+  Variable.h
+  PrivilegePolymorphic.h
+  VariableExLib.c
+  TcgMorLockSmm.c
+  SpeculationBarrierSmm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+  StandaloneMmDriverEntryPoint
+  MemoryAllocationLib
+  BaseLib
+  SynchronizationLib
+  BaseMemoryLib
+  DebugLib
+  HobLib
+  PcdLib
+  AuthVariableLib
+  VarCheckLib
+  MemLib
+  MmServicesTableLib
+
+[Protocols]
+  gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
+  ## CONSUMES
+  ## NOTIFY
+  gEfiSmmFaultTolerantWriteProtocolGuid
+  ## PRODUCES
+  ## UNDEFINED # SmiHandlerRegister
+  gEfiSmmVariableProtocolGuid
+  ##gEfiSmmEndOfDxeProtocolGuid                   ## NOTIFY
+  gEdkiiSmmVarCheckProtocolGuid                 ## PRODUCES
+  gEfiTcgProtocolGuid                           ## SOMETIMES_CONSUMES
+  gEfiTcg2ProtocolGuid                          ## SOMETIMES_CONSUMES
+
+[Guids]
+  ## SOMETIMES_CONSUMES   ## GUID # Signature of Variable store header
+  ## SOMETIMES_PRODUCES   ## GUID # Signature of Variable store header
+  ## SOMETIMES_CONSUMES   ## HOB
+  ## SOMETIMES_PRODUCES   ## SystemTable
+  gEfiAuthenticatedVariableGuid
+
+  ## SOMETIMES_CONSUMES   ## GUID # Signature of Variable store header
+  ## SOMETIMES_PRODUCES   ## GUID # Signature of Variable store header
+  ## SOMETIMES_CONSUMES   ## HOB
+  ## SOMETIMES_PRODUCES   ## SystemTable
+  gEfiVariableGuid
+
+  ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"
+  ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"
+  ## SOMETIMES_CONSUMES   ## Variable:L"Lang"
+  ## SOMETIMES_PRODUCES   ## Variable:L"Lang"
+  gEfiGlobalVariableGuid
+
+  gEfiMemoryOverwriteControlDataGuid            ## SOMETIMES_CONSUMES   ## Variable:L"MemoryOverwriteRequestControl"
+  gEfiMemoryOverwriteRequestControlLockGuid     ## SOMETIMES_PRODUCES   ## Variable:L"MemoryOverwriteRequestControlLock"
+
+  gSmmVariableWriteGuid                         ## PRODUCES             ## GUID # Install protocol
+  gEfiSystemNvDataFvGuid                        ## CONSUMES             ## GUID
+  gEdkiiFaultTolerantWriteGuid                  ## SOMETIMES_CONSUMES   ## HOB
+
+  ## SOMETIMES_CONSUMES   ## Variable:L"VarErrorFlag"
+  ## SOMETIMES_PRODUCES   ## Variable:L"VarErrorFlag"
+  gEdkiiVarErrorFlagGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize       ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase       ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64     ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize              ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize          ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize     ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                 ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxUserNvVariableSpaceSize           ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBoottimeReservedNvVariableSpaceSize  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe   ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics        ## CONSUMES  # statistic the information of variable.
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate       ## CONSUMES  # Auto update PlatformLang/Lang
+
+[Depex]
+  TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  VariableSmmExtra.uni
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 08/11] MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this library
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (6 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 07/11] MdeModulePkg/Variable/RuntimeDxe: adapt as a MM Standalone driver Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-04 10:36   ` Ard Biesheuvel
  2019-01-02 13:13 ` [PATCH v2 09/11] ArmPlatformPkg/NorFlashDxe: allow reusability as a MM driver Jagadeesh Ujja
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

“VarCheckLib” library can be used by MM_STANDALONE drivers as well.
So add MM_STANDALONE as the module type this library supports.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf b/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
index 099f83d..c8cf810 100644
--- a/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+++ b/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
@@ -2,6 +2,7 @@
 #  Provides variable check services and database management.
 #
 #  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions
@@ -21,12 +22,12 @@
   FILE_GUID                      = 63E12D08-0C5D-47F8-95E4-09F89D7506C5
   MODULE_TYPE                    = DXE_RUNTIME_DRIVER
   VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = VarCheckLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = VarCheckLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
 
 #
 # The following information is for reference only and not required by the build tools.
 #
-#  VALID_ARCHITECTURES           = IA32 X64
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
 #
 
 [Sources]
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 09/11] ArmPlatformPkg/NorFlashDxe: allow reusability as a MM driver
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (7 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 08/11] MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
  2019-01-02 13:13 ` [PATCH v2 11/11] CryptoPkg/BaseCryptLib: " Jagadeesh Ujja
  10 siblings, 0 replies; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

Adapt the NorFlashDxe driver to be used as a MM_STANDALONE driver to
allow access to NOR flash for code executing in MM_STANDALONE mode.
This allows storing of EFI variables on NOR flash which is accessible
only via the MM STANDALONE mode software.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h            |    4 +-
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf          |    2 +
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c         |   96 +-
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c   | 1339 ++++++++++++++++++++
 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf |   76 ++
 5 files changed, 1470 insertions(+), 47 deletions(-)

diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
index c0563f6..d149652 100644
--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
+++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
@@ -1,6 +1,6 @@
 /** @file  NorFlashDxe.h
 
-  Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2011 - 2019, ARM Ltd. All rights reserved.<BR>
 
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -19,6 +19,7 @@
 #include <Base.h>
 #include <PiDxe.h>
 
+#include <PiMm.h>
 #include <Guid/EventGroup.h>
 
 #include <Protocol/BlockIo.h>
@@ -30,6 +31,7 @@
 #include <Library/NorFlashPlatformLib.h>
 #include <Library/UefiLib.h>
 #include <Library/UefiRuntimeLib.h>
+#include <Library/StandaloneMmServicesTableLib.h>
 
 #define NOR_FLASH_ERASE_RETRY                     10
 
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
index a59a21a..6bf0ff2 100644
--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
+++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -44,6 +44,7 @@
   UefiBootServicesTableLib
   UefiRuntimeLib
   DxeServicesTableLib
+  StandaloneMmServicesTableLib
 
 [Guids]
   gEfiSystemNvDataFvGuid
@@ -57,6 +58,7 @@
   gEfiDevicePathProtocolGuid
   gEfiFirmwareVolumeBlockProtocolGuid
   gEfiDiskIoProtocolGuid
+  gEfiSmmFirmwareVolumeBlockProtocolGuid
 
 [Pcd.common]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
index e62ffbb..024da28 100644
--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
+++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
@@ -1,6 +1,6 @@
 /*++ @file  NorFlashFvbDxe.c
 
- Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2011 - 2019, ARM Ltd. All rights reserved.<BR>
 
  This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
@@ -720,27 +720,29 @@ NorFlashFvbInitialize (
   DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
   ASSERT((Instance != NULL));
 
-  //
-  // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
-  //
-
-  // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
-  //       even if we only use the small block region at the top of the NOR Flash.
-  //       The reason is when the NOR Flash memory is set into program mode, the command
-  //       is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
-  RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
-
-  Status = gDS->AddMemorySpace (
-      EfiGcdMemoryTypeMemoryMappedIo,
-      Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
-      EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
-      );
-  ASSERT_EFI_ERROR (Status);
-
-  Status = gDS->SetMemorySpaceAttributes (
-      Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
-      EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
-  ASSERT_EFI_ERROR (Status);
+  if (!InMm ()) {
+    //
+    // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+    //
+
+    // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
+    //       even if we only use the small block region at the top of the NOR Flash.
+    //       The reason is when the NOR Flash memory is set into program mode, the command
+    //       is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
+    RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
+
+    Status = gDS->AddMemorySpace (
+        EfiGcdMemoryTypeMemoryMappedIo,
+        Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+        EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+        );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gDS->SetMemorySpaceAttributes (
+        Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+        EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+    ASSERT_EFI_ERROR (Status);
+  }
 
   mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase);
 
@@ -777,30 +779,32 @@ NorFlashFvbInitialize (
     }
   }
 
-  //
-  // The driver implementing the variable read service can now be dispatched;
-  // the varstore headers are in place.
-  //
-  Status = gBS->InstallProtocolInterface (
-                  &gImageHandle,
-                  &gEdkiiNvVarStoreFormattedGuid,
-                  EFI_NATIVE_INTERFACE,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Register for the virtual address change event
-  //
-  Status = gBS->CreateEventEx (
-                  EVT_NOTIFY_SIGNAL,
-                  TPL_NOTIFY,
-                  FvbVirtualNotifyEvent,
-                  NULL,
-                  &gEfiEventVirtualAddressChangeGuid,
-                  &mFvbVirtualAddrChangeEvent
-                  );
-  ASSERT_EFI_ERROR (Status);
+  if (!InMm ()) {
+    //
+    // The driver implementing the variable read service can now be dispatched;
+    // the varstore headers are in place.
+    //
+    Status = gBS->InstallProtocolInterface (
+                    &gImageHandle,
+                    &gEdkiiNvVarStoreFormattedGuid,
+                    EFI_NATIVE_INTERFACE,
+                    NULL
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Register for the virtual address change event
+    //
+    Status = gBS->CreateEventEx (
+                    EVT_NOTIFY_SIGNAL,
+                    TPL_NOTIFY,
+                    FvbVirtualNotifyEvent,
+                    NULL,
+                    &gEfiEventVirtualAddressChangeGuid,
+                    &mFvbVirtualAddrChangeEvent
+                    );
+    ASSERT_EFI_ERROR (Status);
+  }
 
   return Status;
 }
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c
new file mode 100644
index 0000000..0dbfc98
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c
@@ -0,0 +1,1339 @@
+/** @file  NorFlashDxe.c
+
+  Copyright (c) 2011 - 2019, ARM Ltd. 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.
+
+**/
+
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+#include "NorFlashDxe.h"
+
+
+//
+// Global variable declarations
+//
+NOR_FLASH_INSTANCE **mNorFlashInstances;
+UINT32               mNorFlashDeviceCount;
+
+NOR_FLASH_INSTANCE  mNorFlashInstanceTemplate = {
+  NOR_FLASH_SIGNATURE, // Signature
+  NULL, // Handle ... NEED TO BE FILLED
+
+  0, // DeviceBaseAddress ... NEED TO BE FILLED
+  0, // RegionBaseAddress ... NEED TO BE FILLED
+  0, // Size ... NEED TO BE FILLED
+  0, // StartLba
+
+  {
+    EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
+    NULL, // Media ... NEED TO BE FILLED
+    NorFlashBlockIoReset, // Reset;
+    NorFlashBlockIoReadBlocks,          // ReadBlocks
+    NorFlashBlockIoWriteBlocks,         // WriteBlocks
+    NorFlashBlockIoFlushBlocks          // FlushBlocks
+  }, // BlockIoProtocol
+
+  {
+    0, // MediaId ... NEED TO BE FILLED
+    FALSE, // RemovableMedia
+    TRUE, // MediaPresent
+    FALSE, // LogicalPartition
+    FALSE, // ReadOnly
+    FALSE, // WriteCaching;
+    0, // BlockSize ... NEED TO BE FILLED
+    4, //  IoAlign
+    0, // LastBlock ... NEED TO BE FILLED
+    0, // LowestAlignedLba
+    1, // LogicalBlocksPerPhysicalBlock
+  }, //Media;
+
+  {
+    EFI_DISK_IO_PROTOCOL_REVISION, // Revision
+    NorFlashDiskIoReadDisk,        // ReadDisk
+    NorFlashDiskIoWriteDisk        // WriteDisk
+  },
+
+  {
+    FvbGetAttributes, // GetAttributes
+    FvbSetAttributes, // SetAttributes
+    FvbGetPhysicalAddress,  // GetPhysicalAddress
+    FvbGetBlockSize,  // GetBlockSize
+    FvbRead,  // Read
+    FvbWrite, // Write
+    FvbEraseBlocks, // EraseBlocks
+    NULL, //ParentHandle
+  }, //  FvbProtoccol;
+  NULL, // ShadowBuffer
+  {
+    {
+      {
+        HARDWARE_DEVICE_PATH,
+        HW_VENDOR_DP,
+        {
+          (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
+          (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
+        }
+      },
+      { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GUID ... NEED TO BE FILLED
+    },
+    0, // Index
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+    }
+    } // DevicePath
+};
+
+EFI_STATUS
+NorFlashCreateInstance (
+  IN UINTN                  NorFlashDeviceBase,
+  IN UINTN                  NorFlashRegionBase,
+  IN UINTN                  NorFlashSize,
+  IN UINT32                 Index,
+  IN UINT32                 BlockSize,
+  IN BOOLEAN                SupportFvb,
+  OUT NOR_FLASH_INSTANCE**  NorFlashInstance
+  )
+{
+  EFI_STATUS Status;
+  NOR_FLASH_INSTANCE* Instance;
+
+  ASSERT(NorFlashInstance != NULL);
+
+  Instance = AllocateRuntimeCopyPool (sizeof(NOR_FLASH_INSTANCE),&mNorFlashInstanceTemplate);
+  if (Instance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Instance->DeviceBaseAddress = NorFlashDeviceBase;
+  Instance->RegionBaseAddress = NorFlashRegionBase;
+  Instance->Size = NorFlashSize;
+
+  Instance->BlockIoProtocol.Media = &Instance->Media;
+  Instance->Media.MediaId = Index;
+  Instance->Media.BlockSize = BlockSize;
+  Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
+
+  CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
+  Instance->DevicePath.Index = (UINT8)Index;
+
+  Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);;
+  if (Instance->ShadowBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if (SupportFvb) {
+    NorFlashFvbInitialize (Instance);
+
+    //Install DevicePath Protocol
+    Status = gMmst->MmInstallProtocolInterface (
+                      &Instance->Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &Instance->DevicePath
+                      );
+    if (EFI_ERROR(Status)) {
+      FreePool (Instance);
+      return Status;
+    }
+    //Install BlockIo Protocol
+    Status = gMmst->MmInstallProtocolInterface (
+                      &Instance->Handle,
+                      &gEfiBlockIoProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &Instance->BlockIoProtocol
+                      );
+    if (EFI_ERROR(Status)) {
+      FreePool (Instance);
+      return Status;
+    }
+    //Install FirmwareVolumeBlock Protocol
+    Status = gMmst->MmInstallProtocolInterface (
+                      &Instance->Handle,
+                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &Instance->FvbProtocol
+                      );
+    if (EFI_ERROR(Status)) {
+      FreePool (Instance);
+      return Status;
+    }
+  } else {
+    //Install DevicePath Protocol
+    Status = gMmst->MmInstallProtocolInterface (
+                      &Instance->Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &Instance->DevicePath
+                      );
+    if (EFI_ERROR(Status)) {
+      FreePool (Instance);
+      return Status;
+    }
+    //Install BlockIo Protocol
+    Status = gMmst->MmInstallProtocolInterface (
+                      &Instance->Handle,
+                      &gEfiBlockIoProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &Instance->BlockIoProtocol
+                      );
+    if (EFI_ERROR(Status)) {
+      FreePool (Instance);
+      return Status;
+    }
+    //Install DiskIO Protocol
+    Status = gMmst->MmInstallProtocolInterface (
+                      &Instance->Handle,
+                      &gEfiDiskIoProtocolGuid,
+                      EFI_NATIVE_INTERFACE,
+                      &Instance->DiskIoProtocol
+                      );
+    if (EFI_ERROR(Status)) {
+      FreePool (Instance);
+      return Status;
+    }
+  }
+
+  *NorFlashInstance = Instance;
+  return Status;
+}
+
+UINT32
+NorFlashReadStatusRegister (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  SR_Address
+  )
+{
+  // Prepare to read the status register
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
+  return MmioRead32 (Instance->DeviceBaseAddress);
+}
+
+STATIC
+BOOLEAN
+NorFlashBlockIsLocked (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  BlockAddress
+  )
+{
+  UINT32                LockStatus;
+
+  // Send command for reading device id
+  SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
+
+  // Read block lock status
+  LockStatus = MmioRead32 (CREATE_NOR_ADDRESS(BlockAddress, 2));
+
+  // Decode block lock status
+  LockStatus = FOLD_32BIT_INTO_16BIT(LockStatus);
+
+  if ((LockStatus & 0x2) != 0) {
+    DEBUG((EFI_D_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));
+  }
+
+  return ((LockStatus & 0x1) != 0);
+}
+
+STATIC
+EFI_STATUS
+NorFlashUnlockSingleBlock (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  BlockAddress
+  )
+{
+  UINT32                LockStatus;
+
+  // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
+  // and to protect shared data structures.
+
+  if (FeaturePcdGet (PcdNorFlashCheckBlockLocked) == TRUE) {
+    do {
+      // Request a lock setup
+      SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
+
+      // Request an unlock
+      SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
+
+      // Send command for reading device id
+      SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
+
+      // Read block lock status
+      LockStatus = MmioRead32 (CREATE_NOR_ADDRESS(BlockAddress, 2));
+
+      // Decode block lock status
+      LockStatus = FOLD_32BIT_INTO_16BIT(LockStatus);
+    } while ((LockStatus & 0x1) == 1);
+  } else {
+    // Request a lock setup
+    SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
+
+    // Request an unlock
+    SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
+
+    // Wait until the status register gives us the all clear
+    do {
+      LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
+    } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+  }
+
+  // Put device back into Read Array mode
+  SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
+
+  DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+NorFlashUnlockSingleBlockIfNecessary (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  BlockAddress
+  )
+{
+  EFI_STATUS Status;
+
+  Status = EFI_SUCCESS;
+
+  if (NorFlashBlockIsLocked (Instance, BlockAddress) == TRUE) {
+    Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
+  }
+
+  return Status;
+}
+
+
+/**
+ * The following function presumes that the block has already been unlocked.
+ **/
+STATIC
+EFI_STATUS
+NorFlashEraseSingleBlock (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  BlockAddress
+  )
+{
+  EFI_STATUS            Status;
+  UINT32                StatusRegister;
+
+  Status = EFI_SUCCESS;
+
+  // Request a block erase and then confirm it
+  SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
+  SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
+
+  // Wait until the status register gives us the all clear
+  do {
+    StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
+  } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+  if (StatusRegister & P30_SR_BIT_VPP) {
+    DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) {
+    DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (StatusRegister & P30_SR_BIT_ERASE) {
+    DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+    // The debug level message has been reduced because a device lock might happen. In this case we just retry it ...
+    DEBUG((EFI_D_INFO,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress));
+    Status = EFI_WRITE_PROTECTED;
+  }
+
+  if (EFI_ERROR(Status)) {
+    // Clear the Status Register
+    SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+  }
+
+  // Put device back into Read Array mode
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+  return Status;
+}
+
+/**
+ * This function unlock and erase an entire NOR Flash block.
+ **/
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  BlockAddress
+  )
+{
+  EFI_STATUS      Status;
+  UINTN           Index;
+
+  Index = 0;
+  // The block erase might fail a first time (SW bug ?). Retry it ...
+  do {
+    // Unlock the block if we have to
+    Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+    Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
+    Index++;
+  } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
+
+  if (Index == NOR_FLASH_ERASE_RETRY) {
+    DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress,Index));
+  }
+
+
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+NorFlashWriteSingleWord (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  WordAddress,
+  IN UINT32                 WriteData
+  )
+{
+  EFI_STATUS            Status;
+  UINT32                StatusRegister;
+
+  Status = EFI_SUCCESS;
+
+  // Request a write single word command
+  SEND_NOR_COMMAND(WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP);
+
+  // Store the word into NOR Flash;
+  MmioWrite32 (WordAddress, WriteData);
+
+  // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+  do {
+    // Prepare to read the status register
+    StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
+    // The chip is busy while the WRITE bit is not asserted
+  } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+
+  // Perform a full status check:
+  // Mask the relevant bits of Status Register.
+  // Everything should be zero, if not, we have a problem
+
+  if (StatusRegister & P30_SR_BIT_VPP) {
+    DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n",WordAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (StatusRegister & P30_SR_BIT_PROGRAM) {
+    DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n",WordAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+    DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n",WordAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (!EFI_ERROR(Status)) {
+    // Clear the Status Register
+    SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+  }
+
+  // Put device back into Read Array mode
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+  return Status;
+}
+
+/*
+ * Writes data to the NOR Flash using the Buffered Programming method.
+ *
+ * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
+ * Therefore this function will only handle buffers up to 32 words or 128 bytes.
+ * To deal with larger buffers, call this function again.
+ *
+ * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
+ * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
+ *
+ * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
+ * then programming time is doubled and power consumption is increased.
+ * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
+ * i.e. the last 4 bits of the target start address must be zero: 0x......00
+ */
+EFI_STATUS
+NorFlashWriteBuffer (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN UINTN                  TargetAddress,
+  IN UINTN                  BufferSizeInBytes,
+  IN UINT32                 *Buffer
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 BufferSizeInWords;
+  UINTN                 Count;
+  volatile UINT32       *Data;
+  UINTN                 WaitForBuffer;
+  BOOLEAN               BufferAvailable;
+  UINT32                StatusRegister;
+
+  WaitForBuffer   = MAX_BUFFERED_PROG_ITERATIONS;
+  BufferAvailable = FALSE;
+
+  // Check that the target address does not cross a 32-word boundary.
+  if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check there are some data to program
+  if (BufferSizeInBytes == 0) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
+  if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // Check that the buffer size is a multiple of 32-bit words
+  if ((BufferSizeInBytes % 4) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // Pre-programming conditions checked, now start the algorithm.
+
+  // Prepare the data destination address
+  Data = (UINT32 *)TargetAddress;
+
+  // Check the availability of the buffer
+  do {
+    // Issue the Buffered Program Setup command
+    SEND_NOR_COMMAND(TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP);
+
+    // Read back the status register bit#7 from the same address
+    if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) {
+      BufferAvailable = TRUE;
+    }
+
+    // Update the loop counter
+    WaitForBuffer--;
+
+  } while ((WaitForBuffer > 0) && (BufferAvailable == FALSE));
+
+  // The buffer was not available for writing
+  if (WaitForBuffer == 0) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+  // From now on we work in 32-bit words
+  BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
+
+  // Write the word count, which is (buffer_size_in_words - 1),
+  // because word count 0 means one word.
+  SEND_NOR_COMMAND(TargetAddress, 0, (BufferSizeInWords - 1));
+
+  // Write the data to the NOR Flash, advancing each address by 4 bytes
+  for(Count=0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {
+    MmioWrite32 ((UINTN)Data, *Buffer);
+  }
+
+  // Issue the Buffered Program Confirm command, to start the programming operation
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
+
+  // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+  do {
+    StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
+    // The chip is busy while the WRITE bit is not asserted
+  } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+
+  // Perform a full status check:
+  // Mask the relevant bits of Status Register.
+  // Everything should be zero, if not, we have a problem
+
+  Status          = EFI_SUCCESS;
+
+  if (StatusRegister & P30_SR_BIT_VPP) {
+    DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (StatusRegister & P30_SR_BIT_PROGRAM) {
+    DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+    DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n",TargetAddress));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (!EFI_ERROR(Status)) {
+    // Clear the Status Register
+    SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+  }
+
+EXIT:
+  // Put device back into Read Array mode
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+NorFlashWriteFullBlock (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN EFI_LBA                Lba,
+  IN UINT32                 *DataBuffer,
+  IN UINT32                 BlockSizeInWords
+  )
+{
+  EFI_STATUS    Status;
+  UINTN         WordAddress;
+  UINT32        WordIndex;
+  UINTN         BufferIndex;
+  UINTN         BlockAddress;
+  UINTN         BuffersInBlock;
+  UINTN         RemainingWords;
+  UINTN         Cnt;
+
+  Status = EFI_SUCCESS;
+
+  // Get the physical address of the block
+  BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
+
+  // Start writing from the first address at the start of the block
+  WordAddress = BlockAddress;
+
+  Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
+    goto EXIT;
+  }
+
+  // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
+
+  // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
+  if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
+
+    // First, break the entire block into buffer-sized chunks.
+    BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
+
+    // Then feed each buffer chunk to the NOR Flash
+    // If a buffer does not contain any data, don't write it.
+    for(BufferIndex=0;
+         BufferIndex < BuffersInBlock;
+         BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
+      ) {
+      // Check the buffer to see if it contains any data (not set all 1s).
+      for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
+        if (~DataBuffer[Cnt] != 0 ) {
+          // Some data found, write the buffer.
+          Status = NorFlashWriteBuffer (Instance, WordAddress, P30_MAX_BUFFER_SIZE_IN_BYTES,
+                                        DataBuffer);
+          if (EFI_ERROR(Status)) {
+            goto EXIT;
+          }
+          break;
+        }
+      }
+    }
+
+    // Finally, finish off any remaining words that are less than the maximum size of the buffer
+    RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
+
+    if(RemainingWords != 0) {
+      Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);
+      if (EFI_ERROR(Status)) {
+        goto EXIT;
+      }
+    }
+
+  } else {
+    // For now, use the single word programming algorithm
+    // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
+    // i.e. which ends in the range 0x......01 - 0x......7F.
+    for(WordIndex=0; WordIndex<BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {
+      Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
+      if (EFI_ERROR(Status)) {
+        goto EXIT;
+      }
+    }
+  }
+
+EXIT:
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
+  }
+  return Status;
+}
+
+
+EFI_STATUS
+NorFlashWriteBlocks (
+  IN NOR_FLASH_INSTANCE     *Instance,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSizeInBytes,
+  IN VOID                   *Buffer
+  )
+{
+  UINT32          *pWriteBuffer;
+  EFI_STATUS      Status = EFI_SUCCESS;
+  EFI_LBA         CurrentBlock;
+  UINT32          BlockSizeInWords;
+  UINT32          NumBlocks;
+  UINT32          BlockCount;
+
+  // The buffer must be valid
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if(Instance->Media.ReadOnly == TRUE) {
+    return EFI_WRITE_PROTECTED;
+  }
+
+  // We must have some bytes to read
+  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
+  if(BufferSizeInBytes == 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // The size of the buffer must be a multiple of the block size
+  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize));
+  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // All blocks must be within the device
+  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
+
+  if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
+    DEBUG((EFI_D_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BlockSizeInWords = Instance->Media.BlockSize / 4;
+
+  // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
+  // to a proper data type, so use *ReadBuffer
+  pWriteBuffer = (UINT32 *)Buffer;
+
+  CurrentBlock = Lba;
+  for (BlockCount=0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
+
+    DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock));
+
+    Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
+
+    if (EFI_ERROR(Status)) {
+      break;
+    }
+  }
+
+  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
+  return Status;
+}
+
+#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
+
+/**
+  Copy Length bytes from Source to Destination, using aligned accesses only.
+  Note that this implementation uses memcpy() semantics rather then memmove()
+  semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
+
+  @param  DestinationBuffer The target of the copy request.
+  @param  SourceBuffer      The place to copy from.
+  @param  Length            The number of bytes to copy.
+
+  @return Destination
+
+**/
+STATIC
+VOID *
+AlignedCopyMem (
+  OUT     VOID                      *DestinationBuffer,
+  IN      CONST VOID                *SourceBuffer,
+  IN      UINTN                     Length
+  )
+{
+  UINT8             *Destination8;
+  CONST UINT8       *Source8;
+  UINT32            *Destination32;
+  CONST UINT32      *Source32;
+  UINT64            *Destination64;
+  CONST UINT64      *Source64;
+
+  if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 8) && Length >= 8) {
+    Destination64 = DestinationBuffer;
+    Source64 = SourceBuffer;
+    while (Length >= 8) {
+      *Destination64++ = *Source64++;
+      Length -= 8;
+    }
+
+    Destination8 = (UINT8 *)Destination64;
+    Source8 = (CONST UINT8 *)Source64;
+  } else if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 4) && Length >= 4) {
+    Destination32 = DestinationBuffer;
+    Source32 = SourceBuffer;
+    while (Length >= 4) {
+      *Destination32++ = *Source32++;
+      Length -= 4;
+    }
+
+    Destination8 = (UINT8 *)Destination32;
+    Source8 = (CONST UINT8 *)Source32;
+  } else {
+    Destination8 = DestinationBuffer;
+    Source8 = SourceBuffer;
+  }
+  while (Length-- != 0) {
+    *Destination8++ = *Source8++;
+  }
+  return DestinationBuffer;
+}
+
+EFI_STATUS
+NorFlashReadBlocks (
+  IN NOR_FLASH_INSTANCE   *Instance,
+  IN EFI_LBA              Lba,
+  IN UINTN                BufferSizeInBytes,
+  OUT VOID                *Buffer
+  )
+{
+  UINT32              NumBlocks;
+  UINTN               StartAddress;
+
+  DEBUG((DEBUG_BLKIO, "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
+      BufferSizeInBytes, Instance->Media.BlockSize, Instance->Media.LastBlock, Lba));
+
+  // The buffer must be valid
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Return if we have not any byte to read
+  if (BufferSizeInBytes == 0) {
+    return EFI_SUCCESS;
+  }
+
+  // The size of the buffer must be a multiple of the block size
+  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // All blocks must be within the device
+  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+  if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
+    DEBUG((EFI_D_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Get the address to start reading from
+  StartAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+                                        Lba,
+                                        Instance->Media.BlockSize
+                                       );
+
+  // Put the device into Read Array mode
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+  // Readout the data
+  AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashRead (
+  IN NOR_FLASH_INSTANCE   *Instance,
+  IN EFI_LBA              Lba,
+  IN UINTN                Offset,
+  IN UINTN                BufferSizeInBytes,
+  OUT VOID                *Buffer
+  )
+{
+  UINTN  StartAddress;
+
+  // The buffer must be valid
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Return if we have not any byte to read
+  if (BufferSizeInBytes == 0) {
+    return EFI_SUCCESS;
+  }
+
+  if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
+    DEBUG ((EFI_D_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Get the address to start reading from
+  StartAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+                                        Lba,
+                                        Instance->Media.BlockSize
+                                       );
+
+  // Put the device into Read Array mode
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+  // Readout the data
+  AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
+
+  return EFI_SUCCESS;
+}
+
+/*
+  Write a full or portion of a block. It must not span block boundaries; that is,
+  Offset + *NumBytes <= Instance->Media.BlockSize.
+*/
+EFI_STATUS
+NorFlashWriteSingleBlock (
+  IN        NOR_FLASH_INSTANCE   *Instance,
+  IN        EFI_LBA               Lba,
+  IN        UINTN                 Offset,
+  IN OUT    UINTN                *NumBytes,
+  IN        UINT8                *Buffer
+  )
+{
+  EFI_STATUS  TempStatus;
+  UINT32      Tmp;
+  UINT32      TmpBuf;
+  UINT32      WordToWrite;
+  UINT32      Mask;
+  BOOLEAN     DoErase;
+  UINTN       BytesToWrite;
+  UINTN       CurOffset;
+  UINTN       WordAddr;
+  UINTN       BlockSize;
+  UINTN       BlockAddress;
+  UINTN       PrevBlockAddress;
+
+  PrevBlockAddress = 0;
+
+  DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
+
+  // Detect WriteDisabled state
+  if (Instance->Media.ReadOnly == TRUE) {
+    DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n"));
+    // It is in WriteDisabled state, return an error right away
+    return EFI_ACCESS_DENIED;
+  }
+
+  // Cache the block size to avoid de-referencing pointers all the time
+  BlockSize = Instance->Media.BlockSize;
+
+  // The write must not span block boundaries.
+  // We need to check each variable individually because adding two large values together overflows.
+  if ( ( Offset               >= BlockSize ) ||
+       ( *NumBytes            >  BlockSize ) ||
+       ( (Offset + *NumBytes) >  BlockSize )    ) {
+    DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // We must have some bytes to write
+  if (*NumBytes == 0) {
+    DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // Pick 128bytes as a good start for word operations as opposed to erasing the
+  // block and writing the data regardless if an erase is really needed.
+  // It looks like most individual NV variable writes are smaller than 128bytes.
+  if (*NumBytes <= 128) {
+    // Check to see if we need to erase before programming the data into NOR.
+    // If the destination bits are only changing from 1s to 0s we can just write.
+    // After a block is erased all bits in the block is set to 1.
+    // If any byte requires us to erase we just give up and rewrite all of it.
+    DoErase      = FALSE;
+    BytesToWrite = *NumBytes;
+    CurOffset    = Offset;
+
+    while (BytesToWrite > 0) {
+      // Read full word from NOR, splice as required. A word is the smallest
+      // unit we can write.
+      TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof(Tmp), &Tmp);
+      if (EFI_ERROR (TempStatus)) {
+        return EFI_DEVICE_ERROR;
+      }
+
+      // Physical address of word in NOR to write.
+      WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+                                                               Lba, BlockSize);
+      // The word of data that is to be written.
+      TmpBuf = *((UINT32*)(Buffer + (*NumBytes - BytesToWrite)));
+
+      // First do word aligned chunks.
+      if ((CurOffset & 0x3) == 0) {
+        if (BytesToWrite >= 4) {
+          // Is the destination still in 'erased' state?
+          if (~Tmp != 0) {
+            // Check to see if we are only changing bits to zero.
+            if ((Tmp ^ TmpBuf) & TmpBuf) {
+              DoErase = TRUE;
+              break;
+            }
+          }
+          // Write this word to NOR
+          WordToWrite = TmpBuf;
+          CurOffset += sizeof(TmpBuf);
+          BytesToWrite -= sizeof(TmpBuf);
+        } else {
+          // BytesToWrite < 4. Do small writes and left-overs
+          Mask = ~((~0) << (BytesToWrite * 8));
+          // Mask out the bytes we want.
+          TmpBuf &= Mask;
+          // Is the destination still in 'erased' state?
+          if ((Tmp & Mask) != Mask) {
+            // Check to see if we are only changing bits to zero.
+            if ((Tmp ^ TmpBuf) & TmpBuf) {
+              DoErase = TRUE;
+              break;
+            }
+          }
+          // Merge old and new data. Write merged word to NOR
+          WordToWrite = (Tmp & ~Mask) | TmpBuf;
+          CurOffset += BytesToWrite;
+          BytesToWrite = 0;
+        }
+      } else {
+        // Do multiple words, but starting unaligned.
+        if (BytesToWrite > (4 - (CurOffset & 0x3))) {
+          Mask = ((~0) << ((CurOffset & 0x3) * 8));
+          // Mask out the bytes we want.
+          TmpBuf &= Mask;
+          // Is the destination still in 'erased' state?
+          if ((Tmp & Mask) != Mask) {
+            // Check to see if we are only changing bits to zero.
+            if ((Tmp ^ TmpBuf) & TmpBuf) {
+              DoErase = TRUE;
+              break;
+            }
+          }
+          // Merge old and new data. Write merged word to NOR
+          WordToWrite = (Tmp & ~Mask) | TmpBuf;
+          BytesToWrite -= (4 - (CurOffset & 0x3));
+          CurOffset += (4 - (CurOffset & 0x3));
+        } else {
+          // Unaligned and fits in one word.
+          Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
+          // Mask out the bytes we want.
+          TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
+          // Is the destination still in 'erased' state?
+          if ((Tmp & Mask) != Mask) {
+            // Check to see if we are only changing bits to zero.
+            if ((Tmp ^ TmpBuf) & TmpBuf) {
+              DoErase = TRUE;
+              break;
+            }
+          }
+          // Merge old and new data. Write merged word to NOR
+          WordToWrite = (Tmp & ~Mask) | TmpBuf;
+          CurOffset += BytesToWrite;
+          BytesToWrite = 0;
+        }
+      }
+
+      //
+      // Write the word to NOR.
+      //
+
+      BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
+      if (BlockAddress != PrevBlockAddress) {
+        TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+        if (EFI_ERROR (TempStatus)) {
+          return EFI_DEVICE_ERROR;
+        }
+        PrevBlockAddress = BlockAddress;
+      }
+      TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
+      if (EFI_ERROR (TempStatus)) {
+        return EFI_DEVICE_ERROR;
+      }
+    }
+    // Exit if we got here and could write all the data. Otherwise do the
+    // Erase-Write cycle.
+    if (!DoErase) {
+      return EFI_SUCCESS;
+    }
+  }
+
+  // Check we did get some memory. Buffer is BlockSize.
+  if (Instance->ShadowBuffer == NULL) {
+    DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Read NOR Flash data into shadow buffer
+  TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
+  if (EFI_ERROR (TempStatus)) {
+    // Return one of the pre-approved error statuses
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Put the data at the appropriate location inside the buffer area
+  CopyMem ((VOID*)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
+
+  // Write the modified buffer back to the NorFlash
+  TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
+  if (EFI_ERROR (TempStatus)) {
+    // Return one of the pre-approved error statuses
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/*
+  Although DiskIoDxe will automatically install the DiskIO protocol whenever
+  we install the BlockIO protocol, its implementation is sub-optimal as it reads
+  and writes entire blocks using the BlockIO protocol. In fact we can access
+  NOR flash with a finer granularity than that, so we can improve performance
+  by directly producing the DiskIO protocol.
+*/
+
+/**
+  Read BufferSize bytes from Offset into Buffer.
+
+  @param  This                  Protocol instance pointer.
+  @param  MediaId               Id of the media, changes every time the media is replaced.
+  @param  Offset                The starting byte offset to read from
+  @param  BufferSize            Size of Buffer
+  @param  Buffer                Buffer containing read data
+
+  @retval EFI_SUCCESS           The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
+  @retval EFI_NO_MEDIA          There is no media in the device.
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
+  @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
+                                valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoReadDisk (
+  IN EFI_DISK_IO_PROTOCOL         *This,
+  IN UINT32                       MediaId,
+  IN UINT64                       DiskOffset,
+  IN UINTN                        BufferSize,
+  OUT VOID                        *Buffer
+  )
+{
+  NOR_FLASH_INSTANCE *Instance;
+  UINT32              BlockSize;
+  UINT32              BlockOffset;
+  EFI_LBA             Lba;
+
+  Instance = INSTANCE_FROM_DISKIO_THIS(This);
+
+  if (MediaId != Instance->Media.MediaId) {
+    return EFI_MEDIA_CHANGED;
+  }
+
+  BlockSize = Instance->Media.BlockSize;
+  Lba = (EFI_LBA) DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
+
+  return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer);
+}
+
+/**
+  Writes a specified number of bytes to a device.
+
+  @param  This       Indicates a pointer to the calling context.
+  @param  MediaId    ID of the medium to be written.
+  @param  Offset     The starting byte offset on the logical block I/O device to write.
+  @param  BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
+  @param  Buffer     A pointer to the buffer containing the data to be written.
+
+  @retval EFI_SUCCESS           The data was written correctly to the device.
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
+  @retval EFI_NO_MEDIA          There is no media in the device.
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
+  @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
+                                 valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoWriteDisk (
+  IN EFI_DISK_IO_PROTOCOL         *This,
+  IN UINT32                       MediaId,
+  IN UINT64                       DiskOffset,
+  IN UINTN                        BufferSize,
+  IN VOID                         *Buffer
+  )
+{
+  NOR_FLASH_INSTANCE *Instance;
+  UINT32              BlockSize;
+  UINT32              BlockOffset;
+  EFI_LBA             Lba;
+  UINTN               RemainingBytes;
+  UINTN               WriteSize;
+  EFI_STATUS          Status;
+
+  Instance = INSTANCE_FROM_DISKIO_THIS(This);
+
+  if (MediaId != Instance->Media.MediaId) {
+    return EFI_MEDIA_CHANGED;
+  }
+
+  BlockSize = Instance->Media.BlockSize;
+  Lba = (EFI_LBA) DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
+
+  RemainingBytes = BufferSize;
+
+  // Write either all the remaining bytes, or the number of bytes that bring
+  // us up to a block boundary, whichever is less.
+  // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
+  // block boundary (even if it is already on one).
+  WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset);
+
+  do {
+    if (WriteSize == BlockSize) {
+      // Write a full block
+      Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32));
+    } else {
+      // Write a partial block
+      Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer);
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    // Now continue writing either all the remaining bytes or single blocks.
+    RemainingBytes -= WriteSize;
+    Buffer = (UINT8 *) Buffer + WriteSize;
+    Lba++;
+    BlockOffset = 0;
+    WriteSize = MIN (RemainingBytes, BlockSize);
+  } while (RemainingBytes);
+
+  return Status;
+}
+
+EFI_STATUS
+NorFlashReset (
+  IN  NOR_FLASH_INSTANCE *Instance
+  )
+{
+  // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
+  SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+  return EFI_SUCCESS;
+}
+
+/**
+  Fixup internal data so that EFI can be call in virtual mode.
+  Call the passed in Child Notify event and convert any pointers in
+  lib to virtual mode.
+
+  @param[in]    Event   The Event that is being processed
+  @param[in]    Context Event Context
+**/
+VOID
+EFIAPI
+NorFlashVirtualNotifyEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
+
+    // Convert BlockIo protocol
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
+
+    // Convert Fvb
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
+    EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
+
+    if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
+      EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->ShadowBuffer);
+    }
+  }
+
+  return;
+}
+
+EFI_STATUS
+EFIAPI
+StandaloneMmNorFlashInitialise (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_MM_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+  UINT32                  Index;
+  NOR_FLASH_DESCRIPTION*  NorFlashDevices;
+  BOOLEAN                 ContainVariableStorage;
+
+  Status = NorFlashPlatformInitialization ();
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
+    return Status;
+  }
+
+  Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
+    return Status;
+  }
+
+  mNorFlashInstances = AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) * mNorFlashDeviceCount);
+
+  for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+    // Check if this NOR Flash device contain the variable storage region
+    ContainVariableStorage =
+        (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
+        (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <= NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
+
+    Status = NorFlashCreateInstance (
+      NorFlashDevices[Index].DeviceBaseAddress,
+      NorFlashDevices[Index].RegionBaseAddress,
+      NorFlashDevices[Index].Size,
+      Index,
+      NorFlashDevices[Index].BlockSize,
+      ContainVariableStorage,
+      &mNorFlashInstances[Index]
+    );
+    if (EFI_ERROR(Status)) {
+      DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",Index));
+    }
+  }
+  return Status;
+}
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf
new file mode 100644
index 0000000..9f29bd4
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf
@@ -0,0 +1,76 @@
+#/** @file
+#
+#  Component description file for NorFlashDxe module
+#
+#  Copyright (c) 2018, ARM Limited. All rights reserved.
+#
+#  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.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = StandaloneMmNorFlash
+  FILE_GUID                      = 166F677B-DAC9-4AE4-AD34-2FF2504B0637
+  MODULE_TYPE                    = MM_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  ENTRY_POINT                    = StandaloneMmNorFlashInitialise
+
+[Sources.common]
+  NorFlashStandaloneMm.c
+  NorFlashFvbDxe.c
+  NorFlashBlockIoDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+  StandaloneMmDriverEntryPoint
+  BaseMemoryLib
+  ArmSvcLib
+  ArmLib
+  IoLib
+  BaseLib
+  DebugLib
+  HobLib
+  MemoryAllocationLib
+  NorFlashPlatformLib
+  MmServicesTableLib
+
+[Guids]
+  gEfiSystemNvDataFvGuid
+  gEfiVariableGuid
+  gEfiAuthenticatedVariableGuid
+  gEfiEventVirtualAddressChangeGuid
+  gEdkiiNvVarStoreFormattedGuid     ## PRODUCES ## PROTOCOL
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiDevicePathProtocolGuid
+  gEfiSmmFirmwareVolumeBlockProtocolGuid
+  gEfiDiskIoProtocolGuid
+
+[Pcd.common]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+  gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked
+
+[Depex]
+  TRUE
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (8 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 09/11] ArmPlatformPkg/NorFlashDxe: allow reusability as a MM driver Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-03  1:14   ` Zhang, Chao B
  2019-01-02 13:13 ` [PATCH v2 11/11] CryptoPkg/BaseCryptLib: " Jagadeesh Ujja
  10 siblings, 1 reply; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

“AuthVariableLib” library can be used by MM_STANDALONE drivers as well.
So add MM_STANDALONE as the module type this library supports.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
---
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
index 572ba4e..4294d3b 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
@@ -2,6 +2,7 @@
 #  Provides authenticated variable services.
 #
 #  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions
@@ -21,12 +22,12 @@
   FILE_GUID                      = B23CF5FB-6FCC-4422-B145-D855DBC05457
   MODULE_TYPE                    = DXE_RUNTIME_DRIVER
   VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
 
 #
 # The following information is for reference only and not required by the build tools.
 #
-#  VALID_ARCHITECTURES           = IA32 X64
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
 #
 
 [Sources]
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 11/11] CryptoPkg/BaseCryptLib: allow MM_STANDALONE drivers to use this library
  2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
                   ` (9 preceding siblings ...)
  2019-01-02 13:13 ` [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
@ 2019-01-02 13:13 ` Jagadeesh Ujja
  2019-01-04 10:35   ` Ard Biesheuvel
  10 siblings, 1 reply; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-02 13:13 UTC (permalink / raw)
  To: edk2-devel, liming.gao, chao.b.zhang, leif.lindholm,
	ard.biesheuvel, Achin.Gupta, Supreeth.Venkatesh, jian.j.wang

“SmmCryptLib” library can be used by MM_STANDALONE drivers as well.
So add MM_STANDALONE as the module type this library supports.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
---
 CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index 4829669..9a63419 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -30,7 +30,7 @@
   MODULE_TYPE                    = DXE_SMM_DRIVER
   VERSION_STRING                 = 1.0
   PI_SPECIFICATION_VERSION       = 0x0001000A
-  LIBRARY_CLASS                  = BaseCryptLib|DXE_SMM_DRIVER SMM_CORE
+  LIBRARY_CLASS                  = BaseCryptLib|DXE_SMM_DRIVER SMM_CORE MM_STANDALONE
 
 #
 # The following information is for reference only and not required by the build tools.
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 05/11] MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver
  2019-01-02 13:13 ` [PATCH v2 05/11] MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver Jagadeesh Ujja
@ 2019-01-02 17:15   ` Ard Biesheuvel
  0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-02 17:15 UTC (permalink / raw)
  To: Jagadeesh Ujja
  Cc: edk2-devel@lists.01.org, Gao, Liming, Zhang, Chao B,
	Leif Lindholm, Achin Gupta, Supreeth Venkatesh, Jian J Wang

On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>
> Adapt the FaultTolerantWriteDxe driver to be used as a MM_STANDALONE
> driver to provide UEFI fault tolerant write protocol functionality
> for variable reclaim operation on EFI variables stored on a NOR flash
> that is only accessible to code executing in MM Standalone mode.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> ---
>  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf          |   1 +
>  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c            | 203 +++++++++++++++-----
>  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf | 101 ++++++++++
>  MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c               |  27 +--
>  4 files changed, 271 insertions(+), 61 deletions(-)
>
> diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
> index dcde58d..026bc60 100644
> --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
> +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
> @@ -77,6 +77,7 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase      ## SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64    ## CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize      ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
>
>  #
>  # gBS->CalculateCrc32() is consumed in EntryPoint.
> diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
> index 481fea3..33f99e6 100644
> --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
> +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
> @@ -44,6 +44,7 @@
>    This driver need to make sure the CommBuffer is not in the SMRAM range.
>
>  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2018, ARM Limited. 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
> @@ -55,13 +56,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>  **/
>
>  #include <PiSmm.h>
> +#include <PiMm.h>
>  #include <Library/SmmServicesTableLib.h>
>  #include <Library/SmmMemLib.h>
> +#include <Library/StandaloneMmMemLib.h>
>  #include <Library/BaseLib.h>
>  #include <Protocol/SmmSwapAddressRange.h>
>  #include "FaultTolerantWrite.h"
>  #include "FaultTolerantWriteSmmCommon.h"
>  #include <Protocol/SmmEndOfDxe.h>
> +#include <Library/StandaloneMmServicesTableLib.h>
>
>  EFI_EVENT                                 mFvbRegistration = NULL;
>  EFI_FTW_DEVICE                            *mFtwDevice      = NULL;
> @@ -92,11 +96,19 @@ FtwGetFvbByHandle (
>    //
>    // To get the SMM FVB protocol interface on the handle
>    //
> -  return gSmst->SmmHandleProtocol (
> -                  FvBlockHandle,
> -                  &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> -                  (VOID **) FvBlock
> -                  );
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    return gSmst->SmmHandleProtocol (
> +                    FvBlockHandle,
> +                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                    (VOID **) FvBlock
> +                    );
> +  } else {
> +    return gMmst->MmHandleProtocol (
> +                    FvBlockHandle,
> +                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                    (VOID **) FvBlock
> +                    );
> +  }
>  }
>
>  /**
> @@ -119,11 +131,19 @@ FtwGetSarProtocol (
>    //
>    // Locate Smm Swap Address Range protocol
>    //
> -  Status = gSmst->SmmLocateProtocol (
> -                    &gEfiSmmSwapAddressRangeProtocolGuid,
> -                    NULL,
> -                    SarProtocol
> -                    );
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    Status = gSmst->SmmLocateProtocol (
> +                      &gEfiSmmSwapAddressRangeProtocolGuid,
> +                      NULL,
> +                      SarProtocol
> +                      );
> +  } else {
> +    Status = gMmst->MmLocateProtocol (
> +                      &gEfiSmmSwapAddressRangeProtocolGuid,
> +                      NULL,
> +                      SarProtocol
> +                      );
> +  }
>    return Status;
>  }
>
> @@ -158,13 +178,23 @@ GetFvbCountAndBuffer (
>    BufferSize     = 0;
>    *NumberHandles = 0;
>    *Buffer        = NULL;
> -  Status = gSmst->SmmLocateHandle (
> -                    ByProtocol,
> -                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> -                    NULL,
> -                    &BufferSize,
> -                    *Buffer
> -                    );
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    Status = gSmst->SmmLocateHandle (
> +                      ByProtocol,
> +                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                      NULL,
> +                      &BufferSize,
> +                      *Buffer
> +                      );
> +  } else {
> +    Status = gMmst->MmLocateHandle (
> +                      ByProtocol,
> +                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                      NULL,
> +                      &BufferSize,
> +                      *Buffer
> +                      );
> +  }
>    if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
>      return EFI_NOT_FOUND;
>    }
> @@ -173,15 +203,23 @@ GetFvbCountAndBuffer (
>    if (*Buffer == NULL) {
>      return EFI_OUT_OF_RESOURCES;
>    }
> -
> -  Status = gSmst->SmmLocateHandle (
> -                    ByProtocol,
> -                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> -                    NULL,
> -                    &BufferSize,
> -                    *Buffer
> -                    );
> -
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    Status = gSmst->SmmLocateHandle (
> +                      ByProtocol,
> +                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                      NULL,
> +                      &BufferSize,
> +                      *Buffer
> +                      );
> +  } else {
> +    Status = gMmst->MmLocateHandle (
> +                      ByProtocol,
> +                      &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                      NULL,
> +                      &BufferSize,
> +                      *Buffer
> +                      );
> +  }
>    *NumberHandles = BufferSize / sizeof(EFI_HANDLE);
>    if (EFI_ERROR(Status)) {
>      *NumberHandles = 0;
> @@ -335,10 +373,16 @@ SmmFaultTolerantWriteHandler (
>      return EFI_SUCCESS;
>    }
>    CommBufferPayloadSize = TempCommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE;
> -
> -  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
> -    DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
> -    return EFI_SUCCESS;
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
> +      DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
> +      return EFI_SUCCESS;
> +    }
> +  } else {
> +    if (!MmIsBufferOutsideMmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
> +      DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
> +      return EFI_SUCCESS;
> +    }
>    }
>
>    SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)CommBuffer;
> @@ -531,11 +575,19 @@ FvbNotificationEvent (
>    // Just return to avoid install SMM FaultTolerantWriteProtocol again
>    // if SMM Fault Tolerant Write protocol had been installed.
>    //
> -  Status = gSmst->SmmLocateProtocol (
> -                    &gEfiSmmFaultTolerantWriteProtocolGuid,
> -                    NULL,
> -                    (VOID **) &FtwProtocol
> -                    );
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    Status = gSmst->SmmLocateProtocol (
> +                      &gEfiSmmFaultTolerantWriteProtocolGuid,
> +                      NULL,
> +                      (VOID **) &FtwProtocol
> +                      );
> +  } else {
> +    Status = gMmst->MmLocateProtocol (
> +                      &gEfiSmmFaultTolerantWriteProtocolGuid,
> +                      NULL,
> +                      (VOID **) &FtwProtocol
> +                      );
> +  }
>    if (!EFI_ERROR (Status)) {
>      return EFI_SUCCESS;
>    }
> @@ -551,31 +603,45 @@ FvbNotificationEvent (
>    //
>    // Install protocol interface
>    //
> -  Status = gSmst->SmmInstallProtocolInterface (
> -                    &mFtwDevice->Handle,
> -                    &gEfiSmmFaultTolerantWriteProtocolGuid,
> -                    EFI_NATIVE_INTERFACE,
> -                    &mFtwDevice->FtwInstance
> -                    );
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    Status = gSmst->SmmInstallProtocolInterface (
> +                      &mFtwDevice->Handle,
> +                      &gEfiSmmFaultTolerantWriteProtocolGuid,
> +                      EFI_NATIVE_INTERFACE,
> +                      &mFtwDevice->FtwInstance
> +                      );
> +  } else {
> +    Status = gMmst->MmInstallProtocolInterface (
> +                      &mFtwDevice->Handle,
> +                      &gEfiSmmFaultTolerantWriteProtocolGuid,
> +                      EFI_NATIVE_INTERFACE,
> +                      &mFtwDevice->FtwInstance
> +                      );
> +  }
>    ASSERT_EFI_ERROR (Status);
>
>    ///
>    /// Register SMM FTW SMI handler
>    ///
> -  Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
> -  ASSERT_EFI_ERROR (Status);
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
> +    ASSERT_EFI_ERROR (Status);
>
> -  //
> -  // Notify the Ftw wrapper driver SMM Ftw is ready
> -  //
> -  FtwHandle = NULL;
> -  Status = gBS->InstallProtocolInterface (
> +    //
> +    // Notify the Ftw wrapper driver SMM Ftw is ready
> +    //
> +    FtwHandle = NULL;
> +    Status = gBS->InstallProtocolInterface (
>                    &FtwHandle,
>                    &gEfiSmmFaultTolerantWriteProtocolGuid,
>                    EFI_NATIVE_INTERFACE,
>                    NULL
>                    );
> -  ASSERT_EFI_ERROR (Status);
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    Status = gMmst->MmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
> +    ASSERT_EFI_ERROR (Status);
> +  }
>
>    return EFI_SUCCESS;
>  }
> @@ -655,3 +721,42 @@ SmmFaultTolerantWriteInitialize (
>
>    return EFI_SUCCESS;
>  }
> +
> +/**
> +  This function is the entry point of the Fault Tolerant Write driver.
> +
> +  @param[in] ImageHandle        A handle for the image that is initializing this driver
> +  @param[in] SystemTable        A pointer to the EFI system table
> +
> +  @retval EFI_SUCCESS           The initialization finished successfully.
> +  @retval EFI_OUT_OF_RESOURCES  Allocate memory error
> +  @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +StandaloneMmFaultTolerantWriteInitialize (
> +  IN EFI_HANDLE                           ImageHandle,
> +  IN EFI_MM_SYSTEM_TABLE                  *SystemTable
> +  )
> +{
> +  EFI_STATUS                              Status;
> +
> +  //
> +  // Allocate private data structure for SMM FTW protocol and do some initialization
> +  //
> +  Status = InitFtwDevice (&mFtwDevice);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +  Status = gMmst->MmRegisterProtocolNotify (
> +                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
> +                    FvbNotificationEvent,
> +                    &mFvbRegistration
> +                    );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  FvbNotificationEvent (NULL, NULL, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
> new file mode 100644
> index 0000000..615f688
> --- /dev/null
> +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
> @@ -0,0 +1,101 @@
> +## @file
> +#   Fault Tolerant Write Smm Driver.
> +#
> +#   This driver installs SMM Fault Tolerant Write (FTW) protocol, which provides fault
> +#   tolerant write capability in SMM environment for block devices. Its implementation
> +#   depends on the full functionality SMM FVB protocol that support read, write/erase
> +#   flash access.
> +#
> +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2018, ARM Limited. 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.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = FaultTolerantWriteMmStandalone
> +  MODULE_UNI_FILE                = SmmFaultTolerantWriteDxe.uni
> +  FILE_GUID                      = 470CB248-E8AC-473c-BB4F-81069A1FE6FD
> +  MODULE_TYPE                    = MM_STANDALONE
> +  VERSION_STRING                 = 1.0
> +  PI_SPECIFICATION_VERSION       = 0x00010032
> +  ENTRY_POINT                    = StandaloneMmFaultTolerantWriteInitialize
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
> +#
> +
> +[Sources]
> +  FtwMisc.c
> +  UpdateWorkingBlock.c
> +  FaultTolerantWrite.c
> +  FaultTolerantWriteSmm.c
> +  FaultTolerantWrite.h
> +  FaultTolerantWriteSmmCommon.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  StandaloneMmPkg/StandaloneMmPkg.dec
> +
> +[LibraryClasses]
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +  DebugLib
> +  PcdLib
> +  ReportStatusCodeLib
> +  MemLib
> +  StandaloneMmDriverEntryPoint
> +  BaseLib
> +  MmServicesTableLib
> +
> +[Guids]
> +  #
> +  # Signature in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
> +  #
> +  ## CONSUMES           ## GUID
> +  ## PRODUCES           ## GUID
> +  gEdkiiWorkingBlockSignatureGuid
> +
> +[Protocols]
> +  gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable  ## SOMETIMES_CONSUMES
> +  ## NOTIFY
> +  ## CONSUMES
> +  gEfiSmmFirmwareVolumeBlockProtocolGuid
> +  ## PRODUCES
> +  ## UNDEFINED # SmiHandlerRegister
> +  gEfiSmmFaultTolerantWriteProtocolGuid
> +  gEfiSmmEndOfDxeProtocolGuid                      ## CONSUMES
> +
> +[FeaturePcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable    ## CONSUMES
> +
> +[Pcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase    ## SOMETIMES_CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64  ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize    ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase      ## SOMETIMES_CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64    ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize      ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdStandaloneMmVariableEnabled
> +#
> +# gBS->CalculateCrc32() is consumed in EntryPoint.
> +# PI spec said: When the DXE Foundation is notified that the EFI_RUNTIME_ARCH_PROTOCOL
> +# has been installed, then the Boot Service CalculateCrc32() is available.
> +# So add gEfiRuntimeArchProtocolGuid Depex here.
> +#
> +[Depex]
> +  TRUE
> +  #gEfiSmmFirmwareVolumeBlockProtocolGuid AND gEfiRuntimeArchProtocolGuid
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  SmmFaultTolerantWriteDxeExtra.uni
> diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
> index 50d3421..9c98e57 100644
> --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
> +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
> @@ -3,6 +3,7 @@
>     Internal functions to operate Working Block Space.
>
>  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2018, ARM Limited. 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
> @@ -57,19 +58,21 @@ InitializeLocalWorkSpaceHeader (
>      );
>    mWorkingBlockHeader.WriteQueueSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
>
> -  //
> -  // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
> -  //
> +  if (!PcdGetBool (PcdStandaloneMmVariableEnabled)) {
> +    //
> +    // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
> +    //
>
> -  //
> -  // Calculate the Crc of woking block header
> -  //
> -  Status = gBS->CalculateCrc32 (
> -                  &mWorkingBlockHeader,
> -                  sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
> -                  &mWorkingBlockHeader.Crc
> -                  );
> -  ASSERT_EFI_ERROR (Status);
> +    //
> +    // Calculate the Crc of woking block header
> +    //
> +    Status = gBS->CalculateCrc32 (
> +                    &mWorkingBlockHeader,
> +                    sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
> +                    &mWorkingBlockHeader.Crc
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +  }
>

You cannot just remove this CRC32 calculation, can you?


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
  2019-01-02 13:13 ` [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
@ 2019-01-03  1:14   ` Zhang, Chao B
  2019-01-03  6:15     ` Jagadeesh Ujja
  0 siblings, 1 reply; 32+ messages in thread
From: Zhang, Chao B @ 2019-01-03  1:14 UTC (permalink / raw)
  To: Jagadeesh Ujja, edk2-devel@lists.01.org, Gao, Liming,
	leif.lindholm@linaro.org, ard.biesheuvel@linaro.org,
	Achin.Gupta@arm.com, Supreeth.Venkatesh@arm.com, Wang, Jian J

Reviewed-by : Chao Zhang <chao.b.zhang@intel.com>


-----Original Message-----
From: Jagadeesh Ujja [mailto:jagadeesh.ujja@arm.com] 
Sent: Wednesday, January 2, 2019 9:14 PM
To: edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; leif.lindholm@linaro.org; ard.biesheuvel@linaro.org; Achin.Gupta@arm.com; Supreeth.Venkatesh@arm.com; Wang, Jian J <jian.j.wang@intel.com>
Subject: [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library

“AuthVariableLib” library can be used by MM_STANDALONE drivers as well.
So add MM_STANDALONE as the module type this library supports.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
---
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
index 572ba4e..4294d3b 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
@@ -2,6 +2,7 @@
 #  Provides authenticated variable services.
 #
 #  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
 #
 #  This program and the accompanying materials  #  are licensed and made available under the terms and conditions @@ -21,12 +22,12 @@
   FILE_GUID                      = B23CF5FB-6FCC-4422-B145-D855DBC05457
   MODULE_TYPE                    = DXE_RUNTIME_DRIVER
   VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
 
 #
 # The following information is for reference only and not required by the build tools.
 #
-#  VALID_ARCHITECTURES           = IA32 X64
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
 #
 
 [Sources]
--
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
  2019-01-03  1:14   ` Zhang, Chao B
@ 2019-01-03  6:15     ` Jagadeesh Ujja
  2019-01-04 10:41       ` Ard Biesheuvel
  0 siblings, 1 reply; 32+ messages in thread
From: Jagadeesh Ujja @ 2019-01-03  6:15 UTC (permalink / raw)
  To: Zhang, Chao B
  Cc: edk2-devel@lists.01.org, Gao, Liming, leif.lindholm@linaro.org,
	ard.biesheuvel@linaro.org, Achin.Gupta@arm.com,
	Supreeth.Venkatesh@arm.com, Wang, Jian J

On Thu, Jan 3, 2019 at 6:45 AM Zhang, Chao B <chao.b.zhang@intel.com> wrote:
>
> Reviewed-by : Chao Zhang <chao.b.zhang@intel.com>

Hi Chao Zhang,

Thanks for the review, I will not be having any new changes with this
specific patch.
Can you please merge this patch, so that I will not resubmit with
other patch set

Thanks
Jagadeesh
>
> -----Original Message-----
> From: Jagadeesh Ujja [mailto:jagadeesh.ujja@arm.com]
> Sent: Wednesday, January 2, 2019 9:14 PM
> To: edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; leif.lindholm@linaro.org; ard.biesheuvel@linaro.org; Achin.Gupta@arm.com; Supreeth.Venkatesh@arm.com; Wang, Jian J <jian.j.wang@intel.com>
> Subject: [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
>
> “AuthVariableLib” library can be used by MM_STANDALONE drivers as well.
> So add MM_STANDALONE as the module type this library supports.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
> ---
>  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
> index 572ba4e..4294d3b 100644
> --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
> +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
> @@ -2,6 +2,7 @@
>  #  Provides authenticated variable services.
>  #
>  #  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
>  #
>  #  This program and the accompanying materials  #  are licensed and made available under the terms and conditions @@ -21,12 +22,12 @@
>    FILE_GUID                      = B23CF5FB-6FCC-4422-B145-D855DBC05457
>    MODULE_TYPE                    = DXE_RUNTIME_DRIVER
>    VERSION_STRING                 = 1.0
> -  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
> +  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
>
>  #
>  # The following information is for reference only and not required by the build tools.
>  #
> -#  VALID_ARCHITECTURES           = IA32 X64
> +#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
>  #
>
>  [Sources]
> --
> 2.7.4
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-02 13:13 ` [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library Jagadeesh Ujja
@ 2019-01-03 11:03   ` Ard Biesheuvel
  2019-01-03 16:14     ` Laszlo Ersek
  0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-03 11:03 UTC (permalink / raw)
  To: Jagadeesh Ujja, Gao, Liming, Kinney, Michael D, Laszlo Ersek
  Cc: edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Achin Gupta, Supreeth Venkatesh, Jian J Wang

On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>
> Some of the existing DXE drivers can be refactored to execute within
> the Standalone MM execution environment as well. Allow such drivers to
> get access to the Standalone MM services tables.
>
> Add a mechanism to determine the execution mode is required.
> i.e, in MM or non-MM
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> ---
>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
>  MdePkg/MdePkg.dec                                                            |  4 ++
>  4 files changed, 122 insertions(+)
>

OK, so since the PI spec only refers to MM mode now, this library
class should be

MmServicesTableLib|Include/Library/MmServicesTableLib.h

with an implementation in MdeModulePkg that exposes the deprecated SMM
system table as the MM system table.

In StandaloneMmPkg, we can add an implementation that exposes the
standalone MM system table.

(They are binary compatible, so it is just a matter of casting one
pointer to the other)

With this in place, we can go ahead and update FaultTolerantWrite and
Variable SMM driver to switch from SmmServicesTableLib to
MmServicesTableLib. This will require existing x86 platforms to define
a new library class resolution for MmServicesTableLib, referring to
the implementation in MdeModulePkg. This is unfortunate, but it is an
unavoidable consequence of the PI spec changes.

Remaining question is what to do with InSmm() ...


> diff --git a/MdePkg/Include/Library/StandaloneMmServicesTableLib.h b/MdePkg/Include/Library/StandaloneMmServicesTableLib.h
> new file mode 100644
> index 0000000..3a27ac4
> --- /dev/null
> +++ b/MdePkg/Include/Library/StandaloneMmServicesTableLib.h
> @@ -0,0 +1,43 @@
> +/** @file
> +  Provides a service to retrieve a pointer to the Standalone MM Services Table.
> +  Provides a InMm implementation for RUNTIME DXE drivers
> +
> +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2016 - 2018, ARM Limited. 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 __MM_SERVICES_TABLE_LIB_H__
> +#define __MM_SERVICES_TABLE_LIB_H__
> +
> +#include <PiMm.h>
> +#include <PiDxe.h>
> +
> +extern EFI_MM_SYSTEM_TABLE         *gMmst;
> +
> +/**
> +  This function allows the caller to determine if the driver is executing in
> +  Standalone Management Mode(SMM).
> +
> +  This function returns TRUE if the driver is executing in SMM and FALSE if the
> +  driver is not executing in SMM.
> +
> +  @retval  TRUE  The driver is executing in Standalone Management Mode (SMM).
> +  @retval  FALSE The driver is not executing in Standalone Management Mode (SMM).
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +InMm (
> +  VOID
> +  );
> +
> +#endif
> diff --git a/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
> new file mode 100644
> index 0000000..6f37cd8
> --- /dev/null
> +++ b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c
> @@ -0,0 +1,39 @@
> +/** @file
> +  Standalone MM Services Table Library.
> +
> +  Copyright (c) 2018, ARM Limited. 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.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <PiMm.h>
> +
> +EFI_MM_SYSTEM_TABLE         *gMmst = NULL;
> +
> +/**
> +  This function allows the caller to determine if the driver is executing in
> +  Standalone Management Mode(SMM).
> +
> +  This function returns TRUE if the driver is executing in SMM and FALSE if the
> +  driver is not executing in SMM.
> +
> +  @retval  TRUE  The driver is executing in Standalone Management Mode (SMM).
> +  @retval  FALSE The driver is not executing in Standalone Management Mode (SMM).
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +InMm (
> +  VOID
> +  )
> +{
> +  return FALSE;
> +}
> diff --git a/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
> new file mode 100644
> index 0000000..c94b605
> --- /dev/null
> +++ b/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
> @@ -0,0 +1,36 @@
> +## @file
> +#  Provides StandaloneMmServicesTableLib.
> +#
> +#  Copyright (c) 2018, ARM Limited. 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.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = StandaloneMmServicesTableLib
> +  FILE_GUID                      = 8099cfbf-9564-4c9b-9052-e66b1da88930
> +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = StandaloneMmServicesTableLib |DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
> +#
> +
> +[Sources]
> +  StandaloneMmServicesTableLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +
> diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
> index 712bd46..ec9b266 100644
> --- a/MdePkg/MdePkg.dec
> +++ b/MdePkg/MdePkg.dec
> @@ -243,6 +243,10 @@
>    ##
>    SafeIntLib|Include/Library/SafeIntLib.h
>
> +  ## @libraryclass Provides a service to retrieve a pointer to the Standalone MM Services Table.
> +  #                 Only available to MM_STANDALONE module types.
> +  MmServicesTableLib|Include/Library/StandaloneMmServicesTableLib.h
> +
>  [LibraryClasses.IA32, LibraryClasses.X64]
>    ##  @libraryclass  Abstracts both S/W SMI generation and detection.
>    ##
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-03 11:03   ` Ard Biesheuvel
@ 2019-01-03 16:14     ` Laszlo Ersek
  2019-01-04 11:57       ` Ard Biesheuvel
  0 siblings, 1 reply; 32+ messages in thread
From: Laszlo Ersek @ 2019-01-03 16:14 UTC (permalink / raw)
  To: Ard Biesheuvel, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D
  Cc: edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Achin Gupta, Supreeth Venkatesh, Jian J Wang

On 01/03/19 12:03, Ard Biesheuvel wrote:
> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>>
>> Some of the existing DXE drivers can be refactored to execute within
>> the Standalone MM execution environment as well. Allow such drivers to
>> get access to the Standalone MM services tables.
>>
>> Add a mechanism to determine the execution mode is required.
>> i.e, in MM or non-MM
>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
>> ---
>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
>>  MdePkg/MdePkg.dec                                                            |  4 ++
>>  4 files changed, 122 insertions(+)
>>
> 
> OK, so since the PI spec only refers to MM mode now, this library
> class should be
> 
> MmServicesTableLib|Include/Library/MmServicesTableLib.h
> 
> with an implementation in MdeModulePkg that exposes the deprecated SMM
> system table as the MM system table.
> 
> In StandaloneMmPkg, we can add an implementation that exposes the
> standalone MM system table.
> 
> (They are binary compatible, so it is just a matter of casting one
> pointer to the other)
> 
> With this in place, we can go ahead and update FaultTolerantWrite and
> Variable SMM driver to switch from SmmServicesTableLib to
> MmServicesTableLib. This will require existing x86 platforms to define
> a new library class resolution for MmServicesTableLib, referring to
> the implementation in MdeModulePkg. This is unfortunate, but it is an
> unavoidable consequence of the PI spec changes.

It shouldn't be too intrusive or hard to review, I expect.

> 
> Remaining question is what to do with InSmm() ...

I'm lacking the context on this; on the other hand, I can refer back to
at least one earlier discussion -- there had been multiple -- of the
discrepancy between the PI spec and the edk2 code. See:

- bullet (9) in
<http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
- and
<http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.

Not sure how that can be applied to Arm.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 11/11] CryptoPkg/BaseCryptLib: allow MM_STANDALONE drivers to use this library
  2019-01-02 13:13 ` [PATCH v2 11/11] CryptoPkg/BaseCryptLib: " Jagadeesh Ujja
@ 2019-01-04 10:35   ` Ard Biesheuvel
  0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-04 10:35 UTC (permalink / raw)
  To: Jagadeesh Ujja, Ting Ye
  Cc: edk2-devel@lists.01.org, Gao, Liming, Zhang, Chao B,
	Leif Lindholm, Achin Gupta, Supreeth Venkatesh, Jian J Wang

(add the CryptoPkg maintainer)

On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>
> “SmmCryptLib” library can be used by MM_STANDALONE drivers as well.
> So add MM_STANDALONE as the module type this library supports.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>

The subject is a bit misleading, please change it to

CryptoPkg/BaseCryptLib: allow MM_STANDALONE drivers to use SmmCryptLib

With that,

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>


> ---
>  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> index 4829669..9a63419 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> @@ -30,7 +30,7 @@
>    MODULE_TYPE                    = DXE_SMM_DRIVER
>    VERSION_STRING                 = 1.0
>    PI_SPECIFICATION_VERSION       = 0x0001000A
> -  LIBRARY_CLASS                  = BaseCryptLib|DXE_SMM_DRIVER SMM_CORE
> +  LIBRARY_CLASS                  = BaseCryptLib|DXE_SMM_DRIVER SMM_CORE MM_STANDALONE
>
>  #
>  # The following information is for reference only and not required by the build tools.
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 08/11] MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this library
  2019-01-02 13:13 ` [PATCH v2 08/11] MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
@ 2019-01-04 10:36   ` Ard Biesheuvel
  0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-04 10:36 UTC (permalink / raw)
  To: Jagadeesh Ujja
  Cc: edk2-devel@lists.01.org, Gao, Liming, Zhang, Chao B,
	Leif Lindholm, Achin Gupta, Supreeth Venkatesh, Jian J Wang

On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>
> “VarCheckLib” library can be used by MM_STANDALONE drivers as well.
> So add MM_STANDALONE as the module type this library supports.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf b/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> index 099f83d..c8cf810 100644
> --- a/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> +++ b/MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> @@ -2,6 +2,7 @@
>  #  Provides variable check services and database management.
>  #
>  #  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
>  #
>  #  This program and the accompanying materials
>  #  are licensed and made available under the terms and conditions
> @@ -21,12 +22,12 @@
>    FILE_GUID                      = 63E12D08-0C5D-47F8-95E4-09F89D7506C5
>    MODULE_TYPE                    = DXE_RUNTIME_DRIVER
>    VERSION_STRING                 = 1.0
> -  LIBRARY_CLASS                  = VarCheckLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
> +  LIBRARY_CLASS                  = VarCheckLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
>
>  #
>  # The following information is for reference only and not required by the build tools.
>  #
> -#  VALID_ARCHITECTURES           = IA32 X64
> +#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
>  #
>
>  [Sources]
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
  2019-01-03  6:15     ` Jagadeesh Ujja
@ 2019-01-04 10:41       ` Ard Biesheuvel
  0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-04 10:41 UTC (permalink / raw)
  To: Jagadeesh Ujja
  Cc: Zhang, Chao B, edk2-devel@lists.01.org, Gao, Liming,
	leif.lindholm@linaro.org, Achin.Gupta@arm.com,
	Supreeth.Venkatesh@arm.com, Wang, Jian J

On Thu, 3 Jan 2019 at 07:15, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>
> On Thu, Jan 3, 2019 at 6:45 AM Zhang, Chao B <chao.b.zhang@intel.com> wrote:
> >
> > Reviewed-by : Chao Zhang <chao.b.zhang@intel.com>
>
> Hi Chao Zhang,
>
> Thanks for the review, I will not be having any new changes with this
> specific patch.
> Can you please merge this patch, so that I will not resubmit with
> other patch set
>

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Pushed as 8ef653aa5aad..38f3c1b0d274

> >
> > -----Original Message-----
> > From: Jagadeesh Ujja [mailto:jagadeesh.ujja@arm.com]
> > Sent: Wednesday, January 2, 2019 9:14 PM
> > To: edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; leif.lindholm@linaro.org; ard.biesheuvel@linaro.org; Achin.Gupta@arm.com; Supreeth.Venkatesh@arm.com; Wang, Jian J <jian.j.wang@intel.com>
> > Subject: [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library
> >
> > “AuthVariableLib” library can be used by MM_STANDALONE drivers as well.
> > So add MM_STANDALONE as the module type this library supports.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> > Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
> > ---
> >  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
> > index 572ba4e..4294d3b 100644
> > --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
> > +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
> > @@ -2,6 +2,7 @@
> >  #  Provides authenticated variable services.
> >  #
> >  #  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
> > +#  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
> >  #
> >  #  This program and the accompanying materials  #  are licensed and made available under the terms and conditions @@ -21,12 +22,12 @@
> >    FILE_GUID                      = B23CF5FB-6FCC-4422-B145-D855DBC05457
> >    MODULE_TYPE                    = DXE_RUNTIME_DRIVER
> >    VERSION_STRING                 = 1.0
> > -  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
> > +  LIBRARY_CLASS                  = AuthVariableLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER MM_STANDALONE
> >
> >  #
> >  # The following information is for reference only and not required by the build tools.
> >  #
> > -#  VALID_ARCHITECTURES           = IA32 X64
> > +#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
> >  #
> >
> >  [Sources]
> > --
> > 2.7.4
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-03 16:14     ` Laszlo Ersek
@ 2019-01-04 11:57       ` Ard Biesheuvel
  2019-01-07 15:28         ` Laszlo Ersek
  0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-04 11:57 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Achin Gupta, Supreeth Venkatesh, Jian J Wang

On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 01/03/19 12:03, Ard Biesheuvel wrote:
> > On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
> >>
> >> Some of the existing DXE drivers can be refactored to execute within
> >> the Standalone MM execution environment as well. Allow such drivers to
> >> get access to the Standalone MM services tables.
> >>
> >> Add a mechanism to determine the execution mode is required.
> >> i.e, in MM or non-MM
> >>
> >> Contributed-under: TianoCore Contribution Agreement 1.1
> >> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> >> ---
> >>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
> >>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
> >>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
> >>  MdePkg/MdePkg.dec                                                            |  4 ++
> >>  4 files changed, 122 insertions(+)
> >>
> >
> > OK, so since the PI spec only refers to MM mode now, this library
> > class should be
> >
> > MmServicesTableLib|Include/Library/MmServicesTableLib.h
> >
> > with an implementation in MdeModulePkg that exposes the deprecated SMM
> > system table as the MM system table.
> >
> > In StandaloneMmPkg, we can add an implementation that exposes the
> > standalone MM system table.
> >
> > (They are binary compatible, so it is just a matter of casting one
> > pointer to the other)
> >
> > With this in place, we can go ahead and update FaultTolerantWrite and
> > Variable SMM driver to switch from SmmServicesTableLib to
> > MmServicesTableLib. This will require existing x86 platforms to define
> > a new library class resolution for MmServicesTableLib, referring to
> > the implementation in MdeModulePkg. This is unfortunate, but it is an
> > unavoidable consequence of the PI spec changes.
>
> It shouldn't be too intrusive or hard to review, I expect.
>
> >
> > Remaining question is what to do with InSmm() ...
>
> I'm lacking the context on this; on the other hand, I can refer back to
> at least one earlier discussion -- there had been multiple -- of the
> discrepancy between the PI spec and the edk2 code. See:
>
> - bullet (9) in
> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
> - and
> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
>
> Not sure how that can be applied to Arm.
>

The code I posted yesterday does not use InMm() at all. For standalone
MM, it should always return TRUE anyway, and any code that a driver
would execute if it returned FALSE needs to be factored out anyway,
since it should not end up in standalone MM binaries as dead code.


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-04 11:57       ` Ard Biesheuvel
@ 2019-01-07 15:28         ` Laszlo Ersek
  2019-01-07 17:33           ` Ard Biesheuvel
  0 siblings, 1 reply; 32+ messages in thread
From: Laszlo Ersek @ 2019-01-07 15:28 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Achin Gupta, Supreeth Venkatesh, Jian J Wang

On 01/04/19 12:57, Ard Biesheuvel wrote:
> On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
>>
>> On 01/03/19 12:03, Ard Biesheuvel wrote:
>>> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
>>>>
>>>> Some of the existing DXE drivers can be refactored to execute within
>>>> the Standalone MM execution environment as well. Allow such drivers to
>>>> get access to the Standalone MM services tables.
>>>>
>>>> Add a mechanism to determine the execution mode is required.
>>>> i.e, in MM or non-MM
>>>>
>>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
>>>> ---
>>>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
>>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
>>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
>>>>  MdePkg/MdePkg.dec                                                            |  4 ++
>>>>  4 files changed, 122 insertions(+)
>>>>
>>>
>>> OK, so since the PI spec only refers to MM mode now, this library
>>> class should be
>>>
>>> MmServicesTableLib|Include/Library/MmServicesTableLib.h
>>>
>>> with an implementation in MdeModulePkg that exposes the deprecated SMM
>>> system table as the MM system table.
>>>
>>> In StandaloneMmPkg, we can add an implementation that exposes the
>>> standalone MM system table.
>>>
>>> (They are binary compatible, so it is just a matter of casting one
>>> pointer to the other)
>>>
>>> With this in place, we can go ahead and update FaultTolerantWrite and
>>> Variable SMM driver to switch from SmmServicesTableLib to
>>> MmServicesTableLib. This will require existing x86 platforms to define
>>> a new library class resolution for MmServicesTableLib, referring to
>>> the implementation in MdeModulePkg. This is unfortunate, but it is an
>>> unavoidable consequence of the PI spec changes.
>>
>> It shouldn't be too intrusive or hard to review, I expect.
>>
>>>
>>> Remaining question is what to do with InSmm() ...
>>
>> I'm lacking the context on this; on the other hand, I can refer back to
>> at least one earlier discussion -- there had been multiple -- of the
>> discrepancy between the PI spec and the edk2 code. See:
>>
>> - bullet (9) in
>> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
>> - and
>> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
>>
>> Not sure how that can be applied to Arm.
>>
> 
> The code I posted yesterday does not use InMm() at all. For standalone
> MM, it should always return TRUE anyway, and any code that a driver
> would execute if it returned FALSE needs to be factored out anyway,
> since it should not end up in standalone MM binaries as dead code.
> 

OK. That seems to make sense. I've read up a bit on "standalone MM" in
the PI v1.6 spec, vol 4. Having no access to UEFI protocols even in the
entry point function, at driver init time, seems challenging to me. I
guess I'll learn more about this as a part of the usual list traffic.

What is the MODULE_TYPE that standalone MM drivers use, in place of
DXE_SMM_DRIVER (= EFI_FV_FILETYPE_MM, 0x0A)?

Hm... from the other patches, it seems to be MM_STANDALONE (=
EFI_FV_FILETYPE_MM_STANDALONE, 0x0E). OK.

If I'd like to see a short summary of standalone MM, relative to
traditional MM, and why it is more suitable -- I presume -- for aarch64,
which document should I look at, from
<https://mantis.uefi.org/mantis/view.php?id=1390>, for example?

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 15:28         ` Laszlo Ersek
@ 2019-01-07 17:33           ` Ard Biesheuvel
  2019-01-07 18:50             ` Achin Gupta
  0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-07 17:33 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Achin Gupta, Supreeth Venkatesh, Jian J Wang

On Mon, 7 Jan 2019 at 16:28, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 01/04/19 12:57, Ard Biesheuvel wrote:
> > On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
> >>
> >> On 01/03/19 12:03, Ard Biesheuvel wrote:
> >>> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
> >>>>
> >>>> Some of the existing DXE drivers can be refactored to execute within
> >>>> the Standalone MM execution environment as well. Allow such drivers to
> >>>> get access to the Standalone MM services tables.
> >>>>
> >>>> Add a mechanism to determine the execution mode is required.
> >>>> i.e, in MM or non-MM
> >>>>
> >>>> Contributed-under: TianoCore Contribution Agreement 1.1
> >>>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> >>>> ---
> >>>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
> >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
> >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
> >>>>  MdePkg/MdePkg.dec                                                            |  4 ++
> >>>>  4 files changed, 122 insertions(+)
> >>>>
> >>>
> >>> OK, so since the PI spec only refers to MM mode now, this library
> >>> class should be
> >>>
> >>> MmServicesTableLib|Include/Library/MmServicesTableLib.h
> >>>
> >>> with an implementation in MdeModulePkg that exposes the deprecated SMM
> >>> system table as the MM system table.
> >>>
> >>> In StandaloneMmPkg, we can add an implementation that exposes the
> >>> standalone MM system table.
> >>>
> >>> (They are binary compatible, so it is just a matter of casting one
> >>> pointer to the other)
> >>>
> >>> With this in place, we can go ahead and update FaultTolerantWrite and
> >>> Variable SMM driver to switch from SmmServicesTableLib to
> >>> MmServicesTableLib. This will require existing x86 platforms to define
> >>> a new library class resolution for MmServicesTableLib, referring to
> >>> the implementation in MdeModulePkg. This is unfortunate, but it is an
> >>> unavoidable consequence of the PI spec changes.
> >>
> >> It shouldn't be too intrusive or hard to review, I expect.
> >>
> >>>
> >>> Remaining question is what to do with InSmm() ...
> >>
> >> I'm lacking the context on this; on the other hand, I can refer back to
> >> at least one earlier discussion -- there had been multiple -- of the
> >> discrepancy between the PI spec and the edk2 code. See:
> >>
> >> - bullet (9) in
> >> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
> >> - and
> >> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
> >>
> >> Not sure how that can be applied to Arm.
> >>
> >
> > The code I posted yesterday does not use InMm() at all. For standalone
> > MM, it should always return TRUE anyway, and any code that a driver
> > would execute if it returned FALSE needs to be factored out anyway,
> > since it should not end up in standalone MM binaries as dead code.
> >
>
> OK. That seems to make sense. I've read up a bit on "standalone MM" in
> the PI v1.6 spec, vol 4. Having no access to UEFI protocols even in the
> entry point function, at driver init time, seems challenging to me. I
> guess I'll learn more about this as a part of the usual list traffic.
>
> What is the MODULE_TYPE that standalone MM drivers use, in place of
> DXE_SMM_DRIVER (= EFI_FV_FILETYPE_MM, 0x0A)?
>
> Hm... from the other patches, it seems to be MM_STANDALONE (=
> EFI_FV_FILETYPE_MM_STANDALONE, 0x0E). OK.
>
> If I'd like to see a short summary of standalone MM, relative to
> traditional MM, and why it is more suitable -- I presume -- for aarch64,
> which document should I look at, from
> <https://mantis.uefi.org/mantis/view.php?id=1390>, for example?
>

Perhaps Achin can answer this, since he has been driving the spec side
of this? (and maintains StandaloneMmPkg)


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 17:33           ` Ard Biesheuvel
@ 2019-01-07 18:50             ` Achin Gupta
  2019-01-07 18:55               ` Ard Biesheuvel
  0 siblings, 1 reply; 32+ messages in thread
From: Achin Gupta @ 2019-01-07 18:50 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Laszlo Ersek, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On Mon, Jan 07, 2019 at 06:33:26PM +0100, Ard Biesheuvel wrote:
> On Mon, 7 Jan 2019 at 16:28, Laszlo Ersek <lersek@redhat.com> wrote:
> >
> > On 01/04/19 12:57, Ard Biesheuvel wrote:
> > > On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
> > >>
> > >> On 01/03/19 12:03, Ard Biesheuvel wrote:
> > >>> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
> > >>>>
> > >>>> Some of the existing DXE drivers can be refactored to execute within
> > >>>> the Standalone MM execution environment as well. Allow such drivers to
> > >>>> get access to the Standalone MM services tables.
> > >>>>
> > >>>> Add a mechanism to determine the execution mode is required.
> > >>>> i.e, in MM or non-MM
> > >>>>
> > >>>> Contributed-under: TianoCore Contribution Agreement 1.1
> > >>>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> > >>>> ---
> > >>>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
> > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
> > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
> > >>>>  MdePkg/MdePkg.dec                                                            |  4 ++
> > >>>>  4 files changed, 122 insertions(+)
> > >>>>
> > >>>
> > >>> OK, so since the PI spec only refers to MM mode now, this library
> > >>> class should be
> > >>>
> > >>> MmServicesTableLib|Include/Library/MmServicesTableLib.h
> > >>>
> > >>> with an implementation in MdeModulePkg that exposes the deprecated SMM
> > >>> system table as the MM system table.
> > >>>
> > >>> In StandaloneMmPkg, we can add an implementation that exposes the
> > >>> standalone MM system table.
> > >>>
> > >>> (They are binary compatible, so it is just a matter of casting one
> > >>> pointer to the other)
> > >>>
> > >>> With this in place, we can go ahead and update FaultTolerantWrite and
> > >>> Variable SMM driver to switch from SmmServicesTableLib to
> > >>> MmServicesTableLib. This will require existing x86 platforms to define
> > >>> a new library class resolution for MmServicesTableLib, referring to
> > >>> the implementation in MdeModulePkg. This is unfortunate, but it is an
> > >>> unavoidable consequence of the PI spec changes.
> > >>
> > >> It shouldn't be too intrusive or hard to review, I expect.
> > >>
> > >>>
> > >>> Remaining question is what to do with InSmm() ...
> > >>
> > >> I'm lacking the context on this; on the other hand, I can refer back to
> > >> at least one earlier discussion -- there had been multiple -- of the
> > >> discrepancy between the PI spec and the edk2 code. See:
> > >>
> > >> - bullet (9) in
> > >> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
> > >> - and
> > >> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
> > >>
> > >> Not sure how that can be applied to Arm.
> > >>
> > >
> > > The code I posted yesterday does not use InMm() at all. For standalone
> > > MM, it should always return TRUE anyway, and any code that a driver
> > > would execute if it returned FALSE needs to be factored out anyway,
> > > since it should not end up in standalone MM binaries as dead code.
> > >
> >
> > OK. That seems to make sense. I've read up a bit on "standalone MM" in
> > the PI v1.6 spec, vol 4. Having no access to UEFI protocols even in the
> > entry point function, at driver init time, seems challenging to me. I
> > guess I'll learn more about this as a part of the usual list traffic.
> >
> > What is the MODULE_TYPE that standalone MM drivers use, in place of
> > DXE_SMM_DRIVER (= EFI_FV_FILETYPE_MM, 0x0A)?
> >
> > Hm... from the other patches, it seems to be MM_STANDALONE (=
> > EFI_FV_FILETYPE_MM_STANDALONE, 0x0E). OK.
> >
> > If I'd like to see a short summary of standalone MM, relative to
> > traditional MM, and why it is more suitable -- I presume -- for aarch64,
> > which document should I look at, from
> > <https://mantis.uefi.org/mantis/view.php?id=1390>, for example?
> >
> 
> Perhaps Achin can answer this, since he has been driving the spec side
> of this? (and maintains StandaloneMmPkg)

The idea behind MM Standalone mode was to sandbox MM code in self sufficient
execution context. This was a step to avoid some of the vulnerabilities in
traditional SMM due to code and data sharing with DXE. 

On AArch64, the MM standalone mode is initialised during the SEC phase. This
corresponds to Trustzone initialisation. Furthermore, the MM standalone
execution context is placed in user mode (Secure EL0) instead of running it in a
privileged processor mode (S-EL1 or EL3 on AArch64, Ring -2 or SMM on x86). This
restricts what the MM standalone context can see and do. Lastly, after SEC no
more MM Standalone drivers can be initialized during PEI or DXE (in contrast to
the example in PI 1.6 Section 1.5.2). 

Hope that makes sense?

I have not seen all the patches in this and related series but the use of InMM()
to allow code to have a DXE driver or a MM Standalone driver personality seems
to defeat the entire purpose of Standalone MM. My concern is that any code that
is relevant only to DXE or PEI must not be a part of the MM Standalone
context. This could be achieved through proper refactoring + conditional
compilation. If the decision is taken at runtime then this is just traditional
MM.

Please let me know if I am missing something.

cheers,
Achin



^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 18:50             ` Achin Gupta
@ 2019-01-07 18:55               ` Ard Biesheuvel
  2019-01-07 19:21                 ` Achin Gupta
  0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-07 18:55 UTC (permalink / raw)
  To: Achin Gupta
  Cc: Laszlo Ersek, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On Mon, 7 Jan 2019 at 19:50, Achin Gupta <Achin.Gupta@arm.com> wrote:
>
> On Mon, Jan 07, 2019 at 06:33:26PM +0100, Ard Biesheuvel wrote:
> > On Mon, 7 Jan 2019 at 16:28, Laszlo Ersek <lersek@redhat.com> wrote:
> > >
> > > On 01/04/19 12:57, Ard Biesheuvel wrote:
> > > > On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
> > > >>
> > > >> On 01/03/19 12:03, Ard Biesheuvel wrote:
> > > >>> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
> > > >>>>
> > > >>>> Some of the existing DXE drivers can be refactored to execute within
> > > >>>> the Standalone MM execution environment as well. Allow such drivers to
> > > >>>> get access to the Standalone MM services tables.
> > > >>>>
> > > >>>> Add a mechanism to determine the execution mode is required.
> > > >>>> i.e, in MM or non-MM
> > > >>>>
> > > >>>> Contributed-under: TianoCore Contribution Agreement 1.1
> > > >>>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> > > >>>> ---
> > > >>>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
> > > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
> > > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
> > > >>>>  MdePkg/MdePkg.dec                                                            |  4 ++
> > > >>>>  4 files changed, 122 insertions(+)
> > > >>>>
> > > >>>
> > > >>> OK, so since the PI spec only refers to MM mode now, this library
> > > >>> class should be
> > > >>>
> > > >>> MmServicesTableLib|Include/Library/MmServicesTableLib.h
> > > >>>
> > > >>> with an implementation in MdeModulePkg that exposes the deprecated SMM
> > > >>> system table as the MM system table.
> > > >>>
> > > >>> In StandaloneMmPkg, we can add an implementation that exposes the
> > > >>> standalone MM system table.
> > > >>>
> > > >>> (They are binary compatible, so it is just a matter of casting one
> > > >>> pointer to the other)
> > > >>>
> > > >>> With this in place, we can go ahead and update FaultTolerantWrite and
> > > >>> Variable SMM driver to switch from SmmServicesTableLib to
> > > >>> MmServicesTableLib. This will require existing x86 platforms to define
> > > >>> a new library class resolution for MmServicesTableLib, referring to
> > > >>> the implementation in MdeModulePkg. This is unfortunate, but it is an
> > > >>> unavoidable consequence of the PI spec changes.
> > > >>
> > > >> It shouldn't be too intrusive or hard to review, I expect.
> > > >>
> > > >>>
> > > >>> Remaining question is what to do with InSmm() ...
> > > >>
> > > >> I'm lacking the context on this; on the other hand, I can refer back to
> > > >> at least one earlier discussion -- there had been multiple -- of the
> > > >> discrepancy between the PI spec and the edk2 code. See:
> > > >>
> > > >> - bullet (9) in
> > > >> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
> > > >> - and
> > > >> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
> > > >>
> > > >> Not sure how that can be applied to Arm.
> > > >>
> > > >
> > > > The code I posted yesterday does not use InMm() at all. For standalone
> > > > MM, it should always return TRUE anyway, and any code that a driver
> > > > would execute if it returned FALSE needs to be factored out anyway,
> > > > since it should not end up in standalone MM binaries as dead code.
> > > >
> > >
> > > OK. That seems to make sense. I've read up a bit on "standalone MM" in
> > > the PI v1.6 spec, vol 4. Having no access to UEFI protocols even in the
> > > entry point function, at driver init time, seems challenging to me. I
> > > guess I'll learn more about this as a part of the usual list traffic.
> > >
> > > What is the MODULE_TYPE that standalone MM drivers use, in place of
> > > DXE_SMM_DRIVER (= EFI_FV_FILETYPE_MM, 0x0A)?
> > >
> > > Hm... from the other patches, it seems to be MM_STANDALONE (=
> > > EFI_FV_FILETYPE_MM_STANDALONE, 0x0E). OK.
> > >
> > > If I'd like to see a short summary of standalone MM, relative to
> > > traditional MM, and why it is more suitable -- I presume -- for aarch64,
> > > which document should I look at, from
> > > <https://mantis.uefi.org/mantis/view.php?id=1390>, for example?
> > >
> >
> > Perhaps Achin can answer this, since he has been driving the spec side
> > of this? (and maintains StandaloneMmPkg)
>
> The idea behind MM Standalone mode was to sandbox MM code in self sufficient
> execution context. This was a step to avoid some of the vulnerabilities in
> traditional SMM due to code and data sharing with DXE.
>
> On AArch64, the MM standalone mode is initialised during the SEC phase. This
> corresponds to Trustzone initialisation. Furthermore, the MM standalone
> execution context is placed in user mode (Secure EL0) instead of running it in a
> privileged processor mode (S-EL1 or EL3 on AArch64, Ring -2 or SMM on x86). This
> restricts what the MM standalone context can see and do. Lastly, after SEC no
> more MM Standalone drivers can be initialized during PEI or DXE (in contrast to
> the example in PI 1.6 Section 1.5.2).
>
> Hope that makes sense?
>

I agree, but this is not what StandaloneMmPkg implements today: it
implements a MmFvDispatchHandler that permits a FV to be brough into
the MM environment, and the MM dispatcher will happily dispatch all
the MM_STANDALONE modules it contains.

Also, there are some other pieces missing (which I mentioned in one of
the other threads but I suppose you may not have caught up yet):
EndOfDxe (as well as some other PI defined events) needs to be
signalled to the standalone MM context by some non-MM agent, and I
think there are other parts of the traditional SMM IPL that have not
been ported to standalone MM yet.

> I have not seen all the patches in this and related series but the use of InMM()
> to allow code to have a DXE driver or a MM Standalone driver personality seems
> to defeat the entire purpose of Standalone MM. My concern is that any code that
> is relevant only to DXE or PEI must not be a part of the MM Standalone
> context. This could be achieved through proper refactoring + conditional
> compilation. If the decision is taken at runtime then this is just traditional
> MM.
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 18:55               ` Ard Biesheuvel
@ 2019-01-07 19:21                 ` Achin Gupta
  2019-01-07 19:37                   ` Ard Biesheuvel
  0 siblings, 1 reply; 32+ messages in thread
From: Achin Gupta @ 2019-01-07 19:21 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Laszlo Ersek, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On Mon, Jan 07, 2019 at 07:55:36PM +0100, Ard Biesheuvel wrote:
> On Mon, 7 Jan 2019 at 19:50, Achin Gupta <Achin.Gupta@arm.com> wrote:
> >
> > On Mon, Jan 07, 2019 at 06:33:26PM +0100, Ard Biesheuvel wrote:
> > > On Mon, 7 Jan 2019 at 16:28, Laszlo Ersek <lersek@redhat.com> wrote:
> > > >
> > > > On 01/04/19 12:57, Ard Biesheuvel wrote:
> > > > > On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
> > > > >>
> > > > >> On 01/03/19 12:03, Ard Biesheuvel wrote:
> > > > >>> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
> > > > >>>>
> > > > >>>> Some of the existing DXE drivers can be refactored to execute within
> > > > >>>> the Standalone MM execution environment as well. Allow such drivers to
> > > > >>>> get access to the Standalone MM services tables.
> > > > >>>>
> > > > >>>> Add a mechanism to determine the execution mode is required.
> > > > >>>> i.e, in MM or non-MM
> > > > >>>>
> > > > >>>> Contributed-under: TianoCore Contribution Agreement 1.1
> > > > >>>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> > > > >>>> ---
> > > > >>>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
> > > > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
> > > > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
> > > > >>>>  MdePkg/MdePkg.dec                                                            |  4 ++
> > > > >>>>  4 files changed, 122 insertions(+)
> > > > >>>>
> > > > >>>
> > > > >>> OK, so since the PI spec only refers to MM mode now, this library
> > > > >>> class should be
> > > > >>>
> > > > >>> MmServicesTableLib|Include/Library/MmServicesTableLib.h
> > > > >>>
> > > > >>> with an implementation in MdeModulePkg that exposes the deprecated SMM
> > > > >>> system table as the MM system table.
> > > > >>>
> > > > >>> In StandaloneMmPkg, we can add an implementation that exposes the
> > > > >>> standalone MM system table.
> > > > >>>
> > > > >>> (They are binary compatible, so it is just a matter of casting one
> > > > >>> pointer to the other)
> > > > >>>
> > > > >>> With this in place, we can go ahead and update FaultTolerantWrite and
> > > > >>> Variable SMM driver to switch from SmmServicesTableLib to
> > > > >>> MmServicesTableLib. This will require existing x86 platforms to define
> > > > >>> a new library class resolution for MmServicesTableLib, referring to
> > > > >>> the implementation in MdeModulePkg. This is unfortunate, but it is an
> > > > >>> unavoidable consequence of the PI spec changes.
> > > > >>
> > > > >> It shouldn't be too intrusive or hard to review, I expect.
> > > > >>
> > > > >>>
> > > > >>> Remaining question is what to do with InSmm() ...
> > > > >>
> > > > >> I'm lacking the context on this; on the other hand, I can refer back to
> > > > >> at least one earlier discussion -- there had been multiple -- of the
> > > > >> discrepancy between the PI spec and the edk2 code. See:
> > > > >>
> > > > >> - bullet (9) in
> > > > >> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
> > > > >> - and
> > > > >> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
> > > > >>
> > > > >> Not sure how that can be applied to Arm.
> > > > >>
> > > > >
> > > > > The code I posted yesterday does not use InMm() at all. For standalone
> > > > > MM, it should always return TRUE anyway, and any code that a driver
> > > > > would execute if it returned FALSE needs to be factored out anyway,
> > > > > since it should not end up in standalone MM binaries as dead code.
> > > > >
> > > >
> > > > OK. That seems to make sense. I've read up a bit on "standalone MM" in
> > > > the PI v1.6 spec, vol 4. Having no access to UEFI protocols even in the
> > > > entry point function, at driver init time, seems challenging to me. I
> > > > guess I'll learn more about this as a part of the usual list traffic.
> > > >
> > > > What is the MODULE_TYPE that standalone MM drivers use, in place of
> > > > DXE_SMM_DRIVER (= EFI_FV_FILETYPE_MM, 0x0A)?
> > > >
> > > > Hm... from the other patches, it seems to be MM_STANDALONE (=
> > > > EFI_FV_FILETYPE_MM_STANDALONE, 0x0E). OK.
> > > >
> > > > If I'd like to see a short summary of standalone MM, relative to
> > > > traditional MM, and why it is more suitable -- I presume -- for aarch64,
> > > > which document should I look at, from
> > > > <https://mantis.uefi.org/mantis/view.php?id=1390>, for example?
> > > >
> > >
> > > Perhaps Achin can answer this, since he has been driving the spec side
> > > of this? (and maintains StandaloneMmPkg)
> >
> > The idea behind MM Standalone mode was to sandbox MM code in self sufficient
> > execution context. This was a step to avoid some of the vulnerabilities in
> > traditional SMM due to code and data sharing with DXE.
> >
> > On AArch64, the MM standalone mode is initialised during the SEC phase. This
> > corresponds to Trustzone initialisation. Furthermore, the MM standalone
> > execution context is placed in user mode (Secure EL0) instead of running it in a
> > privileged processor mode (S-EL1 or EL3 on AArch64, Ring -2 or SMM on x86). This
> > restricts what the MM standalone context can see and do. Lastly, after SEC no
> > more MM Standalone drivers can be initialized during PEI or DXE (in contrast to
> > the example in PI 1.6 Section 1.5.2).
> >
> > Hope that makes sense?
> >
> 
> I agree, but this is not what StandaloneMmPkg implements today: it
> implements a MmFvDispatchHandler that permits a FV to be brough into
> the MM environment, and the MM dispatcher will happily dispatch all
> the MM_STANDALONE modules it contains.

Umm! Not following why is that a problem. The FV on AArch64 must only contain
MM_STANDALONE drivers. These drivers rely on the MMST which is exclusively used
in the secure world. So the isolation is still achieved right? Are you saying
that additional checks are required to enforce this on AArch64?

> 
> Also, there are some other pieces missing (which I mentioned in one of
> the other threads but I suppose you may not have caught up yet):
> EndOfDxe (as well as some other PI defined events) needs to be
> signalled to the standalone MM context by some non-MM agent, and I
> think there are other parts of the traditional SMM IPL that have not
> been ported to standalone MM yet.

Yes! I am still catching up but saw the patches that Supreeth has reviewed and
they make sense. Could you please explain the need for End of DXE signalling and
the traditional SMM IPL. It is not obvious to me :o(

cheers,
Achin

> 
> > I have not seen all the patches in this and related series but the use of InMM()
> > to allow code to have a DXE driver or a MM Standalone driver personality seems
> > to defeat the entire purpose of Standalone MM. My concern is that any code that
> > is relevant only to DXE or PEI must not be a part of the MM Standalone
> > context. This could be achieved through proper refactoring + conditional
> > compilation. If the decision is taken at runtime then this is just traditional
> > MM.
> >


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 19:21                 ` Achin Gupta
@ 2019-01-07 19:37                   ` Ard Biesheuvel
  2019-01-08  1:11                     ` Laszlo Ersek
  2019-01-13 12:42                     ` Cohen, Eugene
  0 siblings, 2 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-07 19:37 UTC (permalink / raw)
  To: Achin Gupta
  Cc: Laszlo Ersek, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On Mon, 7 Jan 2019 at 20:21, Achin Gupta <Achin.Gupta@arm.com> wrote:
>
> On Mon, Jan 07, 2019 at 07:55:36PM +0100, Ard Biesheuvel wrote:
> > On Mon, 7 Jan 2019 at 19:50, Achin Gupta <Achin.Gupta@arm.com> wrote:
> > >
> > > On Mon, Jan 07, 2019 at 06:33:26PM +0100, Ard Biesheuvel wrote:
> > > > On Mon, 7 Jan 2019 at 16:28, Laszlo Ersek <lersek@redhat.com> wrote:
> > > > >
> > > > > On 01/04/19 12:57, Ard Biesheuvel wrote:
> > > > > > On Thu, 3 Jan 2019 at 17:14, Laszlo Ersek <lersek@redhat.com> wrote:
> > > > > >>
> > > > > >> On 01/03/19 12:03, Ard Biesheuvel wrote:
> > > > > >>> On Wed, 2 Jan 2019 at 14:14, Jagadeesh Ujja <jagadeesh.ujja@arm.com> wrote:
> > > > > >>>>
> > > > > >>>> Some of the existing DXE drivers can be refactored to execute within
> > > > > >>>> the Standalone MM execution environment as well. Allow such drivers to
> > > > > >>>> get access to the Standalone MM services tables.
> > > > > >>>>
> > > > > >>>> Add a mechanism to determine the execution mode is required.
> > > > > >>>> i.e, in MM or non-MM
> > > > > >>>>
> > > > > >>>> Contributed-under: TianoCore Contribution Agreement 1.1
> > > > > >>>> Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com>
> > > > > >>>> ---
> > > > > >>>>  MdePkg/Include/Library/StandaloneMmServicesTableLib.h                        | 43 ++++++++++++++++++++
> > > > > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c   | 39 ++++++++++++++++++
> > > > > >>>>  MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf | 36 ++++++++++++++++
> > > > > >>>>  MdePkg/MdePkg.dec                                                            |  4 ++
> > > > > >>>>  4 files changed, 122 insertions(+)
> > > > > >>>>
> > > > > >>>
> > > > > >>> OK, so since the PI spec only refers to MM mode now, this library
> > > > > >>> class should be
> > > > > >>>
> > > > > >>> MmServicesTableLib|Include/Library/MmServicesTableLib.h
> > > > > >>>
> > > > > >>> with an implementation in MdeModulePkg that exposes the deprecated SMM
> > > > > >>> system table as the MM system table.
> > > > > >>>
> > > > > >>> In StandaloneMmPkg, we can add an implementation that exposes the
> > > > > >>> standalone MM system table.
> > > > > >>>
> > > > > >>> (They are binary compatible, so it is just a matter of casting one
> > > > > >>> pointer to the other)
> > > > > >>>
> > > > > >>> With this in place, we can go ahead and update FaultTolerantWrite and
> > > > > >>> Variable SMM driver to switch from SmmServicesTableLib to
> > > > > >>> MmServicesTableLib. This will require existing x86 platforms to define
> > > > > >>> a new library class resolution for MmServicesTableLib, referring to
> > > > > >>> the implementation in MdeModulePkg. This is unfortunate, but it is an
> > > > > >>> unavoidable consequence of the PI spec changes.
> > > > > >>
> > > > > >> It shouldn't be too intrusive or hard to review, I expect.
> > > > > >>
> > > > > >>>
> > > > > >>> Remaining question is what to do with InSmm() ...
> > > > > >>
> > > > > >> I'm lacking the context on this; on the other hand, I can refer back to
> > > > > >> at least one earlier discussion -- there had been multiple -- of the
> > > > > >> discrepancy between the PI spec and the edk2 code. See:
> > > > > >>
> > > > > >> - bullet (9) in
> > > > > >> <http://mid.mail-archive.com/aada511c-bdb9-d833-caa5-bee56cc47d27@redhat.com>,
> > > > > >> - and
> > > > > >> <http://mid.mail-archive.com/0C09AFA07DD0434D9E2A0C6AEB0483103BB55B46@shsmsx102.ccr.corp.intel.com>.
> > > > > >>
> > > > > >> Not sure how that can be applied to Arm.
> > > > > >>
> > > > > >
> > > > > > The code I posted yesterday does not use InMm() at all. For standalone
> > > > > > MM, it should always return TRUE anyway, and any code that a driver
> > > > > > would execute if it returned FALSE needs to be factored out anyway,
> > > > > > since it should not end up in standalone MM binaries as dead code.
> > > > > >
> > > > >
> > > > > OK. That seems to make sense. I've read up a bit on "standalone MM" in
> > > > > the PI v1.6 spec, vol 4. Having no access to UEFI protocols even in the
> > > > > entry point function, at driver init time, seems challenging to me. I
> > > > > guess I'll learn more about this as a part of the usual list traffic.
> > > > >
> > > > > What is the MODULE_TYPE that standalone MM drivers use, in place of
> > > > > DXE_SMM_DRIVER (= EFI_FV_FILETYPE_MM, 0x0A)?
> > > > >
> > > > > Hm... from the other patches, it seems to be MM_STANDALONE (=
> > > > > EFI_FV_FILETYPE_MM_STANDALONE, 0x0E). OK.
> > > > >
> > > > > If I'd like to see a short summary of standalone MM, relative to
> > > > > traditional MM, and why it is more suitable -- I presume -- for aarch64,
> > > > > which document should I look at, from
> > > > > <https://mantis.uefi.org/mantis/view.php?id=1390>, for example?
> > > > >
> > > >
> > > > Perhaps Achin can answer this, since he has been driving the spec side
> > > > of this? (and maintains StandaloneMmPkg)
> > >
> > > The idea behind MM Standalone mode was to sandbox MM code in self sufficient
> > > execution context. This was a step to avoid some of the vulnerabilities in
> > > traditional SMM due to code and data sharing with DXE.
> > >
> > > On AArch64, the MM standalone mode is initialised during the SEC phase. This
> > > corresponds to Trustzone initialisation. Furthermore, the MM standalone
> > > execution context is placed in user mode (Secure EL0) instead of running it in a
> > > privileged processor mode (S-EL1 or EL3 on AArch64, Ring -2 or SMM on x86). This
> > > restricts what the MM standalone context can see and do. Lastly, after SEC no
> > > more MM Standalone drivers can be initialized during PEI or DXE (in contrast to
> > > the example in PI 1.6 Section 1.5.2).
> > >
> > > Hope that makes sense?
> > >
> >
> > I agree, but this is not what StandaloneMmPkg implements today: it
> > implements a MmFvDispatchHandler that permits a FV to be brough into
> > the MM environment, and the MM dispatcher will happily dispatch all
> > the MM_STANDALONE modules it contains.
>
> Umm! Not following why is that a problem. The FV on AArch64 must only contain
> MM_STANDALONE drivers. These drivers rely on the MMST which is exclusively used
> in the secure world. So the isolation is still achieved right? Are you saying
> that additional checks are required to enforce this on AArch64?
>

It means you can invoke a standalone MM service during DXE to dispatch
additional modules on the secure side.


> >
> > Also, there are some other pieces missing (which I mentioned in one of
> > the other threads but I suppose you may not have caught up yet):
> > EndOfDxe (as well as some other PI defined events) needs to be
> > signalled to the standalone MM context by some non-MM agent, and I
> > think there are other parts of the traditional SMM IPL that have not
> > been ported to standalone MM yet.
>
> Yes! I am still catching up but saw the patches that Supreeth has reviewed and
> they make sense. Could you please explain the need for End of DXE signalling and
> the traditional SMM IPL. It is not obvious to me :o(
>

The point is that there are PI specified events that we are currently
not signalling in standalone MM, so in that sense, we are not
implementing the PI spec fully.

Note that EndOfDxe is security sensitive - it is used as a trigger to
lock down and/or secure stuff, and if it never get signalled,
standalone MM drivers may falsely assume that the context is more
secure than it is.

If we don't want to deviate too much from the existing capsule update
implementation, we may have to rely on this: perform the
authentication on the non-secure side (but before EndOfDxe), and have
a minimal implementation in standalone MM that does little more than
write the blocks to storage. Without signalling EndOfDxe to the secure
side, this would open up a security hole.


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 19:37                   ` Ard Biesheuvel
@ 2019-01-08  1:11                     ` Laszlo Ersek
  2019-01-08 13:27                       ` Ard Biesheuvel
  2019-01-13 12:42                     ` Cohen, Eugene
  1 sibling, 1 reply; 32+ messages in thread
From: Laszlo Ersek @ 2019-01-08  1:11 UTC (permalink / raw)
  To: Ard Biesheuvel, Achin Gupta
  Cc: Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On 01/07/19 20:37, Ard Biesheuvel wrote:
> On Mon, 7 Jan 2019 at 20:21, Achin Gupta <Achin.Gupta@arm.com> wrote:

>> Could you please explain the need for End of DXE signalling and
>> the traditional SMM IPL. It is not obvious to me :o(
>>
> 
> The point is that there are PI specified events that we are currently
> not signalling in standalone MM, so in that sense, we are not
> implementing the PI spec fully.
> 
> Note that EndOfDxe is security sensitive - it is used as a trigger to
> lock down and/or secure stuff, and if it never get signalled,
> standalone MM drivers may falsely assume that the context is more
> secure than it is.

Yes, see PI 1.6, Vol2 ("DXE"), 5.1.2.1 "End of DXE Event".

(I won't quote the spec here, as I could quote the entire section; all
of it is relevant here.)

In my interpretation anyway, the MM infrastructure basically "trusts"
DXE until End-of-DXE is signaled. See also:
- 5.6 "DXE MM Ready to Lock Protocol",
- 4.6 "MM Ready to Lock Protocol",
in Vol4.

The kind of "early distrust" that Achin describes up-thread may be
well-founded, and it might obviate the above event groups. I'm not sure.
The concept is novel to me (after having struggled for months in ~2015
to wrap my brain around traditional SMM in the first place), so I'm
having trouble at reasoning about standalone MM.

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-08  1:11                     ` Laszlo Ersek
@ 2019-01-08 13:27                       ` Ard Biesheuvel
  2019-01-08 16:52                         ` Laszlo Ersek
  0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-08 13:27 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Achin Gupta, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On Tue, 8 Jan 2019 at 02:11, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 01/07/19 20:37, Ard Biesheuvel wrote:
> > On Mon, 7 Jan 2019 at 20:21, Achin Gupta <Achin.Gupta@arm.com> wrote:
>
> >> Could you please explain the need for End of DXE signalling and
> >> the traditional SMM IPL. It is not obvious to me :o(
> >>
> >
> > The point is that there are PI specified events that we are currently
> > not signalling in standalone MM, so in that sense, we are not
> > implementing the PI spec fully.
> >
> > Note that EndOfDxe is security sensitive - it is used as a trigger to
> > lock down and/or secure stuff, and if it never get signalled,
> > standalone MM drivers may falsely assume that the context is more
> > secure than it is.
>
> Yes, see PI 1.6, Vol2 ("DXE"), 5.1.2.1 "End of DXE Event".
>
> (I won't quote the spec here, as I could quote the entire section; all
> of it is relevant here.)
>
> In my interpretation anyway, the MM infrastructure basically "trusts"
> DXE until End-of-DXE is signaled. See also:
> - 5.6 "DXE MM Ready to Lock Protocol",
> - 4.6 "MM Ready to Lock Protocol",
> in Vol4.
>
> The kind of "early distrust" that Achin describes up-thread may be
> well-founded, and it might obviate the above event groups. I'm not sure.

I disagree. The whole point of standalone MM is to have parity with
x86 in terms of having a separate execution context where platform
specific services can reside. Even though DXE_SMM_DRIVER and
MM_STANDALONE modules are dispatched in different ways, they should be
able to be built from a shared source, and not signalling the EndOfDxe
event is highly likely to cause more problems that it solves.

And actually, I think it is a valid security model to distinguish
between before and after EndOfDxe, since EndOfDxe will be signalled
before loading any third-party drivers, and so whatever has executed
up to that point can be held to higher standards in terms of trust.

> The concept is novel to me (after having struggled for months in ~2015
> to wrap my brain around traditional SMM in the first place), so I'm
> having trouble at reasoning about standalone MM.
>

I think that applies to all of us :-)


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-08 13:27                       ` Ard Biesheuvel
@ 2019-01-08 16:52                         ` Laszlo Ersek
  0 siblings, 0 replies; 32+ messages in thread
From: Laszlo Ersek @ 2019-01-08 16:52 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Achin Gupta, Jagadeesh Ujja, Gao, Liming, Kinney, Michael D,
	edk2-devel@lists.01.org, Zhang, Chao B, Leif Lindholm,
	Supreeth Venkatesh, Jian J Wang, nd

On 01/08/19 14:27, Ard Biesheuvel wrote:
> On Tue, 8 Jan 2019 at 02:11, Laszlo Ersek <lersek@redhat.com> wrote:
>>
>> On 01/07/19 20:37, Ard Biesheuvel wrote:
>>> On Mon, 7 Jan 2019 at 20:21, Achin Gupta <Achin.Gupta@arm.com> wrote:
>>
>>>> Could you please explain the need for End of DXE signalling and
>>>> the traditional SMM IPL. It is not obvious to me :o(
>>>>
>>>
>>> The point is that there are PI specified events that we are currently
>>> not signalling in standalone MM, so in that sense, we are not
>>> implementing the PI spec fully.
>>>
>>> Note that EndOfDxe is security sensitive - it is used as a trigger to
>>> lock down and/or secure stuff, and if it never get signalled,
>>> standalone MM drivers may falsely assume that the context is more
>>> secure than it is.
>>
>> Yes, see PI 1.6, Vol2 ("DXE"), 5.1.2.1 "End of DXE Event".
>>
>> (I won't quote the spec here, as I could quote the entire section; all
>> of it is relevant here.)
>>
>> In my interpretation anyway, the MM infrastructure basically "trusts"
>> DXE until End-of-DXE is signaled. See also:
>> - 5.6 "DXE MM Ready to Lock Protocol",
>> - 4.6 "MM Ready to Lock Protocol",
>> in Vol4.
>>
>> The kind of "early distrust" that Achin describes up-thread may be
>> well-founded, and it might obviate the above event groups. I'm not sure.
> 
> I disagree. The whole point of standalone MM is to have parity with
> x86 in terms of having a separate execution context where platform
> specific services can reside. Even though DXE_SMM_DRIVER and
> MM_STANDALONE modules are dispatched in different ways, they should be
> able to be built from a shared source, and not signalling the EndOfDxe
> event is highly likely to cause more problems that it solves.
> 
> And actually, I think it is a valid security model to distinguish
> between before and after EndOfDxe, since EndOfDxe will be signalled
> before loading any third-party drivers, and so whatever has executed
> up to that point can be held to higher standards in terms of trust.

What you describe is absolutely *easier* to understand and to agree
with, so I'm naturally drawn to it.

I'm just pointing out -- sort of reasoning against myself! -- that Achin
wrote up-thread,

> The idea behind MM Standalone mode was to sandbox MM code in self
> sufficient execution context. This was a step to avoid some of the
> vulnerabilities in traditional SMM due to code and data sharing with
> DXE.

Through this, Achin seemed to imply that some SMM vulnerabilities had
occurred due to SMM being *capable* of reading *any* RAM (and MMIO too)
outside of SMRAM ("data sharing"); hence invalid pointer dereferences
(even just reads) could lead to really bad problems.

Then, I tried to fill the term "sandbox" with meaning -- i.e. MM would
be prevented from reading any DXE data (anything outside of MMRAM). This
looked sort of consistent with the extra restriction that standalone MM
code couldn't consume UEFI protocols even at init time.

And then I extrapolated: if MM can't trust DXE *at all*, then MM needs
no notification that, due to BDS reaching a specific point, MM can trust
DXE even *less* than before. There is no "less" than "not at all".

In short, I agree with you, I'm just trying to comprehend the "threat
model" (is that the right term?) behind Achin's story (AIUI).

Thanks!
Laszlo

>> The concept is novel to me (after having struggled for months in ~2015
>> to wrap my brain around traditional SMM in the first place), so I'm
>> having trouble at reasoning about standalone MM.
>>
> 
> I think that applies to all of us :-)
> 



^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-07 19:37                   ` Ard Biesheuvel
  2019-01-08  1:11                     ` Laszlo Ersek
@ 2019-01-13 12:42                     ` Cohen, Eugene
  2019-01-14 18:51                       ` Ard Biesheuvel
  1 sibling, 1 reply; 32+ messages in thread
From: Cohen, Eugene @ 2019-01-13 12:42 UTC (permalink / raw)
  To: Ard Biesheuvel, Achin Gupta
  Cc: edk2-devel@lists.01.org, Gao, Liming, Kinney, Michael D, nd,
	Laszlo Ersek, Zhang, Chao B

I saw this thread earlier this week and wanted to chime in.

> > Also, there are some other pieces missing (which I mentioned in one of
> > the other threads but I suppose you may not have caught up yet):
> > EndOfDxe (as well as some other PI defined events) needs to be
> > signalled to the standalone MM context by some non-MM agent, and I
> > think there are other parts of the traditional SMM IPL that have not
> > been ported to standalone MM yet.

I haven't been following closely the state of StandaloneMmPkg on edk2  - as we were ready to sync up some of our earlier MM stuff to edk2 I learned that the support in place is only partial as patches have been coming in slowly so we chose to implement a version based on the early joint prototype work we did ("uefiproto" repo).  In this there is a DXE component that produces the SMM Communication protocol and also ensures that when key GUIDed events occur in DXE that they are forwarded to MM including EndOfDxe.

I don't see a strong argument for not forwarding the event signaling information to MM - MM can either use the information or ignore it as it sees fit.  I can see scenarios around variable services where knowing what phase of boot the normal world is in is necessary.


Eugene



^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library
  2019-01-13 12:42                     ` Cohen, Eugene
@ 2019-01-14 18:51                       ` Ard Biesheuvel
  0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2019-01-14 18:51 UTC (permalink / raw)
  To: Cohen, Eugene
  Cc: Achin Gupta, edk2-devel@lists.01.org, Gao, Liming,
	Kinney, Michael D, nd, Laszlo Ersek, Zhang, Chao B

On Sun, 13 Jan 2019 at 13:42, Cohen, Eugene <eugene@hp.com> wrote:
>
> I saw this thread earlier this week and wanted to chime in.
>
> > > Also, there are some other pieces missing (which I mentioned in one of
> > > the other threads but I suppose you may not have caught up yet):
> > > EndOfDxe (as well as some other PI defined events) needs to be
> > > signalled to the standalone MM context by some non-MM agent, and I
> > > think there are other parts of the traditional SMM IPL that have not
> > > been ported to standalone MM yet.
>
> I haven't been following closely the state of StandaloneMmPkg on edk2  - as we were ready to sync up some of our earlier MM stuff to edk2 I learned that the support in place is only partial as patches have been coming in slowly so we chose to implement a version based on the early joint prototype work we did ("uefiproto" repo).  In this there is a DXE component that produces the SMM Communication protocol and also ensures that when key GUIDed events occur in DXE that they are forwarded to MM including EndOfDxe.
>
> I don't see a strong argument for not forwarding the event signaling information to MM - MM can either use the information or ignore it as it sees fit.  I can see scenarios around variable services where knowing what phase of boot the normal world is in is necessary.
>

I agree. If the normal world firmware is guaranteed to signal EndOfDxe
before loading any third party modules, it is not unreasonable to use
this on the secure side as a trust indicator as well.


^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2019-01-14 18:51 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-02 13:13 [PATCH v2 00/11] Extend secure variable service to be usable from Standalone MM Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 01/11] StandaloneMmPkg: Remove MM_STANDALONE LIBRARY_CLASS from StandaloneMmCoreHobLib Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 02/11] StandaloneMmPkg: Adding the library packages used by MM_STANDALONE drivers Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 03/11] MdeModulePkg: Add a PCD to indicate Standalone MM supports secure variable Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 04/11] MdePkg/Include: Add StandaloneMmServicesTableLib library Jagadeesh Ujja
2019-01-03 11:03   ` Ard Biesheuvel
2019-01-03 16:14     ` Laszlo Ersek
2019-01-04 11:57       ` Ard Biesheuvel
2019-01-07 15:28         ` Laszlo Ersek
2019-01-07 17:33           ` Ard Biesheuvel
2019-01-07 18:50             ` Achin Gupta
2019-01-07 18:55               ` Ard Biesheuvel
2019-01-07 19:21                 ` Achin Gupta
2019-01-07 19:37                   ` Ard Biesheuvel
2019-01-08  1:11                     ` Laszlo Ersek
2019-01-08 13:27                       ` Ard Biesheuvel
2019-01-08 16:52                         ` Laszlo Ersek
2019-01-13 12:42                     ` Cohen, Eugene
2019-01-14 18:51                       ` Ard Biesheuvel
2019-01-02 13:13 ` [PATCH v2 05/11] MdeModulePkg/FaultTolerantWriteDxe: allow reusability as a MM driver Jagadeesh Ujja
2019-01-02 17:15   ` Ard Biesheuvel
2019-01-02 13:13 ` [PATCH v2 06/11] MdeModulePkg/Variable/RuntimeDxe: adapt for usability with MM Standalone Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 07/11] MdeModulePkg/Variable/RuntimeDxe: adapt as a MM Standalone driver Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 08/11] MdeModulePkg/VarCheckLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
2019-01-04 10:36   ` Ard Biesheuvel
2019-01-02 13:13 ` [PATCH v2 09/11] ArmPlatformPkg/NorFlashDxe: allow reusability as a MM driver Jagadeesh Ujja
2019-01-02 13:13 ` [PATCH v2 10/11] SecurityPkg/AuthVariableLib: allow MM_STANDALONE drivers to use this library Jagadeesh Ujja
2019-01-03  1:14   ` Zhang, Chao B
2019-01-03  6:15     ` Jagadeesh Ujja
2019-01-04 10:41       ` Ard Biesheuvel
2019-01-02 13:13 ` [PATCH v2 11/11] CryptoPkg/BaseCryptLib: " Jagadeesh Ujja
2019-01-04 10:35   ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox