Hi Hao, Got it. In this case, Reviewed-by: Eric Dong <eric.d...@intel.com> for 6,7,8 patches.
Thanks, Eric > -----Original Message----- > From: Wu, Hao A > Sent: Monday, February 18, 2019 2:07 PM > To: Dong, Eric <eric.d...@intel.com>; edk2-devel@lists.01.org > Cc: Wang, Jian J <jian.j.w...@intel.com>; Ni, Ray <ray...@intel.com> > Subject: RE: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to > produce SSC PPI > > > -----Original Message----- > > From: Dong, Eric > > Sent: Monday, February 18, 2019 10:59 AM > > To: Wu, Hao A; edk2-devel@lists.01.org > > Cc: Wang, Jian J; Ni, Ray > > Subject: RE: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic > to > > produce SSC PPI > > > > Hi Hao, > > > > > -----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...@intel.com>; Wang, Jian J > > <jian.j.w...@intel.com>; > > > Ni, Ray <ray...@intel.com>; Dong, Eric <eric.d...@intel.com> > > > Subject: [PATCH v5 06/13] 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.w...@intel.com> > > > Cc: Ray Ni <ray...@intel.com> > > > Cc: Eric Dong <eric.d...@intel.com> > > > Contributed-under: TianoCore Contribution Agreement 1.1 > > > Signed-off-by: Hao Wu <hao.a...@intel.com> > > > --- > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 10 > > +- > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h | 58 > > ++- > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h | > 20 > > +- > > > > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.h > > > | 247 ++++++++++++ > > > MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c | 231 > > > +++++++++++ > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c | 143 > > > +++++-- > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c | > 32 > > +- > > > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.c > > > | 423 ++++++++++++++++++++ > > > 8 files changed, 1075 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..92c3854c6e 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,47 @@ NvmePeimEndOfPei ( > > > IN VOID *Ppi > > > ); > > > > > > +/** > > > + 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..5dab447f09 > > > --- /dev/null > > > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c > > > @@ -0,0 +1,231 @@ > > > +/** @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]); > > > +} > > > > 1. DevicePathLib has same API, can leverage that API. > > Hi Eric, > > Actually, Ray had similar comments as well. For the comments on patch > 06/13 & 07/13, the reason I choose to add driver internal implementation > of those functions are: > > 1. I found that the DevicePathLib instances will consume the Boot Services > Table (e.g. try to get the 'Handle' of a device path), which is not available > in the PEI phase. > > 2. There are some 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. > > Best Regards, > Hao Wu > > > > > > + > > > +/** > > > + 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)); > > > +} > > > > 2. DevicePathLib has same API, can leverage that API. > > > > > + > > > +/** > > > + 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; > > > + } > > > + > > > + // > > > + // Validate the DevicePathLength is big enough to touch the first node. > > > + // > > > + if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + > > > + Start = DevicePath; > > > + while (!(DevicePath->Type == END_DEVICE_PATH_TYPE && > > > + DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) { > > > + DevicePath = NextDevicePathNode (DevicePath); > > > + > > > + // > > > + // Prevent overflow and invalid zero in the 'Length' field of a > > > device > path > > > + // node. > > > + // > > > + if ((UINTN) DevicePath <= (UINTN) Start) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + > > > + // > > > + // Prevent touching memory beyond given DevicePathLength. > > > + // > > > + if ((UINTN) DevicePath - (UINTN) Start > > > > + DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + } > > > + > > > + // > > > + // Check if the device path and its size match exactly with each other. > > > + // > > > + Size = ((UINTN) DevicePath - (UINTN) Start) + sizeof > > > (EFI_DEVICE_PATH_PROTOCOL); > > > + if (Size != DevicePathLength) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + > > > + return EFI_SUCCESS; > > > +} > > > > 3. Seems like this function just do validation for the input device path. > > UefiDevicePathLib has IsDevicePathValid API, can we leverage that > function? > > > > Thanks, > > Eric > > > + > > > +/** > > > + 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 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel