]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdePkg: Implement SCSI commands for Security Protocol In/Out
authorZurcher, Christopher J <christopher.j.zurcher@intel.com>
Fri, 27 Sep 2019 02:19:57 +0000 (10:19 +0800)
committerHao A Wu <hao.a.wu@intel.com>
Sun, 29 Sep 2019 08:43:45 +0000 (16:43 +0800)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546

This patch implements the Security Protocol In and Security Protocol Out
commands in UefiScsiLib to prepare support for the Storage Security
Command Protocol.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
MdePkg/Include/IndustryStandard/Scsi.h
MdePkg/Include/Library/UefiScsiLib.h
MdePkg/Library/UefiScsiLib/UefiScsiLib.c

index cbe5709fe53e9a551fb9b8e3daa83d9c4a35726d..d03886417f861cb86be7766b8602138a67a44f76 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Support for SCSI-2 standard\r
 \r
-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 #define EFI_SCSI_OP_SEND_MESSAGE10  0x2a\r
 #define EFI_SCSI_OP_SEND_MESSAGE12  0xaa\r
 \r
+//\r
+// Additional commands for Secure Transactions\r
+//\r
+#define EFI_SCSI_OP_SECURITY_PROTOCOL_IN  0xa2\r
+#define EFI_SCSI_OP_SECURITY_PROTOCOL_OUT 0xb5\r
+\r
 //\r
 // SCSI Data Transfer Direction\r
 //\r
 //\r
 // Peripheral Device Type Definitions\r
 //\r
-#define EFI_SCSI_TYPE_DISK          0x00  ///< Direct-access device (e.g. magnetic disk)\r
-#define EFI_SCSI_TYPE_TAPE          0x01  ///< Sequential-access device (e.g. magnetic tape)\r
-#define EFI_SCSI_TYPE_PRINTER       0x02  ///< Printer device\r
-#define EFI_SCSI_TYPE_PROCESSOR     0x03  ///< Processor device\r
-#define EFI_SCSI_TYPE_WORM          0x04  ///< Write-once device (e.g. some optical disks)\r
-#define EFI_SCSI_TYPE_CDROM         0x05  ///< CD-ROM device\r
-#define EFI_SCSI_TYPE_SCANNER       0x06  ///< Scanner device\r
-#define EFI_SCSI_TYPE_OPTICAL       0x07  ///< Optical memory device (e.g. some optical disks)\r
-#define EFI_SCSI_TYPE_MEDIUMCHANGER 0x08  ///< Medium changer device (e.g. jukeboxes)\r
-#define EFI_SCSI_TYPE_COMMUNICATION 0x09  ///< Communications device\r
-#define EFI_SCSI_TYPE_ASCIT8_1      0x0A  ///< Defined by ASC IT8 (Graphic arts pre-press devices)\r
-#define EFI_SCSI_TYPE_ASCIT8_2      0x0B  ///< Defined by ASC IT8 (Graphic arts pre-press devices)\r
-//\r
-// 0Ch - 1Eh are reserved\r
-//\r
-#define EFI_SCSI_TYPE_UNKNOWN       0x1F  ///< Unknown or no device type\r
+#define EFI_SCSI_TYPE_DISK            0x00  ///< Direct-access device (e.g. magnetic disk)\r
+#define EFI_SCSI_TYPE_TAPE            0x01  ///< Sequential-access device (e.g. magnetic tape)\r
+#define EFI_SCSI_TYPE_PRINTER         0x02  ///< Printer device\r
+#define EFI_SCSI_TYPE_PROCESSOR       0x03  ///< Processor device\r
+#define EFI_SCSI_TYPE_WORM            0x04  ///< Write-once device (e.g. some optical disks)\r
+#define EFI_SCSI_TYPE_CDROM           0x05  ///< CD/DVD device\r
+#define EFI_SCSI_TYPE_SCANNER         0x06  ///< Scanner device (obsolete)\r
+#define EFI_SCSI_TYPE_OPTICAL         0x07  ///< Optical memory device (e.g. some optical disks)\r
+#define EFI_SCSI_TYPE_MEDIUMCHANGER   0x08  ///< Medium changer device (e.g. jukeboxes)\r
+#define EFI_SCSI_TYPE_COMMUNICATION   0x09  ///< Communications device (obsolete)\r
+#define EFI_SCSI_TYPE_ASCIT8_1        0x0A  ///< Defined by ASC IT8 (Graphic arts pre-press devices)\r
+#define EFI_SCSI_TYPE_ASCIT8_2        0x0B  ///< Defined by ASC IT8 (Graphic arts pre-press devices)\r
+#define EFI_SCSI_TYPE_RAID            0x0C  ///< Storage array controller device (e.g., RAID)\r
+#define EFI_SCSI_TYPE_SES             0x0D  ///< Enclosure services device\r
+#define EFI_SCSI_TYPE_RBC             0x0E  ///< Simplified direct-access device (e.g., magnetic disk)\r
+#define EFI_SCSI_TYPE_OCRW            0x0F  ///< Optical card reader/writer device\r
+#define EFI_SCSI_TYPE_BRIDGE          0x10  ///< Bridge Controller Commands\r
+#define EFI_SCSI_TYPE_OSD             0x11  ///< Object-based Storage Device\r
+#define EFI_SCSI_TYPE_AUTOMATION      0x12  ///< Automation/Drive Interface\r
+#define EFI_SCSI_TYPE_SECURITYMANAGER 0x13  ///< Security manager device\r
+#define EFI_SCSI_TYPE_RESERVED_LOW    0x14  ///< Reserved (low)\r
+#define EFI_SCSI_TYPE_RESERVED_HIGH   0x1D  ///< Reserved (high)\r
+#define EFI_SCSI_TYPE_WLUN            0x1E  ///< Well known logical unit\r
+#define EFI_SCSI_TYPE_UNKNOWN         0x1F  ///< Unknown or no device type\r
 \r
 //\r
 // Page Codes for INQUIRY command\r
index 10dd81902bc5251b4f9f4888c9553211723f925a..2a81883ca9c3bf6c143f51ac546e8a4963a9dc81 100644 (file)
@@ -5,7 +5,7 @@
   for hard drive, CD and DVD devices that are the most common SCSI boot targets used by UEFI platforms.\r
   This library class depends on SCSI I/O Protocol defined in UEFI Specification and SCSI-2 industry standard.\r
 \r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -813,6 +813,134 @@ ScsiWrite16Command (
   );\r
 \r
 \r
+/**\r
+  Execute Security Protocol In SCSI command on a specific SCSI target.\r
+\r
+  Executes the SCSI Security Protocol In command on the SCSI target specified by ScsiIo.\r
+  If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+  If Timeout is greater than zero, then the command is executed and will timeout after\r
+  Timeout 100 ns units.\r
+  If ScsiIo is NULL, then ASSERT().\r
+  If SenseDataLength is NULL, then ASSERT().\r
+  If HostAdapterStatus is NULL, then ASSERT().\r
+  If TargetStatus is NULL, then ASSERT().\r
+  If TransferLength is NULL, then ASSERT().\r
+\r
+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  @param[in]      ScsiIo                    SCSI IO Protocol to use.\r
+  @param[in]      Timeout                   The length of timeout period.\r
+  @param[in, out] SenseData                 A pointer to output sense data.\r
+  @param[in, out] SenseDataLength           The length of output sense data.\r
+  @param[out]     HostAdapterStatus         The status of Host Adapter.\r
+  @param[out]     TargetStatus              The status of the target.\r
+  @param[in]      SecurityProtocol          The Security Protocol to use.\r
+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.\r
+  @param[in]      Inc512                    If TRUE, 512 increment (INC_512) bit will be set for the\r
+                                            SECURITY PROTOCOL IN command.\r
+  @param[in]      DataLength                The size in bytes of the data buffer.\r
+  @param[in, out] DataBuffer                A pointer to a data buffer.\r
+  @param[out]     TransferLength            A pointer to a buffer to store the size in\r
+                                            bytes of the data written to the data buffer.\r
+\r
+  @retval  EFI_SUCCESS                 Command is executed successfully.\r
+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed, but the entire DataBuffer could\r
+                                       not be transferred. The actual number of bytes transferred is returned in TransferLength.\r
+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent because there are too many\r
+                                       SCSI Command Packets already queued.\r
+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting to send SCSI Request Packet.\r
+  @retval  EFI_UNSUPPORTED             The command described by the SCSI Request Packet is not supported by\r
+                                       the SCSI initiator(i.e., SCSI  Host Controller)\r
+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolInCommand (\r
+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,\r
+  IN     UINT64                Timeout,\r
+  IN OUT VOID                  *SenseData,   OPTIONAL\r
+  IN OUT UINT8                 *SenseDataLength,\r
+     OUT UINT8                 *HostAdapterStatus,\r
+     OUT UINT8                 *TargetStatus,\r
+  IN     UINT8                 SecurityProtocol,\r
+  IN     UINT16                SecurityProtocolSpecific,\r
+  IN     BOOLEAN               Inc512,\r
+  IN     UINTN                 DataLength,\r
+  IN OUT VOID                  *DataBuffer,  OPTIONAL\r
+     OUT UINTN                 *TransferLength\r
+  );\r
+\r
+\r
+/**\r
+  Execute Security Protocol Out SCSI command on a specific SCSI target.\r
+\r
+  Executes the SCSI Security Protocol Out command on the SCSI target specified by ScsiIo.\r
+  If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+  If Timeout is greater than zero, then the command is executed and will timeout after\r
+  Timeout 100 ns units.\r
+  If ScsiIo is NULL, then ASSERT().\r
+  If SenseDataLength is NULL, then ASSERT().\r
+  If HostAdapterStatus is NULL, then ASSERT().\r
+  If TargetStatus is NULL, then ASSERT().\r
+\r
+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  @param[in]      ScsiIo                    SCSI IO Protocol to use.\r
+  @param[in]      Timeout                   The length of timeout period.\r
+  @param[in, out] SenseData                 A pointer to output sense data.\r
+  @param[in, out] SenseDataLength           The length of output sense data.\r
+  @param[out]     HostAdapterStatus         The status of Host Adapter.\r
+  @param[out]     TargetStatus              The status of the target.\r
+  @param[in]      SecurityProtocol          The Security Protocol to use.\r
+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.\r
+  @param[in]      Inc512                    If TRUE, 512 increment (INC_512) bit will be set for the\r
+                                            SECURITY PROTOCOL OUT command.\r
+  @param[in]      DataLength                The size in bytes of the transfer data.\r
+  @param[in, out] DataBuffer                A pointer to a data buffer.\r
+\r
+  @retval  EFI_SUCCESS                 Command is executed successfully.\r
+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed, but the entire DataBuffer could\r
+                                       not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent because there are too many\r
+                                       SCSI Command Packets already queued.\r
+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting to send SCSI Request Packet.\r
+  @retval  EFI_UNSUPPORTED             The command described by the SCSI Request Packet is not supported by\r
+                                       the SCSI initiator(i.e., SCSI  Host Controller)\r
+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolOutCommand (\r
+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,\r
+  IN     UINT64                Timeout,\r
+  IN OUT VOID                  *SenseData,   OPTIONAL\r
+  IN OUT UINT8                 *SenseDataLength,\r
+     OUT UINT8                 *HostAdapterStatus,\r
+     OUT UINT8                 *TargetStatus,\r
+  IN     UINT8                 SecurityProtocol,\r
+  IN     UINT16                SecurityProtocolSpecific,\r
+  IN     BOOLEAN               Inc512,\r
+  IN     UINTN                 DataLength,\r
+  IN OUT VOID                  *DataBuffer   OPTIONAL\r
+  );\r
+\r
+\r
 /**\r
   Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI\r
   target.\r
index c7491d1436908f88160302721772b59e16440a79..13a2a1912cbe8a23f5d018965d34db627902c162 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   UEFI SCSI Library implementation\r
 \r
-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -23,6 +23,7 @@
   //\r
 #define EFI_SCSI_OP_LENGTH_SIX      0x6\r
 #define EFI_SCSI_OP_LENGTH_TEN      0xa\r
+#define EFI_SCSI_OP_LENGTH_TWELVE   0xc\r
 #define EFI_SCSI_OP_LENGTH_SIXTEEN  0x10\r
 \r
 //\r
@@ -1280,6 +1281,232 @@ ScsiWrite16Command (
 }\r
 \r
 \r
+/**\r
+  Execute Security Protocol In SCSI command on a specific SCSI target.\r
+\r
+  Executes the SCSI Security Protocol In command on the SCSI target specified by ScsiIo.\r
+  If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+  If Timeout is greater than zero, then the command is executed and will timeout after\r
+  Timeout 100 ns units.\r
+  If ScsiIo is NULL, then ASSERT().\r
+  If SenseDataLength is NULL, then ASSERT().\r
+  If HostAdapterStatus is NULL, then ASSERT().\r
+  If TargetStatus is NULL, then ASSERT().\r
+  If TransferLength is NULL, then ASSERT().\r
+\r
+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  @param[in]      ScsiIo                    SCSI IO Protocol to use.\r
+  @param[in]      Timeout                   The length of timeout period.\r
+  @param[in, out] SenseData                 A pointer to output sense data.\r
+  @param[in, out] SenseDataLength           The length of output sense data.\r
+  @param[out]     HostAdapterStatus         The status of Host Adapter.\r
+  @param[out]     TargetStatus              The status of the target.\r
+  @param[in]      SecurityProtocol          The Security Protocol to use.\r
+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.\r
+  @param[in]      Inc512                    If TRUE, 512 increment (INC_512) bit will be set for the\r
+                                            SECURITY PROTOCOL IN command.\r
+  @param[in]      DataLength                The size in bytes of the data buffer.\r
+  @param[in, out] DataBuffer                A pointer to a data buffer.\r
+  @param[out]     TransferLength            A pointer to a buffer to store the size in\r
+                                            bytes of the data written to the data buffer.\r
+\r
+  @retval  EFI_SUCCESS                 Command is executed successfully.\r
+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed, but the entire DataBuffer could\r
+                                       not be transferred. The actual number of bytes transferred is returned in TransferLength.\r
+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent because there are too many\r
+                                       SCSI Command Packets already queued.\r
+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting to send SCSI Request Packet.\r
+  @retval  EFI_UNSUPPORTED             The command described by the SCSI Request Packet is not supported by\r
+                                       the SCSI initiator(i.e., SCSI  Host Controller)\r
+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolInCommand (\r
+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,\r
+  IN     UINT64                Timeout,\r
+  IN OUT VOID                  *SenseData,   OPTIONAL\r
+  IN OUT UINT8                 *SenseDataLength,\r
+     OUT UINT8                 *HostAdapterStatus,\r
+     OUT UINT8                 *TargetStatus,\r
+  IN     UINT8                 SecurityProtocol,\r
+  IN     UINT16                SecurityProtocolSpecific,\r
+  IN     BOOLEAN               Inc512,\r
+  IN     UINTN                 DataLength,\r
+  IN OUT VOID                  *DataBuffer,  OPTIONAL\r
+     OUT UINTN                 *TransferLength\r
+  )\r
+{\r
+  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
+\r
+  ASSERT (SenseDataLength != NULL);\r
+  ASSERT (HostAdapterStatus != NULL);\r
+  ASSERT (TargetStatus != NULL);\r
+  ASSERT (ScsiIo != NULL);\r
+  ASSERT (TransferLength != NULL);\r
+  ASSERT (DataLength <= MAX_UINT32);\r
+\r
+  ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+  ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
+\r
+  CommandPacket.Timeout           = Timeout;\r
+  CommandPacket.InDataBuffer      = DataBuffer;\r
+  CommandPacket.SenseData         = SenseData;\r
+  CommandPacket.InTransferLength  = (UINT32) DataLength;\r
+  CommandPacket.Cdb               = Cdb;\r
+  //\r
+  // Fill Cdb for Security Protocol In Command\r
+  //\r
+  Cdb[0]                        = EFI_SCSI_OP_SECURITY_PROTOCOL_IN;\r
+  Cdb[1]                        = SecurityProtocol;\r
+  WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
+\r
+  if (Inc512) {\r
+    if (DataLength % 512 != 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Cdb[4]                      = BIT7;\r
+    WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512));\r
+  } else {\r
+    WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength));\r
+  }\r
+\r
+  CommandPacket.CdbLength       = EFI_SCSI_OP_LENGTH_TWELVE;\r
+  CommandPacket.DataDirection   = EFI_SCSI_DATA_IN;\r
+  CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+  Status                        = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+  *HostAdapterStatus            = CommandPacket.HostAdapterStatus;\r
+  *TargetStatus                 = CommandPacket.TargetStatus;\r
+  *SenseDataLength              = CommandPacket.SenseDataLength;\r
+  *TransferLength               = (UINTN) CommandPacket.InTransferLength;\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Execute Security Protocol Out SCSI command on a specific SCSI target.\r
+\r
+  Executes the SCSI Security Protocol Out command on the SCSI target specified by ScsiIo.\r
+  If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+  If Timeout is greater than zero, then the command is executed and will timeout after\r
+  Timeout 100 ns units.\r
+  If ScsiIo is NULL, then ASSERT().\r
+  If SenseDataLength is NULL, then ASSERT().\r
+  If HostAdapterStatus is NULL, then ASSERT().\r
+  If TargetStatus is NULL, then ASSERT().\r
+\r
+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+  gets returned.\r
+\r
+  @param[in]      ScsiIo                    SCSI IO Protocol to use.\r
+  @param[in]      Timeout                   The length of timeout period.\r
+  @param[in, out] SenseData                 A pointer to output sense data.\r
+  @param[in, out] SenseDataLength           The length of output sense data.\r
+  @param[out]     HostAdapterStatus         The status of Host Adapter.\r
+  @param[out]     TargetStatus              The status of the target.\r
+  @param[in]      SecurityProtocol          The Security Protocol to use.\r
+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.\r
+  @param[in]      Inc512                    If TRUE, 512 increment (INC_512) bit will be set for the\r
+                                            SECURITY PROTOCOL OUT command.\r
+  @param[in]      DataLength                The size in bytes of the transfer data.\r
+  @param[in, out] DataBuffer                A pointer to a data buffer.\r
+\r
+  @retval  EFI_SUCCESS                 Command is executed successfully.\r
+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed, but the entire DataBuffer could\r
+                                       not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent because there are too many\r
+                                       SCSI Command Packets already queued.\r
+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting to send SCSI Request Packet.\r
+  @retval  EFI_UNSUPPORTED             The command described by the SCSI Request Packet is not supported by\r
+                                       the SCSI initiator(i.e., SCSI  Host Controller)\r
+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolOutCommand (\r
+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,\r
+  IN     UINT64                Timeout,\r
+  IN OUT VOID                  *SenseData,   OPTIONAL\r
+  IN OUT UINT8                 *SenseDataLength,\r
+     OUT UINT8                 *HostAdapterStatus,\r
+     OUT UINT8                 *TargetStatus,\r
+  IN     UINT8                 SecurityProtocol,\r
+  IN     UINT16                SecurityProtocolSpecific,\r
+  IN     BOOLEAN               Inc512,\r
+  IN     UINTN                 DataLength,\r
+  IN OUT VOID                  *DataBuffer   OPTIONAL\r
+  )\r
+{\r
+  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
+\r
+  ASSERT (SenseDataLength != NULL);\r
+  ASSERT (HostAdapterStatus != NULL);\r
+  ASSERT (TargetStatus != NULL);\r
+  ASSERT (ScsiIo != NULL);\r
+  ASSERT (DataLength <= MAX_UINT32);\r
+\r
+  ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+  ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
+\r
+  CommandPacket.Timeout           = Timeout;\r
+  CommandPacket.OutDataBuffer     = DataBuffer;\r
+  CommandPacket.SenseData         = SenseData;\r
+  CommandPacket.OutTransferLength = (UINT32) DataLength;\r
+  CommandPacket.Cdb               = Cdb;\r
+  //\r
+  // Fill Cdb for Security Protocol Out Command\r
+  //\r
+  Cdb[0]                        = EFI_SCSI_OP_SECURITY_PROTOCOL_OUT;\r
+  Cdb[1]                        = SecurityProtocol;\r
+  WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
+\r
+  if (Inc512) {\r
+    if (DataLength % 512 != 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Cdb[4]                      = BIT7;\r
+    WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512));\r
+  } else {\r
+    WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength));\r
+  }\r
+\r
+  CommandPacket.CdbLength       = EFI_SCSI_OP_LENGTH_TWELVE;\r
+  CommandPacket.DataDirection   = EFI_SCSI_DATA_OUT;\r
+  CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+  Status                        = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+  *HostAdapterStatus            = CommandPacket.HostAdapterStatus;\r
+  *TargetStatus                 = CommandPacket.TargetStatus;\r
+  *SenseDataLength              = CommandPacket.SenseDataLength;\r
+\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Internal helper notify function in which update the result of the\r
   non-blocking SCSI Read/Write commands and signal caller event.\r