public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V2 0/7] OpalPassword: New solution without SMM device code
@ 2018-03-07 13:19 Star Zeng
  2018-03-07 13:19 ` [PATCH V2 1/7] MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY Star Zeng
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

The patch series is also at
https://github.com/lzeng14/edk2 OpalPasswordNewV2 branch.

After IOMMU is enabled in S3, original solution with SMM device
code (OpalPasswordSmm) to unlock OPAL device for S3 will not work
as the DMA operation will be aborted without granted DMA buffer.
Instead, this solution is to add OpalPasswordPei to eliminate
SMM device code, and OPAL setup UI produced by OpalPasswordDxe
will be updated to send requests (set password, update password,
and etc), and then the requests will be processed in next boot
before SmmReadyToLock, password and device info will be saved to
lock box used by OpalPasswordPei to unlock OPAL device for S3.

The old solution related codes are also removed.

V2: Thanks for Jiewen's great comments.
1. Still use suppressif for unavailabe requests, and use grayoutif
for conflict requests.
2. Zero DevInfo in BuildOpalDeviceInfoAta() and BuildOpalDeviceInfoNvme().
3. Zero Mask and Unicode in OpalDriverPopUpPsidInput() and
OpalDriverPopUpPasswordInput() even for NULL return path.
4. Do some HII related refinement.
5. Do more NULL pointer check.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>

Star Zeng (7):
  MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
  SecurityPkg TcgStorageOpalLib: Make it be base type really
  SecurityPkg TcgStorageCoreLib: Make it be base type really
  SecurityPkg OpalPassword: Add solution without SMM device code
  SecurityPkg OpalPassword: Remove old solution
  SecurityPkg OpalPasswordSupportLib: Remove it
  SecurityPkg OpalPasswordExtraInfoVariable.h: Remove it

 MdeModulePkg/Include/Library/LockBoxLib.h          |   14 +-
 .../Library/SmmLockBoxLib/SmmLockBoxDxeLib.c       |    4 +-
 .../Library/SmmLockBoxLib/SmmLockBoxSmmLib.c       |  227 +-
 .../Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf     |   10 +-
 .../Include/Guid/OpalPasswordExtraInfoVariable.h   |   27 -
 .../Include/Library/OpalPasswordSupportLib.h       |  289 --
 .../OpalPasswordSupportLib.c                       |  781 -----
 .../OpalPasswordSupportLib.inf                     |   55 -
 .../OpalPasswordSupportNotify.h                    |   55 -
 .../TcgStorageCoreLib/TcgStorageCoreLib.inf        |    4 +-
 .../TcgStorageOpalLib/TcgStorageOpalLib.inf        |    8 +-
 SecurityPkg/SecurityPkg.dec                        |    4 -
 SecurityPkg/SecurityPkg.dsc                        |    6 +-
 .../ComponentName.c                                |    0
 .../OpalAhciMode.c                                 |  492 ++--
 .../OpalAhciMode.h                                 |   93 +-
 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c     | 3003 ++++++++++++++++++++
 .../{OpalPasswordDxe => OpalPassword}/OpalDriver.h |  215 +-
 .../{OpalPasswordDxe => OpalPassword}/OpalHii.c    |  895 ++----
 .../OpalHiiPrivate.h => OpalPassword/OpalHii.h}    |  150 +-
 .../OpalHiiCallbacks.c                             |    6 +-
 .../OpalHiiFormStrings.uni                         |   49 +-
 .../OpalHiiFormValues.h                            |   97 +-
 .../OpalNvmeMode.c                                 |   95 +-
 .../OpalNvmeMode.h                                 |   19 +-
 .../OpalNvmeReg.h                                  |    5 +-
 .../Tcg/Opal/OpalPassword/OpalPasswordCommon.h     |   65 +
 .../OpalPasswordDxe.inf                            |   25 +-
 .../OpalPasswordForm.vfr                           |  279 +-
 .../Tcg/Opal/OpalPassword/OpalPasswordPei.c        |  940 ++++++
 .../Tcg/Opal/OpalPassword/OpalPasswordPei.h        |  133 +
 .../Tcg/Opal/OpalPassword/OpalPasswordPei.inf      |   63 +
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c  | 1091 -------
 .../Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h   |  102 -
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h     |  146 -
 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c |  767 -----
 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h |  173 --
 .../Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c     | 1088 -------
 .../Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h     |  299 --
 .../Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf   |   77 -
 40 files changed, 5656 insertions(+), 6195 deletions(-)
 delete mode 100644 SecurityPkg/Include/Guid/OpalPasswordExtraInfoVariable.h
 delete mode 100644 SecurityPkg/Include/Library/OpalPasswordSupportLib.h
 delete mode 100644 SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.c
 delete mode 100644 SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf
 delete mode 100644 SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportNotify.h
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/ComponentName.c (100%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordSmm => OpalPassword}/OpalAhciMode.c (68%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordSmm => OpalPassword}/OpalAhciMode.h (85%)
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalDriver.h (71%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalHii.c (56%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe/OpalHiiPrivate.h => OpalPassword/OpalHii.h} (72%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalHiiCallbacks.c (91%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalHiiFormStrings.uni (66%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalHiiFormValues.h (56%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordSmm => OpalPassword}/OpalNvmeMode.c (93%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordSmm => OpalPassword}/OpalNvmeMode.h (93%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordSmm => OpalPassword}/OpalNvmeReg.h (96%)
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalPasswordDxe.inf (80%)
 rename SecurityPkg/Tcg/Opal/{OpalPasswordDxe => OpalPassword}/OpalPasswordForm.vfr (55%)
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf

-- 
2.7.0.windows.1



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

* [PATCH V2 1/7] MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  2018-03-07 13:19 ` [PATCH V2 2/7] SecurityPkg TcgStorageOpalLib: Make it be base type really Star Zeng
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao

With this flag, the LockBox can be restored in S3 resume only.
The LockBox can not be restored after SmmReadyToLock in normal boot
and after EndOfS3Resume in S3 resume.
It can not be set together with LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Library/LockBoxLib.h          |  14 +-
 .../Library/SmmLockBoxLib/SmmLockBoxDxeLib.c       |   4 +-
 .../Library/SmmLockBoxLib/SmmLockBoxSmmLib.c       | 227 ++++++++++++++++++++-
 .../Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf     |  10 +-
 4 files changed, 247 insertions(+), 8 deletions(-)

diff --git a/MdeModulePkg/Include/Library/LockBoxLib.h b/MdeModulePkg/Include/Library/LockBoxLib.h
index db7fd05def58..80beb4d0f880 100644
--- a/MdeModulePkg/Include/Library/LockBoxLib.h
+++ b/MdeModulePkg/Include/Library/LockBoxLib.h
@@ -2,7 +2,7 @@
   This library is only intended to be used by DXE modules that need save
   confidential information to LockBox and get it by PEI modules in S3 phase.
 
-Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 
 This program and the accompanying materials
 are licensed and made available under the terms and conditions
@@ -62,9 +62,17 @@ SetLockBoxAttributes (
   );
 
 //
-// With this flag, this LockBox can be restored to this Buffer with RestoreAllLockBoxInPlace()
+// With this flag, this LockBox can be restored to this Buffer
+// with RestoreAllLockBoxInPlace()
 //
-#define LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE  BIT0
+#define LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE     BIT0
+//
+// With this flag, this LockBox can be restored in S3 resume only.
+// This LockBox can not be restored after SmmReadyToLock in normal boot
+// and after EndOfS3Resume in S3 resume.
+// It can not be set together with LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE.
+//
+#define LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY   BIT1
 
 /**
   This function will update confidential information to lockbox.
diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c
index b75f81e69e04..9b6f0bedbd4f 100644
--- a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c
+++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 
 This program and the accompanying materials
 are licensed and made available under the terms and conditions
@@ -241,7 +241,7 @@ SetLockBoxAttributes (
   // Basic check
   //
   if ((Guid == NULL) ||
-      ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) {
+      ((Attributes & ~(LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE | LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY)) != 0)) {
     return EFI_INVALID_PARAMETER;
   }
 
diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
index 4960df755534..af75a4cb9cd1 100644
--- a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
+++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 
 This program and the accompanying materials
 are licensed and made available under the terms and conditions
@@ -20,6 +20,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/LockBoxLib.h>
 #include <Library/DebugLib.h>
 #include <Guid/SmmLockBox.h>
+#include <Guid/EndOfS3Resume.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <Protocol/SmmEndOfDxe.h>
+#include <Protocol/SmmSxDispatch2.h>
 
 #include "SmmLockBoxLibPrivate.h"
 
@@ -31,6 +35,11 @@ SMM_LOCK_BOX_CONTEXT mSmmLockBoxContext;
 LIST_ENTRY           mLockBoxQueue = INITIALIZE_LIST_HEAD_VARIABLE (mLockBoxQueue);
 
 BOOLEAN              mSmmConfigurationTableInstalled = FALSE;
+VOID                 *mRegistrationSmmEndOfDxe = NULL;
+VOID                 *mRegistrationSmmReadyToLock = NULL;
+VOID                 *mRegistrationEndOfS3Resume = NULL;
+BOOLEAN              mSmmLockBoxSmmReadyToLock = FALSE;
+BOOLEAN              mSmmLockBoxDuringS3Resume = FALSE;
 
 /**
   This function return SmmLockBox context from SMST.
@@ -64,6 +73,128 @@ InternalGetSmmLockBoxContext (
 }
 
 /**
+  Notification for SMM ReadyToLock protocol.
+
+  @param[in] Protocol   Points to the protocol's unique identifier.
+  @param[in] Interface  Points to the interface instance.
+  @param[in] Handle     The handle on which the interface was installed.
+
+  @retval EFI_SUCCESS   Notification runs successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxSmmReadyToLockNotify (
+  IN CONST EFI_GUID  *Protocol,
+  IN VOID            *Interface,
+  IN EFI_HANDLE      Handle
+  )
+{
+  mSmmLockBoxSmmReadyToLock = TRUE;
+  return EFI_SUCCESS;
+}
+
+/**
+  Main entry point for an SMM handler dispatch or communicate-based callback.
+
+  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]     Context         Points to an optional handler context which was specified when the
+                                 handler was registered.
+  @param[in,out] CommBuffer      A pointer to a collection of data in memory that will
+                                 be conveyed from a non-SMM environment into an SMM environment.
+  @param[in,out] CommBufferSize  The size of the CommBuffer.
+
+  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
+                                              should still be called.
+  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
+                                              still be called.
+  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
+                                              be called.
+  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxS3EntryCallBack (
+  IN           EFI_HANDLE           DispatchHandle,
+  IN     CONST VOID                 *Context         OPTIONAL,
+  IN OUT       VOID                 *CommBuffer      OPTIONAL,
+  IN OUT       UINTN                *CommBufferSize  OPTIONAL
+  )
+{
+  mSmmLockBoxDuringS3Resume = TRUE;
+  return EFI_SUCCESS;
+}
+
+/**
+  Notification for SMM EndOfDxe protocol.
+
+  @param[in] Protocol   Points to the protocol's unique identifier.
+  @param[in] Interface  Points to the interface instance.
+  @param[in] Handle     The handle on which the interface was installed.
+
+  @retval EFI_SUCCESS   Notification runs successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxSmmEndOfDxeNotify (
+  IN CONST EFI_GUID  *Protocol,
+  IN VOID            *Interface,
+  IN EFI_HANDLE      Handle
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_SMM_SX_DISPATCH2_PROTOCOL     *SxDispatch;
+  EFI_SMM_SX_REGISTER_CONTEXT       EntryRegisterContext;
+  EFI_HANDLE                        S3EntryHandle;
+
+  //
+  // Locate SmmSxDispatch2 protocol.
+  //
+  Status = gSmst->SmmLocateProtocol (
+                    &gEfiSmmSxDispatch2ProtocolGuid,
+                    NULL,
+                    (VOID **)&SxDispatch
+                    );
+  if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {
+    //
+    // Register a S3 entry callback function to
+    // determine if it will be during S3 resume.
+    //
+    EntryRegisterContext.Type  = SxS3;
+    EntryRegisterContext.Phase = SxEntry;
+    Status = SxDispatch->Register (
+                           SxDispatch,
+                           SmmLockBoxS3EntryCallBack,
+                           &EntryRegisterContext,
+                           &S3EntryHandle
+                           );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Notification for SMM EndOfS3Resume protocol.
+
+  @param[in] Protocol   Points to the protocol's unique identifier.
+  @param[in] Interface  Points to the interface instance.
+  @param[in] Handle     The handle on which the interface was installed.
+
+  @retval EFI_SUCCESS   Notification runs successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxEndOfS3ResumeNotify (
+  IN CONST EFI_GUID  *Protocol,
+  IN VOID            *Interface,
+  IN EFI_HANDLE      Handle
+  )
+{
+  mSmmLockBoxDuringS3Resume = FALSE;
+  return EFI_SUCCESS;
+}
+
+/**
   Constructor for SmmLockBox library.
   This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
 
@@ -86,6 +217,36 @@ SmmLockBoxSmmConstructor (
   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Enter\n"));
 
   //
+  // Register SmmReadyToLock notification.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gEfiSmmReadyToLockProtocolGuid,
+                    SmmLockBoxSmmReadyToLockNotify,
+                    &mRegistrationSmmReadyToLock
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register SmmEndOfDxe notification.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gEfiSmmEndOfDxeProtocolGuid,
+                    SmmLockBoxSmmEndOfDxeNotify,
+                    &mRegistrationSmmEndOfDxe
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register EndOfS3Resume notification.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gEdkiiEndOfS3ResumeGuid,
+                    SmmLockBoxEndOfS3ResumeNotify,
+                    &mRegistrationEndOfS3Resume
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
   // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
   //
   SmmLockBoxContext = InternalGetSmmLockBoxContext ();
@@ -158,6 +319,40 @@ SmmLockBoxSmmDestructor (
     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib uninstall SmmLockBoxCommunication configuration table\n"));
   }
 
+  if (mRegistrationSmmReadyToLock != NULL) {
+    //
+    // Unregister SmmReadyToLock notification.
+    //
+    Status = gSmst->SmmRegisterProtocolNotify (
+                      &gEfiSmmReadyToLockProtocolGuid,
+                      NULL,
+                      &mRegistrationSmmReadyToLock
+                      );
+    ASSERT_EFI_ERROR (Status);
+  }
+  if (mRegistrationSmmEndOfDxe != NULL) {
+    //
+    // Unregister SmmEndOfDxe notification.
+    //
+    Status = gSmst->SmmRegisterProtocolNotify (
+                      &gEfiSmmEndOfDxeProtocolGuid,
+                      NULL,
+                      &mRegistrationSmmEndOfDxe
+                      );
+    ASSERT_EFI_ERROR (Status);
+  }
+  if (mRegistrationEndOfS3Resume != NULL) {
+    //
+    // Unregister EndOfS3Resume notification.
+    //
+    Status = gSmst->SmmRegisterProtocolNotify (
+                      &gEdkiiEndOfS3ResumeGuid,
+                      NULL,
+                      &mRegistrationEndOfS3Resume
+                      );
+    ASSERT_EFI_ERROR (Status);
+  }
+
   return EFI_SUCCESS;
 }
 
@@ -354,8 +549,16 @@ SetLockBoxAttributes (
   // Basic check
   //
   if ((Guid == NULL) ||
-      ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) {
+      ((Attributes & ~(LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE | LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY)) != 0)) {
+    DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&
+      ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) {
     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));
+    DEBUG ((EFI_D_INFO, "  LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));
+    DEBUG ((EFI_D_INFO, "  can not be set together\n"));
     return EFI_INVALID_PARAMETER;
   }
 
@@ -368,6 +571,16 @@ SetLockBoxAttributes (
     return EFI_NOT_FOUND;
   }
 
+  if ((((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&
+      ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) ||
+      (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&
+      ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0))) {
+    DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes 0x%lx 0x%lx - Exit (%r)\n", LockBox->Attributes, Attributes, EFI_INVALID_PARAMETER));
+    DEBUG ((EFI_D_INFO, "  LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));
+    DEBUG ((EFI_D_INFO, "  can not be set together\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
   //
   // Update data
   //
@@ -496,6 +709,16 @@ RestoreLockBox (
     return EFI_NOT_FOUND;
   }
 
+  if (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) &&
+      mSmmLockBoxSmmReadyToLock &&
+      !mSmmLockBoxDuringS3Resume) {
+    //
+    // With LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,
+    // this LockBox can be restored in S3 resume only.
+    //
+    return EFI_ACCESS_DENIED;
+  }
+
   //
   // Set RestoreBuffer
   //
diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
index eb7ba0bb2e89..426af4cccfe0 100644
--- a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
@@ -1,7 +1,7 @@
 ## @file
 #  SMM LockBox library instance.
 #
-#  Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions
@@ -44,7 +44,15 @@ [LibraryClasses]
   BaseLib
   DebugLib
 
+[Protocols]
+  gEfiSmmReadyToLockProtocolGuid    ## NOTIFY
+  gEfiSmmEndOfDxeProtocolGuid       ## NOTIFY
+  gEfiSmmSxDispatch2ProtocolGuid    ## NOTIFY
+
 [Guids]
   ## SOMETIMES_CONSUMES   ## UNDEFINED # SmmSystemTable
   ## SOMETIMES_PRODUCES   ## UNDEFINED # SmmSystemTable
   gEfiSmmLockBoxCommunicationGuid
+  ## CONSUMES             ## UNDEFINED # Protocol notify
+  gEdkiiEndOfS3ResumeGuid
+
-- 
2.7.0.windows.1



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

* [PATCH V2 2/7] SecurityPkg TcgStorageOpalLib: Make it be base type really
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
  2018-03-07 13:19 ` [PATCH V2 1/7] MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  2018-03-07 13:19 ` [PATCH V2 3/7] SecurityPkg TcgStorageCoreLib: " Star Zeng
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf b/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf
index ec26111ee2c3..78e47387a981 100644
--- a/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf
+++ b/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf
@@ -3,7 +3,7 @@
 #
 #  This module is used to provide API used by Opal password solution.
 #
-# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
 # This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD License
 # which accompanies this distribution. The full text of the license may be found at
@@ -18,7 +18,7 @@ [Defines]
   FILE_GUID                      = F8B56221-FD5D-4215-B578-C3574AD1E253
   VERSION_STRING                 = 1.0
   MODULE_TYPE                    = BASE
-  LIBRARY_CLASS                  = TcgStorageOpalLib|DXE_DRIVER DXE_CORE DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = TcgStorageOpalLib
 
 #
 # The following information is for reference only and not required by the build tools.
@@ -37,11 +37,7 @@ [LibraryClasses]
   DebugLib
   TimerLib
   TcgStorageCoreLib
-  UefiLib
 
 [Packages]
   MdePkg/MdePkg.dec
   SecurityPkg/SecurityPkg.dec
-
-[Protocols]
-  gEfiStorageSecurityCommandProtocolGuid                         ## CONSUMES
-- 
2.7.0.windows.1



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

* [PATCH V2 3/7] SecurityPkg TcgStorageCoreLib: Make it be base type really
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
  2018-03-07 13:19 ` [PATCH V2 1/7] MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY Star Zeng
  2018-03-07 13:19 ` [PATCH V2 2/7] SecurityPkg TcgStorageOpalLib: Make it be base type really Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  2018-03-07 13:19 ` [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code Star Zeng
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
index a80cb00a9ce3..78a0557bfe42 100644
--- a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
+++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
@@ -3,7 +3,7 @@
 #
 #  This module is used to provide API used by Opal password solution.
 #
-# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
 # This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD License
 # which accompanies this distribution. The full text of the license may be found at
@@ -18,7 +18,7 @@ [Defines]
   FILE_GUID                      = ad63b09b-1fc9-4789-af0c-5af8a3fb1f9c
   VERSION_STRING                 = 1.0
   MODULE_TYPE                    = BASE
-  LIBRARY_CLASS                  = TcgStorageCoreLib|DXE_DRIVER DXE_CORE DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = TcgStorageCoreLib
 #
 # The following information is for reference only and not required by the build tools.
 #
-- 
2.7.0.windows.1



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

* [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
                   ` (2 preceding siblings ...)
  2018-03-07 13:19 ` [PATCH V2 3/7] SecurityPkg TcgStorageCoreLib: " Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  2018-03-08 11:44   ` Yao, Jiewen
  2018-03-07 13:19 ` [PATCH V2 5/7] SecurityPkg OpalPassword: Remove old solution Star Zeng
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

After IOMMU is enabled in S3, original solution with SMM device
code (OpalPasswordSmm) to unlock OPAL device for S3 will not work
as the DMA operation will be aborted without granted DMA buffer.
Instead, this solution is to add OpalPasswordPei to eliminate
SMM device code, and OPAL setup UI produced by OpalPasswordDxe
will be updated to send requests (set password, update password,
and etc), and then the requests will be processed in next boot
before SmmReadyToLock, password and device info will be saved to
lock box used by OpalPasswordPei to unlock OPAL device for S3.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
---
 SecurityPkg/SecurityPkg.dsc                        |    2 +
 SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c  |  398 +++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c   | 1335 +++++++++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h   |  435 +++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c     | 3003 ++++++++++++++++++++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h     |  613 ++++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c        | 1178 ++++++++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h        |  380 +++
 .../Tcg/Opal/OpalPassword/OpalHiiCallbacks.c       |  219 ++
 .../Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni   |   84 +
 .../Tcg/Opal/OpalPassword/OpalHiiFormValues.h      |  123 +
 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c   | 2144 ++++++++++++++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h   |  455 +++
 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h    |  815 ++++++
 .../Tcg/Opal/OpalPassword/OpalPasswordCommon.h     |   65 +
 .../Tcg/Opal/OpalPassword/OpalPasswordDxe.inf      |   81 +
 .../Tcg/Opal/OpalPassword/OpalPasswordForm.vfr     |  309 ++
 .../Tcg/Opal/OpalPassword/OpalPasswordPei.c        |  940 ++++++
 .../Tcg/Opal/OpalPassword/OpalPasswordPei.h        |  133 +
 .../Tcg/Opal/OpalPassword/OpalPasswordPei.inf      |   63 +
 20 files changed, 12775 insertions(+)
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
 create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf

diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 65a2fe3d7967..f82703a17b82 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -324,6 +324,8 @@ [Components.IA32, Components.X64]
   #
   SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
   SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf
+  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
+  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
 
 [Components.IPF]
   SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/EsalVariableDxeSal.inf
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c b/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
new file mode 100644
index 000000000000..ef963d0e0b62
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
@@ -0,0 +1,398 @@
+/** @file
+  UEFI Component Name(2) protocol implementation for Opal driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalDriver.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gOpalComponentName = {
+  OpalEfiDriverComponentNameGetDriverName,
+  OpalEfiDriverComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOpalComponentName2 = {
+  OpalEfiDriverComponentName2GetDriverName,
+  OpalEfiDriverComponentName2GetControllerName,
+  "en"
+};
+
+
+/// The name of the driver in all the languages we support.
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOpalDriverNameTable[] = {
+    { LANGUAGE_RFC_3066_ENGLISH, (CHAR16*)EFI_DRIVER_NAME_UNICODE },
+    { LANGUAGE_ISO_639_2_ENGLISH, (CHAR16*)EFI_DRIVER_NAME_UNICODE },
+    { 0, 0 }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetDriverName(
+  EFI_COMPONENT_NAME_PROTOCOL*    This,
+  CHAR8*                          Language,
+  CHAR16**                        DriverName
+  )
+{
+  return LookupUnicodeString2(
+    Language,
+    This->SupportedLanguages,
+    mOpalDriverNameTable,
+    DriverName,
+    TRUE
+    );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetDriverName(
+  EFI_COMPONENT_NAME2_PROTOCOL*   This,
+  CHAR8*                          Language,
+  CHAR16**                        DriverName
+  )
+{
+  return LookupUnicodeString2(
+    Language,
+    This->SupportedLanguages,
+    mOpalDriverNameTable,
+    DriverName,
+    FALSE
+    );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+GetControllerName(
+  EFI_HANDLE  ControllerHandle,
+  EFI_HANDLE  ChildHandle,
+  CHAR8*      Language,
+  CHAR16**    ControllerName
+  )
+{
+  if (Language == NULL || ControllerName == NULL || ControllerHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // don't support any controller or children names
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetControllerName(
+  EFI_COMPONENT_NAME_PROTOCOL*    This,
+  EFI_HANDLE                      ControllerHandle,
+  EFI_HANDLE                      ChildHandle,
+  CHAR8*                          Language,
+  CHAR16**                        ControllerName
+  )
+{
+  return (GetControllerName( ControllerHandle, ChildHandle, Language, ControllerName));
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetControllerName(
+  EFI_COMPONENT_NAME2_PROTOCOL*   This,
+  EFI_HANDLE                      ControllerHandle,
+  EFI_HANDLE                      ChildHandle,
+  CHAR8*                          Language,
+  CHAR16**                        ControllerName
+  )
+{
+  return (GetControllerName(ControllerHandle, ChildHandle, Language, ControllerName));
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
new file mode 100644
index 000000000000..550abacc9c75
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
@@ -0,0 +1,1335 @@
+/** @file
+  This driver is used for Opal Password Feature support at AHCI mode.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "OpalPasswordPei.h"
+
+/**
+  Start command for give slot on specific port.
+
+  @param  AhciBar            AHCI bar address.
+  @param  Port               The number of port.
+  @param  CommandSlot        The number of CommandSlot.
+  @param  Timeout            The timeout Value of start.
+
+  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
+  @retval EFI_TIMEOUT        The operation is time out.
+  @retval EFI_SUCCESS        The command start successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciStartCommand (
+  IN  UINT32                    AhciBar,
+  IN  UINT8                     Port,
+  IN  UINT8                     CommandSlot,
+  IN  UINT64                    Timeout
+  );
+
+/**
+  Stop command running for giving port
+
+  @param  AhciBar            AHCI bar address.
+  @param  Port               The number of port.
+  @param  Timeout            The timeout Value of stop.
+
+  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
+  @retval EFI_TIMEOUT        The operation is time out.
+  @retval EFI_SUCCESS        The command stop successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciStopCommand (
+  IN  UINT32                    AhciBar,
+  IN  UINT8                     Port,
+  IN  UINT64                    Timeout
+  );
+
+/**
+  Read AHCI Operation register.
+
+  @param  AhciBar      AHCI bar address.
+  @param  Offset       The operation register offset.
+
+  @return The register content read.
+
+**/
+UINT32
+EFIAPI
+AhciReadReg (
+  IN  UINT32              AhciBar,
+  IN  UINT32              Offset
+  )
+{
+  UINT32   Data;
+
+  Data = 0;
+
+  Data = MmioRead32 (AhciBar + Offset);
+
+  return Data;
+}
+
+/**
+  Write AHCI Operation register.
+
+  @param  AhciBar      AHCI bar address.
+  @param  Offset       The operation register offset.
+  @param  Data         The Data used to write down.
+
+**/
+VOID
+EFIAPI
+AhciWriteReg (
+  IN UINT32               AhciBar,
+  IN UINT32               Offset,
+  IN UINT32               Data
+  )
+{
+  MmioWrite32 (AhciBar + Offset, Data);
+
+  return ;
+}
+
+/**
+  Do AND operation with the Value of AHCI Operation register.
+
+  @param  AhciBar      AHCI bar address.
+  @param  Offset       The operation register offset.
+  @param  AndData      The Data used to do AND operation.
+
+**/
+VOID
+EFIAPI
+AhciAndReg (
+  IN UINT32               AhciBar,
+  IN UINT32               Offset,
+  IN UINT32               AndData
+  )
+{
+  UINT32 Data;
+
+  Data  = AhciReadReg (AhciBar, Offset);
+
+  Data &= AndData;
+
+  AhciWriteReg (AhciBar, Offset, Data);
+}
+
+/**
+  Do OR operation with the Value of AHCI Operation register.
+
+  @param  AhciBar      AHCI bar address.
+  @param  Offset       The operation register offset.
+  @param  OrData       The Data used to do OR operation.
+
+**/
+VOID
+EFIAPI
+AhciOrReg (
+  IN UINT32               AhciBar,
+  IN UINT32               Offset,
+  IN UINT32               OrData
+  )
+{
+  UINT32 Data;
+
+  Data  = AhciReadReg (AhciBar, Offset);
+
+  Data |= OrData;
+
+  AhciWriteReg (AhciBar, Offset, Data);
+}
+
+/**
+  Wait for memory set to the test Value.
+
+  @param  AhciBar           AHCI bar address.
+  @param  Offset            The memory offset to test.
+  @param  MaskValue         The mask Value of memory.
+  @param  TestValue         The test Value of memory.
+  @param  Timeout           The time out Value for wait memory set.
+
+  @retval EFI_DEVICE_ERROR  The memory is not set.
+  @retval EFI_TIMEOUT       The memory setting is time out.
+  @retval EFI_SUCCESS       The memory is correct set.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciWaitMmioSet (
+  IN  UINT32                    AhciBar,
+  IN  UINT32                    Offset,
+  IN  UINT32                    MaskValue,
+  IN  UINT32                    TestValue,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32     Value;
+  UINT32     Delay;
+
+  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
+
+  do {
+    Value = AhciReadReg (AhciBar, Offset) & MaskValue;
+
+    if (Value == TestValue) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Stall for 100 microseconds.
+    //
+    MicroSecondDelay (100);
+
+    Delay--;
+
+  } while (Delay > 0);
+
+  return EFI_TIMEOUT;
+}
+/**
+  Wait for the Value of the specified system memory set to the test Value.
+
+  @param  Address           The system memory address to test.
+  @param  MaskValue         The mask Value of memory.
+  @param  TestValue         The test Value of memory.
+  @param  Timeout           The time out Value for wait memory set, uses 100ns as a unit.
+
+  @retval EFI_TIMEOUT       The system memory setting is time out.
+  @retval EFI_SUCCESS       The system memory is correct set.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciWaitMemSet (
+  IN  EFI_PHYSICAL_ADDRESS      Address,
+  IN  UINT32                    MaskValue,
+  IN  UINT32                    TestValue,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32     Value;
+  UINT32     Delay;
+
+  Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
+
+  do {
+    //
+    // Access sytem memory to see if the Value is the tested one.
+    //
+    // The system memory pointed by Address will be updated by the
+    // SATA Host Controller, "volatile" is introduced to prevent
+    // compiler from optimizing the access to the memory address
+    // to only read once.
+    //
+    Value  = *(volatile UINT32 *) (UINTN) Address;
+    Value &= MaskValue;
+
+    if (Value == TestValue) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Stall for 100 microseconds.
+    //
+    MicroSecondDelay (100);
+
+    Delay--;
+
+  } while (Delay > 0);
+
+  return EFI_TIMEOUT;
+}
+
+/**
+  Check the memory status to the test Value.
+
+  @param[in]       Address           The memory address to test.
+  @param[in]       MaskValue         The mask Value of memory.
+  @param[in]       TestValue         The test Value of memory.
+  @param[in, out]  RetryTimes        The retry times Value for waitting memory set. If 0, then just try once.
+
+  @retval EFI_NOTREADY      The memory is not set.
+  @retval EFI_TIMEOUT       The memory setting retry times out.
+  @retval EFI_SUCCESS       The memory is correct set.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciCheckMemSet (
+  IN     UINTN                     Address,
+  IN     UINT32                    MaskValue,
+  IN     UINT32                    TestValue,
+  IN OUT UINTN                     *RetryTimes OPTIONAL
+  )
+{
+  UINT32     Value;
+
+  if (RetryTimes != NULL) {
+    (*RetryTimes)--;
+  }
+
+  Value  = *(volatile UINT32 *) Address;
+  Value &= MaskValue;
+
+  if (Value == TestValue) {
+    return EFI_SUCCESS;
+  }
+
+  if ((RetryTimes != NULL) && (*RetryTimes == 0)) {
+    return EFI_TIMEOUT;
+  } else {
+    return EFI_NOT_READY;
+  }
+}
+
+/**
+  Clear the port interrupt and error status. It will also clear
+  HBA interrupt status.
+
+  @param      AhciBar        AHCI bar address.
+  @param      Port           The number of port.
+
+**/
+VOID
+EFIAPI
+AhciClearPortStatus (
+  IN  UINT32                 AhciBar,
+  IN  UINT8                  Port
+  )
+{
+  UINT32 Offset;
+
+  //
+  // Clear any error status
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
+  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
+
+  //
+  // Clear any port interrupt status
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
+  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
+
+  //
+  // Clear any HBA interrupt status
+  //
+  AhciWriteReg (AhciBar, EFI_AHCI_IS_OFFSET, AhciReadReg (AhciBar, EFI_AHCI_IS_OFFSET));
+}
+
+/**
+  Enable the FIS running for giving port.
+
+  @param      AhciBar        AHCI bar address.
+  @param      Port           The number of port.
+  @param      Timeout        The timeout Value of enabling FIS.
+
+  @retval EFI_DEVICE_ERROR   The FIS enable setting fails.
+  @retval EFI_TIMEOUT        The FIS enable setting is time out.
+  @retval EFI_SUCCESS        The FIS enable successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciEnableFisReceive (
+  IN  UINT32                    AhciBar,
+  IN  UINT8                     Port,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32 Offset;
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_FRE);
+
+  return AhciWaitMmioSet (
+           AhciBar,
+           Offset,
+           EFI_AHCI_PORT_CMD_FR,
+           EFI_AHCI_PORT_CMD_FR,
+           Timeout
+           );
+}
+
+/**
+  Disable the FIS running for giving port.
+
+  @param      AhciBar        AHCI bar address.
+  @param      Port           The number of port.
+  @param      Timeout        The timeout Value of disabling FIS.
+
+  @retval EFI_DEVICE_ERROR   The FIS disable setting fails.
+  @retval EFI_TIMEOUT        The FIS disable setting is time out.
+  @retval EFI_UNSUPPORTED    The port is in running state.
+  @retval EFI_SUCCESS        The FIS disable successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciDisableFisReceive (
+  IN  UINT32                    AhciBar,
+  IN  UINT8                     Port,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32 Offset;
+  UINT32 Data;
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  Data   = AhciReadReg (AhciBar, Offset);
+
+  //
+  // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
+  //
+  if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check if the Fis receive DMA engine for the port is running.
+  //
+  if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
+    return EFI_SUCCESS;
+  }
+
+  AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
+
+  return AhciWaitMmioSet (
+           AhciBar,
+           Offset,
+           EFI_AHCI_PORT_CMD_FR,
+           0,
+           Timeout
+           );
+}
+
+/**
+  Build the command list, command table and prepare the fis receiver.
+
+  @param    AhciContext           The pointer to the AHCI_CONTEXT.
+  @param    Port                  The number of port.
+  @param    PortMultiplier        The timeout Value of stop.
+  @param    CommandFis            The control fis will be used for the transfer.
+  @param    CommandList           The command list will be used for the transfer.
+  @param    AtapiCommand          The atapi command will be used for the transfer.
+  @param    AtapiCommandLength    The Length of the atapi command.
+  @param    CommandSlotNumber     The command slot will be used for the transfer.
+  @param    DataPhysicalAddr      The pointer to the Data Buffer pci bus master address.
+  @param    DataLength            The Data count to be transferred.
+
+**/
+VOID
+EFIAPI
+AhciBuildCommand (
+  IN     AHCI_CONTEXT               *AhciContext,
+  IN     UINT8                      Port,
+  IN     UINT8                      PortMultiplier,
+  IN     EFI_AHCI_COMMAND_FIS       *CommandFis,
+  IN     EFI_AHCI_COMMAND_LIST      *CommandList,
+  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
+  IN     UINT8                      AtapiCommandLength,
+  IN     UINT8                      CommandSlotNumber,
+  IN OUT VOID                       *DataPhysicalAddr,
+  IN     UINT64                     DataLength
+  )
+{
+  EFI_AHCI_REGISTERS    *AhciRegisters;
+  UINT32                AhciBar;
+  UINT64                BaseAddr;
+  UINT64                PrdtNumber;
+  UINTN                 RemainedData;
+  UINTN                 MemAddr;
+  DATA_64               Data64;
+  UINT32                Offset;
+
+  AhciRegisters = &AhciContext->AhciRegisters;
+  AhciBar = AhciContext->AhciBar;
+
+  //
+  // Filling the PRDT
+  //
+  PrdtNumber = DivU64x32 (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1, EFI_AHCI_MAX_DATA_PER_PRDT);
+
+  //
+  // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB Data block.
+  // It also limits that the maximum amount of the PRDT entry in the command table
+  // is 65535.
+  //
+  ASSERT (PrdtNumber <= 1);
+
+  Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis);
+
+  BaseAddr = Data64.Uint64;
+
+  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
+
+  ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
+
+  CommandFis->AhciCFisPmNum = PortMultiplier;
+
+  CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  if (AtapiCommand != NULL) {
+    CopyMem (
+      &AhciRegisters->AhciCommandTable->AtapiCmd,
+      AtapiCommand,
+      AtapiCommandLength
+      );
+
+    CommandList->AhciCmdA = 1;
+    CommandList->AhciCmdP = 1;
+
+    AhciOrReg (AhciBar, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
+  } else {
+    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
+  }
+
+  RemainedData = (UINTN) DataLength;
+  MemAddr      = (UINTN) DataPhysicalAddr;
+  CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
+
+  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbc = (UINT32)RemainedData - 1;
+
+  Data64.Uint64 = (UINT64)MemAddr;
+  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDba  = Data64.Uint32.Lower32;
+  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbau = Data64.Uint32.Upper32;
+
+  //
+  // Set the last PRDT to Interrupt On Complete
+  //
+  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtIoc = 1;
+
+  CopyMem (
+    (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
+    CommandList,
+    sizeof (EFI_AHCI_COMMAND_LIST)
+    );
+
+  Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTable;
+  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba  = Data64.Uint32.Lower32;
+  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
+  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp   = PortMultiplier;
+
+}
+
+/**
+  Buid a command FIS.
+
+  @param  CmdFis            A pointer to the EFI_AHCI_COMMAND_FIS Data structure.
+  @param  AtaCommandBlock   A pointer to the AhciBuildCommandFis Data structure.
+
+**/
+VOID
+EFIAPI
+AhciBuildCommandFis (
+  IN OUT EFI_AHCI_COMMAND_FIS    *CmdFis,
+  IN     EFI_ATA_COMMAND_BLOCK   *AtaCommandBlock
+  )
+{
+  ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
+
+  CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
+  //
+  // Indicator it's a command
+  //
+  CmdFis->AhciCFisCmdInd      = 0x1;
+  CmdFis->AhciCFisCmd         = AtaCommandBlock->AtaCommand;
+
+  CmdFis->AhciCFisFeature     = AtaCommandBlock->AtaFeatures;
+  CmdFis->AhciCFisFeatureExp  = AtaCommandBlock->AtaFeaturesExp;
+
+  CmdFis->AhciCFisSecNum      = AtaCommandBlock->AtaSectorNumber;
+  CmdFis->AhciCFisSecNumExp   = AtaCommandBlock->AtaSectorNumberExp;
+
+  CmdFis->AhciCFisClyLow      = AtaCommandBlock->AtaCylinderLow;
+  CmdFis->AhciCFisClyLowExp   = AtaCommandBlock->AtaCylinderLowExp;
+
+  CmdFis->AhciCFisClyHigh     = AtaCommandBlock->AtaCylinderHigh;
+  CmdFis->AhciCFisClyHighExp  = AtaCommandBlock->AtaCylinderHighExp;
+
+  CmdFis->AhciCFisSecCount    = AtaCommandBlock->AtaSectorCount;
+  CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
+
+  CmdFis->AhciCFisDevHead     = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
+}
+
+/**
+  Start a PIO Data transfer on specific port.
+
+  @param  AhciContext         The pointer to the AHCI_CONTEXT.
+  @param  Port                The number of port.
+  @param  PortMultiplier      The timeout Value of stop.
+  @param  AtapiCommand        The atapi command will be used for the transfer.
+  @param  AtapiCommandLength  The Length of the atapi command.
+  @param  Read                The transfer direction.
+  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
+  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
+  @param  MemoryAddr          The pointer to the Data Buffer.
+  @param  DataCount           The Data count to be transferred.
+  @param  Timeout             The timeout Value of non Data transfer.
+
+  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
+  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciPioTransfer (
+  IN     AHCI_CONTEXT               *AhciContext,
+  IN     UINT8                      Port,
+  IN     UINT8                      PortMultiplier,
+  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
+  IN     UINT8                      AtapiCommandLength,
+  IN     BOOLEAN                    Read,
+  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
+  IN OUT VOID                       *MemoryAddr,
+  IN     UINT32                     DataCount,
+  IN     UINT64                     Timeout
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_AHCI_REGISTERS            *AhciRegisters;
+  UINT32                        AhciBar;
+  UINT32                        FisBaseAddr;
+  UINT32                        Offset;
+  UINT32                        Delay;
+  EFI_AHCI_COMMAND_FIS          CFis;
+  EFI_AHCI_COMMAND_LIST         CmdList;
+  UINT32                        PortTfd;
+  UINT32                        PrdCount;
+  UINT32                        OldRfisLo;
+  UINT32                        OldRfisHi;
+  UINT32                        OldCmdListLo;
+  UINT32                        OldCmdListHi;
+
+  AhciRegisters = &AhciContext->AhciRegisters;
+  AhciBar = AhciContext->AhciBar;
+
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
+  OldRfisLo = AhciReadReg (AhciBar, Offset);
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
+  OldRfisHi = AhciReadReg (AhciBar, Offset);
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
+  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
+  AhciWriteReg (AhciBar, Offset, 0);
+
+  //
+  // Single task envrionment, we only use one command table for all port
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
+  OldCmdListLo = AhciReadReg (AhciBar, Offset);
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
+  OldCmdListHi = AhciReadReg (AhciBar, Offset);
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
+  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
+  AhciWriteReg (AhciBar, Offset, 0);
+
+  //
+  // Package read needed
+  //
+  AhciBuildCommandFis (&CFis, AtaCommandBlock);
+
+  ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
+
+  CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
+  CmdList.AhciCmdW   = Read ? 0 : 1;
+
+  AhciBuildCommand (
+    AhciContext,
+    Port,
+    PortMultiplier,
+    &CFis,
+    &CmdList,
+    AtapiCommand,
+    AtapiCommandLength,
+    0,
+    MemoryAddr,
+    DataCount
+    );
+
+  Status = AhciStartCommand (
+             AhciBar,
+             Port,
+             0,
+             Timeout
+             );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Checking the status and wait the driver sending Data
+  //
+  FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis;
+  if (Read && (AtapiCommand == 0)) {
+    //
+    // Wait device sends the PIO setup fis before Data transfer
+    //
+    Status = EFI_TIMEOUT;
+    Delay  = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
+    do {
+      Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
+
+      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0);
+      if (!EFI_ERROR (Status)) {
+        Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+        PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
+        //
+        // PxTFD will be updated if there is a D2H or SetupFIS received.
+        // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.
+        //
+        if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
+          Status = EFI_DEVICE_ERROR;
+          break;
+        }
+
+        PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
+        if (PrdCount == DataCount) {
+          break;
+        }
+      }
+
+      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
+      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, 0);
+      if (!EFI_ERROR (Status)) {
+        Status = EFI_DEVICE_ERROR;
+        break;
+      }
+
+      //
+      // Stall for 100 microseconds.
+      //
+      MicroSecondDelay(100);
+
+      Delay--;
+    } while (Delay > 0);
+  } else {
+    //
+    // Wait for D2H Fis is received
+    //
+    Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
+    Status = AhciWaitMemSet (
+               Offset,
+               EFI_AHCI_FIS_TYPE_MASK,
+               EFI_AHCI_FIS_REGISTER_D2H,
+               Timeout
+               );
+
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+
+    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+    PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
+    if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
+      Status = EFI_DEVICE_ERROR;
+    }
+  }
+
+Exit:
+  AhciStopCommand (
+    AhciBar,
+    Port,
+    Timeout
+    );
+
+  AhciDisableFisReceive (
+    AhciBar,
+    Port,
+    Timeout
+    );
+
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
+  AhciWriteReg (AhciBar, Offset, OldRfisLo);
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
+  AhciWriteReg (AhciBar, Offset, OldRfisHi);
+
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
+  AhciWriteReg (AhciBar, Offset, OldCmdListLo);
+  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
+  AhciWriteReg (AhciBar, Offset, OldCmdListHi);
+
+  return Status;
+}
+
+/**
+  Stop command running for giving port
+
+  @param  AhciBar            AHCI bar address.
+  @param  Port               The number of port.
+  @param  Timeout            The timeout Value of stop.
+
+  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
+  @retval EFI_TIMEOUT        The operation is time out.
+  @retval EFI_SUCCESS        The command stop successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciStopCommand (
+  IN  UINT32                    AhciBar,
+  IN  UINT8                     Port,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32 Offset;
+  UINT32 Data;
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  Data   = AhciReadReg (AhciBar, Offset);
+
+  if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {
+    return EFI_SUCCESS;
+  }
+
+  if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
+    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
+  }
+
+  return AhciWaitMmioSet (
+           AhciBar,
+           Offset,
+           EFI_AHCI_PORT_CMD_CR,
+           0,
+           Timeout
+           );
+}
+
+/**
+  Start command for give slot on specific port.
+
+  @param  AhciBar            AHCI bar address.
+  @param  Port               The number of port.
+  @param  CommandSlot        The number of CommandSlot.
+  @param  Timeout            The timeout Value of start.
+
+  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
+  @retval EFI_TIMEOUT        The operation is time out.
+  @retval EFI_SUCCESS        The command start successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciStartCommand (
+  IN  UINT32                    AhciBar,
+  IN  UINT8                     Port,
+  IN  UINT8                     CommandSlot,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32                        CmdSlotBit;
+  EFI_STATUS                    Status;
+  UINT32                        PortStatus;
+  UINT32                        StartCmd;
+  UINT32                        PortTfd;
+  UINT32                        Offset;
+  UINT32                        Capability;
+
+  //
+  // Collect AHCI controller information
+  //
+  Capability = AhciReadReg(AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
+
+  CmdSlotBit = (UINT32) (1 << CommandSlot);
+
+  AhciClearPortStatus (
+    AhciBar,
+    Port
+    );
+
+  Status = AhciEnableFisReceive (
+             AhciBar,
+             Port,
+             Timeout
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  PortStatus = AhciReadReg (AhciBar, Offset);
+
+  StartCmd = 0;
+  if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
+    StartCmd = AhciReadReg (AhciBar, Offset);
+    StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
+    StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
+  }
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+  PortTfd = AhciReadReg (AhciBar, Offset);
+
+  if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
+    if ((Capability & BIT24) != 0) {
+      Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+      AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_COL);
+
+      AhciWaitMmioSet (
+        AhciBar,
+        Offset,
+        EFI_AHCI_PORT_CMD_COL,
+        0,
+        Timeout
+        );
+    }
+  }
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
+
+  //
+  // Setting the command
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SACT;
+  AhciAndReg (AhciBar, Offset, 0);
+  AhciOrReg (AhciBar, Offset, CmdSlotBit);
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
+  AhciAndReg (AhciBar, Offset, 0);
+  AhciOrReg (AhciBar, Offset, CmdSlotBit);
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Do AHCI HBA reset.
+
+  @param[in]  AhciBar        AHCI bar address.
+  @param[in]  Timeout        The timeout Value of reset.
+
+  @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete hardware reset.
+  @retval EFI_TIMEOUT        The reset operation is time out.
+  @retval EFI_SUCCESS        AHCI controller is reset successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciReset (
+  IN  UINT32                    AhciBar,
+  IN  UINT64                    Timeout
+  )
+{
+  UINT32                 Delay;
+  UINT32                 Value;
+  UINT32                 Capability;
+
+  //
+  // Collect AHCI controller information
+  //
+  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
+
+  //
+  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
+  //
+  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
+    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
+  }
+
+  AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
+
+  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
+
+  do {
+    Value = AhciReadReg(AhciBar, EFI_AHCI_GHC_OFFSET);
+    if ((Value & EFI_AHCI_GHC_RESET) == 0) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Stall for 100 microseconds.
+    //
+    MicroSecondDelay(100);
+
+    Delay--;
+  } while (Delay > 0);
+
+  return EFI_TIMEOUT;
+
+
+}
+
+/**
+  Send Buffer cmd to specific device.
+
+  @param[in]  AhciContext         The pointer to the AHCI_CONTEXT.
+  @param[in]  Port                The port number of attached ATA device.
+  @param[in]  PortMultiplier      The port number of port multiplier of attached ATA device.
+  @param[in, out]  Buffer         The Data Buffer to store IDENTIFY PACKET Data.
+
+  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for executing.
+  @retval EFI_SUCCESS         The cmd executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciIdentify (
+  IN AHCI_CONTEXT             *AhciContext,
+  IN UINT8                    Port,
+  IN UINT8                    PortMultiplier,
+  IN OUT ATA_IDENTIFY_DATA    *Buffer
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
+
+  if (AhciContext == NULL || Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
+
+  AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DRIVE;
+  AtaCommandBlock.AtaSectorCount = 1;
+
+  Status = AhciPioTransfer (
+             AhciContext,
+             Port,
+             PortMultiplier,
+             NULL,
+             0,
+             TRUE,
+             &AtaCommandBlock,
+             NULL,
+             Buffer,
+             sizeof (ATA_IDENTIFY_DATA),
+             ATA_TIMEOUT
+             );
+
+  return Status;
+}
+
+/**
+  Allocate transfer-related data struct which is used at AHCI mode.
+
+  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
+
+  @retval EFI_OUT_OF_RESOURCE   No enough resource.
+  @retval EFI_SUCCESS           Successful to allocate resource.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciAllocateResource (
+  IN OUT AHCI_CONTEXT       *AhciContext
+  )
+{
+  EFI_STATUS                Status;
+  EFI_AHCI_REGISTERS        *AhciRegisters;
+  EFI_PHYSICAL_ADDRESS      DeviceAddress;
+  VOID                      *Base;
+  VOID                      *Mapping;
+
+  AhciRegisters = &AhciContext->AhciRegisters;
+
+  //
+  // Allocate resources required by AHCI host controller.
+  //
+  Status = IoMmuAllocateBuffer (
+             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
+             &Base,
+             &DeviceAddress,
+             &Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
+  AhciRegisters->AhciRFisMapping = Mapping;
+  AhciRegisters->AhciRFis = Base;
+  ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)));
+
+  Status = IoMmuAllocateBuffer (
+             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
+             &Base,
+             &DeviceAddress,
+             &Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
+       AhciRegisters->AhciRFis,
+       AhciRegisters->AhciRFisMapping
+       );
+    AhciRegisters->AhciRFis = NULL;
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
+  AhciRegisters->AhciCmdListMapping = Mapping;
+  AhciRegisters->AhciCmdList = Base;
+  ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
+
+  Status = IoMmuAllocateBuffer (
+             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
+             &Base,
+             &DeviceAddress,
+             &Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
+       AhciRegisters->AhciRFis,
+       AhciRegisters->AhciRFisMapping
+       );
+    AhciRegisters->AhciRFis = NULL;
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
+       AhciRegisters->AhciCmdList,
+       AhciRegisters->AhciCmdListMapping
+       );
+    AhciRegisters->AhciCmdList = NULL;
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
+  AhciRegisters->AhciCommandTableMapping = Mapping;
+  AhciRegisters->AhciCommandTable = Base;
+  ZeroMem (AhciRegisters->AhciCommandTable, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));
+
+  //
+  // Allocate resources for data transfer.
+  //
+  Status = IoMmuAllocateBuffer (
+             EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
+             &Base,
+             &DeviceAddress,
+             &Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
+       AhciRegisters->AhciRFis,
+       AhciRegisters->AhciRFisMapping
+       );
+    AhciRegisters->AhciRFis = NULL;
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
+       AhciRegisters->AhciCmdList,
+       AhciRegisters->AhciCmdListMapping
+       );
+    AhciRegisters->AhciCmdList = NULL;
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
+       AhciRegisters->AhciCommandTable,
+       AhciRegisters->AhciCommandTableMapping
+       );
+    AhciRegisters->AhciCommandTable = NULL;
+
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
+  AhciContext->BufferMapping = Mapping;
+  AhciContext->Buffer = Base;
+  ZeroMem (AhciContext->Buffer, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (HDD_PAYLOAD));
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a() AhciContext 0x%x 0x%x 0x%x 0x%x\n",
+    __FUNCTION__,
+    AhciContext->Buffer,
+    AhciRegisters->AhciRFis,
+    AhciRegisters->AhciCmdList,
+    AhciRegisters->AhciCommandTable
+    ));
+  return EFI_SUCCESS;
+}
+
+/**
+  Free allocated transfer-related data struct which is used at AHCI mode.
+
+  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
+
+**/
+VOID
+EFIAPI
+AhciFreeResource (
+  IN OUT AHCI_CONTEXT       *AhciContext
+  )
+{
+  EFI_AHCI_REGISTERS        *AhciRegisters;
+
+  AhciRegisters = &AhciContext->AhciRegisters;
+
+  if (AhciRegisters->AhciRFis != NULL) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
+       AhciRegisters->AhciRFis,
+       AhciRegisters->AhciRFisMapping
+       );
+    AhciRegisters->AhciRFis = NULL;
+  }
+
+  if (AhciRegisters->AhciCmdList != NULL) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
+       AhciRegisters->AhciCmdList,
+       AhciRegisters->AhciCmdListMapping
+       );
+    AhciRegisters->AhciCmdList = NULL;
+  }
+
+  if (AhciRegisters->AhciCommandTable != NULL) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
+       AhciRegisters->AhciCommandTable,
+       AhciRegisters->AhciCommandTableMapping
+       );
+    AhciRegisters->AhciCommandTable = NULL;
+  }
+
+  if (AhciContext->Buffer != NULL) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
+       AhciContext->Buffer,
+       AhciContext->BufferMapping
+       );
+    AhciContext->Buffer = NULL;
+  }
+}
+
+/**
+  Initialize ATA host controller at AHCI mode.
+
+  The function is designed to initialize ATA host controller.
+
+  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.
+  @param[in]  Port          The port number to do initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciModeInitialize (
+  IN AHCI_CONTEXT    *AhciContext,
+  IN UINT8           Port
+  )
+{
+  EFI_STATUS         Status;
+  EFI_AHCI_REGISTERS *AhciRegisters;
+  UINT32             AhciBar;
+  UINT32             Capability;
+  UINT32             Offset;
+  UINT32             Data;
+  UINT32             PhyDetectDelay;
+
+  AhciRegisters = &AhciContext->AhciRegisters;
+  AhciBar = AhciContext->AhciBar;
+
+  Status = AhciReset (AhciBar, ATA_TIMEOUT);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Collect AHCI controller information
+  //
+  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
+
+  //
+  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
+  //
+  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
+    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
+  }
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
+  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
+
+  //
+  // Single task envrionment, we only use one command table for all port
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
+  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+  Data = AhciReadReg (AhciBar, Offset);
+  if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
+    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_POD);
+  }
+
+  if ((Capability & BIT27) != 0) {
+    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_SUD);
+  }
+
+  //
+  // Disable aggressive power management.
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
+  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
+  //
+  // Disable the reporting of the corresponding interrupt to system software.
+  //
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
+  AhciAndReg (AhciBar, Offset, 0);
+
+  Status = AhciEnableFisReceive (
+             AhciBar,
+             Port,
+             5000000
+             );
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
+  // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
+  //
+  PhyDetectDelay = 16 * 1000;
+  do {
+    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
+    if (AhciReadReg(AhciBar, Offset) != 0) {
+      AhciWriteReg (AhciBar, Offset, AhciReadReg(AhciBar, Offset));
+    }
+    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+
+    Data = AhciReadReg (AhciBar, Offset) & EFI_AHCI_PORT_TFD_MASK;
+    if (Data == 0) {
+      break;
+    }
+
+    MicroSecondDelay (1000);
+    PhyDetectDelay--;
+  } while (PhyDetectDelay > 0);
+
+  if (PhyDetectDelay == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
+  Status = AhciWaitMmioSet (
+             AhciBar,
+             Offset,
+             0x0000FFFF,
+             0x00000101,
+             160000000
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return Status;
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
new file mode 100644
index 000000000000..b1d6ed13d5b9
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
@@ -0,0 +1,435 @@
+/** @file
+  Header file for AHCI mode of ATA host controller.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __OPAL_PASSWORD_AHCI_MODE_H__
+#define __OPAL_PASSWORD_AHCI_MODE_H__
+
+//
+// OPAL LIBRARY CALLBACKS
+//
+#define ATA_COMMAND_TRUSTED_RECEIVE            0x5C
+#define ATA_COMMAND_TRUSTED_SEND               0x5E
+
+//
+// ATA TRUSTED commands express transfer Length in 512 byte multiple
+//
+#define ATA_TRUSTED_TRANSFER_LENGTH_MULTIPLE   512
+#define ATA_DEVICE_LBA                         0x40    ///< Set for commands with LBA (rather than CHS) addresses
+
+
+#define EFI_AHCI_BAR_INDEX                     0x05
+
+#define EFI_AHCI_CAPABILITY_OFFSET             0x0000
+#define   EFI_AHCI_CAP_SAM                     BIT18
+#define EFI_AHCI_GHC_OFFSET                    0x0004
+#define   EFI_AHCI_GHC_RESET                   BIT0
+#define   EFI_AHCI_GHC_IE                      BIT1
+#define   EFI_AHCI_GHC_ENABLE                  BIT31
+#define EFI_AHCI_IS_OFFSET                     0x0008
+#define EFI_AHCI_PI_OFFSET                     0x000C
+
+typedef struct {
+  UINT32  Lower32;
+  UINT32  Upper32;
+} DATA_32;
+
+typedef union {
+  DATA_32   Uint32;
+  UINT64    Uint64;
+} DATA_64;
+
+//
+// Each PRDT entry can point to a memory block up to 4M byte
+//
+#define EFI_AHCI_MAX_DATA_PER_PRDT             0x400000
+
+#define EFI_AHCI_FIS_REGISTER_H2D              0x27      //Register FIS - Host to Device
+#define   EFI_AHCI_FIS_REGISTER_H2D_LENGTH     20
+#define EFI_AHCI_FIS_REGISTER_D2H              0x34      //Register FIS - Device to Host
+#define   EFI_AHCI_FIS_REGISTER_D2H_LENGTH     20
+#define EFI_AHCI_FIS_DMA_ACTIVATE              0x39      //DMA Activate FIS - Device to Host
+#define   EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH     4
+#define EFI_AHCI_FIS_DMA_SETUP                 0x41      //DMA Setup FIS - Bi-directional
+#define   EFI_AHCI_FIS_DMA_SETUP_LENGTH        28
+#define EFI_AHCI_FIS_DATA                      0x46      //Data FIS - Bi-directional
+#define EFI_AHCI_FIS_BIST                      0x58      //BIST Activate FIS - Bi-directional
+#define   EFI_AHCI_FIS_BIST_LENGTH             12
+#define EFI_AHCI_FIS_PIO_SETUP                 0x5F      //PIO Setup FIS - Device to Host
+#define   EFI_AHCI_FIS_PIO_SETUP_LENGTH        20
+#define EFI_AHCI_FIS_SET_DEVICE                0xA1      //Set Device Bits FIS - Device to Host
+#define   EFI_AHCI_FIS_SET_DEVICE_LENGTH       8
+
+#define EFI_AHCI_D2H_FIS_OFFSET                0x40
+#define EFI_AHCI_DMA_FIS_OFFSET                0x00
+#define EFI_AHCI_PIO_FIS_OFFSET                0x20
+#define EFI_AHCI_SDB_FIS_OFFSET                0x58
+#define EFI_AHCI_FIS_TYPE_MASK                 0xFF
+#define EFI_AHCI_U_FIS_OFFSET                  0x60
+
+//
+// Port register
+//
+#define EFI_AHCI_PORT_START                    0x0100
+#define EFI_AHCI_PORT_REG_WIDTH                0x0080
+#define EFI_AHCI_PORT_CLB                      0x0000
+#define EFI_AHCI_PORT_CLBU                     0x0004
+#define EFI_AHCI_PORT_FB                       0x0008
+#define EFI_AHCI_PORT_FBU                      0x000C
+#define EFI_AHCI_PORT_IS                       0x0010
+#define   EFI_AHCI_PORT_IS_DHRS                BIT0
+#define   EFI_AHCI_PORT_IS_PSS                 BIT1
+#define   EFI_AHCI_PORT_IS_SSS                 BIT2
+#define   EFI_AHCI_PORT_IS_SDBS                BIT3
+#define   EFI_AHCI_PORT_IS_UFS                 BIT4
+#define   EFI_AHCI_PORT_IS_DPS                 BIT5
+#define   EFI_AHCI_PORT_IS_PCS                 BIT6
+#define   EFI_AHCI_PORT_IS_DIS                 BIT7
+#define   EFI_AHCI_PORT_IS_PRCS                BIT22
+#define   EFI_AHCI_PORT_IS_IPMS                BIT23
+#define   EFI_AHCI_PORT_IS_OFS                 BIT24
+#define   EFI_AHCI_PORT_IS_INFS                BIT26
+#define   EFI_AHCI_PORT_IS_IFS                 BIT27
+#define   EFI_AHCI_PORT_IS_HBDS                BIT28
+#define   EFI_AHCI_PORT_IS_HBFS                BIT29
+#define   EFI_AHCI_PORT_IS_TFES                BIT30
+#define   EFI_AHCI_PORT_IS_CPDS                BIT31
+#define   EFI_AHCI_PORT_IS_CLEAR               0xFFFFFFFF
+#define   EFI_AHCI_PORT_IS_FIS_CLEAR           0x0000000F
+
+#define EFI_AHCI_PORT_IE                       0x0014
+#define EFI_AHCI_PORT_CMD                      0x0018
+#define   EFI_AHCI_PORT_CMD_ST_MASK            0xFFFFFFFE
+#define   EFI_AHCI_PORT_CMD_ST                 BIT0
+#define   EFI_AHCI_PORT_CMD_SUD                BIT1
+#define   EFI_AHCI_PORT_CMD_POD                BIT2
+#define   EFI_AHCI_PORT_CMD_COL                BIT3
+#define   EFI_AHCI_PORT_CMD_CR                 BIT15
+#define   EFI_AHCI_PORT_CMD_FRE                BIT4
+#define   EFI_AHCI_PORT_CMD_FR                 BIT14
+#define   EFI_AHCI_PORT_CMD_MASK               ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL)
+#define   EFI_AHCI_PORT_CMD_PMA                BIT17
+#define   EFI_AHCI_PORT_CMD_HPCP               BIT18
+#define   EFI_AHCI_PORT_CMD_MPSP               BIT19
+#define   EFI_AHCI_PORT_CMD_CPD                BIT20
+#define   EFI_AHCI_PORT_CMD_ESP                BIT21
+#define   EFI_AHCI_PORT_CMD_ATAPI              BIT24
+#define   EFI_AHCI_PORT_CMD_DLAE               BIT25
+#define   EFI_AHCI_PORT_CMD_ALPE               BIT26
+#define   EFI_AHCI_PORT_CMD_ASP                BIT27
+#define   EFI_AHCI_PORT_CMD_ICC_MASK           (BIT28 | BIT29 | BIT30 | BIT31)
+#define   EFI_AHCI_PORT_CMD_ACTIVE             (1 << 28 )
+#define EFI_AHCI_PORT_TFD                      0x0020
+#define   EFI_AHCI_PORT_TFD_MASK               (BIT7 | BIT3 | BIT0)
+#define   EFI_AHCI_PORT_TFD_BSY                BIT7
+#define   EFI_AHCI_PORT_TFD_DRQ                BIT3
+#define   EFI_AHCI_PORT_TFD_ERR                BIT0
+#define   EFI_AHCI_PORT_TFD_ERR_MASK           0x00FF00
+#define EFI_AHCI_PORT_SIG                      0x0024
+#define EFI_AHCI_PORT_SSTS                     0x0028
+#define   EFI_AHCI_PORT_SSTS_DET_MASK          0x000F
+#define   EFI_AHCI_PORT_SSTS_DET               0x0001
+#define   EFI_AHCI_PORT_SSTS_DET_PCE           0x0003
+#define   EFI_AHCI_PORT_SSTS_SPD_MASK          0x00F0
+#define EFI_AHCI_PORT_SCTL                     0x002C
+#define   EFI_AHCI_PORT_SCTL_DET_MASK          0x000F
+#define   EFI_AHCI_PORT_SCTL_MASK              (~EFI_AHCI_PORT_SCTL_DET_MASK)
+#define   EFI_AHCI_PORT_SCTL_DET_INIT          0x0001
+#define   EFI_AHCI_PORT_SCTL_DET_PHYCOMM       0x0003
+#define   EFI_AHCI_PORT_SCTL_SPD_MASK          0x00F0
+#define   EFI_AHCI_PORT_SCTL_IPM_MASK          0x0F00
+#define   EFI_AHCI_PORT_SCTL_IPM_INIT          0x0300
+#define   EFI_AHCI_PORT_SCTL_IPM_PSD           0x0100
+#define   EFI_AHCI_PORT_SCTL_IPM_SSD           0x0200
+#define EFI_AHCI_PORT_SERR                     0x0030
+#define   EFI_AHCI_PORT_SERR_RDIE              BIT0
+#define   EFI_AHCI_PORT_SERR_RCE               BIT1
+#define   EFI_AHCI_PORT_SERR_TDIE              BIT8
+#define   EFI_AHCI_PORT_SERR_PCDIE             BIT9
+#define   EFI_AHCI_PORT_SERR_PE                BIT10
+#define   EFI_AHCI_PORT_SERR_IE                BIT11
+#define   EFI_AHCI_PORT_SERR_PRC               BIT16
+#define   EFI_AHCI_PORT_SERR_PIE               BIT17
+#define   EFI_AHCI_PORT_SERR_CW                BIT18
+#define   EFI_AHCI_PORT_SERR_BDE               BIT19
+#define   EFI_AHCI_PORT_SERR_DE                BIT20
+#define   EFI_AHCI_PORT_SERR_CRCE              BIT21
+#define   EFI_AHCI_PORT_SERR_HE                BIT22
+#define   EFI_AHCI_PORT_SERR_LSE               BIT23
+#define   EFI_AHCI_PORT_SERR_TSTE              BIT24
+#define   EFI_AHCI_PORT_SERR_UFT               BIT25
+#define   EFI_AHCI_PORT_SERR_EX                BIT26
+#define   EFI_AHCI_PORT_ERR_CLEAR              0xFFFFFFFF
+#define EFI_AHCI_PORT_SACT                     0x0034
+#define EFI_AHCI_PORT_CI                       0x0038
+#define EFI_AHCI_PORT_SNTF                     0x003C
+
+
+#pragma pack(1)
+//
+// Command List structure includes total 32 entries.
+// The entry Data structure is listed at the following.
+//
+typedef struct {
+  UINT32   AhciCmdCfl:5;      //Command FIS Length
+  UINT32   AhciCmdA:1;        //ATAPI
+  UINT32   AhciCmdW:1;        //Write
+  UINT32   AhciCmdP:1;        //Prefetchable
+  UINT32   AhciCmdR:1;        //Reset
+  UINT32   AhciCmdB:1;        //BIST
+  UINT32   AhciCmdC:1;        //Clear Busy upon R_OK
+  UINT32   AhciCmdRsvd:1;
+  UINT32   AhciCmdPmp:4;      //Port Multiplier Port
+  UINT32   AhciCmdPrdtl:16;   //Physical Region Descriptor Table Length
+  UINT32   AhciCmdPrdbc;      //Physical Region Descriptor Byte Count
+  UINT32   AhciCmdCtba;       //Command Table Descriptor Base Address
+  UINT32   AhciCmdCtbau;      //Command Table Descriptor Base Address Upper 32-BITs
+  UINT32   AhciCmdRsvd1[4];
+} EFI_AHCI_COMMAND_LIST;
+
+//
+// This is a software constructed FIS.
+// For Data transfer operations, this is the H2D Register FIS format as
+// specified in the Serial ATA Revision 2.6 specification.
+//
+typedef struct {
+  UINT8    AhciCFisType;
+  UINT8    AhciCFisPmNum:4;
+  UINT8    AhciCFisRsvd:1;
+  UINT8    AhciCFisRsvd1:1;
+  UINT8    AhciCFisRsvd2:1;
+  UINT8    AhciCFisCmdInd:1;
+  UINT8    AhciCFisCmd;
+  UINT8    AhciCFisFeature;
+  UINT8    AhciCFisSecNum;
+  UINT8    AhciCFisClyLow;
+  UINT8    AhciCFisClyHigh;
+  UINT8    AhciCFisDevHead;
+  UINT8    AhciCFisSecNumExp;
+  UINT8    AhciCFisClyLowExp;
+  UINT8    AhciCFisClyHighExp;
+  UINT8    AhciCFisFeatureExp;
+  UINT8    AhciCFisSecCount;
+  UINT8    AhciCFisSecCountExp;
+  UINT8    AhciCFisRsvd3;
+  UINT8    AhciCFisControl;
+  UINT8    AhciCFisRsvd4[4];
+  UINT8    AhciCFisRsvd5[44];
+} EFI_AHCI_COMMAND_FIS;
+
+//
+// ACMD: ATAPI command (12 or 16 bytes)
+//
+typedef struct {
+  UINT8    AtapiCmd[0x10];
+} EFI_AHCI_ATAPI_COMMAND;
+
+//
+// Physical Region Descriptor Table includes up to 65535 entries
+// The entry Data structure is listed at the following.
+// the actual entry number comes from the PRDTL field in the command
+// list entry for this command slot.
+//
+typedef struct {
+  UINT32   AhciPrdtDba;       //Data Base Address
+  UINT32   AhciPrdtDbau;      //Data Base Address Upper 32-BITs
+  UINT32   AhciPrdtRsvd;
+  UINT32   AhciPrdtDbc:22;    //Data Byte Count
+  UINT32   AhciPrdtRsvd1:9;
+  UINT32   AhciPrdtIoc:1;     //Interrupt on Completion
+} EFI_AHCI_COMMAND_PRDT;
+
+//
+// Command table Data strucute which is pointed to by the entry in the command list
+//
+typedef struct {
+  EFI_AHCI_COMMAND_FIS      CommandFis;       // A software constructed FIS.
+  EFI_AHCI_ATAPI_COMMAND    AtapiCmd;         // 12 or 16 bytes ATAPI cmd.
+  UINT8                     Reserved[0x30];
+  EFI_AHCI_COMMAND_PRDT     PrdtTable;    // The scatter/gather list for Data transfer
+} EFI_AHCI_COMMAND_TABLE;
+
+//
+// Received FIS structure
+//
+typedef struct {
+  UINT8    AhciDmaSetupFis[0x1C];         // Dma Setup Fis: offset 0x00
+  UINT8    AhciDmaSetupFisRsvd[0x04];
+  UINT8    AhciPioSetupFis[0x14];         // Pio Setup Fis: offset 0x20
+  UINT8    AhciPioSetupFisRsvd[0x0C];
+  UINT8    AhciD2HRegisterFis[0x14];      // D2H Register Fis: offset 0x40
+  UINT8    AhciD2HRegisterFisRsvd[0x04];
+  UINT64   AhciSetDeviceBitsFis;          // Set Device Bits Fix: offset 0x58
+  UINT8    AhciUnknownFis[0x40];          // Unkonwn Fis: offset 0x60
+  UINT8    AhciUnknownFisRsvd[0x60];
+} EFI_AHCI_RECEIVED_FIS;
+
+#pragma pack()
+
+typedef struct {
+  EFI_AHCI_RECEIVED_FIS     *AhciRFis;
+  VOID                      *AhciRFisMapping;
+  EFI_AHCI_COMMAND_LIST     *AhciCmdList;
+  VOID                      *AhciCmdListMapping;
+  EFI_AHCI_COMMAND_TABLE    *AhciCommandTable;
+  VOID                      *AhciCommandTableMapping;
+} EFI_AHCI_REGISTERS;
+
+typedef struct {
+  VOID                      *Buffer;
+  VOID                      *BufferMapping;
+  EFI_AHCI_REGISTERS        AhciRegisters;
+  UINT32                    AhciBar;
+} AHCI_CONTEXT;
+
+/**
+  Send Buffer cmd to specific device.
+
+  @param  AhciContext         The pointer to the AHCI_CONTEXT.
+  @param  Port                The number of port.
+  @param  PortMultiplier      The timeout Value of stop.
+  @param  Buffer              The Data Buffer to store IDENTIFY PACKET Data.
+
+  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for executing.
+  @retval EFI_SUCCESS         The cmd executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciIdentify (
+  IN AHCI_CONTEXT             *AhciContext,
+  IN UINT8                    Port,
+  IN UINT8                    PortMultiplier,
+  IN OUT ATA_IDENTIFY_DATA    *Buffer
+  );
+
+/**
+  Allocate transfer-related data struct which is used at AHCI mode.
+
+  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
+
+  @retval EFI_OUT_OF_RESOURCE   No enough resource.
+  @retval EFI_SUCCESS           Successful to allocate resource.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciAllocateResource (
+  IN OUT AHCI_CONTEXT       *AhciContext
+  );
+
+/**
+  Free allocated transfer-related data struct which is used at AHCI mode.
+
+  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
+
+**/
+VOID
+EFIAPI
+AhciFreeResource (
+  IN OUT AHCI_CONTEXT       *AhciContext
+  );
+
+/**
+  Initialize ATA host controller at AHCI mode.
+
+  The function is designed to initialize ATA host controller.
+
+  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.
+  @param[in]  Port          The port number to do initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciModeInitialize (
+  IN AHCI_CONTEXT    *AhciContext,
+  IN UINT8           Port
+  );
+
+typedef struct _EFI_ATA_COMMAND_BLOCK {
+  UINT8 Reserved1[2];
+  UINT8 AtaCommand;
+  UINT8 AtaFeatures;
+  UINT8 AtaSectorNumber;
+  UINT8 AtaCylinderLow;
+  UINT8 AtaCylinderHigh;
+  UINT8 AtaDeviceHead;
+  UINT8 AtaSectorNumberExp;
+  UINT8 AtaCylinderLowExp;
+  UINT8 AtaCylinderHighExp; 
+  UINT8 AtaFeaturesExp;
+  UINT8 AtaSectorCount;
+  UINT8 AtaSectorCountExp;
+  UINT8 Reserved2[6];
+} EFI_ATA_COMMAND_BLOCK;
+
+typedef struct _EFI_ATA_STATUS_BLOCK {
+  UINT8 Reserved1[2];
+  UINT8 AtaStatus;
+  UINT8 AtaError;
+  UINT8 AtaSectorNumber;
+  UINT8 AtaCylinderLow;
+  UINT8 AtaCylinderHigh;
+  UINT8 AtaDeviceHead;
+  UINT8 AtaSectorNumberExp;
+  UINT8 AtaCylinderLowExp;
+  UINT8 AtaCylinderHighExp; 
+  UINT8 Reserved2;
+  UINT8 AtaSectorCount;
+  UINT8 AtaSectorCountExp;
+  UINT8 Reserved3[6];
+} EFI_ATA_STATUS_BLOCK;
+
+/**
+  Start a PIO Data transfer on specific port.
+
+  @param  AhciContext         The pointer to the AHCI_CONTEXT.
+  @param  Port                The number of port.
+  @param  PortMultiplier      The timeout Value of stop.
+  @param  AtapiCommand        The atapi command will be used for the transfer.
+  @param  AtapiCommandLength  The Length of the atapi command.
+  @param  Read                The transfer direction.
+  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
+  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
+  @param  MemoryAddr          The pointer to the Data Buffer.
+  @param  DataCount           The Data count to be transferred.
+  @param  Timeout             The timeout Value of non Data transfer.
+
+  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
+  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciPioTransfer (
+  IN     AHCI_CONTEXT               *AhciContext,
+  IN     UINT8                      Port,
+  IN     UINT8                      PortMultiplier,
+  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
+  IN     UINT8                      AtapiCommandLength,
+  IN     BOOLEAN                    Read,
+  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
+  IN OUT VOID                       *MemoryAddr,
+  IN     UINT32                     DataCount,
+  IN     UINT64                     Timeout
+  );
+
+
+#endif
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
new file mode 100644
index 000000000000..62a71d9f440f
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
@@ -0,0 +1,3003 @@
+/** @file
+  Entrypoint of Opal UEFI Driver and contains all the logic to
+  register for new Opal device instances.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances and installs an
+// HII GUI to manage Opal features if the device is Opal capable
+// If the Opal device is being managed by the UEFI Driver, it shall provide a popup
+// window during boot requesting a user password
+
+#include "OpalDriver.h"
+#include "OpalHii.h"
+
+EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
+EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
+
+BOOLEAN                 mOpalEndOfDxe = FALSE;
+OPAL_REQUEST_VARIABLE   *mOpalRequestVariable = NULL;
+UINTN                   mOpalRequestVariableSize = 0;
+CHAR16                  mPopUpString[256];
+
+typedef struct {
+  UINT32                   Address;
+  S3_BOOT_SCRIPT_LIB_WIDTH Width;
+} OPAL_HC_PCI_REGISTER_SAVE;
+
+//
+// To unlock the Intel SATA controller at S3 Resume, restored the following registers.
+//
+const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {
+  {0x9,  S3BootScriptWidthUint8},
+  {0x10, S3BootScriptWidthUint32},
+  {0x14, S3BootScriptWidthUint32},
+  {0x18, S3BootScriptWidthUint32},
+  {0x1C, S3BootScriptWidthUint32},
+  {0x20, S3BootScriptWidthUint32},
+  {0x24, S3BootScriptWidthUint32},
+  {0x3c, S3BootScriptWidthUint8},
+  {0x3d, S3BootScriptWidthUint8},
+  {0x40, S3BootScriptWidthUint16},
+  {0x42, S3BootScriptWidthUint16},
+  {0x92, S3BootScriptWidthUint16},
+  {0x94, S3BootScriptWidthUint32},
+  {0x9C, S3BootScriptWidthUint32},
+  {0x4,  S3BootScriptWidthUint16},
+};
+
+OPAL_DRIVER mOpalDriver;
+
+//
+// Globals
+//
+EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {
+  OpalEfiDriverBindingSupported,
+  OpalEfiDriverBindingStart,
+  OpalEfiDriverBindingStop,
+  0x1b,
+  NULL,
+  NULL
+};
+
+/**
+
+  The function determines the available actions for the OPAL_DISK provided.
+
+  @param[in]   SupportedAttributes   The supported attributes for the device.
+  @param[in]   LockingFeature        The locking status for the device.
+  @param[in]   OwnerShip             The ownership for the device.
+  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate disk actions.
+
+**/
+TCG_RESULT
+EFIAPI
+OpalSupportGetAvailableActions(
+  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
+  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
+  IN  UINT16                           OwnerShip,
+  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
+  )
+{
+  BOOLEAN ExistingPassword;
+
+  NULL_CHECK(AvalDiskActions);
+
+  AvalDiskActions->AdminPass = 1;
+  AvalDiskActions->UserPass = 0;
+  AvalDiskActions->DisableUser = 0;
+  AvalDiskActions->Unlock = 0;
+
+  //
+  // Revert is performed on locking sp, so only allow if locking sp is enabled
+  //
+  if (LockingFeature->LockingEnabled) {
+    AvalDiskActions->Revert = 1;
+  }
+
+  //
+  // Psid revert is available for any device with media encryption support
+  // Revert is allowed for any device with media encryption support, however it requires
+  //
+  if (SupportedAttributes->MediaEncryption) {
+
+    //
+    // Only allow psid revert if media encryption is enabled.
+    // Otherwise, someone who steals a disk can psid revert the disk and the user Data is still
+    // intact and accessible
+    //
+    AvalDiskActions->PsidRevert = 1;
+    AvalDiskActions->RevertKeepDataForced = 0;
+
+    //
+    // Secure erase is performed by generating a new encryption key
+    // this is only available if encryption is supported
+    //
+    AvalDiskActions->SecureErase = 1;
+  } else {
+    AvalDiskActions->PsidRevert = 0;
+    AvalDiskActions->SecureErase = 0;
+
+    //
+    // If no media encryption is supported, then a revert (using password) will not
+    // erase the Data (since you can't generate a new encryption key)
+    //
+    AvalDiskActions->RevertKeepDataForced = 1;
+  }
+
+  if (LockingFeature->Locked) {
+    AvalDiskActions->Unlock = 1;
+  } else {
+    AvalDiskActions->Unlock = 0;
+  }
+
+  //
+  // Only allow user to set password if an admin password exists
+  //
+  ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip, LockingFeature);
+  AvalDiskActions->UserPass = ExistingPassword;
+
+  //
+  // This will still show up even if there isn't a user, which is fine
+  //
+  AvalDiskActions->DisableUser = ExistingPassword;
+
+  return TcgResultSuccess;
+}
+
+/**
+  Enable Opal Feature for the input device.
+
+  @param[in]      Session            The opal session for the opal device.
+  @param[in]      Msid               Msid
+  @param[in]      MsidLength         Msid Length
+  @param[in]      Password           Admin password
+  @param[in]      PassLength         Length of password in bytes
+
+**/
+TCG_RESULT
+EFIAPI
+OpalSupportEnableOpalFeature (
+  IN OPAL_SESSION              *Session,
+  IN VOID                      *Msid,
+  IN UINT32                    MsidLength,
+  IN VOID                      *Password,
+  IN UINT32                    PassLength
+  )
+{
+  TCG_RESULT   Ret;
+
+  NULL_CHECK(Session);
+  NULL_CHECK(Msid);
+  NULL_CHECK(Password);
+
+  Ret = OpalUtilSetAdminPasswordAsSid(
+                          Session,
+                          Msid,
+                          MsidLength,
+                          Password,
+                          PassLength
+                          );
+  if (Ret == TcgResultSuccess) {
+    //
+    // Enable global locking range
+    //
+    Ret = OpalUtilSetOpalLockingRange(
+                              Session,
+                              Password,
+                              PassLength,
+                              OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,
+                              0,
+                              0,
+                              TRUE,
+                              TRUE,
+                              FALSE,
+                              FALSE
+                              );
+  }
+
+  return Ret;
+}
+
+/**
+  Update password for the Opal disk.
+
+  @param[in, out] OpalDisk          The disk to update password.
+  @param[in]      Password          The input password.
+  @param[in]      PasswordLength    The input password length.
+
+**/
+VOID
+OpalSupportUpdatePassword (
+  IN OUT OPAL_DISK      *OpalDisk,
+  IN VOID               *Password,
+  IN UINT32             PasswordLength
+  )
+{
+  CopyMem (OpalDisk->Password, Password, PasswordLength);
+  OpalDisk->PasswordLength = (UINT8) PasswordLength;
+}
+
+/**
+  Extract device info from the device path.
+
+  @param[in]  DevicePath        Device path info for the device.
+  @param[out] DevInfoLength     Device information length needed.
+  @param[out] DevInfo           Device information extracted.
+
+  @return Device type.
+
+**/
+UINT8
+ExtractDeviceInfoFromDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+  OUT UINT16                    *DevInfoLength,
+  OUT OPAL_DEVICE_COMMON        *DevInfo OPTIONAL
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath;
+  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath2;
+  PCI_DEVICE_PATH               *PciDevPath;
+  UINT8                         DeviceType;
+  UINT8                         BusNum;
+  OPAL_PCI_DEVICE               *PciDevice;
+  OPAL_DEVICE_ATA               *DevInfoAta;
+  OPAL_DEVICE_NVME              *DevInfoNvme;
+  SATA_DEVICE_PATH              *SataDevPath;
+  NVME_NAMESPACE_DEVICE_PATH    *NvmeDevPath;
+
+  ASSERT (DevicePath != NULL);
+  ASSERT (DevInfoLength != NULL);
+
+  DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;
+  *DevInfoLength = 0;
+
+  TmpDevPath = DevicePath;
+
+  //
+  // Get device type.
+  //
+  while (!IsDevicePathEnd (TmpDevPath)) {
+    if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {
+      //
+      // SATA
+      //
+      if (DevInfo != NULL) {
+        SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;
+        DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
+        DevInfoAta->Port = SataDevPath->HBAPortNumber;
+        DevInfoAta->PortMultiplierPort = SataDevPath->PortMultiplierPortNumber;
+      }
+      DeviceType = OPAL_DEVICE_TYPE_ATA;
+      *DevInfoLength = sizeof (OPAL_DEVICE_ATA);
+      break;
+    } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {
+      //
+      // NVMe
+      //
+      if (DevInfo != NULL) {
+        NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;
+        DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
+        DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;
+      }
+      DeviceType = OPAL_DEVICE_TYPE_NVME;
+      *DevInfoLength = sizeof (OPAL_DEVICE_NVME);
+      break;
+    }
+    TmpDevPath = NextDevicePathNode (TmpDevPath);
+  }
+
+  //
+  // Get device info.
+  //
+  BusNum = 0;
+  TmpDevPath = DevicePath;
+  TmpDevPath2 = NextDevicePathNode (DevicePath);
+  while (!IsDevicePathEnd (TmpDevPath2)) {
+    if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {
+      PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
+      if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||
+          (TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {
+        if (DevInfo != NULL) {
+          PciDevice = &DevInfo->Device;
+          PciDevice->Segment = 0;
+          PciDevice->Bus = BusNum;
+          PciDevice->Device = PciDevPath->Device;
+          PciDevice->Function = PciDevPath->Function;
+        }
+      } else {
+        if (DevInfo != NULL) {
+          PciDevice = (OPAL_PCI_DEVICE *) ((UINTN) DevInfo + *DevInfoLength);
+          PciDevice->Segment = 0;
+          PciDevice->Bus = BusNum;
+          PciDevice->Device = PciDevPath->Device;
+          PciDevice->Function = PciDevPath->Function;
+        }
+        *DevInfoLength += sizeof (OPAL_PCI_DEVICE);
+        if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {
+          BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
+        }
+      }
+    }
+
+    TmpDevPath  = NextDevicePathNode (TmpDevPath);
+    TmpDevPath2 = NextDevicePathNode (TmpDevPath2);
+  }
+
+  ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);
+  return DeviceType;
+}
+
+/**
+  Save boot script for ATA OPAL device.
+
+  @param[in] DevInfo    Pointer to ATA Opal device information.
+
+ **/
+VOID
+OpalDeviceAtaSaveBootScript (
+  IN OPAL_DEVICE_ATA    *DevInfo
+  )
+{
+  UINTN                         Bus;
+  UINTN                         Device;
+  UINTN                         Function;
+  UINTN                         Index;
+  EFI_STATUS                    Status;
+  UINTN                         Offset;
+  UINT64                        Address;
+  S3_BOOT_SCRIPT_LIB_WIDTH      Width;
+  UINT32                        Data;
+  OPAL_HC_PCI_REGISTER_SAVE     *HcRegisterSaveListPtr;
+  UINTN                         Count;
+
+  Data = 0;
+
+  Bus        = DevInfo->Device.Bus;
+  Device     = DevInfo->Device.Device;
+  Function   = DevInfo->Device.Function;
+
+  HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;
+  Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);
+
+  for (Index = 0; Index < Count; Index++) {
+    Offset  = HcRegisterSaveListPtr[Index].Address;
+    Width   = HcRegisterSaveListPtr[Index].Width;
+
+    switch (Width) {
+      case S3BootScriptWidthUint8:
+        Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
+        break;
+      case S3BootScriptWidthUint16:
+        Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
+        break;
+      case S3BootScriptWidthUint32:
+        Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
+        break;
+      default:
+        ASSERT (FALSE);
+        break;
+    }
+
+    Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);
+    Status  = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
+    ASSERT_EFI_ERROR (Status);
+  }
+}
+
+/**
+  Build ATA OPAL device info and save them to LockBox.
+
+  @param[in] BarAddr    Bar address allocated.
+
+ **/
+VOID
+BuildOpalDeviceInfoAta (
+  IN UINT32     BarAddr
+  )
+{
+  EFI_STATUS            Status;
+  UINT8                 DeviceType;
+  OPAL_DEVICE_ATA       *DevInfoAta;
+  OPAL_DEVICE_ATA       *TempDevInfoAta;
+  UINTN                 DevInfoLengthAta;
+  UINT16                DevInfoLength;
+  OPAL_DRIVER_DEVICE    *TmpDev;
+
+  //
+  // Build ATA OPAL device info and save them to LockBox.
+  //
+  DevInfoLengthAta = 0;
+  TmpDev = mOpalDriver.DeviceList;
+  while (TmpDev != NULL) {
+    DeviceType = ExtractDeviceInfoFromDevicePath (
+                   TmpDev->OpalDisk.OpalDevicePath,
+                   &DevInfoLength,
+                   NULL
+                   );
+    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
+      DevInfoLengthAta += DevInfoLength;
+    }
+
+    TmpDev = TmpDev->Next;
+  }
+
+  if (DevInfoLengthAta == 0) {
+    return;
+  }
+
+  DevInfoAta = AllocateZeroPool (DevInfoLengthAta);
+  ASSERT (DevInfoAta != NULL);
+
+  TempDevInfoAta = DevInfoAta;
+  TmpDev = mOpalDriver.DeviceList;
+  while (TmpDev != NULL) {
+    DeviceType = ExtractDeviceInfoFromDevicePath (
+                   TmpDev->OpalDisk.OpalDevicePath,
+                   &DevInfoLength,
+                   NULL
+                   );
+    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
+      ExtractDeviceInfoFromDevicePath (
+        TmpDev->OpalDisk.OpalDevicePath,
+        &DevInfoLength,
+        (OPAL_DEVICE_COMMON *) TempDevInfoAta
+        );
+      TempDevInfoAta->Length = DevInfoLength;
+      TempDevInfoAta->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
+      TempDevInfoAta->BarAddr = BarAddr;
+      CopyMem (
+        TempDevInfoAta->Password,
+        TmpDev->OpalDisk.Password,
+        TmpDev->OpalDisk.PasswordLength
+        );
+      TempDevInfoAta->PasswordLength = TmpDev->OpalDisk.PasswordLength;
+      OpalDeviceAtaSaveBootScript (TempDevInfoAta);
+      TempDevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) TempDevInfoAta + DevInfoLength);
+    }
+
+    TmpDev = TmpDev->Next;
+  }
+
+  Status = SaveLockBox (
+             &mOpalDeviceAtaGuid,
+             DevInfoAta,
+             DevInfoLengthAta
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = SetLockBoxAttributes (
+             &mOpalDeviceAtaGuid,
+             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  ZeroMem (DevInfoAta, DevInfoLengthAta);
+  FreePool (DevInfoAta);
+}
+
+/**
+  Build NVMe OPAL device info and save them to LockBox.
+
+  @param[in] BarAddr    Bar address allocated.
+
+ **/
+VOID
+BuildOpalDeviceInfoNvme (
+  IN UINT32     BarAddr
+  )
+{
+  EFI_STATUS            Status;
+  UINT8                 DeviceType;
+  OPAL_DEVICE_NVME      *DevInfoNvme;
+  OPAL_DEVICE_NVME      *TempDevInfoNvme;
+  UINTN                 DevInfoLengthNvme;
+  UINT16                DevInfoLength;
+  OPAL_DRIVER_DEVICE    *TmpDev;
+
+  //
+  // Build NVMe OPAL device info and save them to LockBox.
+  //
+  DevInfoLengthNvme = 0;
+  TmpDev = mOpalDriver.DeviceList;
+  while (TmpDev != NULL) {
+    DeviceType = ExtractDeviceInfoFromDevicePath (
+                   TmpDev->OpalDisk.OpalDevicePath,
+                   &DevInfoLength,
+                   NULL
+                   );
+    if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
+      DevInfoLengthNvme += DevInfoLength;
+    }
+
+    TmpDev = TmpDev->Next;
+  }
+
+  if (DevInfoLengthNvme == 0) {
+    return;
+  }
+
+  DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);
+  ASSERT (DevInfoNvme != NULL);
+
+  TempDevInfoNvme = DevInfoNvme;
+  TmpDev = mOpalDriver.DeviceList;
+  while (TmpDev != NULL) {
+    DeviceType = ExtractDeviceInfoFromDevicePath (
+                   TmpDev->OpalDisk.OpalDevicePath,
+                   &DevInfoLength,
+                   NULL
+                   );
+    if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
+      ExtractDeviceInfoFromDevicePath (
+        TmpDev->OpalDisk.OpalDevicePath,
+        &DevInfoLength,
+        (OPAL_DEVICE_COMMON *) TempDevInfoNvme
+        );
+      TempDevInfoNvme->Length = DevInfoLength;
+      TempDevInfoNvme->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
+      TempDevInfoNvme->BarAddr = BarAddr;
+      CopyMem (
+        TempDevInfoNvme->Password,
+        TmpDev->OpalDisk.Password,
+        TmpDev->OpalDisk.PasswordLength
+        );
+      TempDevInfoNvme->PasswordLength = TmpDev->OpalDisk.PasswordLength;
+      TempDevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) TempDevInfoNvme + DevInfoLength);
+    }
+
+    TmpDev = TmpDev->Next;
+  }
+
+  Status = SaveLockBox (
+             &mOpalDeviceNvmeGuid,
+             DevInfoNvme,
+             DevInfoLengthNvme
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = SetLockBoxAttributes (
+             &mOpalDeviceNvmeGuid,
+             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  ZeroMem (DevInfoNvme, DevInfoLengthNvme);
+  FreePool (DevInfoNvme);
+}
+
+/**
+  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OpalEndOfDxeEventNotify (
+  EFI_EVENT                               Event,
+  VOID                                    *Context
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  Address;
+  UINT64                Length;
+  OPAL_DRIVER_DEVICE    *TmpDev;
+
+  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
+
+  mOpalEndOfDxe = TRUE;
+
+  if (mOpalRequestVariable != NULL) {
+    //
+    // Free the OPAL request variable buffer here
+    // as the OPAL requests should have been processed.
+    //
+    FreePool (mOpalRequestVariable);
+    mOpalRequestVariable = NULL;
+    mOpalRequestVariableSize = 0;
+  }
+
+  //
+  // Assume 64K size and alignment are enough.
+  //
+  Length = 0x10000;
+  Address = 0xFFFFFFFF;
+  Status = gDS->AllocateMemorySpace (
+                  EfiGcdAllocateMaxAddressSearchBottomUp,
+                  EfiGcdMemoryTypeMemoryMappedIo,
+                  16,                             // 2^16: 64K Alignment
+                  Length,
+                  &Address,
+                  gImageHandle,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  BuildOpalDeviceInfoAta ((UINT32) Address);
+  BuildOpalDeviceInfoNvme ((UINT32) Address);
+
+  //
+  // Zero passsword.
+  //
+  TmpDev = mOpalDriver.DeviceList;
+  while (TmpDev != NULL) {
+    ZeroMem (TmpDev->OpalDisk.Password, TmpDev->OpalDisk.PasswordLength);
+    TmpDev = TmpDev->Next;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
+
+  gBS->CloseEvent (Event);
+}
+
+/**
+  Get Psid input from the popup window.
+
+  @param[in]  Dev           The device which need Psid to process Psid Revert
+                            OPAL request.
+  @param[in]  PopUpString   Pop up string.
+  @param[out] PressEsc      Whether user escape function through Press ESC.
+
+  @retval Password string if success. NULL if failed.
+
+**/
+CHAR8 *
+OpalDriverPopUpPsidInput (
+  IN OPAL_DRIVER_DEVICE     *Dev,
+  IN CHAR16                 *PopUpString,
+  OUT BOOLEAN               *PressEsc
+  )
+{
+  EFI_INPUT_KEY             InputKey;
+  UINTN                     InputLength;
+  CHAR16                    Mask[PSID_CHARACTER_LENGTH + 1];
+  CHAR16                    Unicode[PSID_CHARACTER_LENGTH + 1];
+  CHAR8                     *Ascii;
+
+  ZeroMem(Unicode, sizeof(Unicode));
+  ZeroMem(Mask, sizeof(Mask));
+
+  *PressEsc = FALSE;
+
+  gST->ConOut->ClearScreen(gST->ConOut);
+
+  InputLength = 0;
+  while (TRUE) {
+    Mask[InputLength] = L'_';
+    CreatePopUp (
+      EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+      &InputKey,
+      PopUpString,
+      L"---------------------",
+      Mask,
+      NULL
+    );
+
+    //
+    // Check key.
+    //
+    if (InputKey.ScanCode == SCAN_NULL) {
+      //
+      // password finished
+      //
+      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+        //
+        // Add the null terminator.
+        //
+        Unicode[InputLength] = 0;
+        Mask[InputLength] = 0;
+        break;
+      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
+                 (InputKey.UnicodeChar == CHAR_TAB) ||
+                 (InputKey.UnicodeChar == CHAR_LINEFEED)
+                ) {
+        continue;
+      } else {
+        //
+        // delete last key entered
+        //
+        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
+          if (InputLength > 0) {
+            Unicode[InputLength] = 0;
+            Mask[InputLength] = 0;
+            InputLength--;
+          }
+        } else {
+          //
+          // add Next key entry
+          //
+          Unicode[InputLength] = InputKey.UnicodeChar;
+          Mask[InputLength] = InputKey.UnicodeChar;
+          InputLength++;
+          if (InputLength == PSID_CHARACTER_LENGTH) {
+            //
+            // Add the null terminator.
+            //
+            Unicode[InputLength] = 0;
+            Mask[InputLength] = 0;
+            break;
+          }
+        }
+      }
+    }
+
+    //
+    // exit on ESC
+    //
+    if (InputKey.ScanCode == SCAN_ESC) {
+      *PressEsc = TRUE;
+      break;
+    }
+  }
+
+  gST->ConOut->ClearScreen(gST->ConOut);
+
+  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
+    return NULL;
+  }
+
+  Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);
+  if (Ascii == NULL) {
+    ZeroMem (Unicode, sizeof (Unicode));
+    ZeroMem (Mask, sizeof (Mask));
+    return NULL;
+  }
+
+  UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);
+  ZeroMem (Unicode, sizeof (Unicode));
+  ZeroMem (Mask, sizeof (Mask));
+
+  return Ascii;
+}
+
+
+/**
+  Get password input from the popup window.
+
+  @param[in]  Dev           The device which need password to unlock or
+                            process OPAL request.
+  @param[in]  PopUpString1  Pop up string 1.
+  @param[in]  PopUpString2  Pop up string 2.
+  @param[out] PressEsc      Whether user escape function through Press ESC.
+
+  @retval Password string if success. NULL if failed.
+
+**/
+CHAR8 *
+OpalDriverPopUpPasswordInput (
+  IN OPAL_DRIVER_DEVICE     *Dev,
+  IN CHAR16                 *PopUpString1,
+  IN CHAR16                 *PopUpString2,
+  OUT BOOLEAN               *PressEsc
+  )
+{
+  EFI_INPUT_KEY             InputKey;
+  UINTN                     InputLength;
+  CHAR16                    Mask[MAX_PASSWORD_SIZE + 1];
+  CHAR16                    Unicode[MAX_PASSWORD_SIZE + 1];
+  CHAR8                     *Ascii;
+
+  ZeroMem(Unicode, sizeof(Unicode));
+  ZeroMem(Mask, sizeof(Mask));
+
+  *PressEsc = FALSE;
+
+  gST->ConOut->ClearScreen(gST->ConOut);
+
+  InputLength = 0;
+  while (TRUE) {
+    Mask[InputLength] = L'_';
+    if (PopUpString2 == NULL) {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &InputKey,
+        PopUpString1,
+        L"---------------------",
+        Mask,
+        NULL
+      );
+    } else {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &InputKey,
+        PopUpString1,
+        PopUpString2,
+        L"---------------------",
+        Mask,
+        NULL
+      );
+    }
+
+    //
+    // Check key.
+    //
+    if (InputKey.ScanCode == SCAN_NULL) {
+      //
+      // password finished
+      //
+      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+        //
+        // Add the null terminator.
+        //
+        Unicode[InputLength] = 0;
+        Mask[InputLength] = 0;
+        break;
+      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
+                 (InputKey.UnicodeChar == CHAR_TAB) ||
+                 (InputKey.UnicodeChar == CHAR_LINEFEED)
+                ) {
+        continue;
+      } else {
+        //
+        // delete last key entered
+        //
+        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
+          if (InputLength > 0) {
+            Unicode[InputLength] = 0;
+            Mask[InputLength] = 0;
+            InputLength--;
+          }
+        } else {
+          //
+          // add Next key entry
+          //
+          Unicode[InputLength] = InputKey.UnicodeChar;
+          Mask[InputLength] = L'*';
+          InputLength++;
+          if (InputLength == MAX_PASSWORD_SIZE) {
+            //
+            // Add the null terminator.
+            //
+            Unicode[InputLength] = 0;
+            Mask[InputLength] = 0;
+            break;
+          }
+        }
+      }
+    }
+
+    //
+    // exit on ESC
+    //
+    if (InputKey.ScanCode == SCAN_ESC) {
+      *PressEsc = TRUE;
+      break;
+    }
+  }
+
+  gST->ConOut->ClearScreen(gST->ConOut);
+
+  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
+    return NULL;
+  }
+
+  Ascii = AllocateZeroPool (MAX_PASSWORD_SIZE + 1);
+  if (Ascii == NULL) {
+    ZeroMem (Unicode, sizeof (Unicode));
+    return NULL;
+  }
+
+  UnicodeStrToAsciiStrS (Unicode, Ascii, MAX_PASSWORD_SIZE + 1);
+  ZeroMem (Unicode, sizeof (Unicode));
+
+  return Ascii;
+}
+
+/**
+  Check if disk is locked, show popup window and ask for password if it is.
+
+  @param[in] Dev            The device which need to be unlocked.
+  @param[in] RequestString  Request string.
+
+**/
+CHAR16 *
+OpalGetPopUpString (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINTN                 StrLength;
+
+  StrLength = StrLen (RequestString) + 1 + MAX (StrLen (Dev->Name16), StrLen (L"Disk"));
+  ASSERT (StrLength < sizeof (mPopUpString) / sizeof (CHAR16));
+
+  if (Dev->Name16 == NULL) {
+    UnicodeSPrint (mPopUpString, StrLength + 1, L"%s Disk", RequestString);
+  } else {
+    UnicodeSPrint (mPopUpString, StrLength + 1, L"%s %s", RequestString, Dev->Name16);
+  }
+
+  return mPopUpString;
+}
+
+/**
+  Check if disk is locked, show popup window and ask for password if it is.
+
+  @param[in] Dev            The device which need to be unlocked.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+OpalDriverRequestPassword (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  BOOLEAN               IsEnabled;
+  BOOLEAN               IsLocked;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
+  if (IsEnabled) {
+    ZeroMem(&Session, sizeof(Session));
+    Session.Sscp = Dev->OpalDisk.Sscp;
+    Session.MediaId = Dev->OpalDisk.MediaId;
+    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+    IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
+
+    while (Count < MAX_PASSWORD_TRY_COUNT) {
+      Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);
+      if (PressEsc) {
+        if (IsLocked) {
+          //
+          // Current device in the lock status and
+          // User not input password and press ESC,
+          // keep device in lock status and continue boot.
+          //
+          do {
+            CreatePopUp (
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+              &Key,
+              L"Press ENTER to skip the request and continue boot,",
+              L"Press ESC to input password again",
+              NULL
+              );
+          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+            gST->ConOut->ClearScreen(gST->ConOut);
+            //
+            // Keep lock and continue boot.
+            //
+            return;
+          } else {
+            //
+            // Let user input password again.
+            //
+            continue;
+          }
+        } else {
+          //
+          // Current device in the unlock status and
+          // User not input password and press ESC,
+          // Shutdown the device.
+          //
+          do {
+            CreatePopUp (
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+              &Key,
+              L"Press ENTER to shutdown, Press ESC to input password again",
+              NULL
+              );
+          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+          } else {
+            //
+            // Let user input password again.
+            //
+            continue;
+          }
+        }
+      }
+
+      if (Password == NULL) {
+        Count ++;
+        continue;
+      }
+      PasswordLen = (UINT32) AsciiStrLen(Password);
+
+      if (IsLocked) {
+        Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);
+      } else {
+        Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, TRUE, TRUE);
+        if (Ret == TcgResultSuccess) {
+          Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);
+        }
+      }
+
+      if (Ret == TcgResultSuccess) {
+        OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+        DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+      } else {
+        DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+      }
+
+      if (Password != NULL) {
+        ZeroMem (Password, PasswordLen);
+        FreePool (Password);
+      }
+
+      if (Ret == TcgResultSuccess) {
+        break;
+      }
+
+      Count++;
+
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"Invalid password.",
+          L"Press ENTER to retry",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    }
+
+    if (Count >= MAX_PASSWORD_TRY_COUNT) {
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"Opal password retry count exceeds the limit. Must shutdown!",
+          L"Press ENTER to shutdown",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+      gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+    }
+  }
+}
+
+/**
+  Process Enable Feature OPAL request.
+
+  @param[in] Dev            The device which has Enable Feature OPAL request.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestEnableFeature (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  CHAR8                 *PasswordConfirm;
+  UINT32                PasswordLenConfirm;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = Dev->OpalDisk.Sscp;
+  Session.MediaId = Dev->OpalDisk.MediaId;
+  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+  while (Count < MAX_PASSWORD_TRY_COUNT) {
+    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input password again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input password again.
+          //
+          continue;
+        }
+    }
+
+    if (Password == NULL) {
+      Count ++;
+      continue;
+    }
+    PasswordLen = (UINT32) AsciiStrLen(Password);
+
+    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);
+    if (PasswordConfirm == NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+      Count ++;
+      continue;
+    }
+    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
+    if ((PasswordLen != PasswordLenConfirm) ||
+        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+      ZeroMem (PasswordConfirm, PasswordLenConfirm);
+      FreePool (PasswordConfirm);
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"Passwords are not the same.",
+          L"Press ENTER to retry",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+      Count ++;
+      continue;
+    }
+
+    if (PasswordConfirm != NULL) {
+      ZeroMem (PasswordConfirm, PasswordLenConfirm);
+      FreePool (PasswordConfirm);
+    }
+
+    Ret = OpalSupportEnableOpalFeature (&Session, Dev->OpalDisk.Msid,  Dev->OpalDisk.MsidLength, Password, PasswordLen);
+    if (Ret == TcgResultSuccess) {
+      OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (Password != NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PASSWORD_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal password retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process Disable User OPAL request.
+
+  @param[in] Dev            The device which has Disable User OPAL request.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestDisableUser (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  BOOLEAN               PasswordFailed;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = Dev->OpalDisk.Sscp;
+  Session.MediaId = Dev->OpalDisk.MediaId;
+  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+  while (Count < MAX_PASSWORD_TRY_COUNT) {
+    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input password again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input password again.
+          //
+          continue;
+        }
+    }
+
+    if (Password == NULL) {
+      Count ++;
+      continue;
+    }
+    PasswordLen = (UINT32) AsciiStrLen(Password);
+
+    Ret = OpalUtilDisableUser(&Session, Password, PasswordLen, &PasswordFailed);
+    if (Ret == TcgResultSuccess) {
+      OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (Password != NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Invalid password, request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PASSWORD_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal password retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process Psid Revert OPAL request.
+
+  @param[in] Dev            The device which has Psid Revert OPAL request.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestPsidRevert (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *Psid;
+  UINT32                PsidLen;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = Dev->OpalDisk.Sscp;
+  Session.MediaId = Dev->OpalDisk.MediaId;
+  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+  while (Count < MAX_PSID_TRY_COUNT) {
+    Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input Psid again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input Psid again.
+          //
+          continue;
+        }
+    }
+
+    if (Psid == NULL) {
+      Count ++;
+      continue;
+    }
+    PsidLen = (UINT32) AsciiStrLen(Psid);
+
+    Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);
+    if (Ret == TcgResultSuccess) {
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (Psid != NULL) {
+      ZeroMem (Psid, PsidLen);
+      FreePool (Psid);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Invalid Psid, request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PSID_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal Psid retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process Admin Revert OPAL request.
+
+  @param[in] Dev            The device which has Revert OPAL request.
+  @param[in] KeepUserData   Whether to keep user data or not.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestRevert (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN BOOLEAN            KeepUserData,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  BOOLEAN               PasswordFailed;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = Dev->OpalDisk.Sscp;
+  Session.MediaId = Dev->OpalDisk.MediaId;
+  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+  while (Count < MAX_PASSWORD_TRY_COUNT) {
+    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input password again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input password again.
+          //
+          continue;
+        }
+    }
+
+    if (Password == NULL) {
+      Count ++;
+      continue;
+    }
+    PasswordLen = (UINT32) AsciiStrLen(Password);
+
+    if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&
+        (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {
+      //
+      // For pyrite type device which does not support media encryption,
+      // it does not accept "Keep User Data" parameter.
+      // So here hardcode a FALSE for this case.
+      //
+      Ret = OpalUtilRevert(
+              &Session,
+              FALSE,
+              Password,
+              PasswordLen,
+              &PasswordFailed,
+              Dev->OpalDisk.Msid,
+              Dev->OpalDisk.MsidLength
+              );
+    } else {
+      Ret = OpalUtilRevert(
+              &Session,
+              KeepUserData,
+              Password,
+              PasswordLen,
+              &PasswordFailed,
+              Dev->OpalDisk.Msid,
+              Dev->OpalDisk.MsidLength
+              );
+    }
+    if (Ret == TcgResultSuccess) {
+      OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (Password != NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Invalid password, request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PASSWORD_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal password retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process Secure Erase OPAL request.
+
+  @param[in] Dev            The device which has Secure Erase OPAL request.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestSecureErase (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  BOOLEAN               PasswordFailed;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = Dev->OpalDisk.Sscp;
+  Session.MediaId = Dev->OpalDisk.MediaId;
+  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+  while (Count < MAX_PASSWORD_TRY_COUNT) {
+    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input password again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input password again.
+          //
+          continue;
+        }
+    }
+
+    if (Password == NULL) {
+      Count ++;
+      continue;
+    }
+    PasswordLen = (UINT32) AsciiStrLen(Password);
+
+    Ret = OpalUtilSecureErase(&Session, Password, PasswordLen, &PasswordFailed);
+    if (Ret == TcgResultSuccess) {
+      OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (Password != NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Invalid password, request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PASSWORD_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal password retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process Set Admin Pwd OPAL request.
+
+  @param[in] Dev            The device which has Set Admin Pwd Feature OPAL request.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestSetUserPwd (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *OldPassword;
+  UINT32                OldPasswordLen;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  CHAR8                 *PasswordConfirm;
+  UINT32                PasswordLenConfirm;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  while (Count < MAX_PASSWORD_TRY_COUNT) {
+    OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input password again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input password again.
+          //
+          continue;
+        }
+    }
+
+    if (OldPassword == NULL) {
+      Count ++;
+      continue;
+    }
+    OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
+
+    ZeroMem(&Session, sizeof(Session));
+    Session.Sscp = Dev->OpalDisk.Sscp;
+    Session.MediaId = Dev->OpalDisk.MediaId;
+    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+    Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_USER1_AUTHORITY);
+    if (Ret == TcgResultSuccess) {
+      DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));
+    } else {
+      Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
+      if (Ret == TcgResultSuccess) {
+        DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));
+      } else {
+        ZeroMem (OldPassword, OldPasswordLen);
+        FreePool (OldPassword);
+        DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Incorrect password.",
+            L"Press ENTER to retry",
+            NULL
+            );
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+        Count ++;
+        continue;
+      }
+    }
+
+    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);
+    if (Password == NULL) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      Count ++;
+      continue;
+    }
+    PasswordLen = (UINT32) AsciiStrLen(Password);
+
+    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);
+    if (PasswordConfirm == NULL) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+      Count ++;
+      continue;
+    }
+    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
+    if ((PasswordLen != PasswordLenConfirm) ||
+        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+      ZeroMem (PasswordConfirm, PasswordLenConfirm);
+      FreePool (PasswordConfirm);
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"Passwords are not the same.",
+          L"Press ENTER to retry",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+      Count ++;
+      continue;
+    }
+
+    if (PasswordConfirm != NULL) {
+      ZeroMem (PasswordConfirm, PasswordLenConfirm);
+      FreePool (PasswordConfirm);
+    }
+
+    ZeroMem(&Session, sizeof(Session));
+    Session.Sscp = Dev->OpalDisk.Sscp;
+    Session.MediaId = Dev->OpalDisk.MediaId;
+    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+    Ret = OpalUtilSetUserPassword(
+            &Session,
+            OldPassword,
+            OldPasswordLen,
+            Password,
+            PasswordLen
+            );
+    if (Ret == TcgResultSuccess) {
+      OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (OldPassword != NULL) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+    }
+
+    if (Password != NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PASSWORD_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal password retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process Set Admin Pwd OPAL request.
+
+  @param[in] Dev            The device which has Set Admin Pwd Feature OPAL request.
+  @param[in] RequestString  Request string.
+
+**/
+VOID
+ProcessOpalRequestSetAdminPwd (
+  IN OPAL_DRIVER_DEVICE *Dev,
+  IN CHAR16             *RequestString
+  )
+{
+  UINT8                 Count;
+  CHAR8                 *OldPassword;
+  UINT32                OldPasswordLen;
+  CHAR8                 *Password;
+  UINT32                PasswordLen;
+  CHAR8                 *PasswordConfirm;
+  UINT32                PasswordLenConfirm;
+  OPAL_SESSION          Session;
+  BOOLEAN               PressEsc;
+  EFI_INPUT_KEY         Key;
+  TCG_RESULT            Ret;
+  CHAR16                *PopUpString;
+
+  if (Dev == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
+
+  PopUpString = OpalGetPopUpString (Dev, RequestString);
+
+  Count = 0;
+
+  while (Count < MAX_PASSWORD_TRY_COUNT) {
+    OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);
+    if (PressEsc) {
+        do {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"Press ENTER to skip the request and continue boot,",
+            L"Press ESC to input password again",
+            NULL
+            );
+        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+          gST->ConOut->ClearScreen(gST->ConOut);
+          return;
+        } else {
+          //
+          // Let user input password again.
+          //
+          continue;
+        }
+    }
+
+    if (OldPassword == NULL) {
+      Count ++;
+      continue;
+    }
+    OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
+
+    ZeroMem(&Session, sizeof(Session));
+    Session.Sscp = Dev->OpalDisk.Sscp;
+    Session.MediaId = Dev->OpalDisk.MediaId;
+    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+    Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
+    if (Ret == TcgResultSuccess) {
+      DEBUG ((DEBUG_INFO, "Verify: Success\n"));
+    } else {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"Incorrect password.",
+          L"Press ENTER to retry",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+      Count ++;
+      continue;
+    }
+
+    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);
+    if (Password == NULL) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      Count ++;
+      continue;
+    }
+    PasswordLen = (UINT32) AsciiStrLen(Password);
+
+    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);
+    if (PasswordConfirm == NULL) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+      Count ++;
+      continue;
+    }
+    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
+    if ((PasswordLen != PasswordLenConfirm) ||
+        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+      ZeroMem (PasswordConfirm, PasswordLenConfirm);
+      FreePool (PasswordConfirm);
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"Passwords are not the same.",
+          L"Press ENTER to retry",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+      Count ++;
+      continue;
+    }
+
+    if (PasswordConfirm != NULL) {
+      ZeroMem (PasswordConfirm, PasswordLenConfirm);
+      FreePool (PasswordConfirm);
+    }
+
+
+    ZeroMem(&Session, sizeof(Session));
+    Session.Sscp = Dev->OpalDisk.Sscp;
+    Session.MediaId = Dev->OpalDisk.MediaId;
+    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+    Ret = OpalUtilSetAdminPassword(
+            &Session,
+            OldPassword,
+            OldPasswordLen,
+            Password,
+            PasswordLen
+            );
+    if (Ret == TcgResultSuccess) {
+      OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
+      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
+    } else {
+      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
+    }
+
+    if (OldPassword != NULL) {
+      ZeroMem (OldPassword, OldPasswordLen);
+      FreePool (OldPassword);
+    }
+
+    if (Password != NULL) {
+      ZeroMem (Password, PasswordLen);
+      FreePool (Password);
+    }
+
+    if (Ret == TcgResultSuccess) {
+      break;
+    }
+
+    Count++;
+
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Request failed.",
+        L"Press ENTER to retry",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+  }
+
+  if (Count >= MAX_PASSWORD_TRY_COUNT) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"Opal password retry count exceeds the limit.",
+        L"Press ENTER to skip the request and continue boot",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+    gST->ConOut->ClearScreen(gST->ConOut);
+  }
+}
+
+/**
+  Process OPAL request.
+
+  @param[in] Dev            The device which has OPAL request.
+
+**/
+VOID
+ProcessOpalRequest (
+  IN OPAL_DRIVER_DEVICE     *Dev
+  )
+{
+  EFI_STATUS                Status;
+  OPAL_REQUEST_VARIABLE     *TempVariable;
+  OPAL_REQUEST_VARIABLE     *Variable;
+  UINTN                     VariableSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
+  UINTN                     DevicePathSizeInVariable;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     DevicePathSize;
+  BOOLEAN                   KeepUserData;
+
+  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
+
+  if (mOpalRequestVariable == NULL) {
+    Status = GetVariable2 (
+               OPAL_REQUEST_VARIABLE_NAME,
+               &gHiiSetupVariableGuid,
+               (VOID **) &Variable,
+               &VariableSize
+               );
+    if (EFI_ERROR (Status) || (Variable == NULL)) {
+      return;
+    }
+    mOpalRequestVariable = Variable;
+    mOpalRequestVariableSize = VariableSize;
+
+    //
+    // Delete the OPAL request variable.
+    //
+    Status = gRT->SetVariable (
+                    OPAL_REQUEST_VARIABLE_NAME,
+                    (EFI_GUID *) &gHiiSetupVariableGuid,
+                    0,
+                    0,
+                    NULL
+                    );
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    Variable = mOpalRequestVariable;
+    VariableSize = mOpalRequestVariableSize;
+  }
+
+  //
+  // Process the OPAL requests.
+  //
+  TempVariable = Variable;
+  while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
+         (VariableSize >= TempVariable->Length) &&
+         (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
+    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
+    DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
+    DevicePath = Dev->OpalDisk.OpalDevicePath;
+    DevicePathSize = GetDevicePathSize (DevicePath);
+    if ((DevicePathSize == DevicePathSizeInVariable) &&
+        (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {
+      //
+      // Found the node for the OPAL device.
+      //
+      if (TempVariable->OpalRequest.SetAdminPwd != 0) {
+        ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");
+      }
+      if (TempVariable->OpalRequest.SetUserPwd != 0) {
+        ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");
+      }
+      if (TempVariable->OpalRequest.SecureErase!= 0) {
+        ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");
+      }
+      if (TempVariable->OpalRequest.Revert != 0) {
+        KeepUserData = (BOOLEAN) TempVariable->OpalRequest.KeepUserData;
+        ProcessOpalRequestRevert (
+          Dev,
+          KeepUserData,
+          KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"
+          );
+      }
+      if (TempVariable->OpalRequest.PsidRevert != 0) {
+        ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");
+      }
+      if (TempVariable->OpalRequest.DisableUser != 0) {
+        ProcessOpalRequestDisableUser (Dev, L"Disable User:");
+      }
+      if (TempVariable->OpalRequest.EnableFeature != 0) {
+        ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");
+      }
+
+      break;
+    }
+
+    VariableSize -= TempVariable->Length;
+    TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);
+  }
+
+  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
+}
+
+/**
+  Add new device to the global device list.
+
+  @param Dev             New create device.
+
+**/
+VOID
+AddDeviceToTail(
+  IN OPAL_DRIVER_DEVICE    *Dev
+  )
+{
+  OPAL_DRIVER_DEVICE                *TmpDev;
+
+  if (mOpalDriver.DeviceList == NULL) {
+    mOpalDriver.DeviceList = Dev;
+  } else {
+    TmpDev = mOpalDriver.DeviceList;
+    while (TmpDev->Next != NULL) {
+      TmpDev = TmpDev->Next;
+    }
+
+    TmpDev->Next = Dev;
+  }
+}
+
+/**
+  Remove one device in the global device list.
+
+  @param Dev             The device need to be removed.
+
+**/
+VOID
+RemoveDevice (
+  IN OPAL_DRIVER_DEVICE    *Dev
+  )
+{
+  OPAL_DRIVER_DEVICE                *TmpDev;
+
+  if (mOpalDriver.DeviceList == NULL) {
+    return;
+  }
+
+  if (mOpalDriver.DeviceList == Dev) {
+    mOpalDriver.DeviceList = NULL;
+    return;
+  }
+
+  TmpDev = mOpalDriver.DeviceList;
+  while (TmpDev->Next != NULL) {
+    if (TmpDev->Next == Dev) {
+      TmpDev->Next = Dev->Next;
+      break;
+    }
+  }
+}
+
+/**
+  Get current device count.
+
+  @retval  return the current created device count.
+
+**/
+UINT8
+GetDeviceCount (
+  VOID
+  )
+{
+  UINT8                Count;
+  OPAL_DRIVER_DEVICE   *TmpDev;
+
+  Count = 0;
+  TmpDev = mOpalDriver.DeviceList;
+
+  while (TmpDev != NULL) {
+    Count++;
+    TmpDev = TmpDev->Next;
+  }
+
+  return Count;
+}
+
+/**
+  Get devcie list info.
+
+  @retval     return the device list pointer.
+**/
+OPAL_DRIVER_DEVICE*
+OpalDriverGetDeviceList(
+  VOID
+  )
+{
+  return mOpalDriver.DeviceList;
+}
+
+/**
+  ReadyToBoot callback to send BlockSid command.
+
+  @param  Event   Pointer to this event
+  @param  Context Event handler private Data
+
+**/
+VOID
+EFIAPI
+ReadyToBootCallback (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  OPAL_DRIVER_DEVICE                         *Itr;
+  TCG_RESULT                                 Result;
+  OPAL_SESSION                               Session;
+  UINT32                                     PpStorageFlag;
+
+  gBS->CloseEvent (Event);
+
+  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
+  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
+    //
+    // Send BlockSID command to each Opal disk
+    //
+    Itr = mOpalDriver.DeviceList;
+    while (Itr != NULL) {
+      if (Itr->OpalDisk.SupportedAttributes.BlockSid) {
+        ZeroMem(&Session, sizeof(Session));
+        Session.Sscp = Itr->OpalDisk.Sscp;
+        Session.MediaId = Itr->OpalDisk.MediaId;
+        Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
+
+        Result = OpalBlockSid (&Session, TRUE);  // HardwareReset must always be TRUE
+        if (Result != TcgResultSuccess) {
+          DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
+          break;
+        }
+      }
+
+      Itr = Itr->Next;
+    }
+  }
+}
+
+/**
+  Stop this Controller.
+
+  @param  Dev               The device need to be stopped.
+
+**/
+VOID
+OpalDriverStopDevice (
+  OPAL_DRIVER_DEVICE     *Dev
+  )
+{
+  //
+  // free each name
+  //
+  FreePool(Dev->Name16);
+
+  //
+  // remove OPAL_DRIVER_DEVICE from the list
+  // it updates the controllerList pointer
+  //
+  RemoveDevice(Dev);
+
+  //
+  // close protocols that were opened
+  //
+  gBS->CloseProtocol(
+    Dev->Handle,
+    &gEfiStorageSecurityCommandProtocolGuid,
+    gOpalDriverBinding.DriverBindingHandle,
+    Dev->Handle
+    );
+
+  gBS->CloseProtocol(
+    Dev->Handle,
+    &gEfiBlockIoProtocolGuid,
+    gOpalDriverBinding.DriverBindingHandle,
+    Dev->Handle
+    );
+
+  FreePool(Dev);
+}
+
+/**
+  Get devcie name through the component name protocol.
+
+  @param[in]       AllHandlesBuffer   The handle buffer for current system.
+  @param[in]       NumAllHandles      The number of handles for the handle buffer.
+  @param[in]       Dev                The device which need to get name.
+  @param[in]       UseComp1           Whether use component name or name2 protocol.
+
+  @retval     TRUE        Find the name for this device.
+  @retval     FALSE       Not found the name for this device.
+**/
+BOOLEAN
+OpalDriverGetDeviceNameByProtocol(
+  EFI_HANDLE             *AllHandlesBuffer,
+  UINTN                  NumAllHandles,
+  OPAL_DRIVER_DEVICE     *Dev,
+  BOOLEAN                UseComp1
+  )
+{
+  EFI_HANDLE*                   ProtocolHandlesBuffer;
+  UINTN                         NumProtocolHandles;
+  EFI_STATUS                    Status;
+  EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout
+  EFI_GUID                      Protocol;
+  UINTN                         StrLength;
+  EFI_DEVICE_PATH_PROTOCOL*     TmpDevPath;
+  UINTN                         Index1;
+  UINTN                         Index2;
+  EFI_HANDLE                    TmpHandle;
+  CHAR16                        *DevName;
+
+  if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
+    return FALSE;
+  }
+
+  Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;
+
+  //
+  // Find all EFI_HANDLES with protocol
+  //
+  Status = gBS->LocateHandleBuffer(
+               ByProtocol,
+               &Protocol,
+               NULL,
+               &NumProtocolHandles,
+               &ProtocolHandlesBuffer
+               );
+  if (EFI_ERROR(Status)) {
+    return FALSE;
+  }
+
+
+  //
+  // Exit early if no supported devices
+  //
+  if (NumProtocolHandles == 0) {
+    return FALSE;
+  }
+
+  //
+  // Get printable name by iterating through all protocols
+  // using the handle as the child, and iterate through all handles for the controller
+  // exit loop early once found, if not found, then delete device
+  // storage security protocol instances already exist, add them to internal list
+  //
+  Status = EFI_DEVICE_ERROR;
+  for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
+    DevName = NULL;
+
+    if (Dev->Name16 != NULL) {
+      return TRUE;
+    }
+
+    TmpHandle = ProtocolHandlesBuffer[Index1];
+
+    Status = gBS->OpenProtocol(
+                 TmpHandle,
+                 &Protocol,
+                 (VOID**)&Cnp1_2,
+                 gImageHandle,
+                 NULL,
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                 );
+    if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
+      continue;
+    }
+
+    //
+    // Use all handles array as controller handle
+    //
+    for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
+      Status = Cnp1_2->GetControllerName(
+                   Cnp1_2,
+                   AllHandlesBuffer[Index2],
+                   Dev->Handle,
+                   LANGUAGE_ISO_639_2_ENGLISH,
+                   &DevName
+                   );
+      if (EFI_ERROR(Status)) {
+        Status = Cnp1_2->GetControllerName(
+                     Cnp1_2,
+                     AllHandlesBuffer[Index2],
+                     Dev->Handle,
+                     LANGUAGE_RFC_3066_ENGLISH,
+                     &DevName
+                     );
+      }
+      if (!EFI_ERROR(Status) && DevName != NULL) {
+        StrLength = StrLen(DevName) + 1;        // Add one for NULL terminator
+        Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
+        ASSERT (Dev->Name16 != NULL);
+        StrCpyS (Dev->Name16, StrLength, DevName);
+        Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
+        UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);
+
+        //
+        // Retrieve bridge BDF info and port number or namespace depending on type
+        //
+        TmpDevPath = NULL;
+        Status = gBS->OpenProtocol(
+            Dev->Handle,
+            &gEfiDevicePathProtocolGuid,
+            (VOID**)&TmpDevPath,
+            gImageHandle,
+            NULL,
+            EFI_OPEN_PROTOCOL_GET_PROTOCOL
+            );
+        if (!EFI_ERROR(Status)) {
+          Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
+          return TRUE;
+        }
+
+        if (Dev->Name16 != NULL) {
+          FreePool(Dev->Name16);
+          Dev->Name16 = NULL;
+        }
+        if (Dev->NameZ != NULL) {
+          FreePool(Dev->NameZ);
+          Dev->NameZ = NULL;
+        }
+      }
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Get devcie name through the component name protocol.
+
+  @param[in]       Dev                The device which need to get name.
+
+  @retval     TRUE        Find the name for this device.
+  @retval     FALSE       Not found the name for this device.
+**/
+BOOLEAN
+OpalDriverGetDriverDeviceName(
+  OPAL_DRIVER_DEVICE          *Dev
+  )
+{
+  EFI_HANDLE*                  AllHandlesBuffer;
+  UINTN                        NumAllHandles;
+  EFI_STATUS                   Status;
+
+  if (Dev == NULL) {
+    DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));
+    return FALSE;
+  }
+
+  //
+  // Iterate through ComponentName2 handles to get name, if fails, try ComponentName
+  //
+  if (Dev->Name16 == NULL) {
+    DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
+    //
+    // Find all EFI_HANDLES
+    //
+    Status = gBS->LocateHandleBuffer(
+                 AllHandles,
+                 NULL,
+                 NULL,
+                 &NumAllHandles,
+                 &AllHandlesBuffer
+                 );
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));
+      return FALSE;
+    }
+
+    //
+    // Try component Name2
+    //
+    if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {
+      DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));
+      if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {
+        DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));
+        return FALSE;
+      }
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Main entry for this driver.
+
+  @param ImageHandle     Image Handle this driver.
+  @param SystemTable     Pointer to SystemTable.
+
+  @retval EFI_SUCESS     This function always complete successfully.
+**/
+EFI_STATUS
+EFIAPI
+EfiDriverEntryPoint(
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE*  SystemTable
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_EVENT                      ReadyToBootEvent;
+  EFI_EVENT                      EndOfDxeEvent;
+
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gOpalDriverBinding,
+             ImageHandle,
+             &gOpalComponentName,
+             &gOpalComponentName2
+             );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));
+    return Status ;
+  }
+
+  //
+  // Initialize Driver object
+  //
+  ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
+  mOpalDriver.Handle = ImageHandle;
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  OpalEndOfDxeEventNotify,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // register a ReadyToBoot event callback for sending BlockSid command
+  //
+  Status = EfiCreateEventReadyToBootEx (
+                  TPL_CALLBACK,
+                  ReadyToBootCallback,
+                  (VOID *) &ImageHandle,
+                  &ReadyToBootEvent
+                  );
+
+  //
+  // Install Hii packages.
+  //
+  HiiInstall();
+
+  return Status;
+}
+
+/**
+  Tests to see if this driver supports a given controller.
+
+  This function checks to see if the controller contains an instance of the
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL
+  and returns EFI_SUCCESS if it does.
+
+  @param[in]  This                  A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle      The Handle of the controller to test. This Handle
+                                    must support a protocol interface that supplies
+                                    an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  This parameter is ignored.
+
+  @retval EFI_SUCCESS               The device contains required protocols
+  @retval EFI_ALREADY_STARTED       The device specified by ControllerHandle and
+                                    RemainingDevicePath is already being managed by the driver
+                                    specified by This.
+  @retval EFI_ACCESS_DENIED         The device specified by ControllerHandle and
+                                    RemainingDevicePath is already being managed by a different
+                                    driver or an application that requires exclusive access.
+                                    Currently not implemented.
+  @retval EFI_UNSUPPORTED           The device does not contain requires protocols
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingSupported(
+  IN EFI_DRIVER_BINDING_PROTOCOL* This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL*  SecurityCommand;
+  EFI_BLOCK_IO_PROTOCOL*                  BlkIo;
+
+  if (mOpalEndOfDxe) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.
+  //
+  Status = gBS->OpenProtocol(
+    Controller,
+    &gEfiStorageSecurityCommandProtocolGuid,
+    ( VOID ** )&SecurityCommand,
+    This->DriverBindingHandle,
+    Controller,
+    EFI_OPEN_PROTOCOL_BY_DRIVER
+    );
+
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // Close protocol and reopen in Start call
+  //
+  gBS->CloseProtocol(
+      Controller,
+      &gEfiStorageSecurityCommandProtocolGuid,
+      This->DriverBindingHandle,
+      Controller
+      );
+
+  //
+  // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
+  // function APIs
+  //
+  Status = gBS->OpenProtocol(
+    Controller,
+    &gEfiBlockIoProtocolGuid,
+    (VOID **)&BlkIo,
+    This->DriverBindingHandle,
+    Controller,
+    EFI_OPEN_PROTOCOL_BY_DRIVER
+    );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));
+    return Status;
+  }
+
+  //
+  // Close protocol and reopen in Start call
+  //
+  gBS->CloseProtocol(
+    Controller,
+    &gEfiBlockIoProtocolGuid,
+    This->DriverBindingHandle,
+    Controller
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Enables Opal Management on a supported device if available.
+
+  The start function is designed to be called after the Opal UEFI Driver has confirmed the
+  "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
+  This function will complete the other necessary checks, such as verifying the device supports
+  the correct version of Opal.  Upon verification, it will add the device to the
+  Opal HII list in order to expose Opal managmeent options.
+
+  @param[in]  This                  A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle      The Handle of the controller to start. This Handle
+                                    must support a protocol interface that supplies
+                                    an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath   A pointer to the remaining portion of a device path.  This
+                                    parameter is ignored by device drivers, and is optional for bus
+                                    drivers. For a bus driver, if this parameter is NULL, then handles
+                                    for all the children of Controller are created by this driver.
+                                    If this parameter is not NULL and the first Device Path Node is
+                                    not the End of Device Path Node, then only the Handle for the
+                                    child device specified by the first Device Path Node of
+                                    RemainingDevicePath is created by this driver.
+                                    If the first Device Path Node of RemainingDevicePath is
+                                    the End of Device Path Node, no child Handle is created by this
+                                    driver.
+
+  @retval EFI_SUCCESS               Opal management was enabled.
+  @retval EFI_DEVICE_ERROR          The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES      The request could not be completed due to a lack of resources.
+  @retval Others                    The driver failed to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStart(
+  IN EFI_DRIVER_BINDING_PROTOCOL* This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_BLOCK_IO_PROTOCOL       *BlkIo;
+  OPAL_DRIVER_DEVICE          *Dev;
+  OPAL_DRIVER_DEVICE          *Itr;
+  BOOLEAN                     Result;
+
+  Itr = mOpalDriver.DeviceList;
+  while (Itr != NULL) {
+    if (Controller == Itr->Handle) {
+      return EFI_SUCCESS;
+    }
+    Itr = Itr->Next;
+  }
+
+  //
+  // Create internal device for tracking.  This allows all disks to be tracked
+  // by same HII form
+  //
+  Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
+  if (Dev == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  Dev->Handle = Controller;
+
+  //
+  // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks
+  //
+  Status = gBS->OpenProtocol(
+    Controller,
+    &gEfiStorageSecurityCommandProtocolGuid,
+    (VOID **)&Dev->Sscp,
+    This->DriverBindingHandle,
+    Controller,
+    EFI_OPEN_PROTOCOL_BY_DRIVER
+    );
+  if (EFI_ERROR(Status)) {
+    FreePool(Dev);
+    return Status;
+  }
+
+  //
+  // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
+  // function APIs
+  //
+  Status = gBS->OpenProtocol(
+    Controller,
+    &gEfiBlockIoProtocolGuid,
+    (VOID **)&BlkIo,
+    This->DriverBindingHandle,
+    Controller,
+    EFI_OPEN_PROTOCOL_BY_DRIVER
+    );
+  if (EFI_ERROR(Status)) {
+    //
+    // Close storage security that was opened
+    //
+    gBS->CloseProtocol(
+        Controller,
+        &gEfiStorageSecurityCommandProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+    FreePool(Dev);
+    return Status;
+  }
+
+  //
+  // Save mediaId
+  //
+  Dev->MediaId = BlkIo->Media->MediaId;
+
+  gBS->CloseProtocol(
+    Controller,
+    &gEfiBlockIoProtocolGuid,
+    This->DriverBindingHandle,
+    Controller
+    );
+
+  //
+  // Acquire Ascii printable name of child, if not found, then ignore device
+  //
+  Result = OpalDriverGetDriverDeviceName (Dev);
+  if (!Result) {
+    goto Done;
+  }
+
+  Status = OpalDiskInitialize (Dev);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  AddDeviceToTail(Dev);
+
+  //
+  // Check if device is locked and prompt for password.
+  //
+  OpalDriverRequestPassword (Dev, L"Unlock:");
+
+  //
+  // Process OPAL request from last boot.
+  //
+  ProcessOpalRequest (Dev);
+
+  return EFI_SUCCESS;
+
+Done:
+  //
+  // free device, close protocols and exit
+  //
+  gBS->CloseProtocol(
+      Controller,
+      &gEfiStorageSecurityCommandProtocolGuid,
+      This->DriverBindingHandle,
+      Controller
+      );
+
+  FreePool(Dev);
+
+  return EFI_DEVICE_ERROR;
+}
+
+/**
+  Stop this driver on Controller.
+
+  @param  This              Protocol instance pointer.
+  @param  Controller        Handle of device to stop driver on
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
+                            children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval EFI_SUCCESS       This driver is removed Controller.
+  @retval other             This driver could not be removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStop(
+  EFI_DRIVER_BINDING_PROTOCOL*    This,
+  EFI_HANDLE                      Controller,
+  UINTN                           NumberOfChildren,
+  EFI_HANDLE*                     ChildHandleBuffer
+  )
+{
+  OPAL_DRIVER_DEVICE*   Itr;
+
+  Itr = mOpalDriver.DeviceList;
+
+  //
+  // does Controller match any of the devices we are managing for Opal
+  //
+  while (Itr != NULL) {
+    if (Itr->Handle == Controller) {
+      OpalDriverStopDevice (Itr);
+      return EFI_SUCCESS;
+    }
+
+    Itr = Itr->Next;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
+/**
+  Unloads UEFI Driver.  Very useful for debugging and testing.
+
+  @param ImageHandle            Image Handle this driver.
+
+  @retval EFI_SUCCESS           This function always complete successfully.
+  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverUnload (
+  IN EFI_HANDLE ImageHandle
+  )
+{
+  EFI_STATUS                     Status;
+  OPAL_DRIVER_DEVICE                   *Itr;
+
+  Status = EFI_SUCCESS;
+
+  if (ImageHandle != gImageHandle) {
+    return (EFI_INVALID_PARAMETER);
+  }
+
+  //
+  // Uninstall any interface added to each device by us
+  //
+  while (mOpalDriver.DeviceList) {
+    Itr = mOpalDriver.DeviceList;
+    //
+    // Remove OPAL_DRIVER_DEVICE from the list
+    // it updates the controllerList pointer
+    //
+    OpalDriverStopDevice(Itr);
+  }
+
+  //
+  // Uninstall the HII capability
+  //
+  Status = HiiUninstall();
+
+  return Status;
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
new file mode 100644
index 000000000000..a66b5a5345ff
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
@@ -0,0 +1,613 @@
+/** @file
+  Values defined and used by the Opal UEFI Driver.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_DRIVER_H_
+#define _OPAL_DRIVER_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/SmmCommunication.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/StorageSecurityCommand.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/PciLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/TcgStorageOpalLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include "OpalPasswordCommon.h"
+#include "OpalHiiFormValues.h"
+
+#define EFI_DRIVER_NAME_UNICODE L"1.0 UEFI Opal Driver"
+
+// UEFI 2.1
+#define LANGUAGE_RFC_3066_ENGLISH ((CHAR8*)"en")
+
+// UEFI/EFI < 2.1
+#define LANGUAGE_ISO_639_2_ENGLISH ((CHAR8*)"eng")
+
+#define CONCAT_(x, y) x ## y
+#define CONCAT(x, y) CONCAT_(x, y)
+
+#define UNICODE_STR(x) CONCAT( L, x )
+
+extern EFI_DRIVER_BINDING_PROTOCOL   gOpalDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL   gOpalComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gOpalComponentName2;
+
+#define OPAL_MSID_LENGHT        128
+
+#define MAX_PASSWORD_SIZE       32
+#define MAX_PASSWORD_TRY_COUNT  5
+
+// PSID Length
+#define PSID_CHARACTER_LENGTH   0x20
+#define MAX_PSID_TRY_COUNT      5
+
+#pragma pack(1)
+
+//
+// Structure that is used to represent the available actions for an OpalDisk.
+// The data can then be utilized to expose/hide certain actions available to an end user
+// by the consumer of this library.
+//
+typedef struct {
+    //
+    // Indicates if the disk can support PSID Revert action.  should verify disk supports PSID authority
+    //
+    UINT16 PsidRevert : 1;
+
+    //
+    // Indicates if the disk can support Revert action
+    //
+    UINT16 Revert : 1;
+
+    //
+    // Indicates if the user must keep data for revert action.  It is true if no media encryption is supported.
+    //
+    UINT16 RevertKeepDataForced : 1;
+
+    //
+    // Indicates if the disk can support set Admin password
+    //
+    UINT16 AdminPass : 1;
+
+    //
+    // Indicates if the disk can support set User password.  This action requires that a user
+    // password is first enabled.
+    //
+    UINT16 UserPass : 1;
+
+    //
+    // Indicates if unlock action is available.  Requires disk to be currently locked.
+    //
+    UINT16 Unlock : 1;
+
+    //
+    // Indicates if Secure Erase action is available.  Action requires admin credentials and media encryption support.
+    //
+    UINT16 SecureErase : 1;
+
+    //
+    // Indicates if Disable User action is available.  Action requires admin credentials.
+    //
+    UINT16 DisableUser : 1;
+} OPAL_DISK_ACTIONS;
+
+//
+// Structure that is used to represent an OPAL_DISK.
+//
+typedef struct {
+  UINT32                                          MsidLength;             // Byte length of MSID Pin for device
+  UINT8                                           Msid[OPAL_MSID_LENGHT]; // MSID Pin for device
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;
+  UINT32                                          MediaId;                // MediaId is used by Ssc Protocol.
+  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
+  UINT16                                          OpalBaseComId;          // Opal SSC 1 base com id.
+  OPAL_OWNER_SHIP                                 Owner;
+  OPAL_DISK_SUPPORT_ATTRIBUTE                     SupportedAttributes;
+  TCG_LOCKING_FEATURE_DESCRIPTOR                  LockingFeature;         // Locking Feature Descriptor retrieved from performing a Level 0 Discovery
+  UINT8                                           PasswordLength;
+  UINT8                                           Password[MAX_PASSWORD_SIZE];
+} OPAL_DISK;
+
+//
+// Device with block IO protocol
+//
+typedef struct _OPAL_DRIVER_DEVICE OPAL_DRIVER_DEVICE;
+
+struct _OPAL_DRIVER_DEVICE {
+  OPAL_DRIVER_DEVICE                              *Next;              ///< Linked list pointer
+  EFI_HANDLE                                      Handle;             ///< Device handle
+  OPAL_DISK                                       OpalDisk;           ///< User context
+  CHAR16                                          *Name16;            ///< Allocated/freed by UEFI Filter Driver at device creation/removal
+  CHAR8                                           *NameZ;             ///< Allocated/freed by UEFI Filter Driver at device creation/removal
+  UINT32                                          MediaId;            ///< Required parameter for EFI_STORAGE_SECURITY_COMMAND_PROTOCOL, from BLOCK_IO_MEDIA
+
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;              /// Device protocols consumed
+  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
+};
+
+//
+// Opal Driver UEFI Driver Model
+//
+typedef struct {
+  EFI_HANDLE           Handle;              ///< Driver image handle
+  OPAL_DRIVER_DEVICE   *DeviceList;         ///< Linked list of controllers owned by this Driver
+} OPAL_DRIVER;
+
+#pragma pack()
+
+//
+// Retrieves a OPAL_DRIVER_DEVICE based on the pointer to its StorageSecurity protocol.
+//
+#define DRIVER_DEVICE_FROM_OPALDISK(OpalDiskPointer) (OPAL_DRIVER_DEVICE*)(BASE_CR(OpalDiskPointer, OPAL_DRIVER_DEVICE, OpalDisk))
+
+/**
+  Get devcie list info.
+
+  @retval     return the device list pointer.
+**/
+OPAL_DRIVER_DEVICE*
+OpalDriverGetDeviceList(
+  VOID
+  );
+
+/**
+  Get devcie name through the component name protocol.
+
+  @param[in]       Dev                The device which need to get name.
+
+  @retval     TRUE        Find the name for this device.
+  @retval     FALSE       Not found the name for this device.
+**/
+BOOLEAN
+OpalDriverGetDriverDeviceName(
+  OPAL_DRIVER_DEVICE          *Dev
+  );
+
+/**
+  Get current device count.
+
+  @retval  return the current created device count.
+
+**/
+UINT8
+GetDeviceCount (
+  VOID
+  );
+
+/**
+  Update password for the Opal disk.
+
+  @param[in, out] OpalDisk          The disk to update password.
+  @param[in]      Password          The input password.
+  @param[in]      PasswordLength    The input password length.
+
+**/
+VOID
+OpalSupportUpdatePassword (
+  IN OUT OPAL_DISK      *OpalDisk,
+  IN VOID               *Password,
+  IN UINT32             PasswordLength
+  );
+
+/**
+
+  The function performs determines the available actions for the OPAL_DISK provided.
+
+  @param[in]   SupportedAttributes   The support attribute for the device.
+  @param[in]   LockingFeature        The locking status for the device.
+  @param[in]   OwnerShip             The ownership for the device.
+  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate disk actions.
+
+**/
+TCG_RESULT
+EFIAPI
+OpalSupportGetAvailableActions(
+  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
+  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
+  IN  UINT16                           OwnerShip,
+  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
+  );
+
+/**
+  Enable Opal Feature for the input device.
+
+  @param[in]      Session            The opal session for the opal device.
+  @param[in]      Msid               Msid
+  @param[in]      MsidLength         Msid Length
+  @param[in]      Password           Admin password
+  @param[in]      PassLength         Length of password in bytes 
+
+**/
+TCG_RESULT
+EFIAPI
+OpalSupportEnableOpalFeature (
+  IN OPAL_SESSION              *Session,
+  IN VOID                      *Msid,
+  IN UINT32                    MsidLength,
+  IN VOID                      *Password,
+  IN UINT32                    PassLength
+  );
+
+/**
+  Unloads UEFI Driver.  Very useful for debugging and testing.
+
+  @param ImageHandle            Image handle this driver.
+
+  @retval EFI_SUCCESS           This function always complete successfully.
+  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
+**/
+EFI_STATUS
+EFIAPI
+EfiDriverUnload(
+  EFI_HANDLE ImageHandle
+  );
+
+
+/**
+  Test to see if this driver supports Controller.
+
+  @param  This                Protocol instance pointer.
+  @param  ControllerHandle    Handle of device to test
+  @param  RemainingDevicePath Optional parameter use to pick a specific child
+                              device to start.
+
+  @retval EFI_SUCCESS         This driver supports this device.
+  @retval EFI_ALREADY_STARTED This driver is already running on this device.
+  @retval other               This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingSupported(
+  EFI_DRIVER_BINDING_PROTOCOL*    This,
+  EFI_HANDLE                      Controller,
+  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
+  );
+
+/**
+  Enables Opal Management on a supported device if available.
+
+  The start function is designed to be called after the Opal UEFI Driver has confirmed the
+  "controller", which is a child handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
+  This function will complete the other necessary checks, such as verifying the device supports
+  the correct version of Opal.  Upon verification, it will add the device to the
+  Opal HII list in order to expose Opal managmeent options.
+
+  @param[in]  This                  A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle      The handle of the controller to start. This handle
+                                    must support a protocol interface that supplies
+                                    an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath   A pointer to the remaining portion of a device path.  This
+                                    parameter is ignored by device drivers, and is optional for bus
+                                    drivers. For a bus driver, if this parameter is NULL, then handles
+                                    for all the children of Controller are created by this driver.
+                                    If this parameter is not NULL and the first Device Path Node is
+                                    not the End of Device Path Node, then only the handle for the
+                                    child device specified by the first Device Path Node of
+                                    RemainingDevicePath is created by this driver.
+                                    If the first Device Path Node of RemainingDevicePath is
+                                    the End of Device Path Node, no child handle is created by this
+                                    driver.
+
+  @retval EFI_SUCCESS               Opal management was enabled.
+  @retval EFI_DEVICE_ERROR          The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES      The request could not be completed due to a lack of resources.
+  @retval Others                    The driver failed to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStart(
+  EFI_DRIVER_BINDING_PROTOCOL*    This,
+  EFI_HANDLE                      Controller,
+  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
+  );
+
+/**
+  Stop this driver on Controller.
+
+  @param  This              Protocol instance pointer.
+  @param  Controller        Handle of device to stop driver on
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
+                            children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval EFI_SUCCESS       This driver is removed Controller.
+  @retval other             This driver could not be removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStop(
+  EFI_DRIVER_BINDING_PROTOCOL*    This,
+  EFI_HANDLE                      Controller,
+  UINTN                           NumberOfChildren,
+  EFI_HANDLE*                     ChildHandleBuffer
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetDriverName(
+  EFI_COMPONENT_NAME_PROTOCOL*    This,
+  CHAR8*                          Language,
+  CHAR16**                        DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetControllerName(
+  EFI_COMPONENT_NAME_PROTOCOL*    This,
+  EFI_HANDLE                      ControllerHandle,
+  EFI_HANDLE                      ChildHandle,
+  CHAR8*                          Language,
+  CHAR16**                        ControllerName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetDriverName(
+  EFI_COMPONENT_NAME2_PROTOCOL*   This,
+  CHAR8*                          Language,
+  CHAR16**                        DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetControllerName(
+  EFI_COMPONENT_NAME2_PROTOCOL*   This,
+  EFI_HANDLE                      ControllerHandle,
+  EFI_HANDLE                      ChildHandle,
+  CHAR8*                          Language,
+  CHAR16**                        ControllerName
+  );
+
+#endif //_OPAL_DRIVER_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
new file mode 100644
index 000000000000..e4972227b669
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
@@ -0,0 +1,1178 @@
+/** @file
+  Implementation of the HII for the Opal UEFI Driver.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalHii.h"
+
+//
+// This is the generated IFR binary Data for each formset defined in VFR.
+// This Data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8  OpalPasswordFormBin[];
+
+//
+// This is the generated String package Data for all .UNI files.
+// This Data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8  OpalPasswordDxeStrings[];
+
+CHAR16  OpalPasswordStorageName[] = L"OpalHiiConfig";
+
+EFI_HII_CONFIG_ACCESS_PROTOCOL gHiiConfigAccessProtocol;
+
+//
+// Handle to the list of HII packages (forms and strings) for this driver
+//
+EFI_HII_HANDLE gHiiPackageListHandle = NULL;
+
+//
+// Package List GUID containing all form and string packages
+//
+const EFI_GUID gHiiPackageListGuid = PACKAGE_LIST_GUID;
+const EFI_GUID gHiiSetupVariableGuid = SETUP_VARIABLE_GUID;
+
+//
+// Structure that contains state of the HII
+// This structure is updated by Hii.cpp and its contents
+// is rendered in the HII.
+//
+OPAL_HII_CONFIGURATION gHiiConfiguration;
+
+//
+// The device path containing the VENDOR_DEVICE_PATH and EFI_DEVICE_PATH_PROTOCOL
+//
+HII_VENDOR_DEVICE_PATH gHiiVendorDevicePath = {
+    {
+        {
+            HARDWARE_DEVICE_PATH,
+            HW_VENDOR_DP,
+            {
+                (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+                (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
+            }
+        },
+        OPAL_PASSWORD_CONFIG_GUID
+    },
+    {
+        END_DEVICE_PATH_TYPE,
+        END_ENTIRE_DEVICE_PATH_SUBTYPE,
+        {
+            (UINT8)(END_DEVICE_PATH_LENGTH),
+            (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+        }
+    }
+};
+
+/**
+  Get saved OPAL request.
+
+  @param[in]  OpalDisk      The disk needs to get the saved OPAL request.
+  @param[out] OpalRequest   OPAL request got.
+
+**/
+VOID
+GetSavedOpalRequest (
+  IN OPAL_DISK              *OpalDisk,
+  OUT OPAL_REQUEST          *OpalRequest
+  )
+{
+  EFI_STATUS                Status;
+  OPAL_REQUEST_VARIABLE     *TempVariable;
+  OPAL_REQUEST_VARIABLE     *Variable;
+  UINTN                     VariableSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
+  UINTN                     DevicePathSizeInVariable;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     DevicePathSize;
+
+  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
+
+  Variable = NULL;
+  VariableSize = 0;
+
+  Status = GetVariable2 (
+             OPAL_REQUEST_VARIABLE_NAME,
+             &gHiiSetupVariableGuid,
+             (VOID **) &Variable,
+             &VariableSize
+             );
+  if (EFI_ERROR (Status) || (Variable == NULL)) {
+    return;
+  }
+
+  TempVariable = Variable;
+  while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
+         (VariableSize >= TempVariable->Length) &&
+         (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
+    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
+    DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
+    DevicePath = OpalDisk->OpalDevicePath;
+    DevicePathSize = GetDevicePathSize (DevicePath);
+    if ((DevicePathSize == DevicePathSizeInVariable) &&
+        (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {
+      //
+      // Found the node for the OPAL device.
+      // Get the OPAL request.
+      //
+      CopyMem (OpalRequest, &TempVariable->OpalRequest, sizeof (OPAL_REQUEST));
+      DEBUG ((
+        DEBUG_INFO,
+        "OpalRequest got: 0x%x\n",
+        *OpalRequest
+        ));
+      break;
+    }
+    VariableSize -= TempVariable->Length;
+    TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);
+  }
+
+  FreePool (Variable);
+
+  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
+}
+
+/**
+  Save OPAL request.
+
+  @param[in] OpalDisk       The disk has OPAL request to save.
+  @param[in] OpalRequest    OPAL request to save.
+
+**/
+VOID
+SaveOpalRequest (
+  IN OPAL_DISK              *OpalDisk,
+  IN OPAL_REQUEST           OpalRequest
+  )
+{
+  EFI_STATUS                Status;
+  OPAL_REQUEST_VARIABLE     *TempVariable;
+  UINTN                     TempVariableSize;
+  OPAL_REQUEST_VARIABLE     *Variable;
+  UINTN                     VariableSize;
+  OPAL_REQUEST_VARIABLE     *NewVariable;
+  UINTN                     NewVariableSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
+  UINTN                     DevicePathSizeInVariable;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     DevicePathSize;
+
+  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
+
+  DEBUG ((
+    DEBUG_INFO,
+    "OpalRequest to save: 0x%x\n",
+    OpalRequest
+    ));
+
+  Variable = NULL;
+  VariableSize = 0;
+  NewVariable = NULL;
+  NewVariableSize = 0;
+
+  Status = GetVariable2 (
+             OPAL_REQUEST_VARIABLE_NAME,
+             &gHiiSetupVariableGuid,
+             (VOID **) &Variable,
+             &VariableSize
+             );
+  if (!EFI_ERROR (Status) && (Variable != NULL)) {
+    TempVariable = Variable;
+    TempVariableSize = VariableSize;
+    while ((TempVariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
+           (TempVariableSize >= TempVariable->Length) &&
+           (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
+      DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
+      DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
+      DevicePath = OpalDisk->OpalDevicePath;
+      DevicePathSize = GetDevicePathSize (DevicePath);
+      if ((DevicePathSize == DevicePathSizeInVariable) &&
+          (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {
+        //
+        // Found the node for the OPAL device.
+        // Update the OPAL request.
+        //
+        CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof (OPAL_REQUEST));
+        NewVariable = Variable;
+        NewVariableSize = VariableSize;
+        break;
+      }
+      TempVariableSize -= TempVariable->Length;
+      TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);
+    }
+    if (NewVariable == NULL) {
+      //
+      // The node for the OPAL device is not found.
+      // Create node for the OPAL device.
+      //
+      DevicePath = OpalDisk->OpalDevicePath;
+      DevicePathSize = GetDevicePathSize (DevicePath);
+      NewVariableSize = VariableSize + sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize;
+      NewVariable = AllocatePool (NewVariableSize);
+      ASSERT (NewVariable != NULL);
+      CopyMem (NewVariable, Variable, VariableSize);
+      TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) NewVariable + VariableSize);
+      TempVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize);
+      CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof (OPAL_REQUEST));
+      DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
+      CopyMem (DevicePathInVariable, DevicePath, DevicePathSize);
+    }
+  } else {
+    DevicePath = OpalDisk->OpalDevicePath;
+    DevicePathSize = GetDevicePathSize (DevicePath);
+    NewVariableSize = sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize;
+    NewVariable = AllocatePool (NewVariableSize);
+    ASSERT (NewVariable != NULL);
+    NewVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize);
+    CopyMem (&NewVariable->OpalRequest, &OpalRequest, sizeof (OPAL_REQUEST));
+    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) NewVariable + sizeof (OPAL_REQUEST_VARIABLE));
+    CopyMem (DevicePathInVariable, DevicePath, DevicePathSize);
+  }
+  Status = gRT->SetVariable (
+                  OPAL_REQUEST_VARIABLE_NAME,
+                  (EFI_GUID *) &gHiiSetupVariableGuid,
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                  NewVariableSize,
+                  NewVariable
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "OpalRequest variable set failed (%r)\n", Status));
+  }
+  if (NewVariable != Variable) {
+    FreePool (NewVariable);
+  }
+  if (Variable != NULL) {
+    FreePool (Variable);
+  }
+
+  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
+}
+
+/**
+  Sets the current system state of global config variables.
+
+**/
+VOID
+HiiSetCurrentConfiguration(
+  VOID
+  )
+{
+  UINT32                                       PpStorageFlag;
+  EFI_STRING                                   NewString;
+
+  gHiiConfiguration.NumDisks = GetDeviceCount();
+
+  //
+  // Update the BlockSID status string.
+  //
+  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
+
+  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_ENABLED), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  } else {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISABLED), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  }
+  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS1), NewString, NULL);
+  FreePool (NewString);
+
+  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) != 0) {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  } else {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  }
+  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS2), NewString, NULL);
+  FreePool (NewString);
+
+  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) != 0) {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  } else {
+    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), NULL);
+    if (NewString == NULL) {
+      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
+      return;
+    }
+  }
+  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS3), NewString, NULL);
+  FreePool (NewString);
+}
+
+/**
+  Install the HII related resources.
+
+  @retval  EFI_SUCCESS        Install all the resources success.
+  @retval  other              Error occur when install the resources.
+**/
+EFI_STATUS
+HiiInstall(
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HANDLE                   DriverHandle;
+
+  //
+  // Clear the global configuration.
+  //
+  ZeroMem(&gHiiConfiguration, sizeof(gHiiConfiguration));
+
+  //
+  // Obtain the driver handle that the BIOS assigned us
+  //
+  DriverHandle = HiiGetDriverImageHandleCB();
+
+  //
+  // Populate the config access protocol with the three functions we are publishing
+  //
+  gHiiConfigAccessProtocol.ExtractConfig = ExtractConfig;
+  gHiiConfigAccessProtocol.RouteConfig = RouteConfig;
+  gHiiConfigAccessProtocol.Callback = DriverCallback;
+
+  //
+  // Associate the required protocols with our driver handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces(
+               &DriverHandle,
+               &gEfiHiiConfigAccessProtocolGuid,
+               &gHiiConfigAccessProtocol,      // HII callback
+               &gEfiDevicePathProtocolGuid,
+               &gHiiVendorDevicePath,        // required for HII callback allow all disks to be shown in same hii
+               NULL
+           );
+
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  return OpalHiiAddPackages();
+}
+
+/**
+  Install the HII form and string packages.
+
+  @retval  EFI_SUCCESS           Install all the resources success.
+  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
+**/
+EFI_STATUS
+OpalHiiAddPackages(
+  VOID
+  )
+{
+  EFI_HANDLE                   DriverHandle;
+  CHAR16                       *NewString;
+
+  DriverHandle = HiiGetDriverImageHandleCB();
+
+  //
+  // Publish the HII form and HII string packages
+  //
+  gHiiPackageListHandle = HiiAddPackages(
+                                &gHiiPackageListGuid,
+                                DriverHandle,
+                                OpalPasswordDxeStrings,
+                                OpalPasswordFormBin,
+                                (VOID*)NULL
+                                );
+
+  //
+  // Make sure the packages installed successfully
+  //
+  if (gHiiPackageListHandle == NULL) {
+    DEBUG ((DEBUG_INFO, "OpalHiiAddPackages failed\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Update Version String in main window
+  //
+  NewString = HiiGetDriverNameCB ();
+  if (HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_MAIN_OPAL_VERSION), NewString, NULL) == 0) {
+    DEBUG ((DEBUG_INFO,  "OpalHiiAddPackages: HiiSetString( ) failed\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Uninstall the HII capability.
+
+  @retval  EFI_SUCCESS           Uninstall all the resources success.
+  @retval  others                Other errors occur when unistall the hii resource.
+**/
+EFI_STATUS
+HiiUninstall(
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+
+  //
+  // Remove the packages we've provided to the BIOS
+  //
+  HiiRemovePackages(gHiiPackageListHandle);
+
+  //
+  // Remove the protocols from our driver handle
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces(
+                          HiiGetDriverImageHandleCB(),
+                          &gEfiHiiConfigAccessProtocolGuid,
+                          &gHiiConfigAccessProtocol,        // HII callback
+                          &gEfiDevicePathProtocolGuid,
+                          &gHiiVendorDevicePath,            // required for HII callback
+                          NULL
+                      );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_INFO, "Cannot uninstall Hii Protocols: %r\n", Status));
+  }
+
+  return Status;
+}
+
+/**
+  Updates the main menu form.
+
+  @retval  EFI_SUCCESS           update the main form success.
+**/
+EFI_STATUS
+HiiPopulateMainMenuForm (
+  VOID
+  )
+{
+  UINT8         Index;
+  CHAR8         *DiskName;
+  EFI_STRING_ID DiskNameId;
+  OPAL_DISK     *OpalDisk;
+
+  HiiSetCurrentConfiguration();
+
+  gHiiConfiguration.SupportedDisks = 0;
+
+  for (Index = 0; Index < gHiiConfiguration.NumDisks; Index++) {
+    OpalDisk = HiiGetOpalDiskCB (Index);
+    if ((OpalDisk != NULL) && OpalFeatureSupported (&OpalDisk->SupportedAttributes)) {
+      gHiiConfiguration.SupportedDisks |= (1 << Index);
+      DiskNameId = GetDiskNameStringId (Index);
+      DiskName = HiiDiskGetNameCB (Index);
+      if ((DiskName == NULL) || (DiskNameId == 0)) {
+        return EFI_UNSUPPORTED;
+      }
+      HiiSetFormString(DiskNameId, DiskName);
+    }
+  }
+
+  OpalHiiSetBrowserData ();
+  return EFI_SUCCESS;
+}
+
+/**
+  Get disk name string id.
+
+  @param   DiskIndex             The input disk index info.
+
+  @retval  The disk name string id.
+
+**/
+EFI_STRING_ID
+GetDiskNameStringId(
+  UINT8 DiskIndex
+  )
+{
+  switch (DiskIndex) {
+    case 0: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0);
+    case 1: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1);
+    case 2: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2);
+    case 3: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3);
+    case 4: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4);
+    case 5: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5);
+  }
+  return 0;
+}
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback(
+  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
+  EFI_BROWSER_ACTION                      Action,
+  EFI_QUESTION_ID                         QuestionId,
+  UINT8                                   Type,
+  EFI_IFR_TYPE_VALUE                      *Value,
+  EFI_BROWSER_ACTION_REQUEST              *ActionRequest
+  )
+{
+  HII_KEY    HiiKey;
+  UINT8      HiiKeyId;
+  UINT32     PpRequest;
+  OPAL_DISK  *OpalDisk;
+
+  if (ActionRequest != NULL) {
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If QuestionId is an auto-generated key (label, empty line, etc.), ignore it.
+  //
+  if ((QuestionId & HII_KEY_FLAG) == 0) {
+    return EFI_SUCCESS;
+  }
+
+  HiiKey.Raw = QuestionId;
+  HiiKeyId   = (UINT8) HiiKey.KeyBits.Id;
+
+  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
+    switch (HiiKeyId) {
+      case HII_KEY_ID_VAR_SUPPORTED_DISKS:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_VAR_SUPPORTED_DISKS\n"));
+        return HiiPopulateMainMenuForm ();
+
+      case HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS\n"));
+        return HiiPopulateDiskInfoForm();
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    switch (HiiKeyId) {
+      case HII_KEY_ID_GOTO_DISK_INFO:
+        return HiiSelectDisk((UINT8)HiiKey.KeyBits.Index);
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    switch (HiiKeyId) {
+      case HII_KEY_ID_BLOCKSID:
+        switch (Value->u8) {
+          case 0:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+            break;
+
+          case 1:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID;
+            break;
+
+          case 2:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID;
+            break;
+
+          case 3:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE;
+            break;
+
+          case 4:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE;
+            break;
+
+          case 5:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE;
+            break;
+
+          case 6:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE;
+            break;
+
+          default:
+            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+            DEBUG ((DEBUG_ERROR, "Invalid value input!\n"));
+            break;
+        }
+        HiiSetBlockSidAction(PpRequest);
+
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      case HII_KEY_ID_SET_ADMIN_PWD:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SET_ADMIN_PWD\n"));
+        gHiiConfiguration.OpalRequest.SetAdminPwd = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      case HII_KEY_ID_SET_USER_PWD:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SET_USER_PWD\n"));
+        gHiiConfiguration.OpalRequest.SetUserPwd = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      case HII_KEY_ID_SECURE_ERASE:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SECURE_ERASE\n"));
+        gHiiConfiguration.OpalRequest.SecureErase = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+ 
+      case HII_KEY_ID_REVERT:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_REVERT\n"));
+        gHiiConfiguration.OpalRequest.Revert = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+      case HII_KEY_ID_KEEP_USER_DATA:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_KEEP_USER_DATA\n"));
+        gHiiConfiguration.OpalRequest.KeepUserData = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      case HII_KEY_ID_PSID_REVERT:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_PSID_REVERT\n"));
+        gHiiConfiguration.OpalRequest.PsidRevert = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      case HII_KEY_ID_DISABLE_USER:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_DISABLE_USER\n"));
+        gHiiConfiguration.OpalRequest.DisableUser = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      case HII_KEY_ID_ENABLE_FEATURE:
+        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_ENABLE_FEATURE\n"));
+        gHiiConfiguration.OpalRequest.EnableFeature = Value->b;
+        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+        if (OpalDisk != NULL) {
+          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
+        }
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+        return EFI_SUCCESS;
+
+      default:
+        break;
+    }
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Update the global Disk index info.
+
+  @param   Index             The input disk index info.
+
+  @retval  EFI_SUCCESS       Update the disk index info success.
+
+**/
+EFI_STATUS
+HiiSelectDisk(
+  UINT8 Index
+  )
+{
+  OpalHiiGetBrowserData();
+  gHiiConfiguration.SelectedDiskIndex = Index;
+  OpalHiiSetBrowserData ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Draws the disk info form.
+
+  @retval  EFI_SUCCESS       Draw the disk info success.
+
+**/
+EFI_STATUS
+HiiPopulateDiskInfoForm(
+  VOID
+  )
+{
+  OPAL_DISK*                    OpalDisk;
+  OPAL_DISK_ACTIONS             AvailActions;
+  TCG_RESULT                    Ret;
+  CHAR8                         *DiskName;
+
+  OpalHiiGetBrowserData();
+
+  DiskName = HiiDiskGetNameCB (gHiiConfiguration.SelectedDiskIndex);
+  if (DiskName == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+  HiiSetFormString(STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME), DiskName);
+
+  gHiiConfiguration.SelectedDiskAvailableActions = HII_ACTION_NONE;
+  ZeroMem (&gHiiConfiguration.OpalRequest, sizeof (OPAL_REQUEST));
+  gHiiConfiguration.KeepUserDataForced = FALSE;
+
+  OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+
+  if (OpalDisk != NULL) {
+    OpalDiskUpdateStatus (OpalDisk);
+    Ret = OpalSupportGetAvailableActions(&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions);
+    if (Ret == TcgResultSuccess) {
+      //
+      // Update actions, always allow PSID Revert
+      //
+      gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.PsidRevert == 1) ? HII_ACTION_PSID_REVERT : HII_ACTION_NONE;
+
+      //
+      // Always allow unlock to handle device migration
+      //
+      gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Unlock == 1) ? HII_ACTION_UNLOCK : HII_ACTION_NONE;
+
+      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
+        if (OpalDisk->Owner == OpalOwnershipNobody) {
+          gHiiConfiguration.SelectedDiskAvailableActions |= HII_ACTION_ENABLE_FEATURE;
+
+          //
+          // Update strings
+          //
+          HiiSetFormString( STRING_TOKEN(STR_DISK_INFO_PSID_REVERT), "PSID Revert to factory default");
+        } else {
+          DEBUG ((DEBUG_INFO, "Feature disabled but ownership != nobody\n"));
+        }
+      } else {
+        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Revert == 1) ? HII_ACTION_REVERT : HII_ACTION_NONE;
+        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.AdminPass == 1) ? HII_ACTION_SET_ADMIN_PWD : HII_ACTION_NONE;
+        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.UserPass == 1) ? HII_ACTION_SET_USER_PWD : HII_ACTION_NONE;
+        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.SecureErase == 1) ? HII_ACTION_SECURE_ERASE : HII_ACTION_NONE;
+        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.DisableUser == 1) ? HII_ACTION_DISABLE_USER : HII_ACTION_NONE;
+
+        HiiSetFormString (STRING_TOKEN(STR_DISK_INFO_PSID_REVERT), "PSID Revert to factory default and Disable");
+
+        //
+        // Determine revert options for disk
+        // Default initialize keep user Data to be true
+        //
+        gHiiConfiguration.OpalRequest.KeepUserData = 1;
+        if (AvailActions.RevertKeepDataForced) {
+          gHiiConfiguration.KeepUserDataForced = TRUE;
+        }
+      }
+    }
+
+    GetSavedOpalRequest (OpalDisk, &gHiiConfiguration.OpalRequest);
+  }
+
+  //
+  // Pass the current configuration to the BIOS
+  //
+  OpalHiiSetBrowserData ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Send BlockSid request through TPM physical presence module.
+
+  @param   PpRequest         TPM physical presence operation request.
+
+  @retval  EFI_SUCCESS       Do the required action success.
+  @retval  Others            Other error occur.
+
+**/
+EFI_STATUS
+HiiSetBlockSidAction (
+  IN UINT32          PpRequest
+  )
+{
+  UINT32                           ReturnCode;
+  EFI_STATUS                       Status;
+
+  ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (PpRequest, 0);
+  if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
+    Status = EFI_SUCCESS;
+  } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) {
+    Status = EFI_OUT_OF_RESOURCES;
+  } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) {
+    Status = EFI_UNSUPPORTED;
+  } else {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  return Status;
+}
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Configuration          A null-terminated Unicode string in <ConfigResp>
+                                 format.
+  @param  Progress               A pointer to a string filled in with the offset of
+                                 the most recent '&' before the first failing
+                                 name/value pair (or the beginning of the string if
+                                 the failure is in the first name/value pair) or
+                                 the terminating NULL if all was successful.
+
+  @retval EFI_SUCCESS            The Results is processed successfully.
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
+                                 driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig(
+  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
+  CONST EFI_STRING                        Configuration,
+  EFI_STRING                              *Progress
+  )
+{
+  if (Configuration == NULL || Progress == NULL) {
+    return (EFI_INVALID_PARAMETER);
+  }
+
+  *Progress = Configuration;
+  if (!HiiIsConfigHdrMatch (Configuration, &gHiiSetupVariableGuid, OpalPasswordStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  *Progress = Configuration + StrLen (Configuration);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Request                A null-terminated Unicode string in
+                                 <ConfigRequest> format.
+  @param  Progress               On return, points to a character in the Request
+                                 string. Points to the string's null terminator if
+                                 request was successful. Points to the most recent
+                                 '&' before the first failing name/value pair (or
+                                 the beginning of the string if the failure is in
+                                 the first name/value pair) if the request was not
+                                 successful.
+  @param  Results                A null-terminated Unicode string in
+                                 <ConfigAltResp> format which has all values filled
+                                 in for the names in the Request string. String to
+                                 be allocated by the called function.
+
+  @retval EFI_SUCCESS            The Results is filled with the requested values.
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
+  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
+                                 driver.
+
+**/
+EFI_STATUS
+EFIAPI
+ExtractConfig(
+  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
+  CONST EFI_STRING                        Request,
+  EFI_STRING                              *Progress,
+  EFI_STRING                              *Results
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_STRING                              ConfigRequest;
+  EFI_STRING                              ConfigRequestHdr;
+  UINTN                                   BufferSize;
+  UINTN                                   Size;
+  BOOLEAN                                 AllocatedRequest;
+  EFI_HANDLE                              DriverHandle;
+
+  //
+  // Check for valid parameters
+  //
+  if (Progress == NULL || Results == NULL) {
+    return (EFI_INVALID_PARAMETER);
+  }
+
+  *Progress = Request;
+  if ((Request != NULL) &&
+    !HiiIsConfigHdrMatch (Request, &gHiiSetupVariableGuid, OpalPasswordStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  AllocatedRequest = FALSE;
+  BufferSize = sizeof (OPAL_HII_CONFIGURATION);
+  ConfigRequest = Request;
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+    //
+    // Request has no request element, construct full request string.
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+    //
+    DriverHandle = HiiGetDriverImageHandleCB();
+    ConfigRequestHdr = HiiConstructConfigHdr (&gHiiSetupVariableGuid, OpalPasswordStorageName, DriverHandle);
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    if (ConfigRequest == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    AllocatedRequest = TRUE;
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+    FreePool (ConfigRequestHdr);
+  }
+
+  //
+  // Convert Buffer Data to <ConfigResp> by helper function BlockToConfig( )
+  //
+  Status = gHiiConfigRouting->BlockToConfig(
+               gHiiConfigRouting,
+               ConfigRequest,
+               (UINT8*)&gHiiConfiguration,
+               sizeof(OPAL_HII_CONFIGURATION),
+               Results,
+               Progress
+           );
+
+  //
+  // Free the allocated config request string.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+    ConfigRequest = NULL;
+  }
+
+  //
+  // Set Progress string to the original request string.
+  //
+  if (Request == NULL) {
+    *Progress = NULL;
+  } else if (StrStr (Request, L"OFFSET") == NULL) {
+    *Progress = Request + StrLen (Request);
+  }
+
+  return (Status);
+}
+
+
+/**
+
+  Pass the current system state to the bios via the hii_G_Configuration.
+
+**/
+VOID
+OpalHiiSetBrowserData (
+  VOID
+  )
+{
+  HiiSetBrowserData(
+      &gHiiSetupVariableGuid,
+      (CHAR16*)L"OpalHiiConfig",
+      sizeof(gHiiConfiguration),
+      (UINT8*)&gHiiConfiguration,
+      NULL
+  );
+}
+
+
+/**
+
+  Populate the hii_g_Configuraton with the browser Data.
+
+**/
+VOID
+OpalHiiGetBrowserData (
+  VOID
+  )
+{
+  HiiGetBrowserData(
+      &gHiiSetupVariableGuid,
+      (CHAR16*)L"OpalHiiConfig",
+      sizeof(gHiiConfiguration),
+      (UINT8*)&gHiiConfiguration
+  );
+}
+
+/**
+  Set a string Value in a form.
+
+  @param      DestStringId   The stringid which need to update.
+  @param      SrcAsciiStr    The string nned to update.
+
+  @retval  EFI_SUCCESS       Do the required action success.
+  @retval  Others            Other error occur.
+
+**/
+EFI_STATUS
+HiiSetFormString(
+  EFI_STRING_ID       DestStringId,
+  CHAR8               *SrcAsciiStr
+  )
+{
+  UINT32                    Len;
+  UINT32                    UniSize;
+  CHAR16*                   UniStr;
+
+  //
+  // Determine the Length of the sting
+  //
+  Len = ( UINT32 )AsciiStrLen( SrcAsciiStr );
+
+  //
+  // Allocate space for the unicode string, including terminator
+  //
+  UniSize = (Len + 1) * sizeof(CHAR16);
+  UniStr = (CHAR16*)AllocateZeroPool(UniSize);
+
+  //
+  // Copy into unicode string, then copy into string id
+  //
+  AsciiStrToUnicodeStrS ( SrcAsciiStr, UniStr, Len + 1);
+
+  //
+  // Update the string in the form
+  //
+  if (HiiSetString(gHiiPackageListHandle, DestStringId, UniStr, NULL) == 0) {
+    DEBUG ((DEBUG_INFO,  "HiiSetFormString( ) failed\n"));
+    FreePool(UniStr);
+    return (EFI_OUT_OF_RESOURCES);
+  }
+
+  //
+  // Free the memory
+  //
+  FreePool(UniStr);
+
+  return (EFI_SUCCESS);
+}
+
+/**
+  Initialize the Opal disk base on the hardware info get from device.
+
+  @param Dev                  The Opal device.
+
+  @retval EFI_SUCESS          Initialize the device success.
+  @retval EFI_DEVICE_ERROR    Get info from device failed.
+
+**/
+EFI_STATUS
+OpalDiskInitialize (
+  IN OPAL_DRIVER_DEVICE          *Dev
+  )
+{
+  TCG_RESULT                  TcgResult;
+  OPAL_SESSION                Session;
+
+  ZeroMem(&Dev->OpalDisk, sizeof(OPAL_DISK));
+  Dev->OpalDisk.Sscp = Dev->Sscp;
+  Dev->OpalDisk.MediaId = Dev->MediaId;
+  Dev->OpalDisk.OpalDevicePath = Dev->OpalDevicePath;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = Dev->Sscp;
+  Session.MediaId = Dev->MediaId;
+
+  TcgResult = OpalGetSupportedAttributesInfo (&Session, &Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.OpalBaseComId);
+  if (TcgResult != TcgResultSuccess) {
+    return EFI_DEVICE_ERROR;
+  }
+  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+  TcgResult = OpalUtilGetMsid (&Session, Dev->OpalDisk.Msid, OPAL_MSID_LENGHT, &Dev->OpalDisk.MsidLength);
+  if (TcgResult != TcgResultSuccess) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return OpalDiskUpdateStatus (&Dev->OpalDisk);
+}
+
+/**
+  Update the device info.
+
+  @param OpalDisk                The Opal device.
+
+  @retval EFI_SUCESS             Initialize the device success.
+  @retval EFI_DEVICE_ERROR       Get info from device failed.
+  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership info.
+
+**/
+EFI_STATUS
+OpalDiskUpdateStatus (
+  OPAL_DISK        *OpalDisk
+  )
+{
+  TCG_RESULT                  TcgResult;
+  OPAL_SESSION                Session;
+
+  ZeroMem(&Session, sizeof(Session));
+  Session.Sscp = OpalDisk->Sscp;
+  Session.MediaId = OpalDisk->MediaId;
+  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+  TcgResult = OpalGetLockingInfo(&Session, &OpalDisk->LockingFeature);
+  if (TcgResult != TcgResultSuccess) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (OpalDisk->MsidLength == 0) {
+    return EFI_INVALID_PARAMETER;
+  } else {
+    //
+    // Base on the Msid info to get the ownership, so Msid info must get first.
+    //
+    OpalDisk->Owner = OpalUtilDetermineOwnership(&Session, OpalDisk->Msid, OpalDisk->MsidLength);
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
new file mode 100644
index 000000000000..a1b1131c1380
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
@@ -0,0 +1,380 @@
+/** @file
+  Public Header file of HII library used by Opal UEFI Driver.
+  Defines required callbacks of Opal HII library.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_HII_H_
+#define _OPAL_HII_H_
+
+#include <Protocol/HiiConfigAccess.h>
+
+#include "OpalDriver.h"
+#include "OpalHiiFormValues.h"
+
+#define  OPAL_PASSWORD_CONFIG_GUID \
+  { \
+    0x0d510a4f, 0xa81b, 0x473f, { 0x87, 0x07, 0xb7, 0xfd, 0xfb, 0xc0, 0x45, 0xba } \
+  }
+
+#pragma pack(1)
+
+typedef struct {
+  UINT16 Id: HII_KEY_ID_BITS;
+  UINT16 Index: HII_KEY_INDEX_BITS;
+  UINT16 Flag: HII_KEY_FLAG_BITS;
+} KEY_BITS;
+
+typedef union {
+    UINT16    Raw;
+    KEY_BITS  KeyBits;
+} HII_KEY;
+
+typedef struct {
+    VENDOR_DEVICE_PATH             VendorDevicePath;
+    EFI_DEVICE_PATH_PROTOCOL       End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+extern const EFI_GUID gHiiSetupVariableGuid;
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Configuration          A null-terminated Unicode string in <ConfigResp>
+                                 format.
+  @param  Progress               A pointer to a string filled in with the offset of
+                                 the most recent '&' before the first failing
+                                 name/value pair (or the beginning of the string if
+                                 the failure is in the first name/value pair) or
+                                 the terminating NULL if all was successful.
+
+  @retval EFI_SUCCESS            The Results is processed successfully.
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
+                                 driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig(
+  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
+  CONST EFI_STRING                        Configuration,
+  EFI_STRING                              *Progress
+  );
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Request                A null-terminated Unicode string in
+                                 <ConfigRequest> format.
+  @param  Progress               On return, points to a character in the Request
+                                 string. Points to the string's null terminator if
+                                 request was successful. Points to the most recent
+                                 '&' before the first failing name/value pair (or
+                                 the beginning of the string if the failure is in
+                                 the first name/value pair) if the request was not
+                                 successful.
+  @param  Results                A null-terminated Unicode string in
+                                 <ConfigAltResp> format which has all values filled
+                                 in for the names in the Request string. String to
+                                 be allocated by the called function.
+
+  @retval EFI_SUCCESS            The Results is filled with the requested values.
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
+  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
+                                 driver.
+
+**/
+EFI_STATUS
+EFIAPI
+ExtractConfig(
+  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
+  CONST EFI_STRING                        Request,
+  EFI_STRING                              *Progress,
+  EFI_STRING                              *Results
+  );
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback(
+  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL*   This,
+  EFI_BROWSER_ACTION                      Action,
+  EFI_QUESTION_ID                         QuestionId,
+  UINT8                                   Type,
+  EFI_IFR_TYPE_VALUE*                     Value,
+  EFI_BROWSER_ACTION_REQUEST*             ActionRequest
+  );
+
+/**
+
+  Pass the current system state to the bios via the hii_G_Configuration.
+
+**/
+VOID
+OpalHiiSetBrowserData (
+  VOID
+  );
+
+/**
+
+  Populate the hii_g_Configuraton with the browser Data.
+
+**/
+VOID
+OpalHiiGetBrowserData (
+  VOID
+  );
+
+/**
+  Draws the disk info form.
+
+  @retval  EFI_SUCCESS       Draw the disk info success.
+
+**/
+EFI_STATUS
+HiiPopulateDiskInfoForm(
+  VOID
+  );
+
+/**
+  Update the global Disk index info.
+
+  @param   Index             The input disk index info.
+
+  @retval  EFI_SUCCESS       Update the disk index info success.
+
+**/
+EFI_STATUS
+HiiSelectDisk(
+  UINT8 Index
+  );
+
+/**
+  Use the input password to do the specified action.
+
+  @param      Str            The input password saved in.
+
+  @retval  EFI_SUCCESS       Do the required action success.
+  @retval  Others            Other error occur.
+
+**/
+EFI_STATUS
+HiiPasswordEntered(
+  EFI_STRING_ID            Str
+  );
+
+/**
+  Update block sid info.
+
+  @param      PpRequest      Input the Pp Request.
+
+  @retval  EFI_SUCCESS       Do the required action success.
+  @retval  Others            Other error occur.
+
+**/
+EFI_STATUS
+HiiSetBlockSidAction (
+  UINT32          PpRequest
+  );
+
+/**
+  Reverts the Opal disk to factory default.
+
+  @param   PsidStringId      The string id for the PSID info.
+
+  @retval  EFI_SUCCESS       Do the required action success.
+
+**/
+EFI_STATUS
+HiiPsidRevert(
+  EFI_STRING_ID         PsidStringId
+  );
+
+/**
+  Get disk name string id.
+
+  @param   DiskIndex             The input disk index info.
+
+  @retval  The disk name string id.
+
+**/
+EFI_STRING_ID
+GetDiskNameStringId(
+  UINT8 DiskIndex
+  );
+
+/**
+  Update the device info.
+
+  @param OpalDisk                The Opal device.
+
+  @retval EFI_SUCESS             Initialize the device success.
+  @retval EFI_DEVICE_ERROR       Get info from device failed.
+  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership info.
+
+**/
+EFI_STATUS
+OpalDiskUpdateStatus (
+  OPAL_DISK        *OpalDisk
+  );
+
+/**
+  Get the driver image handle.
+
+  @retval  the driver image handle.
+
+**/
+EFI_HANDLE
+HiiGetDriverImageHandleCB(
+  VOID
+  );
+
+/**
+  Install the HII form and string packages.
+
+  @retval  EFI_SUCCESS           Install all the resources success.
+  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
+**/
+EFI_STATUS
+OpalHiiAddPackages(
+  VOID
+  );
+
+/**
+  Check whether enable feature or not.
+
+  @retval  Return the disk number.
+
+**/
+UINT8
+HiiGetNumConfigRequiredOpalDisksCB(
+  VOID
+  );
+
+/**
+  Returns the driver name.
+
+  @retval Returns the driver name.
+
+**/
+CHAR16*
+HiiGetDriverNameCB(
+  VOID
+  );
+
+/**
+  Returns the opaque pointer to a physical disk context.
+
+  @param  DiskIndex       Input the disk index.
+
+  @retval The device pointer.
+
+**/
+OPAL_DISK*
+HiiGetOpalDiskCB(
+  UINT8 DiskIndex
+  );
+
+/**
+  Returns the disk name.
+
+  @param  DiskIndex       Input the disk index.
+
+  @retval Returns the disk name.
+
+**/
+CHAR8*
+HiiDiskGetNameCB(
+  UINT8 DiskIndex
+  );
+
+/**
+  Set a string Value in a form.
+
+  @param      DestStringId   The stringid which need to update.
+  @param      SrcAsciiStr    The string nned to update.
+
+  @retval  EFI_SUCCESS       Do the required action success.
+  @retval  Others            Other error occur.
+
+**/
+EFI_STATUS
+HiiSetFormString(
+  EFI_STRING_ID       DestStringId,
+  CHAR8               *SrcAsciiStr
+  );
+
+/**
+  Install the HII related resources.
+
+  @retval  EFI_SUCCESS        Install all the resources success.
+  @retval  other              Error occur when install the resources.
+**/
+EFI_STATUS
+HiiInstall(
+  VOID
+  );
+
+/**
+  Uninstall the HII capability.
+
+  @retval  EFI_SUCCESS           Uninstall all the resources success.
+  @retval  others                Other errors occur when unistall the hii resource.
+**/
+EFI_STATUS
+HiiUninstall(
+  VOID
+  );
+
+/**
+  Initialize the Opal disk base on the hardware info get from device.
+
+  @param Dev                  The Opal device.
+
+  @retval EFI_SUCESS          Initialize the device success.
+  @retval EFI_DEVICE_ERROR    Get info from device failed.
+
+**/
+EFI_STATUS
+OpalDiskInitialize (
+  IN OPAL_DRIVER_DEVICE          *Dev
+  );
+
+#endif // _HII_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
new file mode 100644
index 000000000000..b07e38c1449d
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
@@ -0,0 +1,219 @@
+/** @file
+  Callbacks required by the HII of the Opal UEFI Driver to help display
+  Opal device information.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalHii.h"
+
+/**
+  Get Opal var name.
+  The return Value must be freed by caller if not NULL
+
+  @param      OpalDisk       The disk.
+  @param      Prefix         The prefix string.
+
+  @retval  The var name string.
+
+**/
+CHAR16*
+OpalDriverGetOpalVarName(
+  OPAL_DISK        *OpalDisk,
+  const CHAR16     *Prefix
+  )
+{
+  OPAL_DRIVER_DEVICE*          Dev;
+  UINTN                        PrefixLen;
+  UINTN                        NameLen;
+  UINTN                        VarNameLen;
+  CHAR16*                      VarName;
+
+  Dev = DRIVER_DEVICE_FROM_OPALDISK(OpalDisk);
+  if (Dev == NULL) {
+    return NULL;
+  }
+
+  PrefixLen = StrLen(Prefix);
+
+  NameLen = 0;
+  if (Dev->Name16 != NULL) {
+    NameLen = StrLen(Dev->Name16);
+  }
+
+  VarNameLen = PrefixLen + NameLen;
+
+  VarName = (CHAR16*)AllocateZeroPool((VarNameLen + 1) * sizeof(CHAR16));
+  if (VarName == NULL) {
+    return NULL;
+  }
+
+  CopyMem(VarName, Prefix, PrefixLen * sizeof(CHAR16));
+  if (Dev->Name16 != NULL) {
+    CopyMem(VarName + PrefixLen, Dev->Name16, NameLen * sizeof(CHAR16));
+  }
+  VarName[VarNameLen] = 0;
+
+  return VarName;
+}
+
+/**
+  Get the driver image handle.
+
+  @retval  the driver image handle.
+
+**/
+EFI_HANDLE
+HiiGetDriverImageHandleCB(
+  VOID
+  )
+{
+  return gImageHandle;
+}
+
+/**
+  Check whether enable feature or not.
+
+  @retval  Return the disk number.
+
+**/
+UINT8
+HiiGetNumConfigRequiredOpalDisksCB(
+  VOID
+  )
+{
+  UINT8                        NumDisks;
+  UINT8                        NumLockedOpalDisks;
+  OPAL_DISK                    *OpalDisk;
+  UINT8                        Index;
+
+  NumLockedOpalDisks = 0;
+
+  NumDisks = GetDeviceCount();
+
+  for (Index = 0; Index < NumDisks; Index++) {
+    OpalDisk = HiiGetOpalDiskCB(Index);
+
+    if (OpalDisk != NULL) {
+      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
+        DEBUG ((DEBUG_INFO, "Ignoring disk %u because feature is disabled or health has already been inspected\n", Index));
+      } else if (OpalDeviceLocked (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
+        NumLockedOpalDisks++;
+      }
+    }
+  }
+
+  return NumLockedOpalDisks;
+}
+
+
+
+/**
+  Returns the opaque pointer to a physical disk context.
+
+  @param  DiskIndex       Input the disk index.
+
+  @retval The device pointer.
+
+**/
+VOID *
+HiiGetDiskContextCB(
+  UINT8 DiskIndex
+  )
+{
+  OPAL_DRIVER_DEVICE*                Dev;
+  UINT8                              CurrentDisk;
+
+  Dev = OpalDriverGetDeviceList();
+  CurrentDisk = 0;
+
+  if (DiskIndex >= GetDeviceCount()) {
+    return NULL;
+  }
+
+  while (Dev != NULL) {
+    if (CurrentDisk == DiskIndex) {
+      return Dev;
+    } else {
+      Dev = Dev->Next;
+      CurrentDisk++;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Returns the opaque pointer to a physical disk context.
+
+  @param  DiskIndex       Input the disk index.
+
+  @retval The device pointer.
+
+**/
+OPAL_DISK*
+HiiGetOpalDiskCB(
+  UINT8 DiskIndex
+  )
+{
+  VOID                           *Ctx;
+  OPAL_DRIVER_DEVICE             *Tmp;
+
+  Ctx = HiiGetDiskContextCB (DiskIndex);
+
+  if (Ctx == NULL) {
+    return NULL;
+  }
+
+  Tmp = (OPAL_DRIVER_DEVICE*) Ctx;
+
+  return &Tmp->OpalDisk;
+}
+
+/**
+  Returns the disk name.
+
+  @param  DiskIndex       Input the disk index.
+
+  @retval Returns the disk name.
+
+**/
+CHAR8*
+HiiDiskGetNameCB(
+  UINT8 DiskIndex
+  )
+{
+  OPAL_DRIVER_DEVICE*                Ctx;
+
+  Ctx = (OPAL_DRIVER_DEVICE*) HiiGetDiskContextCB (DiskIndex);
+
+  if (Ctx != NULL) {
+    if (Ctx->NameZ == NULL) {
+      OpalDriverGetDriverDeviceName (Ctx);
+    }
+    return Ctx->NameZ;
+  }
+  return NULL;
+}
+
+/**
+  Returns the driver name.
+
+  @retval Returns the driver name.
+
+**/
+CHAR16*
+HiiGetDriverNameCB(
+  VOID
+  )
+{
+  return (CHAR16*)EFI_DRIVER_NAME_UNICODE;
+}
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
new file mode 100644
index 000000000000..69abc561cc56
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
@@ -0,0 +1,84 @@
+// /** @file
+//
+//   String definitions for Setup formset.
+//
+// Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+/=#
+/////////////////////////////////   GENERIC DEFINITIONS   /////////////////////////////////
+#langdef en-US                                  "English"
+#string STR_NULL                                #language en-US " "
+
+/////////////////////////////////   FORM SET   /////////////////////////////////
+#string STR_FORM_SET_HELP                        #language en-US "Manage Opal disks"
+
+/////////////////////////////////   MULTIPLE FORMS   /////////////////////////////////
+#string STR_OPAL                                 #language en-US "Opal"
+#string STR_MAIN_OPAL_VERSION                    #language en-US "Version 00.0.0.0000"
+
+/////////////////////////////////   MAIN MENU FORM   /////////////////////////////////
+#string STR_MAIN_PHY_DISKS_LBL                   #language en-US "Physical Disks:"
+
+#string STR_MAIN_GOTO_DISK_INFO_0                #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_1                #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_2                #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_3                #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_4                #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_5                #language en-US " "
+
+#string STR_MAIN_GOTO_DISK_INFO_HELP             #language en-US "Select to see Opal disk actions"
+
+#string STR_MAIN_NO_DISKS_PRESENT_LBL            #language en-US "No disks connected to system"
+
+/////////////////////////////////   DISK INFO MENU FORM   /////////////////////////////////
+#string STR_DISK_INFO_SELECTED_DISK_NAME         #language en-US " "
+
+#string STR_DISK_INFO_LOCK                       #language en-US "Lock"
+#string STR_DISK_INFO_UNLOCK                     #language en-US "Unlock"
+#string STR_DISK_INFO_SET_ADMIN_PSWD             #language en-US "Update Drive Admin Password"
+#string STR_DISK_INFO_SET_USER_PSWD              #language en-US "Set Drive User Password"
+#string STR_DISK_INFO_SECURE_ERASE               #language en-US "Secure Erase User Data"
+#string STR_DISK_INFO_PSID_REVERT                #language en-US "PSID Revert to factory default"
+#string STR_DISK_INFO_REVERT                     #language en-US "Admin Revert to factory default and Disable"
+#string STR_DISK_INFO_DISABLE_USER               #language en-US "Disable User"
+#string STR_DISK_INFO_ENABLE_FEATURE             #language en-US "Enable Feature"
+#string STR_DISK_INFO_ENABLE_BLOCKSID            #language en-US "TCG Storage Action"
+#string STR_ENABLED                              #language en-US "Enable BlockSID"
+#string STR_DISABLED                             #language en-US "Disable BlockSID"
+
+#string STR_NONE                                 #language en-US "None"
+#string STR_DISK_INFO_ENABLE_BLOCKSID_TRUE       #language en-US "Require physical presence when remote enable BlockSID"
+#string STR_DISK_INFO_ENABLE_BLOCKSID_FALSE      #language en-US "Not require physical presence when remote enable BlockSID"
+#string STR_DISK_INFO_DISABLE_BLOCKSID_TRUE      #language en-US "Require physical presence when remote disable BlockSID"
+#string STR_DISK_INFO_DISABLE_BLOCKSID_FALSE     #language en-US "Not require physical presence when remote disable BlockSID"
+
+#string STR_BLOCKSID_STATUS_HELP                 #language en-US "BlockSID action change status"
+#string STR_BLOCKSID_STATUS                      #language en-US "Current BlockSID Status:"
+#string STR_BLOCKSID_STATUS1                     #language en-US ""
+#string STR_BLOCKSID_STATUS2                     #language en-US ""
+#string STR_BLOCKSID_STATUS3                     #language en-US ""
+
+#string STR_OPAL_REQUESTS_LBL                    #language en-US "Opal Requests:"
+#string STR_DISK_INFO_LOCK_HELP                  #language en-US "Lock the disk"
+#string STR_DISK_INFO_UNLOCK_HELP                #language en-US "Unlock the disk"
+#string STR_DISK_INFO_SET_ADMIN_PSWD_HELP        #language en-US "Set password for the administrator"
+#string STR_DISK_INFO_SET_USER_PSWD_HELP         #language en-US "Set password for User 1"
+#string STR_DISK_INFO_SECURE_ERASE_HELP          #language en-US "Securely erase the disk"
+#string STR_DISK_INFO_REVERT_HELP                #language en-US "Revert the disk to factory defaults"
+#string STR_DISK_INFO_PSID_REVERT_HELP           #language en-US "Revert the disk to factory defaults, PSID is a 32 character case sensitive value"
+#string STR_DISK_INFO_DISABLE_USER_HELP          #language en-US "Disable User"
+#string STR_DISK_INFO_ENABLE_FEATURE_HELP        #language en-US "Enable Feature"
+#string STR_KEEP_USER_DATA_PROMPT                #language en-US "  Keep User Data"
+#string STR_KEEP_USER_DATA_HELP                  #language en-US "Check to keep user data, otherwise data will be lost"
+
+#string STR_DISK_INFO_ENABLE_BLOCKSID_HELP       #language en-US "Change BlockSID actions, includes enable or disable BlockSID, Require or not require physical presence when remote enable or disable BlockSID"
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
new file mode 100644
index 000000000000..3ff7d4726d5e
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
@@ -0,0 +1,123 @@
+/** @file
+  Defines Opal HII form ids, structures and values.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef _OPAL_HII_FORM_VALUES_H_
+#define _OPAL_HII_FORM_VALUES_H_
+
+// ID's for various forms that will be used by HII
+#define FORMID_VALUE_MAIN_MENU                             0x01
+#define FORMID_VALUE_DISK_INFO_FORM_MAIN                   0x02
+
+#define OPAL_REQUEST_VARIABLE_NAME                         L"OpalRequest"
+
+#pragma pack(1)
+typedef struct {
+  UINT16    Lock:1;
+  UINT16    Unlock:1;
+  UINT16    SetAdminPwd:1;
+  UINT16    SetUserPwd:1;
+  UINT16    SecureErase:1;
+  UINT16    Revert:1;
+  UINT16    PsidRevert:1;
+  UINT16    DisableUser:1;
+  UINT16    DisableFeature:1;
+  UINT16    EnableFeature:1;
+  UINT16    Reserved:5;
+  UINT16    KeepUserData:1;
+} OPAL_REQUEST;
+
+typedef struct {
+  UINT8           NumDisks;
+  UINT8           SelectedDiskIndex;
+  UINT16          SelectedDiskAvailableActions;
+  UINT16          SupportedDisks;
+  BOOLEAN         KeepUserDataForced;
+  OPAL_REQUEST    OpalRequest;
+  UINT8           EnableBlockSid;
+} OPAL_HII_CONFIGURATION;
+
+typedef struct {
+  UINT32                   Length;
+  OPAL_REQUEST             OpalRequest;
+  //EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
+} OPAL_REQUEST_VARIABLE;
+
+#pragma pack()
+
+/* Action Flags */
+#define HII_ACTION_NONE                                        0x0000
+#define HII_ACTION_LOCK                                        0x0001
+#define HII_ACTION_UNLOCK                                      0x0002
+#define HII_ACTION_SET_ADMIN_PWD                               0x0004
+#define HII_ACTION_SET_USER_PWD                                0x0008
+#define HII_ACTION_SECURE_ERASE                                0x0010
+#define HII_ACTION_REVERT                                      0x0020
+#define HII_ACTION_PSID_REVERT                                 0x0040
+#define HII_ACTION_DISABLE_USER                                0x0080
+#define HII_ACTION_DISABLE_FEATURE                             0x0100
+#define HII_ACTION_ENABLE_FEATURE                              0x0200
+
+/* Number of bits allocated for each part of a unique key for an HII_ITEM
+ * all bits together must be <= 16 (EFI_QUESTION_ID is UINT16)
+ * 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
+ * |   |-----------------------|   |---------------------------|
+ * FLG INDEX                       ID
+ */
+#define HII_KEY_ID_BITS                                     8
+#define HII_KEY_INDEX_BITS                                  7
+#define HII_KEY_FLAG_BITS                                   1
+
+#define HII_KEY_FLAG                                        0x8000 // bit 15 (zero based)
+
+/***********/
+/* Key IDs */
+/***********/
+
+#define HII_KEY_ID_GOTO_DISK_INFO                       1
+
+#define HII_KEY_ID_VAR_SUPPORTED_DISKS                  2
+#define HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS  3
+
+#define HII_KEY_ID_BLOCKSID                             4
+#define HII_KEY_ID_SET_ADMIN_PWD                        5
+#define HII_KEY_ID_SET_USER_PWD                         6
+#define HII_KEY_ID_SECURE_ERASE                         7
+#define HII_KEY_ID_REVERT                               8
+#define HII_KEY_ID_KEEP_USER_DATA                       9
+#define HII_KEY_ID_PSID_REVERT                          0xA
+#define HII_KEY_ID_DISABLE_USER                         0xB
+#define HII_KEY_ID_ENABLE_FEATURE                       0xC
+
+#define HII_KEY_ID_MAX                                  0xC // !!Update each time a new ID is added!!
+
+#define HII_KEY_WITH_INDEX(id, index) \
+    ( \
+        HII_KEY_FLAG | \
+        (id) | \
+        ((index) << HII_KEY_ID_BITS) \
+    )
+
+#define HII_KEY(id) HII_KEY_WITH_INDEX(id, 0)
+
+#define PACKAGE_LIST_GUID { 0xf0308176, 0x9058, 0x4153, { 0x93, 0x3d, 0xda, 0x2f, 0xdc, 0xc8, 0x3e, 0x44 } }
+
+/* {410483CF-F4F9-4ece-848A-1958FD31CEB7} */
+#define SETUP_FORMSET_GUID { 0x410483cf, 0xf4f9, 0x4ece, { 0x84, 0x8a, 0x19, 0x58, 0xfd, 0x31, 0xce, 0xb7 } }
+
+// {BBF1ACD2-28D8-44ea-A291-58A237FEDF1A}
+#define SETUP_VARIABLE_GUID { 0xbbf1acd2, 0x28d8, 0x44ea, { 0xa2, 0x91, 0x58, 0xa2, 0x37, 0xfe, 0xdf, 0x1a } }
+
+#endif //_HII_FORM_VALUES_H_
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
new file mode 100644
index 000000000000..7657bb26e23c
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
@@ -0,0 +1,2144 @@
+/** @file
+  Provide functions to initialize NVME controller and perform NVME commands
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalPasswordPei.h"
+
+
+#define ALIGN(v, a)                         (UINTN)((((v) - 1) | ((a) - 1)) + 1)
+
+///
+/// NVME Host controller registers operation
+///
+#define NVME_GET_CAP(Nvme, Cap)             NvmeMmioRead  (Cap, Nvme->Nbar + NVME_CAP_OFFSET, sizeof (NVME_CAP))
+#define NVME_GET_CC(Nvme, Cc)               NvmeMmioRead  (Cc, Nvme->Nbar + NVME_CC_OFFSET, sizeof (NVME_CC))
+#define NVME_SET_CC(Nvme, Cc)               NvmeMmioWrite (Nvme->Nbar + NVME_CC_OFFSET, Cc, sizeof (NVME_CC))
+#define NVME_GET_CSTS(Nvme, Csts)           NvmeMmioRead  (Csts, Nvme->Nbar + NVME_CSTS_OFFSET, sizeof (NVME_CSTS))
+#define NVME_GET_AQA(Nvme, Aqa)             NvmeMmioRead  (Aqa, Nvme->Nbar + NVME_AQA_OFFSET, sizeof (NVME_AQA))
+#define NVME_SET_AQA(Nvme, Aqa)             NvmeMmioWrite (Nvme->Nbar + NVME_AQA_OFFSET, Aqa, sizeof (NVME_AQA))
+#define NVME_GET_ASQ(Nvme, Asq)             NvmeMmioRead  (Asq, Nvme->Nbar + NVME_ASQ_OFFSET, sizeof (NVME_ASQ))
+#define NVME_SET_ASQ(Nvme, Asq)             NvmeMmioWrite (Nvme->Nbar + NVME_ASQ_OFFSET, Asq, sizeof (NVME_ASQ))
+#define NVME_GET_ACQ(Nvme, Acq)             NvmeMmioRead  (Acq, Nvme->Nbar + NVME_ACQ_OFFSET, sizeof (NVME_ACQ))
+#define NVME_SET_ACQ(Nvme, Acq)             NvmeMmioWrite (Nvme->Nbar + NVME_ACQ_OFFSET, Acq, sizeof (NVME_ACQ))
+#define NVME_GET_VER(Nvme, Ver)             NvmeMmioRead  (Ver, Nvme->Nbar + NVME_VER_OFFSET, sizeof (NVME_VER))
+#define NVME_SET_SQTDBL(Nvme, Qid, Sqtdbl)  NvmeMmioWrite (Nvme->Nbar + NVME_SQTDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Sqtdbl, sizeof (NVME_SQTDBL))
+#define NVME_SET_CQHDBL(Nvme, Qid, Cqhdbl)  NvmeMmioWrite (Nvme->Nbar + NVME_CQHDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Cqhdbl, sizeof (NVME_CQHDBL))
+
+///
+/// Base memory address
+///
+enum {
+  BASEMEM_CONTROLLER_DATA,
+  BASEMEM_IDENTIFY_DATA,
+  BASEMEM_ASQ,
+  BASEMEM_ACQ,
+  BASEMEM_SQ,
+  BASEMEM_CQ,
+  BASEMEM_PRP,
+  BASEMEM_SECURITY,
+  MAX_BASEMEM_COUNT
+};
+
+///
+/// All of base memories are 4K(0x1000) alignment
+///
+#define NVME_MEM_BASE(Nvme)                 ((UINTN)(Nvme->BaseMem))
+#define NVME_CONTROL_DATA_BASE(Nvme)        (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CONTROLLER_DATA))                        * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_NAMESPACE_DATA_BASE(Nvme)      (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_IDENTIFY_DATA))                          * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_ASQ_BASE(Nvme)                 (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ASQ))                                    * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_ACQ_BASE(Nvme)                 (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ACQ))                                    * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_SQ_BASE(Nvme, index)           (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SQ) + ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_CQ_BASE(Nvme, index)           (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CQ) + ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_PRP_BASE(Nvme, index)          (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_PRP) + ((index)*NVME_PRP_SIZE))          * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+#define NVME_SEC_BASE(Nvme)                 (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SECURITY))                               * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
+
+/**
+  Transfer MMIO Data to memory.
+
+  @param[in,out] MemBuffer - Destination: Memory address
+  @param[in] MmioAddr      - Source: MMIO address
+  @param[in] Size          - Size for read
+
+  @retval EFI_SUCCESS - MMIO read sucessfully
+**/
+EFI_STATUS
+NvmeMmioRead (
+  IN OUT VOID *MemBuffer,
+  IN     UINTN MmioAddr,
+  IN     UINTN Size
+  )
+{
+  UINTN  Offset;
+  UINT8  Data;
+  UINT8  *Ptr;
+
+  // priority has adjusted
+  switch (Size) {
+    case 4:
+      *((UINT32 *)MemBuffer) = MmioRead32 (MmioAddr);
+      break;
+
+    case 8:
+      *((UINT64 *)MemBuffer) = MmioRead64 (MmioAddr);
+      break;
+
+    case 2:
+      *((UINT16 *)MemBuffer) = MmioRead16 (MmioAddr);
+      break;
+
+    case 1:
+      *((UINT8 *)MemBuffer) = MmioRead8 (MmioAddr);
+      break;
+
+    default:
+      Ptr = (UINT8 *)MemBuffer;
+      for (Offset = 0; Offset < Size; Offset += 1) {
+        Data = MmioRead8 (MmioAddr + Offset);
+        Ptr[Offset] = Data;
+      }
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Transfer memory data to MMIO.
+
+  @param[in,out] MmioAddr - Destination: MMIO address
+  @param[in] MemBuffer    - Source: Memory address
+  @param[in] Size         - Size for write
+
+  @retval EFI_SUCCESS - MMIO write sucessfully
+**/
+EFI_STATUS
+NvmeMmioWrite (
+  IN OUT UINTN MmioAddr,
+  IN     VOID *MemBuffer,
+  IN     UINTN Size
+  )
+{
+  UINTN  Offset;
+  UINT8  Data;
+  UINT8  *Ptr;
+
+  // priority has adjusted
+  switch (Size) {
+    case 4:
+      MmioWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
+      break;
+
+    case 8:
+      MmioWrite64 (MmioAddr, *((UINT64 *)MemBuffer));
+      break;
+
+    case 2:
+      MmioWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
+      break;
+
+    case 1:
+      MmioWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
+      break;
+
+    default:
+      Ptr = (UINT8 *)MemBuffer;
+      for (Offset = 0; Offset < Size; Offset += 1) {
+        Data = Ptr[Offset];
+        MmioWrite8 (MmioAddr + Offset, Data);
+      }
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Transfer MMIO data to memory.
+
+  @param[in,out] MemBuffer - Destination: Memory address
+  @param[in] MmioAddr      - Source: MMIO address
+  @param[in] Size          - Size for read
+
+  @retval EFI_SUCCESS - MMIO read sucessfully
+**/
+EFI_STATUS
+OpalPciRead (
+  IN OUT VOID *MemBuffer,
+  IN     UINTN MmioAddr,
+  IN     UINTN Size
+  )
+{
+  UINTN  Offset;
+  UINT8  Data;
+  UINT8  *Ptr;
+
+  // priority has adjusted
+  switch (Size) {
+    case 4:
+      *((UINT32 *)MemBuffer) = PciRead32 (MmioAddr);
+      break;
+
+    case 2:
+      *((UINT16 *)MemBuffer) = PciRead16 (MmioAddr);
+      break;
+
+    case 1:
+      *((UINT8 *)MemBuffer) = PciRead8 (MmioAddr);
+      break;
+
+    default:
+      Ptr = (UINT8 *)MemBuffer;
+      for (Offset = 0; Offset < Size; Offset += 1) {
+        Data = PciRead8 (MmioAddr + Offset);
+        Ptr[Offset] = Data;
+      }
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Transfer memory data to MMIO.
+
+  @param[in,out] MmioAddr - Destination: MMIO address
+  @param[in] MemBuffer    - Source: Memory address
+  @param[in] Size         - Size for write
+
+  @retval EFI_SUCCESS - MMIO write sucessfully
+**/
+EFI_STATUS
+OpalPciWrite (
+  IN OUT UINTN MmioAddr,
+  IN     VOID *MemBuffer,
+  IN     UINTN Size
+  )
+{
+  UINTN  Offset;
+  UINT8  Data;
+  UINT8  *Ptr;
+
+  // priority has adjusted
+  switch (Size) {
+    case 4:
+      PciWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
+      break;
+
+    case 2:
+      PciWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
+      break;
+
+    case 1:
+      PciWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
+      break;
+
+    default:
+      Ptr = (UINT8 *)MemBuffer;
+      for (Offset = 0; Offset < Size; Offset += 1) {
+        Data = Ptr[Offset];
+        PciWrite8 (MmioAddr + Offset, Data);
+      }
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get total pages for specific NVME based memory.
+
+  @param[in] BaseMemIndex           - The Index of BaseMem (0-based).
+
+  @retval - The page count for specific BaseMem Index
+
+**/
+UINT32
+NvmeGetBaseMemPages (
+  IN UINTN              BaseMemIndex
+  )
+{
+  UINT32                Pages;
+  UINTN                 Index;
+  UINT32                PageSizeList[8];
+
+  PageSizeList[0] = 1;  /* Controller Data */
+  PageSizeList[1] = 1;  /* Identify Data */
+  PageSizeList[2] = 1;  /* ASQ */
+  PageSizeList[3] = 1;  /* ACQ */
+  PageSizeList[4] = 1;  /* SQs */
+  PageSizeList[5] = 1;  /* CQs */
+  PageSizeList[6] = NVME_PRP_SIZE * NVME_CSQ_DEPTH;  /* PRPs */
+  PageSizeList[7] = 1;  /* Security Commands */
+
+  if (BaseMemIndex > MAX_BASEMEM_COUNT) {
+    ASSERT (FALSE);
+    return 0;
+  }
+
+  Pages = 0;
+  for (Index = 0; Index < BaseMemIndex; Index++) {
+    Pages += PageSizeList[Index];
+  }
+
+  return Pages;
+}
+
+/**
+  Wait for NVME controller status to be ready or not.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] WaitReady              - Flag for waitting status ready or not
+
+  @return EFI_SUCCESS               - Successfully to wait specific status.
+  @return others                    - Fail to wait for specific controller status.
+
+**/
+STATIC
+EFI_STATUS
+NvmeWaitController (
+  IN NVME_CONTEXT       *Nvme,
+  IN BOOLEAN            WaitReady
+  )
+{
+  NVME_CSTS              Csts;
+  EFI_STATUS             Status;
+  UINT32                 Index;
+  UINT8                  Timeout;
+
+  //
+  // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
+  // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
+  //
+  if (Nvme->Cap.To == 0) {
+    Timeout = 1;
+  } else {
+    Timeout = Nvme->Cap.To;
+  }
+
+  Status = EFI_SUCCESS;
+  for(Index = (Timeout * 500); Index != 0; --Index) {
+    MicroSecondDelay (1000);
+
+    //
+    // Check if the controller is initialized
+    //
+    Status = NVME_GET_CSTS (Nvme, &Csts);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n", Status));
+      return Status;
+    }
+
+    if ((BOOLEAN) Csts.Rdy == WaitReady) {
+      break;
+    }
+  }
+
+  if (Index == 0) {
+    Status = EFI_TIMEOUT;
+  }
+
+  return Status;
+}
+
+/**
+  Disable the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully disable the controller.
+  @return others                    - Fail to disable the controller.
+
+**/
+STATIC
+EFI_STATUS
+NvmeDisableController (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  NVME_CC                Cc;
+  NVME_CSTS              Csts;
+  EFI_STATUS             Status;
+
+  Status = NVME_GET_CSTS (Nvme, &Csts);
+
+  ///
+  /// Read Controller Configuration Register.
+  ///
+  Status = NVME_GET_CC (Nvme, &Cc);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
+    goto Done;
+  }
+
+  if (Cc.En == 1) {
+    Cc.En = 0;
+    ///
+    /// Disable the controller.
+    ///
+    Status = NVME_SET_CC (Nvme, &Cc);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
+      goto Done;
+    }
+  }
+
+  Status = NvmeWaitController (Nvme, FALSE);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n", Status));
+    goto Done;
+  }
+
+  return EFI_SUCCESS;
+
+Done:
+  DEBUG ((DEBUG_INFO, "NvmeDisableController fail, Status: %r\n", Status));
+  return Status;
+}
+
+/**
+  Enable the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully enable the controller.
+  @return EFI_DEVICE_ERROR          - Fail to enable the controller.
+  @return EFI_TIMEOUT               - Fail to enable the controller in given time slot.
+
+**/
+STATIC
+EFI_STATUS
+NvmeEnableController (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  NVME_CC                Cc;
+  EFI_STATUS             Status;
+
+  //
+  // Enable the controller
+  //
+  ZeroMem (&Cc, sizeof (NVME_CC));
+  Cc.En     = 1;
+  Cc.Iosqes = 6;
+  Cc.Iocqes = 4;
+  Status    = NVME_SET_CC (Nvme, &Cc);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
+    goto Done;
+  }
+
+  Status = NvmeWaitController (Nvme, TRUE);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n", Status));
+    goto Done;
+  }
+
+  return EFI_SUCCESS;
+
+Done:
+  DEBUG ((DEBUG_INFO, "NvmeEnableController fail, Status: %r\n", Status));
+  return Status;
+}
+
+/**
+  Shutdown the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully shutdown the controller.
+  @return EFI_DEVICE_ERROR          - Fail to shutdown the controller.
+  @return EFI_TIMEOUT               - Fail to shutdown the controller in given time slot.
+
+**/
+STATIC
+EFI_STATUS
+NvmeShutdownController (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  NVME_CC                Cc;
+  NVME_CSTS              Csts;
+  EFI_STATUS             Status;
+  UINT32                 Index;
+  UINTN                  Timeout;
+
+  Status    = NVME_GET_CC (Nvme, &Cc);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
+    return Status;
+  }
+
+  Cc.Shn     = 1; // Normal shutdown
+
+  Status    = NVME_SET_CC (Nvme, &Cc);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
+    return Status;
+  }
+
+  Timeout = NVME_GENERIC_TIMEOUT/1000; // ms
+  for(Index = (UINT32)(Timeout); Index != 0; --Index) {
+    MicroSecondDelay (1000);
+
+    Status = NVME_GET_CSTS (Nvme, &Csts);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n", Status));
+      return Status;
+    }
+
+    if (Csts.Shst == 2) { // Shutdown processing complete
+      break;
+    }
+  }
+
+  if (Index == 0) {
+    Status = EFI_TIMEOUT;
+  }
+
+  return Status;
+}
+
+/**
+  Check the execution status from a given completion queue entry.
+
+  @param[in]     Cq                 - A pointer to the NVME_CQ item.
+
+**/
+EFI_STATUS
+NvmeCheckCqStatus (
+  IN NVME_CQ             *Cq
+  )
+{
+  if (Cq->Sct == 0x0 && Cq->Sc == 0x0) {
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_INFO, "Dump NVMe Completion Entry Status from [0x%x]:\n", (UINTN)Cq));
+  DEBUG ((DEBUG_INFO, "  SQ Identifier : [0x%x], Phase Tag : [%d], Cmd Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
+  DEBUG ((DEBUG_INFO, "  NVMe Cmd Execution Result - "));
+
+  switch (Cq->Sct) {
+    case 0x0:
+      switch (Cq->Sc) {
+        case 0x0:
+          DEBUG ((DEBUG_INFO, "Successful Completion\n"));
+          return EFI_SUCCESS;
+        case 0x1:
+          DEBUG ((DEBUG_INFO, "Invalid Command Opcode\n"));
+          break;
+        case 0x2:
+          DEBUG ((DEBUG_INFO, "Invalid Field in Command\n"));
+          break;
+        case 0x3:
+          DEBUG ((DEBUG_INFO, "Command ID Conflict\n"));
+          break;
+        case 0x4:
+          DEBUG ((DEBUG_INFO, "Data Transfer Error\n"));
+          break;
+        case 0x5:
+          DEBUG ((DEBUG_INFO, "Commands Aborted due to Power Loss Notification\n"));
+          break;
+        case 0x6:
+          DEBUG ((DEBUG_INFO, "Internal Device Error\n"));
+          break;
+        case 0x7:
+          DEBUG ((DEBUG_INFO, "Command Abort Requested\n"));
+          break;
+        case 0x8:
+          DEBUG ((DEBUG_INFO, "Command Aborted due to SQ Deletion\n"));
+          break;
+        case 0x9:
+          DEBUG ((DEBUG_INFO, "Command Aborted due to Failed Fused Command\n"));
+          break;
+        case 0xA:
+          DEBUG ((DEBUG_INFO, "Command Aborted due to Missing Fused Command\n"));
+          break;
+        case 0xB:
+          DEBUG ((DEBUG_INFO, "Invalid Namespace or Format\n"));
+          break;
+        case 0xC:
+          DEBUG ((DEBUG_INFO, "Command Sequence Error\n"));
+          break;
+        case 0xD:
+          DEBUG ((DEBUG_INFO, "Invalid SGL Last Segment Descriptor\n"));
+          break;
+        case 0xE:
+          DEBUG ((DEBUG_INFO, "Invalid Number of SGL Descriptors\n"));
+          break;
+        case 0xF:
+          DEBUG ((DEBUG_INFO, "Data SGL Length Invalid\n"));
+          break;
+        case 0x10:
+          DEBUG ((DEBUG_INFO, "Metadata SGL Length Invalid\n"));
+          break;
+        case 0x11:
+          DEBUG ((DEBUG_INFO, "SGL Descriptor Type Invalid\n"));
+          break;
+        case 0x80:
+          DEBUG ((DEBUG_INFO, "LBA Out of Range\n"));
+          break;
+        case 0x81:
+          DEBUG ((DEBUG_INFO, "Capacity Exceeded\n"));
+          break;
+        case 0x82:
+          DEBUG ((DEBUG_INFO, "Namespace Not Ready\n"));
+          break;
+        case 0x83:
+          DEBUG ((DEBUG_INFO, "Reservation Conflict\n"));
+          break;
+      }
+      break;
+
+    case 0x1:
+      switch (Cq->Sc) {
+        case 0x0:
+          DEBUG ((DEBUG_INFO, "Completion Queue Invalid\n"));
+          break;
+        case 0x1:
+          DEBUG ((DEBUG_INFO, "Invalid Queue Identifier\n"));
+          break;
+        case 0x2:
+          DEBUG ((DEBUG_INFO, "Maximum Queue Size Exceeded\n"));
+          break;
+        case 0x3:
+          DEBUG ((DEBUG_INFO, "Abort Command Limit Exceeded\n"));
+          break;
+        case 0x5:
+          DEBUG ((DEBUG_INFO, "Asynchronous Event Request Limit Exceeded\n"));
+          break;
+        case 0x6:
+          DEBUG ((DEBUG_INFO, "Invalid Firmware Slot\n"));
+          break;
+        case 0x7:
+          DEBUG ((DEBUG_INFO, "Invalid Firmware Image\n"));
+          break;
+        case 0x8:
+          DEBUG ((DEBUG_INFO, "Invalid Interrupt Vector\n"));
+          break;
+        case 0x9:
+          DEBUG ((DEBUG_INFO, "Invalid Log Page\n"));
+          break;
+        case 0xA:
+          DEBUG ((DEBUG_INFO, "Invalid Format\n"));
+          break;
+        case 0xB:
+          DEBUG ((DEBUG_INFO, "Firmware Application Requires Conventional Reset\n"));
+          break;
+        case 0xC:
+          DEBUG ((DEBUG_INFO, "Invalid Queue Deletion\n"));
+          break;
+        case 0xD:
+          DEBUG ((DEBUG_INFO, "Feature Identifier Not Saveable\n"));
+          break;
+        case 0xE:
+          DEBUG ((DEBUG_INFO, "Feature Not Changeable\n"));
+          break;
+        case 0xF:
+          DEBUG ((DEBUG_INFO, "Feature Not Namespace Specific\n"));
+          break;
+        case 0x10:
+          DEBUG ((DEBUG_INFO, "Firmware Application Requires NVM Subsystem Reset\n"));
+          break;
+        case 0x80:
+          DEBUG ((DEBUG_INFO, "Conflicting Attributes\n"));
+          break;
+        case 0x81:
+          DEBUG ((DEBUG_INFO, "Invalid Protection Information\n"));
+          break;
+        case 0x82:
+          DEBUG ((DEBUG_INFO, "Attempted Write to Read Only Range\n"));
+          break;
+      }
+      break;
+
+    case 0x2:
+      switch (Cq->Sc) {
+        case 0x80:
+          DEBUG ((DEBUG_INFO, "Write Fault\n"));
+          break;
+        case 0x81:
+          DEBUG ((DEBUG_INFO, "Unrecovered Read Error\n"));
+          break;
+        case 0x82:
+          DEBUG ((DEBUG_INFO, "End-to-end Guard Check Error\n"));
+          break;
+        case 0x83:
+          DEBUG ((DEBUG_INFO, "End-to-end Application Tag Check Error\n"));
+          break;
+        case 0x84:
+          DEBUG ((DEBUG_INFO, "End-to-end Reference Tag Check Error\n"));
+          break;
+        case 0x85:
+          DEBUG ((DEBUG_INFO, "Compare Failure\n"));
+          break;
+        case 0x86:
+          DEBUG ((DEBUG_INFO, "Access Denied\n"));
+          break;
+      }
+      break;
+
+    default:
+      DEBUG ((DEBUG_INFO, "Unknown error\n"));
+      break;
+  }
+
+  return EFI_DEVICE_ERROR;
+}
+
+/**
+  Create PRP lists for Data transfer which is larger than 2 memory pages.
+  Note here we calcuate the number of required PRP lists and allocate them at one time.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] SqId                   - The SQ index for this PRP
+  @param[in] PhysicalAddr           - The physical base address of Data Buffer.
+  @param[in] Pages                  - The number of pages to be transfered.
+  @param[out] PrpListHost           - The host base address of PRP lists.
+  @param[in,out] PrpListNo          - The number of PRP List.
+
+  @retval The pointer Value to the first PRP List of the PRP lists.
+
+**/
+STATIC
+UINT64
+NvmeCreatePrpList (
+  IN     NVME_CONTEXT                 *Nvme,
+  IN     UINT16                       SqId,
+  IN     EFI_PHYSICAL_ADDRESS         PhysicalAddr,
+  IN     UINTN                        Pages,
+     OUT VOID                         **PrpListHost,
+  IN OUT UINTN                        *PrpListNo
+  )
+{
+  UINTN                       PrpEntryNo;
+  UINT64                      PrpListBase;
+  UINTN                       PrpListIndex;
+  UINTN                       PrpEntryIndex;
+  UINT64                      Remainder;
+  EFI_PHYSICAL_ADDRESS        PrpListPhyAddr;
+  UINTN                       Bytes;
+  UINT8                       *PrpEntry;
+  EFI_PHYSICAL_ADDRESS        NewPhyAddr;
+
+  ///
+  /// The number of Prp Entry in a memory page.
+  ///
+  PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
+
+  ///
+  /// Calculate total PrpList number.
+  ///
+  *PrpListNo = (UINTN) DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo, &Remainder);
+  if (Remainder != 0) {
+    *PrpListNo += 1;
+  }
+
+  if (*PrpListNo > NVME_PRP_SIZE) {
+    DEBUG ((DEBUG_INFO, "NvmeCreatePrpList (PhysicalAddr: %lx, Pages: %x) PrpEntryNo: %x\n",
+      PhysicalAddr, Pages, PrpEntryNo));
+    DEBUG ((DEBUG_INFO, "*PrpListNo: %x, Remainder: %lx", *PrpListNo, Remainder));
+    ASSERT (FALSE);
+  }
+  *PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Nvme, SqId);
+
+  Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
+  PrpListPhyAddr = (UINT64)(UINTN)(*PrpListHost);
+
+  ///
+  /// Fill all PRP lists except of last one.
+  ///
+  ZeroMem (*PrpListHost, Bytes);
+  for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
+    PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
+
+    for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
+      PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64));
+      if (PrpEntryIndex != PrpEntryNo - 1) {
+        ///
+        /// Fill all PRP entries except of last one.
+        ///
+        CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
+        PhysicalAddr += EFI_PAGE_SIZE;
+      } else {
+        ///
+        /// Fill last PRP entries with next PRP List pointer.
+        ///
+        NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE);
+        CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof (UINT64));
+      }
+    }
+  }
+
+  ///
+  /// Fill last PRP list.
+  ///
+  PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
+  for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder : PrpEntryNo); ++PrpEntryIndex) {
+    PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64));
+    CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
+
+    PhysicalAddr += EFI_PAGE_SIZE;
+  }
+
+  return PrpListPhyAddr;
+}
+
+/**
+  Check whether there are available command slots.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Qid                    - Queue index
+
+  @retval EFI_SUCCESS               - Available command slot is found
+  @retval EFI_NOT_READY             - No available command slot is found
+  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
+
+**/
+EFI_STATUS
+NvmeHasFreeCmdSlot (
+  IN NVME_CONTEXT       *Nvme,
+  IN UINT8              Qid
+  )
+{
+  return TRUE;
+}
+
+/**
+  Check whether all command slots are clean.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Qid                    - Queue index
+
+  @retval EFI_SUCCESS               - All command slots are clean
+  @retval EFI_NOT_READY             - Not all command slots are clean
+  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
+
+**/
+EFI_STATUS
+NvmeIsAllCmdSlotClean (
+  IN NVME_CONTEXT       *Nvme,
+  IN UINT8              Qid
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Waits until all NVME commands completed.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Qid                    - Queue index
+
+  @retval EFI_SUCCESS               - All NVME commands have completed
+  @retval EFI_TIMEOUT               - Timeout occured
+  @retval EFI_NOT_READY             - Not all NVME commands have completed
+  @retval others                    - Error occurred on device side.
+**/
+EFI_STATUS
+NvmeWaitAllComplete (
+  IN NVME_CONTEXT       *Nvme,
+  IN UINT8              Qid
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
+  both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
+  I/O functionality is optional.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
+                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
+                                      ID specifies that the command packet should be sent to all valid namespaces.
+  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
+                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
+                                      UUID specifies that the command packet should be sent to all valid namespaces.
+  @param[in,out] Packet             - A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
+                                      by NamespaceId.
+
+  @retval EFI_SUCCESS               - The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
+                                      to, or from DataBuffer.
+  @retval EFI_NOT_READY             - The NVM Express Command Packet could not be sent because the controller is not ready. The caller
+                                      may retry again later.
+  @retval EFI_DEVICE_ERROR          - A device error occurred while attempting to send the NVM Express Command Packet.
+  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
+                                      Express Command Packet was not sent, so no additional status information is available.
+  @retval EFI_UNSUPPORTED           - The command described by the NVM Express Command Packet is not supported by the host adapter.
+                                      The NVM Express Command Packet was not sent, so no additional status information is available.
+  @retval EFI_TIMEOUT               - A timeout occurred while waiting for the NVM Express Command Packet to execute.
+
+**/
+EFI_STATUS
+NvmePassThru (
+  IN     NVME_CONTEXT                         *Nvme,
+  IN     UINT32                               NamespaceId,
+  IN     UINT64                               NamespaceUuid,
+  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
+  )
+{
+  EFI_STATUS                    Status;
+  NVME_SQ                       *Sq;
+  NVME_CQ                       *Cq;
+  UINT8                         Qid;
+  UINT32                        Bytes;
+  UINT32                        Offset;
+  EFI_PHYSICAL_ADDRESS          PhyAddr;
+  VOID                          *PrpListHost;
+  UINTN                         PrpListNo;
+  UINT32                        Timer;
+  UINTN SqSize;
+  UINTN CqSize;
+
+  ///
+  /// check the Data fields in Packet parameter.
+  ///
+  if ((Nvme == NULL) || (Packet == NULL)) {
+    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter: Nvme(%x)/Packet(%x)\n",
+      (UINTN)Nvme, (UINTN)Packet));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Packet->NvmeCmd == NULL) || (Packet->NvmeResponse == NULL)) {
+    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter: NvmeCmd(%x)/NvmeResponse(%x)\n",
+      (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeResponse));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Packet->QueueId != NVME_ADMIN_QUEUE && Packet->QueueId != NVME_IO_QUEUE) {
+    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter: QueueId(%x)\n",
+      Packet->QueueId));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PrpListHost = NULL;
+  PrpListNo   = 0;
+  Status      = EFI_SUCCESS;
+
+  Qid = Packet->QueueId;
+  Sq  = Nvme->SqBuffer[Qid] + Nvme->SqTdbl[Qid].Sqt;
+  Cq  = Nvme->CqBuffer[Qid] + Nvme->CqHdbl[Qid].Cqh;
+  if (Qid == NVME_ADMIN_QUEUE) {
+    SqSize = NVME_ASQ_SIZE + 1;
+    CqSize = NVME_ACQ_SIZE + 1;
+  } else {
+    SqSize = NVME_CSQ_DEPTH;
+    CqSize = NVME_CCQ_DEPTH;
+  }
+
+  if (Packet->NvmeCmd->Nsid != NamespaceId) {
+    DEBUG ((DEBUG_ERROR, "NvmePassThru: Nsid mismatch (%x, %x)\n",
+      Packet->NvmeCmd->Nsid, NamespaceId));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (Sq, sizeof (NVME_SQ));
+  Sq->Opc  = Packet->NvmeCmd->Cdw0.Opcode;
+  Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation;
+  Sq->Cid  = Packet->NvmeCmd->Cdw0.Cid;
+  Sq->Nsid = Packet->NvmeCmd->Nsid;
+
+  ///
+  /// Currently we only support PRP for Data transfer, SGL is NOT supported.
+  ///
+  ASSERT (Sq->Psdt == 0);
+  if (Sq->Psdt != 0) {
+    DEBUG ((DEBUG_ERROR, "NvmePassThru: doesn't support SGL mechanism\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  Sq->Prp[0] = Packet->TransferBuffer;
+  Sq->Prp[1] = 0;
+
+  if(Packet->MetadataBuffer != (UINT64)(UINTN)NULL) {
+    Sq->Mptr = Packet->MetadataBuffer;
+  }
+
+  ///
+  /// If the Buffer Size spans more than two memory pages (page Size as defined in CC.Mps),
+  /// then build a PRP list in the second PRP submission queue entry.
+  ///
+  Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
+  Bytes  = Packet->TransferLength;
+
+  if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
+    ///
+    /// Create PrpList for remaining Data Buffer.
+    ///
+    PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
+    Sq->Prp[1] = NvmeCreatePrpList (Nvme, Nvme->SqTdbl[Qid].Sqt, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo);
+    if (Sq->Prp[1] == 0) {
+      Status = EFI_OUT_OF_RESOURCES;
+      DEBUG ((DEBUG_ERROR, "NvmeCreatePrpList fail, Status: %r\n", Status));
+      goto EXIT;
+    }
+
+  } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
+    Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
+  }
+
+  if(Packet->NvmeCmd->Flags & CDW10_VALID) {
+    Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
+  }
+  if(Packet->NvmeCmd->Flags & CDW11_VALID) {
+    Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
+  }
+  if(Packet->NvmeCmd->Flags & CDW12_VALID) {
+    Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
+  }
+  if(Packet->NvmeCmd->Flags & CDW13_VALID) {
+    Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
+  }
+  if(Packet->NvmeCmd->Flags & CDW14_VALID) {
+    Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
+  }
+  if(Packet->NvmeCmd->Flags & CDW15_VALID) {
+    Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
+  }
+
+  ///
+  /// Ring the submission queue doorbell.
+  ///
+  Nvme->SqTdbl[Qid].Sqt++;
+  if(Nvme->SqTdbl[Qid].Sqt == SqSize) {
+    Nvme->SqTdbl[Qid].Sqt = 0;
+  }
+  Status = NVME_SET_SQTDBL (Nvme, Qid, &Nvme->SqTdbl[Qid]);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NVME_SET_SQTDBL fail, Status: %r\n", Status));
+    goto EXIT;
+  }
+
+  ///
+  /// Wait for completion queue to get filled in.
+  ///
+  Status = EFI_TIMEOUT;
+  Timer   = 0;
+  while (Timer < NVME_CMD_TIMEOUT) {
+    //DEBUG ((DEBUG_VERBOSE, "Timer: %x, Cq:\n", Timer));
+    //DumpMem (Cq, sizeof (NVME_CQ));
+    if (Cq->Pt != Nvme->Pt[Qid]) {
+      Status = EFI_SUCCESS;
+      break;
+    }
+
+    MicroSecondDelay (NVME_CMD_WAIT);
+    Timer += NVME_CMD_WAIT;
+  }
+
+  Nvme->CqHdbl[Qid].Cqh++;
+  if (Nvme->CqHdbl[Qid].Cqh == CqSize) {
+    Nvme->CqHdbl[Qid].Cqh = 0;
+    Nvme->Pt[Qid] ^= 1;
+  }
+
+  ///
+  /// Copy the Respose Queue entry for this command to the callers response Buffer
+  ///
+  CopyMem (Packet->NvmeResponse, Cq, sizeof(NVM_EXPRESS_RESPONSE));
+
+  if (!EFI_ERROR(Status)) { // We still need to check CQ status if no timeout error occured
+    Status = NvmeCheckCqStatus (Cq);
+  }
+  NVME_SET_CQHDBL (Nvme, Qid, &Nvme->CqHdbl[Qid]);
+
+EXIT:
+  return Status;
+}
+
+/**
+  Get identify controller Data.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Buffer                 - The Buffer used to store the identify controller Data.
+
+  @return EFI_SUCCESS               - Successfully get the identify controller Data.
+  @return others                    - Fail to get the identify controller Data.
+
+**/
+STATIC
+EFI_STATUS
+NvmeIdentifyController (
+  IN NVME_CONTEXT                          *Nvme,
+  IN VOID                                  *Buffer
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  //
+  // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
+  // For the Identify command, the Namespace Identifier is only used for the Namespace Data structure.
+  //
+  Command.Nsid        = 0;
+
+  CommandPacket.NvmeCmd        = &Command;
+  CommandPacket.NvmeResponse   = &Response;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
+  CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA);
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+  //
+  // Set bit 0 (Cns bit) to 1 to identify a controller
+  //
+  Command.Cdw10                = 1;
+  Command.Flags                = CDW10_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NVME_CONTROLLER_ID,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Get specified identify namespace Data.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] NamespaceId            - The specified namespace identifier.
+  @param[in] Buffer                 - The Buffer used to store the identify namespace Data.
+
+  @return EFI_SUCCESS               - Successfully get the identify namespace Data.
+  @return others                    - Fail to get the identify namespace Data.
+
+**/
+STATIC
+EFI_STATUS
+NvmeIdentifyNamespace (
+  IN NVME_CONTEXT                          *Nvme,
+  IN UINT32                                NamespaceId,
+  IN VOID                                  *Buffer
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  Command.Nsid        = NamespaceId;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
+  CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+  //
+  // Set bit 0 (Cns bit) to 1 to identify a namespace
+  //
+  CommandPacket.NvmeCmd->Cdw10 = 0;
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NamespaceId,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Get Block Size for specific namespace of NVME.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return                           - Block Size in bytes
+
+**/
+STATIC
+UINT32
+NvmeGetBlockSize (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  UINT32                BlockSize;
+  UINT32                Lbads;
+  UINT32                Flbas;
+  UINT32                LbaFmtIdx;
+
+  Flbas     = Nvme->NamespaceData->Flbas;
+  LbaFmtIdx = Flbas & 3;
+  Lbads     = Nvme->NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
+
+  BlockSize = (UINT32)1 << Lbads;
+  return BlockSize;
+}
+
+/**
+  Get last LBA for specific namespace of NVME.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return                           - Last LBA address
+
+**/
+STATIC
+EFI_LBA
+NvmeGetLastLba (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  EFI_LBA               LastBlock;
+  LastBlock = Nvme->NamespaceData->Nsze - 1;
+  return LastBlock;
+}
+
+/**
+  Create io completion queue.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully create io completion queue.
+  @return others                    - Fail to create io completion queue.
+
+**/
+STATIC
+EFI_STATUS
+NvmeCreateIoCompletionQueue (
+  IN     NVME_CONTEXT                      *Nvme
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  NVME_ADMIN_CRIOCQ                        CrIoCq;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+  ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
+  CommandPacket.TransferLength = EFI_PAGE_SIZE;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+
+  CrIoCq.Qid   = NVME_IO_QUEUE;
+  CrIoCq.Qsize = NVME_CCQ_SIZE;
+  CrIoCq.Pc    = 1;
+  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NVME_CONTROLLER_ID,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Create io submission queue.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully create io submission queue.
+  @return others                    - Fail to create io submission queue.
+
+**/
+STATIC
+EFI_STATUS
+NvmeCreateIoSubmissionQueue (
+  IN NVME_CONTEXT                          *Nvme
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  NVME_ADMIN_CRIOSQ                        CrIoSq;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+  ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
+  CommandPacket.TransferLength = EFI_PAGE_SIZE;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+
+  CrIoSq.Qid   = NVME_IO_QUEUE;
+  CrIoSq.Qsize = NVME_CSQ_SIZE;
+  CrIoSq.Pc    = 1;
+  CrIoSq.Cqid  = NVME_IO_QUEUE;
+  CrIoSq.Qprio = 0;
+  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NVME_CONTROLLER_ID,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Security send and receive commands.
+
+  @param[in]     Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in]     SendCommand            - The flag to indicate the command type, TRUE for Send command and FALSE for receive command
+  @param[in]     SecurityProtocol       - Security Protocol
+  @param[in]     SpSpecific             - Security Protocol Specific
+  @param[in]     TransferLength         - Transfer Length of Buffer (in bytes) - always a multiple of 512
+  @param[in,out] TransferBuffer         - Address of Data to transfer
+
+  @return EFI_SUCCESS               - Successfully create io submission queue.
+  @return others                    - Fail to send/receive commands.
+
+**/
+EFI_STATUS
+NvmeSecuritySendReceive (
+  IN NVME_CONTEXT                          *Nvme,
+  IN BOOLEAN                               SendCommand,
+  IN UINT8                                 SecurityProtocol,
+  IN UINT16                                SpSpecific,
+  IN UINTN                                 TransferLength,
+  IN OUT VOID                              *TransferBuffer
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  NVME_ADMIN_SECSEND                       SecSend;
+  OACS                                     *Oacs;
+  UINT8                                    Opcode;
+  VOID*                                    *SecBuff;
+
+  Oacs = (OACS *)&Nvme->ControllerData->Oacs;
+
+  //
+  // Verify security bit for Security Send/Receive commands
+  //
+  if (Oacs->Security == 0) {
+    DEBUG ((DEBUG_ERROR, "Security command doesn't support.\n"));
+    return EFI_NOT_READY;
+  }
+
+  SecBuff = (VOID *)(UINTN) NVME_SEC_BASE (Nvme);
+
+  //
+  // Actions for sending security command
+  //
+  if (SendCommand) {
+    CopyMem (SecBuff, TransferBuffer, TransferLength);
+  }
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+  ZeroMem (&SecSend, sizeof(NVME_ADMIN_SECSEND));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  Opcode = (UINT8)(SendCommand ? NVME_ADMIN_SECURITY_SEND_OPC : NVME_ADMIN_SECURITY_RECV_OPC);
+  Command.Cdw0.Opcode = Opcode;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)SecBuff;
+  CommandPacket.TransferLength = (UINT32)TransferLength;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+
+  SecSend.Spsp = SpSpecific;
+  SecSend.Secp = SecurityProtocol;
+  SecSend.Tl   = (UINT32)TransferLength;
+
+  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &SecSend, sizeof (NVME_ADMIN_SECSEND));
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NVME_CONTROLLER_ID,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  //
+  // Actions for receiving security command
+  //
+  if (!SendCommand) {
+    CopyMem (TransferBuffer, SecBuff, TransferLength);
+  }
+
+  return Status;
+}
+
+/**
+  Destroy io completion queue.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully destroy io completion queue.
+  @return others                    - Fail to destroy io completion queue.
+
+**/
+STATIC
+EFI_STATUS
+NvmeDestroyIoCompletionQueue (
+  IN     NVME_CONTEXT                      *Nvme
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  NVME_ADMIN_DEIOCQ                        DelIoCq;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+  ZeroMem (&DelIoCq, sizeof(NVME_ADMIN_DEIOCQ));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  Command.Cdw0.Opcode = NVME_ADMIN_DELIOCQ_OPC;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
+  CommandPacket.TransferLength = EFI_PAGE_SIZE;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+
+  DelIoCq.Qid   = NVME_IO_QUEUE;
+  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoCq, sizeof (NVME_ADMIN_DEIOCQ));
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NVME_CONTROLLER_ID,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Destroy io submission queue.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @return EFI_SUCCESS               - Successfully destroy io submission queue.
+  @return others                    - Fail to destroy io submission queue.
+
+**/
+STATIC
+EFI_STATUS
+NvmeDestroyIoSubmissionQueue (
+  IN NVME_CONTEXT                          *Nvme
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  NVME_ADMIN_DEIOSQ                        DelIoSq;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+  ZeroMem (&DelIoSq, sizeof(NVME_ADMIN_DEIOSQ));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  Command.Cdw0.Opcode = NVME_ADMIN_DELIOSQ_OPC;
+  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
+  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
+  CommandPacket.TransferLength = EFI_PAGE_SIZE;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
+
+  DelIoSq.Qid   = NVME_IO_QUEUE;
+  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoSq, sizeof (NVME_ADMIN_DEIOSQ));
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              NVME_CONTROLLER_ID,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Allocate transfer-related Data struct which is used at Nvme.
+
+  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_OUT_OF_RESOURCE   No enough resource.
+  @retval EFI_SUCCESS           Successful to allocate resource.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeAllocateResource (
+  IN OUT NVME_CONTEXT       *Nvme
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      DeviceAddress;
+  VOID                      *Base;
+  VOID                      *Mapping;
+
+  //
+  // Allocate resources for DMA.
+  //
+  Status = IoMmuAllocateBuffer (
+             EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
+             &Base,
+             &DeviceAddress,
+             &Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
+  Nvme->BaseMemMapping = Mapping;
+  Nvme->BaseMem = Base;
+  ZeroMem (Nvme->BaseMem, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE));
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a() NvmeContext 0x%x\n",
+    __FUNCTION__,
+    Nvme->BaseMem
+    ));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Free allocated transfer-related Data struct which is used at NVMe.
+
+  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data structure.
+
+**/
+VOID
+EFIAPI
+NvmeFreeResource (
+  IN OUT NVME_CONTEXT       *Nvme
+  )
+{
+  if (Nvme->BaseMem != NULL) {
+    IoMmuFreeBuffer (
+       EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
+       Nvme->BaseMem,
+       Nvme->BaseMemMapping
+       );
+    Nvme->BaseMem = NULL;
+  }
+}
+
+/**
+  Initialize the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_SUCCESS               - The NVM Express Controller is initialized successfully.
+  @retval Others                    - A device error occurred while initializing the controller.
+
+**/
+EFI_STATUS
+NvmeControllerInit (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  EFI_STATUS            Status;
+  NVME_AQA              Aqa;
+  NVME_ASQ              Asq;
+  NVME_ACQ              Acq;
+  NVME_VER              Ver;
+
+  UINT32                MlBAR;
+  UINT32                MuBAR;
+
+  ///
+  /// Update PCIE BAR0/1 for NVME device
+  ///
+  MlBAR = Nvme->Nbar;
+  MuBAR = 0;
+  PciWrite32 (Nvme->PciBase + 0x10, MlBAR); // MLBAR (BAR0)
+  PciWrite32 (Nvme->PciBase + 0x14, MuBAR); // MUBAR (BAR1)
+
+  ///
+  /// Enable PCIE decode
+  ///
+  PciWrite8 (Nvme->PciBase + NVME_PCIE_PCICMD, 0x6);
+
+  // Version
+  NVME_GET_VER (Nvme, &Ver);
+  if (!(Ver.Mjr == 0x0001) && (Ver.Mnr == 0x0000)) {
+    DEBUG ((DEBUG_INFO, "\n!!!\n!!! NVME Version mismatch for the implementation !!!\n!!!\n"));
+  }
+
+  ///
+  /// Read the Controller Capabilities register and verify that the NVM command set is supported
+  ///
+  Status = NVME_GET_CAP (Nvme, &Nvme->Cap);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "NVME_GET_CAP fail, Status: %r\n", Status));
+    goto Done;
+  }
+
+  if (Nvme->Cap.Css != 0x01) {
+    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: the controller doesn't support NVMe command set\n"));
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  ///
+  /// Currently the driver only supports 4k page Size.
+  ///
+  if ((Nvme->Cap.Mpsmin + 12) > EFI_PAGE_SHIFT) {
+    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: only supports 4k page Size\n"));
+    ASSERT (FALSE);
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  Nvme->Cid[0] = 0;
+  Nvme->Cid[1] = 0;
+
+  Nvme->Pt[0]  = 0;
+  Nvme->Pt[1]  = 0;
+
+  ZeroMem ((VOID *)(UINTN)(&(Nvme->SqTdbl[0])), sizeof (NVME_SQTDBL) * NVME_MAX_IO_QUEUES);
+  ZeroMem ((VOID *)(UINTN)(&(Nvme->CqHdbl[0])), sizeof (NVME_CQHDBL) * NVME_MAX_IO_QUEUES);
+
+  ZeroMem (Nvme->BaseMem, NVME_MEM_MAX_SIZE);
+
+  Status = NvmeDisableController (Nvme);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NvmeDisableController fail, Status: %r\n", Status));
+    goto Done;
+  }
+
+  ///
+  /// set number of entries admin submission & completion queues.
+  ///
+  Aqa.Asqs  = NVME_ASQ_SIZE;
+  Aqa.Rsvd1 = 0;
+  Aqa.Acqs  = NVME_ACQ_SIZE;
+  Aqa.Rsvd2 = 0;
+
+  ///
+  /// Address of admin submission queue.
+  ///
+  Asq = (UINT64)(UINTN)(NVME_ASQ_BASE (Nvme) & ~0xFFF);
+
+  ///
+  /// Address of admin completion queue.
+  ///
+  Acq = (UINT64)(UINTN)(NVME_ACQ_BASE (Nvme) & ~0xFFF);
+
+  ///
+  /// Address of I/O submission & completion queue.
+  ///
+  Nvme->SqBuffer[0] = (NVME_SQ *)(UINTN)NVME_ASQ_BASE (Nvme);   // NVME_ADMIN_QUEUE
+  Nvme->CqBuffer[0] = (NVME_CQ *)(UINTN)NVME_ACQ_BASE (Nvme);   // NVME_ADMIN_QUEUE
+  Nvme->SqBuffer[1] = (NVME_SQ *)(UINTN)NVME_SQ_BASE (Nvme, 0); // NVME_IO_QUEUE
+  Nvme->CqBuffer[1] = (NVME_CQ *)(UINTN)NVME_CQ_BASE (Nvme, 0); // NVME_IO_QUEUE
+
+  DEBUG ((DEBUG_INFO, "Admin Submission Queue Size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));
+  DEBUG ((DEBUG_INFO, "Admin Completion Queue Size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));
+  DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) =   [%08X]\n", Nvme->SqBuffer[0]));
+  DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) =   [%08X]\n", Nvme->CqBuffer[0]));
+  DEBUG ((DEBUG_INFO, "I/O   Submission Queue (SqBuffer[1]) =   [%08X]\n", Nvme->SqBuffer[1]));
+  DEBUG ((DEBUG_INFO, "I/O   Completion Queue (CqBuffer[1]) =   [%08X]\n", Nvme->CqBuffer[1]));
+
+  ///
+  /// Program admin queue attributes.
+  ///
+  Status = NVME_SET_AQA (Nvme, &Aqa);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  ///
+  /// Program admin submission queue address.
+  ///
+  Status = NVME_SET_ASQ (Nvme, &Asq);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  ///
+  /// Program admin completion queue address.
+  ///
+  Status = NVME_SET_ACQ (Nvme, &Acq);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  Status = NvmeEnableController (Nvme);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  ///
+  /// Create one I/O completion queue.
+  ///
+  Status = NvmeCreateIoCompletionQueue (Nvme);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  ///
+  /// Create one I/O Submission queue.
+  ///
+  Status = NvmeCreateIoSubmissionQueue (Nvme);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  ///
+  /// Get current Identify Controller Data
+  ///
+  Nvme->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)(UINTN) NVME_CONTROL_DATA_BASE (Nvme);
+  Status = NvmeIdentifyController (Nvme, Nvme->ControllerData);
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  ///
+  /// Dump NvmExpress Identify Controller Data
+  ///
+  Nvme->ControllerData->Sn[19] = 0;
+  Nvme->ControllerData->Mn[39] = 0;
+  //NvmeDumpIdentifyController (Nvme->ControllerData);
+
+  ///
+  /// Get current Identify Namespace Data
+  ///
+  Nvme->NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)NVME_NAMESPACE_DATA_BASE (Nvme);
+  Status = NvmeIdentifyNamespace (Nvme, Nvme->Nsid, Nvme->NamespaceData);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "NvmeIdentifyNamespace fail, Status = %r\n", Status));
+    goto Done;
+  }
+
+  ///
+  /// Dump NvmExpress Identify Namespace Data
+  ///
+  if (Nvme->NamespaceData->Ncap == 0) {
+    DEBUG ((DEBUG_ERROR, "Invalid Namespace, Ncap: %lx\n", Nvme->NamespaceData->Ncap));
+    Status = EFI_DEVICE_ERROR;
+    goto Done;
+  }
+
+  Nvme->BlockSize = NvmeGetBlockSize (Nvme);
+  Nvme->LastBlock = NvmeGetLastLba (Nvme);
+
+  Nvme->State    = NvmeStatusInit;
+
+  return EFI_SUCCESS;
+
+Done:
+  return Status;
+}
+
+/**
+  Un-initialize the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_SUCCESS               - The NVM Express Controller is un-initialized successfully.
+  @retval Others                    - A device error occurred while un-initializing the controller.
+
+**/
+EFI_STATUS
+NvmeControllerExit (
+  IN NVME_CONTEXT       *Nvme
+  )
+{
+  EFI_STATUS            Status;
+
+  Status = EFI_SUCCESS;
+  if (Nvme->State == NvmeStatusInit || Nvme->State == NvmeStatusMax) {
+    ///
+    /// Destroy I/O Submission queue.
+    ///
+    Status = NvmeDestroyIoSubmissionQueue (Nvme);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoSubmissionQueue fail, Status = %r\n", Status));
+      return Status;
+    }
+
+    ///
+    /// Destroy I/O completion queue.
+    ///
+    Status = NvmeDestroyIoCompletionQueue (Nvme);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoCompletionQueue fail, Status = %r\n", Status));
+      return Status;
+    }
+
+    Status = NvmeShutdownController (Nvme);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NvmeShutdownController fail, Status: %r\n", Status));
+    }
+  }
+
+  ///
+  /// Disable PCIE decode
+  ///
+  PciWrite8  (Nvme->PciBase + NVME_PCIE_PCICMD, 0x0);
+  PciWrite32 (Nvme->PciBase + 0x10, 0); // MLBAR (BAR0)
+  PciWrite32 (Nvme->PciBase + 0x14, 0); // MUBAR (BAR1)
+
+  Nvme->State = NvmeStatusUnknown;
+  return Status;
+}
+
+/**
+  Read sector Data from the NVMe device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in,out] Buffer             - The Buffer used to store the Data read from the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be read.
+
+  @retval EFI_SUCCESS               - Datum are read from the device.
+  @retval Others                    - Fail to read all the datum.
+
+**/
+EFI_STATUS
+NvmeReadSectors (
+  IN NVME_CONTEXT                          *Nvme,
+  IN OUT UINT64                            Buffer,
+  IN UINT64                                Lba,
+  IN UINT32                                Blocks
+  )
+{
+  UINT32                                   Bytes;
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  UINT32                                   BlockSize;
+
+  BlockSize  = Nvme->BlockSize;
+  Bytes      = Blocks * BlockSize;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
+  CommandPacket.NvmeCmd->Cdw0.Cid    = Nvme->Cid[NVME_IO_QUEUE]++;
+  CommandPacket.NvmeCmd->Nsid        = Nvme->Nsid;
+  CommandPacket.TransferBuffer       = Buffer;
+
+  CommandPacket.TransferLength = Bytes;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_IO_QUEUE;
+
+  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
+  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
+  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
+
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              Nvme->Nsid,
+              0,
+              &CommandPacket
+              );
+
+  return Status;
+}
+
+/**
+  Write sector Data to the NVMe device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Buffer                 - The Buffer to be written into the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be written.
+
+  @retval EFI_SUCCESS               - Datum are written into the Buffer.
+  @retval Others                    - Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeWriteSectors (
+  IN NVME_CONTEXT                          *Nvme,
+  IN UINT64                                Buffer,
+  IN UINT64                                Lba,
+  IN UINT32                                Blocks
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+  UINT32                                   Bytes;
+  UINT32                                   BlockSize;
+
+  BlockSize  = Nvme->BlockSize;
+  Bytes      = Blocks * BlockSize;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
+  CommandPacket.NvmeCmd->Cdw0.Cid    = Nvme->Cid[NVME_IO_QUEUE]++;
+  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
+  CommandPacket.TransferBuffer = Buffer;
+
+  CommandPacket.TransferLength = Bytes;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_IO_QUEUE;
+
+  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
+  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
+  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
+
+  CommandPacket.MetadataBuffer = (UINT64)(UINTN)NULL;
+  CommandPacket.MetadataLength = 0;
+
+  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
+
+  Status = NvmePassThru (
+              Nvme,
+              Nvme->Nsid,
+              0,
+              &CommandPacket
+              );
+
+  return Status;
+}
+
+/**
+  Flushes all modified Data to the device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_SUCCESS               - Datum are written into the Buffer.
+  @retval Others                    - Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeFlush (
+  IN NVME_CONTEXT                          *Nvme
+  )
+{
+  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
+  NVM_EXPRESS_COMMAND                      Command;
+  NVM_EXPRESS_RESPONSE                     Response;
+  EFI_STATUS                               Status;
+
+  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+  CommandPacket.NvmeCmd      = &Command;
+  CommandPacket.NvmeResponse = &Response;
+
+  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC;
+  CommandPacket.NvmeCmd->Cdw0.Cid    = Nvme->Cid[NVME_IO_QUEUE]++;
+  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
+  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+  CommandPacket.QueueId        = NVME_IO_QUEUE;
+
+  Status = NvmePassThru (
+              Nvme,
+              Nvme->Nsid,
+              0,
+              &CommandPacket
+              );
+  if (!EFI_ERROR (Status)) {
+    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
+  }
+
+  return Status;
+}
+
+/**
+  Read some blocks from the device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[out] Buffer                - The Buffer used to store the Data read from the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be read.
+
+  @retval EFI_SUCCESS               - Datum are read from the device.
+  @retval Others                    - Fail to read all the datum.
+
+**/
+EFI_STATUS
+NvmeRead (
+  IN NVME_CONTEXT                  *Nvme,
+  OUT UINT64                       Buffer,
+  IN UINT64                        Lba,
+  IN UINTN                         Blocks
+  )
+{
+  EFI_STATUS                       Status;
+  UINT32                           BlockSize;
+  UINT32                           MaxTransferBlocks;
+
+  ASSERT (Blocks <= NVME_MAX_SECTORS);
+  Status        = EFI_SUCCESS;
+  BlockSize     = Nvme->BlockSize;
+  if (Nvme->ControllerData->Mdts != 0) {
+    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 << (Nvme->Cap.Mpsmin + 12)) / BlockSize;
+  } else {
+    MaxTransferBlocks = 1024;
+  }
+
+  while (Blocks > 0) {
+    if (Blocks > MaxTransferBlocks) {
+      Status = NvmeReadSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
+
+      Blocks -= MaxTransferBlocks;
+      Buffer += (MaxTransferBlocks * BlockSize);
+      Lba    += MaxTransferBlocks;
+    } else {
+      Status = NvmeReadSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
+      Blocks = 0;
+    }
+
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NvmeRead fail, Status = %r\n", Status));
+      break;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Write some blocks to the device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Buffer                 - The Buffer to be written into the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be written.
+
+  @retval EFI_SUCCESS               - Datum are written into the Buffer.
+  @retval Others                    - Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeWrite (
+  IN NVME_CONTEXT                  *Nvme,
+  IN UINT64                        Buffer,
+  IN UINT64                        Lba,
+  IN UINTN                         Blocks
+  )
+{
+  EFI_STATUS                       Status;
+  UINT32                           BlockSize;
+  UINT32                           MaxTransferBlocks;
+
+  ASSERT (Blocks <= NVME_MAX_SECTORS);
+  Status        = EFI_SUCCESS;
+  BlockSize     = Nvme->BlockSize;
+
+  if (Nvme->ControllerData->Mdts != 0) {
+    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 << (Nvme->Cap.Mpsmin + 12)) / BlockSize;
+  } else {
+    MaxTransferBlocks = 1024;
+  }
+
+  while (Blocks > 0) {
+    if (Blocks > MaxTransferBlocks) {
+      Status = NvmeWriteSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
+
+      Blocks -= MaxTransferBlocks;
+      Buffer += (MaxTransferBlocks * BlockSize);
+      Lba    += MaxTransferBlocks;
+    } else {
+      Status = NvmeWriteSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
+      Blocks = 0;
+    }
+
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "NvmeWrite fail, Status = %r\n", Status));
+      break;
+    }
+  }
+
+  return Status;
+}
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
new file mode 100644
index 000000000000..3fef3dbc1c0d
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
@@ -0,0 +1,455 @@
+/** @file
+  Header file for NVMe function definitions
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __OPAL_PASSWORD_NVME_MODE_H__
+#define __OPAL_PASSWORD_NVME_MODE_H__
+
+
+#include "OpalNvmeReg.h"
+
+#define NVME_MAX_SECTORS            0x10000
+//
+// QueueId
+//
+#define NVME_ADMIN_QUEUE            0x00
+#define NVME_IO_QUEUE               0x01
+
+typedef struct {
+  UINT8                             Opcode;
+  UINT8                             FusedOperation;
+    #define NORMAL_CMD              0x00
+    #define FUSED_FIRST_CMD         0x01
+    #define FUSED_SECOND_CMD        0x02
+  UINT16                            Cid;
+} NVME_CDW0;
+
+typedef struct {
+  NVME_CDW0                         Cdw0;
+  UINT8                             Flags;
+    #define CDW10_VALID             0x01
+    #define CDW11_VALID             0x02
+    #define CDW12_VALID             0x04
+    #define CDW13_VALID             0x08
+    #define CDW14_VALID             0x10
+    #define CDW15_VALID             0x20
+  UINT32                            Nsid;
+  UINT32                            Cdw10;
+  UINT32                            Cdw11;
+  UINT32                            Cdw12;
+  UINT32                            Cdw13;
+  UINT32                            Cdw14;
+  UINT32                            Cdw15;
+} NVM_EXPRESS_COMMAND;
+
+typedef struct {
+  UINT32                            Cdw0;
+  UINT32                            Cdw1;
+  UINT32                            Cdw2;
+  UINT32                            Cdw3;
+} NVM_EXPRESS_RESPONSE;
+
+typedef struct {
+  UINT64                            CommandTimeout;
+  UINT64                            TransferBuffer;
+  UINT32                            TransferLength;
+  UINT64                            MetadataBuffer;
+  UINT32                            MetadataLength;
+  UINT8                             QueueId;
+  NVM_EXPRESS_COMMAND               *NvmeCmd;
+  NVM_EXPRESS_RESPONSE              *NvmeResponse;
+} NVM_EXPRESS_PASS_THRU_COMMAND_PACKET;
+
+
+#pragma pack(1)
+
+// Internal fields
+typedef enum {
+  NvmeStatusUnknown,
+  NvmeStatusInit,
+  NvmeStatusInuse,
+  NvmeStatusMax,
+} NVME_STATUS;
+
+typedef struct {
+  UINT32                            Nbar;
+  VOID                              *BaseMem;
+  VOID                              *BaseMemMapping;
+  BOOLEAN                           PollCancellation;
+  UINT16                            NvmeInitWaitTime;
+
+  NVME_STATUS                       State;
+  UINT8                             BusID;
+  UINT8                             DeviceID;
+  UINT8                             FuncID;
+  UINTN                             PciBase;
+
+  UINT32                            Nsid;
+  UINT64                            Nsuuid;
+  UINT32                            BlockSize;
+  EFI_LBA                           LastBlock;
+
+  //
+  // Pointers to 4kB aligned submission & completion queues.
+  //
+  NVME_SQ                           *SqBuffer[NVME_MAX_IO_QUEUES];
+  NVME_CQ                           *CqBuffer[NVME_MAX_IO_QUEUES];
+  UINT16                            Cid[NVME_MAX_IO_QUEUES];
+
+  //
+  // Submission and completion queue indices.
+  //
+  NVME_SQTDBL                       SqTdbl[NVME_MAX_IO_QUEUES];
+  NVME_CQHDBL                       CqHdbl[NVME_MAX_IO_QUEUES];
+  UINT8                             Pt[NVME_MAX_IO_QUEUES];
+
+  UINTN                             SqeCount[NVME_MAX_IO_QUEUES];
+
+  //
+  // Nvme controller capabilities
+  //
+  NVME_CAP                          Cap;
+
+  //
+  // pointer to identify controller Data
+  //
+  NVME_ADMIN_CONTROLLER_DATA        *ControllerData;
+  NVME_ADMIN_NAMESPACE_DATA         *NamespaceData;
+} NVME_CONTEXT;
+
+#pragma pack()
+
+/**
+  Transfer MMIO Data to memory.
+
+  @param[in,out] MemBuffer - Destination: Memory address
+  @param[in] MmioAddr      - Source: MMIO address
+  @param[in] Size          - Size for read
+
+  @retval EFI_SUCCESS - MMIO read sucessfully
+**/
+EFI_STATUS
+NvmeMmioRead (
+  IN OUT VOID *MemBuffer,
+  IN     UINTN MmioAddr,
+  IN     UINTN Size
+  );
+
+/**
+  Transfer memory Data to MMIO.
+
+  @param[in,out] MmioAddr - Destination: MMIO address
+  @param[in] MemBuffer    - Source: Memory address
+  @param[in] Size         - Size for write
+
+  @retval EFI_SUCCESS - MMIO write sucessfully
+**/
+EFI_STATUS
+NvmeMmioWrite (
+  IN OUT UINTN MmioAddr,
+  IN     VOID *MemBuffer,
+  IN     UINTN Size
+  );
+
+/**
+  Transfer memory data to MMIO.
+
+  @param[in,out] MmioAddr - Destination: MMIO address
+  @param[in] MemBuffer    - Source: Memory address
+  @param[in] Size         - Size for write
+
+  @retval EFI_SUCCESS - MMIO write sucessfully
+**/
+EFI_STATUS
+OpalPciWrite (
+  IN OUT UINTN MmioAddr,
+  IN     VOID *MemBuffer,
+  IN     UINTN Size
+  );
+
+/**
+  Transfer MMIO data to memory.
+
+  @param[in,out] MemBuffer - Destination: Memory address
+  @param[in] MmioAddr      - Source: MMIO address
+  @param[in] Size          - Size for read
+
+  @retval EFI_SUCCESS - MMIO read sucessfully
+**/
+EFI_STATUS
+OpalPciRead (
+  IN OUT VOID *MemBuffer,
+  IN     UINTN MmioAddr,
+  IN     UINTN Size
+  );
+
+/**
+  Allocate transfer-related Data struct which is used at Nvme.
+
+  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_OUT_OF_RESOURCE   No enough resource.
+  @retval EFI_SUCCESS           Successful to allocate resource.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeAllocateResource (
+  IN OUT NVME_CONTEXT       *Nvme
+  );
+
+/**
+  Free allocated transfer-related Data struct which is used at NVMe.
+
+  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data structure.
+
+**/
+VOID
+EFIAPI
+NvmeFreeResource (
+  IN OUT NVME_CONTEXT       *Nvme
+  );
+
+/**
+  Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
+  both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
+  I/O functionality is optional.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
+                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
+                                      ID specifies that the command packet should be sent to all valid namespaces.
+  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
+                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
+                                      UUID specifies that the command packet should be sent to all valid namespaces.
+  @param[in,out] Packet             - A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
+                                      by NamespaceId.
+
+  @retval EFI_SUCCESS               - The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
+                                      to, or from DataBuffer.
+  @retval EFI_NOT_READY             - The NVM Express Command Packet could not be sent because the controller is not ready. The caller
+                                      may retry again later.
+  @retval EFI_DEVICE_ERROR          - A device error occurred while attempting to send the NVM Express Command Packet.
+  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
+                                      Express Command Packet was not sent, so no additional status information is available.
+  @retval EFI_UNSUPPORTED           - The command described by the NVM Express Command Packet is not supported by the host adapter.
+                                      The NVM Express Command Packet was not sent, so no additional status information is available.
+  @retval EFI_TIMEOUT               - A timeout occurred while waiting for the NVM Express Command Packet to execute.
+
+**/
+EFI_STATUS
+NvmePassThru (
+  IN     NVME_CONTEXT                         *Nvme,
+  IN     UINT32                               NamespaceId,
+  IN     UINT64                               NamespaceUuid,
+  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
+  );
+
+/**
+  Waits until all NVME commands completed.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Qid                    - Queue index
+
+  @retval EFI_SUCCESS               - All NVME commands have completed
+  @retval EFI_TIMEOUT               - Timeout occured
+  @retval EFI_NOT_READY             - Not all NVME commands have completed
+  @retval others                    - Error occurred on device side.
+**/
+EFI_STATUS
+NvmeWaitAllComplete (
+  IN NVME_CONTEXT       *Nvme,
+  IN UINT8              Qid
+  );
+
+/**
+  Initialize the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_SUCCESS               - The NVM Express Controller is initialized successfully.
+  @retval Others                    - A device error occurred while initializing the controller.
+
+**/
+EFI_STATUS
+NvmeControllerInit (
+  IN NVME_CONTEXT       *Nvme
+  );
+
+/**
+  Un-initialize the Nvm Express controller.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_SUCCESS               - The NVM Express Controller is un-initialized successfully.
+  @retval Others                    - A device error occurred while un-initializing the controller.
+
+**/
+EFI_STATUS
+NvmeControllerExit (
+  IN NVME_CONTEXT       *Nvme
+  );
+
+/**
+  Check whether there are available command slots.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Qid                    - Queue index
+
+  @retval EFI_SUCCESS               - Available command slot is found
+  @retval EFI_NOT_READY             - No available command slot is found
+  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
+
+**/
+EFI_STATUS
+NvmeHasFreeCmdSlot (
+  IN NVME_CONTEXT       *Nvme,
+  IN UINT8              Qid
+  );
+
+/**
+  Check whether all command slots are clean.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Qid                    - Queue index
+
+  @retval EFI_SUCCESS               - All command slots are clean
+  @retval EFI_NOT_READY             - Not all command slots are clean
+  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
+
+**/
+EFI_STATUS
+NvmeIsAllCmdSlotClean (
+  IN NVME_CONTEXT       *Nvme,
+  IN UINT8              Qid
+  );
+
+/**
+  Read sector Data from the NVMe device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in,out] Buffer             - The Buffer used to store the Data read from the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be read.
+
+  @retval EFI_SUCCESS               - Datum are read from the device.
+  @retval Others                    - Fail to read all the datum.
+
+**/
+EFI_STATUS
+NvmeReadSectors (
+  IN NVME_CONTEXT                          *Nvme,
+  IN OUT UINT64                            Buffer,
+  IN UINT64                                Lba,
+  IN UINT32                                Blocks
+  );
+
+/**
+  Write sector Data to the NVMe device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Buffer                 - The Buffer to be written into the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be written.
+
+  @retval EFI_SUCCESS               - Datum are written into the Buffer.
+  @retval Others                    - Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeWriteSectors (
+  IN NVME_CONTEXT                          *Nvme,
+  IN UINT64                                Buffer,
+  IN UINT64                                Lba,
+  IN UINT32                                Blocks
+  );
+
+/**
+  Flushes all modified Data to the device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+
+  @retval EFI_SUCCESS               - Datum are written into the Buffer.
+  @retval Others                    - Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeFlush (
+  IN NVME_CONTEXT                          *Nvme
+  );
+
+/**
+  Read some blocks from the device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[out] Buffer                - The Buffer used to store the Data read from the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be read.
+
+  @retval EFI_SUCCESS               - Datum are read from the device.
+  @retval Others                    - Fail to read all the datum.
+
+**/
+EFI_STATUS
+NvmeRead (
+  IN NVME_CONTEXT                  *Nvme,
+  OUT UINT64                       Buffer,
+  IN UINT64                        Lba,
+  IN UINTN                         Blocks
+  );
+
+/**
+  Write some blocks to the device.
+
+  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in] Buffer                 - The Buffer to be written into the device.
+  @param[in] Lba                    - The start block number.
+  @param[in] Blocks                 - Total block number to be written.
+
+  @retval EFI_SUCCESS               - Datum are written into the Buffer.
+  @retval Others                    - Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeWrite (
+  IN NVME_CONTEXT                  *Nvme,
+  IN UINT64                        Buffer,
+  IN UINT64                        Lba,
+  IN UINTN                         Blocks
+  );
+
+/**
+  Security send and receive commands.
+
+  @param[in]     Nvme                   - The pointer to the NVME_CONTEXT Data structure.
+  @param[in]     SendCommand            - The flag to indicate the command type, TRUE for Send command and FALSE for receive command
+  @param[in]     SecurityProtocol       - Security Protocol
+  @param[in]     SpSpecific             - Security Protocol Specific
+  @param[in]     TransferLength         - Transfer Length of Buffer (in bytes) - always a multiple of 512
+  @param[in,out] TransferBuffer         - Address of Data to transfer
+
+  @return EFI_SUCCESS               - Successfully create io submission queue.
+  @return others                    - Fail to send/receive commands.
+
+**/
+EFI_STATUS
+NvmeSecuritySendReceive (
+  IN NVME_CONTEXT                          *Nvme,
+  IN BOOLEAN                               SendCommand,
+  IN UINT8                                 SecurityProtocol,
+  IN UINT16                                SpSpecific,
+  IN UINTN                                 TransferLength,
+  IN OUT VOID                              *TransferBuffer
+  );
+
+#endif
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
new file mode 100644
index 000000000000..03376b9e6c9a
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
@@ -0,0 +1,815 @@
+/** @file
+  Header file for Registers and Structure definitions
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef __OPAL_PASSWORD_NVME_REG_H__
+#define __OPAL_PASSWORD_NVME_REG_H__
+
+//
+// PCI Header for PCIe root port configuration
+//
+#define NVME_PCIE_PCICMD                         0x04
+#define NVME_PCIE_BNUM                           0x18
+#define NVME_PCIE_SEC_BNUM                       0x19
+#define NVME_PCIE_IOBL                           0x1C
+#define NVME_PCIE_MBL                            0x20
+#define NVME_PCIE_PMBL                           0x24
+#define NVME_PCIE_PMBU32                         0x28
+#define NVME_PCIE_PMLU32                         0x2C
+#define NVME_PCIE_INTR                           0x3C
+
+//
+// NVMe related definitions
+//
+#define PCI_CLASS_MASS_STORAGE_NVM                0x08  // mass storage sub-class non-volatile memory.
+#define PCI_IF_NVMHCI                             0x02  // mass storage programming interface NVMHCI.
+
+#define NVME_ASQ_SIZE                                    1     // Number of admin submission queue entries, which is 0-based
+#define NVME_ACQ_SIZE                                    1     // Number of admin completion queue entries, which is 0-based
+
+#define NVME_CSQ_SIZE                                    63     // Number of I/O submission queue entries, which is 0-based
+#define NVME_CCQ_SIZE                                    63     // Number of I/O completion queue entries, which is 0-based
+
+#define NVME_MAX_IO_QUEUES                               2     // Number of I/O queues supported by the driver, 1 for AQ, 1 for CQ
+
+#define NVME_CSQ_DEPTH                                   (NVME_CSQ_SIZE+1)
+#define NVME_CCQ_DEPTH                                   (NVME_CCQ_SIZE+1)
+#define NVME_PRP_SIZE                                    (4)    // Pages of PRP list
+
+#define NVME_CONTROLLER_ID                               0
+
+//
+// Time out Value for Nvme transaction execution
+//
+#define NVME_GENERIC_TIMEOUT                             5000000   ///< us
+#define NVME_CMD_WAIT                                    100       ///< us
+#define NVME_CMD_TIMEOUT                                 20000000  ///< us
+
+
+
+#define NVME_MEM_MAX_SIZE \
+  (( \
+  1                                         /* Controller Data */ +  \
+  1                                         /* Identify Data */   +  \
+  1                                         /* ASQ */             +  \
+  1                                         /* ACQ */             +  \
+  1                                         /* SQs */             +  \
+  1                                         /* CQs */             +  \
+  NVME_PRP_SIZE * NVME_CSQ_DEPTH            /* PRPs */            +  \
+  1                                         /* SECURITY */           \
+  ) * EFI_PAGE_SIZE)
+
+
+//
+// controller register offsets
+//
+#define NVME_CAP_OFFSET          0x0000  // Controller Capabilities
+#define NVME_VER_OFFSET          0x0008  // Version
+#define NVME_INTMS_OFFSET        0x000c  // Interrupt Mask Set
+#define NVME_INTMC_OFFSET        0x0010  // Interrupt Mask Clear
+#define NVME_CC_OFFSET           0x0014  // Controller Configuration
+#define NVME_CSTS_OFFSET         0x001c  // Controller Status
+#define NVME_AQA_OFFSET          0x0024  // Admin Queue Attributes
+#define NVME_ASQ_OFFSET          0x0028  // Admin Submission Queue Base Address
+#define NVME_ACQ_OFFSET          0x0030  // Admin Completion Queue Base Address
+#define NVME_SQ0_OFFSET          0x1000  // Submission Queue 0 (admin) Tail Doorbell
+#define NVME_CQ0_OFFSET          0x1004  // Completion Queue 0 (admin) Head Doorbell
+
+//
+// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD))
+// Get the doorbell stride bit shift Value from the controller capabilities.
+//
+#define NVME_SQTDBL_OFFSET(QID, DSTRD)    0x1000 + ((2 * (QID)) * (4 << (DSTRD)))       // Submission Queue y (NVM) Tail Doorbell
+#define NVME_CQHDBL_OFFSET(QID, DSTRD)    0x1000 + (((2 * (QID)) + 1) * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell
+
+
+#pragma pack(1)
+
+//
+// 3.1.1 Offset 00h: CAP - Controller Capabilities
+//
+typedef struct {
+  UINT16 Mqes;      // Maximum Queue Entries Supported
+  UINT8  Cqr:1;     // Contiguous Queues Required
+  UINT8  Ams:2;     // Arbitration Mechanism Supported
+  UINT8  Rsvd1:5;
+  UINT8  To;        // Timeout
+  UINT16 Dstrd:4;
+  UINT16 Rsvd2:1;
+  UINT16 Css:4;     // Command Sets Supported
+  UINT16 Rsvd3:7;
+  UINT8  Mpsmin:4;
+  UINT8  Mpsmax:4;
+  UINT8  Rsvd4;
+} NVME_CAP;
+
+//
+// 3.1.2 Offset 08h: VS - Version
+//
+typedef struct {
+  UINT16 Mnr;       // Minor version number
+  UINT16 Mjr;       // Major version number
+} NVME_VER;
+
+//
+// 3.1.5 Offset 14h: CC - Controller Configuration
+//
+typedef struct {
+  UINT16 En:1;       // Enable
+  UINT16 Rsvd1:3;
+  UINT16 Css:3;      // Command Set Selected
+  UINT16 Mps:4;      // Memory Page Size
+  UINT16 Ams:3;      // Arbitration Mechanism Selected
+  UINT16 Shn:2;      // Shutdown Notification
+  UINT8  Iosqes:4;   // I/O Submission Queue Entry Size
+  UINT8  Iocqes:4;   // I/O Completion Queue Entry Size
+  UINT8  Rsvd2;
+} NVME_CC;
+
+//
+// 3.1.6 Offset 1Ch: CSTS - Controller Status
+//
+typedef struct {
+  UINT32 Rdy:1;      // Ready
+  UINT32 Cfs:1;      // Controller Fatal Status
+  UINT32 Shst:2;     // Shutdown Status
+  UINT32 Nssro:1;    // NVM Subsystem Reset Occurred
+  UINT32 Rsvd1:27;
+} NVME_CSTS;
+
+//
+// 3.1.8 Offset 24h: AQA - Admin Queue Attributes
+//
+typedef struct {
+  UINT16 Asqs:12;    // Submission Queue Size
+  UINT16 Rsvd1:4;
+  UINT16 Acqs:12;    // Completion Queue Size
+  UINT16 Rsvd2:4;
+} NVME_AQA;
+
+//
+// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address
+//
+#define NVME_ASQ      UINT64
+
+//
+// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address
+//
+#define NVME_ACQ      UINT64
+
+//
+// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission Queue y Tail Doorbell
+//
+typedef struct {
+  UINT16 Sqt;
+  UINT16 Rsvd1;
+} NVME_SQTDBL;
+
+//
+// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL - Completion Queue y Head Doorbell
+//
+typedef struct {
+  UINT16 Cqh;
+  UINT16 Rsvd1;
+} NVME_CQHDBL;
+
+//
+// NVM command set structures
+//
+// Read Command
+//
+typedef struct {
+  //
+  // CDW 10, 11
+  //
+  UINT64 Slba;                /* Starting Sector Address */
+  //
+  // CDW 12
+  //
+  UINT16 Nlb;                 /* Number of Sectors */
+  UINT16 Rsvd1:10;
+  UINT16 Prinfo:4;            /* Protection Info Check */
+  UINT16 Fua:1;               /* Force Unit Access */
+  UINT16 Lr:1;                /* Limited Retry */
+  //
+  // CDW 13
+  //
+  UINT32 Af:4;                /* Access Frequency */
+  UINT32 Al:2;                /* Access Latency */
+  UINT32 Sr:1;                /* Sequential Request */
+  UINT32 In:1;                /* Incompressible */
+  UINT32 Rsvd2:24;
+  //
+  // CDW 14
+  //
+  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag */
+  //
+  // CDW 15
+  //
+  UINT16 Elbat;               /* Expected Logical Block Application Tag */
+  UINT16 Elbatm;              /* Expected Logical Block Application Tag Mask */
+} NVME_READ;
+
+//
+// Write Command
+//
+typedef struct {
+  //
+  // CDW 10, 11
+  //
+  UINT64 Slba;                /* Starting Sector Address */
+  //
+  // CDW 12
+  //
+  UINT16 Nlb;                 /* Number of Sectors */
+  UINT16 Rsvd1:10;
+  UINT16 Prinfo:4;            /* Protection Info Check */
+  UINT16 Fua:1;               /* Force Unit Access */
+  UINT16 Lr:1;                /* Limited Retry */
+  //
+  // CDW 13
+  //
+  UINT32 Af:4;                /* Access Frequency */
+  UINT32 Al:2;                /* Access Latency */
+  UINT32 Sr:1;                /* Sequential Request */
+  UINT32 In:1;                /* Incompressible */
+  UINT32 Rsvd2:24;
+  //
+  // CDW 14
+  //
+  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
+  //
+  // CDW 15
+  //
+  UINT16 Lbat;                /* Logical Block Application Tag */
+  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
+} NVME_WRITE;
+
+//
+// Flush
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Flush;               /* Flush */
+} NVME_FLUSH;
+
+//
+// Write Uncorrectable command
+//
+typedef struct {
+  //
+  // CDW 10, 11
+  //
+  UINT64 Slba;                /* Starting LBA */
+  //
+  // CDW 12
+  //
+  UINT32 Nlb:16;              /* Number of  Logical Blocks */
+  UINT32 Rsvd1:16;
+} NVME_WRITE_UNCORRECTABLE;
+
+//
+// Write Zeroes command
+//
+typedef struct {
+  //
+  // CDW 10, 11
+  //
+  UINT64 Slba;                /* Starting LBA */
+  //
+  // CDW 12
+  //
+  UINT16 Nlb;                 /* Number of Logical Blocks */
+  UINT16 Rsvd1:10;
+  UINT16 Prinfo:4;            /* Protection Info Check */
+  UINT16 Fua:1;               /* Force Unit Access */
+  UINT16 Lr:1;                /* Limited Retry */
+  //
+  // CDW 13
+  //
+  UINT32 Rsvd2;
+  //
+  // CDW 14
+  //
+  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
+  //
+  // CDW 15
+  //
+  UINT16 Lbat;                /* Logical Block Application Tag */
+  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
+} NVME_WRITE_ZEROES;
+
+//
+// Compare command
+//
+typedef struct {
+  //
+  // CDW 10, 11
+  //
+  UINT64 Slba;                /* Starting LBA */
+  //
+  // CDW 12
+  //
+  UINT16 Nlb;                 /* Number of Logical Blocks */
+  UINT16 Rsvd1:10;
+  UINT16 Prinfo:4;            /* Protection Info Check */
+  UINT16 Fua:1;               /* Force Unit Access */
+  UINT16 Lr:1;                /* Limited Retry */
+  //
+  // CDW 13
+  //
+  UINT32 Rsvd2;
+  //
+  // CDW 14
+  //
+  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag */
+  //
+  // CDW 15
+  //
+  UINT16 Elbat;               /* Expected Logical Block Application Tag */
+  UINT16 Elbatm;              /* Expected Logical Block Application Tag Mask */
+} NVME_COMPARE;
+
+typedef union {
+  NVME_READ                   Read;
+  NVME_WRITE                  Write;
+  NVME_FLUSH                  Flush;
+  NVME_WRITE_UNCORRECTABLE    WriteUncorrectable;
+  NVME_WRITE_ZEROES           WriteZeros;
+  NVME_COMPARE                Compare;
+} NVME_CMD;
+
+typedef struct {
+  UINT16 Mp;                /* Maximum Power */
+  UINT8  Rsvd1;             /* Reserved as of Nvm Express 1.1 Spec */
+  UINT8  Mps:1;             /* Max Power Scale */
+  UINT8  Nops:1;            /* Non-Operational State */
+  UINT8  Rsvd2:6;           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT32 Enlat;             /* Entry Latency */
+  UINT32 Exlat;             /* Exit Latency */
+  UINT8  Rrt:5;             /* Relative Read Throughput */
+  UINT8  Rsvd3:3;           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT8  Rrl:5;             /* Relative Read Leatency */
+  UINT8  Rsvd4:3;           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT8  Rwt:5;             /* Relative Write Throughput */
+  UINT8  Rsvd5:3;           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT8  Rwl:5;             /* Relative Write Leatency */
+  UINT8  Rsvd6:3;           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT8  Rsvd7[16];         /* Reserved as of Nvm Express 1.1 Spec */
+} NVME_PSDESCRIPTOR;
+
+//
+//  Identify Controller Data
+//
+typedef struct {
+  //
+  // Controller Capabilities and Features 0-255
+  //
+  UINT16 Vid;                 /* PCI Vendor ID */
+  UINT16 Ssvid;               /* PCI sub-system vendor ID */
+  UINT8  Sn[20];              /* Produce serial number */
+
+  UINT8  Mn[40];              /* Proeduct model number */
+  UINT8  Fr[8];               /* Firmware Revision */
+  UINT8  Rab;                 /* Recommended Arbitration Burst */
+  UINT8  Ieee_oiu[3];         /* Organization Unique Identifier */
+  UINT8  Cmic;                /* Multi-interface Capabilities */
+  UINT8  Mdts;                /* Maximum Data Transfer Size */
+  UINT8  Cntlid[2];           /* Controller ID */
+  UINT8  Rsvd1[176];          /* Reserved as of Nvm Express 1.1 Spec */
+  //
+  // Admin Command Set Attributes
+  //
+  UINT16 Oacs;                /* Optional Admin Command Support */
+  UINT8  Acl;                 /* Abort Command Limit */
+  UINT8  Aerl;                /* Async Event Request Limit */
+  UINT8  Frmw;                /* Firmware updates */
+  UINT8  Lpa;                 /* Log Page Attributes */
+  UINT8  Elpe;                /* Error Log Page Entries */
+  UINT8  Npss;                /* Number of Power States Support */
+  UINT8  Avscc;               /* Admin Vendor Specific Command Configuration */
+  UINT8  Apsta;               /* Autonomous Power State Transition Attributes */
+  UINT8  Rsvd2[246];          /* Reserved as of Nvm Express 1.1 Spec */
+  //
+  // NVM Command Set Attributes
+  //
+  UINT8  Sqes;                /* Submission Queue Entry Size */
+  UINT8  Cqes;                /* Completion Queue Entry Size */
+  UINT16 Rsvd3;               /* Reserved as of Nvm Express 1.1 Spec */
+  UINT32 Nn;                  /* Number of Namespaces */
+  UINT16 Oncs;                /* Optional NVM Command Support */
+  UINT16 Fuses;               /* Fused Operation Support */
+  UINT8  Fna;                 /* Format NVM Attributes */
+  UINT8  Vwc;                 /* Volatile Write Cache */
+  UINT16 Awun;                /* Atomic Write Unit Normal */
+  UINT16 Awupf;               /* Atomic Write Unit Power Fail */
+  UINT8  Nvscc;               /* NVM Vendor Specific Command Configuration */
+  UINT8  Rsvd4;               /* Reserved as of Nvm Express 1.1 Spec */
+  UINT16 Acwu;                /* Atomic Compare & Write Unit */
+  UINT16 Rsvd5;               /* Reserved as of Nvm Express 1.1 Spec */
+  UINT32 Sgls;                /* SGL Support  */
+  UINT8  Rsvd6[164];          /* Reserved as of Nvm Express 1.1 Spec */
+  //
+  // I/O Command set Attributes
+  //
+  UINT8 Rsvd7[1344];          /* Reserved as of Nvm Express 1.1 Spec */
+  //
+  // Power State Descriptors
+  //
+  NVME_PSDESCRIPTOR PsDescriptor[32];
+
+  UINT8  VendorData[1024];    /* Vendor specific Data */
+} NVME_ADMIN_CONTROLLER_DATA;
+
+typedef struct {
+  UINT16        Security  : 1;    /* supports security send/receive commands */
+  UINT16        Format    : 1;    /* supports format nvm command */
+  UINT16        Firmware  : 1;    /* supports firmware activate/download commands */
+  UINT16        Oacs_rsvd : 13;
+ } OACS; // optional admin command support: NVME_ADMIN_CONTROLLER_DATA.Oacs
+
+typedef struct {
+  UINT16 Ms;                /* Metadata Size */
+  UINT8  Lbads;             /* LBA Data Size */
+  UINT8  Rp:2;              /* Relative Performance */
+    #define LBAF_RP_BEST      00b
+    #define LBAF_RP_BETTER    01b
+    #define LBAF_RP_GOOD      10b
+    #define LBAF_RP_DEGRADED  11b
+  UINT8  Rsvd1:6;           /* Reserved as of Nvm Express 1.1 Spec */
+} NVME_LBAFORMAT;
+
+//
+// Identify Namespace Data
+//
+typedef struct {
+  //
+  // NVM Command Set Specific
+  //
+  UINT64 Nsze;                /* Namespace Size (total number of blocks in formatted namespace) */
+  UINT64 Ncap;                /* Namespace Capacity (max number of logical blocks) */
+  UINT64 Nuse;                /* Namespace Utilization */
+  UINT8  Nsfeat;              /* Namespace Features */
+  UINT8  Nlbaf;               /* Number of LBA Formats */
+  UINT8  Flbas;               /* Formatted LBA Size */
+  UINT8  Mc;                  /* Metadata Capabilities */
+  UINT8  Dpc;                 /* End-to-end Data Protection capabilities */
+  UINT8  Dps;                 /* End-to-end Data Protection Type Settings */
+  UINT8  Nmic;                /* Namespace Multi-path I/O and Namespace Sharing Capabilities */
+  UINT8  Rescap;              /* Reservation Capabilities */
+  UINT8  Rsvd1[88];           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT64 Eui64;               /* IEEE Extended Unique Identifier */
+  //
+  // LBA Format
+  //
+  NVME_LBAFORMAT LbaFormat[16];
+
+  UINT8 Rsvd2[192];           /* Reserved as of Nvm Express 1.1 Spec */
+  UINT8 VendorData[3712];     /* Vendor specific Data */
+} NVME_ADMIN_NAMESPACE_DATA;
+
+//
+// NvmExpress Admin Identify Cmd
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Cns:2;
+  UINT32 Rsvd1:30;
+} NVME_ADMIN_IDENTIFY;
+
+//
+// NvmExpress Admin Create I/O Completion Queue
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Qid:16;              /* Queue Identifier */
+  UINT32 Qsize:16;            /* Queue Size */
+
+  //
+  // CDW 11
+  //
+  UINT32 Pc:1;                /* Physically Contiguous */
+  UINT32 Ien:1;               /* Interrupts Enabled */
+  UINT32 Rsvd1:14;            /* reserved as of Nvm Express 1.1 Spec */
+  UINT32 Iv:16;               /* Interrupt Vector */
+} NVME_ADMIN_CRIOCQ;
+
+//
+// NvmExpress Admin Create I/O Submission Queue
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Qid:16;              /* Queue Identifier */
+  UINT32 Qsize:16;            /* Queue Size */
+
+  //
+  // CDW 11
+  //
+  UINT32 Pc:1;                /* Physically Contiguous */
+  UINT32 Qprio:2;             /* Queue Priority */
+  UINT32 Rsvd1:13;            /* Reserved as of Nvm Express 1.1 Spec */
+  UINT32 Cqid:16;             /* Completion Queue ID */
+} NVME_ADMIN_CRIOSQ;
+
+//
+// NvmExpress Admin Delete I/O Completion Queue
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT16 Qid;
+  UINT16 Rsvd1;
+} NVME_ADMIN_DEIOCQ;
+
+//
+// NvmExpress Admin Delete I/O Submission Queue
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT16 Qid;
+  UINT16 Rsvd1;
+} NVME_ADMIN_DEIOSQ;
+
+//
+// NvmExpress Admin Security Send
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Resv:8;              /* Reserve */
+  UINT32 Spsp:16;             /* SP Specific */
+  UINT32 Secp:8;              /* Security Protocol */
+
+  //
+  // CDW 11
+  //
+  UINT32 Tl;                  /* Transfer Length */
+} NVME_ADMIN_SECSEND;
+
+//
+// NvmExpress Admin Abort Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Sqid:16;             /* Submission Queue identifier */
+  UINT32 Cid:16;              /* Command Identifier */
+} NVME_ADMIN_ABORT;
+
+//
+// NvmExpress Admin Firmware Activate Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Fs:3;                /* Submission Queue identifier */
+  UINT32 Aa:2;                /* Command Identifier */
+  UINT32 Rsvd1:27;
+} NVME_ADMIN_FIRMWARE_ACTIVATE;
+
+//
+// NvmExpress Admin Firmware Image Download Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Numd;                /* Number of Dwords */
+  //
+  // CDW 11
+  //
+  UINT32 Ofst;                /* Offset */
+} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD;
+
+//
+// NvmExpress Admin Get Features Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Fid:8;                /* Feature Identifier */
+  UINT32 Sel:3;                /* Select */
+  UINT32 Rsvd1:21;
+} NVME_ADMIN_GET_FEATURES;
+
+//
+// NvmExpress Admin Get Log Page Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Lid:8;               /* Log Page Identifier */
+    #define LID_ERROR_INFO
+    #define LID_SMART_INFO
+    #define LID_FW_SLOT_INFO
+  UINT32 Rsvd1:8;
+  UINT32 Numd:12;             /* Number of Dwords */
+  UINT32 Rsvd2:4;             /* Reserved as of Nvm Express 1.1 Spec */
+} NVME_ADMIN_GET_LOG_PAGE;
+
+//
+// NvmExpress Admin Set Features Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Fid:8;               /* Feature Identifier */
+  UINT32 Rsvd1:23;
+  UINT32 Sv:1;                /* Save */
+} NVME_ADMIN_SET_FEATURES;
+
+//
+// NvmExpress Admin Format NVM Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Lbaf:4;              /* LBA Format */
+  UINT32 Ms:1;                /* Metadata Settings */
+  UINT32 Pi:3;                /* Protection Information */
+  UINT32 Pil:1;               /* Protection Information Location */
+  UINT32 Ses:3;               /* Secure Erase Settings */
+  UINT32 Rsvd1:20;
+} NVME_ADMIN_FORMAT_NVM;
+
+//
+// NvmExpress Admin Security Receive Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Rsvd1:8;
+  UINT32 Spsp:16;             /* SP Specific */
+  UINT32 Secp:8;              /* Security Protocol */
+  //
+  // CDW 11
+  //
+  UINT32 Al;                  /* Allocation Length */
+} NVME_ADMIN_SECURITY_RECEIVE;
+
+//
+// NvmExpress Admin Security Send Command
+//
+typedef struct {
+  //
+  // CDW 10
+  //
+  UINT32 Rsvd1:8;
+  UINT32 Spsp:16;             /* SP Specific */
+  UINT32 Secp:8;              /* Security Protocol */
+  //
+  // CDW 11
+  //
+  UINT32 Tl;                  /* Transfer Length */
+} NVME_ADMIN_SECURITY_SEND;
+
+typedef union {
+  NVME_ADMIN_IDENTIFY                   Identify;
+  NVME_ADMIN_CRIOCQ                     CrIoCq;
+  NVME_ADMIN_CRIOSQ                     CrIoSq;
+  NVME_ADMIN_DEIOCQ                     DeIoCq;
+  NVME_ADMIN_DEIOSQ                     DeIoSq;
+  NVME_ADMIN_ABORT                      Abort;
+  NVME_ADMIN_FIRMWARE_ACTIVATE          Activate;
+  NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD    FirmwareImageDownload;
+  NVME_ADMIN_GET_FEATURES               GetFeatures;
+  NVME_ADMIN_GET_LOG_PAGE               GetLogPage;
+  NVME_ADMIN_SET_FEATURES               SetFeatures;
+  NVME_ADMIN_FORMAT_NVM                 FormatNvm;
+  NVME_ADMIN_SECURITY_RECEIVE           SecurityReceive;
+  NVME_ADMIN_SECURITY_SEND              SecuritySend;
+} NVME_ADMIN_CMD;
+
+typedef struct {
+  UINT32 Cdw10;
+  UINT32 Cdw11;
+  UINT32 Cdw12;
+  UINT32 Cdw13;
+  UINT32 Cdw14;
+  UINT32 Cdw15;
+} NVME_RAW;
+
+typedef union {
+  NVME_ADMIN_CMD Admin;   // Union of Admin commands
+  NVME_CMD       Nvm;     // Union of Nvm commands
+  NVME_RAW       Raw;
+} NVME_PAYLOAD;
+
+//
+// Submission Queue
+//
+typedef struct {
+  //
+  // CDW 0, Common to all comnmands
+  //
+  UINT8  Opc;               // Opcode
+  UINT8  Fuse:2;            // Fused Operation
+  UINT8  Rsvd1:5;
+  UINT8  Psdt:1;            // PRP or SGL for Data Transfer
+  UINT16 Cid;               // Command Identifier
+
+  //
+  // CDW 1
+  //
+  UINT32 Nsid;              // Namespace Identifier
+
+  //
+  // CDW 2,3
+  //
+  UINT64 Rsvd2;
+
+  //
+  // CDW 4,5
+  //
+  UINT64 Mptr;              // Metadata Pointer
+
+  //
+  // CDW 6-9
+  //
+  UINT64 Prp[2];            // First and second PRP entries
+
+  NVME_PAYLOAD Payload;
+
+} NVME_SQ;
+
+//
+// Completion Queue
+//
+typedef struct {
+  //
+  // CDW 0
+  //
+  UINT32 Dword0;
+  //
+  // CDW 1
+  //
+  UINT32 Rsvd1;
+  //
+  // CDW 2
+  //
+  UINT16 Sqhd;              // Submission Queue Head Pointer
+  UINT16 Sqid;              // Submission Queue Identifier
+  //
+  // CDW 3
+  //
+  UINT16 Cid;               // Command Identifier
+  UINT16 Pt:1;              // Phase Tag
+  UINT16 Sc:8;              // Status Code
+  UINT16 Sct:3;             // Status Code Type
+  UINT16 Rsvd2:2;
+  UINT16 Mo:1;              // More
+  UINT16 Dnr:1;             // Retry
+} NVME_CQ;
+
+//
+// Nvm Express Admin cmd opcodes
+//
+#define NVME_ADMIN_DELIOSQ_OPC               0
+#define NVME_ADMIN_CRIOSQ_OPC                1
+#define NVME_ADMIN_DELIOCQ_OPC               4
+#define NVME_ADMIN_CRIOCQ_OPC                5
+#define NVME_ADMIN_IDENTIFY_OPC              6
+#define NVME_ADMIN_SECURITY_SEND_OPC         0x81
+#define NVME_ADMIN_SECURITY_RECV_OPC         0x82
+
+#define NVME_IO_FLUSH_OPC                    0
+#define NVME_IO_WRITE_OPC                    1
+#define NVME_IO_READ_OPC                     2
+
+//
+// Offset from the beginning of private Data queue Buffer
+//
+#define NVME_ASQ_BUF_OFFSET                  EFI_PAGE_SIZE
+
+#pragma pack()
+
+#endif
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
new file mode 100644
index 000000000000..17fda410dc54
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
@@ -0,0 +1,65 @@
+/** @file
+  Opal Password common header file.
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_PASSWORD_COMMON_H_
+#define _OPAL_PASSWORD_COMMON_H_
+
+#define OPAL_DEVICE_TYPE_UNKNOWN    0x0
+#define OPAL_DEVICE_TYPE_ATA        0x1
+#define OPAL_DEVICE_TYPE_NVME       0x2
+
+typedef struct {
+  UINT16            Segment;
+  UINT8             Bus;
+  UINT8             Device;
+  UINT8             Function;
+  UINT8             Reserved;
+} OPAL_PCI_DEVICE;
+
+typedef struct {
+  UINT16            Length;
+  OPAL_PCI_DEVICE   Device;
+  UINT8             PasswordLength;
+  UINT8             Password[32];
+  UINT16            OpalBaseComId;
+  UINT32            BarAddr;
+} OPAL_DEVICE_COMMON;
+
+#define OPAL_DEVICE_ATA_GUID { 0xcb934fe1, 0xb8cd, 0x46b1, { 0xa0, 0x58, 0xdd, 0xcb, 0x7, 0xb7, 0xb4, 0x17 } }
+
+typedef struct {
+  UINT16            Length;
+  OPAL_PCI_DEVICE   Device;
+  UINT8             PasswordLength;
+  UINT8             Password[32];
+  UINT16            OpalBaseComId;
+  UINT32            BarAddr;
+  UINT16            Port;
+  UINT16            PortMultiplierPort;
+} OPAL_DEVICE_ATA;
+
+#define OPAL_DEVICE_NVME_GUID { 0xde116925, 0xaf7f, 0x42d9, { 0x83, 0xc0, 0x7e, 0xd6, 0x26, 0x59, 0x0, 0xfb } }
+
+typedef struct {
+  UINT16            Length;
+  OPAL_PCI_DEVICE   Device;
+  UINT8             PasswordLength;
+  UINT8             Password[32];
+  UINT16            OpalBaseComId;
+  UINT32            BarAddr;
+  UINT32            NvmeNamespaceId;
+  OPAL_PCI_DEVICE   PciBridgeNode[0];
+} OPAL_DEVICE_NVME;
+
+#endif // _OPAL_PASSWORD_COMMON_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
new file mode 100644
index 000000000000..0ac550a72873
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
@@ -0,0 +1,81 @@
+## @file
+#  This is a OpalPasswordDxe driver.
+#
+#  This module is used to Management the Opal feature
+#  for Opal supported devices.
+#
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+[Defines]
+  INF_VERSION                    = 0x00010007
+  BASE_NAME                      = OpalPasswordDxe
+  FILE_GUID                      = E3E4048D-6C0C-43E4-AE1C-FFB579D8EF41
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = EfiDriverEntryPoint
+  UNLOAD_IMAGE                   = OpalEfiDriverUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  OpalDriver.c
+  OpalDriver.h
+  OpalPasswordCommon.h
+  OpalHii.c
+  OpalHii.h
+  OpalHiiCallbacks.c
+  OpalHiiFormValues.h
+  OpalHiiFormStrings.uni
+  OpalPasswordForm.vfr
+  ComponentName.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiRuntimeServicesTableLib
+  DxeServicesTableLib
+  UefiHiiServicesLib
+  BaseMemoryLib
+  DebugLib
+  HiiLib
+  PrintLib
+  DevicePathLib
+  UefiLib
+  TcgStorageOpalLib
+  Tcg2PhysicalPresenceLib
+  PciLib
+  S3BootScriptLib
+  LockBoxLib
+
+[Protocols]
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
+  gEfiStorageSecurityCommandProtocolGuid        ## CONSUMES
+  gEfiComponentNameProtocolGuid                 ## PRODUCES
+  gEfiComponentName2ProtocolGuid                ## PRODUCES
+  gEfiBlockIoProtocolGuid                       ## CONSUMES
+  gEfiPciIoProtocolGuid                         ## CONSUMES
+  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES             ## Event
+
+[Depex]
+  gEfiHiiStringProtocolGuid AND gEfiHiiDatabaseProtocolGuid
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
new file mode 100644
index 000000000000..cba388723305
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
@@ -0,0 +1,309 @@
+/** @file
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "OpalHiiFormValues.h"
+
+
+#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
+  { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } }
+
+formset
+  guid      = SETUP_FORMSET_GUID,
+  title     = STRING_TOKEN(STR_OPAL),
+  help      = STRING_TOKEN(STR_FORM_SET_HELP),
+  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
+
+  // Define a Buffer Storage (EFI_IFR_VARSTORE) that will be filled
+  // out initially through extractConfig call
+  varstore OPAL_HII_CONFIGURATION,           // This is the Data structure type
+    name  = OpalHiiConfig,                   // Define referenced name in vfr
+    guid  = SETUP_VARIABLE_GUID;             // GUID of this Buffer storage
+
+form formid = FORMID_VALUE_MAIN_MENU,
+    title  = STRING_TOKEN(STR_OPAL);
+
+    //CONFIG_VARIABLE(HII_KEY(HII_KEY_ID_VAR_SUPPORTED_DISKS), SupportedDisks, 0x0, 0xFFFF);
+    suppressif TRUE;
+        numeric
+            name    = SupportedDisks,
+            varid   = OpalHiiConfig.SupportedDisks,
+            prompt  = STRING_TOKEN(STR_NULL),
+            help    = STRING_TOKEN(STR_NULL),
+            flags   = INTERACTIVE,
+            key     = 0x8002,
+            minimum = 0x0,
+            maximum = 0xFFFF,
+        endnumeric;
+    endif;
+
+    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    subtitle text = STRING_TOKEN(STR_MAIN_PHY_DISKS_LBL);
+
+    //DISK( 0 );
+    suppressif ( questionref(SupportedDisks) & ( 0x1 ) ) == 0;
+        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0 ),
+            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+            flags   = INTERACTIVE,
+            key     = 0x8001;
+    endif;
+
+    //DISK( 1 );
+    suppressif ( questionref(SupportedDisks) & ( 0x2 ) ) == 0;
+        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1 ),
+            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+            flags   = INTERACTIVE,
+            key     = 0x8101;
+    endif;
+
+    //DISK( 2 );
+    suppressif ( questionref(SupportedDisks) & ( 0x4 ) ) == 0;
+        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2 ),
+            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+            flags   = INTERACTIVE,
+            key     = 0x8201;
+    endif;
+
+    //DISK( 3 );
+    suppressif ( questionref(SupportedDisks) & ( 0x8 ) ) == 0;
+        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3 ),
+            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+            flags   = INTERACTIVE,
+            key     = 0x8301;
+    endif;
+
+    //DISK( 4 );
+    suppressif ( questionref(SupportedDisks) & ( 0x10 ) ) == 0;
+        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4 ),
+            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+            flags   = INTERACTIVE,
+            key     = 0x8401;
+    endif;
+
+    //DISK( 5 );
+    suppressif ( questionref(SupportedDisks) & ( 0x20 ) ) == 0;
+        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5 ),
+            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+            flags   = INTERACTIVE,
+            key     = 0x8501;
+    endif;
+
+    //No disks on system
+    suppressif ideqval OpalHiiConfig.NumDisks > 0;
+        text
+            help    = STRING_TOKEN(STR_NULL),
+            text    = STRING_TOKEN(STR_MAIN_NO_DISKS_PRESENT_LBL);
+    endif;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    grayoutif TRUE;
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS);
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS1);
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS2);
+      text
+          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
+          text    = STRING_TOKEN(STR_BLOCKSID_STATUS3);
+      subtitle text = STRING_TOKEN(STR_NULL);
+    endif;
+
+    oneof varid   = OpalHiiConfig.EnableBlockSid,
+      questionid  = 0x8004,
+      prompt      = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID),
+      help        = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_HELP),
+      flags       = INTERACTIVE,
+      option text = STRING_TOKEN(STR_NONE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISABLED), value = 2, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), value = 3, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), value = 4, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), value = 5, flags = RESET_REQUIRED;
+      option text = STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), value = 6, flags = RESET_REQUIRED;
+    endoneof;
+
+
+
+endform;  // MAIN MENU FORM
+
+//
+/////////////////   DISK INFO FORM   /////////////////
+//
+form formid = FORMID_VALUE_DISK_INFO_FORM_MAIN,
+    title  = STRING_TOKEN(STR_OPAL);
+
+    suppressif TRUE;
+        numeric
+            name    = SelectedDiskAvailableActions,
+            varid   = OpalHiiConfig.SelectedDiskAvailableActions,
+            prompt  = STRING_TOKEN(STR_NULL),
+            help    = STRING_TOKEN(STR_NULL),
+            flags   = INTERACTIVE,
+            key     = 0x8003,
+            minimum = 0x0,
+            maximum = 0xFFFF,
+        endnumeric;
+    endif;
+
+    suppressif TRUE;
+        checkbox varid = OpalHiiConfig.KeepUserDataForced,
+            prompt = STRING_TOKEN(STR_NULL),
+            help = STRING_TOKEN(STR_NULL),
+        endcheckbox;
+    endif;
+
+    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    text
+        help   = STRING_TOKEN(STR_NULL),
+        text   = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    subtitle text = STRING_TOKEN(STR_OPAL_REQUESTS_LBL);
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SET_ADMIN_PWD ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.SetAdminPwd,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD),
+            help    = STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x8005,
+        endcheckbox;
+    endif;
+    endif;
+    endif;
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SET_USER_PWD ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.SetUserPwd,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD),
+            help    = STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x8006,
+        endcheckbox;
+    endif;
+    endif;
+    endif;
+    endif;
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SECURE_ERASE ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.SecureErase,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE),
+            help    = STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x8007,
+        endcheckbox;
+    endif;
+    endif;
+    endif;
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_REVERT ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SetAdminPwd == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SecureErase == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.Revert,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_REVERT),
+            help    = STRING_TOKEN(STR_DISK_INFO_REVERT_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x8008,
+        endcheckbox;
+    endif;
+    endif;
+    endif;
+    endif;
+    endif;
+    endif;
+
+    suppressif ideqval OpalHiiConfig.OpalRequest.Revert == 0;
+        grayoutif ideqval OpalHiiConfig.KeepUserDataForced == 1;
+            checkbox varid = OpalHiiConfig.OpalRequest.KeepUserData,
+                prompt  = STRING_TOKEN(STR_KEEP_USER_DATA_PROMPT),
+                help    = STRING_TOKEN(STR_KEEP_USER_DATA_HELP),
+                flags   = INTERACTIVE | RESET_REQUIRED,
+                key     = 0x8009,
+            endcheckbox;
+        endif;
+    endif;
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_PSID_REVERT ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SetAdminPwd == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SecureErase == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.EnableFeature == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.PsidRevert,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
+            help    = STRING_TOKEN(STR_DISK_INFO_PSID_REVERT_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x800A,
+         endcheckbox;
+    endif;
+    endif;
+    endif;
+    endif;
+    endif;
+    endif;
+    endif;
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_DISABLE_USER ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.DisableUser,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_DISABLE_USER),
+            help    = STRING_TOKEN(STR_DISK_INFO_DISABLE_USER_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x800B,
+         endcheckbox;
+    endif;
+    endif;
+    endif;
+    endif;
+
+    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_ENABLE_FEATURE ) == 0;
+    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
+        checkbox varid = OpalHiiConfig.OpalRequest.EnableFeature,
+            prompt  = STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE),
+            help    = STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE_HELP),
+            flags   = INTERACTIVE | RESET_REQUIRED,
+            key     = 0x800C,
+        endcheckbox;
+    endif;
+    endif;
+
+endform;  // DISK INFO FORM
+
+endformset;
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
new file mode 100644
index 000000000000..1788b2ad3339
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
@@ -0,0 +1,940 @@
+/** @file
+  Opal Password PEI driver which is used to unlock Opal Password for S3.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalPasswordPei.h"
+
+EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
+EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
+
+#define OPAL_PCIE_ROOTPORT_SAVESIZE               (0x40)
+#define STORE_INVALID_ROOTPORT_INDEX              ((UINT8) -1)
+
+/**
+  Get IOMMU PPI.
+
+  @return Pointer to IOMMU PPI.
+
+**/
+EDKII_IOMMU_PPI *
+GetIoMmu (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+  EDKII_IOMMU_PPI           *IoMmu;
+
+  IoMmu = NULL;
+  Status = PeiServicesLocatePpi (
+             &gEdkiiIoMmuPpiGuid,
+             0,
+             NULL,
+             (VOID **) &IoMmu
+             );
+  if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
+    return IoMmu;
+  }
+
+  return NULL;
+}
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param Pages                  The number of pages to allocate.
+  @param HostAddress            A pointer to store the base system memory address of the
+                                allocated range.
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param Mapping                A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+IoMmuAllocateBuffer (
+  IN UINTN                  Pages,
+  OUT VOID                  **HostAddress,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 NumberOfBytes;
+  EFI_PHYSICAL_ADDRESS  HostPhyAddress;
+  EDKII_IOMMU_PPI       *IoMmu;
+
+  *HostAddress = NULL;
+  *DeviceAddress = 0;
+  *Mapping = NULL;
+
+  IoMmu = GetIoMmu ();
+
+  if (IoMmu != NULL) {
+    Status = IoMmu->AllocateBuffer (
+                      IoMmu,
+                      EfiBootServicesData,
+                      Pages,
+                      HostAddress,
+                      0
+                      );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
+    Status = IoMmu->Map (
+                      IoMmu,
+                      EdkiiIoMmuOperationBusMasterCommonBuffer,
+                      *HostAddress,
+                      &NumberOfBytes,
+                      DeviceAddress,
+                      Mapping
+                      );
+    if (EFI_ERROR (Status)) {
+      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
+      *HostAddress = NULL;
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Status = IoMmu->SetAttribute (
+                      IoMmu,
+                      *Mapping,
+                      EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
+                      );
+    if (EFI_ERROR (Status)) {
+      IoMmu->Unmap (IoMmu, *Mapping);
+      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
+      *Mapping = NULL;
+      *HostAddress = NULL;
+      return Status;
+    }
+  } else {
+    Status = PeiServicesAllocatePages (
+               EfiBootServicesData,
+               Pages,
+               &HostPhyAddress
+               );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    *HostAddress = (VOID *) (UINTN) HostPhyAddress;
+    *DeviceAddress = HostPhyAddress;
+    *Mapping = NULL;
+  }
+  return Status;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param Pages              The number of pages to free.
+  @param HostAddress        The base system memory address of the allocated range.
+  @param Mapping            The mapping value returned from Map().
+
+**/
+VOID
+IoMmuFreeBuffer (
+  IN UINTN                  Pages,
+  IN VOID                   *HostAddress,
+  IN VOID                   *Mapping
+  )
+{
+  EDKII_IOMMU_PPI       *IoMmu;
+
+  IoMmu = GetIoMmu ();
+
+  if (IoMmu != NULL) {
+    IoMmu->SetAttribute (IoMmu, Mapping, 0);
+    IoMmu->Unmap (IoMmu, Mapping);
+    IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);
+  } else {
+    PeiServicesFreePages (
+      (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
+      Pages
+      );
+  }
+}
+
+/**
+  Provide IO action support.
+
+  @param[in]     PeiDev             The opal device need to perform trusted IO.
+  @param[in]     IoType             OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.
+  @param[in]     SecurityProtocol   Security Protocol
+  @param[in]     SpSpecific         Security Protocol Specific
+  @param[in]     TransferLength     Transfer Length of Buffer (in bytes) - always a multiple of 512
+  @param[in]     Buffer             Address of Data to transfer
+
+  @retval        EFI_SUCCESS        Perform the IO action success.
+  @retval        Others             Perform the IO action failed.
+
+**/
+EFI_STATUS
+PerformTrustedIo (
+  OPAL_PEI_DEVICE  *PeiDev,
+  OPAL_IO_TYPE     IoType,
+  UINT8            SecurityProtocol,
+  UINT16           SpSpecific,
+  UINTN            TransferLength,
+  VOID             *Buffer
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         BufferSizeBlocks;
+  EFI_ATA_COMMAND_BLOCK         AtaCommandBlock;
+  OPAL_DEVICE_ATA               *DevInfoAta;
+  AHCI_CONTEXT                  *AhciContext;
+  NVME_CONTEXT                  *NvmeContext;
+
+  Status = EFI_DEVICE_ERROR;
+  if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_ATA) {
+    DevInfoAta = (OPAL_DEVICE_ATA *) PeiDev->Device;
+    AhciContext = (AHCI_CONTEXT *) PeiDev->Context;
+
+    BufferSizeBlocks = TransferLength / 512;
+
+    ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
+    AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ? ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
+    AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
+    AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
+    AtaCommandBlock.AtaFeatures = SecurityProtocol;
+    AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
+    AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
+    AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
+
+
+    ZeroMem( AhciContext->Buffer, HDD_PAYLOAD );
+    ASSERT( TransferLength <= HDD_PAYLOAD );
+
+    if (IoType == OpalSend) {
+      CopyMem( AhciContext->Buffer, Buffer, TransferLength );
+    }
+
+    Status = AhciPioTransfer(
+                AhciContext,
+                (UINT8) DevInfoAta->Port,
+                (UINT8) DevInfoAta->PortMultiplierPort,
+                NULL,
+                0,
+                ( IoType == OpalSend ) ? FALSE : TRUE,   // i/o direction
+                &AtaCommandBlock,
+                NULL,
+                AhciContext->Buffer,
+                (UINT32)TransferLength,
+                ATA_TIMEOUT
+                );
+
+    if (IoType == OpalRecv) {
+      CopyMem( Buffer, AhciContext->Buffer, TransferLength );
+    }
+  } else if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
+    NvmeContext = (NVME_CONTEXT *) PeiDev->Context;
+    Status = NvmeSecuritySendReceive (
+                NvmeContext,
+                IoType == OpalSend,
+                SecurityProtocol,
+                SwapBytes16(SpSpecific),
+                TransferLength,
+                Buffer
+              );
+  } else {
+    DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", PeiDev->DeviceType));
+  }
+
+  return Status;
+}
+
+/**
+  Send a security protocol command to a device that receives data and/or the result
+  of one or more commands sent by SendData.
+
+  The ReceiveData function sends a security protocol command to the given MediaId.
+  The security protocol command sent is defined by SecurityProtocolId and contains
+  the security protocol specific data SecurityProtocolSpecificData. The function
+  returns the data from the security protocol command in PayloadBuffer.
+
+  For devices supporting the SCSI command set, the security protocol command is sent
+  using the SECURITY PROTOCOL IN command defined in SPC-4.
+
+  For devices supporting the ATA command set, the security protocol command is sent
+  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
+  is non-zero.
+
+  If the PayloadBufferSize is zero, the security protocol command is sent using the
+  Trusted Non-Data command defined in ATA8-ACS.
+
+  If PayloadBufferSize is too small to store the available data from the security
+  protocol command, the function shall copy PayloadBufferSize bytes into the
+  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
+
+  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
+  the function shall return EFI_INVALID_PARAMETER.
+
+  If the given MediaId does not support security protocol commands, the function shall
+  return EFI_UNSUPPORTED. If there is no media in the device, the function returns
+  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
+  the function returns EFI_MEDIA_CHANGED.
+
+  If the security protocol fails to complete within the Timeout period, the function
+  shall return EFI_TIMEOUT.
+
+  If the security protocol command completes without an error, the function shall
+  return EFI_SUCCESS. If the security protocol command completes with an error, the
+  function shall return EFI_DEVICE_ERROR.
+
+  @param  This                         Indicates a pointer to the calling context.
+  @param  MediaId                      ID of the medium to receive data from.
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution
+                                       of the security protocol command. A Timeout value of 0
+                                       means that this function will wait indefinitely for the
+                                       security protocol command to execute. If Timeout is greater
+                                       than zero, then this function will return EFI_TIMEOUT
+                                       if the time required to execute the receive data command
+                                       is greater than Timeout.
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
+                                       the security protocol command to be sent.
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
+                                       of the security protocol command to be sent.
+  @param  PayloadBufferSize            Size in bytes of the payload data buffer.
+  @param  PayloadBuffer                A pointer to a destination buffer to store the security
+                                       protocol command specific payload data for the security
+                                       protocol command. The caller is responsible for having
+                                       either implicit or explicit ownership of the buffer.
+  @param  PayloadTransferSize          A pointer to a buffer to store the size in bytes of the
+                                       data written to the payload data buffer.
+
+  @retval EFI_SUCCESS                  The security protocol command completed successfully.
+  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too small to store the available
+                                       data from the device. The PayloadBuffer contains the truncated data.
+  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
+  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
+  @retval EFI_NO_MEDIA                 There is no media in the device.
+  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
+  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or PayloadTransferSize is NULL and
+                                       PayloadBufferSize is non-zero.
+  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
+                                       protocol command to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+SecurityReceiveData (
+  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
+  IN  UINT32                                   MediaId,
+  IN  UINT64                                   Timeout,
+  IN  UINT8                                    SecurityProtocolId,
+  IN  UINT16                                   SecurityProtocolSpecificData,
+  IN  UINTN                                    PayloadBufferSize,
+  OUT VOID                                     *PayloadBuffer,
+  OUT UINTN                                    *PayloadTransferSize
+  )
+{
+  OPAL_PEI_DEVICE               *PeiDev;
+
+  PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
+  if (PeiDev == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return PerformTrustedIo (
+                        PeiDev,
+                        OpalRecv,
+                        SecurityProtocolId,
+                        SecurityProtocolSpecificData,
+                        PayloadBufferSize,
+                        PayloadBuffer
+                        );
+}
+
+/**
+  Send a security protocol command to a device.
+
+  The SendData function sends a security protocol command containing the payload
+  PayloadBuffer to the given MediaId. The security protocol command sent is
+  defined by SecurityProtocolId and contains the security protocol specific data
+  SecurityProtocolSpecificData. If the underlying protocol command requires a
+  specific padding for the command payload, the SendData function shall add padding
+  bytes to the command payload to satisfy the padding requirements.
+
+  For devices supporting the SCSI command set, the security protocol command is sent
+  using the SECURITY PROTOCOL OUT command defined in SPC-4.
+
+  For devices supporting the ATA command set, the security protocol command is sent
+  using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
+  is non-zero. If the PayloadBufferSize is zero, the security protocol command is
+  sent using the Trusted Non-Data command defined in ATA8-ACS.
+
+  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
+  return EFI_INVALID_PARAMETER.
+
+  If the given MediaId does not support security protocol commands, the function
+  shall return EFI_UNSUPPORTED. If there is no media in the device, the function
+  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
+  device, the function returns EFI_MEDIA_CHANGED.
+
+  If the security protocol fails to complete within the Timeout period, the function
+  shall return EFI_TIMEOUT.
+
+  If the security protocol command completes without an error, the function shall return
+  EFI_SUCCESS. If the security protocol command completes with an error, the function
+  shall return EFI_DEVICE_ERROR.
+
+  @param  This                         Indicates a pointer to the calling context.
+  @param  MediaId                      ID of the medium to receive data from.
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution
+                                       of the security protocol command. A Timeout value of 0
+                                       means that this function will wait indefinitely for the
+                                       security protocol command to execute. If Timeout is greater
+                                       than zero, then this function will return EFI_TIMEOUT
+                                       if the time required to execute the send data command
+                                       is greater than Timeout.
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
+                                       the security protocol command to be sent.
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
+                                       of the security protocol command to be sent.
+  @param  PayloadBufferSize            Size in bytes of the payload data buffer.
+  @param  PayloadBuffer                A pointer to a destination buffer to store the security
+                                       protocol command specific payload data for the security
+                                       protocol command.
+
+  @retval EFI_SUCCESS                  The security protocol command completed successfully.
+  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
+  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
+  @retval EFI_NO_MEDIA                 There is no media in the device.
+  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
+  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
+  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
+                                       protocol command to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+SecuritySendData (
+  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
+  IN UINT32                                   MediaId,
+  IN UINT64                                   Timeout,
+  IN UINT8                                    SecurityProtocolId,
+  IN UINT16                                   SecurityProtocolSpecificData,
+  IN UINTN                                    PayloadBufferSize,
+  IN VOID                                     *PayloadBuffer
+  )
+{
+  OPAL_PEI_DEVICE               *PeiDev;
+
+  PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
+  if (PeiDev == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return PerformTrustedIo (
+                          PeiDev,
+                          OpalSend,
+                          SecurityProtocolId,
+                          SecurityProtocolSpecificData,
+                          PayloadBufferSize,
+                          PayloadBuffer
+                          );
+
+}
+
+/**
+  Save/Restore RootPort configuration space.
+
+  @param[in]     DevInfoNvme            Pointer to NVMe device info.
+  @param[in]     SaveAction             TRUE: Save, FALSE: Restore
+  @param[in,out] PcieConfBufferList    Configuration space data buffer for save/restore
+
+  @return PCIE base address of this RootPort
+**/
+UINTN
+SaveRestoreRootportConfSpace (
+  IN     OPAL_DEVICE_NVME               *DevInfoNvme,
+  IN     BOOLEAN                        SaveAction,
+  IN OUT UINT8                          **PcieConfBufferList
+  )
+{
+  UINTN             RpBase;
+  UINTN             Length;
+  OPAL_PCI_DEVICE   *DevNode;
+  UINT8             *StorePcieConfData;
+  UINTN             Index;
+
+  Length = 0;
+  Index  = 0;
+  RpBase = 0;
+
+  while (sizeof (OPAL_DEVICE_NVME) + Length < DevInfoNvme->Length) {
+    DevNode = (OPAL_PCI_DEVICE *)((UINT8*)DevInfoNvme->PciBridgeNode + Length);
+    RpBase = PCI_LIB_ADDRESS (DevNode->Bus, DevNode->Device, DevNode->Function, 0x0);
+
+    if (PcieConfBufferList != NULL) {
+      if (SaveAction) {
+        StorePcieConfData = (UINT8 *) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE);
+        ASSERT (StorePcieConfData != NULL);
+        OpalPciRead (StorePcieConfData, RpBase, OPAL_PCIE_ROOTPORT_SAVESIZE);
+        PcieConfBufferList[Index] = StorePcieConfData;
+      } else {
+        // Skip PCIe Command & Status registers
+        StorePcieConfData = PcieConfBufferList[Index];
+        OpalPciWrite (RpBase, StorePcieConfData, 4);
+        OpalPciWrite (RpBase + 8, StorePcieConfData + 8, OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
+
+        FreePool (StorePcieConfData);
+      }
+    }
+
+    Length += sizeof (OPAL_PCI_DEVICE);
+    Index ++;
+  }
+
+  return RpBase;
+}
+
+/**
+  Configure RootPort for downstream PCIe NAND devices.
+
+  @param[in] RpBase             - PCIe configuration space address of this RootPort
+  @param[in] BusNumber          - Bus number
+  @param[in] MemoryBase         - Memory base address
+  @param[in] MemoryLength       - Memory size
+
+**/
+VOID
+ConfigureRootPortForPcieNand (
+  IN UINTN   RpBase,
+  IN UINTN   BusNumber,
+  IN UINT32  MemoryBase,
+  IN UINT32  MemoryLength
+  )
+{
+  UINT32  MemoryLimit;
+
+  DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",
+    BusNumber, MemoryBase, MemoryLength));
+
+  if (MemoryLength == 0) {
+    MemoryLimit = MemoryBase;
+  } else {
+    MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
+  }
+
+  ///
+  /// Configue PCIE configuration space for RootPort
+  ///
+  PciWrite8  (RpBase + NVME_PCIE_BNUM + 1,  (UINT8) BusNumber);           // Secondary Bus Number registers
+  PciWrite8  (RpBase + NVME_PCIE_BNUM + 2,  (UINT8) BusNumber);           // Subordinate Bus Number registers
+  PciWrite8  (RpBase + NVME_PCIE_IOBL,      0xFF);                        // I/O Base registers
+  PciWrite8  (RpBase + NVME_PCIE_IOBL + 1,  0x00);                        // I/O Limit registers
+  PciWrite16 (RpBase + NVME_PCIE_MBL,       (UINT16) RShiftU64 ((UINTN)MemoryBase, 16));  // Memory Base register
+  PciWrite16 (RpBase + NVME_PCIE_MBL + 2,   (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register
+  PciWrite16 (RpBase + NVME_PCIE_PMBL,      0xFFFF);                      // Prefetchable Memory Base registers
+  PciWrite16 (RpBase + NVME_PCIE_PMBL + 2,  0x0000);                      // Prefetchable Memory Limit registers
+  PciWrite32 (RpBase + NVME_PCIE_PMBU32,    0xFFFFFFFF);                  // Prefetchable Memory Upper Base registers
+  PciWrite32 (RpBase + NVME_PCIE_PMLU32,    0x00000000);                  // Prefetchable Memory Upper Limit registers
+}
+
+/**
+
+  The function returns whether or not the device is Opal Locked.
+  TRUE means that the device is partially or fully locked.
+  This will perform a Level 0 Discovery and parse the locking feature descriptor
+
+  @param[in]      OpalDev             Opal object to determine if locked.
+  @param[out]     BlockSidSupported   Whether device support BlockSid feature.
+
+**/
+BOOLEAN
+IsOpalDeviceLocked(
+  OPAL_PEI_DEVICE    *OpalDev,
+  BOOLEAN            *BlockSidSupported
+  )
+{
+  OPAL_SESSION                   Session;
+  OPAL_DISK_SUPPORT_ATTRIBUTE    SupportedAttributes;
+  TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;
+  UINT16                         OpalBaseComId;
+  TCG_RESULT                     Ret;
+
+  Session.Sscp = &OpalDev->Sscp;
+  Session.MediaId = 0;
+
+  Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes, &OpalBaseComId);
+  if (Ret != TcgResultSuccess) {
+    return FALSE;
+  }
+
+  Session.OpalBaseComId  = OpalBaseComId;
+  *BlockSidSupported     = SupportedAttributes.BlockSid == 1 ? TRUE : FALSE;
+
+  Ret = OpalGetLockingInfo(&Session, &LockingFeature);
+  if (Ret != TcgResultSuccess) {
+    return FALSE;
+  }
+
+  return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);
+}
+
+/**
+  Unlock OPAL password for S3.
+
+  @param[in] OpalDev            Opal object to unlock.
+
+**/
+VOID
+UnlockOpalPassword (
+  IN OPAL_PEI_DEVICE            *OpalDev
+  )
+{
+  TCG_RESULT                    Result;
+  OPAL_SESSION                  Session;
+  BOOLEAN                       BlockSidSupport;
+  UINT32                        PpStorageFlags;
+  BOOLEAN                       BlockSIDEnabled;
+
+  BlockSidSupport = FALSE;
+  if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
+    ZeroMem(&Session, sizeof (Session));
+    Session.Sscp = &OpalDev->Sscp;
+    Session.MediaId = 0;
+    Session.OpalBaseComId = OpalDev->Device->OpalBaseComId;
+
+    Result = OpalUtilUpdateGlobalLockingRange (
+               &Session,
+               OpalDev->Device->Password,
+               OpalDev->Device->PasswordLength,
+               FALSE,
+               FALSE
+               );
+    DEBUG ((
+      DEBUG_INFO,
+      "%a() OpalUtilUpdateGlobalLockingRange() Result = 0x%x\n",
+      __FUNCTION__,
+      Result
+      ));
+  }
+
+  PpStorageFlags = Tcg2PhysicalPresenceLibGetManagementFlags ();
+  if ((PpStorageFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
+    BlockSIDEnabled = TRUE;
+  } else {
+    BlockSIDEnabled = FALSE;
+  }
+  if (BlockSIDEnabled && BlockSidSupport) {
+    Result = OpalBlockSid (&Session, TRUE);
+    DEBUG ((
+      DEBUG_INFO,
+      "%a() OpalBlockSid() Result = 0x%x\n",
+      __FUNCTION__,
+      Result
+      ));
+  }
+}
+
+/**
+  Unlock ATA OPAL password for S3.
+
+**/
+VOID
+UnlockOpalPasswordAta (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  UINT8                         *DevInfo;
+  OPAL_DEVICE_ATA               TempDevInfoAta;
+  OPAL_DEVICE_ATA               *DevInfoAta;
+  UINTN                         DevInfoLengthAta;
+  UINT8                         Bus;
+  UINT8                         Device;
+  UINT8                         Function;
+  OPAL_PEI_DEVICE               OpalDev;
+  UINT8                         BaseClassCode;
+  UINT8                         SubClassCode;
+  UINT8                         SataCmdSt;
+  AHCI_CONTEXT                  AhciContext;
+  UINT32                        AhciBar;
+
+  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
+
+  //
+  // Get ATA OPAL device info from LockBox.
+  //
+  DevInfo = (UINT8 *) &TempDevInfoAta;
+  DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);
+  Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));
+    if (DevInfo != NULL) {
+      Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);
+    }
+  }
+  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
+    return;
+  }
+
+  for (DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
+       (UINTN) DevInfoAta < ((UINTN) DevInfo + DevInfoLengthAta);
+       DevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) DevInfoAta + DevInfoAta->Length)) {
+    Bus = DevInfoAta->Device.Bus;
+    Device = DevInfoAta->Device.Device;
+    Function = DevInfoAta->Device.Function;
+
+    SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET));
+    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), 0x6);
+
+    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
+    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
+    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
+        ((SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) && (SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))) {
+      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode are not supported\n", __FUNCTION__));
+    } else {
+      AhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
+      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), DevInfoAta->BarAddr);
+
+      ZeroMem (&AhciContext, sizeof (AHCI_CONTEXT));
+      AhciContext.AhciBar = DevInfoAta->BarAddr;
+      AhciAllocateResource (&AhciContext);
+      Status = AhciModeInitialize (&AhciContext, (UINT8)DevInfoAta->Port);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a() AhciModeInitialize() error, Status: %r\n", __FUNCTION__, Status));
+      }
+
+      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
+      OpalDev.Sscp.ReceiveData = SecurityReceiveData;
+      OpalDev.Sscp.SendData = SecuritySendData;
+      OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;
+      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;
+      OpalDev.Context = &AhciContext;
+
+      UnlockOpalPassword (&OpalDev);
+
+      AhciFreeResource (&AhciContext);
+      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), AhciBar);
+    }
+    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), SataCmdSt);
+  }
+
+  ZeroMem (DevInfo, DevInfoLengthAta);
+  if ((UINTN) DevInfo != (UINTN) &TempDevInfoAta) {
+    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthAta));
+  }
+
+  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
+}
+
+/**
+  Unlock NVMe OPAL password for S3.
+
+**/
+VOID
+UnlockOpalPasswordNvme (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  UINT8                         *DevInfo;
+  OPAL_DEVICE_NVME              TempDevInfoNvme;
+  OPAL_DEVICE_NVME              *DevInfoNvme;
+  UINTN                         DevInfoLengthNvme;
+  UINT8                         Bus;
+  UINT8                         Device;
+  UINT8                         Function;
+  OPAL_PEI_DEVICE               OpalDev;
+  UINT8                         BaseClassCode;
+  UINT8                         SubClassCode;
+  UINT8                         ProgInt;
+  UINT8                         NvmeCmdSt;
+  UINT8                         *StorePcieConfDataList[16];
+  UINTN                         RpBase;
+  UINTN                         MemoryBase;
+  UINTN                         MemoryLength;
+  NVME_CONTEXT                  NvmeContext;
+
+  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
+
+  //
+  // Get NVMe OPAL device info from LockBox.
+  //
+  DevInfo = (UINT8 *) &TempDevInfoNvme;
+  DevInfoLengthNvme = sizeof (OPAL_DEVICE_NVME);
+  Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
+    if (DevInfo != NULL) {
+      Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);
+    }
+  }
+  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
+    return;
+  }
+
+  for (DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
+       (UINTN) DevInfoNvme < ((UINTN) DevInfo + DevInfoLengthNvme);
+       DevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) DevInfoNvme + DevInfoNvme->Length)) {
+    Bus = DevInfoNvme->Device.Bus;
+    Device = DevInfoNvme->Device.Device;
+    Function = DevInfoNvme->Device.Function;
+
+    RpBase    = 0;
+    NvmeCmdSt = 0;
+
+    ///
+    /// Save original RootPort configuration space to heap
+    ///
+    RpBase = SaveRestoreRootportConfSpace (
+                DevInfoNvme,
+                TRUE, // save
+                StorePcieConfDataList
+                );
+    MemoryBase = DevInfoNvme->BarAddr;
+    MemoryLength = 0;
+    ConfigureRootPortForPcieNand (RpBase, Bus, (UINT32) MemoryBase, (UINT32) MemoryLength);
+
+    ///
+    /// Enable PCIE decode for RootPort
+    ///
+    NvmeCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
+    PciWrite8  (RpBase + NVME_PCIE_PCICMD,  0x6);
+
+    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
+    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
+    ProgInt       = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x09));
+    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
+        (SubClassCode != PCI_CLASS_MASS_STORAGE_NVM) ||
+        (ProgInt != PCI_IF_NVMHCI)) {
+      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode/PI are not supported\n", __FUNCTION__));
+    } else {
+      ZeroMem (&NvmeContext, sizeof (NVME_CONTEXT));
+      NvmeContext.Nbar = DevInfoNvme->BarAddr;
+      NvmeContext.PciBase = PCI_LIB_ADDRESS (Bus, Device, Function, 0x0);
+      NvmeContext.NvmeInitWaitTime = 0;
+      NvmeContext.Nsid = DevInfoNvme->NvmeNamespaceId;
+      NvmeAllocateResource (&NvmeContext);
+      Status = NvmeControllerInit (&NvmeContext);
+
+      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
+      OpalDev.Sscp.ReceiveData = SecurityReceiveData;
+      OpalDev.Sscp.SendData = SecuritySendData;
+      OpalDev.DeviceType = OPAL_DEVICE_TYPE_NVME;
+      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoNvme;
+      OpalDev.Context = &NvmeContext;
+
+      UnlockOpalPassword (&OpalDev);
+
+      Status = NvmeControllerExit (&NvmeContext);
+      NvmeFreeResource (&NvmeContext);
+    }
+
+    ASSERT (RpBase != 0);
+    PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);
+    RpBase = SaveRestoreRootportConfSpace (
+                DevInfoNvme,
+                FALSE,  // restore
+                StorePcieConfDataList
+                );
+    PciWrite8  (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
+  }
+
+  ZeroMem (DevInfo, DevInfoLengthNvme);
+  if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
+    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
+  }
+
+  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
+}
+
+/**
+  Unlock OPAL password for S3.
+
+**/
+VOID
+OpalPasswordS3 (
+  VOID
+  )
+{
+  UnlockOpalPasswordAta ();
+  UnlockOpalPasswordNvme ();
+}
+
+/**
+  Entry point of the notification callback function itself within the PEIM.
+  It is to unlock OPAL password for S3.
+
+  @param  PeiServices      Indirect reference to the PEI Services Table.
+  @param  NotifyDescriptor Address of the notification descriptor data structure.
+  @param  Ppi              Address of the PPI that was installed.
+
+  @return Status of the notification.
+          The status code returned from this function is ignored.
+**/
+EFI_STATUS
+EFIAPI
+OpalPasswordEndOfPeiNotify(
+  IN EFI_PEI_SERVICES          **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+  IN VOID                      *Ppi
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_BOOT_MODE                     BootMode;
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+  if (BootMode != BOOT_ON_S3_RESUME) {
+    return EFI_UNSUPPORTED;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
+
+  OpalPasswordS3 ();
+
+  DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));
+
+  return EFI_SUCCESS;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordEndOfPeiNotifyDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiEndOfPeiSignalPpiGuid,
+  OpalPasswordEndOfPeiNotify
+};
+
+/**
+  Main entry for this module.
+
+  @param FileHandle             Handle of the file being invoked.
+  @param PeiServices            Pointer to PEI Services table.
+
+  @return Status from PeiServicesNotifyPpi.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalPasswordPeiInit (
+  IN EFI_PEI_FILE_HANDLE        FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS                    Status;
+
+  Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
new file mode 100644
index 000000000000..31aab37f5d91
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
@@ -0,0 +1,133 @@
+/** @file
+  Opal Password PEI driver which is used to unlock Opal Password for S3.
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_PASSWORD_PEI_H_
+#define _OPAL_PASSWORD_PEI_H_
+
+#include <PiPei.h>
+#include <IndustryStandard/Atapi.h>
+#include <IndustryStandard/Pci.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <Library/TimerLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/TcgStorageOpalLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include <Protocol/StorageSecurityCommand.h>
+
+#include <Ppi/IoMmu.h>
+
+#include "OpalPasswordCommon.h"
+#include "OpalAhciMode.h"
+#include "OpalNvmeMode.h"
+
+//
+// Time out Value for ATA pass through protocol
+//
+#define ATA_TIMEOUT                      30000000
+
+//
+// The payload Length of HDD related ATA commands
+//
+#define HDD_PAYLOAD                      512
+//
+// According to ATA spec, the max Length of hdd password is 32 bytes
+//
+#define OPAL_PASSWORD_MAX_LENGTH         32
+
+#pragma pack(1)
+
+/**
+* Opal I/O Type utilized by the Trusted IO callback
+*
+* The type indicates if the I/O is a send or receive
+*/
+typedef enum {
+    //
+    // I/O is a TCG Trusted Send command
+    //
+    OpalSend,
+
+    //
+    // I/O is a TCG Trusted Receive command
+    //
+    OpalRecv
+} OPAL_IO_TYPE;
+
+#define OPAL_PEI_DEVICE_SIGNATURE SIGNATURE_32 ('o', 'p', 'd', 's')
+
+typedef struct {
+  UINTN                                     Signature;
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL     Sscp;
+  UINT8                                     DeviceType;
+  OPAL_DEVICE_COMMON                        *Device;
+  VOID                                      *Context;
+} OPAL_PEI_DEVICE;
+
+#define OPAL_PEI_DEVICE_FROM_THIS(a)  CR (a, OPAL_PEI_DEVICE, Sscp, OPAL_PEI_DEVICE_SIGNATURE)
+
+#pragma pack()
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param Pages                  The number of pages to allocate.
+  @param HostAddress            A pointer to store the base system memory address of the
+                                allocated range.
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param Mapping                A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+IoMmuAllocateBuffer (
+  IN UINTN                  Pages,
+  OUT VOID                  **HostAddress,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  );
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param Pages              The number of pages to free.
+  @param HostAddress        The base system memory address of the allocated range.
+  @param Mapping            The mapping value returned from Map().
+
+**/
+VOID
+IoMmuFreeBuffer (
+  IN UINTN                  Pages,
+  IN VOID                   *HostAddress,
+  IN VOID                   *Mapping
+  );
+
+#endif // _OPAL_PASSWORD_PEI_H_
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
new file mode 100644
index 000000000000..81c57c36d2aa
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
@@ -0,0 +1,63 @@
+## @file
+#  This is a Opal Password PEI driver.
+#
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = OpalPasswordPei
+  FILE_GUID                      = DED60489-979C-4B5A-8EE4-4068B0CC38DC
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = OpalPasswordPeiInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  OpalPasswordPei.c
+  OpalPasswordPei.h
+  OpalPasswordCommon.h
+  OpalAhciMode.c
+  OpalAhciMode.h
+  OpalNvmeMode.c
+  OpalNvmeMode.h
+  OpalNvmeReg.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  PeimEntryPoint
+  PeiServicesLib
+  DebugLib
+  IoLib
+  PciLib
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  TimerLib
+  HobLib
+  LockBoxLib
+  TcgStorageOpalLib
+  Tcg2PhysicalPresenceLib
+
+[Ppis]
+  gEdkiiIoMmuPpiGuid                            ## SOMETIMES_CONSUMES
+  gEfiEndOfPeiSignalPpiGuid                     ## NOTIFY
+
+[Depex]
+  gEfiPeiMasterBootModePpiGuid
-- 
2.7.0.windows.1



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

* [PATCH V2 5/7] SecurityPkg OpalPassword: Remove old solution
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
                   ` (3 preceding siblings ...)
  2018-03-07 13:19 ` [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  2018-03-07 13:19 ` [PATCH V2 6/7] SecurityPkg OpalPasswordSupportLib: Remove it Star Zeng
  2018-03-07 13:19 ` [PATCH V2 7/7] SecurityPkg OpalPasswordExtraInfoVariable.h: " Star Zeng
  6 siblings, 0 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/SecurityPkg.dsc                        |    2 -
 .../Tcg/Opal/OpalPasswordDxe/ComponentName.c       |  398 ----
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c  | 1091 ----------
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h  |  412 ----
 .../Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h   |  102 -
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c     | 1527 --------------
 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h     |  146 --
 .../Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c    |  221 --
 .../Opal/OpalPasswordDxe/OpalHiiFormStrings.uni    |  103 -
 .../Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h   |  120 --
 .../Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h      |  268 ---
 .../Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf   |   82 -
 .../Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr  |  350 ----
 .../Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c        | 1267 ------------
 .../Tcg/Opal/OpalPasswordSmm/OpalAhciMode.h        |  408 ----
 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c |  767 -------
 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h |  173 --
 .../Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.c        | 2165 --------------------
 .../Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.h        |  456 -----
 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeReg.h |  814 --------
 .../Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c     | 1088 ----------
 .../Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h     |  299 ---
 .../Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf   |   77 -
 23 files changed, 12336 deletions(-)
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeReg.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h
 delete mode 100644 SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf

diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index f82703a17b82..9be484877cc2 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -322,8 +322,6 @@ [Components.IA32, Components.X64]
   #
   # Opal Password solution
   #
-  SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
-  SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf
   SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
   SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
 
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c
deleted file mode 100644
index ef963d0e0b62..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/** @file
-  UEFI Component Name(2) protocol implementation for Opal driver.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalDriver.h"
-
-//
-// EFI Component Name Protocol
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gOpalComponentName = {
-  OpalEfiDriverComponentNameGetDriverName,
-  OpalEfiDriverComponentNameGetControllerName,
-  "eng"
-};
-
-//
-// EFI Component Name 2 Protocol
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOpalComponentName2 = {
-  OpalEfiDriverComponentName2GetDriverName,
-  OpalEfiDriverComponentName2GetControllerName,
-  "en"
-};
-
-
-/// The name of the driver in all the languages we support.
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOpalDriverNameTable[] = {
-    { LANGUAGE_RFC_3066_ENGLISH, (CHAR16*)EFI_DRIVER_NAME_UNICODE },
-    { LANGUAGE_ISO_639_2_ENGLISH, (CHAR16*)EFI_DRIVER_NAME_UNICODE },
-    { 0, 0 }
-};
-
-/**
-  Retrieves a Unicode string that is the user readable name of the driver.
-
-  This function retrieves the user readable name of a driver in the form of a
-  Unicode string. If the driver specified by This has a user readable name in
-  the language specified by Language, then a pointer to the driver name is
-  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
-  by This does not support the language specified by Language,
-  then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language. This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified
-                                in RFC 4646 or ISO 639-2 language code format.
-
-  @param  DriverName[out]       A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                driver specified by This in the language
-                                specified by Language.
-
-  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
-                                This and the language specified by Language was
-                                returned in DriverName.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER DriverName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentNameGetDriverName(
-  EFI_COMPONENT_NAME_PROTOCOL*    This,
-  CHAR8*                          Language,
-  CHAR16**                        DriverName
-  )
-{
-  return LookupUnicodeString2(
-    Language,
-    This->SupportedLanguages,
-    mOpalDriverNameTable,
-    DriverName,
-    TRUE
-    );
-}
-
-/**
-  Retrieves a Unicode string that is the user readable name of the driver.
-
-  This function retrieves the user readable name of a driver in the form of a
-  Unicode string. If the driver specified by This has a user readable name in
-  the language specified by Language, then a pointer to the driver name is
-  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
-  by This does not support the language specified by Language,
-  then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language. This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified
-                                in RFC 4646 or ISO 639-2 language code format.
-
-  @param  DriverName[out]       A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                driver specified by This in the language
-                                specified by Language.
-
-  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
-                                This and the language specified by Language was
-                                returned in DriverName.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER DriverName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentName2GetDriverName(
-  EFI_COMPONENT_NAME2_PROTOCOL*   This,
-  CHAR8*                          Language,
-  CHAR16**                        DriverName
-  )
-{
-  return LookupUnicodeString2(
-    Language,
-    This->SupportedLanguages,
-    mOpalDriverNameTable,
-    DriverName,
-    FALSE
-    );
-}
-
-/**
-  Retrieves a Unicode string that is the user readable name of the controller
-  that is being managed by a driver.
-
-  This function retrieves the user readable name of the controller specified by
-  ControllerHandle and ChildHandle in the form of a Unicode string. If the
-  driver specified by This has a user readable name in the language specified by
-  Language, then a pointer to the controller name is returned in ControllerName,
-  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
-  managing the controller specified by ControllerHandle and ChildHandle,
-  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
-  support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
-  @param  ControllerHandle[in]  The handle of a controller that the driver
-                                specified by This is managing.  This handle
-                                specifies the controller whose name is to be
-                                returned.
-
-  @param  ChildHandle[in]       The handle of the child controller to retrieve
-                                the name of.  This is an optional parameter that
-                                may be NULL.  It will be NULL for device
-                                drivers.  It will also be NULL for a bus drivers
-                                that wish to retrieve the name of the bus
-                                controller.  It will not be NULL for a bus
-                                driver that wishes to retrieve the name of a
-                                child controller.
-
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language.  This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified in
-                                RFC 4646 or ISO 639-2 language code format.
-
-  @param  ControllerName[out]   A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                controller specified by ControllerHandle and
-                                ChildHandle in the language specified by
-                                Language from the point of view of the driver
-                                specified by This.
-
-  @retval EFI_SUCCESS           The Unicode string for the user readable name in
-                                the language specified by Language for the
-                                driver specified by This was returned in
-                                DriverName.
-
-  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
-
-  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
-                                EFI_HANDLE.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
-                                managing the controller specified by
-                                ControllerHandle and ChildHandle.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-GetControllerName(
-  EFI_HANDLE  ControllerHandle,
-  EFI_HANDLE  ChildHandle,
-  CHAR8*      Language,
-  CHAR16**    ControllerName
-  )
-{
-  if (Language == NULL || ControllerName == NULL || ControllerHandle == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // don't support any controller or children names
-  return EFI_UNSUPPORTED;
-}
-
-/**
-  Retrieves a Unicode string that is the user readable name of the controller
-  that is being managed by a driver.
-
-  This function retrieves the user readable name of the controller specified by
-  ControllerHandle and ChildHandle in the form of a Unicode string. If the
-  driver specified by This has a user readable name in the language specified by
-  Language, then a pointer to the controller name is returned in ControllerName,
-  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
-  managing the controller specified by ControllerHandle and ChildHandle,
-  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
-  support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  ControllerHandle[in]  The handle of a controller that the driver
-                                specified by This is managing.  This handle
-                                specifies the controller whose name is to be
-                                returned.
-
-  @param  ChildHandle[in]       The handle of the child controller to retrieve
-                                the name of.  This is an optional parameter that
-                                may be NULL.  It will be NULL for device
-                                drivers.  It will also be NULL for a bus drivers
-                                that wish to retrieve the name of the bus
-                                controller.  It will not be NULL for a bus
-                                driver that wishes to retrieve the name of a
-                                child controller.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language.  This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified in
-                                RFC 4646 or ISO 639-2 language code format.
-
-  @param  ControllerName[out]   A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                controller specified by ControllerHandle and
-                                ChildHandle in the language specified by
-                                Language from the point of view of the driver
-                                specified by This.
-
-  @retval EFI_SUCCESS           The Unicode string for the user readable name in
-                                the language specified by Language for the
-                                driver specified by This was returned in
-                                DriverName.
-
-  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
-
-  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
-                                EFI_HANDLE.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
-                                managing the controller specified by
-                                ControllerHandle and ChildHandle.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentNameGetControllerName(
-  EFI_COMPONENT_NAME_PROTOCOL*    This,
-  EFI_HANDLE                      ControllerHandle,
-  EFI_HANDLE                      ChildHandle,
-  CHAR8*                          Language,
-  CHAR16**                        ControllerName
-  )
-{
-  return (GetControllerName( ControllerHandle, ChildHandle, Language, ControllerName));
-}
-
-/**
-  Retrieves a Unicode string that is the user readable name of the controller
-  that is being managed by a driver.
-
-  This function retrieves the user readable name of the controller specified by
-  ControllerHandle and ChildHandle in the form of a Unicode string. If the
-  driver specified by This has a user readable name in the language specified by
-  Language, then a pointer to the controller name is returned in ControllerName,
-  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
-  managing the controller specified by ControllerHandle and ChildHandle,
-  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
-  support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  ControllerHandle[in]  The handle of a controller that the driver
-                                specified by This is managing.  This handle
-                                specifies the controller whose name is to be
-                                returned.
-
-  @param  ChildHandle[in]       The handle of the child controller to retrieve
-                                the name of.  This is an optional parameter that
-                                may be NULL.  It will be NULL for device
-                                drivers.  It will also be NULL for a bus drivers
-                                that wish to retrieve the name of the bus
-                                controller.  It will not be NULL for a bus
-                                driver that wishes to retrieve the name of a
-                                child controller.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language.  This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified in
-                                RFC 4646 or ISO 639-2 language code format.
-
-  @param  ControllerName[out]   A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                controller specified by ControllerHandle and
-                                ChildHandle in the language specified by
-                                Language from the point of view of the driver
-                                specified by This.
-
-  @retval EFI_SUCCESS           The Unicode string for the user readable name in
-                                the language specified by Language for the
-                                driver specified by This was returned in
-                                DriverName.
-
-  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
-
-  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
-                                EFI_HANDLE.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
-                                managing the controller specified by
-                                ControllerHandle and ChildHandle.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentName2GetControllerName(
-  EFI_COMPONENT_NAME2_PROTOCOL*   This,
-  EFI_HANDLE                      ControllerHandle,
-  EFI_HANDLE                      ChildHandle,
-  CHAR8*                          Language,
-  CHAR16**                        ControllerName
-  )
-{
-  return (GetControllerName(ControllerHandle, ChildHandle, Language, ControllerName));
-}
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
deleted file mode 100644
index cd0c5a4096a0..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/** @file
-  Entrypoint of Opal UEFI Driver and contains all the logic to
-  register for new Opal device instances.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances and installs an
-// HII GUI to manage Opal features if the device is Opal capable
-// If the Opal device is being managed by the UEFI Driver, it shall provide a popup
-// window during boot requesting a user password
-
-#include "OpalDriver.h"
-#include "OpalDriverPrivate.h"
-#include "OpalHii.h"
-
-OPAL_DRIVER mOpalDriver;
-
-#define MAX_PASSWORD_SIZE        32
-#define MAX_PASSWORD_TRY_COUNT   5
-
-//
-// Globals
-//
-EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {
-  OpalEfiDriverBindingSupported,
-  OpalEfiDriverBindingStart,
-  OpalEfiDriverBindingStop,
-  0x1b,
-  NULL,
-  NULL
-};
-
-
-/**
-  Add new device to the global device list.
-
-  @param Dev             New create device.
-
-**/
-VOID
-AddDeviceToTail(
-  IN OPAL_DRIVER_DEVICE    *Dev
-  )
-{
-  OPAL_DRIVER_DEVICE                *TmpDev;
-
-  if (mOpalDriver.DeviceList == NULL) {
-    mOpalDriver.DeviceList = Dev;
-  } else {
-    TmpDev = mOpalDriver.DeviceList;
-    while (TmpDev->Next != NULL) {
-      TmpDev = TmpDev->Next;
-    }
-
-    TmpDev->Next = Dev;
-  }
-}
-
-/**
-  Remove one device in the global device list.
-
-  @param Dev             The device need to be removed.
-
-**/
-VOID
-RemoveDevice (
-  IN OPAL_DRIVER_DEVICE    *Dev
-  )
-{
-  OPAL_DRIVER_DEVICE                *TmpDev;
-
-  if (mOpalDriver.DeviceList == NULL) {
-    return;
-  }
-
-  if (mOpalDriver.DeviceList == Dev) {
-    mOpalDriver.DeviceList = NULL;
-    return;
-  }
-
-  TmpDev = mOpalDriver.DeviceList;
-  while (TmpDev->Next != NULL) {
-    if (TmpDev->Next == Dev) {
-      TmpDev->Next = Dev->Next;
-      break;
-    }
-  }
-}
-
-/**
-  Get current device count.
-
-  @retval  return the current created device count.
-
-**/
-UINT8
-GetDeviceCount (
-  VOID
-  )
-{
-  UINT8                Count;
-  OPAL_DRIVER_DEVICE   *TmpDev;
-
-  Count = 0;
-  TmpDev = mOpalDriver.DeviceList;
-
-  while (TmpDev != NULL) {
-    Count++;
-    TmpDev = TmpDev->Next;
-  }
-
-  return Count;
-}
-
-/**
-  Get password input from the popup windows, and unlock the device.
-
-  @param[in]       Dev          The device which need to be unlock.
-  @param[out]      PressEsc     Whether user escape function through Press ESC.
-
-  @retval   Password string if success. NULL if failed.
-
-**/
-CHAR8 *
-OpalDriverPopUpHddPassword (
-  IN  OPAL_DRIVER_DEVICE         *Dev,
-  OUT BOOLEAN                    *PressEsc
-  )
-{
-  EFI_INPUT_KEY                InputKey;
-  UINTN                        InputLength;
-  CHAR16                       Mask[MAX_PASSWORD_SIZE + 1];
-  CHAR16                       Unicode[MAX_PASSWORD_SIZE + 1];
-  CHAR8                        *Ascii;
-  CHAR16                       *PopUpString;
-  UINTN                        StrLength;
-
-  ZeroMem(Unicode, sizeof(Unicode));
-  ZeroMem(Mask, sizeof(Mask));
-
-  StrLength = StrLen(Dev->Name16);
-  PopUpString = (CHAR16*) AllocateZeroPool ((8 + StrLength) * 2);
-  *PressEsc = FALSE;
-
-  if (Dev->Name16 == NULL) {
-    UnicodeSPrint(PopUpString, StrLen(L"Unlock Disk") + 1, L"Unlock Disk");
-  } else {
-    UnicodeSPrint(PopUpString, StrLen(L"Unlock ") + StrLength + 1, L"Unlock %s", Dev->Name16);
-  }
-
-  gST->ConOut->ClearScreen(gST->ConOut);
-
-  InputLength = 0;
-  while (TRUE) {
-    Mask[InputLength] = L'_';
-    CreatePopUp(
-        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
-        &InputKey,
-        PopUpString,
-        L"---------------------",
-        Mask,
-        NULL
-    );
-
-    //
-    // Check key.
-    //
-    if (InputKey.ScanCode == SCAN_NULL) {
-      //
-      // password finished
-      //
-      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
-        //
-        // Add the null terminator.
-        //
-        Unicode[InputLength] = 0;
-        InputLength++;
-        break;
-      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
-                 (InputKey.UnicodeChar == CHAR_TAB) ||
-                 (InputKey.UnicodeChar == CHAR_LINEFEED)
-                ) {
-        continue;
-      } else {
-        //
-        // delete last key entered
-        //
-        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
-          if (InputLength > 0) {
-            Unicode[InputLength] = 0;
-            Mask[InputLength] = 0;
-            InputLength--;
-          }
-        } else {
-          //
-          // add Next key entry
-          //
-          Unicode[InputLength] = InputKey.UnicodeChar;
-          Mask[InputLength] = L'*';
-          InputLength++;
-          if (InputLength == MAX_PASSWORD_SIZE) {
-            //
-            // Add the null terminator.
-            //
-            Unicode[InputLength] = 0;
-            Mask[InputLength] = 0;
-            break;
-          }
-        }
-      }
-    }
-
-    //
-    // exit on ESC
-    //
-    if (InputKey.ScanCode == SCAN_ESC) {
-      *PressEsc = TRUE;
-      break;
-    }
-  }
-
-  gST->ConOut->ClearScreen(gST->ConOut);
-
-  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
-    return NULL;
-  }
-
-  Ascii = AllocateZeroPool (MAX_PASSWORD_SIZE + 1);
-  if (Ascii == NULL) {
-    return NULL;
-  }
-
-  UnicodeStrToAsciiStrS (Unicode, Ascii, MAX_PASSWORD_SIZE + 1);
-  ZeroMem (Unicode, sizeof (Unicode));
-
-  return Ascii;
-}
-
-/**
-  Check if disk is locked, show popup window and ask for password if it is
-
-  @param[in]       Dev          The device which need to be unlock.
-
-**/
-VOID
-OpalDriverRequestPassword (
-  OPAL_DRIVER_DEVICE       *Dev
-  )
-{
-  UINT8               Count;
-  BOOLEAN             IsEnabled;
-  CHAR8               *Password;
-  UINT32              PasswordLen;
-  TCG_RESULT          Ret;
-  EFI_INPUT_KEY       Key;
-  OPAL_SESSION        Session;
-  BOOLEAN             PressEsc;
-  BOOLEAN             Locked;
-
-  if (Dev == NULL) {
-    return;
-  }
-
-  Count = 0;
-
-  IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
-  if (IsEnabled) {
-    ZeroMem(&Session, sizeof(Session));
-    Session.Sscp = Dev->OpalDisk.Sscp;
-    Session.MediaId = Dev->OpalDisk.MediaId;
-    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
-
-    Locked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
-
-    while (Count < MAX_PASSWORD_TRY_COUNT) {
-      Password = OpalDriverPopUpHddPassword (Dev, &PressEsc);
-      if (PressEsc) {
-        if (Locked) {
-          //
-          // Current device in the lock status and
-          // User not input password and press ESC,
-          // keep device in lock status and continue boot.
-          //
-          do {
-            CreatePopUp (
-                    EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
-                    &Key,
-                    L"Press ENTER to skip password, Press ESC to input password",
-                    NULL
-                    );
-          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
-
-          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
-            gST->ConOut->ClearScreen(gST->ConOut);
-            //
-            // Keep lock and continue boot.
-            //
-            return;
-          } else {
-            //
-            // Let user input password again.
-            //
-            continue;
-          }
-        } else {
-          //
-          // Current device in the unlock status and
-          // User not input password and press ESC,
-          // Shutdown the device.
-          //
-          do {
-            CreatePopUp (
-                    EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
-                    &Key,
-                    L"Press ENTER to shutdown, Press ESC to input password",
-                    NULL
-                    );
-          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
-
-          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
-            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
-          } else {
-            //
-            // Let user input password again.
-            //
-            continue;
-          }
-        }
-      }
-
-      if (Password == NULL) {
-        Count ++;
-        continue;
-      }
-      PasswordLen = (UINT32) AsciiStrLen(Password);
-
-      if (Locked) {
-        Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
-      } else {
-        Ret = OpalSupportLock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
-        if (Ret == TcgResultSuccess) {
-          Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
-        }
-      }
-
-      if (Password != NULL) {
-        ZeroMem (Password, PasswordLen);
-        FreePool (Password);
-      }
-
-      if (Ret == TcgResultSuccess) {
-        break;
-      }
-
-      Count++;
-
-      do {
-        CreatePopUp (
-                  EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
-                  &Key,
-                  L"Invalid password.",
-                  L"Press ENTER to retry",
-                  NULL
-                  );
-      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-    }
-
-    if (Count >= MAX_PASSWORD_TRY_COUNT) {
-      do {
-        CreatePopUp (
-                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
-                &Key,
-                L"Opal password retry count exceeds the limit. Must shutdown!",
-                L"Press ENTER to shutdown",
-                NULL
-                );
-      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
-      gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
-    }
-  }
-}
-
-/**
-  Get devcie list info.
-
-  @retval     return the device list pointer.
-**/
-OPAL_DRIVER_DEVICE*
-OpalDriverGetDeviceList(
-  VOID
-  )
-{
-  return mOpalDriver.DeviceList;
-}
-
-/**
-  ReadyToBoot callback to send BlockSid command.
-
-  @param  Event   Pointer to this event
-  @param  Context Event handler private Data
-
-**/
-VOID
-EFIAPI
-ReadyToBootCallback (
-  IN EFI_EVENT        Event,
-  IN VOID             *Context
-  )
-{
-  OPAL_DRIVER_DEVICE                         *Itr;
-  TCG_RESULT                                 Result;
-  OPAL_SESSION                               Session;
-  UINT32                                     PpStorageFlag;
-
-  gBS->CloseEvent (Event);
-
-  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
-  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
-    //
-    // Send BlockSID command to each Opal disk
-    //
-    Itr = mOpalDriver.DeviceList;
-    while (Itr != NULL) {
-      if (Itr->OpalDisk.SupportedAttributes.BlockSid) {
-        ZeroMem(&Session, sizeof(Session));
-        Session.Sscp = Itr->OpalDisk.Sscp;
-        Session.MediaId = Itr->OpalDisk.MediaId;
-        Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
-
-        Result = OpalBlockSid (&Session, TRUE);  // HardwareReset must always be TRUE
-        if (Result != TcgResultSuccess) {
-          DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
-          break;
-        }
-      }
-
-      Itr = Itr->Next;
-    }
-  }
-}
-
-/**
-  Stop this Controller.
-
-  @param  Dev               The device need to be stopped.
-
-**/
-VOID
-OpalDriverStopDevice (
-  OPAL_DRIVER_DEVICE     *Dev
-  )
-{
-  //
-  // free each name
-  //
-  FreePool(Dev->Name16);
-
-  //
-  // remove OPAL_DRIVER_DEVICE from the list
-  // it updates the controllerList pointer
-  //
-  RemoveDevice(Dev);
-
-  //
-  // close protocols that were opened
-  //
-  gBS->CloseProtocol(
-    Dev->Handle,
-    &gEfiStorageSecurityCommandProtocolGuid,
-    gOpalDriverBinding.DriverBindingHandle,
-    Dev->Handle
-    );
-
-  gBS->CloseProtocol(
-    Dev->Handle,
-    &gEfiBlockIoProtocolGuid,
-    gOpalDriverBinding.DriverBindingHandle,
-    Dev->Handle
-    );
-
-  FreePool(Dev);
-}
-
-/**
-  Get devcie name through the component name protocol.
-
-  @param[in]       AllHandlesBuffer   The handle buffer for current system.
-  @param[in]       NumAllHandles      The number of handles for the handle buffer.
-  @param[in]       Dev                The device which need to get name.
-  @param[in]       UseComp1           Whether use component name or name2 protocol.
-
-  @retval     TRUE        Find the name for this device.
-  @retval     FALSE       Not found the name for this device.
-**/
-BOOLEAN
-OpalDriverGetDeviceNameByProtocol(
-  EFI_HANDLE             *AllHandlesBuffer,
-  UINTN                  NumAllHandles,
-  OPAL_DRIVER_DEVICE     *Dev,
-  BOOLEAN                UseComp1
-  )
-{
-  EFI_HANDLE*                   ProtocolHandlesBuffer;
-  UINTN                         NumProtocolHandles;
-  EFI_STATUS                    Status;
-  EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout
-  EFI_GUID                      Protocol;
-  UINTN                         StrLength;
-  EFI_DEVICE_PATH_PROTOCOL*     TmpDevPath;
-  UINTN                         Index1;
-  UINTN                         Index2;
-  EFI_HANDLE                    TmpHandle;
-  CHAR16                        *DevName;
-
-  if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
-    return FALSE;
-  }
-
-  Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;
-
-  //
-  // Find all EFI_HANDLES with protocol
-  //
-  Status = gBS->LocateHandleBuffer(
-               ByProtocol,
-               &Protocol,
-               NULL,
-               &NumProtocolHandles,
-               &ProtocolHandlesBuffer
-               );
-  if (EFI_ERROR(Status)) {
-    return FALSE;
-  }
-
-
-  //
-  // Exit early if no supported devices
-  //
-  if (NumProtocolHandles == 0) {
-    return FALSE;
-  }
-
-  //
-  // Get printable name by iterating through all protocols
-  // using the handle as the child, and iterate through all handles for the controller
-  // exit loop early once found, if not found, then delete device
-  // storage security protocol instances already exist, add them to internal list
-  //
-  Status = EFI_DEVICE_ERROR;
-  for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
-    DevName = NULL;
-
-    if (Dev->Name16 != NULL) {
-      return TRUE;
-    }
-
-    TmpHandle = ProtocolHandlesBuffer[Index1];
-
-    Status = gBS->OpenProtocol(
-                 TmpHandle,
-                 &Protocol,
-                 (VOID**)&Cnp1_2,
-                 gImageHandle,
-                 NULL,
-                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
-                 );
-    if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
-      continue;
-    }
-
-    //
-    // Use all handles array as controller handle
-    //
-    for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
-      Status = Cnp1_2->GetControllerName(
-                   Cnp1_2,
-                   AllHandlesBuffer[Index2],
-                   Dev->Handle,
-                   LANGUAGE_ISO_639_2_ENGLISH,
-                   &DevName
-                   );
-      if (EFI_ERROR(Status)) {
-        Status = Cnp1_2->GetControllerName(
-                     Cnp1_2,
-                     AllHandlesBuffer[Index2],
-                     Dev->Handle,
-                     LANGUAGE_RFC_3066_ENGLISH,
-                     &DevName
-                     );
-      }
-      if (!EFI_ERROR(Status) && DevName != NULL) {
-        StrLength = StrLen(DevName) + 1;        // Add one for NULL terminator
-        Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
-        ASSERT (Dev->Name16 != NULL);
-        StrCpyS (Dev->Name16, StrLength, DevName);
-        Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
-        UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);
-
-        //
-        // Retrieve bridge BDF info and port number or namespace depending on type
-        //
-        TmpDevPath = NULL;
-        Status = gBS->OpenProtocol(
-            Dev->Handle,
-            &gEfiDevicePathProtocolGuid,
-            (VOID**)&TmpDevPath,
-            gImageHandle,
-            NULL,
-            EFI_OPEN_PROTOCOL_GET_PROTOCOL
-            );
-        if (!EFI_ERROR(Status)) {
-          Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
-          return TRUE;
-        }
-
-        if (Dev->Name16 != NULL) {
-          FreePool(Dev->Name16);
-          Dev->Name16 = NULL;
-        }
-        if (Dev->NameZ != NULL) {
-          FreePool(Dev->NameZ);
-          Dev->NameZ = NULL;
-        }
-      }
-    }
-  }
-
-  return FALSE;
-}
-
-/**
-  Get devcie name through the component name protocol.
-
-  @param[in]       Dev                The device which need to get name.
-
-  @retval     TRUE        Find the name for this device.
-  @retval     FALSE       Not found the name for this device.
-**/
-BOOLEAN
-OpalDriverGetDriverDeviceName(
-  OPAL_DRIVER_DEVICE          *Dev
-  )
-{
-  EFI_HANDLE*                  AllHandlesBuffer;
-  UINTN                        NumAllHandles;
-  EFI_STATUS                   Status;
-
-  if (Dev == NULL) {
-    DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));
-    return FALSE;
-  }
-
-  //
-  // Iterate through ComponentName2 handles to get name, if fails, try ComponentName
-  //
-  if (Dev->Name16 == NULL) {
-    DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
-    //
-    // Find all EFI_HANDLES
-    //
-    Status = gBS->LocateHandleBuffer(
-                 AllHandles,
-                 NULL,
-                 NULL,
-                 &NumAllHandles,
-                 &AllHandlesBuffer
-                 );
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));
-      return FALSE;
-    }
-
-    //
-    // Try component Name2
-    //
-    if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {
-      DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));
-      if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {
-        DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));
-        return FALSE;
-      }
-    }
-  }
-
-  return TRUE;
-}
-
-/**
-  Main entry for this driver.
-
-  @param ImageHandle     Image Handle this driver.
-  @param SystemTable     Pointer to SystemTable.
-
-  @retval EFI_SUCESS     This function always complete successfully.
-**/
-EFI_STATUS
-EFIAPI
-EfiDriverEntryPoint(
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE*  SystemTable
-  )
-{
-  EFI_STATUS                     Status;
-  EFI_EVENT                      ReadyToBootEvent;
-
-  Status = EfiLibInstallDriverBindingComponentName2 (
-             ImageHandle,
-             SystemTable,
-             &gOpalDriverBinding,
-             ImageHandle,
-             &gOpalComponentName,
-             &gOpalComponentName2
-             );
-
-  if (EFI_ERROR(Status)) {
-    DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));
-    return Status ;
-  }
-
-  //
-  // Initialize Driver object
-  //
-  ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
-  mOpalDriver.Handle = ImageHandle;
-
-  //
-  // register a ReadyToBoot event callback for sending BlockSid command
-  //
-  Status = EfiCreateEventReadyToBootEx (
-                  TPL_CALLBACK,
-                  ReadyToBootCallback,
-                  (VOID *) &ImageHandle,
-                  &ReadyToBootEvent
-                  );
-
-  //
-  // Install Hii packages.
-  //
-  HiiInstall();
-
-  return Status;
-}
-
-/**
-  Tests to see if this driver supports a given controller.
-
-  This function checks to see if the controller contains an instance of the
-  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL
-  and returns EFI_SUCCESS if it does.
-
-  @param[in]  This                  A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
-  @param[in]  ControllerHandle      The Handle of the controller to test. This Handle
-                                    must support a protocol interface that supplies
-                                    an I/O abstraction to the driver.
-  @param[in]  RemainingDevicePath  This parameter is ignored.
-
-  @retval EFI_SUCCESS               The device contains required protocols
-  @retval EFI_ALREADY_STARTED       The device specified by ControllerHandle and
-                                    RemainingDevicePath is already being managed by the driver
-                                    specified by This.
-  @retval EFI_ACCESS_DENIED         The device specified by ControllerHandle and
-                                    RemainingDevicePath is already being managed by a different
-                                    driver or an application that requires exclusive access.
-                                    Currently not implemented.
-  @retval EFI_UNSUPPORTED           The device does not contain requires protocols
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverBindingSupported(
-  IN EFI_DRIVER_BINDING_PROTOCOL* This,
-  IN EFI_HANDLE                   Controller,
-  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
-  )
-{
-  EFI_STATUS                              Status;
-  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL*  SecurityCommand;
-  EFI_BLOCK_IO_PROTOCOL*                  BlkIo;
-
-  //
-  // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.
-  //
-  Status = gBS->OpenProtocol(
-    Controller,
-    &gEfiStorageSecurityCommandProtocolGuid,
-    ( VOID ** )&SecurityCommand,
-    This->DriverBindingHandle,
-    Controller,
-    EFI_OPEN_PROTOCOL_BY_DRIVER
-    );
-
-  if (Status == EFI_ALREADY_STARTED) {
-    return EFI_SUCCESS;
-  }
-
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-
-  //
-  // Close protocol and reopen in Start call
-  //
-  gBS->CloseProtocol(
-      Controller,
-      &gEfiStorageSecurityCommandProtocolGuid,
-      This->DriverBindingHandle,
-      Controller
-      );
-
-  //
-  // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
-  // function APIs
-  //
-  Status = gBS->OpenProtocol(
-    Controller,
-    &gEfiBlockIoProtocolGuid,
-    (VOID **)&BlkIo,
-    This->DriverBindingHandle,
-    Controller,
-    EFI_OPEN_PROTOCOL_BY_DRIVER
-    );
-
-  if (EFI_ERROR(Status)) {
-    DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));
-    return Status;
-  }
-
-  //
-  // Close protocol and reopen in Start call
-  //
-  gBS->CloseProtocol(
-    Controller,
-    &gEfiBlockIoProtocolGuid,
-    This->DriverBindingHandle,
-    Controller
-    );
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Enables Opal Management on a supported device if available.
-
-  The start function is designed to be called after the Opal UEFI Driver has confirmed the
-  "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
-  This function will complete the other necessary checks, such as verifying the device supports
-  the correct version of Opal.  Upon verification, it will add the device to the
-  Opal HII list in order to expose Opal managmeent options.
-
-  @param[in]  This                  A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
-  @param[in]  ControllerHandle      The Handle of the controller to start. This Handle
-                                    must support a protocol interface that supplies
-                                    an I/O abstraction to the driver.
-  @param[in]  RemainingDevicePath   A pointer to the remaining portion of a device path.  This
-                                    parameter is ignored by device drivers, and is optional for bus
-                                    drivers. For a bus driver, if this parameter is NULL, then handles
-                                    for all the children of Controller are created by this driver.
-                                    If this parameter is not NULL and the first Device Path Node is
-                                    not the End of Device Path Node, then only the Handle for the
-                                    child device specified by the first Device Path Node of
-                                    RemainingDevicePath is created by this driver.
-                                    If the first Device Path Node of RemainingDevicePath is
-                                    the End of Device Path Node, no child Handle is created by this
-                                    driver.
-
-  @retval EFI_SUCCESS               Opal management was enabled.
-  @retval EFI_DEVICE_ERROR          The device could not be started due to a device error.Currently not implemented.
-  @retval EFI_OUT_OF_RESOURCES      The request could not be completed due to a lack of resources.
-  @retval Others                    The driver failed to start the device.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverBindingStart(
-  IN EFI_DRIVER_BINDING_PROTOCOL* This,
-  IN EFI_HANDLE                   Controller,
-  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
-  )
-{
-  EFI_STATUS                  Status;
-  EFI_BLOCK_IO_PROTOCOL       *BlkIo;
-  OPAL_DRIVER_DEVICE          *Dev;
-  OPAL_DRIVER_DEVICE          *Itr;
-  BOOLEAN                     Result;
-
-  Itr = mOpalDriver.DeviceList;
-  while (Itr != NULL) {
-    if (Controller == Itr->Handle) {
-      return EFI_SUCCESS;
-    }
-    Itr = Itr->Next;
-  }
-
-  //
-  // Create internal device for tracking.  This allows all disks to be tracked
-  // by same HII form
-  //
-  Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
-  if (Dev == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-  Dev->Handle = Controller;
-
-  //
-  // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks
-  //
-  Status = gBS->OpenProtocol(
-    Controller,
-    &gEfiStorageSecurityCommandProtocolGuid,
-    (VOID **)&Dev->Sscp,
-    This->DriverBindingHandle,
-    Controller,
-    EFI_OPEN_PROTOCOL_BY_DRIVER
-    );
-  if (EFI_ERROR(Status)) {
-    FreePool(Dev);
-    return Status;
-  }
-
-  //
-  // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
-  // function APIs
-  //
-  Status = gBS->OpenProtocol(
-    Controller,
-    &gEfiBlockIoProtocolGuid,
-    (VOID **)&BlkIo,
-    This->DriverBindingHandle,
-    Controller,
-    EFI_OPEN_PROTOCOL_BY_DRIVER
-    );
-  if (EFI_ERROR(Status)) {
-    //
-    // Close storage security that was opened
-    //
-    gBS->CloseProtocol(
-        Controller,
-        &gEfiStorageSecurityCommandProtocolGuid,
-        This->DriverBindingHandle,
-        Controller
-        );
-
-    FreePool(Dev);
-    return Status;
-  }
-
-  //
-  // Save mediaId
-  //
-  Dev->MediaId = BlkIo->Media->MediaId;
-
-  gBS->CloseProtocol(
-    Controller,
-    &gEfiBlockIoProtocolGuid,
-    This->DriverBindingHandle,
-    Controller
-    );
-
-  //
-  // Acquire Ascii printable name of child, if not found, then ignore device
-  //
-  Result = OpalDriverGetDriverDeviceName (Dev);
-  if (!Result) {
-    goto Done;
-  }
-
-  Status = OpalDiskInitialize (Dev);
-  if (EFI_ERROR (Status)) {
-    goto Done;
-  }
-
-  AddDeviceToTail(Dev);
-
-  //
-  // check if device is locked and prompt for password
-  //
-  OpalDriverRequestPassword (Dev);
-
-  return EFI_SUCCESS;
-
-Done:
-  //
-  // free device, close protocols and exit
-  //
-  gBS->CloseProtocol(
-      Controller,
-      &gEfiStorageSecurityCommandProtocolGuid,
-      This->DriverBindingHandle,
-      Controller
-      );
-
-  FreePool(Dev);
-
-  return EFI_DEVICE_ERROR;
-}
-
-/**
-  Stop this driver on Controller.
-
-  @param  This              Protocol instance pointer.
-  @param  Controller        Handle of device to stop driver on
-  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
-                            children is zero stop the entire bus driver.
-  @param  ChildHandleBuffer List of Child Handles to Stop.
-
-  @retval EFI_SUCCESS       This driver is removed Controller.
-  @retval other             This driver could not be removed from this device.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverBindingStop(
-  EFI_DRIVER_BINDING_PROTOCOL*    This,
-  EFI_HANDLE                      Controller,
-  UINTN                           NumberOfChildren,
-  EFI_HANDLE*                     ChildHandleBuffer
-  )
-{
-  OPAL_DRIVER_DEVICE*   Itr;
-
-  Itr = mOpalDriver.DeviceList;
-
-  //
-  // does Controller match any of the devices we are managing for Opal
-  //
-  while (Itr != NULL) {
-    if (Itr->Handle == Controller) {
-      OpalDriverStopDevice (Itr);
-      return EFI_SUCCESS;
-    }
-
-    Itr = Itr->Next;
-  }
-
-  return EFI_NOT_FOUND;
-}
-
-
-/**
-  Unloads UEFI Driver.  Very useful for debugging and testing.
-
-  @param ImageHandle            Image Handle this driver.
-
-  @retval EFI_SUCCESS           This function always complete successfully.
-  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverUnload (
-  IN EFI_HANDLE ImageHandle
-  )
-{
-  EFI_STATUS                     Status;
-  OPAL_DRIVER_DEVICE                   *Itr;
-
-  Status = EFI_SUCCESS;
-
-  if (ImageHandle != gImageHandle) {
-    return (EFI_INVALID_PARAMETER);
-  }
-
-  //
-  // Uninstall any interface added to each device by us
-  //
-  while (mOpalDriver.DeviceList) {
-    Itr = mOpalDriver.DeviceList;
-    //
-    // Remove OPAL_DRIVER_DEVICE from the list
-    // it updates the controllerList pointer
-    //
-    OpalDriverStopDevice(Itr);
-  }
-
-  //
-  // Uninstall the HII capability
-  //
-  Status = HiiUninstall();
-
-  return Status;
-}
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
deleted file mode 100644
index 7761d64cbb28..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
+++ /dev/null
@@ -1,412 +0,0 @@
-/** @file
-  Values defined and used by the Opal UEFI Driver.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _OPAL_DRIVER_H_
-#define _OPAL_DRIVER_H_
-
-#include <PiDxe.h>
-
-#include <Protocol/PciIo.h>
-#include <Protocol/SmmCommunication.h>
-#include <Protocol/BlockIo.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/DevicePathToText.h>
-#include <Protocol/StorageSecurityCommand.h>
-
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/BaseLib.h>
-#include <Library/PrintLib.h>
-#include <Library/DebugLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/HiiLib.h>
-#include <Library/UefiHiiServicesLib.h>
-#include <Library/TcgStorageOpalLib.h>
-#include <Library/OpalPasswordSupportLib.h>
-#include <Library/Tcg2PhysicalPresenceLib.h>
-
-#define EFI_DRIVER_NAME_UNICODE L"1.0 UEFI Opal Driver"
-
-// UEFI 2.1
-#define LANGUAGE_RFC_3066_ENGLISH ((CHAR8*)"en")
-
-// UEFI/EFI < 2.1
-#define LANGUAGE_ISO_639_2_ENGLISH ((CHAR8*)"eng")
-
-
-#define UNLOCK_VAR_NAME                 (const CHAR16*)L"UNLOCK"
-#define OPAL_FILTER_DRIVER_VAR_NAME     L"FILTER_DRIVER"
-
-
-#define CONCAT_(x, y) x ## y
-#define CONCAT(x, y) CONCAT_(x, y)
-
-#define UNICODE_STR(x) CONCAT( L, x )
-
-extern EFI_DRIVER_BINDING_PROTOCOL   gOpalDriverBinding;
-extern EFI_COMPONENT_NAME_PROTOCOL   gOpalComponentName;
-extern EFI_COMPONENT_NAME2_PROTOCOL  gOpalComponentName2;
-
-/**
-  Unloads UEFI Driver.  Very useful for debugging and testing.
-
-  @param ImageHandle            Image handle this driver.
-
-  @retval EFI_SUCCESS           This function always complete successfully.
-  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
-**/
-EFI_STATUS
-EFIAPI
-EfiDriverUnload(
-  EFI_HANDLE ImageHandle
-  );
-
-
-/**
-  Test to see if this driver supports Controller.
-
-  @param  This                Protocol instance pointer.
-  @param  ControllerHandle    Handle of device to test
-  @param  RemainingDevicePath Optional parameter use to pick a specific child
-                              device to start.
-
-  @retval EFI_SUCCESS         This driver supports this device.
-  @retval EFI_ALREADY_STARTED This driver is already running on this device.
-  @retval other               This driver does not support this device.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverBindingSupported(
-  EFI_DRIVER_BINDING_PROTOCOL*    This,
-  EFI_HANDLE                      Controller,
-  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
-  );
-
-/**
-  Enables Opal Management on a supported device if available.
-
-  The start function is designed to be called after the Opal UEFI Driver has confirmed the
-  "controller", which is a child handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
-  This function will complete the other necessary checks, such as verifying the device supports
-  the correct version of Opal.  Upon verification, it will add the device to the
-  Opal HII list in order to expose Opal managmeent options.
-
-  @param[in]  This                  A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
-  @param[in]  ControllerHandle      The handle of the controller to start. This handle
-                                    must support a protocol interface that supplies
-                                    an I/O abstraction to the driver.
-  @param[in]  RemainingDevicePath   A pointer to the remaining portion of a device path.  This
-                                    parameter is ignored by device drivers, and is optional for bus
-                                    drivers. For a bus driver, if this parameter is NULL, then handles
-                                    for all the children of Controller are created by this driver.
-                                    If this parameter is not NULL and the first Device Path Node is
-                                    not the End of Device Path Node, then only the handle for the
-                                    child device specified by the first Device Path Node of
-                                    RemainingDevicePath is created by this driver.
-                                    If the first Device Path Node of RemainingDevicePath is
-                                    the End of Device Path Node, no child handle is created by this
-                                    driver.
-
-  @retval EFI_SUCCESS               Opal management was enabled.
-  @retval EFI_DEVICE_ERROR          The device could not be started due to a device error.Currently not implemented.
-  @retval EFI_OUT_OF_RESOURCES      The request could not be completed due to a lack of resources.
-  @retval Others                    The driver failed to start the device.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverBindingStart(
-  EFI_DRIVER_BINDING_PROTOCOL*    This,
-  EFI_HANDLE                      Controller,
-  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
-  );
-
-/**
-  Stop this driver on Controller.
-
-  @param  This              Protocol instance pointer.
-  @param  Controller        Handle of device to stop driver on
-  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
-                            children is zero stop the entire bus driver.
-  @param  ChildHandleBuffer List of Child Handles to Stop.
-
-  @retval EFI_SUCCESS       This driver is removed Controller.
-  @retval other             This driver could not be removed from this device.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverBindingStop(
-  EFI_DRIVER_BINDING_PROTOCOL*    This,
-  EFI_HANDLE                      Controller,
-  UINTN                           NumberOfChildren,
-  EFI_HANDLE*                     ChildHandleBuffer
-  );
-
-/**
-  Retrieves a Unicode string that is the user readable name of the driver.
-
-  This function retrieves the user readable name of a driver in the form of a
-  Unicode string. If the driver specified by This has a user readable name in
-  the language specified by Language, then a pointer to the driver name is
-  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
-  by This does not support the language specified by Language,
-  then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language. This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified
-                                in RFC 4646 or ISO 639-2 language code format.
-
-  @param  DriverName[out]       A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                driver specified by This in the language
-                                specified by Language.
-
-  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
-                                This and the language specified by Language was
-                                returned in DriverName.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER DriverName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentNameGetDriverName(
-  EFI_COMPONENT_NAME_PROTOCOL*    This,
-  CHAR8*                          Language,
-  CHAR16**                        DriverName
-  );
-
-/**
-  Retrieves a Unicode string that is the user readable name of the controller
-  that is being managed by a driver.
-
-  This function retrieves the user readable name of the controller specified by
-  ControllerHandle and ChildHandle in the form of a Unicode string. If the
-  driver specified by This has a user readable name in the language specified by
-  Language, then a pointer to the controller name is returned in ControllerName,
-  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
-  managing the controller specified by ControllerHandle and ChildHandle,
-  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
-  support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  ControllerHandle[in]  The handle of a controller that the driver
-                                specified by This is managing.  This handle
-                                specifies the controller whose name is to be
-                                returned.
-
-  @param  ChildHandle[in]       The handle of the child controller to retrieve
-                                the name of.  This is an optional parameter that
-                                may be NULL.  It will be NULL for device
-                                drivers.  It will also be NULL for a bus drivers
-                                that wish to retrieve the name of the bus
-                                controller.  It will not be NULL for a bus
-                                driver that wishes to retrieve the name of a
-                                child controller.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language.  This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified in
-                                RFC 4646 or ISO 639-2 language code format.
-
-  @param  ControllerName[out]   A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                controller specified by ControllerHandle and
-                                ChildHandle in the language specified by
-                                Language from the point of view of the driver
-                                specified by This.
-
-  @retval EFI_SUCCESS           The Unicode string for the user readable name in
-                                the language specified by Language for the
-                                driver specified by This was returned in
-                                DriverName.
-
-  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
-
-  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
-                                EFI_HANDLE.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
-                                managing the controller specified by
-                                ControllerHandle and ChildHandle.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentNameGetControllerName(
-  EFI_COMPONENT_NAME_PROTOCOL*    This,
-  EFI_HANDLE                      ControllerHandle,
-  EFI_HANDLE                      ChildHandle,
-  CHAR8*                          Language,
-  CHAR16**                        ControllerName
-  );
-
-/**
-  Retrieves a Unicode string that is the user readable name of the driver.
-
-  This function retrieves the user readable name of a driver in the form of a
-  Unicode string. If the driver specified by This has a user readable name in
-  the language specified by Language, then a pointer to the driver name is
-  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
-  by This does not support the language specified by Language,
-  then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language. This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified
-                                in RFC 4646 or ISO 639-2 language code format.
-
-  @param  DriverName[out]       A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                driver specified by This in the language
-                                specified by Language.
-
-  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
-                                This and the language specified by Language was
-                                returned in DriverName.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER DriverName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentName2GetDriverName(
-  EFI_COMPONENT_NAME2_PROTOCOL*   This,
-  CHAR8*                          Language,
-  CHAR16**                        DriverName
-  );
-
-/**
-  Retrieves a Unicode string that is the user readable name of the controller
-  that is being managed by a driver.
-
-  This function retrieves the user readable name of the controller specified by
-  ControllerHandle and ChildHandle in the form of a Unicode string. If the
-  driver specified by This has a user readable name in the language specified by
-  Language, then a pointer to the controller name is returned in ControllerName,
-  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
-  managing the controller specified by ControllerHandle and ChildHandle,
-  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
-  support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
-  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
-                                EFI_COMPONENT_NAME_PROTOCOL instance.
-
-  @param  ControllerHandle[in]  The handle of a controller that the driver
-                                specified by This is managing.  This handle
-                                specifies the controller whose name is to be
-                                returned.
-
-  @param  ChildHandle[in]       The handle of the child controller to retrieve
-                                the name of.  This is an optional parameter that
-                                may be NULL.  It will be NULL for device
-                                drivers.  It will also be NULL for a bus drivers
-                                that wish to retrieve the name of the bus
-                                controller.  It will not be NULL for a bus
-                                driver that wishes to retrieve the name of a
-                                child controller.
-
-  @param  Language[in]          A pointer to a Null-terminated ASCII string
-                                array indicating the language.  This is the
-                                language of the driver name that the caller is
-                                requesting, and it must match one of the
-                                languages specified in SupportedLanguages. The
-                                number of languages supported by a driver is up
-                                to the driver writer. Language is specified in
-                                RFC 4646 or ISO 639-2 language code format.
-
-  @param  ControllerName[out]   A pointer to the Unicode string to return.
-                                This Unicode string is the name of the
-                                controller specified by ControllerHandle and
-                                ChildHandle in the language specified by
-                                Language from the point of view of the driver
-                                specified by This.
-
-  @retval EFI_SUCCESS           The Unicode string for the user readable name in
-                                the language specified by Language for the
-                                driver specified by This was returned in
-                                DriverName.
-
-  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
-
-  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
-                                EFI_HANDLE.
-
-  @retval EFI_INVALID_PARAMETER Language is NULL.
-
-  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
-                                managing the controller specified by
-                                ControllerHandle and ChildHandle.
-
-  @retval EFI_UNSUPPORTED       The driver specified by This does not support
-                                the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalEfiDriverComponentName2GetControllerName(
-  EFI_COMPONENT_NAME2_PROTOCOL*   This,
-  EFI_HANDLE                      ControllerHandle,
-  EFI_HANDLE                      ChildHandle,
-  CHAR8*                          Language,
-  CHAR16**                        ControllerName
-  );
-
-#endif //_OPAL_DRIVER_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h
deleted file mode 100644
index 19ebc3262319..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/** @file
-  Private structures and functions used within OPAL_DRIVER
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _OPAL_DRIVER_PRIVATE_H_
-#define _OPAL_DRIVER_PRIVATE_H_
-#include "OpalDriver.h"
-
-#define OPAL_MSID_LENGHT    128
-
-#pragma pack(1)
-//
-// Structure that is used to represent an OPAL_DISK.
-//
-typedef struct {
-  UINT32                                          MsidLength;             // Byte length of MSID Pin for device
-  UINT8                                           Msid[OPAL_MSID_LENGHT]; // MSID Pin for device
-  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;
-  UINT32                                          MediaId;                // MediaId is used by Ssc Protocol.
-  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
-  UINT16                                          OpalBaseComId;          // Opal SSC 1 base com id.
-  OPAL_OWNER_SHIP                                 Owner;
-  OPAL_DISK_SUPPORT_ATTRIBUTE                     SupportedAttributes;
-  TCG_LOCKING_FEATURE_DESCRIPTOR                  LockingFeature;         // Locking Feature Descriptor retrieved from performing a Level 0 Discovery
-} OPAL_DISK;
-
-//
-// Device with block IO protocol
-//
-typedef struct _OPAL_DRIVER_DEVICE OPAL_DRIVER_DEVICE;
-
-struct _OPAL_DRIVER_DEVICE {
-  OPAL_DRIVER_DEVICE                              *Next;              ///< Linked list pointer
-  EFI_HANDLE                                      Handle;             ///< Device handle
-  OPAL_DISK                                       OpalDisk;           ///< User context
-  CHAR16                                          *Name16;            ///< Allocated/freed by UEFI Filter Driver at device creation/removal
-  CHAR8                                           *NameZ;             ///< Allocated/freed by UEFI Filter Driver at device creation/removal
-  UINT32                                          MediaId;            ///< Required parameter for EFI_STORAGE_SECURITY_COMMAND_PROTOCOL, from BLOCK_IO_MEDIA
-
-  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;              /// Device protocols consumed
-  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
-};
-
-//
-// Opal Driver UEFI Driver Model
-//
-typedef struct {
-  EFI_HANDLE           Handle;              ///< Driver image handle
-  OPAL_DRIVER_DEVICE   *DeviceList;         ///< Linked list of controllers owned by this Driver
-} OPAL_DRIVER;
-#pragma pack()
-
-//
-// Retrieves a OPAL_DRIVER_DEVICE based on the pointer to its StorageSecurity protocol.
-//
-#define DRIVER_DEVICE_FROM_OPALDISK(OpalDiskPointer) (OPAL_DRIVER_DEVICE*)(BASE_CR(OpalDiskPointer, OPAL_DRIVER_DEVICE, OpalDisk))
-
-/**
-  Get devcie list info.
-
-  @retval     return the device list pointer.
-**/
-OPAL_DRIVER_DEVICE*
-OpalDriverGetDeviceList(
-  VOID
-  );
-
-/**
-  Get devcie name through the component name protocol.
-
-  @param[in]       Dev                The device which need to get name.
-
-  @retval     TRUE        Find the name for this device.
-  @retval     FALSE       Not found the name for this device.
-**/
-BOOLEAN
-OpalDriverGetDriverDeviceName(
-  OPAL_DRIVER_DEVICE          *Dev
-  );
-
-/**
-  Get current device count.
-
-  @retval  return the current created device count.
-
-**/
-UINT8
-GetDeviceCount (
-  VOID
-  );
-
-#endif // _OPAL_DRIVER_P_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
deleted file mode 100644
index e3bde4275dfa..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
+++ /dev/null
@@ -1,1527 +0,0 @@
-/** @file
-  Implementation of the HII for the Opal UEFI Driver.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalHii.h"
-#include "OpalDriver.h"
-#include "OpalHiiPrivate.h"
-
-//
-// This is the generated IFR binary Data for each formset defined in VFR.
-// This Data array is ready to be used as input of HiiAddPackages() to
-// create a packagelist (which contains Form packages, String packages, etc).
-//
-extern UINT8  OpalPasswordFormBin[];
-
-//
-// This is the generated String package Data for all .UNI files.
-// This Data array is ready to be used as input of HiiAddPackages() to
-// create a packagelist (which contains Form packages, String packages, etc).
-//
-extern UINT8  OpalPasswordDxeStrings[];
-
-CHAR16  OpalPasswordStorageName[] = L"OpalHiiConfig";
-
-EFI_HII_CONFIG_ACCESS_PROTOCOL gHiiConfigAccessProtocol;
-
-//
-// Handle to the list of HII packages (forms and strings) for this driver
-//
-EFI_HII_HANDLE gHiiPackageListHandle = NULL;
-
-//
-// Package List GUID containing all form and string packages
-//
-const EFI_GUID gHiiPackageListGuid = PACKAGE_LIST_GUID;
-const EFI_GUID gHiiSetupVariableGuid = SETUP_VARIABLE_GUID;
-
-//
-// Structure that contains state of the HII
-// This structure is updated by Hii.cpp and its contents
-// is rendered in the HII.
-//
-OPAL_HII_CONFIGURATION gHiiConfiguration;
-
-CHAR8 gHiiOldPassword[MAX_PASSWORD_CHARACTER_LENGTH] = {0};
-UINT32 gHiiOldPasswordLength = 0;
-
-//
-// The device path containing the VENDOR_DEVICE_PATH and EFI_DEVICE_PATH_PROTOCOL
-//
-HII_VENDOR_DEVICE_PATH gHiiVendorDevicePath = {
-    {
-        {
-            HARDWARE_DEVICE_PATH,
-            HW_VENDOR_DP,
-            {
-                (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
-                (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
-            }
-        },
-        OPAL_PASSWORD_CONFIG_GUID
-    },
-    {
-        END_DEVICE_PATH_TYPE,
-        END_ENTIRE_DEVICE_PATH_SUBTYPE,
-        {
-            (UINT8)(END_DEVICE_PATH_LENGTH),
-            (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
-        }
-    }
-};
-
-
-/**
-  Sets the current system state of global config variables.
-
-**/
-VOID
-HiiSetCurrentConfiguration(
-  VOID
-  )
-{
-  UINT32                                       PpStorageFlag;
-  EFI_STRING                                   NewString;
-
-  gHiiConfiguration.NumDisks = GetDeviceCount();
-
-  //
-  // Update the BlockSID status string.
-  //
-  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
-
-  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
-    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_ENABLED), NULL);
-    if (NewString == NULL) {
-      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
-      return;
-    }
-  } else {
-    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISABLED), NULL);
-    if (NewString == NULL) {
-      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
-      return;
-    }
-  }
-  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS1), NewString, NULL);
-  FreePool (NewString);
-
-  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) != 0) {
-    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), NULL);
-    if (NewString == NULL) {
-      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
-      return;
-    }
-  } else {
-    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), NULL);
-    if (NewString == NULL) {
-      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
-      return;
-    }
-  }
-  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS2), NewString, NULL);
-  FreePool (NewString);
-
-  if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) != 0) {
-    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), NULL);
-    if (NewString == NULL) {
-      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
-      return;
-    }
-  } else {
-    NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), NULL);
-    if (NewString == NULL) {
-      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( ) failed\n"));
-      return;
-    }
-  }
-  HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS3), NewString, NULL);
-  FreePool (NewString);
-}
-
-/**
-  Install the HII related resources.
-
-  @retval  EFI_SUCCESS        Install all the resources success.
-  @retval  other              Error occur when install the resources.
-**/
-EFI_STATUS
-HiiInstall(
-  VOID
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_HANDLE                   DriverHandle;
-
-  //
-  // Clear the global configuration.
-  //
-  ZeroMem(&gHiiConfiguration, sizeof(gHiiConfiguration));
-
-  //
-  // Obtain the driver handle that the BIOS assigned us
-  //
-  DriverHandle = HiiGetDriverImageHandleCB();
-
-  //
-  // Populate the config access protocol with the three functions we are publishing
-  //
-  gHiiConfigAccessProtocol.ExtractConfig = ExtractConfig;
-  gHiiConfigAccessProtocol.RouteConfig = RouteConfig;
-  gHiiConfigAccessProtocol.Callback = DriverCallback;
-
-  //
-  // Associate the required protocols with our driver handle
-  //
-  Status = gBS->InstallMultipleProtocolInterfaces(
-               &DriverHandle,
-               &gEfiHiiConfigAccessProtocolGuid,
-               &gHiiConfigAccessProtocol,      // HII callback
-               &gEfiDevicePathProtocolGuid,
-               &gHiiVendorDevicePath,        // required for HII callback allow all disks to be shown in same hii
-               NULL
-           );
-
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-
-  return OpalHiiAddPackages();
-}
-
-/**
-  Install the HII form and string packages.
-
-  @retval  EFI_SUCCESS           Install all the resources success.
-  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
-**/
-EFI_STATUS
-OpalHiiAddPackages(
-  VOID
-  )
-{
-  EFI_HANDLE                   DriverHandle;
-  CHAR16                       *NewString;
-
-  DriverHandle = HiiGetDriverImageHandleCB();
-
-  //
-  // Publish the HII form and HII string packages
-  //
-  gHiiPackageListHandle = HiiAddPackages(
-                                &gHiiPackageListGuid,
-                                DriverHandle,
-                                OpalPasswordDxeStrings,
-                                OpalPasswordFormBin,
-                                (VOID*)NULL
-                                );
-
-  //
-  // Make sure the packages installed successfully
-  //
-  if (gHiiPackageListHandle == NULL) {
-    DEBUG ((DEBUG_INFO, "OpalHiiAddPackages failed\n"));
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  //
-  // Update Version String in main window
-  //
-  NewString = HiiGetDriverNameCB ();
-  if (HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_MAIN_OPAL_VERSION), NewString, NULL) == 0) {
-    DEBUG ((DEBUG_INFO,  "OpalHiiAddPackages: HiiSetString( ) failed\n"));
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Uninstall the HII capability.
-
-  @retval  EFI_SUCCESS           Uninstall all the resources success.
-  @retval  others                Other errors occur when unistall the hii resource.
-**/
-EFI_STATUS
-HiiUninstall(
-  VOID
-  )
-{
-  EFI_STATUS                   Status;
-
-  //
-  // Remove the packages we've provided to the BIOS
-  //
-  HiiRemovePackages(gHiiPackageListHandle);
-
-  //
-  // Remove the protocols from our driver handle
-  //
-  Status = gBS->UninstallMultipleProtocolInterfaces(
-                          HiiGetDriverImageHandleCB(),
-                          &gEfiHiiConfigAccessProtocolGuid,
-                          &gHiiConfigAccessProtocol,        // HII callback
-                          &gEfiDevicePathProtocolGuid,
-                          &gHiiVendorDevicePath,            // required for HII callback
-                          NULL
-                      );
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_INFO, "Cannot uninstall Hii Protocols: %r\n", Status));
-  }
-
-  return Status;
-}
-
-/**
-  Updates the main menu form.
-
-  @retval  EFI_SUCCESS           update the main form success.
-**/
-EFI_STATUS
-HiiPopulateMainMenuForm (
-  VOID
-  )
-{
-  UINT8         Index;
-  CHAR8         *DiskName;
-  EFI_STRING_ID DiskNameId;
-  OPAL_DISK     *OpalDisk;
-
-  HiiSetCurrentConfiguration();
-
-  gHiiConfiguration.SupportedDisks = 0;
-
-  for (Index = 0; Index < gHiiConfiguration.NumDisks; Index++) {
-    OpalDisk = HiiGetOpalDiskCB (Index);
-    if ((OpalDisk != NULL) && OpalFeatureSupported (&OpalDisk->SupportedAttributes)) {
-      gHiiConfiguration.SupportedDisks |= (1 << Index);
-      DiskNameId = GetDiskNameStringId (Index);
-      DiskName = HiiDiskGetNameCB (Index);
-      if ((DiskName == NULL) || (DiskNameId == 0)) {
-        return EFI_UNSUPPORTED;
-      }
-      HiiSetFormString(DiskNameId, DiskName);
-    }
-  }
-
-  OpalHiiSetBrowserData ();
-  return EFI_SUCCESS;
-}
-
-/**
-  Update the disk action info.
-
-  @param     ActionString
-  @param     SelectedAction
-
-  @retval  EFI_SUCCESS           Uninstall all the resources success.
-**/
-EFI_STATUS
-HiiSelectDiskAction (
-  CHAR8           *ActionString,
-  UINT8           SelectedAction
-  )
-{
-  OPAL_DISK                     *OpalDisk;
-  OPAL_DISK_ACTIONS              AvailActions;
-
-  OpalHiiGetBrowserData ();
-
-  HiiSetFormString(STRING_TOKEN(STR_DISK_ACTION_LBL), ActionString);
-  HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), " ");
-
-  gHiiConfiguration.SelectedAction = SelectedAction;
-  gHiiConfiguration.AvailableFields = 0;
-
-  OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
-  if (OpalDisk == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (OpalSupportGetAvailableActions (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions) != TcgResultSuccess) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  switch (SelectedAction) {
-    case HII_KEY_ID_GOTO_LOCK:
-    case HII_KEY_ID_GOTO_UNLOCK:
-    case HII_KEY_ID_GOTO_SET_ADMIN_PWD:
-    case HII_KEY_ID_GOTO_SET_USER_PWD:
-    case HII_KEY_ID_GOTO_SECURE_ERASE:
-    case HII_KEY_ID_GOTO_DISABLE_USER:
-    case HII_KEY_ID_GOTO_ENABLE_FEATURE:   // User is required to enter Password to enable Feature
-      gHiiConfiguration.AvailableFields |= HII_FIELD_PASSWORD;
-      break;
-
-    case HII_KEY_ID_GOTO_PSID_REVERT:
-      gHiiConfiguration.AvailableFields |= HII_FIELD_PSID;
-      break;
-
-    case HII_KEY_ID_GOTO_REVERT:
-      gHiiConfiguration.AvailableFields |= HII_FIELD_PASSWORD;
-      gHiiConfiguration.AvailableFields |= HII_FIELD_KEEP_USER_DATA;
-      if (AvailActions.RevertKeepDataForced) {
-        gHiiConfiguration.AvailableFields |= HII_FIELD_KEEP_USER_DATA_FORCED;
-      }
-      break;
-  }
-
-  OpalHiiSetBrowserData ();
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Get disk name string id.
-
-  @param   DiskIndex             The input disk index info.
-
-  @retval  The disk name string id.
-
-**/
-EFI_STRING_ID
-GetDiskNameStringId(
-  UINT8 DiskIndex
-  )
-{
-  switch (DiskIndex) {
-    case 0: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0);
-    case 1: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1);
-    case 2: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2);
-    case 3: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3);
-    case 4: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4);
-    case 5: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5);
-  }
-  return 0;
-}
-
-/**
-  This function processes the results of changes in configuration.
-
-  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param  Action                 Specifies the type of action taken by the browser.
-  @param  QuestionId             A unique value which is sent to the original
-                                 exporting driver so that it can identify the type
-                                 of data to expect.
-  @param  Type                   The type of value for the question.
-  @param  Value                  A pointer to the data being sent to the original
-                                 exporting driver.
-  @param  ActionRequest          On return, points to the action requested by the
-                                 callback function.
-
-  @retval EFI_SUCCESS            The callback successfully handled the action.
-  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
-                                 variable and its data.
-  @retval EFI_DEVICE_ERROR       The variable could not be saved.
-  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
-                                 callback.
-
-**/
-EFI_STATUS
-EFIAPI
-DriverCallback(
-  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
-  EFI_BROWSER_ACTION                      Action,
-  EFI_QUESTION_ID                         QuestionId,
-  UINT8                                   Type,
-  EFI_IFR_TYPE_VALUE                      *Value,
-  EFI_BROWSER_ACTION_REQUEST              *ActionRequest
-  )
-{
-  HII_KEY    HiiKey;
-  UINT8      HiiKeyId;
-  UINT32     PpRequest;
-
-  if (ActionRequest != NULL) {
-    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-  } else {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // If QuestionId is an auto-generated key (label, empty line, etc.), ignore it.
-  //
-  if ((QuestionId & HII_KEY_FLAG) == 0) {
-    return EFI_SUCCESS;
-  }
-
-  HiiKey.Raw = QuestionId;
-  HiiKeyId   = (UINT8) HiiKey.KeyBits.Id;
-
-  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
-    switch (HiiKeyId) {
-      case HII_KEY_ID_VAR_SUPPORTED_DISKS:
-        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_VAR_SUPPORTED_DISKS\n"));
-        return HiiPopulateMainMenuForm ();
-
-      case HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS:
-        return HiiPopulateDiskInfoForm();
-    }
-  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
-    switch (HiiKeyId) {
-      case HII_KEY_ID_GOTO_DISK_INFO:
-        return HiiSelectDisk((UINT8)HiiKey.KeyBits.Index);
-
-      case HII_KEY_ID_GOTO_LOCK:
-        return HiiSelectDiskAction("Action: Lock", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_UNLOCK:
-        return HiiSelectDiskAction("Action: Unlock", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_SET_ADMIN_PWD:
-        return HiiSelectDiskAction("Action: Set Administrator Password", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_SET_USER_PWD:
-        return HiiSelectDiskAction("Action: Set User Password", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_SECURE_ERASE:
-        return HiiSelectDiskAction("Action: Secure Erase", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_PSID_REVERT:
-        return HiiSelectDiskAction("Action: Revert to Factory Defaults with PSID", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_REVERT:
-        return HiiSelectDiskAction("Action: Revert to Factory Defaults", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_DISABLE_USER:
-        return HiiSelectDiskAction("Action: Disable User", HiiKeyId);
-
-      case HII_KEY_ID_GOTO_ENABLE_FEATURE:
-        return HiiSelectDiskAction("Action: Enable Feature", HiiKeyId);
-
-      case HII_KEY_ID_ENTER_PASSWORD:
-        return HiiPasswordEntered(Value->string);
-
-      case HII_KEY_ID_ENTER_PSID:
-        return HiiPsidRevert(Value->string);
-
-    }
-  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
-    switch (HiiKeyId) {
-      case HII_KEY_ID_BLOCKSID:
-        switch (Value->u8) {
-          case 0:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
-            break;
-
-          case 1:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID;
-            break;
-
-          case 2:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID;
-            break;
-
-          case 3:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE;
-            break;
-
-          case 4:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE;
-            break;
-
-          case 5:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE;
-            break;
-
-          case 6:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE;
-            break;
-
-          default:
-            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
-            DEBUG ((DEBUG_ERROR, "Invalid value input!\n"));
-            break;
-        }
-        HiiSetBlockSidAction(PpRequest);
-
-        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
-        return EFI_SUCCESS;
-
-      default:
-        break;
-    }
-  }
-
-  return EFI_UNSUPPORTED;
-}
-
-/**
-  Update the global Disk index info.
-
-  @param   Index             The input disk index info.
-
-  @retval  EFI_SUCCESS       Update the disk index info success.
-
-**/
-EFI_STATUS
-HiiSelectDisk(
-  UINT8 Index
-  )
-{
-  OpalHiiGetBrowserData();
-  gHiiConfiguration.SelectedDiskIndex = Index;
-  OpalHiiSetBrowserData ();
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Draws the disk info form.
-
-  @retval  EFI_SUCCESS       Draw the disk info success.
-
-**/
-EFI_STATUS
-HiiPopulateDiskInfoForm(
-  VOID
-  )
-{
-  OPAL_DISK*                    OpalDisk;
-  OPAL_DISK_ACTIONS             AvailActions;
-  TCG_RESULT                    Ret;
-  CHAR8                         *DiskName;
-
-  OpalHiiGetBrowserData();
-
-  DiskName = HiiDiskGetNameCB (gHiiConfiguration.SelectedDiskIndex);
-  if (DiskName == NULL) {
-    return EFI_UNSUPPORTED;
-  }
-  HiiSetFormString(STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME), DiskName);
-
-  ZeroMem(gHiiConfiguration.Psid, sizeof(gHiiConfiguration.Psid));
-
-  gHiiConfiguration.SelectedDiskAvailableActions = HII_ACTION_NONE;
-
-  OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
-
-  if (OpalDisk != NULL) {
-    OpalDiskUpdateStatus (OpalDisk);
-    Ret = OpalSupportGetAvailableActions(&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions);
-    if (Ret == TcgResultSuccess) {
-      //
-      // Update actions, always allow PSID Revert
-      //
-      gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.PsidRevert == 1) ? HII_ACTION_PSID_REVERT : HII_ACTION_NONE;
-
-      //
-      // Always allow unlock to handle device migration
-      //
-      gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Unlock == 1) ? HII_ACTION_UNLOCK : HII_ACTION_NONE;
-
-      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
-        if (OpalDisk->Owner == OpalOwnershipNobody) {
-          gHiiConfiguration.SelectedDiskAvailableActions |= HII_ACTION_ENABLE_FEATURE;
-
-          //
-          // Update strings
-          //
-          HiiSetFormString( STRING_TOKEN(STR_DISK_INFO_PSID_REVERT), "PSID Revert to factory default");
-        } else {
-          DEBUG ((DEBUG_INFO, "Feature disabled but ownership != nobody\n"));
-        }
-      } else {
-        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Revert == 1) ? HII_ACTION_REVERT : HII_ACTION_NONE;
-        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.AdminPass == 1) ? HII_ACTION_SET_ADMIN_PWD : HII_ACTION_NONE;
-        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.UserPass == 1) ? HII_ACTION_SET_USER_PWD : HII_ACTION_NONE;
-        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.SecureErase == 1) ? HII_ACTION_SECURE_ERASE : HII_ACTION_NONE;
-        gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.DisableUser == 1) ? HII_ACTION_DISABLE_USER : HII_ACTION_NONE;
-
-        HiiSetFormString (STRING_TOKEN(STR_DISK_INFO_PSID_REVERT), "PSID Revert to factory default and Disable");
-
-        //
-        // Determine revert options for disk
-        // Default initialize keep user Data to be true
-        //
-        gHiiConfiguration.KeepUserData = 1;
-      }
-    }
-  }
-
-  //
-  // Pass the current configuration to the BIOS
-  //
-  OpalHiiSetBrowserData ();
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Reverts the Opal disk to factory default.
-
-  @param   PsidStringId      The string id for the PSID info.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiPsidRevert(
-  EFI_STRING_ID         PsidStringId
-  )
-{
-  CHAR8                         Response[DEFAULT_RESPONSE_SIZE];
-  TCG_PSID                      Psid;
-  OPAL_DISK                     *OpalDisk;
-  TCG_RESULT                    Ret;
-  OPAL_SESSION                  Session;
-  CHAR16                        *UnicodeStr;
-  UINT8                         TmpBuf[PSID_CHARACTER_STRING_END_LENGTH];
-
-  Ret = TcgResultFailure;
-
-  UnicodeStr = HiiGetString (gHiiPackageListHandle, PsidStringId, NULL);
-  ZeroMem (TmpBuf, sizeof (TmpBuf));
-  UnicodeStrToAsciiStrS (UnicodeStr, (CHAR8*)TmpBuf, PSID_CHARACTER_STRING_END_LENGTH);
-  CopyMem (Psid.Psid, TmpBuf, PSID_CHARACTER_LENGTH);
-  HiiSetString (gHiiPackageListHandle, PsidStringId, L"", NULL);
-  ZeroMem (TmpBuf, sizeof (TmpBuf));
-  ZeroMem (UnicodeStr, StrSize (UnicodeStr));
-  FreePool (UnicodeStr);
-
-  OpalDisk = HiiGetOpalDiskCB (gHiiConfiguration.SelectedDiskIndex);
-  if (OpalDisk != NULL) {
-    ZeroMem(&Session, sizeof(Session));
-    Session.Sscp = OpalDisk->Sscp;
-    Session.MediaId = OpalDisk->MediaId;
-    Session.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-    Ret = OpalSupportPsidRevert(&Session, Psid.Psid, (UINT32)sizeof(Psid.Psid), OpalDisk->OpalDevicePath);
-  }
-
-  ZeroMem (Psid.Psid, PSID_CHARACTER_LENGTH);
-
-  if (Ret == TcgResultSuccess) {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "PSID Revert: Success" );
-  } else {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "PSID Revert: Failure" );
-  }
-
-  HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Set password for the disk.
-
-  @param      OpalDisk       The disk need to set the password.
-  @param      Password       The input password.
-  @param      PassLength     The input password length.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiSetPassword(
-  OPAL_DISK          *OpalDisk,
-  VOID               *Password,
-  UINT32             PassLength
-  )
-{
-  CHAR8                         Response[DEFAULT_RESPONSE_SIZE];
-  TCG_RESULT                    Ret;
-  BOOLEAN                       ExistingPassword;
-  OPAL_SESSION                  Session;
-
-  ExistingPassword = FALSE;
-
-  //
-  // PassLength = 0 means check whether exist old password.
-  //
-  if (PassLength == 0) {
-    ZeroMem(gHiiOldPassword, sizeof(gHiiOldPassword));
-    gHiiOldPasswordLength = 0;
-
-    if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_ENABLE_FEATURE) {
-      ExistingPassword = FALSE;
-    } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_ADMIN_PWD) {
-      ExistingPassword = OpalUtilAdminPasswordExists(OpalDisk->Owner, &OpalDisk->LockingFeature);
-    } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_USER_PWD) {
-      //
-      // Set user Password option shall only be shown if an Admin Password exists
-      // so a Password is always required (Admin or Existing User Password)
-      //
-      ExistingPassword = TRUE;
-    }
-
-    //
-    // Return error if there is a previous Password
-    // see UEFI 2.4 errata B, Figure 121. Password Flowchart
-    //
-    return ExistingPassword ? EFI_DEVICE_ERROR : EFI_SUCCESS;
-  }
-
-  ZeroMem(&Session, sizeof(Session));
-  Session.Sscp = OpalDisk->Sscp;
-  Session.MediaId = OpalDisk->MediaId;
-  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-  AsciiSPrint(Response, DEFAULT_RESPONSE_SIZE, "%a", "Set Password: Failure");
-  //
-  // Password entered.
-  // No current Owner, so set new Password, must be admin Password
-  //
-  if (OpalDisk->Owner == OpalOwnershipNobody) {
-    Ret = OpalSupportEnableOpalFeature (&Session, OpalDisk->Msid, OpalDisk->MsidLength,Password, PassLength, OpalDisk->OpalDevicePath);
-    if (Ret == TcgResultSuccess) {
-      AsciiSPrint(Response, DEFAULT_RESPONSE_SIZE, "%a", "Set Password: Success");
-    }
-
-    HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
-    return EFI_SUCCESS;
-  }
-
-  //
-  // 1st Password entered
-  //
-  if (OpalDisk->Owner == OpalOwnershipUnknown && gHiiOldPasswordLength == 0) {
-
-    //
-    // Unknown ownership - prompt for old Password, then new
-    // old Password is not set yet - first time through
-    // assume authority provided is admin1, overwritten if user1 authority works below
-    //
-    if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_USER_PWD) {
-      //
-      // First try to login as USER1 to Locking SP to see if we're simply updating its Password
-      //
-      Ret =  OpalUtilVerifyPassword (&Session, Password, PassLength, OPAL_LOCKING_SP_USER1_AUTHORITY);
-      if (Ret == TcgResultSuccess) {
-        //
-        // User1 worked so authority 1 means user 1
-        //
-        CopyMem(gHiiOldPassword, Password, PassLength);
-        gHiiOldPasswordLength = PassLength;
-
-        return EFI_SUCCESS;
-      }
-    }
-
-    //
-    // Else try admin1 below
-    //
-    Ret =  OpalUtilVerifyPassword (&Session, Password, PassLength, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
-    if (Ret == TcgResultSuccess) {
-      CopyMem(gHiiOldPassword, Password, PassLength);
-      gHiiOldPasswordLength = PassLength;
-
-      return EFI_SUCCESS;
-    } else {
-      DEBUG ((DEBUG_INFO, "start session with old PW failed - return EFI_NOT_READY - mistyped old PW\n"));
-      HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), "Authentication Failure");
-
-      ZeroMem(gHiiOldPassword, sizeof(gHiiOldPassword));
-      gHiiOldPasswordLength = 0;
-
-      return EFI_NOT_READY;
-    }
-  }
-
-  //
-  // New Password entered
-  //
-  if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_USER_PWD) {
-    Ret = OpalSupportSetPassword(
-                            &Session,
-                            gHiiOldPassword,
-                            gHiiOldPasswordLength,
-                            Password,
-                            PassLength,
-                            OpalDisk->OpalDevicePath,
-                            FALSE
-                            );
-  } else {
-    Ret = OpalSupportSetPassword(
-                            &Session,
-                            gHiiOldPassword,
-                            gHiiOldPasswordLength,
-                            Password,
-                            PassLength,
-                            OpalDisk->OpalDevicePath,
-                            TRUE
-                            );
-  }
-
-  if (Ret == TcgResultSuccess) {
-    AsciiSPrint(Response, DEFAULT_RESPONSE_SIZE, "%a", "Set Password: Success");
-  }
-
-  //
-  // Reset old Password storage
-  //
-  ZeroMem(gHiiOldPassword, sizeof(gHiiOldPassword));
-  gHiiOldPasswordLength = 0;
-
-  HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
-  return Ret == TcgResultSuccess ? EFI_SUCCESS : EFI_NOT_READY;
-}
-
-/**
-  Secure Erases Opal Disk.
-
-  @param      OpalDisk       The disk need to erase data.
-  @param      Password       The input password.
-  @param      PassLength     The input password length.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiSecureErase(
-  OPAL_DISK       *OpalDisk,
-  const VOID      *Password,
-  UINT32          PassLength
-  )
-{
-  CHAR8                        Response[DEFAULT_RESPONSE_SIZE];
-  BOOLEAN                      PasswordFailed;
-  TCG_RESULT                   Ret;
-  OPAL_SESSION                 AdminSpSession;
-
-  if (PassLength == 0) {
-    return EFI_DEVICE_ERROR; // return error to indicate there is an existing Password
-  }
-
-  ZeroMem(&AdminSpSession, sizeof(AdminSpSession));
-  AdminSpSession.Sscp = OpalDisk->Sscp;
-  AdminSpSession.MediaId = OpalDisk->MediaId;
-  AdminSpSession.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-  Ret = OpalUtilSecureErase(&AdminSpSession, Password, PassLength, &PasswordFailed);
-  if (Ret == TcgResultSuccess) {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Secure Erase: Success" );
-  } else {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Secure Erase: Failure" );
-  }
-  HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
-
-  //
-  // If Password failed, return invalid passowrd
-  //
-  if (PasswordFailed) {
-    DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
-    return EFI_NOT_READY;
-  }
-
-  //
-  // Indicates Password was valid and is not changing to UEFI
-  // Response string will indicate action error
-  //
-  return EFI_DEVICE_ERROR;
-}
-
-
-/**
-  Disables User for Opal Disk.
-
-  @param      OpalDisk       The disk need to the action.
-  @param      Password       The input password.
-  @param      PassLength     The input password length.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiDisableUser(
-  OPAL_DISK      *OpalDisk,
-  VOID           *Password,
-  UINT32         PassLength
-  )
-{
-  CHAR8                        Response[ DEFAULT_RESPONSE_SIZE ];
-  BOOLEAN                      PasswordFailed;
-  TCG_RESULT                   Ret;
-  OPAL_SESSION                 Session;
-
-  if (PassLength == 0) {
-    return EFI_DEVICE_ERROR; // return error to indicate there is an existing Password
-  }
-
-  ZeroMem(&Session, sizeof(Session));
-  Session.Sscp = OpalDisk->Sscp;
-  Session.MediaId = OpalDisk->MediaId;
-  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-  Ret = OpalSupportDisableUser(&Session, Password, PassLength, &PasswordFailed, OpalDisk->OpalDevicePath);
-  if (Ret == TcgResultSuccess) {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Disable User: Success" );
-  } else {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Disable User: Failure" );
-  }
-  HiiSetFormString (STRING_TOKEN(STR_ACTION_STATUS), Response);
-
-  //
-  // If Password failed, return invalid passowrd
-  //
-  if (PasswordFailed) {
-    DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
-    return EFI_NOT_READY;
-  }
-
-  //
-  // Indicates Password was valid and is not changing to UEFI
-  // Response string will indicate action error
-  //
-  return EFI_DEVICE_ERROR;
-}
-
-/**
-  Revert Opal Disk as Admin1.
-
-  @param      OpalDisk       The disk need to the action.
-  @param      Password       The input password.
-  @param      PassLength     The input password length.
-  @param      KeepUserData   Whether need to keey user data.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiRevert(
-  OPAL_DISK       *OpalDisk,
-  VOID            *Password,
-  UINT32          PassLength,
-  BOOLEAN         KeepUserData
-  )
-{
-  CHAR8                         Response[ DEFAULT_RESPONSE_SIZE ];
-  BOOLEAN                      PasswordFailed;
-  TCG_RESULT                    Ret;
-  OPAL_SESSION                  Session;
-
-  if (PassLength == 0) {
-    DEBUG ((DEBUG_INFO, "Returning error to indicate there is an existing Password\n"));
-    // return error to indicate there is an existing Password
-    return EFI_DEVICE_ERROR;
-  }
-
-  ZeroMem(&Session, sizeof(Session));
-  Session.Sscp = OpalDisk->Sscp;
-  Session.MediaId = OpalDisk->MediaId;
-  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-  Ret = OpalSupportRevert(
-                      &Session,
-                      KeepUserData,
-                      Password,
-                      PassLength,
-                      OpalDisk->Msid,
-                      OpalDisk->MsidLength,
-                      &PasswordFailed,
-                      OpalDisk->OpalDevicePath
-                      );
-  if (Ret == TcgResultSuccess) {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Revert: Success" );
-  } else {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Revert: Failure" );
-  }
-  HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
-
-  //
-  // If Password failed, return invalid passowrd
-  //
-  if (PasswordFailed) {
-    DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
-    return EFI_NOT_READY;
-  }
-
-  //
-  // Indicates Password was valid and is not changing to UEFI
-  // Response string will indicate action error
-  //
-  return EFI_DEVICE_ERROR;
-}
-
-/**
-  Unlocks Opal Disk.
-
-  @param      OpalDisk       The disk need to the action.
-  @param      Password       The input password.
-  @param      PassLength     The input password length.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiUnlock(
-  OPAL_DISK         *OpalDisk,
-  VOID              *Password,
-  UINT32            PassLength
-  )
-{
-  CHAR8                         Response[DEFAULT_RESPONSE_SIZE];
-  TCG_RESULT                    Ret;
-  OPAL_SESSION                  Session;
-
-  if (PassLength == 0) {
-    DEBUG ((DEBUG_INFO, "Returning error to indicate there is an existing Password\n"));
-    return EFI_DEVICE_ERROR; // return error to indicate there is an existing Password
-  }
-
-  ZeroMem(&Session, sizeof(Session));
-  Session.Sscp = OpalDisk->Sscp;
-  Session.MediaId = OpalDisk->MediaId;
-  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-  Ret = OpalSupportUnlock(&Session, Password, PassLength, OpalDisk->OpalDevicePath);
-  if (Ret == TcgResultSuccess) {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Unlock: Success" );
-  } else {
-    AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Unlock: Failure" );
-  }
-
-  HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
-
-  if (Ret == TcgResultSuccess) {
-    DEBUG ((DEBUG_INFO, "returning error to indicate Password was correct but is not changing\n"));
-    return EFI_DEVICE_ERROR;
-  } else {
-    DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
-    return EFI_NOT_READY;
-  }
-}
-
-/**
-  Use the input password to do the specified action.
-
-  @param      Str            The input password saved in.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Other error occur.
-
-**/
-EFI_STATUS
-HiiPasswordEntered(
-  EFI_STRING_ID            Str
-  )
-{
-  OPAL_DISK*                   OpalDisk;
-  CHAR8                        Password[MAX_PASSWORD_CHARACTER_LENGTH + 1];
-  CHAR16*                      UniStr;
-  UINT32                       PassLength;
-  EFI_STATUS                   Status;
-
-  OpalHiiGetBrowserData();
-
-  OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
-  if (OpalDisk == NULL) {
-    DEBUG ((DEBUG_INFO, "ERROR: disk %u not found\n", gHiiConfiguration.SelectedDiskIndex));
-    return EFI_NOT_FOUND;
-  }
-
-  if (Str == 0) {
-    DEBUG ((DEBUG_INFO, "ERROR: str=NULL\n"));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ZeroMem(Password, sizeof(Password));
-
-  UniStr = HiiGetString(gHiiPackageListHandle, Str, NULL);
-  if (UniStr == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  HiiSetString(gHiiPackageListHandle, Str, L"", NULL);
-
-  PassLength = (UINT32) StrLen (UniStr);
-  if (PassLength >= sizeof(Password)) {
-    HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), "Password too long");
-    ZeroMem (UniStr, StrSize (UniStr));
-    FreePool(UniStr);
-    return EFI_BUFFER_TOO_SMALL;
-  }
-
-  UnicodeStrToAsciiStrS (UniStr, Password, sizeof (Password));
-  ZeroMem (UniStr, StrSize (UniStr));
-  FreePool(UniStr);
-
-  if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_UNLOCK) {
-    Status = HiiUnlock (OpalDisk, Password, PassLength);
-  } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SECURE_ERASE) {
-    Status = HiiSecureErase (OpalDisk, Password, PassLength);
-  } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_DISABLE_USER) {
-    Status = HiiDisableUser (OpalDisk, Password, PassLength);
-  } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_REVERT) {
-    if (OpalDisk->SupportedAttributes.PyriteSsc == 1 && OpalDisk->LockingFeature.MediaEncryption == 0) {
-      //
-      // For pyrite type device which also not supports media encryption, it not accept "Keep User Data" parameter.
-      // So here hardcode a FALSE for this case.
-      //
-      Status = HiiRevert(OpalDisk, Password, PassLength, FALSE);
-    } else {
-      Status = HiiRevert(OpalDisk, Password, PassLength, gHiiConfiguration.KeepUserData);
-    }
-  } else {
-    Status = HiiSetPassword(OpalDisk, Password, PassLength);
-  }
-
-  ZeroMem (Password, sizeof (Password));
-
-  OpalHiiSetBrowserData ();
-
-  return Status;
-}
-
-/**
-  Send BlockSid request through TPM physical presence module.
-
-  @param   PpRequest         TPM physical presence operation request.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Other error occur.
-
-**/
-EFI_STATUS
-HiiSetBlockSidAction (
-  IN UINT32          PpRequest
-  )
-{
-  UINT32                           ReturnCode;
-  EFI_STATUS                       Status;
-
-  ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (PpRequest, 0);
-  if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
-    Status = EFI_SUCCESS;
-  } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) {
-    Status = EFI_OUT_OF_RESOURCES;
-  } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) {
-    Status = EFI_UNSUPPORTED;
-  } else {
-    Status = EFI_DEVICE_ERROR;
-  }
-
-  return Status;
-}
-
-/**
-  This function processes the results of changes in configuration.
-
-  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param  Configuration          A null-terminated Unicode string in <ConfigResp>
-                                 format.
-  @param  Progress               A pointer to a string filled in with the offset of
-                                 the most recent '&' before the first failing
-                                 name/value pair (or the beginning of the string if
-                                 the failure is in the first name/value pair) or
-                                 the terminating NULL if all was successful.
-
-  @retval EFI_SUCCESS            The Results is processed successfully.
-  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
-  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
-                                 driver.
-
-**/
-EFI_STATUS
-EFIAPI
-RouteConfig(
-  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
-  CONST EFI_STRING                        Configuration,
-  EFI_STRING                              *Progress
-  )
-{
-  if (Configuration == NULL || Progress == NULL) {
-    return (EFI_INVALID_PARAMETER);
-  }
-
-  *Progress = Configuration;
-  if (!HiiIsConfigHdrMatch (Configuration, &gHiiSetupVariableGuid, OpalPasswordStorageName)) {
-    return EFI_NOT_FOUND;
-  }
-
-  *Progress = Configuration + StrLen (Configuration);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  This function allows a caller to extract the current configuration for one
-  or more named elements from the target driver.
-
-  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param  Request                A null-terminated Unicode string in
-                                 <ConfigRequest> format.
-  @param  Progress               On return, points to a character in the Request
-                                 string. Points to the string's null terminator if
-                                 request was successful. Points to the most recent
-                                 '&' before the first failing name/value pair (or
-                                 the beginning of the string if the failure is in
-                                 the first name/value pair) if the request was not
-                                 successful.
-  @param  Results                A null-terminated Unicode string in
-                                 <ConfigAltResp> format which has all values filled
-                                 in for the names in the Request string. String to
-                                 be allocated by the called function.
-
-  @retval EFI_SUCCESS            The Results is filled with the requested values.
-  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
-  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
-  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
-                                 driver.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtractConfig(
-  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
-  CONST EFI_STRING                        Request,
-  EFI_STRING                              *Progress,
-  EFI_STRING                              *Results
-  )
-{
-  EFI_STATUS                              Status;
-  EFI_STRING                              ConfigRequest;
-  EFI_STRING                              ConfigRequestHdr;
-  UINTN                                   BufferSize;
-  UINTN                                   Size;
-  BOOLEAN                                 AllocatedRequest;
-  EFI_HANDLE                              DriverHandle;
-
-  //
-  // Check for valid parameters
-  //
-  if (Progress == NULL || Results == NULL) {
-    return (EFI_INVALID_PARAMETER);
-  }
-
-  *Progress = Request;
-  if ((Request != NULL) &&
-    !HiiIsConfigHdrMatch (Request, &gHiiSetupVariableGuid, OpalPasswordStorageName)) {
-    return EFI_NOT_FOUND;
-  }
-
-  AllocatedRequest = FALSE;
-  BufferSize = sizeof (OPAL_HII_CONFIGURATION);
-  ConfigRequest = Request;
-  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
-    //
-    // Request has no request element, construct full request string.
-    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
-    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
-    //
-    DriverHandle = HiiGetDriverImageHandleCB();
-    ConfigRequestHdr = HiiConstructConfigHdr (&gHiiSetupVariableGuid, OpalPasswordStorageName, DriverHandle);
-    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
-    ConfigRequest = AllocateZeroPool (Size);
-    if (ConfigRequest == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-    AllocatedRequest = TRUE;
-    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
-    FreePool (ConfigRequestHdr);
-  }
-
-  //
-  // Convert Buffer Data to <ConfigResp> by helper function BlockToConfig( )
-  //
-  Status = gHiiConfigRouting->BlockToConfig(
-               gHiiConfigRouting,
-               ConfigRequest,
-               (UINT8*)&gHiiConfiguration,
-               sizeof(OPAL_HII_CONFIGURATION),
-               Results,
-               Progress
-           );
-
-  //
-  // Free the allocated config request string.
-  //
-  if (AllocatedRequest) {
-    FreePool (ConfigRequest);
-    ConfigRequest = NULL;
-  }
-
-  //
-  // Set Progress string to the original request string.
-  //
-  if (Request == NULL) {
-    *Progress = NULL;
-  } else if (StrStr (Request, L"OFFSET") == NULL) {
-    *Progress = Request + StrLen (Request);
-  }
-
-  return (Status);
-}
-
-
-/**
-
-  Pass the current system state to the bios via the hii_G_Configuration.
-
-**/
-VOID
-OpalHiiSetBrowserData (
-  VOID
-  )
-{
-  HiiSetBrowserData(
-      &gHiiSetupVariableGuid,
-      (CHAR16*)L"OpalHiiConfig",
-      sizeof(gHiiConfiguration),
-      (UINT8*)&gHiiConfiguration,
-      NULL
-  );
-}
-
-
-/**
-
-  Populate the hii_g_Configuraton with the browser Data.
-
-**/
-VOID
-OpalHiiGetBrowserData (
-  VOID
-  )
-{
-  HiiGetBrowserData(
-      &gHiiSetupVariableGuid,
-      (CHAR16*)L"OpalHiiConfig",
-      sizeof(gHiiConfiguration),
-      (UINT8*)&gHiiConfiguration
-  );
-}
-
-/**
-  Set a string Value in a form.
-
-  @param      DestStringId   The stringid which need to update.
-  @param      SrcAsciiStr    The string nned to update.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Other error occur.
-
-**/
-EFI_STATUS
-HiiSetFormString(
-  EFI_STRING_ID       DestStringId,
-  CHAR8               *SrcAsciiStr
-  )
-{
-  UINT32                    Len;
-  UINT32                    UniSize;
-  CHAR16*                   UniStr;
-
-  //
-  // Determine the Length of the sting
-  //
-  Len = ( UINT32 )AsciiStrLen( SrcAsciiStr );
-
-  //
-  // Allocate space for the unicode string, including terminator
-  //
-  UniSize = (Len + 1) * sizeof(CHAR16);
-  UniStr = (CHAR16*)AllocateZeroPool(UniSize);
-
-  //
-  // Copy into unicode string, then copy into string id
-  //
-  AsciiStrToUnicodeStrS ( SrcAsciiStr, UniStr, Len + 1);
-
-  //
-  // Update the string in the form
-  //
-  if (HiiSetString(gHiiPackageListHandle, DestStringId, UniStr, NULL) == 0) {
-    DEBUG ((DEBUG_INFO,  "HiiSetFormString( ) failed\n"));
-    FreePool(UniStr);
-    return (EFI_OUT_OF_RESOURCES);
-  }
-
-  //
-  // Free the memory
-  //
-  FreePool(UniStr);
-
-  return (EFI_SUCCESS);
-}
-
-/**
-  Initialize the Opal disk base on the hardware info get from device.
-
-  @param Dev                  The Opal device.
-
-  @retval EFI_SUCESS          Initialize the device success.
-  @retval EFI_DEVICE_ERROR    Get info from device failed.
-
-**/
-EFI_STATUS
-OpalDiskInitialize (
-  IN OPAL_DRIVER_DEVICE          *Dev
-  )
-{
-  TCG_RESULT                  TcgResult;
-  OPAL_SESSION                Session;
-
-  ZeroMem(&Dev->OpalDisk, sizeof(OPAL_DISK));
-  Dev->OpalDisk.Sscp = Dev->Sscp;
-  Dev->OpalDisk.MediaId = Dev->MediaId;
-  Dev->OpalDisk.OpalDevicePath = Dev->OpalDevicePath;
-
-  ZeroMem(&Session, sizeof(Session));
-  Session.Sscp = Dev->Sscp;
-  Session.MediaId = Dev->MediaId;
-
-  TcgResult = OpalGetSupportedAttributesInfo (&Session, &Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.OpalBaseComId);
-  if (TcgResult != TcgResultSuccess) {
-    return EFI_DEVICE_ERROR;
-  }
-  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
-
-  TcgResult = OpalUtilGetMsid (&Session, Dev->OpalDisk.Msid, OPAL_MSID_LENGHT, &Dev->OpalDisk.MsidLength);
-  if (TcgResult != TcgResultSuccess) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  return OpalDiskUpdateStatus (&Dev->OpalDisk);
-}
-
-/**
-  Update the device info.
-
-  @param OpalDisk                The Opal device.
-
-  @retval EFI_SUCESS             Initialize the device success.
-  @retval EFI_DEVICE_ERROR       Get info from device failed.
-  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership info.
-
-**/
-EFI_STATUS
-OpalDiskUpdateStatus (
-  OPAL_DISK        *OpalDisk
-  )
-{
-  TCG_RESULT                  TcgResult;
-  OPAL_SESSION                Session;
-
-  ZeroMem(&Session, sizeof(Session));
-  Session.Sscp = OpalDisk->Sscp;
-  Session.MediaId = OpalDisk->MediaId;
-  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
-
-  TcgResult = OpalGetLockingInfo(&Session, &OpalDisk->LockingFeature);
-  if (TcgResult != TcgResultSuccess) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  if (OpalDisk->MsidLength == 0) {
-    return EFI_INVALID_PARAMETER;
-  } else {
-    //
-    // Base on the Msid info to get the ownership, so Msid info must get first.
-    //
-    OpalDisk->Owner = OpalUtilDetermineOwnership(&Session, OpalDisk->Msid, OpalDisk->MsidLength);
-  }
-
-  return EFI_SUCCESS;
-}
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h
deleted file mode 100644
index c03f0827807f..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/** @file
-  Public Header file of HII library used by Opal UEFI Driver.
-  Defines required callbacks of Opal HII library.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _OPAL_HII_H_
-#define _OPAL_HII_H_
-
-#include <Library/OpalPasswordSupportLib.h>
-#include <OpalDriverPrivate.h>
-
-#define DEFAULT_RESPONSE_SIZE 200
-
-/**
-  Get the driver image handle.
-
-  @retval  the driver image handle.
-
-**/
-EFI_HANDLE
-HiiGetDriverImageHandleCB(
-  VOID
-  );
-
-/**
-  Install the HII form and string packages.
-
-  @retval  EFI_SUCCESS           Install all the resources success.
-  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
-**/
-EFI_STATUS
-OpalHiiAddPackages(
-  VOID
-  );
-
-/**
-  Check whether enable feature or not.
-
-  @retval  Return the disk number.
-
-**/
-UINT8
-HiiGetNumConfigRequiredOpalDisksCB(
-  VOID
-  );
-
-/**
-  Returns the driver name.
-
-  @retval Returns the driver name.
-
-**/
-CHAR16*
-HiiGetDriverNameCB(
-  VOID
-  );
-
-/**
-  Returns the opaque pointer to a physical disk context.
-
-  @param  DiskIndex       Input the disk index.
-
-  @retval The device pointer.
-
-**/
-OPAL_DISK*
-HiiGetOpalDiskCB(
-  UINT8 DiskIndex
-  );
-
-/**
-  Returns the disk name.
-
-  @param  DiskIndex       Input the disk index.
-
-  @retval Returns the disk name.
-
-**/
-CHAR8*
-HiiDiskGetNameCB(
-  UINT8 DiskIndex
-  );
-
-/**
-  Set a string Value in a form.
-
-  @param      DestStringId   The stringid which need to update.
-  @param      SrcAsciiStr    The string nned to update.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Other error occur.
-
-**/
-EFI_STATUS
-HiiSetFormString(
-  EFI_STRING_ID       DestStringId,
-  CHAR8               *SrcAsciiStr
-  );
-
-/**
-  Install the HII related resources.
-
-  @retval  EFI_SUCCESS        Install all the resources success.
-  @retval  other              Error occur when install the resources.
-**/
-EFI_STATUS
-HiiInstall(
-  VOID
-  );
-
-/**
-  Uninstall the HII capability.
-
-  @retval  EFI_SUCCESS           Uninstall all the resources success.
-  @retval  others                Other errors occur when unistall the hii resource.
-**/
-EFI_STATUS
-HiiUninstall(
-  VOID
-  );
-
-/**
-  Initialize the Opal disk base on the hardware info get from device.
-
-  @param Dev                  The Opal device.
-
-  @retval EFI_SUCESS          Initialize the device success.
-  @retval EFI_DEVICE_ERROR    Get info from device failed.
-
-**/
-EFI_STATUS
-OpalDiskInitialize (
-  IN OPAL_DRIVER_DEVICE          *Dev
-  );
-
-#endif // _HII_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c
deleted file mode 100644
index 6f2eaeb4c3fe..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/** @file
-  Callbacks required by the HII of the Opal UEFI Driver to help display
-  Opal device information and to send password to SMM handler.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalHii.h"
-#include "OpalDriver.h"
-#include "OpalDriverPrivate.h"
-
-/**
-  Get Opal var name.
-  The return Value must be freed by caller if not NULL
-
-  @param      OpalDisk       The disk.
-  @param      Prefix         The prefix string.
-
-  @retval  The var name string.
-
-**/
-CHAR16*
-OpalDriverGetOpalVarName(
-  OPAL_DISK        *OpalDisk,
-  const CHAR16     *Prefix
-  )
-{
-  OPAL_DRIVER_DEVICE*          Dev;
-  UINTN                        PrefixLen;
-  UINTN                        NameLen;
-  UINTN                        VarNameLen;
-  CHAR16*                      VarName;
-
-  Dev = DRIVER_DEVICE_FROM_OPALDISK(OpalDisk);
-  if (Dev == NULL) {
-    return NULL;
-  }
-
-  PrefixLen = StrLen(Prefix);
-
-  NameLen = 0;
-  if (Dev->Name16 != NULL) {
-    NameLen = StrLen(Dev->Name16);
-  }
-
-  VarNameLen = PrefixLen + NameLen;
-
-  VarName = (CHAR16*)AllocateZeroPool((VarNameLen + 1) * sizeof(CHAR16));
-  if (VarName == NULL) {
-    return NULL;
-  }
-
-  CopyMem(VarName, Prefix, PrefixLen * sizeof(CHAR16));
-  if (Dev->Name16 != NULL) {
-    CopyMem(VarName + PrefixLen, Dev->Name16, NameLen * sizeof(CHAR16));
-  }
-  VarName[VarNameLen] = 0;
-
-  return VarName;
-}
-
-/**
-  Get the driver image handle.
-
-  @retval  the driver image handle.
-
-**/
-EFI_HANDLE
-HiiGetDriverImageHandleCB(
-  VOID
-  )
-{
-  return gImageHandle;
-}
-
-/**
-  Check whether enable feature or not.
-
-  @retval  Return the disk number.
-
-**/
-UINT8
-HiiGetNumConfigRequiredOpalDisksCB(
-  VOID
-  )
-{
-  UINT8                        NumDisks;
-  UINT8                        NumLockedOpalDisks;
-  OPAL_DISK                    *OpalDisk;
-  UINT8                        Index;
-
-  NumLockedOpalDisks = 0;
-
-  NumDisks = GetDeviceCount();
-
-  for (Index = 0; Index < NumDisks; Index++) {
-    OpalDisk = HiiGetOpalDiskCB(Index);
-
-    if (OpalDisk != NULL) {
-      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
-        DEBUG ((DEBUG_INFO, "Ignoring disk %u because feature is disabled or health has already been inspected\n", Index));
-      } else if (OpalDeviceLocked (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
-        NumLockedOpalDisks++;
-      }
-    }
-  }
-
-  return NumLockedOpalDisks;
-}
-
-
-
-/**
-  Returns the opaque pointer to a physical disk context.
-
-  @param  DiskIndex       Input the disk index.
-
-  @retval The device pointer.
-
-**/
-VOID *
-HiiGetDiskContextCB(
-  UINT8 DiskIndex
-  )
-{
-  OPAL_DRIVER_DEVICE*                Dev;
-  UINT8                              CurrentDisk;
-
-  Dev = OpalDriverGetDeviceList();
-  CurrentDisk = 0;
-
-  if (DiskIndex >= GetDeviceCount()) {
-    return NULL;
-  }
-
-  while (Dev != NULL) {
-    if (CurrentDisk == DiskIndex) {
-      return Dev;
-    } else {
-      Dev = Dev->Next;
-      CurrentDisk++;
-    }
-  }
-
-  return NULL;
-}
-
-/**
-  Returns the opaque pointer to a physical disk context.
-
-  @param  DiskIndex       Input the disk index.
-
-  @retval The device pointer.
-
-**/
-OPAL_DISK*
-HiiGetOpalDiskCB(
-  UINT8 DiskIndex
-  )
-{
-  VOID                           *Ctx;
-  OPAL_DRIVER_DEVICE             *Tmp;
-
-  Ctx = HiiGetDiskContextCB (DiskIndex);
-
-  if (Ctx == NULL) {
-    return NULL;
-  }
-
-  Tmp = (OPAL_DRIVER_DEVICE*) Ctx;
-
-  return &Tmp->OpalDisk;
-}
-
-/**
-  Returns the disk name.
-
-  @param  DiskIndex       Input the disk index.
-
-  @retval Returns the disk name.
-
-**/
-CHAR8*
-HiiDiskGetNameCB(
-  UINT8 DiskIndex
-  )
-{
-  OPAL_DRIVER_DEVICE*                Ctx;
-
-  Ctx = (OPAL_DRIVER_DEVICE*) HiiGetDiskContextCB (DiskIndex);
-
-  if (Ctx != NULL) {
-    if (Ctx->NameZ == NULL) {
-      OpalDriverGetDriverDeviceName (Ctx);
-    }
-    return Ctx->NameZ;
-  }
-  return NULL;
-}
-
-/**
-  Returns the driver name.
-
-  @retval Returns the driver name.
-
-**/
-CHAR16*
-HiiGetDriverNameCB(
-  VOID
-  )
-{
-  return (CHAR16*)EFI_DRIVER_NAME_UNICODE;
-}
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
deleted file mode 100644
index 4cfbde3f847e..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
+++ /dev/null
@@ -1,103 +0,0 @@
-// /** @file
-//
-//   String definitions for Setup formset.
-//
-// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-//
-// This program and the accompanying materials
-// are licensed and made available under the terms and conditions of the BSD License
-// which accompanies this distribution. The full text of the license may be found at
-// http://opensource.org/licenses/bsd-license.php
-//
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-//
-// **/
-
-/=#
-/////////////////////////////////   GENERIC DEFINITIONS   /////////////////////////////////
-#langdef en-US                                  "English"
-#string STR_NULL                                #language en-US " "
-
-/////////////////////////////////   FORM SET   /////////////////////////////////
-#string STR_FORM_SET_HELP                        #language en-US "Manage Opal disks"
-
-/////////////////////////////////   MULTIPLE FORMS   /////////////////////////////////
-#string STR_OPAL                                 #language en-US "Opal"
-#string STR_MAIN_OPAL_VERSION                    #language en-US "Version 00.0.0.0000"
-
-/////////////////////////////////   MAIN MENU FORM   /////////////////////////////////
-#string STR_MAIN_PHY_DISKS_LBL                   #language en-US "Physical Disks:"
-#string STR_MAIN_LOCKED_DISKS_LBL                #language en-US "Locked Disks:"
-
-#string STR_MAIN_GOTO_DISK_INFO_0                #language en-US " "
-#string STR_MAIN_GOTO_DISK_INFO_1                #language en-US " "
-#string STR_MAIN_GOTO_DISK_INFO_2                #language en-US " "
-#string STR_MAIN_GOTO_DISK_INFO_3                #language en-US " "
-#string STR_MAIN_GOTO_DISK_INFO_4                #language en-US " "
-#string STR_MAIN_GOTO_DISK_INFO_5                #language en-US " "
-
-#string STR_MAIN_GOTO_DISK_INFO_HELP             #language en-US "Select to see Opal disk actions"
-#string STR_MAIN_GOTO_DISK_HEALTH_HELP           #language en-US "Select disk to unlock"
-
-#string STR_MAIN_NO_DISKS_PRESENT_LBL            #language en-US "No disks connected to system"
-
-/////////////////////////////////   DISK INFO MENU FORM   /////////////////////////////////
-#string STR_DISK_INFO_SELECTED_DISK_NAME         #language en-US " "
-
-#string STR_DISK_INFO_LOCK                       #language en-US "Lock"
-#string STR_DISK_INFO_UNLOCK                     #language en-US "Unlock"
-#string STR_DISK_INFO_SET_ADMIN_PSWD             #language en-US "Update Drive Admin Password"
-#string STR_DISK_INFO_SET_USER_PSWD              #language en-US "Set Drive User Password"
-#string STR_DISK_INFO_SECURE_ERASE               #language en-US "Secure Erase User Data"
-#string STR_DISK_INFO_PSID_REVERT                #language en-US "PSID Revert to factory default"
-#string STR_DISK_INFO_REVERT                     #language en-US "Admin Revert to factory default and Disable"
-#string STR_DISK_INFO_DISABLE_USER               #language en-US "Disable User"
-#string STR_DISK_INFO_ENABLE_FEATURE             #language en-US "Enable Feature"
-#string STR_DISK_INFO_ENABLE_BLOCKSID            #language en-US "TCG Storage Action"
-#string STR_ENABLED                              #language en-US "Enable BlockSID"
-#string STR_DISABLED                             #language en-US "Disable BlockSID"
-
-#string STR_NONE                                 #language en-US "None"
-#string STR_DISK_INFO_ENABLE_BLOCKSID_TRUE       #language en-US "Require physical presence when remote enable BlockSID"
-#string STR_DISK_INFO_ENABLE_BLOCKSID_FALSE      #language en-US "Not require physical presence when remote enable BlockSID"
-#string STR_DISK_INFO_DISABLE_BLOCKSID_TRUE      #language en-US "Require physical presence when remote disable BlockSID"
-#string STR_DISK_INFO_DISABLE_BLOCKSID_FALSE     #language en-US "Not require physical presence when remote disable BlockSID"
-
-#string STR_BLOCKSID_STATUS_HELP                 #language en-US "BlockSID action change status"
-#string STR_BLOCKSID_STATUS                      #language en-US "Current BlockSID Status:"
-#string STR_BLOCKSID_STATUS1                     #language en-US ""
-#string STR_BLOCKSID_STATUS2                     #language en-US ""
-#string STR_BLOCKSID_STATUS3                     #language en-US ""
-
-#string STR_DISK_INFO_GOTO_LOCK_HELP             #language en-US "Lock the disk"
-#string STR_DISK_INFO_GOTO_UNLOCK_HELP           #language en-US "Unlock the disk"
-#string STR_DISK_INFO_GOTO_SET_ADMIN_PSWD_HELP   #language en-US "Set password for the administrator"
-#string STR_DISK_INFO_GOTO_SET_USER_PSWD_HELP    #language en-US "Set password for User 1"
-#string STR_DISK_INFO_GOTO_SECURE_ERASE_HELP     #language en-US "Securely erase the disk"
-#string STR_DISK_INFO_GOTO_PSID_REVERT_HELP      #language en-US "Revert the disk to factory defaults"
-#string STR_DISK_INFO_GOTO_DISABLE_USER_HELP     #language en-US "Disable User"
-#string STR_DISK_INFO_GOTO_ENABLE_FEATURE_HELP   #language en-US "Enable Feature"
-#string STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP  #language en-US "Change BlockSID actions, includes enable or disable BlockSID, Require or not require physical presence when remote enable or disable BlockSID"
-
-/////////////////////////////////   DISK ACTION MENU FORM   /////////////////////////////////
-#string STR_DISK_ACTION_LBL                     #language en-US " "
-
-#string STR_PASSWORD_PROMPT                     #language en-US "Enter Password"
-#string STR_PASSWORD_HELP                       #language en-US "Password must be between 6 and 20 characters"
-
-#string STR_REVERT_PROMPT                       #language en-US "Enter PSID"
-#string STR_REVERT_HELP                         #language en-US "PSID is a 32 character case sensitive value"
-#string STR_ACTION_STATUS                       #language en-US " "
-
-#string STR_PASSWORD_SUBMIT                     #language en-US "Submit Password Changes"
-#string STR_PASSWORD_SUBMIT_HELP                #language en-US "Submits Password Changes (new and update) after passwords have been entered"
-
-#string STR_GOTO_HOME                           #language en-US "Main Menu"
-#string STR_GOTO_HOME_HELP                      #language en-US "Return to the main menu"
-
-#string STR_KEEP_USER_DATA_PROMPT               #language en-US "Keep User Data"
-#string STR_KEEP_USER_DATA_HELP                 #language en-US "Checkmark to keep user data, otherwise data will be lost"
-
-#string STR_OK                                  #language en-US "OK"
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h
deleted file mode 100644
index 88cf9f5b59dd..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/** @file
-  Defines Opal HII form ids, structures and values.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-#ifndef _OPAL_HII_FORM_VALUES_H_
-#define _OPAL_HII_FORM_VALUES_H_
-
-// Maximum Opal password Length
-#define MAX_PASSWORD_CHARACTER_LENGTH                      0x14
-
-// PSID Length
-#define PSID_CHARACTER_LENGTH                              0x20
-#define PSID_CHARACTER_STRING_END_LENGTH                   0x21
-
-// ID's for various forms that will be used by HII
-#define FORMID_VALUE_MAIN_MENU                             0x01
-#define FORMID_VALUE_DISK_INFO_FORM_MAIN                   0x02
-#define FORMID_VALUE_DISK_ACTION_FORM                      0x03
-
-// Structure defining the OPAL_HII_CONFIGURATION
-#pragma pack(1)
-typedef struct {
-    UINT8   NumDisks;
-    UINT8   SelectedDiskIndex;
-    UINT8   SelectedAction;
-    UINT16  SelectedDiskAvailableActions;
-    UINT16  SupportedDisks;
-    UINT8   KeepUserData;
-    UINT16  AvailableFields;
-    UINT16  Password[MAX_PASSWORD_CHARACTER_LENGTH];
-    UINT16  Psid[PSID_CHARACTER_STRING_END_LENGTH];
-    UINT8   EnableBlockSid;
-} OPAL_HII_CONFIGURATION;
-#pragma pack()
-
-/* Action Flags */
-#define HII_ACTION_NONE                                        0x0000
-#define HII_ACTION_LOCK                                        0x0001
-#define HII_ACTION_UNLOCK                                      0x0002
-#define HII_ACTION_SET_ADMIN_PWD                               0x0004
-#define HII_ACTION_SET_USER_PWD                                0x0008
-#define HII_ACTION_SECURE_ERASE                                0x0010
-#define HII_ACTION_PSID_REVERT                                 0x0020
-#define HII_ACTION_DISABLE_USER                                0x0040
-#define HII_ACTION_REVERT                                      0x0080
-#define HII_ACTION_DISABLE_FEATURE                             0x0100
-#define HII_ACTION_ENABLE_FEATURE                              0x0200
-
-/* Flags for diskActionAvailableFields */
-#define HII_FIELD_PASSWORD                      0x0001
-#define HII_FIELD_PSID                          0x0002
-#define HII_FIELD_KEEP_USER_DATA                0x0004
-#define HII_FIELD_KEEP_USER_DATA_FORCED         0x0008
-
-/* Number of bits allocated for each part of a unique key for an HII_ITEM
- * all bits together must be <= 16 (EFI_QUESTION_ID is UINT16)
- * 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
- * |   |-----------------------|   |---------------------------|
- * FLG INDEX                       ID
- */
-#define HII_KEY_ID_BITS                                     8
-#define HII_KEY_INDEX_BITS                                  7
-#define HII_KEY_FLAG_BITS                                   1
-
-#define HII_KEY_FLAG                                        0x8000 // bit 15 (zero based)
-
-/***********/
-/* Key IDs */
-/***********/
-
-#define HII_KEY_ID_GOTO_MAIN_MENU                       0
-#define HII_KEY_ID_GOTO_DISK_INFO                       1
-#define HII_KEY_ID_GOTO_LOCK                            2
-#define HII_KEY_ID_GOTO_UNLOCK                          3
-#define HII_KEY_ID_GOTO_SET_ADMIN_PWD                   4
-#define HII_KEY_ID_GOTO_SET_USER_PWD                    5
-#define HII_KEY_ID_GOTO_SECURE_ERASE                    6
-#define HII_KEY_ID_GOTO_PSID_REVERT                     7
-#define HII_KEY_ID_GOTO_REVERT                          8
-#define HII_KEY_ID_GOTO_DISABLE_USER                    9
-#define HII_KEY_ID_GOTO_ENABLE_FEATURE                  0xA //10
-#define HII_KEY_ID_GOTO_CONFIRM_TO_MAIN_MENU            0xB //11
-#define HII_KEY_ID_ENTER_PASSWORD                       0xC //12
-#define HII_KEY_ID_ENTER_PSID                           0xD //13
-#define HII_KEY_ID_VAR_SUPPORTED_DISKS                  0xE //14
-#define HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS  0xF //15
-
-#define HII_KEY_ID_BLOCKSID                             0x17 //23
-#define HII_KEY_ID_MAX                                  0x17 //23 // !!Update each time a new ID is added!!
-
-#define HII_KEY_WITH_INDEX(id, index) \
-    ( \
-        HII_KEY_FLAG | \
-        (id) | \
-        ((index) << HII_KEY_ID_BITS) \
-    )
-
-#define HII_KEY(id) HII_KEY_WITH_INDEX(id, 0)
-
-#define PACKAGE_LIST_GUID { 0xf0308176, 0x9058, 0x4153, { 0x93, 0x3d, 0xda, 0x2f, 0xdc, 0xc8, 0x3e, 0x44 } }
-
-/* {410483CF-F4F9-4ece-848A-1958FD31CEB7} */
-#define SETUP_FORMSET_GUID { 0x410483cf, 0xf4f9, 0x4ece, { 0x84, 0x8a, 0x19, 0x58, 0xfd, 0x31, 0xce, 0xb7 } }
-
-// {BBF1ACD2-28D8-44ea-A291-58A237FEDF1A}
-#define SETUP_VARIABLE_GUID { 0xbbf1acd2, 0x28d8, 0x44ea, { 0xa2, 0x91, 0x58, 0xa2, 0x37, 0xfe, 0xdf, 0x1a } }
-
-#endif //_HII_FORM_VALUES_H_
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
deleted file mode 100644
index ec5a93cf3f3e..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/** @file
-  Private functions and sturctures used by the Opal UEFI Driver.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _OPAL_HII_PRIVATE_H_
-#define _OPAL_HII_PRIVATE_H_
-
-
-
-#include <Library/OpalPasswordSupportLib.h>
-#include <Protocol/HiiConfigAccess.h>
-
-#include "OpalHii.h"
-#include "OpalHiiFormValues.h"
-
-
-#define  OPAL_PASSWORD_CONFIG_GUID \
-  { \
-    0x0d510a4f, 0xa81b, 0x473f, { 0x87, 0x07, 0xb7, 0xfd, 0xfb, 0xc0, 0x45, 0xba } \
-  }
-
-#pragma pack(1)
-
-typedef struct {
-  UINT16 Id: HII_KEY_ID_BITS;
-  UINT16 Index: HII_KEY_INDEX_BITS;
-  UINT16 Flag: HII_KEY_FLAG_BITS;
-} KEY_BITS;
-
-typedef union {
-    UINT16    Raw;
-    KEY_BITS  KeyBits;
-} HII_KEY;
-
-typedef struct {
-    VENDOR_DEVICE_PATH             VendorDevicePath;
-    EFI_DEVICE_PATH_PROTOCOL       End;
-} HII_VENDOR_DEVICE_PATH;
-
-/**
-* Opal PSID Authority utilized for PSID revert
-*
-* The type indicates the structure of the PSID authority
-*/
-typedef struct {
-    UINT8 Psid[PSID_CHARACTER_LENGTH];
-} TCG_PSID;
-
-/**
-  This function processes the results of changes in configuration.
-
-  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param  Configuration          A null-terminated Unicode string in <ConfigResp>
-                                 format.
-  @param  Progress               A pointer to a string filled in with the offset of
-                                 the most recent '&' before the first failing
-                                 name/value pair (or the beginning of the string if
-                                 the failure is in the first name/value pair) or
-                                 the terminating NULL if all was successful.
-
-  @retval EFI_SUCCESS            The Results is processed successfully.
-  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
-  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
-                                 driver.
-
-**/
-EFI_STATUS
-EFIAPI
-RouteConfig(
-  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
-  CONST EFI_STRING                        Configuration,
-  EFI_STRING                              *Progress
-  );
-
-/**
-  This function allows a caller to extract the current configuration for one
-  or more named elements from the target driver.
-
-  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param  Request                A null-terminated Unicode string in
-                                 <ConfigRequest> format.
-  @param  Progress               On return, points to a character in the Request
-                                 string. Points to the string's null terminator if
-                                 request was successful. Points to the most recent
-                                 '&' before the first failing name/value pair (or
-                                 the beginning of the string if the failure is in
-                                 the first name/value pair) if the request was not
-                                 successful.
-  @param  Results                A null-terminated Unicode string in
-                                 <ConfigAltResp> format which has all values filled
-                                 in for the names in the Request string. String to
-                                 be allocated by the called function.
-
-  @retval EFI_SUCCESS            The Results is filled with the requested values.
-  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
-  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
-  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
-                                 driver.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtractConfig(
-  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
-  CONST EFI_STRING                        Request,
-  EFI_STRING                              *Progress,
-  EFI_STRING                              *Results
-  );
-
-/**
-  This function processes the results of changes in configuration.
-
-  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param  Action                 Specifies the type of action taken by the browser.
-  @param  QuestionId             A unique value which is sent to the original
-                                 exporting driver so that it can identify the type
-                                 of data to expect.
-  @param  Type                   The type of value for the question.
-  @param  Value                  A pointer to the data being sent to the original
-                                 exporting driver.
-  @param  ActionRequest          On return, points to the action requested by the
-                                 callback function.
-
-  @retval EFI_SUCCESS            The callback successfully handled the action.
-  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
-                                 variable and its data.
-  @retval EFI_DEVICE_ERROR       The variable could not be saved.
-  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
-                                 callback.
-
-**/
-EFI_STATUS
-EFIAPI
-DriverCallback(
-  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL*   This,
-  EFI_BROWSER_ACTION                      Action,
-  EFI_QUESTION_ID                         QuestionId,
-  UINT8                                   Type,
-  EFI_IFR_TYPE_VALUE*                     Value,
-  EFI_BROWSER_ACTION_REQUEST*             ActionRequest
-  );
-
-/**
-
-  Pass the current system state to the bios via the hii_G_Configuration.
-
-**/
-VOID
-OpalHiiSetBrowserData (
-  VOID
-  );
-
-/**
-
-  Populate the hii_g_Configuraton with the browser Data.
-
-**/
-VOID
-OpalHiiGetBrowserData (
-  VOID
-  );
-
-/**
-  Draws the disk info form.
-
-  @retval  EFI_SUCCESS       Draw the disk info success.
-
-**/
-EFI_STATUS
-HiiPopulateDiskInfoForm(
-  VOID
-  );
-
-/**
-  Update the global Disk index info.
-
-  @param   Index             The input disk index info.
-
-  @retval  EFI_SUCCESS       Update the disk index info success.
-
-**/
-EFI_STATUS
-HiiSelectDisk(
-  UINT8 Index
-  );
-
-/**
-  Use the input password to do the specified action.
-
-  @param      Str            The input password saved in.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Other error occur.
-
-**/
-EFI_STATUS
-HiiPasswordEntered(
-  EFI_STRING_ID            Str
-  );
-
-/**
-  Update block sid info.
-
-  @param      PpRequest      Input the Pp Request.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Other error occur.
-
-**/
-EFI_STATUS
-HiiSetBlockSidAction (
-  UINT32          PpRequest
-  );
-
-/**
-  Reverts the Opal disk to factory default.
-
-  @param   PsidStringId      The string id for the PSID info.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-
-**/
-EFI_STATUS
-HiiPsidRevert(
-  EFI_STRING_ID         PsidStringId
-  );
-
-/**
-  Get disk name string id.
-
-  @param   DiskIndex             The input disk index info.
-
-  @retval  The disk name string id.
-
-**/
-EFI_STRING_ID
-GetDiskNameStringId(
-  UINT8 DiskIndex
-  );
-
-/**
-  Update the device info.
-
-  @param OpalDisk                The Opal device.
-
-  @retval EFI_SUCESS             Initialize the device success.
-  @retval EFI_DEVICE_ERROR       Get info from device failed.
-  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership info.
-
-**/
-EFI_STATUS
-OpalDiskUpdateStatus (
-  OPAL_DISK        *OpalDisk
-  );
-
-#pragma pack()
-
-#endif // _HII_P_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
deleted file mode 100644
index f2afc378108c..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
+++ /dev/null
@@ -1,82 +0,0 @@
-## @file
-#  This is a OpalPasswordDxe driver.
-#
-#  This module is used to Management the Opal feature
-#  for Opal supported devices.
-#
-#
-# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-##
-[Defines]
-  INF_VERSION                    = 0x00010007
-  BASE_NAME                      = OpalPasswordDxe
-  FILE_GUID                      = E3E4048D-6C0C-43E4-AE1C-FFB579D8EF41
-  MODULE_TYPE                    = DXE_DRIVER
-  VERSION_STRING                 = 1.0
-  ENTRY_POINT                    = EfiDriverEntryPoint
-  UNLOAD_IMAGE                   = OpalEfiDriverUnload
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
-#
-
-[Sources]
-  OpalDriver.h
-  OpalHii.c
-  OpalHiiCallbacks.c
-  OpalDriver.c
-  OpalDriverPrivate.h
-  OpalHii.h
-  OpalHiiPrivate.h
-  OpalHiiFormValues.h
-  OpalPasswordForm.vfr
-  OpalHiiFormStrings.uni
-  ComponentName.c
-
-[Packages]
-  MdePkg/MdePkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-  SecurityPkg/SecurityPkg.dec
-
-[LibraryClasses]
-  BaseLib
-  MemoryAllocationLib
-  UefiBootServicesTableLib
-  UefiDriverEntryPoint
-  UefiHiiServicesLib
-  UefiRuntimeServicesTableLib
-  BaseMemoryLib
-  DebugLib
-  HiiLib
-  PrintLib
-  DevicePathLib
-  OpalPasswordSupportLib
-  UefiLib
-  TcgStorageOpalLib
-  Tcg2PhysicalPresenceLib
-
-[Protocols]
-  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
-  gEfiStorageSecurityCommandProtocolGuid        ## CONSUMES
-  gEfiComponentNameProtocolGuid                 ## PRODUCES
-  gEfiComponentName2ProtocolGuid                ## PRODUCES
-  gEfiBlockIoProtocolGuid                       ## CONSUMES
-  gEfiSmmCommunicationProtocolGuid              ## PRODUCES
-  gEfiPciIoProtocolGuid                         ## CONSUMES
-  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
-
-[Guids]
-  gEfiEventExitBootServicesGuid                 ## CONSUMES ## Event
-  gOpalExtraInfoVariableGuid                    ## PRODUCES ## GUID
-
-[Depex]
-  gEfiSmmCommunicationProtocolGuid AND gEfiHiiStringProtocolGuid AND gEfiHiiDatabaseProtocolGuid
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
deleted file mode 100644
index 218e0f442ce6..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
+++ /dev/null
@@ -1,350 +0,0 @@
-/** @file
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-#include "OpalHiiFormValues.h"
-
-
-#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
-  { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } }
-
-formset
-  guid      = SETUP_FORMSET_GUID,
-  title     = STRING_TOKEN(STR_OPAL),
-  help      = STRING_TOKEN(STR_FORM_SET_HELP),
-  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
-
-  // Define a Buffer Storage (EFI_IFR_VARSTORE) that will be filled
-  // out initially through extractConfig call
-  varstore OPAL_HII_CONFIGURATION,           // This is the Data structure type
-    name  = OpalHiiConfig,                   // Define referenced name in vfr
-    guid  = SETUP_VARIABLE_GUID;         // GUID of this Buffer storage
-
-form formid = FORMID_VALUE_MAIN_MENU,
-    title  = STRING_TOKEN(STR_OPAL);
-
-    //CONFIG_VARIABLE(HII_KEY(HII_KEY_ID_VAR_SUPPORTED_DISKS), SupportedDisks, 0x0, 0xFFFF);
-    suppressif TRUE;
-        numeric
-            name    = SupportedDisks,
-            varid   = OpalHiiConfig.SupportedDisks,
-            prompt  = STRING_TOKEN(STR_NULL),
-            help    = STRING_TOKEN(STR_NULL),
-            flags   = INTERACTIVE,
-            key     = 0x800E,   //32782,
-            minimum = 0x0,
-            maximum = 0xFFFF,
-    endnumeric;
-    endif;
-
-    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    text
-        help   = STRING_TOKEN(STR_NULL),
-        text   = STRING_TOKEN(STR_MAIN_PHY_DISKS_LBL);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    //DISK( 0 );
-    suppressif ( questionref(SupportedDisks) & ( 0x1 ) ) == 0;
-        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
-            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0 ),
-            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
-            flags   = INTERACTIVE, \
-            key     = 0x8001;   //32769
-    endif;
-
-    //DISK( 1 );
-    suppressif ( questionref(SupportedDisks) & ( 0x2 ) ) == 0;
-        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
-            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1 ),
-            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
-            flags   = INTERACTIVE, \
-            key     = 0x8101;   //33025
-    endif;
-
-    //DISK( 2 );
-    suppressif ( questionref(SupportedDisks) & ( 0x4 ) ) == 0;
-        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
-            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2 ),
-            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
-            flags   = INTERACTIVE, \
-            key     = 0x8201;   //33281
-    endif;
-
-    //DISK( 3 );
-    suppressif ( questionref(SupportedDisks) & ( 0x8 ) ) == 0;
-        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
-            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3 ),
-            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
-            flags   = INTERACTIVE, \
-            key     = 0x8301;  // 33537
-    endif;
-
-    //DISK( 4 );
-    suppressif ( questionref(SupportedDisks) & ( 0x10 ) ) == 0;
-        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
-            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4 ),
-            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
-            flags   = INTERACTIVE, \
-            key     = 0x8401;  // 33793
-    endif;
-
-    //DISK( 5 );
-    suppressif ( questionref(SupportedDisks) & ( 0x20 ) ) == 0;
-        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
-            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5 ),
-            help    = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
-            flags   = INTERACTIVE, \
-            key     = 0x8501;   // 34049
-    endif;
-
-    //No disks on system
-    suppressif ideqval OpalHiiConfig.NumDisks > 0;
-        text
-            help    = STRING_TOKEN(STR_NULL),
-            text    = STRING_TOKEN(STR_MAIN_NO_DISKS_PRESENT_LBL);
-    endif;
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    grayoutif TRUE;
-      text
-          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
-          text    = STRING_TOKEN(STR_BLOCKSID_STATUS);
-      text
-          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
-          text    = STRING_TOKEN(STR_BLOCKSID_STATUS1);
-      text
-          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
-          text    = STRING_TOKEN(STR_BLOCKSID_STATUS2);
-      text
-          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
-          text    = STRING_TOKEN(STR_BLOCKSID_STATUS3);
-      subtitle text = STRING_TOKEN(STR_NULL);
-    endif;
-
-    oneof varid   = OpalHiiConfig.EnableBlockSid,
-      questionid  = 0x8017, // 32791,
-      prompt      = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID),
-      help        = STRING_TOKEN(STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP),
-      flags       = INTERACTIVE,
-      option text = STRING_TOKEN(STR_NONE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
-      option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;
-      option text = STRING_TOKEN(STR_DISABLED), value = 2, flags = RESET_REQUIRED;
-      option text = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), value = 3, flags = RESET_REQUIRED;
-      option text = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), value = 4, flags = RESET_REQUIRED;
-      option text = STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), value = 5, flags = RESET_REQUIRED;
-      option text = STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), value = 6, flags = RESET_REQUIRED;
-    endoneof;
-
-
-
-endform;  // MAIN MENU FORM
-
-//
-/////////////////   DISK INFO FORM   /////////////////
-//
-form formid = FORMID_VALUE_DISK_INFO_FORM_MAIN,
-    title  = STRING_TOKEN(STR_OPAL);
-
-    suppressif TRUE;
-        numeric
-            name    = SelectedDiskAvailableActions,
-            varid   = OpalHiiConfig.SelectedDiskAvailableActions,
-            prompt  = STRING_TOKEN(STR_NULL),
-            help    = STRING_TOKEN(STR_NULL),
-            flags   = INTERACTIVE,
-            key     = 0x800F,     // 32783
-            minimum = 0x0,
-            maximum = 0xFFFF,
-    endnumeric;
-    endif;
-
-    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    text
-        help   = STRING_TOKEN(STR_NULL),
-        text   = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_LOCK ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_LOCK),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_LOCK_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8002;    // 32770
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_UNLOCK ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_UNLOCK),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_UNLOCK_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8003; //32771;
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SET_ADMIN_PWD ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_SET_ADMIN_PSWD_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8004; //32772;
-        endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SET_USER_PWD ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_SET_USER_PSWD_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8005; //32773;
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SECURE_ERASE ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_SECURE_ERASE_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8006; //32774;
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_REVERT ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_REVERT),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_PSID_REVERT_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8008; //32776;
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_PSID_REVERT ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_PSID_REVERT_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8007; //32775;
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_DISABLE_USER ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_DISABLE_USER),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_DISABLE_USER_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x8009; //32777;
-    endif;
-
-    suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_ENABLE_FEATURE ) == 0;
-        goto FORMID_VALUE_DISK_ACTION_FORM,
-            prompt  = STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE),
-            help    = STRING_TOKEN(STR_DISK_INFO_GOTO_ENABLE_FEATURE_HELP),
-            flags   = INTERACTIVE,
-            key     = 0x800A; //32778;
-    endif;
-
-endform;  // DISK INFO FORM
-
-//
-/////////////////   DISK ACTION FORM   /////////////////
-//
-form formid = FORMID_VALUE_DISK_ACTION_FORM,
-    title  = STRING_TOKEN(STR_OPAL);
-
-    suppressif TRUE;
-        numeric
-            name    = AvailableFields,
-            varid   = OpalHiiConfig.AvailableFields,
-            prompt  = STRING_TOKEN(STR_NULL),
-            help    = STRING_TOKEN(STR_NULL),
-            flags   = INTERACTIVE,
-            key     = 0x8012,  //32786,
-            minimum = 0x0,
-            maximum = 0xFFFF,
-    endnumeric;
-    endif;
-
-    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    text
-        help   = STRING_TOKEN(STR_NULL),
-        text   = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    text
-        help   = STRING_TOKEN(STR_NULL),
-        text   = STRING_TOKEN(STR_DISK_ACTION_LBL);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    suppressif (questionref(AvailableFields) & HII_FIELD_KEEP_USER_DATA) == 0;
-        grayoutif (questionref(AvailableFields) & HII_FIELD_KEEP_USER_DATA_FORCED) != 0;
-            checkbox
-                name = MyCheckbox,
-                varid = OpalHiiConfig.KeepUserData,
-                prompt = STRING_TOKEN(STR_KEEP_USER_DATA_PROMPT),
-                help = STRING_TOKEN(STR_KEEP_USER_DATA_HELP),
-                key = 0x8011,    //32785,
-            endcheckbox;
-
-            //EMPTY_LINE;
-            text
-                help    = STRING_TOKEN(STR_NULL),
-                text    = STRING_TOKEN(STR_NULL);
-        endif;
-    endif;
-
-    suppressif (questionref(AvailableFields) & HII_FIELD_PASSWORD) == 0;
-        password
-            varid = OpalHiiConfig.Password,
-            prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
-            help = STRING_TOKEN(STR_PASSWORD_HELP),
-            flags = INTERACTIVE,
-            key = 0x800C,   //32780,
-            minsize = 6,
-            maxsize = 20,
-        endpassword;
-    endif;
-
-    suppressif (questionref(AvailableFields) & HII_FIELD_PSID) == 0;
-        string
-            varid = OpalHiiConfig.Psid,
-            prompt = STRING_TOKEN(STR_REVERT_PROMPT),
-            help = STRING_TOKEN(STR_REVERT_HELP),
-            flags = INTERACTIVE,
-            key = 0x800D,   //32781,
-            minsize = PSID_CHARACTER_LENGTH,
-            maxsize = PSID_CHARACTER_LENGTH,
-        endstring;
-    endif;
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    text
-        help   = STRING_TOKEN(STR_NULL),
-        text   = STRING_TOKEN(STR_ACTION_STATUS);
-
-    subtitle text = STRING_TOKEN(STR_NULL);
-
-    goto FORMID_VALUE_MAIN_MENU,
-        prompt  = STRING_TOKEN(STR_GOTO_HOME),
-        help    = STRING_TOKEN(STR_GOTO_HOME_HELP),
-        flags   = INTERACTIVE,
-        key     = 0x8000;   //32768;
-
-endform;  // DISK ACTION FORM
-
-endformset;
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c
deleted file mode 100644
index e38acfd052b5..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c
+++ /dev/null
@@ -1,1267 +0,0 @@
-/** @file
-  This driver is used for Opal Password Feature support at AHCI mode.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-#include "OpalPasswordSmm.h"
-
-/**
-  Start command for give slot on specific port.
-
-  @param  Port               The number of port.
-  @param  CommandSlot        The number of CommandSlot.
-  @param  Timeout            The timeout Value of start.
-
-  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
-  @retval EFI_TIMEOUT        The operation is time out.
-  @retval EFI_SUCCESS        The command start successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciStartCommand (
-  IN  UINT8                     Port,
-  IN  UINT8                     CommandSlot,
-  IN  UINT64                    Timeout
-  );
-
-/**
-  Stop command running for giving port
-
-  @param  Port               The number of port.
-  @param  Timeout            The timeout Value of stop.
-
-  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
-  @retval EFI_TIMEOUT        The operation is time out.
-  @retval EFI_SUCCESS        The command stop successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciStopCommand (
-  IN  UINT8                     Port,
-  IN  UINT64                    Timeout
-  );
-
-/**
-  Read AHCI Operation register.
-
-  @param  Offset       The operation register offset.
-
-  @return The register content read.
-
-**/
-UINT32
-EFIAPI
-AhciReadReg (
-  IN  UINT32              Offset
-  )
-{
-  UINT32   Data;
-
-  Data = 0;
-
-  Data = MmioRead32 (mAhciBar + Offset);
-
-  return Data;
-}
-
-/**
-  Write AHCI Operation register.
-
-  @param  Offset       The operation register offset.
-  @param  Data         The Data used to write down.
-
-**/
-VOID
-EFIAPI
-AhciWriteReg (
-  IN UINT32               Offset,
-  IN UINT32               Data
-  )
-{
-  MmioWrite32 (mAhciBar + Offset, Data);
-
-  return ;
-}
-
-/**
-  Do AND operation with the Value of AHCI Operation register.
-
-  @param  Offset       The operation register offset.
-  @param  AndData      The Data used to do AND operation.
-
-**/
-VOID
-EFIAPI
-AhciAndReg (
-  IN UINT32               Offset,
-  IN UINT32               AndData
-  )
-{
-  UINT32 Data;
-
-  Data  = AhciReadReg (Offset);
-
-  Data &= AndData;
-
-  AhciWriteReg (Offset, Data);
-}
-
-/**
-  Do OR operation with the Value of AHCI Operation register.
-
-  @param  Offset       The operation register offset.
-  @param  OrData       The Data used to do OR operation.
-
-**/
-VOID
-EFIAPI
-AhciOrReg (
-  IN UINT32               Offset,
-  IN UINT32               OrData
-  )
-{
-  UINT32 Data;
-
-  Data  = AhciReadReg (Offset);
-
-  Data |= OrData;
-
-  AhciWriteReg (Offset, Data);
-}
-
-/**
-  Wait for memory set to the test Value.
-
-  @param  Offset            The memory address to test.
-  @param  MaskValue         The mask Value of memory.
-  @param  TestValue         The test Value of memory.
-  @param  Timeout           The time out Value for wait memory set.
-
-  @retval EFI_DEVICE_ERROR  The memory is not set.
-  @retval EFI_TIMEOUT       The memory setting is time out.
-  @retval EFI_SUCCESS       The memory is correct set.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciWaitMmioSet (
-  IN  UINT32                    Offset,
-  IN  UINT32                    MaskValue,
-  IN  UINT32                    TestValue,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32     Value;
-  UINT32     Delay;
-
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
-
-  do {
-    Value = AhciReadReg (Offset) & MaskValue;
-
-    if (Value == TestValue) {
-      return EFI_SUCCESS;
-    }
-
-    //
-    // Stall for 100 microseconds.
-    //
-    MicroSecondDelay (100);
-
-    Delay--;
-
-  } while (Delay > 0);
-
-  return EFI_TIMEOUT;
-}
-/**
-  Wait for the Value of the specified system memory set to the test Value.
-
-  @param  Address           The system memory address to test.
-  @param  MaskValue         The mask Value of memory.
-  @param  TestValue         The test Value of memory.
-  @param  Timeout           The time out Value for wait memory set, uses 100ns as a unit.
-
-  @retval EFI_TIMEOUT       The system memory setting is time out.
-  @retval EFI_SUCCESS       The system memory is correct set.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciWaitMemSet (
-  IN  EFI_PHYSICAL_ADDRESS      Address,
-  IN  UINT32                    MaskValue,
-  IN  UINT32                    TestValue,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32     Value;
-  UINT32     Delay;
-
-  Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
-
-  do {
-    //
-    // Access sytem memory to see if the Value is the tested one.
-    //
-    // The system memory pointed by Address will be updated by the
-    // SATA Host Controller, "volatile" is introduced to prevent
-    // compiler from optimizing the access to the memory address
-    // to only read once.
-    //
-    Value  = *(volatile UINT32 *) (UINTN) Address;
-    Value &= MaskValue;
-
-    if (Value == TestValue) {
-      return EFI_SUCCESS;
-    }
-
-    //
-    // Stall for 100 microseconds.
-    //
-    MicroSecondDelay (100);
-
-    Delay--;
-
-  } while (Delay > 0);
-
-  return EFI_TIMEOUT;
-}
-
-/**
-  Check the memory status to the test Value.
-
-  @param[in]       Address           The memory address to test.
-  @param[in]       MaskValue         The mask Value of memory.
-  @param[in]       TestValue         The test Value of memory.
-  @param[in, out]  RetryTimes        The retry times Value for waitting memory set. If 0, then just try once.
-
-  @retval EFI_NOTREADY      The memory is not set.
-  @retval EFI_TIMEOUT       The memory setting retry times out.
-  @retval EFI_SUCCESS       The memory is correct set.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciCheckMemSet (
-  IN     UINTN                     Address,
-  IN     UINT32                    MaskValue,
-  IN     UINT32                    TestValue,
-  IN OUT UINTN                     *RetryTimes OPTIONAL
-  )
-{
-  UINT32     Value;
-
-  if (RetryTimes != NULL) {
-    (*RetryTimes)--;
-  }
-
-  Value  = *(volatile UINT32 *) Address;
-  Value &= MaskValue;
-
-  if (Value == TestValue) {
-    return EFI_SUCCESS;
-  }
-
-  if ((RetryTimes != NULL) && (*RetryTimes == 0)) {
-    return EFI_TIMEOUT;
-  } else {
-    return EFI_NOT_READY;
-  }
-}
-
-/**
-  Clear the port interrupt and error status. It will also clear
-  HBA interrupt status.
-
-  @param      Port           The number of port.
-
-**/
-VOID
-EFIAPI
-AhciClearPortStatus (
-  IN  UINT8                  Port
-  )
-{
-  UINT32 Offset;
-
-  //
-  // Clear any error status
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
-  AhciWriteReg (Offset, AhciReadReg (Offset));
-
-  //
-  // Clear any port interrupt status
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
-  AhciWriteReg (Offset, AhciReadReg (Offset));
-
-  //
-  // Clear any HBA interrupt status
-  //
-  AhciWriteReg (EFI_AHCI_IS_OFFSET, AhciReadReg (EFI_AHCI_IS_OFFSET));
-}
-
-/**
-  Enable the FIS running for giving port.
-
-  @param      Port           The number of port.
-  @param      Timeout        The timeout Value of enabling FIS.
-
-  @retval EFI_DEVICE_ERROR   The FIS enable setting fails.
-  @retval EFI_TIMEOUT        The FIS enable setting is time out.
-  @retval EFI_SUCCESS        The FIS enable successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciEnableFisReceive (
-  IN  UINT8                     Port,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32 Offset;
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  AhciOrReg (Offset, EFI_AHCI_PORT_CMD_FRE);
-
-  return AhciWaitMmioSet (
-           Offset,
-           EFI_AHCI_PORT_CMD_FR,
-           EFI_AHCI_PORT_CMD_FR,
-           Timeout
-           );
-}
-
-/**
-  Disable the FIS running for giving port.
-
-  @param      Port           The number of port.
-  @param      Timeout        The timeout Value of disabling FIS.
-
-  @retval EFI_DEVICE_ERROR   The FIS disable setting fails.
-  @retval EFI_TIMEOUT        The FIS disable setting is time out.
-  @retval EFI_UNSUPPORTED    The port is in running state.
-  @retval EFI_SUCCESS        The FIS disable successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciDisableFisReceive (
-  IN  UINT8                     Port,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32 Offset;
-  UINT32 Data;
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  Data   = AhciReadReg (Offset);
-
-  //
-  // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
-  //
-  if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
-    return EFI_UNSUPPORTED;
-  }
-
-  //
-  // Check if the Fis receive DMA engine for the port is running.
-  //
-  if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
-    return EFI_SUCCESS;
-  }
-
-  AhciAndReg (Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
-
-  return AhciWaitMmioSet (
-           Offset,
-           EFI_AHCI_PORT_CMD_FR,
-           0,
-           Timeout
-           );
-}
-
-/**
-  Build the command list, command table and prepare the fis receiver.
-
-  @param    AhciRegisters         The pointer to the EFI_AHCI_REGISTERS.
-  @param    Port                  The number of port.
-  @param    PortMultiplier        The timeout Value of stop.
-  @param    CommandFis            The control fis will be used for the transfer.
-  @param    CommandList           The command list will be used for the transfer.
-  @param    AtapiCommand          The atapi command will be used for the transfer.
-  @param    AtapiCommandLength    The Length of the atapi command.
-  @param    CommandSlotNumber     The command slot will be used for the transfer.
-  @param    DataPhysicalAddr      The pointer to the Data Buffer pci bus master address.
-  @param    DataLength            The Data count to be transferred.
-
-**/
-VOID
-EFIAPI
-AhciBuildCommand (
-  IN     EFI_AHCI_REGISTERS         *AhciRegisters,
-  IN     UINT8                      Port,
-  IN     UINT8                      PortMultiplier,
-  IN     EFI_AHCI_COMMAND_FIS       *CommandFis,
-  IN     EFI_AHCI_COMMAND_LIST      *CommandList,
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
-  IN     UINT8                      AtapiCommandLength,
-  IN     UINT8                      CommandSlotNumber,
-  IN OUT VOID                       *DataPhysicalAddr,
-  IN     UINT64                     DataLength
-  )
-{
-  UINT64     BaseAddr;
-  UINT64     PrdtNumber;
-  UINTN      RemainedData;
-  UINTN      MemAddr;
-  DATA_64    Data64;
-  UINT32     Offset;
-
-  //
-  // Filling the PRDT
-  //
-  PrdtNumber = DivU64x32 (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1, EFI_AHCI_MAX_DATA_PER_PRDT);
-
-  //
-  // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB Data block.
-  // It also limits that the maximum amount of the PRDT entry in the command table
-  // is 65535.
-  //
-  ASSERT (PrdtNumber <= 1);
-
-  Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis);
-
-  BaseAddr = Data64.Uint64;
-
-  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
-
-  ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
-
-  CommandFis->AhciCFisPmNum = PortMultiplier;
-
-  CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  if (AtapiCommand != NULL) {
-    CopyMem (
-      &AhciRegisters->AhciCommandTable->AtapiCmd,
-      AtapiCommand,
-      AtapiCommandLength
-      );
-
-    CommandList->AhciCmdA = 1;
-    CommandList->AhciCmdP = 1;
-
-    AhciOrReg (Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
-  } else {
-    AhciAndReg (Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
-  }
-
-  RemainedData = (UINTN) DataLength;
-  MemAddr      = (UINTN) DataPhysicalAddr;
-  CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
-
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbc = (UINT32)RemainedData - 1;
-
-  Data64.Uint64 = (UINT64)MemAddr;
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDba  = Data64.Uint32.Lower32;
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbau = Data64.Uint32.Upper32;
-
-  //
-  // Set the last PRDT to Interrupt On Complete
-  //
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtIoc = 1;
-
-  CopyMem (
-    (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
-    CommandList,
-    sizeof (EFI_AHCI_COMMAND_LIST)
-    );
-
-  Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTable;
-  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba  = Data64.Uint32.Lower32;
-  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
-  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp   = PortMultiplier;
-
-}
-
-/**
-  Buid a command FIS.
-
-  @param  CmdFis            A pointer to the EFI_AHCI_COMMAND_FIS Data structure.
-  @param  AtaCommandBlock   A pointer to the AhciBuildCommandFis Data structure.
-
-**/
-VOID
-EFIAPI
-AhciBuildCommandFis (
-  IN OUT EFI_AHCI_COMMAND_FIS    *CmdFis,
-  IN     EFI_ATA_COMMAND_BLOCK   *AtaCommandBlock
-  )
-{
-  ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
-
-  CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
-  //
-  // Indicator it's a command
-  //
-  CmdFis->AhciCFisCmdInd      = 0x1;
-  CmdFis->AhciCFisCmd         = AtaCommandBlock->AtaCommand;
-
-  CmdFis->AhciCFisFeature     = AtaCommandBlock->AtaFeatures;
-  CmdFis->AhciCFisFeatureExp  = AtaCommandBlock->AtaFeaturesExp;
-
-  CmdFis->AhciCFisSecNum      = AtaCommandBlock->AtaSectorNumber;
-  CmdFis->AhciCFisSecNumExp   = AtaCommandBlock->AtaSectorNumberExp;
-
-  CmdFis->AhciCFisClyLow      = AtaCommandBlock->AtaCylinderLow;
-  CmdFis->AhciCFisClyLowExp   = AtaCommandBlock->AtaCylinderLowExp;
-
-  CmdFis->AhciCFisClyHigh     = AtaCommandBlock->AtaCylinderHigh;
-  CmdFis->AhciCFisClyHighExp  = AtaCommandBlock->AtaCylinderHighExp;
-
-  CmdFis->AhciCFisSecCount    = AtaCommandBlock->AtaSectorCount;
-  CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
-
-  CmdFis->AhciCFisDevHead     = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
-}
-
-/**
-  Start a PIO Data transfer on specific port.
-
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
-  @param  Port                The number of port.
-  @param  PortMultiplier      The timeout Value of stop.
-  @param  AtapiCommand        The atapi command will be used for the transfer.
-  @param  AtapiCommandLength  The Length of the atapi command.
-  @param  Read                The transfer direction.
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
-  @param  MemoryAddr          The pointer to the Data Buffer.
-  @param  DataCount           The Data count to be transferred.
-  @param  Timeout             The timeout Value of non Data transfer.
-
-  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error occurs.
-  @retval EFI_TIMEOUT         The operation is time out.
-  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
-  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciPioTransfer (
-  IN     EFI_AHCI_REGISTERS         *AhciRegisters,
-  IN     UINT8                      Port,
-  IN     UINT8                      PortMultiplier,
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
-  IN     UINT8                      AtapiCommandLength,
-  IN     BOOLEAN                    Read,
-  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
-  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
-  IN OUT VOID                       *MemoryAddr,
-  IN     UINT32                     DataCount,
-  IN     UINT64                     Timeout
-  )
-{
-  EFI_STATUS                    Status;
-  UINT32                        FisBaseAddr;
-  UINT32                        Offset;
-  UINT32                        Delay;
-  EFI_AHCI_COMMAND_FIS          CFis;
-  EFI_AHCI_COMMAND_LIST         CmdList;
-  UINT32                        PortTfd;
-  UINT32                        PrdCount;
-  UINT32                        OldRfisLo;
-  UINT32                        OldRfisHi;
-  UINT32                        OldCmdListLo;
-  UINT32                        OldCmdListHi;
-
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
-  OldRfisLo = AhciReadReg (Offset);
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
-  OldRfisHi = AhciReadReg (Offset);
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
-  AhciWriteReg (Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
-  AhciWriteReg (Offset, 0);
-
-  //
-  // Single task envrionment, we only use one command table for all port
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
-  OldCmdListLo = AhciReadReg (Offset);
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
-  OldCmdListHi = AhciReadReg (Offset);
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
-  AhciWriteReg (Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
-  AhciWriteReg (Offset, 0);
-
-  //
-  // Package read needed
-  //
-  AhciBuildCommandFis (&CFis, AtaCommandBlock);
-
-  ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
-
-  CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
-  CmdList.AhciCmdW   = Read ? 0 : 1;
-
-  AhciBuildCommand (
-    AhciRegisters,
-    Port,
-    PortMultiplier,
-    &CFis,
-    &CmdList,
-    AtapiCommand,
-    AtapiCommandLength,
-    0,
-    (VOID *)(UINTN)MemoryAddr,
-    DataCount
-    );
-
-  Status = AhciStartCommand (
-             Port,
-             0,
-             Timeout
-             );
-  if (EFI_ERROR (Status)) {
-    goto Exit;
-  }
-
-  //
-  // Checking the status and wait the driver sending Data
-  //
-  FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis;
-  if (Read && (AtapiCommand == 0)) {
-    //
-    // Wait device sends the PIO setup fis before Data transfer
-    //
-    Status = EFI_TIMEOUT;
-    Delay  = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
-    do {
-      Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
-
-      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0);
-      if (!EFI_ERROR (Status)) {
-        Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
-        PortTfd = AhciReadReg ((UINT32) Offset);
-        //
-        // PxTFD will be updated if there is a D2H or SetupFIS received.
-        // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.
-        //
-        if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
-          Status = EFI_DEVICE_ERROR;
-          break;
-        }
-
-        PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
-        if (PrdCount == DataCount) {
-          break;
-        }
-      }
-
-      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
-      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, 0);
-      if (!EFI_ERROR (Status)) {
-        Status = EFI_DEVICE_ERROR;
-        break;
-      }
-
-      //
-      // Stall for 100 microseconds.
-      //
-      MicroSecondDelay(100);
-
-      Delay--;
-    } while (Delay > 0);
-  } else {
-    //
-    // Wait for D2H Fis is received
-    //
-    Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
-    Status = AhciWaitMemSet (
-               Offset,
-               EFI_AHCI_FIS_TYPE_MASK,
-               EFI_AHCI_FIS_REGISTER_D2H,
-               Timeout
-               );
-
-    if (EFI_ERROR (Status)) {
-      goto Exit;
-    }
-
-    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
-    PortTfd = AhciReadReg ((UINT32) Offset);
-    if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
-      Status = EFI_DEVICE_ERROR;
-    }
-  }
-
-Exit:
-  AhciStopCommand (
-    Port,
-    Timeout
-    );
-
-  AhciDisableFisReceive (
-    Port,
-    Timeout
-    );
-
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
-  AhciWriteReg (Offset, OldRfisLo);
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
-  AhciWriteReg (Offset, OldRfisHi);
-
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
-  AhciWriteReg (Offset, OldCmdListLo);
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
-  AhciWriteReg (Offset, OldCmdListHi);
-
-  return Status;
-}
-
-/**
-  Stop command running for giving port
-
-  @param  Port               The number of port.
-  @param  Timeout            The timeout Value of stop.
-
-  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
-  @retval EFI_TIMEOUT        The operation is time out.
-  @retval EFI_SUCCESS        The command stop successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciStopCommand (
-  IN  UINT8                     Port,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32 Offset;
-  UINT32 Data;
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  Data   = AhciReadReg (Offset);
-
-  if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {
-    return EFI_SUCCESS;
-  }
-
-  if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
-    AhciAndReg (Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
-  }
-
-  return AhciWaitMmioSet (
-           Offset,
-           EFI_AHCI_PORT_CMD_CR,
-           0,
-           Timeout
-           );
-}
-
-/**
-  Start command for give slot on specific port.
-
-  @param  Port               The number of port.
-  @param  CommandSlot        The number of CommandSlot.
-  @param  Timeout            The timeout Value of start.
-
-  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
-  @retval EFI_TIMEOUT        The operation is time out.
-  @retval EFI_SUCCESS        The command start successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciStartCommand (
-  IN  UINT8                     Port,
-  IN  UINT8                     CommandSlot,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32                        CmdSlotBit;
-  EFI_STATUS                    Status;
-  UINT32                        PortStatus;
-  UINT32                        StartCmd;
-  UINT32                        PortTfd;
-  UINT32                        Offset;
-  UINT32                        Capability;
-
-  //
-  // Collect AHCI controller information
-  //
-  Capability = AhciReadReg(EFI_AHCI_CAPABILITY_OFFSET);
-
-  CmdSlotBit = (UINT32) (1 << CommandSlot);
-
-  AhciClearPortStatus (
-    Port
-    );
-
-  Status = AhciEnableFisReceive (
-             Port,
-             Timeout
-             );
-
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  PortStatus = AhciReadReg (Offset);
-
-  StartCmd = 0;
-  if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
-    StartCmd = AhciReadReg (Offset);
-    StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
-    StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
-  }
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
-  PortTfd = AhciReadReg (Offset);
-
-  if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
-    if ((Capability & BIT24) != 0) {
-      Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-      AhciOrReg (Offset, EFI_AHCI_PORT_CMD_COL);
-
-      AhciWaitMmioSet (
-        Offset,
-        EFI_AHCI_PORT_CMD_COL,
-        0,
-        Timeout
-        );
-    }
-  }
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  AhciOrReg (Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
-
-  //
-  // Setting the command
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SACT;
-  AhciAndReg (Offset, 0);
-  AhciOrReg (Offset, CmdSlotBit);
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
-  AhciAndReg (Offset, 0);
-  AhciOrReg (Offset, CmdSlotBit);
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Do AHCI HBA reset.
-
-  @param[in]  Timeout        The timeout Value of reset.
-
-  @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete hardware reset.
-  @retval EFI_TIMEOUT        The reset operation is time out.
-  @retval EFI_SUCCESS        AHCI controller is reset successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciReset (
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32                 Delay;
-  UINT32                 Value;
-  UINT32                 Capability;
-
-  //
-  // Collect AHCI controller information
-  //
-  Capability = AhciReadReg (EFI_AHCI_CAPABILITY_OFFSET);
-
-  //
-  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
-  //
-  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
-    AhciOrReg (EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
-  }
-
-  AhciOrReg (EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
-
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
-
-  do {
-    Value = AhciReadReg(EFI_AHCI_GHC_OFFSET);
-    if ((Value & EFI_AHCI_GHC_RESET) == 0) {
-      return EFI_SUCCESS;
-    }
-
-    //
-    // Stall for 100 microseconds.
-    //
-    MicroSecondDelay(100);
-
-    Delay--;
-  } while (Delay > 0);
-
-  return EFI_TIMEOUT;
-
-
-}
-
-/**
-  Send Buffer cmd to specific device.
-
-  @param[in]  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
-  @param[in]  Port                The port number of attached ATA device.
-  @param[in]  PortMultiplier      The port number of port multiplier of attached ATA device.
-  @param[in, out]  Buffer         The Data Buffer to store IDENTIFY PACKET Data.
-
-  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
-  @retval EFI_TIMEOUT         The operation is time out.
-  @retval EFI_UNSUPPORTED     The device is not ready for executing.
-  @retval EFI_SUCCESS         The cmd executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciIdentify (
-  IN EFI_AHCI_REGISTERS       *AhciRegisters,
-  IN UINT8                    Port,
-  IN UINT8                    PortMultiplier,
-  IN OUT ATA_IDENTIFY_DATA    *Buffer
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
-
-  if (AhciRegisters == NULL || Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
-
-  AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DRIVE;
-  AtaCommandBlock.AtaSectorCount = 1;
-
-  Status = AhciPioTransfer (
-             AhciRegisters,
-             Port,
-             PortMultiplier,
-             NULL,
-             0,
-             TRUE,
-             &AtaCommandBlock,
-             NULL,
-             Buffer,
-             sizeof (ATA_IDENTIFY_DATA),
-             ATA_TIMEOUT
-             );
-
-  return Status;
-}
-
-/**
-  Get AHCI mode MMIO Bar Size.
-
-  @param[in] Bus         The bus number of ata host controller.
-  @param[in] Device      The device number of ata host controller.
-  @param[in] Function    The function number of ata host controller.
-
-  @retval  The Size of AHCI MMIO BAR.
-
-**/
-UINT32
-EFIAPI
-GetAhciBarSize (
-  IN     UINTN                       Bus,
-  IN     UINTN                       Device,
-  IN     UINTN                       Function
-  )
-{
-  UINT32     Size;
-  UINT32     OldBar;
-
-  OldBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
-  //
-  // Disable PCI CMD.MSE bit before calculating MMIO Bar Size as it needs write all 1 to BAR register.
-  //
-  PciAnd32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x04), (UINT32)~BIT1);
-
-  //
-  // Get AHCI MMIO Bar Size.
-  //
-  PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), 0xFFFFFFFF);
-  Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
-  Size = (~(Size & 0xFFFFFFF0)) + 1;
-
-  //
-  // Restore old MMIO Bar.
-  //
-  PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), OldBar);
-  //
-  // Enable PCI CMD.MSE bit after restoring MMIO Bar.
-  //
-  PciOr32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x04), BIT1);
-
-  return Size;
-}
-
-/**
-  Get AHCI mode base address registers' Value.
-
-  @param[in] Bus         The bus number of ata host controller.
-  @param[in] Device      The device number of ata host controller.
-  @param[in] Function    The function number of ata host controller.
-
-  @retval EFI_UNSUPPORTED        Return this Value when the BARs is not IO type
-  @retval EFI_SUCCESS            Get the Base address successfully
-  @retval Other                  Read the pci configureation Data error
-
-**/
-EFI_STATUS
-EFIAPI
-GetAhciBaseAddress (
-  IN     UINTN                       Bus,
-  IN     UINTN                       Device,
-  IN     UINTN                       Function
-  )
-{
-  UINT32  Size;
-
-  //
-  // Get AHCI MMIO Bar
-  //
-  mAhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
-  //
-  // Get AHCI MMIO Bar Size
-  //
-  Size = GetAhciBarSize (Bus, Device, Function);
-  //
-  // Check if the AHCI Bar region is in SMRAM to avoid malicious attack by modifying MMIO Bar to point to SMRAM.
-  //
-  if (!SmmIsMmioValid ((EFI_PHYSICAL_ADDRESS)mAhciBar, Size, NULL)) {
-    return EFI_UNSUPPORTED;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Allocate transfer-related Data struct which is used at AHCI mode.
-
-  @retval  EFI_OUT_OF_RESOURCE   The allocation is failure.
-  @retval  EFI_SUCCESS           Successful to allocate memory.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciAllocateResource (
-  VOID
-  )
-{
-  EFI_STATUS            Status;
-  EFI_PHYSICAL_ADDRESS  Base;
-
-  //
-  // Allocate resources required by AHCI host controller.
-  //
-  Base = 0xFFFFFFFF;
-  Status = gBS->AllocatePages (
-                  AllocateMaxAddress,
-                  EfiACPIMemoryNVS,
-                  EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
-                  &Base
-                  );
-  if (EFI_ERROR (Status)) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  ZeroMem ((VOID *)(UINTN)Base, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)));
-  mAhciRegisters.AhciRFis = (VOID *)(UINTN)Base;
-
-  Base = 0xFFFFFFFF;
-  Status = gBS->AllocatePages (
-                  AllocateMaxAddress,
-                  EfiACPIMemoryNVS,
-                  EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
-                  &Base
-                  );
-  if (EFI_ERROR (Status)) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mAhciRegisters.AhciRFis, EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)));
-    return EFI_OUT_OF_RESOURCES;
-  }
-  ZeroMem ((VOID *)(UINTN)Base, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
-  mAhciRegisters.AhciCmdList = (VOID *)(UINTN)Base;
-
-  Base = 0xFFFFFFFF;
-  Status = gBS->AllocatePages (
-                  AllocateMaxAddress,
-                  EfiACPIMemoryNVS,
-                  EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
-                  &Base
-                  );
-  if (EFI_ERROR (Status)) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mAhciRegisters.AhciRFis, EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)));
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mAhciRegisters.AhciCmdList, EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
-    return EFI_OUT_OF_RESOURCES;
-  }
-  ZeroMem ((VOID *)(UINTN)Base, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));
-  mAhciRegisters.AhciCommandTable = (VOID *)(UINTN)Base;
-  return EFI_SUCCESS;
-}
-
-/**
-  Free allocated transfer-related Data struct which is used at AHCI mode.
-
-**/
-VOID
-EFIAPI
-AhciFreeResource (
-  VOID
-  )
-{
-  if (mAhciRegisters.AhciRFis != NULL) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mAhciRegisters.AhciRFis, EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)));
-  }
-
-  if (mAhciRegisters.AhciCmdList != NULL) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mAhciRegisters.AhciCmdList, EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
-  }
-
-  if (mAhciRegisters.AhciCommandTable != NULL) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mAhciRegisters.AhciCommandTable, EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));
-  }
-}
-
-/**
-  Initialize ATA host controller at AHCI mode.
-
-  The function is designed to initialize ATA host controller.
-
-  @param[in]  Port          The port number to do initialization.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciModeInitialize (
-  UINT8              Port
-  )
-{
-  EFI_STATUS         Status;
-  UINT32             Capability;
-  UINT32             Offset;
-  UINT32             Data;
-  UINT32             PhyDetectDelay;
-
-  Status = AhciReset (ATA_TIMEOUT);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Collect AHCI controller information
-  //
-  Capability = AhciReadReg (EFI_AHCI_CAPABILITY_OFFSET);
-
-  //
-  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
-  //
-  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
-    AhciOrReg (EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
-  }
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
-  AhciWriteReg (Offset, (UINT32)(UINTN)mAhciRegisters.AhciRFis);
-
-  //
-  // Single task envrionment, we only use one command table for all port
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
-  AhciWriteReg (Offset, (UINT32)(UINTN)mAhciRegisters.AhciCmdList);
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
-  Data = AhciReadReg (Offset);
-  if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
-    AhciOrReg (Offset, EFI_AHCI_PORT_CMD_POD);
-  }
-
-  if ((Capability & BIT27) != 0) {
-    AhciOrReg (Offset, EFI_AHCI_PORT_CMD_SUD);
-  }
-
-  //
-  // Disable aggressive power management.
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
-  AhciOrReg (Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
-  //
-  // Disable the reporting of the corresponding interrupt to system software.
-  //
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
-  AhciAndReg (Offset, 0);
-
-  Status = AhciEnableFisReceive (
-             Port,
-             EFI_TIMER_PERIOD_MILLISECONDS(500)
-             );
-  ASSERT_EFI_ERROR (Status);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
-  // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
-  //
-  PhyDetectDelay = 16 * 1000;
-  do {
-    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
-    if (AhciReadReg(Offset) != 0) {
-      AhciWriteReg (Offset, AhciReadReg(Offset));
-    }
-    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
-
-    Data = AhciReadReg (Offset) & EFI_AHCI_PORT_TFD_MASK;
-    if (Data == 0) {
-      break;
-    }
-
-    MicroSecondDelay (1000);
-    PhyDetectDelay--;
-  } while (PhyDetectDelay > 0);
-
-  if (PhyDetectDelay == 0) {
-    return EFI_NOT_FOUND;
-  }
-
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
-  Status = AhciWaitMmioSet (
-             Offset,
-             0x0000FFFF,
-             0x00000101,
-             EFI_TIMER_PERIOD_SECONDS(16)
-             );
-
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  return Status;
-}
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.h
deleted file mode 100644
index 3a7f6331ca1f..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/** @file
-  Header file for AHCI mode of ATA host controller.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-#ifndef __OPAL_PASSWORD_AHCI_MODE_H__
-#define __OPAL_PASSWORD_AHCI_MODE_H__
-
-//
-// OPAL LIBRARY CALLBACKS
-//
-#define ATA_COMMAND_TRUSTED_RECEIVE            0x5C
-#define ATA_COMMAND_TRUSTED_SEND               0x5E
-
-//
-// ATA TRUSTED commands express transfer Length in 512 byte multiple
-//
-#define ATA_TRUSTED_TRANSFER_LENGTH_MULTIPLE   512
-#define ATA_DEVICE_LBA                         0x40    ///< Set for commands with LBA (rather than CHS) addresses
-
-
-#define EFI_AHCI_BAR_INDEX                     0x05
-
-#define EFI_AHCI_CAPABILITY_OFFSET             0x0000
-#define   EFI_AHCI_CAP_SAM                     BIT18
-#define EFI_AHCI_GHC_OFFSET                    0x0004
-#define   EFI_AHCI_GHC_RESET                   BIT0
-#define   EFI_AHCI_GHC_IE                      BIT1
-#define   EFI_AHCI_GHC_ENABLE                  BIT31
-#define EFI_AHCI_IS_OFFSET                     0x0008
-#define EFI_AHCI_PI_OFFSET                     0x000C
-
-typedef struct {
-  UINT32  Lower32;
-  UINT32  Upper32;
-} DATA_32;
-
-typedef union {
-  DATA_32   Uint32;
-  UINT64    Uint64;
-} DATA_64;
-
-//
-// Each PRDT entry can point to a memory block up to 4M byte
-//
-#define EFI_AHCI_MAX_DATA_PER_PRDT             0x400000
-
-#define EFI_AHCI_FIS_REGISTER_H2D              0x27      //Register FIS - Host to Device
-#define   EFI_AHCI_FIS_REGISTER_H2D_LENGTH     20
-#define EFI_AHCI_FIS_REGISTER_D2H              0x34      //Register FIS - Device to Host
-#define   EFI_AHCI_FIS_REGISTER_D2H_LENGTH     20
-#define EFI_AHCI_FIS_DMA_ACTIVATE              0x39      //DMA Activate FIS - Device to Host
-#define   EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH     4
-#define EFI_AHCI_FIS_DMA_SETUP                 0x41      //DMA Setup FIS - Bi-directional
-#define   EFI_AHCI_FIS_DMA_SETUP_LENGTH        28
-#define EFI_AHCI_FIS_DATA                      0x46      //Data FIS - Bi-directional
-#define EFI_AHCI_FIS_BIST                      0x58      //BIST Activate FIS - Bi-directional
-#define   EFI_AHCI_FIS_BIST_LENGTH             12
-#define EFI_AHCI_FIS_PIO_SETUP                 0x5F      //PIO Setup FIS - Device to Host
-#define   EFI_AHCI_FIS_PIO_SETUP_LENGTH        20
-#define EFI_AHCI_FIS_SET_DEVICE                0xA1      //Set Device Bits FIS - Device to Host
-#define   EFI_AHCI_FIS_SET_DEVICE_LENGTH       8
-
-#define EFI_AHCI_D2H_FIS_OFFSET                0x40
-#define EFI_AHCI_DMA_FIS_OFFSET                0x00
-#define EFI_AHCI_PIO_FIS_OFFSET                0x20
-#define EFI_AHCI_SDB_FIS_OFFSET                0x58
-#define EFI_AHCI_FIS_TYPE_MASK                 0xFF
-#define EFI_AHCI_U_FIS_OFFSET                  0x60
-
-//
-// Port register
-//
-#define EFI_AHCI_PORT_START                    0x0100
-#define EFI_AHCI_PORT_REG_WIDTH                0x0080
-#define EFI_AHCI_PORT_CLB                      0x0000
-#define EFI_AHCI_PORT_CLBU                     0x0004
-#define EFI_AHCI_PORT_FB                       0x0008
-#define EFI_AHCI_PORT_FBU                      0x000C
-#define EFI_AHCI_PORT_IS                       0x0010
-#define   EFI_AHCI_PORT_IS_DHRS                BIT0
-#define   EFI_AHCI_PORT_IS_PSS                 BIT1
-#define   EFI_AHCI_PORT_IS_SSS                 BIT2
-#define   EFI_AHCI_PORT_IS_SDBS                BIT3
-#define   EFI_AHCI_PORT_IS_UFS                 BIT4
-#define   EFI_AHCI_PORT_IS_DPS                 BIT5
-#define   EFI_AHCI_PORT_IS_PCS                 BIT6
-#define   EFI_AHCI_PORT_IS_DIS                 BIT7
-#define   EFI_AHCI_PORT_IS_PRCS                BIT22
-#define   EFI_AHCI_PORT_IS_IPMS                BIT23
-#define   EFI_AHCI_PORT_IS_OFS                 BIT24
-#define   EFI_AHCI_PORT_IS_INFS                BIT26
-#define   EFI_AHCI_PORT_IS_IFS                 BIT27
-#define   EFI_AHCI_PORT_IS_HBDS                BIT28
-#define   EFI_AHCI_PORT_IS_HBFS                BIT29
-#define   EFI_AHCI_PORT_IS_TFES                BIT30
-#define   EFI_AHCI_PORT_IS_CPDS                BIT31
-#define   EFI_AHCI_PORT_IS_CLEAR               0xFFFFFFFF
-#define   EFI_AHCI_PORT_IS_FIS_CLEAR           0x0000000F
-
-#define EFI_AHCI_PORT_IE                       0x0014
-#define EFI_AHCI_PORT_CMD                      0x0018
-#define   EFI_AHCI_PORT_CMD_ST_MASK            0xFFFFFFFE
-#define   EFI_AHCI_PORT_CMD_ST                 BIT0
-#define   EFI_AHCI_PORT_CMD_SUD                BIT1
-#define   EFI_AHCI_PORT_CMD_POD                BIT2
-#define   EFI_AHCI_PORT_CMD_COL                BIT3
-#define   EFI_AHCI_PORT_CMD_CR                 BIT15
-#define   EFI_AHCI_PORT_CMD_FRE                BIT4
-#define   EFI_AHCI_PORT_CMD_FR                 BIT14
-#define   EFI_AHCI_PORT_CMD_MASK               ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL)
-#define   EFI_AHCI_PORT_CMD_PMA                BIT17
-#define   EFI_AHCI_PORT_CMD_HPCP               BIT18
-#define   EFI_AHCI_PORT_CMD_MPSP               BIT19
-#define   EFI_AHCI_PORT_CMD_CPD                BIT20
-#define   EFI_AHCI_PORT_CMD_ESP                BIT21
-#define   EFI_AHCI_PORT_CMD_ATAPI              BIT24
-#define   EFI_AHCI_PORT_CMD_DLAE               BIT25
-#define   EFI_AHCI_PORT_CMD_ALPE               BIT26
-#define   EFI_AHCI_PORT_CMD_ASP                BIT27
-#define   EFI_AHCI_PORT_CMD_ICC_MASK           (BIT28 | BIT29 | BIT30 | BIT31)
-#define   EFI_AHCI_PORT_CMD_ACTIVE             (1 << 28 )
-#define EFI_AHCI_PORT_TFD                      0x0020
-#define   EFI_AHCI_PORT_TFD_MASK               (BIT7 | BIT3 | BIT0)
-#define   EFI_AHCI_PORT_TFD_BSY                BIT7
-#define   EFI_AHCI_PORT_TFD_DRQ                BIT3
-#define   EFI_AHCI_PORT_TFD_ERR                BIT0
-#define   EFI_AHCI_PORT_TFD_ERR_MASK           0x00FF00
-#define EFI_AHCI_PORT_SIG                      0x0024
-#define EFI_AHCI_PORT_SSTS                     0x0028
-#define   EFI_AHCI_PORT_SSTS_DET_MASK          0x000F
-#define   EFI_AHCI_PORT_SSTS_DET               0x0001
-#define   EFI_AHCI_PORT_SSTS_DET_PCE           0x0003
-#define   EFI_AHCI_PORT_SSTS_SPD_MASK          0x00F0
-#define EFI_AHCI_PORT_SCTL                     0x002C
-#define   EFI_AHCI_PORT_SCTL_DET_MASK          0x000F
-#define   EFI_AHCI_PORT_SCTL_MASK              (~EFI_AHCI_PORT_SCTL_DET_MASK)
-#define   EFI_AHCI_PORT_SCTL_DET_INIT          0x0001
-#define   EFI_AHCI_PORT_SCTL_DET_PHYCOMM       0x0003
-#define   EFI_AHCI_PORT_SCTL_SPD_MASK          0x00F0
-#define   EFI_AHCI_PORT_SCTL_IPM_MASK          0x0F00
-#define   EFI_AHCI_PORT_SCTL_IPM_INIT          0x0300
-#define   EFI_AHCI_PORT_SCTL_IPM_PSD           0x0100
-#define   EFI_AHCI_PORT_SCTL_IPM_SSD           0x0200
-#define EFI_AHCI_PORT_SERR                     0x0030
-#define   EFI_AHCI_PORT_SERR_RDIE              BIT0
-#define   EFI_AHCI_PORT_SERR_RCE               BIT1
-#define   EFI_AHCI_PORT_SERR_TDIE              BIT8
-#define   EFI_AHCI_PORT_SERR_PCDIE             BIT9
-#define   EFI_AHCI_PORT_SERR_PE                BIT10
-#define   EFI_AHCI_PORT_SERR_IE                BIT11
-#define   EFI_AHCI_PORT_SERR_PRC               BIT16
-#define   EFI_AHCI_PORT_SERR_PIE               BIT17
-#define   EFI_AHCI_PORT_SERR_CW                BIT18
-#define   EFI_AHCI_PORT_SERR_BDE               BIT19
-#define   EFI_AHCI_PORT_SERR_DE                BIT20
-#define   EFI_AHCI_PORT_SERR_CRCE              BIT21
-#define   EFI_AHCI_PORT_SERR_HE                BIT22
-#define   EFI_AHCI_PORT_SERR_LSE               BIT23
-#define   EFI_AHCI_PORT_SERR_TSTE              BIT24
-#define   EFI_AHCI_PORT_SERR_UFT               BIT25
-#define   EFI_AHCI_PORT_SERR_EX                BIT26
-#define   EFI_AHCI_PORT_ERR_CLEAR              0xFFFFFFFF
-#define EFI_AHCI_PORT_SACT                     0x0034
-#define EFI_AHCI_PORT_CI                       0x0038
-#define EFI_AHCI_PORT_SNTF                     0x003C
-
-
-#pragma pack(1)
-//
-// Command List structure includes total 32 entries.
-// The entry Data structure is listed at the following.
-//
-typedef struct {
-  UINT32   AhciCmdCfl:5;      //Command FIS Length
-  UINT32   AhciCmdA:1;        //ATAPI
-  UINT32   AhciCmdW:1;        //Write
-  UINT32   AhciCmdP:1;        //Prefetchable
-  UINT32   AhciCmdR:1;        //Reset
-  UINT32   AhciCmdB:1;        //BIST
-  UINT32   AhciCmdC:1;        //Clear Busy upon R_OK
-  UINT32   AhciCmdRsvd:1;
-  UINT32   AhciCmdPmp:4;      //Port Multiplier Port
-  UINT32   AhciCmdPrdtl:16;   //Physical Region Descriptor Table Length
-  UINT32   AhciCmdPrdbc;      //Physical Region Descriptor Byte Count
-  UINT32   AhciCmdCtba;       //Command Table Descriptor Base Address
-  UINT32   AhciCmdCtbau;      //Command Table Descriptor Base Address Upper 32-BITs
-  UINT32   AhciCmdRsvd1[4];
-} EFI_AHCI_COMMAND_LIST;
-
-//
-// This is a software constructed FIS.
-// For Data transfer operations, this is the H2D Register FIS format as
-// specified in the Serial ATA Revision 2.6 specification.
-//
-typedef struct {
-  UINT8    AhciCFisType;
-  UINT8    AhciCFisPmNum:4;
-  UINT8    AhciCFisRsvd:1;
-  UINT8    AhciCFisRsvd1:1;
-  UINT8    AhciCFisRsvd2:1;
-  UINT8    AhciCFisCmdInd:1;
-  UINT8    AhciCFisCmd;
-  UINT8    AhciCFisFeature;
-  UINT8    AhciCFisSecNum;
-  UINT8    AhciCFisClyLow;
-  UINT8    AhciCFisClyHigh;
-  UINT8    AhciCFisDevHead;
-  UINT8    AhciCFisSecNumExp;
-  UINT8    AhciCFisClyLowExp;
-  UINT8    AhciCFisClyHighExp;
-  UINT8    AhciCFisFeatureExp;
-  UINT8    AhciCFisSecCount;
-  UINT8    AhciCFisSecCountExp;
-  UINT8    AhciCFisRsvd3;
-  UINT8    AhciCFisControl;
-  UINT8    AhciCFisRsvd4[4];
-  UINT8    AhciCFisRsvd5[44];
-} EFI_AHCI_COMMAND_FIS;
-
-//
-// ACMD: ATAPI command (12 or 16 bytes)
-//
-typedef struct {
-  UINT8    AtapiCmd[0x10];
-} EFI_AHCI_ATAPI_COMMAND;
-
-//
-// Physical Region Descriptor Table includes up to 65535 entries
-// The entry Data structure is listed at the following.
-// the actual entry number comes from the PRDTL field in the command
-// list entry for this command slot.
-//
-typedef struct {
-  UINT32   AhciPrdtDba;       //Data Base Address
-  UINT32   AhciPrdtDbau;      //Data Base Address Upper 32-BITs
-  UINT32   AhciPrdtRsvd;
-  UINT32   AhciPrdtDbc:22;    //Data Byte Count
-  UINT32   AhciPrdtRsvd1:9;
-  UINT32   AhciPrdtIoc:1;     //Interrupt on Completion
-} EFI_AHCI_COMMAND_PRDT;
-
-//
-// Command table Data strucute which is pointed to by the entry in the command list
-//
-typedef struct {
-  EFI_AHCI_COMMAND_FIS      CommandFis;       // A software constructed FIS.
-  EFI_AHCI_ATAPI_COMMAND    AtapiCmd;         // 12 or 16 bytes ATAPI cmd.
-  UINT8                     Reserved[0x30];
-  EFI_AHCI_COMMAND_PRDT     PrdtTable;    // The scatter/gather list for Data transfer
-} EFI_AHCI_COMMAND_TABLE;
-
-//
-// Received FIS structure
-//
-typedef struct {
-  UINT8    AhciDmaSetupFis[0x1C];         // Dma Setup Fis: offset 0x00
-  UINT8    AhciDmaSetupFisRsvd[0x04];
-  UINT8    AhciPioSetupFis[0x14];         // Pio Setup Fis: offset 0x20
-  UINT8    AhciPioSetupFisRsvd[0x0C];
-  UINT8    AhciD2HRegisterFis[0x14];      // D2H Register Fis: offset 0x40
-  UINT8    AhciD2HRegisterFisRsvd[0x04];
-  UINT64   AhciSetDeviceBitsFis;          // Set Device Bits Fix: offset 0x58
-  UINT8    AhciUnknownFis[0x40];          // Unkonwn Fis: offset 0x60
-  UINT8    AhciUnknownFisRsvd[0x60];
-} EFI_AHCI_RECEIVED_FIS;
-
-#pragma pack()
-
-typedef struct {
-  EFI_AHCI_RECEIVED_FIS     *AhciRFis;
-  EFI_AHCI_COMMAND_LIST     *AhciCmdList;
-  EFI_AHCI_COMMAND_TABLE    *AhciCommandTable;
-} EFI_AHCI_REGISTERS;
-
-extern EFI_AHCI_REGISTERS   mAhciRegisters;
-extern UINT32               mAhciBar;
-
-/**
-  Send Buffer cmd to specific device.
-
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
-  @param  Port                The number of port.
-  @param  PortMultiplier      The timeout Value of stop.
-  @param  Buffer              The Data Buffer to store IDENTIFY PACKET Data.
-
-  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
-  @retval EFI_TIMEOUT         The operation is time out.
-  @retval EFI_UNSUPPORTED     The device is not ready for executing.
-  @retval EFI_SUCCESS         The cmd executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciIdentify (
-  IN EFI_AHCI_REGISTERS       *AhciRegisters,
-  IN UINT8                    Port,
-  IN UINT8                    PortMultiplier,
-  IN OUT ATA_IDENTIFY_DATA    *Buffer
-  );
-
-/**
-  Get AHCI mode base address registers' Value.
-
-  @param[in] Bus         The bus number of ata host controller.
-  @param[in] Device      The device number of ata host controller.
-  @param[in] Function    The function number of ata host controller.
-
-  @retval EFI_UNSUPPORTED        Return this Value when the BARs is not IO type
-  @retval EFI_SUCCESS            Get the Base address successfully
-  @retval Other                  Read the pci configureation Data error
-
-**/
-EFI_STATUS
-EFIAPI
-GetAhciBaseAddress (
-  IN     UINTN                       Bus,
-  IN     UINTN                       Device,
-  IN     UINTN                       Function
-  );
-
-/**
-  Allocate transfer-related Data struct which is used at AHCI mode.
-
-  @retval  EFI_OUT_OF_RESOURCE   The allocation is failure.
-  @retval  EFI_SUCCESS           Successful to allocate memory.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciAllocateResource (
-  VOID
-  );
-
-/**
-  Free allocated transfer-related Data struct which is used at AHCI mode.
-
-**/
-VOID
-EFIAPI
-AhciFreeResource (
-  VOID
-  );
-
-/**
-  Initialize ATA host controller at AHCI mode.
-
-  The function is designed to initialize ATA host controller.
-
-  @param[in]  Port          The port number to do initialization.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciModeInitialize (
-  UINT8      Port
-  );
-
-/**
-  Start a PIO Data transfer on specific port.
-
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
-  @param  Port                The number of port.
-  @param  PortMultiplier      The timeout Value of stop.
-  @param  AtapiCommand        The atapi command will be used for the transfer.
-  @param  AtapiCommandLength  The Length of the atapi command.
-  @param  Read                The transfer direction.
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
-  @param  MemoryAddr          The pointer to the Data Buffer.
-  @param  DataCount           The Data count to be transferred.
-  @param  Timeout             The timeout Value of non Data transfer.
-
-  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error occurs.
-  @retval EFI_TIMEOUT         The operation is time out.
-  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
-  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciPioTransfer (
-  IN     EFI_AHCI_REGISTERS         *AhciRegisters,
-  IN     UINT8                      Port,
-  IN     UINT8                      PortMultiplier,
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
-  IN     UINT8                      AtapiCommandLength,
-  IN     BOOLEAN                    Read,
-  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
-  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
-  IN OUT VOID                       *MemoryAddr,
-  IN     UINT32                     DataCount,
-  IN     UINT64                     Timeout
-  );
-
-
-#endif
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c
deleted file mode 100644
index 76204625dd6e..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/** @file
-  This driver is used for Opal Password Feature support at IDE mode.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalPasswordSmm.h"
-
-/**
-  Write multiple words of Data to the IDE Data port.
-  Call the IO abstraction once to do the complete read,
-  not one word at a time
-
-  @param  Port       IO port to read
-  @param  Count      No. of UINT16's to read
-  @param  Buffer     Pointer to the Data Buffer for read
-
-**/
-VOID
-EFIAPI
-IdeWritePortWMultiple (
-  IN  UINT16                Port,
-  IN  UINTN                 Count,
-  IN  UINT16                *Buffer
-  )
-{
-  UINTN Index;
-
-  for (Index = 0; Index < Count; Index++) {
-    IoWrite16 (Port, Buffer[Index]);
-  }
-}
-
-/**
-  Reads multiple words of Data from the IDE Data port.
-  Call the IO abstraction once to do the complete read,
-  not one word at a time
-
-  @param  Port     IO port to read
-  @param  Count    Number of UINT16's to read
-  @param  Buffer   Pointer to the Data Buffer for read
-
-**/
-VOID
-EFIAPI
-IdeReadPortWMultiple (
-  IN  UINT16                Port,
-  IN  UINTN                 Count,
-  IN  UINT16                *Buffer
-  )
-{
-  UINTN Index;
-
-  for (Index = 0; Index < Count; Index++) {
-    Buffer[Count] = IoRead16 (Port);
-  }
-}
-
-/**
-  This function is used to analyze the Status Register and print out
-  some debug information and if there is ERR bit set in the Status
-  Register, the Error Register's Value is also be parsed and print out.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-
-**/
-VOID
-EFIAPI
-DumpAllIdeRegisters (
-  IN     EFI_IDE_REGISTERS        *IdeRegisters
-  )
-{
-  ASSERT (IdeRegisters != NULL);
-
-  DEBUG_CODE_BEGIN ();
-  if ((IoRead8 (IdeRegisters->CmdOrStatus) & ATA_STSREG_DWF) != 0) {
-    DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Write Fault\n", IoRead8 (IdeRegisters->CmdOrStatus)));
-  }
-
-  if ((IoRead8 (IdeRegisters->CmdOrStatus) & ATA_STSREG_CORR) != 0) {
-    DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Corrected Data\n", IoRead8 (IdeRegisters->CmdOrStatus)));
-  }
-
-  if ((IoRead8 (IdeRegisters->CmdOrStatus) & ATA_STSREG_ERR) != 0) {
-    if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_BBK) != 0) {
-      DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Bad Block Detected\n", IoRead8 (IdeRegisters->ErrOrFeature)));
-    }
-
-    if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_UNC) != 0) {
-      DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Uncorrectable Data\n", IoRead8 (IdeRegisters->ErrOrFeature)));
-    }
-
-    if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_MC) != 0) {
-      DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Media Change\n", IoRead8 (IdeRegisters->ErrOrFeature)));
-    }
-
-    if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_ABRT) != 0) {
-      DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Abort\n", IoRead8 (IdeRegisters->ErrOrFeature)));
-    }
-
-    if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_TK0NF) != 0) {
-      DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Track 0 Not Found\n", IoRead8 (IdeRegisters->ErrOrFeature)));
-    }
-
-    if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_AMNF) != 0) {
-      DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Address Mark Not Found\n", IoRead8 (IdeRegisters->ErrOrFeature)));
-    }
-  }
-  DEBUG_CODE_END ();
-}
-
-/**
-  This function is used to analyze the Status Register and print out
-  some debug information and if there is ERR bit set in the Status
-  Register, the Error Register's Value is also be parsed and print out.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-
-  @retval EFI_SUCCESS       No err information in the Status Register.
-  @retval EFI_DEVICE_ERROR  Any err information in the Status Register.
-
-**/
-EFI_STATUS
-EFIAPI
-CheckStatusRegister (
-  IN  EFI_IDE_REGISTERS        *IdeRegisters
-  )
-{
-  EFI_STATUS      Status;
-  UINT8           StatusRegister;
-
-  ASSERT (IdeRegisters != NULL);
-
-  StatusRegister = IoRead8 (IdeRegisters->CmdOrStatus);
-
-  if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {
-    Status = EFI_SUCCESS;
-  } else {
-    Status = EFI_DEVICE_ERROR;
-  }
-
-  return Status;
-}
-
-/**
-  This function is used to poll for the DRQ bit clear in the Status
-  Register. DRQ is cleared when the device is finished transferring Data.
-  So this function is called after Data transfer is finished.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval EFI_SUCCESS     DRQ bit clear within the time out.
-  @retval EFI_TIMEOUT     DRQ bit not clear within the time out.
-
-  @note
-  Read Status Register will clear interrupt status.
-
-**/
-EFI_STATUS
-EFIAPI
-DRQClear (
-  IN  EFI_IDE_REGISTERS         *IdeRegisters,
-  IN  UINT64                    Timeout
-  )
-{
-  UINT32  Delay;
-  UINT8   StatusRegister;
-
-  ASSERT (IdeRegisters != NULL);
-
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
-  do {
-    StatusRegister = IoRead8 (IdeRegisters->CmdOrStatus);
-
-    //
-    // wait for BSY == 0 and DRQ == 0
-    //
-    if ((StatusRegister & ATA_STSREG_BSY) == 0) {
-
-      if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {
-        return EFI_DEVICE_ERROR;
-      } else {
-        return EFI_SUCCESS;
-      }
-    }
-
-    //
-    //  Stall for 100 microseconds.
-    //
-    MicroSecondDelay (100);
-
-    Delay--;
-
-  } while (Delay > 0);
-
-    return EFI_TIMEOUT;
-}
-/**
-  This function is used to poll for the DRQ bit clear in the Alternate
-  Status Register. DRQ is cleared when the device is finished
-  transferring Data. So this function is called after Data transfer
-  is finished.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval EFI_SUCCESS     DRQ bit clear within the time out.
-
-  @retval EFI_TIMEOUT     DRQ bit not clear within the time out.
-  @note   Read Alternate Status Register will not clear interrupt status.
-
-**/
-EFI_STATUS
-EFIAPI
-DRQClear2 (
-  IN  EFI_IDE_REGISTERS    *IdeRegisters,
-  IN  UINT64               Timeout
-  )
-{
-  UINT32  Delay;
-  UINT8   AltRegister;
-
-  ASSERT (IdeRegisters != NULL);
-
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
-  do {
-    AltRegister = IoRead8 (IdeRegisters->AltOrDev);
-
-    //
-    //  wait for BSY == 0 and DRQ == 0
-    //
-    if ((AltRegister & ATA_STSREG_BSY) == 0) {
-      if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {
-        return EFI_DEVICE_ERROR;
-      } else {
-        return EFI_SUCCESS;
-      }
-    }
-
-    //
-    // Stall for 100 microseconds.
-    //
-    MicroSecondDelay (100);
-
-    Delay--;
-
-  } while (Delay > 0);
-
-  return EFI_TIMEOUT;
-}
-
-
-/**
-  This function is used to poll for the DRQ bit set in the Alternate Status Register.
-  DRQ is set when the device is ready to transfer Data. So this function is called after
-  the command is sent to the device and before required Data is transferred.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval EFI_SUCCESS     DRQ bit set within the time out.
-  @retval EFI_TIMEOUT     DRQ bit not set within the time out.
-  @retval EFI_ABORTED     DRQ bit not set caused by the command abort.
-  @note  Read Alternate Status Register will not clear interrupt status.
-
-**/
-EFI_STATUS
-EFIAPI
-DRQReady2 (
-  IN  EFI_IDE_REGISTERS    *IdeRegisters,
-  IN  UINT64               Timeout
-  )
-{
-  UINT32  Delay;
-  UINT8   AltRegister;
-  UINT8   ErrorRegister;
-
-  ASSERT (IdeRegisters != NULL);
-
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
-
-  do {
-    //
-    //  Read Alternate Status Register will not clear interrupt status
-    //
-    AltRegister = IoRead8 (IdeRegisters->AltOrDev);
-    //
-    // BSY == 0 , DRQ == 1
-    //
-    if ((AltRegister & ATA_STSREG_BSY) == 0) {
-      if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {
-        ErrorRegister = IoRead8 (IdeRegisters->ErrOrFeature);
-
-        if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
-          return EFI_ABORTED;
-        }
-        return EFI_DEVICE_ERROR;
-      }
-
-      if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {
-        return EFI_SUCCESS;
-      } else {
-        return EFI_NOT_READY;
-      }
-    }
-
-    //
-    // Stall for 100 microseconds.
-    //
-    MicroSecondDelay (100);
-
-    Delay--;
-  } while (Delay > 0);
-
-  return EFI_TIMEOUT;
-}
-
-/**
-  This function is used to poll for the BSY bit clear in the Status Register. BSY
-  is clear when the device is not busy. Every command must be sent after device is not busy.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval EFI_SUCCESS     BSY bit clear within the time out.
-  @retval EFI_TIMEOUT     BSY bit not clear within the time out.
-
-  @note Read Status Register will clear interrupt status.
-**/
-EFI_STATUS
-EFIAPI
-WaitForBSYClear (
-  IN  EFI_IDE_REGISTERS    *IdeRegisters,
-  IN  UINT64               Timeout
-  )
-{
-  UINT32  Delay;
-  UINT8   StatusRegister;
-
-  ASSERT (IdeRegisters != NULL);
-
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
-  do {
-    StatusRegister = IoRead8 (IdeRegisters->CmdOrStatus);
-
-    if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {
-      return EFI_SUCCESS;
-    }
-
-    //
-    // Stall for 100 microseconds.
-    //
-    MicroSecondDelay (100);
-
-    Delay--;
-
-  } while (Delay > 0);
-
-  return EFI_TIMEOUT;
-}
-
-/**
-  Get IDE i/o port registers' base addresses by mode.
-
-  In 'Compatibility' mode, use fixed addresses.
-  In Native-PCI mode, get base addresses from BARs in the PCI IDE controller's
-  Configuration Space.
-
-  The steps to get IDE i/o port registers' base addresses for each channel
-  as follows:
-
-  1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
-  controller's Configuration Space to determine the operating mode.
-
-  2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
-   ___________________________________________
-  |           | Command Block | Control Block |
-  |  Channel  |   Registers   |   Registers   |
-  |___________|_______________|_______________|
-  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
-  |___________|_______________|_______________|
-  | Secondary |  170h - 177h  |  376h - 377h  |
-  |___________|_______________|_______________|
-
-  Table 1. Compatibility resource mappings
-
-  b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
-  in IDE controller's PCI Configuration Space, shown in the Table 2 below.
-   ___________________________________________________
-  |           |   Command Block   |   Control Block   |
-  |  Channel  |     Registers     |     Registers     |
-  |___________|___________________|___________________|
-  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
-  |___________|___________________|___________________|
-  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
-  |___________|___________________|___________________|
-
-  Table 2. BARs for Register Mapping
-
-  @param[in] Bus                 The bus number of ata host controller.
-  @param[in] Device              The device number of ata host controller.
-  @param[in] Function            The function number of ata host controller.
-  @param[in, out] IdeRegisters   Pointer to EFI_IDE_REGISTERS which is used to
-                                 store the IDE i/o port registers' base addresses
-
-  @retval EFI_UNSUPPORTED        Return this Value when the BARs is not IO type
-  @retval EFI_SUCCESS            Get the Base address successfully
-  @retval Other                  Read the pci configureation Data error
-
-**/
-EFI_STATUS
-EFIAPI
-GetIdeRegisterIoAddr (
-  IN     UINTN                       Bus,
-  IN     UINTN                       Device,
-  IN     UINTN                       Function,
-  IN OUT EFI_IDE_REGISTERS           *IdeRegisters
-  )
-{
-  UINT16            CommandBlockBaseAddr;
-  UINT16            ControlBlockBaseAddr;
-  UINT8             ClassCode;
-  UINT32            BaseAddress[4];
-
-  if (IdeRegisters == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x9));
-  BaseAddress[0] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x10));
-  BaseAddress[1] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x14));
-  BaseAddress[2] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x18));
-  BaseAddress[3] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x1C));
-
-  if ((ClassCode & IDE_PRIMARY_OPERATING_MODE) == 0) {
-    CommandBlockBaseAddr = 0x1f0;
-    ControlBlockBaseAddr = 0x3f6;
-  } else {
-    //
-    // The BARs should be of IO type
-    //
-    if ((BaseAddress[0] & BIT0) == 0 ||
-        (BaseAddress[1] & BIT0) == 0) {
-      return EFI_UNSUPPORTED;
-    }
-
-    CommandBlockBaseAddr = (UINT16) (BaseAddress[0] & 0x0000fff8);
-    ControlBlockBaseAddr = (UINT16) ((BaseAddress[1] & 0x0000fffc) + 2);
-  }
-
-  //
-  // Calculate IDE primary channel I/O register base address.
-  //
-  IdeRegisters[EfiIdePrimary].Data              = CommandBlockBaseAddr;
-  IdeRegisters[EfiIdePrimary].ErrOrFeature      = (UINT16) (CommandBlockBaseAddr + 0x01);
-  IdeRegisters[EfiIdePrimary].SectorCount       = (UINT16) (CommandBlockBaseAddr + 0x02);
-  IdeRegisters[EfiIdePrimary].SectorNumber      = (UINT16) (CommandBlockBaseAddr + 0x03);
-  IdeRegisters[EfiIdePrimary].CylinderLsb       = (UINT16) (CommandBlockBaseAddr + 0x04);
-  IdeRegisters[EfiIdePrimary].CylinderMsb       = (UINT16) (CommandBlockBaseAddr + 0x05);
-  IdeRegisters[EfiIdePrimary].Head              = (UINT16) (CommandBlockBaseAddr + 0x06);
-  IdeRegisters[EfiIdePrimary].CmdOrStatus       = (UINT16) (CommandBlockBaseAddr + 0x07);
-  IdeRegisters[EfiIdePrimary].AltOrDev          = ControlBlockBaseAddr;
-
-  if ((ClassCode & IDE_SECONDARY_OPERATING_MODE) == 0) {
-    CommandBlockBaseAddr = 0x170;
-    ControlBlockBaseAddr = 0x376;
-  } else {
-    //
-    // The BARs should be of IO type
-    //
-    if ((BaseAddress[2] & BIT0) == 0 ||
-        (BaseAddress[3] & BIT0) == 0) {
-      return EFI_UNSUPPORTED;
-    }
-
-    CommandBlockBaseAddr = (UINT16) (BaseAddress[2] & 0x0000fff8);
-    ControlBlockBaseAddr = (UINT16) ((BaseAddress[3] & 0x0000fffc) + 2);
-  }
-
-  //
-  // Calculate IDE secondary channel I/O register base address.
-  //
-  IdeRegisters[EfiIdeSecondary].Data              = CommandBlockBaseAddr;
-  IdeRegisters[EfiIdeSecondary].ErrOrFeature      = (UINT16) (CommandBlockBaseAddr + 0x01);
-  IdeRegisters[EfiIdeSecondary].SectorCount       = (UINT16) (CommandBlockBaseAddr + 0x02);
-  IdeRegisters[EfiIdeSecondary].SectorNumber      = (UINT16) (CommandBlockBaseAddr + 0x03);
-  IdeRegisters[EfiIdeSecondary].CylinderLsb       = (UINT16) (CommandBlockBaseAddr + 0x04);
-  IdeRegisters[EfiIdeSecondary].CylinderMsb       = (UINT16) (CommandBlockBaseAddr + 0x05);
-  IdeRegisters[EfiIdeSecondary].Head              = (UINT16) (CommandBlockBaseAddr + 0x06);
-  IdeRegisters[EfiIdeSecondary].CmdOrStatus       = (UINT16) (CommandBlockBaseAddr + 0x07);
-  IdeRegisters[EfiIdeSecondary].AltOrDev          = ControlBlockBaseAddr;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Send ATA Ext command into device with NON_DATA protocol.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval  EFI_SUCCESS Reading succeed
-  @retval  EFI_DEVICE_ERROR Error executing commands on this device.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaIssueCommand (
-  IN  EFI_IDE_REGISTERS         *IdeRegisters,
-  IN  EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,
-  IN  UINT64                    Timeout
-  )
-{
-  EFI_STATUS  Status;
-  UINT8       DeviceHead;
-  UINT8       AtaCommand;
-
-  ASSERT (IdeRegisters != NULL);
-  ASSERT (AtaCommandBlock != NULL);
-
-  DeviceHead = AtaCommandBlock->AtaDeviceHead;
-  AtaCommand = AtaCommandBlock->AtaCommand;
-
-  Status = WaitForBSYClear (IdeRegisters, Timeout);
-  if (EFI_ERROR (Status)) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  //
-  // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
-  //
-  IoWrite8 (IdeRegisters->Head, (UINT8) (0xe0 | DeviceHead));
-
-  //
-  // set all the command parameters
-  // Before write to all the following registers, BSY and DRQ must be 0.
-  //
-  Status = DRQClear2 (IdeRegisters, Timeout);
-  if (EFI_ERROR (Status)) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  //
-  // Fill the feature register, which is a two-byte FIFO. Need write twice.
-  //
-  IoWrite8 (IdeRegisters->ErrOrFeature, AtaCommandBlock->AtaFeaturesExp);
-  IoWrite8 (IdeRegisters->ErrOrFeature, AtaCommandBlock->AtaFeatures);
-
-  //
-  // Fill the sector count register, which is a two-byte FIFO. Need write twice.
-  //
-  IoWrite8 (IdeRegisters->SectorCount, AtaCommandBlock->AtaSectorCountExp);
-  IoWrite8 (IdeRegisters->SectorCount, AtaCommandBlock->AtaSectorCount);
-
-  //
-  // Fill the start LBA registers, which are also two-byte FIFO
-  //
-  IoWrite8 (IdeRegisters->SectorNumber, AtaCommandBlock->AtaSectorNumberExp);
-  IoWrite8 (IdeRegisters->SectorNumber, AtaCommandBlock->AtaSectorNumber);
-
-  IoWrite8 (IdeRegisters->CylinderLsb, AtaCommandBlock->AtaCylinderLowExp);
-  IoWrite8 (IdeRegisters->CylinderLsb, AtaCommandBlock->AtaCylinderLow);
-
-  IoWrite8 (IdeRegisters->CylinderMsb, AtaCommandBlock->AtaCylinderHighExp);
-  IoWrite8 (IdeRegisters->CylinderMsb, AtaCommandBlock->AtaCylinderHigh);
-
-  //
-  // Send command via Command Register
-  //
-  IoWrite8 (IdeRegisters->CmdOrStatus, AtaCommand);
-
-  //
-  // Stall at least 400 microseconds.
-  //
-  MicroSecondDelay (400);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  This function is used to send out ATA commands conforms to the PIO Data In Protocol.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Buffer           A pointer to the source Buffer for the Data.
-  @param ByteCount        The Length of  the Data.
-  @param Read             Flag used to determine the Data transfer direction.
-                          Read equals 1, means Data transferred from device to host;
-                          Read equals 0, means Data transferred from host to device.
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK Data structure.
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval EFI_SUCCESS      send out the ATA command and device send required Data successfully.
-  @retval EFI_DEVICE_ERROR command sent failed.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPioDataInOut (
-  IN     EFI_IDE_REGISTERS         *IdeRegisters,
-  IN OUT VOID                      *Buffer,
-  IN     UINT64                    ByteCount,
-  IN     BOOLEAN                   Read,
-  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,
-  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,
-  IN     UINT64                    Timeout
-  )
-{
-  UINTN       WordCount;
-  UINTN       Increment;
-  UINT16      *Buffer16;
-  EFI_STATUS  Status;
-
-  if ((IdeRegisters == NULL) || (Buffer == NULL) || (AtaCommandBlock == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Issue ATA command
-  //
-  Status = AtaIssueCommand (IdeRegisters, AtaCommandBlock, Timeout);
-  if (EFI_ERROR (Status)) {
-    Status = EFI_DEVICE_ERROR;
-    goto Exit;
-  }
-
-  Buffer16 = (UINT16 *) Buffer;
-
-  //
-  // According to PIO Data in protocol, host can perform a series of reads to
-  // the Data register after each time device set DRQ ready;
-  // The Data Size of "a series of read" is command specific.
-  // For most ATA command, Data Size received from device will not exceed
-  // 1 sector, hence the Data Size for "a series of read" can be the whole Data
-  // Size of one command request.
-  // For ATA command such as Read Sector command, the Data Size of one ATA
-  // command request is often larger than 1 sector, according to the
-  // Read Sector command, the Data Size of "a series of read" is exactly 1
-  // sector.
-  // Here for simplification reason, we specify the Data Size for
-  // "a series of read" to 1 sector (256 words) if Data Size of one ATA command
-  // request is larger than 256 words.
-  //
-  Increment = 256;
-
-  //
-  // used to record bytes of currently transfered Data
-  //
-  WordCount = 0;
-
-  while (WordCount < RShiftU64(ByteCount, 1)) {
-    //
-    // Poll DRQ bit set, Data transfer can be performed only when DRQ is ready
-    //
-    Status = DRQReady2 (IdeRegisters, Timeout);
-    if (EFI_ERROR (Status)) {
-      Status = EFI_DEVICE_ERROR;
-      goto Exit;
-    }
-
-    //
-    // Get the byte count for one series of read
-    //
-    if ((WordCount + Increment) > RShiftU64(ByteCount, 1)) {
-      Increment = (UINTN)(RShiftU64(ByteCount, 1) - WordCount);
-    }
-
-    if (Read) {
-      IdeReadPortWMultiple (
-        IdeRegisters->Data,
-        Increment,
-        Buffer16
-        );
-    } else {
-      IdeWritePortWMultiple (
-        IdeRegisters->Data,
-        Increment,
-        Buffer16
-        );
-    }
-
-    Status = CheckStatusRegister (IdeRegisters);
-    if (EFI_ERROR (Status)) {
-      Status = EFI_DEVICE_ERROR;
-      goto Exit;
-    }
-
-    WordCount += Increment;
-    Buffer16  += Increment;
-  }
-
-  Status = DRQClear (IdeRegisters, Timeout);
-  if (EFI_ERROR (Status)) {
-    Status = EFI_DEVICE_ERROR;
-    goto Exit;
-  }
-
-Exit:
-  //
-  // Dump All Ide registers to ATA_STATUS_BLOCK
-  //
-  DumpAllIdeRegisters (IdeRegisters);
-
-  return Status;
-}
-
-/**
-  Sends out an ATA Identify Command to the specified device.
-
-  This function sends out the ATA Identify Command to the
-  specified device. Only ATA device responses to this command. If
-  the command succeeds, it returns the Identify Data structure which
-  contains information about the device. This function extracts the
-  information it needs to fill the IDE_BLK_IO_DEV Data structure,
-  including device type, media block Size, media capacity, and etc.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Channel          The channel number of device.
-  @param Device           The device number of device.
-  @param Buffer           A pointer to Data Buffer which is used to contain IDENTIFY Data.
-
-  @retval EFI_SUCCESS          Identify ATA device successfully.
-  @retval EFI_DEVICE_ERROR     ATA Identify Device Command failed or device is not ATA device.
-  @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
-**/
-EFI_STATUS
-EFIAPI
-AtaIdentify (
-  IN     EFI_IDE_REGISTERS             *IdeRegisters,
-  IN     UINT8                         Channel,
-  IN     UINT8                         Device,
-  IN OUT ATA_IDENTIFY_DATA             *Buffer
-  )
-{
-  EFI_STATUS             Status;
-  EFI_ATA_COMMAND_BLOCK  AtaCommandBlock;
-
-  ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
-
-  AtaCommandBlock.AtaCommand    = ATA_CMD_IDENTIFY_DRIVE;
-  AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);
-
-  Status = AtaPioDataInOut (
-             IdeRegisters,
-             Buffer,
-             sizeof (ATA_IDENTIFY_DATA),
-             TRUE,
-             &AtaCommandBlock,
-             NULL,
-             ATA_TIMEOUT
-             );
-
-  return Status;
-}
-
-
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h
deleted file mode 100644
index ba94a9750503..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalIdeMode.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/** @file
-  Header file for IDE mode of ATA host controller.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-
-#ifndef __OPAL_PASSWORD_IDE_MODE_H__
-#define __OPAL_PASSWORD_IDE_MODE_H__
-
-typedef enum {
-  EfiIdePrimary    = 0,
-  EfiIdeSecondary  = 1,
-  EfiIdeMaxChannel = 2
-} EFI_IDE_CHANNEL;
-
-typedef enum {
-  EfiIdeMaster     = 0,
-  EfiIdeSlave      = 1,
-  EfiIdeMaxDevice  = 2
-} EFI_IDE_DEVICE;
-
-//
-// IDE registers set
-//
-typedef struct {
-  UINT16                          Data;
-  UINT16                          ErrOrFeature;
-  UINT16                          SectorCount;
-  UINT16                          SectorNumber;
-  UINT16                          CylinderLsb;
-  UINT16                          CylinderMsb;
-  UINT16                          Head;
-  UINT16                          CmdOrStatus;
-  UINT16                          AltOrDev;
-} EFI_IDE_REGISTERS;
-
-//
-// Bit definitions in Programming Interface byte of the Class Code field
-// in PCI IDE controller's Configuration Space
-//
-#define IDE_PRIMARY_OPERATING_MODE            BIT0
-#define IDE_PRIMARY_PROGRAMMABLE_INDICATOR    BIT1
-#define IDE_SECONDARY_OPERATING_MODE          BIT2
-#define IDE_SECONDARY_PROGRAMMABLE_INDICATOR  BIT3
-
-/**
-  Get IDE i/o port registers' base addresses by mode.
-
-  In 'Compatibility' mode, use fixed addresses.
-  In Native-PCI mode, get base addresses from BARs in the PCI IDE controller's
-  Configuration Space.
-
-  The steps to get IDE i/o port registers' base addresses for each channel
-  as follows:
-
-  1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
-  controller's Configuration Space to determine the operating mode.
-
-  2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
-   ___________________________________________
-  |           | Command Block | Control Block |
-  |  Channel  |   Registers   |   Registers   |
-  |___________|_______________|_______________|
-  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
-  |___________|_______________|_______________|
-  | Secondary |  170h - 177h  |  376h - 377h  |
-  |___________|_______________|_______________|
-
-  Table 1. Compatibility resource mappings
-
-  b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
-  in IDE controller's PCI Configuration Space, shown in the Table 2 below.
-   ___________________________________________________
-  |           |   Command Block   |   Control Block   |
-  |  Channel  |     Registers     |     Registers     |
-  |___________|___________________|___________________|
-  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
-  |___________|___________________|___________________|
-  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
-  |___________|___________________|___________________|
-
-  Table 2. BARs for Register Mapping
-
-  @param[in] Bus                 The bus number of ata host controller.
-  @param[in] Device              The device number of ata host controller.
-  @param[in] Function            The function number of ata host controller.
-  @param[in, out] IdeRegisters   Pointer to EFI_IDE_REGISTERS which is used to
-                                 store the IDE i/o port registers' base addresses
-
-  @retval EFI_UNSUPPORTED        Return this Value when the BARs is not IO type
-  @retval EFI_SUCCESS            Get the Base address successfully
-  @retval Other                  Read the pci configureation Data error
-
-**/
-EFI_STATUS
-EFIAPI
-GetIdeRegisterIoAddr (
-  IN     UINTN                       Bus,
-  IN     UINTN                       Device,
-  IN     UINTN                       Function,
-  IN OUT EFI_IDE_REGISTERS           *IdeRegisters
-  );
-
-/**
-  Sends out an ATA Identify Command to the specified device.
-
-  This function sends out the ATA Identify Command to the
-  specified device. Only ATA device responses to this command. If
-  the command succeeds, it returns the Identify Data structure which
-  contains information about the device. This function extracts the
-  information it needs to fill the IDE_BLK_IO_DEV Data structure,
-  including device type, media block Size, media capacity, and etc.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Channel          The channel number of device.
-  @param Device           The device number of device.
-  @param Buffer           A pointer to Data Buffer which is used to contain IDENTIFY Data.
-
-  @retval EFI_SUCCESS          Identify ATA device successfully.
-  @retval EFI_DEVICE_ERROR     ATA Identify Device Command failed or device is not ATA device.
-  @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
-**/
-EFI_STATUS
-EFIAPI
-AtaIdentify (
-  IN     EFI_IDE_REGISTERS             *IdeRegisters,
-  IN     UINT8                         Channel,
-  IN     UINT8                         Device,
-  IN OUT ATA_IDENTIFY_DATA             *Buffer
-  );
-
-/**
-  This function is used to send out ATA commands conforms to the PIO Data In Protocol.
-
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS Data structure.
-  @param Buffer           A pointer to the source Buffer for the Data.
-  @param ByteCount        The Length of  the Data.
-  @param Read             Flag used to determine the Data transfer direction.
-                          Read equals 1, means Data transferred from device to host;
-                          Read equals 0, means Data transferred from host to device.
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK Data structure.
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK Data structure.
-  @param Timeout          The time to complete the command.
-
-  @retval EFI_SUCCESS      send out the ATA command and device send required Data successfully.
-  @retval EFI_DEVICE_ERROR command sent failed.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPioDataInOut (
-  IN     EFI_IDE_REGISTERS         *IdeRegisters,
-  IN OUT VOID                      *Buffer,
-  IN     UINT64                    ByteCount,
-  IN     BOOLEAN                   Read,
-  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,
-  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,
-  IN     UINT64                    Timeout
-  );
-
-
-#endif
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.c
deleted file mode 100644
index a47d2764c31c..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.c
+++ /dev/null
@@ -1,2165 +0,0 @@
-/** @file
-  Provide functions to initialize NVME controller and perform NVME commands
-
-Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalPasswordSmm.h"
-
-
-#define ALIGN(v, a)                         (UINTN)((((v) - 1) | ((a) - 1)) + 1)
-
-///
-/// NVME Host controller registers operation
-///
-#define NVME_GET_CAP(Nvme, Cap)             NvmeMmioRead  (Cap, Nvme->Nbar + NVME_CAP_OFFSET, sizeof (NVME_CAP))
-#define NVME_GET_CC(Nvme, Cc)               NvmeMmioRead  (Cc, Nvme->Nbar + NVME_CC_OFFSET, sizeof (NVME_CC))
-#define NVME_SET_CC(Nvme, Cc)               NvmeMmioWrite (Nvme->Nbar + NVME_CC_OFFSET, Cc, sizeof (NVME_CC))
-#define NVME_GET_CSTS(Nvme, Csts)           NvmeMmioRead  (Csts, Nvme->Nbar + NVME_CSTS_OFFSET, sizeof (NVME_CSTS))
-#define NVME_GET_AQA(Nvme, Aqa)             NvmeMmioRead  (Aqa, Nvme->Nbar + NVME_AQA_OFFSET, sizeof (NVME_AQA))
-#define NVME_SET_AQA(Nvme, Aqa)             NvmeMmioWrite (Nvme->Nbar + NVME_AQA_OFFSET, Aqa, sizeof (NVME_AQA))
-#define NVME_GET_ASQ(Nvme, Asq)             NvmeMmioRead  (Asq, Nvme->Nbar + NVME_ASQ_OFFSET, sizeof (NVME_ASQ))
-#define NVME_SET_ASQ(Nvme, Asq)             NvmeMmioWrite (Nvme->Nbar + NVME_ASQ_OFFSET, Asq, sizeof (NVME_ASQ))
-#define NVME_GET_ACQ(Nvme, Acq)             NvmeMmioRead  (Acq, Nvme->Nbar + NVME_ACQ_OFFSET, sizeof (NVME_ACQ))
-#define NVME_SET_ACQ(Nvme, Acq)             NvmeMmioWrite (Nvme->Nbar + NVME_ACQ_OFFSET, Acq, sizeof (NVME_ACQ))
-#define NVME_GET_VER(Nvme, Ver)             NvmeMmioRead  (Ver, Nvme->Nbar + NVME_VER_OFFSET, sizeof (NVME_VER))
-#define NVME_SET_SQTDBL(Nvme, Qid, Sqtdbl)  NvmeMmioWrite (Nvme->Nbar + NVME_SQTDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Sqtdbl, sizeof (NVME_SQTDBL))
-#define NVME_SET_CQHDBL(Nvme, Qid, Cqhdbl)  NvmeMmioWrite (Nvme->Nbar + NVME_CQHDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Cqhdbl, sizeof (NVME_CQHDBL))
-
-///
-/// Base memory address
-///
-enum {
-  BASEMEM_CONTROLLER_DATA,
-  BASEMEM_IDENTIFY_DATA,
-  BASEMEM_ASQ,
-  BASEMEM_ACQ,
-  BASEMEM_SQ,
-  BASEMEM_CQ,
-  BASEMEM_PRP,
-  BASEMEM_SECURITY,
-  MAX_BASEMEM_COUNT
-};
-
-///
-/// All of base memories are 4K(0x1000) alignment
-///
-#define NVME_MEM_BASE(Nvme)                 ((UINTN)(Nvme->BaseMem))
-#define NVME_CONTROL_DATA_BASE(Nvme)        (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CONTROLLER_DATA))                        * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_NAMESPACE_DATA_BASE(Nvme)      (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_IDENTIFY_DATA))                          * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_ASQ_BASE(Nvme)                 (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ASQ))                                    * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_ACQ_BASE(Nvme)                 (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ACQ))                                    * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_SQ_BASE(Nvme, index)           (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SQ) + ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_CQ_BASE(Nvme, index)           (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CQ) + ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_PRP_BASE(Nvme, index)          (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_PRP) + ((index)*NVME_PRP_SIZE))          * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-#define NVME_SEC_BASE(Nvme)                 (ALIGN (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SECURITY))                               * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
-
-/**
-  Transfer MMIO Data to memory.
-
-  @param[in,out] MemBuffer - Destination: Memory address
-  @param[in] MmioAddr      - Source: MMIO address
-  @param[in] Size          - Size for read
-
-  @retval EFI_SUCCESS - MMIO read sucessfully
-**/
-EFI_STATUS
-NvmeMmioRead (
-  IN OUT VOID *MemBuffer,
-  IN     UINTN MmioAddr,
-  IN     UINTN Size
-  )
-{
-  UINTN  Offset;
-  UINT8  Data;
-  UINT8  *Ptr;
-
-  // priority has adjusted
-  switch (Size) {
-    case 4:
-      *((UINT32 *)MemBuffer) = MmioRead32 (MmioAddr);
-      break;
-
-    case 8:
-      *((UINT64 *)MemBuffer) = MmioRead64 (MmioAddr);
-      break;
-
-    case 2:
-      *((UINT16 *)MemBuffer) = MmioRead16 (MmioAddr);
-      break;
-
-    case 1:
-      *((UINT8 *)MemBuffer) = MmioRead8 (MmioAddr);
-      break;
-
-    default:
-      Ptr = (UINT8 *)MemBuffer;
-      for (Offset = 0; Offset < Size; Offset += 1) {
-        Data = MmioRead8 (MmioAddr + Offset);
-        Ptr[Offset] = Data;
-      }
-      break;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Transfer memory data to MMIO.
-
-  @param[in,out] MmioAddr - Destination: MMIO address
-  @param[in] MemBuffer    - Source: Memory address
-  @param[in] Size         - Size for write
-
-  @retval EFI_SUCCESS - MMIO write sucessfully
-**/
-EFI_STATUS
-NvmeMmioWrite (
-  IN OUT UINTN MmioAddr,
-  IN     VOID *MemBuffer,
-  IN     UINTN Size
-  )
-{
-  UINTN  Offset;
-  UINT8  Data;
-  UINT8  *Ptr;
-
-  // priority has adjusted
-  switch (Size) {
-    case 4:
-      MmioWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
-      break;
-
-    case 8:
-      MmioWrite64 (MmioAddr, *((UINT64 *)MemBuffer));
-      break;
-
-    case 2:
-      MmioWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
-      break;
-
-    case 1:
-      MmioWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
-      break;
-
-    default:
-      Ptr = (UINT8 *)MemBuffer;
-      for (Offset = 0; Offset < Size; Offset += 1) {
-        Data = Ptr[Offset];
-        MmioWrite8 (MmioAddr + Offset, Data);
-      }
-      break;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Transfer MMIO data to memory.
-
-  @param[in,out] MemBuffer - Destination: Memory address
-  @param[in] MmioAddr      - Source: MMIO address
-  @param[in] Size          - Size for read
-
-  @retval EFI_SUCCESS - MMIO read sucessfully
-**/
-EFI_STATUS
-OpalPciRead (
-  IN OUT VOID *MemBuffer,
-  IN     UINTN MmioAddr,
-  IN     UINTN Size
-  )
-{
-  UINTN  Offset;
-  UINT8  Data;
-  UINT8  *Ptr;
-
-  // priority has adjusted
-  switch (Size) {
-    case 4:
-      *((UINT32 *)MemBuffer) = PciRead32 (MmioAddr);
-      break;
-
-    case 2:
-      *((UINT16 *)MemBuffer) = PciRead16 (MmioAddr);
-      break;
-
-    case 1:
-      *((UINT8 *)MemBuffer) = PciRead8 (MmioAddr);
-      break;
-
-    default:
-      Ptr = (UINT8 *)MemBuffer;
-      for (Offset = 0; Offset < Size; Offset += 1) {
-        Data = PciRead8 (MmioAddr + Offset);
-        Ptr[Offset] = Data;
-      }
-      break;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Transfer memory data to MMIO.
-
-  @param[in,out] MmioAddr - Destination: MMIO address
-  @param[in] MemBuffer    - Source: Memory address
-  @param[in] Size         - Size for write
-
-  @retval EFI_SUCCESS - MMIO write sucessfully
-**/
-EFI_STATUS
-OpalPciWrite (
-  IN OUT UINTN MmioAddr,
-  IN     VOID *MemBuffer,
-  IN     UINTN Size
-  )
-{
-  UINTN  Offset;
-  UINT8  Data;
-  UINT8  *Ptr;
-
-  // priority has adjusted
-  switch (Size) {
-    case 4:
-      PciWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
-      break;
-
-    case 2:
-      PciWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
-      break;
-
-    case 1:
-      PciWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
-      break;
-
-    default:
-      Ptr = (UINT8 *)MemBuffer;
-      for (Offset = 0; Offset < Size; Offset += 1) {
-        Data = Ptr[Offset];
-        PciWrite8 (MmioAddr + Offset, Data);
-      }
-      break;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Get total pages for specific NVME based memory.
-
-  @param[in] BaseMemIndex           - The Index of BaseMem (0-based).
-
-  @retval - The page count for specific BaseMem Index
-
-**/
-UINT32
-NvmeGetBaseMemPages (
-  IN UINTN              BaseMemIndex
-  )
-{
-  UINT32                Pages;
-  UINTN                 Index;
-  UINT32                PageSizeList[8];
-
-  PageSizeList[0] = 1;  /* Controller Data */
-  PageSizeList[1] = 1;  /* Identify Data */
-  PageSizeList[2] = 1;  /* ASQ */
-  PageSizeList[3] = 1;  /* ACQ */
-  PageSizeList[4] = 1;  /* SQs */
-  PageSizeList[5] = 1;  /* CQs */
-  PageSizeList[6] = NVME_PRP_SIZE * NVME_CSQ_DEPTH;  /* PRPs */
-  PageSizeList[7] = 1;  /* Security Commands */
-
-  if (BaseMemIndex > MAX_BASEMEM_COUNT) {
-    ASSERT (FALSE);
-    return 0;
-  }
-
-  Pages = 0;
-  for (Index = 0; Index < BaseMemIndex; Index++) {
-    Pages += PageSizeList[Index];
-  }
-
-  return Pages;
-}
-
-/**
-  Wait for NVME controller status to be ready or not.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] WaitReady              - Flag for waitting status ready or not
-
-  @return EFI_SUCCESS               - Successfully to wait specific status.
-  @return others                    - Fail to wait for specific controller status.
-
-**/
-STATIC
-EFI_STATUS
-NvmeWaitController (
-  IN NVME_CONTEXT       *Nvme,
-  IN BOOLEAN            WaitReady
-  )
-{
-  NVME_CSTS              Csts;
-  EFI_STATUS             Status;
-  UINT32                 Index;
-  UINT8                  Timeout;
-
-  //
-  // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
-  // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
-  //
-  if (Nvme->Cap.To == 0) {
-    Timeout = 1;
-  } else {
-    Timeout = Nvme->Cap.To;
-  }
-
-  Status = EFI_SUCCESS;
-  for(Index = (Timeout * 500); Index != 0; --Index) {
-    MicroSecondDelay (1000);
-
-    //
-    // Check if the controller is initialized
-    //
-    Status = NVME_GET_CSTS (Nvme, &Csts);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n", Status));
-      return Status;
-    }
-
-    if ((BOOLEAN) Csts.Rdy == WaitReady) {
-      break;
-    }
-  }
-
-  if (Index == 0) {
-    Status = EFI_TIMEOUT;
-  }
-
-  return Status;
-}
-
-/**
-  Disable the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully disable the controller.
-  @return others                    - Fail to disable the controller.
-
-**/
-STATIC
-EFI_STATUS
-NvmeDisableController (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  NVME_CC                Cc;
-  NVME_CSTS              Csts;
-  EFI_STATUS             Status;
-
-  Status = NVME_GET_CSTS (Nvme, &Csts);
-
-  ///
-  /// Read Controller Configuration Register.
-  ///
-  Status = NVME_GET_CC (Nvme, &Cc);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
-    goto Done;
-  }
-
-  if (Cc.En == 1) {
-    Cc.En = 0;
-    ///
-    /// Disable the controller.
-    ///
-    Status = NVME_SET_CC (Nvme, &Cc);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
-      goto Done;
-    }
-  }
-
-  Status = NvmeWaitController (Nvme, FALSE);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n", Status));
-    goto Done;
-  }
-
-  return EFI_SUCCESS;
-
-Done:
-  DEBUG ((DEBUG_INFO, "NvmeDisableController fail, Status: %r\n", Status));
-  return Status;
-}
-
-/**
-  Enable the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully enable the controller.
-  @return EFI_DEVICE_ERROR          - Fail to enable the controller.
-  @return EFI_TIMEOUT               - Fail to enable the controller in given time slot.
-
-**/
-STATIC
-EFI_STATUS
-NvmeEnableController (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  NVME_CC                Cc;
-  EFI_STATUS             Status;
-
-  //
-  // Enable the controller
-  //
-  ZeroMem (&Cc, sizeof (NVME_CC));
-  Cc.En     = 1;
-  Cc.Iosqes = 6;
-  Cc.Iocqes = 4;
-  Status    = NVME_SET_CC (Nvme, &Cc);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
-    goto Done;
-  }
-
-  Status = NvmeWaitController (Nvme, TRUE);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n", Status));
-    goto Done;
-  }
-
-  return EFI_SUCCESS;
-
-Done:
-  DEBUG ((DEBUG_INFO, "NvmeEnableController fail, Status: %r\n", Status));
-  return Status;
-}
-
-/**
-  Shutdown the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully shutdown the controller.
-  @return EFI_DEVICE_ERROR          - Fail to shutdown the controller.
-  @return EFI_TIMEOUT               - Fail to shutdown the controller in given time slot.
-
-**/
-STATIC
-EFI_STATUS
-NvmeShutdownController (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  NVME_CC                Cc;
-  NVME_CSTS              Csts;
-  EFI_STATUS             Status;
-  UINT32                 Index;
-  UINTN                  Timeout;
-
-  Status    = NVME_GET_CC (Nvme, &Cc);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
-    return Status;
-  }
-
-  Cc.Shn     = 1; // Normal shutdown
-
-  Status    = NVME_SET_CC (Nvme, &Cc);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
-    return Status;
-  }
-
-  Timeout = NVME_GENERIC_TIMEOUT/1000; // ms
-  for(Index = (UINT32)(Timeout); Index != 0; --Index) {
-    MicroSecondDelay (1000);
-
-    Status = NVME_GET_CSTS (Nvme, &Csts);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n", Status));
-      return Status;
-    }
-
-    if (Csts.Shst == 2) { // Shutdown processing complete
-      break;
-    }
-  }
-
-  if (Index == 0) {
-    Status = EFI_TIMEOUT;
-  }
-
-  return Status;
-}
-
-/**
-  Check the execution status from a given completion queue entry.
-
-  @param[in]     Cq                 - A pointer to the NVME_CQ item.
-
-**/
-EFI_STATUS
-NvmeCheckCqStatus (
-  IN NVME_CQ             *Cq
-  )
-{
-  if (Cq->Sct == 0x0 && Cq->Sc == 0x0) {
-    return EFI_SUCCESS;
-  }
-
-  DEBUG ((DEBUG_INFO, "Dump NVMe Completion Entry Status from [0x%x]:\n", (UINTN)Cq));
-  DEBUG ((DEBUG_INFO, "  SQ Identifier : [0x%x], Phase Tag : [%d], Cmd Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
-  DEBUG ((DEBUG_INFO, "  NVMe Cmd Execution Result - "));
-
-  switch (Cq->Sct) {
-    case 0x0:
-      switch (Cq->Sc) {
-        case 0x0:
-          DEBUG ((DEBUG_INFO, "Successful Completion\n"));
-          return EFI_SUCCESS;
-        case 0x1:
-          DEBUG ((DEBUG_INFO, "Invalid Command Opcode\n"));
-          break;
-        case 0x2:
-          DEBUG ((DEBUG_INFO, "Invalid Field in Command\n"));
-          break;
-        case 0x3:
-          DEBUG ((DEBUG_INFO, "Command ID Conflict\n"));
-          break;
-        case 0x4:
-          DEBUG ((DEBUG_INFO, "Data Transfer Error\n"));
-          break;
-        case 0x5:
-          DEBUG ((DEBUG_INFO, "Commands Aborted due to Power Loss Notification\n"));
-          break;
-        case 0x6:
-          DEBUG ((DEBUG_INFO, "Internal Device Error\n"));
-          break;
-        case 0x7:
-          DEBUG ((DEBUG_INFO, "Command Abort Requested\n"));
-          break;
-        case 0x8:
-          DEBUG ((DEBUG_INFO, "Command Aborted due to SQ Deletion\n"));
-          break;
-        case 0x9:
-          DEBUG ((DEBUG_INFO, "Command Aborted due to Failed Fused Command\n"));
-          break;
-        case 0xA:
-          DEBUG ((DEBUG_INFO, "Command Aborted due to Missing Fused Command\n"));
-          break;
-        case 0xB:
-          DEBUG ((DEBUG_INFO, "Invalid Namespace or Format\n"));
-          break;
-        case 0xC:
-          DEBUG ((DEBUG_INFO, "Command Sequence Error\n"));
-          break;
-        case 0xD:
-          DEBUG ((DEBUG_INFO, "Invalid SGL Last Segment Descriptor\n"));
-          break;
-        case 0xE:
-          DEBUG ((DEBUG_INFO, "Invalid Number of SGL Descriptors\n"));
-          break;
-        case 0xF:
-          DEBUG ((DEBUG_INFO, "Data SGL Length Invalid\n"));
-          break;
-        case 0x10:
-          DEBUG ((DEBUG_INFO, "Metadata SGL Length Invalid\n"));
-          break;
-        case 0x11:
-          DEBUG ((DEBUG_INFO, "SGL Descriptor Type Invalid\n"));
-          break;
-        case 0x80:
-          DEBUG ((DEBUG_INFO, "LBA Out of Range\n"));
-          break;
-        case 0x81:
-          DEBUG ((DEBUG_INFO, "Capacity Exceeded\n"));
-          break;
-        case 0x82:
-          DEBUG ((DEBUG_INFO, "Namespace Not Ready\n"));
-          break;
-        case 0x83:
-          DEBUG ((DEBUG_INFO, "Reservation Conflict\n"));
-          break;
-      }
-      break;
-
-    case 0x1:
-      switch (Cq->Sc) {
-        case 0x0:
-          DEBUG ((DEBUG_INFO, "Completion Queue Invalid\n"));
-          break;
-        case 0x1:
-          DEBUG ((DEBUG_INFO, "Invalid Queue Identifier\n"));
-          break;
-        case 0x2:
-          DEBUG ((DEBUG_INFO, "Maximum Queue Size Exceeded\n"));
-          break;
-        case 0x3:
-          DEBUG ((DEBUG_INFO, "Abort Command Limit Exceeded\n"));
-          break;
-        case 0x5:
-          DEBUG ((DEBUG_INFO, "Asynchronous Event Request Limit Exceeded\n"));
-          break;
-        case 0x6:
-          DEBUG ((DEBUG_INFO, "Invalid Firmware Slot\n"));
-          break;
-        case 0x7:
-          DEBUG ((DEBUG_INFO, "Invalid Firmware Image\n"));
-          break;
-        case 0x8:
-          DEBUG ((DEBUG_INFO, "Invalid Interrupt Vector\n"));
-          break;
-        case 0x9:
-          DEBUG ((DEBUG_INFO, "Invalid Log Page\n"));
-          break;
-        case 0xA:
-          DEBUG ((DEBUG_INFO, "Invalid Format\n"));
-          break;
-        case 0xB:
-          DEBUG ((DEBUG_INFO, "Firmware Application Requires Conventional Reset\n"));
-          break;
-        case 0xC:
-          DEBUG ((DEBUG_INFO, "Invalid Queue Deletion\n"));
-          break;
-        case 0xD:
-          DEBUG ((DEBUG_INFO, "Feature Identifier Not Saveable\n"));
-          break;
-        case 0xE:
-          DEBUG ((DEBUG_INFO, "Feature Not Changeable\n"));
-          break;
-        case 0xF:
-          DEBUG ((DEBUG_INFO, "Feature Not Namespace Specific\n"));
-          break;
-        case 0x10:
-          DEBUG ((DEBUG_INFO, "Firmware Application Requires NVM Subsystem Reset\n"));
-          break;
-        case 0x80:
-          DEBUG ((DEBUG_INFO, "Conflicting Attributes\n"));
-          break;
-        case 0x81:
-          DEBUG ((DEBUG_INFO, "Invalid Protection Information\n"));
-          break;
-        case 0x82:
-          DEBUG ((DEBUG_INFO, "Attempted Write to Read Only Range\n"));
-          break;
-      }
-      break;
-
-    case 0x2:
-      switch (Cq->Sc) {
-        case 0x80:
-          DEBUG ((DEBUG_INFO, "Write Fault\n"));
-          break;
-        case 0x81:
-          DEBUG ((DEBUG_INFO, "Unrecovered Read Error\n"));
-          break;
-        case 0x82:
-          DEBUG ((DEBUG_INFO, "End-to-end Guard Check Error\n"));
-          break;
-        case 0x83:
-          DEBUG ((DEBUG_INFO, "End-to-end Application Tag Check Error\n"));
-          break;
-        case 0x84:
-          DEBUG ((DEBUG_INFO, "End-to-end Reference Tag Check Error\n"));
-          break;
-        case 0x85:
-          DEBUG ((DEBUG_INFO, "Compare Failure\n"));
-          break;
-        case 0x86:
-          DEBUG ((DEBUG_INFO, "Access Denied\n"));
-          break;
-      }
-      break;
-
-    default:
-      DEBUG ((DEBUG_INFO, "Unknown error\n"));
-      break;
-  }
-
-  return EFI_DEVICE_ERROR;
-}
-
-/**
-  Create PRP lists for Data transfer which is larger than 2 memory pages.
-  Note here we calcuate the number of required PRP lists and allocate them at one time.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] SqId                   - The SQ index for this PRP
-  @param[in] PhysicalAddr           - The physical base address of Data Buffer.
-  @param[in] Pages                  - The number of pages to be transfered.
-  @param[out] PrpListHost           - The host base address of PRP lists.
-  @param[in,out] PrpListNo          - The number of PRP List.
-
-  @retval The pointer Value to the first PRP List of the PRP lists.
-
-**/
-STATIC
-UINT64
-NvmeCreatePrpList (
-  IN     NVME_CONTEXT                 *Nvme,
-  IN     UINT16                       SqId,
-  IN     EFI_PHYSICAL_ADDRESS         PhysicalAddr,
-  IN     UINTN                        Pages,
-     OUT VOID                         **PrpListHost,
-  IN OUT UINTN                        *PrpListNo
-  )
-{
-  UINTN                       PrpEntryNo;
-  UINT64                      PrpListBase;
-  UINTN                       PrpListIndex;
-  UINTN                       PrpEntryIndex;
-  UINT64                      Remainder;
-  EFI_PHYSICAL_ADDRESS        PrpListPhyAddr;
-  UINTN                       Bytes;
-  UINT8                       *PrpEntry;
-  EFI_PHYSICAL_ADDRESS        NewPhyAddr;
-
-  ///
-  /// The number of Prp Entry in a memory page.
-  ///
-  PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
-
-  ///
-  /// Calculate total PrpList number.
-  ///
-  *PrpListNo = (UINTN) DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo, &Remainder);
-  if (Remainder != 0) {
-    *PrpListNo += 1;
-  }
-
-  if (*PrpListNo > NVME_PRP_SIZE) {
-    DEBUG ((DEBUG_INFO, "NvmeCreatePrpList (PhysicalAddr: %lx, Pages: %x) PrpEntryNo: %x\n",
-      PhysicalAddr, Pages, PrpEntryNo));
-    DEBUG ((DEBUG_INFO, "*PrpListNo: %x, Remainder: %lx", *PrpListNo, Remainder));
-    ASSERT (FALSE);
-  }
-  *PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Nvme, SqId);
-
-  Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
-  PrpListPhyAddr = (UINT64)(UINTN)(*PrpListHost);
-
-  ///
-  /// Fill all PRP lists except of last one.
-  ///
-  ZeroMem (*PrpListHost, Bytes);
-  for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
-    PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
-
-    for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
-      PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64));
-      if (PrpEntryIndex != PrpEntryNo - 1) {
-        ///
-        /// Fill all PRP entries except of last one.
-        ///
-        CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
-        PhysicalAddr += EFI_PAGE_SIZE;
-      } else {
-        ///
-        /// Fill last PRP entries with next PRP List pointer.
-        ///
-        NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE);
-        CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof (UINT64));
-      }
-    }
-  }
-
-  ///
-  /// Fill last PRP list.
-  ///
-  PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
-  for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder : PrpEntryNo); ++PrpEntryIndex) {
-    PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64));
-    CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
-
-    PhysicalAddr += EFI_PAGE_SIZE;
-  }
-
-  return PrpListPhyAddr;
-}
-
-/**
-  Check whether there are available command slots.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Qid                    - Queue index
-
-  @retval EFI_SUCCESS               - Available command slot is found
-  @retval EFI_NOT_READY             - No available command slot is found
-  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
-
-**/
-EFI_STATUS
-NvmeHasFreeCmdSlot (
-  IN NVME_CONTEXT       *Nvme,
-  IN UINT8              Qid
-  )
-{
-  return TRUE;
-}
-
-/**
-  Check whether all command slots are clean.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Qid                    - Queue index
-
-  @retval EFI_SUCCESS               - All command slots are clean
-  @retval EFI_NOT_READY             - Not all command slots are clean
-  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
-
-**/
-EFI_STATUS
-NvmeIsAllCmdSlotClean (
-  IN NVME_CONTEXT       *Nvme,
-  IN UINT8              Qid
-  )
-{
-  return EFI_SUCCESS;
-}
-
-/**
-  Waits until all NVME commands completed.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Qid                    - Queue index
-
-  @retval EFI_SUCCESS               - All NVME commands have completed
-  @retval EFI_TIMEOUT               - Timeout occured
-  @retval EFI_NOT_READY             - Not all NVME commands have completed
-  @retval others                    - Error occurred on device side.
-**/
-EFI_STATUS
-NvmeWaitAllComplete (
-  IN NVME_CONTEXT       *Nvme,
-  IN UINT8              Qid
-  )
-{
-  return EFI_SUCCESS;
-}
-
-/**
-  Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
-  both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
-  I/O functionality is optional.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
-                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
-                                      ID specifies that the command packet should be sent to all valid namespaces.
-  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
-                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
-                                      UUID specifies that the command packet should be sent to all valid namespaces.
-  @param[in,out] Packet             - A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
-                                      by NamespaceId.
-
-  @retval EFI_SUCCESS               - The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
-                                      to, or from DataBuffer.
-  @retval EFI_NOT_READY             - The NVM Express Command Packet could not be sent because the controller is not ready. The caller
-                                      may retry again later.
-  @retval EFI_DEVICE_ERROR          - A device error occurred while attempting to send the NVM Express Command Packet.
-  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
-                                      Express Command Packet was not sent, so no additional status information is available.
-  @retval EFI_UNSUPPORTED           - The command described by the NVM Express Command Packet is not supported by the host adapter.
-                                      The NVM Express Command Packet was not sent, so no additional status information is available.
-  @retval EFI_TIMEOUT               - A timeout occurred while waiting for the NVM Express Command Packet to execute.
-
-**/
-EFI_STATUS
-NvmePassThru (
-  IN     NVME_CONTEXT                         *Nvme,
-  IN     UINT32                               NamespaceId,
-  IN     UINT64                               NamespaceUuid,
-  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
-  )
-{
-  EFI_STATUS                    Status;
-  NVME_SQ                       *Sq;
-  NVME_CQ                       *Cq;
-  UINT8                         Qid;
-  UINT32                        Bytes;
-  UINT32                        Offset;
-  EFI_PHYSICAL_ADDRESS          PhyAddr;
-  VOID                          *PrpListHost;
-  UINTN                         PrpListNo;
-  UINT32                        Timer;
-  UINTN SqSize;
-  UINTN CqSize;
-
-  ///
-  /// check the Data fields in Packet parameter.
-  ///
-  if ((Nvme == NULL) || (Packet == NULL)) {
-    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter: Nvme(%x)/Packet(%x)\n",
-      (UINTN)Nvme, (UINTN)Packet));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((Packet->NvmeCmd == NULL) || (Packet->NvmeResponse == NULL)) {
-    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter: NvmeCmd(%x)/NvmeResponse(%x)\n",
-      (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeResponse));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (Packet->QueueId != NVME_ADMIN_QUEUE && Packet->QueueId != NVME_IO_QUEUE) {
-    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter: QueueId(%x)\n",
-      Packet->QueueId));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  PrpListHost = NULL;
-  PrpListNo   = 0;
-  Status      = EFI_SUCCESS;
-
-  Qid = Packet->QueueId;
-  Sq  = Nvme->SqBuffer[Qid] + Nvme->SqTdbl[Qid].Sqt;
-  Cq  = Nvme->CqBuffer[Qid] + Nvme->CqHdbl[Qid].Cqh;
-  if (Qid == NVME_ADMIN_QUEUE) {
-    SqSize = NVME_ASQ_SIZE + 1;
-    CqSize = NVME_ACQ_SIZE + 1;
-  } else {
-    SqSize = NVME_CSQ_DEPTH;
-    CqSize = NVME_CCQ_DEPTH;
-  }
-
-  if (Packet->NvmeCmd->Nsid != NamespaceId) {
-    DEBUG ((DEBUG_ERROR, "NvmePassThru: Nsid mismatch (%x, %x)\n",
-      Packet->NvmeCmd->Nsid, NamespaceId));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ZeroMem (Sq, sizeof (NVME_SQ));
-  Sq->Opc  = Packet->NvmeCmd->Cdw0.Opcode;
-  Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation;
-  Sq->Cid  = Packet->NvmeCmd->Cdw0.Cid;
-  Sq->Nsid = Packet->NvmeCmd->Nsid;
-
-  ///
-  /// Currently we only support PRP for Data transfer, SGL is NOT supported.
-  ///
-  ASSERT (Sq->Psdt == 0);
-  if (Sq->Psdt != 0) {
-    DEBUG ((DEBUG_ERROR, "NvmePassThru: doesn't support SGL mechanism\n"));
-    return EFI_UNSUPPORTED;
-  }
-
-  Sq->Prp[0] = Packet->TransferBuffer;
-  Sq->Prp[1] = 0;
-
-  if(Packet->MetadataBuffer != (UINT64)(UINTN)NULL) {
-    Sq->Mptr = Packet->MetadataBuffer;
-  }
-
-  ///
-  /// If the Buffer Size spans more than two memory pages (page Size as defined in CC.Mps),
-  /// then build a PRP list in the second PRP submission queue entry.
-  ///
-  Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
-  Bytes  = Packet->TransferLength;
-
-  if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
-    ///
-    /// Create PrpList for remaining Data Buffer.
-    ///
-    PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
-    Sq->Prp[1] = NvmeCreatePrpList (Nvme, Nvme->SqTdbl[Qid].Sqt, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo);
-    if (Sq->Prp[1] == 0) {
-      Status = EFI_OUT_OF_RESOURCES;
-      DEBUG ((DEBUG_ERROR, "NvmeCreatePrpList fail, Status: %r\n", Status));
-      goto EXIT;
-    }
-
-  } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
-    Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
-  }
-
-  if(Packet->NvmeCmd->Flags & CDW10_VALID) {
-    Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
-  }
-  if(Packet->NvmeCmd->Flags & CDW11_VALID) {
-    Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
-  }
-  if(Packet->NvmeCmd->Flags & CDW12_VALID) {
-    Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
-  }
-  if(Packet->NvmeCmd->Flags & CDW13_VALID) {
-    Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
-  }
-  if(Packet->NvmeCmd->Flags & CDW14_VALID) {
-    Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
-  }
-  if(Packet->NvmeCmd->Flags & CDW15_VALID) {
-    Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
-  }
-
-  ///
-  /// Ring the submission queue doorbell.
-  ///
-  Nvme->SqTdbl[Qid].Sqt++;
-  if(Nvme->SqTdbl[Qid].Sqt == SqSize) {
-    Nvme->SqTdbl[Qid].Sqt = 0;
-  }
-  Status = NVME_SET_SQTDBL (Nvme, Qid, &Nvme->SqTdbl[Qid]);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NVME_SET_SQTDBL fail, Status: %r\n", Status));
-    goto EXIT;
-  }
-
-  ///
-  /// Wait for completion queue to get filled in.
-  ///
-  Status = EFI_TIMEOUT;
-  Timer   = 0;
-  while (Timer < NVME_CMD_TIMEOUT) {
-    //DEBUG ((DEBUG_VERBOSE, "Timer: %x, Cq:\n", Timer));
-    //DumpMem (Cq, sizeof (NVME_CQ));
-    if (Cq->Pt != Nvme->Pt[Qid]) {
-      Status = EFI_SUCCESS;
-      break;
-    }
-
-    MicroSecondDelay (NVME_CMD_WAIT);
-    Timer += NVME_CMD_WAIT;
-  }
-
-  Nvme->CqHdbl[Qid].Cqh++;
-  if (Nvme->CqHdbl[Qid].Cqh == CqSize) {
-    Nvme->CqHdbl[Qid].Cqh = 0;
-    Nvme->Pt[Qid] ^= 1;
-  }
-
-  ///
-  /// Copy the Respose Queue entry for this command to the callers response Buffer
-  ///
-  CopyMem (Packet->NvmeResponse, Cq, sizeof(NVM_EXPRESS_RESPONSE));
-
-  if (!EFI_ERROR(Status)) { // We still need to check CQ status if no timeout error occured
-    Status = NvmeCheckCqStatus (Cq);
-  }
-  NVME_SET_CQHDBL (Nvme, Qid, &Nvme->CqHdbl[Qid]);
-
-EXIT:
-  return Status;
-}
-
-/**
-  Get identify controller Data.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Buffer                 - The Buffer used to store the identify controller Data.
-
-  @return EFI_SUCCESS               - Successfully get the identify controller Data.
-  @return others                    - Fail to get the identify controller Data.
-
-**/
-STATIC
-EFI_STATUS
-NvmeIdentifyController (
-  IN NVME_CONTEXT                          *Nvme,
-  IN VOID                                  *Buffer
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-
-  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  //
-  // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
-  // For the Identify command, the Namespace Identifier is only used for the Namespace Data structure.
-  //
-  Command.Nsid        = 0;
-
-  CommandPacket.NvmeCmd        = &Command;
-  CommandPacket.NvmeResponse   = &Response;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
-  CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA);
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-  //
-  // Set bit 0 (Cns bit) to 1 to identify a controller
-  //
-  Command.Cdw10                = 1;
-  Command.Flags                = CDW10_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NVME_CONTROLLER_ID,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Get specified identify namespace Data.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] NamespaceId            - The specified namespace identifier.
-  @param[in] Buffer                 - The Buffer used to store the identify namespace Data.
-
-  @return EFI_SUCCESS               - Successfully get the identify namespace Data.
-  @return others                    - Fail to get the identify namespace Data.
-
-**/
-STATIC
-EFI_STATUS
-NvmeIdentifyNamespace (
-  IN NVME_CONTEXT                          *Nvme,
-  IN UINT32                                NamespaceId,
-  IN VOID                                  *Buffer
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  Command.Nsid        = NamespaceId;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
-  CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-  //
-  // Set bit 0 (Cns bit) to 1 to identify a namespace
-  //
-  CommandPacket.NvmeCmd->Cdw10 = 0;
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NamespaceId,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Get Block Size for specific namespace of NVME.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return                           - Block Size in bytes
-
-**/
-STATIC
-UINT32
-NvmeGetBlockSize (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  UINT32                BlockSize;
-  UINT32                Lbads;
-  UINT32                Flbas;
-  UINT32                LbaFmtIdx;
-
-  Flbas     = Nvme->NamespaceData->Flbas;
-  LbaFmtIdx = Flbas & 3;
-  Lbads     = Nvme->NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
-
-  BlockSize = (UINT32)1 << Lbads;
-  return BlockSize;
-}
-
-/**
-  Get last LBA for specific namespace of NVME.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return                           - Last LBA address
-
-**/
-STATIC
-EFI_LBA
-NvmeGetLastLba (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  EFI_LBA               LastBlock;
-  LastBlock = Nvme->NamespaceData->Nsze - 1;
-  return LastBlock;
-}
-
-/**
-  Create io completion queue.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully create io completion queue.
-  @return others                    - Fail to create io completion queue.
-
-**/
-STATIC
-EFI_STATUS
-NvmeCreateIoCompletionQueue (
-  IN     NVME_CONTEXT                      *Nvme
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  NVME_ADMIN_CRIOCQ                        CrIoCq;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-  ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
-  CommandPacket.TransferLength = EFI_PAGE_SIZE;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-
-  CrIoCq.Qid   = NVME_IO_QUEUE;
-  CrIoCq.Qsize = NVME_CCQ_SIZE;
-  CrIoCq.Pc    = 1;
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NVME_CONTROLLER_ID,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Create io submission queue.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully create io submission queue.
-  @return others                    - Fail to create io submission queue.
-
-**/
-STATIC
-EFI_STATUS
-NvmeCreateIoSubmissionQueue (
-  IN NVME_CONTEXT                          *Nvme
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  NVME_ADMIN_CRIOSQ                        CrIoSq;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-  ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
-  CommandPacket.TransferLength = EFI_PAGE_SIZE;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-
-  CrIoSq.Qid   = NVME_IO_QUEUE;
-  CrIoSq.Qsize = NVME_CSQ_SIZE;
-  CrIoSq.Pc    = 1;
-  CrIoSq.Cqid  = NVME_IO_QUEUE;
-  CrIoSq.Qprio = 0;
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NVME_CONTROLLER_ID,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Security send and receive commands.
-
-  @param[in]     Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in]     SendCommand            - The flag to indicate the command type, TRUE for Send command and FALSE for receive command
-  @param[in]     SecurityProtocol       - Security Protocol
-  @param[in]     SpSpecific             - Security Protocol Specific
-  @param[in]     TransferLength         - Transfer Length of Buffer (in bytes) - always a multiple of 512
-  @param[in,out] TransferBuffer         - Address of Data to transfer
-
-  @return EFI_SUCCESS               - Successfully create io submission queue.
-  @return others                    - Fail to send/receive commands.
-
-**/
-EFI_STATUS
-NvmeSecuritySendReceive (
-  IN NVME_CONTEXT                          *Nvme,
-  IN BOOLEAN                               SendCommand,
-  IN UINT8                                 SecurityProtocol,
-  IN UINT16                                SpSpecific,
-  IN UINTN                                 TransferLength,
-  IN OUT VOID                              *TransferBuffer
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  NVME_ADMIN_SECSEND                       SecSend;
-  OACS                                     *Oacs;
-  UINT8                                    Opcode;
-  VOID*                                    *SecBuff;
-
-  Oacs = (OACS *)&Nvme->ControllerData->Oacs;
-
-  //
-  // Verify security bit for Security Send/Receive commands
-  //
-  if (Oacs->Security == 0) {
-    DEBUG ((DEBUG_ERROR, "Security command doesn't support.\n"));
-    return EFI_NOT_READY;
-  }
-
-  SecBuff = (VOID *)(UINTN) NVME_SEC_BASE (Nvme);
-
-  //
-  // Actions for sending security command
-  //
-  if (SendCommand) {
-    CopyMem (SecBuff, TransferBuffer, TransferLength);
-  }
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-  ZeroMem (&SecSend, sizeof(NVME_ADMIN_SECSEND));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  Opcode = (UINT8)(SendCommand ? NVME_ADMIN_SECURITY_SEND_OPC : NVME_ADMIN_SECURITY_RECV_OPC);
-  Command.Cdw0.Opcode = Opcode;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)SecBuff;
-  CommandPacket.TransferLength = (UINT32)TransferLength;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-
-  SecSend.Spsp = SpSpecific;
-  SecSend.Secp = SecurityProtocol;
-  SecSend.Tl   = (UINT32)TransferLength;
-
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &SecSend, sizeof (NVME_ADMIN_SECSEND));
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NVME_CONTROLLER_ID,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  //
-  // Actions for receiving security command
-  //
-  if (!SendCommand) {
-    CopyMem (TransferBuffer, SecBuff, TransferLength);
-  }
-
-  return Status;
-}
-
-/**
-  Destroy io completion queue.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully destroy io completion queue.
-  @return others                    - Fail to destroy io completion queue.
-
-**/
-STATIC
-EFI_STATUS
-NvmeDestroyIoCompletionQueue (
-  IN     NVME_CONTEXT                      *Nvme
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  NVME_ADMIN_DEIOCQ                        DelIoCq;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-  ZeroMem (&DelIoCq, sizeof(NVME_ADMIN_DEIOCQ));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  Command.Cdw0.Opcode = NVME_ADMIN_DELIOCQ_OPC;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
-  CommandPacket.TransferLength = EFI_PAGE_SIZE;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-
-  DelIoCq.Qid   = NVME_IO_QUEUE;
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoCq, sizeof (NVME_ADMIN_DEIOCQ));
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NVME_CONTROLLER_ID,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Destroy io submission queue.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @return EFI_SUCCESS               - Successfully destroy io submission queue.
-  @return others                    - Fail to destroy io submission queue.
-
-**/
-STATIC
-EFI_STATUS
-NvmeDestroyIoSubmissionQueue (
-  IN NVME_CONTEXT                          *Nvme
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  NVME_ADMIN_DEIOSQ                        DelIoSq;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-  ZeroMem (&DelIoSq, sizeof(NVME_ADMIN_DEIOSQ));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  Command.Cdw0.Opcode = NVME_ADMIN_DELIOSQ_OPC;
-  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
-  CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
-  CommandPacket.TransferLength = EFI_PAGE_SIZE;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
-
-  DelIoSq.Qid   = NVME_IO_QUEUE;
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoSq, sizeof (NVME_ADMIN_DEIOSQ));
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              NVME_CONTROLLER_ID,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Allocate transfer-related Data struct which is used at Nvme.
-
-  @param[in] ImageHandle         Image handle for this driver image
-  @param[in] Nvme                The pointer to the NVME_CONTEXT Data structure.
-
-  @retval  EFI_OUT_OF_RESOURCE   The allocation is failure.
-  @retval  EFI_SUCCESS           Successful to allocate memory.
-
-**/
-EFI_STATUS
-EFIAPI
-NvmeAllocateResource (
-  IN EFI_HANDLE                         ImageHandle,
-  IN NVME_CONTEXT                       *Nvme
-  )
-{
-  EFI_STATUS            Status;
-  EFI_PHYSICAL_ADDRESS  Addr;
-  UINT32                Size;
-
-  //
-  // Allocate resources required by NVMe host controller.
-  //
-  // NBAR
-  Size = 0x10000;
-  Addr = 0xFFFFFFFF;
-  Status = gDS->AllocateMemorySpace (
-                  EfiGcdAllocateMaxAddressSearchBottomUp,
-                  EfiGcdMemoryTypeMemoryMappedIo,
-                  15,                             // 2^15: 32K Alignment
-                  Size,
-                  &Addr,
-                  ImageHandle,
-                  NULL
-                  );
-  if (EFI_ERROR (Status)) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-  Nvme->Nbar = (UINT32) Addr;
-
-  // DMA Buffer
-  Size = NVME_MEM_MAX_SIZE;
-  Addr = 0xFFFFFFFF;
-  Status = gBS->AllocatePages (
-                  AllocateMaxAddress,
-                  EfiACPIMemoryNVS,
-                  EFI_SIZE_TO_PAGES (Size),
-                  (EFI_PHYSICAL_ADDRESS *)&Addr
-                  );
-  if (EFI_ERROR (Status)) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-  Nvme->BaseMem = (UINT32) Addr;
-
-  // Clean up DMA Buffer before using
-  ZeroMem ((VOID *)(UINTN)Addr, NVME_MEM_MAX_SIZE);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Free allocated transfer-related Data struct which is used at NVMe.
-
-  @param[in] Nvme                The pointer to the NVME_CONTEXT Data structure.
-
-**/
-VOID
-EFIAPI
-NvmeFreeResource (
-  IN NVME_CONTEXT                       *Nvme
-  )
-{
-  UINT32                Size;
-
-  // NBAR
-  if (Nvme->BaseMem != 0) {
-    Size = 0x10000;
-    gDS->FreeMemorySpace (Nvme->Nbar, Size);
-  }
-
-  // DMA Buffer
-  if (Nvme->Nbar != 0) {
-    Size = NVME_MEM_MAX_SIZE;
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN) Nvme->Nbar, EFI_SIZE_TO_PAGES (Size));
-  }
-}
-
-
-/**
-  Initialize the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @retval EFI_SUCCESS               - The NVM Express Controller is initialized successfully.
-  @retval Others                    - A device error occurred while initializing the controller.
-
-**/
-EFI_STATUS
-NvmeControllerInit (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  EFI_STATUS            Status;
-  NVME_AQA              Aqa;
-  NVME_ASQ              Asq;
-  NVME_ACQ              Acq;
-  NVME_VER              Ver;
-
-  UINT32                MlBAR;
-  UINT32                MuBAR;
-
-  ///
-  /// Update PCIE BAR0/1 for NVME device
-  ///
-  MlBAR = Nvme->Nbar;
-  MuBAR = 0;
-  PciWrite32 (Nvme->PciBase + 0x10, MlBAR); // MLBAR (BAR0)
-  PciWrite32 (Nvme->PciBase + 0x14, MuBAR); // MUBAR (BAR1)
-
-  ///
-  /// Enable PCIE decode
-  ///
-  PciWrite8 (Nvme->PciBase + NVME_PCIE_PCICMD, 0x6);
-
-  // Version
-  NVME_GET_VER (Nvme, &Ver);
-  if (!(Ver.Mjr == 0x0001) && (Ver.Mnr == 0x0000)) {
-    DEBUG ((DEBUG_INFO, "\n!!!\n!!! NVME Version mismatch for the implementation !!!\n!!!\n"));
-  }
-
-  ///
-  /// Read the Controller Capabilities register and verify that the NVM command set is supported
-  ///
-  Status = NVME_GET_CAP (Nvme, &Nvme->Cap);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "NVME_GET_CAP fail, Status: %r\n", Status));
-    goto Done;
-  }
-
-  if (Nvme->Cap.Css != 0x01) {
-    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: the controller doesn't support NVMe command set\n"));
-    Status = EFI_UNSUPPORTED;
-    goto Done;
-  }
-
-  ///
-  /// Currently the driver only supports 4k page Size.
-  ///
-  if ((Nvme->Cap.Mpsmin + 12) > EFI_PAGE_SHIFT) {
-    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: only supports 4k page Size\n"));
-    ASSERT (FALSE);
-    Status = EFI_UNSUPPORTED;
-    goto Done;
-  }
-
-  Nvme->Cid[0] = 0;
-  Nvme->Cid[1] = 0;
-
-  Nvme->Pt[0]  = 0;
-  Nvme->Pt[1]  = 0;
-
-  ZeroMem ((VOID *)(UINTN)(&(Nvme->SqTdbl[0])), sizeof (NVME_SQTDBL) * NVME_MAX_IO_QUEUES);
-  ZeroMem ((VOID *)(UINTN)(&(Nvme->CqHdbl[0])), sizeof (NVME_CQHDBL) * NVME_MAX_IO_QUEUES);
-
-  ZeroMem ((VOID *)(UINTN)Nvme->BaseMem, NVME_MEM_MAX_SIZE);
-
-  Status = NvmeDisableController (Nvme);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NvmeDisableController fail, Status: %r\n", Status));
-    goto Done;
-  }
-
-  ///
-  /// set number of entries admin submission & completion queues.
-  ///
-  Aqa.Asqs  = NVME_ASQ_SIZE;
-  Aqa.Rsvd1 = 0;
-  Aqa.Acqs  = NVME_ACQ_SIZE;
-  Aqa.Rsvd2 = 0;
-
-  ///
-  /// Address of admin submission queue.
-  ///
-  Asq = (UINT64)(UINTN)(NVME_ASQ_BASE (Nvme) & ~0xFFF);
-
-  ///
-  /// Address of admin completion queue.
-  ///
-  Acq = (UINT64)(UINTN)(NVME_ACQ_BASE (Nvme) & ~0xFFF);
-
-  ///
-  /// Address of I/O submission & completion queue.
-  ///
-  Nvme->SqBuffer[0] = (NVME_SQ *)(UINTN)NVME_ASQ_BASE (Nvme);   // NVME_ADMIN_QUEUE
-  Nvme->CqBuffer[0] = (NVME_CQ *)(UINTN)NVME_ACQ_BASE (Nvme);   // NVME_ADMIN_QUEUE
-  Nvme->SqBuffer[1] = (NVME_SQ *)(UINTN)NVME_SQ_BASE (Nvme, 0); // NVME_IO_QUEUE
-  Nvme->CqBuffer[1] = (NVME_CQ *)(UINTN)NVME_CQ_BASE (Nvme, 0); // NVME_IO_QUEUE
-
-  DEBUG ((DEBUG_INFO, "BaseMem = [%08X]\n", Nvme->BaseMem));
-  DEBUG ((DEBUG_INFO, "Admin Submission Queue Size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));
-  DEBUG ((DEBUG_INFO, "Admin Completion Queue Size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));
-  DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) =   [%08X]\n", Nvme->SqBuffer[0]));
-  DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) =   [%08X]\n", Nvme->CqBuffer[0]));
-  DEBUG ((DEBUG_INFO, "I/O   Submission Queue (SqBuffer[1]) =   [%08X]\n", Nvme->SqBuffer[1]));
-  DEBUG ((DEBUG_INFO, "I/O   Completion Queue (CqBuffer[1]) =   [%08X]\n", Nvme->CqBuffer[1]));
-
-  ///
-  /// Program admin queue attributes.
-  ///
-  Status = NVME_SET_AQA (Nvme, &Aqa);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  ///
-  /// Program admin submission queue address.
-  ///
-  Status = NVME_SET_ASQ (Nvme, &Asq);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  ///
-  /// Program admin completion queue address.
-  ///
-  Status = NVME_SET_ACQ (Nvme, &Acq);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  Status = NvmeEnableController (Nvme);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  ///
-  /// Create one I/O completion queue.
-  ///
-  Status = NvmeCreateIoCompletionQueue (Nvme);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  ///
-  /// Create one I/O Submission queue.
-  ///
-  Status = NvmeCreateIoSubmissionQueue (Nvme);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  ///
-  /// Get current Identify Controller Data
-  ///
-  Nvme->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)(UINTN) NVME_CONTROL_DATA_BASE (Nvme);
-  Status = NvmeIdentifyController (Nvme, Nvme->ControllerData);
-  if (EFI_ERROR(Status)) {
-    goto Done;
-  }
-
-  ///
-  /// Dump NvmExpress Identify Controller Data
-  ///
-  Nvme->ControllerData->Sn[19] = 0;
-  Nvme->ControllerData->Mn[39] = 0;
-  //NvmeDumpIdentifyController (Nvme->ControllerData);
-
-  ///
-  /// Get current Identify Namespace Data
-  ///
-  Nvme->NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)NVME_NAMESPACE_DATA_BASE (Nvme);
-  Status = NvmeIdentifyNamespace (Nvme, Nvme->Nsid, Nvme->NamespaceData);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, "NvmeIdentifyNamespace fail, Status = %r\n", Status));
-    goto Done;
-  }
-
-  ///
-  /// Dump NvmExpress Identify Namespace Data
-  ///
-  if (Nvme->NamespaceData->Ncap == 0) {
-    DEBUG ((DEBUG_ERROR, "Invalid Namespace, Ncap: %lx\n", Nvme->NamespaceData->Ncap));
-    Status = EFI_DEVICE_ERROR;
-    goto Done;
-  }
-
-  Nvme->BlockSize = NvmeGetBlockSize (Nvme);
-  Nvme->LastBlock = NvmeGetLastLba (Nvme);
-
-  Nvme->State    = NvmeStatusInit;
-
-  return EFI_SUCCESS;
-
-Done:
-  return Status;
-}
-
-/**
-  Un-initialize the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @retval EFI_SUCCESS               - The NVM Express Controller is un-initialized successfully.
-  @retval Others                    - A device error occurred while un-initializing the controller.
-
-**/
-EFI_STATUS
-NvmeControllerExit (
-  IN NVME_CONTEXT       *Nvme
-  )
-{
-  EFI_STATUS            Status;
-
-  Status = EFI_SUCCESS;
-  if (Nvme->State == NvmeStatusInit || Nvme->State == NvmeStatusMax) {
-    ///
-    /// Destroy I/O Submission queue.
-    ///
-    Status = NvmeDestroyIoSubmissionQueue (Nvme);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoSubmissionQueue fail, Status = %r\n", Status));
-      return Status;
-    }
-
-    ///
-    /// Destroy I/O completion queue.
-    ///
-    Status = NvmeDestroyIoCompletionQueue (Nvme);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoCompletionQueue fail, Status = %r\n", Status));
-      return Status;
-    }
-
-    Status = NvmeShutdownController (Nvme);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NvmeShutdownController fail, Status: %r\n", Status));
-    }
-  }
-
-  ///
-  /// Disable PCIE decode
-  ///
-  PciWrite8  (Nvme->PciBase + NVME_PCIE_PCICMD, 0x0);
-  PciWrite32 (Nvme->PciBase + 0x10, 0); // MLBAR (BAR0)
-  PciWrite32 (Nvme->PciBase + 0x14, 0); // MUBAR (BAR1)
-
-  Nvme->State = NvmeStatusUnknown;
-  return Status;
-}
-
-/**
-  Read sector Data from the NVMe device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in,out] Buffer             - The Buffer used to store the Data read from the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be read.
-
-  @retval EFI_SUCCESS               - Datum are read from the device.
-  @retval Others                    - Fail to read all the datum.
-
-**/
-EFI_STATUS
-NvmeReadSectors (
-  IN NVME_CONTEXT                          *Nvme,
-  IN OUT UINT64                            Buffer,
-  IN UINT64                                Lba,
-  IN UINT32                                Blocks
-  )
-{
-  UINT32                                   Bytes;
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  UINT32                                   BlockSize;
-
-  BlockSize  = Nvme->BlockSize;
-  Bytes      = Blocks * BlockSize;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
-  CommandPacket.NvmeCmd->Cdw0.Cid    = Nvme->Cid[NVME_IO_QUEUE]++;
-  CommandPacket.NvmeCmd->Nsid        = Nvme->Nsid;
-  CommandPacket.TransferBuffer       = Buffer;
-
-  CommandPacket.TransferLength = Bytes;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_IO_QUEUE;
-
-  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
-  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
-  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
-
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              Nvme->Nsid,
-              0,
-              &CommandPacket
-              );
-
-  return Status;
-}
-
-/**
-  Write sector Data to the NVMe device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Buffer                 - The Buffer to be written into the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be written.
-
-  @retval EFI_SUCCESS               - Datum are written into the Buffer.
-  @retval Others                    - Fail to write all the datum.
-
-**/
-EFI_STATUS
-NvmeWriteSectors (
-  IN NVME_CONTEXT                          *Nvme,
-  IN UINT64                                Buffer,
-  IN UINT64                                Lba,
-  IN UINT32                                Blocks
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-  UINT32                                   Bytes;
-  UINT32                                   BlockSize;
-
-  BlockSize  = Nvme->BlockSize;
-  Bytes      = Blocks * BlockSize;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
-  CommandPacket.NvmeCmd->Cdw0.Cid    = Nvme->Cid[NVME_IO_QUEUE]++;
-  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
-  CommandPacket.TransferBuffer = Buffer;
-
-  CommandPacket.TransferLength = Bytes;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_IO_QUEUE;
-
-  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
-  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
-  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
-
-  CommandPacket.MetadataBuffer = (UINT64)(UINTN)NULL;
-  CommandPacket.MetadataLength = 0;
-
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
-
-  Status = NvmePassThru (
-              Nvme,
-              Nvme->Nsid,
-              0,
-              &CommandPacket
-              );
-
-  return Status;
-}
-
-/**
-  Flushes all modified Data to the device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @retval EFI_SUCCESS               - Datum are written into the Buffer.
-  @retval Others                    - Fail to write all the datum.
-
-**/
-EFI_STATUS
-NvmeFlush (
-  IN NVME_CONTEXT                          *Nvme
-  )
-{
-  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
-  NVM_EXPRESS_COMMAND                      Command;
-  NVM_EXPRESS_RESPONSE                     Response;
-  EFI_STATUS                               Status;
-
-  ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
-  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
-  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
-
-  CommandPacket.NvmeCmd      = &Command;
-  CommandPacket.NvmeResponse = &Response;
-
-  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC;
-  CommandPacket.NvmeCmd->Cdw0.Cid    = Nvme->Cid[NVME_IO_QUEUE]++;
-  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
-  CommandPacket.QueueId        = NVME_IO_QUEUE;
-
-  Status = NvmePassThru (
-              Nvme,
-              Nvme->Nsid,
-              0,
-              &CommandPacket
-              );
-  if (!EFI_ERROR (Status)) {
-    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
-  }
-
-  return Status;
-}
-
-/**
-  Read some blocks from the device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[out] Buffer                - The Buffer used to store the Data read from the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be read.
-
-  @retval EFI_SUCCESS               - Datum are read from the device.
-  @retval Others                    - Fail to read all the datum.
-
-**/
-EFI_STATUS
-NvmeRead (
-  IN NVME_CONTEXT                  *Nvme,
-  OUT UINT64                       Buffer,
-  IN UINT64                        Lba,
-  IN UINTN                         Blocks
-  )
-{
-  EFI_STATUS                       Status;
-  UINT32                           BlockSize;
-  UINT32                           MaxTransferBlocks;
-
-  ASSERT (Blocks <= NVME_MAX_SECTORS);
-  Status        = EFI_SUCCESS;
-  BlockSize     = Nvme->BlockSize;
-  if (Nvme->ControllerData->Mdts != 0) {
-    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 << (Nvme->Cap.Mpsmin + 12)) / BlockSize;
-  } else {
-    MaxTransferBlocks = 1024;
-  }
-
-  while (Blocks > 0) {
-    if (Blocks > MaxTransferBlocks) {
-      Status = NvmeReadSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
-
-      Blocks -= MaxTransferBlocks;
-      Buffer += (MaxTransferBlocks * BlockSize);
-      Lba    += MaxTransferBlocks;
-    } else {
-      Status = NvmeReadSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
-      Blocks = 0;
-    }
-
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NvmeRead fail, Status = %r\n", Status));
-      break;
-    }
-  }
-
-  return Status;
-}
-
-/**
-  Write some blocks to the device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Buffer                 - The Buffer to be written into the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be written.
-
-  @retval EFI_SUCCESS               - Datum are written into the Buffer.
-  @retval Others                    - Fail to write all the datum.
-
-**/
-EFI_STATUS
-NvmeWrite (
-  IN NVME_CONTEXT                  *Nvme,
-  IN UINT64                        Buffer,
-  IN UINT64                        Lba,
-  IN UINTN                         Blocks
-  )
-{
-  EFI_STATUS                       Status;
-  UINT32                           BlockSize;
-  UINT32                           MaxTransferBlocks;
-
-  ASSERT (Blocks <= NVME_MAX_SECTORS);
-  Status        = EFI_SUCCESS;
-  BlockSize     = Nvme->BlockSize;
-
-  if (Nvme->ControllerData->Mdts != 0) {
-    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 << (Nvme->Cap.Mpsmin + 12)) / BlockSize;
-  } else {
-    MaxTransferBlocks = 1024;
-  }
-
-  while (Blocks > 0) {
-    if (Blocks > MaxTransferBlocks) {
-      Status = NvmeWriteSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
-
-      Blocks -= MaxTransferBlocks;
-      Buffer += (MaxTransferBlocks * BlockSize);
-      Lba    += MaxTransferBlocks;
-    } else {
-      Status = NvmeWriteSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
-      Blocks = 0;
-    }
-
-    if (EFI_ERROR(Status)) {
-      DEBUG ((DEBUG_ERROR, "NvmeWrite fail, Status = %r\n", Status));
-      break;
-    }
-  }
-
-  return Status;
-}
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.h
deleted file mode 100644
index bfa4f10413fb..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeMode.h
+++ /dev/null
@@ -1,456 +0,0 @@
-/** @file
-  Header file for NVMe function definitions
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef __OPAL_PASSWORD_NVME_MODE_H__
-#define __OPAL_PASSWORD_NVME_MODE_H__
-
-
-#include "OpalNvmeReg.h"
-
-#define NVME_MAX_SECTORS            0x10000
-//
-// QueueId
-//
-#define NVME_ADMIN_QUEUE            0x00
-#define NVME_IO_QUEUE               0x01
-
-typedef struct {
-  UINT8                             Opcode;
-  UINT8                             FusedOperation;
-    #define NORMAL_CMD              0x00
-    #define FUSED_FIRST_CMD         0x01
-    #define FUSED_SECOND_CMD        0x02
-  UINT16                            Cid;
-} NVME_CDW0;
-
-typedef struct {
-  NVME_CDW0                         Cdw0;
-  UINT8                             Flags;
-    #define CDW10_VALID             0x01
-    #define CDW11_VALID             0x02
-    #define CDW12_VALID             0x04
-    #define CDW13_VALID             0x08
-    #define CDW14_VALID             0x10
-    #define CDW15_VALID             0x20
-  UINT32                            Nsid;
-  UINT32                            Cdw10;
-  UINT32                            Cdw11;
-  UINT32                            Cdw12;
-  UINT32                            Cdw13;
-  UINT32                            Cdw14;
-  UINT32                            Cdw15;
-} NVM_EXPRESS_COMMAND;
-
-typedef struct {
-  UINT32                            Cdw0;
-  UINT32                            Cdw1;
-  UINT32                            Cdw2;
-  UINT32                            Cdw3;
-} NVM_EXPRESS_RESPONSE;
-
-typedef struct {
-  UINT64                            CommandTimeout;
-  UINT64                            TransferBuffer;
-  UINT32                            TransferLength;
-  UINT64                            MetadataBuffer;
-  UINT32                            MetadataLength;
-  UINT8                             QueueId;
-  NVM_EXPRESS_COMMAND               *NvmeCmd;
-  NVM_EXPRESS_RESPONSE              *NvmeResponse;
-} NVM_EXPRESS_PASS_THRU_COMMAND_PACKET;
-
-
-#pragma pack(1)
-
-// Internal fields
-typedef enum {
-  NvmeStatusUnknown,
-  NvmeStatusInit,
-  NvmeStatusInuse,
-  NvmeStatusMax,
-} NVME_STATUS;
-
-typedef struct {
-  UINT32                            Nbar;
-  UINT32                            BaseMem;
-  BOOLEAN                           PollCancellation;
-  UINT16                            NvmeInitWaitTime;
-
-  NVME_STATUS                       State;
-  UINT8                             BusID;
-  UINT8                             DeviceID;
-  UINT8                             FuncID;
-  UINTN                             PciBase;
-
-  UINT32                            Nsid;
-  UINT64                            Nsuuid;
-  UINT32                            BlockSize;
-  EFI_LBA                           LastBlock;
-
-  //
-  // Pointers to 4kB aligned submission & completion queues.
-  //
-  NVME_SQ                           *SqBuffer[NVME_MAX_IO_QUEUES];
-  NVME_CQ                           *CqBuffer[NVME_MAX_IO_QUEUES];
-  UINT16                            Cid[NVME_MAX_IO_QUEUES];
-
-  //
-  // Submission and completion queue indices.
-  //
-  NVME_SQTDBL                       SqTdbl[NVME_MAX_IO_QUEUES];
-  NVME_CQHDBL                       CqHdbl[NVME_MAX_IO_QUEUES];
-  UINT8                             Pt[NVME_MAX_IO_QUEUES];
-
-  UINTN                             SqeCount[NVME_MAX_IO_QUEUES];
-
-  //
-  // Nvme controller capabilities
-  //
-  NVME_CAP                          Cap;
-
-  //
-  // pointer to identify controller Data
-  //
-  NVME_ADMIN_CONTROLLER_DATA        *ControllerData;
-  NVME_ADMIN_NAMESPACE_DATA         *NamespaceData;
-} NVME_CONTEXT;
-
-#pragma pack()
-
-/**
-  Transfer MMIO Data to memory.
-
-  @param[in,out] MemBuffer - Destination: Memory address
-  @param[in] MmioAddr      - Source: MMIO address
-  @param[in] Size          - Size for read
-
-  @retval EFI_SUCCESS - MMIO read sucessfully
-**/
-EFI_STATUS
-NvmeMmioRead (
-  IN OUT VOID *MemBuffer,
-  IN     UINTN MmioAddr,
-  IN     UINTN Size
-  );
-
-/**
-  Transfer memory Data to MMIO.
-
-  @param[in,out] MmioAddr - Destination: MMIO address
-  @param[in] MemBuffer    - Source: Memory address
-  @param[in] Size         - Size for write
-
-  @retval EFI_SUCCESS - MMIO write sucessfully
-**/
-EFI_STATUS
-NvmeMmioWrite (
-  IN OUT UINTN MmioAddr,
-  IN     VOID *MemBuffer,
-  IN     UINTN Size
-  );
-
-/**
-  Transfer memory data to MMIO.
-
-  @param[in,out] MmioAddr - Destination: MMIO address
-  @param[in] MemBuffer    - Source: Memory address
-  @param[in] Size         - Size for write
-
-  @retval EFI_SUCCESS - MMIO write sucessfully
-**/
-EFI_STATUS
-OpalPciWrite (
-  IN OUT UINTN MmioAddr,
-  IN     VOID *MemBuffer,
-  IN     UINTN Size
-  );
-
-/**
-  Transfer MMIO data to memory.
-
-  @param[in,out] MemBuffer - Destination: Memory address
-  @param[in] MmioAddr      - Source: MMIO address
-  @param[in] Size          - Size for read
-
-  @retval EFI_SUCCESS - MMIO read sucessfully
-**/
-EFI_STATUS
-OpalPciRead (
-  IN OUT VOID *MemBuffer,
-  IN     UINTN MmioAddr,
-  IN     UINTN Size
-  );
-
-/**
-  Allocate transfer-related Data struct which is used at Nvme.
-
-  @param[in] ImageHandle         Image handle for this driver image
-  @param[in] Nvme                The pointer to the NVME_CONTEXT Data structure.
-
-  @retval  EFI_OUT_OF_RESOURCE   The allocation is failure.
-  @retval  EFI_SUCCESS           Successful to allocate memory.
-
-**/
-EFI_STATUS
-EFIAPI
-NvmeAllocateResource (
-  IN EFI_HANDLE                         ImageHandle,
-  IN NVME_CONTEXT                       *Nvme
-  );
-
-/**
-  Free allocated transfer-related Data struct which is used at NVMe.
-
-  @param[in] Nvme                The pointer to the NVME_CONTEXT Data structure.
-
-**/
-VOID
-EFIAPI
-NvmeFreeResource (
-  IN NVME_CONTEXT                       *Nvme
-  );
-
-/**
-  Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
-  both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
-  I/O functionality is optional.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
-                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
-                                      ID specifies that the command packet should be sent to all valid namespaces.
-  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
-                                      A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
-                                      UUID specifies that the command packet should be sent to all valid namespaces.
-  @param[in,out] Packet             - A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
-                                      by NamespaceId.
-
-  @retval EFI_SUCCESS               - The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
-                                      to, or from DataBuffer.
-  @retval EFI_NOT_READY             - The NVM Express Command Packet could not be sent because the controller is not ready. The caller
-                                      may retry again later.
-  @retval EFI_DEVICE_ERROR          - A device error occurred while attempting to send the NVM Express Command Packet.
-  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
-                                      Express Command Packet was not sent, so no additional status information is available.
-  @retval EFI_UNSUPPORTED           - The command described by the NVM Express Command Packet is not supported by the host adapter.
-                                      The NVM Express Command Packet was not sent, so no additional status information is available.
-  @retval EFI_TIMEOUT               - A timeout occurred while waiting for the NVM Express Command Packet to execute.
-
-**/
-EFI_STATUS
-NvmePassThru (
-  IN     NVME_CONTEXT                         *Nvme,
-  IN     UINT32                               NamespaceId,
-  IN     UINT64                               NamespaceUuid,
-  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
-  );
-
-/**
-  Waits until all NVME commands completed.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Qid                    - Queue index
-
-  @retval EFI_SUCCESS               - All NVME commands have completed
-  @retval EFI_TIMEOUT               - Timeout occured
-  @retval EFI_NOT_READY             - Not all NVME commands have completed
-  @retval others                    - Error occurred on device side.
-**/
-EFI_STATUS
-NvmeWaitAllComplete (
-  IN NVME_CONTEXT       *Nvme,
-  IN UINT8              Qid
-  );
-
-/**
-  Initialize the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @retval EFI_SUCCESS               - The NVM Express Controller is initialized successfully.
-  @retval Others                    - A device error occurred while initializing the controller.
-
-**/
-EFI_STATUS
-NvmeControllerInit (
-  IN NVME_CONTEXT       *Nvme
-  );
-
-/**
-  Un-initialize the Nvm Express controller.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @retval EFI_SUCCESS               - The NVM Express Controller is un-initialized successfully.
-  @retval Others                    - A device error occurred while un-initializing the controller.
-
-**/
-EFI_STATUS
-NvmeControllerExit (
-  IN NVME_CONTEXT       *Nvme
-  );
-
-/**
-  Check whether there are available command slots.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Qid                    - Queue index
-
-  @retval EFI_SUCCESS               - Available command slot is found
-  @retval EFI_NOT_READY             - No available command slot is found
-  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
-
-**/
-EFI_STATUS
-NvmeHasFreeCmdSlot (
-  IN NVME_CONTEXT       *Nvme,
-  IN UINT8              Qid
-  );
-
-/**
-  Check whether all command slots are clean.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Qid                    - Queue index
-
-  @retval EFI_SUCCESS               - All command slots are clean
-  @retval EFI_NOT_READY             - Not all command slots are clean
-  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
-
-**/
-EFI_STATUS
-NvmeIsAllCmdSlotClean (
-  IN NVME_CONTEXT       *Nvme,
-  IN UINT8              Qid
-  );
-
-/**
-  Read sector Data from the NVMe device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in,out] Buffer             - The Buffer used to store the Data read from the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be read.
-
-  @retval EFI_SUCCESS               - Datum are read from the device.
-  @retval Others                    - Fail to read all the datum.
-
-**/
-EFI_STATUS
-NvmeReadSectors (
-  IN NVME_CONTEXT                          *Nvme,
-  IN OUT UINT64                            Buffer,
-  IN UINT64                                Lba,
-  IN UINT32                                Blocks
-  );
-
-/**
-  Write sector Data to the NVMe device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Buffer                 - The Buffer to be written into the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be written.
-
-  @retval EFI_SUCCESS               - Datum are written into the Buffer.
-  @retval Others                    - Fail to write all the datum.
-
-**/
-EFI_STATUS
-NvmeWriteSectors (
-  IN NVME_CONTEXT                          *Nvme,
-  IN UINT64                                Buffer,
-  IN UINT64                                Lba,
-  IN UINT32                                Blocks
-  );
-
-/**
-  Flushes all modified Data to the device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-
-  @retval EFI_SUCCESS               - Datum are written into the Buffer.
-  @retval Others                    - Fail to write all the datum.
-
-**/
-EFI_STATUS
-NvmeFlush (
-  IN NVME_CONTEXT                          *Nvme
-  );
-
-/**
-  Read some blocks from the device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[out] Buffer                - The Buffer used to store the Data read from the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be read.
-
-  @retval EFI_SUCCESS               - Datum are read from the device.
-  @retval Others                    - Fail to read all the datum.
-
-**/
-EFI_STATUS
-NvmeRead (
-  IN NVME_CONTEXT                  *Nvme,
-  OUT UINT64                       Buffer,
-  IN UINT64                        Lba,
-  IN UINTN                         Blocks
-  );
-
-/**
-  Write some blocks to the device.
-
-  @param[in] Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in] Buffer                 - The Buffer to be written into the device.
-  @param[in] Lba                    - The start block number.
-  @param[in] Blocks                 - Total block number to be written.
-
-  @retval EFI_SUCCESS               - Datum are written into the Buffer.
-  @retval Others                    - Fail to write all the datum.
-
-**/
-EFI_STATUS
-NvmeWrite (
-  IN NVME_CONTEXT                  *Nvme,
-  IN UINT64                        Buffer,
-  IN UINT64                        Lba,
-  IN UINTN                         Blocks
-  );
-
-/**
-  Security send and receive commands.
-
-  @param[in]     Nvme                   - The pointer to the NVME_CONTEXT Data structure.
-  @param[in]     SendCommand            - The flag to indicate the command type, TRUE for Send command and FALSE for receive command
-  @param[in]     SecurityProtocol       - Security Protocol
-  @param[in]     SpSpecific             - Security Protocol Specific
-  @param[in]     TransferLength         - Transfer Length of Buffer (in bytes) - always a multiple of 512
-  @param[in,out] TransferBuffer         - Address of Data to transfer
-
-  @return EFI_SUCCESS               - Successfully create io submission queue.
-  @return others                    - Fail to send/receive commands.
-
-**/
-EFI_STATUS
-NvmeSecuritySendReceive (
-  IN NVME_CONTEXT                          *Nvme,
-  IN BOOLEAN                               SendCommand,
-  IN UINT8                                 SecurityProtocol,
-  IN UINT16                                SpSpecific,
-  IN UINTN                                 TransferLength,
-  IN OUT VOID                              *TransferBuffer
-  );
-
-#endif
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeReg.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeReg.h
deleted file mode 100644
index b5460cd42e1a..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalNvmeReg.h
+++ /dev/null
@@ -1,814 +0,0 @@
-/** @file
-  Header file for Registers and Structure definitions
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-#ifndef __OPAL_PASSWORD_NVME_REG_H__
-#define __OPAL_PASSWORD_NVME_REG_H__
-
-//
-// PCI Header for PCIe root port configuration
-//
-#define NVME_PCIE_PCICMD                         0x04
-#define NVME_PCIE_BNUM                           0x18
-#define NVME_PCIE_SEC_BNUM                       0x19
-#define NVME_PCIE_IOBL                           0x1C
-#define NVME_PCIE_MBL                            0x20
-#define NVME_PCIE_PMBL                           0x24
-#define NVME_PCIE_PMBU32                         0x28
-#define NVME_PCIE_PMLU32                         0x2C
-#define NVME_PCIE_INTR                           0x3C
-
-//
-// NVMe related definitions
-//
-#define PCI_CLASS_MASS_STORAGE_NVM                0x08  // mass storage sub-class non-volatile memory.
-#define PCI_IF_NVMHCI                             0x02  // mass storage programming interface NVMHCI.
-
-#define NVME_ASQ_SIZE                                    1     // Number of admin submission queue entries, which is 0-based
-#define NVME_ACQ_SIZE                                    1     // Number of admin completion queue entries, which is 0-based
-
-#define NVME_CSQ_SIZE                                    63     // Number of I/O submission queue entries, which is 0-based
-#define NVME_CCQ_SIZE                                    63     // Number of I/O completion queue entries, which is 0-based
-
-#define NVME_MAX_IO_QUEUES                               2     // Number of I/O queues supported by the driver, 1 for AQ, 1 for CQ
-
-#define NVME_CSQ_DEPTH                                   (NVME_CSQ_SIZE+1)
-#define NVME_CCQ_DEPTH                                   (NVME_CCQ_SIZE+1)
-#define NVME_PRP_SIZE                                    (4)    // Pages of PRP list
-
-#define NVME_CONTROLLER_ID                               0
-
-//
-// Time out Value for Nvme transaction execution
-//
-#define NVME_GENERIC_TIMEOUT                             5000000   ///< us
-#define NVME_CMD_WAIT                                    100       ///< us
-#define NVME_CMD_TIMEOUT                                 20000000  ///< us
-
-
-
-#define NVME_MEM_MAX_SIZE \
-  (( \
-  1                                         /* Controller Data */ +  \
-  1                                         /* Identify Data */   +  \
-  1                                         /* ASQ */             +  \
-  1                                         /* ACQ */             +  \
-  1                                         /* SQs */             +  \
-  1                                         /* CQs */             +  \
-  NVME_PRP_SIZE * NVME_CSQ_DEPTH            /* PRPs */               \
-  ) * EFI_PAGE_SIZE)
-
-
-//
-// controller register offsets
-//
-#define NVME_CAP_OFFSET          0x0000  // Controller Capabilities
-#define NVME_VER_OFFSET          0x0008  // Version
-#define NVME_INTMS_OFFSET        0x000c  // Interrupt Mask Set
-#define NVME_INTMC_OFFSET        0x0010  // Interrupt Mask Clear
-#define NVME_CC_OFFSET           0x0014  // Controller Configuration
-#define NVME_CSTS_OFFSET         0x001c  // Controller Status
-#define NVME_AQA_OFFSET          0x0024  // Admin Queue Attributes
-#define NVME_ASQ_OFFSET          0x0028  // Admin Submission Queue Base Address
-#define NVME_ACQ_OFFSET          0x0030  // Admin Completion Queue Base Address
-#define NVME_SQ0_OFFSET          0x1000  // Submission Queue 0 (admin) Tail Doorbell
-#define NVME_CQ0_OFFSET          0x1004  // Completion Queue 0 (admin) Head Doorbell
-
-//
-// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD))
-// Get the doorbell stride bit shift Value from the controller capabilities.
-//
-#define NVME_SQTDBL_OFFSET(QID, DSTRD)    0x1000 + ((2 * (QID)) * (4 << (DSTRD)))       // Submission Queue y (NVM) Tail Doorbell
-#define NVME_CQHDBL_OFFSET(QID, DSTRD)    0x1000 + (((2 * (QID)) + 1) * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell
-
-
-#pragma pack(1)
-
-//
-// 3.1.1 Offset 00h: CAP - Controller Capabilities
-//
-typedef struct {
-  UINT16 Mqes;      // Maximum Queue Entries Supported
-  UINT8  Cqr:1;     // Contiguous Queues Required
-  UINT8  Ams:2;     // Arbitration Mechanism Supported
-  UINT8  Rsvd1:5;
-  UINT8  To;        // Timeout
-  UINT16 Dstrd:4;
-  UINT16 Rsvd2:1;
-  UINT16 Css:4;     // Command Sets Supported
-  UINT16 Rsvd3:7;
-  UINT8  Mpsmin:4;
-  UINT8  Mpsmax:4;
-  UINT8  Rsvd4;
-} NVME_CAP;
-
-//
-// 3.1.2 Offset 08h: VS - Version
-//
-typedef struct {
-  UINT16 Mnr;       // Minor version number
-  UINT16 Mjr;       // Major version number
-} NVME_VER;
-
-//
-// 3.1.5 Offset 14h: CC - Controller Configuration
-//
-typedef struct {
-  UINT16 En:1;       // Enable
-  UINT16 Rsvd1:3;
-  UINT16 Css:3;      // Command Set Selected
-  UINT16 Mps:4;      // Memory Page Size
-  UINT16 Ams:3;      // Arbitration Mechanism Selected
-  UINT16 Shn:2;      // Shutdown Notification
-  UINT8  Iosqes:4;   // I/O Submission Queue Entry Size
-  UINT8  Iocqes:4;   // I/O Completion Queue Entry Size
-  UINT8  Rsvd2;
-} NVME_CC;
-
-//
-// 3.1.6 Offset 1Ch: CSTS - Controller Status
-//
-typedef struct {
-  UINT32 Rdy:1;      // Ready
-  UINT32 Cfs:1;      // Controller Fatal Status
-  UINT32 Shst:2;     // Shutdown Status
-  UINT32 Nssro:1;    // NVM Subsystem Reset Occurred
-  UINT32 Rsvd1:27;
-} NVME_CSTS;
-
-//
-// 3.1.8 Offset 24h: AQA - Admin Queue Attributes
-//
-typedef struct {
-  UINT16 Asqs:12;    // Submission Queue Size
-  UINT16 Rsvd1:4;
-  UINT16 Acqs:12;    // Completion Queue Size
-  UINT16 Rsvd2:4;
-} NVME_AQA;
-
-//
-// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address
-//
-#define NVME_ASQ      UINT64
-
-//
-// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address
-//
-#define NVME_ACQ      UINT64
-
-//
-// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission Queue y Tail Doorbell
-//
-typedef struct {
-  UINT16 Sqt;
-  UINT16 Rsvd1;
-} NVME_SQTDBL;
-
-//
-// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL - Completion Queue y Head Doorbell
-//
-typedef struct {
-  UINT16 Cqh;
-  UINT16 Rsvd1;
-} NVME_CQHDBL;
-
-//
-// NVM command set structures
-//
-// Read Command
-//
-typedef struct {
-  //
-  // CDW 10, 11
-  //
-  UINT64 Slba;                /* Starting Sector Address */
-  //
-  // CDW 12
-  //
-  UINT16 Nlb;                 /* Number of Sectors */
-  UINT16 Rsvd1:10;
-  UINT16 Prinfo:4;            /* Protection Info Check */
-  UINT16 Fua:1;               /* Force Unit Access */
-  UINT16 Lr:1;                /* Limited Retry */
-  //
-  // CDW 13
-  //
-  UINT32 Af:4;                /* Access Frequency */
-  UINT32 Al:2;                /* Access Latency */
-  UINT32 Sr:1;                /* Sequential Request */
-  UINT32 In:1;                /* Incompressible */
-  UINT32 Rsvd2:24;
-  //
-  // CDW 14
-  //
-  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag */
-  //
-  // CDW 15
-  //
-  UINT16 Elbat;               /* Expected Logical Block Application Tag */
-  UINT16 Elbatm;              /* Expected Logical Block Application Tag Mask */
-} NVME_READ;
-
-//
-// Write Command
-//
-typedef struct {
-  //
-  // CDW 10, 11
-  //
-  UINT64 Slba;                /* Starting Sector Address */
-  //
-  // CDW 12
-  //
-  UINT16 Nlb;                 /* Number of Sectors */
-  UINT16 Rsvd1:10;
-  UINT16 Prinfo:4;            /* Protection Info Check */
-  UINT16 Fua:1;               /* Force Unit Access */
-  UINT16 Lr:1;                /* Limited Retry */
-  //
-  // CDW 13
-  //
-  UINT32 Af:4;                /* Access Frequency */
-  UINT32 Al:2;                /* Access Latency */
-  UINT32 Sr:1;                /* Sequential Request */
-  UINT32 In:1;                /* Incompressible */
-  UINT32 Rsvd2:24;
-  //
-  // CDW 14
-  //
-  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
-  //
-  // CDW 15
-  //
-  UINT16 Lbat;                /* Logical Block Application Tag */
-  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
-} NVME_WRITE;
-
-//
-// Flush
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Flush;               /* Flush */
-} NVME_FLUSH;
-
-//
-// Write Uncorrectable command
-//
-typedef struct {
-  //
-  // CDW 10, 11
-  //
-  UINT64 Slba;                /* Starting LBA */
-  //
-  // CDW 12
-  //
-  UINT32 Nlb:16;              /* Number of  Logical Blocks */
-  UINT32 Rsvd1:16;
-} NVME_WRITE_UNCORRECTABLE;
-
-//
-// Write Zeroes command
-//
-typedef struct {
-  //
-  // CDW 10, 11
-  //
-  UINT64 Slba;                /* Starting LBA */
-  //
-  // CDW 12
-  //
-  UINT16 Nlb;                 /* Number of Logical Blocks */
-  UINT16 Rsvd1:10;
-  UINT16 Prinfo:4;            /* Protection Info Check */
-  UINT16 Fua:1;               /* Force Unit Access */
-  UINT16 Lr:1;                /* Limited Retry */
-  //
-  // CDW 13
-  //
-  UINT32 Rsvd2;
-  //
-  // CDW 14
-  //
-  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
-  //
-  // CDW 15
-  //
-  UINT16 Lbat;                /* Logical Block Application Tag */
-  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
-} NVME_WRITE_ZEROES;
-
-//
-// Compare command
-//
-typedef struct {
-  //
-  // CDW 10, 11
-  //
-  UINT64 Slba;                /* Starting LBA */
-  //
-  // CDW 12
-  //
-  UINT16 Nlb;                 /* Number of Logical Blocks */
-  UINT16 Rsvd1:10;
-  UINT16 Prinfo:4;            /* Protection Info Check */
-  UINT16 Fua:1;               /* Force Unit Access */
-  UINT16 Lr:1;                /* Limited Retry */
-  //
-  // CDW 13
-  //
-  UINT32 Rsvd2;
-  //
-  // CDW 14
-  //
-  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag */
-  //
-  // CDW 15
-  //
-  UINT16 Elbat;               /* Expected Logical Block Application Tag */
-  UINT16 Elbatm;              /* Expected Logical Block Application Tag Mask */
-} NVME_COMPARE;
-
-typedef union {
-  NVME_READ                   Read;
-  NVME_WRITE                  Write;
-  NVME_FLUSH                  Flush;
-  NVME_WRITE_UNCORRECTABLE    WriteUncorrectable;
-  NVME_WRITE_ZEROES           WriteZeros;
-  NVME_COMPARE                Compare;
-} NVME_CMD;
-
-typedef struct {
-  UINT16 Mp;                /* Maximum Power */
-  UINT8  Rsvd1;             /* Reserved as of Nvm Express 1.1 Spec */
-  UINT8  Mps:1;             /* Max Power Scale */
-  UINT8  Nops:1;            /* Non-Operational State */
-  UINT8  Rsvd2:6;           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT32 Enlat;             /* Entry Latency */
-  UINT32 Exlat;             /* Exit Latency */
-  UINT8  Rrt:5;             /* Relative Read Throughput */
-  UINT8  Rsvd3:3;           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT8  Rrl:5;             /* Relative Read Leatency */
-  UINT8  Rsvd4:3;           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT8  Rwt:5;             /* Relative Write Throughput */
-  UINT8  Rsvd5:3;           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT8  Rwl:5;             /* Relative Write Leatency */
-  UINT8  Rsvd6:3;           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT8  Rsvd7[16];         /* Reserved as of Nvm Express 1.1 Spec */
-} NVME_PSDESCRIPTOR;
-
-//
-//  Identify Controller Data
-//
-typedef struct {
-  //
-  // Controller Capabilities and Features 0-255
-  //
-  UINT16 Vid;                 /* PCI Vendor ID */
-  UINT16 Ssvid;               /* PCI sub-system vendor ID */
-  UINT8  Sn[20];              /* Produce serial number */
-
-  UINT8  Mn[40];              /* Proeduct model number */
-  UINT8  Fr[8];               /* Firmware Revision */
-  UINT8  Rab;                 /* Recommended Arbitration Burst */
-  UINT8  Ieee_oiu[3];         /* Organization Unique Identifier */
-  UINT8  Cmic;                /* Multi-interface Capabilities */
-  UINT8  Mdts;                /* Maximum Data Transfer Size */
-  UINT8  Cntlid[2];           /* Controller ID */
-  UINT8  Rsvd1[176];          /* Reserved as of Nvm Express 1.1 Spec */
-  //
-  // Admin Command Set Attributes
-  //
-  UINT16 Oacs;                /* Optional Admin Command Support */
-  UINT8  Acl;                 /* Abort Command Limit */
-  UINT8  Aerl;                /* Async Event Request Limit */
-  UINT8  Frmw;                /* Firmware updates */
-  UINT8  Lpa;                 /* Log Page Attributes */
-  UINT8  Elpe;                /* Error Log Page Entries */
-  UINT8  Npss;                /* Number of Power States Support */
-  UINT8  Avscc;               /* Admin Vendor Specific Command Configuration */
-  UINT8  Apsta;               /* Autonomous Power State Transition Attributes */
-  UINT8  Rsvd2[246];          /* Reserved as of Nvm Express 1.1 Spec */
-  //
-  // NVM Command Set Attributes
-  //
-  UINT8  Sqes;                /* Submission Queue Entry Size */
-  UINT8  Cqes;                /* Completion Queue Entry Size */
-  UINT16 Rsvd3;               /* Reserved as of Nvm Express 1.1 Spec */
-  UINT32 Nn;                  /* Number of Namespaces */
-  UINT16 Oncs;                /* Optional NVM Command Support */
-  UINT16 Fuses;               /* Fused Operation Support */
-  UINT8  Fna;                 /* Format NVM Attributes */
-  UINT8  Vwc;                 /* Volatile Write Cache */
-  UINT16 Awun;                /* Atomic Write Unit Normal */
-  UINT16 Awupf;               /* Atomic Write Unit Power Fail */
-  UINT8  Nvscc;               /* NVM Vendor Specific Command Configuration */
-  UINT8  Rsvd4;               /* Reserved as of Nvm Express 1.1 Spec */
-  UINT16 Acwu;                /* Atomic Compare & Write Unit */
-  UINT16 Rsvd5;               /* Reserved as of Nvm Express 1.1 Spec */
-  UINT32 Sgls;                /* SGL Support  */
-  UINT8  Rsvd6[164];          /* Reserved as of Nvm Express 1.1 Spec */
-  //
-  // I/O Command set Attributes
-  //
-  UINT8 Rsvd7[1344];          /* Reserved as of Nvm Express 1.1 Spec */
-  //
-  // Power State Descriptors
-  //
-  NVME_PSDESCRIPTOR PsDescriptor[32];
-
-  UINT8  VendorData[1024];    /* Vendor specific Data */
-} NVME_ADMIN_CONTROLLER_DATA;
-
-typedef struct {
-  UINT16        Security  : 1;    /* supports security send/receive commands */
-  UINT16        Format    : 1;    /* supports format nvm command */
-  UINT16        Firmware  : 1;    /* supports firmware activate/download commands */
-  UINT16        Oacs_rsvd : 13;
- } OACS; // optional admin command support: NVME_ADMIN_CONTROLLER_DATA.Oacs
-
-typedef struct {
-  UINT16 Ms;                /* Metadata Size */
-  UINT8  Lbads;             /* LBA Data Size */
-  UINT8  Rp:2;              /* Relative Performance */
-    #define LBAF_RP_BEST      00b
-    #define LBAF_RP_BETTER    01b
-    #define LBAF_RP_GOOD      10b
-    #define LBAF_RP_DEGRADED  11b
-  UINT8  Rsvd1:6;           /* Reserved as of Nvm Express 1.1 Spec */
-} NVME_LBAFORMAT;
-
-//
-// Identify Namespace Data
-//
-typedef struct {
-  //
-  // NVM Command Set Specific
-  //
-  UINT64 Nsze;                /* Namespace Size (total number of blocks in formatted namespace) */
-  UINT64 Ncap;                /* Namespace Capacity (max number of logical blocks) */
-  UINT64 Nuse;                /* Namespace Utilization */
-  UINT8  Nsfeat;              /* Namespace Features */
-  UINT8  Nlbaf;               /* Number of LBA Formats */
-  UINT8  Flbas;               /* Formatted LBA Size */
-  UINT8  Mc;                  /* Metadata Capabilities */
-  UINT8  Dpc;                 /* End-to-end Data Protection capabilities */
-  UINT8  Dps;                 /* End-to-end Data Protection Type Settings */
-  UINT8  Nmic;                /* Namespace Multi-path I/O and Namespace Sharing Capabilities */
-  UINT8  Rescap;              /* Reservation Capabilities */
-  UINT8  Rsvd1[88];           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT64 Eui64;               /* IEEE Extended Unique Identifier */
-  //
-  // LBA Format
-  //
-  NVME_LBAFORMAT LbaFormat[16];
-
-  UINT8 Rsvd2[192];           /* Reserved as of Nvm Express 1.1 Spec */
-  UINT8 VendorData[3712];     /* Vendor specific Data */
-} NVME_ADMIN_NAMESPACE_DATA;
-
-//
-// NvmExpress Admin Identify Cmd
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Cns:2;
-  UINT32 Rsvd1:30;
-} NVME_ADMIN_IDENTIFY;
-
-//
-// NvmExpress Admin Create I/O Completion Queue
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Qid:16;              /* Queue Identifier */
-  UINT32 Qsize:16;            /* Queue Size */
-
-  //
-  // CDW 11
-  //
-  UINT32 Pc:1;                /* Physically Contiguous */
-  UINT32 Ien:1;               /* Interrupts Enabled */
-  UINT32 Rsvd1:14;            /* reserved as of Nvm Express 1.1 Spec */
-  UINT32 Iv:16;               /* Interrupt Vector */
-} NVME_ADMIN_CRIOCQ;
-
-//
-// NvmExpress Admin Create I/O Submission Queue
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Qid:16;              /* Queue Identifier */
-  UINT32 Qsize:16;            /* Queue Size */
-
-  //
-  // CDW 11
-  //
-  UINT32 Pc:1;                /* Physically Contiguous */
-  UINT32 Qprio:2;             /* Queue Priority */
-  UINT32 Rsvd1:13;            /* Reserved as of Nvm Express 1.1 Spec */
-  UINT32 Cqid:16;             /* Completion Queue ID */
-} NVME_ADMIN_CRIOSQ;
-
-//
-// NvmExpress Admin Delete I/O Completion Queue
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT16 Qid;
-  UINT16 Rsvd1;
-} NVME_ADMIN_DEIOCQ;
-
-//
-// NvmExpress Admin Delete I/O Submission Queue
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT16 Qid;
-  UINT16 Rsvd1;
-} NVME_ADMIN_DEIOSQ;
-
-//
-// NvmExpress Admin Security Send
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Resv:8;              /* Reserve */
-  UINT32 Spsp:16;             /* SP Specific */
-  UINT32 Secp:8;              /* Security Protocol */
-
-  //
-  // CDW 11
-  //
-  UINT32 Tl;                  /* Transfer Length */
-} NVME_ADMIN_SECSEND;
-
-//
-// NvmExpress Admin Abort Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Sqid:16;             /* Submission Queue identifier */
-  UINT32 Cid:16;              /* Command Identifier */
-} NVME_ADMIN_ABORT;
-
-//
-// NvmExpress Admin Firmware Activate Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Fs:3;                /* Submission Queue identifier */
-  UINT32 Aa:2;                /* Command Identifier */
-  UINT32 Rsvd1:27;
-} NVME_ADMIN_FIRMWARE_ACTIVATE;
-
-//
-// NvmExpress Admin Firmware Image Download Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Numd;                /* Number of Dwords */
-  //
-  // CDW 11
-  //
-  UINT32 Ofst;                /* Offset */
-} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD;
-
-//
-// NvmExpress Admin Get Features Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Fid:8;                /* Feature Identifier */
-  UINT32 Sel:3;                /* Select */
-  UINT32 Rsvd1:21;
-} NVME_ADMIN_GET_FEATURES;
-
-//
-// NvmExpress Admin Get Log Page Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Lid:8;               /* Log Page Identifier */
-    #define LID_ERROR_INFO
-    #define LID_SMART_INFO
-    #define LID_FW_SLOT_INFO
-  UINT32 Rsvd1:8;
-  UINT32 Numd:12;             /* Number of Dwords */
-  UINT32 Rsvd2:4;             /* Reserved as of Nvm Express 1.1 Spec */
-} NVME_ADMIN_GET_LOG_PAGE;
-
-//
-// NvmExpress Admin Set Features Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Fid:8;               /* Feature Identifier */
-  UINT32 Rsvd1:23;
-  UINT32 Sv:1;                /* Save */
-} NVME_ADMIN_SET_FEATURES;
-
-//
-// NvmExpress Admin Format NVM Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Lbaf:4;              /* LBA Format */
-  UINT32 Ms:1;                /* Metadata Settings */
-  UINT32 Pi:3;                /* Protection Information */
-  UINT32 Pil:1;               /* Protection Information Location */
-  UINT32 Ses:3;               /* Secure Erase Settings */
-  UINT32 Rsvd1:20;
-} NVME_ADMIN_FORMAT_NVM;
-
-//
-// NvmExpress Admin Security Receive Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Rsvd1:8;
-  UINT32 Spsp:16;             /* SP Specific */
-  UINT32 Secp:8;              /* Security Protocol */
-  //
-  // CDW 11
-  //
-  UINT32 Al;                  /* Allocation Length */
-} NVME_ADMIN_SECURITY_RECEIVE;
-
-//
-// NvmExpress Admin Security Send Command
-//
-typedef struct {
-  //
-  // CDW 10
-  //
-  UINT32 Rsvd1:8;
-  UINT32 Spsp:16;             /* SP Specific */
-  UINT32 Secp:8;              /* Security Protocol */
-  //
-  // CDW 11
-  //
-  UINT32 Tl;                  /* Transfer Length */
-} NVME_ADMIN_SECURITY_SEND;
-
-typedef union {
-  NVME_ADMIN_IDENTIFY                   Identify;
-  NVME_ADMIN_CRIOCQ                     CrIoCq;
-  NVME_ADMIN_CRIOSQ                     CrIoSq;
-  NVME_ADMIN_DEIOCQ                     DeIoCq;
-  NVME_ADMIN_DEIOSQ                     DeIoSq;
-  NVME_ADMIN_ABORT                      Abort;
-  NVME_ADMIN_FIRMWARE_ACTIVATE          Activate;
-  NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD    FirmwareImageDownload;
-  NVME_ADMIN_GET_FEATURES               GetFeatures;
-  NVME_ADMIN_GET_LOG_PAGE               GetLogPage;
-  NVME_ADMIN_SET_FEATURES               SetFeatures;
-  NVME_ADMIN_FORMAT_NVM                 FormatNvm;
-  NVME_ADMIN_SECURITY_RECEIVE           SecurityReceive;
-  NVME_ADMIN_SECURITY_SEND              SecuritySend;
-} NVME_ADMIN_CMD;
-
-typedef struct {
-  UINT32 Cdw10;
-  UINT32 Cdw11;
-  UINT32 Cdw12;
-  UINT32 Cdw13;
-  UINT32 Cdw14;
-  UINT32 Cdw15;
-} NVME_RAW;
-
-typedef union {
-  NVME_ADMIN_CMD Admin;   // Union of Admin commands
-  NVME_CMD       Nvm;     // Union of Nvm commands
-  NVME_RAW       Raw;
-} NVME_PAYLOAD;
-
-//
-// Submission Queue
-//
-typedef struct {
-  //
-  // CDW 0, Common to all comnmands
-  //
-  UINT8  Opc;               // Opcode
-  UINT8  Fuse:2;            // Fused Operation
-  UINT8  Rsvd1:5;
-  UINT8  Psdt:1;            // PRP or SGL for Data Transfer
-  UINT16 Cid;               // Command Identifier
-
-  //
-  // CDW 1
-  //
-  UINT32 Nsid;              // Namespace Identifier
-
-  //
-  // CDW 2,3
-  //
-  UINT64 Rsvd2;
-
-  //
-  // CDW 4,5
-  //
-  UINT64 Mptr;              // Metadata Pointer
-
-  //
-  // CDW 6-9
-  //
-  UINT64 Prp[2];            // First and second PRP entries
-
-  NVME_PAYLOAD Payload;
-
-} NVME_SQ;
-
-//
-// Completion Queue
-//
-typedef struct {
-  //
-  // CDW 0
-  //
-  UINT32 Dword0;
-  //
-  // CDW 1
-  //
-  UINT32 Rsvd1;
-  //
-  // CDW 2
-  //
-  UINT16 Sqhd;              // Submission Queue Head Pointer
-  UINT16 Sqid;              // Submission Queue Identifier
-  //
-  // CDW 3
-  //
-  UINT16 Cid;               // Command Identifier
-  UINT16 Pt:1;              // Phase Tag
-  UINT16 Sc:8;              // Status Code
-  UINT16 Sct:3;             // Status Code Type
-  UINT16 Rsvd2:2;
-  UINT16 Mo:1;              // More
-  UINT16 Dnr:1;             // Retry
-} NVME_CQ;
-
-//
-// Nvm Express Admin cmd opcodes
-//
-#define NVME_ADMIN_DELIOSQ_OPC               0
-#define NVME_ADMIN_CRIOSQ_OPC                1
-#define NVME_ADMIN_DELIOCQ_OPC               4
-#define NVME_ADMIN_CRIOCQ_OPC                5
-#define NVME_ADMIN_IDENTIFY_OPC              6
-#define NVME_ADMIN_SECURITY_SEND_OPC         0x81
-#define NVME_ADMIN_SECURITY_RECV_OPC         0x82
-
-#define NVME_IO_FLUSH_OPC                    0
-#define NVME_IO_WRITE_OPC                    1
-#define NVME_IO_READ_OPC                     2
-
-//
-// Offset from the beginning of private Data queue Buffer
-//
-#define NVME_ASQ_BUF_OFFSET                  EFI_PAGE_SIZE
-
-#pragma pack()
-
-#endif
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c
deleted file mode 100644
index 0ea92b15c067..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c
+++ /dev/null
@@ -1,1088 +0,0 @@
-/** @file
-  Opal password smm driver which is used to support Opal security feature at s3 path.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalPasswordSmm.h"
-
-#define SMM_SIZE_ALLOC_BYTES                      (512)
-#define RESPONSE_SIZE                             (200)
-
-#define PCI_CLASS_MASS_STORAGE_AHCI               (0x06)
-
-#define OPAL_PCIE_ROOTPORT_SAVESIZE               (0x40)
-#define STORE_INVALID_ROOTPORT_INDEX              ((UINT8) -1)
-#define OPAL_DEVICE_TYPE_SATA                     0x1
-#define OPAL_DEVICE_TYPE_NVME                     0x2
-#define OPAL_DEVICE_TYPE_UNKNOWN                  0xFF
-
-//
-// To unlock the Intel SATA controller at S3 Resume, restored the following registers.
-//
-const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {
-  {0x9,  S3BootScriptWidthUint8},
-  {0x10, S3BootScriptWidthUint32},
-  {0x14, S3BootScriptWidthUint32},
-  {0x18, S3BootScriptWidthUint32},
-  {0x1C, S3BootScriptWidthUint32},
-  {0x20, S3BootScriptWidthUint32},
-  {0x24, S3BootScriptWidthUint32},
-  {0x3c, S3BootScriptWidthUint8},
-  {0x3d, S3BootScriptWidthUint8},
-  {0x40, S3BootScriptWidthUint16},
-  {0x42, S3BootScriptWidthUint16},
-  {0x92, S3BootScriptWidthUint16},
-  {0x94, S3BootScriptWidthUint32},
-  {0x9C, S3BootScriptWidthUint32},
-  {0x4,  S3BootScriptWidthUint16},
-};
-
-
-UINT8                mSwSmiValue;
-LIST_ENTRY           *mOpalDeviceList;
-LIST_ENTRY           mSmmDeviceList  = INITIALIZE_LIST_HEAD_VARIABLE (mSmmDeviceList);
-
-BOOLEAN              mSendBlockSID   = FALSE;
-
-// AHCI
-UINT32               mAhciBar = 0;
-EFI_AHCI_REGISTERS   mAhciRegisters;
-VOID                 *mBuffer = NULL; // DMA can not read/write Data to smram, so we pre-allocates Buffer from AcpiNVS.
-//
-// NVME
-NVME_CONTEXT         mNvmeContext;
-
-/**
-  Add new bridge node or nvme device info to the device list.
-
-  @param[in]       BusNum        The bus number.
-  @param[in]       DevNum        The device number.
-  @param[in]       FuncNum       The function number.
-  @param[in]       Dev           The device which need to add device node info.
-
-**/
-VOID
-AddPciDeviceNode (
-  UINT32                  BusNum,
-  UINT32                  DevNum,
-  UINT32                  FuncNum,
-  OPAL_SMM_DEVICE         *Dev
-  )
-{
-  UINT8       *DevList;
-  PCI_DEVICE  *DeviceNode;
-
-  DevList = AllocateZeroPool (sizeof (PCI_DEVICE) + Dev->Length);
-  ASSERT (DevList != NULL);
-
-  if (Dev->Length != 0) {
-    CopyMem (DevList, Dev->PciBridgeNode, Dev->Length);
-    FreePool (Dev->PciBridgeNode);
-  }
-
-  DeviceNode = (PCI_DEVICE *) (DevList + Dev->Length);
-
-  DeviceNode->BusNum  = BusNum;
-  DeviceNode->DevNum  = DevNum;
-  DeviceNode->FuncNum = FuncNum;
-
-  Dev->Length += sizeof (PCI_DEVICE);
-  Dev->PciBridgeNode = (PCI_DEVICE *)DevList;
-}
-
-/**
-  Extract device info from the input device path.
-
-  @param[in]       DevicePath        Device path info for the device.
-  @param[in,out]   Dev               The device which new inputed.
-
-**/
-VOID
-ExtractDeviceInfoFromDevicePath (
-  IN     EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
-  IN OUT OPAL_SMM_DEVICE             *Dev
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath;
-  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath2;
-  PCI_DEVICE_PATH               *PciDevPath;
-  SATA_DEVICE_PATH              *SataDevPath;
-  NVME_NAMESPACE_DEVICE_PATH    *NvmeDevPath;
-  UINTN                         BusNum;
-
-  TmpDevPath = DevicePath;
-  Dev->DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;
-
-  while (!IsDevicePathEnd(TmpDevPath)) {
-    if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {
-      //
-      // SATA
-      //
-      SataDevPath = ( SATA_DEVICE_PATH* )TmpDevPath;
-      Dev->SataPort = SataDevPath->HBAPortNumber;
-      Dev->SataPortMultiplierPort = SataDevPath->PortMultiplierPortNumber;
-      Dev->DeviceType = OPAL_DEVICE_TYPE_SATA;
-      break;
-    } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {
-      //
-      // NVMe
-      //
-      NvmeDevPath = ( NVME_NAMESPACE_DEVICE_PATH* )TmpDevPath;
-      Dev->NvmeNamespaceId = NvmeDevPath->NamespaceId;
-      Dev->DeviceType = OPAL_DEVICE_TYPE_NVME;
-      break;
-    }
-    TmpDevPath = NextDevicePathNode (TmpDevPath);
-  }
-
-  //
-  // Get bridge node info for the nvme device.
-  //
-  BusNum = 0;
-  TmpDevPath = DevicePath;
-  TmpDevPath2 = NextDevicePathNode (DevicePath);
-  while (!IsDevicePathEnd(TmpDevPath2)) {
-    if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {
-      PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
-      if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||
-          (TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {
-        Dev->BusNum = (UINT32)BusNum;
-        Dev->DevNum = PciDevPath->Device;
-        Dev->FuncNum = PciDevPath->Function;
-      } else {
-        AddPciDeviceNode((UINT32)BusNum, PciDevPath->Device, PciDevPath->Function, Dev);
-        if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {
-          BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, NVME_PCIE_SEC_BNUM));
-        }
-      }
-    }
-
-    TmpDevPath  = NextDevicePathNode (TmpDevPath);
-    TmpDevPath2 = NextDevicePathNode (TmpDevPath2);
-  }
-}
-
-/**
-
-  The function returns whether or not the device is Opal Locked.
-  TRUE means that the device is partially or fully locked.
-  This will perform a Level 0 Discovery and parse the locking feature descriptor
-
-  @param[in]      OpalDev             Opal object to determine if locked
-  @param[out]     BlockSidSupported   Whether device support BlockSid feature.
-
-**/
-BOOLEAN
-IsOpalDeviceLocked(
-  OPAL_SMM_DEVICE    *OpalDev,
-  BOOLEAN            *BlockSidSupported
-  )
-{
-  OPAL_SESSION                   Session;
-  OPAL_DISK_SUPPORT_ATTRIBUTE    SupportedAttributes;
-  TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;
-  UINT16                         OpalBaseComId;
-  TCG_RESULT                     Ret;
-
-  Session.Sscp = &OpalDev->Sscp;
-  Session.MediaId = 0;
-
-  Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes, &OpalBaseComId);
-  if (Ret != TcgResultSuccess) {
-    return FALSE;
-  }
-
-  OpalDev->OpalBaseComId = OpalBaseComId;
-  Session.OpalBaseComId  = OpalBaseComId;
-  *BlockSidSupported     = SupportedAttributes.BlockSid == 1 ? TRUE : FALSE;
-
-  Ret = OpalGetLockingInfo(&Session, &LockingFeature);
-  if (Ret != TcgResultSuccess) {
-    return FALSE;
-  }
-
-  return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);
-}
-
-/**
-  Save/Restore RootPort configuration space.
-
-  @param[in] DeviceNode             - The device node.
-  @param[in] SaveAction             - TRUE: Save, FALSE: Restore
-  @param[in,out] PcieConfBufferList     - Configuration space data buffer for save/restore
-
-  @retval - PCIE base address of this RootPort
-**/
-UINTN
-SaveRestoreRootportConfSpace (
-  IN     OPAL_SMM_DEVICE                *DeviceNode,
-  IN     BOOLEAN                        SaveAction,
-  IN OUT UINT8                          **PcieConfBufferList
-  )
-{
-  UINTN      RpBase;
-  UINTN      Length;
-  PCI_DEVICE *DevNode;
-  UINT8      *StorePcieConfData;
-  UINTN      Index;
-
-  Length = 0;
-  Index  = 0;
-  RpBase = 0;
-
-  while (Length < DeviceNode->Length) {
-    DevNode = (PCI_DEVICE *)((UINT8*)DeviceNode->PciBridgeNode + Length);
-    RpBase = PCI_LIB_ADDRESS (DevNode->BusNum, DevNode->DevNum, DevNode->FuncNum, 0x0);
-
-    if (PcieConfBufferList != NULL) {
-      if (SaveAction) {
-        StorePcieConfData = (UINT8 *) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE);
-        ASSERT (StorePcieConfData != NULL);
-        OpalPciRead (StorePcieConfData, RpBase, OPAL_PCIE_ROOTPORT_SAVESIZE);
-        PcieConfBufferList[Index] = StorePcieConfData;
-      } else {
-        // Skip PCIe Command & Status registers
-        StorePcieConfData = PcieConfBufferList[Index];
-        OpalPciWrite (RpBase, StorePcieConfData, 4);
-        OpalPciWrite (RpBase + 8, StorePcieConfData + 8, OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
-
-        FreePool (StorePcieConfData);
-      }
-    }
-
-    Length += sizeof (PCI_DEVICE);
-    Index ++;
-  }
-
-  return RpBase;
-}
-
-/**
-  Configure RootPort for downstream PCIe NAND devices.
-
-  @param[in] RpBase             - PCIe configuration space address of this RootPort
-  @param[in] BusNumber          - Bus number
-  @param[in] MemoryBase         - Memory base address
-  @param[in] MemoryLength       - Memory size
-
-**/
-VOID
-ConfigureRootPortForPcieNand (
-  IN UINTN   RpBase,
-  IN UINTN   BusNumber,
-  IN UINT32  MemoryBase,
-  IN UINT32  MemoryLength
-  )
-{
-  UINT32  MemoryLimit;
-
-  DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",
-    BusNumber, MemoryBase, MemoryLength));
-
-  if (MemoryLength == 0) {
-    MemoryLimit = MemoryBase;
-  } else {
-    MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
-  }
-
-  ///
-  /// Configue PCIE configuration space for RootPort
-  ///
-  PciWrite8  (RpBase + NVME_PCIE_BNUM + 1,  (UINT8) BusNumber);           // Secondary Bus Number registers
-  PciWrite8  (RpBase + NVME_PCIE_BNUM + 2,  (UINT8) BusNumber);           // Subordinate Bus Number registers
-  PciWrite8  (RpBase + NVME_PCIE_IOBL,      0xFF);                        // I/O Base registers
-  PciWrite8  (RpBase + NVME_PCIE_IOBL + 1,  0x00);                        // I/O Limit registers
-  PciWrite16 (RpBase + NVME_PCIE_MBL,       (UINT16) RShiftU64 ((UINTN)MemoryBase, 16));  // Memory Base register
-  PciWrite16 (RpBase + NVME_PCIE_MBL + 2,   (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register
-  PciWrite16 (RpBase + NVME_PCIE_PMBL,      0xFFFF);                      // Prefetchable Memory Base registers
-  PciWrite16 (RpBase + NVME_PCIE_PMBL + 2,  0x0000);                      // Prefetchable Memory Limit registers
-  PciWrite32 (RpBase + NVME_PCIE_PMBU32,    0xFFFFFFFF);                  // Prefetchable Memory Upper Base registers
-  PciWrite32 (RpBase + NVME_PCIE_PMLU32,    0x00000000);                  // Prefetchable Memory Upper Limit registers
-}
-
-
-/**
-  Dispatch function for a Software SMI handler.
-
-  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
-  @param[in]     RegisterContext Points to an optional handler context which was specified when the
-                                 handler was registered.
-  @param[in, out] CommBuffer     A pointer to a collection of Data in memory that will
-                                 be conveyed from a non-SMM environment into an SMM environment.
-  @param[in, out] CommBufferSize The Size of the CommBuffer.
-
-  @retval EFI_SUCCESS            The interrupt was handled and quiesced. No other handlers
-                                 should still be called.
-  @retval Others                 Other execution results.
-**/
-EFI_STATUS
-EFIAPI
-SmmUnlockOpalPassword (
-  IN     EFI_HANDLE              DispatchHandle,
-  IN     CONST VOID              *RegisterContext,
-  IN OUT VOID                    *CommBuffer,
-  IN OUT UINTN                   *CommBufferSize
-  )
-{
-  EFI_STATUS                     Status;
-  OPAL_SMM_DEVICE                *OpalDev;
-  LIST_ENTRY                     *Entry;
-  UINT8                          BaseClassCode;
-  UINT8                          SubClassCode;
-  UINT8                          ProgInt;
-  TCG_RESULT                     Result;
-  UINT8                          SataCmdSt;
-  UINT8                          *StorePcieConfDataList[16];
-  UINTN                          RpBase;
-  UINTN                          MemoryBase;
-  UINTN                          MemoryLength;
-  OPAL_SESSION                   Session;
-  BOOLEAN                        BlockSidSupport;
-
-  ZeroMem (StorePcieConfDataList, sizeof (StorePcieConfDataList));
-  Status = EFI_DEVICE_ERROR;
-
-  //
-  // try to unlock all locked hdd disks.
-  //
-  for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) {
-    OpalDev = BASE_CR(Entry, OPAL_SMM_DEVICE, Link);
-
-    RpBase    = 0;
-    SataCmdSt = 0;
-
-    ///
-    /// Configure RootPort for PCIe AHCI/NVME devices.
-    ///
-    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
-      ///
-      /// Save original RootPort configuration space to heap
-      ///
-      RpBase = SaveRestoreRootportConfSpace (
-                  OpalDev,
-                  TRUE,
-                  StorePcieConfDataList
-                  );
-      MemoryBase = mNvmeContext.Nbar;
-      MemoryLength = 0;
-      ConfigureRootPortForPcieNand (RpBase, OpalDev->BusNum, (UINT32) MemoryBase, (UINT32) MemoryLength);
-
-      ///
-      /// Enable PCIE decode for RootPort
-      ///
-      SataCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
-      PciWrite8  (RpBase + NVME_PCIE_PCICMD,  0x6);
-    } else {
-      SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD));
-      PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), 0x6);
-    }
-
-    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0B));
-    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0A));
-    ProgInt       = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x09));
-    if (BaseClassCode != PCI_CLASS_MASS_STORAGE) {
-      Status = EFI_INVALID_PARAMETER;
-      break;
-    }
-
-    Status = EFI_DEVICE_ERROR;
-    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {
-      if ((SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) || (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) {
-        Status = GetAhciBaseAddress (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum);
-        if (EFI_ERROR (Status)) {
-          DEBUG ((DEBUG_ERROR, "GetAhciBaseAddress error, Status: %r\n", Status));
-          goto done;
-        }
-        Status = AhciModeInitialize ((UINT8)OpalDev->SataPort);
-        ASSERT_EFI_ERROR (Status);
-        if (EFI_ERROR (Status)) {
-          DEBUG ((DEBUG_ERROR, "AhciModeInitialize error, Status: %r\n", Status));
-          goto done;
-        }
-      } else {
-        DEBUG ((DEBUG_ERROR, "SubClassCode not support for SATA device\n"));
-      }
-    } else if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
-      if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {
-        if (ProgInt != PCI_IF_NVMHCI) {
-          DEBUG ((DEBUG_ERROR, "PI not support, skipped\n"));
-          Status = EFI_NOT_FOUND;
-          goto done;
-        }
-
-        mNvmeContext.PciBase = PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0);
-        mNvmeContext.NvmeInitWaitTime = 0;
-        mNvmeContext.Nsid = OpalDev->NvmeNamespaceId;
-        Status = NvmeControllerInit (&mNvmeContext);
-      } else {
-        DEBUG ((DEBUG_ERROR, "SubClassCode not support for NVME device\n"));
-      }
-    } else {
-      DEBUG ((DEBUG_ERROR, "Invalid Devicetype\n"));
-      goto done;
-    }
-
-    Status = EFI_DEVICE_ERROR;
-    BlockSidSupport = FALSE;
-    if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
-      ZeroMem(&Session, sizeof(Session));
-      Session.Sscp = &OpalDev->Sscp;
-      Session.MediaId = 0;
-      Session.OpalBaseComId = OpalDev->OpalBaseComId;
-
-      Result = OpalSupportUnlock (&Session, OpalDev->Password, OpalDev->PasswordLength, NULL);
-      if (Result == TcgResultSuccess) {
-        Status = EFI_SUCCESS;
-      }
-    }
-
-    if (mSendBlockSID && BlockSidSupport) {
-      Result = OpalBlockSid (&Session, TRUE);
-      if (Result != TcgResultSuccess) {
-        break;
-      }
-    }
-
-    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
-      if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {
-        Status = NvmeControllerExit (&mNvmeContext);
-      }
-    }
-
-done:
-    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
-      ASSERT (RpBase != 0);
-      PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);
-      RpBase = SaveRestoreRootportConfSpace (
-                  OpalDev,
-                  FALSE,  // restore
-                  StorePcieConfDataList
-                  );
-      PciWrite8  (RpBase + NVME_PCIE_PCICMD, SataCmdSt);
-    } else {
-      PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), SataCmdSt);
-    }
-
-    if (EFI_ERROR (Status)) {
-      break;
-    }
-  }
-
-  return Status;
-}
-
-/**
-  The function extracts device information from OpalDeviceList and creat SmmDeviceList used for S3.
-
-  @param[in]       OpalDeviceList   Opal device list created at POST which contains the information of OPAL_DISK_AND_PASSWORD_INFO
-  @param[in,out]   SmmDeviceList    Opal Smm device list to be created and used for unlocking devices at S3 resume.
-
-  @retval EFI_SUCCESS            Create SmmDeviceList successfully.
-  @retval Others                 Other execution results.
-**/
-EFI_STATUS
-CreateSmmDeviceList (
-  IN     LIST_ENTRY                 *OpalDeviceList,
-  IN OUT LIST_ENTRY                 *SmmDeviceList
-  )
-{
-  LIST_ENTRY                        *Entry;
-  OPAL_DISK_AND_PASSWORD_INFO       *PciDev;
-  OPAL_SMM_DEVICE                   *SmmDev;
-
-  for (Entry = OpalDeviceList->ForwardLink; Entry != OpalDeviceList; Entry = Entry->ForwardLink) {
-    PciDev = BASE_CR (Entry, OPAL_DISK_AND_PASSWORD_INFO, Link);
-
-    SmmDev = AllocateZeroPool (sizeof (OPAL_SMM_DEVICE));
-    if (SmmDev == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-    SmmDev->Signature = OPAL_SMM_DEVICE_SIGNATURE;
-
-    ExtractDeviceInfoFromDevicePath(&PciDev->OpalDevicePath, SmmDev);
-
-    SmmDev->PasswordLength = PciDev->PasswordLength;
-    CopyMem(&(SmmDev->Password), PciDev->Password, OPAL_PASSWORD_MAX_LENGTH);
-
-    SmmDev->Sscp.ReceiveData = SecurityReceiveData;
-    SmmDev->Sscp.SendData = SecuritySendData;
-
-    DEBUG ((DEBUG_INFO, "Opal SMM: Insert device node to SmmDeviceList:\n"));
-    DEBUG ((DEBUG_INFO, "DeviceType:%x, Bus:%d, Dev:%d, Fun:%d\n", \
-      SmmDev->DeviceType, SmmDev->BusNum, SmmDev->DevNum, SmmDev->FuncNum));
-    DEBUG ((DEBUG_INFO, "SataPort:%x, MultiplierPort:%x, NvmeNamespaceId:%x\n", \
-      SmmDev->SataPort, SmmDev->SataPortMultiplierPort, SmmDev->NvmeNamespaceId));
-
-    InsertHeadList (SmmDeviceList, &SmmDev->Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Main entry point for an SMM handler dispatch or communicate-based callback.
-
-  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
-  @param[in]     Context         Points to an optional handler context which was specified when the
-                                 handler was registered.
-  @param[in,out] CommBuffer      A pointer to a collection of Data in memory that will
-                                 be conveyed from a non-SMM environment into an SMM environment.
-  @param[in,out] CommBufferSize  The Size of the CommBuffer.
-
-  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
-                                              should still be called.
-  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
-                                              still be called.
-  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
-                                              be called.
-  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
-**/
-EFI_STATUS
-EFIAPI
-S3SleepEntryCallBack (
-  IN           EFI_HANDLE           DispatchHandle,
-  IN     CONST VOID                 *Context         OPTIONAL,
-  IN OUT       VOID                 *CommBuffer      OPTIONAL,
-  IN OUT       UINTN                *CommBufferSize  OPTIONAL
-  )
-{
-  UINTN                             Bus;
-  UINTN                             Device;
-  UINTN                             Function;
-  UINTN                             Index;
-  EFI_STATUS                        Status;
-  LIST_ENTRY                        *Entry;
-  UINTN                             Offset;
-  UINT64                            Address;
-  S3_BOOT_SCRIPT_LIB_WIDTH          Width;
-  UINT32                            Data;
-  OPAL_HC_PCI_REGISTER_SAVE         *HcRegisterSaveListPtr;
-  UINTN                             Count;
-  OPAL_SMM_DEVICE                   *SmmDev;
-
-  Data     = 0;
-  Status   = EFI_SUCCESS;
-
-  mOpalDeviceList = OpalSupportGetOpalDeviceList();
-  if (IsListEmpty (mOpalDeviceList)) {
-    //
-    // No Opal enabled device. Do nothing.
-    //
-    return EFI_SUCCESS;
-  }
-
-  if (IsListEmpty (&mSmmDeviceList)) {
-    //
-    // mSmmDeviceList for S3 is empty, creat it by mOpalDeviceList.
-    //
-    Status = CreateSmmDeviceList (mOpalDeviceList, &mSmmDeviceList);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
-
-  //
-  // Go through SmmDeviceList to save register data for S3
-  //
-  for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) {
-    SmmDev = BASE_CR (Entry, OPAL_SMM_DEVICE, Link);
-
-    if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
-      continue;
-    }
-
-    //
-    // Save register Data for S3. Sata controller only.
-    //
-    Bus        = SmmDev->BusNum;
-    Device     = SmmDev->DevNum;
-    Function   = SmmDev->FuncNum;
-
-    ASSERT (SmmDev->DeviceType == OPAL_DEVICE_TYPE_SATA);
-    HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;
-    Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);
-
-    for (Index = 0; Index < Count; Index += 1) {
-      Offset  = HcRegisterSaveListPtr[Index].Address;
-      Width   = HcRegisterSaveListPtr[Index].Width;
-
-      switch (Width) {
-        case S3BootScriptWidthUint8:
-          Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
-          break;
-        case S3BootScriptWidthUint16:
-          Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
-          break;
-        case S3BootScriptWidthUint32:
-          Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
-          break;
-        default:
-          ASSERT (FALSE);
-          break;
-      }
-
-      Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);
-      Status  = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-    }
-  }
-
-  Status = S3BootScriptSaveIoWrite (S3BootScriptWidthUint8, 0xB2, 1, &mSwSmiValue);
-  ASSERT_EFI_ERROR (Status);
-
-  return Status;
-}
-
-/**
-  Main entry for this driver.
-
-  @param ImageHandle     Image handle this driver.
-  @param SystemTable     Pointer to SystemTable.
-
-  @retval EFI_SUCESS     This function always complete successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalPasswordSmmInit (
-  IN EFI_HANDLE                         ImageHandle,
-  IN EFI_SYSTEM_TABLE                   *SystemTable
-  )
-{
-  EFI_STATUS                            Status;
-  EFI_SMM_SW_DISPATCH2_PROTOCOL         *SwDispatch;
-  EFI_SMM_SX_DISPATCH2_PROTOCOL         *SxDispatch;
-  EFI_HANDLE                            SwHandle;
-  EFI_SMM_SW_REGISTER_CONTEXT           Context;
-  EFI_HANDLE                            S3SleepEntryHandle;
-  EFI_SMM_SX_REGISTER_CONTEXT           EntryRegisterContext;
-  EFI_SMM_VARIABLE_PROTOCOL             *SmmVariable;
-  OPAL_EXTRA_INFO_VAR                   OpalExtraInfo;
-  UINTN                                 DataSize;
-  EFI_PHYSICAL_ADDRESS                  Address;
-
-  mBuffer            = NULL;
-  SwHandle           = NULL;
-  S3SleepEntryHandle = NULL;
-  ZeroMem (&mNvmeContext, sizeof (NVME_CONTEXT));
-
-  Status = gSmst->SmmLocateProtocol (
-                    &gEfiSmmSwDispatch2ProtocolGuid,
-                    NULL,
-                    (VOID **)&SwDispatch
-                    );
-  ASSERT_EFI_ERROR (Status);
-  if (EFI_ERROR (Status)) {
-    DEBUG((DEBUG_ERROR, " SmmLocateProtocol gEfiSmmSwDispatch2ProtocolGuid fail, Status: %r\n", Status));
-    return Status;
-  }
-
-  Status = gSmst->SmmLocateProtocol (
-                    &gEfiSmmSxDispatch2ProtocolGuid,
-                    NULL,
-                    (VOID **)&SxDispatch
-                    );
-  ASSERT_EFI_ERROR (Status);
-  if (EFI_ERROR (Status)) {
-    DEBUG((DEBUG_ERROR, " SmmLocateProtocol gEfiSmmSxDispatch2ProtocolGuid fail, Status: %r\n", Status));
-    return Status;
-  }
-
-  //
-  // Preallocate a 512 bytes Buffer to perform trusted I/O.
-  // Assume this is big enough for unlock commands
-  // It's because DMA can not access smmram stack at the cmd execution.
-  //
-  Address = 0xFFFFFFFF;
-  Status = gBS->AllocatePages (
-                  AllocateMaxAddress,
-                  EfiACPIMemoryNVS,
-                  EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES),
-                  &Address
-                  );
-  if (EFI_ERROR (Status)) {
-    DEBUG((DEBUG_ERROR, " AllocatePages for SATA DAM fail, Status: %r\n", Status));
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  mBuffer = (VOID *)(UINTN)Address;
-  ZeroMem ((VOID *)(UINTN)mBuffer, SMM_SIZE_ALLOC_BYTES);
-
-  //
-  // Preallocate resource for AHCI transfer descriptor.
-  //
-  Status = AhciAllocateResource ();
-  if (EFI_ERROR (Status)) {
-    DEBUG((DEBUG_ERROR, " AhciAllocateResource fail, Status: %r\n", Status));
-    Status = EFI_OUT_OF_RESOURCES;
-    goto EXIT;
-  }
-
-  //
-  // Preallocate resource for NVMe configuration space.
-  //
-  Status = NvmeAllocateResource (ImageHandle, &mNvmeContext);
-  if (EFI_ERROR (Status)) {
-    DEBUG((DEBUG_ERROR, " NvmeAllocateResource fail, Status: %r\n", Status));
-    Status = EFI_OUT_OF_RESOURCES;
-    goto EXIT;
-  }
-
-  //
-  // Register a S3 entry callback function to store ATA host controller context to boot script.
-  // These boot scripts would be invoked at S3 path to recovery ATA host controller h/w context
-  // for executing HDD unlock cmd.
-  //
-  EntryRegisterContext.Type  = SxS3;
-  EntryRegisterContext.Phase = SxEntry;
-  Status = SxDispatch->Register (
-                         SxDispatch,
-                         S3SleepEntryCallBack,
-                         &EntryRegisterContext,
-                         &S3SleepEntryHandle
-                         );
-  ASSERT_EFI_ERROR (Status);
-  if (EFI_ERROR (Status)) {
-    goto EXIT;
-  }
-
-  //
-  // Register Opal password smm unlock handler
-  //
-  Context.SwSmiInputValue = (UINTN) -1;
-  Status = SwDispatch->Register (
-               SwDispatch,
-               SmmUnlockOpalPassword,
-               &Context,
-               &SwHandle
-               );
-  ASSERT_EFI_ERROR (Status);
-  if (EFI_ERROR (Status)) {
-    DEBUG((DEBUG_ERROR, " SwDispatch->Register fail, Status: %r\n", Status));
-    goto EXIT;
-  }
-
-  //
-  // trigger smi to unlock hdd if it's locked.
-  //
-  mSwSmiValue = (UINT8) Context.SwSmiInputValue;
-
-  Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&SmmVariable);
-  if (!EFI_ERROR (Status)) {
-    DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
-    Status = SmmVariable->SmmGetVariable (
-                    OPAL_EXTRA_INFO_VAR_NAME,
-                    &gOpalExtraInfoVariableGuid,
-                    NULL,
-                    &DataSize,
-                    &OpalExtraInfo
-                    );
-    if (!EFI_ERROR (Status)) {
-      mSendBlockSID = OpalExtraInfo.EnableBlockSid;
-    }
-  }
-
-  return EFI_SUCCESS;
-
-EXIT:
-  if (S3SleepEntryHandle != NULL) {
-    SxDispatch->UnRegister (SxDispatch, S3SleepEntryHandle);
-  }
-
-  AhciFreeResource ();
-
-  NvmeFreeResource (&mNvmeContext);
-
-  if (mBuffer != NULL) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN) mBuffer, EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES));
-  }
-
-  return Status;
-}
-
-/**
-  Provide Io action support.
-
-  @param[in]     SmmDev             the opal device need to perform trust io.
-  @param[in]     IoType             OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.
-  @param[in]     SecurityProtocol   Security Protocol
-  @param[in]     SpSpecific         Security Protocol Specific
-  @param[in]     TransferLength     Transfer Length of Buffer (in bytes) - always a multiple of 512
-  @param[in]     Buffer             Address of Data to transfer
-
-  @retval        TcgResultSuccess   Perform the io action success.
-  @retval        TcgResultFailure   Perform the io action failed.
-
-**/
-EFI_STATUS
-PerformTrustedIo (
-  OPAL_SMM_DEVICE  *SmmDev,
-  OPAL_IO_TYPE     IoType,
-  UINT8            SecurityProtocol,
-  UINT16           SpSpecific,
-  UINTN            TransferLength,
-  VOID             *Buffer
-  )
-{
-  EFI_STATUS                   Status;
-  UINTN                        BufferSizeBlocks;
-  EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
-
-  Status = EFI_DEVICE_ERROR;
-  if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {
-    BufferSizeBlocks = TransferLength / 512;
-
-    ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
-    AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ? ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
-    AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
-    AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
-    AtaCommandBlock.AtaFeatures = SecurityProtocol;
-    AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
-    AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
-    AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
-
-
-    ZeroMem( mBuffer, HDD_PAYLOAD );
-    ASSERT( TransferLength <= HDD_PAYLOAD );
-
-    if (IoType == OpalSend) {
-      CopyMem( mBuffer, Buffer, TransferLength );
-    }
-
-    Status = AhciPioTransfer(
-                &mAhciRegisters,
-                (UINT8) SmmDev->SataPort,
-                (UINT8) SmmDev->SataPortMultiplierPort,
-                NULL,
-                0,
-                ( IoType == OpalSend ) ? FALSE : TRUE,   // i/o direction
-                &AtaCommandBlock,
-                NULL,
-                mBuffer,
-                (UINT32)TransferLength,
-                ATA_TIMEOUT
-                );
-
-    if (IoType == OpalRecv) {
-      CopyMem( Buffer, mBuffer, TransferLength );
-    }
-  } else if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
-    Status = NvmeSecuritySendReceive (
-                &mNvmeContext,
-                IoType == OpalSend,
-                SecurityProtocol,
-                SwapBytes16(SpSpecific),
-                TransferLength,
-                Buffer
-              );
-  } else {
-    DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", SmmDev->DeviceType));
-  }
-
-  return Status;
-}
-
-/**
-  Send a security protocol command to a device that receives data and/or the result
-  of one or more commands sent by SendData.
-
-  The ReceiveData function sends a security protocol command to the given MediaId.
-  The security protocol command sent is defined by SecurityProtocolId and contains
-  the security protocol specific data SecurityProtocolSpecificData. The function
-  returns the data from the security protocol command in PayloadBuffer.
-
-  For devices supporting the SCSI command set, the security protocol command is sent
-  using the SECURITY PROTOCOL IN command defined in SPC-4.
-
-  For devices supporting the ATA command set, the security protocol command is sent
-  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
-  is non-zero.
-
-  If the PayloadBufferSize is zero, the security protocol command is sent using the
-  Trusted Non-Data command defined in ATA8-ACS.
-
-  If PayloadBufferSize is too small to store the available data from the security
-  protocol command, the function shall copy PayloadBufferSize bytes into the
-  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
-
-  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
-  the function shall return EFI_INVALID_PARAMETER.
-
-  If the given MediaId does not support security protocol commands, the function shall
-  return EFI_UNSUPPORTED. If there is no media in the device, the function returns
-  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
-  the function returns EFI_MEDIA_CHANGED.
-
-  If the security protocol fails to complete within the Timeout period, the function
-  shall return EFI_TIMEOUT.
-
-  If the security protocol command completes without an error, the function shall
-  return EFI_SUCCESS. If the security protocol command completes with an error, the
-  function shall return EFI_DEVICE_ERROR.
-
-  @param  This                         Indicates a pointer to the calling context.
-  @param  MediaId                      ID of the medium to receive data from.
-  @param  Timeout                      The timeout, in 100ns units, to use for the execution
-                                       of the security protocol command. A Timeout value of 0
-                                       means that this function will wait indefinitely for the
-                                       security protocol command to execute. If Timeout is greater
-                                       than zero, then this function will return EFI_TIMEOUT
-                                       if the time required to execute the receive data command
-                                       is greater than Timeout.
-  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
-                                       the security protocol command to be sent.
-  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
-                                       of the security protocol command to be sent.
-  @param  PayloadBufferSize            Size in bytes of the payload data buffer.
-  @param  PayloadBuffer                A pointer to a destination buffer to store the security
-                                       protocol command specific payload data for the security
-                                       protocol command. The caller is responsible for having
-                                       either implicit or explicit ownership of the buffer.
-  @param  PayloadTransferSize          A pointer to a buffer to store the size in bytes of the
-                                       data written to the payload data buffer.
-
-  @retval EFI_SUCCESS                  The security protocol command completed successfully.
-  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too small to store the available
-                                       data from the device. The PayloadBuffer contains the truncated data.
-  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
-  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
-  @retval EFI_NO_MEDIA                 There is no media in the device.
-  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
-  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or PayloadTransferSize is NULL and
-                                       PayloadBufferSize is non-zero.
-  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
-                                       protocol command to execute.
-
-**/
-EFI_STATUS
-EFIAPI
-SecurityReceiveData (
-  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
-  IN  UINT32                                   MediaId,
-  IN  UINT64                                   Timeout,
-  IN  UINT8                                    SecurityProtocolId,
-  IN  UINT16                                   SecurityProtocolSpecificData,
-  IN  UINTN                                    PayloadBufferSize,
-  OUT VOID                                     *PayloadBuffer,
-  OUT UINTN                                    *PayloadTransferSize
-  )
-{
-  OPAL_SMM_DEVICE              *SmmDev;
-
-  SmmDev = OPAL_SMM_DEVICE_FROM_THIS (This);
-  if (SmmDev == NULL) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  return PerformTrustedIo (
-                        SmmDev,
-                        OpalRecv,
-                        SecurityProtocolId,
-                        SecurityProtocolSpecificData,
-                        PayloadBufferSize,
-                        PayloadBuffer
-                        );
-}
-
-/**
-  Send a security protocol command to a device.
-
-  The SendData function sends a security protocol command containing the payload
-  PayloadBuffer to the given MediaId. The security protocol command sent is
-  defined by SecurityProtocolId and contains the security protocol specific data
-  SecurityProtocolSpecificData. If the underlying protocol command requires a
-  specific padding for the command payload, the SendData function shall add padding
-  bytes to the command payload to satisfy the padding requirements.
-
-  For devices supporting the SCSI command set, the security protocol command is sent
-  using the SECURITY PROTOCOL OUT command defined in SPC-4.
-
-  For devices supporting the ATA command set, the security protocol command is sent
-  using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
-  is non-zero. If the PayloadBufferSize is zero, the security protocol command is
-  sent using the Trusted Non-Data command defined in ATA8-ACS.
-
-  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
-  return EFI_INVALID_PARAMETER.
-
-  If the given MediaId does not support security protocol commands, the function
-  shall return EFI_UNSUPPORTED. If there is no media in the device, the function
-  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
-  device, the function returns EFI_MEDIA_CHANGED.
-
-  If the security protocol fails to complete within the Timeout period, the function
-  shall return EFI_TIMEOUT.
-
-  If the security protocol command completes without an error, the function shall return
-  EFI_SUCCESS. If the security protocol command completes with an error, the function
-  shall return EFI_DEVICE_ERROR.
-
-  @param  This                         Indicates a pointer to the calling context.
-  @param  MediaId                      ID of the medium to receive data from.
-  @param  Timeout                      The timeout, in 100ns units, to use for the execution
-                                       of the security protocol command. A Timeout value of 0
-                                       means that this function will wait indefinitely for the
-                                       security protocol command to execute. If Timeout is greater
-                                       than zero, then this function will return EFI_TIMEOUT
-                                       if the time required to execute the send data command
-                                       is greater than Timeout.
-  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
-                                       the security protocol command to be sent.
-  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
-                                       of the security protocol command to be sent.
-  @param  PayloadBufferSize            Size in bytes of the payload data buffer.
-  @param  PayloadBuffer                A pointer to a destination buffer to store the security
-                                       protocol command specific payload data for the security
-                                       protocol command.
-
-  @retval EFI_SUCCESS                  The security protocol command completed successfully.
-  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
-  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
-  @retval EFI_NO_MEDIA                 There is no media in the device.
-  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
-  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
-  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
-                                       protocol command to execute.
-
-**/
-EFI_STATUS
-EFIAPI
-SecuritySendData (
-  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
-  IN UINT32                                   MediaId,
-  IN UINT64                                   Timeout,
-  IN UINT8                                    SecurityProtocolId,
-  IN UINT16                                   SecurityProtocolSpecificData,
-  IN UINTN                                    PayloadBufferSize,
-  IN VOID                                     *PayloadBuffer
-  )
-{
-  OPAL_SMM_DEVICE              *SmmDev;
-
-  SmmDev = OPAL_SMM_DEVICE_FROM_THIS (This);
-  if (SmmDev == NULL) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  return PerformTrustedIo (
-                          SmmDev,
-                          OpalSend,
-                          SecurityProtocolId,
-                          SecurityProtocolSpecificData,
-                          PayloadBufferSize,
-                          PayloadBuffer
-                          );
-
-}
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h
deleted file mode 100644
index ce88786fabc6..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/** @file
-  Opal password smm driver which is used to support Opal security feature at s3 path.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _OPAL_PASSWORD_SMM_H_
-#define _OPAL_PASSWORD_SMM_H_
-
-#include <PiSmm.h>
-#include <IndustryStandard/Atapi.h>
-
-#include <Protocol/SmmSwDispatch2.h>
-#include <Protocol/SmmSxDispatch2.h>
-#include <Protocol/AtaPassThru.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/SmmReadyToLock.h>
-#include <Protocol/SmmVariable.h>
-#include <Protocol/VariableLock.h>
-#include <Protocol/SmmEndOfDxe.h>
-#include <Protocol/StorageSecurityCommand.h>
-
-#include <Library/OpalPasswordSupportLib.h>
-#include <Library/DebugLib.h>
-#include <Library/PcdLib.h>
-#include <Library/IoLib.h>
-#include <Library/TimerLib.h>
-#include <Library/PciLib.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/S3BootScriptLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/SmmIoLib.h>
-
-#include <IndustryStandard/Pci22.h>
-
-#include <Guid/OpalPasswordExtraInfoVariable.h>
-
-#include "OpalAhciMode.h"
-#include "OpalIdeMode.h"
-#include "OpalNvmeMode.h"
-
-//
-// Time out Value for ATA pass through protocol
-//
-#define ATA_TIMEOUT                      EFI_TIMER_PERIOD_SECONDS (3)
-
-//
-// The payload Length of HDD related ATA commands
-//
-#define HDD_PAYLOAD                      512
-//
-// According to ATA spec, the max Length of hdd password is 32 bytes
-//
-#define OPAL_PASSWORD_MAX_LENGTH         32
-
-extern VOID                              *mBuffer;
-
-#pragma pack(1)
-
-typedef struct {
-  UINT32                   Address;
-  S3_BOOT_SCRIPT_LIB_WIDTH Width;
-} OPAL_HC_PCI_REGISTER_SAVE;
-
-
-typedef struct {
-  UINT32                SegNum;
-  UINT32                BusNum;
-  UINT32                DevNum;
-  UINT32                FuncNum;
-} PCI_DEVICE;
-
-/**
-* Opal I/O Type utilized by the Trusted IO callback
-*
-* The type indicates if the I/O is a send or receive
-*/
-typedef enum {
-    //
-    // I/O is a TCG Trusted Send command
-    //
-    OpalSend,
-
-    //
-    // I/O is a TCG Trusted Receive command
-    //
-    OpalRecv
-} OPAL_IO_TYPE;
-
-
-#define OPAL_SMM_DEVICE_SIGNATURE SIGNATURE_32 ('o', 's', 'd', 's')
-
-typedef struct {
-  UINTN                                    Signature;
-  LIST_ENTRY                               Link;
-
-  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    Sscp;
-
-  UINT32                                   SegNum;
-  UINT32                                   BusNum;
-  UINT32                                   DevNum;
-  UINT32                                   FuncNum;
-
-  UINT8                                    DeviceType;
-
-  UINT32                                   SataPort;
-  UINT32                                   SataPortMultiplierPort;
-
-  UINT32                                   NvmeNamespaceId;
-
-  UINT8                                    Password[32];
-  UINT8                                    PasswordLength;
-
-  UINT32                                   Length;
-  PCI_DEVICE                               *PciBridgeNode;
-
-  UINT16                                   OpalBaseComId;
-} OPAL_SMM_DEVICE;
-
-#define OPAL_SMM_DEVICE_FROM_THIS(a)  CR (a, OPAL_SMM_DEVICE, Sscp, OPAL_SMM_DEVICE_SIGNATURE)
-
-#pragma pack()
-
-/**
-  Send a security protocol command to a device that receives data and/or the result
-  of one or more commands sent by SendData.
-
-  The ReceiveData function sends a security protocol command to the given MediaId.
-  The security protocol command sent is defined by SecurityProtocolId and contains
-  the security protocol specific data SecurityProtocolSpecificData. The function
-  returns the data from the security protocol command in PayloadBuffer.
-
-  For devices supporting the SCSI command set, the security protocol command is sent
-  using the SECURITY PROTOCOL IN command defined in SPC-4.
-
-  For devices supporting the ATA command set, the security protocol command is sent
-  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
-  is non-zero.
-
-  If the PayloadBufferSize is zero, the security protocol command is sent using the
-  Trusted Non-Data command defined in ATA8-ACS.
-
-  If PayloadBufferSize is too small to store the available data from the security
-  protocol command, the function shall copy PayloadBufferSize bytes into the
-  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
-
-  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
-  the function shall return EFI_INVALID_PARAMETER.
-
-  If the given MediaId does not support security protocol commands, the function shall
-  return EFI_UNSUPPORTED. If there is no media in the device, the function returns
-  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
-  the function returns EFI_MEDIA_CHANGED.
-
-  If the security protocol fails to complete within the Timeout period, the function
-  shall return EFI_TIMEOUT.
-
-  If the security protocol command completes without an error, the function shall
-  return EFI_SUCCESS. If the security protocol command completes with an error, the
-  function shall return EFI_DEVICE_ERROR.
-
-  @param  This                         Indicates a pointer to the calling context.
-  @param  MediaId                      ID of the medium to receive data from.
-  @param  Timeout                      The timeout, in 100ns units, to use for the execution
-                                       of the security protocol command. A Timeout value of 0
-                                       means that this function will wait indefinitely for the
-                                       security protocol command to execute. If Timeout is greater
-                                       than zero, then this function will return EFI_TIMEOUT
-                                       if the time required to execute the receive data command
-                                       is greater than Timeout.
-  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
-                                       the security protocol command to be sent.
-  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
-                                       of the security protocol command to be sent.
-  @param  PayloadBufferSize            Size in bytes of the payload data buffer.
-  @param  PayloadBuffer                A pointer to a destination buffer to store the security
-                                       protocol command specific payload data for the security
-                                       protocol command. The caller is responsible for having
-                                       either implicit or explicit ownership of the buffer.
-  @param  PayloadTransferSize          A pointer to a buffer to store the size in bytes of the
-                                       data written to the payload data buffer.
-
-  @retval EFI_SUCCESS                  The security protocol command completed successfully.
-  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too small to store the available
-                                       data from the device. The PayloadBuffer contains the truncated data.
-  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
-  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
-  @retval EFI_NO_MEDIA                 There is no media in the device.
-  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
-  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or PayloadTransferSize is NULL and
-                                       PayloadBufferSize is non-zero.
-  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
-                                       protocol command to execute.
-
-**/
-EFI_STATUS
-EFIAPI
-SecurityReceiveData (
-  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL   *This,
-  IN  UINT32                                  MediaId,
-  IN  UINT64                                  Timeout,
-  IN  UINT8                                   SecurityProtocolId,
-  IN  UINT16                                  SecurityProtocolSpecificData,
-  IN  UINTN                                   PayloadBufferSize,
-  OUT VOID                                    *PayloadBuffer,
-  OUT UINTN                                   *PayloadTransferSize
-  );
-
-/**
-  Send a security protocol command to a device.
-
-  The SendData function sends a security protocol command containing the payload
-  PayloadBuffer to the given MediaId. The security protocol command sent is
-  defined by SecurityProtocolId and contains the security protocol specific data
-  SecurityProtocolSpecificData. If the underlying protocol command requires a
-  specific padding for the command payload, the SendData function shall add padding
-  bytes to the command payload to satisfy the padding requirements.
-
-  For devices supporting the SCSI command set, the security protocol command is sent
-  using the SECURITY PROTOCOL OUT command defined in SPC-4.
-
-  For devices supporting the ATA command set, the security protocol command is sent
-  using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
-  is non-zero. If the PayloadBufferSize is zero, the security protocol command is
-  sent using the Trusted Non-Data command defined in ATA8-ACS.
-
-  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
-  return EFI_INVALID_PARAMETER.
-
-  If the given MediaId does not support security protocol commands, the function
-  shall return EFI_UNSUPPORTED. If there is no media in the device, the function
-  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
-  device, the function returns EFI_MEDIA_CHANGED.
-
-  If the security protocol fails to complete within the Timeout period, the function
-  shall return EFI_TIMEOUT.
-
-  If the security protocol command completes without an error, the function shall return
-  EFI_SUCCESS. If the security protocol command completes with an error, the function
-  shall return EFI_DEVICE_ERROR.
-
-  @param  This                         Indicates a pointer to the calling context.
-  @param  MediaId                      ID of the medium to receive data from.
-  @param  Timeout                      The timeout, in 100ns units, to use for the execution
-                                       of the security protocol command. A Timeout value of 0
-                                       means that this function will wait indefinitely for the
-                                       security protocol command to execute. If Timeout is greater
-                                       than zero, then this function will return EFI_TIMEOUT
-                                       if the time required to execute the receive data command
-                                       is greater than Timeout.
-  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
-                                       the security protocol command to be sent.
-  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
-                                       of the security protocol command to be sent.
-  @param  PayloadBufferSize            Size in bytes of the payload data buffer.
-  @param  PayloadBuffer                A pointer to a destination buffer to store the security
-                                       protocol command specific payload data for the security
-                                       protocol command.
-
-  @retval EFI_SUCCESS                  The security protocol command completed successfully.
-  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
-  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
-  @retval EFI_NO_MEDIA                 There is no media in the device.
-  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
-  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
-  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
-                                       protocol command to execute.
-
-**/
-EFI_STATUS
-EFIAPI
-SecuritySendData (
-  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
-  IN UINT32                                   MediaId,
-  IN UINT64                                   Timeout,
-  IN UINT8                                    SecurityProtocolId,
-  IN UINT16                                   SecurityProtocolSpecificData,
-  IN UINTN                                    PayloadBufferSize,
-  IN VOID                                     *PayloadBuffer
-  );
-
-#endif // _OPAL_PASSWORD_SMM_H_
-
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf
deleted file mode 100644
index c62fa13271d8..000000000000
--- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf
+++ /dev/null
@@ -1,77 +0,0 @@
-## @file
-#  This is a Opal Password Smm driver.
-#
-# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-##
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = OpalPasswordSmm
-  FILE_GUID                      = 7D24A234-A8C2-4718-BF60-A2EF070F414E
-  MODULE_TYPE                    = DXE_SMM_DRIVER
-  VERSION_STRING                 = 1.0
-  PI_SPECIFICATION_VERSION       = 0x0001000A
-  ENTRY_POINT                    = OpalPasswordSmmInit
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
-#
-
-[Sources]
-  OpalPasswordSmm.c
-  OpalPasswordSmm.h
-  OpalAhciMode.c
-  OpalAhciMode.h
-  OpalIdeMode.c
-  OpalIdeMode.h
-  OpalNvmeMode.c
-  OpalNvmeMode.h
-  OpalNvmeReg.h
-
-[Packages]
-  MdePkg/MdePkg.dec
-  SecurityPkg/SecurityPkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
-  UefiBootServicesTableLib
-  UefiDriverEntryPoint
-  UefiRuntimeServicesTableLib
-  DebugLib
-  IoLib
-  PciLib
-  BaseLib
-  BaseMemoryLib
-  SmmServicesTableLib
-  MemoryAllocationLib
-  UefiLib
-  TimerLib
-  S3BootScriptLib
-  DxeServicesTableLib
-  DevicePathLib
-  OpalPasswordSupportLib
-  SmmIoLib
-
-[Guids]
-  gOpalExtraInfoVariableGuid                    ## CONSUMES ## GUID
-
-[Protocols]
-  gEfiSmmSwDispatch2ProtocolGuid                ## CONSUMES
-  gEfiAtaPassThruProtocolGuid                   ## CONSUMES
-  gEfiPciIoProtocolGuid                         ## CONSUMES
-  gEfiSmmSxDispatch2ProtocolGuid                ## CONSUMES
-  gEfiSmmVariableProtocolGuid                   ## CONSUMES
-  gEfiStorageSecurityCommandProtocolGuid        ## CONSUMES
-
-[Depex]
-  gEfiSmmSwDispatch2ProtocolGuid AND
-  gEfiSmmSxDispatch2ProtocolGuid AND
-  gEfiSmmVariableProtocolGuid
-- 
2.7.0.windows.1



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

* [PATCH V2 6/7] SecurityPkg OpalPasswordSupportLib: Remove it
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
                   ` (4 preceding siblings ...)
  2018-03-07 13:19 ` [PATCH V2 5/7] SecurityPkg OpalPassword: Remove old solution Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  2018-03-07 13:19 ` [PATCH V2 7/7] SecurityPkg OpalPasswordExtraInfoVariable.h: " Star Zeng
  6 siblings, 0 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

Remove OpalPasswordSupportLib as it is not been used
anymore.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 .../Include/Library/OpalPasswordSupportLib.h       | 289 --------
 .../OpalPasswordSupportLib.c                       | 781 ---------------------
 .../OpalPasswordSupportLib.inf                     |  55 --
 .../OpalPasswordSupportNotify.h                    |  55 --
 SecurityPkg/SecurityPkg.dec                        |   4 -
 SecurityPkg/SecurityPkg.dsc                        |   2 -
 6 files changed, 1186 deletions(-)
 delete mode 100644 SecurityPkg/Include/Library/OpalPasswordSupportLib.h
 delete mode 100644 SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.c
 delete mode 100644 SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf
 delete mode 100644 SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportNotify.h

diff --git a/SecurityPkg/Include/Library/OpalPasswordSupportLib.h b/SecurityPkg/Include/Library/OpalPasswordSupportLib.h
deleted file mode 100644
index e616c763f05c..000000000000
--- a/SecurityPkg/Include/Library/OpalPasswordSupportLib.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/** @file
-  Header file of Opal password support library.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-#ifndef _OPAL_PASSWORD_SUPPORT_LIB_H_
-#define _OPAL_PASSWORD_SUPPORT_LIB_H_
-
-#include <Protocol/DevicePath.h>
-#include <Library/TcgStorageOpalLib.h>
-
-
-#pragma pack(1)
-
-//
-// Structure that is used to represent the available actions for an OpalDisk.
-// The data can then be utilized to expose/hide certain actions available to an end user
-// by the consumer of this library.
-//
-typedef struct {
-    //
-    // Indicates if the disk can support PSID Revert action.  should verify disk supports PSID authority
-    //
-    UINT16 PsidRevert : 1;
-
-    //
-    // Indicates if the disk can support Revert action
-    //
-    UINT16 Revert : 1;
-
-    //
-    // Indicates if the user must keep data for revert action.  It is true if no media encryption is supported.
-    //
-    UINT16 RevertKeepDataForced : 1;
-
-    //
-    // Indicates if the disk can support set Admin password
-    //
-    UINT16 AdminPass : 1;
-
-    //
-    // Indicates if the disk can support set User password.  This action requires that a user
-    // password is first enabled.
-    //
-    UINT16 UserPass : 1;
-
-    //
-    // Indicates if unlock action is available.  Requires disk to be currently locked.
-    //
-    UINT16 Unlock : 1;
-
-    //
-    // Indicates if Secure Erase action is available.  Action requires admin credentials and media encryption support.
-    //
-    UINT16 SecureErase : 1;
-
-    //
-    // Indicates if Disable User action is available.  Action requires admin credentials.
-    //
-    UINT16 DisableUser : 1;
-} OPAL_DISK_ACTIONS;
-
-//
-// Structure that is used to represent the Opal device with password info.
-//
-typedef struct {
-  LIST_ENTRY                 Link;
-
-  UINT8                      Password[32];
-  UINT8                      PasswordLength;
-
-  EFI_DEVICE_PATH_PROTOCOL   OpalDevicePath;
-} OPAL_DISK_AND_PASSWORD_INFO;
-
-#pragma pack()
-
-/**
-
-  The function performs determines the available actions for the OPAL_DISK provided.
-
-  @param[in]   SupportedAttributes   The support attribute for the device.
-  @param[in]   LockingFeature        The locking status for the device.
-  @param[in]   OwnerShip             The ownership for the device.
-  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate disk actions.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportGetAvailableActions(
-  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
-  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
-  IN  UINT16                           OwnerShip,
-  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
-  );
-
-/**
-  Enable Opal Feature for the input device.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Msid               Msid
-  @param[in]      MsidLength         Msid Length
-  @param[in]      Password           Admin password
-  @param[in]      PassLength         Length of password in bytes
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportEnableOpalFeature(
-  IN OPAL_SESSION              *Session,
-  IN VOID                      *Msid,
-  IN UINT32                    MsidLength,
-  IN VOID                      *Password,
-  IN UINT32                    PassLength,
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  );
-
-/**
-  Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Psid               PSID of device to revert.
-  @param[in]      PsidLength         Length of PSID in bytes.
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportPsidRevert(
-  IN OPAL_SESSION              *Session,
-  IN VOID                      *Psid,
-  IN UINT32                    PsidLength,
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  );
-
-/**
-  Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts the device using the RevertSP method.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      KeepUserData       TRUE to keep existing Data on the disk, or FALSE to erase it
-  @param[in]      Password           Admin password
-  @param[in]      PasswordLength     Length of password in bytes
-  @param[in]      Msid               Msid
-  @param[in]      MsidLength         Msid Length
-  @param[out]     PasswordFailed     indicates if password failed (start session didn't work)
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportRevert(
-  IN  OPAL_SESSION              *Session,
-  IN  BOOLEAN                   KeepUserData,
-  IN  VOID                      *Password,
-  IN  UINT32                    PasswordLength,
-  IN  VOID                      *Msid,
-  IN  UINT32                    MsidLength,
-  OUT BOOLEAN                   *PasswordFailed,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  );
-
-/**
-  Set new password.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      OldPassword        Current admin password
-  @param[in]      OldPasswordLength  Length of current admin password in bytes
-  @param[in]      NewPassword        New admin password to set
-  @param[in]      NewPasswordLength  Length of new password in bytes
-  @param[in]      DevicePath         The device path for the opal devcie.
-  @param[in]      SetAdmin           Whether set admin password or user password.
-                                     TRUE for admin, FALSE for user.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportSetPassword(
-  IN OPAL_SESSION              *Session,
-  IN VOID                      *OldPassword,
-  IN UINT32                    OldPasswordLength,
-  IN VOID                      *NewPassword,
-  IN UINT32                    NewPasswordLength,
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
-  IN BOOLEAN                   SetAdmin
-  );
-
-/**
-  Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY and disables the User1 authority.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Password           Admin password
-  @param[in]      PasswordLength     Length of password in bytes
-  @param[out]     PasswordFailed     Indicates if password failed (start session didn't work)
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportDisableUser(
-  IN  OPAL_SESSION              *Session,
-  IN  VOID                      *Password,
-  IN  UINT32                    PasswordLength,
-  OUT BOOLEAN                   *PasswordFailed,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  );
-
-/**
-  Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
-  and updates the global locking range ReadLocked and WriteLocked columns to FALSE.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Password           Admin or user password
-  @param[in]      PasswordLength     Length of password in bytes
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportUnlock(
-  IN OPAL_SESSION               *Session,
-  IN VOID                       *Password,
-  IN UINT32                     PasswordLength,
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
-  );
-
-/**
-  Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
-  and updates the global locking range ReadLocked and WriteLocked columns to TRUE.
-
-  @param[in]      Session             The opal session for the opal device.
-  @param[in]      Password            Admin or user password
-  @param[in]      PasswordLength      Length of password in bytes
-  @param[in]      DevicePath          The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportLock(
-  IN OPAL_SESSION               *Session,
-  IN VOID                       *Password,
-  IN UINT32                     PasswordLength,
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
-  );
-
-/**
-  Check if the password is full zero.
-
-  @param[in]   Password       Points to the Data Buffer
-
-  @retval      TRUE           This password string is full zero.
-  @retval      FALSE          This password string is not full zero.
-
-**/
-LIST_ENTRY *
-EFIAPI
-OpalSupportGetOpalDeviceList (
-  VOID
-  );
-
-/**
-  Transfer the password to the smm driver.
-
-  @param[in]  DevicePath     The device path for the opal devcie.
-  @param      PasswordLen    The input password length.
-  @param      Password       Input password buffer.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Error occured.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalSupportSendPasword(
-  EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
-  UINTN                       PasswordLen,
-  VOID                        *Password
-  );
-
-#endif // _OPAL_CORE_H_
diff --git a/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.c b/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.c
deleted file mode 100644
index 837582359e4f..000000000000
--- a/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.c
+++ /dev/null
@@ -1,781 +0,0 @@
-/** @file
-  Implementation of Opal password support library.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "OpalPasswordSupportNotify.h"
-
-#define OPAL_PASSWORD_MAX_LENGTH         32
-
-LIST_ENTRY           mDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mDeviceList);
-BOOLEAN              gInSmm = FALSE;
-EFI_GUID             gOpalPasswordNotifyProtocolGuid = OPAL_PASSWORD_NOTIFY_PROTOCOL_GUID;
-
-/**
-
-  The function performs determines the available actions for the OPAL_DISK provided.
-
-  @param[in]   SupportedAttributes   The support attribute for the device.
-  @param[in]   LockingFeature        The locking status for the device.
-  @param[in]   OwnerShip             The ownership for the device.
-  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate disk actions.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportGetAvailableActions(
-  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
-  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
-  IN  UINT16                           OwnerShip,
-  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
-  )
-{
-  BOOLEAN ExistingPassword;
-
-  NULL_CHECK(AvalDiskActions);
-
-  AvalDiskActions->AdminPass = 1;
-  AvalDiskActions->UserPass = 0;
-  AvalDiskActions->DisableUser = 0;
-  AvalDiskActions->Unlock = 0;
-
-  //
-  // Revert is performed on locking sp, so only allow if locking sp is enabled
-  //
-  if (LockingFeature->LockingEnabled) {
-    AvalDiskActions->Revert = 1;
-  }
-
-  //
-  // Psid revert is available for any device with media encryption support
-  // Revert is allowed for any device with media encryption support, however it requires
-  //
-  if (SupportedAttributes->MediaEncryption) {
-
-    //
-    // Only allow psid revert if media encryption is enabled.
-    // Otherwise, someone who steals a disk can psid revert the disk and the user Data is still
-    // intact and accessible
-    //
-    AvalDiskActions->PsidRevert = 1;
-    AvalDiskActions->RevertKeepDataForced = 0;
-
-    //
-    // Secure erase is performed by generating a new encryption key
-    // this is only available is encryption is supported
-    //
-    AvalDiskActions->SecureErase = 1;
-  } else {
-    AvalDiskActions->PsidRevert = 0;
-    AvalDiskActions->SecureErase = 0;
-
-    //
-    // If no media encryption is supported, then a revert (using password) will not
-    // erase the Data (since you can't generate a new encryption key)
-    //
-    AvalDiskActions->RevertKeepDataForced = 1;
-  }
-
-  if (LockingFeature->Locked) {
-    AvalDiskActions->Unlock = 1;
-  } else {
-    AvalDiskActions->Unlock = 0;
-  }
-
-  //
-  // Only allow user to set password if an admin password exists
-  //
-  ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip, LockingFeature);
-  AvalDiskActions->UserPass = ExistingPassword;
-
-  //
-  // This will still show up even if there isn't a user, which is fine
-  //
-  AvalDiskActions->DisableUser = ExistingPassword;
-
-  return TcgResultSuccess;
-}
-
-/**
-  Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Psid               PSID of device to revert.
-  @param[in]      PsidLength         Length of PSID in bytes.
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportPsidRevert(
-  IN OPAL_SESSION              *Session,
-  IN VOID                      *Psid,
-  IN UINT32                    PsidLength,
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  )
-{
-  TCG_RESULT   Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(Psid);
-
-  Ret = OpalUtilPsidRevert (Session, Psid, PsidLength);
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, 0, NULL);
-  }
-
-  return Ret;
-}
-
-/**
-  Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY,
-  sets OPAL_UID_ADMIN_SP_C_PIN_SID with the new password,
-  and sets OPAL_LOCKING_SP_C_PIN_ADMIN1 with the new password.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      OldPassword        Current admin password
-  @param[in]      OldPasswordLength  Length of current admin password in bytes
-  @param[in]      NewPassword        New admin password to set
-  @param[in]      NewPasswordLength  Length of new password in bytes
-  @param[in]      DevicePath         The device path for the opal devcie.
-  @param[in]      SetAdmin           Whether set admin password or user password.
-                                     TRUE for admin, FALSE for user.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportSetPassword(
-  IN OPAL_SESSION              *Session,
-  IN VOID                      *OldPassword,
-  IN UINT32                    OldPasswordLength,
-  IN VOID                      *NewPassword,
-  IN UINT32                    NewPasswordLength,
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
-  IN BOOLEAN                   SetAdmin
-  )
-{
-  TCG_RESULT   Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(OldPassword);
-  NULL_CHECK(NewPassword);
-
-  if (SetAdmin) {
-    Ret = OpalUtilSetAdminPassword(Session, OldPassword, OldPasswordLength, NewPassword, NewPasswordLength);
-  } else {
-    Ret = OpalUtilSetUserPassword(Session, OldPassword, OldPasswordLength, NewPassword, NewPasswordLength);
-  }
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, NewPasswordLength, NewPassword);
-  }
-
-  return Ret;
-}
-
-/**
-  Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY and disables the User1 authority.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Password           Admin password
-  @param[in]      PasswordLength     Length of password in bytes
-  @param[out]     PasswordFailed     Indicates if password failed (start session didn't work)
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportDisableUser(
-  IN  OPAL_SESSION              *Session,
-  IN  VOID                      *Password,
-  IN  UINT32                    PasswordLength,
-  OUT BOOLEAN                   *PasswordFailed,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  )
-{
-  TCG_RESULT   Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(Password);
-  NULL_CHECK(PasswordFailed);
-
-  Ret = OpalUtilDisableUser(Session, Password, PasswordLength, PasswordFailed);
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, PasswordLength, Password);
-  }
-
-  return Ret;
-}
-
-/**
-  Enable Opal Feature for the input device.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Msid               Msid
-  @param[in]      MsidLength         Msid Length
-  @param[in]      Password           Admin password
-  @param[in]      PassLength         Length of password in bytes
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportEnableOpalFeature (
-  IN OPAL_SESSION              *Session,
-  IN VOID                      *Msid,
-  IN UINT32                    MsidLength,
-  IN VOID                      *Password,
-  IN UINT32                    PassLength,
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  )
-{
-  TCG_RESULT   Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(Msid);
-  NULL_CHECK(Password);
-
-  Ret = OpalUtilSetAdminPasswordAsSid(
-                          Session,
-                          Msid,
-                          MsidLength,
-                          Password,
-                          PassLength
-                          );
-  if (Ret == TcgResultSuccess) {
-    //
-    // Enable global locking range
-    //
-    Ret = OpalUtilSetOpalLockingRange(
-                              Session,
-                              Password,
-                              PassLength,
-                              OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,
-                              0,
-                              0,
-                              TRUE,
-                              TRUE,
-                              FALSE,
-                              FALSE
-                              );
-  }
-
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, PassLength, Password);
-  }
-
-  return Ret;
-}
-
-/**
-  Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts the device using the RevertSP method.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      KeepUserData       TRUE to keep existing Data on the disk, or FALSE to erase it
-  @param[in]      Password           Admin password
-  @param[in]      PasswordLength     Length of password in bytes
-  @param[in]      Msid               Msid
-  @param[in]      MsidLength         Msid Length
-  @param[out]     PasswordFailed     indicates if password failed (start session didn't work)
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportRevert(
-  IN  OPAL_SESSION              *Session,
-  IN  BOOLEAN                   KeepUserData,
-  IN  VOID                      *Password,
-  IN  UINT32                    PasswordLength,
-  IN  VOID                      *Msid,
-  IN  UINT32                    MsidLength,
-  OUT BOOLEAN                   *PasswordFailed,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
-  )
-{
-  TCG_RESULT   Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(Password);
-  NULL_CHECK(Msid);
-  NULL_CHECK(PasswordFailed);
-
-  Ret = OpalUtilRevert(Session, KeepUserData, Password, PasswordLength, PasswordFailed, Msid, MsidLength);
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, 0, NULL);
-  }
-
-  return Ret;
-}
-
-/**
-  Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
-  and updates the global locking range ReadLocked and WriteLocked columns to FALSE.
-
-  @param[in]      Session            The opal session for the opal device.
-  @param[in]      Password           Admin or user password
-  @param[in]      PasswordLength     Length of password in bytes
-  @param[in]      DevicePath         The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportUnlock(
-  IN OPAL_SESSION               *Session,
-  IN VOID                       *Password,
-  IN UINT32                     PasswordLength,
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
-  )
-{
-  TCG_RESULT   Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(Password);
-
-  Ret = OpalUtilUpdateGlobalLockingRange(Session, Password, PasswordLength, FALSE, FALSE);
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, PasswordLength, Password);
-  }
-
-  return Ret;
-}
-
-/**
-  Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
-  and updates the global locking range ReadLocked and WriteLocked columns to TRUE.
-
-  @param[in]      Session             The opal session for the opal device.
-  @param[in]      Password            Admin or user password
-  @param[in]      PasswordLength      Length of password in bytes
-  @param[in]      DevicePath          The device path for the opal devcie.
-
-**/
-TCG_RESULT
-EFIAPI
-OpalSupportLock(
-  IN OPAL_SESSION               *Session,
-  IN VOID                       *Password,
-  IN UINT32                     PasswordLength,
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
-  )
-{
-  TCG_RESULT  Ret;
-
-  NULL_CHECK(Session);
-  NULL_CHECK(Password);
-
-  Ret = OpalUtilUpdateGlobalLockingRange(Session, Password, PasswordLength, TRUE, TRUE);
-  if (Ret == TcgResultSuccess && !gInSmm) {
-    OpalSupportSendPasword (DevicePath, PasswordLength, Password);
-  }
-
-  return Ret;
-}
-
-/**
-  Initialize the communicate Buffer using DataSize and Function.
-
-  @param[out]      DataPtr          Points to the Data in the communicate Buffer.
-  @param[in]       DataSize         The Data Size to send to SMM.
-  @param[in]       Function         The function number to initialize the communicate Header.
-
-  @retval EFI_INVALID_PARAMETER     The Data Size is too big.
-  @retval EFI_SUCCESS               Find the specified variable.
-
-**/
-VOID*
-OpalInitCommunicateBuffer (
-  OUT     VOID                              **DataPtr OPTIONAL,
-  IN      UINTN                             DataSize,
-  IN      UINTN                             Function
-  )
-{
-  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;
-  OPAL_SMM_COMMUNICATE_HEADER               *SmmFunctionHeader;
-  VOID                                      *Buffer;
-  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE   *SmmCommRegionTable;
-  EFI_MEMORY_DESCRIPTOR                     *SmmCommMemRegion;
-  UINTN                                     Index;
-  UINTN                                     Size;
-  EFI_STATUS                                Status;
-
-  Buffer = NULL;
-  Status = EfiGetSystemConfigurationTable (
-             &gEdkiiPiSmmCommunicationRegionTableGuid,
-             (VOID **) &SmmCommRegionTable
-             );
-  if (EFI_ERROR (Status)) {
-    return NULL;
-  }
-
-  ASSERT (SmmCommRegionTable != NULL);
-  SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) (SmmCommRegionTable + 1);
-  Size = 0;
-  for (Index = 0; Index < SmmCommRegionTable->NumberOfEntries; Index++) {
-    if (SmmCommMemRegion->Type == EfiConventionalMemory) {
-      Size = EFI_PAGES_TO_SIZE ((UINTN) SmmCommMemRegion->NumberOfPages);
-      if (Size >= (DataSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data))) {
-        break;
-      }
-    }
-    SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) SmmCommMemRegion + SmmCommRegionTable->DescriptorSize);
-  }
-  ASSERT (Index < SmmCommRegionTable->NumberOfEntries);
-
-  Buffer = (VOID*)(UINTN)SmmCommMemRegion->PhysicalStart;
-  ASSERT (Buffer != NULL);
-
-  SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) Buffer;
-  CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gOpalPasswordNotifyProtocolGuid);
-  SmmCommunicateHeader->MessageLength = DataSize + OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data);
-
-  SmmFunctionHeader = (OPAL_SMM_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
-  SmmFunctionHeader->Function = Function;
-  if (DataPtr != NULL) {
-    *DataPtr = SmmFunctionHeader->Data;
-  }
-
-  return Buffer;
-}
-
-/**
-  Send the Data in communicate Buffer to SMM.
-
-  @param[in]   Buffer                 Points to the Data in the communicate Buffer.
-  @param[in]   DataSize               This Size of the function Header and the Data.
-
-  @retval      EFI_SUCCESS            Success is returned from the functin in SMM.
-  @retval      Others                 Failure is returned from the function in SMM.
-
-**/
-EFI_STATUS
-OpalSendCommunicateBuffer (
-  IN      VOID                              *Buffer,
-  IN      UINTN                             DataSize
-  )
-{
-  EFI_STATUS                                Status;
-  UINTN                                     CommSize;
-  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;
-  OPAL_SMM_COMMUNICATE_HEADER               *SmmFunctionHeader;
-  EFI_SMM_COMMUNICATION_PROTOCOL            *SmmCommunication;
-
-  Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  CommSize = DataSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data);
-  Status = SmmCommunication->Communicate (SmmCommunication, Buffer, &CommSize);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) Buffer;
-  SmmFunctionHeader    = (OPAL_SMM_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
-
-  return  SmmFunctionHeader->ReturnStatus;
-}
-
-/**
-  Transfer the password to the smm driver.
-
-  @param[in]  DevicePath     The device path for the opal devcie.
-  @param      PasswordLen    The input password length.
-  @param      Password       Input password buffer.
-
-  @retval  EFI_SUCCESS       Do the required action success.
-  @retval  Others            Error occured.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalSupportSendPasword(
-  EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
-  UINTN                       PasswordLen,
-  VOID                        *Password
-  )
-{
-  OPAL_COMM_DEVICE_LIST   *Parameter;
-  VOID                    *Buffer;
-  UINTN                   Length;
-  EFI_STATUS              Status;
-  UINTN                   DevicePathLen;
-
-  Parameter = NULL;
-  Buffer = NULL;
-
-  if (DevicePath == NULL) {
-    //
-    // Assume DevicePath == NULL only when library used by SMM driver
-    // and should not run to here, just return success.
-    //
-    return EFI_SUCCESS;
-  }
-
-  DevicePathLen = GetDevicePathSize (DevicePath);
-  Length = OFFSET_OF (OPAL_COMM_DEVICE_LIST, OpalDevicePath) + DevicePathLen;
-  Buffer = OpalInitCommunicateBuffer((VOID**)&Parameter, Length, SMM_FUNCTION_SET_OPAL_PASSWORD);
-  if (Buffer == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  if (Password != NULL) {
-    CopyMem((VOID*)Parameter->Password, Password, PasswordLen);
-    Parameter->PasswordLength = (UINT8)PasswordLen;
-  }
-  CopyMem (&Parameter->OpalDevicePath, DevicePath, DevicePathLen);
-
-  Status = OpalSendCommunicateBuffer(Buffer, Length);
-  if (EFI_ERROR(Status)) {
-    goto EXIT;
-  }
-
-EXIT:
-  ZeroMem(Parameter, Length);
-  return Status;
-}
-
-/**
-  Get saved Opal device list.
-
-  @retval      return opal device list.
-
-**/
-LIST_ENTRY*
-EFIAPI
-OpalSupportGetOpalDeviceList (
-  VOID
-  )
-{
-  return &mDeviceList;
-}
-
-/**
-  Check if the password is full zero.
-
-  @param[in]   Password       Points to the Data Buffer
-
-  @retval      TRUE           This password string is full zero.
-  @retval      FALSE          This password string is not full zero.
-
-**/
-BOOLEAN
-OpalPasswordIsFullZero (
-  IN UINT8                    *Password
-  )
-{
-  UINTN                       Index;
-
-  for (Index = 0; Index < OPAL_PASSWORD_MAX_LENGTH; Index++) {
-    if (Password[Index] != 0) {
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-/**
-  Save hdd password to SMM.
-
-  @param[in] DevicePath                Input device path info for the device.
-  @param[in] Password                  The hdd password of attached ATA device.
-  @param[in] PasswordLength            The hdd password length.
-
-  @retval EFI_OUT_OF_RESOURCES    Insufficient resources to create database record
-  @retval EFI_SUCCESS             The function has been successfully executed.
-
-**/
-EFI_STATUS
-OpalSavePasswordToSmm (
-  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath,
-  IN  UINT8                         *Password,
-  IN  UINT8                         PasswordLength
-  )
-{
-  OPAL_DISK_AND_PASSWORD_INFO       *List;
-  OPAL_DISK_AND_PASSWORD_INFO       *Dev;
-  LIST_ENTRY                        *Entry;
-  UINTN                             DevicePathLen;
-
-  DevicePathLen = GetDevicePathSize (DevicePath);
-
-  for (Entry = mDeviceList.ForwardLink; Entry != &mDeviceList; Entry = Entry->ForwardLink) {
-    List = BASE_CR (Entry, OPAL_DISK_AND_PASSWORD_INFO, Link);
-    if (CompareMem (&List->OpalDevicePath, DevicePath, DevicePathLen) == 0) {
-      CopyMem(List->Password, Password, OPAL_PASSWORD_MAX_LENGTH);
-      return EFI_SUCCESS;
-    }
-  }
-
-  Dev = AllocateZeroPool (OFFSET_OF (OPAL_DISK_AND_PASSWORD_INFO, OpalDevicePath) + DevicePathLen);
-  if (Dev == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  Dev->PasswordLength = PasswordLength;
-  CopyMem(&(Dev->Password), Password, OPAL_PASSWORD_MAX_LENGTH);
-  CopyMem(&(Dev->OpalDevicePath), DevicePath, DevicePathLen);
-
-  InsertHeadList (&mDeviceList, &Dev->Link);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Communication service SMI Handler entry.
-
-  This SMI handler provides services for saving HDD password and saving S3 boot script when ready to boot.
-
-  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
-  @param[in]     RegisterContext Points to an optional handler context which was specified when the
-                                 handler was registered.
-  @param[in, out] CommBuffer     A pointer to a collection of Data in memory that will
-                                 be conveyed from a non-SMM environment into an SMM environment.
-  @param[in, out] CommBufferSize The Size of the CommBuffer.
-
-  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
-                                              should still be called.
-  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
-                                              still be called.
-  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
-                                              be called.
-  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
-**/
-EFI_STATUS
-EFIAPI
-SmmOpalPasswordHandler (
-  IN     EFI_HANDLE                 DispatchHandle,
-  IN     CONST VOID                 *RegisterContext,
-  IN OUT VOID                       *CommBuffer,
-  IN OUT UINTN                      *CommBufferSize
-  )
-{
-  EFI_STATUS                        Status;
-  OPAL_SMM_COMMUNICATE_HEADER       *SmmFunctionHeader;
-  UINTN                             TempCommBufferSize;
-  UINT8                             *NewPassword;
-  UINT8                             PasswordLength;
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
-
-  if (CommBuffer == NULL || CommBufferSize == NULL) {
-    return EFI_SUCCESS;
-  }
-
-  TempCommBufferSize = *CommBufferSize;
-  if (TempCommBufferSize < OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data)) {
-    return EFI_SUCCESS;
-  }
-
-  Status   = EFI_SUCCESS;
-  SmmFunctionHeader     = (OPAL_SMM_COMMUNICATE_HEADER *)CommBuffer;
-
-  DevicePath = &((OPAL_COMM_DEVICE_LIST*)(SmmFunctionHeader->Data))->OpalDevicePath;
-  PasswordLength = ((OPAL_COMM_DEVICE_LIST*)(SmmFunctionHeader->Data))->PasswordLength;
-  NewPassword = ((OPAL_COMM_DEVICE_LIST*)(SmmFunctionHeader->Data))->Password;
-
-  switch (SmmFunctionHeader->Function) {
-    case SMM_FUNCTION_SET_OPAL_PASSWORD:
-        if (OpalPasswordIsFullZero (NewPassword) || PasswordLength == 0) {
-          Status = EFI_INVALID_PARAMETER;
-          goto EXIT;
-        }
-
-        Status = OpalSavePasswordToSmm (DevicePath, NewPassword, PasswordLength);
-      break;
-
-    default:
-      Status = EFI_UNSUPPORTED;
-      break;
-  }
-
-EXIT:
-  SmmFunctionHeader->ReturnStatus = Status;
-
-  //
-  // Return EFI_SUCCESS cause only one handler can be trigged.
-  // so return EFI_WARN_INTERRUPT_SOURCE_PENDING to make all handler can be trigged.
-  //
-  return EFI_WARN_INTERRUPT_SOURCE_PENDING;
-}
-
-/**
-  The constructor function.
-
-  Register SMI handler when link to SMM driver.
-
-  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalPasswordSupportLibConstructor (
-  VOID
-  )
-{
-  EFI_SMM_BASE2_PROTOCOL         *SmmBase2;
-  EFI_SMM_SYSTEM_TABLE2          *Smst;
-  EFI_HANDLE                     SmmHandle;
-  EFI_STATUS                     Status;
-
-  Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID**) &SmmBase2);
-  if (EFI_ERROR (Status)) {
-    return RETURN_SUCCESS;
-  }
-  Status = SmmBase2->InSmm (SmmBase2, &gInSmm);
-  if (EFI_ERROR (Status)) {
-    return RETURN_SUCCESS;
-  }
-  if (!gInSmm) {
-    return RETURN_SUCCESS;
-  }
-
-  //
-  // Good, we are in SMM
-  //
-  Status = SmmBase2->GetSmstLocation (SmmBase2, &Smst);
-  if (EFI_ERROR (Status)) {
-    return RETURN_SUCCESS;
-  }
-
-  SmmHandle = NULL;
-  Status    = Smst->SmiHandlerRegister (SmmOpalPasswordHandler, &gOpalPasswordNotifyProtocolGuid, &SmmHandle);
-  ASSERT_EFI_ERROR (Status);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  The Destructor function.
-
-  Clean the saved opal device list.
-
-  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-OpalPasswordSupportLibDestructor (
-  VOID
-  )
-{
-  OPAL_DISK_AND_PASSWORD_INFO  *Device;
-
-  while (!IsListEmpty (&mDeviceList)) {
-    Device = BASE_CR (mDeviceList.ForwardLink, OPAL_DISK_AND_PASSWORD_INFO, Link);
-
-    RemoveEntryList (&Device->Link);
-    FreePool (Device);
-  }
-
-  return EFI_SUCCESS;
-}
diff --git a/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf b/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf
deleted file mode 100644
index b7831356e5dd..000000000000
--- a/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf
+++ /dev/null
@@ -1,55 +0,0 @@
-## @file
-#  This is a OpalPassword support library.
-#
-#  This module is used to provide API used by Opal password solution.
-#
-# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-##
-[Defines]
-  INF_VERSION                    = 0x00010017
-  BASE_NAME                      = OpalPasswordSupportLib
-  FILE_GUID                      = 00F93D8C-00A6-42D0-9327-11CE309B944A
-  VERSION_STRING                 = 1.0
-  MODULE_TYPE                    = BASE
-  LIBRARY_CLASS                  = OpalPasswordSupportLib|DXE_DRIVER DXE_CORE DXE_SMM_DRIVER
-
-  CONSTRUCTOR                    = OpalPasswordSupportLibConstructor
-  DESTRUCTOR                     = OpalPasswordSupportLibDestructor
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources]
-  OpalPasswordSupportLib.c
-  OpalPasswordSupportNotify.h
-
-[LibraryClasses]
-  BaseLib
-  BaseMemoryLib
-  PrintLib
-  DebugLib
-  TimerLib
-  TcgStorageOpalLib
-  UefiLib
-
-[Packages]
-  MdePkg/MdePkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-  SecurityPkg/SecurityPkg.dec
-
-[Protocols]
-  gEfiStorageSecurityCommandProtocolGuid                         ## CONSUMES
-  gEfiSmmCommunicationProtocolGuid                               ## CONSUMES
-  gEfiSmmBase2ProtocolGuid                                       ## CONSUMES # only for SMM version
-
-[Guids]
-  gEdkiiPiSmmCommunicationRegionTableGuid       ## CONSUMES ## SystemTable
diff --git a/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportNotify.h b/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportNotify.h
deleted file mode 100644
index a2115b738653..000000000000
--- a/SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportNotify.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/** @file
-  Implementation of Opal password support library.
-
-Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _DXE_OPAL_NOTIFY_H_
-#define _DXE_OPAL_NOTIFY_H_
-
-#include <PiDxe.h>
-#include <PiSmm.h>
-
-#include <Guid/PiSmmCommunicationRegionTable.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/OpalPasswordSupportLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/MemoryAllocationLib.h>
-
-#include <Protocol/SmmCommunication.h>
-#include <Protocol/SmmBase2.h>
-
-
-#pragma pack(1)
-
-typedef struct {
-  UINTN       Function;
-  EFI_STATUS  ReturnStatus;
-  UINT8       Data[1];
-} OPAL_SMM_COMMUNICATE_HEADER;
-
-typedef struct {
-  UINT8                      Password[32];
-  UINT8                      PasswordLength;
-
-  EFI_DEVICE_PATH_PROTOCOL   OpalDevicePath;
-} OPAL_COMM_DEVICE_LIST;
-
-#pragma pack()
-
-#define SMM_FUNCTION_SET_OPAL_PASSWORD        1
-
-#define OPAL_PASSWORD_NOTIFY_PROTOCOL_GUID {0x0ff2ddd0, 0xefc9, 0x4f49, { 0x99, 0x7a, 0xcb, 0x59, 0x44, 0xe6, 0x97, 0xd3 } }
-
-#endif
diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 71963eb750d5..77d6b073d401 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -90,10 +90,6 @@ [LibraryClasses]
   #
   TcgStorageOpalLib|Include/Library/TcgStorageOpalLib.h
 
-  ## @libraryclass  Provides interfaces about Opal commond special for Opal password solution.
-  #
-  OpalPasswordSupportLib|Include/Library/OpalPasswordSupportLib.h
-
 [Guids]
   ## Security package token space guid.
   # Include/Guid/SecurityPkgTokenSpace.h
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 9be484877cc2..ed47fb2fa05b 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -73,7 +73,6 @@ [LibraryClasses]
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   TcgStorageCoreLib|SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
   TcgStorageOpalLib|SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf
-  OpalPasswordSupportLib|SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf
   ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
 
 [LibraryClasses.common.PEIM]
@@ -204,7 +203,6 @@ [Components]
   #
   SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
   SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf
-  SecurityPkg/Library/OpalPasswordSupportLib/OpalPasswordSupportLib.inf
 
   #
   # Other
-- 
2.7.0.windows.1



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

* [PATCH V2 7/7] SecurityPkg OpalPasswordExtraInfoVariable.h: Remove it
  2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
                   ` (5 preceding siblings ...)
  2018-03-07 13:19 ` [PATCH V2 6/7] SecurityPkg OpalPasswordSupportLib: Remove it Star Zeng
@ 2018-03-07 13:19 ` Star Zeng
  6 siblings, 0 replies; 10+ messages in thread
From: Star Zeng @ 2018-03-07 13:19 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao, Eric Dong, Chao Zhang

Remove OpalPasswordExtraInfoVariable.h as it is not been used
anymore.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 .../Include/Guid/OpalPasswordExtraInfoVariable.h   | 27 ----------------------
 1 file changed, 27 deletions(-)
 delete mode 100644 SecurityPkg/Include/Guid/OpalPasswordExtraInfoVariable.h

diff --git a/SecurityPkg/Include/Guid/OpalPasswordExtraInfoVariable.h b/SecurityPkg/Include/Guid/OpalPasswordExtraInfoVariable.h
deleted file mode 100644
index f16d0a4ac360..000000000000
--- a/SecurityPkg/Include/Guid/OpalPasswordExtraInfoVariable.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/** @file
-  Defines Name GUIDs to represent an Opal device variable guid for Opal Security Feature.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _OPAL_PASSWORD_EXTRA_INFO_VARIABLE_H_
-#define _OPAL_PASSWORD_EXTRA_INFO_VARIABLE_H_
-
-#define OPAL_EXTRA_INFO_VAR_NAME L"OpalExtraInfo"
-
-typedef struct {
-  UINT8   EnableBlockSid;
-} OPAL_EXTRA_INFO_VAR;
-
-extern EFI_GUID gOpalExtraInfoVariableGuid;
-
-#endif // _OPAL_PASSWORD_SECURITY_VARIABLE_H_
-
-- 
2.7.0.windows.1



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

* Re: [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code
  2018-03-07 13:19 ` [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code Star Zeng
@ 2018-03-08 11:44   ` Yao, Jiewen
  2018-03-08 11:48     ` Zeng, Star
  0 siblings, 1 reply; 10+ messages in thread
From: Yao, Jiewen @ 2018-03-08 11:44 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org; +Cc: Dong, Eric, Zhang, Chao B

One minor:

> +  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {

I prefer we also zero Unicode here. ESC just means exit, the Unicode buffer might already be filled.

> +    return NULL;
> +  }
> +
> +  Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);
> +  if (Ascii == NULL) {
> +    ZeroMem (Unicode, sizeof (Unicode));
> +    ZeroMem (Mask, sizeof (Mask));
> +    return NULL;
> +  }

With above change, Reviewed-by: Jiewen.yao@intel.com

> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, March 7, 2018 9:19 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> Dong, Eric <eric.dong@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
> Subject: [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM
> device code
> 
> After IOMMU is enabled in S3, original solution with SMM device
> code (OpalPasswordSmm) to unlock OPAL device for S3 will not work
> as the DMA operation will be aborted without granted DMA buffer.
> Instead, this solution is to add OpalPasswordPei to eliminate
> SMM device code, and OPAL setup UI produced by OpalPasswordDxe
> will be updated to send requests (set password, update password,
> and etc), and then the requests will be processed in next boot
> before SmmReadyToLock, password and device info will be saved to
> lock box used by OpalPasswordPei to unlock OPAL device for S3.
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Star Zeng <star.zeng@intel.com>
> ---
>  SecurityPkg/SecurityPkg.dsc                        |    2 +
>  SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c  |  398 +++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c   | 1335 +++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h   |  435 +++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c     | 3003
> ++++++++++++++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h     |  613 ++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c        | 1178 ++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h        |  380 +++
>  .../Tcg/Opal/OpalPassword/OpalHiiCallbacks.c       |  219 ++
>  .../Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni   |   84 +
>  .../Tcg/Opal/OpalPassword/OpalHiiFormValues.h      |  123 +
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c   | 2144
> ++++++++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h   |  455 +++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h    |  815 ++++++
>  .../Tcg/Opal/OpalPassword/OpalPasswordCommon.h     |   65 +
>  .../Tcg/Opal/OpalPassword/OpalPasswordDxe.inf      |   81 +
>  .../Tcg/Opal/OpalPassword/OpalPasswordForm.vfr     |  309 ++
>  .../Tcg/Opal/OpalPassword/OpalPasswordPei.c        |  940 ++++++
>  .../Tcg/Opal/OpalPassword/OpalPasswordPei.h        |  133 +
>  .../Tcg/Opal/OpalPassword/OpalPasswordPei.inf      |   63 +
>  20 files changed, 12775 insertions(+)
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> 
> diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
> index 65a2fe3d7967..f82703a17b82 100644
> --- a/SecurityPkg/SecurityPkg.dsc
> +++ b/SecurityPkg/SecurityPkg.dsc
> @@ -324,6 +324,8 @@ [Components.IA32, Components.X64]
>    #
>    SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
>    SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf
> +  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> +  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> 
>  [Components.IPF]
>    SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/EsalVariableDxeSal.inf
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
> new file mode 100644
> index 000000000000..ef963d0e0b62
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
> @@ -0,0 +1,398 @@
> +/** @file
> +  UEFI Component Name(2) protocol implementation for Opal driver.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalDriver.h"
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL
> gOpalComponentName = {
> +  OpalEfiDriverComponentNameGetDriverName,
> +  OpalEfiDriverComponentNameGetControllerName,
> +  "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
> gOpalComponentName2 = {
> +  OpalEfiDriverComponentName2GetDriverName,
> +  OpalEfiDriverComponentName2GetControllerName,
> +  "en"
> +};
> +
> +
> +/// The name of the driver in all the languages we support.
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mOpalDriverNameTable[] = {
> +    { LANGUAGE_RFC_3066_ENGLISH,
> (CHAR16*)EFI_DRIVER_NAME_UNICODE },
> +    { LANGUAGE_ISO_639_2_ENGLISH,
> (CHAR16*)EFI_DRIVER_NAME_UNICODE },
> +    { 0, 0 }
> +};
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetDriverName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  )
> +{
> +  return LookupUnicodeString2(
> +    Language,
> +    This->SupportedLanguages,
> +    mOpalDriverNameTable,
> +    DriverName,
> +    TRUE
> +    );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetDriverName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  )
> +{
> +  return LookupUnicodeString2(
> +    Language,
> +    This->SupportedLanguages,
> +    mOpalDriverNameTable,
> +    DriverName,
> +    FALSE
> +    );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +GetControllerName(
> +  EFI_HANDLE  ControllerHandle,
> +  EFI_HANDLE  ChildHandle,
> +  CHAR8*      Language,
> +  CHAR16**    ControllerName
> +  )
> +{
> +  if (Language == NULL || ControllerName == NULL || ControllerHandle ==
> NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // don't support any controller or children names
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetControllerName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  )
> +{
> +  return (GetControllerName( ControllerHandle, ChildHandle, Language,
> ControllerName));
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetControllerName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  )
> +{
> +  return (GetControllerName(ControllerHandle, ChildHandle, Language,
> ControllerName));
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> new file mode 100644
> index 000000000000..550abacc9c75
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> @@ -0,0 +1,1335 @@
> +/** @file
> +  This driver is used for Opal Password Feature support at AHCI mode.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +
> +#include "OpalPasswordPei.h"
> +
> +/**
> +  Start command for give slot on specific port.
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  CommandSlot        The number of CommandSlot.
> +  @param  Timeout            The timeout Value of start.
> +
> +  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command start successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStartCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT8                     CommandSlot,
> +  IN  UINT64                    Timeout
> +  );
> +
> +/**
> +  Stop command running for giving port
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  Timeout            The timeout Value of stop.
> +
> +  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command stop successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStopCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  );
> +
> +/**
> +  Read AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +
> +  @return The register content read.
> +
> +**/
> +UINT32
> +EFIAPI
> +AhciReadReg (
> +  IN  UINT32              AhciBar,
> +  IN  UINT32              Offset
> +  )
> +{
> +  UINT32   Data;
> +
> +  Data = 0;
> +
> +  Data = MmioRead32 (AhciBar + Offset);
> +
> +  return Data;
> +}
> +
> +/**
> +  Write AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +  @param  Data         The Data used to write down.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciWriteReg (
> +  IN UINT32               AhciBar,
> +  IN UINT32               Offset,
> +  IN UINT32               Data
> +  )
> +{
> +  MmioWrite32 (AhciBar + Offset, Data);
> +
> +  return ;
> +}
> +
> +/**
> +  Do AND operation with the Value of AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +  @param  AndData      The Data used to do AND operation.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciAndReg (
> +  IN UINT32               AhciBar,
> +  IN UINT32               Offset,
> +  IN UINT32               AndData
> +  )
> +{
> +  UINT32 Data;
> +
> +  Data  = AhciReadReg (AhciBar, Offset);
> +
> +  Data &= AndData;
> +
> +  AhciWriteReg (AhciBar, Offset, Data);
> +}
> +
> +/**
> +  Do OR operation with the Value of AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +  @param  OrData       The Data used to do OR operation.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciOrReg (
> +  IN UINT32               AhciBar,
> +  IN UINT32               Offset,
> +  IN UINT32               OrData
> +  )
> +{
> +  UINT32 Data;
> +
> +  Data  = AhciReadReg (AhciBar, Offset);
> +
> +  Data |= OrData;
> +
> +  AhciWriteReg (AhciBar, Offset, Data);
> +}
> +
> +/**
> +  Wait for memory set to the test Value.
> +
> +  @param  AhciBar           AHCI bar address.
> +  @param  Offset            The memory offset to test.
> +  @param  MaskValue         The mask Value of memory.
> +  @param  TestValue         The test Value of memory.
> +  @param  Timeout           The time out Value for wait memory set.
> +
> +  @retval EFI_DEVICE_ERROR  The memory is not set.
> +  @retval EFI_TIMEOUT       The memory setting is time out.
> +  @retval EFI_SUCCESS       The memory is correct set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciWaitMmioSet (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT32                    Offset,
> +  IN  UINT32                    MaskValue,
> +  IN  UINT32                    TestValue,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32     Value;
> +  UINT32     Delay;
> +
> +  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
> +
> +  do {
> +    Value = AhciReadReg (AhciBar, Offset) & MaskValue;
> +
> +    if (Value == TestValue) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // Stall for 100 microseconds.
> +    //
> +    MicroSecondDelay (100);
> +
> +    Delay--;
> +
> +  } while (Delay > 0);
> +
> +  return EFI_TIMEOUT;
> +}
> +/**
> +  Wait for the Value of the specified system memory set to the test Value.
> +
> +  @param  Address           The system memory address to test.
> +  @param  MaskValue         The mask Value of memory.
> +  @param  TestValue         The test Value of memory.
> +  @param  Timeout           The time out Value for wait memory set,
> uses 100ns as a unit.
> +
> +  @retval EFI_TIMEOUT       The system memory setting is time out.
> +  @retval EFI_SUCCESS       The system memory is correct set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciWaitMemSet (
> +  IN  EFI_PHYSICAL_ADDRESS      Address,
> +  IN  UINT32                    MaskValue,
> +  IN  UINT32                    TestValue,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32     Value;
> +  UINT32     Delay;
> +
> +  Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
> +
> +  do {
> +    //
> +    // Access sytem memory to see if the Value is the tested one.
> +    //
> +    // The system memory pointed by Address will be updated by the
> +    // SATA Host Controller, "volatile" is introduced to prevent
> +    // compiler from optimizing the access to the memory address
> +    // to only read once.
> +    //
> +    Value  = *(volatile UINT32 *) (UINTN) Address;
> +    Value &= MaskValue;
> +
> +    if (Value == TestValue) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // Stall for 100 microseconds.
> +    //
> +    MicroSecondDelay (100);
> +
> +    Delay--;
> +
> +  } while (Delay > 0);
> +
> +  return EFI_TIMEOUT;
> +}
> +
> +/**
> +  Check the memory status to the test Value.
> +
> +  @param[in]       Address           The memory address to test.
> +  @param[in]       MaskValue         The mask Value of memory.
> +  @param[in]       TestValue         The test Value of memory.
> +  @param[in, out]  RetryTimes        The retry times Value for waitting
> memory set. If 0, then just try once.
> +
> +  @retval EFI_NOTREADY      The memory is not set.
> +  @retval EFI_TIMEOUT       The memory setting retry times out.
> +  @retval EFI_SUCCESS       The memory is correct set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciCheckMemSet (
> +  IN     UINTN                     Address,
> +  IN     UINT32                    MaskValue,
> +  IN     UINT32                    TestValue,
> +  IN OUT UINTN                     *RetryTimes OPTIONAL
> +  )
> +{
> +  UINT32     Value;
> +
> +  if (RetryTimes != NULL) {
> +    (*RetryTimes)--;
> +  }
> +
> +  Value  = *(volatile UINT32 *) Address;
> +  Value &= MaskValue;
> +
> +  if (Value == TestValue) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if ((RetryTimes != NULL) && (*RetryTimes == 0)) {
> +    return EFI_TIMEOUT;
> +  } else {
> +    return EFI_NOT_READY;
> +  }
> +}
> +
> +/**
> +  Clear the port interrupt and error status. It will also clear
> +  HBA interrupt status.
> +
> +  @param      AhciBar        AHCI bar address.
> +  @param      Port           The number of port.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciClearPortStatus (
> +  IN  UINT32                 AhciBar,
> +  IN  UINT8                  Port
> +  )
> +{
> +  UINT32 Offset;
> +
> +  //
> +  // Clear any error status
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SERR;
> +  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
> +
> +  //
> +  // Clear any port interrupt status
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_IS;
> +  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
> +
> +  //
> +  // Clear any HBA interrupt status
> +  //
> +  AhciWriteReg (AhciBar, EFI_AHCI_IS_OFFSET, AhciReadReg (AhciBar,
> EFI_AHCI_IS_OFFSET));
> +}
> +
> +/**
> +  Enable the FIS running for giving port.
> +
> +  @param      AhciBar        AHCI bar address.
> +  @param      Port           The number of port.
> +  @param      Timeout        The timeout Value of enabling FIS.
> +
> +  @retval EFI_DEVICE_ERROR   The FIS enable setting fails.
> +  @retval EFI_TIMEOUT        The FIS enable setting is time out.
> +  @retval EFI_SUCCESS        The FIS enable successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciEnableFisReceive (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32 Offset;
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_FRE);
> +
> +  return AhciWaitMmioSet (
> +           AhciBar,
> +           Offset,
> +           EFI_AHCI_PORT_CMD_FR,
> +           EFI_AHCI_PORT_CMD_FR,
> +           Timeout
> +           );
> +}
> +
> +/**
> +  Disable the FIS running for giving port.
> +
> +  @param      AhciBar        AHCI bar address.
> +  @param      Port           The number of port.
> +  @param      Timeout        The timeout Value of disabling FIS.
> +
> +  @retval EFI_DEVICE_ERROR   The FIS disable setting fails.
> +  @retval EFI_TIMEOUT        The FIS disable setting is time out.
> +  @retval EFI_UNSUPPORTED    The port is in running state.
> +  @retval EFI_SUCCESS        The FIS disable successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciDisableFisReceive (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32 Offset;
> +  UINT32 Data;
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  Data   = AhciReadReg (AhciBar, Offset);
> +
> +  //
> +  // Before disabling Fis receive, the DMA engine of the port should NOT be in
> running status.
> +  //
> +  if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Check if the Fis receive DMA engine for the port is running.
> +  //
> +  if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
> +
> +  return AhciWaitMmioSet (
> +           AhciBar,
> +           Offset,
> +           EFI_AHCI_PORT_CMD_FR,
> +           0,
> +           Timeout
> +           );
> +}
> +
> +/**
> +  Build the command list, command table and prepare the fis receiver.
> +
> +  @param    AhciContext           The pointer to the AHCI_CONTEXT.
> +  @param    Port                  The number of port.
> +  @param    PortMultiplier        The timeout Value of stop.
> +  @param    CommandFis            The control fis will be used for the
> transfer.
> +  @param    CommandList           The command list will be used for the
> transfer.
> +  @param    AtapiCommand          The atapi command will be used for
> the transfer.
> +  @param    AtapiCommandLength    The Length of the atapi command.
> +  @param    CommandSlotNumber     The command slot will be used for
> the transfer.
> +  @param    DataPhysicalAddr      The pointer to the Data Buffer pci bus
> master address.
> +  @param    DataLength            The Data count to be transferred.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciBuildCommand (
> +  IN     AHCI_CONTEXT               *AhciContext,
> +  IN     UINT8                      Port,
> +  IN     UINT8                      PortMultiplier,
> +  IN     EFI_AHCI_COMMAND_FIS       *CommandFis,
> +  IN     EFI_AHCI_COMMAND_LIST      *CommandList,
> +  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
> +  IN     UINT8                      AtapiCommandLength,
> +  IN     UINT8                      CommandSlotNumber,
> +  IN OUT VOID                       *DataPhysicalAddr,
> +  IN     UINT64                     DataLength
> +  )
> +{
> +  EFI_AHCI_REGISTERS    *AhciRegisters;
> +  UINT32                AhciBar;
> +  UINT64                BaseAddr;
> +  UINT64                PrdtNumber;
> +  UINTN                 RemainedData;
> +  UINTN                 MemAddr;
> +  DATA_64               Data64;
> +  UINT32                Offset;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +  AhciBar = AhciContext->AhciBar;
> +
> +  //
> +  // Filling the PRDT
> +  //
> +  PrdtNumber = DivU64x32 (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT -
> 1, EFI_AHCI_MAX_DATA_PER_PRDT);
> +
> +  //
> +  // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB
> Data block.
> +  // It also limits that the maximum amount of the PRDT entry in the command
> table
> +  // is 65535.
> +  //
> +  ASSERT (PrdtNumber <= 1);
> +
> +  Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis);
> +
> +  BaseAddr = Data64.Uint64;
> +
> +  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
> +
> +  ZeroMem (AhciRegisters->AhciCommandTable, sizeof
> (EFI_AHCI_COMMAND_TABLE));
> +
> +  CommandFis->AhciCFisPmNum = PortMultiplier;
> +
> +  CopyMem (&AhciRegisters->AhciCommandTable->CommandFis,
> CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  if (AtapiCommand != NULL) {
> +    CopyMem (
> +      &AhciRegisters->AhciCommandTable->AtapiCmd,
> +      AtapiCommand,
> +      AtapiCommandLength
> +      );
> +
> +    CommandList->AhciCmdA = 1;
> +    CommandList->AhciCmdP = 1;
> +
> +    AhciOrReg (AhciBar, Offset, (EFI_AHCI_PORT_CMD_DLAE |
> EFI_AHCI_PORT_CMD_ATAPI));
> +  } else {
> +    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE |
> EFI_AHCI_PORT_CMD_ATAPI));
> +  }
> +
> +  RemainedData = (UINTN) DataLength;
> +  MemAddr      = (UINTN) DataPhysicalAddr;
> +  CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
> +
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbc =
> (UINT32)RemainedData - 1;
> +
> +  Data64.Uint64 = (UINT64)MemAddr;
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDba  =
> Data64.Uint32.Lower32;
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbau =
> Data64.Uint32.Upper32;
> +
> +  //
> +  // Set the last PRDT to Interrupt On Complete
> +  //
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtIoc = 1;
> +
> +  CopyMem (
> +    (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN)
> CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
> +    CommandList,
> +    sizeof (EFI_AHCI_COMMAND_LIST)
> +    );
> +
> +  Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTable;
> +  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba  =
> Data64.Uint32.Lower32;
> +  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau =
> Data64.Uint32.Upper32;
> +  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp   =
> PortMultiplier;
> +
> +}
> +
> +/**
> +  Buid a command FIS.
> +
> +  @param  CmdFis            A pointer to the EFI_AHCI_COMMAND_FIS
> Data structure.
> +  @param  AtaCommandBlock   A pointer to the AhciBuildCommandFis
> Data structure.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciBuildCommandFis (
> +  IN OUT EFI_AHCI_COMMAND_FIS    *CmdFis,
> +  IN     EFI_ATA_COMMAND_BLOCK   *AtaCommandBlock
> +  )
> +{
> +  ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
> +
> +  CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
> +  //
> +  // Indicator it's a command
> +  //
> +  CmdFis->AhciCFisCmdInd      = 0x1;
> +  CmdFis->AhciCFisCmd         = AtaCommandBlock->AtaCommand;
> +
> +  CmdFis->AhciCFisFeature     = AtaCommandBlock->AtaFeatures;
> +  CmdFis->AhciCFisFeatureExp  = AtaCommandBlock->AtaFeaturesExp;
> +
> +  CmdFis->AhciCFisSecNum      = AtaCommandBlock->AtaSectorNumber;
> +  CmdFis->AhciCFisSecNumExp   =
> AtaCommandBlock->AtaSectorNumberExp;
> +
> +  CmdFis->AhciCFisClyLow      = AtaCommandBlock->AtaCylinderLow;
> +  CmdFis->AhciCFisClyLowExp   = AtaCommandBlock->AtaCylinderLowExp;
> +
> +  CmdFis->AhciCFisClyHigh     = AtaCommandBlock->AtaCylinderHigh;
> +  CmdFis->AhciCFisClyHighExp  = AtaCommandBlock->AtaCylinderHighExp;
> +
> +  CmdFis->AhciCFisSecCount    = AtaCommandBlock->AtaSectorCount;
> +  CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
> +
> +  CmdFis->AhciCFisDevHead     = (UINT8)
> (AtaCommandBlock->AtaDeviceHead | 0xE0);
> +}
> +
> +/**
> +  Start a PIO Data transfer on specific port.
> +
> +  @param  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param  Port                The number of port.
> +  @param  PortMultiplier      The timeout Value of stop.
> +  @param  AtapiCommand        The atapi command will be used for the
> transfer.
> +  @param  AtapiCommandLength  The Length of the atapi command.
> +  @param  Read                The transfer direction.
> +  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
> +  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
> +  @param  MemoryAddr          The pointer to the Data Buffer.
> +  @param  DataCount           The Data count to be transferred.
> +  @param  Timeout             The timeout Value of non Data transfer.
> +
> +  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error
> occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
> +  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciPioTransfer (
> +  IN     AHCI_CONTEXT               *AhciContext,
> +  IN     UINT8                      Port,
> +  IN     UINT8                      PortMultiplier,
> +  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
> +  IN     UINT8                      AtapiCommandLength,
> +  IN     BOOLEAN                    Read,
> +  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
> +  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
> +  IN OUT VOID                       *MemoryAddr,
> +  IN     UINT32                     DataCount,
> +  IN     UINT64                     Timeout
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_AHCI_REGISTERS            *AhciRegisters;
> +  UINT32                        AhciBar;
> +  UINT32                        FisBaseAddr;
> +  UINT32                        Offset;
> +  UINT32                        Delay;
> +  EFI_AHCI_COMMAND_FIS          CFis;
> +  EFI_AHCI_COMMAND_LIST         CmdList;
> +  UINT32                        PortTfd;
> +  UINT32                        PrdCount;
> +  UINT32                        OldRfisLo;
> +  UINT32                        OldRfisHi;
> +  UINT32                        OldCmdListLo;
> +  UINT32                        OldCmdListHi;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +  AhciBar = AhciContext->AhciBar;
> +
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  OldRfisLo = AhciReadReg (AhciBar, Offset);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> +  OldRfisHi = AhciReadReg (AhciBar, Offset);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> +  AhciWriteReg (AhciBar, Offset, 0);
> +
> +  //
> +  // Single task envrionment, we only use one command table for all port
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  OldCmdListLo = AhciReadReg (AhciBar, Offset);
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> +  OldCmdListHi = AhciReadReg (AhciBar, Offset);
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> +  AhciWriteReg (AhciBar, Offset, 0);
> +
> +  //
> +  // Package read needed
> +  //
> +  AhciBuildCommandFis (&CFis, AtaCommandBlock);
> +
> +  ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
> +
> +  CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
> +  CmdList.AhciCmdW   = Read ? 0 : 1;
> +
> +  AhciBuildCommand (
> +    AhciContext,
> +    Port,
> +    PortMultiplier,
> +    &CFis,
> +    &CmdList,
> +    AtapiCommand,
> +    AtapiCommandLength,
> +    0,
> +    MemoryAddr,
> +    DataCount
> +    );
> +
> +  Status = AhciStartCommand (
> +             AhciBar,
> +             Port,
> +             0,
> +             Timeout
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto Exit;
> +  }
> +
> +  //
> +  // Checking the status and wait the driver sending Data
> +  //
> +  FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis;
> +  if (Read && (AtapiCommand == 0)) {
> +    //
> +    // Wait device sends the PIO setup fis before Data transfer
> +    //
> +    Status = EFI_TIMEOUT;
> +    Delay  = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
> +    do {
> +      Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
> +
> +      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK,
> EFI_AHCI_FIS_PIO_SETUP, 0);
> +      if (!EFI_ERROR (Status)) {
> +        Offset = EFI_AHCI_PORT_START + Port *
> EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
> +        PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
> +        //
> +        // PxTFD will be updated if there is a D2H or SetupFIS received.
> +        // For PIO IN transfer, D2H means a device error. Therefore we only
> need to check the TFD after receiving a SetupFIS.
> +        //
> +        if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
> +          Status = EFI_DEVICE_ERROR;
> +          break;
> +        }
> +
> +        PrdCount = *(volatile UINT32 *)
> (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
> +        if (PrdCount == DataCount) {
> +          break;
> +        }
> +      }
> +
> +      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
> +      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK,
> EFI_AHCI_FIS_REGISTER_D2H, 0);
> +      if (!EFI_ERROR (Status)) {
> +        Status = EFI_DEVICE_ERROR;
> +        break;
> +      }
> +
> +      //
> +      // Stall for 100 microseconds.
> +      //
> +      MicroSecondDelay(100);
> +
> +      Delay--;
> +    } while (Delay > 0);
> +  } else {
> +    //
> +    // Wait for D2H Fis is received
> +    //
> +    Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
> +    Status = AhciWaitMemSet (
> +               Offset,
> +               EFI_AHCI_FIS_TYPE_MASK,
> +               EFI_AHCI_FIS_REGISTER_D2H,
> +               Timeout
> +               );
> +
> +    if (EFI_ERROR (Status)) {
> +      goto Exit;
> +    }
> +
> +    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> +    PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
> +    if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
> +      Status = EFI_DEVICE_ERROR;
> +    }
> +  }
> +
> +Exit:
> +  AhciStopCommand (
> +    AhciBar,
> +    Port,
> +    Timeout
> +    );
> +
> +  AhciDisableFisReceive (
> +    AhciBar,
> +    Port,
> +    Timeout
> +    );
> +
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  AhciWriteReg (AhciBar, Offset, OldRfisLo);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> +  AhciWriteReg (AhciBar, Offset, OldRfisHi);
> +
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  AhciWriteReg (AhciBar, Offset, OldCmdListLo);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> +  AhciWriteReg (AhciBar, Offset, OldCmdListHi);
> +
> +  return Status;
> +}
> +
> +/**
> +  Stop command running for giving port
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  Timeout            The timeout Value of stop.
> +
> +  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command stop successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStopCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32 Offset;
> +  UINT32 Data;
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  Data   = AhciReadReg (AhciBar, Offset);
> +
> +  if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
> +    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
> +  }
> +
> +  return AhciWaitMmioSet (
> +           AhciBar,
> +           Offset,
> +           EFI_AHCI_PORT_CMD_CR,
> +           0,
> +           Timeout
> +           );
> +}
> +
> +/**
> +  Start command for give slot on specific port.
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  CommandSlot        The number of CommandSlot.
> +  @param  Timeout            The timeout Value of start.
> +
> +  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command start successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStartCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT8                     CommandSlot,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32                        CmdSlotBit;
> +  EFI_STATUS                    Status;
> +  UINT32                        PortStatus;
> +  UINT32                        StartCmd;
> +  UINT32                        PortTfd;
> +  UINT32                        Offset;
> +  UINT32                        Capability;
> +
> +  //
> +  // Collect AHCI controller information
> +  //
> +  Capability = AhciReadReg(AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> +
> +  CmdSlotBit = (UINT32) (1 << CommandSlot);
> +
> +  AhciClearPortStatus (
> +    AhciBar,
> +    Port
> +    );
> +
> +  Status = AhciEnableFisReceive (
> +             AhciBar,
> +             Port,
> +             Timeout
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  PortStatus = AhciReadReg (AhciBar, Offset);
> +
> +  StartCmd = 0;
> +  if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
> +    StartCmd = AhciReadReg (AhciBar, Offset);
> +    StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
> +    StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> +  PortTfd = AhciReadReg (AhciBar, Offset);
> +
> +  if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0)
> {
> +    if ((Capability & BIT24) != 0) {
> +      Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH
> + EFI_AHCI_PORT_CMD;
> +      AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_COL);
> +
> +      AhciWaitMmioSet (
> +        AhciBar,
> +        Offset,
> +        EFI_AHCI_PORT_CMD_COL,
> +        0,
> +        Timeout
> +        );
> +    }
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
> +
> +  //
> +  // Setting the command
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SACT;
> +  AhciAndReg (AhciBar, Offset, 0);
> +  AhciOrReg (AhciBar, Offset, CmdSlotBit);
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CI;
> +  AhciAndReg (AhciBar, Offset, 0);
> +  AhciOrReg (AhciBar, Offset, CmdSlotBit);
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Do AHCI HBA reset.
> +
> +  @param[in]  AhciBar        AHCI bar address.
> +  @param[in]  Timeout        The timeout Value of reset.
> +
> +  @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete
> hardware reset.
> +  @retval EFI_TIMEOUT        The reset operation is time out.
> +  @retval EFI_SUCCESS        AHCI controller is reset successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciReset (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32                 Delay;
> +  UINT32                 Value;
> +  UINT32                 Capability;
> +
> +  //
> +  // Collect AHCI controller information
> +  //
> +  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> +
> +  //
> +  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only
> is not set
> +  //
> +  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
> +    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
> +  }
> +
> +  AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
> +
> +  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
> +
> +  do {
> +    Value = AhciReadReg(AhciBar, EFI_AHCI_GHC_OFFSET);
> +    if ((Value & EFI_AHCI_GHC_RESET) == 0) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // Stall for 100 microseconds.
> +    //
> +    MicroSecondDelay(100);
> +
> +    Delay--;
> +  } while (Delay > 0);
> +
> +  return EFI_TIMEOUT;
> +
> +
> +}
> +
> +/**
> +  Send Buffer cmd to specific device.
> +
> +  @param[in]  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param[in]  Port                The port number of attached ATA
> device.
> +  @param[in]  PortMultiplier      The port number of port multiplier of
> attached ATA device.
> +  @param[in, out]  Buffer         The Data Buffer to store IDENTIFY
> PACKET Data.
> +
> +  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for executing.
> +  @retval EFI_SUCCESS         The cmd executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciIdentify (
> +  IN AHCI_CONTEXT             *AhciContext,
> +  IN UINT8                    Port,
> +  IN UINT8                    PortMultiplier,
> +  IN OUT ATA_IDENTIFY_DATA    *Buffer
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
> +
> +  if (AhciContext == NULL || Buffer == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
> +
> +  AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DRIVE;
> +  AtaCommandBlock.AtaSectorCount = 1;
> +
> +  Status = AhciPioTransfer (
> +             AhciContext,
> +             Port,
> +             PortMultiplier,
> +             NULL,
> +             0,
> +             TRUE,
> +             &AtaCommandBlock,
> +             NULL,
> +             Buffer,
> +             sizeof (ATA_IDENTIFY_DATA),
> +             ATA_TIMEOUT
> +             );
> +
> +  return Status;
> +}
> +
> +/**
> +  Allocate transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciAllocateResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_AHCI_REGISTERS        *AhciRegisters;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
> +  VOID                      *Base;
> +  VOID                      *Mapping;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +
> +  //
> +  // Allocate resources required by AHCI host controller.
> +  //
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciRegisters->AhciRFisMapping = Mapping;
> +  AhciRegisters->AhciRFis = Base;
> +  ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (sizeof (EFI_AHCI_RECEIVED_FIS)));
> +
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciRegisters->AhciCmdListMapping = Mapping;
> +  AhciRegisters->AhciCmdList = Base;
> +  ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE *
> EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
> +
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +       AhciRegisters->AhciCmdList,
> +       AhciRegisters->AhciCmdListMapping
> +       );
> +    AhciRegisters->AhciCmdList = NULL;
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciRegisters->AhciCommandTableMapping = Mapping;
> +  AhciRegisters->AhciCommandTable = Base;
> +  ZeroMem (AhciRegisters->AhciCommandTable, EFI_PAGE_SIZE *
> EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));
> +
> +  //
> +  // Allocate resources for data transfer.
> +  //
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +       AhciRegisters->AhciCmdList,
> +       AhciRegisters->AhciCmdListMapping
> +       );
> +    AhciRegisters->AhciCmdList = NULL;
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciCommandTable,
> +       AhciRegisters->AhciCommandTableMapping
> +       );
> +    AhciRegisters->AhciCommandTable = NULL;
> +
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciContext->BufferMapping = Mapping;
> +  AhciContext->Buffer = Base;
> +  ZeroMem (AhciContext->Buffer, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (HDD_PAYLOAD));
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a() AhciContext 0x%x 0x%x 0x%x 0x%x\n",
> +    __FUNCTION__,
> +    AhciContext->Buffer,
> +    AhciRegisters->AhciRFis,
> +    AhciRegisters->AhciCmdList,
> +    AhciRegisters->AhciCommandTable
> +    ));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Free allocated transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciFreeResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  )
> +{
> +  EFI_AHCI_REGISTERS        *AhciRegisters;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +
> +  if (AhciRegisters->AhciRFis != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +  }
> +
> +  if (AhciRegisters->AhciCmdList != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +       AhciRegisters->AhciCmdList,
> +       AhciRegisters->AhciCmdListMapping
> +       );
> +    AhciRegisters->AhciCmdList = NULL;
> +  }
> +
> +  if (AhciRegisters->AhciCommandTable != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> +       AhciRegisters->AhciCommandTable,
> +       AhciRegisters->AhciCommandTableMapping
> +       );
> +    AhciRegisters->AhciCommandTable = NULL;
> +  }
> +
> +  if (AhciContext->Buffer != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> +       AhciContext->Buffer,
> +       AhciContext->BufferMapping
> +       );
> +    AhciContext->Buffer = NULL;
> +  }
> +}
> +
> +/**
> +  Initialize ATA host controller at AHCI mode.
> +
> +  The function is designed to initialize ATA host controller.
> +
> +  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.
> +  @param[in]  Port          The port number to do initialization.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciModeInitialize (
> +  IN AHCI_CONTEXT    *AhciContext,
> +  IN UINT8           Port
> +  )
> +{
> +  EFI_STATUS         Status;
> +  EFI_AHCI_REGISTERS *AhciRegisters;
> +  UINT32             AhciBar;
> +  UINT32             Capability;
> +  UINT32             Offset;
> +  UINT32             Data;
> +  UINT32             PhyDetectDelay;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +  AhciBar = AhciContext->AhciBar;
> +
> +  Status = AhciReset (AhciBar, ATA_TIMEOUT);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Collect AHCI controller information
> +  //
> +  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> +
> +  //
> +  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only
> is not set
> +  //
> +  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
> +    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
> +
> +  //
> +  // Single task envrionment, we only use one command table for all port
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  Data = AhciReadReg (AhciBar, Offset);
> +  if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
> +    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_POD);
> +  }
> +
> +  if ((Capability & BIT27) != 0) {
> +    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_SUD);
> +  }
> +
> +  //
> +  // Disable aggressive power management.
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SCTL;
> +  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
> +  //
> +  // Disable the reporting of the corresponding interrupt to system software.
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_IE;
> +  AhciAndReg (AhciBar, Offset, 0);
> +
> +  Status = AhciEnableFisReceive (
> +             AhciBar,
> +             Port,
> +             5000000
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY
> and PxTFD.DRQ
> +  // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined
> at ATA spec.
> +  //
> +  PhyDetectDelay = 16 * 1000;
> +  do {
> +    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SERR;
> +    if (AhciReadReg(AhciBar, Offset) != 0) {
> +      AhciWriteReg (AhciBar, Offset, AhciReadReg(AhciBar, Offset));
> +    }
> +    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> +
> +    Data = AhciReadReg (AhciBar, Offset) & EFI_AHCI_PORT_TFD_MASK;
> +    if (Data == 0) {
> +      break;
> +    }
> +
> +    MicroSecondDelay (1000);
> +    PhyDetectDelay--;
> +  } while (PhyDetectDelay > 0);
> +
> +  if (PhyDetectDelay == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SIG;
> +  Status = AhciWaitMmioSet (
> +             AhciBar,
> +             Offset,
> +             0x0000FFFF,
> +             0x00000101,
> +             160000000
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> new file mode 100644
> index 000000000000..b1d6ed13d5b9
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> @@ -0,0 +1,435 @@
> +/** @file
> +  Header file for AHCI mode of ATA host controller.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +
> +#ifndef __OPAL_PASSWORD_AHCI_MODE_H__
> +#define __OPAL_PASSWORD_AHCI_MODE_H__
> +
> +//
> +// OPAL LIBRARY CALLBACKS
> +//
> +#define ATA_COMMAND_TRUSTED_RECEIVE            0x5C
> +#define ATA_COMMAND_TRUSTED_SEND               0x5E
> +
> +//
> +// ATA TRUSTED commands express transfer Length in 512 byte multiple
> +//
> +#define ATA_TRUSTED_TRANSFER_LENGTH_MULTIPLE   512
> +#define ATA_DEVICE_LBA                         0x40    ///< Set for
> commands with LBA (rather than CHS) addresses
> +
> +
> +#define EFI_AHCI_BAR_INDEX                     0x05
> +
> +#define EFI_AHCI_CAPABILITY_OFFSET             0x0000
> +#define   EFI_AHCI_CAP_SAM                     BIT18
> +#define EFI_AHCI_GHC_OFFSET                    0x0004
> +#define   EFI_AHCI_GHC_RESET                   BIT0
> +#define   EFI_AHCI_GHC_IE                      BIT1
> +#define   EFI_AHCI_GHC_ENABLE                  BIT31
> +#define EFI_AHCI_IS_OFFSET                     0x0008
> +#define EFI_AHCI_PI_OFFSET                     0x000C
> +
> +typedef struct {
> +  UINT32  Lower32;
> +  UINT32  Upper32;
> +} DATA_32;
> +
> +typedef union {
> +  DATA_32   Uint32;
> +  UINT64    Uint64;
> +} DATA_64;
> +
> +//
> +// Each PRDT entry can point to a memory block up to 4M byte
> +//
> +#define EFI_AHCI_MAX_DATA_PER_PRDT             0x400000
> +
> +#define EFI_AHCI_FIS_REGISTER_H2D              0x27      //Register
> FIS - Host to Device
> +#define   EFI_AHCI_FIS_REGISTER_H2D_LENGTH     20
> +#define EFI_AHCI_FIS_REGISTER_D2H              0x34      //Register
> FIS - Device to Host
> +#define   EFI_AHCI_FIS_REGISTER_D2H_LENGTH     20
> +#define EFI_AHCI_FIS_DMA_ACTIVATE              0x39      //DMA
> Activate FIS - Device to Host
> +#define   EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH     4
> +#define EFI_AHCI_FIS_DMA_SETUP                 0x41      //DMA
> Setup FIS - Bi-directional
> +#define   EFI_AHCI_FIS_DMA_SETUP_LENGTH        28
> +#define EFI_AHCI_FIS_DATA                      0x46      //Data FIS -
> Bi-directional
> +#define EFI_AHCI_FIS_BIST                      0x58      //BIST
> Activate FIS - Bi-directional
> +#define   EFI_AHCI_FIS_BIST_LENGTH             12
> +#define EFI_AHCI_FIS_PIO_SETUP                 0x5F      //PIO Setup
> FIS - Device to Host
> +#define   EFI_AHCI_FIS_PIO_SETUP_LENGTH        20
> +#define EFI_AHCI_FIS_SET_DEVICE                0xA1      //Set Device
> Bits FIS - Device to Host
> +#define   EFI_AHCI_FIS_SET_DEVICE_LENGTH       8
> +
> +#define EFI_AHCI_D2H_FIS_OFFSET                0x40
> +#define EFI_AHCI_DMA_FIS_OFFSET                0x00
> +#define EFI_AHCI_PIO_FIS_OFFSET                0x20
> +#define EFI_AHCI_SDB_FIS_OFFSET                0x58
> +#define EFI_AHCI_FIS_TYPE_MASK                 0xFF
> +#define EFI_AHCI_U_FIS_OFFSET                  0x60
> +
> +//
> +// Port register
> +//
> +#define EFI_AHCI_PORT_START                    0x0100
> +#define EFI_AHCI_PORT_REG_WIDTH                0x0080
> +#define EFI_AHCI_PORT_CLB                      0x0000
> +#define EFI_AHCI_PORT_CLBU                     0x0004
> +#define EFI_AHCI_PORT_FB                       0x0008
> +#define EFI_AHCI_PORT_FBU                      0x000C
> +#define EFI_AHCI_PORT_IS                       0x0010
> +#define   EFI_AHCI_PORT_IS_DHRS                BIT0
> +#define   EFI_AHCI_PORT_IS_PSS                 BIT1
> +#define   EFI_AHCI_PORT_IS_SSS                 BIT2
> +#define   EFI_AHCI_PORT_IS_SDBS                BIT3
> +#define   EFI_AHCI_PORT_IS_UFS                 BIT4
> +#define   EFI_AHCI_PORT_IS_DPS                 BIT5
> +#define   EFI_AHCI_PORT_IS_PCS                 BIT6
> +#define   EFI_AHCI_PORT_IS_DIS                 BIT7
> +#define   EFI_AHCI_PORT_IS_PRCS                BIT22
> +#define   EFI_AHCI_PORT_IS_IPMS                BIT23
> +#define   EFI_AHCI_PORT_IS_OFS                 BIT24
> +#define   EFI_AHCI_PORT_IS_INFS                BIT26
> +#define   EFI_AHCI_PORT_IS_IFS                 BIT27
> +#define   EFI_AHCI_PORT_IS_HBDS                BIT28
> +#define   EFI_AHCI_PORT_IS_HBFS                BIT29
> +#define   EFI_AHCI_PORT_IS_TFES                BIT30
> +#define   EFI_AHCI_PORT_IS_CPDS                BIT31
> +#define   EFI_AHCI_PORT_IS_CLEAR               0xFFFFFFFF
> +#define   EFI_AHCI_PORT_IS_FIS_CLEAR           0x0000000F
> +
> +#define EFI_AHCI_PORT_IE                       0x0014
> +#define EFI_AHCI_PORT_CMD                      0x0018
> +#define   EFI_AHCI_PORT_CMD_ST_MASK            0xFFFFFFFE
> +#define   EFI_AHCI_PORT_CMD_ST                 BIT0
> +#define   EFI_AHCI_PORT_CMD_SUD                BIT1
> +#define   EFI_AHCI_PORT_CMD_POD                BIT2
> +#define   EFI_AHCI_PORT_CMD_COL                BIT3
> +#define   EFI_AHCI_PORT_CMD_CR                 BIT15
> +#define   EFI_AHCI_PORT_CMD_FRE                BIT4
> +#define   EFI_AHCI_PORT_CMD_FR                 BIT14
> +#define   EFI_AHCI_PORT_CMD_MASK
> ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE |
> EFI_AHCI_PORT_CMD_COL)
> +#define   EFI_AHCI_PORT_CMD_PMA                BIT17
> +#define   EFI_AHCI_PORT_CMD_HPCP               BIT18
> +#define   EFI_AHCI_PORT_CMD_MPSP               BIT19
> +#define   EFI_AHCI_PORT_CMD_CPD                BIT20
> +#define   EFI_AHCI_PORT_CMD_ESP                BIT21
> +#define   EFI_AHCI_PORT_CMD_ATAPI              BIT24
> +#define   EFI_AHCI_PORT_CMD_DLAE               BIT25
> +#define   EFI_AHCI_PORT_CMD_ALPE               BIT26
> +#define   EFI_AHCI_PORT_CMD_ASP                BIT27
> +#define   EFI_AHCI_PORT_CMD_ICC_MASK           (BIT28 | BIT29 |
> BIT30 | BIT31)
> +#define   EFI_AHCI_PORT_CMD_ACTIVE             (1 << 28 )
> +#define EFI_AHCI_PORT_TFD                      0x0020
> +#define   EFI_AHCI_PORT_TFD_MASK               (BIT7 | BIT3 | BIT0)
> +#define   EFI_AHCI_PORT_TFD_BSY                BIT7
> +#define   EFI_AHCI_PORT_TFD_DRQ                BIT3
> +#define   EFI_AHCI_PORT_TFD_ERR                BIT0
> +#define   EFI_AHCI_PORT_TFD_ERR_MASK           0x00FF00
> +#define EFI_AHCI_PORT_SIG                      0x0024
> +#define EFI_AHCI_PORT_SSTS                     0x0028
> +#define   EFI_AHCI_PORT_SSTS_DET_MASK          0x000F
> +#define   EFI_AHCI_PORT_SSTS_DET               0x0001
> +#define   EFI_AHCI_PORT_SSTS_DET_PCE           0x0003
> +#define   EFI_AHCI_PORT_SSTS_SPD_MASK          0x00F0
> +#define EFI_AHCI_PORT_SCTL                     0x002C
> +#define   EFI_AHCI_PORT_SCTL_DET_MASK          0x000F
> +#define   EFI_AHCI_PORT_SCTL_MASK
> (~EFI_AHCI_PORT_SCTL_DET_MASK)
> +#define   EFI_AHCI_PORT_SCTL_DET_INIT          0x0001
> +#define   EFI_AHCI_PORT_SCTL_DET_PHYCOMM       0x0003
> +#define   EFI_AHCI_PORT_SCTL_SPD_MASK          0x00F0
> +#define   EFI_AHCI_PORT_SCTL_IPM_MASK          0x0F00
> +#define   EFI_AHCI_PORT_SCTL_IPM_INIT          0x0300
> +#define   EFI_AHCI_PORT_SCTL_IPM_PSD           0x0100
> +#define   EFI_AHCI_PORT_SCTL_IPM_SSD           0x0200
> +#define EFI_AHCI_PORT_SERR                     0x0030
> +#define   EFI_AHCI_PORT_SERR_RDIE              BIT0
> +#define   EFI_AHCI_PORT_SERR_RCE               BIT1
> +#define   EFI_AHCI_PORT_SERR_TDIE              BIT8
> +#define   EFI_AHCI_PORT_SERR_PCDIE             BIT9
> +#define   EFI_AHCI_PORT_SERR_PE                BIT10
> +#define   EFI_AHCI_PORT_SERR_IE                BIT11
> +#define   EFI_AHCI_PORT_SERR_PRC               BIT16
> +#define   EFI_AHCI_PORT_SERR_PIE               BIT17
> +#define   EFI_AHCI_PORT_SERR_CW                BIT18
> +#define   EFI_AHCI_PORT_SERR_BDE               BIT19
> +#define   EFI_AHCI_PORT_SERR_DE                BIT20
> +#define   EFI_AHCI_PORT_SERR_CRCE              BIT21
> +#define   EFI_AHCI_PORT_SERR_HE                BIT22
> +#define   EFI_AHCI_PORT_SERR_LSE               BIT23
> +#define   EFI_AHCI_PORT_SERR_TSTE              BIT24
> +#define   EFI_AHCI_PORT_SERR_UFT               BIT25
> +#define   EFI_AHCI_PORT_SERR_EX                BIT26
> +#define   EFI_AHCI_PORT_ERR_CLEAR              0xFFFFFFFF
> +#define EFI_AHCI_PORT_SACT                     0x0034
> +#define EFI_AHCI_PORT_CI                       0x0038
> +#define EFI_AHCI_PORT_SNTF                     0x003C
> +
> +
> +#pragma pack(1)
> +//
> +// Command List structure includes total 32 entries.
> +// The entry Data structure is listed at the following.
> +//
> +typedef struct {
> +  UINT32   AhciCmdCfl:5;      //Command FIS Length
> +  UINT32   AhciCmdA:1;        //ATAPI
> +  UINT32   AhciCmdW:1;        //Write
> +  UINT32   AhciCmdP:1;        //Prefetchable
> +  UINT32   AhciCmdR:1;        //Reset
> +  UINT32   AhciCmdB:1;        //BIST
> +  UINT32   AhciCmdC:1;        //Clear Busy upon R_OK
> +  UINT32   AhciCmdRsvd:1;
> +  UINT32   AhciCmdPmp:4;      //Port Multiplier Port
> +  UINT32   AhciCmdPrdtl:16;   //Physical Region Descriptor Table Length
> +  UINT32   AhciCmdPrdbc;      //Physical Region Descriptor Byte Count
> +  UINT32   AhciCmdCtba;       //Command Table Descriptor Base Address
> +  UINT32   AhciCmdCtbau;      //Command Table Descriptor Base Address
> Upper 32-BITs
> +  UINT32   AhciCmdRsvd1[4];
> +} EFI_AHCI_COMMAND_LIST;
> +
> +//
> +// This is a software constructed FIS.
> +// For Data transfer operations, this is the H2D Register FIS format as
> +// specified in the Serial ATA Revision 2.6 specification.
> +//
> +typedef struct {
> +  UINT8    AhciCFisType;
> +  UINT8    AhciCFisPmNum:4;
> +  UINT8    AhciCFisRsvd:1;
> +  UINT8    AhciCFisRsvd1:1;
> +  UINT8    AhciCFisRsvd2:1;
> +  UINT8    AhciCFisCmdInd:1;
> +  UINT8    AhciCFisCmd;
> +  UINT8    AhciCFisFeature;
> +  UINT8    AhciCFisSecNum;
> +  UINT8    AhciCFisClyLow;
> +  UINT8    AhciCFisClyHigh;
> +  UINT8    AhciCFisDevHead;
> +  UINT8    AhciCFisSecNumExp;
> +  UINT8    AhciCFisClyLowExp;
> +  UINT8    AhciCFisClyHighExp;
> +  UINT8    AhciCFisFeatureExp;
> +  UINT8    AhciCFisSecCount;
> +  UINT8    AhciCFisSecCountExp;
> +  UINT8    AhciCFisRsvd3;
> +  UINT8    AhciCFisControl;
> +  UINT8    AhciCFisRsvd4[4];
> +  UINT8    AhciCFisRsvd5[44];
> +} EFI_AHCI_COMMAND_FIS;
> +
> +//
> +// ACMD: ATAPI command (12 or 16 bytes)
> +//
> +typedef struct {
> +  UINT8    AtapiCmd[0x10];
> +} EFI_AHCI_ATAPI_COMMAND;
> +
> +//
> +// Physical Region Descriptor Table includes up to 65535 entries
> +// The entry Data structure is listed at the following.
> +// the actual entry number comes from the PRDTL field in the command
> +// list entry for this command slot.
> +//
> +typedef struct {
> +  UINT32   AhciPrdtDba;       //Data Base Address
> +  UINT32   AhciPrdtDbau;      //Data Base Address Upper 32-BITs
> +  UINT32   AhciPrdtRsvd;
> +  UINT32   AhciPrdtDbc:22;    //Data Byte Count
> +  UINT32   AhciPrdtRsvd1:9;
> +  UINT32   AhciPrdtIoc:1;     //Interrupt on Completion
> +} EFI_AHCI_COMMAND_PRDT;
> +
> +//
> +// Command table Data strucute which is pointed to by the entry in the
> command list
> +//
> +typedef struct {
> +  EFI_AHCI_COMMAND_FIS      CommandFis;       // A software
> constructed FIS.
> +  EFI_AHCI_ATAPI_COMMAND    AtapiCmd;         // 12 or 16 bytes
> ATAPI cmd.
> +  UINT8                     Reserved[0x30];
> +  EFI_AHCI_COMMAND_PRDT     PrdtTable;    // The scatter/gather list
> for Data transfer
> +} EFI_AHCI_COMMAND_TABLE;
> +
> +//
> +// Received FIS structure
> +//
> +typedef struct {
> +  UINT8    AhciDmaSetupFis[0x1C];         // Dma Setup Fis: offset 0x00
> +  UINT8    AhciDmaSetupFisRsvd[0x04];
> +  UINT8    AhciPioSetupFis[0x14];         // Pio Setup Fis: offset 0x20
> +  UINT8    AhciPioSetupFisRsvd[0x0C];
> +  UINT8    AhciD2HRegisterFis[0x14];      // D2H Register Fis: offset 0x40
> +  UINT8    AhciD2HRegisterFisRsvd[0x04];
> +  UINT64   AhciSetDeviceBitsFis;          // Set Device Bits Fix: offset 0x58
> +  UINT8    AhciUnknownFis[0x40];          // Unkonwn Fis: offset 0x60
> +  UINT8    AhciUnknownFisRsvd[0x60];
> +} EFI_AHCI_RECEIVED_FIS;
> +
> +#pragma pack()
> +
> +typedef struct {
> +  EFI_AHCI_RECEIVED_FIS     *AhciRFis;
> +  VOID                      *AhciRFisMapping;
> +  EFI_AHCI_COMMAND_LIST     *AhciCmdList;
> +  VOID                      *AhciCmdListMapping;
> +  EFI_AHCI_COMMAND_TABLE    *AhciCommandTable;
> +  VOID                      *AhciCommandTableMapping;
> +} EFI_AHCI_REGISTERS;
> +
> +typedef struct {
> +  VOID                      *Buffer;
> +  VOID                      *BufferMapping;
> +  EFI_AHCI_REGISTERS        AhciRegisters;
> +  UINT32                    AhciBar;
> +} AHCI_CONTEXT;
> +
> +/**
> +  Send Buffer cmd to specific device.
> +
> +  @param  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param  Port                The number of port.
> +  @param  PortMultiplier      The timeout Value of stop.
> +  @param  Buffer              The Data Buffer to store IDENTIFY PACKET
> Data.
> +
> +  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for executing.
> +  @retval EFI_SUCCESS         The cmd executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciIdentify (
> +  IN AHCI_CONTEXT             *AhciContext,
> +  IN UINT8                    Port,
> +  IN UINT8                    PortMultiplier,
> +  IN OUT ATA_IDENTIFY_DATA    *Buffer
> +  );
> +
> +/**
> +  Allocate transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciAllocateResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  );
> +
> +/**
> +  Free allocated transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciFreeResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  );
> +
> +/**
> +  Initialize ATA host controller at AHCI mode.
> +
> +  The function is designed to initialize ATA host controller.
> +
> +  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.
> +  @param[in]  Port          The port number to do initialization.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciModeInitialize (
> +  IN AHCI_CONTEXT    *AhciContext,
> +  IN UINT8           Port
> +  );
> +
> +typedef struct _EFI_ATA_COMMAND_BLOCK {
> +  UINT8 Reserved1[2];
> +  UINT8 AtaCommand;
> +  UINT8 AtaFeatures;
> +  UINT8 AtaSectorNumber;
> +  UINT8 AtaCylinderLow;
> +  UINT8 AtaCylinderHigh;
> +  UINT8 AtaDeviceHead;
> +  UINT8 AtaSectorNumberExp;
> +  UINT8 AtaCylinderLowExp;
> +  UINT8 AtaCylinderHighExp;
> +  UINT8 AtaFeaturesExp;
> +  UINT8 AtaSectorCount;
> +  UINT8 AtaSectorCountExp;
> +  UINT8 Reserved2[6];
> +} EFI_ATA_COMMAND_BLOCK;
> +
> +typedef struct _EFI_ATA_STATUS_BLOCK {
> +  UINT8 Reserved1[2];
> +  UINT8 AtaStatus;
> +  UINT8 AtaError;
> +  UINT8 AtaSectorNumber;
> +  UINT8 AtaCylinderLow;
> +  UINT8 AtaCylinderHigh;
> +  UINT8 AtaDeviceHead;
> +  UINT8 AtaSectorNumberExp;
> +  UINT8 AtaCylinderLowExp;
> +  UINT8 AtaCylinderHighExp;
> +  UINT8 Reserved2;
> +  UINT8 AtaSectorCount;
> +  UINT8 AtaSectorCountExp;
> +  UINT8 Reserved3[6];
> +} EFI_ATA_STATUS_BLOCK;
> +
> +/**
> +  Start a PIO Data transfer on specific port.
> +
> +  @param  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param  Port                The number of port.
> +  @param  PortMultiplier      The timeout Value of stop.
> +  @param  AtapiCommand        The atapi command will be used for the
> transfer.
> +  @param  AtapiCommandLength  The Length of the atapi command.
> +  @param  Read                The transfer direction.
> +  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
> +  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
> +  @param  MemoryAddr          The pointer to the Data Buffer.
> +  @param  DataCount           The Data count to be transferred.
> +  @param  Timeout             The timeout Value of non Data transfer.
> +
> +  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error
> occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
> +  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciPioTransfer (
> +  IN     AHCI_CONTEXT               *AhciContext,
> +  IN     UINT8                      Port,
> +  IN     UINT8                      PortMultiplier,
> +  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
> +  IN     UINT8                      AtapiCommandLength,
> +  IN     BOOLEAN                    Read,
> +  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
> +  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
> +  IN OUT VOID                       *MemoryAddr,
> +  IN     UINT32                     DataCount,
> +  IN     UINT64                     Timeout
> +  );
> +
> +
> +#endif
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> new file mode 100644
> index 000000000000..62a71d9f440f
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> @@ -0,0 +1,3003 @@
> +/** @file
> +  Entrypoint of Opal UEFI Driver and contains all the logic to
> +  register for new Opal device instances.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances
> and installs an
> +// HII GUI to manage Opal features if the device is Opal capable
> +// If the Opal device is being managed by the UEFI Driver, it shall provide a
> popup
> +// window during boot requesting a user password
> +
> +#include "OpalDriver.h"
> +#include "OpalHii.h"
> +
> +EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
> +EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
> +
> +BOOLEAN                 mOpalEndOfDxe = FALSE;
> +OPAL_REQUEST_VARIABLE   *mOpalRequestVariable = NULL;
> +UINTN                   mOpalRequestVariableSize = 0;
> +CHAR16                  mPopUpString[256];
> +
> +typedef struct {
> +  UINT32                   Address;
> +  S3_BOOT_SCRIPT_LIB_WIDTH Width;
> +} OPAL_HC_PCI_REGISTER_SAVE;
> +
> +//
> +// To unlock the Intel SATA controller at S3 Resume, restored the following
> registers.
> +//
> +const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {
> +  {0x9,  S3BootScriptWidthUint8},
> +  {0x10, S3BootScriptWidthUint32},
> +  {0x14, S3BootScriptWidthUint32},
> +  {0x18, S3BootScriptWidthUint32},
> +  {0x1C, S3BootScriptWidthUint32},
> +  {0x20, S3BootScriptWidthUint32},
> +  {0x24, S3BootScriptWidthUint32},
> +  {0x3c, S3BootScriptWidthUint8},
> +  {0x3d, S3BootScriptWidthUint8},
> +  {0x40, S3BootScriptWidthUint16},
> +  {0x42, S3BootScriptWidthUint16},
> +  {0x92, S3BootScriptWidthUint16},
> +  {0x94, S3BootScriptWidthUint32},
> +  {0x9C, S3BootScriptWidthUint32},
> +  {0x4,  S3BootScriptWidthUint16},
> +};
> +
> +OPAL_DRIVER mOpalDriver;
> +
> +//
> +// Globals
> +//
> +EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {
> +  OpalEfiDriverBindingSupported,
> +  OpalEfiDriverBindingStart,
> +  OpalEfiDriverBindingStop,
> +  0x1b,
> +  NULL,
> +  NULL
> +};
> +
> +/**
> +
> +  The function determines the available actions for the OPAL_DISK provided.
> +
> +  @param[in]   SupportedAttributes   The supported attributes for the
> device.
> +  @param[in]   LockingFeature        The locking status for the device.
> +  @param[in]   OwnerShip             The ownership for the device.
> +  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate
> disk actions.
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportGetAvailableActions(
> +  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
> +  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
> +  IN  UINT16                           OwnerShip,
> +  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
> +  )
> +{
> +  BOOLEAN ExistingPassword;
> +
> +  NULL_CHECK(AvalDiskActions);
> +
> +  AvalDiskActions->AdminPass = 1;
> +  AvalDiskActions->UserPass = 0;
> +  AvalDiskActions->DisableUser = 0;
> +  AvalDiskActions->Unlock = 0;
> +
> +  //
> +  // Revert is performed on locking sp, so only allow if locking sp is enabled
> +  //
> +  if (LockingFeature->LockingEnabled) {
> +    AvalDiskActions->Revert = 1;
> +  }
> +
> +  //
> +  // Psid revert is available for any device with media encryption support
> +  // Revert is allowed for any device with media encryption support, however
> it requires
> +  //
> +  if (SupportedAttributes->MediaEncryption) {
> +
> +    //
> +    // Only allow psid revert if media encryption is enabled.
> +    // Otherwise, someone who steals a disk can psid revert the disk and the
> user Data is still
> +    // intact and accessible
> +    //
> +    AvalDiskActions->PsidRevert = 1;
> +    AvalDiskActions->RevertKeepDataForced = 0;
> +
> +    //
> +    // Secure erase is performed by generating a new encryption key
> +    // this is only available if encryption is supported
> +    //
> +    AvalDiskActions->SecureErase = 1;
> +  } else {
> +    AvalDiskActions->PsidRevert = 0;
> +    AvalDiskActions->SecureErase = 0;
> +
> +    //
> +    // If no media encryption is supported, then a revert (using password) will
> not
> +    // erase the Data (since you can't generate a new encryption key)
> +    //
> +    AvalDiskActions->RevertKeepDataForced = 1;
> +  }
> +
> +  if (LockingFeature->Locked) {
> +    AvalDiskActions->Unlock = 1;
> +  } else {
> +    AvalDiskActions->Unlock = 0;
> +  }
> +
> +  //
> +  // Only allow user to set password if an admin password exists
> +  //
> +  ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip,
> LockingFeature);
> +  AvalDiskActions->UserPass = ExistingPassword;
> +
> +  //
> +  // This will still show up even if there isn't a user, which is fine
> +  //
> +  AvalDiskActions->DisableUser = ExistingPassword;
> +
> +  return TcgResultSuccess;
> +}
> +
> +/**
> +  Enable Opal Feature for the input device.
> +
> +  @param[in]      Session            The opal session for the opal device.
> +  @param[in]      Msid               Msid
> +  @param[in]      MsidLength         Msid Length
> +  @param[in]      Password           Admin password
> +  @param[in]      PassLength         Length of password in bytes
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportEnableOpalFeature (
> +  IN OPAL_SESSION              *Session,
> +  IN VOID                      *Msid,
> +  IN UINT32                    MsidLength,
> +  IN VOID                      *Password,
> +  IN UINT32                    PassLength
> +  )
> +{
> +  TCG_RESULT   Ret;
> +
> +  NULL_CHECK(Session);
> +  NULL_CHECK(Msid);
> +  NULL_CHECK(Password);
> +
> +  Ret = OpalUtilSetAdminPasswordAsSid(
> +                          Session,
> +                          Msid,
> +                          MsidLength,
> +                          Password,
> +                          PassLength
> +                          );
> +  if (Ret == TcgResultSuccess) {
> +    //
> +    // Enable global locking range
> +    //
> +    Ret = OpalUtilSetOpalLockingRange(
> +                              Session,
> +                              Password,
> +                              PassLength,
> +
> OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,
> +                              0,
> +                              0,
> +                              TRUE,
> +                              TRUE,
> +                              FALSE,
> +                              FALSE
> +                              );
> +  }
> +
> +  return Ret;
> +}
> +
> +/**
> +  Update password for the Opal disk.
> +
> +  @param[in, out] OpalDisk          The disk to update password.
> +  @param[in]      Password          The input password.
> +  @param[in]      PasswordLength    The input password length.
> +
> +**/
> +VOID
> +OpalSupportUpdatePassword (
> +  IN OUT OPAL_DISK      *OpalDisk,
> +  IN VOID               *Password,
> +  IN UINT32             PasswordLength
> +  )
> +{
> +  CopyMem (OpalDisk->Password, Password, PasswordLength);
> +  OpalDisk->PasswordLength = (UINT8) PasswordLength;
> +}
> +
> +/**
> +  Extract device info from the device path.
> +
> +  @param[in]  DevicePath        Device path info for the device.
> +  @param[out] DevInfoLength     Device information length needed.
> +  @param[out] DevInfo           Device information extracted.
> +
> +  @return Device type.
> +
> +**/
> +UINT8
> +ExtractDeviceInfoFromDevicePath (
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
> +  OUT UINT16                    *DevInfoLength,
> +  OUT OPAL_DEVICE_COMMON        *DevInfo OPTIONAL
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath;
> +  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath2;
> +  PCI_DEVICE_PATH               *PciDevPath;
> +  UINT8                         DeviceType;
> +  UINT8                         BusNum;
> +  OPAL_PCI_DEVICE               *PciDevice;
> +  OPAL_DEVICE_ATA               *DevInfoAta;
> +  OPAL_DEVICE_NVME              *DevInfoNvme;
> +  SATA_DEVICE_PATH              *SataDevPath;
> +  NVME_NAMESPACE_DEVICE_PATH    *NvmeDevPath;
> +
> +  ASSERT (DevicePath != NULL);
> +  ASSERT (DevInfoLength != NULL);
> +
> +  DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;
> +  *DevInfoLength = 0;
> +
> +  TmpDevPath = DevicePath;
> +
> +  //
> +  // Get device type.
> +  //
> +  while (!IsDevicePathEnd (TmpDevPath)) {
> +    if (TmpDevPath->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath->SubType == MSG_SATA_DP) {
> +      //
> +      // SATA
> +      //
> +      if (DevInfo != NULL) {
> +        SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;
> +        DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
> +        DevInfoAta->Port = SataDevPath->HBAPortNumber;
> +        DevInfoAta->PortMultiplierPort =
> SataDevPath->PortMultiplierPortNumber;
> +      }
> +      DeviceType = OPAL_DEVICE_TYPE_ATA;
> +      *DevInfoLength = sizeof (OPAL_DEVICE_ATA);
> +      break;
> +    } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {
> +      //
> +      // NVMe
> +      //
> +      if (DevInfo != NULL) {
> +        NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;
> +        DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
> +        DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;
> +      }
> +      DeviceType = OPAL_DEVICE_TYPE_NVME;
> +      *DevInfoLength = sizeof (OPAL_DEVICE_NVME);
> +      break;
> +    }
> +    TmpDevPath = NextDevicePathNode (TmpDevPath);
> +  }
> +
> +  //
> +  // Get device info.
> +  //
> +  BusNum = 0;
> +  TmpDevPath = DevicePath;
> +  TmpDevPath2 = NextDevicePathNode (DevicePath);
> +  while (!IsDevicePathEnd (TmpDevPath2)) {
> +    if (TmpDevPath->Type == HARDWARE_DEVICE_PATH &&
> TmpDevPath->SubType == HW_PCI_DP) {
> +      PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
> +      if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||
> +          (TmpDevPath2->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath2->SubType == MSG_SATA_DP)) {
> +        if (DevInfo != NULL) {
> +          PciDevice = &DevInfo->Device;
> +          PciDevice->Segment = 0;
> +          PciDevice->Bus = BusNum;
> +          PciDevice->Device = PciDevPath->Device;
> +          PciDevice->Function = PciDevPath->Function;
> +        }
> +      } else {
> +        if (DevInfo != NULL) {
> +          PciDevice = (OPAL_PCI_DEVICE *) ((UINTN) DevInfo +
> *DevInfoLength);
> +          PciDevice->Segment = 0;
> +          PciDevice->Bus = BusNum;
> +          PciDevice->Device = PciDevPath->Device;
> +          PciDevice->Function = PciDevPath->Function;
> +        }
> +        *DevInfoLength += sizeof (OPAL_PCI_DEVICE);
> +        if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH &&
> TmpDevPath2->SubType == HW_PCI_DP) {
> +          BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum,
> PciDevPath->Device, PciDevPath->Function,
> PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
> +        }
> +      }
> +    }
> +
> +    TmpDevPath  = NextDevicePathNode (TmpDevPath);
> +    TmpDevPath2 = NextDevicePathNode (TmpDevPath2);
> +  }
> +
> +  ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);
> +  return DeviceType;
> +}
> +
> +/**
> +  Save boot script for ATA OPAL device.
> +
> +  @param[in] DevInfo    Pointer to ATA Opal device information.
> +
> + **/
> +VOID
> +OpalDeviceAtaSaveBootScript (
> +  IN OPAL_DEVICE_ATA    *DevInfo
> +  )
> +{
> +  UINTN                         Bus;
> +  UINTN                         Device;
> +  UINTN                         Function;
> +  UINTN                         Index;
> +  EFI_STATUS                    Status;
> +  UINTN                         Offset;
> +  UINT64                        Address;
> +  S3_BOOT_SCRIPT_LIB_WIDTH      Width;
> +  UINT32                        Data;
> +  OPAL_HC_PCI_REGISTER_SAVE     *HcRegisterSaveListPtr;
> +  UINTN                         Count;
> +
> +  Data = 0;
> +
> +  Bus        = DevInfo->Device.Bus;
> +  Device     = DevInfo->Device.Device;
> +  Function   = DevInfo->Device.Function;
> +
> +  HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *)
> mSataHcRegisterSaveTemplate;
> +  Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof
> (OPAL_HC_PCI_REGISTER_SAVE);
> +
> +  for (Index = 0; Index < Count; Index++) {
> +    Offset  = HcRegisterSaveListPtr[Index].Address;
> +    Width   = HcRegisterSaveListPtr[Index].Width;
> +
> +    switch (Width) {
> +      case S3BootScriptWidthUint8:
> +        Data = (UINT32)PciRead8
> (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
> +        break;
> +      case S3BootScriptWidthUint16:
> +        Data = (UINT32)PciRead16
> (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
> +        break;
> +      case S3BootScriptWidthUint32:
> +        Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
> +        break;
> +      default:
> +        ASSERT (FALSE);
> +        break;
> +    }
> +
> +    Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function,
> Offset);
> +    Status  = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +}
> +
> +/**
> +  Build ATA OPAL device info and save them to LockBox.
> +
> +  @param[in] BarAddr    Bar address allocated.
> +
> + **/
> +VOID
> +BuildOpalDeviceInfoAta (
> +  IN UINT32     BarAddr
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINT8                 DeviceType;
> +  OPAL_DEVICE_ATA       *DevInfoAta;
> +  OPAL_DEVICE_ATA       *TempDevInfoAta;
> +  UINTN                 DevInfoLengthAta;
> +  UINT16                DevInfoLength;
> +  OPAL_DRIVER_DEVICE    *TmpDev;
> +
> +  //
> +  // Build ATA OPAL device info and save them to LockBox.
> +  //
> +  DevInfoLengthAta = 0;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
> +      DevInfoLengthAta += DevInfoLength;
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  if (DevInfoLengthAta == 0) {
> +    return;
> +  }
> +
> +  DevInfoAta = AllocateZeroPool (DevInfoLengthAta);
> +  ASSERT (DevInfoAta != NULL);
> +
> +  TempDevInfoAta = DevInfoAta;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
> +      ExtractDeviceInfoFromDevicePath (
> +        TmpDev->OpalDisk.OpalDevicePath,
> +        &DevInfoLength,
> +        (OPAL_DEVICE_COMMON *) TempDevInfoAta
> +        );
> +      TempDevInfoAta->Length = DevInfoLength;
> +      TempDevInfoAta->OpalBaseComId =
> TmpDev->OpalDisk.OpalBaseComId;
> +      TempDevInfoAta->BarAddr = BarAddr;
> +      CopyMem (
> +        TempDevInfoAta->Password,
> +        TmpDev->OpalDisk.Password,
> +        TmpDev->OpalDisk.PasswordLength
> +        );
> +      TempDevInfoAta->PasswordLength =
> TmpDev->OpalDisk.PasswordLength;
> +      OpalDeviceAtaSaveBootScript (TempDevInfoAta);
> +      TempDevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) TempDevInfoAta +
> DevInfoLength);
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  Status = SaveLockBox (
> +             &mOpalDeviceAtaGuid,
> +             DevInfoAta,
> +             DevInfoLengthAta
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = SetLockBoxAttributes (
> +             &mOpalDeviceAtaGuid,
> +             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ZeroMem (DevInfoAta, DevInfoLengthAta);
> +  FreePool (DevInfoAta);
> +}
> +
> +/**
> +  Build NVMe OPAL device info and save them to LockBox.
> +
> +  @param[in] BarAddr    Bar address allocated.
> +
> + **/
> +VOID
> +BuildOpalDeviceInfoNvme (
> +  IN UINT32     BarAddr
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINT8                 DeviceType;
> +  OPAL_DEVICE_NVME      *DevInfoNvme;
> +  OPAL_DEVICE_NVME      *TempDevInfoNvme;
> +  UINTN                 DevInfoLengthNvme;
> +  UINT16                DevInfoLength;
> +  OPAL_DRIVER_DEVICE    *TmpDev;
> +
> +  //
> +  // Build NVMe OPAL device info and save them to LockBox.
> +  //
> +  DevInfoLengthNvme = 0;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
> +      DevInfoLengthNvme += DevInfoLength;
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  if (DevInfoLengthNvme == 0) {
> +    return;
> +  }
> +
> +  DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);
> +  ASSERT (DevInfoNvme != NULL);
> +
> +  TempDevInfoNvme = DevInfoNvme;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
> +      ExtractDeviceInfoFromDevicePath (
> +        TmpDev->OpalDisk.OpalDevicePath,
> +        &DevInfoLength,
> +        (OPAL_DEVICE_COMMON *) TempDevInfoNvme
> +        );
> +      TempDevInfoNvme->Length = DevInfoLength;
> +      TempDevInfoNvme->OpalBaseComId =
> TmpDev->OpalDisk.OpalBaseComId;
> +      TempDevInfoNvme->BarAddr = BarAddr;
> +      CopyMem (
> +        TempDevInfoNvme->Password,
> +        TmpDev->OpalDisk.Password,
> +        TmpDev->OpalDisk.PasswordLength
> +        );
> +      TempDevInfoNvme->PasswordLength =
> TmpDev->OpalDisk.PasswordLength;
> +      TempDevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN)
> TempDevInfoNvme + DevInfoLength);
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  Status = SaveLockBox (
> +             &mOpalDeviceNvmeGuid,
> +             DevInfoNvme,
> +             DevInfoLengthNvme
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = SetLockBoxAttributes (
> +             &mOpalDeviceNvmeGuid,
> +             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ZeroMem (DevInfoNvme, DevInfoLengthNvme);
> +  FreePool (DevInfoNvme);
> +}
> +
> +/**
> +  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event
> group.
> +
> +  This is a notification function registered on
> EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
> +
> +  @param  Event        Event whose notification function is being invoked.
> +  @param  Context      Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +OpalEndOfDxeEventNotify (
> +  EFI_EVENT                               Event,
> +  VOID                                    *Context
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EFI_PHYSICAL_ADDRESS  Address;
> +  UINT64                Length;
> +  OPAL_DRIVER_DEVICE    *TmpDev;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  mOpalEndOfDxe = TRUE;
> +
> +  if (mOpalRequestVariable != NULL) {
> +    //
> +    // Free the OPAL request variable buffer here
> +    // as the OPAL requests should have been processed.
> +    //
> +    FreePool (mOpalRequestVariable);
> +    mOpalRequestVariable = NULL;
> +    mOpalRequestVariableSize = 0;
> +  }
> +
> +  //
> +  // Assume 64K size and alignment are enough.
> +  //
> +  Length = 0x10000;
> +  Address = 0xFFFFFFFF;
> +  Status = gDS->AllocateMemorySpace (
> +                  EfiGcdAllocateMaxAddressSearchBottomUp,
> +                  EfiGcdMemoryTypeMemoryMappedIo,
> +                  16,                             // 2^16: 64K
> Alignment
> +                  Length,
> +                  &Address,
> +                  gImageHandle,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  BuildOpalDeviceInfoAta ((UINT32) Address);
> +  BuildOpalDeviceInfoNvme ((UINT32) Address);
> +
> +  //
> +  // Zero passsword.
> +  //
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    ZeroMem (TmpDev->OpalDisk.Password,
> TmpDev->OpalDisk.PasswordLength);
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +
> +  gBS->CloseEvent (Event);
> +}
> +
> +/**
> +  Get Psid input from the popup window.
> +
> +  @param[in]  Dev           The device which need Psid to process Psid
> Revert
> +                            OPAL request.
> +  @param[in]  PopUpString   Pop up string.
> +  @param[out] PressEsc      Whether user escape function through Press
> ESC.
> +
> +  @retval Password string if success. NULL if failed.
> +
> +**/
> +CHAR8 *
> +OpalDriverPopUpPsidInput (
> +  IN OPAL_DRIVER_DEVICE     *Dev,
> +  IN CHAR16                 *PopUpString,
> +  OUT BOOLEAN               *PressEsc
> +  )
> +{
> +  EFI_INPUT_KEY             InputKey;
> +  UINTN                     InputLength;
> +  CHAR16                    Mask[PSID_CHARACTER_LENGTH + 1];
> +  CHAR16                    Unicode[PSID_CHARACTER_LENGTH + 1];
> +  CHAR8                     *Ascii;
> +
> +  ZeroMem(Unicode, sizeof(Unicode));
> +  ZeroMem(Mask, sizeof(Mask));
> +
> +  *PressEsc = FALSE;
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  InputLength = 0;
> +  while (TRUE) {
> +    Mask[InputLength] = L'_';
> +    CreatePopUp (
> +      EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +      &InputKey,
> +      PopUpString,
> +      L"---------------------",
> +      Mask,
> +      NULL
> +    );
> +
> +    //
> +    // Check key.
> +    //
> +    if (InputKey.ScanCode == SCAN_NULL) {
> +      //
> +      // password finished
> +      //
> +      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +        //
> +        // Add the null terminator.
> +        //
> +        Unicode[InputLength] = 0;
> +        Mask[InputLength] = 0;
> +        break;
> +      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
> +                 (InputKey.UnicodeChar == CHAR_TAB) ||
> +                 (InputKey.UnicodeChar == CHAR_LINEFEED)
> +                ) {
> +        continue;
> +      } else {
> +        //
> +        // delete last key entered
> +        //
> +        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
> +          if (InputLength > 0) {
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            InputLength--;
> +          }
> +        } else {
> +          //
> +          // add Next key entry
> +          //
> +          Unicode[InputLength] = InputKey.UnicodeChar;
> +          Mask[InputLength] = InputKey.UnicodeChar;
> +          InputLength++;
> +          if (InputLength == PSID_CHARACTER_LENGTH) {
> +            //
> +            // Add the null terminator.
> +            //
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            break;
> +          }
> +        }
> +      }
> +    }
> +
> +    //
> +    // exit on ESC
> +    //
> +    if (InputKey.ScanCode == SCAN_ESC) {
> +      *PressEsc = TRUE;
> +      break;
> +    }
> +  }
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
> +    return NULL;
> +  }
> +
> +  Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);
> +  if (Ascii == NULL) {
> +    ZeroMem (Unicode, sizeof (Unicode));
> +    ZeroMem (Mask, sizeof (Mask));
> +    return NULL;
> +  }
> +
> +  UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);
> +  ZeroMem (Unicode, sizeof (Unicode));
> +  ZeroMem (Mask, sizeof (Mask));
> +
> +  return Ascii;
> +}
> +
> +
> +/**
> +  Get password input from the popup window.
> +
> +  @param[in]  Dev           The device which need password to unlock or
> +                            process OPAL request.
> +  @param[in]  PopUpString1  Pop up string 1.
> +  @param[in]  PopUpString2  Pop up string 2.
> +  @param[out] PressEsc      Whether user escape function through Press
> ESC.
> +
> +  @retval Password string if success. NULL if failed.
> +
> +**/
> +CHAR8 *
> +OpalDriverPopUpPasswordInput (
> +  IN OPAL_DRIVER_DEVICE     *Dev,
> +  IN CHAR16                 *PopUpString1,
> +  IN CHAR16                 *PopUpString2,
> +  OUT BOOLEAN               *PressEsc
> +  )
> +{
> +  EFI_INPUT_KEY             InputKey;
> +  UINTN                     InputLength;
> +  CHAR16                    Mask[MAX_PASSWORD_SIZE + 1];
> +  CHAR16                    Unicode[MAX_PASSWORD_SIZE + 1];
> +  CHAR8                     *Ascii;
> +
> +  ZeroMem(Unicode, sizeof(Unicode));
> +  ZeroMem(Mask, sizeof(Mask));
> +
> +  *PressEsc = FALSE;
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  InputLength = 0;
> +  while (TRUE) {
> +    Mask[InputLength] = L'_';
> +    if (PopUpString2 == NULL) {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &InputKey,
> +        PopUpString1,
> +        L"---------------------",
> +        Mask,
> +        NULL
> +      );
> +    } else {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &InputKey,
> +        PopUpString1,
> +        PopUpString2,
> +        L"---------------------",
> +        Mask,
> +        NULL
> +      );
> +    }
> +
> +    //
> +    // Check key.
> +    //
> +    if (InputKey.ScanCode == SCAN_NULL) {
> +      //
> +      // password finished
> +      //
> +      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +        //
> +        // Add the null terminator.
> +        //
> +        Unicode[InputLength] = 0;
> +        Mask[InputLength] = 0;
> +        break;
> +      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
> +                 (InputKey.UnicodeChar == CHAR_TAB) ||
> +                 (InputKey.UnicodeChar == CHAR_LINEFEED)
> +                ) {
> +        continue;
> +      } else {
> +        //
> +        // delete last key entered
> +        //
> +        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
> +          if (InputLength > 0) {
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            InputLength--;
> +          }
> +        } else {
> +          //
> +          // add Next key entry
> +          //
> +          Unicode[InputLength] = InputKey.UnicodeChar;
> +          Mask[InputLength] = L'*';
> +          InputLength++;
> +          if (InputLength == MAX_PASSWORD_SIZE) {
> +            //
> +            // Add the null terminator.
> +            //
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            break;
> +          }
> +        }
> +      }
> +    }
> +
> +    //
> +    // exit on ESC
> +    //
> +    if (InputKey.ScanCode == SCAN_ESC) {
> +      *PressEsc = TRUE;
> +      break;
> +    }
> +  }
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
> +    return NULL;
> +  }
> +
> +  Ascii = AllocateZeroPool (MAX_PASSWORD_SIZE + 1);
> +  if (Ascii == NULL) {
> +    ZeroMem (Unicode, sizeof (Unicode));
> +    return NULL;
> +  }
> +
> +  UnicodeStrToAsciiStrS (Unicode, Ascii, MAX_PASSWORD_SIZE + 1);
> +  ZeroMem (Unicode, sizeof (Unicode));
> +
> +  return Ascii;
> +}
> +
> +/**
> +  Check if disk is locked, show popup window and ask for password if it is.
> +
> +  @param[in] Dev            The device which need to be unlocked.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +CHAR16 *
> +OpalGetPopUpString (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINTN                 StrLength;
> +
> +  StrLength = StrLen (RequestString) + 1 + MAX (StrLen (Dev->Name16),
> StrLen (L"Disk"));
> +  ASSERT (StrLength < sizeof (mPopUpString) / sizeof (CHAR16));
> +
> +  if (Dev->Name16 == NULL) {
> +    UnicodeSPrint (mPopUpString, StrLength + 1, L"%s Disk", RequestString);
> +  } else {
> +    UnicodeSPrint (mPopUpString, StrLength + 1, L"%s %s", RequestString,
> Dev->Name16);
> +  }
> +
> +  return mPopUpString;
> +}
> +
> +/**
> +  Check if disk is locked, show popup window and ask for password if it is.
> +
> +  @param[in] Dev            The device which need to be unlocked.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +OpalDriverRequestPassword (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  BOOLEAN               IsEnabled;
> +  BOOLEAN               IsLocked;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes,
> &Dev->OpalDisk.LockingFeature);
> +  if (IsEnabled) {
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +    IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes,
> &Dev->OpalDisk.LockingFeature);
> +
> +    while (Count < MAX_PASSWORD_TRY_COUNT) {
> +      Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +      if (PressEsc) {
> +        if (IsLocked) {
> +          //
> +          // Current device in the lock status and
> +          // User not input password and press ESC,
> +          // keep device in lock status and continue boot.
> +          //
> +          do {
> +            CreatePopUp (
> +              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +              &Key,
> +              L"Press ENTER to skip the request and continue boot,",
> +              L"Press ESC to input password again",
> +              NULL
> +              );
> +          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +            gST->ConOut->ClearScreen(gST->ConOut);
> +            //
> +            // Keep lock and continue boot.
> +            //
> +            return;
> +          } else {
> +            //
> +            // Let user input password again.
> +            //
> +            continue;
> +          }
> +        } else {
> +          //
> +          // Current device in the unlock status and
> +          // User not input password and press ESC,
> +          // Shutdown the device.
> +          //
> +          do {
> +            CreatePopUp (
> +              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +              &Key,
> +              L"Press ENTER to shutdown, Press ESC to input password
> again",
> +              NULL
> +              );
> +          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
> +          } else {
> +            //
> +            // Let user input password again.
> +            //
> +            continue;
> +          }
> +        }
> +      }
> +
> +      if (Password == NULL) {
> +        Count ++;
> +        continue;
> +      }
> +      PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +      if (IsLocked) {
> +        Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password,
> PasswordLen, FALSE, FALSE);
> +      } else {
> +        Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password,
> PasswordLen, TRUE, TRUE);
> +        if (Ret == TcgResultSuccess) {
> +          Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password,
> PasswordLen, FALSE, FALSE);
> +        }
> +      }
> +
> +      if (Ret == TcgResultSuccess) {
> +        OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +        DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +      } else {
> +        DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +      }
> +
> +      if (Password != NULL) {
> +        ZeroMem (Password, PasswordLen);
> +        FreePool (Password);
> +      }
> +
> +      if (Ret == TcgResultSuccess) {
> +        break;
> +      }
> +
> +      Count++;
> +
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Invalid password.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    }
> +
> +    if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Opal password retry count exceeds the limit. Must shutdown!",
> +          L"Press ENTER to shutdown",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +
> +      gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
> +    }
> +  }
> +}
> +
> +/**
> +  Process Enable Feature OPAL request.
> +
> +  @param[in] Dev            The device which has Enable Feature OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestEnableFeature (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  CHAR8                 *PasswordConfirm;
> +  UINT32                PasswordLenConfirm;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please
> type in your new password", &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please confirm your new password", &PressEsc);
> +    if (PasswordConfirm == NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
> +    if ((PasswordLen != PasswordLenConfirm) ||
> +        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Passwords are not the same.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    if (PasswordConfirm != NULL) {
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +    }
> +
> +    Ret = OpalSupportEnableOpalFeature (&Session, Dev->OpalDisk.Msid,
> Dev->OpalDisk.MsidLength, Password, PasswordLen);
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Disable User OPAL request.
> +
> +  @param[in] Dev            The device which has Disable User OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestDisableUser (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  BOOLEAN               PasswordFailed;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    Ret = OpalUtilDisableUser(&Session, Password, PasswordLen,
> &PasswordFailed);
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid password, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Psid Revert OPAL request.
> +
> +  @param[in] Dev            The device which has Psid Revert OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestPsidRevert (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Psid;
> +  UINT32                PsidLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PSID_TRY_COUNT) {
> +    Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input Psid again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input Psid again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Psid == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PsidLen = (UINT32) AsciiStrLen(Psid);
> +
> +    Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);
> +    if (Ret == TcgResultSuccess) {
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Psid != NULL) {
> +      ZeroMem (Psid, PsidLen);
> +      FreePool (Psid);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid Psid, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PSID_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal Psid retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Admin Revert OPAL request.
> +
> +  @param[in] Dev            The device which has Revert OPAL request.
> +  @param[in] KeepUserData   Whether to keep user data or not.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestRevert (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN BOOLEAN            KeepUserData,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  BOOLEAN               PasswordFailed;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&
> +        (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {
> +      //
> +      // For pyrite type device which does not support media encryption,
> +      // it does not accept "Keep User Data" parameter.
> +      // So here hardcode a FALSE for this case.
> +      //
> +      Ret = OpalUtilRevert(
> +              &Session,
> +              FALSE,
> +              Password,
> +              PasswordLen,
> +              &PasswordFailed,
> +              Dev->OpalDisk.Msid,
> +              Dev->OpalDisk.MsidLength
> +              );
> +    } else {
> +      Ret = OpalUtilRevert(
> +              &Session,
> +              KeepUserData,
> +              Password,
> +              PasswordLen,
> +              &PasswordFailed,
> +              Dev->OpalDisk.Msid,
> +              Dev->OpalDisk.MsidLength
> +              );
> +    }
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid password, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Secure Erase OPAL request.
> +
> +  @param[in] Dev            The device which has Secure Erase OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestSecureErase (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  BOOLEAN               PasswordFailed;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    Ret = OpalUtilSecureErase(&Session, Password, PasswordLen,
> &PasswordFailed);
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid password, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Set Admin Pwd OPAL request.
> +
> +  @param[in] Dev            The device which has Set Admin Pwd Feature
> OPAL request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestSetUserPwd (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *OldPassword;
> +  UINT32                OldPasswordLen;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  CHAR8                 *PasswordConfirm;
> +  UINT32                PasswordLenConfirm;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please type in your password", &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (OldPassword == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen,
> OPAL_LOCKING_SP_USER1_AUTHORITY);
> +    if (Ret == TcgResultSuccess) {
> +      DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));
> +    } else {
> +      Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen,
> OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
> +      if (Ret == TcgResultSuccess) {
> +        DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));
> +      } else {
> +        ZeroMem (OldPassword, OldPasswordLen);
> +        FreePool (OldPassword);
> +        DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Incorrect password.",
> +            L"Press ENTER to retry",
> +            NULL
> +            );
> +        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +        Count ++;
> +        continue;
> +      }
> +    }
> +
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please
> type in your new password", &PressEsc);
> +    if (Password == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please confirm your new password", &PressEsc);
> +    if (PasswordConfirm == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
> +    if ((PasswordLen != PasswordLenConfirm) ||
> +        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Passwords are not the same.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    if (PasswordConfirm != NULL) {
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +    }
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilSetUserPassword(
> +            &Session,
> +            OldPassword,
> +            OldPasswordLen,
> +            Password,
> +            PasswordLen
> +            );
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (OldPassword != NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Set Admin Pwd OPAL request.
> +
> +  @param[in] Dev            The device which has Set Admin Pwd Feature
> OPAL request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestSetAdminPwd (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *OldPassword;
> +  UINT32                OldPasswordLen;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  CHAR8                 *PasswordConfirm;
> +  UINT32                PasswordLenConfirm;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please type in your password", &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (OldPassword == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen,
> OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
> +    if (Ret == TcgResultSuccess) {
> +      DEBUG ((DEBUG_INFO, "Verify: Success\n"));
> +    } else {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Incorrect password.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please
> type in your new password", &PressEsc);
> +    if (Password == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please confirm your new password", &PressEsc);
> +    if (PasswordConfirm == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
> +    if ((PasswordLen != PasswordLenConfirm) ||
> +        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Passwords are not the same.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    if (PasswordConfirm != NULL) {
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +    }
> +
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilSetAdminPassword(
> +            &Session,
> +            OldPassword,
> +            OldPasswordLen,
> +            Password,
> +            PasswordLen
> +            );
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (OldPassword != NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process OPAL request.
> +
> +  @param[in] Dev            The device which has OPAL request.
> +
> +**/
> +VOID
> +ProcessOpalRequest (
> +  IN OPAL_DRIVER_DEVICE     *Dev
> +  )
> +{
> +  EFI_STATUS                Status;
> +  OPAL_REQUEST_VARIABLE     *TempVariable;
> +  OPAL_REQUEST_VARIABLE     *Variable;
> +  UINTN                     VariableSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
> +  UINTN                     DevicePathSizeInVariable;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathSize;
> +  BOOLEAN                   KeepUserData;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  if (mOpalRequestVariable == NULL) {
> +    Status = GetVariable2 (
> +               OPAL_REQUEST_VARIABLE_NAME,
> +               &gHiiSetupVariableGuid,
> +               (VOID **) &Variable,
> +               &VariableSize
> +               );
> +    if (EFI_ERROR (Status) || (Variable == NULL)) {
> +      return;
> +    }
> +    mOpalRequestVariable = Variable;
> +    mOpalRequestVariableSize = VariableSize;
> +
> +    //
> +    // Delete the OPAL request variable.
> +    //
> +    Status = gRT->SetVariable (
> +                    OPAL_REQUEST_VARIABLE_NAME,
> +                    (EFI_GUID *) &gHiiSetupVariableGuid,
> +                    0,
> +                    0,
> +                    NULL
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    Variable = mOpalRequestVariable;
> +    VariableSize = mOpalRequestVariableSize;
> +  }
> +
> +  //
> +  // Process the OPAL requests.
> +  //
> +  TempVariable = Variable;
> +  while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
> +         (VariableSize >= TempVariable->Length) &&
> +         (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
> +    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +    DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
> +    DevicePath = Dev->OpalDisk.OpalDevicePath;
> +    DevicePathSize = GetDevicePathSize (DevicePath);
> +    if ((DevicePathSize == DevicePathSizeInVariable) &&
> +        (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize)
> == 0)) {
> +      //
> +      // Found the node for the OPAL device.
> +      //
> +      if (TempVariable->OpalRequest.SetAdminPwd != 0) {
> +        ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");
> +      }
> +      if (TempVariable->OpalRequest.SetUserPwd != 0) {
> +        ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");
> +      }
> +      if (TempVariable->OpalRequest.SecureErase!= 0) {
> +        ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");
> +      }
> +      if (TempVariable->OpalRequest.Revert != 0) {
> +        KeepUserData = (BOOLEAN)
> TempVariable->OpalRequest.KeepUserData;
> +        ProcessOpalRequestRevert (
> +          Dev,
> +          KeepUserData,
> +          KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"
> +          );
> +      }
> +      if (TempVariable->OpalRequest.PsidRevert != 0) {
> +        ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");
> +      }
> +      if (TempVariable->OpalRequest.DisableUser != 0) {
> +        ProcessOpalRequestDisableUser (Dev, L"Disable User:");
> +      }
> +      if (TempVariable->OpalRequest.EnableFeature != 0) {
> +        ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");
> +      }
> +
> +      break;
> +    }
> +
> +    VariableSize -= TempVariable->Length;
> +    TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable +
> TempVariable->Length);
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Add new device to the global device list.
> +
> +  @param Dev             New create device.
> +
> +**/
> +VOID
> +AddDeviceToTail(
> +  IN OPAL_DRIVER_DEVICE    *Dev
> +  )
> +{
> +  OPAL_DRIVER_DEVICE                *TmpDev;
> +
> +  if (mOpalDriver.DeviceList == NULL) {
> +    mOpalDriver.DeviceList = Dev;
> +  } else {
> +    TmpDev = mOpalDriver.DeviceList;
> +    while (TmpDev->Next != NULL) {
> +      TmpDev = TmpDev->Next;
> +    }
> +
> +    TmpDev->Next = Dev;
> +  }
> +}
> +
> +/**
> +  Remove one device in the global device list.
> +
> +  @param Dev             The device need to be removed.
> +
> +**/
> +VOID
> +RemoveDevice (
> +  IN OPAL_DRIVER_DEVICE    *Dev
> +  )
> +{
> +  OPAL_DRIVER_DEVICE                *TmpDev;
> +
> +  if (mOpalDriver.DeviceList == NULL) {
> +    return;
> +  }
> +
> +  if (mOpalDriver.DeviceList == Dev) {
> +    mOpalDriver.DeviceList = NULL;
> +    return;
> +  }
> +
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev->Next != NULL) {
> +    if (TmpDev->Next == Dev) {
> +      TmpDev->Next = Dev->Next;
> +      break;
> +    }
> +  }
> +}
> +
> +/**
> +  Get current device count.
> +
> +  @retval  return the current created device count.
> +
> +**/
> +UINT8
> +GetDeviceCount (
> +  VOID
> +  )
> +{
> +  UINT8                Count;
> +  OPAL_DRIVER_DEVICE   *TmpDev;
> +
> +  Count = 0;
> +  TmpDev = mOpalDriver.DeviceList;
> +
> +  while (TmpDev != NULL) {
> +    Count++;
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  return Count;
> +}
> +
> +/**
> +  Get devcie list info.
> +
> +  @retval     return the device list pointer.
> +**/
> +OPAL_DRIVER_DEVICE*
> +OpalDriverGetDeviceList(
> +  VOID
> +  )
> +{
> +  return mOpalDriver.DeviceList;
> +}
> +
> +/**
> +  ReadyToBoot callback to send BlockSid command.
> +
> +  @param  Event   Pointer to this event
> +  @param  Context Event handler private Data
> +
> +**/
> +VOID
> +EFIAPI
> +ReadyToBootCallback (
> +  IN EFI_EVENT        Event,
> +  IN VOID             *Context
> +  )
> +{
> +  OPAL_DRIVER_DEVICE                         *Itr;
> +  TCG_RESULT                                 Result;
> +  OPAL_SESSION                               Session;
> +  UINT32                                     PpStorageFlag;
> +
> +  gBS->CloseEvent (Event);
> +
> +  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
> +    //
> +    // Send BlockSID command to each Opal disk
> +    //
> +    Itr = mOpalDriver.DeviceList;
> +    while (Itr != NULL) {
> +      if (Itr->OpalDisk.SupportedAttributes.BlockSid) {
> +        ZeroMem(&Session, sizeof(Session));
> +        Session.Sscp = Itr->OpalDisk.Sscp;
> +        Session.MediaId = Itr->OpalDisk.MediaId;
> +        Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
> +
> +        Result = OpalBlockSid (&Session, TRUE);  // HardwareReset must
> always be TRUE
> +        if (Result != TcgResultSuccess) {
> +          DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
> +          break;
> +        }
> +      }
> +
> +      Itr = Itr->Next;
> +    }
> +  }
> +}
> +
> +/**
> +  Stop this Controller.
> +
> +  @param  Dev               The device need to be stopped.
> +
> +**/
> +VOID
> +OpalDriverStopDevice (
> +  OPAL_DRIVER_DEVICE     *Dev
> +  )
> +{
> +  //
> +  // free each name
> +  //
> +  FreePool(Dev->Name16);
> +
> +  //
> +  // remove OPAL_DRIVER_DEVICE from the list
> +  // it updates the controllerList pointer
> +  //
> +  RemoveDevice(Dev);
> +
> +  //
> +  // close protocols that were opened
> +  //
> +  gBS->CloseProtocol(
> +    Dev->Handle,
> +    &gEfiStorageSecurityCommandProtocolGuid,
> +    gOpalDriverBinding.DriverBindingHandle,
> +    Dev->Handle
> +    );
> +
> +  gBS->CloseProtocol(
> +    Dev->Handle,
> +    &gEfiBlockIoProtocolGuid,
> +    gOpalDriverBinding.DriverBindingHandle,
> +    Dev->Handle
> +    );
> +
> +  FreePool(Dev);
> +}
> +
> +/**
> +  Get devcie name through the component name protocol.
> +
> +  @param[in]       AllHandlesBuffer   The handle buffer for current
> system.
> +  @param[in]       NumAllHandles      The number of handles for the
> handle buffer.
> +  @param[in]       Dev                The device which need to get
> name.
> +  @param[in]       UseComp1           Whether use component name
> or name2 protocol.
> +
> +  @retval     TRUE        Find the name for this device.
> +  @retval     FALSE       Not found the name for this device.
> +**/
> +BOOLEAN
> +OpalDriverGetDeviceNameByProtocol(
> +  EFI_HANDLE             *AllHandlesBuffer,
> +  UINTN                  NumAllHandles,
> +  OPAL_DRIVER_DEVICE     *Dev,
> +  BOOLEAN                UseComp1
> +  )
> +{
> +  EFI_HANDLE*                   ProtocolHandlesBuffer;
> +  UINTN                         NumProtocolHandles;
> +  EFI_STATUS                    Status;
> +  EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name
> and componentName2 have same layout
> +  EFI_GUID                      Protocol;
> +  UINTN                         StrLength;
> +  EFI_DEVICE_PATH_PROTOCOL*     TmpDevPath;
> +  UINTN                         Index1;
> +  UINTN                         Index2;
> +  EFI_HANDLE                    TmpHandle;
> +  CHAR16                        *DevName;
> +
> +  if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
> +    return FALSE;
> +  }
> +
> +  Protocol = UseComp1 ? gEfiComponentNameProtocolGuid :
> gEfiComponentName2ProtocolGuid;
> +
> +  //
> +  // Find all EFI_HANDLES with protocol
> +  //
> +  Status = gBS->LocateHandleBuffer(
> +               ByProtocol,
> +               &Protocol,
> +               NULL,
> +               &NumProtocolHandles,
> +               &ProtocolHandlesBuffer
> +               );
> +  if (EFI_ERROR(Status)) {
> +    return FALSE;
> +  }
> +
> +
> +  //
> +  // Exit early if no supported devices
> +  //
> +  if (NumProtocolHandles == 0) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Get printable name by iterating through all protocols
> +  // using the handle as the child, and iterate through all handles for the
> controller
> +  // exit loop early once found, if not found, then delete device
> +  // storage security protocol instances already exist, add them to internal list
> +  //
> +  Status = EFI_DEVICE_ERROR;
> +  for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
> +    DevName = NULL;
> +
> +    if (Dev->Name16 != NULL) {
> +      return TRUE;
> +    }
> +
> +    TmpHandle = ProtocolHandlesBuffer[Index1];
> +
> +    Status = gBS->OpenProtocol(
> +                 TmpHandle,
> +                 &Protocol,
> +                 (VOID**)&Cnp1_2,
> +                 gImageHandle,
> +                 NULL,
> +                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                 );
> +    if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
> +      continue;
> +    }
> +
> +    //
> +    // Use all handles array as controller handle
> +    //
> +    for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
> +      Status = Cnp1_2->GetControllerName(
> +                   Cnp1_2,
> +                   AllHandlesBuffer[Index2],
> +                   Dev->Handle,
> +                   LANGUAGE_ISO_639_2_ENGLISH,
> +                   &DevName
> +                   );
> +      if (EFI_ERROR(Status)) {
> +        Status = Cnp1_2->GetControllerName(
> +                     Cnp1_2,
> +                     AllHandlesBuffer[Index2],
> +                     Dev->Handle,
> +                     LANGUAGE_RFC_3066_ENGLISH,
> +                     &DevName
> +                     );
> +      }
> +      if (!EFI_ERROR(Status) && DevName != NULL) {
> +        StrLength = StrLen(DevName) + 1;        // Add one for NULL
> terminator
> +        Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
> +        ASSERT (Dev->Name16 != NULL);
> +        StrCpyS (Dev->Name16, StrLength, DevName);
> +        Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
> +        UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);
> +
> +        //
> +        // Retrieve bridge BDF info and port number or namespace depending
> on type
> +        //
> +        TmpDevPath = NULL;
> +        Status = gBS->OpenProtocol(
> +            Dev->Handle,
> +            &gEfiDevicePathProtocolGuid,
> +            (VOID**)&TmpDevPath,
> +            gImageHandle,
> +            NULL,
> +            EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +            );
> +        if (!EFI_ERROR(Status)) {
> +          Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
> +          return TRUE;
> +        }
> +
> +        if (Dev->Name16 != NULL) {
> +          FreePool(Dev->Name16);
> +          Dev->Name16 = NULL;
> +        }
> +        if (Dev->NameZ != NULL) {
> +          FreePool(Dev->NameZ);
> +          Dev->NameZ = NULL;
> +        }
> +      }
> +    }
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +  Get devcie name through the component name protocol.
> +
> +  @param[in]       Dev                The device which need to get
> name.
> +
> +  @retval     TRUE        Find the name for this device.
> +  @retval     FALSE       Not found the name for this device.
> +**/
> +BOOLEAN
> +OpalDriverGetDriverDeviceName(
> +  OPAL_DRIVER_DEVICE          *Dev
> +  )
> +{
> +  EFI_HANDLE*                  AllHandlesBuffer;
> +  UINTN                        NumAllHandles;
> +  EFI_STATUS                   Status;
> +
> +  if (Dev == NULL) {
> +    DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName
> Exiting, Dev=NULL\n"));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Iterate through ComponentName2 handles to get name, if fails, try
> ComponentName
> +  //
> +  if (Dev->Name16 == NULL) {
> +    DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
> +    //
> +    // Find all EFI_HANDLES
> +    //
> +    Status = gBS->LocateHandleBuffer(
> +                 AllHandles,
> +                 NULL,
> +                 NULL,
> +                 &NumAllHandles,
> +                 &AllHandlesBuffer
> +                 );
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n",
> Status ));
> +      return FALSE;
> +    }
> +
> +    //
> +    // Try component Name2
> +    //
> +    if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer,
> NumAllHandles, Dev, FALSE)) {
> +      DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get
> device name, try ComponentName\n"));
> +      if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer,
> NumAllHandles, Dev, TRUE)) {
> +        DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to
> get device name, skip device\n"));
> +        return FALSE;
> +      }
> +    }
> +  }
> +
> +  return TRUE;
> +}
> +
> +/**
> +  Main entry for this driver.
> +
> +  @param ImageHandle     Image Handle this driver.
> +  @param SystemTable     Pointer to SystemTable.
> +
> +  @retval EFI_SUCESS     This function always complete successfully.
> +**/
> +EFI_STATUS
> +EFIAPI
> +EfiDriverEntryPoint(
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE*  SystemTable
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  EFI_EVENT                      ReadyToBootEvent;
> +  EFI_EVENT                      EndOfDxeEvent;
> +
> +  Status = EfiLibInstallDriverBindingComponentName2 (
> +             ImageHandle,
> +             SystemTable,
> +             &gOpalDriverBinding,
> +             ImageHandle,
> +             &gOpalComponentName,
> +             &gOpalComponentName2
> +             );
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle
> failed\n"));
> +    return Status ;
> +  }
> +
> +  //
> +  // Initialize Driver object
> +  //
> +  ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
> +  mOpalDriver.Handle = ImageHandle;
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  OpalEndOfDxeEventNotify,
> +                  NULL,
> +                  &gEfiEndOfDxeEventGroupGuid,
> +                  &EndOfDxeEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // register a ReadyToBoot event callback for sending BlockSid command
> +  //
> +  Status = EfiCreateEventReadyToBootEx (
> +                  TPL_CALLBACK,
> +                  ReadyToBootCallback,
> +                  (VOID *) &ImageHandle,
> +                  &ReadyToBootEvent
> +                  );
> +
> +  //
> +  // Install Hii packages.
> +  //
> +  HiiInstall();
> +
> +  return Status;
> +}
> +
> +/**
> +  Tests to see if this driver supports a given controller.
> +
> +  This function checks to see if the controller contains an instance of the
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the
> EFI_BLOCK_IO_PROTOCL
> +  and returns EFI_SUCCESS if it does.
> +
> +  @param[in]  This                  A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> +  @param[in]  ControllerHandle      The Handle of the controller to test.
> This Handle
> +                                    must support a protocol interface
> that supplies
> +                                    an I/O abstraction to the driver.
> +  @param[in]  RemainingDevicePath  This parameter is ignored.
> +
> +  @retval EFI_SUCCESS               The device contains required
> protocols
> +  @retval EFI_ALREADY_STARTED       The device specified by
> ControllerHandle and
> +                                    RemainingDevicePath is already
> being managed by the driver
> +                                    specified by This.
> +  @retval EFI_ACCESS_DENIED         The device specified by
> ControllerHandle and
> +                                    RemainingDevicePath is already
> being managed by a different
> +                                    driver or an application that requires
> exclusive access.
> +                                    Currently not implemented.
> +  @retval EFI_UNSUPPORTED           The device does not contain
> requires protocols
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingSupported(
> +  IN EFI_DRIVER_BINDING_PROTOCOL* This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL*  SecurityCommand;
> +  EFI_BLOCK_IO_PROTOCOL*                  BlkIo;
> +
> +  if (mOpalEndOfDxe) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller
> Handle.
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiStorageSecurityCommandProtocolGuid,
> +    ( VOID ** )&SecurityCommand,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +
> +  if (Status == EFI_ALREADY_STARTED) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Close protocol and reopen in Start call
> +  //
> +  gBS->CloseProtocol(
> +      Controller,
> +      &gEfiStorageSecurityCommandProtocolGuid,
> +      This->DriverBindingHandle,
> +      Controller
> +      );
> +
> +  //
> +  // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by
> EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> +  // function APIs
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    (VOID **)&BlkIo,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));
> +    return Status;
> +  }
> +
> +  //
> +  // Close protocol and reopen in Start call
> +  //
> +  gBS->CloseProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    This->DriverBindingHandle,
> +    Controller
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Enables Opal Management on a supported device if available.
> +
> +  The start function is designed to be called after the Opal UEFI Driver has
> confirmed the
> +  "controller", which is a child Handle, contains the
> EF_STORAGE_SECURITY_COMMAND protocols.
> +  This function will complete the other necessary checks, such as verifying the
> device supports
> +  the correct version of Opal.  Upon verification, it will add the device to the
> +  Opal HII list in order to expose Opal managmeent options.
> +
> +  @param[in]  This                  A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> +  @param[in]  ControllerHandle      The Handle of the controller to start.
> This Handle
> +                                    must support a protocol interface
> that supplies
> +                                    an I/O abstraction to the driver.
> +  @param[in]  RemainingDevicePath   A pointer to the remaining portion of
> a device path.  This
> +                                    parameter is ignored by device
> drivers, and is optional for bus
> +                                    drivers. For a bus driver, if this
> parameter is NULL, then handles
> +                                    for all the children of Controller are
> created by this driver.
> +                                    If this parameter is not NULL and the
> first Device Path Node is
> +                                    not the End of Device Path Node,
> then only the Handle for the
> +                                    child device specified by the first
> Device Path Node of
> +                                    RemainingDevicePath is created by
> this driver.
> +                                    If the first Device Path Node of
> RemainingDevicePath is
> +                                    the End of Device Path Node, no
> child Handle is created by this
> +                                    driver.
> +
> +  @retval EFI_SUCCESS               Opal management was enabled.
> +  @retval EFI_DEVICE_ERROR          The device could not be started due
> to a device error.Currently not implemented.
> +  @retval EFI_OUT_OF_RESOURCES      The request could not be
> completed due to a lack of resources.
> +  @retval Others                    The driver failed to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStart(
> +  IN EFI_DRIVER_BINDING_PROTOCOL* This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_BLOCK_IO_PROTOCOL       *BlkIo;
> +  OPAL_DRIVER_DEVICE          *Dev;
> +  OPAL_DRIVER_DEVICE          *Itr;
> +  BOOLEAN                     Result;
> +
> +  Itr = mOpalDriver.DeviceList;
> +  while (Itr != NULL) {
> +    if (Controller == Itr->Handle) {
> +      return EFI_SUCCESS;
> +    }
> +    Itr = Itr->Next;
> +  }
> +
> +  //
> +  // Create internal device for tracking.  This allows all disks to be tracked
> +  // by same HII form
> +  //
> +  Dev =
> (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
> +  if (Dev == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  Dev->Handle = Controller;
> +
> +  //
> +  // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal
> supported checks
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiStorageSecurityCommandProtocolGuid,
> +    (VOID **)&Dev->Sscp,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +  if (EFI_ERROR(Status)) {
> +    FreePool(Dev);
> +    return Status;
> +  }
> +
> +  //
> +  // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by
> EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> +  // function APIs
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    (VOID **)&BlkIo,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +  if (EFI_ERROR(Status)) {
> +    //
> +    // Close storage security that was opened
> +    //
> +    gBS->CloseProtocol(
> +        Controller,
> +        &gEfiStorageSecurityCommandProtocolGuid,
> +        This->DriverBindingHandle,
> +        Controller
> +        );
> +
> +    FreePool(Dev);
> +    return Status;
> +  }
> +
> +  //
> +  // Save mediaId
> +  //
> +  Dev->MediaId = BlkIo->Media->MediaId;
> +
> +  gBS->CloseProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    This->DriverBindingHandle,
> +    Controller
> +    );
> +
> +  //
> +  // Acquire Ascii printable name of child, if not found, then ignore device
> +  //
> +  Result = OpalDriverGetDriverDeviceName (Dev);
> +  if (!Result) {
> +    goto Done;
> +  }
> +
> +  Status = OpalDiskInitialize (Dev);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  AddDeviceToTail(Dev);
> +
> +  //
> +  // Check if device is locked and prompt for password.
> +  //
> +  OpalDriverRequestPassword (Dev, L"Unlock:");
> +
> +  //
> +  // Process OPAL request from last boot.
> +  //
> +  ProcessOpalRequest (Dev);
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  //
> +  // free device, close protocols and exit
> +  //
> +  gBS->CloseProtocol(
> +      Controller,
> +      &gEfiStorageSecurityCommandProtocolGuid,
> +      This->DriverBindingHandle,
> +      Controller
> +      );
> +
> +  FreePool(Dev);
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> +  Stop this driver on Controller.
> +
> +  @param  This              Protocol instance pointer.
> +  @param  Controller        Handle of device to stop driver on
> +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If
> number of
> +                            children is zero stop the entire bus driver.
> +  @param  ChildHandleBuffer List of Child Handles to Stop.
> +
> +  @retval EFI_SUCCESS       This driver is removed Controller.
> +  @retval other             This driver could not be removed from this
> device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStop(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  UINTN                           NumberOfChildren,
> +  EFI_HANDLE*                     ChildHandleBuffer
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*   Itr;
> +
> +  Itr = mOpalDriver.DeviceList;
> +
> +  //
> +  // does Controller match any of the devices we are managing for Opal
> +  //
> +  while (Itr != NULL) {
> +    if (Itr->Handle == Controller) {
> +      OpalDriverStopDevice (Itr);
> +      return EFI_SUCCESS;
> +    }
> +
> +    Itr = Itr->Next;
> +  }
> +
> +  return EFI_NOT_FOUND;
> +}
> +
> +
> +/**
> +  Unloads UEFI Driver.  Very useful for debugging and testing.
> +
> +  @param ImageHandle            Image Handle this driver.
> +
> +  @retval EFI_SUCCESS           This function always complete
> successfully.
> +  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverUnload (
> +  IN EFI_HANDLE ImageHandle
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  OPAL_DRIVER_DEVICE                   *Itr;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (ImageHandle != gImageHandle) {
> +    return (EFI_INVALID_PARAMETER);
> +  }
> +
> +  //
> +  // Uninstall any interface added to each device by us
> +  //
> +  while (mOpalDriver.DeviceList) {
> +    Itr = mOpalDriver.DeviceList;
> +    //
> +    // Remove OPAL_DRIVER_DEVICE from the list
> +    // it updates the controllerList pointer
> +    //
> +    OpalDriverStopDevice(Itr);
> +  }
> +
> +  //
> +  // Uninstall the HII capability
> +  //
> +  Status = HiiUninstall();
> +
> +  return Status;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> new file mode 100644
> index 000000000000..a66b5a5345ff
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> @@ -0,0 +1,613 @@
> +/** @file
> +  Values defined and used by the Opal UEFI Driver.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_DRIVER_H_
> +#define _OPAL_DRIVER_H_
> +
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Protocol/PciIo.h>
> +#include <Protocol/SmmCommunication.h>
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/DevicePathToText.h>
> +#include <Protocol/StorageSecurityCommand.h>
> +
> +#include <Guid/EventGroup.h>
> +
> +#include <Library/UefiLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/UefiHiiServicesLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Library/LockBoxLib.h>
> +#include <Library/TcgStorageOpalLib.h>
> +#include <Library/Tcg2PhysicalPresenceLib.h>
> +
> +#include "OpalPasswordCommon.h"
> +#include "OpalHiiFormValues.h"
> +
> +#define EFI_DRIVER_NAME_UNICODE L"1.0 UEFI Opal Driver"
> +
> +// UEFI 2.1
> +#define LANGUAGE_RFC_3066_ENGLISH ((CHAR8*)"en")
> +
> +// UEFI/EFI < 2.1
> +#define LANGUAGE_ISO_639_2_ENGLISH ((CHAR8*)"eng")
> +
> +#define CONCAT_(x, y) x ## y
> +#define CONCAT(x, y) CONCAT_(x, y)
> +
> +#define UNICODE_STR(x) CONCAT( L, x )
> +
> +extern EFI_DRIVER_BINDING_PROTOCOL   gOpalDriverBinding;
> +extern EFI_COMPONENT_NAME_PROTOCOL   gOpalComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL  gOpalComponentName2;
> +
> +#define OPAL_MSID_LENGHT        128
> +
> +#define MAX_PASSWORD_SIZE       32
> +#define MAX_PASSWORD_TRY_COUNT  5
> +
> +// PSID Length
> +#define PSID_CHARACTER_LENGTH   0x20
> +#define MAX_PSID_TRY_COUNT      5
> +
> +#pragma pack(1)
> +
> +//
> +// Structure that is used to represent the available actions for an OpalDisk.
> +// The data can then be utilized to expose/hide certain actions available to an
> end user
> +// by the consumer of this library.
> +//
> +typedef struct {
> +    //
> +    // Indicates if the disk can support PSID Revert action.  should verify disk
> supports PSID authority
> +    //
> +    UINT16 PsidRevert : 1;
> +
> +    //
> +    // Indicates if the disk can support Revert action
> +    //
> +    UINT16 Revert : 1;
> +
> +    //
> +    // Indicates if the user must keep data for revert action.  It is true if no
> media encryption is supported.
> +    //
> +    UINT16 RevertKeepDataForced : 1;
> +
> +    //
> +    // Indicates if the disk can support set Admin password
> +    //
> +    UINT16 AdminPass : 1;
> +
> +    //
> +    // Indicates if the disk can support set User password.  This action
> requires that a user
> +    // password is first enabled.
> +    //
> +    UINT16 UserPass : 1;
> +
> +    //
> +    // Indicates if unlock action is available.  Requires disk to be currently
> locked.
> +    //
> +    UINT16 Unlock : 1;
> +
> +    //
> +    // Indicates if Secure Erase action is available.  Action requires admin
> credentials and media encryption support.
> +    //
> +    UINT16 SecureErase : 1;
> +
> +    //
> +    // Indicates if Disable User action is available.  Action requires admin
> credentials.
> +    //
> +    UINT16 DisableUser : 1;
> +} OPAL_DISK_ACTIONS;
> +
> +//
> +// Structure that is used to represent an OPAL_DISK.
> +//
> +typedef struct {
> +  UINT32                                          MsidLength;
> // Byte length of MSID Pin for device
> +  UINT8
> Msid[OPAL_MSID_LENGHT]; // MSID Pin for device
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;
> +  UINT32                                          MediaId;
> // MediaId is used by Ssc Protocol.
> +  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
> +  UINT16                                          OpalBaseComId;
> // Opal SSC 1 base com id.
> +  OPAL_OWNER_SHIP                                 Owner;
> +  OPAL_DISK_SUPPORT_ATTRIBUTE
> SupportedAttributes;
> +  TCG_LOCKING_FEATURE_DESCRIPTOR                  LockingFeature;
> // Locking Feature Descriptor retrieved from performing a Level 0 Discovery
> +  UINT8                                           PasswordLength;
> +  UINT8
> Password[MAX_PASSWORD_SIZE];
> +} OPAL_DISK;
> +
> +//
> +// Device with block IO protocol
> +//
> +typedef struct _OPAL_DRIVER_DEVICE OPAL_DRIVER_DEVICE;
> +
> +struct _OPAL_DRIVER_DEVICE {
> +  OPAL_DRIVER_DEVICE                              *Next;
> ///< Linked list pointer
> +  EFI_HANDLE                                      Handle;
> ///< Device handle
> +  OPAL_DISK                                       OpalDisk;
> ///< User context
> +  CHAR16                                          *Name16;
> ///< Allocated/freed by UEFI Filter Driver at device creation/removal
> +  CHAR8                                           *NameZ;
> ///< Allocated/freed by UEFI Filter Driver at device creation/removal
> +  UINT32                                          MediaId;
> ///< Required parameter for EFI_STORAGE_SECURITY_COMMAND_PROTOCOL,
> from BLOCK_IO_MEDIA
> +
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;
> /// Device protocols consumed
> +  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
> +};
> +
> +//
> +// Opal Driver UEFI Driver Model
> +//
> +typedef struct {
> +  EFI_HANDLE           Handle;              ///< Driver image handle
> +  OPAL_DRIVER_DEVICE   *DeviceList;         ///< Linked list of controllers
> owned by this Driver
> +} OPAL_DRIVER;
> +
> +#pragma pack()
> +
> +//
> +// Retrieves a OPAL_DRIVER_DEVICE based on the pointer to its StorageSecurity
> protocol.
> +//
> +#define DRIVER_DEVICE_FROM_OPALDISK(OpalDiskPointer)
> (OPAL_DRIVER_DEVICE*)(BASE_CR(OpalDiskPointer, OPAL_DRIVER_DEVICE,
> OpalDisk))
> +
> +/**
> +  Get devcie list info.
> +
> +  @retval     return the device list pointer.
> +**/
> +OPAL_DRIVER_DEVICE*
> +OpalDriverGetDeviceList(
> +  VOID
> +  );
> +
> +/**
> +  Get devcie name through the component name protocol.
> +
> +  @param[in]       Dev                The device which need to get
> name.
> +
> +  @retval     TRUE        Find the name for this device.
> +  @retval     FALSE       Not found the name for this device.
> +**/
> +BOOLEAN
> +OpalDriverGetDriverDeviceName(
> +  OPAL_DRIVER_DEVICE          *Dev
> +  );
> +
> +/**
> +  Get current device count.
> +
> +  @retval  return the current created device count.
> +
> +**/
> +UINT8
> +GetDeviceCount (
> +  VOID
> +  );
> +
> +/**
> +  Update password for the Opal disk.
> +
> +  @param[in, out] OpalDisk          The disk to update password.
> +  @param[in]      Password          The input password.
> +  @param[in]      PasswordLength    The input password length.
> +
> +**/
> +VOID
> +OpalSupportUpdatePassword (
> +  IN OUT OPAL_DISK      *OpalDisk,
> +  IN VOID               *Password,
> +  IN UINT32             PasswordLength
> +  );
> +
> +/**
> +
> +  The function performs determines the available actions for the OPAL_DISK
> provided.
> +
> +  @param[in]   SupportedAttributes   The support attribute for the device.
> +  @param[in]   LockingFeature        The locking status for the device.
> +  @param[in]   OwnerShip             The ownership for the device.
> +  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate
> disk actions.
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportGetAvailableActions(
> +  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
> +  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
> +  IN  UINT16                           OwnerShip,
> +  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
> +  );
> +
> +/**
> +  Enable Opal Feature for the input device.
> +
> +  @param[in]      Session            The opal session for the opal device.
> +  @param[in]      Msid               Msid
> +  @param[in]      MsidLength         Msid Length
> +  @param[in]      Password           Admin password
> +  @param[in]      PassLength         Length of password in bytes
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportEnableOpalFeature (
> +  IN OPAL_SESSION              *Session,
> +  IN VOID                      *Msid,
> +  IN UINT32                    MsidLength,
> +  IN VOID                      *Password,
> +  IN UINT32                    PassLength
> +  );
> +
> +/**
> +  Unloads UEFI Driver.  Very useful for debugging and testing.
> +
> +  @param ImageHandle            Image handle this driver.
> +
> +  @retval EFI_SUCCESS           This function always complete
> successfully.
> +  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
> +**/
> +EFI_STATUS
> +EFIAPI
> +EfiDriverUnload(
> +  EFI_HANDLE ImageHandle
> +  );
> +
> +
> +/**
> +  Test to see if this driver supports Controller.
> +
> +  @param  This                Protocol instance pointer.
> +  @param  ControllerHandle    Handle of device to test
> +  @param  RemainingDevicePath Optional parameter use to pick a specific
> child
> +                              device to start.
> +
> +  @retval EFI_SUCCESS         This driver supports this device.
> +  @retval EFI_ALREADY_STARTED This driver is already running on this device.
> +  @retval other               This driver does not support this device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingSupported(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
> +  );
> +
> +/**
> +  Enables Opal Management on a supported device if available.
> +
> +  The start function is designed to be called after the Opal UEFI Driver has
> confirmed the
> +  "controller", which is a child handle, contains the
> EF_STORAGE_SECURITY_COMMAND protocols.
> +  This function will complete the other necessary checks, such as verifying the
> device supports
> +  the correct version of Opal.  Upon verification, it will add the device to the
> +  Opal HII list in order to expose Opal managmeent options.
> +
> +  @param[in]  This                  A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> +  @param[in]  ControllerHandle      The handle of the controller to start.
> This handle
> +                                    must support a protocol interface
> that supplies
> +                                    an I/O abstraction to the driver.
> +  @param[in]  RemainingDevicePath   A pointer to the remaining portion of
> a device path.  This
> +                                    parameter is ignored by device
> drivers, and is optional for bus
> +                                    drivers. For a bus driver, if this
> parameter is NULL, then handles
> +                                    for all the children of Controller are
> created by this driver.
> +                                    If this parameter is not NULL and the
> first Device Path Node is
> +                                    not the End of Device Path Node,
> then only the handle for the
> +                                    child device specified by the first
> Device Path Node of
> +                                    RemainingDevicePath is created by
> this driver.
> +                                    If the first Device Path Node of
> RemainingDevicePath is
> +                                    the End of Device Path Node, no
> child handle is created by this
> +                                    driver.
> +
> +  @retval EFI_SUCCESS               Opal management was enabled.
> +  @retval EFI_DEVICE_ERROR          The device could not be started due
> to a device error.Currently not implemented.
> +  @retval EFI_OUT_OF_RESOURCES      The request could not be
> completed due to a lack of resources.
> +  @retval Others                    The driver failed to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStart(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
> +  );
> +
> +/**
> +  Stop this driver on Controller.
> +
> +  @param  This              Protocol instance pointer.
> +  @param  Controller        Handle of device to stop driver on
> +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If
> number of
> +                            children is zero stop the entire bus driver.
> +  @param  ChildHandleBuffer List of Child Handles to Stop.
> +
> +  @retval EFI_SUCCESS       This driver is removed Controller.
> +  @retval other             This driver could not be removed from this
> device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStop(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  UINTN                           NumberOfChildren,
> +  EFI_HANDLE*                     ChildHandleBuffer
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetDriverName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetControllerName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetDriverName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetControllerName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  );
> +
> +#endif //_OPAL_DRIVER_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
> new file mode 100644
> index 000000000000..e4972227b669
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
> @@ -0,0 +1,1178 @@
> +/** @file
> +  Implementation of the HII for the Opal UEFI Driver.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalHii.h"
> +
> +//
> +// This is the generated IFR binary Data for each formset defined in VFR.
> +// This Data array is ready to be used as input of HiiAddPackages() to
> +// create a packagelist (which contains Form packages, String packages, etc).
> +//
> +extern UINT8  OpalPasswordFormBin[];
> +
> +//
> +// This is the generated String package Data for all .UNI files.
> +// This Data array is ready to be used as input of HiiAddPackages() to
> +// create a packagelist (which contains Form packages, String packages, etc).
> +//
> +extern UINT8  OpalPasswordDxeStrings[];
> +
> +CHAR16  OpalPasswordStorageName[] = L"OpalHiiConfig";
> +
> +EFI_HII_CONFIG_ACCESS_PROTOCOL gHiiConfigAccessProtocol;
> +
> +//
> +// Handle to the list of HII packages (forms and strings) for this driver
> +//
> +EFI_HII_HANDLE gHiiPackageListHandle = NULL;
> +
> +//
> +// Package List GUID containing all form and string packages
> +//
> +const EFI_GUID gHiiPackageListGuid = PACKAGE_LIST_GUID;
> +const EFI_GUID gHiiSetupVariableGuid = SETUP_VARIABLE_GUID;
> +
> +//
> +// Structure that contains state of the HII
> +// This structure is updated by Hii.cpp and its contents
> +// is rendered in the HII.
> +//
> +OPAL_HII_CONFIGURATION gHiiConfiguration;
> +
> +//
> +// The device path containing the VENDOR_DEVICE_PATH and
> EFI_DEVICE_PATH_PROTOCOL
> +//
> +HII_VENDOR_DEVICE_PATH gHiiVendorDevicePath = {
> +    {
> +        {
> +            HARDWARE_DEVICE_PATH,
> +            HW_VENDOR_DP,
> +            {
> +                (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
> +                (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
> +            }
> +        },
> +        OPAL_PASSWORD_CONFIG_GUID
> +    },
> +    {
> +        END_DEVICE_PATH_TYPE,
> +        END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +        {
> +            (UINT8)(END_DEVICE_PATH_LENGTH),
> +            (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
> +        }
> +    }
> +};
> +
> +/**
> +  Get saved OPAL request.
> +
> +  @param[in]  OpalDisk      The disk needs to get the saved OPAL request.
> +  @param[out] OpalRequest   OPAL request got.
> +
> +**/
> +VOID
> +GetSavedOpalRequest (
> +  IN OPAL_DISK              *OpalDisk,
> +  OUT OPAL_REQUEST          *OpalRequest
> +  )
> +{
> +  EFI_STATUS                Status;
> +  OPAL_REQUEST_VARIABLE     *TempVariable;
> +  OPAL_REQUEST_VARIABLE     *Variable;
> +  UINTN                     VariableSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
> +  UINTN                     DevicePathSizeInVariable;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathSize;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  Variable = NULL;
> +  VariableSize = 0;
> +
> +  Status = GetVariable2 (
> +             OPAL_REQUEST_VARIABLE_NAME,
> +             &gHiiSetupVariableGuid,
> +             (VOID **) &Variable,
> +             &VariableSize
> +             );
> +  if (EFI_ERROR (Status) || (Variable == NULL)) {
> +    return;
> +  }
> +
> +  TempVariable = Variable;
> +  while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
> +         (VariableSize >= TempVariable->Length) &&
> +         (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
> +    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +    DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
> +    DevicePath = OpalDisk->OpalDevicePath;
> +    DevicePathSize = GetDevicePathSize (DevicePath);
> +    if ((DevicePathSize == DevicePathSizeInVariable) &&
> +        (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize)
> == 0)) {
> +      //
> +      // Found the node for the OPAL device.
> +      // Get the OPAL request.
> +      //
> +      CopyMem (OpalRequest, &TempVariable->OpalRequest, sizeof
> (OPAL_REQUEST));
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "OpalRequest got: 0x%x\n",
> +        *OpalRequest
> +        ));
> +      break;
> +    }
> +    VariableSize -= TempVariable->Length;
> +    TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable +
> TempVariable->Length);
> +  }
> +
> +  FreePool (Variable);
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Save OPAL request.
> +
> +  @param[in] OpalDisk       The disk has OPAL request to save.
> +  @param[in] OpalRequest    OPAL request to save.
> +
> +**/
> +VOID
> +SaveOpalRequest (
> +  IN OPAL_DISK              *OpalDisk,
> +  IN OPAL_REQUEST           OpalRequest
> +  )
> +{
> +  EFI_STATUS                Status;
> +  OPAL_REQUEST_VARIABLE     *TempVariable;
> +  UINTN                     TempVariableSize;
> +  OPAL_REQUEST_VARIABLE     *Variable;
> +  UINTN                     VariableSize;
> +  OPAL_REQUEST_VARIABLE     *NewVariable;
> +  UINTN                     NewVariableSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
> +  UINTN                     DevicePathSizeInVariable;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathSize;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "OpalRequest to save: 0x%x\n",
> +    OpalRequest
> +    ));
> +
> +  Variable = NULL;
> +  VariableSize = 0;
> +  NewVariable = NULL;
> +  NewVariableSize = 0;
> +
> +  Status = GetVariable2 (
> +             OPAL_REQUEST_VARIABLE_NAME,
> +             &gHiiSetupVariableGuid,
> +             (VOID **) &Variable,
> +             &VariableSize
> +             );
> +  if (!EFI_ERROR (Status) && (Variable != NULL)) {
> +    TempVariable = Variable;
> +    TempVariableSize = VariableSize;
> +    while ((TempVariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
> +           (TempVariableSize >= TempVariable->Length) &&
> +           (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
> +      DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +      DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
> +      DevicePath = OpalDisk->OpalDevicePath;
> +      DevicePathSize = GetDevicePathSize (DevicePath);
> +      if ((DevicePathSize == DevicePathSizeInVariable) &&
> +          (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize)
> == 0)) {
> +        //
> +        // Found the node for the OPAL device.
> +        // Update the OPAL request.
> +        //
> +        CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof
> (OPAL_REQUEST));
> +        NewVariable = Variable;
> +        NewVariableSize = VariableSize;
> +        break;
> +      }
> +      TempVariableSize -= TempVariable->Length;
> +      TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable +
> TempVariable->Length);
> +    }
> +    if (NewVariable == NULL) {
> +      //
> +      // The node for the OPAL device is not found.
> +      // Create node for the OPAL device.
> +      //
> +      DevicePath = OpalDisk->OpalDevicePath;
> +      DevicePathSize = GetDevicePathSize (DevicePath);
> +      NewVariableSize = VariableSize + sizeof (OPAL_REQUEST_VARIABLE) +
> DevicePathSize;
> +      NewVariable = AllocatePool (NewVariableSize);
> +      ASSERT (NewVariable != NULL);
> +      CopyMem (NewVariable, Variable, VariableSize);
> +      TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) NewVariable +
> VariableSize);
> +      TempVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) +
> DevicePathSize);
> +      CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof
> (OPAL_REQUEST));
> +      DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +      CopyMem (DevicePathInVariable, DevicePath, DevicePathSize);
> +    }
> +  } else {
> +    DevicePath = OpalDisk->OpalDevicePath;
> +    DevicePathSize = GetDevicePathSize (DevicePath);
> +    NewVariableSize = sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize;
> +    NewVariable = AllocatePool (NewVariableSize);
> +    ASSERT (NewVariable != NULL);
> +    NewVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) +
> DevicePathSize);
> +    CopyMem (&NewVariable->OpalRequest, &OpalRequest, sizeof
> (OPAL_REQUEST));
> +    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> NewVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +    CopyMem (DevicePathInVariable, DevicePath, DevicePathSize);
> +  }
> +  Status = gRT->SetVariable (
> +                  OPAL_REQUEST_VARIABLE_NAME,
> +                  (EFI_GUID *) &gHiiSetupVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  NewVariableSize,
> +                  NewVariable
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_INFO, "OpalRequest variable set failed (%r)\n", Status));
> +  }
> +  if (NewVariable != Variable) {
> +    FreePool (NewVariable);
> +  }
> +  if (Variable != NULL) {
> +    FreePool (Variable);
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Sets the current system state of global config variables.
> +
> +**/
> +VOID
> +HiiSetCurrentConfiguration(
> +  VOID
> +  )
> +{
> +  UINT32                                       PpStorageFlag;
> +  EFI_STRING                                   NewString;
> +
> +  gHiiConfiguration.NumDisks = GetDeviceCount();
> +
> +  //
> +  // Update the BlockSID status string.
> +  //
> +  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
> +
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_ENABLED), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  } else {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISABLED), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  }
> +  HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_BLOCKSID_STATUS1), NewString, NULL);
> +  FreePool (NewString);
> +
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BL
> OCK_SID) != 0) {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  } else {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  }
> +  HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_BLOCKSID_STATUS2), NewString, NULL);
> +  FreePool (NewString);
> +
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BL
> OCK_SID) != 0) {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  } else {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  }
> +  HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_BLOCKSID_STATUS3), NewString, NULL);
> +  FreePool (NewString);
> +}
> +
> +/**
> +  Install the HII related resources.
> +
> +  @retval  EFI_SUCCESS        Install all the resources success.
> +  @retval  other              Error occur when install the resources.
> +**/
> +EFI_STATUS
> +HiiInstall(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_HANDLE                   DriverHandle;
> +
> +  //
> +  // Clear the global configuration.
> +  //
> +  ZeroMem(&gHiiConfiguration, sizeof(gHiiConfiguration));
> +
> +  //
> +  // Obtain the driver handle that the BIOS assigned us
> +  //
> +  DriverHandle = HiiGetDriverImageHandleCB();
> +
> +  //
> +  // Populate the config access protocol with the three functions we are
> publishing
> +  //
> +  gHiiConfigAccessProtocol.ExtractConfig = ExtractConfig;
> +  gHiiConfigAccessProtocol.RouteConfig = RouteConfig;
> +  gHiiConfigAccessProtocol.Callback = DriverCallback;
> +
> +  //
> +  // Associate the required protocols with our driver handle
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces(
> +               &DriverHandle,
> +               &gEfiHiiConfigAccessProtocolGuid,
> +               &gHiiConfigAccessProtocol,      // HII callback
> +               &gEfiDevicePathProtocolGuid,
> +               &gHiiVendorDevicePath,        // required for HII callback
> allow all disks to be shown in same hii
> +               NULL
> +           );
> +
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  return OpalHiiAddPackages();
> +}
> +
> +/**
> +  Install the HII form and string packages.
> +
> +  @retval  EFI_SUCCESS           Install all the resources success.
> +  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
> +**/
> +EFI_STATUS
> +OpalHiiAddPackages(
> +  VOID
> +  )
> +{
> +  EFI_HANDLE                   DriverHandle;
> +  CHAR16                       *NewString;
> +
> +  DriverHandle = HiiGetDriverImageHandleCB();
> +
> +  //
> +  // Publish the HII form and HII string packages
> +  //
> +  gHiiPackageListHandle = HiiAddPackages(
> +                                &gHiiPackageListGuid,
> +                                DriverHandle,
> +                                OpalPasswordDxeStrings,
> +                                OpalPasswordFormBin,
> +                                (VOID*)NULL
> +                                );
> +
> +  //
> +  // Make sure the packages installed successfully
> +  //
> +  if (gHiiPackageListHandle == NULL) {
> +    DEBUG ((DEBUG_INFO, "OpalHiiAddPackages failed\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Update Version String in main window
> +  //
> +  NewString = HiiGetDriverNameCB ();
> +  if (HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_MAIN_OPAL_VERSION), NewString, NULL) == 0) {
> +    DEBUG ((DEBUG_INFO,  "OpalHiiAddPackages: HiiSetString( ) failed\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Uninstall the HII capability.
> +
> +  @retval  EFI_SUCCESS           Uninstall all the resources success.
> +  @retval  others                Other errors occur when unistall the hii
> resource.
> +**/
> +EFI_STATUS
> +HiiUninstall(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +
> +  //
> +  // Remove the packages we've provided to the BIOS
> +  //
> +  HiiRemovePackages(gHiiPackageListHandle);
> +
> +  //
> +  // Remove the protocols from our driver handle
> +  //
> +  Status = gBS->UninstallMultipleProtocolInterfaces(
> +                          HiiGetDriverImageHandleCB(),
> +                          &gEfiHiiConfigAccessProtocolGuid,
> +                          &gHiiConfigAccessProtocol,        // HII
> callback
> +                          &gEfiDevicePathProtocolGuid,
> +                          &gHiiVendorDevicePath,            //
> required for HII callback
> +                          NULL
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_INFO, "Cannot uninstall Hii Protocols: %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Updates the main menu form.
> +
> +  @retval  EFI_SUCCESS           update the main form success.
> +**/
> +EFI_STATUS
> +HiiPopulateMainMenuForm (
> +  VOID
> +  )
> +{
> +  UINT8         Index;
> +  CHAR8         *DiskName;
> +  EFI_STRING_ID DiskNameId;
> +  OPAL_DISK     *OpalDisk;
> +
> +  HiiSetCurrentConfiguration();
> +
> +  gHiiConfiguration.SupportedDisks = 0;
> +
> +  for (Index = 0; Index < gHiiConfiguration.NumDisks; Index++) {
> +    OpalDisk = HiiGetOpalDiskCB (Index);
> +    if ((OpalDisk != NULL) && OpalFeatureSupported
> (&OpalDisk->SupportedAttributes)) {
> +      gHiiConfiguration.SupportedDisks |= (1 << Index);
> +      DiskNameId = GetDiskNameStringId (Index);
> +      DiskName = HiiDiskGetNameCB (Index);
> +      if ((DiskName == NULL) || (DiskNameId == 0)) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      HiiSetFormString(DiskNameId, DiskName);
> +    }
> +  }
> +
> +  OpalHiiSetBrowserData ();
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get disk name string id.
> +
> +  @param   DiskIndex             The input disk index info.
> +
> +  @retval  The disk name string id.
> +
> +**/
> +EFI_STRING_ID
> +GetDiskNameStringId(
> +  UINT8 DiskIndex
> +  )
> +{
> +  switch (DiskIndex) {
> +    case 0: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0);
> +    case 1: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1);
> +    case 2: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2);
> +    case 3: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3);
> +    case 4: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4);
> +    case 5: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5);
> +  }
> +  return 0;
> +}
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Action                 Specifies the type of action taken by the
> browser.
> +  @param  QuestionId             A unique value which is sent to the
> original
> +                                 exporting driver so that it can identify
> the type
> +                                 of data to expect.
> +  @param  Type                   The type of value for the question.
> +  @param  Value                  A pointer to the data being sent to the
> original
> +                                 exporting driver.
> +  @param  ActionRequest          On return, points to the action
> requested by the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the
> action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported
> by the
> +                                 callback.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DriverCallback(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  EFI_BROWSER_ACTION                      Action,
> +  EFI_QUESTION_ID                         QuestionId,
> +  UINT8                                   Type,
> +  EFI_IFR_TYPE_VALUE                      *Value,
> +  EFI_BROWSER_ACTION_REQUEST              *ActionRequest
> +  )
> +{
> +  HII_KEY    HiiKey;
> +  UINT8      HiiKeyId;
> +  UINT32     PpRequest;
> +  OPAL_DISK  *OpalDisk;
> +
> +  if (ActionRequest != NULL) {
> +    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
> +  } else {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // If QuestionId is an auto-generated key (label, empty line, etc.), ignore it.
> +  //
> +  if ((QuestionId & HII_KEY_FLAG) == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  HiiKey.Raw = QuestionId;
> +  HiiKeyId   = (UINT8) HiiKey.KeyBits.Id;
> +
> +  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
> +    switch (HiiKeyId) {
> +      case HII_KEY_ID_VAR_SUPPORTED_DISKS:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_VAR_SUPPORTED_DISKS\n"));
> +        return HiiPopulateMainMenuForm ();
> +
> +      case HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS:
> +        DEBUG ((DEBUG_INFO,
> "HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS\n"));
> +        return HiiPopulateDiskInfoForm();
> +    }
> +  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
> +    switch (HiiKeyId) {
> +      case HII_KEY_ID_GOTO_DISK_INFO:
> +        return HiiSelectDisk((UINT8)HiiKey.KeyBits.Index);
> +    }
> +  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
> +    switch (HiiKeyId) {
> +      case HII_KEY_ID_BLOCKSID:
> +        switch (Value->u8) {
> +          case 0:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
> +            break;
> +
> +          case 1:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID;
> +            break;
> +
> +          case 2:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID;
> +            break;
> +
> +          case 3:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FU
> NC_TRUE;
> +            break;
> +
> +          case 4:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FU
> NC_FALSE;
> +            break;
> +
> +          case 5:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FU
> NC_TRUE;
> +            break;
> +
> +          case 6:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FU
> NC_FALSE;
> +            break;
> +
> +          default:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
> +            DEBUG ((DEBUG_ERROR, "Invalid value input!\n"));
> +            break;
> +        }
> +        HiiSetBlockSidAction(PpRequest);
> +
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_SET_ADMIN_PWD:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SET_ADMIN_PWD\n"));
> +        gHiiConfiguration.OpalRequest.SetAdminPwd = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_SET_USER_PWD:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SET_USER_PWD\n"));
> +        gHiiConfiguration.OpalRequest.SetUserPwd = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_SECURE_ERASE:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SECURE_ERASE\n"));
> +        gHiiConfiguration.OpalRequest.SecureErase = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_REVERT:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_REVERT\n"));
> +        gHiiConfiguration.OpalRequest.Revert = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +      case HII_KEY_ID_KEEP_USER_DATA:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_KEEP_USER_DATA\n"));
> +        gHiiConfiguration.OpalRequest.KeepUserData = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_PSID_REVERT:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_PSID_REVERT\n"));
> +        gHiiConfiguration.OpalRequest.PsidRevert = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_DISABLE_USER:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_DISABLE_USER\n"));
> +        gHiiConfiguration.OpalRequest.DisableUser = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_ENABLE_FEATURE:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_ENABLE_FEATURE\n"));
> +        gHiiConfiguration.OpalRequest.EnableFeature = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      default:
> +        break;
> +    }
> +  }
> +
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Update the global Disk index info.
> +
> +  @param   Index             The input disk index info.
> +
> +  @retval  EFI_SUCCESS       Update the disk index info success.
> +
> +**/
> +EFI_STATUS
> +HiiSelectDisk(
> +  UINT8 Index
> +  )
> +{
> +  OpalHiiGetBrowserData();
> +  gHiiConfiguration.SelectedDiskIndex = Index;
> +  OpalHiiSetBrowserData ();
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Draws the disk info form.
> +
> +  @retval  EFI_SUCCESS       Draw the disk info success.
> +
> +**/
> +EFI_STATUS
> +HiiPopulateDiskInfoForm(
> +  VOID
> +  )
> +{
> +  OPAL_DISK*                    OpalDisk;
> +  OPAL_DISK_ACTIONS             AvailActions;
> +  TCG_RESULT                    Ret;
> +  CHAR8                         *DiskName;
> +
> +  OpalHiiGetBrowserData();
> +
> +  DiskName = HiiDiskGetNameCB (gHiiConfiguration.SelectedDiskIndex);
> +  if (DiskName == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +  HiiSetFormString(STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME),
> DiskName);
> +
> +  gHiiConfiguration.SelectedDiskAvailableActions = HII_ACTION_NONE;
> +  ZeroMem (&gHiiConfiguration.OpalRequest, sizeof (OPAL_REQUEST));
> +  gHiiConfiguration.KeepUserDataForced = FALSE;
> +
> +  OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +
> +  if (OpalDisk != NULL) {
> +    OpalDiskUpdateStatus (OpalDisk);
> +    Ret = OpalSupportGetAvailableActions(&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions);
> +    if (Ret == TcgResultSuccess) {
> +      //
> +      // Update actions, always allow PSID Revert
> +      //
> +      gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.PsidRevert == 1) ? HII_ACTION_PSID_REVERT :
> HII_ACTION_NONE;
> +
> +      //
> +      // Always allow unlock to handle device migration
> +      //
> +      gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Unlock
> == 1) ? HII_ACTION_UNLOCK : HII_ACTION_NONE;
> +
> +      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature)) {
> +        if (OpalDisk->Owner == OpalOwnershipNobody) {
> +          gHiiConfiguration.SelectedDiskAvailableActions |=
> HII_ACTION_ENABLE_FEATURE;
> +
> +          //
> +          // Update strings
> +          //
> +          HiiSetFormString( STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
> "PSID Revert to factory default");
> +        } else {
> +          DEBUG ((DEBUG_INFO, "Feature disabled but ownership !=
> nobody\n"));
> +        }
> +      } else {
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.Revert == 1) ? HII_ACTION_REVERT : HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.AdminPass == 1) ? HII_ACTION_SET_ADMIN_PWD :
> HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.UserPass == 1) ? HII_ACTION_SET_USER_PWD :
> HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.SecureErase == 1) ? HII_ACTION_SECURE_ERASE :
> HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.DisableUser == 1) ? HII_ACTION_DISABLE_USER :
> HII_ACTION_NONE;
> +
> +        HiiSetFormString (STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
> "PSID Revert to factory default and Disable");
> +
> +        //
> +        // Determine revert options for disk
> +        // Default initialize keep user Data to be true
> +        //
> +        gHiiConfiguration.OpalRequest.KeepUserData = 1;
> +        if (AvailActions.RevertKeepDataForced) {
> +          gHiiConfiguration.KeepUserDataForced = TRUE;
> +        }
> +      }
> +    }
> +
> +    GetSavedOpalRequest (OpalDisk, &gHiiConfiguration.OpalRequest);
> +  }
> +
> +  //
> +  // Pass the current configuration to the BIOS
> +  //
> +  OpalHiiSetBrowserData ();
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Send BlockSid request through TPM physical presence module.
> +
> +  @param   PpRequest         TPM physical presence operation request.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetBlockSidAction (
> +  IN UINT32          PpRequest
> +  )
> +{
> +  UINT32                           ReturnCode;
> +  EFI_STATUS                       Status;
> +
> +  ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction
> (PpRequest, 0);
> +  if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
> +    Status = EFI_SUCCESS;
> +  } else if (ReturnCode ==
> TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +  } else if (ReturnCode ==
> TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) {
> +    Status = EFI_UNSUPPORTED;
> +  } else {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Configuration          A null-terminated Unicode string in
> <ConfigResp>
> +                                 format.
> +  @param  Progress               A pointer to a string filled in with the
> offset of
> +                                 the most recent '&' before the first
> failing
> +                                 name/value pair (or the beginning of the
> string if
> +                                 the failure is in the first name/value pair)
> or
> +                                 the terminating NULL if all was
> successful.
> +
> +  @retval EFI_SUCCESS            The Results is processed successfully.
> +  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RouteConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Configuration,
> +  EFI_STRING                              *Progress
> +  )
> +{
> +  if (Configuration == NULL || Progress == NULL) {
> +    return (EFI_INVALID_PARAMETER);
> +  }
> +
> +  *Progress = Configuration;
> +  if (!HiiIsConfigHdrMatch (Configuration, &gHiiSetupVariableGuid,
> OpalPasswordStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  *Progress = Configuration + StrLen (Configuration);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function allows a caller to extract the current configuration for one
> +  or more named elements from the target driver.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Request                A null-terminated Unicode string in
> +                                 <ConfigRequest> format.
> +  @param  Progress               On return, points to a character in the
> Request
> +                                 string. Points to the string's null
> terminator if
> +                                 request was successful. Points to the
> most recent
> +                                 '&' before the first failing name/value
> pair (or
> +                                 the beginning of the string if the failure
> is in
> +                                 the first name/value pair) if the request
> was not
> +                                 successful.
> +  @param  Results                A null-terminated Unicode string in
> +                                 <ConfigAltResp> format which has all
> values filled
> +                                 in for the names in the Request string.
> String to
> +                                 be allocated by the called function.
> +
> +  @retval EFI_SUCCESS            The Results is filled with the requested
> values.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the
> results.
> +  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown
> name.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ExtractConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Request,
> +  EFI_STRING                              *Progress,
> +  EFI_STRING                              *Results
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  EFI_STRING                              ConfigRequest;
> +  EFI_STRING                              ConfigRequestHdr;
> +  UINTN                                   BufferSize;
> +  UINTN                                   Size;
> +  BOOLEAN                                 AllocatedRequest;
> +  EFI_HANDLE                              DriverHandle;
> +
> +  //
> +  // Check for valid parameters
> +  //
> +  if (Progress == NULL || Results == NULL) {
> +    return (EFI_INVALID_PARAMETER);
> +  }
> +
> +  *Progress = Request;
> +  if ((Request != NULL) &&
> +    !HiiIsConfigHdrMatch (Request, &gHiiSetupVariableGuid,
> OpalPasswordStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  AllocatedRequest = FALSE;
> +  BufferSize = sizeof (OPAL_HII_CONFIGURATION);
> +  ConfigRequest = Request;
> +  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
> +    //
> +    // Request has no request element, construct full request string.
> +    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
> +    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW"
> followed by a Null-terminator
> +    //
> +    DriverHandle = HiiGetDriverImageHandleCB();
> +    ConfigRequestHdr = HiiConstructConfigHdr (&gHiiSetupVariableGuid,
> OpalPasswordStorageName, DriverHandle);
> +    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
> +    ConfigRequest = AllocateZeroPool (Size);
> +    if (ConfigRequest == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    AllocatedRequest = TRUE;
> +    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX",
> ConfigRequestHdr, (UINT64)BufferSize);
> +    FreePool (ConfigRequestHdr);
> +  }
> +
> +  //
> +  // Convert Buffer Data to <ConfigResp> by helper function BlockToConfig( )
> +  //
> +  Status = gHiiConfigRouting->BlockToConfig(
> +               gHiiConfigRouting,
> +               ConfigRequest,
> +               (UINT8*)&gHiiConfiguration,
> +               sizeof(OPAL_HII_CONFIGURATION),
> +               Results,
> +               Progress
> +           );
> +
> +  //
> +  // Free the allocated config request string.
> +  //
> +  if (AllocatedRequest) {
> +    FreePool (ConfigRequest);
> +    ConfigRequest = NULL;
> +  }
> +
> +  //
> +  // Set Progress string to the original request string.
> +  //
> +  if (Request == NULL) {
> +    *Progress = NULL;
> +  } else if (StrStr (Request, L"OFFSET") == NULL) {
> +    *Progress = Request + StrLen (Request);
> +  }
> +
> +  return (Status);
> +}
> +
> +
> +/**
> +
> +  Pass the current system state to the bios via the hii_G_Configuration.
> +
> +**/
> +VOID
> +OpalHiiSetBrowserData (
> +  VOID
> +  )
> +{
> +  HiiSetBrowserData(
> +      &gHiiSetupVariableGuid,
> +      (CHAR16*)L"OpalHiiConfig",
> +      sizeof(gHiiConfiguration),
> +      (UINT8*)&gHiiConfiguration,
> +      NULL
> +  );
> +}
> +
> +
> +/**
> +
> +  Populate the hii_g_Configuraton with the browser Data.
> +
> +**/
> +VOID
> +OpalHiiGetBrowserData (
> +  VOID
> +  )
> +{
> +  HiiGetBrowserData(
> +      &gHiiSetupVariableGuid,
> +      (CHAR16*)L"OpalHiiConfig",
> +      sizeof(gHiiConfiguration),
> +      (UINT8*)&gHiiConfiguration
> +  );
> +}
> +
> +/**
> +  Set a string Value in a form.
> +
> +  @param      DestStringId   The stringid which need to update.
> +  @param      SrcAsciiStr    The string nned to update.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetFormString(
> +  EFI_STRING_ID       DestStringId,
> +  CHAR8               *SrcAsciiStr
> +  )
> +{
> +  UINT32                    Len;
> +  UINT32                    UniSize;
> +  CHAR16*                   UniStr;
> +
> +  //
> +  // Determine the Length of the sting
> +  //
> +  Len = ( UINT32 )AsciiStrLen( SrcAsciiStr );
> +
> +  //
> +  // Allocate space for the unicode string, including terminator
> +  //
> +  UniSize = (Len + 1) * sizeof(CHAR16);
> +  UniStr = (CHAR16*)AllocateZeroPool(UniSize);
> +
> +  //
> +  // Copy into unicode string, then copy into string id
> +  //
> +  AsciiStrToUnicodeStrS ( SrcAsciiStr, UniStr, Len + 1);
> +
> +  //
> +  // Update the string in the form
> +  //
> +  if (HiiSetString(gHiiPackageListHandle, DestStringId, UniStr, NULL) == 0) {
> +    DEBUG ((DEBUG_INFO,  "HiiSetFormString( ) failed\n"));
> +    FreePool(UniStr);
> +    return (EFI_OUT_OF_RESOURCES);
> +  }
> +
> +  //
> +  // Free the memory
> +  //
> +  FreePool(UniStr);
> +
> +  return (EFI_SUCCESS);
> +}
> +
> +/**
> +  Initialize the Opal disk base on the hardware info get from device.
> +
> +  @param Dev                  The Opal device.
> +
> +  @retval EFI_SUCESS          Initialize the device success.
> +  @retval EFI_DEVICE_ERROR    Get info from device failed.
> +
> +**/
> +EFI_STATUS
> +OpalDiskInitialize (
> +  IN OPAL_DRIVER_DEVICE          *Dev
> +  )
> +{
> +  TCG_RESULT                  TcgResult;
> +  OPAL_SESSION                Session;
> +
> +  ZeroMem(&Dev->OpalDisk, sizeof(OPAL_DISK));
> +  Dev->OpalDisk.Sscp = Dev->Sscp;
> +  Dev->OpalDisk.MediaId = Dev->MediaId;
> +  Dev->OpalDisk.OpalDevicePath = Dev->OpalDevicePath;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->Sscp;
> +  Session.MediaId = Dev->MediaId;
> +
> +  TcgResult = OpalGetSupportedAttributesInfo (&Session,
> &Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.OpalBaseComId);
> +  if (TcgResult != TcgResultSuccess) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  TcgResult = OpalUtilGetMsid (&Session, Dev->OpalDisk.Msid,
> OPAL_MSID_LENGHT, &Dev->OpalDisk.MsidLength);
> +  if (TcgResult != TcgResultSuccess) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return OpalDiskUpdateStatus (&Dev->OpalDisk);
> +}
> +
> +/**
> +  Update the device info.
> +
> +  @param OpalDisk                The Opal device.
> +
> +  @retval EFI_SUCESS             Initialize the device success.
> +  @retval EFI_DEVICE_ERROR       Get info from device failed.
> +  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership
> info.
> +
> +**/
> +EFI_STATUS
> +OpalDiskUpdateStatus (
> +  OPAL_DISK        *OpalDisk
> +  )
> +{
> +  TCG_RESULT                  TcgResult;
> +  OPAL_SESSION                Session;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = OpalDisk->Sscp;
> +  Session.MediaId = OpalDisk->MediaId;
> +  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
> +
> +  TcgResult = OpalGetLockingInfo(&Session, &OpalDisk->LockingFeature);
> +  if (TcgResult != TcgResultSuccess) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  if (OpalDisk->MsidLength == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  } else {
> +    //
> +    // Base on the Msid info to get the ownership, so Msid info must get first.
> +    //
> +    OpalDisk->Owner = OpalUtilDetermineOwnership(&Session,
> OpalDisk->Msid, OpalDisk->MsidLength);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
> new file mode 100644
> index 000000000000..a1b1131c1380
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
> @@ -0,0 +1,380 @@
> +/** @file
> +  Public Header file of HII library used by Opal UEFI Driver.
> +  Defines required callbacks of Opal HII library.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_HII_H_
> +#define _OPAL_HII_H_
> +
> +#include <Protocol/HiiConfigAccess.h>
> +
> +#include "OpalDriver.h"
> +#include "OpalHiiFormValues.h"
> +
> +#define  OPAL_PASSWORD_CONFIG_GUID \
> +  { \
> +    0x0d510a4f, 0xa81b, 0x473f, { 0x87, 0x07, 0xb7, 0xfd, 0xfb, 0xc0, 0x45,
> 0xba } \
> +  }
> +
> +#pragma pack(1)
> +
> +typedef struct {
> +  UINT16 Id: HII_KEY_ID_BITS;
> +  UINT16 Index: HII_KEY_INDEX_BITS;
> +  UINT16 Flag: HII_KEY_FLAG_BITS;
> +} KEY_BITS;
> +
> +typedef union {
> +    UINT16    Raw;
> +    KEY_BITS  KeyBits;
> +} HII_KEY;
> +
> +typedef struct {
> +    VENDOR_DEVICE_PATH             VendorDevicePath;
> +    EFI_DEVICE_PATH_PROTOCOL       End;
> +} HII_VENDOR_DEVICE_PATH;
> +
> +#pragma pack()
> +
> +extern const EFI_GUID gHiiSetupVariableGuid;
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Configuration          A null-terminated Unicode string in
> <ConfigResp>
> +                                 format.
> +  @param  Progress               A pointer to a string filled in with the
> offset of
> +                                 the most recent '&' before the first
> failing
> +                                 name/value pair (or the beginning of the
> string if
> +                                 the failure is in the first name/value pair)
> or
> +                                 the terminating NULL if all was
> successful.
> +
> +  @retval EFI_SUCCESS            The Results is processed successfully.
> +  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RouteConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Configuration,
> +  EFI_STRING                              *Progress
> +  );
> +
> +/**
> +  This function allows a caller to extract the current configuration for one
> +  or more named elements from the target driver.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Request                A null-terminated Unicode string in
> +                                 <ConfigRequest> format.
> +  @param  Progress               On return, points to a character in the
> Request
> +                                 string. Points to the string's null
> terminator if
> +                                 request was successful. Points to the
> most recent
> +                                 '&' before the first failing name/value
> pair (or
> +                                 the beginning of the string if the failure
> is in
> +                                 the first name/value pair) if the request
> was not
> +                                 successful.
> +  @param  Results                A null-terminated Unicode string in
> +                                 <ConfigAltResp> format which has all
> values filled
> +                                 in for the names in the Request string.
> String to
> +                                 be allocated by the called function.
> +
> +  @retval EFI_SUCCESS            The Results is filled with the requested
> values.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the
> results.
> +  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown
> name.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ExtractConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Request,
> +  EFI_STRING                              *Progress,
> +  EFI_STRING                              *Results
> +  );
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Action                 Specifies the type of action taken by the
> browser.
> +  @param  QuestionId             A unique value which is sent to the
> original
> +                                 exporting driver so that it can identify
> the type
> +                                 of data to expect.
> +  @param  Type                   The type of value for the question.
> +  @param  Value                  A pointer to the data being sent to the
> original
> +                                 exporting driver.
> +  @param  ActionRequest          On return, points to the action
> requested by the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the
> action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported
> by the
> +                                 callback.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DriverCallback(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL*   This,
> +  EFI_BROWSER_ACTION                      Action,
> +  EFI_QUESTION_ID                         QuestionId,
> +  UINT8                                   Type,
> +  EFI_IFR_TYPE_VALUE*                     Value,
> +  EFI_BROWSER_ACTION_REQUEST*             ActionRequest
> +  );
> +
> +/**
> +
> +  Pass the current system state to the bios via the hii_G_Configuration.
> +
> +**/
> +VOID
> +OpalHiiSetBrowserData (
> +  VOID
> +  );
> +
> +/**
> +
> +  Populate the hii_g_Configuraton with the browser Data.
> +
> +**/
> +VOID
> +OpalHiiGetBrowserData (
> +  VOID
> +  );
> +
> +/**
> +  Draws the disk info form.
> +
> +  @retval  EFI_SUCCESS       Draw the disk info success.
> +
> +**/
> +EFI_STATUS
> +HiiPopulateDiskInfoForm(
> +  VOID
> +  );
> +
> +/**
> +  Update the global Disk index info.
> +
> +  @param   Index             The input disk index info.
> +
> +  @retval  EFI_SUCCESS       Update the disk index info success.
> +
> +**/
> +EFI_STATUS
> +HiiSelectDisk(
> +  UINT8 Index
> +  );
> +
> +/**
> +  Use the input password to do the specified action.
> +
> +  @param      Str            The input password saved in.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiPasswordEntered(
> +  EFI_STRING_ID            Str
> +  );
> +
> +/**
> +  Update block sid info.
> +
> +  @param      PpRequest      Input the Pp Request.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetBlockSidAction (
> +  UINT32          PpRequest
> +  );
> +
> +/**
> +  Reverts the Opal disk to factory default.
> +
> +  @param   PsidStringId      The string id for the PSID info.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +
> +**/
> +EFI_STATUS
> +HiiPsidRevert(
> +  EFI_STRING_ID         PsidStringId
> +  );
> +
> +/**
> +  Get disk name string id.
> +
> +  @param   DiskIndex             The input disk index info.
> +
> +  @retval  The disk name string id.
> +
> +**/
> +EFI_STRING_ID
> +GetDiskNameStringId(
> +  UINT8 DiskIndex
> +  );
> +
> +/**
> +  Update the device info.
> +
> +  @param OpalDisk                The Opal device.
> +
> +  @retval EFI_SUCESS             Initialize the device success.
> +  @retval EFI_DEVICE_ERROR       Get info from device failed.
> +  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership
> info.
> +
> +**/
> +EFI_STATUS
> +OpalDiskUpdateStatus (
> +  OPAL_DISK        *OpalDisk
> +  );
> +
> +/**
> +  Get the driver image handle.
> +
> +  @retval  the driver image handle.
> +
> +**/
> +EFI_HANDLE
> +HiiGetDriverImageHandleCB(
> +  VOID
> +  );
> +
> +/**
> +  Install the HII form and string packages.
> +
> +  @retval  EFI_SUCCESS           Install all the resources success.
> +  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
> +**/
> +EFI_STATUS
> +OpalHiiAddPackages(
> +  VOID
> +  );
> +
> +/**
> +  Check whether enable feature or not.
> +
> +  @retval  Return the disk number.
> +
> +**/
> +UINT8
> +HiiGetNumConfigRequiredOpalDisksCB(
> +  VOID
> +  );
> +
> +/**
> +  Returns the driver name.
> +
> +  @retval Returns the driver name.
> +
> +**/
> +CHAR16*
> +HiiGetDriverNameCB(
> +  VOID
> +  );
> +
> +/**
> +  Returns the opaque pointer to a physical disk context.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval The device pointer.
> +
> +**/
> +OPAL_DISK*
> +HiiGetOpalDiskCB(
> +  UINT8 DiskIndex
> +  );
> +
> +/**
> +  Returns the disk name.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval Returns the disk name.
> +
> +**/
> +CHAR8*
> +HiiDiskGetNameCB(
> +  UINT8 DiskIndex
> +  );
> +
> +/**
> +  Set a string Value in a form.
> +
> +  @param      DestStringId   The stringid which need to update.
> +  @param      SrcAsciiStr    The string nned to update.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetFormString(
> +  EFI_STRING_ID       DestStringId,
> +  CHAR8               *SrcAsciiStr
> +  );
> +
> +/**
> +  Install the HII related resources.
> +
> +  @retval  EFI_SUCCESS        Install all the resources success.
> +  @retval  other              Error occur when install the resources.
> +**/
> +EFI_STATUS
> +HiiInstall(
> +  VOID
> +  );
> +
> +/**
> +  Uninstall the HII capability.
> +
> +  @retval  EFI_SUCCESS           Uninstall all the resources success.
> +  @retval  others                Other errors occur when unistall the hii
> resource.
> +**/
> +EFI_STATUS
> +HiiUninstall(
> +  VOID
> +  );
> +
> +/**
> +  Initialize the Opal disk base on the hardware info get from device.
> +
> +  @param Dev                  The Opal device.
> +
> +  @retval EFI_SUCESS          Initialize the device success.
> +  @retval EFI_DEVICE_ERROR    Get info from device failed.
> +
> +**/
> +EFI_STATUS
> +OpalDiskInitialize (
> +  IN OPAL_DRIVER_DEVICE          *Dev
> +  );
> +
> +#endif // _HII_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
> new file mode 100644
> index 000000000000..b07e38c1449d
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
> @@ -0,0 +1,219 @@
> +/** @file
> +  Callbacks required by the HII of the Opal UEFI Driver to help display
> +  Opal device information.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalHii.h"
> +
> +/**
> +  Get Opal var name.
> +  The return Value must be freed by caller if not NULL
> +
> +  @param      OpalDisk       The disk.
> +  @param      Prefix         The prefix string.
> +
> +  @retval  The var name string.
> +
> +**/
> +CHAR16*
> +OpalDriverGetOpalVarName(
> +  OPAL_DISK        *OpalDisk,
> +  const CHAR16     *Prefix
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*          Dev;
> +  UINTN                        PrefixLen;
> +  UINTN                        NameLen;
> +  UINTN                        VarNameLen;
> +  CHAR16*                      VarName;
> +
> +  Dev = DRIVER_DEVICE_FROM_OPALDISK(OpalDisk);
> +  if (Dev == NULL) {
> +    return NULL;
> +  }
> +
> +  PrefixLen = StrLen(Prefix);
> +
> +  NameLen = 0;
> +  if (Dev->Name16 != NULL) {
> +    NameLen = StrLen(Dev->Name16);
> +  }
> +
> +  VarNameLen = PrefixLen + NameLen;
> +
> +  VarName = (CHAR16*)AllocateZeroPool((VarNameLen + 1) *
> sizeof(CHAR16));
> +  if (VarName == NULL) {
> +    return NULL;
> +  }
> +
> +  CopyMem(VarName, Prefix, PrefixLen * sizeof(CHAR16));
> +  if (Dev->Name16 != NULL) {
> +    CopyMem(VarName + PrefixLen, Dev->Name16, NameLen *
> sizeof(CHAR16));
> +  }
> +  VarName[VarNameLen] = 0;
> +
> +  return VarName;
> +}
> +
> +/**
> +  Get the driver image handle.
> +
> +  @retval  the driver image handle.
> +
> +**/
> +EFI_HANDLE
> +HiiGetDriverImageHandleCB(
> +  VOID
> +  )
> +{
> +  return gImageHandle;
> +}
> +
> +/**
> +  Check whether enable feature or not.
> +
> +  @retval  Return the disk number.
> +
> +**/
> +UINT8
> +HiiGetNumConfigRequiredOpalDisksCB(
> +  VOID
> +  )
> +{
> +  UINT8                        NumDisks;
> +  UINT8                        NumLockedOpalDisks;
> +  OPAL_DISK                    *OpalDisk;
> +  UINT8                        Index;
> +
> +  NumLockedOpalDisks = 0;
> +
> +  NumDisks = GetDeviceCount();
> +
> +  for (Index = 0; Index < NumDisks; Index++) {
> +    OpalDisk = HiiGetOpalDiskCB(Index);
> +
> +    if (OpalDisk != NULL) {
> +      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature)) {
> +        DEBUG ((DEBUG_INFO, "Ignoring disk %u because feature is disabled
> or health has already been inspected\n", Index));
> +      } else if (OpalDeviceLocked (&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature)) {
> +        NumLockedOpalDisks++;
> +      }
> +    }
> +  }
> +
> +  return NumLockedOpalDisks;
> +}
> +
> +
> +
> +/**
> +  Returns the opaque pointer to a physical disk context.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval The device pointer.
> +
> +**/
> +VOID *
> +HiiGetDiskContextCB(
> +  UINT8 DiskIndex
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*                Dev;
> +  UINT8                              CurrentDisk;
> +
> +  Dev = OpalDriverGetDeviceList();
> +  CurrentDisk = 0;
> +
> +  if (DiskIndex >= GetDeviceCount()) {
> +    return NULL;
> +  }
> +
> +  while (Dev != NULL) {
> +    if (CurrentDisk == DiskIndex) {
> +      return Dev;
> +    } else {
> +      Dev = Dev->Next;
> +      CurrentDisk++;
> +    }
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Returns the opaque pointer to a physical disk context.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval The device pointer.
> +
> +**/
> +OPAL_DISK*
> +HiiGetOpalDiskCB(
> +  UINT8 DiskIndex
> +  )
> +{
> +  VOID                           *Ctx;
> +  OPAL_DRIVER_DEVICE             *Tmp;
> +
> +  Ctx = HiiGetDiskContextCB (DiskIndex);
> +
> +  if (Ctx == NULL) {
> +    return NULL;
> +  }
> +
> +  Tmp = (OPAL_DRIVER_DEVICE*) Ctx;
> +
> +  return &Tmp->OpalDisk;
> +}
> +
> +/**
> +  Returns the disk name.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval Returns the disk name.
> +
> +**/
> +CHAR8*
> +HiiDiskGetNameCB(
> +  UINT8 DiskIndex
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*                Ctx;
> +
> +  Ctx = (OPAL_DRIVER_DEVICE*) HiiGetDiskContextCB (DiskIndex);
> +
> +  if (Ctx != NULL) {
> +    if (Ctx->NameZ == NULL) {
> +      OpalDriverGetDriverDeviceName (Ctx);
> +    }
> +    return Ctx->NameZ;
> +  }
> +  return NULL;
> +}
> +
> +/**
> +  Returns the driver name.
> +
> +  @retval Returns the driver name.
> +
> +**/
> +CHAR16*
> +HiiGetDriverNameCB(
> +  VOID
> +  )
> +{
> +  return (CHAR16*)EFI_DRIVER_NAME_UNICODE;
> +}
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
> new file mode 100644
> index 000000000000..69abc561cc56
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
> @@ -0,0 +1,84 @@
> +// /** @file
> +//
> +//   String definitions for Setup formset.
> +//
> +// Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD
> License
> +// which accompanies this distribution. The full text of the license may be found
> at
> +// http://opensource.org/licenses/bsd-license.php
> +//
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +/=#
> +/////////////////////////////////   GENERIC DEFINITIONS
> /////////////////////////////////
> +#langdef en-US                                  "English"
> +#string STR_NULL                                #language en-US " "
> +
> +/////////////////////////////////   FORM SET   /////////////////////////////////
> +#string STR_FORM_SET_HELP                        #language en-US
> "Manage Opal disks"
> +
> +/////////////////////////////////   MULTIPLE FORMS
> /////////////////////////////////
> +#string STR_OPAL                                 #language en-US
> "Opal"
> +#string STR_MAIN_OPAL_VERSION                    #language en-US
> "Version 00.0.0.0000"
> +
> +/////////////////////////////////   MAIN MENU FORM
> /////////////////////////////////
> +#string STR_MAIN_PHY_DISKS_LBL                   #language en-US
> "Physical Disks:"
> +
> +#string STR_MAIN_GOTO_DISK_INFO_0                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_1                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_2                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_3                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_4                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_5                #language en-US " "
> +
> +#string STR_MAIN_GOTO_DISK_INFO_HELP             #language en-US
> "Select to see Opal disk actions"
> +
> +#string STR_MAIN_NO_DISKS_PRESENT_LBL            #language en-US
> "No disks connected to system"
> +
> +/////////////////////////////////   DISK INFO MENU FORM
> /////////////////////////////////
> +#string STR_DISK_INFO_SELECTED_DISK_NAME         #language en-US " "
> +
> +#string STR_DISK_INFO_LOCK                       #language en-US
> "Lock"
> +#string STR_DISK_INFO_UNLOCK                     #language en-US
> "Unlock"
> +#string STR_DISK_INFO_SET_ADMIN_PSWD             #language en-US
> "Update Drive Admin Password"
> +#string STR_DISK_INFO_SET_USER_PSWD              #language en-US
> "Set Drive User Password"
> +#string STR_DISK_INFO_SECURE_ERASE               #language en-US
> "Secure Erase User Data"
> +#string STR_DISK_INFO_PSID_REVERT                #language en-US
> "PSID Revert to factory default"
> +#string STR_DISK_INFO_REVERT                     #language en-US
> "Admin Revert to factory default and Disable"
> +#string STR_DISK_INFO_DISABLE_USER               #language en-US
> "Disable User"
> +#string STR_DISK_INFO_ENABLE_FEATURE             #language en-US
> "Enable Feature"
> +#string STR_DISK_INFO_ENABLE_BLOCKSID            #language en-US
> "TCG Storage Action"
> +#string STR_ENABLED                              #language en-US
> "Enable BlockSID"
> +#string STR_DISABLED                             #language en-US
> "Disable BlockSID"
> +
> +#string STR_NONE                                 #language en-US
> "None"
> +#string STR_DISK_INFO_ENABLE_BLOCKSID_TRUE       #language en-US
> "Require physical presence when remote enable BlockSID"
> +#string STR_DISK_INFO_ENABLE_BLOCKSID_FALSE      #language en-US
> "Not require physical presence when remote enable BlockSID"
> +#string STR_DISK_INFO_DISABLE_BLOCKSID_TRUE      #language en-US
> "Require physical presence when remote disable BlockSID"
> +#string STR_DISK_INFO_DISABLE_BLOCKSID_FALSE     #language en-US
> "Not require physical presence when remote disable BlockSID"
> +
> +#string STR_BLOCKSID_STATUS_HELP                 #language en-US
> "BlockSID action change status"
> +#string STR_BLOCKSID_STATUS                      #language en-US
> "Current BlockSID Status:"
> +#string STR_BLOCKSID_STATUS1                     #language en-US ""
> +#string STR_BLOCKSID_STATUS2                     #language en-US ""
> +#string STR_BLOCKSID_STATUS3                     #language en-US ""
> +
> +#string STR_OPAL_REQUESTS_LBL                    #language en-US
> "Opal Requests:"
> +#string STR_DISK_INFO_LOCK_HELP                  #language en-US
> "Lock the disk"
> +#string STR_DISK_INFO_UNLOCK_HELP                #language en-US
> "Unlock the disk"
> +#string STR_DISK_INFO_SET_ADMIN_PSWD_HELP        #language en-US
> "Set password for the administrator"
> +#string STR_DISK_INFO_SET_USER_PSWD_HELP         #language en-US
> "Set password for User 1"
> +#string STR_DISK_INFO_SECURE_ERASE_HELP          #language en-US
> "Securely erase the disk"
> +#string STR_DISK_INFO_REVERT_HELP                #language en-US
> "Revert the disk to factory defaults"
> +#string STR_DISK_INFO_PSID_REVERT_HELP           #language en-US
> "Revert the disk to factory defaults, PSID is a 32 character case sensitive value"
> +#string STR_DISK_INFO_DISABLE_USER_HELP          #language en-US
> "Disable User"
> +#string STR_DISK_INFO_ENABLE_FEATURE_HELP        #language en-US
> "Enable Feature"
> +#string STR_KEEP_USER_DATA_PROMPT                #language en-US "
> Keep User Data"
> +#string STR_KEEP_USER_DATA_HELP                  #language en-US
> "Check to keep user data, otherwise data will be lost"
> +
> +#string STR_DISK_INFO_ENABLE_BLOCKSID_HELP       #language en-US
> "Change BlockSID actions, includes enable or disable BlockSID, Require or not
> require physical presence when remote enable or disable BlockSID"
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
> new file mode 100644
> index 000000000000..3ff7d4726d5e
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
> @@ -0,0 +1,123 @@
> +/** @file
> +  Defines Opal HII form ids, structures and values.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +
> +#ifndef _OPAL_HII_FORM_VALUES_H_
> +#define _OPAL_HII_FORM_VALUES_H_
> +
> +// ID's for various forms that will be used by HII
> +#define FORMID_VALUE_MAIN_MENU                             0x01
> +#define FORMID_VALUE_DISK_INFO_FORM_MAIN                   0x02
> +
> +#define OPAL_REQUEST_VARIABLE_NAME
> L"OpalRequest"
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT16    Lock:1;
> +  UINT16    Unlock:1;
> +  UINT16    SetAdminPwd:1;
> +  UINT16    SetUserPwd:1;
> +  UINT16    SecureErase:1;
> +  UINT16    Revert:1;
> +  UINT16    PsidRevert:1;
> +  UINT16    DisableUser:1;
> +  UINT16    DisableFeature:1;
> +  UINT16    EnableFeature:1;
> +  UINT16    Reserved:5;
> +  UINT16    KeepUserData:1;
> +} OPAL_REQUEST;
> +
> +typedef struct {
> +  UINT8           NumDisks;
> +  UINT8           SelectedDiskIndex;
> +  UINT16          SelectedDiskAvailableActions;
> +  UINT16          SupportedDisks;
> +  BOOLEAN         KeepUserDataForced;
> +  OPAL_REQUEST    OpalRequest;
> +  UINT8           EnableBlockSid;
> +} OPAL_HII_CONFIGURATION;
> +
> +typedef struct {
> +  UINT32                   Length;
> +  OPAL_REQUEST             OpalRequest;
> +  //EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
> +} OPAL_REQUEST_VARIABLE;
> +
> +#pragma pack()
> +
> +/* Action Flags */
> +#define HII_ACTION_NONE
> 0x0000
> +#define HII_ACTION_LOCK
> 0x0001
> +#define HII_ACTION_UNLOCK
> 0x0002
> +#define HII_ACTION_SET_ADMIN_PWD
> 0x0004
> +#define HII_ACTION_SET_USER_PWD
> 0x0008
> +#define HII_ACTION_SECURE_ERASE
> 0x0010
> +#define HII_ACTION_REVERT
> 0x0020
> +#define HII_ACTION_PSID_REVERT
> 0x0040
> +#define HII_ACTION_DISABLE_USER
> 0x0080
> +#define HII_ACTION_DISABLE_FEATURE
> 0x0100
> +#define HII_ACTION_ENABLE_FEATURE
> 0x0200
> +
> +/* Number of bits allocated for each part of a unique key for an HII_ITEM
> + * all bits together must be <= 16 (EFI_QUESTION_ID is UINT16)
> + * 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
> + * |   |-----------------------|   |---------------------------|
> + * FLG INDEX                       ID
> + */
> +#define HII_KEY_ID_BITS                                     8
> +#define HII_KEY_INDEX_BITS                                  7
> +#define HII_KEY_FLAG_BITS                                   1
> +
> +#define HII_KEY_FLAG                                        0x8000
> // bit 15 (zero based)
> +
> +/***********/
> +/* Key IDs */
> +/***********/
> +
> +#define HII_KEY_ID_GOTO_DISK_INFO                       1
> +
> +#define HII_KEY_ID_VAR_SUPPORTED_DISKS                  2
> +#define HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS  3
> +
> +#define HII_KEY_ID_BLOCKSID                             4
> +#define HII_KEY_ID_SET_ADMIN_PWD                        5
> +#define HII_KEY_ID_SET_USER_PWD                         6
> +#define HII_KEY_ID_SECURE_ERASE                         7
> +#define HII_KEY_ID_REVERT                               8
> +#define HII_KEY_ID_KEEP_USER_DATA                       9
> +#define HII_KEY_ID_PSID_REVERT                          0xA
> +#define HII_KEY_ID_DISABLE_USER                         0xB
> +#define HII_KEY_ID_ENABLE_FEATURE                       0xC
> +
> +#define HII_KEY_ID_MAX                                  0xC
> // !!Update each time a new ID is added!!
> +
> +#define HII_KEY_WITH_INDEX(id, index) \
> +    ( \
> +        HII_KEY_FLAG | \
> +        (id) | \
> +        ((index) << HII_KEY_ID_BITS) \
> +    )
> +
> +#define HII_KEY(id) HII_KEY_WITH_INDEX(id, 0)
> +
> +#define PACKAGE_LIST_GUID { 0xf0308176, 0x9058, 0x4153, { 0x93, 0x3d,
> 0xda, 0x2f, 0xdc, 0xc8, 0x3e, 0x44 } }
> +
> +/* {410483CF-F4F9-4ece-848A-1958FD31CEB7} */
> +#define SETUP_FORMSET_GUID { 0x410483cf, 0xf4f9, 0x4ece, { 0x84, 0x8a,
> 0x19, 0x58, 0xfd, 0x31, 0xce, 0xb7 } }
> +
> +// {BBF1ACD2-28D8-44ea-A291-58A237FEDF1A}
> +#define SETUP_VARIABLE_GUID { 0xbbf1acd2, 0x28d8, 0x44ea, { 0xa2, 0x91,
> 0x58, 0xa2, 0x37, 0xfe, 0xdf, 0x1a } }
> +
> +#endif //_HII_FORM_VALUES_H_
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> new file mode 100644
> index 000000000000..7657bb26e23c
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> @@ -0,0 +1,2144 @@
> +/** @file
> +  Provide functions to initialize NVME controller and perform NVME
> commands
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalPasswordPei.h"
> +
> +
> +#define ALIGN(v, a)                         (UINTN)((((v) - 1) | ((a) - 1)) +
> 1)
> +
> +///
> +/// NVME Host controller registers operation
> +///
> +#define NVME_GET_CAP(Nvme, Cap)             NvmeMmioRead  (Cap,
> Nvme->Nbar + NVME_CAP_OFFSET, sizeof (NVME_CAP))
> +#define NVME_GET_CC(Nvme, Cc)               NvmeMmioRead  (Cc,
> Nvme->Nbar + NVME_CC_OFFSET, sizeof (NVME_CC))
> +#define NVME_SET_CC(Nvme, Cc)               NvmeMmioWrite
> (Nvme->Nbar + NVME_CC_OFFSET, Cc, sizeof (NVME_CC))
> +#define NVME_GET_CSTS(Nvme, Csts)           NvmeMmioRead  (Csts,
> Nvme->Nbar + NVME_CSTS_OFFSET, sizeof (NVME_CSTS))
> +#define NVME_GET_AQA(Nvme, Aqa)             NvmeMmioRead  (Aqa,
> Nvme->Nbar + NVME_AQA_OFFSET, sizeof (NVME_AQA))
> +#define NVME_SET_AQA(Nvme, Aqa)             NvmeMmioWrite
> (Nvme->Nbar + NVME_AQA_OFFSET, Aqa, sizeof (NVME_AQA))
> +#define NVME_GET_ASQ(Nvme, Asq)             NvmeMmioRead  (Asq,
> Nvme->Nbar + NVME_ASQ_OFFSET, sizeof (NVME_ASQ))
> +#define NVME_SET_ASQ(Nvme, Asq)             NvmeMmioWrite
> (Nvme->Nbar + NVME_ASQ_OFFSET, Asq, sizeof (NVME_ASQ))
> +#define NVME_GET_ACQ(Nvme, Acq)             NvmeMmioRead  (Acq,
> Nvme->Nbar + NVME_ACQ_OFFSET, sizeof (NVME_ACQ))
> +#define NVME_SET_ACQ(Nvme, Acq)             NvmeMmioWrite
> (Nvme->Nbar + NVME_ACQ_OFFSET, Acq, sizeof (NVME_ACQ))
> +#define NVME_GET_VER(Nvme, Ver)             NvmeMmioRead  (Ver,
> Nvme->Nbar + NVME_VER_OFFSET, sizeof (NVME_VER))
> +#define NVME_SET_SQTDBL(Nvme, Qid, Sqtdbl)  NvmeMmioWrite
> (Nvme->Nbar + NVME_SQTDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Sqtdbl, sizeof
> (NVME_SQTDBL))
> +#define NVME_SET_CQHDBL(Nvme, Qid, Cqhdbl)  NvmeMmioWrite
> (Nvme->Nbar + NVME_CQHDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Cqhdbl, sizeof
> (NVME_CQHDBL))
> +
> +///
> +/// Base memory address
> +///
> +enum {
> +  BASEMEM_CONTROLLER_DATA,
> +  BASEMEM_IDENTIFY_DATA,
> +  BASEMEM_ASQ,
> +  BASEMEM_ACQ,
> +  BASEMEM_SQ,
> +  BASEMEM_CQ,
> +  BASEMEM_PRP,
> +  BASEMEM_SECURITY,
> +  MAX_BASEMEM_COUNT
> +};
> +
> +///
> +/// All of base memories are 4K(0x1000) alignment
> +///
> +#define NVME_MEM_BASE(Nvme)
> ((UINTN)(Nvme->BaseMem))
> +#define NVME_CONTROL_DATA_BASE(Nvme)        (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_CONTROLLER_DATA))                        * EFI_PAGE_SIZE),
> EFI_PAGE_SIZE))
> +#define NVME_NAMESPACE_DATA_BASE(Nvme)      (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_IDENTIFY_DATA))                          * EFI_PAGE_SIZE),
> EFI_PAGE_SIZE))
> +#define NVME_ASQ_BASE(Nvme)                 (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ASQ))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_ACQ_BASE(Nvme)                 (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ACQ))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_SQ_BASE(Nvme, index)           (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SQ) +
> ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_CQ_BASE(Nvme, index)           (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CQ) +
> ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_PRP_BASE(Nvme, index)          (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_PRP) +
> ((index)*NVME_PRP_SIZE))          * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_SEC_BASE(Nvme)                 (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SECURITY))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +
> +/**
> +  Transfer MMIO Data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      *((UINT32 *)MemBuffer) = MmioRead32 (MmioAddr);
> +      break;
> +
> +    case 8:
> +      *((UINT64 *)MemBuffer) = MmioRead64 (MmioAddr);
> +      break;
> +
> +    case 2:
> +      *((UINT16 *)MemBuffer) = MmioRead16 (MmioAddr);
> +      break;
> +
> +    case 1:
> +      *((UINT8 *)MemBuffer) = MmioRead8 (MmioAddr);
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = MmioRead8 (MmioAddr + Offset);
> +        Ptr[Offset] = Data;
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Transfer memory data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      MmioWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
> +      break;
> +
> +    case 8:
> +      MmioWrite64 (MmioAddr, *((UINT64 *)MemBuffer));
> +      break;
> +
> +    case 2:
> +      MmioWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
> +      break;
> +
> +    case 1:
> +      MmioWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = Ptr[Offset];
> +        MmioWrite8 (MmioAddr + Offset, Data);
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Transfer MMIO data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +OpalPciRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      *((UINT32 *)MemBuffer) = PciRead32 (MmioAddr);
> +      break;
> +
> +    case 2:
> +      *((UINT16 *)MemBuffer) = PciRead16 (MmioAddr);
> +      break;
> +
> +    case 1:
> +      *((UINT8 *)MemBuffer) = PciRead8 (MmioAddr);
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = PciRead8 (MmioAddr + Offset);
> +        Ptr[Offset] = Data;
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Transfer memory data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +OpalPciWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      PciWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
> +      break;
> +
> +    case 2:
> +      PciWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
> +      break;
> +
> +    case 1:
> +      PciWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = Ptr[Offset];
> +        PciWrite8 (MmioAddr + Offset, Data);
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get total pages for specific NVME based memory.
> +
> +  @param[in] BaseMemIndex           - The Index of BaseMem (0-based).
> +
> +  @retval - The page count for specific BaseMem Index
> +
> +**/
> +UINT32
> +NvmeGetBaseMemPages (
> +  IN UINTN              BaseMemIndex
> +  )
> +{
> +  UINT32                Pages;
> +  UINTN                 Index;
> +  UINT32                PageSizeList[8];
> +
> +  PageSizeList[0] = 1;  /* Controller Data */
> +  PageSizeList[1] = 1;  /* Identify Data */
> +  PageSizeList[2] = 1;  /* ASQ */
> +  PageSizeList[3] = 1;  /* ACQ */
> +  PageSizeList[4] = 1;  /* SQs */
> +  PageSizeList[5] = 1;  /* CQs */
> +  PageSizeList[6] = NVME_PRP_SIZE * NVME_CSQ_DEPTH;  /* PRPs */
> +  PageSizeList[7] = 1;  /* Security Commands */
> +
> +  if (BaseMemIndex > MAX_BASEMEM_COUNT) {
> +    ASSERT (FALSE);
> +    return 0;
> +  }
> +
> +  Pages = 0;
> +  for (Index = 0; Index < BaseMemIndex; Index++) {
> +    Pages += PageSizeList[Index];
> +  }
> +
> +  return Pages;
> +}
> +
> +/**
> +  Wait for NVME controller status to be ready or not.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] WaitReady              - Flag for waitting status ready or not
> +
> +  @return EFI_SUCCESS               - Successfully to wait specific status.
> +  @return others                    - Fail to wait for specific controller
> status.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeWaitController (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN BOOLEAN            WaitReady
> +  )
> +{
> +  NVME_CSTS              Csts;
> +  EFI_STATUS             Status;
> +  UINT32                 Index;
> +  UINT8                  Timeout;
> +
> +  //
> +  // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set
> after
> +  // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 *
> Cap.To.
> +  //
> +  if (Nvme->Cap.To == 0) {
> +    Timeout = 1;
> +  } else {
> +    Timeout = Nvme->Cap.To;
> +  }
> +
> +  Status = EFI_SUCCESS;
> +  for(Index = (Timeout * 500); Index != 0; --Index) {
> +    MicroSecondDelay (1000);
> +
> +    //
> +    // Check if the controller is initialized
> +    //
> +    Status = NVME_GET_CSTS (Nvme, &Csts);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n",
> Status));
> +      return Status;
> +    }
> +
> +    if ((BOOLEAN) Csts.Rdy == WaitReady) {
> +      break;
> +    }
> +  }
> +
> +  if (Index == 0) {
> +    Status = EFI_TIMEOUT;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Disable the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully disable the controller.
> +  @return others                    - Fail to disable the controller.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeDisableController (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  NVME_CC                Cc;
> +  NVME_CSTS              Csts;
> +  EFI_STATUS             Status;
> +
> +  Status = NVME_GET_CSTS (Nvme, &Csts);
> +
> +  ///
> +  /// Read Controller Configuration Register.
> +  ///
> +  Status = NVME_GET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  if (Cc.En == 1) {
> +    Cc.En = 0;
> +    ///
> +    /// Disable the controller.
> +    ///
> +    Status = NVME_SET_CC (Nvme, &Cc);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> +      goto Done;
> +    }
> +  }
> +
> +  Status = NvmeWaitController (Nvme, FALSE);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  DEBUG ((DEBUG_INFO, "NvmeDisableController fail, Status: %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  Enable the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully enable the controller.
> +  @return EFI_DEVICE_ERROR          - Fail to enable the controller.
> +  @return EFI_TIMEOUT               - Fail to enable the controller in
> given time slot.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeEnableController (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  NVME_CC                Cc;
> +  EFI_STATUS             Status;
> +
> +  //
> +  // Enable the controller
> +  //
> +  ZeroMem (&Cc, sizeof (NVME_CC));
> +  Cc.En     = 1;
> +  Cc.Iosqes = 6;
> +  Cc.Iocqes = 4;
> +  Status    = NVME_SET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  Status = NvmeWaitController (Nvme, TRUE);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  DEBUG ((DEBUG_INFO, "NvmeEnableController fail, Status: %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  Shutdown the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully shutdown the
> controller.
> +  @return EFI_DEVICE_ERROR          - Fail to shutdown the controller.
> +  @return EFI_TIMEOUT               - Fail to shutdown the controller in
> given time slot.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeShutdownController (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  NVME_CC                Cc;
> +  NVME_CSTS              Csts;
> +  EFI_STATUS             Status;
> +  UINT32                 Index;
> +  UINTN                  Timeout;
> +
> +  Status    = NVME_GET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
> +    return Status;
> +  }
> +
> +  Cc.Shn     = 1; // Normal shutdown
> +
> +  Status    = NVME_SET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> +    return Status;
> +  }
> +
> +  Timeout = NVME_GENERIC_TIMEOUT/1000; // ms
> +  for(Index = (UINT32)(Timeout); Index != 0; --Index) {
> +    MicroSecondDelay (1000);
> +
> +    Status = NVME_GET_CSTS (Nvme, &Csts);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n",
> Status));
> +      return Status;
> +    }
> +
> +    if (Csts.Shst == 2) { // Shutdown processing complete
> +      break;
> +    }
> +  }
> +
> +  if (Index == 0) {
> +    Status = EFI_TIMEOUT;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Check the execution status from a given completion queue entry.
> +
> +  @param[in]     Cq                 - A pointer to the NVME_CQ item.
> +
> +**/
> +EFI_STATUS
> +NvmeCheckCqStatus (
> +  IN NVME_CQ             *Cq
> +  )
> +{
> +  if (Cq->Sct == 0x0 && Cq->Sc == 0x0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Dump NVMe Completion Entry Status from
> [0x%x]:\n", (UINTN)Cq));
> +  DEBUG ((DEBUG_INFO, "  SQ Identifier : [0x%x], Phase Tag : [%d], Cmd
> Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
> +  DEBUG ((DEBUG_INFO, "  NVMe Cmd Execution Result - "));
> +
> +  switch (Cq->Sct) {
> +    case 0x0:
> +      switch (Cq->Sc) {
> +        case 0x0:
> +          DEBUG ((DEBUG_INFO, "Successful Completion\n"));
> +          return EFI_SUCCESS;
> +        case 0x1:
> +          DEBUG ((DEBUG_INFO, "Invalid Command Opcode\n"));
> +          break;
> +        case 0x2:
> +          DEBUG ((DEBUG_INFO, "Invalid Field in Command\n"));
> +          break;
> +        case 0x3:
> +          DEBUG ((DEBUG_INFO, "Command ID Conflict\n"));
> +          break;
> +        case 0x4:
> +          DEBUG ((DEBUG_INFO, "Data Transfer Error\n"));
> +          break;
> +        case 0x5:
> +          DEBUG ((DEBUG_INFO, "Commands Aborted due to Power Loss
> Notification\n"));
> +          break;
> +        case 0x6:
> +          DEBUG ((DEBUG_INFO, "Internal Device Error\n"));
> +          break;
> +        case 0x7:
> +          DEBUG ((DEBUG_INFO, "Command Abort Requested\n"));
> +          break;
> +        case 0x8:
> +          DEBUG ((DEBUG_INFO, "Command Aborted due to SQ
> Deletion\n"));
> +          break;
> +        case 0x9:
> +          DEBUG ((DEBUG_INFO, "Command Aborted due to Failed Fused
> Command\n"));
> +          break;
> +        case 0xA:
> +          DEBUG ((DEBUG_INFO, "Command Aborted due to Missing Fused
> Command\n"));
> +          break;
> +        case 0xB:
> +          DEBUG ((DEBUG_INFO, "Invalid Namespace or Format\n"));
> +          break;
> +        case 0xC:
> +          DEBUG ((DEBUG_INFO, "Command Sequence Error\n"));
> +          break;
> +        case 0xD:
> +          DEBUG ((DEBUG_INFO, "Invalid SGL Last Segment Descriptor\n"));
> +          break;
> +        case 0xE:
> +          DEBUG ((DEBUG_INFO, "Invalid Number of SGL Descriptors\n"));
> +          break;
> +        case 0xF:
> +          DEBUG ((DEBUG_INFO, "Data SGL Length Invalid\n"));
> +          break;
> +        case 0x10:
> +          DEBUG ((DEBUG_INFO, "Metadata SGL Length Invalid\n"));
> +          break;
> +        case 0x11:
> +          DEBUG ((DEBUG_INFO, "SGL Descriptor Type Invalid\n"));
> +          break;
> +        case 0x80:
> +          DEBUG ((DEBUG_INFO, "LBA Out of Range\n"));
> +          break;
> +        case 0x81:
> +          DEBUG ((DEBUG_INFO, "Capacity Exceeded\n"));
> +          break;
> +        case 0x82:
> +          DEBUG ((DEBUG_INFO, "Namespace Not Ready\n"));
> +          break;
> +        case 0x83:
> +          DEBUG ((DEBUG_INFO, "Reservation Conflict\n"));
> +          break;
> +      }
> +      break;
> +
> +    case 0x1:
> +      switch (Cq->Sc) {
> +        case 0x0:
> +          DEBUG ((DEBUG_INFO, "Completion Queue Invalid\n"));
> +          break;
> +        case 0x1:
> +          DEBUG ((DEBUG_INFO, "Invalid Queue Identifier\n"));
> +          break;
> +        case 0x2:
> +          DEBUG ((DEBUG_INFO, "Maximum Queue Size Exceeded\n"));
> +          break;
> +        case 0x3:
> +          DEBUG ((DEBUG_INFO, "Abort Command Limit Exceeded\n"));
> +          break;
> +        case 0x5:
> +          DEBUG ((DEBUG_INFO, "Asynchronous Event Request Limit
> Exceeded\n"));
> +          break;
> +        case 0x6:
> +          DEBUG ((DEBUG_INFO, "Invalid Firmware Slot\n"));
> +          break;
> +        case 0x7:
> +          DEBUG ((DEBUG_INFO, "Invalid Firmware Image\n"));
> +          break;
> +        case 0x8:
> +          DEBUG ((DEBUG_INFO, "Invalid Interrupt Vector\n"));
> +          break;
> +        case 0x9:
> +          DEBUG ((DEBUG_INFO, "Invalid Log Page\n"));
> +          break;
> +        case 0xA:
> +          DEBUG ((DEBUG_INFO, "Invalid Format\n"));
> +          break;
> +        case 0xB:
> +          DEBUG ((DEBUG_INFO, "Firmware Application Requires
> Conventional Reset\n"));
> +          break;
> +        case 0xC:
> +          DEBUG ((DEBUG_INFO, "Invalid Queue Deletion\n"));
> +          break;
> +        case 0xD:
> +          DEBUG ((DEBUG_INFO, "Feature Identifier Not Saveable\n"));
> +          break;
> +        case 0xE:
> +          DEBUG ((DEBUG_INFO, "Feature Not Changeable\n"));
> +          break;
> +        case 0xF:
> +          DEBUG ((DEBUG_INFO, "Feature Not Namespace Specific\n"));
> +          break;
> +        case 0x10:
> +          DEBUG ((DEBUG_INFO, "Firmware Application Requires NVM
> Subsystem Reset\n"));
> +          break;
> +        case 0x80:
> +          DEBUG ((DEBUG_INFO, "Conflicting Attributes\n"));
> +          break;
> +        case 0x81:
> +          DEBUG ((DEBUG_INFO, "Invalid Protection Information\n"));
> +          break;
> +        case 0x82:
> +          DEBUG ((DEBUG_INFO, "Attempted Write to Read Only Range\n"));
> +          break;
> +      }
> +      break;
> +
> +    case 0x2:
> +      switch (Cq->Sc) {
> +        case 0x80:
> +          DEBUG ((DEBUG_INFO, "Write Fault\n"));
> +          break;
> +        case 0x81:
> +          DEBUG ((DEBUG_INFO, "Unrecovered Read Error\n"));
> +          break;
> +        case 0x82:
> +          DEBUG ((DEBUG_INFO, "End-to-end Guard Check Error\n"));
> +          break;
> +        case 0x83:
> +          DEBUG ((DEBUG_INFO, "End-to-end Application Tag Check
> Error\n"));
> +          break;
> +        case 0x84:
> +          DEBUG ((DEBUG_INFO, "End-to-end Reference Tag Check
> Error\n"));
> +          break;
> +        case 0x85:
> +          DEBUG ((DEBUG_INFO, "Compare Failure\n"));
> +          break;
> +        case 0x86:
> +          DEBUG ((DEBUG_INFO, "Access Denied\n"));
> +          break;
> +      }
> +      break;
> +
> +    default:
> +      DEBUG ((DEBUG_INFO, "Unknown error\n"));
> +      break;
> +  }
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> +  Create PRP lists for Data transfer which is larger than 2 memory pages.
> +  Note here we calcuate the number of required PRP lists and allocate them at
> one time.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] SqId                   - The SQ index for this PRP
> +  @param[in] PhysicalAddr           - The physical base address of Data
> Buffer.
> +  @param[in] Pages                  - The number of pages to be
> transfered.
> +  @param[out] PrpListHost           - The host base address of PRP lists.
> +  @param[in,out] PrpListNo          - The number of PRP List.
> +
> +  @retval The pointer Value to the first PRP List of the PRP lists.
> +
> +**/
> +STATIC
> +UINT64
> +NvmeCreatePrpList (
> +  IN     NVME_CONTEXT                 *Nvme,
> +  IN     UINT16                       SqId,
> +  IN     EFI_PHYSICAL_ADDRESS         PhysicalAddr,
> +  IN     UINTN                        Pages,
> +     OUT VOID                         **PrpListHost,
> +  IN OUT UINTN                        *PrpListNo
> +  )
> +{
> +  UINTN                       PrpEntryNo;
> +  UINT64                      PrpListBase;
> +  UINTN                       PrpListIndex;
> +  UINTN                       PrpEntryIndex;
> +  UINT64                      Remainder;
> +  EFI_PHYSICAL_ADDRESS        PrpListPhyAddr;
> +  UINTN                       Bytes;
> +  UINT8                       *PrpEntry;
> +  EFI_PHYSICAL_ADDRESS        NewPhyAddr;
> +
> +  ///
> +  /// The number of Prp Entry in a memory page.
> +  ///
> +  PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
> +
> +  ///
> +  /// Calculate total PrpList number.
> +  ///
> +  *PrpListNo = (UINTN) DivU64x64Remainder ((UINT64)Pages,
> (UINT64)PrpEntryNo, &Remainder);
> +  if (Remainder != 0) {
> +    *PrpListNo += 1;
> +  }
> +
> +  if (*PrpListNo > NVME_PRP_SIZE) {
> +    DEBUG ((DEBUG_INFO, "NvmeCreatePrpList (PhysicalAddr: %lx, Pages: %x)
> PrpEntryNo: %x\n",
> +      PhysicalAddr, Pages, PrpEntryNo));
> +    DEBUG ((DEBUG_INFO, "*PrpListNo: %x, Remainder: %lx", *PrpListNo,
> Remainder));
> +    ASSERT (FALSE);
> +  }
> +  *PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Nvme, SqId);
> +
> +  Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
> +  PrpListPhyAddr = (UINT64)(UINTN)(*PrpListHost);
> +
> +  ///
> +  /// Fill all PRP lists except of last one.
> +  ///
> +  ZeroMem (*PrpListHost, Bytes);
> +  for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
> +    PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
> +
> +    for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
> +      PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex *
> sizeof(UINT64));
> +      if (PrpEntryIndex != PrpEntryNo - 1) {
> +        ///
> +        /// Fill all PRP entries except of last one.
> +        ///
> +        CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof
> (UINT64));
> +        PhysicalAddr += EFI_PAGE_SIZE;
> +      } else {
> +        ///
> +        /// Fill last PRP entries with next PRP List pointer.
> +        ///
> +        NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) *
> EFI_PAGE_SIZE);
> +        CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof
> (UINT64));
> +      }
> +    }
> +  }
> +
> +  ///
> +  /// Fill last PRP list.
> +  ///
> +  PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
> +  for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder :
> PrpEntryNo); ++PrpEntryIndex) {
> +    PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex *
> sizeof(UINT64));
> +    CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
> +
> +    PhysicalAddr += EFI_PAGE_SIZE;
> +  }
> +
> +  return PrpListPhyAddr;
> +}
> +
> +/**
> +  Check whether there are available command slots.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - Available command slot is found
> +  @retval EFI_NOT_READY             - No available command slot is found
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeHasFreeCmdSlot (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  )
> +{
> +  return TRUE;
> +}
> +
> +/**
> +  Check whether all command slots are clean.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All command slots are clean
> +  @retval EFI_NOT_READY             - Not all command slots are clean
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeIsAllCmdSlotClean (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Waits until all NVME commands completed.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All NVME commands have
> completed
> +  @retval EFI_TIMEOUT               - Timeout occured
> +  @retval EFI_NOT_READY             - Not all NVME commands have
> completed
> +  @retval others                    - Error occurred on device side.
> +**/
> +EFI_STATUS
> +NvmeWaitAllComplete (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Sends an NVM Express Command Packet to an NVM Express controller or
> namespace. This function supports
> +  both blocking I/O and nonblocking I/O. The blocking I/O functionality is
> required, and the nonblocking
> +  I/O functionality is optional.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which
> the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      ID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to
> which the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      UUID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in,out] Packet             - A pointer to the NVM Express HCI
> Command Packet to send to the NVMe namespace specified
> +                                      by NamespaceId.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Command Packet
> was sent by the host. TransferLength bytes were transferred
> +                                      to, or from DataBuffer.
> +  @retval EFI_NOT_READY             - The NVM Express Command Packet
> could not be sent because the controller is not ready. The caller
> +                                      may retry again later.
> +  @retval EFI_DEVICE_ERROR          - A device error occurred while
> attempting to send the NVM Express Command Packet.
> +  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of
> NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
> +                                      Express Command Packet was not
> sent, so no additional status information is available.
> +  @retval EFI_UNSUPPORTED           - The command described by the
> NVM Express Command Packet is not supported by the host adapter.
> +                                      The NVM Express Command
> Packet was not sent, so no additional status information is available.
> +  @retval EFI_TIMEOUT               - A timeout occurred while waiting
> for the NVM Express Command Packet to execute.
> +
> +**/
> +EFI_STATUS
> +NvmePassThru (
> +  IN     NVME_CONTEXT                         *Nvme,
> +  IN     UINT32                               NamespaceId,
> +  IN     UINT64                               NamespaceUuid,
> +  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  NVME_SQ                       *Sq;
> +  NVME_CQ                       *Cq;
> +  UINT8                         Qid;
> +  UINT32                        Bytes;
> +  UINT32                        Offset;
> +  EFI_PHYSICAL_ADDRESS          PhyAddr;
> +  VOID                          *PrpListHost;
> +  UINTN                         PrpListNo;
> +  UINT32                        Timer;
> +  UINTN SqSize;
> +  UINTN CqSize;
> +
> +  ///
> +  /// check the Data fields in Packet parameter.
> +  ///
> +  if ((Nvme == NULL) || (Packet == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> Nvme(%x)/Packet(%x)\n",
> +      (UINTN)Nvme, (UINTN)Packet));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((Packet->NvmeCmd == NULL) || (Packet->NvmeResponse == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> NvmeCmd(%x)/NvmeResponse(%x)\n",
> +      (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeResponse));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Packet->QueueId != NVME_ADMIN_QUEUE && Packet->QueueId !=
> NVME_IO_QUEUE) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> QueueId(%x)\n",
> +      Packet->QueueId));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PrpListHost = NULL;
> +  PrpListNo   = 0;
> +  Status      = EFI_SUCCESS;
> +
> +  Qid = Packet->QueueId;
> +  Sq  = Nvme->SqBuffer[Qid] + Nvme->SqTdbl[Qid].Sqt;
> +  Cq  = Nvme->CqBuffer[Qid] + Nvme->CqHdbl[Qid].Cqh;
> +  if (Qid == NVME_ADMIN_QUEUE) {
> +    SqSize = NVME_ASQ_SIZE + 1;
> +    CqSize = NVME_ACQ_SIZE + 1;
> +  } else {
> +    SqSize = NVME_CSQ_DEPTH;
> +    CqSize = NVME_CCQ_DEPTH;
> +  }
> +
> +  if (Packet->NvmeCmd->Nsid != NamespaceId) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru: Nsid mismatch (%x, %x)\n",
> +      Packet->NvmeCmd->Nsid, NamespaceId));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ZeroMem (Sq, sizeof (NVME_SQ));
> +  Sq->Opc  = Packet->NvmeCmd->Cdw0.Opcode;
> +  Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation;
> +  Sq->Cid  = Packet->NvmeCmd->Cdw0.Cid;
> +  Sq->Nsid = Packet->NvmeCmd->Nsid;
> +
> +  ///
> +  /// Currently we only support PRP for Data transfer, SGL is NOT supported.
> +  ///
> +  ASSERT (Sq->Psdt == 0);
> +  if (Sq->Psdt != 0) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru: doesn't support SGL
> mechanism\n"));
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Sq->Prp[0] = Packet->TransferBuffer;
> +  Sq->Prp[1] = 0;
> +
> +  if(Packet->MetadataBuffer != (UINT64)(UINTN)NULL) {
> +    Sq->Mptr = Packet->MetadataBuffer;
> +  }
> +
> +  ///
> +  /// If the Buffer Size spans more than two memory pages (page Size as
> defined in CC.Mps),
> +  /// then build a PRP list in the second PRP submission queue entry.
> +  ///
> +  Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
> +  Bytes  = Packet->TransferLength;
> +
> +  if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
> +    ///
> +    /// Create PrpList for remaining Data Buffer.
> +    ///
> +    PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
> +    Sq->Prp[1] = NvmeCreatePrpList (Nvme, Nvme->SqTdbl[Qid].Sqt, PhyAddr,
> EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo);
> +    if (Sq->Prp[1] == 0) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      DEBUG ((DEBUG_ERROR, "NvmeCreatePrpList fail, Status: %r\n",
> Status));
> +      goto EXIT;
> +    }
> +
> +  } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
> +    Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
> +  }
> +
> +  if(Packet->NvmeCmd->Flags & CDW10_VALID) {
> +    Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW11_VALID) {
> +    Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW12_VALID) {
> +    Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW13_VALID) {
> +    Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW14_VALID) {
> +    Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW15_VALID) {
> +    Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
> +  }
> +
> +  ///
> +  /// Ring the submission queue doorbell.
> +  ///
> +  Nvme->SqTdbl[Qid].Sqt++;
> +  if(Nvme->SqTdbl[Qid].Sqt == SqSize) {
> +    Nvme->SqTdbl[Qid].Sqt = 0;
> +  }
> +  Status = NVME_SET_SQTDBL (Nvme, Qid, &Nvme->SqTdbl[Qid]);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_SET_SQTDBL fail, Status: %r\n",
> Status));
> +    goto EXIT;
> +  }
> +
> +  ///
> +  /// Wait for completion queue to get filled in.
> +  ///
> +  Status = EFI_TIMEOUT;
> +  Timer   = 0;
> +  while (Timer < NVME_CMD_TIMEOUT) {
> +    //DEBUG ((DEBUG_VERBOSE, "Timer: %x, Cq:\n", Timer));
> +    //DumpMem (Cq, sizeof (NVME_CQ));
> +    if (Cq->Pt != Nvme->Pt[Qid]) {
> +      Status = EFI_SUCCESS;
> +      break;
> +    }
> +
> +    MicroSecondDelay (NVME_CMD_WAIT);
> +    Timer += NVME_CMD_WAIT;
> +  }
> +
> +  Nvme->CqHdbl[Qid].Cqh++;
> +  if (Nvme->CqHdbl[Qid].Cqh == CqSize) {
> +    Nvme->CqHdbl[Qid].Cqh = 0;
> +    Nvme->Pt[Qid] ^= 1;
> +  }
> +
> +  ///
> +  /// Copy the Respose Queue entry for this command to the callers response
> Buffer
> +  ///
> +  CopyMem (Packet->NvmeResponse, Cq, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  if (!EFI_ERROR(Status)) { // We still need to check CQ status if no timeout
> error occured
> +    Status = NvmeCheckCqStatus (Cq);
> +  }
> +  NVME_SET_CQHDBL (Nvme, Qid, &Nvme->CqHdbl[Qid]);
> +
> +EXIT:
> +  return Status;
> +}
> +
> +/**
> +  Get identify controller Data.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer used to store the identify
> controller Data.
> +
> +  @return EFI_SUCCESS               - Successfully get the identify
> controller Data.
> +  @return others                    - Fail to get the identify controller
> Data.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeIdentifyController (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN VOID                                  *Buffer
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  //
> +  // According to Nvm Express 1.1 spec Figure 38, When not used, the field
> shall be cleared to 0h.
> +  // For the Identify command, the Namespace Identifier is only used for the
> Namespace Data structure.
> +  //
> +  Command.Nsid        = 0;
> +
> +  CommandPacket.NvmeCmd        = &Command;
> +  CommandPacket.NvmeResponse   = &Response;
> +  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
> +  CommandPacket.TransferLength = sizeof
> (NVME_ADMIN_CONTROLLER_DATA);
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +  //
> +  // Set bit 0 (Cns bit) to 1 to identify a controller
> +  //
> +  Command.Cdw10                = 1;
> +  Command.Flags                = CDW10_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get specified identify namespace Data.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] NamespaceId            - The specified namespace identifier.
> +  @param[in] Buffer                 - The Buffer used to store the identify
> namespace Data.
> +
> +  @return EFI_SUCCESS               - Successfully get the identify
> namespace Data.
> +  @return others                    - Fail to get the identify namespace
> Data.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeIdentifyNamespace (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN UINT32                                NamespaceId,
> +  IN VOID                                  *Buffer
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  Command.Nsid        = NamespaceId;
> +  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
> +  CommandPacket.TransferLength = sizeof
> (NVME_ADMIN_NAMESPACE_DATA);
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +  //
> +  // Set bit 0 (Cns bit) to 1 to identify a namespace
> +  //
> +  CommandPacket.NvmeCmd->Cdw10 = 0;
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NamespaceId,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get Block Size for specific namespace of NVME.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return                           - Block Size in bytes
> +
> +**/
> +STATIC
> +UINT32
> +NvmeGetBlockSize (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  UINT32                BlockSize;
> +  UINT32                Lbads;
> +  UINT32                Flbas;
> +  UINT32                LbaFmtIdx;
> +
> +  Flbas     = Nvme->NamespaceData->Flbas;
> +  LbaFmtIdx = Flbas & 3;
> +  Lbads     = Nvme->NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
> +
> +  BlockSize = (UINT32)1 << Lbads;
> +  return BlockSize;
> +}
> +
> +/**
> +  Get last LBA for specific namespace of NVME.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return                           - Last LBA address
> +
> +**/
> +STATIC
> +EFI_LBA
> +NvmeGetLastLba (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_LBA               LastBlock;
> +  LastBlock = Nvme->NamespaceData->Nsze - 1;
> +  return LastBlock;
> +}
> +
> +/**
> +  Create io completion queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully create io completion
> queue.
> +  @return others                    - Fail to create io completion queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeCreateIoCompletionQueue (
> +  IN     NVME_CONTEXT                      *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_CRIOCQ                        CrIoCq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  CrIoCq.Qid   = NVME_IO_QUEUE;
> +  CrIoCq.Qsize = NVME_CCQ_SIZE;
> +  CrIoCq.Pc    = 1;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof
> (NVME_ADMIN_CRIOCQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Create io submission queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully create io submission
> queue.
> +  @return others                    - Fail to create io submission queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeCreateIoSubmissionQueue (
> +  IN NVME_CONTEXT                          *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_CRIOSQ                        CrIoSq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  CrIoSq.Qid   = NVME_IO_QUEUE;
> +  CrIoSq.Qsize = NVME_CSQ_SIZE;
> +  CrIoSq.Pc    = 1;
> +  CrIoSq.Cqid  = NVME_IO_QUEUE;
> +  CrIoSq.Qprio = 0;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof
> (NVME_ADMIN_CRIOSQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Security send and receive commands.
> +
> +  @param[in]     Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in]     SendCommand            - The flag to indicate the
> command type, TRUE for Send command and FALSE for receive command
> +  @param[in]     SecurityProtocol       - Security Protocol
> +  @param[in]     SpSpecific             - Security Protocol Specific
> +  @param[in]     TransferLength         - Transfer Length of Buffer (in
> bytes) - always a multiple of 512
> +  @param[in,out] TransferBuffer         - Address of Data to transfer
> +
> +  @return EFI_SUCCESS               - Successfully create io submission
> queue.
> +  @return others                    - Fail to send/receive commands.
> +
> +**/
> +EFI_STATUS
> +NvmeSecuritySendReceive (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN BOOLEAN                               SendCommand,
> +  IN UINT8                                 SecurityProtocol,
> +  IN UINT16                                SpSpecific,
> +  IN UINTN                                 TransferLength,
> +  IN OUT VOID                              *TransferBuffer
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_SECSEND                       SecSend;
> +  OACS                                     *Oacs;
> +  UINT8                                    Opcode;
> +  VOID*                                    *SecBuff;
> +
> +  Oacs = (OACS *)&Nvme->ControllerData->Oacs;
> +
> +  //
> +  // Verify security bit for Security Send/Receive commands
> +  //
> +  if (Oacs->Security == 0) {
> +    DEBUG ((DEBUG_ERROR, "Security command doesn't support.\n"));
> +    return EFI_NOT_READY;
> +  }
> +
> +  SecBuff = (VOID *)(UINTN) NVME_SEC_BASE (Nvme);
> +
> +  //
> +  // Actions for sending security command
> +  //
> +  if (SendCommand) {
> +    CopyMem (SecBuff, TransferBuffer, TransferLength);
> +  }
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&SecSend, sizeof(NVME_ADMIN_SECSEND));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Opcode = (UINT8)(SendCommand ? NVME_ADMIN_SECURITY_SEND_OPC :
> NVME_ADMIN_SECURITY_RECV_OPC);
> +  Command.Cdw0.Opcode = Opcode;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer = (UINT64)(UINTN)SecBuff;
> +  CommandPacket.TransferLength = (UINT32)TransferLength;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  SecSend.Spsp = SpSpecific;
> +  SecSend.Secp = SecurityProtocol;
> +  SecSend.Tl   = (UINT32)TransferLength;
> +
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &SecSend, sizeof
> (NVME_ADMIN_SECSEND));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  //
> +  // Actions for receiving security command
> +  //
> +  if (!SendCommand) {
> +    CopyMem (TransferBuffer, SecBuff, TransferLength);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Destroy io completion queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully destroy io completion
> queue.
> +  @return others                    - Fail to destroy io completion queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeDestroyIoCompletionQueue (
> +  IN     NVME_CONTEXT                      *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_DEIOCQ                        DelIoCq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&DelIoCq, sizeof(NVME_ADMIN_DEIOCQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_DELIOCQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  DelIoCq.Qid   = NVME_IO_QUEUE;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoCq, sizeof
> (NVME_ADMIN_DEIOCQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Destroy io submission queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully destroy io submission
> queue.
> +  @return others                    - Fail to destroy io submission queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeDestroyIoSubmissionQueue (
> +  IN NVME_CONTEXT                          *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_DEIOSQ                        DelIoSq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&DelIoSq, sizeof(NVME_ADMIN_DEIOSQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_DELIOSQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  DelIoSq.Qid   = NVME_IO_QUEUE;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoSq, sizeof
> (NVME_ADMIN_DEIOSQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Allocate transfer-related Data struct which is used at Nvme.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeAllocateResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
> +  VOID                      *Base;
> +  VOID                      *Mapping;
> +
> +  //
> +  // Allocate resources for DMA.
> +  //
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  Nvme->BaseMemMapping = Mapping;
> +  Nvme->BaseMem = Base;
> +  ZeroMem (Nvme->BaseMem, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (NVME_MEM_MAX_SIZE));
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a() NvmeContext 0x%x\n",
> +    __FUNCTION__,
> +    Nvme->BaseMem
> +    ));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Free allocated transfer-related Data struct which is used at NVMe.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +**/
> +VOID
> +EFIAPI
> +NvmeFreeResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  )
> +{
> +  if (Nvme->BaseMem != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
> +       Nvme->BaseMem,
> +       Nvme->BaseMemMapping
> +       );
> +    Nvme->BaseMem = NULL;
> +  }
> +}
> +
> +/**
> +  Initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> initialized successfully.
> +  @retval Others                    - A device error occurred while
> initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerInit (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_STATUS            Status;
> +  NVME_AQA              Aqa;
> +  NVME_ASQ              Asq;
> +  NVME_ACQ              Acq;
> +  NVME_VER              Ver;
> +
> +  UINT32                MlBAR;
> +  UINT32                MuBAR;
> +
> +  ///
> +  /// Update PCIE BAR0/1 for NVME device
> +  ///
> +  MlBAR = Nvme->Nbar;
> +  MuBAR = 0;
> +  PciWrite32 (Nvme->PciBase + 0x10, MlBAR); // MLBAR (BAR0)
> +  PciWrite32 (Nvme->PciBase + 0x14, MuBAR); // MUBAR (BAR1)
> +
> +  ///
> +  /// Enable PCIE decode
> +  ///
> +  PciWrite8 (Nvme->PciBase + NVME_PCIE_PCICMD, 0x6);
> +
> +  // Version
> +  NVME_GET_VER (Nvme, &Ver);
> +  if (!(Ver.Mjr == 0x0001) && (Ver.Mnr == 0x0000)) {
> +    DEBUG ((DEBUG_INFO, "\n!!!\n!!! NVME Version mismatch for the
> implementation !!!\n!!!\n"));
> +  }
> +
> +  ///
> +  /// Read the Controller Capabilities register and verify that the NVM
> command set is supported
> +  ///
> +  Status = NVME_GET_CAP (Nvme, &Nvme->Cap);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_GET_CAP fail, Status: %r\n", Status));
> +    goto Done;
> +  }
> +
> +  if (Nvme->Cap.Css != 0x01) {
> +    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: the controller doesn't
> support NVMe command set\n"));
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Currently the driver only supports 4k page Size.
> +  ///
> +  if ((Nvme->Cap.Mpsmin + 12) > EFI_PAGE_SHIFT) {
> +    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: only supports 4k page
> Size\n"));
> +    ASSERT (FALSE);
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
> +  Nvme->Cid[0] = 0;
> +  Nvme->Cid[1] = 0;
> +
> +  Nvme->Pt[0]  = 0;
> +  Nvme->Pt[1]  = 0;
> +
> +  ZeroMem ((VOID *)(UINTN)(&(Nvme->SqTdbl[0])), sizeof (NVME_SQTDBL) *
> NVME_MAX_IO_QUEUES);
> +  ZeroMem ((VOID *)(UINTN)(&(Nvme->CqHdbl[0])), sizeof (NVME_CQHDBL)
> * NVME_MAX_IO_QUEUES);
> +
> +  ZeroMem (Nvme->BaseMem, NVME_MEM_MAX_SIZE);
> +
> +  Status = NvmeDisableController (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeDisableController fail, Status: %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  ///
> +  /// set number of entries admin submission & completion queues.
> +  ///
> +  Aqa.Asqs  = NVME_ASQ_SIZE;
> +  Aqa.Rsvd1 = 0;
> +  Aqa.Acqs  = NVME_ACQ_SIZE;
> +  Aqa.Rsvd2 = 0;
> +
> +  ///
> +  /// Address of admin submission queue.
> +  ///
> +  Asq = (UINT64)(UINTN)(NVME_ASQ_BASE (Nvme) & ~0xFFF);
> +
> +  ///
> +  /// Address of admin completion queue.
> +  ///
> +  Acq = (UINT64)(UINTN)(NVME_ACQ_BASE (Nvme) & ~0xFFF);
> +
> +  ///
> +  /// Address of I/O submission & completion queue.
> +  ///
> +  Nvme->SqBuffer[0] = (NVME_SQ *)(UINTN)NVME_ASQ_BASE (Nvme);   //
> NVME_ADMIN_QUEUE
> +  Nvme->CqBuffer[0] = (NVME_CQ *)(UINTN)NVME_ACQ_BASE (Nvme);   //
> NVME_ADMIN_QUEUE
> +  Nvme->SqBuffer[1] = (NVME_SQ *)(UINTN)NVME_SQ_BASE (Nvme, 0); //
> NVME_IO_QUEUE
> +  Nvme->CqBuffer[1] = (NVME_CQ *)(UINTN)NVME_CQ_BASE (Nvme, 0); //
> NVME_IO_QUEUE
> +
> +  DEBUG ((DEBUG_INFO, "Admin Submission Queue Size (Aqa.Asqs) =
> [%08X]\n", Aqa.Asqs));
> +  DEBUG ((DEBUG_INFO, "Admin Completion Queue Size (Aqa.Acqs) =
> [%08X]\n", Aqa.Acqs));
> +  DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) =
> [%08X]\n", Nvme->SqBuffer[0]));
> +  DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) =
> [%08X]\n", Nvme->CqBuffer[0]));
> +  DEBUG ((DEBUG_INFO, "I/O   Submission Queue (SqBuffer[1]) =
> [%08X]\n", Nvme->SqBuffer[1]));
> +  DEBUG ((DEBUG_INFO, "I/O   Completion Queue (CqBuffer[1]) =
> [%08X]\n", Nvme->CqBuffer[1]));
> +
> +  ///
> +  /// Program admin queue attributes.
> +  ///
> +  Status = NVME_SET_AQA (Nvme, &Aqa);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Program admin submission queue address.
> +  ///
> +  Status = NVME_SET_ASQ (Nvme, &Asq);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Program admin completion queue address.
> +  ///
> +  Status = NVME_SET_ACQ (Nvme, &Acq);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  Status = NvmeEnableController (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Create one I/O completion queue.
> +  ///
> +  Status = NvmeCreateIoCompletionQueue (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Create one I/O Submission queue.
> +  ///
> +  Status = NvmeCreateIoSubmissionQueue (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Get current Identify Controller Data
> +  ///
> +  Nvme->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)(UINTN)
> NVME_CONTROL_DATA_BASE (Nvme);
> +  Status = NvmeIdentifyController (Nvme, Nvme->ControllerData);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Dump NvmExpress Identify Controller Data
> +  ///
> +  Nvme->ControllerData->Sn[19] = 0;
> +  Nvme->ControllerData->Mn[39] = 0;
> +  //NvmeDumpIdentifyController (Nvme->ControllerData);
> +
> +  ///
> +  /// Get current Identify Namespace Data
> +  ///
> +  Nvme->NamespaceData = (NVME_ADMIN_NAMESPACE_DATA
> *)NVME_NAMESPACE_DATA_BASE (Nvme);
> +  Status = NvmeIdentifyNamespace (Nvme, Nvme->Nsid,
> Nvme->NamespaceData);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeIdentifyNamespace fail, Status = %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Dump NvmExpress Identify Namespace Data
> +  ///
> +  if (Nvme->NamespaceData->Ncap == 0) {
> +    DEBUG ((DEBUG_ERROR, "Invalid Namespace, Ncap: %lx\n",
> Nvme->NamespaceData->Ncap));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Done;
> +  }
> +
> +  Nvme->BlockSize = NvmeGetBlockSize (Nvme);
> +  Nvme->LastBlock = NvmeGetLastLba (Nvme);
> +
> +  Nvme->State    = NvmeStatusInit;
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  return Status;
> +}
> +
> +/**
> +  Un-initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> un-initialized successfully.
> +  @retval Others                    - A device error occurred while
> un-initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerExit (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_STATUS            Status;
> +
> +  Status = EFI_SUCCESS;
> +  if (Nvme->State == NvmeStatusInit || Nvme->State == NvmeStatusMax) {
> +    ///
> +    /// Destroy I/O Submission queue.
> +    ///
> +    Status = NvmeDestroyIoSubmissionQueue (Nvme);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoSubmissionQueue fail, Status
> = %r\n", Status));
> +      return Status;
> +    }
> +
> +    ///
> +    /// Destroy I/O completion queue.
> +    ///
> +    Status = NvmeDestroyIoCompletionQueue (Nvme);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoCompletionQueue fail, Status
> = %r\n", Status));
> +      return Status;
> +    }
> +
> +    Status = NvmeShutdownController (Nvme);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeShutdownController fail, Status: %r\n",
> Status));
> +    }
> +  }
> +
> +  ///
> +  /// Disable PCIE decode
> +  ///
> +  PciWrite8  (Nvme->PciBase + NVME_PCIE_PCICMD, 0x0);
> +  PciWrite32 (Nvme->PciBase + 0x10, 0); // MLBAR (BAR0)
> +  PciWrite32 (Nvme->PciBase + 0x14, 0); // MUBAR (BAR1)
> +
> +  Nvme->State = NvmeStatusUnknown;
> +  return Status;
> +}
> +
> +/**
> +  Read sector Data from the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in,out] Buffer             - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeReadSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN OUT UINT64                            Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  )
> +{
> +  UINT32                                   Bytes;
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  UINT32                                   BlockSize;
> +
> +  BlockSize  = Nvme->BlockSize;
> +  Bytes      = Blocks * BlockSize;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
> +  CommandPacket.NvmeCmd->Cdw0.Cid    =
> Nvme->Cid[NVME_IO_QUEUE]++;
> +  CommandPacket.NvmeCmd->Nsid        = Nvme->Nsid;
> +  CommandPacket.TransferBuffer       = Buffer;
> +
> +  CommandPacket.TransferLength = Bytes;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_IO_QUEUE;
> +
> +  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
> +  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
> +  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
> +
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID |
> CDW12_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              Nvme->Nsid,
> +              0,
> +              &CommandPacket
> +              );
> +
> +  return Status;
> +}
> +
> +/**
> +  Write sector Data to the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWriteSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN UINT64                                Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  UINT32                                   Bytes;
> +  UINT32                                   BlockSize;
> +
> +  BlockSize  = Nvme->BlockSize;
> +  Bytes      = Blocks * BlockSize;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
> +  CommandPacket.NvmeCmd->Cdw0.Cid    =
> Nvme->Cid[NVME_IO_QUEUE]++;
> +  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
> +  CommandPacket.TransferBuffer = Buffer;
> +
> +  CommandPacket.TransferLength = Bytes;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_IO_QUEUE;
> +
> +  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
> +  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
> +  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
> +
> +  CommandPacket.MetadataBuffer = (UINT64)(UINTN)NULL;
> +  CommandPacket.MetadataLength = 0;
> +
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID |
> CDW12_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              Nvme->Nsid,
> +              0,
> +              &CommandPacket
> +              );
> +
> +  return Status;
> +}
> +
> +/**
> +  Flushes all modified Data to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeFlush (
> +  IN NVME_CONTEXT                          *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC;
> +  CommandPacket.NvmeCmd->Cdw0.Cid    =
> Nvme->Cid[NVME_IO_QUEUE]++;
> +  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_IO_QUEUE;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              Nvme->Nsid,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Read some blocks from the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[out] Buffer                - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeRead (
> +  IN NVME_CONTEXT                  *Nvme,
> +  OUT UINT64                       Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINT32                           BlockSize;
> +  UINT32                           MaxTransferBlocks;
> +
> +  ASSERT (Blocks <= NVME_MAX_SECTORS);
> +  Status        = EFI_SUCCESS;
> +  BlockSize     = Nvme->BlockSize;
> +  if (Nvme->ControllerData->Mdts != 0) {
> +    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 <<
> (Nvme->Cap.Mpsmin + 12)) / BlockSize;
> +  } else {
> +    MaxTransferBlocks = 1024;
> +  }
> +
> +  while (Blocks > 0) {
> +    if (Blocks > MaxTransferBlocks) {
> +      Status = NvmeReadSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
> +
> +      Blocks -= MaxTransferBlocks;
> +      Buffer += (MaxTransferBlocks * BlockSize);
> +      Lba    += MaxTransferBlocks;
> +    } else {
> +      Status = NvmeReadSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
> +      Blocks = 0;
> +    }
> +
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeRead fail, Status = %r\n", Status));
> +      break;
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Write some blocks to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWrite (
> +  IN NVME_CONTEXT                  *Nvme,
> +  IN UINT64                        Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINT32                           BlockSize;
> +  UINT32                           MaxTransferBlocks;
> +
> +  ASSERT (Blocks <= NVME_MAX_SECTORS);
> +  Status        = EFI_SUCCESS;
> +  BlockSize     = Nvme->BlockSize;
> +
> +  if (Nvme->ControllerData->Mdts != 0) {
> +    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 <<
> (Nvme->Cap.Mpsmin + 12)) / BlockSize;
> +  } else {
> +    MaxTransferBlocks = 1024;
> +  }
> +
> +  while (Blocks > 0) {
> +    if (Blocks > MaxTransferBlocks) {
> +      Status = NvmeWriteSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
> +
> +      Blocks -= MaxTransferBlocks;
> +      Buffer += (MaxTransferBlocks * BlockSize);
> +      Lba    += MaxTransferBlocks;
> +    } else {
> +      Status = NvmeWriteSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
> +      Blocks = 0;
> +    }
> +
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeWrite fail, Status = %r\n", Status));
> +      break;
> +    }
> +  }
> +
> +  return Status;
> +}
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> new file mode 100644
> index 000000000000..3fef3dbc1c0d
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> @@ -0,0 +1,455 @@
> +/** @file
> +  Header file for NVMe function definitions
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef __OPAL_PASSWORD_NVME_MODE_H__
> +#define __OPAL_PASSWORD_NVME_MODE_H__
> +
> +
> +#include "OpalNvmeReg.h"
> +
> +#define NVME_MAX_SECTORS            0x10000
> +//
> +// QueueId
> +//
> +#define NVME_ADMIN_QUEUE            0x00
> +#define NVME_IO_QUEUE               0x01
> +
> +typedef struct {
> +  UINT8                             Opcode;
> +  UINT8                             FusedOperation;
> +    #define NORMAL_CMD              0x00
> +    #define FUSED_FIRST_CMD         0x01
> +    #define FUSED_SECOND_CMD        0x02
> +  UINT16                            Cid;
> +} NVME_CDW0;
> +
> +typedef struct {
> +  NVME_CDW0                         Cdw0;
> +  UINT8                             Flags;
> +    #define CDW10_VALID             0x01
> +    #define CDW11_VALID             0x02
> +    #define CDW12_VALID             0x04
> +    #define CDW13_VALID             0x08
> +    #define CDW14_VALID             0x10
> +    #define CDW15_VALID             0x20
> +  UINT32                            Nsid;
> +  UINT32                            Cdw10;
> +  UINT32                            Cdw11;
> +  UINT32                            Cdw12;
> +  UINT32                            Cdw13;
> +  UINT32                            Cdw14;
> +  UINT32                            Cdw15;
> +} NVM_EXPRESS_COMMAND;
> +
> +typedef struct {
> +  UINT32                            Cdw0;
> +  UINT32                            Cdw1;
> +  UINT32                            Cdw2;
> +  UINT32                            Cdw3;
> +} NVM_EXPRESS_RESPONSE;
> +
> +typedef struct {
> +  UINT64                            CommandTimeout;
> +  UINT64                            TransferBuffer;
> +  UINT32                            TransferLength;
> +  UINT64                            MetadataBuffer;
> +  UINT32                            MetadataLength;
> +  UINT8                             QueueId;
> +  NVM_EXPRESS_COMMAND               *NvmeCmd;
> +  NVM_EXPRESS_RESPONSE              *NvmeResponse;
> +} NVM_EXPRESS_PASS_THRU_COMMAND_PACKET;
> +
> +
> +#pragma pack(1)
> +
> +// Internal fields
> +typedef enum {
> +  NvmeStatusUnknown,
> +  NvmeStatusInit,
> +  NvmeStatusInuse,
> +  NvmeStatusMax,
> +} NVME_STATUS;
> +
> +typedef struct {
> +  UINT32                            Nbar;
> +  VOID                              *BaseMem;
> +  VOID                              *BaseMemMapping;
> +  BOOLEAN                           PollCancellation;
> +  UINT16                            NvmeInitWaitTime;
> +
> +  NVME_STATUS                       State;
> +  UINT8                             BusID;
> +  UINT8                             DeviceID;
> +  UINT8                             FuncID;
> +  UINTN                             PciBase;
> +
> +  UINT32                            Nsid;
> +  UINT64                            Nsuuid;
> +  UINT32                            BlockSize;
> +  EFI_LBA                           LastBlock;
> +
> +  //
> +  // Pointers to 4kB aligned submission & completion queues.
> +  //
> +  NVME_SQ
> *SqBuffer[NVME_MAX_IO_QUEUES];
> +  NVME_CQ
> *CqBuffer[NVME_MAX_IO_QUEUES];
> +  UINT16                            Cid[NVME_MAX_IO_QUEUES];
> +
> +  //
> +  // Submission and completion queue indices.
> +  //
> +  NVME_SQTDBL
> SqTdbl[NVME_MAX_IO_QUEUES];
> +  NVME_CQHDBL
> CqHdbl[NVME_MAX_IO_QUEUES];
> +  UINT8                             Pt[NVME_MAX_IO_QUEUES];
> +
> +  UINTN
> SqeCount[NVME_MAX_IO_QUEUES];
> +
> +  //
> +  // Nvme controller capabilities
> +  //
> +  NVME_CAP                          Cap;
> +
> +  //
> +  // pointer to identify controller Data
> +  //
> +  NVME_ADMIN_CONTROLLER_DATA        *ControllerData;
> +  NVME_ADMIN_NAMESPACE_DATA         *NamespaceData;
> +} NVME_CONTEXT;
> +
> +#pragma pack()
> +
> +/**
> +  Transfer MMIO Data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Transfer memory Data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Transfer memory data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +OpalPciWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Transfer MMIO data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +OpalPciRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Allocate transfer-related Data struct which is used at Nvme.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeAllocateResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Free allocated transfer-related Data struct which is used at NVMe.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +**/
> +VOID
> +EFIAPI
> +NvmeFreeResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Sends an NVM Express Command Packet to an NVM Express controller or
> namespace. This function supports
> +  both blocking I/O and nonblocking I/O. The blocking I/O functionality is
> required, and the nonblocking
> +  I/O functionality is optional.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which
> the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      ID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to
> which the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      UUID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in,out] Packet             - A pointer to the NVM Express HCI
> Command Packet to send to the NVMe namespace specified
> +                                      by NamespaceId.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Command Packet
> was sent by the host. TransferLength bytes were transferred
> +                                      to, or from DataBuffer.
> +  @retval EFI_NOT_READY             - The NVM Express Command Packet
> could not be sent because the controller is not ready. The caller
> +                                      may retry again later.
> +  @retval EFI_DEVICE_ERROR          - A device error occurred while
> attempting to send the NVM Express Command Packet.
> +  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of
> NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
> +                                      Express Command Packet was not
> sent, so no additional status information is available.
> +  @retval EFI_UNSUPPORTED           - The command described by the
> NVM Express Command Packet is not supported by the host adapter.
> +                                      The NVM Express Command
> Packet was not sent, so no additional status information is available.
> +  @retval EFI_TIMEOUT               - A timeout occurred while waiting
> for the NVM Express Command Packet to execute.
> +
> +**/
> +EFI_STATUS
> +NvmePassThru (
> +  IN     NVME_CONTEXT                         *Nvme,
> +  IN     UINT32                               NamespaceId,
> +  IN     UINT64                               NamespaceUuid,
> +  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
> +  );
> +
> +/**
> +  Waits until all NVME commands completed.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All NVME commands have
> completed
> +  @retval EFI_TIMEOUT               - Timeout occured
> +  @retval EFI_NOT_READY             - Not all NVME commands have
> completed
> +  @retval others                    - Error occurred on device side.
> +**/
> +EFI_STATUS
> +NvmeWaitAllComplete (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  );
> +
> +/**
> +  Initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> initialized successfully.
> +  @retval Others                    - A device error occurred while
> initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerInit (
> +  IN NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Un-initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> un-initialized successfully.
> +  @retval Others                    - A device error occurred while
> un-initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerExit (
> +  IN NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Check whether there are available command slots.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - Available command slot is found
> +  @retval EFI_NOT_READY             - No available command slot is found
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeHasFreeCmdSlot (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  );
> +
> +/**
> +  Check whether all command slots are clean.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All command slots are clean
> +  @retval EFI_NOT_READY             - Not all command slots are clean
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeIsAllCmdSlotClean (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  );
> +
> +/**
> +  Read sector Data from the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in,out] Buffer             - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeReadSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN OUT UINT64                            Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  );
> +
> +/**
> +  Write sector Data to the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWriteSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN UINT64                                Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  );
> +
> +/**
> +  Flushes all modified Data to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeFlush (
> +  IN NVME_CONTEXT                          *Nvme
> +  );
> +
> +/**
> +  Read some blocks from the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[out] Buffer                - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeRead (
> +  IN NVME_CONTEXT                  *Nvme,
> +  OUT UINT64                       Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  );
> +
> +/**
> +  Write some blocks to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWrite (
> +  IN NVME_CONTEXT                  *Nvme,
> +  IN UINT64                        Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  );
> +
> +/**
> +  Security send and receive commands.
> +
> +  @param[in]     Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in]     SendCommand            - The flag to indicate the
> command type, TRUE for Send command and FALSE for receive command
> +  @param[in]     SecurityProtocol       - Security Protocol
> +  @param[in]     SpSpecific             - Security Protocol Specific
> +  @param[in]     TransferLength         - Transfer Length of Buffer (in
> bytes) - always a multiple of 512
> +  @param[in,out] TransferBuffer         - Address of Data to transfer
> +
> +  @return EFI_SUCCESS               - Successfully create io submission
> queue.
> +  @return others                    - Fail to send/receive commands.
> +
> +**/
> +EFI_STATUS
> +NvmeSecuritySendReceive (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN BOOLEAN                               SendCommand,
> +  IN UINT8                                 SecurityProtocol,
> +  IN UINT16                                SpSpecific,
> +  IN UINTN                                 TransferLength,
> +  IN OUT VOID                              *TransferBuffer
> +  );
> +
> +#endif
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> new file mode 100644
> index 000000000000..03376b9e6c9a
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> @@ -0,0 +1,815 @@
> +/** @file
> +  Header file for Registers and Structure definitions
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +#ifndef __OPAL_PASSWORD_NVME_REG_H__
> +#define __OPAL_PASSWORD_NVME_REG_H__
> +
> +//
> +// PCI Header for PCIe root port configuration
> +//
> +#define NVME_PCIE_PCICMD                         0x04
> +#define NVME_PCIE_BNUM                           0x18
> +#define NVME_PCIE_SEC_BNUM                       0x19
> +#define NVME_PCIE_IOBL                           0x1C
> +#define NVME_PCIE_MBL                            0x20
> +#define NVME_PCIE_PMBL                           0x24
> +#define NVME_PCIE_PMBU32                         0x28
> +#define NVME_PCIE_PMLU32                         0x2C
> +#define NVME_PCIE_INTR                           0x3C
> +
> +//
> +// NVMe related definitions
> +//
> +#define PCI_CLASS_MASS_STORAGE_NVM                0x08  // mass
> storage sub-class non-volatile memory.
> +#define PCI_IF_NVMHCI                             0x02  // mass
> storage programming interface NVMHCI.
> +
> +#define NVME_ASQ_SIZE                                    1     //
> Number of admin submission queue entries, which is 0-based
> +#define NVME_ACQ_SIZE                                    1     //
> Number of admin completion queue entries, which is 0-based
> +
> +#define NVME_CSQ_SIZE                                    63     //
> Number of I/O submission queue entries, which is 0-based
> +#define NVME_CCQ_SIZE                                    63     //
> Number of I/O completion queue entries, which is 0-based
> +
> +#define NVME_MAX_IO_QUEUES                               2     //
> Number of I/O queues supported by the driver, 1 for AQ, 1 for CQ
> +
> +#define NVME_CSQ_DEPTH
> (NVME_CSQ_SIZE+1)
> +#define NVME_CCQ_DEPTH
> (NVME_CCQ_SIZE+1)
> +#define NVME_PRP_SIZE                                    (4)    //
> Pages of PRP list
> +
> +#define NVME_CONTROLLER_ID                               0
> +
> +//
> +// Time out Value for Nvme transaction execution
> +//
> +#define NVME_GENERIC_TIMEOUT                             5000000
> ///< us
> +#define NVME_CMD_WAIT                                    100
> ///< us
> +#define NVME_CMD_TIMEOUT
> 20000000  ///< us
> +
> +
> +
> +#define NVME_MEM_MAX_SIZE \
> +  (( \
> +  1                                         /* Controller Data */ +  \
> +  1                                         /* Identify Data */   +  \
> +  1                                         /* ASQ */             +
> \
> +  1                                         /* ACQ */             +
> \
> +  1                                         /* SQs */             +
> \
> +  1                                         /* CQs */             +
> \
> +  NVME_PRP_SIZE * NVME_CSQ_DEPTH            /* PRPs */
> +  \
> +  1                                         /* SECURITY */
> \
> +  ) * EFI_PAGE_SIZE)
> +
> +
> +//
> +// controller register offsets
> +//
> +#define NVME_CAP_OFFSET          0x0000  // Controller Capabilities
> +#define NVME_VER_OFFSET          0x0008  // Version
> +#define NVME_INTMS_OFFSET        0x000c  // Interrupt Mask Set
> +#define NVME_INTMC_OFFSET        0x0010  // Interrupt Mask Clear
> +#define NVME_CC_OFFSET           0x0014  // Controller Configuration
> +#define NVME_CSTS_OFFSET         0x001c  // Controller Status
> +#define NVME_AQA_OFFSET          0x0024  // Admin Queue Attributes
> +#define NVME_ASQ_OFFSET          0x0028  // Admin Submission Queue
> Base Address
> +#define NVME_ACQ_OFFSET          0x0030  // Admin Completion Queue
> Base Address
> +#define NVME_SQ0_OFFSET          0x1000  // Submission Queue 0
> (admin) Tail Doorbell
> +#define NVME_CQ0_OFFSET          0x1004  // Completion Queue 0
> (admin) Head Doorbell
> +
> +//
> +// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD))
> +// Get the doorbell stride bit shift Value from the controller capabilities.
> +//
> +#define NVME_SQTDBL_OFFSET(QID, DSTRD)    0x1000 + ((2 * (QID)) * (4
> << (DSTRD)))       // Submission Queue y (NVM) Tail Doorbell
> +#define NVME_CQHDBL_OFFSET(QID, DSTRD)    0x1000 + (((2 * (QID)) + 1)
> * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell
> +
> +
> +#pragma pack(1)
> +
> +//
> +// 3.1.1 Offset 00h: CAP - Controller Capabilities
> +//
> +typedef struct {
> +  UINT16 Mqes;      // Maximum Queue Entries Supported
> +  UINT8  Cqr:1;     // Contiguous Queues Required
> +  UINT8  Ams:2;     // Arbitration Mechanism Supported
> +  UINT8  Rsvd1:5;
> +  UINT8  To;        // Timeout
> +  UINT16 Dstrd:4;
> +  UINT16 Rsvd2:1;
> +  UINT16 Css:4;     // Command Sets Supported
> +  UINT16 Rsvd3:7;
> +  UINT8  Mpsmin:4;
> +  UINT8  Mpsmax:4;
> +  UINT8  Rsvd4;
> +} NVME_CAP;
> +
> +//
> +// 3.1.2 Offset 08h: VS - Version
> +//
> +typedef struct {
> +  UINT16 Mnr;       // Minor version number
> +  UINT16 Mjr;       // Major version number
> +} NVME_VER;
> +
> +//
> +// 3.1.5 Offset 14h: CC - Controller Configuration
> +//
> +typedef struct {
> +  UINT16 En:1;       // Enable
> +  UINT16 Rsvd1:3;
> +  UINT16 Css:3;      // Command Set Selected
> +  UINT16 Mps:4;      // Memory Page Size
> +  UINT16 Ams:3;      // Arbitration Mechanism Selected
> +  UINT16 Shn:2;      // Shutdown Notification
> +  UINT8  Iosqes:4;   // I/O Submission Queue Entry Size
> +  UINT8  Iocqes:4;   // I/O Completion Queue Entry Size
> +  UINT8  Rsvd2;
> +} NVME_CC;
> +
> +//
> +// 3.1.6 Offset 1Ch: CSTS - Controller Status
> +//
> +typedef struct {
> +  UINT32 Rdy:1;      // Ready
> +  UINT32 Cfs:1;      // Controller Fatal Status
> +  UINT32 Shst:2;     // Shutdown Status
> +  UINT32 Nssro:1;    // NVM Subsystem Reset Occurred
> +  UINT32 Rsvd1:27;
> +} NVME_CSTS;
> +
> +//
> +// 3.1.8 Offset 24h: AQA - Admin Queue Attributes
> +//
> +typedef struct {
> +  UINT16 Asqs:12;    // Submission Queue Size
> +  UINT16 Rsvd1:4;
> +  UINT16 Acqs:12;    // Completion Queue Size
> +  UINT16 Rsvd2:4;
> +} NVME_AQA;
> +
> +//
> +// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address
> +//
> +#define NVME_ASQ      UINT64
> +
> +//
> +// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address
> +//
> +#define NVME_ACQ      UINT64
> +
> +//
> +// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission
> Queue y Tail Doorbell
> +//
> +typedef struct {
> +  UINT16 Sqt;
> +  UINT16 Rsvd1;
> +} NVME_SQTDBL;
> +
> +//
> +// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL -
> Completion Queue y Head Doorbell
> +//
> +typedef struct {
> +  UINT16 Cqh;
> +  UINT16 Rsvd1;
> +} NVME_CQHDBL;
> +
> +//
> +// NVM command set structures
> +//
> +// Read Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting Sector Address */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Sectors */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Af:4;                /* Access Frequency */
> +  UINT32 Al:2;                /* Access Latency */
> +  UINT32 Sr:1;                /* Sequential Request */
> +  UINT32 In:1;                /* Incompressible */
> +  UINT32 Rsvd2:24;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag
> */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Elbat;               /* Expected Logical Block Application Tag */
> +  UINT16 Elbatm;              /* Expected Logical Block Application Tag
> Mask */
> +} NVME_READ;
> +
> +//
> +// Write Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting Sector Address */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Sectors */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Af:4;                /* Access Frequency */
> +  UINT32 Al:2;                /* Access Latency */
> +  UINT32 Sr:1;                /* Sequential Request */
> +  UINT32 In:1;                /* Incompressible */
> +  UINT32 Rsvd2:24;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Lbat;                /* Logical Block Application Tag */
> +  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
> +} NVME_WRITE;
> +
> +//
> +// Flush
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Flush;               /* Flush */
> +} NVME_FLUSH;
> +
> +//
> +// Write Uncorrectable command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting LBA */
> +  //
> +  // CDW 12
> +  //
> +  UINT32 Nlb:16;              /* Number of  Logical Blocks */
> +  UINT32 Rsvd1:16;
> +} NVME_WRITE_UNCORRECTABLE;
> +
> +//
> +// Write Zeroes command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting LBA */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Logical Blocks */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Rsvd2;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Lbat;                /* Logical Block Application Tag */
> +  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
> +} NVME_WRITE_ZEROES;
> +
> +//
> +// Compare command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting LBA */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Logical Blocks */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Rsvd2;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag
> */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Elbat;               /* Expected Logical Block Application Tag */
> +  UINT16 Elbatm;              /* Expected Logical Block Application Tag
> Mask */
> +} NVME_COMPARE;
> +
> +typedef union {
> +  NVME_READ                   Read;
> +  NVME_WRITE                  Write;
> +  NVME_FLUSH                  Flush;
> +  NVME_WRITE_UNCORRECTABLE    WriteUncorrectable;
> +  NVME_WRITE_ZEROES           WriteZeros;
> +  NVME_COMPARE                Compare;
> +} NVME_CMD;
> +
> +typedef struct {
> +  UINT16 Mp;                /* Maximum Power */
> +  UINT8  Rsvd1;             /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Mps:1;             /* Max Power Scale */
> +  UINT8  Nops:1;            /* Non-Operational State */
> +  UINT8  Rsvd2:6;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Enlat;             /* Entry Latency */
> +  UINT32 Exlat;             /* Exit Latency */
> +  UINT8  Rrt:5;             /* Relative Read Throughput */
> +  UINT8  Rsvd3:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rrl:5;             /* Relative Read Leatency */
> +  UINT8  Rsvd4:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rwt:5;             /* Relative Write Throughput */
> +  UINT8  Rsvd5:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rwl:5;             /* Relative Write Leatency */
> +  UINT8  Rsvd6:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rsvd7[16];         /* Reserved as of Nvm Express 1.1 Spec */
> +} NVME_PSDESCRIPTOR;
> +
> +//
> +//  Identify Controller Data
> +//
> +typedef struct {
> +  //
> +  // Controller Capabilities and Features 0-255
> +  //
> +  UINT16 Vid;                 /* PCI Vendor ID */
> +  UINT16 Ssvid;               /* PCI sub-system vendor ID */
> +  UINT8  Sn[20];              /* Produce serial number */
> +
> +  UINT8  Mn[40];              /* Proeduct model number */
> +  UINT8  Fr[8];               /* Firmware Revision */
> +  UINT8  Rab;                 /* Recommended Arbitration Burst */
> +  UINT8  Ieee_oiu[3];         /* Organization Unique Identifier */
> +  UINT8  Cmic;                /* Multi-interface Capabilities */
> +  UINT8  Mdts;                /* Maximum Data Transfer Size */
> +  UINT8  Cntlid[2];           /* Controller ID */
> +  UINT8  Rsvd1[176];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // Admin Command Set Attributes
> +  //
> +  UINT16 Oacs;                /* Optional Admin Command Support */
> +  UINT8  Acl;                 /* Abort Command Limit */
> +  UINT8  Aerl;                /* Async Event Request Limit */
> +  UINT8  Frmw;                /* Firmware updates */
> +  UINT8  Lpa;                 /* Log Page Attributes */
> +  UINT8  Elpe;                /* Error Log Page Entries */
> +  UINT8  Npss;                /* Number of Power States Support */
> +  UINT8  Avscc;               /* Admin Vendor Specific Command
> Configuration */
> +  UINT8  Apsta;               /* Autonomous Power State Transition
> Attributes */
> +  UINT8  Rsvd2[246];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // NVM Command Set Attributes
> +  //
> +  UINT8  Sqes;                /* Submission Queue Entry Size */
> +  UINT8  Cqes;                /* Completion Queue Entry Size */
> +  UINT16 Rsvd3;               /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Nn;                  /* Number of Namespaces */
> +  UINT16 Oncs;                /* Optional NVM Command Support */
> +  UINT16 Fuses;               /* Fused Operation Support */
> +  UINT8  Fna;                 /* Format NVM Attributes */
> +  UINT8  Vwc;                 /* Volatile Write Cache */
> +  UINT16 Awun;                /* Atomic Write Unit Normal */
> +  UINT16 Awupf;               /* Atomic Write Unit Power Fail */
> +  UINT8  Nvscc;               /* NVM Vendor Specific Command
> Configuration */
> +  UINT8  Rsvd4;               /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT16 Acwu;                /* Atomic Compare & Write Unit */
> +  UINT16 Rsvd5;               /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Sgls;                /* SGL Support  */
> +  UINT8  Rsvd6[164];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // I/O Command set Attributes
> +  //
> +  UINT8 Rsvd7[1344];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // Power State Descriptors
> +  //
> +  NVME_PSDESCRIPTOR PsDescriptor[32];
> +
> +  UINT8  VendorData[1024];    /* Vendor specific Data */
> +} NVME_ADMIN_CONTROLLER_DATA;
> +
> +typedef struct {
> +  UINT16        Security  : 1;    /* supports security send/receive
> commands */
> +  UINT16        Format    : 1;    /* supports format nvm command */
> +  UINT16        Firmware  : 1;    /* supports firmware
> activate/download commands */
> +  UINT16        Oacs_rsvd : 13;
> + } OACS; // optional admin command support:
> NVME_ADMIN_CONTROLLER_DATA.Oacs
> +
> +typedef struct {
> +  UINT16 Ms;                /* Metadata Size */
> +  UINT8  Lbads;             /* LBA Data Size */
> +  UINT8  Rp:2;              /* Relative Performance */
> +    #define LBAF_RP_BEST      00b
> +    #define LBAF_RP_BETTER    01b
> +    #define LBAF_RP_GOOD      10b
> +    #define LBAF_RP_DEGRADED  11b
> +  UINT8  Rsvd1:6;           /* Reserved as of Nvm Express 1.1 Spec */
> +} NVME_LBAFORMAT;
> +
> +//
> +// Identify Namespace Data
> +//
> +typedef struct {
> +  //
> +  // NVM Command Set Specific
> +  //
> +  UINT64 Nsze;                /* Namespace Size (total number of blocks
> in formatted namespace) */
> +  UINT64 Ncap;                /* Namespace Capacity (max number of
> logical blocks) */
> +  UINT64 Nuse;                /* Namespace Utilization */
> +  UINT8  Nsfeat;              /* Namespace Features */
> +  UINT8  Nlbaf;               /* Number of LBA Formats */
> +  UINT8  Flbas;               /* Formatted LBA Size */
> +  UINT8  Mc;                  /* Metadata Capabilities */
> +  UINT8  Dpc;                 /* End-to-end Data Protection capabilities
> */
> +  UINT8  Dps;                 /* End-to-end Data Protection Type Settings
> */
> +  UINT8  Nmic;                /* Namespace Multi-path I/O and
> Namespace Sharing Capabilities */
> +  UINT8  Rescap;              /* Reservation Capabilities */
> +  UINT8  Rsvd1[88];           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT64 Eui64;               /* IEEE Extended Unique Identifier */
> +  //
> +  // LBA Format
> +  //
> +  NVME_LBAFORMAT LbaFormat[16];
> +
> +  UINT8 Rsvd2[192];           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8 VendorData[3712];     /* Vendor specific Data */
> +} NVME_ADMIN_NAMESPACE_DATA;
> +
> +//
> +// NvmExpress Admin Identify Cmd
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Cns:2;
> +  UINT32 Rsvd1:30;
> +} NVME_ADMIN_IDENTIFY;
> +
> +//
> +// NvmExpress Admin Create I/O Completion Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Qid:16;              /* Queue Identifier */
> +  UINT32 Qsize:16;            /* Queue Size */
> +
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Pc:1;                /* Physically Contiguous */
> +  UINT32 Ien:1;               /* Interrupts Enabled */
> +  UINT32 Rsvd1:14;            /* reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Iv:16;               /* Interrupt Vector */
> +} NVME_ADMIN_CRIOCQ;
> +
> +//
> +// NvmExpress Admin Create I/O Submission Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Qid:16;              /* Queue Identifier */
> +  UINT32 Qsize:16;            /* Queue Size */
> +
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Pc:1;                /* Physically Contiguous */
> +  UINT32 Qprio:2;             /* Queue Priority */
> +  UINT32 Rsvd1:13;            /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Cqid:16;             /* Completion Queue ID */
> +} NVME_ADMIN_CRIOSQ;
> +
> +//
> +// NvmExpress Admin Delete I/O Completion Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT16 Qid;
> +  UINT16 Rsvd1;
> +} NVME_ADMIN_DEIOCQ;
> +
> +//
> +// NvmExpress Admin Delete I/O Submission Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT16 Qid;
> +  UINT16 Rsvd1;
> +} NVME_ADMIN_DEIOSQ;
> +
> +//
> +// NvmExpress Admin Security Send
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Resv:8;              /* Reserve */
> +  UINT32 Spsp:16;             /* SP Specific */
> +  UINT32 Secp:8;              /* Security Protocol */
> +
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Tl;                  /* Transfer Length */
> +} NVME_ADMIN_SECSEND;
> +
> +//
> +// NvmExpress Admin Abort Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Sqid:16;             /* Submission Queue identifier */
> +  UINT32 Cid:16;              /* Command Identifier */
> +} NVME_ADMIN_ABORT;
> +
> +//
> +// NvmExpress Admin Firmware Activate Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Fs:3;                /* Submission Queue identifier */
> +  UINT32 Aa:2;                /* Command Identifier */
> +  UINT32 Rsvd1:27;
> +} NVME_ADMIN_FIRMWARE_ACTIVATE;
> +
> +//
> +// NvmExpress Admin Firmware Image Download Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Numd;                /* Number of Dwords */
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Ofst;                /* Offset */
> +} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD;
> +
> +//
> +// NvmExpress Admin Get Features Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Fid:8;                /* Feature Identifier */
> +  UINT32 Sel:3;                /* Select */
> +  UINT32 Rsvd1:21;
> +} NVME_ADMIN_GET_FEATURES;
> +
> +//
> +// NvmExpress Admin Get Log Page Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Lid:8;               /* Log Page Identifier */
> +    #define LID_ERROR_INFO
> +    #define LID_SMART_INFO
> +    #define LID_FW_SLOT_INFO
> +  UINT32 Rsvd1:8;
> +  UINT32 Numd:12;             /* Number of Dwords */
> +  UINT32 Rsvd2:4;             /* Reserved as of Nvm Express 1.1 Spec */
> +} NVME_ADMIN_GET_LOG_PAGE;
> +
> +//
> +// NvmExpress Admin Set Features Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Fid:8;               /* Feature Identifier */
> +  UINT32 Rsvd1:23;
> +  UINT32 Sv:1;                /* Save */
> +} NVME_ADMIN_SET_FEATURES;
> +
> +//
> +// NvmExpress Admin Format NVM Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Lbaf:4;              /* LBA Format */
> +  UINT32 Ms:1;                /* Metadata Settings */
> +  UINT32 Pi:3;                /* Protection Information */
> +  UINT32 Pil:1;               /* Protection Information Location */
> +  UINT32 Ses:3;               /* Secure Erase Settings */
> +  UINT32 Rsvd1:20;
> +} NVME_ADMIN_FORMAT_NVM;
> +
> +//
> +// NvmExpress Admin Security Receive Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Rsvd1:8;
> +  UINT32 Spsp:16;             /* SP Specific */
> +  UINT32 Secp:8;              /* Security Protocol */
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Al;                  /* Allocation Length */
> +} NVME_ADMIN_SECURITY_RECEIVE;
> +
> +//
> +// NvmExpress Admin Security Send Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Rsvd1:8;
> +  UINT32 Spsp:16;             /* SP Specific */
> +  UINT32 Secp:8;              /* Security Protocol */
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Tl;                  /* Transfer Length */
> +} NVME_ADMIN_SECURITY_SEND;
> +
> +typedef union {
> +  NVME_ADMIN_IDENTIFY                   Identify;
> +  NVME_ADMIN_CRIOCQ                     CrIoCq;
> +  NVME_ADMIN_CRIOSQ                     CrIoSq;
> +  NVME_ADMIN_DEIOCQ                     DeIoCq;
> +  NVME_ADMIN_DEIOSQ                     DeIoSq;
> +  NVME_ADMIN_ABORT                      Abort;
> +  NVME_ADMIN_FIRMWARE_ACTIVATE          Activate;
> +  NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD
> FirmwareImageDownload;
> +  NVME_ADMIN_GET_FEATURES               GetFeatures;
> +  NVME_ADMIN_GET_LOG_PAGE               GetLogPage;
> +  NVME_ADMIN_SET_FEATURES               SetFeatures;
> +  NVME_ADMIN_FORMAT_NVM                 FormatNvm;
> +  NVME_ADMIN_SECURITY_RECEIVE           SecurityReceive;
> +  NVME_ADMIN_SECURITY_SEND              SecuritySend;
> +} NVME_ADMIN_CMD;
> +
> +typedef struct {
> +  UINT32 Cdw10;
> +  UINT32 Cdw11;
> +  UINT32 Cdw12;
> +  UINT32 Cdw13;
> +  UINT32 Cdw14;
> +  UINT32 Cdw15;
> +} NVME_RAW;
> +
> +typedef union {
> +  NVME_ADMIN_CMD Admin;   // Union of Admin commands
> +  NVME_CMD       Nvm;     // Union of Nvm commands
> +  NVME_RAW       Raw;
> +} NVME_PAYLOAD;
> +
> +//
> +// Submission Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 0, Common to all comnmands
> +  //
> +  UINT8  Opc;               // Opcode
> +  UINT8  Fuse:2;            // Fused Operation
> +  UINT8  Rsvd1:5;
> +  UINT8  Psdt:1;            // PRP or SGL for Data Transfer
> +  UINT16 Cid;               // Command Identifier
> +
> +  //
> +  // CDW 1
> +  //
> +  UINT32 Nsid;              // Namespace Identifier
> +
> +  //
> +  // CDW 2,3
> +  //
> +  UINT64 Rsvd2;
> +
> +  //
> +  // CDW 4,5
> +  //
> +  UINT64 Mptr;              // Metadata Pointer
> +
> +  //
> +  // CDW 6-9
> +  //
> +  UINT64 Prp[2];            // First and second PRP entries
> +
> +  NVME_PAYLOAD Payload;
> +
> +} NVME_SQ;
> +
> +//
> +// Completion Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 0
> +  //
> +  UINT32 Dword0;
> +  //
> +  // CDW 1
> +  //
> +  UINT32 Rsvd1;
> +  //
> +  // CDW 2
> +  //
> +  UINT16 Sqhd;              // Submission Queue Head Pointer
> +  UINT16 Sqid;              // Submission Queue Identifier
> +  //
> +  // CDW 3
> +  //
> +  UINT16 Cid;               // Command Identifier
> +  UINT16 Pt:1;              // Phase Tag
> +  UINT16 Sc:8;              // Status Code
> +  UINT16 Sct:3;             // Status Code Type
> +  UINT16 Rsvd2:2;
> +  UINT16 Mo:1;              // More
> +  UINT16 Dnr:1;             // Retry
> +} NVME_CQ;
> +
> +//
> +// Nvm Express Admin cmd opcodes
> +//
> +#define NVME_ADMIN_DELIOSQ_OPC               0
> +#define NVME_ADMIN_CRIOSQ_OPC                1
> +#define NVME_ADMIN_DELIOCQ_OPC               4
> +#define NVME_ADMIN_CRIOCQ_OPC                5
> +#define NVME_ADMIN_IDENTIFY_OPC              6
> +#define NVME_ADMIN_SECURITY_SEND_OPC         0x81
> +#define NVME_ADMIN_SECURITY_RECV_OPC         0x82
> +
> +#define NVME_IO_FLUSH_OPC                    0
> +#define NVME_IO_WRITE_OPC                    1
> +#define NVME_IO_READ_OPC                     2
> +
> +//
> +// Offset from the beginning of private Data queue Buffer
> +//
> +#define NVME_ASQ_BUF_OFFSET                  EFI_PAGE_SIZE
> +
> +#pragma pack()
> +
> +#endif
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> new file mode 100644
> index 000000000000..17fda410dc54
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> @@ -0,0 +1,65 @@
> +/** @file
> +  Opal Password common header file.
> +
> +Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_PASSWORD_COMMON_H_
> +#define _OPAL_PASSWORD_COMMON_H_
> +
> +#define OPAL_DEVICE_TYPE_UNKNOWN    0x0
> +#define OPAL_DEVICE_TYPE_ATA        0x1
> +#define OPAL_DEVICE_TYPE_NVME       0x2
> +
> +typedef struct {
> +  UINT16            Segment;
> +  UINT8             Bus;
> +  UINT8             Device;
> +  UINT8             Function;
> +  UINT8             Reserved;
> +} OPAL_PCI_DEVICE;
> +
> +typedef struct {
> +  UINT16            Length;
> +  OPAL_PCI_DEVICE   Device;
> +  UINT8             PasswordLength;
> +  UINT8             Password[32];
> +  UINT16            OpalBaseComId;
> +  UINT32            BarAddr;
> +} OPAL_DEVICE_COMMON;
> +
> +#define OPAL_DEVICE_ATA_GUID { 0xcb934fe1, 0xb8cd, 0x46b1, { 0xa0, 0x58,
> 0xdd, 0xcb, 0x7, 0xb7, 0xb4, 0x17 } }
> +
> +typedef struct {
> +  UINT16            Length;
> +  OPAL_PCI_DEVICE   Device;
> +  UINT8             PasswordLength;
> +  UINT8             Password[32];
> +  UINT16            OpalBaseComId;
> +  UINT32            BarAddr;
> +  UINT16            Port;
> +  UINT16            PortMultiplierPort;
> +} OPAL_DEVICE_ATA;
> +
> +#define OPAL_DEVICE_NVME_GUID { 0xde116925, 0xaf7f, 0x42d9, { 0x83,
> 0xc0, 0x7e, 0xd6, 0x26, 0x59, 0x0, 0xfb } }
> +
> +typedef struct {
> +  UINT16            Length;
> +  OPAL_PCI_DEVICE   Device;
> +  UINT8             PasswordLength;
> +  UINT8             Password[32];
> +  UINT16            OpalBaseComId;
> +  UINT32            BarAddr;
> +  UINT32            NvmeNamespaceId;
> +  OPAL_PCI_DEVICE   PciBridgeNode[0];
> +} OPAL_DEVICE_NVME;
> +
> +#endif // _OPAL_PASSWORD_COMMON_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> new file mode 100644
> index 000000000000..0ac550a72873
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> @@ -0,0 +1,81 @@
> +## @file
> +#  This is a OpalPasswordDxe driver.
> +#
> +#  This module is used to Management the Opal feature
> +#  for Opal supported devices.
> +#
> +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be found
> at
> +# http://opensource.org/licenses/bsd-license.php
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +[Defines]
> +  INF_VERSION                    = 0x00010007
> +  BASE_NAME                      = OpalPasswordDxe
> +  FILE_GUID                      =
> E3E4048D-6C0C-43E4-AE1C-FFB579D8EF41
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = EfiDriverEntryPoint
> +  UNLOAD_IMAGE                   = OpalEfiDriverUnload
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
> +#
> +
> +[Sources]
> +  OpalDriver.c
> +  OpalDriver.h
> +  OpalPasswordCommon.h
> +  OpalHii.c
> +  OpalHii.h
> +  OpalHiiCallbacks.c
> +  OpalHiiFormValues.h
> +  OpalHiiFormStrings.uni
> +  OpalPasswordForm.vfr
> +  ComponentName.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  SecurityPkg/SecurityPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiRuntimeServicesTableLib
> +  DxeServicesTableLib
> +  UefiHiiServicesLib
> +  BaseMemoryLib
> +  DebugLib
> +  HiiLib
> +  PrintLib
> +  DevicePathLib
> +  UefiLib
> +  TcgStorageOpalLib
> +  Tcg2PhysicalPresenceLib
> +  PciLib
> +  S3BootScriptLib
> +  LockBoxLib
> +
> +[Protocols]
> +  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
> +  gEfiStorageSecurityCommandProtocolGuid        ## CONSUMES
> +  gEfiComponentNameProtocolGuid                 ## PRODUCES
> +  gEfiComponentName2ProtocolGuid                ## PRODUCES
> +  gEfiBlockIoProtocolGuid                       ## CONSUMES
> +  gEfiPciIoProtocolGuid                         ## CONSUMES
> +  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
> ## Event
> +
> +[Depex]
> +  gEfiHiiStringProtocolGuid AND gEfiHiiDatabaseProtocolGuid
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
> new file mode 100644
> index 000000000000..cba388723305
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
> @@ -0,0 +1,309 @@
> +/** @file
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +#include "OpalHiiFormValues.h"
> +
> +
> +#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
> +  { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4,
> 0xe } }
> +
> +formset
> +  guid      = SETUP_FORMSET_GUID,
> +  title     = STRING_TOKEN(STR_OPAL),
> +  help      = STRING_TOKEN(STR_FORM_SET_HELP),
> +  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
> +
> +  // Define a Buffer Storage (EFI_IFR_VARSTORE) that will be filled
> +  // out initially through extractConfig call
> +  varstore OPAL_HII_CONFIGURATION,           // This is the Data
> structure type
> +    name  = OpalHiiConfig,                   // Define referenced name
> in vfr
> +    guid  = SETUP_VARIABLE_GUID;             // GUID of this Buffer
> storage
> +
> +form formid = FORMID_VALUE_MAIN_MENU,
> +    title  = STRING_TOKEN(STR_OPAL);
> +
> +    //CONFIG_VARIABLE(HII_KEY(HII_KEY_ID_VAR_SUPPORTED_DISKS),
> SupportedDisks, 0x0, 0xFFFF);
> +    suppressif TRUE;
> +        numeric
> +            name    = SupportedDisks,
> +            varid   = OpalHiiConfig.SupportedDisks,
> +            prompt  = STRING_TOKEN(STR_NULL),
> +            help    = STRING_TOKEN(STR_NULL),
> +            flags   = INTERACTIVE,
> +            key     = 0x8002,
> +            minimum = 0x0,
> +            maximum = 0xFFFF,
> +        endnumeric;
> +    endif;
> +
> +    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    subtitle text = STRING_TOKEN(STR_MAIN_PHY_DISKS_LBL);
> +
> +    //DISK( 0 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x1 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8001;
> +    endif;
> +
> +    //DISK( 1 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x2 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8101;
> +    endif;
> +
> +    //DISK( 2 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x4 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8201;
> +    endif;
> +
> +    //DISK( 3 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x8 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8301;
> +    endif;
> +
> +    //DISK( 4 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x10 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8401;
> +    endif;
> +
> +    //DISK( 5 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x20 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8501;
> +    endif;
> +
> +    //No disks on system
> +    suppressif ideqval OpalHiiConfig.NumDisks > 0;
> +        text
> +            help    = STRING_TOKEN(STR_NULL),
> +            text    =
> STRING_TOKEN(STR_MAIN_NO_DISKS_PRESENT_LBL);
> +    endif;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    grayoutif TRUE;
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS);
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS1);
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS2);
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS3);
> +      subtitle text = STRING_TOKEN(STR_NULL);
> +    endif;
> +
> +    oneof varid   = OpalHiiConfig.EnableBlockSid,
> +      questionid  = 0x8004,
> +      prompt      = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID),
> +      help        =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_HELP),
> +      flags       = INTERACTIVE,
> +      option text = STRING_TOKEN(STR_NONE), value = 0, flags = DEFAULT |
> MANUFACTURING | RESET_REQUIRED;
> +      option text = STRING_TOKEN(STR_ENABLED), value = 1, flags =
> RESET_REQUIRED;
> +      option text = STRING_TOKEN(STR_DISABLED), value = 2, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), value = 3, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), value = 4, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), value = 5, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), value = 6, flags =
> RESET_REQUIRED;
> +    endoneof;
> +
> +
> +
> +endform;  // MAIN MENU FORM
> +
> +//
> +/////////////////   DISK INFO FORM   /////////////////
> +//
> +form formid = FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +    title  = STRING_TOKEN(STR_OPAL);
> +
> +    suppressif TRUE;
> +        numeric
> +            name    = SelectedDiskAvailableActions,
> +            varid   = OpalHiiConfig.SelectedDiskAvailableActions,
> +            prompt  = STRING_TOKEN(STR_NULL),
> +            help    = STRING_TOKEN(STR_NULL),
> +            flags   = INTERACTIVE,
> +            key     = 0x8003,
> +            minimum = 0x0,
> +            maximum = 0xFFFF,
> +        endnumeric;
> +    endif;
> +
> +    suppressif TRUE;
> +        checkbox varid = OpalHiiConfig.KeepUserDataForced,
> +            prompt = STRING_TOKEN(STR_NULL),
> +            help = STRING_TOKEN(STR_NULL),
> +        endcheckbox;
> +    endif;
> +
> +    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    text
> +        help   = STRING_TOKEN(STR_NULL),
> +        text   = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    subtitle text = STRING_TOKEN(STR_OPAL_REQUESTS_LBL);
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_SET_ADMIN_PWD ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.SetAdminPwd,
> +            prompt  =
> STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8005,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_SET_USER_PWD ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.SetUserPwd,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8006,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_SECURE_ERASE ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.SecureErase,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8007,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_REVERT ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetAdminPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SecureErase == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.Revert,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_REVERT),
> +            help    = STRING_TOKEN(STR_DISK_INFO_REVERT_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8008,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ideqval OpalHiiConfig.OpalRequest.Revert == 0;
> +        grayoutif ideqval OpalHiiConfig.KeepUserDataForced == 1;
> +            checkbox varid = OpalHiiConfig.OpalRequest.KeepUserData,
> +                prompt  =
> STRING_TOKEN(STR_KEEP_USER_DATA_PROMPT),
> +                help    = STRING_TOKEN(STR_KEEP_USER_DATA_HELP),
> +                flags   = INTERACTIVE | RESET_REQUIRED,
> +                key     = 0x8009,
> +            endcheckbox;
> +        endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_PSID_REVERT ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetAdminPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SecureErase == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.EnableFeature == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.PsidRevert,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_PSID_REVERT_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x800A,
> +         endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_DISABLE_USER ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.DisableUser,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_DISABLE_USER),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_DISABLE_USER_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x800B,
> +         endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_ENABLE_FEATURE ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.EnableFeature,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x800C,
> +        endcheckbox;
> +    endif;
> +    endif;
> +
> +endform;  // DISK INFO FORM
> +
> +endformset;
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> new file mode 100644
> index 000000000000..1788b2ad3339
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> @@ -0,0 +1,940 @@
> +/** @file
> +  Opal Password PEI driver which is used to unlock Opal Password for S3.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalPasswordPei.h"
> +
> +EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
> +EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
> +
> +#define OPAL_PCIE_ROOTPORT_SAVESIZE               (0x40)
> +#define STORE_INVALID_ROOTPORT_INDEX              ((UINT8) -1)
> +
> +/**
> +  Get IOMMU PPI.
> +
> +  @return Pointer to IOMMU PPI.
> +
> +**/
> +EDKII_IOMMU_PPI *
> +GetIoMmu (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EDKII_IOMMU_PPI           *IoMmu;
> +
> +  IoMmu = NULL;
> +  Status = PeiServicesLocatePpi (
> +             &gEdkiiIoMmuPpiGuid,
> +             0,
> +             NULL,
> +             (VOID **) &IoMmu
> +             );
> +  if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
> +    return IoMmu;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Allocates pages that are suitable for an OperationBusMasterCommonBuffer
> or
> +  OperationBusMasterCommonBuffer64 mapping.
> +
> +  @param Pages                  The number of pages to allocate.
> +  @param HostAddress            A pointer to store the base system
> memory address of the
> +                                allocated range.
> +  @param DeviceAddress          The resulting map address for the bus
> master PCI controller to use to
> +                                access the hosts HostAddress.
> +  @param Mapping                A resulting value to pass to Unmap().
> +
> +  @retval EFI_SUCCESS           The requested memory pages were
> allocated.
> +  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal
> attribute bits are
> +                                MEMORY_WRITE_COMBINE and
> MEMORY_CACHED.
> +  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be
> allocated.
> +
> +**/
> +EFI_STATUS
> +IoMmuAllocateBuffer (
> +  IN UINTN                  Pages,
> +  OUT VOID                  **HostAddress,
> +  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
> +  OUT VOID                  **Mapping
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINTN                 NumberOfBytes;
> +  EFI_PHYSICAL_ADDRESS  HostPhyAddress;
> +  EDKII_IOMMU_PPI       *IoMmu;
> +
> +  *HostAddress = NULL;
> +  *DeviceAddress = 0;
> +  *Mapping = NULL;
> +
> +  IoMmu = GetIoMmu ();
> +
> +  if (IoMmu != NULL) {
> +    Status = IoMmu->AllocateBuffer (
> +                      IoMmu,
> +                      EfiBootServicesData,
> +                      Pages,
> +                      HostAddress,
> +                      0
> +                      );
> +    if (EFI_ERROR (Status)) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +
> +    NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
> +    Status = IoMmu->Map (
> +                      IoMmu,
> +                      EdkiiIoMmuOperationBusMasterCommonBuffer,
> +                      *HostAddress,
> +                      &NumberOfBytes,
> +                      DeviceAddress,
> +                      Mapping
> +                      );
> +    if (EFI_ERROR (Status)) {
> +      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
> +      *HostAddress = NULL;
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    Status = IoMmu->SetAttribute (
> +                      IoMmu,
> +                      *Mapping,
> +                      EDKII_IOMMU_ACCESS_READ |
> EDKII_IOMMU_ACCESS_WRITE
> +                      );
> +    if (EFI_ERROR (Status)) {
> +      IoMmu->Unmap (IoMmu, *Mapping);
> +      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
> +      *Mapping = NULL;
> +      *HostAddress = NULL;
> +      return Status;
> +    }
> +  } else {
> +    Status = PeiServicesAllocatePages (
> +               EfiBootServicesData,
> +               Pages,
> +               &HostPhyAddress
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    *HostAddress = (VOID *) (UINTN) HostPhyAddress;
> +    *DeviceAddress = HostPhyAddress;
> +    *Mapping = NULL;
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Frees memory that was allocated with AllocateBuffer().
> +
> +  @param Pages              The number of pages to free.
> +  @param HostAddress        The base system memory address of the
> allocated range.
> +  @param Mapping            The mapping value returned from Map().
> +
> +**/
> +VOID
> +IoMmuFreeBuffer (
> +  IN UINTN                  Pages,
> +  IN VOID                   *HostAddress,
> +  IN VOID                   *Mapping
> +  )
> +{
> +  EDKII_IOMMU_PPI       *IoMmu;
> +
> +  IoMmu = GetIoMmu ();
> +
> +  if (IoMmu != NULL) {
> +    IoMmu->SetAttribute (IoMmu, Mapping, 0);
> +    IoMmu->Unmap (IoMmu, Mapping);
> +    IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);
> +  } else {
> +    PeiServicesFreePages (
> +      (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
> +      Pages
> +      );
> +  }
> +}
> +
> +/**
> +  Provide IO action support.
> +
> +  @param[in]     PeiDev             The opal device need to perform
> trusted IO.
> +  @param[in]     IoType             OPAL_IO_TYPE indicating whether to
> perform a Trusted Send or Trusted Receive.
> +  @param[in]     SecurityProtocol   Security Protocol
> +  @param[in]     SpSpecific         Security Protocol Specific
> +  @param[in]     TransferLength     Transfer Length of Buffer (in bytes) -
> always a multiple of 512
> +  @param[in]     Buffer             Address of Data to transfer
> +
> +  @retval        EFI_SUCCESS        Perform the IO action success.
> +  @retval        Others             Perform the IO action failed.
> +
> +**/
> +EFI_STATUS
> +PerformTrustedIo (
> +  OPAL_PEI_DEVICE  *PeiDev,
> +  OPAL_IO_TYPE     IoType,
> +  UINT8            SecurityProtocol,
> +  UINT16           SpSpecific,
> +  UINTN            TransferLength,
> +  VOID             *Buffer
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         BufferSizeBlocks;
> +  EFI_ATA_COMMAND_BLOCK         AtaCommandBlock;
> +  OPAL_DEVICE_ATA               *DevInfoAta;
> +  AHCI_CONTEXT                  *AhciContext;
> +  NVME_CONTEXT                  *NvmeContext;
> +
> +  Status = EFI_DEVICE_ERROR;
> +  if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_ATA) {
> +    DevInfoAta = (OPAL_DEVICE_ATA *) PeiDev->Device;
> +    AhciContext = (AHCI_CONTEXT *) PeiDev->Context;
> +
> +    BufferSizeBlocks = TransferLength / 512;
> +
> +    ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
> +    AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ?
> ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
> +    AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
> +    AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
> +    AtaCommandBlock.AtaFeatures = SecurityProtocol;
> +    AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
> +    AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
> +    AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
> +
> +
> +    ZeroMem( AhciContext->Buffer, HDD_PAYLOAD );
> +    ASSERT( TransferLength <= HDD_PAYLOAD );
> +
> +    if (IoType == OpalSend) {
> +      CopyMem( AhciContext->Buffer, Buffer, TransferLength );
> +    }
> +
> +    Status = AhciPioTransfer(
> +                AhciContext,
> +                (UINT8) DevInfoAta->Port,
> +                (UINT8) DevInfoAta->PortMultiplierPort,
> +                NULL,
> +                0,
> +                ( IoType == OpalSend ) ? FALSE : TRUE,   // i/o direction
> +                &AtaCommandBlock,
> +                NULL,
> +                AhciContext->Buffer,
> +                (UINT32)TransferLength,
> +                ATA_TIMEOUT
> +                );
> +
> +    if (IoType == OpalRecv) {
> +      CopyMem( Buffer, AhciContext->Buffer, TransferLength );
> +    }
> +  } else if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
> +    NvmeContext = (NVME_CONTEXT *) PeiDev->Context;
> +    Status = NvmeSecuritySendReceive (
> +                NvmeContext,
> +                IoType == OpalSend,
> +                SecurityProtocol,
> +                SwapBytes16(SpSpecific),
> +                TransferLength,
> +                Buffer
> +              );
> +  } else {
> +    DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n",
> PeiDev->DeviceType));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Send a security protocol command to a device that receives data and/or the
> result
> +  of one or more commands sent by SendData.
> +
> +  The ReceiveData function sends a security protocol command to the given
> MediaId.
> +  The security protocol command sent is defined by SecurityProtocolId and
> contains
> +  the security protocol specific data SecurityProtocolSpecificData. The function
> +  returns the data from the security protocol command in PayloadBuffer.
> +
> +  For devices supporting the SCSI command set, the security protocol
> command is sent
> +  using the SECURITY PROTOCOL IN command defined in SPC-4.
> +
> +  For devices supporting the ATA command set, the security protocol
> command is sent
> +  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if
> PayloadBufferSize
> +  is non-zero.
> +
> +  If the PayloadBufferSize is zero, the security protocol command is sent using
> the
> +  Trusted Non-Data command defined in ATA8-ACS.
> +
> +  If PayloadBufferSize is too small to store the available data from the security
> +  protocol command, the function shall copy PayloadBufferSize bytes into the
> +  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
> +
> +  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is
> non-zero,
> +  the function shall return EFI_INVALID_PARAMETER.
> +
> +  If the given MediaId does not support security protocol commands, the
> function shall
> +  return EFI_UNSUPPORTED. If there is no media in the device, the function
> returns
> +  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
> device,
> +  the function returns EFI_MEDIA_CHANGED.
> +
> +  If the security protocol fails to complete within the Timeout period, the
> function
> +  shall return EFI_TIMEOUT.
> +
> +  If the security protocol command completes without an error, the function
> shall
> +  return EFI_SUCCESS. If the security protocol command completes with an
> error, the
> +  function shall return EFI_DEVICE_ERROR.
> +
> +  @param  This                         Indicates a pointer to the calling
> context.
> +  @param  MediaId                      ID of the medium to receive
> data from.
> +  @param  Timeout                      The timeout, in 100ns units, to
> use for the execution
> +                                       of the security protocol
> command. A Timeout value of 0
> +                                       means that this function will wait
> indefinitely for the
> +                                       security protocol command to
> execute. If Timeout is greater
> +                                       than zero, then this function will
> return EFI_TIMEOUT
> +                                       if the time required to execute
> the receive data command
> +                                       is greater than Timeout.
> +  @param  SecurityProtocolId           The value of the "Security
> Protocol" parameter of
> +                                       the security protocol command
> to be sent.
> +  @param  SecurityProtocolSpecificData The value of the "Security Protocol
> Specific" parameter
> +                                       of the security protocol
> command to be sent.
> +  @param  PayloadBufferSize            Size in bytes of the payload data
> buffer.
> +  @param  PayloadBuffer                A pointer to a destination buffer
> to store the security
> +                                       protocol command specific
> payload data for the security
> +                                       protocol command. The caller is
> responsible for having
> +                                       either implicit or explicit
> ownership of the buffer.
> +  @param  PayloadTransferSize          A pointer to a buffer to store the
> size in bytes of the
> +                                       data written to the payload data
> buffer.
> +
> +  @retval EFI_SUCCESS                  The security protocol command
> completed successfully.
> +  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was
> too small to store the available
> +                                       data from the device. The
> PayloadBuffer contains the truncated data.
> +  @retval EFI_UNSUPPORTED              The given MediaId does not
> support security protocol commands.
> +  @retval EFI_DEVICE_ERROR             The security protocol command
> completed with an error.
> +  @retval EFI_NO_MEDIA                 There is no media in the device.
> +  @retval EFI_MEDIA_CHANGED            The MediaId is not for the
> current media.
> +  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or
> PayloadTransferSize is NULL and
> +                                       PayloadBufferSize is non-zero.
> +  @retval EFI_TIMEOUT                  A timeout occurred while waiting
> for the security
> +                                       protocol command to execute.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SecurityReceiveData (
> +  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN  UINT32                                   MediaId,
> +  IN  UINT64                                   Timeout,
> +  IN  UINT8                                    SecurityProtocolId,
> +  IN  UINT16
> SecurityProtocolSpecificData,
> +  IN  UINTN                                    PayloadBufferSize,
> +  OUT VOID                                     *PayloadBuffer,
> +  OUT UINTN                                    *PayloadTransferSize
> +  )
> +{
> +  OPAL_PEI_DEVICE               *PeiDev;
> +
> +  PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
> +  if (PeiDev == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return PerformTrustedIo (
> +                        PeiDev,
> +                        OpalRecv,
> +                        SecurityProtocolId,
> +                        SecurityProtocolSpecificData,
> +                        PayloadBufferSize,
> +                        PayloadBuffer
> +                        );
> +}
> +
> +/**
> +  Send a security protocol command to a device.
> +
> +  The SendData function sends a security protocol command containing the
> payload
> +  PayloadBuffer to the given MediaId. The security protocol command sent is
> +  defined by SecurityProtocolId and contains the security protocol specific data
> +  SecurityProtocolSpecificData. If the underlying protocol command requires a
> +  specific padding for the command payload, the SendData function shall add
> padding
> +  bytes to the command payload to satisfy the padding requirements.
> +
> +  For devices supporting the SCSI command set, the security protocol
> command is sent
> +  using the SECURITY PROTOCOL OUT command defined in SPC-4.
> +
> +  For devices supporting the ATA command set, the security protocol
> command is sent
> +  using one of the TRUSTED SEND commands defined in ATA8-ACS if
> PayloadBufferSize
> +  is non-zero. If the PayloadBufferSize is zero, the security protocol command
> is
> +  sent using the Trusted Non-Data command defined in ATA8-ACS.
> +
> +  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
> +  return EFI_INVALID_PARAMETER.
> +
> +  If the given MediaId does not support security protocol commands, the
> function
> +  shall return EFI_UNSUPPORTED. If there is no media in the device, the
> function
> +  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in
> the
> +  device, the function returns EFI_MEDIA_CHANGED.
> +
> +  If the security protocol fails to complete within the Timeout period, the
> function
> +  shall return EFI_TIMEOUT.
> +
> +  If the security protocol command completes without an error, the function
> shall return
> +  EFI_SUCCESS. If the security protocol command completes with an error, the
> function
> +  shall return EFI_DEVICE_ERROR.
> +
> +  @param  This                         Indicates a pointer to the calling
> context.
> +  @param  MediaId                      ID of the medium to receive
> data from.
> +  @param  Timeout                      The timeout, in 100ns units, to
> use for the execution
> +                                       of the security protocol
> command. A Timeout value of 0
> +                                       means that this function will wait
> indefinitely for the
> +                                       security protocol command to
> execute. If Timeout is greater
> +                                       than zero, then this function will
> return EFI_TIMEOUT
> +                                       if the time required to execute
> the send data command
> +                                       is greater than Timeout.
> +  @param  SecurityProtocolId           The value of the "Security
> Protocol" parameter of
> +                                       the security protocol command
> to be sent.
> +  @param  SecurityProtocolSpecificData The value of the "Security Protocol
> Specific" parameter
> +                                       of the security protocol
> command to be sent.
> +  @param  PayloadBufferSize            Size in bytes of the payload data
> buffer.
> +  @param  PayloadBuffer                A pointer to a destination buffer
> to store the security
> +                                       protocol command specific
> payload data for the security
> +                                       protocol command.
> +
> +  @retval EFI_SUCCESS                  The security protocol command
> completed successfully.
> +  @retval EFI_UNSUPPORTED              The given MediaId does not
> support security protocol commands.
> +  @retval EFI_DEVICE_ERROR             The security protocol command
> completed with an error.
> +  @retval EFI_NO_MEDIA                 There is no media in the device.
> +  @retval EFI_MEDIA_CHANGED            The MediaId is not for the
> current media.
> +  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and
> PayloadBufferSize is non-zero.
> +  @retval EFI_TIMEOUT                  A timeout occurred while waiting
> for the security
> +                                       protocol command to execute.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SecuritySendData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16
> SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  IN VOID                                     *PayloadBuffer
> +  )
> +{
> +  OPAL_PEI_DEVICE               *PeiDev;
> +
> +  PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
> +  if (PeiDev == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return PerformTrustedIo (
> +                          PeiDev,
> +                          OpalSend,
> +                          SecurityProtocolId,
> +                          SecurityProtocolSpecificData,
> +                          PayloadBufferSize,
> +                          PayloadBuffer
> +                          );
> +
> +}
> +
> +/**
> +  Save/Restore RootPort configuration space.
> +
> +  @param[in]     DevInfoNvme            Pointer to NVMe device info.
> +  @param[in]     SaveAction             TRUE: Save, FALSE: Restore
> +  @param[in,out] PcieConfBufferList    Configuration space data buffer for
> save/restore
> +
> +  @return PCIE base address of this RootPort
> +**/
> +UINTN
> +SaveRestoreRootportConfSpace (
> +  IN     OPAL_DEVICE_NVME               *DevInfoNvme,
> +  IN     BOOLEAN                        SaveAction,
> +  IN OUT UINT8                          **PcieConfBufferList
> +  )
> +{
> +  UINTN             RpBase;
> +  UINTN             Length;
> +  OPAL_PCI_DEVICE   *DevNode;
> +  UINT8             *StorePcieConfData;
> +  UINTN             Index;
> +
> +  Length = 0;
> +  Index  = 0;
> +  RpBase = 0;
> +
> +  while (sizeof (OPAL_DEVICE_NVME) + Length < DevInfoNvme->Length) {
> +    DevNode = (OPAL_PCI_DEVICE *)((UINT8*)DevInfoNvme->PciBridgeNode
> + Length);
> +    RpBase = PCI_LIB_ADDRESS (DevNode->Bus, DevNode->Device,
> DevNode->Function, 0x0);
> +
> +    if (PcieConfBufferList != NULL) {
> +      if (SaveAction) {
> +        StorePcieConfData = (UINT8 *) AllocateZeroPool
> (OPAL_PCIE_ROOTPORT_SAVESIZE);
> +        ASSERT (StorePcieConfData != NULL);
> +        OpalPciRead (StorePcieConfData, RpBase,
> OPAL_PCIE_ROOTPORT_SAVESIZE);
> +        PcieConfBufferList[Index] = StorePcieConfData;
> +      } else {
> +        // Skip PCIe Command & Status registers
> +        StorePcieConfData = PcieConfBufferList[Index];
> +        OpalPciWrite (RpBase, StorePcieConfData, 4);
> +        OpalPciWrite (RpBase + 8, StorePcieConfData + 8,
> OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
> +
> +        FreePool (StorePcieConfData);
> +      }
> +    }
> +
> +    Length += sizeof (OPAL_PCI_DEVICE);
> +    Index ++;
> +  }
> +
> +  return RpBase;
> +}
> +
> +/**
> +  Configure RootPort for downstream PCIe NAND devices.
> +
> +  @param[in] RpBase             - PCIe configuration space address of this
> RootPort
> +  @param[in] BusNumber          - Bus number
> +  @param[in] MemoryBase         - Memory base address
> +  @param[in] MemoryLength       - Memory size
> +
> +**/
> +VOID
> +ConfigureRootPortForPcieNand (
> +  IN UINTN   RpBase,
> +  IN UINTN   BusNumber,
> +  IN UINT32  MemoryBase,
> +  IN UINT32  MemoryLength
> +  )
> +{
> +  UINT32  MemoryLimit;
> +
> +  DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x,
> MemoryBase: %x, MemoryLength: %x\n",
> +    BusNumber, MemoryBase, MemoryLength));
> +
> +  if (MemoryLength == 0) {
> +    MemoryLimit = MemoryBase;
> +  } else {
> +    MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
> +  }
> +
> +  ///
> +  /// Configue PCIE configuration space for RootPort
> +  ///
> +  PciWrite8  (RpBase + NVME_PCIE_BNUM + 1,  (UINT8) BusNumber);
> // Secondary Bus Number registers
> +  PciWrite8  (RpBase + NVME_PCIE_BNUM + 2,  (UINT8) BusNumber);
> // Subordinate Bus Number registers
> +  PciWrite8  (RpBase + NVME_PCIE_IOBL,      0xFF);
> // I/O Base registers
> +  PciWrite8  (RpBase + NVME_PCIE_IOBL + 1,  0x00);
> // I/O Limit registers
> +  PciWrite16 (RpBase + NVME_PCIE_MBL,       (UINT16) RShiftU64
> ((UINTN)MemoryBase, 16));  // Memory Base register
> +  PciWrite16 (RpBase + NVME_PCIE_MBL + 2,   (UINT16) RShiftU64
> ((UINTN)MemoryLimit, 16)); // Memory Limit register
> +  PciWrite16 (RpBase + NVME_PCIE_PMBL,      0xFFFF);
> // Prefetchable Memory Base registers
> +  PciWrite16 (RpBase + NVME_PCIE_PMBL + 2,  0x0000);
> // Prefetchable Memory Limit registers
> +  PciWrite32 (RpBase + NVME_PCIE_PMBU32,    0xFFFFFFFF);
> // Prefetchable Memory Upper Base registers
> +  PciWrite32 (RpBase + NVME_PCIE_PMLU32,    0x00000000);
> // Prefetchable Memory Upper Limit registers
> +}
> +
> +/**
> +
> +  The function returns whether or not the device is Opal Locked.
> +  TRUE means that the device is partially or fully locked.
> +  This will perform a Level 0 Discovery and parse the locking feature descriptor
> +
> +  @param[in]      OpalDev             Opal object to determine if
> locked.
> +  @param[out]     BlockSidSupported   Whether device support BlockSid
> feature.
> +
> +**/
> +BOOLEAN
> +IsOpalDeviceLocked(
> +  OPAL_PEI_DEVICE    *OpalDev,
> +  BOOLEAN            *BlockSidSupported
> +  )
> +{
> +  OPAL_SESSION                   Session;
> +  OPAL_DISK_SUPPORT_ATTRIBUTE    SupportedAttributes;
> +  TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;
> +  UINT16                         OpalBaseComId;
> +  TCG_RESULT                     Ret;
> +
> +  Session.Sscp = &OpalDev->Sscp;
> +  Session.MediaId = 0;
> +
> +  Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes,
> &OpalBaseComId);
> +  if (Ret != TcgResultSuccess) {
> +    return FALSE;
> +  }
> +
> +  Session.OpalBaseComId  = OpalBaseComId;
> +  *BlockSidSupported     = SupportedAttributes.BlockSid == 1 ? TRUE :
> FALSE;
> +
> +  Ret = OpalGetLockingInfo(&Session, &LockingFeature);
> +  if (Ret != TcgResultSuccess) {
> +    return FALSE;
> +  }
> +
> +  return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);
> +}
> +
> +/**
> +  Unlock OPAL password for S3.
> +
> +  @param[in] OpalDev            Opal object to unlock.
> +
> +**/
> +VOID
> +UnlockOpalPassword (
> +  IN OPAL_PEI_DEVICE            *OpalDev
> +  )
> +{
> +  TCG_RESULT                    Result;
> +  OPAL_SESSION                  Session;
> +  BOOLEAN                       BlockSidSupport;
> +  UINT32                        PpStorageFlags;
> +  BOOLEAN                       BlockSIDEnabled;
> +
> +  BlockSidSupport = FALSE;
> +  if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
> +    ZeroMem(&Session, sizeof (Session));
> +    Session.Sscp = &OpalDev->Sscp;
> +    Session.MediaId = 0;
> +    Session.OpalBaseComId = OpalDev->Device->OpalBaseComId;
> +
> +    Result = OpalUtilUpdateGlobalLockingRange (
> +               &Session,
> +               OpalDev->Device->Password,
> +               OpalDev->Device->PasswordLength,
> +               FALSE,
> +               FALSE
> +               );
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a() OpalUtilUpdateGlobalLockingRange() Result = 0x%x\n",
> +      __FUNCTION__,
> +      Result
> +      ));
> +  }
> +
> +  PpStorageFlags = Tcg2PhysicalPresenceLibGetManagementFlags ();
> +  if ((PpStorageFlags &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
> +    BlockSIDEnabled = TRUE;
> +  } else {
> +    BlockSIDEnabled = FALSE;
> +  }
> +  if (BlockSIDEnabled && BlockSidSupport) {
> +    Result = OpalBlockSid (&Session, TRUE);
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a() OpalBlockSid() Result = 0x%x\n",
> +      __FUNCTION__,
> +      Result
> +      ));
> +  }
> +}
> +
> +/**
> +  Unlock ATA OPAL password for S3.
> +
> +**/
> +VOID
> +UnlockOpalPasswordAta (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINT8                         *DevInfo;
> +  OPAL_DEVICE_ATA               TempDevInfoAta;
> +  OPAL_DEVICE_ATA               *DevInfoAta;
> +  UINTN                         DevInfoLengthAta;
> +  UINT8                         Bus;
> +  UINT8                         Device;
> +  UINT8                         Function;
> +  OPAL_PEI_DEVICE               OpalDev;
> +  UINT8                         BaseClassCode;
> +  UINT8                         SubClassCode;
> +  UINT8                         SataCmdSt;
> +  AHCI_CONTEXT                  AhciContext;
> +  UINT32                        AhciBar;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  //
> +  // Get ATA OPAL device info from LockBox.
> +  //
> +  DevInfo = (UINT8 *) &TempDevInfoAta;
> +  DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);
> +  Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo,
> &DevInfoLengthAta);
> +  if (Status == EFI_BUFFER_TOO_SMALL) {
> +    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));
> +    if (DevInfo != NULL) {
> +      Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo,
> &DevInfoLengthAta);
> +    }
> +  }
> +  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
> +    return;
> +  }
> +
> +  for (DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
> +       (UINTN) DevInfoAta < ((UINTN) DevInfo + DevInfoLengthAta);
> +       DevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) DevInfoAta +
> DevInfoAta->Length)) {
> +    Bus = DevInfoAta->Device.Bus;
> +    Device = DevInfoAta->Device.Device;
> +    Function = DevInfoAta->Device.Function;
> +
> +    SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> PCI_COMMAND_OFFSET));
> +    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> PCI_COMMAND_OFFSET), 0x6);
> +
> +    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0B));
> +    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0A));
> +    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
> +        ((SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) &&
> (SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))) {
> +      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode are not
> supported\n", __FUNCTION__));
> +    } else {
> +      AhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
> +      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24),
> DevInfoAta->BarAddr);
> +
> +      ZeroMem (&AhciContext, sizeof (AHCI_CONTEXT));
> +      AhciContext.AhciBar = DevInfoAta->BarAddr;
> +      AhciAllocateResource (&AhciContext);
> +      Status = AhciModeInitialize (&AhciContext, (UINT8)DevInfoAta->Port);
> +      ASSERT_EFI_ERROR (Status);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a() AhciModeInitialize() error,
> Status: %r\n", __FUNCTION__, Status));
> +      }
> +
> +      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
> +      OpalDev.Sscp.ReceiveData = SecurityReceiveData;
> +      OpalDev.Sscp.SendData = SecuritySendData;
> +      OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;
> +      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;
> +      OpalDev.Context = &AhciContext;
> +
> +      UnlockOpalPassword (&OpalDev);
> +
> +      AhciFreeResource (&AhciContext);
> +      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), AhciBar);
> +    }
> +    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> PCI_COMMAND_OFFSET), SataCmdSt);
> +  }
> +
> +  ZeroMem (DevInfo, DevInfoLengthAta);
> +  if ((UINTN) DevInfo != (UINTN) &TempDevInfoAta) {
> +    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthAta));
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Unlock NVMe OPAL password for S3.
> +
> +**/
> +VOID
> +UnlockOpalPasswordNvme (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINT8                         *DevInfo;
> +  OPAL_DEVICE_NVME              TempDevInfoNvme;
> +  OPAL_DEVICE_NVME              *DevInfoNvme;
> +  UINTN                         DevInfoLengthNvme;
> +  UINT8                         Bus;
> +  UINT8                         Device;
> +  UINT8                         Function;
> +  OPAL_PEI_DEVICE               OpalDev;
> +  UINT8                         BaseClassCode;
> +  UINT8                         SubClassCode;
> +  UINT8                         ProgInt;
> +  UINT8                         NvmeCmdSt;
> +  UINT8                         *StorePcieConfDataList[16];
> +  UINTN                         RpBase;
> +  UINTN                         MemoryBase;
> +  UINTN                         MemoryLength;
> +  NVME_CONTEXT                  NvmeContext;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  //
> +  // Get NVMe OPAL device info from LockBox.
> +  //
> +  DevInfo = (UINT8 *) &TempDevInfoNvme;
> +  DevInfoLengthNvme = sizeof (OPAL_DEVICE_NVME);
> +  Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo,
> &DevInfoLengthNvme);
> +  if (Status == EFI_BUFFER_TOO_SMALL) {
> +    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
> +    if (DevInfo != NULL) {
> +      Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo,
> &DevInfoLengthNvme);
> +    }
> +  }
> +  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
> +    return;
> +  }
> +
> +  for (DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
> +       (UINTN) DevInfoNvme < ((UINTN) DevInfo + DevInfoLengthNvme);
> +       DevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) DevInfoNvme +
> DevInfoNvme->Length)) {
> +    Bus = DevInfoNvme->Device.Bus;
> +    Device = DevInfoNvme->Device.Device;
> +    Function = DevInfoNvme->Device.Function;
> +
> +    RpBase    = 0;
> +    NvmeCmdSt = 0;
> +
> +    ///
> +    /// Save original RootPort configuration space to heap
> +    ///
> +    RpBase = SaveRestoreRootportConfSpace (
> +                DevInfoNvme,
> +                TRUE, // save
> +                StorePcieConfDataList
> +                );
> +    MemoryBase = DevInfoNvme->BarAddr;
> +    MemoryLength = 0;
> +    ConfigureRootPortForPcieNand (RpBase, Bus, (UINT32) MemoryBase,
> (UINT32) MemoryLength);
> +
> +    ///
> +    /// Enable PCIE decode for RootPort
> +    ///
> +    NvmeCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
> +    PciWrite8  (RpBase + NVME_PCIE_PCICMD,  0x6);
> +
> +    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0B));
> +    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0A));
> +    ProgInt       = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x09));
> +    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
> +        (SubClassCode != PCI_CLASS_MASS_STORAGE_NVM) ||
> +        (ProgInt != PCI_IF_NVMHCI)) {
> +      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode/PI are not
> supported\n", __FUNCTION__));
> +    } else {
> +      ZeroMem (&NvmeContext, sizeof (NVME_CONTEXT));
> +      NvmeContext.Nbar = DevInfoNvme->BarAddr;
> +      NvmeContext.PciBase = PCI_LIB_ADDRESS (Bus, Device, Function, 0x0);
> +      NvmeContext.NvmeInitWaitTime = 0;
> +      NvmeContext.Nsid = DevInfoNvme->NvmeNamespaceId;
> +      NvmeAllocateResource (&NvmeContext);
> +      Status = NvmeControllerInit (&NvmeContext);
> +
> +      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
> +      OpalDev.Sscp.ReceiveData = SecurityReceiveData;
> +      OpalDev.Sscp.SendData = SecuritySendData;
> +      OpalDev.DeviceType = OPAL_DEVICE_TYPE_NVME;
> +      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoNvme;
> +      OpalDev.Context = &NvmeContext;
> +
> +      UnlockOpalPassword (&OpalDev);
> +
> +      Status = NvmeControllerExit (&NvmeContext);
> +      NvmeFreeResource (&NvmeContext);
> +    }
> +
> +    ASSERT (RpBase != 0);
> +    PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);
> +    RpBase = SaveRestoreRootportConfSpace (
> +                DevInfoNvme,
> +                FALSE,  // restore
> +                StorePcieConfDataList
> +                );
> +    PciWrite8  (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
> +  }
> +
> +  ZeroMem (DevInfo, DevInfoLengthNvme);
> +  if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
> +    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Unlock OPAL password for S3.
> +
> +**/
> +VOID
> +OpalPasswordS3 (
> +  VOID
> +  )
> +{
> +  UnlockOpalPasswordAta ();
> +  UnlockOpalPasswordNvme ();
> +}
> +
> +/**
> +  Entry point of the notification callback function itself within the PEIM.
> +  It is to unlock OPAL password for S3.
> +
> +  @param  PeiServices      Indirect reference to the PEI Services Table.
> +  @param  NotifyDescriptor Address of the notification descriptor data
> structure.
> +  @param  Ppi              Address of the PPI that was installed.
> +
> +  @return Status of the notification.
> +          The status code returned from this function is ignored.
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalPasswordEndOfPeiNotify(
> +  IN EFI_PEI_SERVICES          **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
> +  IN VOID                      *Ppi
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_BOOT_MODE                     BootMode;
> +
> +  Status = PeiServicesGetBootMode (&BootMode);
> +  ASSERT_EFI_ERROR (Status);
> +  if (BootMode != BOOT_ON_S3_RESUME) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
> +
> +  OpalPasswordS3 ();
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordEndOfPeiNotifyDesc = {
> +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEfiEndOfPeiSignalPpiGuid,
> +  OpalPasswordEndOfPeiNotify
> +};
> +
> +/**
> +  Main entry for this module.
> +
> +  @param FileHandle             Handle of the file being invoked.
> +  @param PeiServices            Pointer to PEI Services table.
> +
> +  @return Status from PeiServicesNotifyPpi.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalPasswordPeiInit (
> +  IN EFI_PEI_FILE_HANDLE        FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  EFI_STATUS                    Status;
> +
> +  Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> new file mode 100644
> index 000000000000..31aab37f5d91
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> @@ -0,0 +1,133 @@
> +/** @file
> +  Opal Password PEI driver which is used to unlock Opal Password for S3.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_PASSWORD_PEI_H_
> +#define _OPAL_PASSWORD_PEI_H_
> +
> +#include <PiPei.h>
> +#include <IndustryStandard/Atapi.h>
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PeimEntryPoint.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/LockBoxLib.h>
> +#include <Library/TcgStorageOpalLib.h>
> +#include <Library/Tcg2PhysicalPresenceLib.h>
> +
> +#include <Protocol/StorageSecurityCommand.h>
> +
> +#include <Ppi/IoMmu.h>
> +
> +#include "OpalPasswordCommon.h"
> +#include "OpalAhciMode.h"
> +#include "OpalNvmeMode.h"
> +
> +//
> +// Time out Value for ATA pass through protocol
> +//
> +#define ATA_TIMEOUT                      30000000
> +
> +//
> +// The payload Length of HDD related ATA commands
> +//
> +#define HDD_PAYLOAD                      512
> +//
> +// According to ATA spec, the max Length of hdd password is 32 bytes
> +//
> +#define OPAL_PASSWORD_MAX_LENGTH         32
> +
> +#pragma pack(1)
> +
> +/**
> +* Opal I/O Type utilized by the Trusted IO callback
> +*
> +* The type indicates if the I/O is a send or receive
> +*/
> +typedef enum {
> +    //
> +    // I/O is a TCG Trusted Send command
> +    //
> +    OpalSend,
> +
> +    //
> +    // I/O is a TCG Trusted Receive command
> +    //
> +    OpalRecv
> +} OPAL_IO_TYPE;
> +
> +#define OPAL_PEI_DEVICE_SIGNATURE SIGNATURE_32 ('o', 'p', 'd', 's')
> +
> +typedef struct {
> +  UINTN                                     Signature;
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL     Sscp;
> +  UINT8                                     DeviceType;
> +  OPAL_DEVICE_COMMON                        *Device;
> +  VOID                                      *Context;
> +} OPAL_PEI_DEVICE;
> +
> +#define OPAL_PEI_DEVICE_FROM_THIS(a)  CR (a, OPAL_PEI_DEVICE, Sscp,
> OPAL_PEI_DEVICE_SIGNATURE)
> +
> +#pragma pack()
> +
> +/**
> +  Allocates pages that are suitable for an OperationBusMasterCommonBuffer
> or
> +  OperationBusMasterCommonBuffer64 mapping.
> +
> +  @param Pages                  The number of pages to allocate.
> +  @param HostAddress            A pointer to store the base system
> memory address of the
> +                                allocated range.
> +  @param DeviceAddress          The resulting map address for the bus
> master PCI controller to use to
> +                                access the hosts HostAddress.
> +  @param Mapping                A resulting value to pass to Unmap().
> +
> +  @retval EFI_SUCCESS           The requested memory pages were
> allocated.
> +  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal
> attribute bits are
> +                                MEMORY_WRITE_COMBINE and
> MEMORY_CACHED.
> +  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be
> allocated.
> +
> +**/
> +EFI_STATUS
> +IoMmuAllocateBuffer (
> +  IN UINTN                  Pages,
> +  OUT VOID                  **HostAddress,
> +  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
> +  OUT VOID                  **Mapping
> +  );
> +
> +/**
> +  Frees memory that was allocated with AllocateBuffer().
> +
> +  @param Pages              The number of pages to free.
> +  @param HostAddress        The base system memory address of the
> allocated range.
> +  @param Mapping            The mapping value returned from Map().
> +
> +**/
> +VOID
> +IoMmuFreeBuffer (
> +  IN UINTN                  Pages,
> +  IN VOID                   *HostAddress,
> +  IN VOID                   *Mapping
> +  );
> +
> +#endif // _OPAL_PASSWORD_PEI_H_
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> new file mode 100644
> index 000000000000..81c57c36d2aa
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> @@ -0,0 +1,63 @@
> +## @file
> +#  This is a Opal Password PEI driver.
> +#
> +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be found
> at
> +# http://opensource.org/licenses/bsd-license.php
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = OpalPasswordPei
> +  FILE_GUID                      =
> DED60489-979C-4B5A-8EE4-4068B0CC38DC
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = OpalPasswordPeiInit
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  OpalPasswordPei.c
> +  OpalPasswordPei.h
> +  OpalPasswordCommon.h
> +  OpalAhciMode.c
> +  OpalAhciMode.h
> +  OpalNvmeMode.c
> +  OpalNvmeMode.h
> +  OpalNvmeReg.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  SecurityPkg/SecurityPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  PeimEntryPoint
> +  PeiServicesLib
> +  DebugLib
> +  IoLib
> +  PciLib
> +  BaseLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> +  TimerLib
> +  HobLib
> +  LockBoxLib
> +  TcgStorageOpalLib
> +  Tcg2PhysicalPresenceLib
> +
> +[Ppis]
> +  gEdkiiIoMmuPpiGuid                            ##
> SOMETIMES_CONSUMES
> +  gEfiEndOfPeiSignalPpiGuid                     ## NOTIFY
> +
> +[Depex]
> +  gEfiPeiMasterBootModePpiGuid
> --
> 2.7.0.windows.1



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

* Re: [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code
  2018-03-08 11:44   ` Yao, Jiewen
@ 2018-03-08 11:48     ` Zeng, Star
  0 siblings, 0 replies; 10+ messages in thread
From: Zeng, Star @ 2018-03-08 11:48 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Dong, Eric, Zhang, Chao B, Zeng, Star

Got the point and agree.
Thanks for the good comment. :)


Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Thursday, March 8, 2018 7:44 PM
To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
Cc: Dong, Eric <eric.dong@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code

One minor:

> +  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {

I prefer we also zero Unicode here. ESC just means exit, the Unicode buffer might already be filled.

> +    return NULL;
> +  }
> +
> +  Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);
> +  if (Ascii == NULL) {
> +    ZeroMem (Unicode, sizeof (Unicode));
> +    ZeroMem (Mask, sizeof (Mask));
> +    return NULL;
> +  }

With above change, Reviewed-by: Jiewen.yao@intel.com

> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, March 7, 2018 9:19 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> Dong, Eric <eric.dong@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
> Subject: [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM
> device code
> 
> After IOMMU is enabled in S3, original solution with SMM device
> code (OpalPasswordSmm) to unlock OPAL device for S3 will not work
> as the DMA operation will be aborted without granted DMA buffer.
> Instead, this solution is to add OpalPasswordPei to eliminate
> SMM device code, and OPAL setup UI produced by OpalPasswordDxe
> will be updated to send requests (set password, update password,
> and etc), and then the requests will be processed in next boot
> before SmmReadyToLock, password and device info will be saved to
> lock box used by OpalPasswordPei to unlock OPAL device for S3.
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Star Zeng <star.zeng@intel.com>
> ---
>  SecurityPkg/SecurityPkg.dsc                        |    2 +
>  SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c  |  398 +++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c   | 1335 +++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h   |  435 +++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c     | 3003
> ++++++++++++++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h     |  613 ++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c        | 1178 ++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h        |  380 +++
>  .../Tcg/Opal/OpalPassword/OpalHiiCallbacks.c       |  219 ++
>  .../Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni   |   84 +
>  .../Tcg/Opal/OpalPassword/OpalHiiFormValues.h      |  123 +
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c   | 2144
> ++++++++++++++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h   |  455 +++
>  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h    |  815 ++++++
>  .../Tcg/Opal/OpalPassword/OpalPasswordCommon.h     |   65 +
>  .../Tcg/Opal/OpalPassword/OpalPasswordDxe.inf      |   81 +
>  .../Tcg/Opal/OpalPassword/OpalPasswordForm.vfr     |  309 ++
>  .../Tcg/Opal/OpalPassword/OpalPasswordPei.c        |  940 ++++++
>  .../Tcg/Opal/OpalPassword/OpalPasswordPei.h        |  133 +
>  .../Tcg/Opal/OpalPassword/OpalPasswordPei.inf      |   63 +
>  20 files changed, 12775 insertions(+)
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
>  create mode 100644 SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
>  create mode 100644
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> 
> diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
> index 65a2fe3d7967..f82703a17b82 100644
> --- a/SecurityPkg/SecurityPkg.dsc
> +++ b/SecurityPkg/SecurityPkg.dsc
> @@ -324,6 +324,8 @@ [Components.IA32, Components.X64]
>    #
>    SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
>    SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf
> +  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> +  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> 
>  [Components.IPF]
>    SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/EsalVariableDxeSal.inf
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
> new file mode 100644
> index 000000000000..ef963d0e0b62
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/ComponentName.c
> @@ -0,0 +1,398 @@
> +/** @file
> +  UEFI Component Name(2) protocol implementation for Opal driver.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalDriver.h"
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL
> gOpalComponentName = {
> +  OpalEfiDriverComponentNameGetDriverName,
> +  OpalEfiDriverComponentNameGetControllerName,
> +  "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
> gOpalComponentName2 = {
> +  OpalEfiDriverComponentName2GetDriverName,
> +  OpalEfiDriverComponentName2GetControllerName,
> +  "en"
> +};
> +
> +
> +/// The name of the driver in all the languages we support.
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mOpalDriverNameTable[] = {
> +    { LANGUAGE_RFC_3066_ENGLISH,
> (CHAR16*)EFI_DRIVER_NAME_UNICODE },
> +    { LANGUAGE_ISO_639_2_ENGLISH,
> (CHAR16*)EFI_DRIVER_NAME_UNICODE },
> +    { 0, 0 }
> +};
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetDriverName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  )
> +{
> +  return LookupUnicodeString2(
> +    Language,
> +    This->SupportedLanguages,
> +    mOpalDriverNameTable,
> +    DriverName,
> +    TRUE
> +    );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetDriverName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  )
> +{
> +  return LookupUnicodeString2(
> +    Language,
> +    This->SupportedLanguages,
> +    mOpalDriverNameTable,
> +    DriverName,
> +    FALSE
> +    );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +GetControllerName(
> +  EFI_HANDLE  ControllerHandle,
> +  EFI_HANDLE  ChildHandle,
> +  CHAR8*      Language,
> +  CHAR16**    ControllerName
> +  )
> +{
> +  if (Language == NULL || ControllerName == NULL || ControllerHandle ==
> NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // don't support any controller or children names
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetControllerName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  )
> +{
> +  return (GetControllerName( ControllerHandle, ChildHandle, Language,
> ControllerName));
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetControllerName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  )
> +{
> +  return (GetControllerName(ControllerHandle, ChildHandle, Language,
> ControllerName));
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> new file mode 100644
> index 000000000000..550abacc9c75
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> @@ -0,0 +1,1335 @@
> +/** @file
> +  This driver is used for Opal Password Feature support at AHCI mode.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +
> +#include "OpalPasswordPei.h"
> +
> +/**
> +  Start command for give slot on specific port.
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  CommandSlot        The number of CommandSlot.
> +  @param  Timeout            The timeout Value of start.
> +
> +  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command start successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStartCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT8                     CommandSlot,
> +  IN  UINT64                    Timeout
> +  );
> +
> +/**
> +  Stop command running for giving port
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  Timeout            The timeout Value of stop.
> +
> +  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command stop successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStopCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  );
> +
> +/**
> +  Read AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +
> +  @return The register content read.
> +
> +**/
> +UINT32
> +EFIAPI
> +AhciReadReg (
> +  IN  UINT32              AhciBar,
> +  IN  UINT32              Offset
> +  )
> +{
> +  UINT32   Data;
> +
> +  Data = 0;
> +
> +  Data = MmioRead32 (AhciBar + Offset);
> +
> +  return Data;
> +}
> +
> +/**
> +  Write AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +  @param  Data         The Data used to write down.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciWriteReg (
> +  IN UINT32               AhciBar,
> +  IN UINT32               Offset,
> +  IN UINT32               Data
> +  )
> +{
> +  MmioWrite32 (AhciBar + Offset, Data);
> +
> +  return ;
> +}
> +
> +/**
> +  Do AND operation with the Value of AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +  @param  AndData      The Data used to do AND operation.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciAndReg (
> +  IN UINT32               AhciBar,
> +  IN UINT32               Offset,
> +  IN UINT32               AndData
> +  )
> +{
> +  UINT32 Data;
> +
> +  Data  = AhciReadReg (AhciBar, Offset);
> +
> +  Data &= AndData;
> +
> +  AhciWriteReg (AhciBar, Offset, Data);
> +}
> +
> +/**
> +  Do OR operation with the Value of AHCI Operation register.
> +
> +  @param  AhciBar      AHCI bar address.
> +  @param  Offset       The operation register offset.
> +  @param  OrData       The Data used to do OR operation.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciOrReg (
> +  IN UINT32               AhciBar,
> +  IN UINT32               Offset,
> +  IN UINT32               OrData
> +  )
> +{
> +  UINT32 Data;
> +
> +  Data  = AhciReadReg (AhciBar, Offset);
> +
> +  Data |= OrData;
> +
> +  AhciWriteReg (AhciBar, Offset, Data);
> +}
> +
> +/**
> +  Wait for memory set to the test Value.
> +
> +  @param  AhciBar           AHCI bar address.
> +  @param  Offset            The memory offset to test.
> +  @param  MaskValue         The mask Value of memory.
> +  @param  TestValue         The test Value of memory.
> +  @param  Timeout           The time out Value for wait memory set.
> +
> +  @retval EFI_DEVICE_ERROR  The memory is not set.
> +  @retval EFI_TIMEOUT       The memory setting is time out.
> +  @retval EFI_SUCCESS       The memory is correct set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciWaitMmioSet (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT32                    Offset,
> +  IN  UINT32                    MaskValue,
> +  IN  UINT32                    TestValue,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32     Value;
> +  UINT32     Delay;
> +
> +  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
> +
> +  do {
> +    Value = AhciReadReg (AhciBar, Offset) & MaskValue;
> +
> +    if (Value == TestValue) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // Stall for 100 microseconds.
> +    //
> +    MicroSecondDelay (100);
> +
> +    Delay--;
> +
> +  } while (Delay > 0);
> +
> +  return EFI_TIMEOUT;
> +}
> +/**
> +  Wait for the Value of the specified system memory set to the test Value.
> +
> +  @param  Address           The system memory address to test.
> +  @param  MaskValue         The mask Value of memory.
> +  @param  TestValue         The test Value of memory.
> +  @param  Timeout           The time out Value for wait memory set,
> uses 100ns as a unit.
> +
> +  @retval EFI_TIMEOUT       The system memory setting is time out.
> +  @retval EFI_SUCCESS       The system memory is correct set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciWaitMemSet (
> +  IN  EFI_PHYSICAL_ADDRESS      Address,
> +  IN  UINT32                    MaskValue,
> +  IN  UINT32                    TestValue,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32     Value;
> +  UINT32     Delay;
> +
> +  Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
> +
> +  do {
> +    //
> +    // Access sytem memory to see if the Value is the tested one.
> +    //
> +    // The system memory pointed by Address will be updated by the
> +    // SATA Host Controller, "volatile" is introduced to prevent
> +    // compiler from optimizing the access to the memory address
> +    // to only read once.
> +    //
> +    Value  = *(volatile UINT32 *) (UINTN) Address;
> +    Value &= MaskValue;
> +
> +    if (Value == TestValue) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // Stall for 100 microseconds.
> +    //
> +    MicroSecondDelay (100);
> +
> +    Delay--;
> +
> +  } while (Delay > 0);
> +
> +  return EFI_TIMEOUT;
> +}
> +
> +/**
> +  Check the memory status to the test Value.
> +
> +  @param[in]       Address           The memory address to test.
> +  @param[in]       MaskValue         The mask Value of memory.
> +  @param[in]       TestValue         The test Value of memory.
> +  @param[in, out]  RetryTimes        The retry times Value for waitting
> memory set. If 0, then just try once.
> +
> +  @retval EFI_NOTREADY      The memory is not set.
> +  @retval EFI_TIMEOUT       The memory setting retry times out.
> +  @retval EFI_SUCCESS       The memory is correct set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciCheckMemSet (
> +  IN     UINTN                     Address,
> +  IN     UINT32                    MaskValue,
> +  IN     UINT32                    TestValue,
> +  IN OUT UINTN                     *RetryTimes OPTIONAL
> +  )
> +{
> +  UINT32     Value;
> +
> +  if (RetryTimes != NULL) {
> +    (*RetryTimes)--;
> +  }
> +
> +  Value  = *(volatile UINT32 *) Address;
> +  Value &= MaskValue;
> +
> +  if (Value == TestValue) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if ((RetryTimes != NULL) && (*RetryTimes == 0)) {
> +    return EFI_TIMEOUT;
> +  } else {
> +    return EFI_NOT_READY;
> +  }
> +}
> +
> +/**
> +  Clear the port interrupt and error status. It will also clear
> +  HBA interrupt status.
> +
> +  @param      AhciBar        AHCI bar address.
> +  @param      Port           The number of port.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciClearPortStatus (
> +  IN  UINT32                 AhciBar,
> +  IN  UINT8                  Port
> +  )
> +{
> +  UINT32 Offset;
> +
> +  //
> +  // Clear any error status
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SERR;
> +  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
> +
> +  //
> +  // Clear any port interrupt status
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_IS;
> +  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
> +
> +  //
> +  // Clear any HBA interrupt status
> +  //
> +  AhciWriteReg (AhciBar, EFI_AHCI_IS_OFFSET, AhciReadReg (AhciBar,
> EFI_AHCI_IS_OFFSET));
> +}
> +
> +/**
> +  Enable the FIS running for giving port.
> +
> +  @param      AhciBar        AHCI bar address.
> +  @param      Port           The number of port.
> +  @param      Timeout        The timeout Value of enabling FIS.
> +
> +  @retval EFI_DEVICE_ERROR   The FIS enable setting fails.
> +  @retval EFI_TIMEOUT        The FIS enable setting is time out.
> +  @retval EFI_SUCCESS        The FIS enable successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciEnableFisReceive (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32 Offset;
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_FRE);
> +
> +  return AhciWaitMmioSet (
> +           AhciBar,
> +           Offset,
> +           EFI_AHCI_PORT_CMD_FR,
> +           EFI_AHCI_PORT_CMD_FR,
> +           Timeout
> +           );
> +}
> +
> +/**
> +  Disable the FIS running for giving port.
> +
> +  @param      AhciBar        AHCI bar address.
> +  @param      Port           The number of port.
> +  @param      Timeout        The timeout Value of disabling FIS.
> +
> +  @retval EFI_DEVICE_ERROR   The FIS disable setting fails.
> +  @retval EFI_TIMEOUT        The FIS disable setting is time out.
> +  @retval EFI_UNSUPPORTED    The port is in running state.
> +  @retval EFI_SUCCESS        The FIS disable successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciDisableFisReceive (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32 Offset;
> +  UINT32 Data;
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  Data   = AhciReadReg (AhciBar, Offset);
> +
> +  //
> +  // Before disabling Fis receive, the DMA engine of the port should NOT be in
> running status.
> +  //
> +  if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Check if the Fis receive DMA engine for the port is running.
> +  //
> +  if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
> +
> +  return AhciWaitMmioSet (
> +           AhciBar,
> +           Offset,
> +           EFI_AHCI_PORT_CMD_FR,
> +           0,
> +           Timeout
> +           );
> +}
> +
> +/**
> +  Build the command list, command table and prepare the fis receiver.
> +
> +  @param    AhciContext           The pointer to the AHCI_CONTEXT.
> +  @param    Port                  The number of port.
> +  @param    PortMultiplier        The timeout Value of stop.
> +  @param    CommandFis            The control fis will be used for the
> transfer.
> +  @param    CommandList           The command list will be used for the
> transfer.
> +  @param    AtapiCommand          The atapi command will be used for
> the transfer.
> +  @param    AtapiCommandLength    The Length of the atapi command.
> +  @param    CommandSlotNumber     The command slot will be used for
> the transfer.
> +  @param    DataPhysicalAddr      The pointer to the Data Buffer pci bus
> master address.
> +  @param    DataLength            The Data count to be transferred.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciBuildCommand (
> +  IN     AHCI_CONTEXT               *AhciContext,
> +  IN     UINT8                      Port,
> +  IN     UINT8                      PortMultiplier,
> +  IN     EFI_AHCI_COMMAND_FIS       *CommandFis,
> +  IN     EFI_AHCI_COMMAND_LIST      *CommandList,
> +  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
> +  IN     UINT8                      AtapiCommandLength,
> +  IN     UINT8                      CommandSlotNumber,
> +  IN OUT VOID                       *DataPhysicalAddr,
> +  IN     UINT64                     DataLength
> +  )
> +{
> +  EFI_AHCI_REGISTERS    *AhciRegisters;
> +  UINT32                AhciBar;
> +  UINT64                BaseAddr;
> +  UINT64                PrdtNumber;
> +  UINTN                 RemainedData;
> +  UINTN                 MemAddr;
> +  DATA_64               Data64;
> +  UINT32                Offset;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +  AhciBar = AhciContext->AhciBar;
> +
> +  //
> +  // Filling the PRDT
> +  //
> +  PrdtNumber = DivU64x32 (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT -
> 1, EFI_AHCI_MAX_DATA_PER_PRDT);
> +
> +  //
> +  // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB
> Data block.
> +  // It also limits that the maximum amount of the PRDT entry in the command
> table
> +  // is 65535.
> +  //
> +  ASSERT (PrdtNumber <= 1);
> +
> +  Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis);
> +
> +  BaseAddr = Data64.Uint64;
> +
> +  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
> +
> +  ZeroMem (AhciRegisters->AhciCommandTable, sizeof
> (EFI_AHCI_COMMAND_TABLE));
> +
> +  CommandFis->AhciCFisPmNum = PortMultiplier;
> +
> +  CopyMem (&AhciRegisters->AhciCommandTable->CommandFis,
> CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  if (AtapiCommand != NULL) {
> +    CopyMem (
> +      &AhciRegisters->AhciCommandTable->AtapiCmd,
> +      AtapiCommand,
> +      AtapiCommandLength
> +      );
> +
> +    CommandList->AhciCmdA = 1;
> +    CommandList->AhciCmdP = 1;
> +
> +    AhciOrReg (AhciBar, Offset, (EFI_AHCI_PORT_CMD_DLAE |
> EFI_AHCI_PORT_CMD_ATAPI));
> +  } else {
> +    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE |
> EFI_AHCI_PORT_CMD_ATAPI));
> +  }
> +
> +  RemainedData = (UINTN) DataLength;
> +  MemAddr      = (UINTN) DataPhysicalAddr;
> +  CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
> +
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbc =
> (UINT32)RemainedData - 1;
> +
> +  Data64.Uint64 = (UINT64)MemAddr;
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDba  =
> Data64.Uint32.Lower32;
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbau =
> Data64.Uint32.Upper32;
> +
> +  //
> +  // Set the last PRDT to Interrupt On Complete
> +  //
> +  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtIoc = 1;
> +
> +  CopyMem (
> +    (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN)
> CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
> +    CommandList,
> +    sizeof (EFI_AHCI_COMMAND_LIST)
> +    );
> +
> +  Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTable;
> +  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba  =
> Data64.Uint32.Lower32;
> +  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau =
> Data64.Uint32.Upper32;
> +  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp   =
> PortMultiplier;
> +
> +}
> +
> +/**
> +  Buid a command FIS.
> +
> +  @param  CmdFis            A pointer to the EFI_AHCI_COMMAND_FIS
> Data structure.
> +  @param  AtaCommandBlock   A pointer to the AhciBuildCommandFis
> Data structure.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciBuildCommandFis (
> +  IN OUT EFI_AHCI_COMMAND_FIS    *CmdFis,
> +  IN     EFI_ATA_COMMAND_BLOCK   *AtaCommandBlock
> +  )
> +{
> +  ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
> +
> +  CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
> +  //
> +  // Indicator it's a command
> +  //
> +  CmdFis->AhciCFisCmdInd      = 0x1;
> +  CmdFis->AhciCFisCmd         = AtaCommandBlock->AtaCommand;
> +
> +  CmdFis->AhciCFisFeature     = AtaCommandBlock->AtaFeatures;
> +  CmdFis->AhciCFisFeatureExp  = AtaCommandBlock->AtaFeaturesExp;
> +
> +  CmdFis->AhciCFisSecNum      = AtaCommandBlock->AtaSectorNumber;
> +  CmdFis->AhciCFisSecNumExp   =
> AtaCommandBlock->AtaSectorNumberExp;
> +
> +  CmdFis->AhciCFisClyLow      = AtaCommandBlock->AtaCylinderLow;
> +  CmdFis->AhciCFisClyLowExp   = AtaCommandBlock->AtaCylinderLowExp;
> +
> +  CmdFis->AhciCFisClyHigh     = AtaCommandBlock->AtaCylinderHigh;
> +  CmdFis->AhciCFisClyHighExp  = AtaCommandBlock->AtaCylinderHighExp;
> +
> +  CmdFis->AhciCFisSecCount    = AtaCommandBlock->AtaSectorCount;
> +  CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
> +
> +  CmdFis->AhciCFisDevHead     = (UINT8)
> (AtaCommandBlock->AtaDeviceHead | 0xE0);
> +}
> +
> +/**
> +  Start a PIO Data transfer on specific port.
> +
> +  @param  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param  Port                The number of port.
> +  @param  PortMultiplier      The timeout Value of stop.
> +  @param  AtapiCommand        The atapi command will be used for the
> transfer.
> +  @param  AtapiCommandLength  The Length of the atapi command.
> +  @param  Read                The transfer direction.
> +  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
> +  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
> +  @param  MemoryAddr          The pointer to the Data Buffer.
> +  @param  DataCount           The Data count to be transferred.
> +  @param  Timeout             The timeout Value of non Data transfer.
> +
> +  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error
> occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
> +  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciPioTransfer (
> +  IN     AHCI_CONTEXT               *AhciContext,
> +  IN     UINT8                      Port,
> +  IN     UINT8                      PortMultiplier,
> +  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
> +  IN     UINT8                      AtapiCommandLength,
> +  IN     BOOLEAN                    Read,
> +  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
> +  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
> +  IN OUT VOID                       *MemoryAddr,
> +  IN     UINT32                     DataCount,
> +  IN     UINT64                     Timeout
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_AHCI_REGISTERS            *AhciRegisters;
> +  UINT32                        AhciBar;
> +  UINT32                        FisBaseAddr;
> +  UINT32                        Offset;
> +  UINT32                        Delay;
> +  EFI_AHCI_COMMAND_FIS          CFis;
> +  EFI_AHCI_COMMAND_LIST         CmdList;
> +  UINT32                        PortTfd;
> +  UINT32                        PrdCount;
> +  UINT32                        OldRfisLo;
> +  UINT32                        OldRfisHi;
> +  UINT32                        OldCmdListLo;
> +  UINT32                        OldCmdListHi;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +  AhciBar = AhciContext->AhciBar;
> +
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  OldRfisLo = AhciReadReg (AhciBar, Offset);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> +  OldRfisHi = AhciReadReg (AhciBar, Offset);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> +  AhciWriteReg (AhciBar, Offset, 0);
> +
> +  //
> +  // Single task envrionment, we only use one command table for all port
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  OldCmdListLo = AhciReadReg (AhciBar, Offset);
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> +  OldCmdListHi = AhciReadReg (AhciBar, Offset);
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> +  AhciWriteReg (AhciBar, Offset, 0);
> +
> +  //
> +  // Package read needed
> +  //
> +  AhciBuildCommandFis (&CFis, AtaCommandBlock);
> +
> +  ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
> +
> +  CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
> +  CmdList.AhciCmdW   = Read ? 0 : 1;
> +
> +  AhciBuildCommand (
> +    AhciContext,
> +    Port,
> +    PortMultiplier,
> +    &CFis,
> +    &CmdList,
> +    AtapiCommand,
> +    AtapiCommandLength,
> +    0,
> +    MemoryAddr,
> +    DataCount
> +    );
> +
> +  Status = AhciStartCommand (
> +             AhciBar,
> +             Port,
> +             0,
> +             Timeout
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto Exit;
> +  }
> +
> +  //
> +  // Checking the status and wait the driver sending Data
> +  //
> +  FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis;
> +  if (Read && (AtapiCommand == 0)) {
> +    //
> +    // Wait device sends the PIO setup fis before Data transfer
> +    //
> +    Status = EFI_TIMEOUT;
> +    Delay  = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
> +    do {
> +      Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
> +
> +      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK,
> EFI_AHCI_FIS_PIO_SETUP, 0);
> +      if (!EFI_ERROR (Status)) {
> +        Offset = EFI_AHCI_PORT_START + Port *
> EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
> +        PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
> +        //
> +        // PxTFD will be updated if there is a D2H or SetupFIS received.
> +        // For PIO IN transfer, D2H means a device error. Therefore we only
> need to check the TFD after receiving a SetupFIS.
> +        //
> +        if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
> +          Status = EFI_DEVICE_ERROR;
> +          break;
> +        }
> +
> +        PrdCount = *(volatile UINT32 *)
> (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
> +        if (PrdCount == DataCount) {
> +          break;
> +        }
> +      }
> +
> +      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
> +      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK,
> EFI_AHCI_FIS_REGISTER_D2H, 0);
> +      if (!EFI_ERROR (Status)) {
> +        Status = EFI_DEVICE_ERROR;
> +        break;
> +      }
> +
> +      //
> +      // Stall for 100 microseconds.
> +      //
> +      MicroSecondDelay(100);
> +
> +      Delay--;
> +    } while (Delay > 0);
> +  } else {
> +    //
> +    // Wait for D2H Fis is received
> +    //
> +    Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
> +    Status = AhciWaitMemSet (
> +               Offset,
> +               EFI_AHCI_FIS_TYPE_MASK,
> +               EFI_AHCI_FIS_REGISTER_D2H,
> +               Timeout
> +               );
> +
> +    if (EFI_ERROR (Status)) {
> +      goto Exit;
> +    }
> +
> +    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> +    PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
> +    if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
> +      Status = EFI_DEVICE_ERROR;
> +    }
> +  }
> +
> +Exit:
> +  AhciStopCommand (
> +    AhciBar,
> +    Port,
> +    Timeout
> +    );
> +
> +  AhciDisableFisReceive (
> +    AhciBar,
> +    Port,
> +    Timeout
> +    );
> +
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  AhciWriteReg (AhciBar, Offset, OldRfisLo);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> +  AhciWriteReg (AhciBar, Offset, OldRfisHi);
> +
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  AhciWriteReg (AhciBar, Offset, OldCmdListLo);
> +  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> +  AhciWriteReg (AhciBar, Offset, OldCmdListHi);
> +
> +  return Status;
> +}
> +
> +/**
> +  Stop command running for giving port
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  Timeout            The timeout Value of stop.
> +
> +  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command stop successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStopCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32 Offset;
> +  UINT32 Data;
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  Data   = AhciReadReg (AhciBar, Offset);
> +
> +  if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
> +    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
> +  }
> +
> +  return AhciWaitMmioSet (
> +           AhciBar,
> +           Offset,
> +           EFI_AHCI_PORT_CMD_CR,
> +           0,
> +           Timeout
> +           );
> +}
> +
> +/**
> +  Start command for give slot on specific port.
> +
> +  @param  AhciBar            AHCI bar address.
> +  @param  Port               The number of port.
> +  @param  CommandSlot        The number of CommandSlot.
> +  @param  Timeout            The timeout Value of start.
> +
> +  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
> +  @retval EFI_TIMEOUT        The operation is time out.
> +  @retval EFI_SUCCESS        The command start successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciStartCommand (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT8                     Port,
> +  IN  UINT8                     CommandSlot,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32                        CmdSlotBit;
> +  EFI_STATUS                    Status;
> +  UINT32                        PortStatus;
> +  UINT32                        StartCmd;
> +  UINT32                        PortTfd;
> +  UINT32                        Offset;
> +  UINT32                        Capability;
> +
> +  //
> +  // Collect AHCI controller information
> +  //
> +  Capability = AhciReadReg(AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> +
> +  CmdSlotBit = (UINT32) (1 << CommandSlot);
> +
> +  AhciClearPortStatus (
> +    AhciBar,
> +    Port
> +    );
> +
> +  Status = AhciEnableFisReceive (
> +             AhciBar,
> +             Port,
> +             Timeout
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  PortStatus = AhciReadReg (AhciBar, Offset);
> +
> +  StartCmd = 0;
> +  if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
> +    StartCmd = AhciReadReg (AhciBar, Offset);
> +    StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
> +    StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> +  PortTfd = AhciReadReg (AhciBar, Offset);
> +
> +  if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0)
> {
> +    if ((Capability & BIT24) != 0) {
> +      Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH
> + EFI_AHCI_PORT_CMD;
> +      AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_COL);
> +
> +      AhciWaitMmioSet (
> +        AhciBar,
> +        Offset,
> +        EFI_AHCI_PORT_CMD_COL,
> +        0,
> +        Timeout
> +        );
> +    }
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
> +
> +  //
> +  // Setting the command
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SACT;
> +  AhciAndReg (AhciBar, Offset, 0);
> +  AhciOrReg (AhciBar, Offset, CmdSlotBit);
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CI;
> +  AhciAndReg (AhciBar, Offset, 0);
> +  AhciOrReg (AhciBar, Offset, CmdSlotBit);
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Do AHCI HBA reset.
> +
> +  @param[in]  AhciBar        AHCI bar address.
> +  @param[in]  Timeout        The timeout Value of reset.
> +
> +  @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete
> hardware reset.
> +  @retval EFI_TIMEOUT        The reset operation is time out.
> +  @retval EFI_SUCCESS        AHCI controller is reset successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciReset (
> +  IN  UINT32                    AhciBar,
> +  IN  UINT64                    Timeout
> +  )
> +{
> +  UINT32                 Delay;
> +  UINT32                 Value;
> +  UINT32                 Capability;
> +
> +  //
> +  // Collect AHCI controller information
> +  //
> +  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> +
> +  //
> +  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only
> is not set
> +  //
> +  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
> +    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
> +  }
> +
> +  AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
> +
> +  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
> +
> +  do {
> +    Value = AhciReadReg(AhciBar, EFI_AHCI_GHC_OFFSET);
> +    if ((Value & EFI_AHCI_GHC_RESET) == 0) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // Stall for 100 microseconds.
> +    //
> +    MicroSecondDelay(100);
> +
> +    Delay--;
> +  } while (Delay > 0);
> +
> +  return EFI_TIMEOUT;
> +
> +
> +}
> +
> +/**
> +  Send Buffer cmd to specific device.
> +
> +  @param[in]  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param[in]  Port                The port number of attached ATA
> device.
> +  @param[in]  PortMultiplier      The port number of port multiplier of
> attached ATA device.
> +  @param[in, out]  Buffer         The Data Buffer to store IDENTIFY
> PACKET Data.
> +
> +  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for executing.
> +  @retval EFI_SUCCESS         The cmd executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciIdentify (
> +  IN AHCI_CONTEXT             *AhciContext,
> +  IN UINT8                    Port,
> +  IN UINT8                    PortMultiplier,
> +  IN OUT ATA_IDENTIFY_DATA    *Buffer
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
> +
> +  if (AhciContext == NULL || Buffer == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
> +
> +  AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DRIVE;
> +  AtaCommandBlock.AtaSectorCount = 1;
> +
> +  Status = AhciPioTransfer (
> +             AhciContext,
> +             Port,
> +             PortMultiplier,
> +             NULL,
> +             0,
> +             TRUE,
> +             &AtaCommandBlock,
> +             NULL,
> +             Buffer,
> +             sizeof (ATA_IDENTIFY_DATA),
> +             ATA_TIMEOUT
> +             );
> +
> +  return Status;
> +}
> +
> +/**
> +  Allocate transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciAllocateResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_AHCI_REGISTERS        *AhciRegisters;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
> +  VOID                      *Base;
> +  VOID                      *Mapping;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +
> +  //
> +  // Allocate resources required by AHCI host controller.
> +  //
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciRegisters->AhciRFisMapping = Mapping;
> +  AhciRegisters->AhciRFis = Base;
> +  ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (sizeof (EFI_AHCI_RECEIVED_FIS)));
> +
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciRegisters->AhciCmdListMapping = Mapping;
> +  AhciRegisters->AhciCmdList = Base;
> +  ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE *
> EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
> +
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +       AhciRegisters->AhciCmdList,
> +       AhciRegisters->AhciCmdListMapping
> +       );
> +    AhciRegisters->AhciCmdList = NULL;
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciRegisters->AhciCommandTableMapping = Mapping;
> +  AhciRegisters->AhciCommandTable = Base;
> +  ZeroMem (AhciRegisters->AhciCommandTable, EFI_PAGE_SIZE *
> EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));
> +
> +  //
> +  // Allocate resources for data transfer.
> +  //
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +       AhciRegisters->AhciCmdList,
> +       AhciRegisters->AhciCmdListMapping
> +       );
> +    AhciRegisters->AhciCmdList = NULL;
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciCommandTable,
> +       AhciRegisters->AhciCommandTableMapping
> +       );
> +    AhciRegisters->AhciCommandTable = NULL;
> +
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  AhciContext->BufferMapping = Mapping;
> +  AhciContext->Buffer = Base;
> +  ZeroMem (AhciContext->Buffer, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (HDD_PAYLOAD));
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a() AhciContext 0x%x 0x%x 0x%x 0x%x\n",
> +    __FUNCTION__,
> +    AhciContext->Buffer,
> +    AhciRegisters->AhciRFis,
> +    AhciRegisters->AhciCmdList,
> +    AhciRegisters->AhciCommandTable
> +    ));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Free allocated transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciFreeResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  )
> +{
> +  EFI_AHCI_REGISTERS        *AhciRegisters;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +
> +  if (AhciRegisters->AhciRFis != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> +       AhciRegisters->AhciRFis,
> +       AhciRegisters->AhciRFisMapping
> +       );
> +    AhciRegisters->AhciRFis = NULL;
> +  }
> +
> +  if (AhciRegisters->AhciCmdList != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> +       AhciRegisters->AhciCmdList,
> +       AhciRegisters->AhciCmdListMapping
> +       );
> +    AhciRegisters->AhciCmdList = NULL;
> +  }
> +
> +  if (AhciRegisters->AhciCommandTable != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> +       AhciRegisters->AhciCommandTable,
> +       AhciRegisters->AhciCommandTableMapping
> +       );
> +    AhciRegisters->AhciCommandTable = NULL;
> +  }
> +
> +  if (AhciContext->Buffer != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> +       AhciContext->Buffer,
> +       AhciContext->BufferMapping
> +       );
> +    AhciContext->Buffer = NULL;
> +  }
> +}
> +
> +/**
> +  Initialize ATA host controller at AHCI mode.
> +
> +  The function is designed to initialize ATA host controller.
> +
> +  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.
> +  @param[in]  Port          The port number to do initialization.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciModeInitialize (
> +  IN AHCI_CONTEXT    *AhciContext,
> +  IN UINT8           Port
> +  )
> +{
> +  EFI_STATUS         Status;
> +  EFI_AHCI_REGISTERS *AhciRegisters;
> +  UINT32             AhciBar;
> +  UINT32             Capability;
> +  UINT32             Offset;
> +  UINT32             Data;
> +  UINT32             PhyDetectDelay;
> +
> +  AhciRegisters = &AhciContext->AhciRegisters;
> +  AhciBar = AhciContext->AhciBar;
> +
> +  Status = AhciReset (AhciBar, ATA_TIMEOUT);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Collect AHCI controller information
> +  //
> +  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> +
> +  //
> +  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only
> is not set
> +  //
> +  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
> +    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
> +
> +  //
> +  // Single task envrionment, we only use one command table for all port
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> +  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> +  Data = AhciReadReg (AhciBar, Offset);
> +  if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
> +    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_POD);
> +  }
> +
> +  if ((Capability & BIT27) != 0) {
> +    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_SUD);
> +  }
> +
> +  //
> +  // Disable aggressive power management.
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SCTL;
> +  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
> +  //
> +  // Disable the reporting of the corresponding interrupt to system software.
> +  //
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_IE;
> +  AhciAndReg (AhciBar, Offset, 0);
> +
> +  Status = AhciEnableFisReceive (
> +             AhciBar,
> +             Port,
> +             5000000
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY
> and PxTFD.DRQ
> +  // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined
> at ATA spec.
> +  //
> +  PhyDetectDelay = 16 * 1000;
> +  do {
> +    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SERR;
> +    if (AhciReadReg(AhciBar, Offset) != 0) {
> +      AhciWriteReg (AhciBar, Offset, AhciReadReg(AhciBar, Offset));
> +    }
> +    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> +
> +    Data = AhciReadReg (AhciBar, Offset) & EFI_AHCI_PORT_TFD_MASK;
> +    if (Data == 0) {
> +      break;
> +    }
> +
> +    MicroSecondDelay (1000);
> +    PhyDetectDelay--;
> +  } while (PhyDetectDelay > 0);
> +
> +  if (PhyDetectDelay == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SIG;
> +  Status = AhciWaitMmioSet (
> +             AhciBar,
> +             Offset,
> +             0x0000FFFF,
> +             0x00000101,
> +             160000000
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> new file mode 100644
> index 000000000000..b1d6ed13d5b9
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> @@ -0,0 +1,435 @@
> +/** @file
> +  Header file for AHCI mode of ATA host controller.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +
> +#ifndef __OPAL_PASSWORD_AHCI_MODE_H__
> +#define __OPAL_PASSWORD_AHCI_MODE_H__
> +
> +//
> +// OPAL LIBRARY CALLBACKS
> +//
> +#define ATA_COMMAND_TRUSTED_RECEIVE            0x5C
> +#define ATA_COMMAND_TRUSTED_SEND               0x5E
> +
> +//
> +// ATA TRUSTED commands express transfer Length in 512 byte multiple
> +//
> +#define ATA_TRUSTED_TRANSFER_LENGTH_MULTIPLE   512
> +#define ATA_DEVICE_LBA                         0x40    ///< Set for
> commands with LBA (rather than CHS) addresses
> +
> +
> +#define EFI_AHCI_BAR_INDEX                     0x05
> +
> +#define EFI_AHCI_CAPABILITY_OFFSET             0x0000
> +#define   EFI_AHCI_CAP_SAM                     BIT18
> +#define EFI_AHCI_GHC_OFFSET                    0x0004
> +#define   EFI_AHCI_GHC_RESET                   BIT0
> +#define   EFI_AHCI_GHC_IE                      BIT1
> +#define   EFI_AHCI_GHC_ENABLE                  BIT31
> +#define EFI_AHCI_IS_OFFSET                     0x0008
> +#define EFI_AHCI_PI_OFFSET                     0x000C
> +
> +typedef struct {
> +  UINT32  Lower32;
> +  UINT32  Upper32;
> +} DATA_32;
> +
> +typedef union {
> +  DATA_32   Uint32;
> +  UINT64    Uint64;
> +} DATA_64;
> +
> +//
> +// Each PRDT entry can point to a memory block up to 4M byte
> +//
> +#define EFI_AHCI_MAX_DATA_PER_PRDT             0x400000
> +
> +#define EFI_AHCI_FIS_REGISTER_H2D              0x27      //Register
> FIS - Host to Device
> +#define   EFI_AHCI_FIS_REGISTER_H2D_LENGTH     20
> +#define EFI_AHCI_FIS_REGISTER_D2H              0x34      //Register
> FIS - Device to Host
> +#define   EFI_AHCI_FIS_REGISTER_D2H_LENGTH     20
> +#define EFI_AHCI_FIS_DMA_ACTIVATE              0x39      //DMA
> Activate FIS - Device to Host
> +#define   EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH     4
> +#define EFI_AHCI_FIS_DMA_SETUP                 0x41      //DMA
> Setup FIS - Bi-directional
> +#define   EFI_AHCI_FIS_DMA_SETUP_LENGTH        28
> +#define EFI_AHCI_FIS_DATA                      0x46      //Data FIS -
> Bi-directional
> +#define EFI_AHCI_FIS_BIST                      0x58      //BIST
> Activate FIS - Bi-directional
> +#define   EFI_AHCI_FIS_BIST_LENGTH             12
> +#define EFI_AHCI_FIS_PIO_SETUP                 0x5F      //PIO Setup
> FIS - Device to Host
> +#define   EFI_AHCI_FIS_PIO_SETUP_LENGTH        20
> +#define EFI_AHCI_FIS_SET_DEVICE                0xA1      //Set Device
> Bits FIS - Device to Host
> +#define   EFI_AHCI_FIS_SET_DEVICE_LENGTH       8
> +
> +#define EFI_AHCI_D2H_FIS_OFFSET                0x40
> +#define EFI_AHCI_DMA_FIS_OFFSET                0x00
> +#define EFI_AHCI_PIO_FIS_OFFSET                0x20
> +#define EFI_AHCI_SDB_FIS_OFFSET                0x58
> +#define EFI_AHCI_FIS_TYPE_MASK                 0xFF
> +#define EFI_AHCI_U_FIS_OFFSET                  0x60
> +
> +//
> +// Port register
> +//
> +#define EFI_AHCI_PORT_START                    0x0100
> +#define EFI_AHCI_PORT_REG_WIDTH                0x0080
> +#define EFI_AHCI_PORT_CLB                      0x0000
> +#define EFI_AHCI_PORT_CLBU                     0x0004
> +#define EFI_AHCI_PORT_FB                       0x0008
> +#define EFI_AHCI_PORT_FBU                      0x000C
> +#define EFI_AHCI_PORT_IS                       0x0010
> +#define   EFI_AHCI_PORT_IS_DHRS                BIT0
> +#define   EFI_AHCI_PORT_IS_PSS                 BIT1
> +#define   EFI_AHCI_PORT_IS_SSS                 BIT2
> +#define   EFI_AHCI_PORT_IS_SDBS                BIT3
> +#define   EFI_AHCI_PORT_IS_UFS                 BIT4
> +#define   EFI_AHCI_PORT_IS_DPS                 BIT5
> +#define   EFI_AHCI_PORT_IS_PCS                 BIT6
> +#define   EFI_AHCI_PORT_IS_DIS                 BIT7
> +#define   EFI_AHCI_PORT_IS_PRCS                BIT22
> +#define   EFI_AHCI_PORT_IS_IPMS                BIT23
> +#define   EFI_AHCI_PORT_IS_OFS                 BIT24
> +#define   EFI_AHCI_PORT_IS_INFS                BIT26
> +#define   EFI_AHCI_PORT_IS_IFS                 BIT27
> +#define   EFI_AHCI_PORT_IS_HBDS                BIT28
> +#define   EFI_AHCI_PORT_IS_HBFS                BIT29
> +#define   EFI_AHCI_PORT_IS_TFES                BIT30
> +#define   EFI_AHCI_PORT_IS_CPDS                BIT31
> +#define   EFI_AHCI_PORT_IS_CLEAR               0xFFFFFFFF
> +#define   EFI_AHCI_PORT_IS_FIS_CLEAR           0x0000000F
> +
> +#define EFI_AHCI_PORT_IE                       0x0014
> +#define EFI_AHCI_PORT_CMD                      0x0018
> +#define   EFI_AHCI_PORT_CMD_ST_MASK            0xFFFFFFFE
> +#define   EFI_AHCI_PORT_CMD_ST                 BIT0
> +#define   EFI_AHCI_PORT_CMD_SUD                BIT1
> +#define   EFI_AHCI_PORT_CMD_POD                BIT2
> +#define   EFI_AHCI_PORT_CMD_COL                BIT3
> +#define   EFI_AHCI_PORT_CMD_CR                 BIT15
> +#define   EFI_AHCI_PORT_CMD_FRE                BIT4
> +#define   EFI_AHCI_PORT_CMD_FR                 BIT14
> +#define   EFI_AHCI_PORT_CMD_MASK
> ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE |
> EFI_AHCI_PORT_CMD_COL)
> +#define   EFI_AHCI_PORT_CMD_PMA                BIT17
> +#define   EFI_AHCI_PORT_CMD_HPCP               BIT18
> +#define   EFI_AHCI_PORT_CMD_MPSP               BIT19
> +#define   EFI_AHCI_PORT_CMD_CPD                BIT20
> +#define   EFI_AHCI_PORT_CMD_ESP                BIT21
> +#define   EFI_AHCI_PORT_CMD_ATAPI              BIT24
> +#define   EFI_AHCI_PORT_CMD_DLAE               BIT25
> +#define   EFI_AHCI_PORT_CMD_ALPE               BIT26
> +#define   EFI_AHCI_PORT_CMD_ASP                BIT27
> +#define   EFI_AHCI_PORT_CMD_ICC_MASK           (BIT28 | BIT29 |
> BIT30 | BIT31)
> +#define   EFI_AHCI_PORT_CMD_ACTIVE             (1 << 28 )
> +#define EFI_AHCI_PORT_TFD                      0x0020
> +#define   EFI_AHCI_PORT_TFD_MASK               (BIT7 | BIT3 | BIT0)
> +#define   EFI_AHCI_PORT_TFD_BSY                BIT7
> +#define   EFI_AHCI_PORT_TFD_DRQ                BIT3
> +#define   EFI_AHCI_PORT_TFD_ERR                BIT0
> +#define   EFI_AHCI_PORT_TFD_ERR_MASK           0x00FF00
> +#define EFI_AHCI_PORT_SIG                      0x0024
> +#define EFI_AHCI_PORT_SSTS                     0x0028
> +#define   EFI_AHCI_PORT_SSTS_DET_MASK          0x000F
> +#define   EFI_AHCI_PORT_SSTS_DET               0x0001
> +#define   EFI_AHCI_PORT_SSTS_DET_PCE           0x0003
> +#define   EFI_AHCI_PORT_SSTS_SPD_MASK          0x00F0
> +#define EFI_AHCI_PORT_SCTL                     0x002C
> +#define   EFI_AHCI_PORT_SCTL_DET_MASK          0x000F
> +#define   EFI_AHCI_PORT_SCTL_MASK
> (~EFI_AHCI_PORT_SCTL_DET_MASK)
> +#define   EFI_AHCI_PORT_SCTL_DET_INIT          0x0001
> +#define   EFI_AHCI_PORT_SCTL_DET_PHYCOMM       0x0003
> +#define   EFI_AHCI_PORT_SCTL_SPD_MASK          0x00F0
> +#define   EFI_AHCI_PORT_SCTL_IPM_MASK          0x0F00
> +#define   EFI_AHCI_PORT_SCTL_IPM_INIT          0x0300
> +#define   EFI_AHCI_PORT_SCTL_IPM_PSD           0x0100
> +#define   EFI_AHCI_PORT_SCTL_IPM_SSD           0x0200
> +#define EFI_AHCI_PORT_SERR                     0x0030
> +#define   EFI_AHCI_PORT_SERR_RDIE              BIT0
> +#define   EFI_AHCI_PORT_SERR_RCE               BIT1
> +#define   EFI_AHCI_PORT_SERR_TDIE              BIT8
> +#define   EFI_AHCI_PORT_SERR_PCDIE             BIT9
> +#define   EFI_AHCI_PORT_SERR_PE                BIT10
> +#define   EFI_AHCI_PORT_SERR_IE                BIT11
> +#define   EFI_AHCI_PORT_SERR_PRC               BIT16
> +#define   EFI_AHCI_PORT_SERR_PIE               BIT17
> +#define   EFI_AHCI_PORT_SERR_CW                BIT18
> +#define   EFI_AHCI_PORT_SERR_BDE               BIT19
> +#define   EFI_AHCI_PORT_SERR_DE                BIT20
> +#define   EFI_AHCI_PORT_SERR_CRCE              BIT21
> +#define   EFI_AHCI_PORT_SERR_HE                BIT22
> +#define   EFI_AHCI_PORT_SERR_LSE               BIT23
> +#define   EFI_AHCI_PORT_SERR_TSTE              BIT24
> +#define   EFI_AHCI_PORT_SERR_UFT               BIT25
> +#define   EFI_AHCI_PORT_SERR_EX                BIT26
> +#define   EFI_AHCI_PORT_ERR_CLEAR              0xFFFFFFFF
> +#define EFI_AHCI_PORT_SACT                     0x0034
> +#define EFI_AHCI_PORT_CI                       0x0038
> +#define EFI_AHCI_PORT_SNTF                     0x003C
> +
> +
> +#pragma pack(1)
> +//
> +// Command List structure includes total 32 entries.
> +// The entry Data structure is listed at the following.
> +//
> +typedef struct {
> +  UINT32   AhciCmdCfl:5;      //Command FIS Length
> +  UINT32   AhciCmdA:1;        //ATAPI
> +  UINT32   AhciCmdW:1;        //Write
> +  UINT32   AhciCmdP:1;        //Prefetchable
> +  UINT32   AhciCmdR:1;        //Reset
> +  UINT32   AhciCmdB:1;        //BIST
> +  UINT32   AhciCmdC:1;        //Clear Busy upon R_OK
> +  UINT32   AhciCmdRsvd:1;
> +  UINT32   AhciCmdPmp:4;      //Port Multiplier Port
> +  UINT32   AhciCmdPrdtl:16;   //Physical Region Descriptor Table Length
> +  UINT32   AhciCmdPrdbc;      //Physical Region Descriptor Byte Count
> +  UINT32   AhciCmdCtba;       //Command Table Descriptor Base Address
> +  UINT32   AhciCmdCtbau;      //Command Table Descriptor Base Address
> Upper 32-BITs
> +  UINT32   AhciCmdRsvd1[4];
> +} EFI_AHCI_COMMAND_LIST;
> +
> +//
> +// This is a software constructed FIS.
> +// For Data transfer operations, this is the H2D Register FIS format as
> +// specified in the Serial ATA Revision 2.6 specification.
> +//
> +typedef struct {
> +  UINT8    AhciCFisType;
> +  UINT8    AhciCFisPmNum:4;
> +  UINT8    AhciCFisRsvd:1;
> +  UINT8    AhciCFisRsvd1:1;
> +  UINT8    AhciCFisRsvd2:1;
> +  UINT8    AhciCFisCmdInd:1;
> +  UINT8    AhciCFisCmd;
> +  UINT8    AhciCFisFeature;
> +  UINT8    AhciCFisSecNum;
> +  UINT8    AhciCFisClyLow;
> +  UINT8    AhciCFisClyHigh;
> +  UINT8    AhciCFisDevHead;
> +  UINT8    AhciCFisSecNumExp;
> +  UINT8    AhciCFisClyLowExp;
> +  UINT8    AhciCFisClyHighExp;
> +  UINT8    AhciCFisFeatureExp;
> +  UINT8    AhciCFisSecCount;
> +  UINT8    AhciCFisSecCountExp;
> +  UINT8    AhciCFisRsvd3;
> +  UINT8    AhciCFisControl;
> +  UINT8    AhciCFisRsvd4[4];
> +  UINT8    AhciCFisRsvd5[44];
> +} EFI_AHCI_COMMAND_FIS;
> +
> +//
> +// ACMD: ATAPI command (12 or 16 bytes)
> +//
> +typedef struct {
> +  UINT8    AtapiCmd[0x10];
> +} EFI_AHCI_ATAPI_COMMAND;
> +
> +//
> +// Physical Region Descriptor Table includes up to 65535 entries
> +// The entry Data structure is listed at the following.
> +// the actual entry number comes from the PRDTL field in the command
> +// list entry for this command slot.
> +//
> +typedef struct {
> +  UINT32   AhciPrdtDba;       //Data Base Address
> +  UINT32   AhciPrdtDbau;      //Data Base Address Upper 32-BITs
> +  UINT32   AhciPrdtRsvd;
> +  UINT32   AhciPrdtDbc:22;    //Data Byte Count
> +  UINT32   AhciPrdtRsvd1:9;
> +  UINT32   AhciPrdtIoc:1;     //Interrupt on Completion
> +} EFI_AHCI_COMMAND_PRDT;
> +
> +//
> +// Command table Data strucute which is pointed to by the entry in the
> command list
> +//
> +typedef struct {
> +  EFI_AHCI_COMMAND_FIS      CommandFis;       // A software
> constructed FIS.
> +  EFI_AHCI_ATAPI_COMMAND    AtapiCmd;         // 12 or 16 bytes
> ATAPI cmd.
> +  UINT8                     Reserved[0x30];
> +  EFI_AHCI_COMMAND_PRDT     PrdtTable;    // The scatter/gather list
> for Data transfer
> +} EFI_AHCI_COMMAND_TABLE;
> +
> +//
> +// Received FIS structure
> +//
> +typedef struct {
> +  UINT8    AhciDmaSetupFis[0x1C];         // Dma Setup Fis: offset 0x00
> +  UINT8    AhciDmaSetupFisRsvd[0x04];
> +  UINT8    AhciPioSetupFis[0x14];         // Pio Setup Fis: offset 0x20
> +  UINT8    AhciPioSetupFisRsvd[0x0C];
> +  UINT8    AhciD2HRegisterFis[0x14];      // D2H Register Fis: offset 0x40
> +  UINT8    AhciD2HRegisterFisRsvd[0x04];
> +  UINT64   AhciSetDeviceBitsFis;          // Set Device Bits Fix: offset 0x58
> +  UINT8    AhciUnknownFis[0x40];          // Unkonwn Fis: offset 0x60
> +  UINT8    AhciUnknownFisRsvd[0x60];
> +} EFI_AHCI_RECEIVED_FIS;
> +
> +#pragma pack()
> +
> +typedef struct {
> +  EFI_AHCI_RECEIVED_FIS     *AhciRFis;
> +  VOID                      *AhciRFisMapping;
> +  EFI_AHCI_COMMAND_LIST     *AhciCmdList;
> +  VOID                      *AhciCmdListMapping;
> +  EFI_AHCI_COMMAND_TABLE    *AhciCommandTable;
> +  VOID                      *AhciCommandTableMapping;
> +} EFI_AHCI_REGISTERS;
> +
> +typedef struct {
> +  VOID                      *Buffer;
> +  VOID                      *BufferMapping;
> +  EFI_AHCI_REGISTERS        AhciRegisters;
> +  UINT32                    AhciBar;
> +} AHCI_CONTEXT;
> +
> +/**
> +  Send Buffer cmd to specific device.
> +
> +  @param  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param  Port                The number of port.
> +  @param  PortMultiplier      The timeout Value of stop.
> +  @param  Buffer              The Data Buffer to store IDENTIFY PACKET
> Data.
> +
> +  @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for executing.
> +  @retval EFI_SUCCESS         The cmd executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciIdentify (
> +  IN AHCI_CONTEXT             *AhciContext,
> +  IN UINT8                    Port,
> +  IN UINT8                    PortMultiplier,
> +  IN OUT ATA_IDENTIFY_DATA    *Buffer
> +  );
> +
> +/**
> +  Allocate transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciAllocateResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  );
> +
> +/**
> +  Free allocated transfer-related data struct which is used at AHCI mode.
> +
> +  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +AhciFreeResource (
> +  IN OUT AHCI_CONTEXT       *AhciContext
> +  );
> +
> +/**
> +  Initialize ATA host controller at AHCI mode.
> +
> +  The function is designed to initialize ATA host controller.
> +
> +  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.
> +  @param[in]  Port          The port number to do initialization.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciModeInitialize (
> +  IN AHCI_CONTEXT    *AhciContext,
> +  IN UINT8           Port
> +  );
> +
> +typedef struct _EFI_ATA_COMMAND_BLOCK {
> +  UINT8 Reserved1[2];
> +  UINT8 AtaCommand;
> +  UINT8 AtaFeatures;
> +  UINT8 AtaSectorNumber;
> +  UINT8 AtaCylinderLow;
> +  UINT8 AtaCylinderHigh;
> +  UINT8 AtaDeviceHead;
> +  UINT8 AtaSectorNumberExp;
> +  UINT8 AtaCylinderLowExp;
> +  UINT8 AtaCylinderHighExp;
> +  UINT8 AtaFeaturesExp;
> +  UINT8 AtaSectorCount;
> +  UINT8 AtaSectorCountExp;
> +  UINT8 Reserved2[6];
> +} EFI_ATA_COMMAND_BLOCK;
> +
> +typedef struct _EFI_ATA_STATUS_BLOCK {
> +  UINT8 Reserved1[2];
> +  UINT8 AtaStatus;
> +  UINT8 AtaError;
> +  UINT8 AtaSectorNumber;
> +  UINT8 AtaCylinderLow;
> +  UINT8 AtaCylinderHigh;
> +  UINT8 AtaDeviceHead;
> +  UINT8 AtaSectorNumberExp;
> +  UINT8 AtaCylinderLowExp;
> +  UINT8 AtaCylinderHighExp;
> +  UINT8 Reserved2;
> +  UINT8 AtaSectorCount;
> +  UINT8 AtaSectorCountExp;
> +  UINT8 Reserved3[6];
> +} EFI_ATA_STATUS_BLOCK;
> +
> +/**
> +  Start a PIO Data transfer on specific port.
> +
> +  @param  AhciContext         The pointer to the AHCI_CONTEXT.
> +  @param  Port                The number of port.
> +  @param  PortMultiplier      The timeout Value of stop.
> +  @param  AtapiCommand        The atapi command will be used for the
> transfer.
> +  @param  AtapiCommandLength  The Length of the atapi command.
> +  @param  Read                The transfer direction.
> +  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.
> +  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.
> +  @param  MemoryAddr          The pointer to the Data Buffer.
> +  @param  DataCount           The Data count to be transferred.
> +  @param  Timeout             The timeout Value of non Data transfer.
> +
> +  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error
> occurs.
> +  @retval EFI_TIMEOUT         The operation is time out.
> +  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
> +  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciPioTransfer (
> +  IN     AHCI_CONTEXT               *AhciContext,
> +  IN     UINT8                      Port,
> +  IN     UINT8                      PortMultiplier,
> +  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
> +  IN     UINT8                      AtapiCommandLength,
> +  IN     BOOLEAN                    Read,
> +  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
> +  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
> +  IN OUT VOID                       *MemoryAddr,
> +  IN     UINT32                     DataCount,
> +  IN     UINT64                     Timeout
> +  );
> +
> +
> +#endif
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> new file mode 100644
> index 000000000000..62a71d9f440f
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> @@ -0,0 +1,3003 @@
> +/** @file
> +  Entrypoint of Opal UEFI Driver and contains all the logic to
> +  register for new Opal device instances.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances
> and installs an
> +// HII GUI to manage Opal features if the device is Opal capable
> +// If the Opal device is being managed by the UEFI Driver, it shall provide a
> popup
> +// window during boot requesting a user password
> +
> +#include "OpalDriver.h"
> +#include "OpalHii.h"
> +
> +EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
> +EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
> +
> +BOOLEAN                 mOpalEndOfDxe = FALSE;
> +OPAL_REQUEST_VARIABLE   *mOpalRequestVariable = NULL;
> +UINTN                   mOpalRequestVariableSize = 0;
> +CHAR16                  mPopUpString[256];
> +
> +typedef struct {
> +  UINT32                   Address;
> +  S3_BOOT_SCRIPT_LIB_WIDTH Width;
> +} OPAL_HC_PCI_REGISTER_SAVE;
> +
> +//
> +// To unlock the Intel SATA controller at S3 Resume, restored the following
> registers.
> +//
> +const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {
> +  {0x9,  S3BootScriptWidthUint8},
> +  {0x10, S3BootScriptWidthUint32},
> +  {0x14, S3BootScriptWidthUint32},
> +  {0x18, S3BootScriptWidthUint32},
> +  {0x1C, S3BootScriptWidthUint32},
> +  {0x20, S3BootScriptWidthUint32},
> +  {0x24, S3BootScriptWidthUint32},
> +  {0x3c, S3BootScriptWidthUint8},
> +  {0x3d, S3BootScriptWidthUint8},
> +  {0x40, S3BootScriptWidthUint16},
> +  {0x42, S3BootScriptWidthUint16},
> +  {0x92, S3BootScriptWidthUint16},
> +  {0x94, S3BootScriptWidthUint32},
> +  {0x9C, S3BootScriptWidthUint32},
> +  {0x4,  S3BootScriptWidthUint16},
> +};
> +
> +OPAL_DRIVER mOpalDriver;
> +
> +//
> +// Globals
> +//
> +EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {
> +  OpalEfiDriverBindingSupported,
> +  OpalEfiDriverBindingStart,
> +  OpalEfiDriverBindingStop,
> +  0x1b,
> +  NULL,
> +  NULL
> +};
> +
> +/**
> +
> +  The function determines the available actions for the OPAL_DISK provided.
> +
> +  @param[in]   SupportedAttributes   The supported attributes for the
> device.
> +  @param[in]   LockingFeature        The locking status for the device.
> +  @param[in]   OwnerShip             The ownership for the device.
> +  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate
> disk actions.
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportGetAvailableActions(
> +  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
> +  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
> +  IN  UINT16                           OwnerShip,
> +  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
> +  )
> +{
> +  BOOLEAN ExistingPassword;
> +
> +  NULL_CHECK(AvalDiskActions);
> +
> +  AvalDiskActions->AdminPass = 1;
> +  AvalDiskActions->UserPass = 0;
> +  AvalDiskActions->DisableUser = 0;
> +  AvalDiskActions->Unlock = 0;
> +
> +  //
> +  // Revert is performed on locking sp, so only allow if locking sp is enabled
> +  //
> +  if (LockingFeature->LockingEnabled) {
> +    AvalDiskActions->Revert = 1;
> +  }
> +
> +  //
> +  // Psid revert is available for any device with media encryption support
> +  // Revert is allowed for any device with media encryption support, however
> it requires
> +  //
> +  if (SupportedAttributes->MediaEncryption) {
> +
> +    //
> +    // Only allow psid revert if media encryption is enabled.
> +    // Otherwise, someone who steals a disk can psid revert the disk and the
> user Data is still
> +    // intact and accessible
> +    //
> +    AvalDiskActions->PsidRevert = 1;
> +    AvalDiskActions->RevertKeepDataForced = 0;
> +
> +    //
> +    // Secure erase is performed by generating a new encryption key
> +    // this is only available if encryption is supported
> +    //
> +    AvalDiskActions->SecureErase = 1;
> +  } else {
> +    AvalDiskActions->PsidRevert = 0;
> +    AvalDiskActions->SecureErase = 0;
> +
> +    //
> +    // If no media encryption is supported, then a revert (using password) will
> not
> +    // erase the Data (since you can't generate a new encryption key)
> +    //
> +    AvalDiskActions->RevertKeepDataForced = 1;
> +  }
> +
> +  if (LockingFeature->Locked) {
> +    AvalDiskActions->Unlock = 1;
> +  } else {
> +    AvalDiskActions->Unlock = 0;
> +  }
> +
> +  //
> +  // Only allow user to set password if an admin password exists
> +  //
> +  ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip,
> LockingFeature);
> +  AvalDiskActions->UserPass = ExistingPassword;
> +
> +  //
> +  // This will still show up even if there isn't a user, which is fine
> +  //
> +  AvalDiskActions->DisableUser = ExistingPassword;
> +
> +  return TcgResultSuccess;
> +}
> +
> +/**
> +  Enable Opal Feature for the input device.
> +
> +  @param[in]      Session            The opal session for the opal device.
> +  @param[in]      Msid               Msid
> +  @param[in]      MsidLength         Msid Length
> +  @param[in]      Password           Admin password
> +  @param[in]      PassLength         Length of password in bytes
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportEnableOpalFeature (
> +  IN OPAL_SESSION              *Session,
> +  IN VOID                      *Msid,
> +  IN UINT32                    MsidLength,
> +  IN VOID                      *Password,
> +  IN UINT32                    PassLength
> +  )
> +{
> +  TCG_RESULT   Ret;
> +
> +  NULL_CHECK(Session);
> +  NULL_CHECK(Msid);
> +  NULL_CHECK(Password);
> +
> +  Ret = OpalUtilSetAdminPasswordAsSid(
> +                          Session,
> +                          Msid,
> +                          MsidLength,
> +                          Password,
> +                          PassLength
> +                          );
> +  if (Ret == TcgResultSuccess) {
> +    //
> +    // Enable global locking range
> +    //
> +    Ret = OpalUtilSetOpalLockingRange(
> +                              Session,
> +                              Password,
> +                              PassLength,
> +
> OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,
> +                              0,
> +                              0,
> +                              TRUE,
> +                              TRUE,
> +                              FALSE,
> +                              FALSE
> +                              );
> +  }
> +
> +  return Ret;
> +}
> +
> +/**
> +  Update password for the Opal disk.
> +
> +  @param[in, out] OpalDisk          The disk to update password.
> +  @param[in]      Password          The input password.
> +  @param[in]      PasswordLength    The input password length.
> +
> +**/
> +VOID
> +OpalSupportUpdatePassword (
> +  IN OUT OPAL_DISK      *OpalDisk,
> +  IN VOID               *Password,
> +  IN UINT32             PasswordLength
> +  )
> +{
> +  CopyMem (OpalDisk->Password, Password, PasswordLength);
> +  OpalDisk->PasswordLength = (UINT8) PasswordLength;
> +}
> +
> +/**
> +  Extract device info from the device path.
> +
> +  @param[in]  DevicePath        Device path info for the device.
> +  @param[out] DevInfoLength     Device information length needed.
> +  @param[out] DevInfo           Device information extracted.
> +
> +  @return Device type.
> +
> +**/
> +UINT8
> +ExtractDeviceInfoFromDevicePath (
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
> +  OUT UINT16                    *DevInfoLength,
> +  OUT OPAL_DEVICE_COMMON        *DevInfo OPTIONAL
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath;
> +  EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath2;
> +  PCI_DEVICE_PATH               *PciDevPath;
> +  UINT8                         DeviceType;
> +  UINT8                         BusNum;
> +  OPAL_PCI_DEVICE               *PciDevice;
> +  OPAL_DEVICE_ATA               *DevInfoAta;
> +  OPAL_DEVICE_NVME              *DevInfoNvme;
> +  SATA_DEVICE_PATH              *SataDevPath;
> +  NVME_NAMESPACE_DEVICE_PATH    *NvmeDevPath;
> +
> +  ASSERT (DevicePath != NULL);
> +  ASSERT (DevInfoLength != NULL);
> +
> +  DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;
> +  *DevInfoLength = 0;
> +
> +  TmpDevPath = DevicePath;
> +
> +  //
> +  // Get device type.
> +  //
> +  while (!IsDevicePathEnd (TmpDevPath)) {
> +    if (TmpDevPath->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath->SubType == MSG_SATA_DP) {
> +      //
> +      // SATA
> +      //
> +      if (DevInfo != NULL) {
> +        SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;
> +        DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
> +        DevInfoAta->Port = SataDevPath->HBAPortNumber;
> +        DevInfoAta->PortMultiplierPort =
> SataDevPath->PortMultiplierPortNumber;
> +      }
> +      DeviceType = OPAL_DEVICE_TYPE_ATA;
> +      *DevInfoLength = sizeof (OPAL_DEVICE_ATA);
> +      break;
> +    } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {
> +      //
> +      // NVMe
> +      //
> +      if (DevInfo != NULL) {
> +        NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;
> +        DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
> +        DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;
> +      }
> +      DeviceType = OPAL_DEVICE_TYPE_NVME;
> +      *DevInfoLength = sizeof (OPAL_DEVICE_NVME);
> +      break;
> +    }
> +    TmpDevPath = NextDevicePathNode (TmpDevPath);
> +  }
> +
> +  //
> +  // Get device info.
> +  //
> +  BusNum = 0;
> +  TmpDevPath = DevicePath;
> +  TmpDevPath2 = NextDevicePathNode (DevicePath);
> +  while (!IsDevicePathEnd (TmpDevPath2)) {
> +    if (TmpDevPath->Type == HARDWARE_DEVICE_PATH &&
> TmpDevPath->SubType == HW_PCI_DP) {
> +      PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
> +      if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||
> +          (TmpDevPath2->Type == MESSAGING_DEVICE_PATH &&
> TmpDevPath2->SubType == MSG_SATA_DP)) {
> +        if (DevInfo != NULL) {
> +          PciDevice = &DevInfo->Device;
> +          PciDevice->Segment = 0;
> +          PciDevice->Bus = BusNum;
> +          PciDevice->Device = PciDevPath->Device;
> +          PciDevice->Function = PciDevPath->Function;
> +        }
> +      } else {
> +        if (DevInfo != NULL) {
> +          PciDevice = (OPAL_PCI_DEVICE *) ((UINTN) DevInfo +
> *DevInfoLength);
> +          PciDevice->Segment = 0;
> +          PciDevice->Bus = BusNum;
> +          PciDevice->Device = PciDevPath->Device;
> +          PciDevice->Function = PciDevPath->Function;
> +        }
> +        *DevInfoLength += sizeof (OPAL_PCI_DEVICE);
> +        if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH &&
> TmpDevPath2->SubType == HW_PCI_DP) {
> +          BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum,
> PciDevPath->Device, PciDevPath->Function,
> PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
> +        }
> +      }
> +    }
> +
> +    TmpDevPath  = NextDevicePathNode (TmpDevPath);
> +    TmpDevPath2 = NextDevicePathNode (TmpDevPath2);
> +  }
> +
> +  ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);
> +  return DeviceType;
> +}
> +
> +/**
> +  Save boot script for ATA OPAL device.
> +
> +  @param[in] DevInfo    Pointer to ATA Opal device information.
> +
> + **/
> +VOID
> +OpalDeviceAtaSaveBootScript (
> +  IN OPAL_DEVICE_ATA    *DevInfo
> +  )
> +{
> +  UINTN                         Bus;
> +  UINTN                         Device;
> +  UINTN                         Function;
> +  UINTN                         Index;
> +  EFI_STATUS                    Status;
> +  UINTN                         Offset;
> +  UINT64                        Address;
> +  S3_BOOT_SCRIPT_LIB_WIDTH      Width;
> +  UINT32                        Data;
> +  OPAL_HC_PCI_REGISTER_SAVE     *HcRegisterSaveListPtr;
> +  UINTN                         Count;
> +
> +  Data = 0;
> +
> +  Bus        = DevInfo->Device.Bus;
> +  Device     = DevInfo->Device.Device;
> +  Function   = DevInfo->Device.Function;
> +
> +  HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *)
> mSataHcRegisterSaveTemplate;
> +  Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof
> (OPAL_HC_PCI_REGISTER_SAVE);
> +
> +  for (Index = 0; Index < Count; Index++) {
> +    Offset  = HcRegisterSaveListPtr[Index].Address;
> +    Width   = HcRegisterSaveListPtr[Index].Width;
> +
> +    switch (Width) {
> +      case S3BootScriptWidthUint8:
> +        Data = (UINT32)PciRead8
> (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
> +        break;
> +      case S3BootScriptWidthUint16:
> +        Data = (UINT32)PciRead16
> (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
> +        break;
> +      case S3BootScriptWidthUint32:
> +        Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
> +        break;
> +      default:
> +        ASSERT (FALSE);
> +        break;
> +    }
> +
> +    Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function,
> Offset);
> +    Status  = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +}
> +
> +/**
> +  Build ATA OPAL device info and save them to LockBox.
> +
> +  @param[in] BarAddr    Bar address allocated.
> +
> + **/
> +VOID
> +BuildOpalDeviceInfoAta (
> +  IN UINT32     BarAddr
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINT8                 DeviceType;
> +  OPAL_DEVICE_ATA       *DevInfoAta;
> +  OPAL_DEVICE_ATA       *TempDevInfoAta;
> +  UINTN                 DevInfoLengthAta;
> +  UINT16                DevInfoLength;
> +  OPAL_DRIVER_DEVICE    *TmpDev;
> +
> +  //
> +  // Build ATA OPAL device info and save them to LockBox.
> +  //
> +  DevInfoLengthAta = 0;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
> +      DevInfoLengthAta += DevInfoLength;
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  if (DevInfoLengthAta == 0) {
> +    return;
> +  }
> +
> +  DevInfoAta = AllocateZeroPool (DevInfoLengthAta);
> +  ASSERT (DevInfoAta != NULL);
> +
> +  TempDevInfoAta = DevInfoAta;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
> +      ExtractDeviceInfoFromDevicePath (
> +        TmpDev->OpalDisk.OpalDevicePath,
> +        &DevInfoLength,
> +        (OPAL_DEVICE_COMMON *) TempDevInfoAta
> +        );
> +      TempDevInfoAta->Length = DevInfoLength;
> +      TempDevInfoAta->OpalBaseComId =
> TmpDev->OpalDisk.OpalBaseComId;
> +      TempDevInfoAta->BarAddr = BarAddr;
> +      CopyMem (
> +        TempDevInfoAta->Password,
> +        TmpDev->OpalDisk.Password,
> +        TmpDev->OpalDisk.PasswordLength
> +        );
> +      TempDevInfoAta->PasswordLength =
> TmpDev->OpalDisk.PasswordLength;
> +      OpalDeviceAtaSaveBootScript (TempDevInfoAta);
> +      TempDevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) TempDevInfoAta +
> DevInfoLength);
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  Status = SaveLockBox (
> +             &mOpalDeviceAtaGuid,
> +             DevInfoAta,
> +             DevInfoLengthAta
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = SetLockBoxAttributes (
> +             &mOpalDeviceAtaGuid,
> +             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ZeroMem (DevInfoAta, DevInfoLengthAta);
> +  FreePool (DevInfoAta);
> +}
> +
> +/**
> +  Build NVMe OPAL device info and save them to LockBox.
> +
> +  @param[in] BarAddr    Bar address allocated.
> +
> + **/
> +VOID
> +BuildOpalDeviceInfoNvme (
> +  IN UINT32     BarAddr
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINT8                 DeviceType;
> +  OPAL_DEVICE_NVME      *DevInfoNvme;
> +  OPAL_DEVICE_NVME      *TempDevInfoNvme;
> +  UINTN                 DevInfoLengthNvme;
> +  UINT16                DevInfoLength;
> +  OPAL_DRIVER_DEVICE    *TmpDev;
> +
> +  //
> +  // Build NVMe OPAL device info and save them to LockBox.
> +  //
> +  DevInfoLengthNvme = 0;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
> +      DevInfoLengthNvme += DevInfoLength;
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  if (DevInfoLengthNvme == 0) {
> +    return;
> +  }
> +
> +  DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);
> +  ASSERT (DevInfoNvme != NULL);
> +
> +  TempDevInfoNvme = DevInfoNvme;
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    DeviceType = ExtractDeviceInfoFromDevicePath (
> +                   TmpDev->OpalDisk.OpalDevicePath,
> +                   &DevInfoLength,
> +                   NULL
> +                   );
> +    if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
> +      ExtractDeviceInfoFromDevicePath (
> +        TmpDev->OpalDisk.OpalDevicePath,
> +        &DevInfoLength,
> +        (OPAL_DEVICE_COMMON *) TempDevInfoNvme
> +        );
> +      TempDevInfoNvme->Length = DevInfoLength;
> +      TempDevInfoNvme->OpalBaseComId =
> TmpDev->OpalDisk.OpalBaseComId;
> +      TempDevInfoNvme->BarAddr = BarAddr;
> +      CopyMem (
> +        TempDevInfoNvme->Password,
> +        TmpDev->OpalDisk.Password,
> +        TmpDev->OpalDisk.PasswordLength
> +        );
> +      TempDevInfoNvme->PasswordLength =
> TmpDev->OpalDisk.PasswordLength;
> +      TempDevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN)
> TempDevInfoNvme + DevInfoLength);
> +    }
> +
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  Status = SaveLockBox (
> +             &mOpalDeviceNvmeGuid,
> +             DevInfoNvme,
> +             DevInfoLengthNvme
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = SetLockBoxAttributes (
> +             &mOpalDeviceNvmeGuid,
> +             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ZeroMem (DevInfoNvme, DevInfoLengthNvme);
> +  FreePool (DevInfoNvme);
> +}
> +
> +/**
> +  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event
> group.
> +
> +  This is a notification function registered on
> EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
> +
> +  @param  Event        Event whose notification function is being invoked.
> +  @param  Context      Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +OpalEndOfDxeEventNotify (
> +  EFI_EVENT                               Event,
> +  VOID                                    *Context
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EFI_PHYSICAL_ADDRESS  Address;
> +  UINT64                Length;
> +  OPAL_DRIVER_DEVICE    *TmpDev;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  mOpalEndOfDxe = TRUE;
> +
> +  if (mOpalRequestVariable != NULL) {
> +    //
> +    // Free the OPAL request variable buffer here
> +    // as the OPAL requests should have been processed.
> +    //
> +    FreePool (mOpalRequestVariable);
> +    mOpalRequestVariable = NULL;
> +    mOpalRequestVariableSize = 0;
> +  }
> +
> +  //
> +  // Assume 64K size and alignment are enough.
> +  //
> +  Length = 0x10000;
> +  Address = 0xFFFFFFFF;
> +  Status = gDS->AllocateMemorySpace (
> +                  EfiGcdAllocateMaxAddressSearchBottomUp,
> +                  EfiGcdMemoryTypeMemoryMappedIo,
> +                  16,                             // 2^16: 64K
> Alignment
> +                  Length,
> +                  &Address,
> +                  gImageHandle,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  BuildOpalDeviceInfoAta ((UINT32) Address);
> +  BuildOpalDeviceInfoNvme ((UINT32) Address);
> +
> +  //
> +  // Zero passsword.
> +  //
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev != NULL) {
> +    ZeroMem (TmpDev->OpalDisk.Password,
> TmpDev->OpalDisk.PasswordLength);
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +
> +  gBS->CloseEvent (Event);
> +}
> +
> +/**
> +  Get Psid input from the popup window.
> +
> +  @param[in]  Dev           The device which need Psid to process Psid
> Revert
> +                            OPAL request.
> +  @param[in]  PopUpString   Pop up string.
> +  @param[out] PressEsc      Whether user escape function through Press
> ESC.
> +
> +  @retval Password string if success. NULL if failed.
> +
> +**/
> +CHAR8 *
> +OpalDriverPopUpPsidInput (
> +  IN OPAL_DRIVER_DEVICE     *Dev,
> +  IN CHAR16                 *PopUpString,
> +  OUT BOOLEAN               *PressEsc
> +  )
> +{
> +  EFI_INPUT_KEY             InputKey;
> +  UINTN                     InputLength;
> +  CHAR16                    Mask[PSID_CHARACTER_LENGTH + 1];
> +  CHAR16                    Unicode[PSID_CHARACTER_LENGTH + 1];
> +  CHAR8                     *Ascii;
> +
> +  ZeroMem(Unicode, sizeof(Unicode));
> +  ZeroMem(Mask, sizeof(Mask));
> +
> +  *PressEsc = FALSE;
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  InputLength = 0;
> +  while (TRUE) {
> +    Mask[InputLength] = L'_';
> +    CreatePopUp (
> +      EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +      &InputKey,
> +      PopUpString,
> +      L"---------------------",
> +      Mask,
> +      NULL
> +    );
> +
> +    //
> +    // Check key.
> +    //
> +    if (InputKey.ScanCode == SCAN_NULL) {
> +      //
> +      // password finished
> +      //
> +      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +        //
> +        // Add the null terminator.
> +        //
> +        Unicode[InputLength] = 0;
> +        Mask[InputLength] = 0;
> +        break;
> +      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
> +                 (InputKey.UnicodeChar == CHAR_TAB) ||
> +                 (InputKey.UnicodeChar == CHAR_LINEFEED)
> +                ) {
> +        continue;
> +      } else {
> +        //
> +        // delete last key entered
> +        //
> +        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
> +          if (InputLength > 0) {
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            InputLength--;
> +          }
> +        } else {
> +          //
> +          // add Next key entry
> +          //
> +          Unicode[InputLength] = InputKey.UnicodeChar;
> +          Mask[InputLength] = InputKey.UnicodeChar;
> +          InputLength++;
> +          if (InputLength == PSID_CHARACTER_LENGTH) {
> +            //
> +            // Add the null terminator.
> +            //
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            break;
> +          }
> +        }
> +      }
> +    }
> +
> +    //
> +    // exit on ESC
> +    //
> +    if (InputKey.ScanCode == SCAN_ESC) {
> +      *PressEsc = TRUE;
> +      break;
> +    }
> +  }
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
> +    return NULL;
> +  }
> +
> +  Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);
> +  if (Ascii == NULL) {
> +    ZeroMem (Unicode, sizeof (Unicode));
> +    ZeroMem (Mask, sizeof (Mask));
> +    return NULL;
> +  }
> +
> +  UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);
> +  ZeroMem (Unicode, sizeof (Unicode));
> +  ZeroMem (Mask, sizeof (Mask));
> +
> +  return Ascii;
> +}
> +
> +
> +/**
> +  Get password input from the popup window.
> +
> +  @param[in]  Dev           The device which need password to unlock or
> +                            process OPAL request.
> +  @param[in]  PopUpString1  Pop up string 1.
> +  @param[in]  PopUpString2  Pop up string 2.
> +  @param[out] PressEsc      Whether user escape function through Press
> ESC.
> +
> +  @retval Password string if success. NULL if failed.
> +
> +**/
> +CHAR8 *
> +OpalDriverPopUpPasswordInput (
> +  IN OPAL_DRIVER_DEVICE     *Dev,
> +  IN CHAR16                 *PopUpString1,
> +  IN CHAR16                 *PopUpString2,
> +  OUT BOOLEAN               *PressEsc
> +  )
> +{
> +  EFI_INPUT_KEY             InputKey;
> +  UINTN                     InputLength;
> +  CHAR16                    Mask[MAX_PASSWORD_SIZE + 1];
> +  CHAR16                    Unicode[MAX_PASSWORD_SIZE + 1];
> +  CHAR8                     *Ascii;
> +
> +  ZeroMem(Unicode, sizeof(Unicode));
> +  ZeroMem(Mask, sizeof(Mask));
> +
> +  *PressEsc = FALSE;
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  InputLength = 0;
> +  while (TRUE) {
> +    Mask[InputLength] = L'_';
> +    if (PopUpString2 == NULL) {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &InputKey,
> +        PopUpString1,
> +        L"---------------------",
> +        Mask,
> +        NULL
> +      );
> +    } else {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &InputKey,
> +        PopUpString1,
> +        PopUpString2,
> +        L"---------------------",
> +        Mask,
> +        NULL
> +      );
> +    }
> +
> +    //
> +    // Check key.
> +    //
> +    if (InputKey.ScanCode == SCAN_NULL) {
> +      //
> +      // password finished
> +      //
> +      if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +        //
> +        // Add the null terminator.
> +        //
> +        Unicode[InputLength] = 0;
> +        Mask[InputLength] = 0;
> +        break;
> +      } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
> +                 (InputKey.UnicodeChar == CHAR_TAB) ||
> +                 (InputKey.UnicodeChar == CHAR_LINEFEED)
> +                ) {
> +        continue;
> +      } else {
> +        //
> +        // delete last key entered
> +        //
> +        if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
> +          if (InputLength > 0) {
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            InputLength--;
> +          }
> +        } else {
> +          //
> +          // add Next key entry
> +          //
> +          Unicode[InputLength] = InputKey.UnicodeChar;
> +          Mask[InputLength] = L'*';
> +          InputLength++;
> +          if (InputLength == MAX_PASSWORD_SIZE) {
> +            //
> +            // Add the null terminator.
> +            //
> +            Unicode[InputLength] = 0;
> +            Mask[InputLength] = 0;
> +            break;
> +          }
> +        }
> +      }
> +    }
> +
> +    //
> +    // exit on ESC
> +    //
> +    if (InputKey.ScanCode == SCAN_ESC) {
> +      *PressEsc = TRUE;
> +      break;
> +    }
> +  }
> +
> +  gST->ConOut->ClearScreen(gST->ConOut);
> +
> +  if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
> +    return NULL;
> +  }
> +
> +  Ascii = AllocateZeroPool (MAX_PASSWORD_SIZE + 1);
> +  if (Ascii == NULL) {
> +    ZeroMem (Unicode, sizeof (Unicode));
> +    return NULL;
> +  }
> +
> +  UnicodeStrToAsciiStrS (Unicode, Ascii, MAX_PASSWORD_SIZE + 1);
> +  ZeroMem (Unicode, sizeof (Unicode));
> +
> +  return Ascii;
> +}
> +
> +/**
> +  Check if disk is locked, show popup window and ask for password if it is.
> +
> +  @param[in] Dev            The device which need to be unlocked.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +CHAR16 *
> +OpalGetPopUpString (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINTN                 StrLength;
> +
> +  StrLength = StrLen (RequestString) + 1 + MAX (StrLen (Dev->Name16),
> StrLen (L"Disk"));
> +  ASSERT (StrLength < sizeof (mPopUpString) / sizeof (CHAR16));
> +
> +  if (Dev->Name16 == NULL) {
> +    UnicodeSPrint (mPopUpString, StrLength + 1, L"%s Disk", RequestString);
> +  } else {
> +    UnicodeSPrint (mPopUpString, StrLength + 1, L"%s %s", RequestString,
> Dev->Name16);
> +  }
> +
> +  return mPopUpString;
> +}
> +
> +/**
> +  Check if disk is locked, show popup window and ask for password if it is.
> +
> +  @param[in] Dev            The device which need to be unlocked.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +OpalDriverRequestPassword (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  BOOLEAN               IsEnabled;
> +  BOOLEAN               IsLocked;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes,
> &Dev->OpalDisk.LockingFeature);
> +  if (IsEnabled) {
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +    IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes,
> &Dev->OpalDisk.LockingFeature);
> +
> +    while (Count < MAX_PASSWORD_TRY_COUNT) {
> +      Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +      if (PressEsc) {
> +        if (IsLocked) {
> +          //
> +          // Current device in the lock status and
> +          // User not input password and press ESC,
> +          // keep device in lock status and continue boot.
> +          //
> +          do {
> +            CreatePopUp (
> +              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +              &Key,
> +              L"Press ENTER to skip the request and continue boot,",
> +              L"Press ESC to input password again",
> +              NULL
> +              );
> +          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +            gST->ConOut->ClearScreen(gST->ConOut);
> +            //
> +            // Keep lock and continue boot.
> +            //
> +            return;
> +          } else {
> +            //
> +            // Let user input password again.
> +            //
> +            continue;
> +          }
> +        } else {
> +          //
> +          // Current device in the unlock status and
> +          // User not input password and press ESC,
> +          // Shutdown the device.
> +          //
> +          do {
> +            CreatePopUp (
> +              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +              &Key,
> +              L"Press ENTER to shutdown, Press ESC to input password
> again",
> +              NULL
> +              );
> +          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
> +          } else {
> +            //
> +            // Let user input password again.
> +            //
> +            continue;
> +          }
> +        }
> +      }
> +
> +      if (Password == NULL) {
> +        Count ++;
> +        continue;
> +      }
> +      PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +      if (IsLocked) {
> +        Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password,
> PasswordLen, FALSE, FALSE);
> +      } else {
> +        Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password,
> PasswordLen, TRUE, TRUE);
> +        if (Ret == TcgResultSuccess) {
> +          Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password,
> PasswordLen, FALSE, FALSE);
> +        }
> +      }
> +
> +      if (Ret == TcgResultSuccess) {
> +        OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +        DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +      } else {
> +        DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +      }
> +
> +      if (Password != NULL) {
> +        ZeroMem (Password, PasswordLen);
> +        FreePool (Password);
> +      }
> +
> +      if (Ret == TcgResultSuccess) {
> +        break;
> +      }
> +
> +      Count++;
> +
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Invalid password.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    }
> +
> +    if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Opal password retry count exceeds the limit. Must shutdown!",
> +          L"Press ENTER to shutdown",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +
> +      gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
> +    }
> +  }
> +}
> +
> +/**
> +  Process Enable Feature OPAL request.
> +
> +  @param[in] Dev            The device which has Enable Feature OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestEnableFeature (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  CHAR8                 *PasswordConfirm;
> +  UINT32                PasswordLenConfirm;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please
> type in your new password", &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please confirm your new password", &PressEsc);
> +    if (PasswordConfirm == NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
> +    if ((PasswordLen != PasswordLenConfirm) ||
> +        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Passwords are not the same.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    if (PasswordConfirm != NULL) {
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +    }
> +
> +    Ret = OpalSupportEnableOpalFeature (&Session, Dev->OpalDisk.Msid,
> Dev->OpalDisk.MsidLength, Password, PasswordLen);
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Disable User OPAL request.
> +
> +  @param[in] Dev            The device which has Disable User OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestDisableUser (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  BOOLEAN               PasswordFailed;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    Ret = OpalUtilDisableUser(&Session, Password, PasswordLen,
> &PasswordFailed);
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid password, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Psid Revert OPAL request.
> +
> +  @param[in] Dev            The device which has Psid Revert OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestPsidRevert (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Psid;
> +  UINT32                PsidLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PSID_TRY_COUNT) {
> +    Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input Psid again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input Psid again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Psid == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PsidLen = (UINT32) AsciiStrLen(Psid);
> +
> +    Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);
> +    if (Ret == TcgResultSuccess) {
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Psid != NULL) {
> +      ZeroMem (Psid, PsidLen);
> +      FreePool (Psid);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid Psid, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PSID_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal Psid retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Admin Revert OPAL request.
> +
> +  @param[in] Dev            The device which has Revert OPAL request.
> +  @param[in] KeepUserData   Whether to keep user data or not.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestRevert (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN BOOLEAN            KeepUserData,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  BOOLEAN               PasswordFailed;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&
> +        (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {
> +      //
> +      // For pyrite type device which does not support media encryption,
> +      // it does not accept "Keep User Data" parameter.
> +      // So here hardcode a FALSE for this case.
> +      //
> +      Ret = OpalUtilRevert(
> +              &Session,
> +              FALSE,
> +              Password,
> +              PasswordLen,
> +              &PasswordFailed,
> +              Dev->OpalDisk.Msid,
> +              Dev->OpalDisk.MsidLength
> +              );
> +    } else {
> +      Ret = OpalUtilRevert(
> +              &Session,
> +              KeepUserData,
> +              Password,
> +              PasswordLen,
> +              &PasswordFailed,
> +              Dev->OpalDisk.Msid,
> +              Dev->OpalDisk.MsidLength
> +              );
> +    }
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid password, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Secure Erase OPAL request.
> +
> +  @param[in] Dev            The device which has Secure Erase OPAL
> request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestSecureErase (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  BOOLEAN               PasswordFailed;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->OpalDisk.Sscp;
> +  Session.MediaId = Dev->OpalDisk.MediaId;
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL,
> &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (Password == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    Ret = OpalUtilSecureErase(&Session, Password, PasswordLen,
> &PasswordFailed);
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Invalid password, request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Set Admin Pwd OPAL request.
> +
> +  @param[in] Dev            The device which has Set Admin Pwd Feature
> OPAL request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestSetUserPwd (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *OldPassword;
> +  UINT32                OldPasswordLen;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  CHAR8                 *PasswordConfirm;
> +  UINT32                PasswordLenConfirm;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please type in your password", &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (OldPassword == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen,
> OPAL_LOCKING_SP_USER1_AUTHORITY);
> +    if (Ret == TcgResultSuccess) {
> +      DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));
> +    } else {
> +      Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen,
> OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
> +      if (Ret == TcgResultSuccess) {
> +        DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));
> +      } else {
> +        ZeroMem (OldPassword, OldPasswordLen);
> +        FreePool (OldPassword);
> +        DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Incorrect password.",
> +            L"Press ENTER to retry",
> +            NULL
> +            );
> +        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +        Count ++;
> +        continue;
> +      }
> +    }
> +
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please
> type in your new password", &PressEsc);
> +    if (Password == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please confirm your new password", &PressEsc);
> +    if (PasswordConfirm == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
> +    if ((PasswordLen != PasswordLenConfirm) ||
> +        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Passwords are not the same.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    if (PasswordConfirm != NULL) {
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +    }
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilSetUserPassword(
> +            &Session,
> +            OldPassword,
> +            OldPasswordLen,
> +            Password,
> +            PasswordLen
> +            );
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (OldPassword != NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process Set Admin Pwd OPAL request.
> +
> +  @param[in] Dev            The device which has Set Admin Pwd Feature
> OPAL request.
> +  @param[in] RequestString  Request string.
> +
> +**/
> +VOID
> +ProcessOpalRequestSetAdminPwd (
> +  IN OPAL_DRIVER_DEVICE *Dev,
> +  IN CHAR16             *RequestString
> +  )
> +{
> +  UINT8                 Count;
> +  CHAR8                 *OldPassword;
> +  UINT32                OldPasswordLen;
> +  CHAR8                 *Password;
> +  UINT32                PasswordLen;
> +  CHAR8                 *PasswordConfirm;
> +  UINT32                PasswordLenConfirm;
> +  OPAL_SESSION          Session;
> +  BOOLEAN               PressEsc;
> +  EFI_INPUT_KEY         Key;
> +  TCG_RESULT            Ret;
> +  CHAR16                *PopUpString;
> +
> +  if (Dev == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
> +
> +  PopUpString = OpalGetPopUpString (Dev, RequestString);
> +
> +  Count = 0;
> +
> +  while (Count < MAX_PASSWORD_TRY_COUNT) {
> +    OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please type in your password", &PressEsc);
> +    if (PressEsc) {
> +        do {
> +          CreatePopUp (
> +            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +            &Key,
> +            L"Press ENTER to skip the request and continue boot,",
> +            L"Press ESC to input password again",
> +            NULL
> +            );
> +        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar !=
> CHAR_CARRIAGE_RETURN));
> +
> +        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
> +          gST->ConOut->ClearScreen(gST->ConOut);
> +          return;
> +        } else {
> +          //
> +          // Let user input password again.
> +          //
> +          continue;
> +        }
> +    }
> +
> +    if (OldPassword == NULL) {
> +      Count ++;
> +      continue;
> +    }
> +    OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen,
> OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
> +    if (Ret == TcgResultSuccess) {
> +      DEBUG ((DEBUG_INFO, "Verify: Success\n"));
> +    } else {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Incorrect password.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please
> type in your new password", &PressEsc);
> +    if (Password == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLen = (UINT32) AsciiStrLen(Password);
> +
> +    PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString,
> L"Please confirm your new password", &PressEsc);
> +    if (PasswordConfirm == NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      Count ++;
> +      continue;
> +    }
> +    PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
> +    if ((PasswordLen != PasswordLenConfirm) ||
> +        (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +      do {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"Passwords are not the same.",
> +          L"Press ENTER to retry",
> +          NULL
> +          );
> +      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +      Count ++;
> +      continue;
> +    }
> +
> +    if (PasswordConfirm != NULL) {
> +      ZeroMem (PasswordConfirm, PasswordLenConfirm);
> +      FreePool (PasswordConfirm);
> +    }
> +
> +
> +    ZeroMem(&Session, sizeof(Session));
> +    Session.Sscp = Dev->OpalDisk.Sscp;
> +    Session.MediaId = Dev->OpalDisk.MediaId;
> +    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +    Ret = OpalUtilSetAdminPassword(
> +            &Session,
> +            OldPassword,
> +            OldPasswordLen,
> +            Password,
> +            PasswordLen
> +            );
> +    if (Ret == TcgResultSuccess) {
> +      OpalSupportUpdatePassword (&Dev->OpalDisk, Password,
> PasswordLen);
> +      DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
> +    } else {
> +      DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
> +    }
> +
> +    if (OldPassword != NULL) {
> +      ZeroMem (OldPassword, OldPasswordLen);
> +      FreePool (OldPassword);
> +    }
> +
> +    if (Password != NULL) {
> +      ZeroMem (Password, PasswordLen);
> +      FreePool (Password);
> +    }
> +
> +    if (Ret == TcgResultSuccess) {
> +      break;
> +    }
> +
> +    Count++;
> +
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Request failed.",
> +        L"Press ENTER to retry",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +  }
> +
> +  if (Count >= MAX_PASSWORD_TRY_COUNT) {
> +    do {
> +      CreatePopUp (
> +        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +        &Key,
> +        L"Opal password retry count exceeds the limit.",
> +        L"Press ENTER to skip the request and continue boot",
> +        NULL
> +        );
> +    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
> +    gST->ConOut->ClearScreen(gST->ConOut);
> +  }
> +}
> +
> +/**
> +  Process OPAL request.
> +
> +  @param[in] Dev            The device which has OPAL request.
> +
> +**/
> +VOID
> +ProcessOpalRequest (
> +  IN OPAL_DRIVER_DEVICE     *Dev
> +  )
> +{
> +  EFI_STATUS                Status;
> +  OPAL_REQUEST_VARIABLE     *TempVariable;
> +  OPAL_REQUEST_VARIABLE     *Variable;
> +  UINTN                     VariableSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
> +  UINTN                     DevicePathSizeInVariable;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathSize;
> +  BOOLEAN                   KeepUserData;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  if (mOpalRequestVariable == NULL) {
> +    Status = GetVariable2 (
> +               OPAL_REQUEST_VARIABLE_NAME,
> +               &gHiiSetupVariableGuid,
> +               (VOID **) &Variable,
> +               &VariableSize
> +               );
> +    if (EFI_ERROR (Status) || (Variable == NULL)) {
> +      return;
> +    }
> +    mOpalRequestVariable = Variable;
> +    mOpalRequestVariableSize = VariableSize;
> +
> +    //
> +    // Delete the OPAL request variable.
> +    //
> +    Status = gRT->SetVariable (
> +                    OPAL_REQUEST_VARIABLE_NAME,
> +                    (EFI_GUID *) &gHiiSetupVariableGuid,
> +                    0,
> +                    0,
> +                    NULL
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    Variable = mOpalRequestVariable;
> +    VariableSize = mOpalRequestVariableSize;
> +  }
> +
> +  //
> +  // Process the OPAL requests.
> +  //
> +  TempVariable = Variable;
> +  while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
> +         (VariableSize >= TempVariable->Length) &&
> +         (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
> +    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +    DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
> +    DevicePath = Dev->OpalDisk.OpalDevicePath;
> +    DevicePathSize = GetDevicePathSize (DevicePath);
> +    if ((DevicePathSize == DevicePathSizeInVariable) &&
> +        (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize)
> == 0)) {
> +      //
> +      // Found the node for the OPAL device.
> +      //
> +      if (TempVariable->OpalRequest.SetAdminPwd != 0) {
> +        ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");
> +      }
> +      if (TempVariable->OpalRequest.SetUserPwd != 0) {
> +        ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");
> +      }
> +      if (TempVariable->OpalRequest.SecureErase!= 0) {
> +        ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");
> +      }
> +      if (TempVariable->OpalRequest.Revert != 0) {
> +        KeepUserData = (BOOLEAN)
> TempVariable->OpalRequest.KeepUserData;
> +        ProcessOpalRequestRevert (
> +          Dev,
> +          KeepUserData,
> +          KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"
> +          );
> +      }
> +      if (TempVariable->OpalRequest.PsidRevert != 0) {
> +        ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");
> +      }
> +      if (TempVariable->OpalRequest.DisableUser != 0) {
> +        ProcessOpalRequestDisableUser (Dev, L"Disable User:");
> +      }
> +      if (TempVariable->OpalRequest.EnableFeature != 0) {
> +        ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");
> +      }
> +
> +      break;
> +    }
> +
> +    VariableSize -= TempVariable->Length;
> +    TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable +
> TempVariable->Length);
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Add new device to the global device list.
> +
> +  @param Dev             New create device.
> +
> +**/
> +VOID
> +AddDeviceToTail(
> +  IN OPAL_DRIVER_DEVICE    *Dev
> +  )
> +{
> +  OPAL_DRIVER_DEVICE                *TmpDev;
> +
> +  if (mOpalDriver.DeviceList == NULL) {
> +    mOpalDriver.DeviceList = Dev;
> +  } else {
> +    TmpDev = mOpalDriver.DeviceList;
> +    while (TmpDev->Next != NULL) {
> +      TmpDev = TmpDev->Next;
> +    }
> +
> +    TmpDev->Next = Dev;
> +  }
> +}
> +
> +/**
> +  Remove one device in the global device list.
> +
> +  @param Dev             The device need to be removed.
> +
> +**/
> +VOID
> +RemoveDevice (
> +  IN OPAL_DRIVER_DEVICE    *Dev
> +  )
> +{
> +  OPAL_DRIVER_DEVICE                *TmpDev;
> +
> +  if (mOpalDriver.DeviceList == NULL) {
> +    return;
> +  }
> +
> +  if (mOpalDriver.DeviceList == Dev) {
> +    mOpalDriver.DeviceList = NULL;
> +    return;
> +  }
> +
> +  TmpDev = mOpalDriver.DeviceList;
> +  while (TmpDev->Next != NULL) {
> +    if (TmpDev->Next == Dev) {
> +      TmpDev->Next = Dev->Next;
> +      break;
> +    }
> +  }
> +}
> +
> +/**
> +  Get current device count.
> +
> +  @retval  return the current created device count.
> +
> +**/
> +UINT8
> +GetDeviceCount (
> +  VOID
> +  )
> +{
> +  UINT8                Count;
> +  OPAL_DRIVER_DEVICE   *TmpDev;
> +
> +  Count = 0;
> +  TmpDev = mOpalDriver.DeviceList;
> +
> +  while (TmpDev != NULL) {
> +    Count++;
> +    TmpDev = TmpDev->Next;
> +  }
> +
> +  return Count;
> +}
> +
> +/**
> +  Get devcie list info.
> +
> +  @retval     return the device list pointer.
> +**/
> +OPAL_DRIVER_DEVICE*
> +OpalDriverGetDeviceList(
> +  VOID
> +  )
> +{
> +  return mOpalDriver.DeviceList;
> +}
> +
> +/**
> +  ReadyToBoot callback to send BlockSid command.
> +
> +  @param  Event   Pointer to this event
> +  @param  Context Event handler private Data
> +
> +**/
> +VOID
> +EFIAPI
> +ReadyToBootCallback (
> +  IN EFI_EVENT        Event,
> +  IN VOID             *Context
> +  )
> +{
> +  OPAL_DRIVER_DEVICE                         *Itr;
> +  TCG_RESULT                                 Result;
> +  OPAL_SESSION                               Session;
> +  UINT32                                     PpStorageFlag;
> +
> +  gBS->CloseEvent (Event);
> +
> +  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
> +    //
> +    // Send BlockSID command to each Opal disk
> +    //
> +    Itr = mOpalDriver.DeviceList;
> +    while (Itr != NULL) {
> +      if (Itr->OpalDisk.SupportedAttributes.BlockSid) {
> +        ZeroMem(&Session, sizeof(Session));
> +        Session.Sscp = Itr->OpalDisk.Sscp;
> +        Session.MediaId = Itr->OpalDisk.MediaId;
> +        Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
> +
> +        Result = OpalBlockSid (&Session, TRUE);  // HardwareReset must
> always be TRUE
> +        if (Result != TcgResultSuccess) {
> +          DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
> +          break;
> +        }
> +      }
> +
> +      Itr = Itr->Next;
> +    }
> +  }
> +}
> +
> +/**
> +  Stop this Controller.
> +
> +  @param  Dev               The device need to be stopped.
> +
> +**/
> +VOID
> +OpalDriverStopDevice (
> +  OPAL_DRIVER_DEVICE     *Dev
> +  )
> +{
> +  //
> +  // free each name
> +  //
> +  FreePool(Dev->Name16);
> +
> +  //
> +  // remove OPAL_DRIVER_DEVICE from the list
> +  // it updates the controllerList pointer
> +  //
> +  RemoveDevice(Dev);
> +
> +  //
> +  // close protocols that were opened
> +  //
> +  gBS->CloseProtocol(
> +    Dev->Handle,
> +    &gEfiStorageSecurityCommandProtocolGuid,
> +    gOpalDriverBinding.DriverBindingHandle,
> +    Dev->Handle
> +    );
> +
> +  gBS->CloseProtocol(
> +    Dev->Handle,
> +    &gEfiBlockIoProtocolGuid,
> +    gOpalDriverBinding.DriverBindingHandle,
> +    Dev->Handle
> +    );
> +
> +  FreePool(Dev);
> +}
> +
> +/**
> +  Get devcie name through the component name protocol.
> +
> +  @param[in]       AllHandlesBuffer   The handle buffer for current
> system.
> +  @param[in]       NumAllHandles      The number of handles for the
> handle buffer.
> +  @param[in]       Dev                The device which need to get
> name.
> +  @param[in]       UseComp1           Whether use component name
> or name2 protocol.
> +
> +  @retval     TRUE        Find the name for this device.
> +  @retval     FALSE       Not found the name for this device.
> +**/
> +BOOLEAN
> +OpalDriverGetDeviceNameByProtocol(
> +  EFI_HANDLE             *AllHandlesBuffer,
> +  UINTN                  NumAllHandles,
> +  OPAL_DRIVER_DEVICE     *Dev,
> +  BOOLEAN                UseComp1
> +  )
> +{
> +  EFI_HANDLE*                   ProtocolHandlesBuffer;
> +  UINTN                         NumProtocolHandles;
> +  EFI_STATUS                    Status;
> +  EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name
> and componentName2 have same layout
> +  EFI_GUID                      Protocol;
> +  UINTN                         StrLength;
> +  EFI_DEVICE_PATH_PROTOCOL*     TmpDevPath;
> +  UINTN                         Index1;
> +  UINTN                         Index2;
> +  EFI_HANDLE                    TmpHandle;
> +  CHAR16                        *DevName;
> +
> +  if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
> +    return FALSE;
> +  }
> +
> +  Protocol = UseComp1 ? gEfiComponentNameProtocolGuid :
> gEfiComponentName2ProtocolGuid;
> +
> +  //
> +  // Find all EFI_HANDLES with protocol
> +  //
> +  Status = gBS->LocateHandleBuffer(
> +               ByProtocol,
> +               &Protocol,
> +               NULL,
> +               &NumProtocolHandles,
> +               &ProtocolHandlesBuffer
> +               );
> +  if (EFI_ERROR(Status)) {
> +    return FALSE;
> +  }
> +
> +
> +  //
> +  // Exit early if no supported devices
> +  //
> +  if (NumProtocolHandles == 0) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Get printable name by iterating through all protocols
> +  // using the handle as the child, and iterate through all handles for the
> controller
> +  // exit loop early once found, if not found, then delete device
> +  // storage security protocol instances already exist, add them to internal list
> +  //
> +  Status = EFI_DEVICE_ERROR;
> +  for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
> +    DevName = NULL;
> +
> +    if (Dev->Name16 != NULL) {
> +      return TRUE;
> +    }
> +
> +    TmpHandle = ProtocolHandlesBuffer[Index1];
> +
> +    Status = gBS->OpenProtocol(
> +                 TmpHandle,
> +                 &Protocol,
> +                 (VOID**)&Cnp1_2,
> +                 gImageHandle,
> +                 NULL,
> +                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                 );
> +    if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
> +      continue;
> +    }
> +
> +    //
> +    // Use all handles array as controller handle
> +    //
> +    for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
> +      Status = Cnp1_2->GetControllerName(
> +                   Cnp1_2,
> +                   AllHandlesBuffer[Index2],
> +                   Dev->Handle,
> +                   LANGUAGE_ISO_639_2_ENGLISH,
> +                   &DevName
> +                   );
> +      if (EFI_ERROR(Status)) {
> +        Status = Cnp1_2->GetControllerName(
> +                     Cnp1_2,
> +                     AllHandlesBuffer[Index2],
> +                     Dev->Handle,
> +                     LANGUAGE_RFC_3066_ENGLISH,
> +                     &DevName
> +                     );
> +      }
> +      if (!EFI_ERROR(Status) && DevName != NULL) {
> +        StrLength = StrLen(DevName) + 1;        // Add one for NULL
> terminator
> +        Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
> +        ASSERT (Dev->Name16 != NULL);
> +        StrCpyS (Dev->Name16, StrLength, DevName);
> +        Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
> +        UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);
> +
> +        //
> +        // Retrieve bridge BDF info and port number or namespace depending
> on type
> +        //
> +        TmpDevPath = NULL;
> +        Status = gBS->OpenProtocol(
> +            Dev->Handle,
> +            &gEfiDevicePathProtocolGuid,
> +            (VOID**)&TmpDevPath,
> +            gImageHandle,
> +            NULL,
> +            EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +            );
> +        if (!EFI_ERROR(Status)) {
> +          Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
> +          return TRUE;
> +        }
> +
> +        if (Dev->Name16 != NULL) {
> +          FreePool(Dev->Name16);
> +          Dev->Name16 = NULL;
> +        }
> +        if (Dev->NameZ != NULL) {
> +          FreePool(Dev->NameZ);
> +          Dev->NameZ = NULL;
> +        }
> +      }
> +    }
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +  Get devcie name through the component name protocol.
> +
> +  @param[in]       Dev                The device which need to get
> name.
> +
> +  @retval     TRUE        Find the name for this device.
> +  @retval     FALSE       Not found the name for this device.
> +**/
> +BOOLEAN
> +OpalDriverGetDriverDeviceName(
> +  OPAL_DRIVER_DEVICE          *Dev
> +  )
> +{
> +  EFI_HANDLE*                  AllHandlesBuffer;
> +  UINTN                        NumAllHandles;
> +  EFI_STATUS                   Status;
> +
> +  if (Dev == NULL) {
> +    DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName
> Exiting, Dev=NULL\n"));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Iterate through ComponentName2 handles to get name, if fails, try
> ComponentName
> +  //
> +  if (Dev->Name16 == NULL) {
> +    DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
> +    //
> +    // Find all EFI_HANDLES
> +    //
> +    Status = gBS->LocateHandleBuffer(
> +                 AllHandles,
> +                 NULL,
> +                 NULL,
> +                 &NumAllHandles,
> +                 &AllHandlesBuffer
> +                 );
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n",
> Status ));
> +      return FALSE;
> +    }
> +
> +    //
> +    // Try component Name2
> +    //
> +    if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer,
> NumAllHandles, Dev, FALSE)) {
> +      DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get
> device name, try ComponentName\n"));
> +      if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer,
> NumAllHandles, Dev, TRUE)) {
> +        DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to
> get device name, skip device\n"));
> +        return FALSE;
> +      }
> +    }
> +  }
> +
> +  return TRUE;
> +}
> +
> +/**
> +  Main entry for this driver.
> +
> +  @param ImageHandle     Image Handle this driver.
> +  @param SystemTable     Pointer to SystemTable.
> +
> +  @retval EFI_SUCESS     This function always complete successfully.
> +**/
> +EFI_STATUS
> +EFIAPI
> +EfiDriverEntryPoint(
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE*  SystemTable
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  EFI_EVENT                      ReadyToBootEvent;
> +  EFI_EVENT                      EndOfDxeEvent;
> +
> +  Status = EfiLibInstallDriverBindingComponentName2 (
> +             ImageHandle,
> +             SystemTable,
> +             &gOpalDriverBinding,
> +             ImageHandle,
> +             &gOpalComponentName,
> +             &gOpalComponentName2
> +             );
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle
> failed\n"));
> +    return Status ;
> +  }
> +
> +  //
> +  // Initialize Driver object
> +  //
> +  ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
> +  mOpalDriver.Handle = ImageHandle;
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  OpalEndOfDxeEventNotify,
> +                  NULL,
> +                  &gEfiEndOfDxeEventGroupGuid,
> +                  &EndOfDxeEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // register a ReadyToBoot event callback for sending BlockSid command
> +  //
> +  Status = EfiCreateEventReadyToBootEx (
> +                  TPL_CALLBACK,
> +                  ReadyToBootCallback,
> +                  (VOID *) &ImageHandle,
> +                  &ReadyToBootEvent
> +                  );
> +
> +  //
> +  // Install Hii packages.
> +  //
> +  HiiInstall();
> +
> +  return Status;
> +}
> +
> +/**
> +  Tests to see if this driver supports a given controller.
> +
> +  This function checks to see if the controller contains an instance of the
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the
> EFI_BLOCK_IO_PROTOCL
> +  and returns EFI_SUCCESS if it does.
> +
> +  @param[in]  This                  A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> +  @param[in]  ControllerHandle      The Handle of the controller to test.
> This Handle
> +                                    must support a protocol interface
> that supplies
> +                                    an I/O abstraction to the driver.
> +  @param[in]  RemainingDevicePath  This parameter is ignored.
> +
> +  @retval EFI_SUCCESS               The device contains required
> protocols
> +  @retval EFI_ALREADY_STARTED       The device specified by
> ControllerHandle and
> +                                    RemainingDevicePath is already
> being managed by the driver
> +                                    specified by This.
> +  @retval EFI_ACCESS_DENIED         The device specified by
> ControllerHandle and
> +                                    RemainingDevicePath is already
> being managed by a different
> +                                    driver or an application that requires
> exclusive access.
> +                                    Currently not implemented.
> +  @retval EFI_UNSUPPORTED           The device does not contain
> requires protocols
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingSupported(
> +  IN EFI_DRIVER_BINDING_PROTOCOL* This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL*  SecurityCommand;
> +  EFI_BLOCK_IO_PROTOCOL*                  BlkIo;
> +
> +  if (mOpalEndOfDxe) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller
> Handle.
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiStorageSecurityCommandProtocolGuid,
> +    ( VOID ** )&SecurityCommand,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +
> +  if (Status == EFI_ALREADY_STARTED) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Close protocol and reopen in Start call
> +  //
> +  gBS->CloseProtocol(
> +      Controller,
> +      &gEfiStorageSecurityCommandProtocolGuid,
> +      This->DriverBindingHandle,
> +      Controller
> +      );
> +
> +  //
> +  // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by
> EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> +  // function APIs
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    (VOID **)&BlkIo,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));
> +    return Status;
> +  }
> +
> +  //
> +  // Close protocol and reopen in Start call
> +  //
> +  gBS->CloseProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    This->DriverBindingHandle,
> +    Controller
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Enables Opal Management on a supported device if available.
> +
> +  The start function is designed to be called after the Opal UEFI Driver has
> confirmed the
> +  "controller", which is a child Handle, contains the
> EF_STORAGE_SECURITY_COMMAND protocols.
> +  This function will complete the other necessary checks, such as verifying the
> device supports
> +  the correct version of Opal.  Upon verification, it will add the device to the
> +  Opal HII list in order to expose Opal managmeent options.
> +
> +  @param[in]  This                  A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> +  @param[in]  ControllerHandle      The Handle of the controller to start.
> This Handle
> +                                    must support a protocol interface
> that supplies
> +                                    an I/O abstraction to the driver.
> +  @param[in]  RemainingDevicePath   A pointer to the remaining portion of
> a device path.  This
> +                                    parameter is ignored by device
> drivers, and is optional for bus
> +                                    drivers. For a bus driver, if this
> parameter is NULL, then handles
> +                                    for all the children of Controller are
> created by this driver.
> +                                    If this parameter is not NULL and the
> first Device Path Node is
> +                                    not the End of Device Path Node,
> then only the Handle for the
> +                                    child device specified by the first
> Device Path Node of
> +                                    RemainingDevicePath is created by
> this driver.
> +                                    If the first Device Path Node of
> RemainingDevicePath is
> +                                    the End of Device Path Node, no
> child Handle is created by this
> +                                    driver.
> +
> +  @retval EFI_SUCCESS               Opal management was enabled.
> +  @retval EFI_DEVICE_ERROR          The device could not be started due
> to a device error.Currently not implemented.
> +  @retval EFI_OUT_OF_RESOURCES      The request could not be
> completed due to a lack of resources.
> +  @retval Others                    The driver failed to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStart(
> +  IN EFI_DRIVER_BINDING_PROTOCOL* This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_BLOCK_IO_PROTOCOL       *BlkIo;
> +  OPAL_DRIVER_DEVICE          *Dev;
> +  OPAL_DRIVER_DEVICE          *Itr;
> +  BOOLEAN                     Result;
> +
> +  Itr = mOpalDriver.DeviceList;
> +  while (Itr != NULL) {
> +    if (Controller == Itr->Handle) {
> +      return EFI_SUCCESS;
> +    }
> +    Itr = Itr->Next;
> +  }
> +
> +  //
> +  // Create internal device for tracking.  This allows all disks to be tracked
> +  // by same HII form
> +  //
> +  Dev =
> (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
> +  if (Dev == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  Dev->Handle = Controller;
> +
> +  //
> +  // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal
> supported checks
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiStorageSecurityCommandProtocolGuid,
> +    (VOID **)&Dev->Sscp,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +  if (EFI_ERROR(Status)) {
> +    FreePool(Dev);
> +    return Status;
> +  }
> +
> +  //
> +  // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by
> EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> +  // function APIs
> +  //
> +  Status = gBS->OpenProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    (VOID **)&BlkIo,
> +    This->DriverBindingHandle,
> +    Controller,
> +    EFI_OPEN_PROTOCOL_BY_DRIVER
> +    );
> +  if (EFI_ERROR(Status)) {
> +    //
> +    // Close storage security that was opened
> +    //
> +    gBS->CloseProtocol(
> +        Controller,
> +        &gEfiStorageSecurityCommandProtocolGuid,
> +        This->DriverBindingHandle,
> +        Controller
> +        );
> +
> +    FreePool(Dev);
> +    return Status;
> +  }
> +
> +  //
> +  // Save mediaId
> +  //
> +  Dev->MediaId = BlkIo->Media->MediaId;
> +
> +  gBS->CloseProtocol(
> +    Controller,
> +    &gEfiBlockIoProtocolGuid,
> +    This->DriverBindingHandle,
> +    Controller
> +    );
> +
> +  //
> +  // Acquire Ascii printable name of child, if not found, then ignore device
> +  //
> +  Result = OpalDriverGetDriverDeviceName (Dev);
> +  if (!Result) {
> +    goto Done;
> +  }
> +
> +  Status = OpalDiskInitialize (Dev);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  AddDeviceToTail(Dev);
> +
> +  //
> +  // Check if device is locked and prompt for password.
> +  //
> +  OpalDriverRequestPassword (Dev, L"Unlock:");
> +
> +  //
> +  // Process OPAL request from last boot.
> +  //
> +  ProcessOpalRequest (Dev);
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  //
> +  // free device, close protocols and exit
> +  //
> +  gBS->CloseProtocol(
> +      Controller,
> +      &gEfiStorageSecurityCommandProtocolGuid,
> +      This->DriverBindingHandle,
> +      Controller
> +      );
> +
> +  FreePool(Dev);
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> +  Stop this driver on Controller.
> +
> +  @param  This              Protocol instance pointer.
> +  @param  Controller        Handle of device to stop driver on
> +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If
> number of
> +                            children is zero stop the entire bus driver.
> +  @param  ChildHandleBuffer List of Child Handles to Stop.
> +
> +  @retval EFI_SUCCESS       This driver is removed Controller.
> +  @retval other             This driver could not be removed from this
> device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStop(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  UINTN                           NumberOfChildren,
> +  EFI_HANDLE*                     ChildHandleBuffer
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*   Itr;
> +
> +  Itr = mOpalDriver.DeviceList;
> +
> +  //
> +  // does Controller match any of the devices we are managing for Opal
> +  //
> +  while (Itr != NULL) {
> +    if (Itr->Handle == Controller) {
> +      OpalDriverStopDevice (Itr);
> +      return EFI_SUCCESS;
> +    }
> +
> +    Itr = Itr->Next;
> +  }
> +
> +  return EFI_NOT_FOUND;
> +}
> +
> +
> +/**
> +  Unloads UEFI Driver.  Very useful for debugging and testing.
> +
> +  @param ImageHandle            Image Handle this driver.
> +
> +  @retval EFI_SUCCESS           This function always complete
> successfully.
> +  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverUnload (
> +  IN EFI_HANDLE ImageHandle
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  OPAL_DRIVER_DEVICE                   *Itr;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (ImageHandle != gImageHandle) {
> +    return (EFI_INVALID_PARAMETER);
> +  }
> +
> +  //
> +  // Uninstall any interface added to each device by us
> +  //
> +  while (mOpalDriver.DeviceList) {
> +    Itr = mOpalDriver.DeviceList;
> +    //
> +    // Remove OPAL_DRIVER_DEVICE from the list
> +    // it updates the controllerList pointer
> +    //
> +    OpalDriverStopDevice(Itr);
> +  }
> +
> +  //
> +  // Uninstall the HII capability
> +  //
> +  Status = HiiUninstall();
> +
> +  return Status;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> new file mode 100644
> index 000000000000..a66b5a5345ff
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> @@ -0,0 +1,613 @@
> +/** @file
> +  Values defined and used by the Opal UEFI Driver.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_DRIVER_H_
> +#define _OPAL_DRIVER_H_
> +
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Protocol/PciIo.h>
> +#include <Protocol/SmmCommunication.h>
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/DevicePathToText.h>
> +#include <Protocol/StorageSecurityCommand.h>
> +
> +#include <Guid/EventGroup.h>
> +
> +#include <Library/UefiLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/UefiHiiServicesLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Library/LockBoxLib.h>
> +#include <Library/TcgStorageOpalLib.h>
> +#include <Library/Tcg2PhysicalPresenceLib.h>
> +
> +#include "OpalPasswordCommon.h"
> +#include "OpalHiiFormValues.h"
> +
> +#define EFI_DRIVER_NAME_UNICODE L"1.0 UEFI Opal Driver"
> +
> +// UEFI 2.1
> +#define LANGUAGE_RFC_3066_ENGLISH ((CHAR8*)"en")
> +
> +// UEFI/EFI < 2.1
> +#define LANGUAGE_ISO_639_2_ENGLISH ((CHAR8*)"eng")
> +
> +#define CONCAT_(x, y) x ## y
> +#define CONCAT(x, y) CONCAT_(x, y)
> +
> +#define UNICODE_STR(x) CONCAT( L, x )
> +
> +extern EFI_DRIVER_BINDING_PROTOCOL   gOpalDriverBinding;
> +extern EFI_COMPONENT_NAME_PROTOCOL   gOpalComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL  gOpalComponentName2;
> +
> +#define OPAL_MSID_LENGHT        128
> +
> +#define MAX_PASSWORD_SIZE       32
> +#define MAX_PASSWORD_TRY_COUNT  5
> +
> +// PSID Length
> +#define PSID_CHARACTER_LENGTH   0x20
> +#define MAX_PSID_TRY_COUNT      5
> +
> +#pragma pack(1)
> +
> +//
> +// Structure that is used to represent the available actions for an OpalDisk.
> +// The data can then be utilized to expose/hide certain actions available to an
> end user
> +// by the consumer of this library.
> +//
> +typedef struct {
> +    //
> +    // Indicates if the disk can support PSID Revert action.  should verify disk
> supports PSID authority
> +    //
> +    UINT16 PsidRevert : 1;
> +
> +    //
> +    // Indicates if the disk can support Revert action
> +    //
> +    UINT16 Revert : 1;
> +
> +    //
> +    // Indicates if the user must keep data for revert action.  It is true if no
> media encryption is supported.
> +    //
> +    UINT16 RevertKeepDataForced : 1;
> +
> +    //
> +    // Indicates if the disk can support set Admin password
> +    //
> +    UINT16 AdminPass : 1;
> +
> +    //
> +    // Indicates if the disk can support set User password.  This action
> requires that a user
> +    // password is first enabled.
> +    //
> +    UINT16 UserPass : 1;
> +
> +    //
> +    // Indicates if unlock action is available.  Requires disk to be currently
> locked.
> +    //
> +    UINT16 Unlock : 1;
> +
> +    //
> +    // Indicates if Secure Erase action is available.  Action requires admin
> credentials and media encryption support.
> +    //
> +    UINT16 SecureErase : 1;
> +
> +    //
> +    // Indicates if Disable User action is available.  Action requires admin
> credentials.
> +    //
> +    UINT16 DisableUser : 1;
> +} OPAL_DISK_ACTIONS;
> +
> +//
> +// Structure that is used to represent an OPAL_DISK.
> +//
> +typedef struct {
> +  UINT32                                          MsidLength;
> // Byte length of MSID Pin for device
> +  UINT8
> Msid[OPAL_MSID_LENGHT]; // MSID Pin for device
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;
> +  UINT32                                          MediaId;
> // MediaId is used by Ssc Protocol.
> +  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
> +  UINT16                                          OpalBaseComId;
> // Opal SSC 1 base com id.
> +  OPAL_OWNER_SHIP                                 Owner;
> +  OPAL_DISK_SUPPORT_ATTRIBUTE
> SupportedAttributes;
> +  TCG_LOCKING_FEATURE_DESCRIPTOR                  LockingFeature;
> // Locking Feature Descriptor retrieved from performing a Level 0 Discovery
> +  UINT8                                           PasswordLength;
> +  UINT8
> Password[MAX_PASSWORD_SIZE];
> +} OPAL_DISK;
> +
> +//
> +// Device with block IO protocol
> +//
> +typedef struct _OPAL_DRIVER_DEVICE OPAL_DRIVER_DEVICE;
> +
> +struct _OPAL_DRIVER_DEVICE {
> +  OPAL_DRIVER_DEVICE                              *Next;
> ///< Linked list pointer
> +  EFI_HANDLE                                      Handle;
> ///< Device handle
> +  OPAL_DISK                                       OpalDisk;
> ///< User context
> +  CHAR16                                          *Name16;
> ///< Allocated/freed by UEFI Filter Driver at device creation/removal
> +  CHAR8                                           *NameZ;
> ///< Allocated/freed by UEFI Filter Driver at device creation/removal
> +  UINT32                                          MediaId;
> ///< Required parameter for EFI_STORAGE_SECURITY_COMMAND_PROTOCOL,
> from BLOCK_IO_MEDIA
> +
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL           *Sscp;
> /// Device protocols consumed
> +  EFI_DEVICE_PATH_PROTOCOL                        *OpalDevicePath;
> +};
> +
> +//
> +// Opal Driver UEFI Driver Model
> +//
> +typedef struct {
> +  EFI_HANDLE           Handle;              ///< Driver image handle
> +  OPAL_DRIVER_DEVICE   *DeviceList;         ///< Linked list of controllers
> owned by this Driver
> +} OPAL_DRIVER;
> +
> +#pragma pack()
> +
> +//
> +// Retrieves a OPAL_DRIVER_DEVICE based on the pointer to its StorageSecurity
> protocol.
> +//
> +#define DRIVER_DEVICE_FROM_OPALDISK(OpalDiskPointer)
> (OPAL_DRIVER_DEVICE*)(BASE_CR(OpalDiskPointer, OPAL_DRIVER_DEVICE,
> OpalDisk))
> +
> +/**
> +  Get devcie list info.
> +
> +  @retval     return the device list pointer.
> +**/
> +OPAL_DRIVER_DEVICE*
> +OpalDriverGetDeviceList(
> +  VOID
> +  );
> +
> +/**
> +  Get devcie name through the component name protocol.
> +
> +  @param[in]       Dev                The device which need to get
> name.
> +
> +  @retval     TRUE        Find the name for this device.
> +  @retval     FALSE       Not found the name for this device.
> +**/
> +BOOLEAN
> +OpalDriverGetDriverDeviceName(
> +  OPAL_DRIVER_DEVICE          *Dev
> +  );
> +
> +/**
> +  Get current device count.
> +
> +  @retval  return the current created device count.
> +
> +**/
> +UINT8
> +GetDeviceCount (
> +  VOID
> +  );
> +
> +/**
> +  Update password for the Opal disk.
> +
> +  @param[in, out] OpalDisk          The disk to update password.
> +  @param[in]      Password          The input password.
> +  @param[in]      PasswordLength    The input password length.
> +
> +**/
> +VOID
> +OpalSupportUpdatePassword (
> +  IN OUT OPAL_DISK      *OpalDisk,
> +  IN VOID               *Password,
> +  IN UINT32             PasswordLength
> +  );
> +
> +/**
> +
> +  The function performs determines the available actions for the OPAL_DISK
> provided.
> +
> +  @param[in]   SupportedAttributes   The support attribute for the device.
> +  @param[in]   LockingFeature        The locking status for the device.
> +  @param[in]   OwnerShip             The ownership for the device.
> +  @param[out]  AvalDiskActions       Pointer to fill-out with appropriate
> disk actions.
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportGetAvailableActions(
> +  IN  OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
> +  IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature,
> +  IN  UINT16                           OwnerShip,
> +  OUT OPAL_DISK_ACTIONS                *AvalDiskActions
> +  );
> +
> +/**
> +  Enable Opal Feature for the input device.
> +
> +  @param[in]      Session            The opal session for the opal device.
> +  @param[in]      Msid               Msid
> +  @param[in]      MsidLength         Msid Length
> +  @param[in]      Password           Admin password
> +  @param[in]      PassLength         Length of password in bytes
> +
> +**/
> +TCG_RESULT
> +EFIAPI
> +OpalSupportEnableOpalFeature (
> +  IN OPAL_SESSION              *Session,
> +  IN VOID                      *Msid,
> +  IN UINT32                    MsidLength,
> +  IN VOID                      *Password,
> +  IN UINT32                    PassLength
> +  );
> +
> +/**
> +  Unloads UEFI Driver.  Very useful for debugging and testing.
> +
> +  @param ImageHandle            Image handle this driver.
> +
> +  @retval EFI_SUCCESS           This function always complete
> successfully.
> +  @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
> +**/
> +EFI_STATUS
> +EFIAPI
> +EfiDriverUnload(
> +  EFI_HANDLE ImageHandle
> +  );
> +
> +
> +/**
> +  Test to see if this driver supports Controller.
> +
> +  @param  This                Protocol instance pointer.
> +  @param  ControllerHandle    Handle of device to test
> +  @param  RemainingDevicePath Optional parameter use to pick a specific
> child
> +                              device to start.
> +
> +  @retval EFI_SUCCESS         This driver supports this device.
> +  @retval EFI_ALREADY_STARTED This driver is already running on this device.
> +  @retval other               This driver does not support this device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingSupported(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
> +  );
> +
> +/**
> +  Enables Opal Management on a supported device if available.
> +
> +  The start function is designed to be called after the Opal UEFI Driver has
> confirmed the
> +  "controller", which is a child handle, contains the
> EF_STORAGE_SECURITY_COMMAND protocols.
> +  This function will complete the other necessary checks, such as verifying the
> device supports
> +  the correct version of Opal.  Upon verification, it will add the device to the
> +  Opal HII list in order to expose Opal managmeent options.
> +
> +  @param[in]  This                  A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> +  @param[in]  ControllerHandle      The handle of the controller to start.
> This handle
> +                                    must support a protocol interface
> that supplies
> +                                    an I/O abstraction to the driver.
> +  @param[in]  RemainingDevicePath   A pointer to the remaining portion of
> a device path.  This
> +                                    parameter is ignored by device
> drivers, and is optional for bus
> +                                    drivers. For a bus driver, if this
> parameter is NULL, then handles
> +                                    for all the children of Controller are
> created by this driver.
> +                                    If this parameter is not NULL and the
> first Device Path Node is
> +                                    not the End of Device Path Node,
> then only the handle for the
> +                                    child device specified by the first
> Device Path Node of
> +                                    RemainingDevicePath is created by
> this driver.
> +                                    If the first Device Path Node of
> RemainingDevicePath is
> +                                    the End of Device Path Node, no
> child handle is created by this
> +                                    driver.
> +
> +  @retval EFI_SUCCESS               Opal management was enabled.
> +  @retval EFI_DEVICE_ERROR          The device could not be started due
> to a device error.Currently not implemented.
> +  @retval EFI_OUT_OF_RESOURCES      The request could not be
> completed due to a lack of resources.
> +  @retval Others                    The driver failed to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStart(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  EFI_DEVICE_PATH_PROTOCOL*       RemainingDevicePath
> +  );
> +
> +/**
> +  Stop this driver on Controller.
> +
> +  @param  This              Protocol instance pointer.
> +  @param  Controller        Handle of device to stop driver on
> +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If
> number of
> +                            children is zero stop the entire bus driver.
> +  @param  ChildHandleBuffer List of Child Handles to Stop.
> +
> +  @retval EFI_SUCCESS       This driver is removed Controller.
> +  @retval other             This driver could not be removed from this
> device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverBindingStop(
> +  EFI_DRIVER_BINDING_PROTOCOL*    This,
> +  EFI_HANDLE                      Controller,
> +  UINTN                           NumberOfChildren,
> +  EFI_HANDLE*                     ChildHandleBuffer
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetDriverName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentNameGetControllerName(
> +  EFI_COMPONENT_NAME_PROTOCOL*    This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language. This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to
> return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified
> by
> +                                This and the language specified by
> Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetDriverName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  CHAR8*                          Language,
> +  CHAR16**                        DriverName
> +  );
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL
> instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This
> handle
> +                                specifies the controller whose name is to
> be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to
> retrieve
> +                                the name of.  This is an optional
> parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of
> a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII
> string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the
> caller is
> +                                requesting, and it must match one of the
> +                                languages specified in
> SupportedLanguages. The
> +                                number of languages supported by a
> driver is up
> +                                to the driver writer. Language is specified
> in
> +                                RFC 4646 or ISO 639-2 language code
> format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle
> and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the
> driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable
> name in
> +                                the language specified by Language for
> the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not
> currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalEfiDriverComponentName2GetControllerName(
> +  EFI_COMPONENT_NAME2_PROTOCOL*   This,
> +  EFI_HANDLE                      ControllerHandle,
> +  EFI_HANDLE                      ChildHandle,
> +  CHAR8*                          Language,
> +  CHAR16**                        ControllerName
> +  );
> +
> +#endif //_OPAL_DRIVER_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
> new file mode 100644
> index 000000000000..e4972227b669
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
> @@ -0,0 +1,1178 @@
> +/** @file
> +  Implementation of the HII for the Opal UEFI Driver.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalHii.h"
> +
> +//
> +// This is the generated IFR binary Data for each formset defined in VFR.
> +// This Data array is ready to be used as input of HiiAddPackages() to
> +// create a packagelist (which contains Form packages, String packages, etc).
> +//
> +extern UINT8  OpalPasswordFormBin[];
> +
> +//
> +// This is the generated String package Data for all .UNI files.
> +// This Data array is ready to be used as input of HiiAddPackages() to
> +// create a packagelist (which contains Form packages, String packages, etc).
> +//
> +extern UINT8  OpalPasswordDxeStrings[];
> +
> +CHAR16  OpalPasswordStorageName[] = L"OpalHiiConfig";
> +
> +EFI_HII_CONFIG_ACCESS_PROTOCOL gHiiConfigAccessProtocol;
> +
> +//
> +// Handle to the list of HII packages (forms and strings) for this driver
> +//
> +EFI_HII_HANDLE gHiiPackageListHandle = NULL;
> +
> +//
> +// Package List GUID containing all form and string packages
> +//
> +const EFI_GUID gHiiPackageListGuid = PACKAGE_LIST_GUID;
> +const EFI_GUID gHiiSetupVariableGuid = SETUP_VARIABLE_GUID;
> +
> +//
> +// Structure that contains state of the HII
> +// This structure is updated by Hii.cpp and its contents
> +// is rendered in the HII.
> +//
> +OPAL_HII_CONFIGURATION gHiiConfiguration;
> +
> +//
> +// The device path containing the VENDOR_DEVICE_PATH and
> EFI_DEVICE_PATH_PROTOCOL
> +//
> +HII_VENDOR_DEVICE_PATH gHiiVendorDevicePath = {
> +    {
> +        {
> +            HARDWARE_DEVICE_PATH,
> +            HW_VENDOR_DP,
> +            {
> +                (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
> +                (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
> +            }
> +        },
> +        OPAL_PASSWORD_CONFIG_GUID
> +    },
> +    {
> +        END_DEVICE_PATH_TYPE,
> +        END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +        {
> +            (UINT8)(END_DEVICE_PATH_LENGTH),
> +            (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
> +        }
> +    }
> +};
> +
> +/**
> +  Get saved OPAL request.
> +
> +  @param[in]  OpalDisk      The disk needs to get the saved OPAL request.
> +  @param[out] OpalRequest   OPAL request got.
> +
> +**/
> +VOID
> +GetSavedOpalRequest (
> +  IN OPAL_DISK              *OpalDisk,
> +  OUT OPAL_REQUEST          *OpalRequest
> +  )
> +{
> +  EFI_STATUS                Status;
> +  OPAL_REQUEST_VARIABLE     *TempVariable;
> +  OPAL_REQUEST_VARIABLE     *Variable;
> +  UINTN                     VariableSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
> +  UINTN                     DevicePathSizeInVariable;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathSize;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  Variable = NULL;
> +  VariableSize = 0;
> +
> +  Status = GetVariable2 (
> +             OPAL_REQUEST_VARIABLE_NAME,
> +             &gHiiSetupVariableGuid,
> +             (VOID **) &Variable,
> +             &VariableSize
> +             );
> +  if (EFI_ERROR (Status) || (Variable == NULL)) {
> +    return;
> +  }
> +
> +  TempVariable = Variable;
> +  while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
> +         (VariableSize >= TempVariable->Length) &&
> +         (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
> +    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +    DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
> +    DevicePath = OpalDisk->OpalDevicePath;
> +    DevicePathSize = GetDevicePathSize (DevicePath);
> +    if ((DevicePathSize == DevicePathSizeInVariable) &&
> +        (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize)
> == 0)) {
> +      //
> +      // Found the node for the OPAL device.
> +      // Get the OPAL request.
> +      //
> +      CopyMem (OpalRequest, &TempVariable->OpalRequest, sizeof
> (OPAL_REQUEST));
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "OpalRequest got: 0x%x\n",
> +        *OpalRequest
> +        ));
> +      break;
> +    }
> +    VariableSize -= TempVariable->Length;
> +    TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable +
> TempVariable->Length);
> +  }
> +
> +  FreePool (Variable);
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Save OPAL request.
> +
> +  @param[in] OpalDisk       The disk has OPAL request to save.
> +  @param[in] OpalRequest    OPAL request to save.
> +
> +**/
> +VOID
> +SaveOpalRequest (
> +  IN OPAL_DISK              *OpalDisk,
> +  IN OPAL_REQUEST           OpalRequest
> +  )
> +{
> +  EFI_STATUS                Status;
> +  OPAL_REQUEST_VARIABLE     *TempVariable;
> +  UINTN                     TempVariableSize;
> +  OPAL_REQUEST_VARIABLE     *Variable;
> +  UINTN                     VariableSize;
> +  OPAL_REQUEST_VARIABLE     *NewVariable;
> +  UINTN                     NewVariableSize;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInVariable;
> +  UINTN                     DevicePathSizeInVariable;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathSize;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "OpalRequest to save: 0x%x\n",
> +    OpalRequest
> +    ));
> +
> +  Variable = NULL;
> +  VariableSize = 0;
> +  NewVariable = NULL;
> +  NewVariableSize = 0;
> +
> +  Status = GetVariable2 (
> +             OPAL_REQUEST_VARIABLE_NAME,
> +             &gHiiSetupVariableGuid,
> +             (VOID **) &Variable,
> +             &VariableSize
> +             );
> +  if (!EFI_ERROR (Status) && (Variable != NULL)) {
> +    TempVariable = Variable;
> +    TempVariableSize = VariableSize;
> +    while ((TempVariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
> +           (TempVariableSize >= TempVariable->Length) &&
> +           (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
> +      DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +      DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
> +      DevicePath = OpalDisk->OpalDevicePath;
> +      DevicePathSize = GetDevicePathSize (DevicePath);
> +      if ((DevicePathSize == DevicePathSizeInVariable) &&
> +          (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize)
> == 0)) {
> +        //
> +        // Found the node for the OPAL device.
> +        // Update the OPAL request.
> +        //
> +        CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof
> (OPAL_REQUEST));
> +        NewVariable = Variable;
> +        NewVariableSize = VariableSize;
> +        break;
> +      }
> +      TempVariableSize -= TempVariable->Length;
> +      TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable +
> TempVariable->Length);
> +    }
> +    if (NewVariable == NULL) {
> +      //
> +      // The node for the OPAL device is not found.
> +      // Create node for the OPAL device.
> +      //
> +      DevicePath = OpalDisk->OpalDevicePath;
> +      DevicePathSize = GetDevicePathSize (DevicePath);
> +      NewVariableSize = VariableSize + sizeof (OPAL_REQUEST_VARIABLE) +
> DevicePathSize;
> +      NewVariable = AllocatePool (NewVariableSize);
> +      ASSERT (NewVariable != NULL);
> +      CopyMem (NewVariable, Variable, VariableSize);
> +      TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) NewVariable +
> VariableSize);
> +      TempVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) +
> DevicePathSize);
> +      CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof
> (OPAL_REQUEST));
> +      DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +      CopyMem (DevicePathInVariable, DevicePath, DevicePathSize);
> +    }
> +  } else {
> +    DevicePath = OpalDisk->OpalDevicePath;
> +    DevicePathSize = GetDevicePathSize (DevicePath);
> +    NewVariableSize = sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize;
> +    NewVariable = AllocatePool (NewVariableSize);
> +    ASSERT (NewVariable != NULL);
> +    NewVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) +
> DevicePathSize);
> +    CopyMem (&NewVariable->OpalRequest, &OpalRequest, sizeof
> (OPAL_REQUEST));
> +    DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN)
> NewVariable + sizeof (OPAL_REQUEST_VARIABLE));
> +    CopyMem (DevicePathInVariable, DevicePath, DevicePathSize);
> +  }
> +  Status = gRT->SetVariable (
> +                  OPAL_REQUEST_VARIABLE_NAME,
> +                  (EFI_GUID *) &gHiiSetupVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  NewVariableSize,
> +                  NewVariable
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_INFO, "OpalRequest variable set failed (%r)\n", Status));
> +  }
> +  if (NewVariable != Variable) {
> +    FreePool (NewVariable);
> +  }
> +  if (Variable != NULL) {
> +    FreePool (Variable);
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Sets the current system state of global config variables.
> +
> +**/
> +VOID
> +HiiSetCurrentConfiguration(
> +  VOID
> +  )
> +{
> +  UINT32                                       PpStorageFlag;
> +  EFI_STRING                                   NewString;
> +
> +  gHiiConfiguration.NumDisks = GetDeviceCount();
> +
> +  //
> +  // Update the BlockSID status string.
> +  //
> +  PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
> +
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_ENABLED), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  } else {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISABLED), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  }
> +  HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_BLOCKSID_STATUS1), NewString, NULL);
> +  FreePool (NewString);
> +
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BL
> OCK_SID) != 0) {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  } else {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  }
> +  HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_BLOCKSID_STATUS2), NewString, NULL);
> +  FreePool (NewString);
> +
> +  if ((PpStorageFlag &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BL
> OCK_SID) != 0) {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  } else {
> +    NewString = HiiGetString (gHiiPackageListHandle,
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), NULL);
> +    if (NewString == NULL) {
> +      DEBUG ((DEBUG_INFO,  "HiiSetCurrentConfiguration: HiiGetString( )
> failed\n"));
> +      return;
> +    }
> +  }
> +  HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_BLOCKSID_STATUS3), NewString, NULL);
> +  FreePool (NewString);
> +}
> +
> +/**
> +  Install the HII related resources.
> +
> +  @retval  EFI_SUCCESS        Install all the resources success.
> +  @retval  other              Error occur when install the resources.
> +**/
> +EFI_STATUS
> +HiiInstall(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_HANDLE                   DriverHandle;
> +
> +  //
> +  // Clear the global configuration.
> +  //
> +  ZeroMem(&gHiiConfiguration, sizeof(gHiiConfiguration));
> +
> +  //
> +  // Obtain the driver handle that the BIOS assigned us
> +  //
> +  DriverHandle = HiiGetDriverImageHandleCB();
> +
> +  //
> +  // Populate the config access protocol with the three functions we are
> publishing
> +  //
> +  gHiiConfigAccessProtocol.ExtractConfig = ExtractConfig;
> +  gHiiConfigAccessProtocol.RouteConfig = RouteConfig;
> +  gHiiConfigAccessProtocol.Callback = DriverCallback;
> +
> +  //
> +  // Associate the required protocols with our driver handle
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces(
> +               &DriverHandle,
> +               &gEfiHiiConfigAccessProtocolGuid,
> +               &gHiiConfigAccessProtocol,      // HII callback
> +               &gEfiDevicePathProtocolGuid,
> +               &gHiiVendorDevicePath,        // required for HII callback
> allow all disks to be shown in same hii
> +               NULL
> +           );
> +
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  return OpalHiiAddPackages();
> +}
> +
> +/**
> +  Install the HII form and string packages.
> +
> +  @retval  EFI_SUCCESS           Install all the resources success.
> +  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
> +**/
> +EFI_STATUS
> +OpalHiiAddPackages(
> +  VOID
> +  )
> +{
> +  EFI_HANDLE                   DriverHandle;
> +  CHAR16                       *NewString;
> +
> +  DriverHandle = HiiGetDriverImageHandleCB();
> +
> +  //
> +  // Publish the HII form and HII string packages
> +  //
> +  gHiiPackageListHandle = HiiAddPackages(
> +                                &gHiiPackageListGuid,
> +                                DriverHandle,
> +                                OpalPasswordDxeStrings,
> +                                OpalPasswordFormBin,
> +                                (VOID*)NULL
> +                                );
> +
> +  //
> +  // Make sure the packages installed successfully
> +  //
> +  if (gHiiPackageListHandle == NULL) {
> +    DEBUG ((DEBUG_INFO, "OpalHiiAddPackages failed\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Update Version String in main window
> +  //
> +  NewString = HiiGetDriverNameCB ();
> +  if (HiiSetString(gHiiPackageListHandle,
> STRING_TOKEN(STR_MAIN_OPAL_VERSION), NewString, NULL) == 0) {
> +    DEBUG ((DEBUG_INFO,  "OpalHiiAddPackages: HiiSetString( ) failed\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Uninstall the HII capability.
> +
> +  @retval  EFI_SUCCESS           Uninstall all the resources success.
> +  @retval  others                Other errors occur when unistall the hii
> resource.
> +**/
> +EFI_STATUS
> +HiiUninstall(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +
> +  //
> +  // Remove the packages we've provided to the BIOS
> +  //
> +  HiiRemovePackages(gHiiPackageListHandle);
> +
> +  //
> +  // Remove the protocols from our driver handle
> +  //
> +  Status = gBS->UninstallMultipleProtocolInterfaces(
> +                          HiiGetDriverImageHandleCB(),
> +                          &gEfiHiiConfigAccessProtocolGuid,
> +                          &gHiiConfigAccessProtocol,        // HII
> callback
> +                          &gEfiDevicePathProtocolGuid,
> +                          &gHiiVendorDevicePath,            //
> required for HII callback
> +                          NULL
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_INFO, "Cannot uninstall Hii Protocols: %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Updates the main menu form.
> +
> +  @retval  EFI_SUCCESS           update the main form success.
> +**/
> +EFI_STATUS
> +HiiPopulateMainMenuForm (
> +  VOID
> +  )
> +{
> +  UINT8         Index;
> +  CHAR8         *DiskName;
> +  EFI_STRING_ID DiskNameId;
> +  OPAL_DISK     *OpalDisk;
> +
> +  HiiSetCurrentConfiguration();
> +
> +  gHiiConfiguration.SupportedDisks = 0;
> +
> +  for (Index = 0; Index < gHiiConfiguration.NumDisks; Index++) {
> +    OpalDisk = HiiGetOpalDiskCB (Index);
> +    if ((OpalDisk != NULL) && OpalFeatureSupported
> (&OpalDisk->SupportedAttributes)) {
> +      gHiiConfiguration.SupportedDisks |= (1 << Index);
> +      DiskNameId = GetDiskNameStringId (Index);
> +      DiskName = HiiDiskGetNameCB (Index);
> +      if ((DiskName == NULL) || (DiskNameId == 0)) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      HiiSetFormString(DiskNameId, DiskName);
> +    }
> +  }
> +
> +  OpalHiiSetBrowserData ();
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get disk name string id.
> +
> +  @param   DiskIndex             The input disk index info.
> +
> +  @retval  The disk name string id.
> +
> +**/
> +EFI_STRING_ID
> +GetDiskNameStringId(
> +  UINT8 DiskIndex
> +  )
> +{
> +  switch (DiskIndex) {
> +    case 0: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0);
> +    case 1: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1);
> +    case 2: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2);
> +    case 3: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3);
> +    case 4: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4);
> +    case 5: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5);
> +  }
> +  return 0;
> +}
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Action                 Specifies the type of action taken by the
> browser.
> +  @param  QuestionId             A unique value which is sent to the
> original
> +                                 exporting driver so that it can identify
> the type
> +                                 of data to expect.
> +  @param  Type                   The type of value for the question.
> +  @param  Value                  A pointer to the data being sent to the
> original
> +                                 exporting driver.
> +  @param  ActionRequest          On return, points to the action
> requested by the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the
> action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported
> by the
> +                                 callback.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DriverCallback(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  EFI_BROWSER_ACTION                      Action,
> +  EFI_QUESTION_ID                         QuestionId,
> +  UINT8                                   Type,
> +  EFI_IFR_TYPE_VALUE                      *Value,
> +  EFI_BROWSER_ACTION_REQUEST              *ActionRequest
> +  )
> +{
> +  HII_KEY    HiiKey;
> +  UINT8      HiiKeyId;
> +  UINT32     PpRequest;
> +  OPAL_DISK  *OpalDisk;
> +
> +  if (ActionRequest != NULL) {
> +    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
> +  } else {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // If QuestionId is an auto-generated key (label, empty line, etc.), ignore it.
> +  //
> +  if ((QuestionId & HII_KEY_FLAG) == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  HiiKey.Raw = QuestionId;
> +  HiiKeyId   = (UINT8) HiiKey.KeyBits.Id;
> +
> +  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
> +    switch (HiiKeyId) {
> +      case HII_KEY_ID_VAR_SUPPORTED_DISKS:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_VAR_SUPPORTED_DISKS\n"));
> +        return HiiPopulateMainMenuForm ();
> +
> +      case HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS:
> +        DEBUG ((DEBUG_INFO,
> "HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS\n"));
> +        return HiiPopulateDiskInfoForm();
> +    }
> +  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
> +    switch (HiiKeyId) {
> +      case HII_KEY_ID_GOTO_DISK_INFO:
> +        return HiiSelectDisk((UINT8)HiiKey.KeyBits.Index);
> +    }
> +  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
> +    switch (HiiKeyId) {
> +      case HII_KEY_ID_BLOCKSID:
> +        switch (Value->u8) {
> +          case 0:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
> +            break;
> +
> +          case 1:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID;
> +            break;
> +
> +          case 2:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID;
> +            break;
> +
> +          case 3:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FU
> NC_TRUE;
> +            break;
> +
> +          case 4:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FU
> NC_FALSE;
> +            break;
> +
> +          case 5:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FU
> NC_TRUE;
> +            break;
> +
> +          case 6:
> +            PpRequest =
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FU
> NC_FALSE;
> +            break;
> +
> +          default:
> +            PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
> +            DEBUG ((DEBUG_ERROR, "Invalid value input!\n"));
> +            break;
> +        }
> +        HiiSetBlockSidAction(PpRequest);
> +
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_SET_ADMIN_PWD:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SET_ADMIN_PWD\n"));
> +        gHiiConfiguration.OpalRequest.SetAdminPwd = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_SET_USER_PWD:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SET_USER_PWD\n"));
> +        gHiiConfiguration.OpalRequest.SetUserPwd = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_SECURE_ERASE:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_SECURE_ERASE\n"));
> +        gHiiConfiguration.OpalRequest.SecureErase = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_REVERT:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_REVERT\n"));
> +        gHiiConfiguration.OpalRequest.Revert = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +      case HII_KEY_ID_KEEP_USER_DATA:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_KEEP_USER_DATA\n"));
> +        gHiiConfiguration.OpalRequest.KeepUserData = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_PSID_REVERT:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_PSID_REVERT\n"));
> +        gHiiConfiguration.OpalRequest.PsidRevert = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_DISABLE_USER:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_DISABLE_USER\n"));
> +        gHiiConfiguration.OpalRequest.DisableUser = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      case HII_KEY_ID_ENABLE_FEATURE:
> +        DEBUG ((DEBUG_INFO,  "HII_KEY_ID_ENABLE_FEATURE\n"));
> +        gHiiConfiguration.OpalRequest.EnableFeature = Value->b;
> +        OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +        if (OpalDisk != NULL) {
> +          SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest);
> +        }
> +        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +        return EFI_SUCCESS;
> +
> +      default:
> +        break;
> +    }
> +  }
> +
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Update the global Disk index info.
> +
> +  @param   Index             The input disk index info.
> +
> +  @retval  EFI_SUCCESS       Update the disk index info success.
> +
> +**/
> +EFI_STATUS
> +HiiSelectDisk(
> +  UINT8 Index
> +  )
> +{
> +  OpalHiiGetBrowserData();
> +  gHiiConfiguration.SelectedDiskIndex = Index;
> +  OpalHiiSetBrowserData ();
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Draws the disk info form.
> +
> +  @retval  EFI_SUCCESS       Draw the disk info success.
> +
> +**/
> +EFI_STATUS
> +HiiPopulateDiskInfoForm(
> +  VOID
> +  )
> +{
> +  OPAL_DISK*                    OpalDisk;
> +  OPAL_DISK_ACTIONS             AvailActions;
> +  TCG_RESULT                    Ret;
> +  CHAR8                         *DiskName;
> +
> +  OpalHiiGetBrowserData();
> +
> +  DiskName = HiiDiskGetNameCB (gHiiConfiguration.SelectedDiskIndex);
> +  if (DiskName == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +  HiiSetFormString(STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME),
> DiskName);
> +
> +  gHiiConfiguration.SelectedDiskAvailableActions = HII_ACTION_NONE;
> +  ZeroMem (&gHiiConfiguration.OpalRequest, sizeof (OPAL_REQUEST));
> +  gHiiConfiguration.KeepUserDataForced = FALSE;
> +
> +  OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
> +
> +  if (OpalDisk != NULL) {
> +    OpalDiskUpdateStatus (OpalDisk);
> +    Ret = OpalSupportGetAvailableActions(&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions);
> +    if (Ret == TcgResultSuccess) {
> +      //
> +      // Update actions, always allow PSID Revert
> +      //
> +      gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.PsidRevert == 1) ? HII_ACTION_PSID_REVERT :
> HII_ACTION_NONE;
> +
> +      //
> +      // Always allow unlock to handle device migration
> +      //
> +      gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Unlock
> == 1) ? HII_ACTION_UNLOCK : HII_ACTION_NONE;
> +
> +      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature)) {
> +        if (OpalDisk->Owner == OpalOwnershipNobody) {
> +          gHiiConfiguration.SelectedDiskAvailableActions |=
> HII_ACTION_ENABLE_FEATURE;
> +
> +          //
> +          // Update strings
> +          //
> +          HiiSetFormString( STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
> "PSID Revert to factory default");
> +        } else {
> +          DEBUG ((DEBUG_INFO, "Feature disabled but ownership !=
> nobody\n"));
> +        }
> +      } else {
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.Revert == 1) ? HII_ACTION_REVERT : HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.AdminPass == 1) ? HII_ACTION_SET_ADMIN_PWD :
> HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.UserPass == 1) ? HII_ACTION_SET_USER_PWD :
> HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.SecureErase == 1) ? HII_ACTION_SECURE_ERASE :
> HII_ACTION_NONE;
> +        gHiiConfiguration.SelectedDiskAvailableActions |=
> (AvailActions.DisableUser == 1) ? HII_ACTION_DISABLE_USER :
> HII_ACTION_NONE;
> +
> +        HiiSetFormString (STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
> "PSID Revert to factory default and Disable");
> +
> +        //
> +        // Determine revert options for disk
> +        // Default initialize keep user Data to be true
> +        //
> +        gHiiConfiguration.OpalRequest.KeepUserData = 1;
> +        if (AvailActions.RevertKeepDataForced) {
> +          gHiiConfiguration.KeepUserDataForced = TRUE;
> +        }
> +      }
> +    }
> +
> +    GetSavedOpalRequest (OpalDisk, &gHiiConfiguration.OpalRequest);
> +  }
> +
> +  //
> +  // Pass the current configuration to the BIOS
> +  //
> +  OpalHiiSetBrowserData ();
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Send BlockSid request through TPM physical presence module.
> +
> +  @param   PpRequest         TPM physical presence operation request.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetBlockSidAction (
> +  IN UINT32          PpRequest
> +  )
> +{
> +  UINT32                           ReturnCode;
> +  EFI_STATUS                       Status;
> +
> +  ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction
> (PpRequest, 0);
> +  if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
> +    Status = EFI_SUCCESS;
> +  } else if (ReturnCode ==
> TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +  } else if (ReturnCode ==
> TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) {
> +    Status = EFI_UNSUPPORTED;
> +  } else {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Configuration          A null-terminated Unicode string in
> <ConfigResp>
> +                                 format.
> +  @param  Progress               A pointer to a string filled in with the
> offset of
> +                                 the most recent '&' before the first
> failing
> +                                 name/value pair (or the beginning of the
> string if
> +                                 the failure is in the first name/value pair)
> or
> +                                 the terminating NULL if all was
> successful.
> +
> +  @retval EFI_SUCCESS            The Results is processed successfully.
> +  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RouteConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Configuration,
> +  EFI_STRING                              *Progress
> +  )
> +{
> +  if (Configuration == NULL || Progress == NULL) {
> +    return (EFI_INVALID_PARAMETER);
> +  }
> +
> +  *Progress = Configuration;
> +  if (!HiiIsConfigHdrMatch (Configuration, &gHiiSetupVariableGuid,
> OpalPasswordStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  *Progress = Configuration + StrLen (Configuration);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function allows a caller to extract the current configuration for one
> +  or more named elements from the target driver.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Request                A null-terminated Unicode string in
> +                                 <ConfigRequest> format.
> +  @param  Progress               On return, points to a character in the
> Request
> +                                 string. Points to the string's null
> terminator if
> +                                 request was successful. Points to the
> most recent
> +                                 '&' before the first failing name/value
> pair (or
> +                                 the beginning of the string if the failure
> is in
> +                                 the first name/value pair) if the request
> was not
> +                                 successful.
> +  @param  Results                A null-terminated Unicode string in
> +                                 <ConfigAltResp> format which has all
> values filled
> +                                 in for the names in the Request string.
> String to
> +                                 be allocated by the called function.
> +
> +  @retval EFI_SUCCESS            The Results is filled with the requested
> values.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the
> results.
> +  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown
> name.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ExtractConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Request,
> +  EFI_STRING                              *Progress,
> +  EFI_STRING                              *Results
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  EFI_STRING                              ConfigRequest;
> +  EFI_STRING                              ConfigRequestHdr;
> +  UINTN                                   BufferSize;
> +  UINTN                                   Size;
> +  BOOLEAN                                 AllocatedRequest;
> +  EFI_HANDLE                              DriverHandle;
> +
> +  //
> +  // Check for valid parameters
> +  //
> +  if (Progress == NULL || Results == NULL) {
> +    return (EFI_INVALID_PARAMETER);
> +  }
> +
> +  *Progress = Request;
> +  if ((Request != NULL) &&
> +    !HiiIsConfigHdrMatch (Request, &gHiiSetupVariableGuid,
> OpalPasswordStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  AllocatedRequest = FALSE;
> +  BufferSize = sizeof (OPAL_HII_CONFIGURATION);
> +  ConfigRequest = Request;
> +  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
> +    //
> +    // Request has no request element, construct full request string.
> +    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
> +    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW"
> followed by a Null-terminator
> +    //
> +    DriverHandle = HiiGetDriverImageHandleCB();
> +    ConfigRequestHdr = HiiConstructConfigHdr (&gHiiSetupVariableGuid,
> OpalPasswordStorageName, DriverHandle);
> +    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
> +    ConfigRequest = AllocateZeroPool (Size);
> +    if (ConfigRequest == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    AllocatedRequest = TRUE;
> +    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX",
> ConfigRequestHdr, (UINT64)BufferSize);
> +    FreePool (ConfigRequestHdr);
> +  }
> +
> +  //
> +  // Convert Buffer Data to <ConfigResp> by helper function BlockToConfig( )
> +  //
> +  Status = gHiiConfigRouting->BlockToConfig(
> +               gHiiConfigRouting,
> +               ConfigRequest,
> +               (UINT8*)&gHiiConfiguration,
> +               sizeof(OPAL_HII_CONFIGURATION),
> +               Results,
> +               Progress
> +           );
> +
> +  //
> +  // Free the allocated config request string.
> +  //
> +  if (AllocatedRequest) {
> +    FreePool (ConfigRequest);
> +    ConfigRequest = NULL;
> +  }
> +
> +  //
> +  // Set Progress string to the original request string.
> +  //
> +  if (Request == NULL) {
> +    *Progress = NULL;
> +  } else if (StrStr (Request, L"OFFSET") == NULL) {
> +    *Progress = Request + StrLen (Request);
> +  }
> +
> +  return (Status);
> +}
> +
> +
> +/**
> +
> +  Pass the current system state to the bios via the hii_G_Configuration.
> +
> +**/
> +VOID
> +OpalHiiSetBrowserData (
> +  VOID
> +  )
> +{
> +  HiiSetBrowserData(
> +      &gHiiSetupVariableGuid,
> +      (CHAR16*)L"OpalHiiConfig",
> +      sizeof(gHiiConfiguration),
> +      (UINT8*)&gHiiConfiguration,
> +      NULL
> +  );
> +}
> +
> +
> +/**
> +
> +  Populate the hii_g_Configuraton with the browser Data.
> +
> +**/
> +VOID
> +OpalHiiGetBrowserData (
> +  VOID
> +  )
> +{
> +  HiiGetBrowserData(
> +      &gHiiSetupVariableGuid,
> +      (CHAR16*)L"OpalHiiConfig",
> +      sizeof(gHiiConfiguration),
> +      (UINT8*)&gHiiConfiguration
> +  );
> +}
> +
> +/**
> +  Set a string Value in a form.
> +
> +  @param      DestStringId   The stringid which need to update.
> +  @param      SrcAsciiStr    The string nned to update.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetFormString(
> +  EFI_STRING_ID       DestStringId,
> +  CHAR8               *SrcAsciiStr
> +  )
> +{
> +  UINT32                    Len;
> +  UINT32                    UniSize;
> +  CHAR16*                   UniStr;
> +
> +  //
> +  // Determine the Length of the sting
> +  //
> +  Len = ( UINT32 )AsciiStrLen( SrcAsciiStr );
> +
> +  //
> +  // Allocate space for the unicode string, including terminator
> +  //
> +  UniSize = (Len + 1) * sizeof(CHAR16);
> +  UniStr = (CHAR16*)AllocateZeroPool(UniSize);
> +
> +  //
> +  // Copy into unicode string, then copy into string id
> +  //
> +  AsciiStrToUnicodeStrS ( SrcAsciiStr, UniStr, Len + 1);
> +
> +  //
> +  // Update the string in the form
> +  //
> +  if (HiiSetString(gHiiPackageListHandle, DestStringId, UniStr, NULL) == 0) {
> +    DEBUG ((DEBUG_INFO,  "HiiSetFormString( ) failed\n"));
> +    FreePool(UniStr);
> +    return (EFI_OUT_OF_RESOURCES);
> +  }
> +
> +  //
> +  // Free the memory
> +  //
> +  FreePool(UniStr);
> +
> +  return (EFI_SUCCESS);
> +}
> +
> +/**
> +  Initialize the Opal disk base on the hardware info get from device.
> +
> +  @param Dev                  The Opal device.
> +
> +  @retval EFI_SUCESS          Initialize the device success.
> +  @retval EFI_DEVICE_ERROR    Get info from device failed.
> +
> +**/
> +EFI_STATUS
> +OpalDiskInitialize (
> +  IN OPAL_DRIVER_DEVICE          *Dev
> +  )
> +{
> +  TCG_RESULT                  TcgResult;
> +  OPAL_SESSION                Session;
> +
> +  ZeroMem(&Dev->OpalDisk, sizeof(OPAL_DISK));
> +  Dev->OpalDisk.Sscp = Dev->Sscp;
> +  Dev->OpalDisk.MediaId = Dev->MediaId;
> +  Dev->OpalDisk.OpalDevicePath = Dev->OpalDevicePath;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = Dev->Sscp;
> +  Session.MediaId = Dev->MediaId;
> +
> +  TcgResult = OpalGetSupportedAttributesInfo (&Session,
> &Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.OpalBaseComId);
> +  if (TcgResult != TcgResultSuccess) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +  Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
> +
> +  TcgResult = OpalUtilGetMsid (&Session, Dev->OpalDisk.Msid,
> OPAL_MSID_LENGHT, &Dev->OpalDisk.MsidLength);
> +  if (TcgResult != TcgResultSuccess) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return OpalDiskUpdateStatus (&Dev->OpalDisk);
> +}
> +
> +/**
> +  Update the device info.
> +
> +  @param OpalDisk                The Opal device.
> +
> +  @retval EFI_SUCESS             Initialize the device success.
> +  @retval EFI_DEVICE_ERROR       Get info from device failed.
> +  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership
> info.
> +
> +**/
> +EFI_STATUS
> +OpalDiskUpdateStatus (
> +  OPAL_DISK        *OpalDisk
> +  )
> +{
> +  TCG_RESULT                  TcgResult;
> +  OPAL_SESSION                Session;
> +
> +  ZeroMem(&Session, sizeof(Session));
> +  Session.Sscp = OpalDisk->Sscp;
> +  Session.MediaId = OpalDisk->MediaId;
> +  Session.OpalBaseComId = OpalDisk->OpalBaseComId;
> +
> +  TcgResult = OpalGetLockingInfo(&Session, &OpalDisk->LockingFeature);
> +  if (TcgResult != TcgResultSuccess) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  if (OpalDisk->MsidLength == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  } else {
> +    //
> +    // Base on the Msid info to get the ownership, so Msid info must get first.
> +    //
> +    OpalDisk->Owner = OpalUtilDetermineOwnership(&Session,
> OpalDisk->Msid, OpalDisk->MsidLength);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
> new file mode 100644
> index 000000000000..a1b1131c1380
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.h
> @@ -0,0 +1,380 @@
> +/** @file
> +  Public Header file of HII library used by Opal UEFI Driver.
> +  Defines required callbacks of Opal HII library.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_HII_H_
> +#define _OPAL_HII_H_
> +
> +#include <Protocol/HiiConfigAccess.h>
> +
> +#include "OpalDriver.h"
> +#include "OpalHiiFormValues.h"
> +
> +#define  OPAL_PASSWORD_CONFIG_GUID \
> +  { \
> +    0x0d510a4f, 0xa81b, 0x473f, { 0x87, 0x07, 0xb7, 0xfd, 0xfb, 0xc0, 0x45,
> 0xba } \
> +  }
> +
> +#pragma pack(1)
> +
> +typedef struct {
> +  UINT16 Id: HII_KEY_ID_BITS;
> +  UINT16 Index: HII_KEY_INDEX_BITS;
> +  UINT16 Flag: HII_KEY_FLAG_BITS;
> +} KEY_BITS;
> +
> +typedef union {
> +    UINT16    Raw;
> +    KEY_BITS  KeyBits;
> +} HII_KEY;
> +
> +typedef struct {
> +    VENDOR_DEVICE_PATH             VendorDevicePath;
> +    EFI_DEVICE_PATH_PROTOCOL       End;
> +} HII_VENDOR_DEVICE_PATH;
> +
> +#pragma pack()
> +
> +extern const EFI_GUID gHiiSetupVariableGuid;
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Configuration          A null-terminated Unicode string in
> <ConfigResp>
> +                                 format.
> +  @param  Progress               A pointer to a string filled in with the
> offset of
> +                                 the most recent '&' before the first
> failing
> +                                 name/value pair (or the beginning of the
> string if
> +                                 the failure is in the first name/value pair)
> or
> +                                 the terminating NULL if all was
> successful.
> +
> +  @retval EFI_SUCCESS            The Results is processed successfully.
> +  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RouteConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Configuration,
> +  EFI_STRING                              *Progress
> +  );
> +
> +/**
> +  This function allows a caller to extract the current configuration for one
> +  or more named elements from the target driver.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Request                A null-terminated Unicode string in
> +                                 <ConfigRequest> format.
> +  @param  Progress               On return, points to a character in the
> Request
> +                                 string. Points to the string's null
> terminator if
> +                                 request was successful. Points to the
> most recent
> +                                 '&' before the first failing name/value
> pair (or
> +                                 the beginning of the string if the failure
> is in
> +                                 the first name/value pair) if the request
> was not
> +                                 successful.
> +  @param  Results                A null-terminated Unicode string in
> +                                 <ConfigAltResp> format which has all
> values filled
> +                                 in for the names in the Request string.
> String to
> +                                 be allocated by the called function.
> +
> +  @retval EFI_SUCCESS            The Results is filled with the requested
> values.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the
> results.
> +  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown
> name.
> +  @retval EFI_NOT_FOUND          Routing data doesn't match any
> storage in this
> +                                 driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ExtractConfig(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
> +  CONST EFI_STRING                        Request,
> +  EFI_STRING                              *Progress,
> +  EFI_STRING                              *Results
> +  );
> +
> +/**
> +  This function processes the results of changes in configuration.
> +
> +  @param  This                   Points to the
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Action                 Specifies the type of action taken by the
> browser.
> +  @param  QuestionId             A unique value which is sent to the
> original
> +                                 exporting driver so that it can identify
> the type
> +                                 of data to expect.
> +  @param  Type                   The type of value for the question.
> +  @param  Value                  A pointer to the data being sent to the
> original
> +                                 exporting driver.
> +  @param  ActionRequest          On return, points to the action
> requested by the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the
> action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported
> by the
> +                                 callback.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DriverCallback(
> +  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL*   This,
> +  EFI_BROWSER_ACTION                      Action,
> +  EFI_QUESTION_ID                         QuestionId,
> +  UINT8                                   Type,
> +  EFI_IFR_TYPE_VALUE*                     Value,
> +  EFI_BROWSER_ACTION_REQUEST*             ActionRequest
> +  );
> +
> +/**
> +
> +  Pass the current system state to the bios via the hii_G_Configuration.
> +
> +**/
> +VOID
> +OpalHiiSetBrowserData (
> +  VOID
> +  );
> +
> +/**
> +
> +  Populate the hii_g_Configuraton with the browser Data.
> +
> +**/
> +VOID
> +OpalHiiGetBrowserData (
> +  VOID
> +  );
> +
> +/**
> +  Draws the disk info form.
> +
> +  @retval  EFI_SUCCESS       Draw the disk info success.
> +
> +**/
> +EFI_STATUS
> +HiiPopulateDiskInfoForm(
> +  VOID
> +  );
> +
> +/**
> +  Update the global Disk index info.
> +
> +  @param   Index             The input disk index info.
> +
> +  @retval  EFI_SUCCESS       Update the disk index info success.
> +
> +**/
> +EFI_STATUS
> +HiiSelectDisk(
> +  UINT8 Index
> +  );
> +
> +/**
> +  Use the input password to do the specified action.
> +
> +  @param      Str            The input password saved in.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiPasswordEntered(
> +  EFI_STRING_ID            Str
> +  );
> +
> +/**
> +  Update block sid info.
> +
> +  @param      PpRequest      Input the Pp Request.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetBlockSidAction (
> +  UINT32          PpRequest
> +  );
> +
> +/**
> +  Reverts the Opal disk to factory default.
> +
> +  @param   PsidStringId      The string id for the PSID info.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +
> +**/
> +EFI_STATUS
> +HiiPsidRevert(
> +  EFI_STRING_ID         PsidStringId
> +  );
> +
> +/**
> +  Get disk name string id.
> +
> +  @param   DiskIndex             The input disk index info.
> +
> +  @retval  The disk name string id.
> +
> +**/
> +EFI_STRING_ID
> +GetDiskNameStringId(
> +  UINT8 DiskIndex
> +  );
> +
> +/**
> +  Update the device info.
> +
> +  @param OpalDisk                The Opal device.
> +
> +  @retval EFI_SUCESS             Initialize the device success.
> +  @retval EFI_DEVICE_ERROR       Get info from device failed.
> +  @retval EFI_INVALID_PARAMETER  Not get Msid info before get ownership
> info.
> +
> +**/
> +EFI_STATUS
> +OpalDiskUpdateStatus (
> +  OPAL_DISK        *OpalDisk
> +  );
> +
> +/**
> +  Get the driver image handle.
> +
> +  @retval  the driver image handle.
> +
> +**/
> +EFI_HANDLE
> +HiiGetDriverImageHandleCB(
> +  VOID
> +  );
> +
> +/**
> +  Install the HII form and string packages.
> +
> +  @retval  EFI_SUCCESS           Install all the resources success.
> +  @retval  EFI_OUT_OF_RESOURCES  Out of resource error.
> +**/
> +EFI_STATUS
> +OpalHiiAddPackages(
> +  VOID
> +  );
> +
> +/**
> +  Check whether enable feature or not.
> +
> +  @retval  Return the disk number.
> +
> +**/
> +UINT8
> +HiiGetNumConfigRequiredOpalDisksCB(
> +  VOID
> +  );
> +
> +/**
> +  Returns the driver name.
> +
> +  @retval Returns the driver name.
> +
> +**/
> +CHAR16*
> +HiiGetDriverNameCB(
> +  VOID
> +  );
> +
> +/**
> +  Returns the opaque pointer to a physical disk context.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval The device pointer.
> +
> +**/
> +OPAL_DISK*
> +HiiGetOpalDiskCB(
> +  UINT8 DiskIndex
> +  );
> +
> +/**
> +  Returns the disk name.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval Returns the disk name.
> +
> +**/
> +CHAR8*
> +HiiDiskGetNameCB(
> +  UINT8 DiskIndex
> +  );
> +
> +/**
> +  Set a string Value in a form.
> +
> +  @param      DestStringId   The stringid which need to update.
> +  @param      SrcAsciiStr    The string nned to update.
> +
> +  @retval  EFI_SUCCESS       Do the required action success.
> +  @retval  Others            Other error occur.
> +
> +**/
> +EFI_STATUS
> +HiiSetFormString(
> +  EFI_STRING_ID       DestStringId,
> +  CHAR8               *SrcAsciiStr
> +  );
> +
> +/**
> +  Install the HII related resources.
> +
> +  @retval  EFI_SUCCESS        Install all the resources success.
> +  @retval  other              Error occur when install the resources.
> +**/
> +EFI_STATUS
> +HiiInstall(
> +  VOID
> +  );
> +
> +/**
> +  Uninstall the HII capability.
> +
> +  @retval  EFI_SUCCESS           Uninstall all the resources success.
> +  @retval  others                Other errors occur when unistall the hii
> resource.
> +**/
> +EFI_STATUS
> +HiiUninstall(
> +  VOID
> +  );
> +
> +/**
> +  Initialize the Opal disk base on the hardware info get from device.
> +
> +  @param Dev                  The Opal device.
> +
> +  @retval EFI_SUCESS          Initialize the device success.
> +  @retval EFI_DEVICE_ERROR    Get info from device failed.
> +
> +**/
> +EFI_STATUS
> +OpalDiskInitialize (
> +  IN OPAL_DRIVER_DEVICE          *Dev
> +  );
> +
> +#endif // _HII_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
> new file mode 100644
> index 000000000000..b07e38c1449d
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiCallbacks.c
> @@ -0,0 +1,219 @@
> +/** @file
> +  Callbacks required by the HII of the Opal UEFI Driver to help display
> +  Opal device information.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalHii.h"
> +
> +/**
> +  Get Opal var name.
> +  The return Value must be freed by caller if not NULL
> +
> +  @param      OpalDisk       The disk.
> +  @param      Prefix         The prefix string.
> +
> +  @retval  The var name string.
> +
> +**/
> +CHAR16*
> +OpalDriverGetOpalVarName(
> +  OPAL_DISK        *OpalDisk,
> +  const CHAR16     *Prefix
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*          Dev;
> +  UINTN                        PrefixLen;
> +  UINTN                        NameLen;
> +  UINTN                        VarNameLen;
> +  CHAR16*                      VarName;
> +
> +  Dev = DRIVER_DEVICE_FROM_OPALDISK(OpalDisk);
> +  if (Dev == NULL) {
> +    return NULL;
> +  }
> +
> +  PrefixLen = StrLen(Prefix);
> +
> +  NameLen = 0;
> +  if (Dev->Name16 != NULL) {
> +    NameLen = StrLen(Dev->Name16);
> +  }
> +
> +  VarNameLen = PrefixLen + NameLen;
> +
> +  VarName = (CHAR16*)AllocateZeroPool((VarNameLen + 1) *
> sizeof(CHAR16));
> +  if (VarName == NULL) {
> +    return NULL;
> +  }
> +
> +  CopyMem(VarName, Prefix, PrefixLen * sizeof(CHAR16));
> +  if (Dev->Name16 != NULL) {
> +    CopyMem(VarName + PrefixLen, Dev->Name16, NameLen *
> sizeof(CHAR16));
> +  }
> +  VarName[VarNameLen] = 0;
> +
> +  return VarName;
> +}
> +
> +/**
> +  Get the driver image handle.
> +
> +  @retval  the driver image handle.
> +
> +**/
> +EFI_HANDLE
> +HiiGetDriverImageHandleCB(
> +  VOID
> +  )
> +{
> +  return gImageHandle;
> +}
> +
> +/**
> +  Check whether enable feature or not.
> +
> +  @retval  Return the disk number.
> +
> +**/
> +UINT8
> +HiiGetNumConfigRequiredOpalDisksCB(
> +  VOID
> +  )
> +{
> +  UINT8                        NumDisks;
> +  UINT8                        NumLockedOpalDisks;
> +  OPAL_DISK                    *OpalDisk;
> +  UINT8                        Index;
> +
> +  NumLockedOpalDisks = 0;
> +
> +  NumDisks = GetDeviceCount();
> +
> +  for (Index = 0; Index < NumDisks; Index++) {
> +    OpalDisk = HiiGetOpalDiskCB(Index);
> +
> +    if (OpalDisk != NULL) {
> +      if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature)) {
> +        DEBUG ((DEBUG_INFO, "Ignoring disk %u because feature is disabled
> or health has already been inspected\n", Index));
> +      } else if (OpalDeviceLocked (&OpalDisk->SupportedAttributes,
> &OpalDisk->LockingFeature)) {
> +        NumLockedOpalDisks++;
> +      }
> +    }
> +  }
> +
> +  return NumLockedOpalDisks;
> +}
> +
> +
> +
> +/**
> +  Returns the opaque pointer to a physical disk context.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval The device pointer.
> +
> +**/
> +VOID *
> +HiiGetDiskContextCB(
> +  UINT8 DiskIndex
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*                Dev;
> +  UINT8                              CurrentDisk;
> +
> +  Dev = OpalDriverGetDeviceList();
> +  CurrentDisk = 0;
> +
> +  if (DiskIndex >= GetDeviceCount()) {
> +    return NULL;
> +  }
> +
> +  while (Dev != NULL) {
> +    if (CurrentDisk == DiskIndex) {
> +      return Dev;
> +    } else {
> +      Dev = Dev->Next;
> +      CurrentDisk++;
> +    }
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Returns the opaque pointer to a physical disk context.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval The device pointer.
> +
> +**/
> +OPAL_DISK*
> +HiiGetOpalDiskCB(
> +  UINT8 DiskIndex
> +  )
> +{
> +  VOID                           *Ctx;
> +  OPAL_DRIVER_DEVICE             *Tmp;
> +
> +  Ctx = HiiGetDiskContextCB (DiskIndex);
> +
> +  if (Ctx == NULL) {
> +    return NULL;
> +  }
> +
> +  Tmp = (OPAL_DRIVER_DEVICE*) Ctx;
> +
> +  return &Tmp->OpalDisk;
> +}
> +
> +/**
> +  Returns the disk name.
> +
> +  @param  DiskIndex       Input the disk index.
> +
> +  @retval Returns the disk name.
> +
> +**/
> +CHAR8*
> +HiiDiskGetNameCB(
> +  UINT8 DiskIndex
> +  )
> +{
> +  OPAL_DRIVER_DEVICE*                Ctx;
> +
> +  Ctx = (OPAL_DRIVER_DEVICE*) HiiGetDiskContextCB (DiskIndex);
> +
> +  if (Ctx != NULL) {
> +    if (Ctx->NameZ == NULL) {
> +      OpalDriverGetDriverDeviceName (Ctx);
> +    }
> +    return Ctx->NameZ;
> +  }
> +  return NULL;
> +}
> +
> +/**
> +  Returns the driver name.
> +
> +  @retval Returns the driver name.
> +
> +**/
> +CHAR16*
> +HiiGetDriverNameCB(
> +  VOID
> +  )
> +{
> +  return (CHAR16*)EFI_DRIVER_NAME_UNICODE;
> +}
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
> new file mode 100644
> index 000000000000..69abc561cc56
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormStrings.uni
> @@ -0,0 +1,84 @@
> +// /** @file
> +//
> +//   String definitions for Setup formset.
> +//
> +// Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD
> License
> +// which accompanies this distribution. The full text of the license may be found
> at
> +// http://opensource.org/licenses/bsd-license.php
> +//
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +/=#
> +/////////////////////////////////   GENERIC DEFINITIONS
> /////////////////////////////////
> +#langdef en-US                                  "English"
> +#string STR_NULL                                #language en-US " "
> +
> +/////////////////////////////////   FORM SET   /////////////////////////////////
> +#string STR_FORM_SET_HELP                        #language en-US
> "Manage Opal disks"
> +
> +/////////////////////////////////   MULTIPLE FORMS
> /////////////////////////////////
> +#string STR_OPAL                                 #language en-US
> "Opal"
> +#string STR_MAIN_OPAL_VERSION                    #language en-US
> "Version 00.0.0.0000"
> +
> +/////////////////////////////////   MAIN MENU FORM
> /////////////////////////////////
> +#string STR_MAIN_PHY_DISKS_LBL                   #language en-US
> "Physical Disks:"
> +
> +#string STR_MAIN_GOTO_DISK_INFO_0                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_1                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_2                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_3                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_4                #language en-US " "
> +#string STR_MAIN_GOTO_DISK_INFO_5                #language en-US " "
> +
> +#string STR_MAIN_GOTO_DISK_INFO_HELP             #language en-US
> "Select to see Opal disk actions"
> +
> +#string STR_MAIN_NO_DISKS_PRESENT_LBL            #language en-US
> "No disks connected to system"
> +
> +/////////////////////////////////   DISK INFO MENU FORM
> /////////////////////////////////
> +#string STR_DISK_INFO_SELECTED_DISK_NAME         #language en-US " "
> +
> +#string STR_DISK_INFO_LOCK                       #language en-US
> "Lock"
> +#string STR_DISK_INFO_UNLOCK                     #language en-US
> "Unlock"
> +#string STR_DISK_INFO_SET_ADMIN_PSWD             #language en-US
> "Update Drive Admin Password"
> +#string STR_DISK_INFO_SET_USER_PSWD              #language en-US
> "Set Drive User Password"
> +#string STR_DISK_INFO_SECURE_ERASE               #language en-US
> "Secure Erase User Data"
> +#string STR_DISK_INFO_PSID_REVERT                #language en-US
> "PSID Revert to factory default"
> +#string STR_DISK_INFO_REVERT                     #language en-US
> "Admin Revert to factory default and Disable"
> +#string STR_DISK_INFO_DISABLE_USER               #language en-US
> "Disable User"
> +#string STR_DISK_INFO_ENABLE_FEATURE             #language en-US
> "Enable Feature"
> +#string STR_DISK_INFO_ENABLE_BLOCKSID            #language en-US
> "TCG Storage Action"
> +#string STR_ENABLED                              #language en-US
> "Enable BlockSID"
> +#string STR_DISABLED                             #language en-US
> "Disable BlockSID"
> +
> +#string STR_NONE                                 #language en-US
> "None"
> +#string STR_DISK_INFO_ENABLE_BLOCKSID_TRUE       #language en-US
> "Require physical presence when remote enable BlockSID"
> +#string STR_DISK_INFO_ENABLE_BLOCKSID_FALSE      #language en-US
> "Not require physical presence when remote enable BlockSID"
> +#string STR_DISK_INFO_DISABLE_BLOCKSID_TRUE      #language en-US
> "Require physical presence when remote disable BlockSID"
> +#string STR_DISK_INFO_DISABLE_BLOCKSID_FALSE     #language en-US
> "Not require physical presence when remote disable BlockSID"
> +
> +#string STR_BLOCKSID_STATUS_HELP                 #language en-US
> "BlockSID action change status"
> +#string STR_BLOCKSID_STATUS                      #language en-US
> "Current BlockSID Status:"
> +#string STR_BLOCKSID_STATUS1                     #language en-US ""
> +#string STR_BLOCKSID_STATUS2                     #language en-US ""
> +#string STR_BLOCKSID_STATUS3                     #language en-US ""
> +
> +#string STR_OPAL_REQUESTS_LBL                    #language en-US
> "Opal Requests:"
> +#string STR_DISK_INFO_LOCK_HELP                  #language en-US
> "Lock the disk"
> +#string STR_DISK_INFO_UNLOCK_HELP                #language en-US
> "Unlock the disk"
> +#string STR_DISK_INFO_SET_ADMIN_PSWD_HELP        #language en-US
> "Set password for the administrator"
> +#string STR_DISK_INFO_SET_USER_PSWD_HELP         #language en-US
> "Set password for User 1"
> +#string STR_DISK_INFO_SECURE_ERASE_HELP          #language en-US
> "Securely erase the disk"
> +#string STR_DISK_INFO_REVERT_HELP                #language en-US
> "Revert the disk to factory defaults"
> +#string STR_DISK_INFO_PSID_REVERT_HELP           #language en-US
> "Revert the disk to factory defaults, PSID is a 32 character case sensitive value"
> +#string STR_DISK_INFO_DISABLE_USER_HELP          #language en-US
> "Disable User"
> +#string STR_DISK_INFO_ENABLE_FEATURE_HELP        #language en-US
> "Enable Feature"
> +#string STR_KEEP_USER_DATA_PROMPT                #language en-US "
> Keep User Data"
> +#string STR_KEEP_USER_DATA_HELP                  #language en-US
> "Check to keep user data, otherwise data will be lost"
> +
> +#string STR_DISK_INFO_ENABLE_BLOCKSID_HELP       #language en-US
> "Change BlockSID actions, includes enable or disable BlockSID, Require or not
> require physical presence when remote enable or disable BlockSID"
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
> new file mode 100644
> index 000000000000..3ff7d4726d5e
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalHiiFormValues.h
> @@ -0,0 +1,123 @@
> +/** @file
> +  Defines Opal HII form ids, structures and values.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +
> +#ifndef _OPAL_HII_FORM_VALUES_H_
> +#define _OPAL_HII_FORM_VALUES_H_
> +
> +// ID's for various forms that will be used by HII
> +#define FORMID_VALUE_MAIN_MENU                             0x01
> +#define FORMID_VALUE_DISK_INFO_FORM_MAIN                   0x02
> +
> +#define OPAL_REQUEST_VARIABLE_NAME
> L"OpalRequest"
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT16    Lock:1;
> +  UINT16    Unlock:1;
> +  UINT16    SetAdminPwd:1;
> +  UINT16    SetUserPwd:1;
> +  UINT16    SecureErase:1;
> +  UINT16    Revert:1;
> +  UINT16    PsidRevert:1;
> +  UINT16    DisableUser:1;
> +  UINT16    DisableFeature:1;
> +  UINT16    EnableFeature:1;
> +  UINT16    Reserved:5;
> +  UINT16    KeepUserData:1;
> +} OPAL_REQUEST;
> +
> +typedef struct {
> +  UINT8           NumDisks;
> +  UINT8           SelectedDiskIndex;
> +  UINT16          SelectedDiskAvailableActions;
> +  UINT16          SupportedDisks;
> +  BOOLEAN         KeepUserDataForced;
> +  OPAL_REQUEST    OpalRequest;
> +  UINT8           EnableBlockSid;
> +} OPAL_HII_CONFIGURATION;
> +
> +typedef struct {
> +  UINT32                   Length;
> +  OPAL_REQUEST             OpalRequest;
> +  //EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
> +} OPAL_REQUEST_VARIABLE;
> +
> +#pragma pack()
> +
> +/* Action Flags */
> +#define HII_ACTION_NONE
> 0x0000
> +#define HII_ACTION_LOCK
> 0x0001
> +#define HII_ACTION_UNLOCK
> 0x0002
> +#define HII_ACTION_SET_ADMIN_PWD
> 0x0004
> +#define HII_ACTION_SET_USER_PWD
> 0x0008
> +#define HII_ACTION_SECURE_ERASE
> 0x0010
> +#define HII_ACTION_REVERT
> 0x0020
> +#define HII_ACTION_PSID_REVERT
> 0x0040
> +#define HII_ACTION_DISABLE_USER
> 0x0080
> +#define HII_ACTION_DISABLE_FEATURE
> 0x0100
> +#define HII_ACTION_ENABLE_FEATURE
> 0x0200
> +
> +/* Number of bits allocated for each part of a unique key for an HII_ITEM
> + * all bits together must be <= 16 (EFI_QUESTION_ID is UINT16)
> + * 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
> + * |   |-----------------------|   |---------------------------|
> + * FLG INDEX                       ID
> + */
> +#define HII_KEY_ID_BITS                                     8
> +#define HII_KEY_INDEX_BITS                                  7
> +#define HII_KEY_FLAG_BITS                                   1
> +
> +#define HII_KEY_FLAG                                        0x8000
> // bit 15 (zero based)
> +
> +/***********/
> +/* Key IDs */
> +/***********/
> +
> +#define HII_KEY_ID_GOTO_DISK_INFO                       1
> +
> +#define HII_KEY_ID_VAR_SUPPORTED_DISKS                  2
> +#define HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS  3
> +
> +#define HII_KEY_ID_BLOCKSID                             4
> +#define HII_KEY_ID_SET_ADMIN_PWD                        5
> +#define HII_KEY_ID_SET_USER_PWD                         6
> +#define HII_KEY_ID_SECURE_ERASE                         7
> +#define HII_KEY_ID_REVERT                               8
> +#define HII_KEY_ID_KEEP_USER_DATA                       9
> +#define HII_KEY_ID_PSID_REVERT                          0xA
> +#define HII_KEY_ID_DISABLE_USER                         0xB
> +#define HII_KEY_ID_ENABLE_FEATURE                       0xC
> +
> +#define HII_KEY_ID_MAX                                  0xC
> // !!Update each time a new ID is added!!
> +
> +#define HII_KEY_WITH_INDEX(id, index) \
> +    ( \
> +        HII_KEY_FLAG | \
> +        (id) | \
> +        ((index) << HII_KEY_ID_BITS) \
> +    )
> +
> +#define HII_KEY(id) HII_KEY_WITH_INDEX(id, 0)
> +
> +#define PACKAGE_LIST_GUID { 0xf0308176, 0x9058, 0x4153, { 0x93, 0x3d,
> 0xda, 0x2f, 0xdc, 0xc8, 0x3e, 0x44 } }
> +
> +/* {410483CF-F4F9-4ece-848A-1958FD31CEB7} */
> +#define SETUP_FORMSET_GUID { 0x410483cf, 0xf4f9, 0x4ece, { 0x84, 0x8a,
> 0x19, 0x58, 0xfd, 0x31, 0xce, 0xb7 } }
> +
> +// {BBF1ACD2-28D8-44ea-A291-58A237FEDF1A}
> +#define SETUP_VARIABLE_GUID { 0xbbf1acd2, 0x28d8, 0x44ea, { 0xa2, 0x91,
> 0x58, 0xa2, 0x37, 0xfe, 0xdf, 0x1a } }
> +
> +#endif //_HII_FORM_VALUES_H_
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> new file mode 100644
> index 000000000000..7657bb26e23c
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> @@ -0,0 +1,2144 @@
> +/** @file
> +  Provide functions to initialize NVME controller and perform NVME
> commands
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalPasswordPei.h"
> +
> +
> +#define ALIGN(v, a)                         (UINTN)((((v) - 1) | ((a) - 1)) +
> 1)
> +
> +///
> +/// NVME Host controller registers operation
> +///
> +#define NVME_GET_CAP(Nvme, Cap)             NvmeMmioRead  (Cap,
> Nvme->Nbar + NVME_CAP_OFFSET, sizeof (NVME_CAP))
> +#define NVME_GET_CC(Nvme, Cc)               NvmeMmioRead  (Cc,
> Nvme->Nbar + NVME_CC_OFFSET, sizeof (NVME_CC))
> +#define NVME_SET_CC(Nvme, Cc)               NvmeMmioWrite
> (Nvme->Nbar + NVME_CC_OFFSET, Cc, sizeof (NVME_CC))
> +#define NVME_GET_CSTS(Nvme, Csts)           NvmeMmioRead  (Csts,
> Nvme->Nbar + NVME_CSTS_OFFSET, sizeof (NVME_CSTS))
> +#define NVME_GET_AQA(Nvme, Aqa)             NvmeMmioRead  (Aqa,
> Nvme->Nbar + NVME_AQA_OFFSET, sizeof (NVME_AQA))
> +#define NVME_SET_AQA(Nvme, Aqa)             NvmeMmioWrite
> (Nvme->Nbar + NVME_AQA_OFFSET, Aqa, sizeof (NVME_AQA))
> +#define NVME_GET_ASQ(Nvme, Asq)             NvmeMmioRead  (Asq,
> Nvme->Nbar + NVME_ASQ_OFFSET, sizeof (NVME_ASQ))
> +#define NVME_SET_ASQ(Nvme, Asq)             NvmeMmioWrite
> (Nvme->Nbar + NVME_ASQ_OFFSET, Asq, sizeof (NVME_ASQ))
> +#define NVME_GET_ACQ(Nvme, Acq)             NvmeMmioRead  (Acq,
> Nvme->Nbar + NVME_ACQ_OFFSET, sizeof (NVME_ACQ))
> +#define NVME_SET_ACQ(Nvme, Acq)             NvmeMmioWrite
> (Nvme->Nbar + NVME_ACQ_OFFSET, Acq, sizeof (NVME_ACQ))
> +#define NVME_GET_VER(Nvme, Ver)             NvmeMmioRead  (Ver,
> Nvme->Nbar + NVME_VER_OFFSET, sizeof (NVME_VER))
> +#define NVME_SET_SQTDBL(Nvme, Qid, Sqtdbl)  NvmeMmioWrite
> (Nvme->Nbar + NVME_SQTDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Sqtdbl, sizeof
> (NVME_SQTDBL))
> +#define NVME_SET_CQHDBL(Nvme, Qid, Cqhdbl)  NvmeMmioWrite
> (Nvme->Nbar + NVME_CQHDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Cqhdbl, sizeof
> (NVME_CQHDBL))
> +
> +///
> +/// Base memory address
> +///
> +enum {
> +  BASEMEM_CONTROLLER_DATA,
> +  BASEMEM_IDENTIFY_DATA,
> +  BASEMEM_ASQ,
> +  BASEMEM_ACQ,
> +  BASEMEM_SQ,
> +  BASEMEM_CQ,
> +  BASEMEM_PRP,
> +  BASEMEM_SECURITY,
> +  MAX_BASEMEM_COUNT
> +};
> +
> +///
> +/// All of base memories are 4K(0x1000) alignment
> +///
> +#define NVME_MEM_BASE(Nvme)
> ((UINTN)(Nvme->BaseMem))
> +#define NVME_CONTROL_DATA_BASE(Nvme)        (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_CONTROLLER_DATA))                        * EFI_PAGE_SIZE),
> EFI_PAGE_SIZE))
> +#define NVME_NAMESPACE_DATA_BASE(Nvme)      (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_IDENTIFY_DATA))                          * EFI_PAGE_SIZE),
> EFI_PAGE_SIZE))
> +#define NVME_ASQ_BASE(Nvme)                 (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ASQ))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_ACQ_BASE(Nvme)                 (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ACQ))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_SQ_BASE(Nvme, index)           (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SQ) +
> ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_CQ_BASE(Nvme, index)           (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CQ) +
> ((index)*(NVME_MAX_IO_QUEUES-1)))  * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_PRP_BASE(Nvme, index)          (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_PRP) +
> ((index)*NVME_PRP_SIZE))          * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +#define NVME_SEC_BASE(Nvme)                 (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SECURITY))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> +
> +/**
> +  Transfer MMIO Data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      *((UINT32 *)MemBuffer) = MmioRead32 (MmioAddr);
> +      break;
> +
> +    case 8:
> +      *((UINT64 *)MemBuffer) = MmioRead64 (MmioAddr);
> +      break;
> +
> +    case 2:
> +      *((UINT16 *)MemBuffer) = MmioRead16 (MmioAddr);
> +      break;
> +
> +    case 1:
> +      *((UINT8 *)MemBuffer) = MmioRead8 (MmioAddr);
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = MmioRead8 (MmioAddr + Offset);
> +        Ptr[Offset] = Data;
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Transfer memory data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      MmioWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
> +      break;
> +
> +    case 8:
> +      MmioWrite64 (MmioAddr, *((UINT64 *)MemBuffer));
> +      break;
> +
> +    case 2:
> +      MmioWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
> +      break;
> +
> +    case 1:
> +      MmioWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = Ptr[Offset];
> +        MmioWrite8 (MmioAddr + Offset, Data);
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Transfer MMIO data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +OpalPciRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      *((UINT32 *)MemBuffer) = PciRead32 (MmioAddr);
> +      break;
> +
> +    case 2:
> +      *((UINT16 *)MemBuffer) = PciRead16 (MmioAddr);
> +      break;
> +
> +    case 1:
> +      *((UINT8 *)MemBuffer) = PciRead8 (MmioAddr);
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = PciRead8 (MmioAddr + Offset);
> +        Ptr[Offset] = Data;
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Transfer memory data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +OpalPciWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  )
> +{
> +  UINTN  Offset;
> +  UINT8  Data;
> +  UINT8  *Ptr;
> +
> +  // priority has adjusted
> +  switch (Size) {
> +    case 4:
> +      PciWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
> +      break;
> +
> +    case 2:
> +      PciWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
> +      break;
> +
> +    case 1:
> +      PciWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
> +      break;
> +
> +    default:
> +      Ptr = (UINT8 *)MemBuffer;
> +      for (Offset = 0; Offset < Size; Offset += 1) {
> +        Data = Ptr[Offset];
> +        PciWrite8 (MmioAddr + Offset, Data);
> +      }
> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get total pages for specific NVME based memory.
> +
> +  @param[in] BaseMemIndex           - The Index of BaseMem (0-based).
> +
> +  @retval - The page count for specific BaseMem Index
> +
> +**/
> +UINT32
> +NvmeGetBaseMemPages (
> +  IN UINTN              BaseMemIndex
> +  )
> +{
> +  UINT32                Pages;
> +  UINTN                 Index;
> +  UINT32                PageSizeList[8];
> +
> +  PageSizeList[0] = 1;  /* Controller Data */
> +  PageSizeList[1] = 1;  /* Identify Data */
> +  PageSizeList[2] = 1;  /* ASQ */
> +  PageSizeList[3] = 1;  /* ACQ */
> +  PageSizeList[4] = 1;  /* SQs */
> +  PageSizeList[5] = 1;  /* CQs */
> +  PageSizeList[6] = NVME_PRP_SIZE * NVME_CSQ_DEPTH;  /* PRPs */
> +  PageSizeList[7] = 1;  /* Security Commands */
> +
> +  if (BaseMemIndex > MAX_BASEMEM_COUNT) {
> +    ASSERT (FALSE);
> +    return 0;
> +  }
> +
> +  Pages = 0;
> +  for (Index = 0; Index < BaseMemIndex; Index++) {
> +    Pages += PageSizeList[Index];
> +  }
> +
> +  return Pages;
> +}
> +
> +/**
> +  Wait for NVME controller status to be ready or not.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] WaitReady              - Flag for waitting status ready or not
> +
> +  @return EFI_SUCCESS               - Successfully to wait specific status.
> +  @return others                    - Fail to wait for specific controller
> status.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeWaitController (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN BOOLEAN            WaitReady
> +  )
> +{
> +  NVME_CSTS              Csts;
> +  EFI_STATUS             Status;
> +  UINT32                 Index;
> +  UINT8                  Timeout;
> +
> +  //
> +  // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set
> after
> +  // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 *
> Cap.To.
> +  //
> +  if (Nvme->Cap.To == 0) {
> +    Timeout = 1;
> +  } else {
> +    Timeout = Nvme->Cap.To;
> +  }
> +
> +  Status = EFI_SUCCESS;
> +  for(Index = (Timeout * 500); Index != 0; --Index) {
> +    MicroSecondDelay (1000);
> +
> +    //
> +    // Check if the controller is initialized
> +    //
> +    Status = NVME_GET_CSTS (Nvme, &Csts);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n",
> Status));
> +      return Status;
> +    }
> +
> +    if ((BOOLEAN) Csts.Rdy == WaitReady) {
> +      break;
> +    }
> +  }
> +
> +  if (Index == 0) {
> +    Status = EFI_TIMEOUT;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Disable the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully disable the controller.
> +  @return others                    - Fail to disable the controller.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeDisableController (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  NVME_CC                Cc;
> +  NVME_CSTS              Csts;
> +  EFI_STATUS             Status;
> +
> +  Status = NVME_GET_CSTS (Nvme, &Csts);
> +
> +  ///
> +  /// Read Controller Configuration Register.
> +  ///
> +  Status = NVME_GET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  if (Cc.En == 1) {
> +    Cc.En = 0;
> +    ///
> +    /// Disable the controller.
> +    ///
> +    Status = NVME_SET_CC (Nvme, &Cc);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> +      goto Done;
> +    }
> +  }
> +
> +  Status = NvmeWaitController (Nvme, FALSE);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  DEBUG ((DEBUG_INFO, "NvmeDisableController fail, Status: %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  Enable the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully enable the controller.
> +  @return EFI_DEVICE_ERROR          - Fail to enable the controller.
> +  @return EFI_TIMEOUT               - Fail to enable the controller in
> given time slot.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeEnableController (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  NVME_CC                Cc;
> +  EFI_STATUS             Status;
> +
> +  //
> +  // Enable the controller
> +  //
> +  ZeroMem (&Cc, sizeof (NVME_CC));
> +  Cc.En     = 1;
> +  Cc.Iosqes = 6;
> +  Cc.Iocqes = 4;
> +  Status    = NVME_SET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  Status = NvmeWaitController (Nvme, TRUE);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  DEBUG ((DEBUG_INFO, "NvmeEnableController fail, Status: %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  Shutdown the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully shutdown the
> controller.
> +  @return EFI_DEVICE_ERROR          - Fail to shutdown the controller.
> +  @return EFI_TIMEOUT               - Fail to shutdown the controller in
> given time slot.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeShutdownController (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  NVME_CC                Cc;
> +  NVME_CSTS              Csts;
> +  EFI_STATUS             Status;
> +  UINT32                 Index;
> +  UINTN                  Timeout;
> +
> +  Status    = NVME_GET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
> +    return Status;
> +  }
> +
> +  Cc.Shn     = 1; // Normal shutdown
> +
> +  Status    = NVME_SET_CC (Nvme, &Cc);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> +    return Status;
> +  }
> +
> +  Timeout = NVME_GENERIC_TIMEOUT/1000; // ms
> +  for(Index = (UINT32)(Timeout); Index != 0; --Index) {
> +    MicroSecondDelay (1000);
> +
> +    Status = NVME_GET_CSTS (Nvme, &Csts);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n",
> Status));
> +      return Status;
> +    }
> +
> +    if (Csts.Shst == 2) { // Shutdown processing complete
> +      break;
> +    }
> +  }
> +
> +  if (Index == 0) {
> +    Status = EFI_TIMEOUT;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Check the execution status from a given completion queue entry.
> +
> +  @param[in]     Cq                 - A pointer to the NVME_CQ item.
> +
> +**/
> +EFI_STATUS
> +NvmeCheckCqStatus (
> +  IN NVME_CQ             *Cq
> +  )
> +{
> +  if (Cq->Sct == 0x0 && Cq->Sc == 0x0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Dump NVMe Completion Entry Status from
> [0x%x]:\n", (UINTN)Cq));
> +  DEBUG ((DEBUG_INFO, "  SQ Identifier : [0x%x], Phase Tag : [%d], Cmd
> Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
> +  DEBUG ((DEBUG_INFO, "  NVMe Cmd Execution Result - "));
> +
> +  switch (Cq->Sct) {
> +    case 0x0:
> +      switch (Cq->Sc) {
> +        case 0x0:
> +          DEBUG ((DEBUG_INFO, "Successful Completion\n"));
> +          return EFI_SUCCESS;
> +        case 0x1:
> +          DEBUG ((DEBUG_INFO, "Invalid Command Opcode\n"));
> +          break;
> +        case 0x2:
> +          DEBUG ((DEBUG_INFO, "Invalid Field in Command\n"));
> +          break;
> +        case 0x3:
> +          DEBUG ((DEBUG_INFO, "Command ID Conflict\n"));
> +          break;
> +        case 0x4:
> +          DEBUG ((DEBUG_INFO, "Data Transfer Error\n"));
> +          break;
> +        case 0x5:
> +          DEBUG ((DEBUG_INFO, "Commands Aborted due to Power Loss
> Notification\n"));
> +          break;
> +        case 0x6:
> +          DEBUG ((DEBUG_INFO, "Internal Device Error\n"));
> +          break;
> +        case 0x7:
> +          DEBUG ((DEBUG_INFO, "Command Abort Requested\n"));
> +          break;
> +        case 0x8:
> +          DEBUG ((DEBUG_INFO, "Command Aborted due to SQ
> Deletion\n"));
> +          break;
> +        case 0x9:
> +          DEBUG ((DEBUG_INFO, "Command Aborted due to Failed Fused
> Command\n"));
> +          break;
> +        case 0xA:
> +          DEBUG ((DEBUG_INFO, "Command Aborted due to Missing Fused
> Command\n"));
> +          break;
> +        case 0xB:
> +          DEBUG ((DEBUG_INFO, "Invalid Namespace or Format\n"));
> +          break;
> +        case 0xC:
> +          DEBUG ((DEBUG_INFO, "Command Sequence Error\n"));
> +          break;
> +        case 0xD:
> +          DEBUG ((DEBUG_INFO, "Invalid SGL Last Segment Descriptor\n"));
> +          break;
> +        case 0xE:
> +          DEBUG ((DEBUG_INFO, "Invalid Number of SGL Descriptors\n"));
> +          break;
> +        case 0xF:
> +          DEBUG ((DEBUG_INFO, "Data SGL Length Invalid\n"));
> +          break;
> +        case 0x10:
> +          DEBUG ((DEBUG_INFO, "Metadata SGL Length Invalid\n"));
> +          break;
> +        case 0x11:
> +          DEBUG ((DEBUG_INFO, "SGL Descriptor Type Invalid\n"));
> +          break;
> +        case 0x80:
> +          DEBUG ((DEBUG_INFO, "LBA Out of Range\n"));
> +          break;
> +        case 0x81:
> +          DEBUG ((DEBUG_INFO, "Capacity Exceeded\n"));
> +          break;
> +        case 0x82:
> +          DEBUG ((DEBUG_INFO, "Namespace Not Ready\n"));
> +          break;
> +        case 0x83:
> +          DEBUG ((DEBUG_INFO, "Reservation Conflict\n"));
> +          break;
> +      }
> +      break;
> +
> +    case 0x1:
> +      switch (Cq->Sc) {
> +        case 0x0:
> +          DEBUG ((DEBUG_INFO, "Completion Queue Invalid\n"));
> +          break;
> +        case 0x1:
> +          DEBUG ((DEBUG_INFO, "Invalid Queue Identifier\n"));
> +          break;
> +        case 0x2:
> +          DEBUG ((DEBUG_INFO, "Maximum Queue Size Exceeded\n"));
> +          break;
> +        case 0x3:
> +          DEBUG ((DEBUG_INFO, "Abort Command Limit Exceeded\n"));
> +          break;
> +        case 0x5:
> +          DEBUG ((DEBUG_INFO, "Asynchronous Event Request Limit
> Exceeded\n"));
> +          break;
> +        case 0x6:
> +          DEBUG ((DEBUG_INFO, "Invalid Firmware Slot\n"));
> +          break;
> +        case 0x7:
> +          DEBUG ((DEBUG_INFO, "Invalid Firmware Image\n"));
> +          break;
> +        case 0x8:
> +          DEBUG ((DEBUG_INFO, "Invalid Interrupt Vector\n"));
> +          break;
> +        case 0x9:
> +          DEBUG ((DEBUG_INFO, "Invalid Log Page\n"));
> +          break;
> +        case 0xA:
> +          DEBUG ((DEBUG_INFO, "Invalid Format\n"));
> +          break;
> +        case 0xB:
> +          DEBUG ((DEBUG_INFO, "Firmware Application Requires
> Conventional Reset\n"));
> +          break;
> +        case 0xC:
> +          DEBUG ((DEBUG_INFO, "Invalid Queue Deletion\n"));
> +          break;
> +        case 0xD:
> +          DEBUG ((DEBUG_INFO, "Feature Identifier Not Saveable\n"));
> +          break;
> +        case 0xE:
> +          DEBUG ((DEBUG_INFO, "Feature Not Changeable\n"));
> +          break;
> +        case 0xF:
> +          DEBUG ((DEBUG_INFO, "Feature Not Namespace Specific\n"));
> +          break;
> +        case 0x10:
> +          DEBUG ((DEBUG_INFO, "Firmware Application Requires NVM
> Subsystem Reset\n"));
> +          break;
> +        case 0x80:
> +          DEBUG ((DEBUG_INFO, "Conflicting Attributes\n"));
> +          break;
> +        case 0x81:
> +          DEBUG ((DEBUG_INFO, "Invalid Protection Information\n"));
> +          break;
> +        case 0x82:
> +          DEBUG ((DEBUG_INFO, "Attempted Write to Read Only Range\n"));
> +          break;
> +      }
> +      break;
> +
> +    case 0x2:
> +      switch (Cq->Sc) {
> +        case 0x80:
> +          DEBUG ((DEBUG_INFO, "Write Fault\n"));
> +          break;
> +        case 0x81:
> +          DEBUG ((DEBUG_INFO, "Unrecovered Read Error\n"));
> +          break;
> +        case 0x82:
> +          DEBUG ((DEBUG_INFO, "End-to-end Guard Check Error\n"));
> +          break;
> +        case 0x83:
> +          DEBUG ((DEBUG_INFO, "End-to-end Application Tag Check
> Error\n"));
> +          break;
> +        case 0x84:
> +          DEBUG ((DEBUG_INFO, "End-to-end Reference Tag Check
> Error\n"));
> +          break;
> +        case 0x85:
> +          DEBUG ((DEBUG_INFO, "Compare Failure\n"));
> +          break;
> +        case 0x86:
> +          DEBUG ((DEBUG_INFO, "Access Denied\n"));
> +          break;
> +      }
> +      break;
> +
> +    default:
> +      DEBUG ((DEBUG_INFO, "Unknown error\n"));
> +      break;
> +  }
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> +  Create PRP lists for Data transfer which is larger than 2 memory pages.
> +  Note here we calcuate the number of required PRP lists and allocate them at
> one time.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] SqId                   - The SQ index for this PRP
> +  @param[in] PhysicalAddr           - The physical base address of Data
> Buffer.
> +  @param[in] Pages                  - The number of pages to be
> transfered.
> +  @param[out] PrpListHost           - The host base address of PRP lists.
> +  @param[in,out] PrpListNo          - The number of PRP List.
> +
> +  @retval The pointer Value to the first PRP List of the PRP lists.
> +
> +**/
> +STATIC
> +UINT64
> +NvmeCreatePrpList (
> +  IN     NVME_CONTEXT                 *Nvme,
> +  IN     UINT16                       SqId,
> +  IN     EFI_PHYSICAL_ADDRESS         PhysicalAddr,
> +  IN     UINTN                        Pages,
> +     OUT VOID                         **PrpListHost,
> +  IN OUT UINTN                        *PrpListNo
> +  )
> +{
> +  UINTN                       PrpEntryNo;
> +  UINT64                      PrpListBase;
> +  UINTN                       PrpListIndex;
> +  UINTN                       PrpEntryIndex;
> +  UINT64                      Remainder;
> +  EFI_PHYSICAL_ADDRESS        PrpListPhyAddr;
> +  UINTN                       Bytes;
> +  UINT8                       *PrpEntry;
> +  EFI_PHYSICAL_ADDRESS        NewPhyAddr;
> +
> +  ///
> +  /// The number of Prp Entry in a memory page.
> +  ///
> +  PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
> +
> +  ///
> +  /// Calculate total PrpList number.
> +  ///
> +  *PrpListNo = (UINTN) DivU64x64Remainder ((UINT64)Pages,
> (UINT64)PrpEntryNo, &Remainder);
> +  if (Remainder != 0) {
> +    *PrpListNo += 1;
> +  }
> +
> +  if (*PrpListNo > NVME_PRP_SIZE) {
> +    DEBUG ((DEBUG_INFO, "NvmeCreatePrpList (PhysicalAddr: %lx, Pages: %x)
> PrpEntryNo: %x\n",
> +      PhysicalAddr, Pages, PrpEntryNo));
> +    DEBUG ((DEBUG_INFO, "*PrpListNo: %x, Remainder: %lx", *PrpListNo,
> Remainder));
> +    ASSERT (FALSE);
> +  }
> +  *PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Nvme, SqId);
> +
> +  Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
> +  PrpListPhyAddr = (UINT64)(UINTN)(*PrpListHost);
> +
> +  ///
> +  /// Fill all PRP lists except of last one.
> +  ///
> +  ZeroMem (*PrpListHost, Bytes);
> +  for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
> +    PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
> +
> +    for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
> +      PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex *
> sizeof(UINT64));
> +      if (PrpEntryIndex != PrpEntryNo - 1) {
> +        ///
> +        /// Fill all PRP entries except of last one.
> +        ///
> +        CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof
> (UINT64));
> +        PhysicalAddr += EFI_PAGE_SIZE;
> +      } else {
> +        ///
> +        /// Fill last PRP entries with next PRP List pointer.
> +        ///
> +        NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) *
> EFI_PAGE_SIZE);
> +        CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof
> (UINT64));
> +      }
> +    }
> +  }
> +
> +  ///
> +  /// Fill last PRP list.
> +  ///
> +  PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
> +  for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder :
> PrpEntryNo); ++PrpEntryIndex) {
> +    PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex *
> sizeof(UINT64));
> +    CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
> +
> +    PhysicalAddr += EFI_PAGE_SIZE;
> +  }
> +
> +  return PrpListPhyAddr;
> +}
> +
> +/**
> +  Check whether there are available command slots.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - Available command slot is found
> +  @retval EFI_NOT_READY             - No available command slot is found
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeHasFreeCmdSlot (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  )
> +{
> +  return TRUE;
> +}
> +
> +/**
> +  Check whether all command slots are clean.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All command slots are clean
> +  @retval EFI_NOT_READY             - Not all command slots are clean
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeIsAllCmdSlotClean (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Waits until all NVME commands completed.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All NVME commands have
> completed
> +  @retval EFI_TIMEOUT               - Timeout occured
> +  @retval EFI_NOT_READY             - Not all NVME commands have
> completed
> +  @retval others                    - Error occurred on device side.
> +**/
> +EFI_STATUS
> +NvmeWaitAllComplete (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Sends an NVM Express Command Packet to an NVM Express controller or
> namespace. This function supports
> +  both blocking I/O and nonblocking I/O. The blocking I/O functionality is
> required, and the nonblocking
> +  I/O functionality is optional.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which
> the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      ID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to
> which the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      UUID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in,out] Packet             - A pointer to the NVM Express HCI
> Command Packet to send to the NVMe namespace specified
> +                                      by NamespaceId.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Command Packet
> was sent by the host. TransferLength bytes were transferred
> +                                      to, or from DataBuffer.
> +  @retval EFI_NOT_READY             - The NVM Express Command Packet
> could not be sent because the controller is not ready. The caller
> +                                      may retry again later.
> +  @retval EFI_DEVICE_ERROR          - A device error occurred while
> attempting to send the NVM Express Command Packet.
> +  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of
> NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
> +                                      Express Command Packet was not
> sent, so no additional status information is available.
> +  @retval EFI_UNSUPPORTED           - The command described by the
> NVM Express Command Packet is not supported by the host adapter.
> +                                      The NVM Express Command
> Packet was not sent, so no additional status information is available.
> +  @retval EFI_TIMEOUT               - A timeout occurred while waiting
> for the NVM Express Command Packet to execute.
> +
> +**/
> +EFI_STATUS
> +NvmePassThru (
> +  IN     NVME_CONTEXT                         *Nvme,
> +  IN     UINT32                               NamespaceId,
> +  IN     UINT64                               NamespaceUuid,
> +  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  NVME_SQ                       *Sq;
> +  NVME_CQ                       *Cq;
> +  UINT8                         Qid;
> +  UINT32                        Bytes;
> +  UINT32                        Offset;
> +  EFI_PHYSICAL_ADDRESS          PhyAddr;
> +  VOID                          *PrpListHost;
> +  UINTN                         PrpListNo;
> +  UINT32                        Timer;
> +  UINTN SqSize;
> +  UINTN CqSize;
> +
> +  ///
> +  /// check the Data fields in Packet parameter.
> +  ///
> +  if ((Nvme == NULL) || (Packet == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> Nvme(%x)/Packet(%x)\n",
> +      (UINTN)Nvme, (UINTN)Packet));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((Packet->NvmeCmd == NULL) || (Packet->NvmeResponse == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> NvmeCmd(%x)/NvmeResponse(%x)\n",
> +      (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeResponse));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Packet->QueueId != NVME_ADMIN_QUEUE && Packet->QueueId !=
> NVME_IO_QUEUE) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> QueueId(%x)\n",
> +      Packet->QueueId));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PrpListHost = NULL;
> +  PrpListNo   = 0;
> +  Status      = EFI_SUCCESS;
> +
> +  Qid = Packet->QueueId;
> +  Sq  = Nvme->SqBuffer[Qid] + Nvme->SqTdbl[Qid].Sqt;
> +  Cq  = Nvme->CqBuffer[Qid] + Nvme->CqHdbl[Qid].Cqh;
> +  if (Qid == NVME_ADMIN_QUEUE) {
> +    SqSize = NVME_ASQ_SIZE + 1;
> +    CqSize = NVME_ACQ_SIZE + 1;
> +  } else {
> +    SqSize = NVME_CSQ_DEPTH;
> +    CqSize = NVME_CCQ_DEPTH;
> +  }
> +
> +  if (Packet->NvmeCmd->Nsid != NamespaceId) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru: Nsid mismatch (%x, %x)\n",
> +      Packet->NvmeCmd->Nsid, NamespaceId));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ZeroMem (Sq, sizeof (NVME_SQ));
> +  Sq->Opc  = Packet->NvmeCmd->Cdw0.Opcode;
> +  Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation;
> +  Sq->Cid  = Packet->NvmeCmd->Cdw0.Cid;
> +  Sq->Nsid = Packet->NvmeCmd->Nsid;
> +
> +  ///
> +  /// Currently we only support PRP for Data transfer, SGL is NOT supported.
> +  ///
> +  ASSERT (Sq->Psdt == 0);
> +  if (Sq->Psdt != 0) {
> +    DEBUG ((DEBUG_ERROR, "NvmePassThru: doesn't support SGL
> mechanism\n"));
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Sq->Prp[0] = Packet->TransferBuffer;
> +  Sq->Prp[1] = 0;
> +
> +  if(Packet->MetadataBuffer != (UINT64)(UINTN)NULL) {
> +    Sq->Mptr = Packet->MetadataBuffer;
> +  }
> +
> +  ///
> +  /// If the Buffer Size spans more than two memory pages (page Size as
> defined in CC.Mps),
> +  /// then build a PRP list in the second PRP submission queue entry.
> +  ///
> +  Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
> +  Bytes  = Packet->TransferLength;
> +
> +  if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
> +    ///
> +    /// Create PrpList for remaining Data Buffer.
> +    ///
> +    PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
> +    Sq->Prp[1] = NvmeCreatePrpList (Nvme, Nvme->SqTdbl[Qid].Sqt, PhyAddr,
> EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo);
> +    if (Sq->Prp[1] == 0) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      DEBUG ((DEBUG_ERROR, "NvmeCreatePrpList fail, Status: %r\n",
> Status));
> +      goto EXIT;
> +    }
> +
> +  } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
> +    Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
> +  }
> +
> +  if(Packet->NvmeCmd->Flags & CDW10_VALID) {
> +    Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW11_VALID) {
> +    Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW12_VALID) {
> +    Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW13_VALID) {
> +    Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW14_VALID) {
> +    Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
> +  }
> +  if(Packet->NvmeCmd->Flags & CDW15_VALID) {
> +    Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
> +  }
> +
> +  ///
> +  /// Ring the submission queue doorbell.
> +  ///
> +  Nvme->SqTdbl[Qid].Sqt++;
> +  if(Nvme->SqTdbl[Qid].Sqt == SqSize) {
> +    Nvme->SqTdbl[Qid].Sqt = 0;
> +  }
> +  Status = NVME_SET_SQTDBL (Nvme, Qid, &Nvme->SqTdbl[Qid]);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_SET_SQTDBL fail, Status: %r\n",
> Status));
> +    goto EXIT;
> +  }
> +
> +  ///
> +  /// Wait for completion queue to get filled in.
> +  ///
> +  Status = EFI_TIMEOUT;
> +  Timer   = 0;
> +  while (Timer < NVME_CMD_TIMEOUT) {
> +    //DEBUG ((DEBUG_VERBOSE, "Timer: %x, Cq:\n", Timer));
> +    //DumpMem (Cq, sizeof (NVME_CQ));
> +    if (Cq->Pt != Nvme->Pt[Qid]) {
> +      Status = EFI_SUCCESS;
> +      break;
> +    }
> +
> +    MicroSecondDelay (NVME_CMD_WAIT);
> +    Timer += NVME_CMD_WAIT;
> +  }
> +
> +  Nvme->CqHdbl[Qid].Cqh++;
> +  if (Nvme->CqHdbl[Qid].Cqh == CqSize) {
> +    Nvme->CqHdbl[Qid].Cqh = 0;
> +    Nvme->Pt[Qid] ^= 1;
> +  }
> +
> +  ///
> +  /// Copy the Respose Queue entry for this command to the callers response
> Buffer
> +  ///
> +  CopyMem (Packet->NvmeResponse, Cq, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  if (!EFI_ERROR(Status)) { // We still need to check CQ status if no timeout
> error occured
> +    Status = NvmeCheckCqStatus (Cq);
> +  }
> +  NVME_SET_CQHDBL (Nvme, Qid, &Nvme->CqHdbl[Qid]);
> +
> +EXIT:
> +  return Status;
> +}
> +
> +/**
> +  Get identify controller Data.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer used to store the identify
> controller Data.
> +
> +  @return EFI_SUCCESS               - Successfully get the identify
> controller Data.
> +  @return others                    - Fail to get the identify controller
> Data.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeIdentifyController (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN VOID                                  *Buffer
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  //
> +  // According to Nvm Express 1.1 spec Figure 38, When not used, the field
> shall be cleared to 0h.
> +  // For the Identify command, the Namespace Identifier is only used for the
> Namespace Data structure.
> +  //
> +  Command.Nsid        = 0;
> +
> +  CommandPacket.NvmeCmd        = &Command;
> +  CommandPacket.NvmeResponse   = &Response;
> +  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
> +  CommandPacket.TransferLength = sizeof
> (NVME_ADMIN_CONTROLLER_DATA);
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +  //
> +  // Set bit 0 (Cns bit) to 1 to identify a controller
> +  //
> +  Command.Cdw10                = 1;
> +  Command.Flags                = CDW10_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get specified identify namespace Data.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] NamespaceId            - The specified namespace identifier.
> +  @param[in] Buffer                 - The Buffer used to store the identify
> namespace Data.
> +
> +  @return EFI_SUCCESS               - Successfully get the identify
> namespace Data.
> +  @return others                    - Fail to get the identify namespace
> Data.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeIdentifyNamespace (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN UINT32                                NamespaceId,
> +  IN VOID                                  *Buffer
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  Command.Nsid        = NamespaceId;
> +  CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
> +  CommandPacket.TransferLength = sizeof
> (NVME_ADMIN_NAMESPACE_DATA);
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +  //
> +  // Set bit 0 (Cns bit) to 1 to identify a namespace
> +  //
> +  CommandPacket.NvmeCmd->Cdw10 = 0;
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NamespaceId,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get Block Size for specific namespace of NVME.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return                           - Block Size in bytes
> +
> +**/
> +STATIC
> +UINT32
> +NvmeGetBlockSize (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  UINT32                BlockSize;
> +  UINT32                Lbads;
> +  UINT32                Flbas;
> +  UINT32                LbaFmtIdx;
> +
> +  Flbas     = Nvme->NamespaceData->Flbas;
> +  LbaFmtIdx = Flbas & 3;
> +  Lbads     = Nvme->NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
> +
> +  BlockSize = (UINT32)1 << Lbads;
> +  return BlockSize;
> +}
> +
> +/**
> +  Get last LBA for specific namespace of NVME.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return                           - Last LBA address
> +
> +**/
> +STATIC
> +EFI_LBA
> +NvmeGetLastLba (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_LBA               LastBlock;
> +  LastBlock = Nvme->NamespaceData->Nsze - 1;
> +  return LastBlock;
> +}
> +
> +/**
> +  Create io completion queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully create io completion
> queue.
> +  @return others                    - Fail to create io completion queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeCreateIoCompletionQueue (
> +  IN     NVME_CONTEXT                      *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_CRIOCQ                        CrIoCq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  CrIoCq.Qid   = NVME_IO_QUEUE;
> +  CrIoCq.Qsize = NVME_CCQ_SIZE;
> +  CrIoCq.Pc    = 1;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof
> (NVME_ADMIN_CRIOCQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Create io submission queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully create io submission
> queue.
> +  @return others                    - Fail to create io submission queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeCreateIoSubmissionQueue (
> +  IN NVME_CONTEXT                          *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_CRIOSQ                        CrIoSq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  CrIoSq.Qid   = NVME_IO_QUEUE;
> +  CrIoSq.Qsize = NVME_CSQ_SIZE;
> +  CrIoSq.Pc    = 1;
> +  CrIoSq.Cqid  = NVME_IO_QUEUE;
> +  CrIoSq.Qprio = 0;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof
> (NVME_ADMIN_CRIOSQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Security send and receive commands.
> +
> +  @param[in]     Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in]     SendCommand            - The flag to indicate the
> command type, TRUE for Send command and FALSE for receive command
> +  @param[in]     SecurityProtocol       - Security Protocol
> +  @param[in]     SpSpecific             - Security Protocol Specific
> +  @param[in]     TransferLength         - Transfer Length of Buffer (in
> bytes) - always a multiple of 512
> +  @param[in,out] TransferBuffer         - Address of Data to transfer
> +
> +  @return EFI_SUCCESS               - Successfully create io submission
> queue.
> +  @return others                    - Fail to send/receive commands.
> +
> +**/
> +EFI_STATUS
> +NvmeSecuritySendReceive (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN BOOLEAN                               SendCommand,
> +  IN UINT8                                 SecurityProtocol,
> +  IN UINT16                                SpSpecific,
> +  IN UINTN                                 TransferLength,
> +  IN OUT VOID                              *TransferBuffer
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_SECSEND                       SecSend;
> +  OACS                                     *Oacs;
> +  UINT8                                    Opcode;
> +  VOID*                                    *SecBuff;
> +
> +  Oacs = (OACS *)&Nvme->ControllerData->Oacs;
> +
> +  //
> +  // Verify security bit for Security Send/Receive commands
> +  //
> +  if (Oacs->Security == 0) {
> +    DEBUG ((DEBUG_ERROR, "Security command doesn't support.\n"));
> +    return EFI_NOT_READY;
> +  }
> +
> +  SecBuff = (VOID *)(UINTN) NVME_SEC_BASE (Nvme);
> +
> +  //
> +  // Actions for sending security command
> +  //
> +  if (SendCommand) {
> +    CopyMem (SecBuff, TransferBuffer, TransferLength);
> +  }
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&SecSend, sizeof(NVME_ADMIN_SECSEND));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Opcode = (UINT8)(SendCommand ? NVME_ADMIN_SECURITY_SEND_OPC :
> NVME_ADMIN_SECURITY_RECV_OPC);
> +  Command.Cdw0.Opcode = Opcode;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer = (UINT64)(UINTN)SecBuff;
> +  CommandPacket.TransferLength = (UINT32)TransferLength;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  SecSend.Spsp = SpSpecific;
> +  SecSend.Secp = SecurityProtocol;
> +  SecSend.Tl   = (UINT32)TransferLength;
> +
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &SecSend, sizeof
> (NVME_ADMIN_SECSEND));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  //
> +  // Actions for receiving security command
> +  //
> +  if (!SendCommand) {
> +    CopyMem (TransferBuffer, SecBuff, TransferLength);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Destroy io completion queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully destroy io completion
> queue.
> +  @return others                    - Fail to destroy io completion queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeDestroyIoCompletionQueue (
> +  IN     NVME_CONTEXT                      *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_DEIOCQ                        DelIoCq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&DelIoCq, sizeof(NVME_ADMIN_DEIOCQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_DELIOCQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->CqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  DelIoCq.Qid   = NVME_IO_QUEUE;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoCq, sizeof
> (NVME_ADMIN_DEIOCQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Destroy io submission queue.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @return EFI_SUCCESS               - Successfully destroy io submission
> queue.
> +  @return others                    - Fail to destroy io submission queue.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +NvmeDestroyIoSubmissionQueue (
> +  IN NVME_CONTEXT                          *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  NVME_ADMIN_DEIOSQ                        DelIoSq;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +  ZeroMem (&DelIoSq, sizeof(NVME_ADMIN_DEIOSQ));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  Command.Cdw0.Opcode = NVME_ADMIN_DELIOSQ_OPC;
> +  Command.Cdw0.Cid    = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> +  CommandPacket.TransferBuffer =
> (UINT64)(UINTN)Nvme->SqBuffer[NVME_IO_QUEUE];
> +  CommandPacket.TransferLength = EFI_PAGE_SIZE;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_ADMIN_QUEUE;
> +
> +  DelIoSq.Qid   = NVME_IO_QUEUE;
> +  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoSq, sizeof
> (NVME_ADMIN_DEIOSQ));
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              NVME_CONTROLLER_ID,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Allocate transfer-related Data struct which is used at Nvme.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeAllocateResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
> +  VOID                      *Base;
> +  VOID                      *Mapping;
> +
> +  //
> +  // Allocate resources for DMA.
> +  //
> +  Status = IoMmuAllocateBuffer (
> +             EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
> +             &Base,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> +  Nvme->BaseMemMapping = Mapping;
> +  Nvme->BaseMem = Base;
> +  ZeroMem (Nvme->BaseMem, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (NVME_MEM_MAX_SIZE));
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a() NvmeContext 0x%x\n",
> +    __FUNCTION__,
> +    Nvme->BaseMem
> +    ));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Free allocated transfer-related Data struct which is used at NVMe.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +**/
> +VOID
> +EFIAPI
> +NvmeFreeResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  )
> +{
> +  if (Nvme->BaseMem != NULL) {
> +    IoMmuFreeBuffer (
> +       EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
> +       Nvme->BaseMem,
> +       Nvme->BaseMemMapping
> +       );
> +    Nvme->BaseMem = NULL;
> +  }
> +}
> +
> +/**
> +  Initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> initialized successfully.
> +  @retval Others                    - A device error occurred while
> initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerInit (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_STATUS            Status;
> +  NVME_AQA              Aqa;
> +  NVME_ASQ              Asq;
> +  NVME_ACQ              Acq;
> +  NVME_VER              Ver;
> +
> +  UINT32                MlBAR;
> +  UINT32                MuBAR;
> +
> +  ///
> +  /// Update PCIE BAR0/1 for NVME device
> +  ///
> +  MlBAR = Nvme->Nbar;
> +  MuBAR = 0;
> +  PciWrite32 (Nvme->PciBase + 0x10, MlBAR); // MLBAR (BAR0)
> +  PciWrite32 (Nvme->PciBase + 0x14, MuBAR); // MUBAR (BAR1)
> +
> +  ///
> +  /// Enable PCIE decode
> +  ///
> +  PciWrite8 (Nvme->PciBase + NVME_PCIE_PCICMD, 0x6);
> +
> +  // Version
> +  NVME_GET_VER (Nvme, &Ver);
> +  if (!(Ver.Mjr == 0x0001) && (Ver.Mnr == 0x0000)) {
> +    DEBUG ((DEBUG_INFO, "\n!!!\n!!! NVME Version mismatch for the
> implementation !!!\n!!!\n"));
> +  }
> +
> +  ///
> +  /// Read the Controller Capabilities register and verify that the NVM
> command set is supported
> +  ///
> +  Status = NVME_GET_CAP (Nvme, &Nvme->Cap);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "NVME_GET_CAP fail, Status: %r\n", Status));
> +    goto Done;
> +  }
> +
> +  if (Nvme->Cap.Css != 0x01) {
> +    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: the controller doesn't
> support NVMe command set\n"));
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Currently the driver only supports 4k page Size.
> +  ///
> +  if ((Nvme->Cap.Mpsmin + 12) > EFI_PAGE_SHIFT) {
> +    DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: only supports 4k page
> Size\n"));
> +    ASSERT (FALSE);
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
> +  Nvme->Cid[0] = 0;
> +  Nvme->Cid[1] = 0;
> +
> +  Nvme->Pt[0]  = 0;
> +  Nvme->Pt[1]  = 0;
> +
> +  ZeroMem ((VOID *)(UINTN)(&(Nvme->SqTdbl[0])), sizeof (NVME_SQTDBL) *
> NVME_MAX_IO_QUEUES);
> +  ZeroMem ((VOID *)(UINTN)(&(Nvme->CqHdbl[0])), sizeof (NVME_CQHDBL)
> * NVME_MAX_IO_QUEUES);
> +
> +  ZeroMem (Nvme->BaseMem, NVME_MEM_MAX_SIZE);
> +
> +  Status = NvmeDisableController (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeDisableController fail, Status: %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  ///
> +  /// set number of entries admin submission & completion queues.
> +  ///
> +  Aqa.Asqs  = NVME_ASQ_SIZE;
> +  Aqa.Rsvd1 = 0;
> +  Aqa.Acqs  = NVME_ACQ_SIZE;
> +  Aqa.Rsvd2 = 0;
> +
> +  ///
> +  /// Address of admin submission queue.
> +  ///
> +  Asq = (UINT64)(UINTN)(NVME_ASQ_BASE (Nvme) & ~0xFFF);
> +
> +  ///
> +  /// Address of admin completion queue.
> +  ///
> +  Acq = (UINT64)(UINTN)(NVME_ACQ_BASE (Nvme) & ~0xFFF);
> +
> +  ///
> +  /// Address of I/O submission & completion queue.
> +  ///
> +  Nvme->SqBuffer[0] = (NVME_SQ *)(UINTN)NVME_ASQ_BASE (Nvme);   //
> NVME_ADMIN_QUEUE
> +  Nvme->CqBuffer[0] = (NVME_CQ *)(UINTN)NVME_ACQ_BASE (Nvme);   //
> NVME_ADMIN_QUEUE
> +  Nvme->SqBuffer[1] = (NVME_SQ *)(UINTN)NVME_SQ_BASE (Nvme, 0); //
> NVME_IO_QUEUE
> +  Nvme->CqBuffer[1] = (NVME_CQ *)(UINTN)NVME_CQ_BASE (Nvme, 0); //
> NVME_IO_QUEUE
> +
> +  DEBUG ((DEBUG_INFO, "Admin Submission Queue Size (Aqa.Asqs) =
> [%08X]\n", Aqa.Asqs));
> +  DEBUG ((DEBUG_INFO, "Admin Completion Queue Size (Aqa.Acqs) =
> [%08X]\n", Aqa.Acqs));
> +  DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) =
> [%08X]\n", Nvme->SqBuffer[0]));
> +  DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) =
> [%08X]\n", Nvme->CqBuffer[0]));
> +  DEBUG ((DEBUG_INFO, "I/O   Submission Queue (SqBuffer[1]) =
> [%08X]\n", Nvme->SqBuffer[1]));
> +  DEBUG ((DEBUG_INFO, "I/O   Completion Queue (CqBuffer[1]) =
> [%08X]\n", Nvme->CqBuffer[1]));
> +
> +  ///
> +  /// Program admin queue attributes.
> +  ///
> +  Status = NVME_SET_AQA (Nvme, &Aqa);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Program admin submission queue address.
> +  ///
> +  Status = NVME_SET_ASQ (Nvme, &Asq);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Program admin completion queue address.
> +  ///
> +  Status = NVME_SET_ACQ (Nvme, &Acq);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  Status = NvmeEnableController (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Create one I/O completion queue.
> +  ///
> +  Status = NvmeCreateIoCompletionQueue (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Create one I/O Submission queue.
> +  ///
> +  Status = NvmeCreateIoSubmissionQueue (Nvme);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Get current Identify Controller Data
> +  ///
> +  Nvme->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)(UINTN)
> NVME_CONTROL_DATA_BASE (Nvme);
> +  Status = NvmeIdentifyController (Nvme, Nvme->ControllerData);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Dump NvmExpress Identify Controller Data
> +  ///
> +  Nvme->ControllerData->Sn[19] = 0;
> +  Nvme->ControllerData->Mn[39] = 0;
> +  //NvmeDumpIdentifyController (Nvme->ControllerData);
> +
> +  ///
> +  /// Get current Identify Namespace Data
> +  ///
> +  Nvme->NamespaceData = (NVME_ADMIN_NAMESPACE_DATA
> *)NVME_NAMESPACE_DATA_BASE (Nvme);
> +  Status = NvmeIdentifyNamespace (Nvme, Nvme->Nsid,
> Nvme->NamespaceData);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "NvmeIdentifyNamespace fail, Status = %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  ///
> +  /// Dump NvmExpress Identify Namespace Data
> +  ///
> +  if (Nvme->NamespaceData->Ncap == 0) {
> +    DEBUG ((DEBUG_ERROR, "Invalid Namespace, Ncap: %lx\n",
> Nvme->NamespaceData->Ncap));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Done;
> +  }
> +
> +  Nvme->BlockSize = NvmeGetBlockSize (Nvme);
> +  Nvme->LastBlock = NvmeGetLastLba (Nvme);
> +
> +  Nvme->State    = NvmeStatusInit;
> +
> +  return EFI_SUCCESS;
> +
> +Done:
> +  return Status;
> +}
> +
> +/**
> +  Un-initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> un-initialized successfully.
> +  @retval Others                    - A device error occurred while
> un-initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerExit (
> +  IN NVME_CONTEXT       *Nvme
> +  )
> +{
> +  EFI_STATUS            Status;
> +
> +  Status = EFI_SUCCESS;
> +  if (Nvme->State == NvmeStatusInit || Nvme->State == NvmeStatusMax) {
> +    ///
> +    /// Destroy I/O Submission queue.
> +    ///
> +    Status = NvmeDestroyIoSubmissionQueue (Nvme);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoSubmissionQueue fail, Status
> = %r\n", Status));
> +      return Status;
> +    }
> +
> +    ///
> +    /// Destroy I/O completion queue.
> +    ///
> +    Status = NvmeDestroyIoCompletionQueue (Nvme);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeDestroyIoCompletionQueue fail, Status
> = %r\n", Status));
> +      return Status;
> +    }
> +
> +    Status = NvmeShutdownController (Nvme);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeShutdownController fail, Status: %r\n",
> Status));
> +    }
> +  }
> +
> +  ///
> +  /// Disable PCIE decode
> +  ///
> +  PciWrite8  (Nvme->PciBase + NVME_PCIE_PCICMD, 0x0);
> +  PciWrite32 (Nvme->PciBase + 0x10, 0); // MLBAR (BAR0)
> +  PciWrite32 (Nvme->PciBase + 0x14, 0); // MUBAR (BAR1)
> +
> +  Nvme->State = NvmeStatusUnknown;
> +  return Status;
> +}
> +
> +/**
> +  Read sector Data from the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in,out] Buffer             - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeReadSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN OUT UINT64                            Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  )
> +{
> +  UINT32                                   Bytes;
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  UINT32                                   BlockSize;
> +
> +  BlockSize  = Nvme->BlockSize;
> +  Bytes      = Blocks * BlockSize;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
> +  CommandPacket.NvmeCmd->Cdw0.Cid    =
> Nvme->Cid[NVME_IO_QUEUE]++;
> +  CommandPacket.NvmeCmd->Nsid        = Nvme->Nsid;
> +  CommandPacket.TransferBuffer       = Buffer;
> +
> +  CommandPacket.TransferLength = Bytes;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_IO_QUEUE;
> +
> +  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
> +  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
> +  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
> +
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID |
> CDW12_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              Nvme->Nsid,
> +              0,
> +              &CommandPacket
> +              );
> +
> +  return Status;
> +}
> +
> +/**
> +  Write sector Data to the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWriteSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN UINT64                                Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +  UINT32                                   Bytes;
> +  UINT32                                   BlockSize;
> +
> +  BlockSize  = Nvme->BlockSize;
> +  Bytes      = Blocks * BlockSize;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
> +  CommandPacket.NvmeCmd->Cdw0.Cid    =
> Nvme->Cid[NVME_IO_QUEUE]++;
> +  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
> +  CommandPacket.TransferBuffer = Buffer;
> +
> +  CommandPacket.TransferLength = Bytes;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_IO_QUEUE;
> +
> +  CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
> +  CommandPacket.NvmeCmd->Cdw11 = (UINT32)(RShiftU64 (Lba, 32));
> +  CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
> +
> +  CommandPacket.MetadataBuffer = (UINT64)(UINTN)NULL;
> +  CommandPacket.MetadataLength = 0;
> +
> +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID |
> CDW12_VALID;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              Nvme->Nsid,
> +              0,
> +              &CommandPacket
> +              );
> +
> +  return Status;
> +}
> +
> +/**
> +  Flushes all modified Data to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeFlush (
> +  IN NVME_CONTEXT                          *Nvme
> +  )
> +{
> +  NVM_EXPRESS_PASS_THRU_COMMAND_PACKET     CommandPacket;
> +  NVM_EXPRESS_COMMAND                      Command;
> +  NVM_EXPRESS_RESPONSE                     Response;
> +  EFI_STATUS                               Status;
> +
> +  ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> +  ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> +  ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> +
> +  CommandPacket.NvmeCmd      = &Command;
> +  CommandPacket.NvmeResponse = &Response;
> +
> +  CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC;
> +  CommandPacket.NvmeCmd->Cdw0.Cid    =
> Nvme->Cid[NVME_IO_QUEUE]++;
> +  CommandPacket.NvmeCmd->Nsid  = Nvme->Nsid;
> +  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> +  CommandPacket.QueueId        = NVME_IO_QUEUE;
> +
> +  Status = NvmePassThru (
> +              Nvme,
> +              Nvme->Nsid,
> +              0,
> +              &CommandPacket
> +              );
> +  if (!EFI_ERROR (Status)) {
> +    Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Read some blocks from the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[out] Buffer                - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeRead (
> +  IN NVME_CONTEXT                  *Nvme,
> +  OUT UINT64                       Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINT32                           BlockSize;
> +  UINT32                           MaxTransferBlocks;
> +
> +  ASSERT (Blocks <= NVME_MAX_SECTORS);
> +  Status        = EFI_SUCCESS;
> +  BlockSize     = Nvme->BlockSize;
> +  if (Nvme->ControllerData->Mdts != 0) {
> +    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 <<
> (Nvme->Cap.Mpsmin + 12)) / BlockSize;
> +  } else {
> +    MaxTransferBlocks = 1024;
> +  }
> +
> +  while (Blocks > 0) {
> +    if (Blocks > MaxTransferBlocks) {
> +      Status = NvmeReadSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
> +
> +      Blocks -= MaxTransferBlocks;
> +      Buffer += (MaxTransferBlocks * BlockSize);
> +      Lba    += MaxTransferBlocks;
> +    } else {
> +      Status = NvmeReadSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
> +      Blocks = 0;
> +    }
> +
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeRead fail, Status = %r\n", Status));
> +      break;
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Write some blocks to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWrite (
> +  IN NVME_CONTEXT                  *Nvme,
> +  IN UINT64                        Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINT32                           BlockSize;
> +  UINT32                           MaxTransferBlocks;
> +
> +  ASSERT (Blocks <= NVME_MAX_SECTORS);
> +  Status        = EFI_SUCCESS;
> +  BlockSize     = Nvme->BlockSize;
> +
> +  if (Nvme->ControllerData->Mdts != 0) {
> +    MaxTransferBlocks = (1 << (Nvme->ControllerData->Mdts)) * (1 <<
> (Nvme->Cap.Mpsmin + 12)) / BlockSize;
> +  } else {
> +    MaxTransferBlocks = 1024;
> +  }
> +
> +  while (Blocks > 0) {
> +    if (Blocks > MaxTransferBlocks) {
> +      Status = NvmeWriteSectors (Nvme, Buffer, Lba, MaxTransferBlocks);
> +
> +      Blocks -= MaxTransferBlocks;
> +      Buffer += (MaxTransferBlocks * BlockSize);
> +      Lba    += MaxTransferBlocks;
> +    } else {
> +      Status = NvmeWriteSectors (Nvme, Buffer, Lba, (UINT32) Blocks);
> +      Blocks = 0;
> +    }
> +
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "NvmeWrite fail, Status = %r\n", Status));
> +      break;
> +    }
> +  }
> +
> +  return Status;
> +}
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> new file mode 100644
> index 000000000000..3fef3dbc1c0d
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> @@ -0,0 +1,455 @@
> +/** @file
> +  Header file for NVMe function definitions
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef __OPAL_PASSWORD_NVME_MODE_H__
> +#define __OPAL_PASSWORD_NVME_MODE_H__
> +
> +
> +#include "OpalNvmeReg.h"
> +
> +#define NVME_MAX_SECTORS            0x10000
> +//
> +// QueueId
> +//
> +#define NVME_ADMIN_QUEUE            0x00
> +#define NVME_IO_QUEUE               0x01
> +
> +typedef struct {
> +  UINT8                             Opcode;
> +  UINT8                             FusedOperation;
> +    #define NORMAL_CMD              0x00
> +    #define FUSED_FIRST_CMD         0x01
> +    #define FUSED_SECOND_CMD        0x02
> +  UINT16                            Cid;
> +} NVME_CDW0;
> +
> +typedef struct {
> +  NVME_CDW0                         Cdw0;
> +  UINT8                             Flags;
> +    #define CDW10_VALID             0x01
> +    #define CDW11_VALID             0x02
> +    #define CDW12_VALID             0x04
> +    #define CDW13_VALID             0x08
> +    #define CDW14_VALID             0x10
> +    #define CDW15_VALID             0x20
> +  UINT32                            Nsid;
> +  UINT32                            Cdw10;
> +  UINT32                            Cdw11;
> +  UINT32                            Cdw12;
> +  UINT32                            Cdw13;
> +  UINT32                            Cdw14;
> +  UINT32                            Cdw15;
> +} NVM_EXPRESS_COMMAND;
> +
> +typedef struct {
> +  UINT32                            Cdw0;
> +  UINT32                            Cdw1;
> +  UINT32                            Cdw2;
> +  UINT32                            Cdw3;
> +} NVM_EXPRESS_RESPONSE;
> +
> +typedef struct {
> +  UINT64                            CommandTimeout;
> +  UINT64                            TransferBuffer;
> +  UINT32                            TransferLength;
> +  UINT64                            MetadataBuffer;
> +  UINT32                            MetadataLength;
> +  UINT8                             QueueId;
> +  NVM_EXPRESS_COMMAND               *NvmeCmd;
> +  NVM_EXPRESS_RESPONSE              *NvmeResponse;
> +} NVM_EXPRESS_PASS_THRU_COMMAND_PACKET;
> +
> +
> +#pragma pack(1)
> +
> +// Internal fields
> +typedef enum {
> +  NvmeStatusUnknown,
> +  NvmeStatusInit,
> +  NvmeStatusInuse,
> +  NvmeStatusMax,
> +} NVME_STATUS;
> +
> +typedef struct {
> +  UINT32                            Nbar;
> +  VOID                              *BaseMem;
> +  VOID                              *BaseMemMapping;
> +  BOOLEAN                           PollCancellation;
> +  UINT16                            NvmeInitWaitTime;
> +
> +  NVME_STATUS                       State;
> +  UINT8                             BusID;
> +  UINT8                             DeviceID;
> +  UINT8                             FuncID;
> +  UINTN                             PciBase;
> +
> +  UINT32                            Nsid;
> +  UINT64                            Nsuuid;
> +  UINT32                            BlockSize;
> +  EFI_LBA                           LastBlock;
> +
> +  //
> +  // Pointers to 4kB aligned submission & completion queues.
> +  //
> +  NVME_SQ
> *SqBuffer[NVME_MAX_IO_QUEUES];
> +  NVME_CQ
> *CqBuffer[NVME_MAX_IO_QUEUES];
> +  UINT16                            Cid[NVME_MAX_IO_QUEUES];
> +
> +  //
> +  // Submission and completion queue indices.
> +  //
> +  NVME_SQTDBL
> SqTdbl[NVME_MAX_IO_QUEUES];
> +  NVME_CQHDBL
> CqHdbl[NVME_MAX_IO_QUEUES];
> +  UINT8                             Pt[NVME_MAX_IO_QUEUES];
> +
> +  UINTN
> SqeCount[NVME_MAX_IO_QUEUES];
> +
> +  //
> +  // Nvme controller capabilities
> +  //
> +  NVME_CAP                          Cap;
> +
> +  //
> +  // pointer to identify controller Data
> +  //
> +  NVME_ADMIN_CONTROLLER_DATA        *ControllerData;
> +  NVME_ADMIN_NAMESPACE_DATA         *NamespaceData;
> +} NVME_CONTEXT;
> +
> +#pragma pack()
> +
> +/**
> +  Transfer MMIO Data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Transfer memory Data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +NvmeMmioWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Transfer memory data to MMIO.
> +
> +  @param[in,out] MmioAddr - Destination: MMIO address
> +  @param[in] MemBuffer    - Source: Memory address
> +  @param[in] Size         - Size for write
> +
> +  @retval EFI_SUCCESS - MMIO write sucessfully
> +**/
> +EFI_STATUS
> +OpalPciWrite (
> +  IN OUT UINTN MmioAddr,
> +  IN     VOID *MemBuffer,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Transfer MMIO data to memory.
> +
> +  @param[in,out] MemBuffer - Destination: Memory address
> +  @param[in] MmioAddr      - Source: MMIO address
> +  @param[in] Size          - Size for read
> +
> +  @retval EFI_SUCCESS - MMIO read sucessfully
> +**/
> +EFI_STATUS
> +OpalPciRead (
> +  IN OUT VOID *MemBuffer,
> +  IN     UINTN MmioAddr,
> +  IN     UINTN Size
> +  );
> +
> +/**
> +  Allocate transfer-related Data struct which is used at Nvme.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +  @retval EFI_OUT_OF_RESOURCE   No enough resource.
> +  @retval EFI_SUCCESS           Successful to allocate resource.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeAllocateResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Free allocated transfer-related Data struct which is used at NVMe.
> +
> +  @param[in, out] Nvme          The pointer to the NVME_CONTEXT Data
> structure.
> +
> +**/
> +VOID
> +EFIAPI
> +NvmeFreeResource (
> +  IN OUT NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Sends an NVM Express Command Packet to an NVM Express controller or
> namespace. This function supports
> +  both blocking I/O and nonblocking I/O. The blocking I/O functionality is
> required, and the nonblocking
> +  I/O functionality is optional.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] NamespaceId            - Is a 32 bit Namespace ID to which
> the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      ID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in] NamespaceUuid          - Is a 64 bit Namespace UUID to
> which the Express HCI command packet will be sent.
> +                                      A Value of 0 denotes the NVM
> Express controller, a Value of all 0FFh in the namespace
> +                                      UUID specifies that the command
> packet should be sent to all valid namespaces.
> +  @param[in,out] Packet             - A pointer to the NVM Express HCI
> Command Packet to send to the NVMe namespace specified
> +                                      by NamespaceId.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Command Packet
> was sent by the host. TransferLength bytes were transferred
> +                                      to, or from DataBuffer.
> +  @retval EFI_NOT_READY             - The NVM Express Command Packet
> could not be sent because the controller is not ready. The caller
> +                                      may retry again later.
> +  @retval EFI_DEVICE_ERROR          - A device error occurred while
> attempting to send the NVM Express Command Packet.
> +  @retval EFI_INVALID_PARAMETER     - Namespace, or the contents of
> NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
> +                                      Express Command Packet was not
> sent, so no additional status information is available.
> +  @retval EFI_UNSUPPORTED           - The command described by the
> NVM Express Command Packet is not supported by the host adapter.
> +                                      The NVM Express Command
> Packet was not sent, so no additional status information is available.
> +  @retval EFI_TIMEOUT               - A timeout occurred while waiting
> for the NVM Express Command Packet to execute.
> +
> +**/
> +EFI_STATUS
> +NvmePassThru (
> +  IN     NVME_CONTEXT                         *Nvme,
> +  IN     UINT32                               NamespaceId,
> +  IN     UINT64                               NamespaceUuid,
> +  IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
> +  );
> +
> +/**
> +  Waits until all NVME commands completed.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All NVME commands have
> completed
> +  @retval EFI_TIMEOUT               - Timeout occured
> +  @retval EFI_NOT_READY             - Not all NVME commands have
> completed
> +  @retval others                    - Error occurred on device side.
> +**/
> +EFI_STATUS
> +NvmeWaitAllComplete (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  );
> +
> +/**
> +  Initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> initialized successfully.
> +  @retval Others                    - A device error occurred while
> initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerInit (
> +  IN NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Un-initialize the Nvm Express controller.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - The NVM Express Controller is
> un-initialized successfully.
> +  @retval Others                    - A device error occurred while
> un-initializing the controller.
> +
> +**/
> +EFI_STATUS
> +NvmeControllerExit (
> +  IN NVME_CONTEXT       *Nvme
> +  );
> +
> +/**
> +  Check whether there are available command slots.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - Available command slot is found
> +  @retval EFI_NOT_READY             - No available command slot is found
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeHasFreeCmdSlot (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  );
> +
> +/**
> +  Check whether all command slots are clean.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Qid                    - Queue index
> +
> +  @retval EFI_SUCCESS               - All command slots are clean
> +  @retval EFI_NOT_READY             - Not all command slots are clean
> +  @retval EFI_DEVICE_ERROR          - Error occurred on device side.
> +
> +**/
> +EFI_STATUS
> +NvmeIsAllCmdSlotClean (
> +  IN NVME_CONTEXT       *Nvme,
> +  IN UINT8              Qid
> +  );
> +
> +/**
> +  Read sector Data from the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in,out] Buffer             - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeReadSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN OUT UINT64                            Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  );
> +
> +/**
> +  Write sector Data to the NVMe device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWriteSectors (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN UINT64                                Buffer,
> +  IN UINT64                                Lba,
> +  IN UINT32                                Blocks
> +  );
> +
> +/**
> +  Flushes all modified Data to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeFlush (
> +  IN NVME_CONTEXT                          *Nvme
> +  );
> +
> +/**
> +  Read some blocks from the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[out] Buffer                - The Buffer used to store the Data
> read from the device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be read.
> +
> +  @retval EFI_SUCCESS               - Datum are read from the device.
> +  @retval Others                    - Fail to read all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeRead (
> +  IN NVME_CONTEXT                  *Nvme,
> +  OUT UINT64                       Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  );
> +
> +/**
> +  Write some blocks to the device.
> +
> +  @param[in] Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in] Buffer                 - The Buffer to be written into the
> device.
> +  @param[in] Lba                    - The start block number.
> +  @param[in] Blocks                 - Total block number to be written.
> +
> +  @retval EFI_SUCCESS               - Datum are written into the Buffer.
> +  @retval Others                    - Fail to write all the datum.
> +
> +**/
> +EFI_STATUS
> +NvmeWrite (
> +  IN NVME_CONTEXT                  *Nvme,
> +  IN UINT64                        Buffer,
> +  IN UINT64                        Lba,
> +  IN UINTN                         Blocks
> +  );
> +
> +/**
> +  Security send and receive commands.
> +
> +  @param[in]     Nvme                   - The pointer to the
> NVME_CONTEXT Data structure.
> +  @param[in]     SendCommand            - The flag to indicate the
> command type, TRUE for Send command and FALSE for receive command
> +  @param[in]     SecurityProtocol       - Security Protocol
> +  @param[in]     SpSpecific             - Security Protocol Specific
> +  @param[in]     TransferLength         - Transfer Length of Buffer (in
> bytes) - always a multiple of 512
> +  @param[in,out] TransferBuffer         - Address of Data to transfer
> +
> +  @return EFI_SUCCESS               - Successfully create io submission
> queue.
> +  @return others                    - Fail to send/receive commands.
> +
> +**/
> +EFI_STATUS
> +NvmeSecuritySendReceive (
> +  IN NVME_CONTEXT                          *Nvme,
> +  IN BOOLEAN                               SendCommand,
> +  IN UINT8                                 SecurityProtocol,
> +  IN UINT16                                SpSpecific,
> +  IN UINTN                                 TransferLength,
> +  IN OUT VOID                              *TransferBuffer
> +  );
> +
> +#endif
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> new file mode 100644
> index 000000000000..03376b9e6c9a
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> @@ -0,0 +1,815 @@
> +/** @file
> +  Header file for Registers and Structure definitions
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +#ifndef __OPAL_PASSWORD_NVME_REG_H__
> +#define __OPAL_PASSWORD_NVME_REG_H__
> +
> +//
> +// PCI Header for PCIe root port configuration
> +//
> +#define NVME_PCIE_PCICMD                         0x04
> +#define NVME_PCIE_BNUM                           0x18
> +#define NVME_PCIE_SEC_BNUM                       0x19
> +#define NVME_PCIE_IOBL                           0x1C
> +#define NVME_PCIE_MBL                            0x20
> +#define NVME_PCIE_PMBL                           0x24
> +#define NVME_PCIE_PMBU32                         0x28
> +#define NVME_PCIE_PMLU32                         0x2C
> +#define NVME_PCIE_INTR                           0x3C
> +
> +//
> +// NVMe related definitions
> +//
> +#define PCI_CLASS_MASS_STORAGE_NVM                0x08  // mass
> storage sub-class non-volatile memory.
> +#define PCI_IF_NVMHCI                             0x02  // mass
> storage programming interface NVMHCI.
> +
> +#define NVME_ASQ_SIZE                                    1     //
> Number of admin submission queue entries, which is 0-based
> +#define NVME_ACQ_SIZE                                    1     //
> Number of admin completion queue entries, which is 0-based
> +
> +#define NVME_CSQ_SIZE                                    63     //
> Number of I/O submission queue entries, which is 0-based
> +#define NVME_CCQ_SIZE                                    63     //
> Number of I/O completion queue entries, which is 0-based
> +
> +#define NVME_MAX_IO_QUEUES                               2     //
> Number of I/O queues supported by the driver, 1 for AQ, 1 for CQ
> +
> +#define NVME_CSQ_DEPTH
> (NVME_CSQ_SIZE+1)
> +#define NVME_CCQ_DEPTH
> (NVME_CCQ_SIZE+1)
> +#define NVME_PRP_SIZE                                    (4)    //
> Pages of PRP list
> +
> +#define NVME_CONTROLLER_ID                               0
> +
> +//
> +// Time out Value for Nvme transaction execution
> +//
> +#define NVME_GENERIC_TIMEOUT                             5000000
> ///< us
> +#define NVME_CMD_WAIT                                    100
> ///< us
> +#define NVME_CMD_TIMEOUT
> 20000000  ///< us
> +
> +
> +
> +#define NVME_MEM_MAX_SIZE \
> +  (( \
> +  1                                         /* Controller Data */ +  \
> +  1                                         /* Identify Data */   +  \
> +  1                                         /* ASQ */             +
> \
> +  1                                         /* ACQ */             +
> \
> +  1                                         /* SQs */             +
> \
> +  1                                         /* CQs */             +
> \
> +  NVME_PRP_SIZE * NVME_CSQ_DEPTH            /* PRPs */
> +  \
> +  1                                         /* SECURITY */
> \
> +  ) * EFI_PAGE_SIZE)
> +
> +
> +//
> +// controller register offsets
> +//
> +#define NVME_CAP_OFFSET          0x0000  // Controller Capabilities
> +#define NVME_VER_OFFSET          0x0008  // Version
> +#define NVME_INTMS_OFFSET        0x000c  // Interrupt Mask Set
> +#define NVME_INTMC_OFFSET        0x0010  // Interrupt Mask Clear
> +#define NVME_CC_OFFSET           0x0014  // Controller Configuration
> +#define NVME_CSTS_OFFSET         0x001c  // Controller Status
> +#define NVME_AQA_OFFSET          0x0024  // Admin Queue Attributes
> +#define NVME_ASQ_OFFSET          0x0028  // Admin Submission Queue
> Base Address
> +#define NVME_ACQ_OFFSET          0x0030  // Admin Completion Queue
> Base Address
> +#define NVME_SQ0_OFFSET          0x1000  // Submission Queue 0
> (admin) Tail Doorbell
> +#define NVME_CQ0_OFFSET          0x1004  // Completion Queue 0
> (admin) Head Doorbell
> +
> +//
> +// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD))
> +// Get the doorbell stride bit shift Value from the controller capabilities.
> +//
> +#define NVME_SQTDBL_OFFSET(QID, DSTRD)    0x1000 + ((2 * (QID)) * (4
> << (DSTRD)))       // Submission Queue y (NVM) Tail Doorbell
> +#define NVME_CQHDBL_OFFSET(QID, DSTRD)    0x1000 + (((2 * (QID)) + 1)
> * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell
> +
> +
> +#pragma pack(1)
> +
> +//
> +// 3.1.1 Offset 00h: CAP - Controller Capabilities
> +//
> +typedef struct {
> +  UINT16 Mqes;      // Maximum Queue Entries Supported
> +  UINT8  Cqr:1;     // Contiguous Queues Required
> +  UINT8  Ams:2;     // Arbitration Mechanism Supported
> +  UINT8  Rsvd1:5;
> +  UINT8  To;        // Timeout
> +  UINT16 Dstrd:4;
> +  UINT16 Rsvd2:1;
> +  UINT16 Css:4;     // Command Sets Supported
> +  UINT16 Rsvd3:7;
> +  UINT8  Mpsmin:4;
> +  UINT8  Mpsmax:4;
> +  UINT8  Rsvd4;
> +} NVME_CAP;
> +
> +//
> +// 3.1.2 Offset 08h: VS - Version
> +//
> +typedef struct {
> +  UINT16 Mnr;       // Minor version number
> +  UINT16 Mjr;       // Major version number
> +} NVME_VER;
> +
> +//
> +// 3.1.5 Offset 14h: CC - Controller Configuration
> +//
> +typedef struct {
> +  UINT16 En:1;       // Enable
> +  UINT16 Rsvd1:3;
> +  UINT16 Css:3;      // Command Set Selected
> +  UINT16 Mps:4;      // Memory Page Size
> +  UINT16 Ams:3;      // Arbitration Mechanism Selected
> +  UINT16 Shn:2;      // Shutdown Notification
> +  UINT8  Iosqes:4;   // I/O Submission Queue Entry Size
> +  UINT8  Iocqes:4;   // I/O Completion Queue Entry Size
> +  UINT8  Rsvd2;
> +} NVME_CC;
> +
> +//
> +// 3.1.6 Offset 1Ch: CSTS - Controller Status
> +//
> +typedef struct {
> +  UINT32 Rdy:1;      // Ready
> +  UINT32 Cfs:1;      // Controller Fatal Status
> +  UINT32 Shst:2;     // Shutdown Status
> +  UINT32 Nssro:1;    // NVM Subsystem Reset Occurred
> +  UINT32 Rsvd1:27;
> +} NVME_CSTS;
> +
> +//
> +// 3.1.8 Offset 24h: AQA - Admin Queue Attributes
> +//
> +typedef struct {
> +  UINT16 Asqs:12;    // Submission Queue Size
> +  UINT16 Rsvd1:4;
> +  UINT16 Acqs:12;    // Completion Queue Size
> +  UINT16 Rsvd2:4;
> +} NVME_AQA;
> +
> +//
> +// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address
> +//
> +#define NVME_ASQ      UINT64
> +
> +//
> +// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address
> +//
> +#define NVME_ACQ      UINT64
> +
> +//
> +// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission
> Queue y Tail Doorbell
> +//
> +typedef struct {
> +  UINT16 Sqt;
> +  UINT16 Rsvd1;
> +} NVME_SQTDBL;
> +
> +//
> +// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL -
> Completion Queue y Head Doorbell
> +//
> +typedef struct {
> +  UINT16 Cqh;
> +  UINT16 Rsvd1;
> +} NVME_CQHDBL;
> +
> +//
> +// NVM command set structures
> +//
> +// Read Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting Sector Address */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Sectors */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Af:4;                /* Access Frequency */
> +  UINT32 Al:2;                /* Access Latency */
> +  UINT32 Sr:1;                /* Sequential Request */
> +  UINT32 In:1;                /* Incompressible */
> +  UINT32 Rsvd2:24;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag
> */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Elbat;               /* Expected Logical Block Application Tag */
> +  UINT16 Elbatm;              /* Expected Logical Block Application Tag
> Mask */
> +} NVME_READ;
> +
> +//
> +// Write Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting Sector Address */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Sectors */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Af:4;                /* Access Frequency */
> +  UINT32 Al:2;                /* Access Latency */
> +  UINT32 Sr:1;                /* Sequential Request */
> +  UINT32 In:1;                /* Incompressible */
> +  UINT32 Rsvd2:24;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Lbat;                /* Logical Block Application Tag */
> +  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
> +} NVME_WRITE;
> +
> +//
> +// Flush
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Flush;               /* Flush */
> +} NVME_FLUSH;
> +
> +//
> +// Write Uncorrectable command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting LBA */
> +  //
> +  // CDW 12
> +  //
> +  UINT32 Nlb:16;              /* Number of  Logical Blocks */
> +  UINT32 Rsvd1:16;
> +} NVME_WRITE_UNCORRECTABLE;
> +
> +//
> +// Write Zeroes command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting LBA */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Logical Blocks */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Rsvd2;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Ilbrt;               /* Initial Logical Block Reference Tag */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Lbat;                /* Logical Block Application Tag */
> +  UINT16 Lbatm;               /* Logical Block Application Tag Mask */
> +} NVME_WRITE_ZEROES;
> +
> +//
> +// Compare command
> +//
> +typedef struct {
> +  //
> +  // CDW 10, 11
> +  //
> +  UINT64 Slba;                /* Starting LBA */
> +  //
> +  // CDW 12
> +  //
> +  UINT16 Nlb;                 /* Number of Logical Blocks */
> +  UINT16 Rsvd1:10;
> +  UINT16 Prinfo:4;            /* Protection Info Check */
> +  UINT16 Fua:1;               /* Force Unit Access */
> +  UINT16 Lr:1;                /* Limited Retry */
> +  //
> +  // CDW 13
> +  //
> +  UINT32 Rsvd2;
> +  //
> +  // CDW 14
> +  //
> +  UINT32 Eilbrt;              /* Expected Initial Logical Block Reference Tag
> */
> +  //
> +  // CDW 15
> +  //
> +  UINT16 Elbat;               /* Expected Logical Block Application Tag */
> +  UINT16 Elbatm;              /* Expected Logical Block Application Tag
> Mask */
> +} NVME_COMPARE;
> +
> +typedef union {
> +  NVME_READ                   Read;
> +  NVME_WRITE                  Write;
> +  NVME_FLUSH                  Flush;
> +  NVME_WRITE_UNCORRECTABLE    WriteUncorrectable;
> +  NVME_WRITE_ZEROES           WriteZeros;
> +  NVME_COMPARE                Compare;
> +} NVME_CMD;
> +
> +typedef struct {
> +  UINT16 Mp;                /* Maximum Power */
> +  UINT8  Rsvd1;             /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Mps:1;             /* Max Power Scale */
> +  UINT8  Nops:1;            /* Non-Operational State */
> +  UINT8  Rsvd2:6;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Enlat;             /* Entry Latency */
> +  UINT32 Exlat;             /* Exit Latency */
> +  UINT8  Rrt:5;             /* Relative Read Throughput */
> +  UINT8  Rsvd3:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rrl:5;             /* Relative Read Leatency */
> +  UINT8  Rsvd4:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rwt:5;             /* Relative Write Throughput */
> +  UINT8  Rsvd5:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rwl:5;             /* Relative Write Leatency */
> +  UINT8  Rsvd6:3;           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8  Rsvd7[16];         /* Reserved as of Nvm Express 1.1 Spec */
> +} NVME_PSDESCRIPTOR;
> +
> +//
> +//  Identify Controller Data
> +//
> +typedef struct {
> +  //
> +  // Controller Capabilities and Features 0-255
> +  //
> +  UINT16 Vid;                 /* PCI Vendor ID */
> +  UINT16 Ssvid;               /* PCI sub-system vendor ID */
> +  UINT8  Sn[20];              /* Produce serial number */
> +
> +  UINT8  Mn[40];              /* Proeduct model number */
> +  UINT8  Fr[8];               /* Firmware Revision */
> +  UINT8  Rab;                 /* Recommended Arbitration Burst */
> +  UINT8  Ieee_oiu[3];         /* Organization Unique Identifier */
> +  UINT8  Cmic;                /* Multi-interface Capabilities */
> +  UINT8  Mdts;                /* Maximum Data Transfer Size */
> +  UINT8  Cntlid[2];           /* Controller ID */
> +  UINT8  Rsvd1[176];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // Admin Command Set Attributes
> +  //
> +  UINT16 Oacs;                /* Optional Admin Command Support */
> +  UINT8  Acl;                 /* Abort Command Limit */
> +  UINT8  Aerl;                /* Async Event Request Limit */
> +  UINT8  Frmw;                /* Firmware updates */
> +  UINT8  Lpa;                 /* Log Page Attributes */
> +  UINT8  Elpe;                /* Error Log Page Entries */
> +  UINT8  Npss;                /* Number of Power States Support */
> +  UINT8  Avscc;               /* Admin Vendor Specific Command
> Configuration */
> +  UINT8  Apsta;               /* Autonomous Power State Transition
> Attributes */
> +  UINT8  Rsvd2[246];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // NVM Command Set Attributes
> +  //
> +  UINT8  Sqes;                /* Submission Queue Entry Size */
> +  UINT8  Cqes;                /* Completion Queue Entry Size */
> +  UINT16 Rsvd3;               /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Nn;                  /* Number of Namespaces */
> +  UINT16 Oncs;                /* Optional NVM Command Support */
> +  UINT16 Fuses;               /* Fused Operation Support */
> +  UINT8  Fna;                 /* Format NVM Attributes */
> +  UINT8  Vwc;                 /* Volatile Write Cache */
> +  UINT16 Awun;                /* Atomic Write Unit Normal */
> +  UINT16 Awupf;               /* Atomic Write Unit Power Fail */
> +  UINT8  Nvscc;               /* NVM Vendor Specific Command
> Configuration */
> +  UINT8  Rsvd4;               /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT16 Acwu;                /* Atomic Compare & Write Unit */
> +  UINT16 Rsvd5;               /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Sgls;                /* SGL Support  */
> +  UINT8  Rsvd6[164];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // I/O Command set Attributes
> +  //
> +  UINT8 Rsvd7[1344];          /* Reserved as of Nvm Express 1.1 Spec */
> +  //
> +  // Power State Descriptors
> +  //
> +  NVME_PSDESCRIPTOR PsDescriptor[32];
> +
> +  UINT8  VendorData[1024];    /* Vendor specific Data */
> +} NVME_ADMIN_CONTROLLER_DATA;
> +
> +typedef struct {
> +  UINT16        Security  : 1;    /* supports security send/receive
> commands */
> +  UINT16        Format    : 1;    /* supports format nvm command */
> +  UINT16        Firmware  : 1;    /* supports firmware
> activate/download commands */
> +  UINT16        Oacs_rsvd : 13;
> + } OACS; // optional admin command support:
> NVME_ADMIN_CONTROLLER_DATA.Oacs
> +
> +typedef struct {
> +  UINT16 Ms;                /* Metadata Size */
> +  UINT8  Lbads;             /* LBA Data Size */
> +  UINT8  Rp:2;              /* Relative Performance */
> +    #define LBAF_RP_BEST      00b
> +    #define LBAF_RP_BETTER    01b
> +    #define LBAF_RP_GOOD      10b
> +    #define LBAF_RP_DEGRADED  11b
> +  UINT8  Rsvd1:6;           /* Reserved as of Nvm Express 1.1 Spec */
> +} NVME_LBAFORMAT;
> +
> +//
> +// Identify Namespace Data
> +//
> +typedef struct {
> +  //
> +  // NVM Command Set Specific
> +  //
> +  UINT64 Nsze;                /* Namespace Size (total number of blocks
> in formatted namespace) */
> +  UINT64 Ncap;                /* Namespace Capacity (max number of
> logical blocks) */
> +  UINT64 Nuse;                /* Namespace Utilization */
> +  UINT8  Nsfeat;              /* Namespace Features */
> +  UINT8  Nlbaf;               /* Number of LBA Formats */
> +  UINT8  Flbas;               /* Formatted LBA Size */
> +  UINT8  Mc;                  /* Metadata Capabilities */
> +  UINT8  Dpc;                 /* End-to-end Data Protection capabilities
> */
> +  UINT8  Dps;                 /* End-to-end Data Protection Type Settings
> */
> +  UINT8  Nmic;                /* Namespace Multi-path I/O and
> Namespace Sharing Capabilities */
> +  UINT8  Rescap;              /* Reservation Capabilities */
> +  UINT8  Rsvd1[88];           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT64 Eui64;               /* IEEE Extended Unique Identifier */
> +  //
> +  // LBA Format
> +  //
> +  NVME_LBAFORMAT LbaFormat[16];
> +
> +  UINT8 Rsvd2[192];           /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT8 VendorData[3712];     /* Vendor specific Data */
> +} NVME_ADMIN_NAMESPACE_DATA;
> +
> +//
> +// NvmExpress Admin Identify Cmd
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Cns:2;
> +  UINT32 Rsvd1:30;
> +} NVME_ADMIN_IDENTIFY;
> +
> +//
> +// NvmExpress Admin Create I/O Completion Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Qid:16;              /* Queue Identifier */
> +  UINT32 Qsize:16;            /* Queue Size */
> +
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Pc:1;                /* Physically Contiguous */
> +  UINT32 Ien:1;               /* Interrupts Enabled */
> +  UINT32 Rsvd1:14;            /* reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Iv:16;               /* Interrupt Vector */
> +} NVME_ADMIN_CRIOCQ;
> +
> +//
> +// NvmExpress Admin Create I/O Submission Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Qid:16;              /* Queue Identifier */
> +  UINT32 Qsize:16;            /* Queue Size */
> +
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Pc:1;                /* Physically Contiguous */
> +  UINT32 Qprio:2;             /* Queue Priority */
> +  UINT32 Rsvd1:13;            /* Reserved as of Nvm Express 1.1 Spec */
> +  UINT32 Cqid:16;             /* Completion Queue ID */
> +} NVME_ADMIN_CRIOSQ;
> +
> +//
> +// NvmExpress Admin Delete I/O Completion Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT16 Qid;
> +  UINT16 Rsvd1;
> +} NVME_ADMIN_DEIOCQ;
> +
> +//
> +// NvmExpress Admin Delete I/O Submission Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT16 Qid;
> +  UINT16 Rsvd1;
> +} NVME_ADMIN_DEIOSQ;
> +
> +//
> +// NvmExpress Admin Security Send
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Resv:8;              /* Reserve */
> +  UINT32 Spsp:16;             /* SP Specific */
> +  UINT32 Secp:8;              /* Security Protocol */
> +
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Tl;                  /* Transfer Length */
> +} NVME_ADMIN_SECSEND;
> +
> +//
> +// NvmExpress Admin Abort Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Sqid:16;             /* Submission Queue identifier */
> +  UINT32 Cid:16;              /* Command Identifier */
> +} NVME_ADMIN_ABORT;
> +
> +//
> +// NvmExpress Admin Firmware Activate Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Fs:3;                /* Submission Queue identifier */
> +  UINT32 Aa:2;                /* Command Identifier */
> +  UINT32 Rsvd1:27;
> +} NVME_ADMIN_FIRMWARE_ACTIVATE;
> +
> +//
> +// NvmExpress Admin Firmware Image Download Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Numd;                /* Number of Dwords */
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Ofst;                /* Offset */
> +} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD;
> +
> +//
> +// NvmExpress Admin Get Features Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Fid:8;                /* Feature Identifier */
> +  UINT32 Sel:3;                /* Select */
> +  UINT32 Rsvd1:21;
> +} NVME_ADMIN_GET_FEATURES;
> +
> +//
> +// NvmExpress Admin Get Log Page Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Lid:8;               /* Log Page Identifier */
> +    #define LID_ERROR_INFO
> +    #define LID_SMART_INFO
> +    #define LID_FW_SLOT_INFO
> +  UINT32 Rsvd1:8;
> +  UINT32 Numd:12;             /* Number of Dwords */
> +  UINT32 Rsvd2:4;             /* Reserved as of Nvm Express 1.1 Spec */
> +} NVME_ADMIN_GET_LOG_PAGE;
> +
> +//
> +// NvmExpress Admin Set Features Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Fid:8;               /* Feature Identifier */
> +  UINT32 Rsvd1:23;
> +  UINT32 Sv:1;                /* Save */
> +} NVME_ADMIN_SET_FEATURES;
> +
> +//
> +// NvmExpress Admin Format NVM Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Lbaf:4;              /* LBA Format */
> +  UINT32 Ms:1;                /* Metadata Settings */
> +  UINT32 Pi:3;                /* Protection Information */
> +  UINT32 Pil:1;               /* Protection Information Location */
> +  UINT32 Ses:3;               /* Secure Erase Settings */
> +  UINT32 Rsvd1:20;
> +} NVME_ADMIN_FORMAT_NVM;
> +
> +//
> +// NvmExpress Admin Security Receive Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Rsvd1:8;
> +  UINT32 Spsp:16;             /* SP Specific */
> +  UINT32 Secp:8;              /* Security Protocol */
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Al;                  /* Allocation Length */
> +} NVME_ADMIN_SECURITY_RECEIVE;
> +
> +//
> +// NvmExpress Admin Security Send Command
> +//
> +typedef struct {
> +  //
> +  // CDW 10
> +  //
> +  UINT32 Rsvd1:8;
> +  UINT32 Spsp:16;             /* SP Specific */
> +  UINT32 Secp:8;              /* Security Protocol */
> +  //
> +  // CDW 11
> +  //
> +  UINT32 Tl;                  /* Transfer Length */
> +} NVME_ADMIN_SECURITY_SEND;
> +
> +typedef union {
> +  NVME_ADMIN_IDENTIFY                   Identify;
> +  NVME_ADMIN_CRIOCQ                     CrIoCq;
> +  NVME_ADMIN_CRIOSQ                     CrIoSq;
> +  NVME_ADMIN_DEIOCQ                     DeIoCq;
> +  NVME_ADMIN_DEIOSQ                     DeIoSq;
> +  NVME_ADMIN_ABORT                      Abort;
> +  NVME_ADMIN_FIRMWARE_ACTIVATE          Activate;
> +  NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD
> FirmwareImageDownload;
> +  NVME_ADMIN_GET_FEATURES               GetFeatures;
> +  NVME_ADMIN_GET_LOG_PAGE               GetLogPage;
> +  NVME_ADMIN_SET_FEATURES               SetFeatures;
> +  NVME_ADMIN_FORMAT_NVM                 FormatNvm;
> +  NVME_ADMIN_SECURITY_RECEIVE           SecurityReceive;
> +  NVME_ADMIN_SECURITY_SEND              SecuritySend;
> +} NVME_ADMIN_CMD;
> +
> +typedef struct {
> +  UINT32 Cdw10;
> +  UINT32 Cdw11;
> +  UINT32 Cdw12;
> +  UINT32 Cdw13;
> +  UINT32 Cdw14;
> +  UINT32 Cdw15;
> +} NVME_RAW;
> +
> +typedef union {
> +  NVME_ADMIN_CMD Admin;   // Union of Admin commands
> +  NVME_CMD       Nvm;     // Union of Nvm commands
> +  NVME_RAW       Raw;
> +} NVME_PAYLOAD;
> +
> +//
> +// Submission Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 0, Common to all comnmands
> +  //
> +  UINT8  Opc;               // Opcode
> +  UINT8  Fuse:2;            // Fused Operation
> +  UINT8  Rsvd1:5;
> +  UINT8  Psdt:1;            // PRP or SGL for Data Transfer
> +  UINT16 Cid;               // Command Identifier
> +
> +  //
> +  // CDW 1
> +  //
> +  UINT32 Nsid;              // Namespace Identifier
> +
> +  //
> +  // CDW 2,3
> +  //
> +  UINT64 Rsvd2;
> +
> +  //
> +  // CDW 4,5
> +  //
> +  UINT64 Mptr;              // Metadata Pointer
> +
> +  //
> +  // CDW 6-9
> +  //
> +  UINT64 Prp[2];            // First and second PRP entries
> +
> +  NVME_PAYLOAD Payload;
> +
> +} NVME_SQ;
> +
> +//
> +// Completion Queue
> +//
> +typedef struct {
> +  //
> +  // CDW 0
> +  //
> +  UINT32 Dword0;
> +  //
> +  // CDW 1
> +  //
> +  UINT32 Rsvd1;
> +  //
> +  // CDW 2
> +  //
> +  UINT16 Sqhd;              // Submission Queue Head Pointer
> +  UINT16 Sqid;              // Submission Queue Identifier
> +  //
> +  // CDW 3
> +  //
> +  UINT16 Cid;               // Command Identifier
> +  UINT16 Pt:1;              // Phase Tag
> +  UINT16 Sc:8;              // Status Code
> +  UINT16 Sct:3;             // Status Code Type
> +  UINT16 Rsvd2:2;
> +  UINT16 Mo:1;              // More
> +  UINT16 Dnr:1;             // Retry
> +} NVME_CQ;
> +
> +//
> +// Nvm Express Admin cmd opcodes
> +//
> +#define NVME_ADMIN_DELIOSQ_OPC               0
> +#define NVME_ADMIN_CRIOSQ_OPC                1
> +#define NVME_ADMIN_DELIOCQ_OPC               4
> +#define NVME_ADMIN_CRIOCQ_OPC                5
> +#define NVME_ADMIN_IDENTIFY_OPC              6
> +#define NVME_ADMIN_SECURITY_SEND_OPC         0x81
> +#define NVME_ADMIN_SECURITY_RECV_OPC         0x82
> +
> +#define NVME_IO_FLUSH_OPC                    0
> +#define NVME_IO_WRITE_OPC                    1
> +#define NVME_IO_READ_OPC                     2
> +
> +//
> +// Offset from the beginning of private Data queue Buffer
> +//
> +#define NVME_ASQ_BUF_OFFSET                  EFI_PAGE_SIZE
> +
> +#pragma pack()
> +
> +#endif
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> new file mode 100644
> index 000000000000..17fda410dc54
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> @@ -0,0 +1,65 @@
> +/** @file
> +  Opal Password common header file.
> +
> +Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_PASSWORD_COMMON_H_
> +#define _OPAL_PASSWORD_COMMON_H_
> +
> +#define OPAL_DEVICE_TYPE_UNKNOWN    0x0
> +#define OPAL_DEVICE_TYPE_ATA        0x1
> +#define OPAL_DEVICE_TYPE_NVME       0x2
> +
> +typedef struct {
> +  UINT16            Segment;
> +  UINT8             Bus;
> +  UINT8             Device;
> +  UINT8             Function;
> +  UINT8             Reserved;
> +} OPAL_PCI_DEVICE;
> +
> +typedef struct {
> +  UINT16            Length;
> +  OPAL_PCI_DEVICE   Device;
> +  UINT8             PasswordLength;
> +  UINT8             Password[32];
> +  UINT16            OpalBaseComId;
> +  UINT32            BarAddr;
> +} OPAL_DEVICE_COMMON;
> +
> +#define OPAL_DEVICE_ATA_GUID { 0xcb934fe1, 0xb8cd, 0x46b1, { 0xa0, 0x58,
> 0xdd, 0xcb, 0x7, 0xb7, 0xb4, 0x17 } }
> +
> +typedef struct {
> +  UINT16            Length;
> +  OPAL_PCI_DEVICE   Device;
> +  UINT8             PasswordLength;
> +  UINT8             Password[32];
> +  UINT16            OpalBaseComId;
> +  UINT32            BarAddr;
> +  UINT16            Port;
> +  UINT16            PortMultiplierPort;
> +} OPAL_DEVICE_ATA;
> +
> +#define OPAL_DEVICE_NVME_GUID { 0xde116925, 0xaf7f, 0x42d9, { 0x83,
> 0xc0, 0x7e, 0xd6, 0x26, 0x59, 0x0, 0xfb } }
> +
> +typedef struct {
> +  UINT16            Length;
> +  OPAL_PCI_DEVICE   Device;
> +  UINT8             PasswordLength;
> +  UINT8             Password[32];
> +  UINT16            OpalBaseComId;
> +  UINT32            BarAddr;
> +  UINT32            NvmeNamespaceId;
> +  OPAL_PCI_DEVICE   PciBridgeNode[0];
> +} OPAL_DEVICE_NVME;
> +
> +#endif // _OPAL_PASSWORD_COMMON_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> new file mode 100644
> index 000000000000..0ac550a72873
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> @@ -0,0 +1,81 @@
> +## @file
> +#  This is a OpalPasswordDxe driver.
> +#
> +#  This module is used to Management the Opal feature
> +#  for Opal supported devices.
> +#
> +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be found
> at
> +# http://opensource.org/licenses/bsd-license.php
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +[Defines]
> +  INF_VERSION                    = 0x00010007
> +  BASE_NAME                      = OpalPasswordDxe
> +  FILE_GUID                      =
> E3E4048D-6C0C-43E4-AE1C-FFB579D8EF41
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = EfiDriverEntryPoint
> +  UNLOAD_IMAGE                   = OpalEfiDriverUnload
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
> +#
> +
> +[Sources]
> +  OpalDriver.c
> +  OpalDriver.h
> +  OpalPasswordCommon.h
> +  OpalHii.c
> +  OpalHii.h
> +  OpalHiiCallbacks.c
> +  OpalHiiFormValues.h
> +  OpalHiiFormStrings.uni
> +  OpalPasswordForm.vfr
> +  ComponentName.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  SecurityPkg/SecurityPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiRuntimeServicesTableLib
> +  DxeServicesTableLib
> +  UefiHiiServicesLib
> +  BaseMemoryLib
> +  DebugLib
> +  HiiLib
> +  PrintLib
> +  DevicePathLib
> +  UefiLib
> +  TcgStorageOpalLib
> +  Tcg2PhysicalPresenceLib
> +  PciLib
> +  S3BootScriptLib
> +  LockBoxLib
> +
> +[Protocols]
> +  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
> +  gEfiStorageSecurityCommandProtocolGuid        ## CONSUMES
> +  gEfiComponentNameProtocolGuid                 ## PRODUCES
> +  gEfiComponentName2ProtocolGuid                ## PRODUCES
> +  gEfiBlockIoProtocolGuid                       ## CONSUMES
> +  gEfiPciIoProtocolGuid                         ## CONSUMES
> +  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
> ## Event
> +
> +[Depex]
> +  gEfiHiiStringProtocolGuid AND gEfiHiiDatabaseProtocolGuid
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
> new file mode 100644
> index 000000000000..cba388723305
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordForm.vfr
> @@ -0,0 +1,309 @@
> +/** @file
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +#include "OpalHiiFormValues.h"
> +
> +
> +#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
> +  { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4,
> 0xe } }
> +
> +formset
> +  guid      = SETUP_FORMSET_GUID,
> +  title     = STRING_TOKEN(STR_OPAL),
> +  help      = STRING_TOKEN(STR_FORM_SET_HELP),
> +  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
> +
> +  // Define a Buffer Storage (EFI_IFR_VARSTORE) that will be filled
> +  // out initially through extractConfig call
> +  varstore OPAL_HII_CONFIGURATION,           // This is the Data
> structure type
> +    name  = OpalHiiConfig,                   // Define referenced name
> in vfr
> +    guid  = SETUP_VARIABLE_GUID;             // GUID of this Buffer
> storage
> +
> +form formid = FORMID_VALUE_MAIN_MENU,
> +    title  = STRING_TOKEN(STR_OPAL);
> +
> +    //CONFIG_VARIABLE(HII_KEY(HII_KEY_ID_VAR_SUPPORTED_DISKS),
> SupportedDisks, 0x0, 0xFFFF);
> +    suppressif TRUE;
> +        numeric
> +            name    = SupportedDisks,
> +            varid   = OpalHiiConfig.SupportedDisks,
> +            prompt  = STRING_TOKEN(STR_NULL),
> +            help    = STRING_TOKEN(STR_NULL),
> +            flags   = INTERACTIVE,
> +            key     = 0x8002,
> +            minimum = 0x0,
> +            maximum = 0xFFFF,
> +        endnumeric;
> +    endif;
> +
> +    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    subtitle text = STRING_TOKEN(STR_MAIN_PHY_DISKS_LBL);
> +
> +    //DISK( 0 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x1 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8001;
> +    endif;
> +
> +    //DISK( 1 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x2 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8101;
> +    endif;
> +
> +    //DISK( 2 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x4 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8201;
> +    endif;
> +
> +    //DISK( 3 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x8 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8301;
> +    endif;
> +
> +    //DISK( 4 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x10 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8401;
> +    endif;
> +
> +    //DISK( 5 );
> +    suppressif ( questionref(SupportedDisks) & ( 0x20 ) ) == 0;
> +        goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +            prompt  = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5 ),
> +            help    =
> STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
> +            flags   = INTERACTIVE,
> +            key     = 0x8501;
> +    endif;
> +
> +    //No disks on system
> +    suppressif ideqval OpalHiiConfig.NumDisks > 0;
> +        text
> +            help    = STRING_TOKEN(STR_NULL),
> +            text    =
> STRING_TOKEN(STR_MAIN_NO_DISKS_PRESENT_LBL);
> +    endif;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    grayoutif TRUE;
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS);
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS1);
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS2);
> +      text
> +          help    = STRING_TOKEN(STR_BLOCKSID_STATUS_HELP),
> +          text    = STRING_TOKEN(STR_BLOCKSID_STATUS3);
> +      subtitle text = STRING_TOKEN(STR_NULL);
> +    endif;
> +
> +    oneof varid   = OpalHiiConfig.EnableBlockSid,
> +      questionid  = 0x8004,
> +      prompt      = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID),
> +      help        =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_HELP),
> +      flags       = INTERACTIVE,
> +      option text = STRING_TOKEN(STR_NONE), value = 0, flags = DEFAULT |
> MANUFACTURING | RESET_REQUIRED;
> +      option text = STRING_TOKEN(STR_ENABLED), value = 1, flags =
> RESET_REQUIRED;
> +      option text = STRING_TOKEN(STR_DISABLED), value = 2, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), value = 3, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), value = 4, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), value = 5, flags =
> RESET_REQUIRED;
> +      option text =
> STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), value = 6, flags =
> RESET_REQUIRED;
> +    endoneof;
> +
> +
> +
> +endform;  // MAIN MENU FORM
> +
> +//
> +/////////////////   DISK INFO FORM   /////////////////
> +//
> +form formid = FORMID_VALUE_DISK_INFO_FORM_MAIN,
> +    title  = STRING_TOKEN(STR_OPAL);
> +
> +    suppressif TRUE;
> +        numeric
> +            name    = SelectedDiskAvailableActions,
> +            varid   = OpalHiiConfig.SelectedDiskAvailableActions,
> +            prompt  = STRING_TOKEN(STR_NULL),
> +            help    = STRING_TOKEN(STR_NULL),
> +            flags   = INTERACTIVE,
> +            key     = 0x8003,
> +            minimum = 0x0,
> +            maximum = 0xFFFF,
> +        endnumeric;
> +    endif;
> +
> +    suppressif TRUE;
> +        checkbox varid = OpalHiiConfig.KeepUserDataForced,
> +            prompt = STRING_TOKEN(STR_NULL),
> +            help = STRING_TOKEN(STR_NULL),
> +        endcheckbox;
> +    endif;
> +
> +    subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    text
> +        help   = STRING_TOKEN(STR_NULL),
> +        text   = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    subtitle text = STRING_TOKEN(STR_OPAL_REQUESTS_LBL);
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_SET_ADMIN_PWD ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.SetAdminPwd,
> +            prompt  =
> STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8005,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_SET_USER_PWD ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.SetUserPwd,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8006,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_SECURE_ERASE ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.SecureErase,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8007,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_REVERT ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetAdminPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SecureErase == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.Revert,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_REVERT),
> +            help    = STRING_TOKEN(STR_DISK_INFO_REVERT_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x8008,
> +        endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ideqval OpalHiiConfig.OpalRequest.Revert == 0;
> +        grayoutif ideqval OpalHiiConfig.KeepUserDataForced == 1;
> +            checkbox varid = OpalHiiConfig.OpalRequest.KeepUserData,
> +                prompt  =
> STRING_TOKEN(STR_KEEP_USER_DATA_PROMPT),
> +                help    = STRING_TOKEN(STR_KEEP_USER_DATA_HELP),
> +                flags   = INTERACTIVE | RESET_REQUIRED,
> +                key     = 0x8009,
> +            endcheckbox;
> +        endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_PSID_REVERT ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetAdminPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SecureErase == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.DisableUser == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.EnableFeature == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.PsidRevert,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_PSID_REVERT_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x800A,
> +         endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_DISABLE_USER ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.SetUserPwd == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.Revert == 1;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.DisableUser,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_DISABLE_USER),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_DISABLE_USER_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x800B,
> +         endcheckbox;
> +    endif;
> +    endif;
> +    endif;
> +    endif;
> +
> +    suppressif ( questionref(SelectedDiskAvailableActions) &
> HII_ACTION_ENABLE_FEATURE ) == 0;
> +    grayoutif ideqval OpalHiiConfig.OpalRequest.PsidRevert == 1;
> +        checkbox varid = OpalHiiConfig.OpalRequest.EnableFeature,
> +            prompt  = STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE),
> +            help    =
> STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE_HELP),
> +            flags   = INTERACTIVE | RESET_REQUIRED,
> +            key     = 0x800C,
> +        endcheckbox;
> +    endif;
> +    endif;
> +
> +endform;  // DISK INFO FORM
> +
> +endformset;
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> new file mode 100644
> index 000000000000..1788b2ad3339
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> @@ -0,0 +1,940 @@
> +/** @file
> +  Opal Password PEI driver which is used to unlock Opal Password for S3.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#include "OpalPasswordPei.h"
> +
> +EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
> +EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
> +
> +#define OPAL_PCIE_ROOTPORT_SAVESIZE               (0x40)
> +#define STORE_INVALID_ROOTPORT_INDEX              ((UINT8) -1)
> +
> +/**
> +  Get IOMMU PPI.
> +
> +  @return Pointer to IOMMU PPI.
> +
> +**/
> +EDKII_IOMMU_PPI *
> +GetIoMmu (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EDKII_IOMMU_PPI           *IoMmu;
> +
> +  IoMmu = NULL;
> +  Status = PeiServicesLocatePpi (
> +             &gEdkiiIoMmuPpiGuid,
> +             0,
> +             NULL,
> +             (VOID **) &IoMmu
> +             );
> +  if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
> +    return IoMmu;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Allocates pages that are suitable for an OperationBusMasterCommonBuffer
> or
> +  OperationBusMasterCommonBuffer64 mapping.
> +
> +  @param Pages                  The number of pages to allocate.
> +  @param HostAddress            A pointer to store the base system
> memory address of the
> +                                allocated range.
> +  @param DeviceAddress          The resulting map address for the bus
> master PCI controller to use to
> +                                access the hosts HostAddress.
> +  @param Mapping                A resulting value to pass to Unmap().
> +
> +  @retval EFI_SUCCESS           The requested memory pages were
> allocated.
> +  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal
> attribute bits are
> +                                MEMORY_WRITE_COMBINE and
> MEMORY_CACHED.
> +  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be
> allocated.
> +
> +**/
> +EFI_STATUS
> +IoMmuAllocateBuffer (
> +  IN UINTN                  Pages,
> +  OUT VOID                  **HostAddress,
> +  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
> +  OUT VOID                  **Mapping
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINTN                 NumberOfBytes;
> +  EFI_PHYSICAL_ADDRESS  HostPhyAddress;
> +  EDKII_IOMMU_PPI       *IoMmu;
> +
> +  *HostAddress = NULL;
> +  *DeviceAddress = 0;
> +  *Mapping = NULL;
> +
> +  IoMmu = GetIoMmu ();
> +
> +  if (IoMmu != NULL) {
> +    Status = IoMmu->AllocateBuffer (
> +                      IoMmu,
> +                      EfiBootServicesData,
> +                      Pages,
> +                      HostAddress,
> +                      0
> +                      );
> +    if (EFI_ERROR (Status)) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +
> +    NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
> +    Status = IoMmu->Map (
> +                      IoMmu,
> +                      EdkiiIoMmuOperationBusMasterCommonBuffer,
> +                      *HostAddress,
> +                      &NumberOfBytes,
> +                      DeviceAddress,
> +                      Mapping
> +                      );
> +    if (EFI_ERROR (Status)) {
> +      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
> +      *HostAddress = NULL;
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    Status = IoMmu->SetAttribute (
> +                      IoMmu,
> +                      *Mapping,
> +                      EDKII_IOMMU_ACCESS_READ |
> EDKII_IOMMU_ACCESS_WRITE
> +                      );
> +    if (EFI_ERROR (Status)) {
> +      IoMmu->Unmap (IoMmu, *Mapping);
> +      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
> +      *Mapping = NULL;
> +      *HostAddress = NULL;
> +      return Status;
> +    }
> +  } else {
> +    Status = PeiServicesAllocatePages (
> +               EfiBootServicesData,
> +               Pages,
> +               &HostPhyAddress
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    *HostAddress = (VOID *) (UINTN) HostPhyAddress;
> +    *DeviceAddress = HostPhyAddress;
> +    *Mapping = NULL;
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Frees memory that was allocated with AllocateBuffer().
> +
> +  @param Pages              The number of pages to free.
> +  @param HostAddress        The base system memory address of the
> allocated range.
> +  @param Mapping            The mapping value returned from Map().
> +
> +**/
> +VOID
> +IoMmuFreeBuffer (
> +  IN UINTN                  Pages,
> +  IN VOID                   *HostAddress,
> +  IN VOID                   *Mapping
> +  )
> +{
> +  EDKII_IOMMU_PPI       *IoMmu;
> +
> +  IoMmu = GetIoMmu ();
> +
> +  if (IoMmu != NULL) {
> +    IoMmu->SetAttribute (IoMmu, Mapping, 0);
> +    IoMmu->Unmap (IoMmu, Mapping);
> +    IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);
> +  } else {
> +    PeiServicesFreePages (
> +      (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
> +      Pages
> +      );
> +  }
> +}
> +
> +/**
> +  Provide IO action support.
> +
> +  @param[in]     PeiDev             The opal device need to perform
> trusted IO.
> +  @param[in]     IoType             OPAL_IO_TYPE indicating whether to
> perform a Trusted Send or Trusted Receive.
> +  @param[in]     SecurityProtocol   Security Protocol
> +  @param[in]     SpSpecific         Security Protocol Specific
> +  @param[in]     TransferLength     Transfer Length of Buffer (in bytes) -
> always a multiple of 512
> +  @param[in]     Buffer             Address of Data to transfer
> +
> +  @retval        EFI_SUCCESS        Perform the IO action success.
> +  @retval        Others             Perform the IO action failed.
> +
> +**/
> +EFI_STATUS
> +PerformTrustedIo (
> +  OPAL_PEI_DEVICE  *PeiDev,
> +  OPAL_IO_TYPE     IoType,
> +  UINT8            SecurityProtocol,
> +  UINT16           SpSpecific,
> +  UINTN            TransferLength,
> +  VOID             *Buffer
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         BufferSizeBlocks;
> +  EFI_ATA_COMMAND_BLOCK         AtaCommandBlock;
> +  OPAL_DEVICE_ATA               *DevInfoAta;
> +  AHCI_CONTEXT                  *AhciContext;
> +  NVME_CONTEXT                  *NvmeContext;
> +
> +  Status = EFI_DEVICE_ERROR;
> +  if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_ATA) {
> +    DevInfoAta = (OPAL_DEVICE_ATA *) PeiDev->Device;
> +    AhciContext = (AHCI_CONTEXT *) PeiDev->Context;
> +
> +    BufferSizeBlocks = TransferLength / 512;
> +
> +    ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
> +    AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ?
> ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
> +    AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
> +    AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
> +    AtaCommandBlock.AtaFeatures = SecurityProtocol;
> +    AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
> +    AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
> +    AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
> +
> +
> +    ZeroMem( AhciContext->Buffer, HDD_PAYLOAD );
> +    ASSERT( TransferLength <= HDD_PAYLOAD );
> +
> +    if (IoType == OpalSend) {
> +      CopyMem( AhciContext->Buffer, Buffer, TransferLength );
> +    }
> +
> +    Status = AhciPioTransfer(
> +                AhciContext,
> +                (UINT8) DevInfoAta->Port,
> +                (UINT8) DevInfoAta->PortMultiplierPort,
> +                NULL,
> +                0,
> +                ( IoType == OpalSend ) ? FALSE : TRUE,   // i/o direction
> +                &AtaCommandBlock,
> +                NULL,
> +                AhciContext->Buffer,
> +                (UINT32)TransferLength,
> +                ATA_TIMEOUT
> +                );
> +
> +    if (IoType == OpalRecv) {
> +      CopyMem( Buffer, AhciContext->Buffer, TransferLength );
> +    }
> +  } else if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
> +    NvmeContext = (NVME_CONTEXT *) PeiDev->Context;
> +    Status = NvmeSecuritySendReceive (
> +                NvmeContext,
> +                IoType == OpalSend,
> +                SecurityProtocol,
> +                SwapBytes16(SpSpecific),
> +                TransferLength,
> +                Buffer
> +              );
> +  } else {
> +    DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n",
> PeiDev->DeviceType));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Send a security protocol command to a device that receives data and/or the
> result
> +  of one or more commands sent by SendData.
> +
> +  The ReceiveData function sends a security protocol command to the given
> MediaId.
> +  The security protocol command sent is defined by SecurityProtocolId and
> contains
> +  the security protocol specific data SecurityProtocolSpecificData. The function
> +  returns the data from the security protocol command in PayloadBuffer.
> +
> +  For devices supporting the SCSI command set, the security protocol
> command is sent
> +  using the SECURITY PROTOCOL IN command defined in SPC-4.
> +
> +  For devices supporting the ATA command set, the security protocol
> command is sent
> +  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if
> PayloadBufferSize
> +  is non-zero.
> +
> +  If the PayloadBufferSize is zero, the security protocol command is sent using
> the
> +  Trusted Non-Data command defined in ATA8-ACS.
> +
> +  If PayloadBufferSize is too small to store the available data from the security
> +  protocol command, the function shall copy PayloadBufferSize bytes into the
> +  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
> +
> +  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is
> non-zero,
> +  the function shall return EFI_INVALID_PARAMETER.
> +
> +  If the given MediaId does not support security protocol commands, the
> function shall
> +  return EFI_UNSUPPORTED. If there is no media in the device, the function
> returns
> +  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
> device,
> +  the function returns EFI_MEDIA_CHANGED.
> +
> +  If the security protocol fails to complete within the Timeout period, the
> function
> +  shall return EFI_TIMEOUT.
> +
> +  If the security protocol command completes without an error, the function
> shall
> +  return EFI_SUCCESS. If the security protocol command completes with an
> error, the
> +  function shall return EFI_DEVICE_ERROR.
> +
> +  @param  This                         Indicates a pointer to the calling
> context.
> +  @param  MediaId                      ID of the medium to receive
> data from.
> +  @param  Timeout                      The timeout, in 100ns units, to
> use for the execution
> +                                       of the security protocol
> command. A Timeout value of 0
> +                                       means that this function will wait
> indefinitely for the
> +                                       security protocol command to
> execute. If Timeout is greater
> +                                       than zero, then this function will
> return EFI_TIMEOUT
> +                                       if the time required to execute
> the receive data command
> +                                       is greater than Timeout.
> +  @param  SecurityProtocolId           The value of the "Security
> Protocol" parameter of
> +                                       the security protocol command
> to be sent.
> +  @param  SecurityProtocolSpecificData The value of the "Security Protocol
> Specific" parameter
> +                                       of the security protocol
> command to be sent.
> +  @param  PayloadBufferSize            Size in bytes of the payload data
> buffer.
> +  @param  PayloadBuffer                A pointer to a destination buffer
> to store the security
> +                                       protocol command specific
> payload data for the security
> +                                       protocol command. The caller is
> responsible for having
> +                                       either implicit or explicit
> ownership of the buffer.
> +  @param  PayloadTransferSize          A pointer to a buffer to store the
> size in bytes of the
> +                                       data written to the payload data
> buffer.
> +
> +  @retval EFI_SUCCESS                  The security protocol command
> completed successfully.
> +  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was
> too small to store the available
> +                                       data from the device. The
> PayloadBuffer contains the truncated data.
> +  @retval EFI_UNSUPPORTED              The given MediaId does not
> support security protocol commands.
> +  @retval EFI_DEVICE_ERROR             The security protocol command
> completed with an error.
> +  @retval EFI_NO_MEDIA                 There is no media in the device.
> +  @retval EFI_MEDIA_CHANGED            The MediaId is not for the
> current media.
> +  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or
> PayloadTransferSize is NULL and
> +                                       PayloadBufferSize is non-zero.
> +  @retval EFI_TIMEOUT                  A timeout occurred while waiting
> for the security
> +                                       protocol command to execute.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SecurityReceiveData (
> +  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN  UINT32                                   MediaId,
> +  IN  UINT64                                   Timeout,
> +  IN  UINT8                                    SecurityProtocolId,
> +  IN  UINT16
> SecurityProtocolSpecificData,
> +  IN  UINTN                                    PayloadBufferSize,
> +  OUT VOID                                     *PayloadBuffer,
> +  OUT UINTN                                    *PayloadTransferSize
> +  )
> +{
> +  OPAL_PEI_DEVICE               *PeiDev;
> +
> +  PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
> +  if (PeiDev == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return PerformTrustedIo (
> +                        PeiDev,
> +                        OpalRecv,
> +                        SecurityProtocolId,
> +                        SecurityProtocolSpecificData,
> +                        PayloadBufferSize,
> +                        PayloadBuffer
> +                        );
> +}
> +
> +/**
> +  Send a security protocol command to a device.
> +
> +  The SendData function sends a security protocol command containing the
> payload
> +  PayloadBuffer to the given MediaId. The security protocol command sent is
> +  defined by SecurityProtocolId and contains the security protocol specific data
> +  SecurityProtocolSpecificData. If the underlying protocol command requires a
> +  specific padding for the command payload, the SendData function shall add
> padding
> +  bytes to the command payload to satisfy the padding requirements.
> +
> +  For devices supporting the SCSI command set, the security protocol
> command is sent
> +  using the SECURITY PROTOCOL OUT command defined in SPC-4.
> +
> +  For devices supporting the ATA command set, the security protocol
> command is sent
> +  using one of the TRUSTED SEND commands defined in ATA8-ACS if
> PayloadBufferSize
> +  is non-zero. If the PayloadBufferSize is zero, the security protocol command
> is
> +  sent using the Trusted Non-Data command defined in ATA8-ACS.
> +
> +  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
> +  return EFI_INVALID_PARAMETER.
> +
> +  If the given MediaId does not support security protocol commands, the
> function
> +  shall return EFI_UNSUPPORTED. If there is no media in the device, the
> function
> +  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in
> the
> +  device, the function returns EFI_MEDIA_CHANGED.
> +
> +  If the security protocol fails to complete within the Timeout period, the
> function
> +  shall return EFI_TIMEOUT.
> +
> +  If the security protocol command completes without an error, the function
> shall return
> +  EFI_SUCCESS. If the security protocol command completes with an error, the
> function
> +  shall return EFI_DEVICE_ERROR.
> +
> +  @param  This                         Indicates a pointer to the calling
> context.
> +  @param  MediaId                      ID of the medium to receive
> data from.
> +  @param  Timeout                      The timeout, in 100ns units, to
> use for the execution
> +                                       of the security protocol
> command. A Timeout value of 0
> +                                       means that this function will wait
> indefinitely for the
> +                                       security protocol command to
> execute. If Timeout is greater
> +                                       than zero, then this function will
> return EFI_TIMEOUT
> +                                       if the time required to execute
> the send data command
> +                                       is greater than Timeout.
> +  @param  SecurityProtocolId           The value of the "Security
> Protocol" parameter of
> +                                       the security protocol command
> to be sent.
> +  @param  SecurityProtocolSpecificData The value of the "Security Protocol
> Specific" parameter
> +                                       of the security protocol
> command to be sent.
> +  @param  PayloadBufferSize            Size in bytes of the payload data
> buffer.
> +  @param  PayloadBuffer                A pointer to a destination buffer
> to store the security
> +                                       protocol command specific
> payload data for the security
> +                                       protocol command.
> +
> +  @retval EFI_SUCCESS                  The security protocol command
> completed successfully.
> +  @retval EFI_UNSUPPORTED              The given MediaId does not
> support security protocol commands.
> +  @retval EFI_DEVICE_ERROR             The security protocol command
> completed with an error.
> +  @retval EFI_NO_MEDIA                 There is no media in the device.
> +  @retval EFI_MEDIA_CHANGED            The MediaId is not for the
> current media.
> +  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and
> PayloadBufferSize is non-zero.
> +  @retval EFI_TIMEOUT                  A timeout occurred while waiting
> for the security
> +                                       protocol command to execute.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SecuritySendData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16
> SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  IN VOID                                     *PayloadBuffer
> +  )
> +{
> +  OPAL_PEI_DEVICE               *PeiDev;
> +
> +  PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
> +  if (PeiDev == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return PerformTrustedIo (
> +                          PeiDev,
> +                          OpalSend,
> +                          SecurityProtocolId,
> +                          SecurityProtocolSpecificData,
> +                          PayloadBufferSize,
> +                          PayloadBuffer
> +                          );
> +
> +}
> +
> +/**
> +  Save/Restore RootPort configuration space.
> +
> +  @param[in]     DevInfoNvme            Pointer to NVMe device info.
> +  @param[in]     SaveAction             TRUE: Save, FALSE: Restore
> +  @param[in,out] PcieConfBufferList    Configuration space data buffer for
> save/restore
> +
> +  @return PCIE base address of this RootPort
> +**/
> +UINTN
> +SaveRestoreRootportConfSpace (
> +  IN     OPAL_DEVICE_NVME               *DevInfoNvme,
> +  IN     BOOLEAN                        SaveAction,
> +  IN OUT UINT8                          **PcieConfBufferList
> +  )
> +{
> +  UINTN             RpBase;
> +  UINTN             Length;
> +  OPAL_PCI_DEVICE   *DevNode;
> +  UINT8             *StorePcieConfData;
> +  UINTN             Index;
> +
> +  Length = 0;
> +  Index  = 0;
> +  RpBase = 0;
> +
> +  while (sizeof (OPAL_DEVICE_NVME) + Length < DevInfoNvme->Length) {
> +    DevNode = (OPAL_PCI_DEVICE *)((UINT8*)DevInfoNvme->PciBridgeNode
> + Length);
> +    RpBase = PCI_LIB_ADDRESS (DevNode->Bus, DevNode->Device,
> DevNode->Function, 0x0);
> +
> +    if (PcieConfBufferList != NULL) {
> +      if (SaveAction) {
> +        StorePcieConfData = (UINT8 *) AllocateZeroPool
> (OPAL_PCIE_ROOTPORT_SAVESIZE);
> +        ASSERT (StorePcieConfData != NULL);
> +        OpalPciRead (StorePcieConfData, RpBase,
> OPAL_PCIE_ROOTPORT_SAVESIZE);
> +        PcieConfBufferList[Index] = StorePcieConfData;
> +      } else {
> +        // Skip PCIe Command & Status registers
> +        StorePcieConfData = PcieConfBufferList[Index];
> +        OpalPciWrite (RpBase, StorePcieConfData, 4);
> +        OpalPciWrite (RpBase + 8, StorePcieConfData + 8,
> OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
> +
> +        FreePool (StorePcieConfData);
> +      }
> +    }
> +
> +    Length += sizeof (OPAL_PCI_DEVICE);
> +    Index ++;
> +  }
> +
> +  return RpBase;
> +}
> +
> +/**
> +  Configure RootPort for downstream PCIe NAND devices.
> +
> +  @param[in] RpBase             - PCIe configuration space address of this
> RootPort
> +  @param[in] BusNumber          - Bus number
> +  @param[in] MemoryBase         - Memory base address
> +  @param[in] MemoryLength       - Memory size
> +
> +**/
> +VOID
> +ConfigureRootPortForPcieNand (
> +  IN UINTN   RpBase,
> +  IN UINTN   BusNumber,
> +  IN UINT32  MemoryBase,
> +  IN UINT32  MemoryLength
> +  )
> +{
> +  UINT32  MemoryLimit;
> +
> +  DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x,
> MemoryBase: %x, MemoryLength: %x\n",
> +    BusNumber, MemoryBase, MemoryLength));
> +
> +  if (MemoryLength == 0) {
> +    MemoryLimit = MemoryBase;
> +  } else {
> +    MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
> +  }
> +
> +  ///
> +  /// Configue PCIE configuration space for RootPort
> +  ///
> +  PciWrite8  (RpBase + NVME_PCIE_BNUM + 1,  (UINT8) BusNumber);
> // Secondary Bus Number registers
> +  PciWrite8  (RpBase + NVME_PCIE_BNUM + 2,  (UINT8) BusNumber);
> // Subordinate Bus Number registers
> +  PciWrite8  (RpBase + NVME_PCIE_IOBL,      0xFF);
> // I/O Base registers
> +  PciWrite8  (RpBase + NVME_PCIE_IOBL + 1,  0x00);
> // I/O Limit registers
> +  PciWrite16 (RpBase + NVME_PCIE_MBL,       (UINT16) RShiftU64
> ((UINTN)MemoryBase, 16));  // Memory Base register
> +  PciWrite16 (RpBase + NVME_PCIE_MBL + 2,   (UINT16) RShiftU64
> ((UINTN)MemoryLimit, 16)); // Memory Limit register
> +  PciWrite16 (RpBase + NVME_PCIE_PMBL,      0xFFFF);
> // Prefetchable Memory Base registers
> +  PciWrite16 (RpBase + NVME_PCIE_PMBL + 2,  0x0000);
> // Prefetchable Memory Limit registers
> +  PciWrite32 (RpBase + NVME_PCIE_PMBU32,    0xFFFFFFFF);
> // Prefetchable Memory Upper Base registers
> +  PciWrite32 (RpBase + NVME_PCIE_PMLU32,    0x00000000);
> // Prefetchable Memory Upper Limit registers
> +}
> +
> +/**
> +
> +  The function returns whether or not the device is Opal Locked.
> +  TRUE means that the device is partially or fully locked.
> +  This will perform a Level 0 Discovery and parse the locking feature descriptor
> +
> +  @param[in]      OpalDev             Opal object to determine if
> locked.
> +  @param[out]     BlockSidSupported   Whether device support BlockSid
> feature.
> +
> +**/
> +BOOLEAN
> +IsOpalDeviceLocked(
> +  OPAL_PEI_DEVICE    *OpalDev,
> +  BOOLEAN            *BlockSidSupported
> +  )
> +{
> +  OPAL_SESSION                   Session;
> +  OPAL_DISK_SUPPORT_ATTRIBUTE    SupportedAttributes;
> +  TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;
> +  UINT16                         OpalBaseComId;
> +  TCG_RESULT                     Ret;
> +
> +  Session.Sscp = &OpalDev->Sscp;
> +  Session.MediaId = 0;
> +
> +  Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes,
> &OpalBaseComId);
> +  if (Ret != TcgResultSuccess) {
> +    return FALSE;
> +  }
> +
> +  Session.OpalBaseComId  = OpalBaseComId;
> +  *BlockSidSupported     = SupportedAttributes.BlockSid == 1 ? TRUE :
> FALSE;
> +
> +  Ret = OpalGetLockingInfo(&Session, &LockingFeature);
> +  if (Ret != TcgResultSuccess) {
> +    return FALSE;
> +  }
> +
> +  return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);
> +}
> +
> +/**
> +  Unlock OPAL password for S3.
> +
> +  @param[in] OpalDev            Opal object to unlock.
> +
> +**/
> +VOID
> +UnlockOpalPassword (
> +  IN OPAL_PEI_DEVICE            *OpalDev
> +  )
> +{
> +  TCG_RESULT                    Result;
> +  OPAL_SESSION                  Session;
> +  BOOLEAN                       BlockSidSupport;
> +  UINT32                        PpStorageFlags;
> +  BOOLEAN                       BlockSIDEnabled;
> +
> +  BlockSidSupport = FALSE;
> +  if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
> +    ZeroMem(&Session, sizeof (Session));
> +    Session.Sscp = &OpalDev->Sscp;
> +    Session.MediaId = 0;
> +    Session.OpalBaseComId = OpalDev->Device->OpalBaseComId;
> +
> +    Result = OpalUtilUpdateGlobalLockingRange (
> +               &Session,
> +               OpalDev->Device->Password,
> +               OpalDev->Device->PasswordLength,
> +               FALSE,
> +               FALSE
> +               );
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a() OpalUtilUpdateGlobalLockingRange() Result = 0x%x\n",
> +      __FUNCTION__,
> +      Result
> +      ));
> +  }
> +
> +  PpStorageFlags = Tcg2PhysicalPresenceLibGetManagementFlags ();
> +  if ((PpStorageFlags &
> TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
> +    BlockSIDEnabled = TRUE;
> +  } else {
> +    BlockSIDEnabled = FALSE;
> +  }
> +  if (BlockSIDEnabled && BlockSidSupport) {
> +    Result = OpalBlockSid (&Session, TRUE);
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a() OpalBlockSid() Result = 0x%x\n",
> +      __FUNCTION__,
> +      Result
> +      ));
> +  }
> +}
> +
> +/**
> +  Unlock ATA OPAL password for S3.
> +
> +**/
> +VOID
> +UnlockOpalPasswordAta (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINT8                         *DevInfo;
> +  OPAL_DEVICE_ATA               TempDevInfoAta;
> +  OPAL_DEVICE_ATA               *DevInfoAta;
> +  UINTN                         DevInfoLengthAta;
> +  UINT8                         Bus;
> +  UINT8                         Device;
> +  UINT8                         Function;
> +  OPAL_PEI_DEVICE               OpalDev;
> +  UINT8                         BaseClassCode;
> +  UINT8                         SubClassCode;
> +  UINT8                         SataCmdSt;
> +  AHCI_CONTEXT                  AhciContext;
> +  UINT32                        AhciBar;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  //
> +  // Get ATA OPAL device info from LockBox.
> +  //
> +  DevInfo = (UINT8 *) &TempDevInfoAta;
> +  DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);
> +  Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo,
> &DevInfoLengthAta);
> +  if (Status == EFI_BUFFER_TOO_SMALL) {
> +    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));
> +    if (DevInfo != NULL) {
> +      Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo,
> &DevInfoLengthAta);
> +    }
> +  }
> +  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
> +    return;
> +  }
> +
> +  for (DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
> +       (UINTN) DevInfoAta < ((UINTN) DevInfo + DevInfoLengthAta);
> +       DevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) DevInfoAta +
> DevInfoAta->Length)) {
> +    Bus = DevInfoAta->Device.Bus;
> +    Device = DevInfoAta->Device.Device;
> +    Function = DevInfoAta->Device.Function;
> +
> +    SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> PCI_COMMAND_OFFSET));
> +    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> PCI_COMMAND_OFFSET), 0x6);
> +
> +    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0B));
> +    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0A));
> +    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
> +        ((SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) &&
> (SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))) {
> +      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode are not
> supported\n", __FUNCTION__));
> +    } else {
> +      AhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
> +      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24),
> DevInfoAta->BarAddr);
> +
> +      ZeroMem (&AhciContext, sizeof (AHCI_CONTEXT));
> +      AhciContext.AhciBar = DevInfoAta->BarAddr;
> +      AhciAllocateResource (&AhciContext);
> +      Status = AhciModeInitialize (&AhciContext, (UINT8)DevInfoAta->Port);
> +      ASSERT_EFI_ERROR (Status);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a() AhciModeInitialize() error,
> Status: %r\n", __FUNCTION__, Status));
> +      }
> +
> +      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
> +      OpalDev.Sscp.ReceiveData = SecurityReceiveData;
> +      OpalDev.Sscp.SendData = SecuritySendData;
> +      OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;
> +      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;
> +      OpalDev.Context = &AhciContext;
> +
> +      UnlockOpalPassword (&OpalDev);
> +
> +      AhciFreeResource (&AhciContext);
> +      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), AhciBar);
> +    }
> +    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> PCI_COMMAND_OFFSET), SataCmdSt);
> +  }
> +
> +  ZeroMem (DevInfo, DevInfoLengthAta);
> +  if ((UINTN) DevInfo != (UINTN) &TempDevInfoAta) {
> +    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthAta));
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Unlock NVMe OPAL password for S3.
> +
> +**/
> +VOID
> +UnlockOpalPasswordNvme (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINT8                         *DevInfo;
> +  OPAL_DEVICE_NVME              TempDevInfoNvme;
> +  OPAL_DEVICE_NVME              *DevInfoNvme;
> +  UINTN                         DevInfoLengthNvme;
> +  UINT8                         Bus;
> +  UINT8                         Device;
> +  UINT8                         Function;
> +  OPAL_PEI_DEVICE               OpalDev;
> +  UINT8                         BaseClassCode;
> +  UINT8                         SubClassCode;
> +  UINT8                         ProgInt;
> +  UINT8                         NvmeCmdSt;
> +  UINT8                         *StorePcieConfDataList[16];
> +  UINTN                         RpBase;
> +  UINTN                         MemoryBase;
> +  UINTN                         MemoryLength;
> +  NVME_CONTEXT                  NvmeContext;
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> +
> +  //
> +  // Get NVMe OPAL device info from LockBox.
> +  //
> +  DevInfo = (UINT8 *) &TempDevInfoNvme;
> +  DevInfoLengthNvme = sizeof (OPAL_DEVICE_NVME);
> +  Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo,
> &DevInfoLengthNvme);
> +  if (Status == EFI_BUFFER_TOO_SMALL) {
> +    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
> +    if (DevInfo != NULL) {
> +      Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo,
> &DevInfoLengthNvme);
> +    }
> +  }
> +  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
> +    return;
> +  }
> +
> +  for (DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
> +       (UINTN) DevInfoNvme < ((UINTN) DevInfo + DevInfoLengthNvme);
> +       DevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) DevInfoNvme +
> DevInfoNvme->Length)) {
> +    Bus = DevInfoNvme->Device.Bus;
> +    Device = DevInfoNvme->Device.Device;
> +    Function = DevInfoNvme->Device.Function;
> +
> +    RpBase    = 0;
> +    NvmeCmdSt = 0;
> +
> +    ///
> +    /// Save original RootPort configuration space to heap
> +    ///
> +    RpBase = SaveRestoreRootportConfSpace (
> +                DevInfoNvme,
> +                TRUE, // save
> +                StorePcieConfDataList
> +                );
> +    MemoryBase = DevInfoNvme->BarAddr;
> +    MemoryLength = 0;
> +    ConfigureRootPortForPcieNand (RpBase, Bus, (UINT32) MemoryBase,
> (UINT32) MemoryLength);
> +
> +    ///
> +    /// Enable PCIE decode for RootPort
> +    ///
> +    NvmeCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
> +    PciWrite8  (RpBase + NVME_PCIE_PCICMD,  0x6);
> +
> +    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0B));
> +    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x0A));
> +    ProgInt       = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function,
> 0x09));
> +    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
> +        (SubClassCode != PCI_CLASS_MASS_STORAGE_NVM) ||
> +        (ProgInt != PCI_IF_NVMHCI)) {
> +      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode/PI are not
> supported\n", __FUNCTION__));
> +    } else {
> +      ZeroMem (&NvmeContext, sizeof (NVME_CONTEXT));
> +      NvmeContext.Nbar = DevInfoNvme->BarAddr;
> +      NvmeContext.PciBase = PCI_LIB_ADDRESS (Bus, Device, Function, 0x0);
> +      NvmeContext.NvmeInitWaitTime = 0;
> +      NvmeContext.Nsid = DevInfoNvme->NvmeNamespaceId;
> +      NvmeAllocateResource (&NvmeContext);
> +      Status = NvmeControllerInit (&NvmeContext);
> +
> +      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
> +      OpalDev.Sscp.ReceiveData = SecurityReceiveData;
> +      OpalDev.Sscp.SendData = SecuritySendData;
> +      OpalDev.DeviceType = OPAL_DEVICE_TYPE_NVME;
> +      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoNvme;
> +      OpalDev.Context = &NvmeContext;
> +
> +      UnlockOpalPassword (&OpalDev);
> +
> +      Status = NvmeControllerExit (&NvmeContext);
> +      NvmeFreeResource (&NvmeContext);
> +    }
> +
> +    ASSERT (RpBase != 0);
> +    PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);
> +    RpBase = SaveRestoreRootportConfSpace (
> +                DevInfoNvme,
> +                FALSE,  // restore
> +                StorePcieConfDataList
> +                );
> +    PciWrite8  (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
> +  }
> +
> +  ZeroMem (DevInfo, DevInfoLengthNvme);
> +  if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
> +    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> +}
> +
> +/**
> +  Unlock OPAL password for S3.
> +
> +**/
> +VOID
> +OpalPasswordS3 (
> +  VOID
> +  )
> +{
> +  UnlockOpalPasswordAta ();
> +  UnlockOpalPasswordNvme ();
> +}
> +
> +/**
> +  Entry point of the notification callback function itself within the PEIM.
> +  It is to unlock OPAL password for S3.
> +
> +  @param  PeiServices      Indirect reference to the PEI Services Table.
> +  @param  NotifyDescriptor Address of the notification descriptor data
> structure.
> +  @param  Ppi              Address of the PPI that was installed.
> +
> +  @return Status of the notification.
> +          The status code returned from this function is ignored.
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalPasswordEndOfPeiNotify(
> +  IN EFI_PEI_SERVICES          **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
> +  IN VOID                      *Ppi
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_BOOT_MODE                     BootMode;
> +
> +  Status = PeiServicesGetBootMode (&BootMode);
> +  ASSERT_EFI_ERROR (Status);
> +  if (BootMode != BOOT_ON_S3_RESUME) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
> +
> +  OpalPasswordS3 ();
> +
> +  DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordEndOfPeiNotifyDesc = {
> +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEfiEndOfPeiSignalPpiGuid,
> +  OpalPasswordEndOfPeiNotify
> +};
> +
> +/**
> +  Main entry for this module.
> +
> +  @param FileHandle             Handle of the file being invoked.
> +  @param PeiServices            Pointer to PEI Services table.
> +
> +  @return Status from PeiServicesNotifyPpi.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpalPasswordPeiInit (
> +  IN EFI_PEI_FILE_HANDLE        FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  EFI_STATUS                    Status;
> +
> +  Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> new file mode 100644
> index 000000000000..31aab37f5d91
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> @@ -0,0 +1,133 @@
> +/** @file
> +  Opal Password PEI driver which is used to unlock Opal Password for S3.
> +
> +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be found
> at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +**/
> +
> +#ifndef _OPAL_PASSWORD_PEI_H_
> +#define _OPAL_PASSWORD_PEI_H_
> +
> +#include <PiPei.h>
> +#include <IndustryStandard/Atapi.h>
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PeimEntryPoint.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/LockBoxLib.h>
> +#include <Library/TcgStorageOpalLib.h>
> +#include <Library/Tcg2PhysicalPresenceLib.h>
> +
> +#include <Protocol/StorageSecurityCommand.h>
> +
> +#include <Ppi/IoMmu.h>
> +
> +#include "OpalPasswordCommon.h"
> +#include "OpalAhciMode.h"
> +#include "OpalNvmeMode.h"
> +
> +//
> +// Time out Value for ATA pass through protocol
> +//
> +#define ATA_TIMEOUT                      30000000
> +
> +//
> +// The payload Length of HDD related ATA commands
> +//
> +#define HDD_PAYLOAD                      512
> +//
> +// According to ATA spec, the max Length of hdd password is 32 bytes
> +//
> +#define OPAL_PASSWORD_MAX_LENGTH         32
> +
> +#pragma pack(1)
> +
> +/**
> +* Opal I/O Type utilized by the Trusted IO callback
> +*
> +* The type indicates if the I/O is a send or receive
> +*/
> +typedef enum {
> +    //
> +    // I/O is a TCG Trusted Send command
> +    //
> +    OpalSend,
> +
> +    //
> +    // I/O is a TCG Trusted Receive command
> +    //
> +    OpalRecv
> +} OPAL_IO_TYPE;
> +
> +#define OPAL_PEI_DEVICE_SIGNATURE SIGNATURE_32 ('o', 'p', 'd', 's')
> +
> +typedef struct {
> +  UINTN                                     Signature;
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL     Sscp;
> +  UINT8                                     DeviceType;
> +  OPAL_DEVICE_COMMON                        *Device;
> +  VOID                                      *Context;
> +} OPAL_PEI_DEVICE;
> +
> +#define OPAL_PEI_DEVICE_FROM_THIS(a)  CR (a, OPAL_PEI_DEVICE, Sscp,
> OPAL_PEI_DEVICE_SIGNATURE)
> +
> +#pragma pack()
> +
> +/**
> +  Allocates pages that are suitable for an OperationBusMasterCommonBuffer
> or
> +  OperationBusMasterCommonBuffer64 mapping.
> +
> +  @param Pages                  The number of pages to allocate.
> +  @param HostAddress            A pointer to store the base system
> memory address of the
> +                                allocated range.
> +  @param DeviceAddress          The resulting map address for the bus
> master PCI controller to use to
> +                                access the hosts HostAddress.
> +  @param Mapping                A resulting value to pass to Unmap().
> +
> +  @retval EFI_SUCCESS           The requested memory pages were
> allocated.
> +  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal
> attribute bits are
> +                                MEMORY_WRITE_COMBINE and
> MEMORY_CACHED.
> +  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be
> allocated.
> +
> +**/
> +EFI_STATUS
> +IoMmuAllocateBuffer (
> +  IN UINTN                  Pages,
> +  OUT VOID                  **HostAddress,
> +  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
> +  OUT VOID                  **Mapping
> +  );
> +
> +/**
> +  Frees memory that was allocated with AllocateBuffer().
> +
> +  @param Pages              The number of pages to free.
> +  @param HostAddress        The base system memory address of the
> allocated range.
> +  @param Mapping            The mapping value returned from Map().
> +
> +**/
> +VOID
> +IoMmuFreeBuffer (
> +  IN UINTN                  Pages,
> +  IN VOID                   *HostAddress,
> +  IN VOID                   *Mapping
> +  );
> +
> +#endif // _OPAL_PASSWORD_PEI_H_
> +
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> new file mode 100644
> index 000000000000..81c57c36d2aa
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> @@ -0,0 +1,63 @@
> +## @file
> +#  This is a Opal Password PEI driver.
> +#
> +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be found
> at
> +# http://opensource.org/licenses/bsd-license.php
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = OpalPasswordPei
> +  FILE_GUID                      =
> DED60489-979C-4B5A-8EE4-4068B0CC38DC
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = OpalPasswordPeiInit
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  OpalPasswordPei.c
> +  OpalPasswordPei.h
> +  OpalPasswordCommon.h
> +  OpalAhciMode.c
> +  OpalAhciMode.h
> +  OpalNvmeMode.c
> +  OpalNvmeMode.h
> +  OpalNvmeReg.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  SecurityPkg/SecurityPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  PeimEntryPoint
> +  PeiServicesLib
> +  DebugLib
> +  IoLib
> +  PciLib
> +  BaseLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> +  TimerLib
> +  HobLib
> +  LockBoxLib
> +  TcgStorageOpalLib
> +  Tcg2PhysicalPresenceLib
> +
> +[Ppis]
> +  gEdkiiIoMmuPpiGuid                            ##
> SOMETIMES_CONSUMES
> +  gEfiEndOfPeiSignalPpiGuid                     ## NOTIFY
> +
> +[Depex]
> +  gEfiPeiMasterBootModePpiGuid
> --
> 2.7.0.windows.1



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

end of thread, other threads:[~2018-03-08 11:42 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-03-07 13:19 [PATCH V2 0/7] OpalPassword: New solution without SMM device code Star Zeng
2018-03-07 13:19 ` [PATCH V2 1/7] MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY Star Zeng
2018-03-07 13:19 ` [PATCH V2 2/7] SecurityPkg TcgStorageOpalLib: Make it be base type really Star Zeng
2018-03-07 13:19 ` [PATCH V2 3/7] SecurityPkg TcgStorageCoreLib: " Star Zeng
2018-03-07 13:19 ` [PATCH V2 4/7] SecurityPkg OpalPassword: Add solution without SMM device code Star Zeng
2018-03-08 11:44   ` Yao, Jiewen
2018-03-08 11:48     ` Zeng, Star
2018-03-07 13:19 ` [PATCH V2 5/7] SecurityPkg OpalPassword: Remove old solution Star Zeng
2018-03-07 13:19 ` [PATCH V2 6/7] SecurityPkg OpalPasswordSupportLib: Remove it Star Zeng
2018-03-07 13:19 ` [PATCH V2 7/7] SecurityPkg OpalPasswordExtraInfoVariable.h: " Star Zeng

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