--- /dev/null
+/** @file\r
+ The device path help function.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions\r
+ of the BSD License which accompanies this distribution. The\r
+ full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "NvmExpressPei.h"\r
+\r
+//\r
+// Template for an Nvm Express Device Path node\r
+//\r
+NVME_NAMESPACE_DEVICE_PATH mNvmeDevicePathNodeTemplate = {\r
+ { // Header\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_NVME_NAMESPACE_DP,\r
+ {\r
+ (UINT8) (sizeof (NVME_NAMESPACE_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (NVME_NAMESPACE_DEVICE_PATH)) >> 8)\r
+ }\r
+ },\r
+ 0x0, // NamespaceId\r
+ 0x0 // NamespaceUuid\r
+};\r
+\r
+//\r
+// Template for an End of entire Device Path node\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL mNvmeEndDevicePathNodeTemplate = {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ {\r
+ (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
+ (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)\r
+ }\r
+};\r
+\r
+/**\r
+ Returns the 16-bit Length field of a device path node.\r
+\r
+ Returns the 16-bit Length field of the device path node specified by Node.\r
+ Node is not required to be aligned on a 16-bit boundary, so it is recommended\r
+ that a function such as ReadUnaligned16() be used to extract the contents of\r
+ the Length field.\r
+\r
+ If Node is NULL, then ASSERT().\r
+\r
+ @param Node A pointer to a device path node data structure.\r
+\r
+ @return The 16-bit Length field of the device path node specified by Node.\r
+\r
+**/\r
+UINTN\r
+DevicePathNodeLength (\r
+ IN CONST VOID *Node\r
+ )\r
+{\r
+ ASSERT (Node != NULL);\r
+ return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);\r
+}\r
+\r
+/**\r
+ Returns a pointer to the next node in a device path.\r
+\r
+ If Node is NULL, then ASSERT().\r
+\r
+ @param Node A pointer to a device path node data structure.\r
+\r
+ @return a pointer to the device path node that follows the device path node\r
+ specified by Node.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+NextDevicePathNode (\r
+ IN CONST VOID *Node\r
+ )\r
+{\r
+ ASSERT (Node != NULL);\r
+ return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));\r
+}\r
+\r
+/**\r
+ Check the validity of the device path of a NVM Express host controller.\r
+\r
+ @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL\r
+ structure.\r
+ @param[in] DevicePathLength The length of the device path.\r
+\r
+ @retval EFI_SUCCESS The device path is valid.\r
+ @retval EFI_INVALID_PARAMETER The device path is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+NvmeIsHcDevicePathValid (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINTN DevicePathLength\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Start;\r
+ UINTN Size;\r
+\r
+ if (DevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Validate the DevicePathLength is big enough to touch the first node.\r
+ //\r
+ if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Start = DevicePath;\r
+ while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&\r
+ DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) {\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+\r
+ //\r
+ // Prevent overflow and invalid zero in the 'Length' field of a device path\r
+ // node.\r
+ //\r
+ if ((UINTN) DevicePath <= (UINTN) Start) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Prevent touching memory beyond given DevicePathLength.\r
+ //\r
+ if ((UINTN) DevicePath - (UINTN) Start >\r
+ DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check if the device path and its size match exactly with each other.\r
+ //\r
+ Size = ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+ if (Size != DevicePathLength) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build the device path for an Nvm Express device with given namespace identifier\r
+ and namespace extended unique identifier.\r
+\r
+ @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA\r
+ data structure.\r
+ @param[in] NamespaceId The given namespace identifier.\r
+ @param[in] NamespaceUuid The given namespace extended unique identifier.\r
+ @param[out] DevicePathLength The length of the device path in bytes specified\r
+ by DevicePath.\r
+ @param[out] DevicePath The device path of Nvm Express device.\r
+\r
+ @retval EFI_SUCCESS The operation succeeds.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+NvmeBuildDevicePath (\r
+ IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private,\r
+ IN UINT32 NamespaceId,\r
+ IN UINT64 NamespaceUuid,\r
+ OUT UINTN *DevicePathLength,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;\r
+ NVME_NAMESPACE_DEVICE_PATH *NvmeDeviceNode;\r
+\r
+ if (DevicePathLength == NULL || DevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *DevicePathLength = Private->DevicePathLength + sizeof (NVME_NAMESPACE_DEVICE_PATH);\r
+ *DevicePath = AllocatePool (*DevicePathLength);\r
+ if (*DevicePath == NULL) {\r
+ *DevicePathLength = 0;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Construct the host controller part device nodes\r
+ //\r
+ DevicePathWalker = *DevicePath;\r
+ CopyMem (\r
+ DevicePathWalker,\r
+ Private->DevicePath,\r
+ Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)\r
+ );\r
+\r
+ //\r
+ // Construct the Nvm Express device node\r
+ //\r
+ DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *)DevicePathWalker +\r
+ (Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)));\r
+ CopyMem (\r
+ DevicePathWalker,\r
+ &mNvmeDevicePathNodeTemplate,\r
+ sizeof (mNvmeDevicePathNodeTemplate)\r
+ );\r
+ NvmeDeviceNode = (NVME_NAMESPACE_DEVICE_PATH *)DevicePathWalker;\r
+ NvmeDeviceNode->NamespaceId = NamespaceId;\r
+ NvmeDeviceNode->NamespaceUuid = NamespaceUuid;\r
+\r
+ //\r
+ // Construct the end device node\r
+ //\r
+ DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *)DevicePathWalker +\r
+ sizeof (NVME_NAMESPACE_DEVICE_PATH));\r
+ CopyMem (\r
+ DevicePathWalker,\r
+ &mNvmeEndDevicePathNodeTemplate,\r
+ sizeof (mNvmeEndDevicePathNodeTemplate)\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
};\r
\r
EFI_PEI_PPI_DESCRIPTOR mNvmeBlkIo2PpiListTemplate = {\r
- EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
&gEfiPeiVirtualBlockIo2PpiGuid,\r
NULL\r
};\r
\r
+EFI_PEI_PPI_DESCRIPTOR mNvmeStorageSecurityPpiListTemplate = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEdkiiPeiStorageSecurityCommandPpiGuid,\r
+ NULL\r
+};\r
+\r
EFI_PEI_NOTIFY_DESCRIPTOR mNvmeEndOfPeiNotifyListTemplate = {\r
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
&gEfiEndOfPeiSignalPpiGuid,\r
PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;\r
\r
Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);\r
- NvmeDisableController (Private);\r
- NvmeFreeControllerResource (Private);\r
+ NvmeFreeDmaResource (Private);\r
\r
return EFI_SUCCESS;\r
}\r
EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;\r
UINT8 Controller;\r
UINTN MmioBase;\r
+ UINTN DevicePathLength;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;\r
EFI_PHYSICAL_ADDRESS DeviceAddress;\r
\r
+ DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));\r
+\r
//\r
// Locate the NVME host controller PPI\r
//\r
break;\r
}\r
\r
+ Status = NvmeHcPpi->GetNvmeHcDevicePath (\r
+ NvmeHcPpi,\r
+ Controller,\r
+ &DevicePathLength,\r
+ &DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR, "%a: Fail to allocate get the device path for Controller %d.\n",\r
+ __FUNCTION__, Controller\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check validity of the device path of the NVM Express controller.\r
+ //\r
+ Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR, "%a: The device path is invalid for Controller %d.\n",\r
+ __FUNCTION__, Controller\r
+ ));\r
+ Controller++;\r
+ continue;\r
+ }\r
+\r
//\r
// Memory allocation for controller private data\r
//\r
Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));\r
if (Private == NULL) {\r
DEBUG ((\r
- DEBUG_ERROR,\r
- "%a: Fail to allocate private data for Controller %d.\n",\r
- __FUNCTION__,\r
- Controller\r
+ DEBUG_ERROR, "%a: Fail to allocate private data for Controller %d.\n",\r
+ __FUNCTION__, Controller\r
));\r
return EFI_OUT_OF_RESOURCES;\r
}\r
);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((\r
- DEBUG_ERROR,\r
- "%a: Fail to allocate DMA buffers for Controller %d.\n",\r
- __FUNCTION__,\r
- Controller\r
+ DEBUG_ERROR, "%a: Fail to allocate DMA buffers for Controller %d.\n",\r
+ __FUNCTION__, Controller\r
));\r
- NvmeFreeControllerResource (Private);\r
return Status;\r
}\r
ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Private->Buffer));\r
//\r
// Initialize controller private data\r
//\r
- Private->Signature = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;\r
- Private->MmioBase = MmioBase;\r
- Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;\r
- Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;\r
- Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;\r
- Private->BlkIo2Ppi.Revision = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;\r
- Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;\r
- Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;\r
- Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;\r
- CopyMem (&Private->BlkIoPpiList, &mNvmeBlkIoPpiListTemplate, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
- CopyMem (&Private->BlkIo2PpiList, &mNvmeBlkIo2PpiListTemplate, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
- CopyMem (&Private->EndOfPeiNotifyList, &mNvmeEndOfPeiNotifyListTemplate, sizeof (EFI_PEI_NOTIFY_DESCRIPTOR));\r
- Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;\r
- Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;\r
+ Private->Signature = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;\r
+ Private->MmioBase = MmioBase;\r
+ Private->DevicePathLength = DevicePathLength;\r
+ Private->DevicePath = DevicePath;\r
\r
//\r
// Initialize the NVME controller\r
DEBUG ((\r
DEBUG_ERROR,\r
"%a: Controller initialization fail for Controller %d with Status - %r.\n",\r
- __FUNCTION__,\r
- Controller,\r
- Status\r
+ __FUNCTION__, Controller, Status\r
));\r
- NvmeFreeControllerResource (Private);\r
+ NvmeFreeDmaResource (Private);\r
Controller++;\r
continue;\r
}\r
DEBUG ((\r
DEBUG_ERROR,\r
"%a: Namespaces discovery fail for Controller %d with Status - %r.\n",\r
- __FUNCTION__,\r
- Controller,\r
- Status\r
+ __FUNCTION__, Controller, Status\r
));\r
- NvmeFreeControllerResource (Private);\r
+ NvmeFreeDmaResource (Private);\r
Controller++;\r
continue;\r
}\r
\r
+ Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;\r
+ Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;\r
+ Private->BlkIoPpi.ReadBlocks = NvmeBlockIoPeimReadBlocks;\r
+ CopyMem (\r
+ &Private->BlkIoPpiList,\r
+ &mNvmeBlkIoPpiListTemplate,\r
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
+ );\r
+ Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;\r
+\r
+ Private->BlkIo2Ppi.Revision = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;\r
+ Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;\r
+ Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;\r
+ Private->BlkIo2Ppi.ReadBlocks = NvmeBlockIoPeimReadBlocks2;\r
+ CopyMem (\r
+ &Private->BlkIo2PpiList,\r
+ &mNvmeBlkIo2PpiListTemplate,\r
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
+ );\r
+ Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;\r
PeiServicesInstallPpi (&Private->BlkIoPpiList);\r
- PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);\r
+\r
+ //\r
+ // Check if the NVME controller supports the Security Receive/Send commands\r
+ //\r
+ if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: Security Security Command PPI will be produced for Controller %d.\n",\r
+ __FUNCTION__, Controller\r
+ ));\r
+ Private->StorageSecurityPpi.Revision = EDKII_STORAGE_SECURITY_PPI_REVISION;\r
+ Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;\r
+ Private->StorageSecurityPpi.GetDevicePath = NvmeStorageSecurityGetDevicePath;\r
+ Private->StorageSecurityPpi.ReceiveData = NvmeStorageSecurityReceiveData;\r
+ Private->StorageSecurityPpi.SendData = NvmeStorageSecuritySendData;\r
+ CopyMem (\r
+ &Private->StorageSecurityPpiList,\r
+ &mNvmeStorageSecurityPpiListTemplate,\r
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
+ );\r
+ Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;\r
+ PeiServicesInstallPpi (&Private->StorageSecurityPpiList);\r
+ }\r
+\r
+ CopyMem (\r
+ &Private->EndOfPeiNotifyList,\r
+ &mNvmeEndOfPeiNotifyListTemplate,\r
+ sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)\r
+ );\r
+ PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);\r
+\r
DEBUG ((\r
- DEBUG_INFO,\r
- "%a: BlockIO PPI has been installed on Controller %d.\n",\r
- __FUNCTION__,\r
- Controller\r
+ DEBUG_INFO, "%a: Controller %d has been successfully initialized.\n",\r
+ __FUNCTION__, Controller\r
));\r
Controller++;\r
}\r
#include <Ppi/NvmExpressHostController.h>\r
#include <Ppi/BlockIo.h>\r
#include <Ppi/BlockIo2.h>\r
+#include <Ppi/StorageSecurityCommand.h>\r
#include <Ppi/IoMmu.h>\r
#include <Ppi/EndOfPeiPhase.h>\r
\r
#include "NvmExpressPeiHci.h"\r
#include "NvmExpressPeiPassThru.h"\r
#include "NvmExpressPeiBlockIo.h"\r
+#include "NvmExpressPeiStorageSecurity.h"\r
\r
//\r
// NVME PEI driver implementation related definitions\r
struct _PEI_NVME_CONTROLLER_PRIVATE_DATA {\r
UINT32 Signature;\r
UINTN MmioBase;\r
+ UINTN DevicePathLength;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi;\r
EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi;\r
+ EDKII_PEI_STORAGE_SECURITY_CMD_PPI StorageSecurityPpi;\r
EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList;\r
EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList;\r
+ EFI_PEI_PPI_DESCRIPTOR StorageSecurityPpiList;\r
EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList;\r
\r
//\r
PEI_NVME_NAMESPACE_INFO *NamespaceInfo;\r
};\r
\r
-#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO(a) \\r
+#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO(a) \\r
CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, BlkIoPpi, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)\r
-#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2(a) \\r
+#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2(a) \\r
CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, BlkIo2Ppi, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)\r
-#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) \\r
+#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY(a) \\r
+ CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, StorageSecurityPpi, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)\r
+#define GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) \\r
CR (a, PEI_NVME_CONTROLLER_PRIVATE_DATA, EndOfPeiNotifyList, NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE)\r
\r
\r
IN VOID *Ppi\r
);\r
\r
+/**\r
+ Check the validity of the device path of a NVM Express host controller.\r
+\r
+ @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL\r
+ structure.\r
+ @param[in] DevicePathLength The length of the device path.\r
+\r
+ @retval EFI_SUCCESS The device path is valid.\r
+ @retval EFI_INVALID_PARAMETER The device path is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+NvmeIsHcDevicePathValid (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINTN DevicePathLength\r
+ );\r
+\r
+/**\r
+ Build the device path for an Nvm Express device with given namespace identifier\r
+ and namespace extended unique identifier.\r
+\r
+ @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA\r
+ data structure.\r
+ @param[in] NamespaceId The given namespace identifier.\r
+ @param[in] NamespaceUuid The given namespace extended unique identifier.\r
+ @param[out] DevicePathLength The length of the device path in bytes specified\r
+ by DevicePath.\r
+ @param[out] DevicePath The device path of Nvm Express device.\r
+\r
+ @retval EFI_SUCCESS The operation succeeds.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+NvmeBuildDevicePath (\r
+ IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private,\r
+ IN UINT32 NamespaceId,\r
+ IN UINT64 NamespaceUuid,\r
+ OUT UINTN *DevicePathLength,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ );\r
+\r
#endif\r
# The NvmExpressPei driver is used to manage non-volatile memory subsystem\r
# which follows NVM Express specification at PEI phase.\r
#\r
-# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
#\r
# This program and the accompanying materials\r
# are licensed and made available under the terms and conditions of the BSD License\r
#\r
\r
[Sources]\r
+ DevicePath.c\r
DmaMem.c\r
NvmExpressPei.c\r
NvmExpressPei.h\r
NvmExpressPeiHci.h\r
NvmExpressPeiPassThru.c\r
NvmExpressPeiPassThru.h\r
+ NvmExpressPeiStorageSecurity.c\r
+ NvmExpressPeiStorageSecurity.h\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
PeimEntryPoint\r
\r
[Ppis]\r
- gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES\r
- gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES\r
gEdkiiPeiNvmExpressHostControllerPpiGuid ## CONSUMES\r
gEdkiiIoMmuPpiGuid ## CONSUMES\r
gEfiEndOfPeiSignalPpiGuid ## CONSUMES\r
+ gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES\r
+ gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES\r
+ gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES\r
\r
[Depex]\r
gEfiPeiMemoryDiscoveredPpiGuid AND\r
The NvmExpressPei driver is used to manage non-volatile memory subsystem\r
which follows NVM Express specification at PEI phase.\r
\r
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
}\r
\r
/**\r
- Free the resources allocated by an NVME controller.\r
+ Free the DMA resources allocated by an NVME controller.\r
\r
@param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.\r
\r
**/\r
VOID\r
-NvmeFreeControllerResource (\r
+NvmeFreeDmaResource (\r
IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private\r
)\r
{\r
- //\r
- // Free the controller data buffer\r
- //\r
- if (Private->ControllerData != NULL) {\r
- FreePool (Private->ControllerData);\r
- Private->ControllerData = NULL;\r
- }\r
+ ASSERT (Private != NULL);\r
\r
- //\r
- // Free the DMA buffers\r
- //\r
- if (Private->Buffer != NULL) {\r
+ if (Private->BufferMapping != NULL) {\r
IoMmuFreeBuffer (\r
NVME_MEM_MAX_PAGES,\r
Private->Buffer,\r
Private->BufferMapping\r
);\r
- Private->Buffer = NULL;\r
}\r
\r
- //\r
- // Free the namespaces information buffer\r
- //\r
- if (Private->NamespaceInfo != NULL) {\r
- FreePool (Private->NamespaceInfo);\r
- Private->NamespaceInfo = NULL;\r
- }\r
-\r
- //\r
- // Free the controller private data structure\r
- //\r
- FreePool (Private);\r
return;\r
}\r
The NvmExpressPei driver is used to manage non-volatile memory subsystem\r
which follows NVM Express specification at PEI phase.\r
\r
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
IN UINTN BaseMemIndex\r
);\r
\r
-/**\r
- Disable the Nvm Express controller.\r
-\r
- @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.\r
-\r
- @return EFI_SUCCESS Successfully disable the controller.\r
- @return others Fail to disable the controller.\r
-\r
-**/\r
-EFI_STATUS\r
-NvmeDisableController (\r
- IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private\r
- );\r
-\r
/**\r
Initialize the Nvm Express controller.\r
\r
);\r
\r
/**\r
- Free the resources allocated by an NVME controller.\r
+ Free the DMA resources allocated by an NVME controller.\r
\r
@param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.\r
\r
**/\r
VOID\r
-NvmeFreeControllerResource (\r
+NvmeFreeDmaResource (\r
IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private\r
);\r
\r
--- /dev/null
+/** @file\r
+ The NvmExpressPei driver is used to manage non-volatile memory subsystem\r
+ which follows NVM Express specification at PEI phase.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions\r
+ of the BSD License which accompanies this distribution. The\r
+ full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "NvmExpressPei.h"\r
+\r
+/**\r
+ Trust transfer data from/to NVM Express device.\r
+\r
+ This function performs one NVMe transaction to do a trust transfer from/to NVM\r
+ Express device.\r
+\r
+ @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA\r
+ data structure.\r
+ @param[in,out] Buffer The pointer to the current transaction buffer.\r
+ @param[in] SecurityProtocolId\r
+ The value of the "Security Protocol" parameter\r
+ of the security protocol command to be sent.\r
+ @param[in] SecurityProtocolSpecificData\r
+ The value of the "Security Protocol Specific"\r
+ parameter of the security protocol command to\r
+ be sent.\r
+ @param[in] TransferLength The block number or sector count of the transfer.\r
+ @param[in] IsTrustSend Indicates whether it is a trust send operation\r
+ or not.\r
+ @param[in] Timeout The timeout, in 100ns units, to use for the\r
+ execution of the security protocol command.\r
+ A Timeout value of 0 means that this function\r
+ will wait indefinitely for the security protocol\r
+ command to execute. If Timeout is greater than\r
+ zero, then this function will return EFI_TIMEOUT\r
+ if the time required to execute the receive\r
+ data command is greater than Timeout.\r
+ @param[out] TransferLengthOut A pointer to a buffer to store the size in bytes\r
+ of the data written to the buffer. Ignore it\r
+ when IsTrustSend is TRUE.\r
+\r
+ @retval EFI_SUCCESS The data transfer is complete successfully.\r
+ @return others Some error occurs when transferring data.\r
+\r
+**/\r
+EFI_STATUS\r
+TrustTransferNvmeDevice (\r
+ IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private,\r
+ IN OUT VOID *Buffer,\r
+ IN UINT8 SecurityProtocolId,\r
+ IN UINT16 SecurityProtocolSpecificData,\r
+ IN UINTN TransferLength,\r
+ IN BOOLEAN IsTrustSend,\r
+ IN UINT64 Timeout,\r
+ OUT UINTN *TransferLengthOut\r
+ )\r
+{\r
+ EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;\r
+ EDKII_PEI_NVM_EXPRESS_COMMAND Command;\r
+ EDKII_PEI_NVM_EXPRESS_COMPLETION Completion;\r
+ EFI_STATUS Status;\r
+ UINT16 SpecificData;\r
+\r
+ ZeroMem (&CommandPacket, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
+ ZeroMem (&Command, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND));\r
+ ZeroMem (&Completion, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION));\r
+\r
+ CommandPacket.NvmeCmd = &Command;\r
+ CommandPacket.NvmeCompletion = &Completion;\r
+\r
+ //\r
+ // Change Endianness of SecurityProtocolSpecificData\r
+ //\r
+ SpecificData = (((SecurityProtocolSpecificData << 8) & 0xFF00) | (SecurityProtocolSpecificData >> 8));\r
+\r
+ if (IsTrustSend) {\r
+ Command.Cdw0.Opcode = NVME_ADMIN_SECURITY_SEND_CMD;\r
+ CommandPacket.TransferBuffer = Buffer;\r
+ CommandPacket.TransferLength = (UINT32)TransferLength;\r
+ CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) | (SpecificData << 8));\r
+ CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;\r
+ } else {\r
+ Command.Cdw0.Opcode = NVME_ADMIN_SECURITY_RECEIVE_CMD;\r
+ CommandPacket.TransferBuffer = Buffer;\r
+ CommandPacket.TransferLength = (UINT32)TransferLength;\r
+ CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) | (SpecificData << 8));\r
+ CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;\r
+ }\r
+\r
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
+ CommandPacket.NvmeCmd->Nsid = NVME_CONTROLLER_NSID;\r
+ CommandPacket.CommandTimeout = Timeout;\r
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;\r
+\r
+ Status = NvmePassThru (\r
+ Private,\r
+ NVME_CONTROLLER_NSID,\r
+ &CommandPacket\r
+ );\r
+\r
+ if (!IsTrustSend) {\r
+ if (EFI_ERROR (Status)) {\r
+ *TransferLengthOut = 0;\r
+ } else {\r
+ *TransferLengthOut = (UINTN) TransferLength;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Gets the count of storage security devices that one specific driver detects.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[out] NumberofDevices The number of storage security devices discovered.\r
+\r
+ @retval EFI_SUCCESS The operation performed successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecurityGetDeviceNo (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ OUT UINTN *NumberofDevices\r
+ )\r
+{\r
+ PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+\r
+ if (This == NULL || NumberofDevices == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This);\r
+ *NumberofDevices = Private->ActiveNamespaceNum;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Gets the device path of a specific storage security device.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[in] DeviceIndex Specifies the storage security device to which\r
+ the function wants to talk. Because the driver\r
+ that implements Storage Security Command PPIs\r
+ will manage multiple storage devices, the PPIs\r
+ that want to talk to a single device must specify\r
+ the device index that was assigned during the\r
+ enumeration process. This index is a number from\r
+ one to NumberofDevices.\r
+ @param[out] DevicePathLength The length of the device path in bytes specified\r
+ by DevicePath.\r
+ @param[out] DevicePath The device path of storage security device.\r
+ This field re-uses EFI Device Path Protocol as\r
+ defined by Section 10.2 EFI Device Path Protocol\r
+ of UEFI 2.7 Specification.\r
+\r
+ @retval EFI_SUCCESS The operation succeeds.\r
+ @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL.\r
+ @retval EFI_NOT_FOUND The specified storage security device not found.\r
+ @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecurityGetDevicePath (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ IN UINTN DeviceIndex,\r
+ OUT UINTN *DevicePathLength,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ )\r
+{\r
+ PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+\r
+ if (This == NULL || DevicePathLength == NULL || DevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This);\r
+ if ((DeviceIndex == 0) || (DeviceIndex > Private->ActiveNamespaceNum)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return NvmeBuildDevicePath (\r
+ Private,\r
+ Private->NamespaceInfo[DeviceIndex-1].NamespaceId,\r
+ Private->NamespaceInfo[DeviceIndex-1].NamespaceUuid,\r
+ DevicePathLength,\r
+ DevicePath\r
+ );\r
+}\r
+\r
+/**\r
+ Send a security protocol command to a device that receives data and/or the result\r
+ of one or more commands sent by SendData.\r
+\r
+ The ReceiveData function sends a security protocol command to the given DeviceIndex.\r
+ The security protocol command sent is defined by SecurityProtocolId and contains\r
+ the security protocol specific data SecurityProtocolSpecificData. The function\r
+ returns the data from the security protocol command in PayloadBuffer.\r
+\r
+ For devices supporting the SCSI command set, the security protocol command is sent\r
+ using the SECURITY PROTOCOL IN command defined in SPC-4.\r
+\r
+ For devices supporting the ATA command set, the security protocol command is sent\r
+ using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize\r
+ is non-zero.\r
+\r
+ If the PayloadBufferSize is zero, the security protocol command is sent using the\r
+ Trusted Non-Data command defined in ATA8-ACS.\r
+\r
+ If PayloadBufferSize is too small to store the available data from the security\r
+ protocol command, the function shall copy PayloadBufferSize bytes into the\r
+ PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.\r
+\r
+ If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,\r
+ the function shall return EFI_INVALID_PARAMETER.\r
+\r
+ If the given DeviceIndex does not support security protocol commands, the function\r
+ shall return EFI_UNSUPPORTED.\r
+\r
+ If the security protocol fails to complete within the Timeout period, the function\r
+ shall return EFI_TIMEOUT.\r
+\r
+ If the security protocol command completes without an error, the function shall\r
+ return EFI_SUCCESS. If the security protocol command completes with an error, the\r
+ function shall return EFI_DEVICE_ERROR.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[in] DeviceIndex Specifies the storage security device to which the\r
+ function wants to talk. Because the driver that\r
+ implements Storage Security Command PPIs will manage\r
+ multiple storage devices, the PPIs that want to talk\r
+ to a single device must specify the device index\r
+ that was assigned during the enumeration process.\r
+ This index is a number from one to NumberofDevices.\r
+ @param[in] Timeout The timeout, in 100ns units, to use for the execution\r
+ of the security protocol command. A Timeout value\r
+ of 0 means that this function will wait indefinitely\r
+ for the security protocol command to execute. If\r
+ Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the receive data command is greater than\r
+ Timeout.\r
+ @param[in] SecurityProtocolId\r
+ The value of the "Security Protocol" parameter of\r
+ the security protocol command to be sent.\r
+ @param[in] SecurityProtocolSpecificData\r
+ The value of the "Security Protocol Specific"\r
+ parameter of the security protocol command to be\r
+ sent.\r
+ @param[in] PayloadBufferSize\r
+ Size in bytes of the payload data buffer.\r
+ @param[out] PayloadBuffer A pointer to a destination buffer to store the\r
+ security protocol command specific payload data\r
+ for the security protocol command. The caller is\r
+ responsible for having either implicit or explicit\r
+ ownership of the buffer.\r
+ @param[out] PayloadTransferSize\r
+ A pointer to a buffer to store the size in bytes\r
+ of the data written to the payload data buffer.\r
+\r
+ @retval EFI_SUCCESS The security protocol command completed\r
+ successfully.\r
+ @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to\r
+ store the available data from the device.\r
+ The PayloadBuffer contains the truncated\r
+ data.\r
+ @retval EFI_UNSUPPORTED The given DeviceIndex does not support\r
+ security protocol commands.\r
+ @retval EFI_DEVICE_ERROR The security protocol command completed\r
+ with an error.\r
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize\r
+ is NULL and PayloadBufferSize is non-zero.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
+ security protocol command to execute.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecurityReceiveData (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ IN UINTN DeviceIndex,\r
+ IN UINT64 Timeout,\r
+ IN UINT8 SecurityProtocolId,\r
+ IN UINT16 SecurityProtocolSpecificData,\r
+ IN UINTN PayloadBufferSize,\r
+ OUT VOID *PayloadBuffer,\r
+ OUT UINTN *PayloadTransferSize\r
+ )\r
+{\r
+ PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+\r
+ if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) || (PayloadBufferSize == 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This);\r
+\r
+ Status = TrustTransferNvmeDevice (\r
+ Private,\r
+ PayloadBuffer,\r
+ SecurityProtocolId,\r
+ SecurityProtocolSpecificData,\r
+ PayloadBufferSize,\r
+ FALSE,\r
+ Timeout,\r
+ PayloadTransferSize\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Send a security protocol command to a device.\r
+\r
+ The SendData function sends a security protocol command containing the payload\r
+ PayloadBuffer to the given DeviceIndex. The security protocol command sent is\r
+ defined by SecurityProtocolId and contains the security protocol specific data\r
+ SecurityProtocolSpecificData. If the underlying protocol command requires a\r
+ specific padding for the command payload, the SendData function shall add padding\r
+ bytes to the command payload to satisfy the padding requirements.\r
+\r
+ For devices supporting the SCSI command set, the security protocol command is\r
+ sent using the SECURITY PROTOCOL OUT command defined in SPC-4.\r
+\r
+ For devices supporting the ATA command set, the security protocol command is\r
+ sent using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize\r
+ is non-zero. If the PayloadBufferSize is zero, the security protocol command\r
+ is sent using the Trusted Non-Data command defined in ATA8-ACS.\r
+\r
+ If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall\r
+ return EFI_INVALID_PARAMETER.\r
+\r
+ If the given DeviceIndex does not support security protocol commands, the function\r
+ shall return EFI_UNSUPPORTED.\r
+\r
+ If the security protocol fails to complete within the Timeout period, the function\r
+ shall return EFI_TIMEOUT.\r
+\r
+ If the security protocol command completes without an error, the function shall\r
+ return EFI_SUCCESS. If the security protocol command completes with an error,\r
+ the functio shall return EFI_DEVICE_ERROR.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[in] DeviceIndex The ID of the device.\r
+ @param[in] Timeout The timeout, in 100ns units, to use for the execution\r
+ of the security protocol command. A Timeout value\r
+ of 0 means that this function will wait indefinitely\r
+ for the security protocol command to execute. If\r
+ Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the receive data command is greater than\r
+ Timeout.\r
+ @param[in] SecurityProtocolId\r
+ The value of the "Security Protocol" parameter of\r
+ the security protocol command to be sent.\r
+ @param[in] SecurityProtocolSpecificData\r
+ The value of the "Security Protocol Specific"\r
+ parameter of the security protocol command to be\r
+ sent.\r
+ @param[in] PayloadBufferSize Size in bytes of the payload data buffer.\r
+ @param[in] PayloadBuffer A pointer to a destination buffer to store the\r
+ security protocol command specific payload data\r
+ for the security protocol command.\r
+\r
+ @retval EFI_SUCCESS The security protocol command completed successfully.\r
+ @retval EFI_UNSUPPORTED The given DeviceIndex does not support security\r
+ protocol commands.\r
+ @retval EFI_DEVICE_ERROR The security protocol command completed with\r
+ an error.\r
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize\r
+ is non-zero.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
+ protocol command to execute.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecuritySendData (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ IN UINTN DeviceIndex,\r
+ IN UINT64 Timeout,\r
+ IN UINT8 SecurityProtocolId,\r
+ IN UINT16 SecurityProtocolSpecificData,\r
+ IN UINTN PayloadBufferSize,\r
+ IN VOID *PayloadBuffer\r
+ )\r
+{\r
+ PEI_NVME_CONTROLLER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+\r
+ if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This);\r
+\r
+ Status = TrustTransferNvmeDevice (\r
+ Private,\r
+ PayloadBuffer,\r
+ SecurityProtocolId,\r
+ SecurityProtocolSpecificData,\r
+ PayloadBufferSize,\r
+ TRUE,\r
+ Timeout,\r
+ NULL\r
+ );\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ The NvmExpressPei driver is used to manage non-volatile memory subsystem\r
+ which follows NVM Express specification at PEI phase.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions\r
+ of the BSD License which accompanies this distribution. The\r
+ full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _NVM_EXPRESS_PEI_STORAGE_SECURITY_H_\r
+#define _NVM_EXPRESS_PEI_STORAGE_SECURITY_H_\r
+\r
+/**\r
+ Gets the count of storage security devices that one specific driver detects.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[out] NumberofDevices The number of storage security devices discovered.\r
+\r
+ @retval EFI_SUCCESS The operation performed successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecurityGetDeviceNo (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ OUT UINTN *NumberofDevices\r
+ );\r
+\r
+/**\r
+ Gets the device path of a specific storage security device.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[in] DeviceIndex Specifies the storage security device to which\r
+ the function wants to talk. Because the driver\r
+ that implements Storage Security Command PPIs\r
+ will manage multiple storage devices, the PPIs\r
+ that want to talk to a single device must specify\r
+ the device index that was assigned during the\r
+ enumeration process. This index is a number from\r
+ one to NumberofDevices.\r
+ @param[out] DevicePathLength The length of the device path in bytes specified\r
+ by DevicePath.\r
+ @param[out] DevicePath The device path of storage security device.\r
+ This field re-uses EFI Device Path Protocol as\r
+ defined by Section 10.2 EFI Device Path Protocol\r
+ of UEFI 2.7 Specification.\r
+\r
+ @retval EFI_SUCCESS The operation succeeds.\r
+ @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL.\r
+ @retval EFI_NOT_FOUND The specified storage security device not found.\r
+ @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecurityGetDevicePath (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ IN UINTN DeviceIndex,\r
+ OUT UINTN *DevicePathLength,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ );\r
+\r
+/**\r
+ Send a security protocol command to a device that receives data and/or the result\r
+ of one or more commands sent by SendData.\r
+\r
+ The ReceiveData function sends a security protocol command to the given DeviceIndex.\r
+ The security protocol command sent is defined by SecurityProtocolId and contains\r
+ the security protocol specific data SecurityProtocolSpecificData. The function\r
+ returns the data from the security protocol command in PayloadBuffer.\r
+\r
+ For devices supporting the SCSI command set, the security protocol command is sent\r
+ using the SECURITY PROTOCOL IN command defined in SPC-4.\r
+\r
+ For devices supporting the ATA command set, the security protocol command is sent\r
+ using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize\r
+ is non-zero.\r
+\r
+ If the PayloadBufferSize is zero, the security protocol command is sent using the\r
+ Trusted Non-Data command defined in ATA8-ACS.\r
+\r
+ If PayloadBufferSize is too small to store the available data from the security\r
+ protocol command, the function shall copy PayloadBufferSize bytes into the\r
+ PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.\r
+\r
+ If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,\r
+ the function shall return EFI_INVALID_PARAMETER.\r
+\r
+ If the given DeviceIndex does not support security protocol commands, the function\r
+ shall return EFI_UNSUPPORTED.\r
+\r
+ If the security protocol fails to complete within the Timeout period, the function\r
+ shall return EFI_TIMEOUT.\r
+\r
+ If the security protocol command completes without an error, the function shall\r
+ return EFI_SUCCESS. If the security protocol command completes with an error, the\r
+ function shall return EFI_DEVICE_ERROR.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[in] DeviceIndex Specifies the storage security device to which the\r
+ function wants to talk. Because the driver that\r
+ implements Storage Security Command PPIs will manage\r
+ multiple storage devices, the PPIs that want to talk\r
+ to a single device must specify the device index\r
+ that was assigned during the enumeration process.\r
+ This index is a number from one to NumberofDevices.\r
+ @param[in] Timeout The timeout, in 100ns units, to use for the execution\r
+ of the security protocol command. A Timeout value\r
+ of 0 means that this function will wait indefinitely\r
+ for the security protocol command to execute. If\r
+ Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the receive data command is greater than\r
+ Timeout.\r
+ @param[in] SecurityProtocolId\r
+ The value of the "Security Protocol" parameter of\r
+ the security protocol command to be sent.\r
+ @param[in] SecurityProtocolSpecificData\r
+ The value of the "Security Protocol Specific"\r
+ parameter of the security protocol command to be\r
+ sent.\r
+ @param[in] PayloadBufferSize\r
+ Size in bytes of the payload data buffer.\r
+ @param[out] PayloadBuffer A pointer to a destination buffer to store the\r
+ security protocol command specific payload data\r
+ for the security protocol command. The caller is\r
+ responsible for having either implicit or explicit\r
+ ownership of the buffer.\r
+ @param[out] PayloadTransferSize\r
+ A pointer to a buffer to store the size in bytes\r
+ of the data written to the payload data buffer.\r
+\r
+ @retval EFI_SUCCESS The security protocol command completed\r
+ successfully.\r
+ @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to\r
+ store the available data from the device.\r
+ The PayloadBuffer contains the truncated\r
+ data.\r
+ @retval EFI_UNSUPPORTED The given DeviceIndex does not support\r
+ security protocol commands.\r
+ @retval EFI_DEVICE_ERROR The security protocol command completed\r
+ with an error.\r
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize\r
+ is NULL and PayloadBufferSize is non-zero.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
+ security protocol command to execute.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecurityReceiveData (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ IN UINTN DeviceIndex,\r
+ IN UINT64 Timeout,\r
+ IN UINT8 SecurityProtocolId,\r
+ IN UINT16 SecurityProtocolSpecificData,\r
+ IN UINTN PayloadBufferSize,\r
+ OUT VOID *PayloadBuffer,\r
+ OUT UINTN *PayloadTransferSize\r
+ );\r
+\r
+/**\r
+ Send a security protocol command to a device.\r
+\r
+ The SendData function sends a security protocol command containing the payload\r
+ PayloadBuffer to the given DeviceIndex. The security protocol command sent is\r
+ defined by SecurityProtocolId and contains the security protocol specific data\r
+ SecurityProtocolSpecificData. If the underlying protocol command requires a\r
+ specific padding for the command payload, the SendData function shall add padding\r
+ bytes to the command payload to satisfy the padding requirements.\r
+\r
+ For devices supporting the SCSI command set, the security protocol command is\r
+ sent using the SECURITY PROTOCOL OUT command defined in SPC-4.\r
+\r
+ For devices supporting the ATA command set, the security protocol command is\r
+ sent using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize\r
+ is non-zero. If the PayloadBufferSize is zero, the security protocol command\r
+ is sent using the Trusted Non-Data command defined in ATA8-ACS.\r
+\r
+ If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall\r
+ return EFI_INVALID_PARAMETER.\r
+\r
+ If the given DeviceIndex does not support security protocol commands, the function\r
+ shall return EFI_UNSUPPORTED.\r
+\r
+ If the security protocol fails to complete within the Timeout period, the function\r
+ shall return EFI_TIMEOUT.\r
+\r
+ If the security protocol command completes without an error, the function shall\r
+ return EFI_SUCCESS. If the security protocol command completes with an error,\r
+ the functio shall return EFI_DEVICE_ERROR.\r
+\r
+ @param[in] This The PPI instance pointer.\r
+ @param[in] DeviceIndex The ID of the device.\r
+ @param[in] Timeout The timeout, in 100ns units, to use for the execution\r
+ of the security protocol command. A Timeout value\r
+ of 0 means that this function will wait indefinitely\r
+ for the security protocol command to execute. If\r
+ Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the receive data command is greater than\r
+ Timeout.\r
+ @param[in] SecurityProtocolId\r
+ The value of the "Security Protocol" parameter of\r
+ the security protocol command to be sent.\r
+ @param[in] SecurityProtocolSpecificData\r
+ The value of the "Security Protocol Specific"\r
+ parameter of the security protocol command to be\r
+ sent.\r
+ @param[in] PayloadBufferSize Size in bytes of the payload data buffer.\r
+ @param[in] PayloadBuffer A pointer to a destination buffer to store the\r
+ security protocol command specific payload data\r
+ for the security protocol command.\r
+\r
+ @retval EFI_SUCCESS The security protocol command completed successfully.\r
+ @retval EFI_UNSUPPORTED The given DeviceIndex does not support security\r
+ protocol commands.\r
+ @retval EFI_DEVICE_ERROR The security protocol command completed with\r
+ an error.\r
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize\r
+ is non-zero.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
+ protocol command to execute.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmeStorageSecuritySendData (\r
+ IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This,\r
+ IN UINTN DeviceIndex,\r
+ IN UINT64 Timeout,\r
+ IN UINT8 SecurityProtocolId,\r
+ IN UINT16 SecurityProtocolSpecificData,\r
+ IN UINTN PayloadBufferSize,\r
+ IN VOID *PayloadBuffer\r
+ );\r
+\r
+#endif\r