]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/NvmExpressDxe: Add SecurityStorageProtocol support
authorTian Feng <feng.tian@intel.com>
Tue, 16 Jun 2015 01:04:47 +0000 (01:04 +0000)
committererictian <erictian@Edk2>
Tue, 16 Jun 2015 01:04:47 +0000 (01:04 +0000)
Produce this protocol for each namespace at NVMe controller.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Tian Feng <feng.tian@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17638 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c

index d107d96387d8665e30fada5636ae93d7fa6b386f..9938bf45417e32f16d52fd0f13b12bc43a26ab04 100644 (file)
@@ -154,6 +154,12 @@ EnumerateNvmeDevNamespace (
     Device->BlockIo.WriteBlocks  = NvmeBlockIoWriteBlocks;\r
     Device->BlockIo.FlushBlocks  = NvmeBlockIoFlushBlocks;\r
 \r
+    //\r
+    // Create StorageSecurityProtocol Instance\r
+    //\r
+    Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;\r
+    Device->StorageSecurity.SendData    = NvmeStorageSecuritySendData;\r
+\r
     //\r
     // Create DiskInfo Protocol instance\r
     //\r
@@ -211,6 +217,32 @@ EnumerateNvmeDevNamespace (
     if(EFI_ERROR(Status)) {\r
       goto Exit;\r
     }\r
+\r
+    //\r
+    // Check if the NVMe controller supports the Security Send and Security Receive commands\r
+    //\r
+    if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {\r
+      Status = gBS->InstallProtocolInterface (\r
+                      &Device->DeviceHandle,\r
+                      &gEfiStorageSecurityCommandProtocolGuid,\r
+                      EFI_NATIVE_INTERFACE,\r
+                      &Device->StorageSecurity\r
+                      );\r
+      if(EFI_ERROR(Status)) {\r
+        gBS->UninstallMultipleProtocolInterfaces (\r
+               &Device->DeviceHandle,\r
+               &gEfiDevicePathProtocolGuid,\r
+               Device->DevicePath,\r
+               &gEfiBlockIoProtocolGuid,\r
+               &Device->BlockIo,\r
+               &gEfiDiskInfoProtocolGuid,\r
+               &Device->DiskInfo,\r
+               NULL\r
+               );\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
     gBS->OpenProtocol (\r
            Private->ControllerHandle,\r
            &gEfiNvmExpressPassThruProtocolGuid,\r
@@ -339,6 +371,7 @@ UnregisterNvmeNamespace (
   EFI_BLOCK_IO_PROTOCOL                    *BlockIo;\r
   NVME_DEVICE_PRIVATE_DATA                 *Device;\r
   NVME_CONTROLLER_PRIVATE_DATA             *Private;\r
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *StorageSecurity;\r
 \r
   BlockIo = NULL;\r
 \r
@@ -394,6 +427,37 @@ UnregisterNvmeNamespace (
     return Status;\r
   }\r
 \r
+  //\r
+  // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiStorageSecurityCommandProtocolGuid,\r
+                  (VOID **) &StorageSecurity,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->UninstallProtocolInterface (\r
+                    Handle,\r
+                    &gEfiStorageSecurityCommandProtocolGuid,\r
+                    &Device->StorageSecurity\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->OpenProtocol (\r
+        Controller,\r
+        &gEfiNvmExpressPassThruProtocolGuid,\r
+        (VOID **) &Private->Passthru,\r
+        This->DriverBindingHandle,\r
+        Handle,\r
+        EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+        );\r
+      return Status;\r
+    }\r
+  }\r
+\r
   if(Device->DevicePath != NULL) {\r
     FreePool (Device->DevicePath);\r
   }\r
@@ -480,8 +544,8 @@ NvmExpressDriverBindingSupported (
 \r
       if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||\r
           (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||\r
-           DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH)) {\r
-        return EFI_UNSUPPORTED;\r
+          (DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH))) {\r
+         return EFI_UNSUPPORTED;\r
       }\r
     }\r
   }\r
index 54baac6f004fc4a34b8344bc69d572ea63febb72..21c6255caac26cca81928b68e43a06998680b2b1 100644 (file)
@@ -30,6 +30,7 @@
 #include <Protocol/BlockIo.h>\r
 #include <Protocol/DiskInfo.h>\r
 #include <Protocol/DriverSupportedEfiVersion.h>\r
+#include <Protocol/StorageSecurityCommand.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
@@ -152,29 +153,30 @@ struct _NVME_CONTROLLER_PRIVATE_DATA {
 // Nvme device private data structure\r
 //\r
 struct _NVME_DEVICE_PRIVATE_DATA {\r
-  UINT32                            Signature;\r
+  UINT32                                   Signature;\r
 \r
-  EFI_HANDLE                        DeviceHandle;\r
-  EFI_HANDLE                        ControllerHandle;\r
-  EFI_HANDLE                        DriverBindingHandle;\r
+  EFI_HANDLE                               DeviceHandle;\r
+  EFI_HANDLE                               ControllerHandle;\r
+  EFI_HANDLE                               DriverBindingHandle;\r
 \r
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL                 *DevicePath;\r
 \r
-  EFI_UNICODE_STRING_TABLE          *ControllerNameTable;\r
+  EFI_UNICODE_STRING_TABLE                 *ControllerNameTable;\r
 \r
-  UINT32                            NamespaceId;\r
-  UINT64                            NamespaceUuid;\r
+  UINT32                                   NamespaceId;\r
+  UINT64                                   NamespaceUuid;\r
 \r
-  EFI_BLOCK_IO_MEDIA                Media;\r
-  EFI_BLOCK_IO_PROTOCOL             BlockIo;\r
-  EFI_DISK_INFO_PROTOCOL            DiskInfo;\r
+  EFI_BLOCK_IO_MEDIA                       Media;\r
+  EFI_BLOCK_IO_PROTOCOL                    BlockIo;\r
+  EFI_DISK_INFO_PROTOCOL                   DiskInfo;\r
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    StorageSecurity;\r
 \r
-  EFI_LBA                           NumBlocks;\r
+  EFI_LBA                                  NumBlocks;\r
 \r
-  CHAR16                            ModelName[80];\r
-  NVME_ADMIN_NAMESPACE_DATA         NamespaceData;\r
+  CHAR16                                   ModelName[80];\r
+  NVME_ADMIN_NAMESPACE_DATA                NamespaceData;\r
 \r
-  NVME_CONTROLLER_PRIVATE_DATA      *Controller;\r
+  NVME_CONTROLLER_PRIVATE_DATA             *Controller;\r
 \r
 };\r
 \r
@@ -195,6 +197,13 @@ struct _NVME_DEVICE_PRIVATE_DATA {
       NVME_DEVICE_PRIVATE_DATA_SIGNATURE \\r
       )\r
 \r
+#define NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY(a)\\r
+  CR (a,                                                 \\r
+      NVME_DEVICE_PRIVATE_DATA,                          \\r
+      StorageSecurity,                                   \\r
+      NVME_DEVICE_PRIVATE_DATA_SIGNATURE                 \\r
+      )\r
+\r
 /**\r
   Retrieves a Unicode string that is the user readable name of the driver.\r
 \r
index e7d76513221794326e79783360efebef514ff09c..6cb2f92e8dded76b4f42f0687e4094f09b7b56c8 100644 (file)
@@ -345,6 +345,10 @@ NvmeBlockIoReset (
 \r
   Status  = NvmeControllerInit (Private);\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r
@@ -555,3 +559,325 @@ NvmeBlockIoFlushBlocks (
 \r
   return Status;\r
 }\r
+\r
+/**\r
+  Trust transfer data from/to NVMe device.\r
+\r
+  This function performs one NVMe transaction to do a trust transfer from/to NVMe device.\r
+\r
+  @param  Private                      The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.\r
+  @param  Buffer                       The pointer to the current transaction buffer.\r
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of\r
+                                       the security protocol command to be sent.\r
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
+                                       of the security protocol command to be sent.\r
+  @param  TransferLength               The block number or sector count of the transfer.\r
+  @param  IsTrustSend                  Indicates whether it is a trust send operation or not.\r
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution\r
+                                       of the security protocol command. A Timeout value of 0\r
+                                       means that this function will wait indefinitely for the\r
+                                       security protocol command to execute. If Timeout is greater\r
+                                       than zero, then this function will return EFI_TIMEOUT\r
+                                       if the time required to execute the receive data command\r
+                                       is greater than Timeout.\r
+  @param  TransferLengthOut            A pointer to a buffer to store the size in bytes of the data\r
+                                       written to the buffer. Ignore it 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 OUT 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
+  EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;\r
+  EFI_NVM_EXPRESS_COMMAND                  Command;\r
+  EFI_NVM_EXPRESS_COMPLETION               Completion;\r
+  EFI_STATUS                               Status;\r
+  UINT16                                   SpecificData;\r
+\r
+  ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
+  ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));\r
+  ZeroMem (&Completion, sizeof (EFI_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_ID;\r
+  CommandPacket.CommandTimeout = Timeout;\r
+  CommandPacket.QueueType      = NVME_ADMIN_QUEUE;\r
+\r
+  Status = Private->Passthru.PassThru (\r
+                               &Private->Passthru,\r
+                               NVME_CONTROLLER_ID,\r
+                               &CommandPacket,\r
+                               NULL\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
+  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 MediaId.\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 MediaId does not support security protocol commands, the function shall\r
+  return EFI_UNSUPPORTED. If there is no media in the device, the function returns\r
+  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,\r
+  the function returns EFI_MEDIA_CHANGED.\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  This                         Indicates a pointer to the calling context.\r
+  @param  MediaId                      ID of the medium to receive data from.\r
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution\r
+                                       of the security protocol command. A Timeout value of 0\r
+                                       means that this function will wait indefinitely for the\r
+                                       security protocol command to execute. If Timeout is greater\r
+                                       than zero, then this function will return EFI_TIMEOUT\r
+                                       if the time required to execute the receive data command\r
+                                       is greater than Timeout.\r
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of\r
+                                       the security protocol command to be sent.\r
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
+                                       of the security protocol command to be sent.\r
+  @param  PayloadBufferSize            Size in bytes of the payload data buffer.\r
+  @param  PayloadBuffer                A pointer to a destination buffer to store the security\r
+                                       protocol command specific payload data for the security\r
+                                       protocol command. The caller is responsible for having\r
+                                       either implicit or explicit ownership of the buffer.\r
+  @param  PayloadTransferSize          A pointer to a buffer to store the size in bytes of the\r
+                                       data written to the payload data buffer.\r
+\r
+  @retval EFI_SUCCESS                  The security protocol command completed successfully.\r
+  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too small to store the available\r
+                                       data from the device. The PayloadBuffer contains the truncated data.\r
+  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.\r
+  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.\r
+  @retval EFI_NO_MEDIA                 There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.\r
+  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or PayloadTransferSize is NULL and\r
+                                       PayloadBufferSize 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
+NvmeStorageSecurityReceiveData (\r
+  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,\r
+  IN  UINT32                                   MediaId,\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
+  EFI_STATUS                       Status;\r
+  NVME_DEVICE_PRIVATE_DATA         *Device;\r
+  \r
+  Status  = EFI_SUCCESS;\r
+\r
+  if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) || (PayloadBufferSize == 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);\r
+\r
+  if (MediaId != Device->BlockIo.Media->MediaId) {\r
+    return EFI_MEDIA_CHANGED;\r
+  }\r
+\r
+  if (!Device->BlockIo.Media->MediaPresent) {\r
+    return EFI_NO_MEDIA;\r
+  }\r
+\r
+  Status = TrustTransferNvmeDevice (\r
+             Device->Controller,\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 MediaId. 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 sent\r
+  using the SECURITY PROTOCOL OUT 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 SEND commands defined in ATA8-ACS if PayloadBufferSize\r
+  is non-zero. If the PayloadBufferSize is zero, the security protocol command is\r
+  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 MediaId does not support security protocol commands, the function\r
+  shall return EFI_UNSUPPORTED. If there is no media in the device, the function\r
+  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the\r
+  device, the function returns EFI_MEDIA_CHANGED.\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 return\r
+  EFI_SUCCESS. If the security protocol command completes with an error, the function\r
+  shall return EFI_DEVICE_ERROR.\r
+\r
+  @param  This                         Indicates a pointer to the calling context.\r
+  @param  MediaId                      ID of the medium to receive data from.\r
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution\r
+                                       of the security protocol command. A Timeout value of 0\r
+                                       means that this function will wait indefinitely for the\r
+                                       security protocol command to execute. If Timeout is greater\r
+                                       than zero, then this function will return EFI_TIMEOUT\r
+                                       if the time required to execute the send data command\r
+                                       is greater than Timeout.\r
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of\r
+                                       the security protocol command to be sent.\r
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
+                                       of the security protocol command to be sent.\r
+  @param  PayloadBufferSize            Size in bytes of the payload data buffer.\r
+  @param  PayloadBuffer                A pointer to a destination buffer to store the security\r
+                                       protocol command specific payload data for the security\r
+                                       protocol command.\r
+\r
+  @retval EFI_SUCCESS                  The security protocol command completed successfully.\r
+  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.\r
+  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.\r
+  @retval EFI_NO_MEDIA                 There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.\r
+  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and PayloadBufferSize 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 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,\r
+  IN UINT32                                   MediaId,\r
+  IN UINT64                                   Timeout,\r
+  IN UINT8                                    SecurityProtocolId,\r
+  IN UINT16                                   SecurityProtocolSpecificData,\r
+  IN UINTN                                    PayloadBufferSize,\r
+  IN VOID                                     *PayloadBuffer\r
+  )\r
+{\r
+  EFI_STATUS                       Status; \r
+  NVME_DEVICE_PRIVATE_DATA         *Device;\r
+\r
+  Status  = EFI_SUCCESS;\r
+\r
+  if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);\r
+\r
+  if (MediaId != Device->BlockIo.Media->MediaId) {\r
+    return EFI_MEDIA_CHANGED;\r
+  }\r
+\r
+  if (!Device->BlockIo.Media->MediaPresent) {\r
+    return EFI_NO_MEDIA;\r
+  }\r
+\r
+  Status = TrustTransferNvmeDevice (\r
+             Device->Controller,\r
+             PayloadBuffer,\r
+             SecurityProtocolId,\r
+             SecurityProtocolSpecificData,\r
+             PayloadBufferSize,\r
+             TRUE,\r
+             Timeout,\r
+             NULL\r
+             );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+\r
index 5f896fed816e6924f36aac290245932c21fb9cd2..1c71a81ec5ac7bccb35fe6c34f77965c47b99cd5 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for EFI_BLOCK_IO_PROTOCOL interface.\r
 \r
-Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -108,4 +108,162 @@ NvmeBlockIoFlushBlocks (
   IN  EFI_BLOCK_IO_PROTOCOL   *This\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 MediaId.\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 MediaId does not support security protocol commands, the function shall\r
+  return EFI_UNSUPPORTED. If there is no media in the device, the function returns\r
+  EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,\r
+  the function returns EFI_MEDIA_CHANGED.\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  This                         Indicates a pointer to the calling context.\r
+  @param  MediaId                      ID of the medium to receive data from.\r
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution\r
+                                       of the security protocol command. A Timeout value of 0\r
+                                       means that this function will wait indefinitely for the\r
+                                       security protocol command to execute. If Timeout is greater\r
+                                       than zero, then this function will return EFI_TIMEOUT\r
+                                       if the time required to execute the receive data command\r
+                                       is greater than Timeout.\r
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of\r
+                                       the security protocol command to be sent.\r
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
+                                       of the security protocol command to be sent.\r
+  @param  PayloadBufferSize            Size in bytes of the payload data buffer.\r
+  @param  PayloadBuffer                A pointer to a destination buffer to store the security\r
+                                       protocol command specific payload data for the security\r
+                                       protocol command. The caller is responsible for having\r
+                                       either implicit or explicit ownership of the buffer.\r
+  @param  PayloadTransferSize          A pointer to a buffer to store the size in bytes of the\r
+                                       data written to the payload data buffer.\r
+\r
+  @retval EFI_SUCCESS                  The security protocol command completed successfully.\r
+  @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too small to store the available\r
+                                       data from the device. The PayloadBuffer contains the truncated data.\r
+  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.\r
+  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.\r
+  @retval EFI_NO_MEDIA                 There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.\r
+  @retval EFI_INVALID_PARAMETER        The PayloadBuffer or PayloadTransferSize is NULL and\r
+                                       PayloadBufferSize 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
+NvmeStorageSecurityReceiveData (\r
+  IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL   *This,\r
+  IN  UINT32                                  MediaId,\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 MediaId. 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 sent\r
+  using the SECURITY PROTOCOL OUT 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 SEND commands defined in ATA8-ACS if PayloadBufferSize\r
+  is non-zero. If the PayloadBufferSize is zero, the security protocol command is\r
+  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 MediaId does not support security protocol commands, the function\r
+  shall return EFI_UNSUPPORTED. If there is no media in the device, the function\r
+  returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the\r
+  device, the function returns EFI_MEDIA_CHANGED.\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 return\r
+  EFI_SUCCESS. If the security protocol command completes with an error, the function\r
+  shall return EFI_DEVICE_ERROR.\r
+\r
+  @param  This                         Indicates a pointer to the calling context.\r
+  @param  MediaId                      ID of the medium to receive data from.\r
+  @param  Timeout                      The timeout, in 100ns units, to use for the execution\r
+                                       of the security protocol command. A Timeout value of 0\r
+                                       means that this function will wait indefinitely for the\r
+                                       security protocol command to execute. If Timeout is greater\r
+                                       than zero, then this function will return EFI_TIMEOUT\r
+                                       if the time required to execute the receive data command\r
+                                       is greater than Timeout.\r
+  @param  SecurityProtocolId           The value of the "Security Protocol" parameter of\r
+                                       the security protocol command to be sent.\r
+  @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
+                                       of the security protocol command to be sent.\r
+  @param  PayloadBufferSize            Size in bytes of the payload data buffer.\r
+  @param  PayloadBuffer                A pointer to a destination buffer to store the security\r
+                                       protocol command specific payload data for the security\r
+                                       protocol command.\r
+\r
+  @retval EFI_SUCCESS                  The security protocol command completed successfully.\r
+  @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.\r
+  @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.\r
+  @retval EFI_NO_MEDIA                 There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.\r
+  @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and PayloadBufferSize 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 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,\r
+  IN UINT32                                   MediaId,\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
index f73d6af8aff67f8b4016d77443c8d5f45b73b1ab..00acf2b5cf9c539d40f20731da4d10c20da207ec 100644 (file)
@@ -68,6 +68,7 @@
   gEfiNvmExpressPassThruProtocolGuid          ## BY_START\r
   gEfiBlockIoProtocolGuid                     ## BY_START\r
   gEfiDiskInfoProtocolGuid                    ## BY_START\r
+  gEfiStorageSecurityCommandProtocolGuid      ## BY_START\r
   gEfiDriverSupportedEfiVersionProtocolGuid   ## PRODUCES\r
 \r
 # [Event]\r
index e35f3c0751aa794575e9994a64b9a2c5c50c4561..f6b6288f652f1053511debe25eb52166bdb2ff66 100644 (file)
@@ -582,7 +582,7 @@ NvmeIdentifyController (
   ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
   ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
 \r
-  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;\r
+  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;\r
   //\r
   // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.\r
   // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.\r
@@ -641,7 +641,7 @@ NvmeIdentifyNamespace (
   CommandPacket.NvmeCmd        = &Command;\r
   CommandPacket.NvmeCompletion = &Completion;\r
 \r
-  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;\r
+  Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;\r
   Command.Nsid        = NamespaceId;\r
   CommandPacket.TransferBuffer = Buffer;\r
   CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);\r
@@ -691,7 +691,7 @@ NvmeCreateIoCompletionQueue (
   CommandPacket.NvmeCmd        = &Command;\r
   CommandPacket.NvmeCompletion = &Completion;\r
 \r
-  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;\r
+  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;\r
   CommandPacket.TransferBuffer = Private->CqBufferPciAddr[1];\r
   CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
@@ -741,7 +741,7 @@ NvmeCreateIoSubmissionQueue (
   CommandPacket.NvmeCmd        = &Command;\r
   CommandPacket.NvmeCompletion = &Completion;\r
 \r
-  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;\r
+  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;\r
   CommandPacket.TransferBuffer = Private->SqBufferPciAddr[1];\r
   CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
index aa0ac35c308548fb833111179245fa0346d87a5e..06c1db7d8e915e996400a559ae2ce65215af0a29 100644 (file)
@@ -2,7 +2,7 @@
   NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows\r
   NVM Express specification.\r
 \r
-  Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -348,6 +348,10 @@ typedef struct {
   // Admin Command Set Attributes\r
   //\r
   UINT16 Oacs;                /* Optional Admin Command Support */\r
+    #define NAMESPACE_MANAGEMENT_SUPPORTED  BIT3\r
+    #define FW_DOWNLOAD_ACTIVATE_SUPPORTED  BIT2\r
+    #define FORMAT_NVM_SUPPORTED            BIT1\r
+    #define SECURITY_SEND_RECEIVE_SUPPORTED BIT0\r
   UINT8  Acl;                 /* Abort Command Limit */\r
   UINT8  Aerl;                /* Async Event Request Limit */\r
   UINT8  Frmw;                /* Firmware updates */\r
@@ -556,9 +560,9 @@ typedef struct {
   // CDW 10\r
   //\r
   UINT32 Lid:8;               /* Log Page Identifier */\r
-    #define LID_ERROR_INFO\r
-    #define LID_SMART_INFO\r
-    #define LID_FW_SLOT_INFO\r
+    #define LID_ERROR_INFO   0x1\r
+    #define LID_SMART_INFO   0x2\r
+    #define LID_FW_SLOT_INFO 0x3\r
   UINT32 Rsvd1:8;\r
   UINT32 Numd:12;             /* Number of Dwords */\r
   UINT32 Rsvd2:4;             /* Reserved as of Nvm Express 1.1 Spec */\r
@@ -724,9 +728,23 @@ typedef struct {
 //\r
 // Nvm Express Admin cmd opcodes\r
 //\r
-#define NVME_ADMIN_CRIOSQ_OPC                1\r
-#define NVME_ADMIN_CRIOCQ_OPC                5\r
-#define NVME_ADMIN_IDENTIFY_OPC              6\r
+#define NVME_ADMIN_DEIOSQ_CMD                0x00\r
+#define NVME_ADMIN_CRIOSQ_CMD                0x01\r
+#define NVME_ADMIN_GET_LOG_PAGE_CMD          0x02\r
+#define NVME_ADMIN_DEIOCQ_CMD                0x04\r
+#define NVME_ADMIN_CRIOCQ_CMD                0x05\r
+#define NVME_ADMIN_IDENTIFY_CMD              0x06\r
+#define NVME_ADMIN_ABORT_CMD                 0x08\r
+#define NVME_ADMIN_SET_FEATURES_CMD          0x09\r
+#define NVME_ADMIN_GET_FEATURES_CMD          0x0A\r
+#define NVME_ADMIN_ASYNC_EVENT_REQUEST_CMD   0x0C\r
+#define NVME_ADMIN_NAMESACE_MANAGEMENT_CMD   0x0D\r
+#define NVME_ADMIN_FW_COMMIT_CMD             0x10\r
+#define NVME_ADMIN_FW_IAMGE_DOWNLOAD_CMD     0x11\r
+#define NVME_ADMIN_NAMESACE_ATTACHMENT_CMD   0x15\r
+#define NVME_ADMIN_FORMAT_NVM_CMD            0x80\r
+#define NVME_ADMIN_SECURITY_SEND_CMD         0x81\r
+#define NVME_ADMIN_SECURITY_RECEIVE_CMD      0x82\r
 \r
 #define NVME_IO_FLUSH_OPC                    0\r
 #define NVME_IO_WRITE_OPC                    1\r
index d37194a91043afa42e48a6bf4502ebe0eaec326f..f9871527dd889405dcae061ce94e002c9e67dab0 100644 (file)
@@ -433,7 +433,7 @@ NvmExpressPassThru (
   // these two cmds are special which requires their data buffer must support simultaneous access by both the\r
   // processor and a PCI Bus Master. It's caller's responsbility to ensure this.\r
   //\r
-  if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_OPC) && (Sq->Opc != NVME_ADMIN_CRIOSQ_OPC)) {\r
+  if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_CMD) && (Sq->Opc != NVME_ADMIN_CRIOSQ_CMD)) {\r
     if ((Sq->Opc & BIT0) != 0) {\r
       Flag = EfiPciIoOperationBusMasterRead;\r
     } else {\r
@@ -567,21 +567,31 @@ NvmExpressPassThru (
     }\r
   }\r
 \r
-  if ((Private->CqHdbl[QueueType].Cqh ^= 1) == 0) {\r
-    Private->Pt[QueueType] ^= 1;\r
-  }\r
-\r
   //\r
-  // Copy the Respose Queue entry for this command to the callers response buffer\r
+  // Check the NVMe cmd execution result\r
   //\r
-  CopyMem(Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
+  if (Status != EFI_TIMEOUT) {\r
+    if ((Cq->Sct == 0) && (Cq->Sc == 0)) {\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+      //\r
+      // Copy the Respose Queue entry for this command to the callers response buffer\r
+      //\r
+      CopyMem(Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
+    \r
+      //\r
+      // Dump every completion entry status for debugging.\r
+      //\r
+      DEBUG_CODE_BEGIN();\r
+        NvmeDumpStatus(Cq);\r
+      DEBUG_CODE_END();\r
+    }\r
+  }\r
 \r
-  //\r
-  // Dump every completion entry status for debugging.\r
-  //\r
-  DEBUG_CODE_BEGIN();\r
-    NvmeDumpStatus(Cq);\r
-  DEBUG_CODE_END();\r
+  if ((Private->CqHdbl[QueueType].Cqh ^= 1) == 0) {\r
+    Private->Pt[QueueType] ^= 1;\r
+  }\r
 \r
   Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueType]);\r
   PciIo->Mem.Write (\r