public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "Dong, Eric" <eric.dong@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Zhang, Chao B" <chao.b.zhang@intel.com>,
	"Yao, Jiewen" <jiewen.yao@intel.com>,
	"Ni, Ray" <ray.ni@intel.com>
Subject: Re: [PATCH v5 13/13] SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI
Date: Tue, 19 Feb 2019 02:50:24 +0000	[thread overview]
Message-ID: <B80AF82E9BFB8E4FBD8C89DA810C6A093C897E4D@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <ED077930C258884BBCB450DB737E662259DB1153@shsmsx102.ccr.corp.intel.com>

> -----Original Message-----
> From: Dong, Eric
> Sent: Monday, February 18, 2019 2:21 PM
> To: Wu, Hao A; edk2-devel@lists.01.org
> Cc: Zhang, Chao B; Yao, Jiewen; Ni, Ray
> Subject: RE: [PATCH v5 13/13] SecurityPkg/OpalPassword: Remove HW init
> codes and consume SSC PPI
> 
> Hi Hao,
> 
> Only one minor change that below zero action is not needed.
> > +  ZeroMem (S3InitDevices, S3InitDevicesLength);

Thanks Eric, got your point.

I will also remove the line:
ZeroMem (S3InitDevicesBak, GetDevicePathSize (S3InitDevicesBak));

which similarly clear the device path information in memory.

Best Regards,
Hao Wu

> 
> With above changes, Reviewed-by: Eric Dong <eric.dong@intel.com>
> 
> Thanks,
> Eric
> 
> > -----Original Message-----
> > From: Wu, Hao A
> > Sent: Friday, February 15, 2019 2:24 PM
> > To: edk2-devel@lists.01.org
> > Cc: Wu, Hao A <hao.a.wu@intel.com>; Zhang, Chao B
> > <chao.b.zhang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Ni, Ray
> > <ray.ni@intel.com>; Dong, Eric <eric.dong@intel.com>
> > Subject: [PATCH v5 13/13] SecurityPkg/OpalPassword: Remove HW init
> codes
> > and consume SSC PPI
> >
> > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1409
> >
> > For the current implementation of OpalPassword drivers, it has a feature
> > to support devices being automatically unlocked in the S3 resume. For this
> > feature, two types of devices are supported:
> >
> > * ATA hard disks working under AHCI mode
> > * NVM Express devices
> >
> > The support of this feature requires the above 2 types of device to be
> > initialized at the PEI phase during S3 resume, which is done by the
> > co-work of the OpalPasswordDxe driver and the OpalPasswordPei driver.
> >
> > More specifically, the OpalPasswordDxe will handle:
> >
> > * Pre-allocate MMIO resource and save it in a driver internal LockBox for
> >   OpalPasswordPei to retrieve;
> > * Save the PCI configuration space of ATA controllers into boot script.
> >
> > Meanwhile, the OpalPasswordPei will handle:
> >
> > * Rely on the boot script for the PCI configuration space program of ATA
> >   controllers;
> > * Restore the driver internal LockBox to get the MMIO resource;
> > * Complete the PCI configuration space program for ATA and NVME
> >   controllers;
> > * Initialize ATA and NVME controllers and devices.
> >
> > This commit will remove these hardware initialization related codes from
> > the OpalPassword drivers. The hardware initialization will be covered by
> > PEI storage device drivers (e.g. NvmExpressPei & AhciPei in the
> > MdeModulePkg).
> >
> > After such codes removal, the OpalPasswordDxe will only handle:
> >
> > * Construct/update the S3StorageDeviceInitList LockBox with the managing
> >   ATA and NVME devices.
> >
> > And the OpalPasswordPei will only handle:
> >
> > * Locate Storage Security Command PPI instances to perform the device
> >   automatic unlock during the S3 resume.
> >
> > Cc: Chao Zhang <chao.b.zhang@intel.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Hao Wu <hao.a.wu@intel.com>
> > ---
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf  |    6 +-
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf  |   12 +-
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h       |  412 -----
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h         |    4 +-
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h       |  327 ----
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h        |  815 ---------
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h |   45 +-
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h    |  106 +-
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c       | 1282 ------------
> --
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c         |  416 ++---
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c       | 1823 ----------
> --
> > --------
> >  SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c    |  757 ++------
> >  12 files changed, 361 insertions(+), 5644 deletions(-)
> >
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> > index 11e58b95cd..2e343a4707 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> > @@ -4,7 +4,7 @@
> >  #  This module is used to Management the Opal feature
> >  #  for Opal supported devices.
> >  #
> > -# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +# Copyright (c) 2016 - 2019, 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
> > @@ -62,7 +62,6 @@
> >    TcgStorageOpalLib
> >    Tcg2PhysicalPresenceLib
> >    PciLib
> > -  S3BootScriptLib
> >    LockBoxLib
> >
> >  [Protocols]
> > @@ -73,7 +72,8 @@
> >    gEfiBlockIoProtocolGuid                       ## CONSUMES
> >
> >  [Guids]
> > -  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES             ## Event
> > +  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES ## Event
> > +  gS3StorageDeviceInitListGuid                  ## SOMETIMES_PRODUCES ##
> > UNDEFINED
> >
> >  [Pcd]
> >    gEfiSecurityPkgTokenSpaceGuid.PcdSkipOpalDxeUnlock  ## CONSUMES
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> > index 482b7c25af..5abfc69e80 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> > @@ -1,7 +1,7 @@
> >  ## @file
> >  #  This is a Opal Password PEI driver.
> >  #
> > -# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +# Copyright (c) 2016 - 2019, 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
> > @@ -29,11 +29,6 @@
> >    OpalPasswordPei.c
> >    OpalPasswordPei.h
> >    OpalPasswordCommon.h
> > -  OpalAhciMode.c
> > -  OpalAhciMode.h
> > -  OpalNvmeMode.c
> > -  OpalNvmeMode.h
> > -  OpalNvmeReg.h
> >
> >  [Packages]
> >    MdePkg/MdePkg.dec
> > @@ -49,14 +44,13 @@
> >    BaseLib
> >    BaseMemoryLib
> >    MemoryAllocationLib
> > -  TimerLib
> >    LockBoxLib
> >    TcgStorageOpalLib
> >    Tcg2PhysicalPresenceLib
> > +  PeiServicesTablePointerLib
> >
> >  [Ppis]
> > -  gEdkiiIoMmuPpiGuid                            ## SOMETIMES_CONSUMES
> > -  gEfiEndOfPeiSignalPpiGuid                     ## NOTIFY
> > +  gEdkiiPeiStorageSecurityCommandPpiGuid        ## NOTIFY
> >
> >  [Depex]
> >    gEfiPeiMasterBootModePpiGuid
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> > deleted file mode 100644
> > index 2076b0411b..0000000000
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> > +++ /dev/null
> > @@ -1,412 +0,0 @@
> > -/** @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;
> > -
> > -/**
> > -  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.h
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> > index 2bca770620..1baa483e72 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    Values defined and used by the Opal UEFI Driver.
> >
> > -Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2016 - 2019, 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
> > @@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> ANY
> > KIND, EITHER EXPRESS OR IMPLIED.
> >  #include <Protocol/StorageSecurityCommand.h>
> >
> >  #include <Guid/EventGroup.h>
> > +#include <Guid/S3StorageDeviceInitList.h>
> >
> >  #include <Library/UefiLib.h>
> >  #include <Library/UefiBootServicesTableLib.h>
> > @@ -42,7 +43,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> ANY
> > KIND, EITHER EXPRESS OR IMPLIED.
> >  #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>
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> > deleted file mode 100644
> > index bd2bd5239d..0000000000
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> > +++ /dev/null
> > @@ -1,327 +0,0 @@
> > -/** @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
> > -  );
> > -
> > -/**
> > -  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
> > deleted file mode 100644
> > index 03376b9e6c..0000000000
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> > +++ /dev/null
> > @@ -1,815 +0,0 @@
> > -/** @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
> > index e10146e466..f9fdb64137 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    Opal Password common header file.
> >
> > -Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2018 - 2019, 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
> > @@ -30,38 +30,15 @@ typedef struct {
> >  } OPAL_PCI_DEVICE;
> >
> >  typedef struct {
> > -  UINT16            Length;
> > -  OPAL_PCI_DEVICE   Device;
> > -  UINT8             PasswordLength;
> > -  UINT8             Password[OPAL_MAX_PASSWORD_SIZE];
> > -  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[OPAL_MAX_PASSWORD_SIZE];
> > -  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[OPAL_MAX_PASSWORD_SIZE];
> > -  UINT16            OpalBaseComId;
> > -  UINT32            BarAddr;
> > -  UINT32            NvmeNamespaceId;
> > -  OPAL_PCI_DEVICE   PciBridgeNode[0];
> > -} OPAL_DEVICE_NVME;
> > +  UINT32                      Length;
> > +  OPAL_PCI_DEVICE             Device;
> > +  UINT8                       PasswordLength;
> > +  UINT8                       Password[OPAL_MAX_PASSWORD_SIZE];
> > +  UINT16                      OpalBaseComId;
> > +  UINT32                      DevicePathLength;
> > +  EFI_DEVICE_PATH_PROTOCOL    DevicePath[];
> > +} OPAL_DEVICE_LOCKBOX_DATA;
> > +
> > +#define OPAL_DEVICE_LOCKBOX_GUID  { 0x56a77f0d, 0x6f05, 0x4d47,
> > { 0xb9, 0x11, 0x4f, 0xd, 0xec, 0x5c, 0x58, 0x61 } }
> >
> >  #endif // _OPAL_PASSWORD_COMMON_H_
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> > index 31aab37f5d..c86598f21c 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    Opal Password PEI driver which is used to unlock Opal Password for S3.
> >
> > -Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2016 - 2019, 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
> > @@ -16,8 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> ANY
> > KIND, EITHER EXPRESS OR IMPLIED.
> >  #define _OPAL_PASSWORD_PEI_H_
> >
> >  #include <PiPei.h>
> > -#include <IndustryStandard/Atapi.h>
> > -#include <IndustryStandard/Pci.h>
> >
> >  #include <Library/DebugLib.h>
> >  #include <Library/IoLib.h>
> > @@ -27,107 +25,63 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> > ANY KIND, EITHER EXPRESS OR IMPLIED.
> >  #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 <Library/PeiServicesTablePointerLib.h>
> >
> >  #include <Protocol/StorageSecurityCommand.h>
> >
> >  #include <Ppi/IoMmu.h>
> > +#include <Ppi/StorageSecurityCommand.h>
> >
> >  #include "OpalPasswordCommon.h"
> > -#include "OpalAhciMode.h"
> > -#include "OpalNvmeMode.h"
> >
> >  //
> > -// Time out Value for ATA pass through protocol
> > +// The maximum number of Storage Security Command PPI instance
> > supported
> > +// by the driver
> >  //
> > -#define ATA_TIMEOUT                      30000000
> > +#define OPAL_PEI_MAX_STORAGE_SECURITY_CMD_PPI    32
> >
> >  //
> > -// The payload Length of HDD related ATA commands
> > +// The generic command timeout value (unit in us) for Storage Security
> > Command
> > +// PPI ReceiveData/SendData services
> >  //
> > -#define HDD_PAYLOAD                      512
> > -//
> > -// According to ATA spec, the max Length of hdd password is 32 bytes
> > -//
> > -#define OPAL_PASSWORD_MAX_LENGTH         32
> > +#define SSC_PPI_GENERIC_TIMEOUT                  30000000
> >
> >  #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')
> > +#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;
> > +  UINTN                                    Signature;
> > +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    Sscp;
> > +  OPAL_DEVICE_LOCKBOX_DATA                 *Device;
> > +  VOID                                     *Context;
> > +  EDKII_PEI_STORAGE_SECURITY_CMD_PPI       *SscPpi;
> > +  UINTN                                    DeviceIndex;
> >  } OPAL_PEI_DEVICE;
> >
> > -#define OPAL_PEI_DEVICE_FROM_THIS(a)  CR (a, OPAL_PEI_DEVICE, Sscp,
> > OPAL_PEI_DEVICE_SIGNATURE)
> > +#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
> > -  );
> > +//
> > +// Private data structure for Opal PEI driver
> > +//
> > +#define OPAL_PEI_DRIVER_SIGNATURE       SIGNATURE_32 ('o', 'd', 'r', 'i')
> >
> > -/**
> > -  Frees memory that was allocated with AllocateBuffer().
> > +typedef struct {
> > +  UINTN                        Signature;
> > +  EFI_PEI_NOTIFY_DESCRIPTOR    SscPpiNotifyList;
> >
> > -  @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().
> > +  UINTN                        SscPpiInstanceNum;
> > +  UINTN
> > SscPpiInstances[OPAL_PEI_MAX_STORAGE_SECURITY_CMD_PPI];
> > +} OPAL_PEI_DRIVER_PRIVATE_DATA;
> >
> > -**/
> > -VOID
> > -IoMmuFreeBuffer (
> > -  IN UINTN                  Pages,
> > -  IN VOID                   *HostAddress,
> > -  IN VOID                   *Mapping
> > -  );
> > +#define OPAL_PEI_PRIVATE_DATA_FROM_THIS_NOTIFY(a)    \
> > +  CR (a, OPAL_PEI_DRIVER_PRIVATE_DATA, SscPpiNotifyList,
> > OPAL_PEI_DRIVER_SIGNATURE)
> >
> >  #endif // _OPAL_PASSWORD_PEI_H_
> >
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> > deleted file mode 100644
> > index 0c4edd5346..0000000000
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> > +++ /dev/null
> > @@ -1,1282 +0,0 @@
> > -/** @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;
> > -
> > -
> > -}
> > -
> > -/**
> > -  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_COMMAND_LIST)),
> > -       AhciRegisters->AhciCmdList,
> > -       AhciRegisters->AhciCmdListMapping
> > -       );
> > -    AhciRegisters->AhciCmdList = NULL;
> > -    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->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->AhciCommandTable,
> > -       AhciRegisters->AhciCommandTableMapping
> > -       );
> > -    AhciRegisters->AhciCommandTable = 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->AhciRFis,
> > -       AhciRegisters->AhciRFisMapping
> > -       );
> > -    AhciRegisters->AhciRFis = 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 (AhciContext->Buffer != NULL) {
> > -    IoMmuFreeBuffer (
> > -       EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> > -       AhciContext->Buffer,
> > -       AhciContext->BufferMapping
> > -       );
> > -    AhciContext->Buffer = NULL;
> > -  }
> > -
> > -  if (AhciRegisters->AhciCommandTable != NULL) {
> > -    IoMmuFreeBuffer (
> > -       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> > -       AhciRegisters->AhciCommandTable,
> > -       AhciRegisters->AhciCommandTableMapping
> > -       );
> > -    AhciRegisters->AhciCommandTable = NULL;
> > -  }
> > -
> > -  if (AhciRegisters->AhciCmdList != NULL) {
> > -    IoMmuFreeBuffer (
> > -       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> > -       AhciRegisters->AhciCmdList,
> > -       AhciRegisters->AhciCmdListMapping
> > -       );
> > -    AhciRegisters->AhciCmdList = NULL;
> > -  }
> > -
> > -  if (AhciRegisters->AhciRFis != NULL) {
> > -    IoMmuFreeBuffer (
> > -       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> > -       AhciRegisters->AhciRFis,
> > -       AhciRegisters->AhciRFisMapping
> > -       );
> > -    AhciRegisters->AhciRFis = 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/OpalDriver.c
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> > index b5317d82b8..40fd892bc1 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> > @@ -21,40 +21,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> > ANY KIND, EITHER EXPRESS OR IMPLIED.
> >  #include "OpalDriver.h"
> >  #include "OpalHii.h"
> >
> > -EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
> > -EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
> > +EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;
> >
> >  BOOLEAN                 mOpalEndOfDxe = FALSE;
> >  OPAL_REQUEST_VARIABLE   *mOpalRequestVariable = NULL;
> >  UINTN                   mOpalRequestVariableSize = 0;
> >  CHAR16                  mPopUpString[100];
> >
> > -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;
> >
> >  //
> > @@ -233,14 +206,12 @@ OpalSupportUpdatePassword (
> >    @param[out] DevInfoLength     Device information length needed.
> >    @param[out] DevInfo           Device information extracted.
> >
> > -  @return Device type.
> > -
> >  **/
> > -UINT8
> > +VOID
> >  ExtractDeviceInfoFromDevicePath (
> >    IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
> > -  OUT UINT16                    *DevInfoLength,
> > -  OUT OPAL_DEVICE_COMMON        *DevInfo OPTIONAL
> > +  OUT UINT32                    *DevInfoLength,
> > +  OUT OPAL_DEVICE_LOCKBOX_DATA  *DevInfo OPTIONAL
> >    )
> >  {
> >    EFI_DEVICE_PATH_PROTOCOL      *TmpDevPath;
> > @@ -249,10 +220,6 @@ ExtractDeviceInfoFromDevicePath (
> >    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);
> > @@ -266,30 +233,15 @@ ExtractDeviceInfoFromDevicePath (
> >    // 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 ((TmpDevPath->Type == MESSAGING_DEVICE_PATH) &&
> > +        (TmpDevPath->SubType == MSG_SATA_DP || TmpDevPath-
> >SubType
> > == MSG_NVME_NAMESPACE_DP)) {
> >        if (DevInfo != NULL) {
> > -        NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;
> > -        DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
> > -        DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;
> > +        DevInfo->DevicePathLength = (UINT32) GetDevicePathSize
> > (DevicePath);
> > +        CopyMem (DevInfo->DevicePath, DevicePath, DevInfo-
> > >DevicePathLength);
> >        }
> > -      DeviceType = OPAL_DEVICE_TYPE_NVME;
> > -      *DevInfoLength = sizeof (OPAL_DEVICE_NVME);
> > +
> > +      DeviceType = (TmpDevPath->SubType == MSG_SATA_DP) ?
> > OPAL_DEVICE_TYPE_ATA : OPAL_DEVICE_TYPE_NVME;
> > +      *DevInfoLength = sizeof (OPAL_DEVICE_LOCKBOX_DATA) + (UINT32)
> > GetDevicePathSize (DevicePath);
> >        break;
> >      }
> >      TmpDevPath = NextDevicePathNode (TmpDevPath);
> > @@ -304,8 +256,8 @@ ExtractDeviceInfoFromDevicePath (
> >    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 ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH) &&
> > +          (TmpDevPath2->SubType == MSG_SATA_DP || TmpDevPath2-
> > >SubType == MSG_NVME_NAMESPACE_DP)) {
> >          if (DevInfo != NULL) {
> >            PciDevice = &DevInfo->Device;
> >            PciDevice->Segment = 0;
> > @@ -314,14 +266,6 @@ ExtractDeviceInfoFromDevicePath (
> >            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));
> >          }
> > @@ -333,251 +277,159 @@ ExtractDeviceInfoFromDevicePath (
> >    }
> >
> >    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);
> > -  }
> > +  return;
> >  }
> >
> >  /**
> > -  Build ATA OPAL device info and save them to LockBox.
> > -
> > -  @param[in] BarAddr    Bar address allocated.
> > +  Build OPAL device info and save them to LockBox.
> >
> >   **/
> >  VOID
> > -BuildOpalDeviceInfoAta (
> > -  IN UINT32     BarAddr
> > +BuildOpalDeviceInfo (
> > +  VOID
> >    )
> >  {
> > -  EFI_STATUS            Status;
> > -  UINT8                 DeviceType;
> > -  OPAL_DEVICE_ATA       *DevInfoAta;
> > -  OPAL_DEVICE_ATA       *TempDevInfoAta;
> > -  UINTN                 DevInfoLengthAta;
> > -  UINT16                DevInfoLength;
> > -  OPAL_DRIVER_DEVICE    *TmpDev;
> > +  EFI_STATUS                  Status;
> > +  OPAL_DEVICE_LOCKBOX_DATA    *DevInfo;
> > +  OPAL_DEVICE_LOCKBOX_DATA    *TempDevInfo;
> > +  UINTN                       TotalDevInfoLength;
> > +  UINT32                      DevInfoLength;
> > +  OPAL_DRIVER_DEVICE          *TmpDev;
> > +  UINT8                       DummyData;
> > +  BOOLEAN                     S3InitDevicesExist;
> > +  UINTN                       S3InitDevicesLength;
> > +  EFI_DEVICE_PATH_PROTOCOL    *S3InitDevices;
> > +  EFI_DEVICE_PATH_PROTOCOL    *S3InitDevicesBak;
> >
> >    //
> > -  // Build ATA OPAL device info and save them to LockBox.
> > +  // Build OPAL device info and save them to LockBox.
> >    //
> > -  DevInfoLengthAta = 0;
> > +  TotalDevInfoLength = 0;
> >    TmpDev = mOpalDriver.DeviceList;
> >    while (TmpDev != NULL) {
> > -    DeviceType = ExtractDeviceInfoFromDevicePath (
> > -                   TmpDev->OpalDisk.OpalDevicePath,
> > -                   &DevInfoLength,
> > -                   NULL
> > -                   );
> > -    if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
> > -      DevInfoLengthAta += DevInfoLength;
> > -    }
> > -
> > +    ExtractDeviceInfoFromDevicePath (
> > +      TmpDev->OpalDisk.OpalDevicePath,
> > +      &DevInfoLength,
> > +      NULL
> > +      );
> > +    TotalDevInfoLength += DevInfoLength;
> >      TmpDev = TmpDev->Next;
> >    }
> >
> > -  if (DevInfoLengthAta == 0) {
> > +  if (TotalDevInfoLength == 0) {
> >      return;
> >    }
> >
> > -  DevInfoAta = AllocateZeroPool (DevInfoLengthAta);
> > -  ASSERT (DevInfoAta != NULL);
> > -  if (DevInfoAta == NULL) {
> > -    return;
> > -  }
> > -
> > -  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
> > +  S3InitDevicesLength = sizeof (DummyData);
> > +  Status = RestoreLockBox (
> > +             &gS3StorageDeviceInitListGuid,
> > +             &DummyData,
> > +             &S3InitDevicesLength
> >               );
> > -  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;
> > +  ASSERT ((Status == EFI_NOT_FOUND) || (Status ==
> > EFI_BUFFER_TOO_SMALL));
> > +  if (Status == EFI_NOT_FOUND) {
> > +    S3InitDevices      = NULL;
> > +    S3InitDevicesExist = FALSE;
> > +  } else if (Status == EFI_BUFFER_TOO_SMALL) {
> > +    S3InitDevices = AllocatePool (S3InitDevicesLength);
> > +    ASSERT (S3InitDevices != NULL);
> > +    if (S3InitDevices == NULL) {
> > +      return;
> >      }
> >
> > -    TmpDev = TmpDev->Next;
> > -  }
> > -
> > -  if (DevInfoLengthNvme == 0) {
> > +    Status = RestoreLockBox (
> > +               &gS3StorageDeviceInitListGuid,
> > +               S3InitDevices,
> > +               &S3InitDevicesLength
> > +               );
> > +    ASSERT_EFI_ERROR (Status);
> > +    S3InitDevicesExist = TRUE;
> > +  } else {
> >      return;
> >    }
> >
> > -  DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);
> > -  ASSERT (DevInfoNvme != NULL);
> > -  if (DevInfoNvme == NULL) {
> > +  DevInfo = AllocateZeroPool (TotalDevInfoLength);
> > +  ASSERT (DevInfo != NULL);
> > +  if (DevInfo == NULL) {
> >      return;
> >    }
> >
> > -  TempDevInfoNvme = DevInfoNvme;
> > -  TmpDev = mOpalDriver.DeviceList;
> > +  TempDevInfo = DevInfo;
> > +  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);
> > +    ExtractDeviceInfoFromDevicePath (
> > +      TmpDev->OpalDisk.OpalDevicePath,
> > +      &DevInfoLength,
> > +      TempDevInfo
> > +      );
> > +    TempDevInfo->Length = DevInfoLength;
> > +    TempDevInfo->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
> > +    CopyMem (
> > +      TempDevInfo->Password,
> > +      TmpDev->OpalDisk.Password,
> > +      TmpDev->OpalDisk.PasswordLength
> > +      );
> > +    TempDevInfo->PasswordLength = TmpDev->OpalDisk.PasswordLength;
> > +
> > +    S3InitDevicesBak = S3InitDevices;
> > +    S3InitDevices    = AppendDevicePathInstance (
> > +                         S3InitDevicesBak,
> > +                         TmpDev->OpalDisk.OpalDevicePath
> > +                         );
> > +    if (S3InitDevicesBak != NULL) {
> > +      ZeroMem (S3InitDevicesBak, GetDevicePathSize (S3InitDevicesBak));
> > +      FreePool (S3InitDevicesBak);
> > +    }
> > +    ASSERT (S3InitDevices != NULL);
> > +    if (S3InitDevices == NULL) {
> > +      return;
> >      }
> >
> > +    TempDevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN)
> > TempDevInfo + DevInfoLength);
> >      TmpDev = TmpDev->Next;
> >    }
> >
> >    Status = SaveLockBox (
> > -             &mOpalDeviceNvmeGuid,
> > -             DevInfoNvme,
> > -             DevInfoLengthNvme
> > +             &mOpalDeviceLockBoxGuid,
> > +             DevInfo,
> > +             TotalDevInfoLength
> >               );
> >    ASSERT_EFI_ERROR (Status);
> >
> >    Status = SetLockBoxAttributes (
> > -             &mOpalDeviceNvmeGuid,
> > +             &mOpalDeviceLockBoxGuid,
> >               LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> >               );
> >    ASSERT_EFI_ERROR (Status);
> >
> > -  ZeroMem (DevInfoNvme, DevInfoLengthNvme);
> > -  FreePool (DevInfoNvme);
> > +  S3InitDevicesLength = GetDevicePathSize (S3InitDevices);
> > +  if (S3InitDevicesExist) {
> > +    Status = UpdateLockBox (
> > +               &gS3StorageDeviceInitListGuid,
> > +               0,
> > +               S3InitDevices,
> > +               S3InitDevicesLength
> > +               );
> > +    ASSERT_EFI_ERROR (Status);
> > +  } else {
> > +    Status = SaveLockBox (
> > +               &gS3StorageDeviceInitListGuid,
> > +               S3InitDevices,
> > +               S3InitDevicesLength
> > +               );
> > +    ASSERT_EFI_ERROR (Status);
> > +
> > +    Status = SetLockBoxAttributes (
> > +               &gS3StorageDeviceInitListGuid,
> > +               LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> > +               );
> > +    ASSERT_EFI_ERROR (Status);
> > +  }
> > +
> > +  ZeroMem (DevInfo, TotalDevInfoLength);
> > +  FreePool (DevInfo);
> > +  ZeroMem (S3InitDevices, S3InitDevicesLength);
> > +  FreePool (S3InitDevices);
> >  }
> >
> >  /**
> > @@ -596,9 +448,6 @@ OpalEndOfDxeEventNotify (
> >    VOID                                    *Context
> >    )
> >  {
> > -  EFI_STATUS            Status;
> > -  EFI_PHYSICAL_ADDRESS  Address;
> > -  UINT64                Length;
> >    OPAL_DRIVER_DEVICE    *TmpDev;
> >
> >    DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
> > @@ -623,24 +472,7 @@ OpalEndOfDxeEventNotify (
> >      return;
> >    }
> >
> > -  //
> > -  // 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);
> > +  BuildOpalDeviceInfo ();
> >
> >    //
> >    // Zero passsword.
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> > deleted file mode 100644
> > index 01c316d597..0000000000
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> > +++ /dev/null
> > @@ -1,1823 +0,0 @@
> > -/** @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;
> > -}
> > -
> > -/**
> > -  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;
> > -}
> > diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> > b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> > index edb47ca8bc..4d78a6a4ed 100644
> > --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> > +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    Opal Password PEI driver which is used to unlock Opal Password for S3.
> >
> > -Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2016 - 2019, 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
> > @@ -14,249 +14,34 @@ 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)
> > +EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;
> >
> >  /**
> > -  Get IOMMU PPI.
> > +  Tell whether the input EDKII_PEI_STORAGE_SECURITY_CMD_PPI
> instance
> > has already
> > +  been handled by the Opal PEI driver.
> >
> > -  @return Pointer to IOMMU PPI.
> > +  @param[in] Private        Pointer to the Opal PEI driver private data.
> > +  @param[in] SscInstance    Pointer to the
> > EDKII_PEI_STORAGE_SECURITY_CMD_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.
> > +  @retval TRUE     The PPI instance has already been handled.
> > +  @retval FALSE    The PPI instance has not been handled before.
> >
> >  **/
> > -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
> > +BOOLEAN
> > +IsSscInstanceHandled (
> > +  IN OPAL_PEI_DRIVER_PRIVATE_DATA          *Private,
> > +  IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI    *SscInstance
> >    )
> >  {
> > -  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 );
> > -    }
> > +  UINTN    Index;
> >
> > -    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 );
> > +  for (Index = 0; Index < Private->SscPpiInstanceNum; Index++) {
> > +    if ((UINTN)SscInstance == Private->SscPpiInstances[Index]) {
> > +      return TRUE;
> >      }
> > -  } 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;
> > +  return FALSE;
> >  }
> >
> >  /**
> > @@ -351,14 +136,16 @@ SecurityReceiveData (
> >      return EFI_DEVICE_ERROR;
> >    }
> >
> > -  return PerformTrustedIo (
> > -                        PeiDev,
> > -                        OpalRecv,
> > -                        SecurityProtocolId,
> > -                        SecurityProtocolSpecificData,
> > -                        PayloadBufferSize,
> > -                        PayloadBuffer
> > -                        );
> > +  return PeiDev->SscPpi->ReceiveData (
> > +                           PeiDev->SscPpi,
> > +                           PeiDev->DeviceIndex,
> > +                           SSC_PPI_GENERIC_TIMEOUT,
> > +                           SecurityProtocolId,
> > +                           SecurityProtocolSpecificData,
> > +                           PayloadBufferSize,
> > +                           PayloadBuffer,
> > +                           PayloadTransferSize
> > +                           );
> >  }
> >
> >  /**
> > @@ -441,111 +228,15 @@ SecuritySendData (
> >      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
> > +  return PeiDev->SscPpi->SendData (
> > +                           PeiDev->SscPpi,
> > +                           PeiDev->DeviceIndex,
> > +                           SSC_PPI_GENERIC_TIMEOUT,
> > +                           SecurityProtocolId,
> > +                           SecurityProtocolSpecificData,
> > +                           PayloadBufferSize,
> > +                           PayloadBuffer
> > +                           );
> >  }
> >
> >  /**
> > @@ -651,272 +342,178 @@ UnlockOpalPassword (
> >  }
> >
> >  /**
> > -  Unlock ATA OPAL password for S3.
> > +  Unlock the OPAL NVM Express and ATA devices for S3.
> > +
> > +  @param[in] Private    Pointer to the Opal PEI driver private data.
> >
> >  **/
> >  VOID
> > -UnlockOpalPasswordAta (
> > -  VOID
> > +UnlockOpalPasswordDevices (
> > +  IN OPAL_PEI_DRIVER_PRIVATE_DATA    *Private
> >    )
> >  {
> > -  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__));
> > +  EFI_STATUS                            Status;
> > +  UINT8                                 *DevInfoBuffer;
> > +  UINT8                                 DummyData;
> > +  OPAL_DEVICE_LOCKBOX_DATA              *DevInfo;
> > +  UINTN                                 DevInfoLength;
> > +  EFI_PEI_PPI_DESCRIPTOR                *TempPpiDescriptor;
> > +  UINTN                                 SscPpiInstance;
> > +  EDKII_PEI_STORAGE_SECURITY_CMD_PPI    *SscPpi;
> > +  EFI_DEVICE_PATH_PROTOCOL              *SscDevicePath;
> > +  UINTN                                 SscDevicePathLength;
> > +  UINTN                                 SscDeviceNum;
> > +  UINTN                                 SscDeviceIndex;
> > +  OPAL_PEI_DEVICE                       OpalDev;
> >
> >    //
> > -  // Get ATA OPAL device info from LockBox.
> > +  // Get OPAL devices info from LockBox.
> >    //
> > -  DevInfo = (UINT8 *) &TempDevInfoAta;
> > -  DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);
> > -  Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo,
> > &DevInfoLengthAta);
> > +  DevInfoBuffer = &DummyData;
> > +  DevInfoLength = sizeof (DummyData);
> > +  Status = RestoreLockBox (&mOpalDeviceLockBoxGuid, DevInfoBuffer,
> > &DevInfoLength);
> >    if (Status == EFI_BUFFER_TOO_SMALL) {
> > -    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));
> > -    if (DevInfo != NULL) {
> > -      Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo,
> > &DevInfoLengthAta);
> > +    DevInfoBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLength));
> > +    if (DevInfoBuffer != NULL) {
> > +      Status = RestoreLockBox (&mOpalDeviceLockBoxGuid, DevInfoBuffer,
> > &DevInfoLength);
> >      }
> >    }
> > -  if (EFI_ERROR (Status) || (DevInfo == NULL)) {
> > +  if (DevInfoBuffer == NULL || DevInfoBuffer == &DummyData) {
> > +    return;
> > +  } else if (EFI_ERROR (Status)) {
> > +    FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));
> >      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));
> > -      } else {
> > -        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.
> > +  // Go through the Storage Security Command PPI instances within
> system.
> >    //
> > -  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);
> > +  for (SscPpiInstance = 0;
> > +       SscPpiInstance < OPAL_PEI_MAX_STORAGE_SECURITY_CMD_PPI;
> > +       SscPpiInstance++) {
> > +    Status = PeiServicesLocatePpi (
> > +               &gEdkiiPeiStorageSecurityCommandPpiGuid,
> > +               SscPpiInstance,
> > +               &TempPpiDescriptor,
> > +               (VOID **) &SscPpi
> > +               );
> > +    if (EFI_ERROR (Status)) {
> > +      break;
> >      }
> > -  }
> > -  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__));
> > +    //
> > +    // Check whether this PPI instance has been handled previously.
> > +    //
> > +    if (IsSscInstanceHandled (Private, SscPpi)) {
> > +      DEBUG ((
> > +        DEBUG_INFO, "%a: Ssc PPI instance (0x%p) already handled.\n",
> > +        __FUNCTION__, (UINTN)SscPpi
> > +        ));
> > +      continue;
> >      } 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);
> > +      DEBUG ((
> > +        DEBUG_INFO, "%a: New Ssc PPI instance (0x%p) found.\n",
> > +        __FUNCTION__, (UINTN)SscPpi
> > +        ));
> > +      Private->SscPpiInstances[Private->SscPpiInstanceNum] =
> (UINTN)SscPpi;
> > +      Private->SscPpiInstanceNum++;
> >      }
> >
> > -    ASSERT (RpBase != 0);
> > -    PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);
> > -    RpBase = SaveRestoreRootportConfSpace (
> > -                DevInfoNvme,
> > -                FALSE,  // restore
> > -                StorePcieConfDataList
> > -                );
> > -    PciWrite8  (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
> > -  }
> > +    //
> > +    // Go through all the devices managed by this PPI instance.
> > +    //
> > +    Status = SscPpi->GetNumberofDevices (SscPpi, &SscDeviceNum);
> > +    if (EFI_ERROR (Status)) {
> > +      continue;
> > +    }
> > +    for (SscDeviceIndex = 1; SscDeviceIndex <= SscDeviceNum;
> > SscDeviceIndex++) {
> > +      Status = SscPpi->GetDevicePath (
> > +                         SscPpi,
> > +                         SscDeviceIndex,
> > +                         &SscDevicePathLength,
> > +                         &SscDevicePath
> > +                         );
> > +      if (SscDevicePathLength <= sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
> > +        //
> > +        // Device path validity check.
> > +        //
> > +        continue;
> > +      }
> >
> > -  ZeroMem (DevInfo, DevInfoLengthNvme);
> > -  if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
> > -    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
> > +      //
> > +      // Search the device in the restored LockBox.
> > +      //
> > +      for (DevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) DevInfoBuffer;
> > +           (UINTN) DevInfo < ((UINTN) DevInfoBuffer + DevInfoLength);
> > +           DevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN) DevInfo +
> > DevInfo->Length)) {
> > +        //
> > +        // Find the matching device.
> > +        //
> > +        if ((DevInfo->DevicePathLength >= SscDevicePathLength) &&
> > +            (CompareMem (
> > +               DevInfo->DevicePath,
> > +               SscDevicePath,
> > +               SscDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) ==
> 0))
> > {
> > +          OpalDev.Signature        = OPAL_PEI_DEVICE_SIGNATURE;
> > +          OpalDev.Sscp.ReceiveData = SecurityReceiveData;
> > +          OpalDev.Sscp.SendData    = SecuritySendData;
> > +          OpalDev.Device           = DevInfo;
> > +          OpalDev.Context          = NULL;
> > +          OpalDev.SscPpi           = SscPpi;
> > +          OpalDev.DeviceIndex      = SscDeviceIndex;
> > +          UnlockOpalPassword (&OpalDev);
> > +          break;
> > +        }
> > +      }
> > +    }
> >    }
> >
> > -  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> > -}
> > -
> > -/**
> > -  Unlock OPAL password for S3.
> > +  ZeroMem (DevInfoBuffer, DevInfoLength);
> > +  FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));
> >
> > -**/
> > -VOID
> > -OpalPasswordS3 (
> > -  VOID
> > -  )
> > -{
> > -  UnlockOpalPasswordAta ();
> > -  UnlockOpalPasswordNvme ();
> >  }
> >
> >  /**
> > -  Entry point of the notification callback function itself within the PEIM.
> > +  One notified function at the installation of
> > EDKII_PEI_STORAGE_SECURITY_CMD_PPI.
> >    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.
> > +  @param[in] PeiServices         Indirect reference to the PEI Services Table.
> > +  @param[in] NotifyDescriptor    Address of the notification descriptor
> data
> > structure.
> > +  @param[in] 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
> > +OpalPasswordStorageSecurityPpiNotify (
> > +  IN EFI_PEI_SERVICES             **PeiServices,
> > +  IN EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDesc,
> > +  IN VOID                         *Ppi
> >    )
> >  {
> > -  EFI_STATUS                        Status;
> > -  EFI_BOOT_MODE                     BootMode;
> > +  OPAL_PEI_DRIVER_PRIVATE_DATA    *Private;
> >
> > -  Status = PeiServicesGetBootMode (&BootMode);
> > -  ASSERT_EFI_ERROR (Status);
> > -  if (BootMode != BOOT_ON_S3_RESUME) {
> > -    return EFI_UNSUPPORTED;
> > -  }
> > +  DEBUG ((DEBUG_INFO, "%a entered at S3 resume!\n",
> __FUNCTION__));
> >
> > -  DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
> > +  Private = OPAL_PEI_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDesc);
> > +  UnlockOpalPasswordDevices (Private);
> >
> > -  OpalPasswordS3 ();
> > -
> > -  DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));
> > +  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
> > +OPAL_PEI_DRIVER_PRIVATE_DATA mOpalPeiDriverPrivateTemplate = {
> > +  OPAL_PEI_DRIVER_SIGNATURE,    // Signature
> > +  {                             // SscPpiNotifyList
> > +    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > +    &gEdkiiPeiStorageSecurityCommandPpiGuid,
> > +    OpalPasswordStorageSecurityPpiNotify
> > +  },
> > +  0,                            // SscPpiInstanceNum
> > +  {0}                           // SscPpiInstances
> >  };
> >
> >  /**
> > @@ -935,10 +532,32 @@ OpalPasswordPeiInit (
> >    IN CONST EFI_PEI_SERVICES     **PeiServices
> >    )
> >  {
> > -  EFI_STATUS                    Status;
> > +  EFI_STATUS                      Status;
> > +  EFI_BOOT_MODE                   BootMode;
> > +  OPAL_PEI_DRIVER_PRIVATE_DATA    *Private;
> >
> > -  Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);
> > +  Status = PeiServicesGetBootMode (&BootMode);
> > +  if ((EFI_ERROR (Status)) || (BootMode != BOOT_ON_S3_RESUME)) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  DEBUG ((DEBUG_INFO, "%a: Enters in S3 path.\n", __FUNCTION__));
> > +
> > +  Private = (OPAL_PEI_DRIVER_PRIVATE_DATA *)
> > +              AllocateCopyPool (
> > +                sizeof (OPAL_PEI_DRIVER_PRIVATE_DATA),
> > +                &mOpalPeiDriverPrivateTemplate
> > +                );
> > +  if (Private == NULL) {
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: Failed to allocate memory for
> > OPAL_PEI_DRIVER_PRIVATE_DATA.\n",
> > +      __FUNCTION__
> > +      ));
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  Status = PeiServicesNotifyPpi (&Private->SscPpiNotifyList);
> >    ASSERT_EFI_ERROR (Status);
> >    return Status;
> >  }
> > -
> > --
> > 2.12.0.windows.1



  reply	other threads:[~2019-02-19  2:50 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-15  6:23 [PATCH v5 00/13] Split the S3 PEI phase HW init codes from Opal driver Hao Wu
2019-02-15  6:23 ` [PATCH v5 01/13] MdeModulePkg: Add definitions for ATA AHCI host controller PPI Hao Wu
2019-02-18  1:44   ` Dong, Eric
2019-02-15  6:23 ` [PATCH v5 02/13] MdeModulePkg: Add definitions for EDKII PEI ATA PassThru PPI Hao Wu
2019-02-18  1:44   ` Dong, Eric
2019-02-15  6:23 ` [PATCH v5 03/13] MdeModulePkg: Add definitions for Storage Security Command PPI Hao Wu
2019-02-18  1:45   ` Dong, Eric
2019-02-15  6:23 ` [PATCH v5 04/13] MdeModulePkg: Add GUID for LockBox to save storage dev to init in S3 Hao Wu
2019-02-18  1:45   ` Dong, Eric
2019-02-15  6:23 ` [PATCH v5 05/13] MdeModulePkg/NvmExpressPei: Avoid updating the module-level variable Hao Wu
2019-02-15  6:23 ` [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI Hao Wu
2019-02-18  2:58   ` Dong, Eric
2019-02-18  6:06     ` Wu, Hao A
2019-02-18  6:29       ` Dong, Eric
2019-02-20  8:33   ` Ni, Ray
2019-02-15  6:23 ` [PATCH v5 07/13] MdeModulePkg/NvmExpressPei: Consume S3StorageDeviceInitList LockBox Hao Wu
2019-02-18  3:01   ` Dong, Eric
2019-02-20  9:41   ` Ni, Ray
2019-02-15  6:23 ` [PATCH v5 08/13] MdeModulePkg/AhciPei: Add AHCI mode ATA device support in PEI Hao Wu
2019-02-20  9:51   ` Ni, Ray
2019-02-15  6:23 ` [PATCH v5 09/13] MdeModulePkg/SmmLockBoxLib: Use 'DEBUG_' prefix instead of 'EFI_D_' Hao Wu
2019-02-15  6:23 ` [PATCH v5 10/13] MdeModulePkg/SmmLockBox(PEI): Remove an ASSERT in RestoreLockBox() Hao Wu
2019-02-15  6:23 ` [PATCH v5 11/13] MdeModulePkg/SmmLockBoxLib: Support LockBox enlarge in UpdateLockBox() Hao Wu
2019-02-15  6:23 ` [PATCH v5 12/13] OvmfPkg/LockBoxLib: Update the comments for API UpdateLockBox() Hao Wu
2019-02-15  6:23 ` [PATCH v5 13/13] SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI Hao Wu
2019-02-18  6:20   ` Dong, Eric
2019-02-19  2:50     ` Wu, Hao A [this message]
2019-02-20 13:08   ` Ni, Ray
2019-02-15 13:23 ` [PATCH v5 00/13] Split the S3 PEI phase HW init codes from Opal driver Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=B80AF82E9BFB8E4FBD8C89DA810C6A093C897E4D@SHSMSX104.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox