From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.20; helo=mga02.intel.com; envelope-from=eric.dong@intel.com; receiver=edk2-devel@lists.01.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) (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 9C6DE202E5343 for ; Sun, 17 Feb 2019 18:59:00 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Feb 2019 18:59:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,382,1544515200"; d="scan'208";a="139426094" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by orsmga001.jf.intel.com with ESMTP; 17 Feb 2019 18:58:59 -0800 Received: from fmsmsx123.amr.corp.intel.com (10.18.125.38) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 17 Feb 2019 18:58:59 -0800 Received: from shsmsx153.ccr.corp.intel.com (10.239.6.53) by fmsmsx123.amr.corp.intel.com (10.18.125.38) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 17 Feb 2019 18:58:58 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.207]) by SHSMSX153.ccr.corp.intel.com ([169.254.12.190]) with mapi id 14.03.0415.000; Mon, 18 Feb 2019 10:58:56 +0800 From: "Dong, Eric" To: "Wu, Hao A" , "edk2-devel@lists.01.org" Thread-Topic: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI Thread-Index: AQHUxPcJpIcbb115YE2g1yWZnc2Ku6Xk2rGg Date: Mon, 18 Feb 2019 02:58:56 +0000 Message-ID: References: <20190215062338.19412-1-hao.a.wu@intel.com> <20190215062338.19412-7-hao.a.wu@intel.com> In-Reply-To: <20190215062338.19412-7-hao.a.wu@intel.com> Accept-Language: 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 02:59:00 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable 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 ; Wang, Jian J ; > Ni, Ray ; Dong, Eric > Subject: [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to > produce SSC PPI >=20 > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1409 >=20 > 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. >=20 > 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 | 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(-) >=20 > 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. > # > # This program and the accompanying materials > # are licensed and made available under the terms and conditions of the > BSD License > @@ -30,6 +30,7 @@ > # >=20 > [Sources] > + DevicePath.c > DmaMem.c > NvmExpressPei.c > NvmExpressPei.h > @@ -39,6 +40,8 @@ > NvmExpressPeiHci.h > NvmExpressPeiPassThru.c > NvmExpressPeiPassThru.h > + NvmExpressPeiStorageSecurity.c > + NvmExpressPeiStorageSecurity.h >=20 > [Packages] > MdePkg/MdePkg.dec > @@ -54,11 +57,12 @@ > PeimEntryPoint >=20 > [Ppis] > - gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES > - gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES > gEdkiiPeiNvmExpressHostControllerPpiGuid ## CONSUMES > gEdkiiIoMmuPpiGuid ## CONSUMES > gEfiEndOfPeiSignalPpiGuid ## CONSUMES > + gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES > + gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES > + gEdkiiPeiStorageSecurityCommandPpiGuid ## > SOMETIMES_PRODUCES >=20 > [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 >=20 > @@ -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" >=20 > // > // 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; >=20 > // > @@ -139,11 +146,13 @@ struct _PEI_NVME_CONTROLLER_PRIVATE_DATA { > PEI_NVME_NAMESPACE_INFO *NamespaceInfo; > }; >=20 > -#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) >=20 >=20 > @@ -257,4 +266,47 @@ NvmePeimEndOfPei ( > IN VOID *Ppi > ); >=20 > +/** > + 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 byte= s > 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. >=20 > - Copyright (c) 2018, Intel Corporation. All rights reserved.
> + Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -107,20 +107,6 @@ NvmeBaseMemPageOffset ( > ); >=20 > /** > - 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. >=20 > @param[in] Private The pointer to the > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure. > @@ -153,13 +139,13 @@ NvmeIdentifyNamespace ( > ); >=20 > /** > - Free the resources allocated by an NVME controller. > + Free the DMA resources allocated by an NVME controller. >=20 > @param[in] Private The pointer to the > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure. >=20 > **/ > VOID > -NvmeFreeControllerResource ( > +NvmeFreeDmaResource ( > IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private > ); >=20 > 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 de= tects. > + > + @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 t= he driver > + that implements Storage Security Comm= and PPIs > + will manage multiple storage devices,= the PPIs > + that want to talk to a single device = must specify > + the device index that was assigned du= ring the > + enumeration process. This index is a = number from > + one to NumberofDevices. > + @param[out] DevicePathLength The length of the device path in byte= s > specified > + by DevicePath. > + @param[out] DevicePath The device path of storage security d= evice. > + This field re-uses EFI Device Path Pr= otocol as > + defined by Section 10.2 EFI Device Pa= th 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 give= n > DeviceIndex. > + The security protocol command sent is defined by SecurityProtocolId an= d > 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 sen= t > 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 funct= ion > 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 drive= r that > + implements Storage Security Command PPIs = will manage > + multiple storage devices, the PPIs that w= ant to talk > + to a single device must specify the devic= e index > + that was assigned during the enumeration = process. > + This index is a number from one to Number= ofDevices. > + @param[in] Timeout The timeout, in 100ns units, to use for t= he > execution > + of the security protocol command. A Timeo= ut value > + of 0 means that this function will wait i= ndefinitely > + for the security protocol command to exec= ute. If > + Timeout is greater than zero, then this f= unction > + will return EFI_TIMEOUT if the time requi= red to > + execute the receive data command is great= er than > + Timeout. > + @param[in] SecurityProtocolId > + The value of the "Security Protocol" para= meter of > + the security protocol command to be sent. > + @param[in] SecurityProtocolSpecificData > + The value of the "Security Protocol Speci= fic" > + parameter of the security protocol comman= d to be > + sent. > + @param[in] PayloadBufferSize > + Size in bytes of the payload data buffer. > + @param[out] PayloadBuffer A pointer to a destination buffer to stor= e > the > + security protocol command specific payloa= d data > + for the security protocol command. The ca= ller is > + responsible for having either implicit or= explicit > + ownership of the buffer. > + @param[out] PayloadTransferSize > + A pointer to a buffer to store the size i= n bytes > + of the data written to the payload data b= uffer. > + > + @retval EFI_SUCCESS The security protocol command com= pleted > + successfully. > + @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too > small to > + store the available data from the= device. > + The PayloadBuffer contains the tr= uncated > + 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 exec= ute. > + > +**/ > +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 speci= fic > data > + SecurityProtocolSpecificData. If the underlying protocol command requi= res > 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 functi= on > 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 funct= ion > 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 t= he > execution > + of the security protocol command. A Timeo= ut value > + of 0 means that this function will wait i= ndefinitely > + for the security protocol command to exec= ute. If > + Timeout is greater than zero, then this f= unction > + will return EFI_TIMEOUT if the time requi= red to > + execute the receive data command is great= er than > + Timeout. > + @param[in] SecurityProtocolId > + The value of the "Security Protocol" para= meter of > + the security protocol command to be sent. > + @param[in] SecurityProtocolSpecificData > + The value of the "Security Protocol Speci= fic" > + parameter of the security protocol comman= d to be > + sent. > + @param[in] PayloadBufferSize Size in bytes of the payload data buffer. > + @param[in] PayloadBuffer A pointer to a destination buffer to stor= e the > + security protocol command specific payloa= d data > + for the security protocol command. > + > + @retval EFI_SUCCESS The security protocol command complet= ed > successfully. > + @retval EFI_UNSUPPORTED The given DeviceIndex does not suppor= t > 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.
> + > + 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 N= ode. > + 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 conte= nts > 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 N= ode. > + > +**/ > +UINTN > +DevicePathNodeLength ( > + IN CONST VOID *Node > + ) > +{ > + ASSERT (Node !=3D NULL); > + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL > *)(Node))->Length[0]); > +} 1. DevicePathLib has same API, can leverage that API. > + > +/** > + 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 !=3D 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 =3D=3D 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 =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 devi= ce 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 other= . > + // > + Size =3D ((UINTN) DevicePath - (UINTN) Start) + sizeof > (EFI_DEVICE_PATH_PROTOCOL); > + if (Size !=3D DevicePathLength) { > + return EFI_INVALID_PARAMETER; > + } > + > + return EFI_SUCCESS; > +} 3. Seems like this function just do validation for the input device path. U= efiDevicePathLib 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 byte= s > 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 =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 { > }; >=20 > 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 > }; >=20 > +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; >=20 > Private =3D GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY > (NotifyDescriptor); > - NvmeDisableController (Private); > - NvmeFreeControllerResource (Private); > + NvmeFreeDmaResource (Private); >=20 > 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; >=20 > + DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__)); > + > // > // Locate the NVME host controller PPI > // > @@ -243,16 +252,41 @@ NvmExpressPeimEntry ( > break; > } >=20 > + 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) Private= - > >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 NvmeBlockIoPeimReadBl= ocks; > - 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 NvmeBlockIoPeimReadBl= ocks2; > - 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; >=20 > // > // Initialize the NVME controller > @@ -305,11 +326,9 @@ NvmExpressPeimEntry ( > DEBUG (( > DEBUG_ERROR, > "%a: Controller initialization fail for Controller %d with Statu= s - %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; > } >=20 > + Private->BlkIoPpi.GetNumberOfBlockDevices =3D > NvmeBlockIoPeimGetDeviceNo; > + Private->BlkIoPpi.GetBlockDeviceMediaInfo =3D > NvmeBlockIoPeimGetMediaInfo; > + Private->BlkIoPpi.ReadBlocks =3D NvmeBlockIoPeimReadBl= ocks; > + 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 NvmeBlockIoPeimReadBl= ocks2; > + 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->Stora= geSecurityPpi; > + 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. >=20 > - Copyright (c) 2018, Intel Corporation. All rights reserved.
> + Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -702,47 +702,25 @@ NvmeControllerInit ( > } >=20 > /** > - Free the resources allocated by an NVME controller. > + Free the DMA resources allocated by an NVME controller. >=20 > @param[in] Private The pointer to the > PEI_NVME_CONTROLLER_PRIVATE_DATA data structure. >=20 > **/ > 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); >=20 > - // > - // 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; > } >=20 > - // > - // 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 transactio= n buffer. > + @param[in] SecurityProtocolId > + The value of the "Security Protocol" = parameter > + of the security protocol command to b= e sent. > + @param[in] SecurityProtocolSpecificData > + The value of the "Security Protocol S= pecific" > + parameter of the security protocol co= mmand to > + be sent. > + @param[in] TransferLength The block number or sector count of t= he > transfer. > + @param[in] IsTrustSend Indicates whether it is a trust send = operation > + or not. > + @param[in] Timeout The timeout, in 100ns units, to use f= or the > + execution of the security protocol co= mmand. > + A Timeout value of 0 means that this = function > + will wait indefinitely for the securi= ty protocol > + command to execute. If Timeout is gre= ater than > + zero, then this function will return = EFI_TIMEOUT > + if the time required to execute the r= eceive > + data command is greater than Timeout. > + @param[out] TransferLengthOut A pointer to a buffer to store the si= ze in > bytes > + of the data written to the buffer. Ig= nore 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 SecurityProtocolSpecificDat= a, > + 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 de= tects. > + > + @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 =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 device= to > which > + the function wants to talk. Because t= he driver > + that implements Storage Security Comm= and PPIs > + will manage multiple storage devices,= the PPIs > + that want to talk to a single device = must specify > + the device index that was assigned du= ring the > + enumeration process. This index is a = number from > + one to NumberofDevices. > + @param[out] DevicePathLength The length of the device path in byte= s > specified > + by DevicePath. > + @param[out] DevicePath The device path of storage security d= evice. > + This field re-uses EFI Device Path Pr= otocol as > + defined by Section 10.2 EFI Device Pa= th 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 =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->ActiveNamespaceN= um)) > { > + 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 give= n > DeviceIndex. > + The security protocol command sent is defined by SecurityProtocolId an= d > 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 sen= t > 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 funct= ion > 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 drive= r that > + implements Storage Security Command PPIs = will manage > + multiple storage devices, the PPIs that w= ant to talk > + to a single device must specify the devic= e index > + that was assigned during the enumeration = process. > + This index is a number from one to Number= ofDevices. > + @param[in] Timeout The timeout, in 100ns units, to use for t= he > execution > + of the security protocol command. A Timeo= ut value > + of 0 means that this function will wait i= ndefinitely > + for the security protocol command to exec= ute. If > + Timeout is greater than zero, then this f= unction > + will return EFI_TIMEOUT if the time requi= red to > + execute the receive data command is great= er than > + Timeout. > + @param[in] SecurityProtocolId > + The value of the "Security Protocol" para= meter of > + the security protocol command to be sent. > + @param[in] SecurityProtocolSpecificData > + The value of the "Security Protocol Speci= fic" > + parameter of the security protocol comman= d to be > + sent. > + @param[in] PayloadBufferSize > + Size in bytes of the payload data buffer. > + @param[out] PayloadBuffer A pointer to a destination buffer to stor= e > the > + security protocol command specific payloa= d data > + for the security protocol command. The ca= ller is > + responsible for having either implicit or= explicit > + ownership of the buffer. > + @param[out] PayloadTransferSize > + A pointer to a buffer to store the size i= n bytes > + of the data written to the payload data b= uffer. > + > + @retval EFI_SUCCESS The security protocol command com= pleted > + successfully. > + @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too > small to > + store the available data from the= device. > + The PayloadBuffer contains the tr= uncated > + 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 exec= ute. > + > +**/ > +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 command > sent is > + defined by SecurityProtocolId and contains the security protocol speci= fic > data > + SecurityProtocolSpecificData. If the underlying protocol command requi= res > 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 functi= on > 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 funct= ion > 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 t= he > execution > + of the security protocol command. A Timeo= ut value > + of 0 means that this function will wait i= ndefinitely > + for the security protocol command to exec= ute. If > + Timeout is greater than zero, then this f= unction > + will return EFI_TIMEOUT if the time requi= red to > + execute the receive data command is great= er than > + Timeout. > + @param[in] SecurityProtocolId > + The value of the "Security Protocol" para= meter of > + the security protocol command to be sent. > + @param[in] SecurityProtocolSpecificData > + The value of the "Security Protocol Speci= fic" > + parameter of the security protocol comman= d to be > + sent. > + @param[in] PayloadBufferSize Size in bytes of the payload data buffer. > + @param[in] PayloadBuffer A pointer to a destination buffer to stor= e the > + security protocol command specific payloa= d data > + for the security protocol command. > + > + @retval EFI_SUCCESS The security protocol command complet= ed > successfully. > + @retval EFI_UNSUPPORTED The given DeviceIndex does not suppor= t > 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 =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