From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.43; helo=mga05.intel.com; envelope-from=hao.a.wu@intel.com; receiver=edk2-devel@lists.01.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 565E120886F46 for ; Sun, 17 Feb 2019 22:07:02 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Feb 2019 22:07:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,383,1544515200"; d="scan'208";a="319889900" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by fmsmga006.fm.intel.com with ESMTP; 17 Feb 2019 22:07:01 -0800 Received: from fmsmsx157.amr.corp.intel.com (10.18.116.73) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 17 Feb 2019 22:07:01 -0800 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by FMSMSX157.amr.corp.intel.com (10.18.116.73) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 17 Feb 2019 22:07:00 -0800 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.102]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.109]) with mapi id 14.03.0415.000; Mon, 18 Feb 2019 14:06:59 +0800 From: "Wu, Hao A" To: "Dong, Eric" , "edk2-devel@lists.01.org" Thread-Topic: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI Thread-Index: AQHUxPcIzRHbPBY0kk+Fndl20C4LVKXkW7wAgAC5PXA= Date: Mon, 18 Feb 2019 06:06:58 +0000 Message-ID: References: <20190215062338.19412-1-hao.a.wu@intel.com> <20190215062338.19412-7-hao.a.wu@intel.com> In-Reply-To: Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Feb 2019 06:07:02 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable > -----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 >=20 > Hi Hao, >=20 > > -----Original Message----- > > From: Wu, Hao A > > Sent: Friday, February 15, 2019 2:24 PM > > To: edk2-devel@lists.01.org > > Cc: Wu, Hao A ; Wang, Jian J > ; > > Ni, Ray ; Dong, Eric > > Subject: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to > > produce SSC PPI > > > > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1409 > > > > 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 > > Cc: Ray Ni > > Cc: Eric Dong > > Contributed-under: TianoCore Contribution Agreement 1.1 > > Signed-off-by: Hao Wu > > --- > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 1= 0 > +- > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h | 5= 8 > ++- > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.h | 2= 0 > +- > > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiStorageSecurity.h > > | 247 ++++++++++++ > > MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c | 23= 1 > > +++++++++++ > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c | 14= 3 > > +++++-- > > MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiHci.c | 3= 2 > +- > > > 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.
> > +# 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 t= he > > 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 > > #include > > #include > > +#include > > #include > > #include > > > > @@ -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 controll= er. > > + > > + @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 by= tes > > specified > > + by DevicePath. > > + @param[out] DevicePath The device path of Nvm Express devi= ce. > > + > > + @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.
> > + Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved. > > > > 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.
> > + > > + 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 successfull= y. > > + @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 devi= ce to > > which > > + the function wants to talk. Because= the driver > > + that implements Storage Security Co= mmand PPIs > > + will manage multiple storage device= s, the PPIs > > + that want to talk to a single devic= e 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 by= tes > > 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 devi= ce 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. Th= e > > 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 s= ent > > using the > > + Trusted Non-Data command defined in ATA8-ACS. > > + > > + If PayloadBufferSize is too small to store the available data from t= he > > security > > + protocol command, the function shall copy PayloadBufferSize bytes in= to > > the > > + PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. > > + > > + If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSiz= e 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 t= o > which > > the > > + function wants to talk. Because the dri= ver that > > + implements Storage Security Command PPI= s will manage > > + multiple storage devices, the PPIs that= want to talk > > + to a single device must specify the dev= ice index > > + that was assigned during the enumeratio= n process. > > + This index is a number from one to Numb= erofDevices. > > + @param[in] Timeout The timeout, in 100ns units, to use for= the > > execution > > + of the security protocol command. A Tim= eout value > > + of 0 means that this function will wait= indefinitely > > + for the security protocol command to ex= ecute. If > > + Timeout is greater than zero, then this= function > > + will return EFI_TIMEOUT if the time req= uired to > > + execute the receive data command is gre= ater than > > + Timeout. > > + @param[in] SecurityProtocolId > > + The value of the "Security Protocol" pa= rameter of > > + the security protocol command to be sen= t. > > + @param[in] SecurityProtocolSpecificData > > + The value of the "Security Protocol Spe= cific" > > + parameter of the security protocol comm= and to be > > + sent. > > + @param[in] PayloadBufferSize > > + Size in bytes of the payload data buffe= r. > > + @param[out] PayloadBuffer A pointer to a destination buffer to st= ore > > the > > + security protocol command specific payl= oad 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 t= he 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 i= s non-zero. > > + @retval EFI_TIMEOUT A timeout occurred while waitin= g for the > > + security protocol command to ex= ecute. > > + > > +**/ > > +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 comman= d > > sent is > > + defined by SecurityProtocolId and contains the security protocol spe= cific > > data > > + SecurityProtocolSpecificData. If the underlying protocol command > requires > > a > > + specific padding for the command payload, the SendData function shal= l > > 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 func= tion > > 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 Tim= eout value > > + of 0 means that this function will wait= indefinitely > > + for the security protocol command to ex= ecute. If > > + Timeout is greater than zero, then this= function > > + will return EFI_TIMEOUT if the time req= uired to > > + execute the receive data command is gre= ater than > > + Timeout. > > + @param[in] SecurityProtocolId > > + The value of the "Security Protocol" pa= rameter of > > + the security protocol command to be sen= t. > > + @param[in] SecurityProtocolSpecificData > > + The value of the "Security Protocol Spe= cific" > > + parameter of the security protocol comm= and to be > > + sent. > > + @param[in] PayloadBufferSize Size in bytes of the payload data buffe= r. > > + @param[in] PayloadBuffer A pointer to a destination buffer to st= ore > the > > + security protocol command specific payl= oad data > > + for the security protocol command. > > + > > + @retval EFI_SUCCESS The security protocol command compl= eted > > 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 fo= r 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.
> > + > > + 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 =3D > { > > + { // 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 =3D { > > + 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 !=3D NULL); > > + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL > > *)(Node))->Length[0]); > > +} >=20 > 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 availab= le 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 >=20 > > + > > +/** > > + 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 pa= th > > node > > + specified by Node. > > + > > +**/ > > +EFI_DEVICE_PATH_PROTOCOL * > > +NextDevicePathNode ( > > + IN CONST VOID *Node > > + ) > > +{ > > + ASSERT (Node !=3D NULL); > > + return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + > > DevicePathNodeLength(Node)); > > +} >=20 > 2. DevicePathLib has same API, can leverage that API. >=20 > > + > > +/** > > + Check the validity of the device path of a NVM Express host controll= er. > > + > > + @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 =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // > > + // Validate the DevicePathLength is big enough to touch the first no= de. > > + // > > + if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Start =3D DevicePath; > > + while (!(DevicePath->Type =3D=3D END_DEVICE_PATH_TYPE && > > + DevicePath->SubType =3D=3D END_ENTIRE_DEVICE_PATH_SUBTYPE))= { > > + DevicePath =3D NextDevicePathNode (DevicePath); > > + > > + // > > + // Prevent overflow and invalid zero in the 'Length' field of a de= vice path > > + // node. > > + // > > + if ((UINTN) DevicePath <=3D (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 oth= er. > > + // > > + Size =3D ((UINTN) DevicePath - (UINTN) Start) + sizeof > > (EFI_DEVICE_PATH_PROTOCOL); > > + if (Size !=3D DevicePathLength) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + return EFI_SUCCESS; > > +} >=20 > 3. Seems like this function just do validation for the input device path. > UefiDevicePathLib has IsDevicePathValid API, can we leverage that functio= n? >=20 > 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 by= tes > > specified > > + by DevicePath. > > + @param[out] DevicePath The device path of Nvm Express devi= ce. > > + > > + @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 =3D=3D NULL || DevicePath =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + *DevicePathLength =3D Private->DevicePathLength + sizeof > > (NVME_NAMESPACE_DEVICE_PATH); > > + *DevicePath =3D AllocatePool (*DevicePathLength); > > + if (*DevicePath =3D=3D NULL) { > > + *DevicePathLength =3D 0; > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + // > > + // Construct the host controller part device nodes > > + // > > + DevicePathWalker =3D *DevicePath; > > + CopyMem ( > > + DevicePathWalker, > > + Private->DevicePath, > > + Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL) > > + ); > > + > > + // > > + // Construct the Nvm Express device node > > + // > > + DevicePathWalker =3D (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 > > *)DevicePathWalker + > > + (Private->DevicePathLength - sizeof > > (EFI_DEVICE_PATH_PROTOCOL))); > > + CopyMem ( > > + DevicePathWalker, > > + &mNvmeDevicePathNodeTemplate, > > + sizeof (mNvmeDevicePathNodeTemplate) > > + ); > > + NvmeDeviceNode =3D (NVME_NAMESPACE_DEVICE_PATH > > *)DevicePathWalker; > > + NvmeDeviceNode->NamespaceId =3D NamespaceId; > > + NvmeDeviceNode->NamespaceUuid =3D NamespaceUuid; > > + > > + // > > + // Construct the end device node > > + // > > + DevicePathWalker =3D (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 =3D { > > }; > > > > EFI_PEI_PPI_DESCRIPTOR mNvmeBlkIo2PpiListTemplate =3D { > > - 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 =3D { > > + (EFI_PEI_PPI_DESCRIPTOR_PPI | > > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > > + &gEdkiiPeiStorageSecurityCommandPpiGuid, > > + NULL > > +}; > > + > > EFI_PEI_NOTIFY_DESCRIPTOR mNvmeEndOfPeiNotifyListTemplate =3D { > > (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 =3D 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 =3D 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 =3D 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 =3D AllocateZeroPool (sizeof > > (PEI_NVME_CONTROLLER_PRIVATE_DATA)); > > if (Private =3D=3D 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 =3D=3D ((EFI_PHYSICAL_ADDRESS) (UINTN) Priva= te- > > >Buffer)); > > @@ -282,20 +313,10 @@ NvmExpressPeimEntry ( > > // > > // Initialize controller private data > > // > > - Private->Signature =3D > > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE; > > - Private->MmioBase =3D MmioBase; > > - Private->BlkIoPpi.GetNumberOfBlockDevices =3D > > NvmeBlockIoPeimGetDeviceNo; > > - Private->BlkIoPpi.GetBlockDeviceMediaInfo =3D > > NvmeBlockIoPeimGetMediaInfo; > > - Private->BlkIoPpi.ReadBlocks =3D NvmeBlockIoPeimRead= Blocks; > > - Private->BlkIo2Ppi.Revision =3D > > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION; > > - Private->BlkIo2Ppi.GetNumberOfBlockDevices =3D > > NvmeBlockIoPeimGetDeviceNo2; > > - Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =3D > > NvmeBlockIoPeimGetMediaInfo2; > > - Private->BlkIo2Ppi.ReadBlocks =3D NvmeBlockIoPeimRead= Blocks2; > > - 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 =3D &Private->BlkIoPpi; > > - Private->BlkIo2PpiList.Ppi =3D &Private->BlkIo2Ppi; > > + Private->Signature =3D > > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE; > > + Private->MmioBase =3D MmioBase; > > + Private->DevicePathLength =3D DevicePathLength; > > + Private->DevicePath =3D DevicePath; > > > > // > > // Initialize the NVME controller > > @@ -305,11 +326,9 @@ NvmExpressPeimEntry ( > > DEBUG (( > > DEBUG_ERROR, > > "%a: Controller initialization fail for Controller %d with Sta= tus - %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 =3D > > NvmeBlockIoPeimGetDeviceNo; > > + Private->BlkIoPpi.GetBlockDeviceMediaInfo =3D > > NvmeBlockIoPeimGetMediaInfo; > > + Private->BlkIoPpi.ReadBlocks =3D NvmeBlockIoPeimRead= Blocks; > > + CopyMem ( > > + &Private->BlkIoPpiList, > > + &mNvmeBlkIoPpiListTemplate, > > + sizeof (EFI_PEI_PPI_DESCRIPTOR) > > + ); > > + Private->BlkIoPpiList.Ppi =3D &Private->BlkIoPpi; > > + > > + Private->BlkIo2Ppi.Revision =3D > > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION; > > + Private->BlkIo2Ppi.GetNumberOfBlockDevices =3D > > NvmeBlockIoPeimGetDeviceNo2; > > + Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =3D > > NvmeBlockIoPeimGetMediaInfo2; > > + Private->BlkIo2Ppi.ReadBlocks =3D NvmeBlockIoPeimRead= Blocks2; > > + CopyMem ( > > + &Private->BlkIo2PpiList, > > + &mNvmeBlkIo2PpiListTemplate, > > + sizeof (EFI_PEI_PPI_DESCRIPTOR) > > + ); > > + Private->BlkIo2PpiList.Ppi =3D &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) !=3D 0) { > > + DEBUG (( > > + DEBUG_INFO, > > + "%a: Security Security Command PPI will be produced for > > Controller %d.\n", > > + __FUNCTION__, Controller > > + )); > > + Private->StorageSecurityPpi.Revision =3D > > EDKII_STORAGE_SECURITY_PPI_REVISION; > > + Private->StorageSecurityPpi.GetNumberofDevices =3D > > NvmeStorageSecurityGetDeviceNo; > > + Private->StorageSecurityPpi.GetDevicePath =3D > > NvmeStorageSecurityGetDevicePath; > > + Private->StorageSecurityPpi.ReceiveData =3D > > NvmeStorageSecurityReceiveData; > > + Private->StorageSecurityPpi.SendData =3D > > NvmeStorageSecuritySendData; > > + CopyMem ( > > + &Private->StorageSecurityPpiList, > > + &mNvmeStorageSecurityPpiListTemplate, > > + sizeof (EFI_PEI_PPI_DESCRIPTOR) > > + ); > > + Private->StorageSecurityPpiList.Ppi =3D &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.
> > + Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved. > > > > 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 !=3D NULL) { > > - FreePool (Private->ControllerData); > > - Private->ControllerData =3D NULL; > > - } > > + ASSERT (Private !=3D NULL); > > > > - // > > - // Free the DMA buffers > > - // > > - if (Private->Buffer !=3D NULL) { > > + if (Private->BufferMapping !=3D NULL) { > > IoMmuFreeBuffer ( > > NVME_MEM_MAX_PAGES, > > Private->Buffer, > > Private->BufferMapping > > ); > > - Private->Buffer =3D NULL; > > } > > > > - // > > - // Free the namespaces information buffer > > - // > > - if (Private->NamespaceInfo !=3D NULL) { > > - FreePool (Private->NamespaceInfo); > > - Private->NamespaceInfo =3D 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.
> > + > > + 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 transact= ion > 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 sen= d > 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 thi= s function > > + will wait indefinitely for the secu= rity protocol > > + command to execute. If Timeout is g= reater than > > + zero, then this function will retur= n EFI_TIMEOUT > > + if the time required to execute the= receive > > + data command is greater than Timeou= t. > > + @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 SecurityProtocolSpecificD= ata, > > + 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 =3D &Command; > > + CommandPacket.NvmeCompletion =3D &Completion; > > + > > + // > > + // Change Endianness of SecurityProtocolSpecificData > > + // > > + SpecificData =3D (((SecurityProtocolSpecificData << 8) & 0xFF00) | > > (SecurityProtocolSpecificData >> 8)); > > + > > + if (IsTrustSend) { > > + Command.Cdw0.Opcode =3D NVME_ADMIN_SECURITY_SEND_CMD; > > + CommandPacket.TransferBuffer =3D Buffer; > > + CommandPacket.TransferLength =3D (UINT32)TransferLength; > > + CommandPacket.NvmeCmd->Cdw10 =3D (UINT32)((SecurityProtocolId << > > 24) | (SpecificData << 8)); > > + CommandPacket.NvmeCmd->Cdw11 =3D (UINT32)TransferLength; > > + } else { > > + Command.Cdw0.Opcode =3D > NVME_ADMIN_SECURITY_RECEIVE_CMD; > > + CommandPacket.TransferBuffer =3D Buffer; > > + CommandPacket.TransferLength =3D (UINT32)TransferLength; > > + CommandPacket.NvmeCmd->Cdw10 =3D (UINT32)((SecurityProtocolId << > > 24) | (SpecificData << 8)); > > + CommandPacket.NvmeCmd->Cdw11 =3D (UINT32)TransferLength; > > + } > > + > > + CommandPacket.NvmeCmd->Flags =3D CDW10_VALID | CDW11_VALID; > > + CommandPacket.NvmeCmd->Nsid =3D NVME_CONTROLLER_NSID; > > + CommandPacket.CommandTimeout =3D Timeout; > > + CommandPacket.QueueType =3D NVME_ADMIN_QUEUE; > > + > > + Status =3D NvmePassThru ( > > + Private, > > + NVME_CONTROLLER_NSID, > > + &CommandPacket > > + ); > > + > > + if (!IsTrustSend) { > > + if (EFI_ERROR (Status)) { > > + *TransferLengthOut =3D 0; > > + } else { > > + *TransferLengthOut =3D (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 successfull= y. > > + @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 =3D=3D NULL || NumberofDevices =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D > > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY > > (This); > > + *NumberofDevices =3D 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 devi= ce to > > which > > + the function wants to talk. Because= the driver > > + that implements Storage Security Co= mmand PPIs > > + will manage multiple storage device= s, the PPIs > > + that want to talk to a single devic= e 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 by= tes > > 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 devi= ce 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 =3D=3D NULL || DevicePathLength =3D=3D NULL || DevicePath = =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D > > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY > > (This); > > + if ((DeviceIndex =3D=3D 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. Th= e > > 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 s= ent > > using the > > + Trusted Non-Data command defined in ATA8-ACS. > > + > > + If PayloadBufferSize is too small to store the available data from t= he > > security > > + protocol command, the function shall copy PayloadBufferSize bytes in= to > > the > > + PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. > > + > > + If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSiz= e 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 t= o > which > > the > > + function wants to talk. Because the dri= ver that > > + implements Storage Security Command PPI= s will manage > > + multiple storage devices, the PPIs that= want to talk > > + to a single device must specify the dev= ice index > > + that was assigned during the enumeratio= n process. > > + This index is a number from one to Numb= erofDevices. > > + @param[in] Timeout The timeout, in 100ns units, to use for= the > > execution > > + of the security protocol command. A Tim= eout value > > + of 0 means that this function will wait= indefinitely > > + for the security protocol command to ex= ecute. If > > + Timeout is greater than zero, then this= function > > + will return EFI_TIMEOUT if the time req= uired to > > + execute the receive data command is gre= ater than > > + Timeout. > > + @param[in] SecurityProtocolId > > + The value of the "Security Protocol" pa= rameter of > > + the security protocol command to be sen= t. > > + @param[in] SecurityProtocolSpecificData > > + The value of the "Security Protocol Spe= cific" > > + parameter of the security protocol comm= and to be > > + sent. > > + @param[in] PayloadBufferSize > > + Size in bytes of the payload data buffe= r. > > + @param[out] PayloadBuffer A pointer to a destination buffer to st= ore > > the > > + security protocol command specific payl= oad 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 t= he 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 i= s non-zero. > > + @retval EFI_TIMEOUT A timeout occurred while waitin= g for the > > + security protocol command to ex= ecute. > > + > > +**/ > > +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 =3D=3D NULL) || (PayloadTransferSize =3D=3D NULL)= || > > (PayloadBufferSize =3D=3D 0)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D > > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY > > (This); > > + > > + Status =3D 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 comman= d > > sent is > > + defined by SecurityProtocolId and contains the security protocol spe= cific > > data > > + SecurityProtocolSpecificData. If the underlying protocol command > requires > > a > > + specific padding for the command payload, the SendData function shal= l > > 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 func= tion > > 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 Tim= eout value > > + of 0 means that this function will wait= indefinitely > > + for the security protocol command to ex= ecute. If > > + Timeout is greater than zero, then this= function > > + will return EFI_TIMEOUT if the time req= uired to > > + execute the receive data command is gre= ater than > > + Timeout. > > + @param[in] SecurityProtocolId > > + The value of the "Security Protocol" pa= rameter of > > + the security protocol command to be sen= t. > > + @param[in] SecurityProtocolSpecificData > > + The value of the "Security Protocol Spe= cific" > > + parameter of the security protocol comm= and to be > > + sent. > > + @param[in] PayloadBufferSize Size in bytes of the payload data buffe= r. > > + @param[in] PayloadBuffer A pointer to a destination buffer to st= ore > the > > + security protocol command specific payl= oad data > > + for the security protocol command. > > + > > + @retval EFI_SUCCESS The security protocol command compl= eted > > 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 fo= r 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 =3D=3D NULL) && (PayloadBufferSize !=3D 0)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D > > GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY > > (This); > > + > > + Status =3D TrustTransferNvmeDevice ( > > + Private, > > + PayloadBuffer, > > + SecurityProtocolId, > > + SecurityProtocolSpecificData, > > + PayloadBufferSize, > > + TRUE, > > + Timeout, > > + NULL > > + ); > > + > > + return Status; > > +} > > -- > > 2.12.0.windows.1