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....@intel.com>
Cc: Jian J Wang <jian.j.w...@intel.com>
Cc: Liming Gao <liming....@intel.com>
Signed-off-by: Christopher J Zurcher <christopher.j.zurc...@intel.com>
---
 MdePkg/Include/IndustryStandard/Scsi.h   |  48 +++--
 MdePkg/Include/Library/UefiScsiLib.h     | 128 +++++++++++-
 MdePkg/Library/UefiScsiLib/UefiScsiLib.c | 217 +++++++++++++++++++-
 3 files changed, 374 insertions(+), 19 deletions(-)

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


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#46992): https://edk2.groups.io/g/devel/message/46992
Mute This Topic: https://groups.io/mt/33202221/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to