public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "Ni, Ray" <ray.ni@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Wang, Jian J" <jian.j.wang@intel.com>,
	"Dong, Eric" <eric.dong@intel.com>
Subject: Re: [PATCH v2 06/12] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI
Date: Thu, 31 Jan 2019 05:40:55 +0000	[thread overview]
Message-ID: <B80AF82E9BFB8E4FBD8C89DA810C6A093C892DD2@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <734D49CCEBEEF84792F5B80ED585239D5BFFFFE7@SHSMSX104.ccr.corp.intel.com>

> -----Original Message-----
> From: Ni, Ray
> Sent: Thursday, January 31, 2019 11:35 AM
> To: Wu, Hao A; edk2-devel@lists.01.org
> Cc: Wang, Jian J; Dong, Eric
> Subject: RE: [PATCH v2 06/12] MdeModulePkg/NvmExpressPei: Add logic to
> produce SSC PPI
> 
> 
> 
> > -----Original Message-----
> > From: Wu, Hao A <hao.a.wu@intel.com>
> > Sent: Thursday, January 31, 2019 10:49 AM
> > To: edk2-devel@lists.01.org
> > Cc: Wu, Hao A <hao.a.wu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>;
> > Ni, Ray <ray.ni@intel.com>; Dong, Eric <eric.dong@intel.com>
> > Subject: [PATCH v2 06/12] MdeModulePkg/NvmExpressPei: Add logic to
> > produce SSC PPI
> >
> > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1409
> >
> > For the NvmExpressPei driver, this commit will add codes to produce the
> > Storage Security Command PPI if the underlying NVM Express controller
> > supports the Security Send and Security Receive commands.
> >
> > Cc: Jian J Wang <jian.j.wang@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>
> > ---
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf              |  10 +-
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h                |  81
> > +++-
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h             |  20 +-
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.h
> > | 247 ++++++++++++
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c                   | 317
> > +++++++++++++++
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c                | 143
> > +++++--
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c             |  32 +-
> >  MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.c
> > | 423 ++++++++++++++++++++
> >  8 files changed, 1184 insertions(+), 89 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > index 9591572fec..0666e5892b 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > @@ -2,7 +2,7 @@
> >  #  The NvmExpressPei driver is used to manage non-volatile memory
> > subsystem
> >  #  which follows NVM Express specification at PEI phase.
> >  #
> > -#  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
> > @@ -30,6 +30,7 @@
> >  #
> >
> >  [Sources]
> > +  DevicePath.c
> >    DmaMem.c
> >    NvmExpressPei.c
> >    NvmExpressPei.h
> > @@ -39,6 +40,8 @@
> >    NvmExpressPeiHci.h
> >    NvmExpressPeiPassThru.c
> >    NvmExpressPeiPassThru.h
> > +  NvmExpressPeiStorageSecurity.c
> > +  NvmExpressPeiStorageSecurity.h
> >
> >  [Packages]
> >    MdePkg/MdePkg.dec
> > @@ -54,11 +57,12 @@
> >    PeimEntryPoint
> >
> >  [Ppis]
> > -  gEfiPeiVirtualBlockIoPpiGuid                   ## PRODUCES
> > -  gEfiPeiVirtualBlockIo2PpiGuid                  ## PRODUCES
> >    gEdkiiPeiNvmExpressHostControllerPpiGuid       ## CONSUMES
> >    gEdkiiIoMmuPpiGuid                             ## CONSUMES
> >    gEfiEndOfPeiSignalPpiGuid                      ## CONSUMES
> > +  gEfiPeiVirtualBlockIoPpiGuid                   ## SOMETIMES_PRODUCES
> > +  gEfiPeiVirtualBlockIo2PpiGuid                  ## SOMETIMES_PRODUCES
> > +  gEdkiiPeiStorageSecurityCommandPpiGuid         ##
> > SOMETIMES_PRODUCES
> >
> >  [Depex]
> >    gEfiPeiMemoryDiscoveredPpiGuid AND
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > index 0135eca6f0..7047c4f3ff 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > @@ -25,6 +25,7 @@
> >  #include <Ppi/NvmExpressHostController.h>
> >  #include <Ppi/BlockIo.h>
> >  #include <Ppi/BlockIo2.h>
> > +#include <Ppi/StorageSecurityCommand.h>
> >  #include <Ppi/IoMmu.h>
> >  #include <Ppi/EndOfPeiPhase.h>
> >
> > @@ -44,6 +45,7 @@ typedef struct
> > _PEI_NVME_CONTROLLER_PRIVATE_DATA
> > PEI_NVME_CONTROLLER_PRIVATE_DA
> >  #include "NvmExpressPeiHci.h"
> >  #include "NvmExpressPeiPassThru.h"
> >  #include "NvmExpressPeiBlockIo.h"
> > +#include "NvmExpressPeiStorageSecurity.h"
> >
> >  //
> >  // NVME PEI driver implementation related definitions
> > @@ -90,10 +92,15 @@ struct _PEI_NVME_NAMESPACE_INFO {
> >  struct _PEI_NVME_CONTROLLER_PRIVATE_DATA {
> >    UINT32                                    Signature;
> >    UINTN                                     MmioBase;
> > +  UINTN                                     DevicePathLength;
> > +  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;
> > +
> >    EFI_PEI_RECOVERY_BLOCK_IO_PPI             BlkIoPpi;
> >    EFI_PEI_RECOVERY_BLOCK_IO2_PPI            BlkIo2Ppi;
> > +  EDKII_PEI_STORAGE_SECURITY_CMD_PPI        StorageSecurityPpi;
> >    EFI_PEI_PPI_DESCRIPTOR                    BlkIoPpiList;
> >    EFI_PEI_PPI_DESCRIPTOR                    BlkIo2PpiList;
> > +  EFI_PEI_PPI_DESCRIPTOR                    StorageSecurityPpiList;
> >    EFI_PEI_NOTIFY_DESCRIPTOR                 EndOfPeiNotifyList;
> >
> >    //
> > @@ -139,11 +146,13 @@ struct _PEI_NVME_CONTROLLER_PRIVATE_DATA {
> >    PEI_NVME_NAMESPACE_INFO                   *NamespaceInfo;
> >  };
> >
> > -#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO(a)     \
> > +#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO(a)
> > \
> >    CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, BlkIoPpi,
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)
> > -#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2(a)    \
> > +#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2(a)
> > \
> >    CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, BlkIo2Ppi,
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)
> > -#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a)    \
> > +#define
> > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY(a)
> > \
> > +  CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, StorageSecurityPpi,
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)
> > +#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a)
> > \
> >    CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, EndOfPeiNotifyList,
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)
> >
> >
> > @@ -257,4 +266,70 @@ NvmePeimEndOfPei (
> >    IN VOID                       *Ppi
> >    );
> >
> > +/**
> > +  Creates a copy of the current device path instance and returns a pointer to
> > the
> > +  next device path instance.
> > +
> > +  @param  DevicePath    On input, this holds the pointer to the current
> > +                        device path instance. On output, this holds
> > +                        the pointer to the next device path instance
> > +                        or NULL if there are no more device path
> > +                        instances in the device path pointer to a
> > +                        device path data structure.
> > +  @param  Size          On output, this holds the size of the device
> > +                        path instance, in bytes or zero, if DevicePath
> > +                        is NULL.
> > +
> > +  @return A pointer to the current device path instance.
> > +
> > +**/
> > +EFI_DEVICE_PATH_PROTOCOL *
> > +GetNextDevicePathInstance (
> > +  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
> > +  OUT UINTN                          *Size
> > +  );
> > +
> > +/**
> > +  Check the validity of the device path of a NVM Express host controller.
> > +
> > +  @param[in] DevicePath          A pointer to the
> > EFI_DEVICE_PATH_PROTOCOL
> > +                                 structure.
> > +  @param[in] DevicePathLength    The length of the device path.
> > +
> > +  @retval EFI_SUCCESS              The device path is valid.
> > +  @retval EFI_INVALID_PARAMETER    The device path is invalid.
> > +
> > +**/
> > +EFI_STATUS
> > +NvmeCheckHcDevicePath (
> > +  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
> > +  IN UINTN                       DevicePathLength
> > +  );
> > +
> > +/**
> > +  Build the device path for an Nvm Express device with given namespace
> > identifier
> > +  and namespace extended unique identifier.
> > +
> > +  @param[in]  Private              A pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA
> > +                                   data structure.
> > +  @param[in]  NamespaceId          The given namespace identifier.
> > +  @param[in]  NamespaceUuid        The given namespace extended unique
> > identifier.
> > +  @param[out] DevicePathLength     The length of the device path in bytes
> > specified
> > +                                   by DevicePath.
> > +  @param[out] DevicePath           The device path of Nvm Express device.
> > +
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +  @retval EFI_INVALID_PARAMETER    The parameters are invalid.
> > +  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of
> > resources.
> > +
> > +**/
> > +EFI_STATUS
> > +NvmeBuildDevicePath (
> > +  IN  PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private,
> > +  IN  UINT32                              NamespaceId,
> > +  IN  UINT64                              NamespaceUuid,
> > +  OUT UINTN                               *DevicePathLength,
> > +  OUT EFI_DEVICE_PATH_PROTOCOL            **DevicePath
> > +  );
> > +
> >  #endif
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h
> > index ff334e3e17..ad1d5d0d8a 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h
> > @@ -2,7 +2,7 @@
> >    The NvmExpressPei driver is used to manage non-volatile memory
> > subsystem
> >    which follows NVM Express specification at PEI phase.
> >
> > -  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
> > @@ -107,20 +107,6 @@ NvmeBaseMemPageOffset (
> >    );
> >
> >  /**
> > -  Disable the Nvm Express controller.
> > -
> > -  @param[in] Private     The pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
> > -
> > -  @return EFI_SUCCESS    Successfully disable the controller.
> > -  @return others         Fail to disable the controller.
> > -
> > -**/
> > -EFI_STATUS
> > -NvmeDisableController (
> > -  IN PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private
> > -  );
> > -
> > -/**
> >    Initialize the Nvm Express controller.
> >
> >    @param[in] Private     The pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
> > @@ -153,13 +139,13 @@ NvmeIdentifyNamespace (
> >    );
> >
> >  /**
> > -  Free the resources allocated by an NVME controller.
> > +  Free the DMA resources allocated by an NVME controller.
> >
> >    @param[in] Private     The pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
> >
> >  **/
> >  VOID
> > -NvmeFreeControllerResource (
> > +NvmeFreeDmaResource (
> >    IN PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private
> >    );
> >
> > diff --git
> > a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.
> > h
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.
> > h
> > new file mode 100644
> > index 0000000000..8ccfb425e7
> > --- /dev/null
> > +++
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.
> > h
> > @@ -0,0 +1,247 @@
> > +/** @file
> > +  The NvmExpressPei driver is used to manage non-volatile memory
> > subsystem
> > +  which follows NVM Express specification at PEI phase.
> > +
> > +  Copyright (c) 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
> > +  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 _NVM_EXPRESS_PEI_STORAGE_SECURITY_H_
> > +#define _NVM_EXPRESS_PEI_STORAGE_SECURITY_H_
> > +
> > +/**
> > +  Gets the count of storage security devices that one specific driver detects.
> > +
> > +  @param[in]  This               The PPI instance pointer.
> > +  @param[out] NumberofDevices    The number of storage security devices
> > discovered.
> > +
> > +  @retval EFI_SUCCESS              The operation performed successfully.
> > +  @retval EFI_INVALID_PARAMETER    The parameters are invalid.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecurityGetDeviceNo (
> > +  IN  EDKII_PEI_STORAGE_SECURITY_CMD_PPI    *This,
> > +  OUT UINTN                                 *NumberofDevices
> > +  );
> > +
> > +/**
> > +  Gets the device path of a specific storage security device.
> > +
> > +  @param[in]  This                 The PPI instance pointer.
> > +  @param[in]  DeviceIndex          Specifies the storage security device to
> > which
> > +                                   the function wants to talk. Because the driver
> > +                                   that implements Storage Security Command PPIs
> > +                                   will manage multiple storage devices, the PPIs
> > +                                   that want to talk to a single device must specify
> > +                                   the device index that was assigned during the
> > +                                   enumeration process. This index is a number from
> > +                                   one to NumberofDevices.
> > +  @param[out] DevicePathLength     The length of the device path in bytes
> > specified
> > +                                   by DevicePath.
> > +  @param[out] DevicePath           The device path of storage security device.
> > +                                   This field re-uses EFI Device Path Protocol as
> > +                                   defined by Section 10.2 EFI Device Path Protocol
> > +                                   of UEFI 2.7 Specification.
> > +
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +  @retval EFI_INVALID_PARAMETER    DevicePathLength or DevicePath is
> > NULL.
> > +  @retval EFI_NOT_FOUND            The specified storage security device not
> > found.
> > +  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of
> > resources.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecurityGetDevicePath (
> > +  IN  EDKII_PEI_STORAGE_SECURITY_CMD_PPI  *This,
> > +  IN  UINTN                               DeviceIndex,
> > +  OUT UINTN                               *DevicePathLength,
> > +  OUT EFI_DEVICE_PATH_PROTOCOL            **DevicePath
> > +  );
> > +
> > +/**
> > +  Send a security protocol command to a device that receives data and/or
> > the result
> > +  of one or more commands sent by SendData.
> > +
> > +  The ReceiveData function sends a security protocol command to the given
> > DeviceIndex.
> > +  The security protocol command sent is defined by SecurityProtocolId and
> > contains
> > +  the security protocol specific data SecurityProtocolSpecificData. The
> > function
> > +  returns the data from the security protocol command in PayloadBuffer.
> > +
> > +  For devices supporting the SCSI command set, the security protocol
> > command is sent
> > +  using the SECURITY PROTOCOL IN command defined in SPC-4.
> > +
> > +  For devices supporting the ATA command set, the security protocol
> > command is sent
> > +  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if
> > PayloadBufferSize
> > +  is non-zero.
> > +
> > +  If the PayloadBufferSize is zero, the security protocol command is sent
> > using the
> > +  Trusted Non-Data command defined in ATA8-ACS.
> > +
> > +  If PayloadBufferSize is too small to store the available data from the
> > security
> > +  protocol command, the function shall copy PayloadBufferSize bytes into
> > the
> > +  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
> > +
> > +  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is
> > non-zero,
> > +  the function shall return EFI_INVALID_PARAMETER.
> > +
> > +  If the given DeviceIndex does not support security protocol commands,
> > the function
> > +  shall return EFI_UNSUPPORTED.
> > +
> > +  If the security protocol fails to complete within the Timeout period, the
> > function
> > +  shall return EFI_TIMEOUT.
> > +
> > +  If the security protocol command completes without an error, the function
> > shall
> > +  return EFI_SUCCESS. If the security protocol command completes with an
> > error, the
> > +  function shall return EFI_DEVICE_ERROR.
> > +
> > +  @param[in]  This             The PPI instance pointer.
> > +  @param[in]  DeviceIndex      Specifies the storage security device to which
> > the
> > +                               function wants to talk. Because the driver that
> > +                               implements Storage Security Command PPIs will manage
> > +                               multiple storage devices, the PPIs that want to talk
> > +                               to a single device must specify the device index
> > +                               that was assigned during the enumeration process.
> > +                               This index is a number from one to NumberofDevices.
> > +  @param[in]  Timeout          The timeout, in 100ns units, to use for the
> > execution
> > +                               of the security protocol command. A Timeout value
> > +                               of 0 means that this function will wait indefinitely
> > +                               for the security protocol command to execute. If
> > +                               Timeout is greater than zero, then this function
> > +                               will return EFI_TIMEOUT if the time required to
> > +                               execute the receive data command is greater than
> > +                               Timeout.
> > +  @param[in]  SecurityProtocolId
> > +                               The value of the "Security Protocol" parameter of
> > +                               the security protocol command to be sent.
> > +  @param[in]  SecurityProtocolSpecificData
> > +                               The value of the "Security Protocol Specific"
> > +                               parameter of the security protocol command to be
> > +                               sent.
> > +  @param[in]  PayloadBufferSize
> > +                               Size in bytes of the payload data buffer.
> > +  @param[out] PayloadBuffer    A pointer to a destination buffer to store
> > the
> > +                               security protocol command specific payload data
> > +                               for the security protocol command. The caller is
> > +                               responsible for having either implicit or explicit
> > +                               ownership of the buffer.
> > +  @param[out] PayloadTransferSize
> > +                               A pointer to a buffer to store the size in bytes
> > +                               of the data written to the payload data buffer.
> > +
> > +  @retval EFI_SUCCESS                  The security protocol command completed
> > +                                       successfully.
> > +  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too
> > small to
> > +                                       store the available data from the device.
> > +                                       The PayloadBuffer contains the truncated
> > +                                       data.
> > +  @retval EFI_UNSUPPORTED              The given DeviceIndex does not
> > support
> > +                                       security protocol commands.
> > +  @retval EFI_DEVICE_ERROR             The security protocol command
> > completed
> > +                                       with an error.
> > +  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or
> > PayloadTransferSize
> > +                                       is NULL and PayloadBufferSize is non-zero.
> > +  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the
> > +                                       security protocol command to execute.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecurityReceiveData (
> > +  IN  EDKII_PEI_STORAGE_SECURITY_CMD_PPI  *This,
> > +  IN  UINTN                               DeviceIndex,
> > +  IN  UINT64                              Timeout,
> > +  IN  UINT8                               SecurityProtocolId,
> > +  IN  UINT16                              SecurityProtocolSpecificData,
> > +  IN  UINTN                               PayloadBufferSize,
> > +  OUT VOID                                *PayloadBuffer,
> > +  OUT UINTN                               *PayloadTransferSize
> > +  );
> > +
> > +/**
> > +  Send a security protocol command to a device.
> > +
> > +  The SendData function sends a security protocol command containing the
> > payload
> > +  PayloadBuffer to the given DeviceIndex. The security protocol command
> > sent is
> > +  defined by SecurityProtocolId and contains the security protocol specific
> > data
> > +  SecurityProtocolSpecificData. If the underlying protocol command requires
> > a
> > +  specific padding for the command payload, the SendData function shall
> > add padding
> > +  bytes to the command payload to satisfy the padding requirements.
> > +
> > +  For devices supporting the SCSI command set, the security protocol
> > command is
> > +  sent using the SECURITY PROTOCOL OUT command defined in SPC-4.
> > +
> > +  For devices supporting the ATA command set, the security protocol
> > command is
> > +  sent using one of the TRUSTED SEND commands defined in ATA8-ACS if
> > PayloadBufferSize
> > +  is non-zero. If the PayloadBufferSize is zero, the security protocol
> > command
> > +  is sent using the Trusted Non-Data command defined in ATA8-ACS.
> > +
> > +  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function
> > shall
> > +  return EFI_INVALID_PARAMETER.
> > +
> > +  If the given DeviceIndex does not support security protocol commands,
> > the function
> > +  shall return EFI_UNSUPPORTED.
> > +
> > +  If the security protocol fails to complete within the Timeout period, the
> > function
> > +  shall return EFI_TIMEOUT.
> > +
> > +  If the security protocol command completes without an error, the function
> > shall
> > +  return EFI_SUCCESS. If the security protocol command completes with an
> > error,
> > +  the functio shall return EFI_DEVICE_ERROR.
> > +
> > +  @param[in] This              The PPI instance pointer.
> > +  @param[in] DeviceIndex       The ID of the device.
> > +  @param[in] Timeout           The timeout, in 100ns units, to use for the
> > execution
> > +                               of the security protocol command. A Timeout value
> > +                               of 0 means that this function will wait indefinitely
> > +                               for the security protocol command to execute. If
> > +                               Timeout is greater than zero, then this function
> > +                               will return EFI_TIMEOUT if the time required to
> > +                               execute the receive data command is greater than
> > +                               Timeout.
> > +  @param[in] SecurityProtocolId
> > +                               The value of the "Security Protocol" parameter of
> > +                               the security protocol command to be sent.
> > +  @param[in] SecurityProtocolSpecificData
> > +                               The value of the "Security Protocol Specific"
> > +                               parameter of the security protocol command to be
> > +                               sent.
> > +  @param[in] PayloadBufferSize Size in bytes of the payload data buffer.
> > +  @param[in] PayloadBuffer     A pointer to a destination buffer to store the
> > +                               security protocol command specific payload data
> > +                               for the security protocol command.
> > +
> > +  @retval EFI_SUCCESS              The security protocol command completed
> > successfully.
> > +  @retval EFI_UNSUPPORTED          The given DeviceIndex does not support
> > security
> > +                                   protocol commands.
> > +  @retval EFI_DEVICE_ERROR         The security protocol command
> > completed with
> > +                                   an error.
> > +  @retval EFI_INVALID_PARAMETER    The PayloadBuffer is NULL and
> > PayloadBufferSize
> > +                                   is non-zero.
> > +  @retval EFI_TIMEOUT              A timeout occurred while waiting for the
> > security
> > +                                   protocol command to execute.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecuritySendData (
> > +  IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI  *This,
> > +  IN UINTN                               DeviceIndex,
> > +  IN UINT64                              Timeout,
> > +  IN UINT8                               SecurityProtocolId,
> > +  IN UINT16                              SecurityProtocolSpecificData,
> > +  IN UINTN                               PayloadBufferSize,
> > +  IN VOID                                *PayloadBuffer
> > +  );
> > +
> > +#endif
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > new file mode 100644
> > index 0000000000..56004400bc
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > @@ -0,0 +1,317 @@
> > +/** @file
> > +  The device path help function.
> > +
> > +  Copyright (c) 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
> > +  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 "NvmExpressPei.h"
> > +
> > +//
> > +// Template for an Nvm Express Device Path node
> > +//
> > +NVME_NAMESPACE_DEVICE_PATH  mNvmeDevicePathNodeTemplate = {
> > +  {        // Header
> > +    MESSAGING_DEVICE_PATH,
> > +    MSG_NVME_NAMESPACE_DP,
> > +    {
> > +      (UINT8) (sizeof (NVME_NAMESPACE_DEVICE_PATH)),
> > +      (UINT8) ((sizeof (NVME_NAMESPACE_DEVICE_PATH)) >> 8)
> > +    }
> > +  },
> > +  0x0,     // NamespaceId
> > +  0x0      // NamespaceUuid
> > +};
> > +
> > +//
> > +// Template for an End of entire Device Path node
> > +//
> > +EFI_DEVICE_PATH_PROTOCOL  mNvmeEndDevicePathNodeTemplate = {
> > +  END_DEVICE_PATH_TYPE,
> > +  END_ENTIRE_DEVICE_PATH_SUBTYPE,
> > +  {
> > +    (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),
> > +    (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)
> > +  }
> > +};
> > +
> > +/**
> > +  Returns the 16-bit Length field of a device path node.
> > +
> > +  Returns the 16-bit Length field of the device path node specified by Node.
> > +  Node is not required to be aligned on a 16-bit boundary, so it is
> > recommended
> > +  that a function such as ReadUnaligned16() be used to extract the contents
> > of
> > +  the Length field.
> > +
> > +  If Node is NULL, then ASSERT().
> > +
> > +  @param  Node      A pointer to a device path node data structure.
> > +
> > +  @return The 16-bit Length field of the device path node specified by Node.
> > +
> > +**/
> > +UINTN
> > +DevicePathNodeLength (
> > +  IN CONST VOID  *Node
> > +  )
> > +{
> > +  ASSERT (Node != NULL);
> > +  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL
> > *)(Node))->Length[0]);
> > +}
> > +
> > +/**
> > +  Returns a pointer to the next node in a device path.
> > +
> > +  If Node is NULL, then ASSERT().
> > +
> > +  @param  Node    A pointer to a device path node data structure.
> > +
> > +  @return a pointer to the device path node that follows the device path
> > node
> > +  specified by Node.
> > +
> > +**/
> > +EFI_DEVICE_PATH_PROTOCOL *
> > +NextDevicePathNode (
> > +  IN CONST VOID  *Node
> > +  )
> > +{
> > +  ASSERT (Node != NULL);
> > +  return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) +
> > DevicePathNodeLength(Node));
> > +}
> > +
> > +/**
> > +  Returns the size of a device path in bytes.
> > +
> > +  This function returns the size, in bytes, of the device path data structure
> > +  specified by DevicePath including the end of device path node.
> > +  If DevicePath is NULL or invalid, then 0 is returned.
> > +
> > +  @param  DevicePath  A pointer to a device path data structure.
> > +
> > +  @retval 0           If DevicePath is NULL or invalid.
> > +  @retval Others      The size of a device path in bytes.
> > +
> > +**/
> > +UINTN
> > +GetDevicePathSize (
> > +  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
> > +  )
> > +{
> > +  CONST EFI_DEVICE_PATH_PROTOCOL  *Start;
> > +
> > +  if (DevicePath == NULL) {
> > +    return 0;
> > +  }
> > +
> > +  //
> > +  // Search for the end of the device path structure
> > +  //
> > +  Start = DevicePath;
> > +  while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&
> > +           DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) {
> > +    DevicePath = NextDevicePathNode (DevicePath);
> > +  }
> > +
> > +  //
> > +  // Compute the size and add back in the size of the end device path
> > structure
> > +  //
> > +  return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength
> > (DevicePath);
> > +}
> > +
> > +/**
> > +  Creates a copy of the current device path instance and returns a pointer to
> > the
> > +  next device path instance.
> > +
> > +  @param  DevicePath    On input, this holds the pointer to the current
> > +                        device path instance. On output, this holds
> > +                        the pointer to the next device path instance
> > +                        or NULL if there are no more device path
> > +                        instances in the device path pointer to a
> > +                        device path data structure.
> > +  @param  Size          On output, this holds the size of the device
> > +                        path instance, in bytes or zero, if DevicePath
> > +                        is NULL.
> > +
> > +  @return A pointer to the current device path instance.
> > +
> > +**/
> > +EFI_DEVICE_PATH_PROTOCOL *
> > +GetNextDevicePathInstance (
> > +  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
> > +  OUT UINTN                          *Size
> > +  )
> > +{
> > +  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
> > +  EFI_DEVICE_PATH_PROTOCOL  *ReturnValue;
> > +  UINTN                     DevicePathSize;
> > +  UINT8                     Temp;
> > +
> > +  ASSERT (Size != NULL);
> > +
> > +  if (DevicePath == NULL || *DevicePath == NULL) {
> > +    *Size = 0;
> > +    return NULL;
> > +  }
> > +
> > +  //
> > +  // Find the end of the device path instance
> > +  //
> > +  DevPath = *DevicePath;
> > +  while (DevPath->Type != END_DEVICE_PATH_TYPE) {
> > +    DevPath = NextDevicePathNode (DevPath);
> > +  }
> > +
> > +  //
> > +  // Compute the size of the device path instance
> > +  //
> > +  *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof
> > (EFI_DEVICE_PATH_PROTOCOL);
> > +
> > +  //
> > +  // Make a copy and return the device path instance
> > +  //
> > +  Temp              = DevPath->SubType;
> > +  DevPath->SubType  = END_ENTIRE_DEVICE_PATH_SUBTYPE;
> > +  DevicePathSize    = GetDevicePathSize (*DevicePath);
> > +  ReturnValue       = (DevicePathSize == 0) ? NULL : AllocateCopyPool
> > (DevicePathSize, *DevicePath);
> > +  DevPath->SubType  = Temp;
> > +
> > +  //
> > +  // If DevPath is the end of an entire device path, then another instance
> > +  // does not follow, so *DevicePath is set to NULL.
> > +  //
> > +  if (DevPath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
> > +    *DevicePath = NULL;
> > +  } else {
> > +    *DevicePath = NextDevicePathNode (DevPath);
> > +  }
> > +
> > +  return ReturnValue;
> > +}
> 
> 1. Why duplicate the UefiDevicePathLib implementation here?

I found that the DevicePathLib instances will consume the Boot Services
Table (e.g. try to get the 'Handle' of a device path). It is not available
in the PEI phase.

Also, there are some minor differences between the driver-internal
implementation and the library implementation. Within the driver, some
memory allocation operations are optimized away according to no actual
needs.

> 
> > +
> > +/**
> > +  Check the validity of the device path of a NVM Express host controller.
> > +
> > +  @param[in] DevicePath          A pointer to the
> > EFI_DEVICE_PATH_PROTOCOL
> > +                                 structure.
> > +  @param[in] DevicePathLength    The length of the device path.
> > +
> > +  @retval EFI_SUCCESS              The device path is valid.
> > +  @retval EFI_INVALID_PARAMETER    The device path is invalid.
> > +
> > +**/
> > +EFI_STATUS
> > +NvmeCheckHcDevicePath (
> > +  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
> > +  IN UINTN                       DevicePathLength
> > +  )
> > +{
> > +  EFI_DEVICE_PATH_PROTOCOL    *Start;
> > +  UINTN                       Size;
> > +
> > +  if (DevicePath == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Start = DevicePath;
> > +  while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&
> > +           DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) {
> > +    DevicePath = NextDevicePathNode (DevicePath);
> > +  }
> > +
> > +  //
> > +  // Check if the device path and its size match each other.
> > +  //
> > +  Size = ((UINTN) DevicePath - (UINTN) Start) + sizeof
> > (EFI_DEVICE_PATH_PROTOCOL);
> > +  if (Size != DevicePathLength) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> 2. Can we make use of UefiDevicePathLib API (IsDevicePathValide +
> GetDevicePathSize)
> to do the HC device path check?

I will refine the checks here to further resemble the checks in
IsDevicePathValid().

Best Regards,
Hao Wu

> 
> > +
> > +/**
> > +  Build the device path for an Nvm Express device with given namespace
> > identifier
> > +  and namespace extended unique identifier.
> > +
> > +  @param[in]  Private              A pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA
> > +                                   data structure.
> > +  @param[in]  NamespaceId          The given namespace identifier.
> > +  @param[in]  NamespaceUuid        The given namespace extended unique
> > identifier.
> > +  @param[out] DevicePathLength     The length of the device path in bytes
> > specified
> > +                                   by DevicePath.
> > +  @param[out] DevicePath           The device path of Nvm Express device.
> > +
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +  @retval EFI_INVALID_PARAMETER    The parameters are invalid.
> > +  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of
> > resources.
> > +
> > +**/
> > +EFI_STATUS
> > +NvmeBuildDevicePath (
> > +  IN  PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private,
> > +  IN  UINT32                              NamespaceId,
> > +  IN  UINT64                              NamespaceUuid,
> > +  OUT UINTN                               *DevicePathLength,
> > +  OUT EFI_DEVICE_PATH_PROTOCOL            **DevicePath
> > +  )
> > +{
> > +  EFI_DEVICE_PATH_PROTOCOL      *DevicePathWalker;
> > +  NVME_NAMESPACE_DEVICE_PATH    *NvmeDeviceNode;
> > +
> > +  if (DevicePathLength == NULL || DevicePath == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  *DevicePathLength = Private->DevicePathLength + sizeof
> > (NVME_NAMESPACE_DEVICE_PATH);
> > +  *DevicePath       = AllocatePool (*DevicePathLength);
> > +  if (*DevicePath == NULL) {
> > +    *DevicePathLength = 0;
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  //
> > +  // Construct the host controller part device nodes
> > +  //
> > +  DevicePathWalker = *DevicePath;
> > +  CopyMem (
> > +    DevicePathWalker,
> > +    Private->DevicePath,
> > +    Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
> > +    );
> > +
> > +  //
> > +  // Construct the Nvm Express device node
> > +  //
> > +  DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8
> > *)DevicePathWalker +
> > +                     (Private->DevicePathLength - sizeof
> > (EFI_DEVICE_PATH_PROTOCOL)));
> > +  CopyMem (
> > +    DevicePathWalker,
> > +    &mNvmeDevicePathNodeTemplate,
> > +    sizeof (mNvmeDevicePathNodeTemplate)
> > +    );
> > +  NvmeDeviceNode                = (NVME_NAMESPACE_DEVICE_PATH
> > *)DevicePathWalker;
> > +  NvmeDeviceNode->NamespaceId   = NamespaceId;
> > +  NvmeDeviceNode->NamespaceUuid = NamespaceUuid;
> > +
> > +  //
> > +  // Construct the end device node
> > +  //
> > +  DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8
> > *)DevicePathWalker +
> > +                     sizeof (NVME_NAMESPACE_DEVICE_PATH));
> > +  CopyMem (
> > +    DevicePathWalker,
> > +    &mNvmeEndDevicePathNodeTemplate,
> > +    sizeof (mNvmeEndDevicePathNodeTemplate)
> > +    );
> > +
> > +  return EFI_SUCCESS;
> > +}
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > index 2fe73e942c..96622e6fd5 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > @@ -24,11 +24,17 @@ EFI_PEI_PPI_DESCRIPTOR
> > mNvmeBlkIoPpiListTemplate = {
> >  };
> >
> >  EFI_PEI_PPI_DESCRIPTOR  mNvmeBlkIo2PpiListTemplate = {
> > -  EFI_PEI_PPI_DESCRIPTOR_PPI |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
> > +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> >    &gEfiPeiVirtualBlockIo2PpiGuid,
> >    NULL
> >  };
> >
> > +EFI_PEI_PPI_DESCRIPTOR  mNvmeStorageSecurityPpiListTemplate = {
> > +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > +  &gEdkiiPeiStorageSecurityCommandPpiGuid,
> > +  NULL
> > +};
> > +
> >  EFI_PEI_NOTIFY_DESCRIPTOR  mNvmeEndOfPeiNotifyListTemplate = {
> >    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> >    &gEfiEndOfPeiSignalPpiGuid,
> > @@ -185,8 +191,7 @@ NvmePeimEndOfPei (
> >    PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private;
> >
> >    Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY
> > (NotifyDescriptor);
> > -  NvmeDisableController (Private);
> > -  NvmeFreeControllerResource (Private);
> > +  NvmeFreeDmaResource (Private);
> >
> >    return EFI_SUCCESS;
> >  }
> > @@ -211,9 +216,13 @@ NvmExpressPeimEntry (
> >    EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI    *NvmeHcPpi;
> >    UINT8                                    Controller;
> >    UINTN                                    MmioBase;
> > +  UINTN                                    DevicePathLength;
> > +  EFI_DEVICE_PATH_PROTOCOL                 *DevicePath;
> >    PEI_NVME_CONTROLLER_PRIVATE_DATA         *Private;
> >    EFI_PHYSICAL_ADDRESS                     DeviceAddress;
> >
> > +  DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> > +
> >    //
> >    // Locate the NVME host controller PPI
> >    //
> > @@ -243,16 +252,41 @@ NvmExpressPeimEntry (
> >        break;
> >      }
> >
> > +    Status = NvmeHcPpi->GetNvmeHcDevicePath (
> > +                          NvmeHcPpi,
> > +                          Controller,
> > +                          &DevicePathLength,
> > +                          &DevicePath
> > +                          );
> > +    if (EFI_ERROR (Status)) {
> > +      DEBUG ((
> > +        DEBUG_ERROR, "%a: Fail to allocate get the device path for
> > Controller %d.\n",
> > +        __FUNCTION__, Controller
> > +        ));
> > +      return Status;
> > +    }
> > +
> > +    //
> > +    // Check validity of the device path of the NVM Express controller.
> > +    //
> > +    Status = NvmeCheckHcDevicePath (DevicePath, DevicePathLength);
> > +    if (EFI_ERROR (Status)) {
> > +      DEBUG ((
> > +        DEBUG_ERROR, "%a: The device path is invalid for Controller %d.\n",
> > +        __FUNCTION__, Controller
> > +        ));
> > +      Controller++;
> > +      continue;
> > +    }
> > +
> >      //
> >      // Memory allocation for controller private data
> >      //
> >      Private = AllocateZeroPool (sizeof
> > (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> >      if (Private == NULL) {
> >        DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: Fail to allocate private data for Controller %d.\n",
> > -        __FUNCTION__,
> > -        Controller
> > +        DEBUG_ERROR, "%a: Fail to allocate private data for Controller %d.\n",
> > +        __FUNCTION__, Controller
> >          ));
> >        return EFI_OUT_OF_RESOURCES;
> >      }
> > @@ -268,12 +302,9 @@ NvmExpressPeimEntry (
> >                 );
> >      if (EFI_ERROR (Status)) {
> >        DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: Fail to allocate DMA buffers for Controller %d.\n",
> > -        __FUNCTION__,
> > -        Controller
> > +        DEBUG_ERROR, "%a: Fail to allocate DMA buffers for Controller %d.\n",
> > +        __FUNCTION__, Controller
> >          ));
> > -      NvmeFreeControllerResource (Private);
> >        return Status;
> >      }
> >      ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Private-
> > >Buffer));
> > @@ -282,20 +313,10 @@ NvmExpressPeimEntry (
> >      //
> >      // Initialize controller private data
> >      //
> > -    Private->Signature =
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> > -    Private->MmioBase  = MmioBase;
> > -    Private->BlkIoPpi.GetNumberOfBlockDevices  =
> > NvmeBlockIoPeimGetDeviceNo;
> > -    Private->BlkIoPpi.GetBlockDeviceMediaInfo  =
> > NvmeBlockIoPeimGetMediaInfo;
> > -    Private->BlkIoPpi.ReadBlocks               = NvmeBlockIoPeimReadBlocks;
> > -    Private->BlkIo2Ppi.Revision                =
> > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> > -    Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> > NvmeBlockIoPeimGetDeviceNo2;
> > -    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> > NvmeBlockIoPeimGetMediaInfo2;
> > -    Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
> > -    CopyMem (&Private->BlkIoPpiList, &mNvmeBlkIoPpiListTemplate, sizeof
> > (EFI_PEI_PPI_DESCRIPTOR));
> > -    CopyMem (&Private->BlkIo2PpiList, &mNvmeBlkIo2PpiListTemplate,
> > sizeof (EFI_PEI_PPI_DESCRIPTOR));
> > -    CopyMem (&Private->EndOfPeiNotifyList,
> > &mNvmeEndOfPeiNotifyListTemplate, sizeof
> > (EFI_PEI_NOTIFY_DESCRIPTOR));
> > -    Private->BlkIoPpiList.Ppi   = &Private->BlkIoPpi;
> > -    Private->BlkIo2PpiList.Ppi  = &Private->BlkIo2Ppi;
> > +    Private->Signature        =
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> > +    Private->MmioBase         = MmioBase;
> > +    Private->DevicePathLength = DevicePathLength;
> > +    Private->DevicePath       = DevicePath;
> >
> >      //
> >      // Initialize the NVME controller
> > @@ -305,11 +326,9 @@ NvmExpressPeimEntry (
> >        DEBUG ((
> >          DEBUG_ERROR,
> >          "%a: Controller initialization fail for Controller %d with Status - %r.\n",
> > -        __FUNCTION__,
> > -        Controller,
> > -        Status
> > +        __FUNCTION__, Controller, Status
> >          ));
> > -      NvmeFreeControllerResource (Private);
> > +      NvmeFreeDmaResource (Private);
> >        Controller++;
> >        continue;
> >      }
> > @@ -325,22 +344,68 @@ NvmExpressPeimEntry (
> >        DEBUG ((
> >          DEBUG_ERROR,
> >          "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
> > -        __FUNCTION__,
> > -        Controller,
> > -        Status
> > +        __FUNCTION__, Controller, Status
> >          ));
> > -      NvmeFreeControllerResource (Private);
> > +      NvmeFreeDmaResource (Private);
> >        Controller++;
> >        continue;
> >      }
> >
> > +    Private->BlkIoPpi.GetNumberOfBlockDevices  =
> > NvmeBlockIoPeimGetDeviceNo;
> > +    Private->BlkIoPpi.GetBlockDeviceMediaInfo  =
> > NvmeBlockIoPeimGetMediaInfo;
> > +    Private->BlkIoPpi.ReadBlocks               = NvmeBlockIoPeimReadBlocks;
> > +    CopyMem (
> > +      &Private->BlkIoPpiList,
> > +      &mNvmeBlkIoPpiListTemplate,
> > +      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +      );
> > +    Private->BlkIoPpiList.Ppi                  = &Private->BlkIoPpi;
> > +
> > +    Private->BlkIo2Ppi.Revision                =
> > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> > +    Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> > NvmeBlockIoPeimGetDeviceNo2;
> > +    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> > NvmeBlockIoPeimGetMediaInfo2;
> > +    Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
> > +    CopyMem (
> > +      &Private->BlkIo2PpiList,
> > +      &mNvmeBlkIo2PpiListTemplate,
> > +      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +      );
> > +    Private->BlkIo2PpiList.Ppi                 = &Private->BlkIo2Ppi;
> >      PeiServicesInstallPpi (&Private->BlkIoPpiList);
> > -    PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> > +
> > +    //
> > +    // Check if the NVME controller supports the Security Receive/Send
> > commands
> > +    //
> > +    if ((Private->ControllerData->Oacs &
> > SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> > +      DEBUG ((
> > +        DEBUG_INFO,
> > +        "%a: Security Security Command PPI will be produced for
> > Controller %d.\n",
> > +        __FUNCTION__, Controller
> > +        ));
> > +      Private->StorageSecurityPpi.Revision           =
> > EDKII_STORAGE_SECURITY_PPI_REVISION;
> > +      Private->StorageSecurityPpi.GetNumberofDevices =
> > NvmeStorageSecurityGetDeviceNo;
> > +      Private->StorageSecurityPpi.GetDevicePath      =
> > NvmeStorageSecurityGetDevicePath;
> > +      Private->StorageSecurityPpi.ReceiveData        =
> > NvmeStorageSecurityReceiveData;
> > +      Private->StorageSecurityPpi.SendData           =
> > NvmeStorageSecuritySendData;
> > +      CopyMem (
> > +        &Private->StorageSecurityPpiList,
> > +        &mNvmeStorageSecurityPpiListTemplate,
> > +        sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +        );
> > +      Private->StorageSecurityPpiList.Ppi            = &Private-
> >StorageSecurityPpi;
> > +      PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> > +    }
> > +
> > +    CopyMem (
> > +      &Private->EndOfPeiNotifyList,
> > +      &mNvmeEndOfPeiNotifyListTemplate,
> > +      sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> > +      );
> > +    PeiServicesNotifyPpi  (&Private->EndOfPeiNotifyList);
> > +
> >      DEBUG ((
> > -      DEBUG_INFO,
> > -      "%a: BlockIO PPI has been installed on Controller %d.\n",
> > -      __FUNCTION__,
> > -      Controller
> > +      DEBUG_INFO, "%a: Controller %d has been successfully initialized.\n",
> > +      __FUNCTION__, Controller
> >        ));
> >      Controller++;
> >    }
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c
> > index d4056a2a5b..b9fa3230f8 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c
> > @@ -2,7 +2,7 @@
> >    The NvmExpressPei driver is used to manage non-volatile memory
> > subsystem
> >    which follows NVM Express specification at PEI phase.
> >
> > -  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
> > @@ -702,47 +702,25 @@ NvmeControllerInit (
> >  }
> >
> >  /**
> > -  Free the resources allocated by an NVME controller.
> > +  Free the DMA resources allocated by an NVME controller.
> >
> >    @param[in] Private     The pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
> >
> >  **/
> >  VOID
> > -NvmeFreeControllerResource (
> > +NvmeFreeDmaResource (
> >    IN PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private
> >    )
> >  {
> > -  //
> > -  // Free the controller data buffer
> > -  //
> > -  if (Private->ControllerData != NULL) {
> > -    FreePool (Private->ControllerData);
> > -    Private->ControllerData = NULL;
> > -  }
> > +  ASSERT (Private != NULL);
> >
> > -  //
> > -  // Free the DMA buffers
> > -  //
> > -  if (Private->Buffer != NULL) {
> > +  if (Private->BufferMapping != NULL) {
> >      IoMmuFreeBuffer (
> >         NVME_MEM_MAX_PAGES,
> >         Private->Buffer,
> >         Private->BufferMapping
> >         );
> > -    Private->Buffer = NULL;
> >    }
> >
> > -  //
> > -  // Free the namespaces information buffer
> > -  //
> > -  if (Private->NamespaceInfo != NULL) {
> > -    FreePool (Private->NamespaceInfo);
> > -    Private->NamespaceInfo = NULL;
> > -  }
> > -
> > -  //
> > -  // Free the controller private data structure
> > -  //
> > -  FreePool (Private);
> >    return;
> >  }
> > diff --git
> > a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.
> > c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.
> > c
> > new file mode 100644
> > index 0000000000..e5a2cef3d6
> > --- /dev/null
> > +++
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.
> > c
> > @@ -0,0 +1,423 @@
> > +/** @file
> > +  The NvmExpressPei driver is used to manage non-volatile memory
> > subsystem
> > +  which follows NVM Express specification at PEI phase.
> > +
> > +  Copyright (c) 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
> > +  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 "NvmExpressPei.h"
> > +
> > +/**
> > +  Trust transfer data from/to NVM Express device.
> > +
> > +  This function performs one NVMe transaction to do a trust transfer
> > from/to NVM
> > +  Express device.
> > +
> > +  @param[in]     Private           The pointer to the
> > PEI_NVME_CONTROLLER_PRIVATE_DATA
> > +                                   data structure.
> > +  @param[in,out] Buffer            The pointer to the current transaction buffer.
> > +  @param[in]     SecurityProtocolId
> > +                                   The value of the "Security Protocol" parameter
> > +                                   of the security protocol command to be sent.
> > +  @param[in]     SecurityProtocolSpecificData
> > +                                   The value of the "Security Protocol Specific"
> > +                                   parameter of the security protocol command to
> > +                                   be sent.
> > +  @param[in]     TransferLength    The block number or sector count of the
> > transfer.
> > +  @param[in]     IsTrustSend       Indicates whether it is a trust send operation
> > +                                   or not.
> > +  @param[in]     Timeout           The timeout, in 100ns units, to use for the
> > +                                   execution of the security protocol command.
> > +                                   A Timeout value of 0 means that this function
> > +                                   will wait indefinitely for the security protocol
> > +                                   command to execute. If Timeout is greater than
> > +                                   zero, then this function will return EFI_TIMEOUT
> > +                                   if the time required to execute the receive
> > +                                   data command is greater than Timeout.
> > +  @param[out]    TransferLengthOut A pointer to a buffer to store the size in
> > bytes
> > +                                   of the data written to the buffer. Ignore it
> > +                                   when IsTrustSend is TRUE.
> > +
> > +  @retval EFI_SUCCESS    The data transfer is complete successfully.
> > +  @return others         Some error occurs when transferring data.
> > +
> > +**/
> > +EFI_STATUS
> > +TrustTransferNvmeDevice (
> > +  IN     PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private,
> > +  IN OUT VOID                                *Buffer,
> > +  IN     UINT8                               SecurityProtocolId,
> > +  IN     UINT16                              SecurityProtocolSpecificData,
> > +  IN     UINTN                               TransferLength,
> > +  IN     BOOLEAN                             IsTrustSend,
> > +  IN     UINT64                              Timeout,
> > +     OUT UINTN                               *TransferLengthOut
> > +  )
> > +{
> > +  EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
> > CommandPacket;
> > +  EDKII_PEI_NVM_EXPRESS_COMMAND                     Command;
> > +  EDKII_PEI_NVM_EXPRESS_COMPLETION                  Completion;
> > +  EFI_STATUS                                        Status;
> > +  UINT16                                            SpecificData;
> > +
> > +  ZeroMem (&CommandPacket,
> > sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> > +  ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND));
> > +  ZeroMem (&Completion,
> > sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION));
> > +
> > +  CommandPacket.NvmeCmd        = &Command;
> > +  CommandPacket.NvmeCompletion = &Completion;
> > +
> > +  //
> > +  // Change Endianness of SecurityProtocolSpecificData
> > +  //
> > +  SpecificData = (((SecurityProtocolSpecificData << 8) & 0xFF00) |
> > (SecurityProtocolSpecificData >> 8));
> > +
> > +  if (IsTrustSend) {
> > +    Command.Cdw0.Opcode          = NVME_ADMIN_SECURITY_SEND_CMD;
> > +    CommandPacket.TransferBuffer = Buffer;
> > +    CommandPacket.TransferLength = (UINT32)TransferLength;
> > +    CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId <<
> > 24) | (SpecificData << 8));
> > +    CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;
> > +  } else {
> > +    Command.Cdw0.Opcode          =
> NVME_ADMIN_SECURITY_RECEIVE_CMD;
> > +    CommandPacket.TransferBuffer = Buffer;
> > +    CommandPacket.TransferLength = (UINT32)TransferLength;
> > +    CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId <<
> > 24) | (SpecificData << 8));
> > +    CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;
> > +  }
> > +
> > +  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> > +  CommandPacket.NvmeCmd->Nsid  = NVME_CONTROLLER_NSID;
> > +  CommandPacket.CommandTimeout = Timeout;
> > +  CommandPacket.QueueType      = NVME_ADMIN_QUEUE;
> > +
> > +  Status = NvmePassThru (
> > +             Private,
> > +             NVME_CONTROLLER_NSID,
> > +             &CommandPacket
> > +             );
> > +
> > +  if (!IsTrustSend) {
> > +    if (EFI_ERROR (Status))  {
> > +      *TransferLengthOut = 0;
> > +    } else {
> > +      *TransferLengthOut = (UINTN) TransferLength;
> > +    }
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Gets the count of storage security devices that one specific driver detects.
> > +
> > +  @param[in]  This               The PPI instance pointer.
> > +  @param[out] NumberofDevices    The number of storage security devices
> > discovered.
> > +
> > +  @retval EFI_SUCCESS              The operation performed successfully.
> > +  @retval EFI_INVALID_PARAMETER    The parameters are invalid.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecurityGetDeviceNo (
> > +  IN  EDKII_PEI_STORAGE_SECURITY_CMD_PPI    *This,
> > +  OUT UINTN                                 *NumberofDevices
> > +  )
> > +{
> > +  PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private;
> > +
> > +  if (This == NULL || NumberofDevices == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private =
> > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY
> > (This);
> > +  *NumberofDevices = Private->ActiveNamespaceNum;
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Gets the device path of a specific storage security device.
> > +
> > +  @param[in]  This                 The PPI instance pointer.
> > +  @param[in]  DeviceIndex          Specifies the storage security device to
> > which
> > +                                   the function wants to talk. Because the driver
> > +                                   that implements Storage Security Command PPIs
> > +                                   will manage multiple storage devices, the PPIs
> > +                                   that want to talk to a single device must specify
> > +                                   the device index that was assigned during the
> > +                                   enumeration process. This index is a number from
> > +                                   one to NumberofDevices.
> > +  @param[out] DevicePathLength     The length of the device path in bytes
> > specified
> > +                                   by DevicePath.
> > +  @param[out] DevicePath           The device path of storage security device.
> > +                                   This field re-uses EFI Device Path Protocol as
> > +                                   defined by Section 10.2 EFI Device Path Protocol
> > +                                   of UEFI 2.7 Specification.
> > +
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +  @retval EFI_INVALID_PARAMETER    DevicePathLength or DevicePath is
> > NULL.
> > +  @retval EFI_NOT_FOUND            The specified storage security device not
> > found.
> > +  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of
> > resources.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecurityGetDevicePath (
> > +  IN  EDKII_PEI_STORAGE_SECURITY_CMD_PPI  *This,
> > +  IN  UINTN                               DeviceIndex,
> > +  OUT UINTN                               *DevicePathLength,
> > +  OUT EFI_DEVICE_PATH_PROTOCOL            **DevicePath
> > +  )
> > +{
> > +  PEI_NVME_CONTROLLER_PRIVATE_DATA         *Private;
> > +
> > +  if (This == NULL || DevicePathLength == NULL || DevicePath == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private =
> > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY
> > (This);
> > +  if ((DeviceIndex == 0) || (DeviceIndex > Private->ActiveNamespaceNum))
> > {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  return NvmeBuildDevicePath (
> > +           Private,
> > +           Private->NamespaceInfo[DeviceIndex-1].NamespaceId,
> > +           Private->NamespaceInfo[DeviceIndex-1].NamespaceUuid,
> > +           DevicePathLength,
> > +           DevicePath
> > +           );
> > +}
> > +
> > +/**
> > +  Send a security protocol command to a device that receives data and/or
> > the result
> > +  of one or more commands sent by SendData.
> > +
> > +  The ReceiveData function sends a security protocol command to the given
> > DeviceIndex.
> > +  The security protocol command sent is defined by SecurityProtocolId and
> > contains
> > +  the security protocol specific data SecurityProtocolSpecificData. The
> > function
> > +  returns the data from the security protocol command in PayloadBuffer.
> > +
> > +  For devices supporting the SCSI command set, the security protocol
> > command is sent
> > +  using the SECURITY PROTOCOL IN command defined in SPC-4.
> > +
> > +  For devices supporting the ATA command set, the security protocol
> > command is sent
> > +  using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if
> > PayloadBufferSize
> > +  is non-zero.
> > +
> > +  If the PayloadBufferSize is zero, the security protocol command is sent
> > using the
> > +  Trusted Non-Data command defined in ATA8-ACS.
> > +
> > +  If PayloadBufferSize is too small to store the available data from the
> > security
> > +  protocol command, the function shall copy PayloadBufferSize bytes into
> > the
> > +  PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
> > +
> > +  If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is
> > non-zero,
> > +  the function shall return EFI_INVALID_PARAMETER.
> > +
> > +  If the given DeviceIndex does not support security protocol commands,
> > the function
> > +  shall return EFI_UNSUPPORTED.
> > +
> > +  If the security protocol fails to complete within the Timeout period, the
> > function
> > +  shall return EFI_TIMEOUT.
> > +
> > +  If the security protocol command completes without an error, the function
> > shall
> > +  return EFI_SUCCESS. If the security protocol command completes with an
> > error, the
> > +  function shall return EFI_DEVICE_ERROR.
> > +
> > +  @param[in]  This             The PPI instance pointer.
> > +  @param[in]  DeviceIndex      Specifies the storage security device to which
> > the
> > +                               function wants to talk. Because the driver that
> > +                               implements Storage Security Command PPIs will manage
> > +                               multiple storage devices, the PPIs that want to talk
> > +                               to a single device must specify the device index
> > +                               that was assigned during the enumeration process.
> > +                               This index is a number from one to NumberofDevices.
> > +  @param[in]  Timeout          The timeout, in 100ns units, to use for the
> > execution
> > +                               of the security protocol command. A Timeout value
> > +                               of 0 means that this function will wait indefinitely
> > +                               for the security protocol command to execute. If
> > +                               Timeout is greater than zero, then this function
> > +                               will return EFI_TIMEOUT if the time required to
> > +                               execute the receive data command is greater than
> > +                               Timeout.
> > +  @param[in]  SecurityProtocolId
> > +                               The value of the "Security Protocol" parameter of
> > +                               the security protocol command to be sent.
> > +  @param[in]  SecurityProtocolSpecificData
> > +                               The value of the "Security Protocol Specific"
> > +                               parameter of the security protocol command to be
> > +                               sent.
> > +  @param[in]  PayloadBufferSize
> > +                               Size in bytes of the payload data buffer.
> > +  @param[out] PayloadBuffer    A pointer to a destination buffer to store
> > the
> > +                               security protocol command specific payload data
> > +                               for the security protocol command. The caller is
> > +                               responsible for having either implicit or explicit
> > +                               ownership of the buffer.
> > +  @param[out] PayloadTransferSize
> > +                               A pointer to a buffer to store the size in bytes
> > +                               of the data written to the payload data buffer.
> > +
> > +  @retval EFI_SUCCESS                  The security protocol command completed
> > +                                       successfully.
> > +  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too
> > small to
> > +                                       store the available data from the device.
> > +                                       The PayloadBuffer contains the truncated
> > +                                       data.
> > +  @retval EFI_UNSUPPORTED              The given DeviceIndex does not
> > support
> > +                                       security protocol commands.
> > +  @retval EFI_DEVICE_ERROR             The security protocol command
> > completed
> > +                                       with an error.
> > +  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or
> > PayloadTransferSize
> > +                                       is NULL and PayloadBufferSize is non-zero.
> > +  @retval EFI_TIMEOUT                  A timeout occurred while waiting for the
> > +                                       security protocol command to execute.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecurityReceiveData (
> > +  IN  EDKII_PEI_STORAGE_SECURITY_CMD_PPI  *This,
> > +  IN  UINTN                               DeviceIndex,
> > +  IN  UINT64                              Timeout,
> > +  IN  UINT8                               SecurityProtocolId,
> > +  IN  UINT16                              SecurityProtocolSpecificData,
> > +  IN  UINTN                               PayloadBufferSize,
> > +  OUT VOID                                *PayloadBuffer,
> > +  OUT UINTN                               *PayloadTransferSize
> > +  )
> > +{
> > +  PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private;
> > +  EFI_STATUS                          Status;
> > +
> > +  if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) ||
> > (PayloadBufferSize == 0)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private =
> > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY
> > (This);
> > +
> > +  Status = TrustTransferNvmeDevice (
> > +             Private,
> > +             PayloadBuffer,
> > +             SecurityProtocolId,
> > +             SecurityProtocolSpecificData,
> > +             PayloadBufferSize,
> > +             FALSE,
> > +             Timeout,
> > +             PayloadTransferSize
> > +             );
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Send a security protocol command to a device.
> > +
> > +  The SendData function sends a security protocol command containing the
> > payload
> > +  PayloadBuffer to the given DeviceIndex. The security protocol command
> > sent is
> > +  defined by SecurityProtocolId and contains the security protocol specific
> > data
> > +  SecurityProtocolSpecificData. If the underlying protocol command requires
> > a
> > +  specific padding for the command payload, the SendData function shall
> > add padding
> > +  bytes to the command payload to satisfy the padding requirements.
> > +
> > +  For devices supporting the SCSI command set, the security protocol
> > command is
> > +  sent using the SECURITY PROTOCOL OUT command defined in SPC-4.
> > +
> > +  For devices supporting the ATA command set, the security protocol
> > command is
> > +  sent using one of the TRUSTED SEND commands defined in ATA8-ACS if
> > PayloadBufferSize
> > +  is non-zero. If the PayloadBufferSize is zero, the security protocol
> > command
> > +  is sent using the Trusted Non-Data command defined in ATA8-ACS.
> > +
> > +  If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function
> > shall
> > +  return EFI_INVALID_PARAMETER.
> > +
> > +  If the given DeviceIndex does not support security protocol commands,
> > the function
> > +  shall return EFI_UNSUPPORTED.
> > +
> > +  If the security protocol fails to complete within the Timeout period, the
> > function
> > +  shall return EFI_TIMEOUT.
> > +
> > +  If the security protocol command completes without an error, the function
> > shall
> > +  return EFI_SUCCESS. If the security protocol command completes with an
> > error,
> > +  the functio shall return EFI_DEVICE_ERROR.
> > +
> > +  @param[in] This              The PPI instance pointer.
> > +  @param[in] DeviceIndex       The ID of the device.
> > +  @param[in] Timeout           The timeout, in 100ns units, to use for the
> > execution
> > +                               of the security protocol command. A Timeout value
> > +                               of 0 means that this function will wait indefinitely
> > +                               for the security protocol command to execute. If
> > +                               Timeout is greater than zero, then this function
> > +                               will return EFI_TIMEOUT if the time required to
> > +                               execute the receive data command is greater than
> > +                               Timeout.
> > +  @param[in] SecurityProtocolId
> > +                               The value of the "Security Protocol" parameter of
> > +                               the security protocol command to be sent.
> > +  @param[in] SecurityProtocolSpecificData
> > +                               The value of the "Security Protocol Specific"
> > +                               parameter of the security protocol command to be
> > +                               sent.
> > +  @param[in] PayloadBufferSize Size in bytes of the payload data buffer.
> > +  @param[in] PayloadBuffer     A pointer to a destination buffer to store the
> > +                               security protocol command specific payload data
> > +                               for the security protocol command.
> > +
> > +  @retval EFI_SUCCESS              The security protocol command completed
> > successfully.
> > +  @retval EFI_UNSUPPORTED          The given DeviceIndex does not support
> > security
> > +                                   protocol commands.
> > +  @retval EFI_DEVICE_ERROR         The security protocol command
> > completed with
> > +                                   an error.
> > +  @retval EFI_INVALID_PARAMETER    The PayloadBuffer is NULL and
> > PayloadBufferSize
> > +                                   is non-zero.
> > +  @retval EFI_TIMEOUT              A timeout occurred while waiting for the
> > security
> > +                                   protocol command to execute.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeStorageSecuritySendData (
> > +  IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI  *This,
> > +  IN UINTN                               DeviceIndex,
> > +  IN UINT64                              Timeout,
> > +  IN UINT8                               SecurityProtocolId,
> > +  IN UINT16                              SecurityProtocolSpecificData,
> > +  IN UINTN                               PayloadBufferSize,
> > +  IN VOID                                *PayloadBuffer
> > +  )
> > +{
> > +  PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private;
> > +  EFI_STATUS                          Status;
> > +
> > +  if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private =
> > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY
> > (This);
> > +
> > +  Status = TrustTransferNvmeDevice (
> > +             Private,
> > +             PayloadBuffer,
> > +             SecurityProtocolId,
> > +             SecurityProtocolSpecificData,
> > +             PayloadBufferSize,
> > +             TRUE,
> > +             Timeout,
> > +             NULL
> > +             );
> > +
> > +  return Status;
> > +}
> > --
> > 2.12.0.windows.1



  reply	other threads:[~2019-01-31  5:40 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-31  2:48 [PATCH v2 00/12] Split the S3 PEI phase HW init codes from Opal driver Hao Wu
2019-01-31  2:48 ` [PATCH v2 01/12] MdeModulePkg: Add definitions for ATA AHCI host controller PPI Hao Wu
2019-01-31  3:25   ` Ni, Ray
2019-01-31  2:48 ` [PATCH v2 02/12] MdeModulePkg: Add definitions for EDKII PEI ATA PassThru PPI Hao Wu
2019-01-31  3:22   ` Ni, Ray
2019-01-31  5:28     ` Wu, Hao A
2019-01-31  2:48 ` [PATCH v2 03/12] MdeModulePkg: Add definitions for Storage Security Command PPI Hao Wu
2019-01-31  3:26   ` Ni, Ray
2019-01-31  2:48 ` [PATCH v2 04/12] MdeModulePkg: Add GUID for LockBox to save storage dev to init in S3 Hao Wu
2019-01-31  3:27   ` Ni, Ray
2019-01-31  5:30     ` Wu, Hao A
2019-01-31  2:48 ` [PATCH v2 05/12] MdeModulePkg/NvmExpressPei: Avoid updating the module-level variable Hao Wu
2019-01-31  3:28   ` Ni, Ray
2019-01-31  2:48 ` [PATCH v2 06/12] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI Hao Wu
2019-01-31  3:35   ` Ni, Ray
2019-01-31  5:40     ` Wu, Hao A [this message]
2019-01-31  2:48 ` [PATCH v2 07/12] MdeModulePkg/NvmExpressPei: Consume S3StorageDeviceInitList LockBox Hao Wu
2019-01-31  3:45   ` Ni, Ray
2019-01-31  5:45     ` Wu, Hao A
2019-01-31  2:48 ` [PATCH v2 08/12] MdeModulePkg/AhciPei: Add AHCI mode ATA device support in PEI Hao Wu
2019-01-31  5:49   ` Ni, Ruiyu
2019-01-31  2:48 ` [PATCH v2 09/12] MdeModulePkg/SmmLockBoxLib: Use 'DEBUG_' prefix instead of 'EFI_D_' Hao Wu
2019-01-31  5:49   ` Ni, Ruiyu
2019-01-31  2:48 ` [PATCH v2 10/12] MdeModulePkg/SmmLockBox(PEI): Remove an ASSERT in RestoreLockBox() Hao Wu
2019-01-31  5:50   ` Ni, Ruiyu
2019-01-31  5:53     ` Wu, Hao A
2019-01-31  2:48 ` [PATCH v2 11/12] MdeModulePkg/SmmLockBoxLib: Support LockBox enlarge in UpdateLockBox() Hao Wu
2019-01-31  6:00   ` Ni, Ruiyu
2019-01-31  2:48 ` [PATCH v2 12/12] SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI Hao Wu

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=B80AF82E9BFB8E4FBD8C89DA810C6A093C892DD2@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