Thanks for your sharp eyesight to find out these typos:)

I will fix them at check-in.

-----Original Message-----
From: Zeng, Star 
Sent: Monday, June 15, 2015 21:47
To: Tian, Feng
Cc: edk2-devel@lists.sourceforge.net
Subject: RE: [patch] MdeModulePkg/NvmExpressDxe: Add SecurityStorageProtocl 
support

How about update the "SecurityStorageProtocl" to "SecurityStorageProtocol"?

How about update "FW_DOWNLOAD_ACTIVATE_SUPORTED" to 
"FW_DOWNLOAD_ACTIVATE_SUPPORTED" in NvmExpressHci.h?

Others are good to me.

Star
-----Original Message-----
From: Tian, Feng
Sent: Thursday, June 11, 2015 1:46 PM
To: Zeng, Star
Cc: edk2-devel@lists.sourceforge.net
Subject: [patch] MdeModulePkg/NvmExpressDxe: Add SecurityStorageProtocl support

Produce this protocol for each namespace at NVMe controller.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Tian Feng <feng.t...@intel.com>
---
 MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c    |  68 ++++-
 MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h    |  39 ++-
 .../Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c      | 326 +++++++++++++++++++++
 .../Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h      | 160 +++++++++-
 .../Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf        |   1 +
 MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c |   8 +-
 MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h |  32 +-
 .../Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c     |  36 ++-
 8 files changed, 628 insertions(+), 42 deletions(-)

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


------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to