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>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher J Zurcher <christopher.j.zurc...@intel.com>
---
 MdePkg/Include/IndustryStandard/Scsi.h   |  48 +++++---
 MdePkg/Include/Library/UefiScsiLib.h     | 126 ++++++++++++++++++-
 MdePkg/Include/Protocol/ScsiIo.h         |   9 +-
 MdePkg/Library/UefiScsiLib/UefiScsiLib.c | 205 ++++++++++++++++++++++++++++++-
 4 files changed, 366 insertions(+), 22 deletions(-)

diff --git a/MdePkg/Include/IndustryStandard/Scsi.h 
b/MdePkg/Include/IndustryStandard/Scsi.h
index 213d8acc2d..59509a0256 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>
   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
@@ -169,6 +169,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
 //
@@ -178,22 +184,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_A               0x0A  ///< Obsolete
+#define EFI_SCSI_TYPE_B               0x0B  ///< Obsolete
+#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 dbb248972b..594f495d7d 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>
 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
@@ -819,6 +819,130 @@ 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.  The StartLba and SectorSize parameters are used to 
construct
+  the CDB for this SCSI command.
+  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 DataLength 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]      TransferLength       The size in bytes of the data 
allocation.
+  @param[in, out] DataBuffer           A pointer to a data buffer.
+  @param[in, out] DataLength           The length of 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
+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     UINT32                TransferLength,
+  IN OUT VOID                  *DataBuffer,  OPTIONAL
+  IN OUT UINT32                *DataLength
+  );
+
+
+/**
+  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.  The StartLba and SectorSize parameters are used to 
construct
+  the CDB for this SCSI command.
+  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 DataLength 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]      TransferLength       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     UINT32                TransferLength,
+  IN OUT VOID                  *DataBuffer  OPTIONAL
+  );
+
+
 /**
   Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
   target.
diff --git a/MdePkg/Include/Protocol/ScsiIo.h b/MdePkg/Include/Protocol/ScsiIo.h
index 1e7bc86b29..cddf395cb1 100644
--- a/MdePkg/Include/Protocol/ScsiIo.h
+++ b/MdePkg/Include/Protocol/ScsiIo.h
@@ -4,7 +4,7 @@
   services environment to access SCSI devices. In particular, functions for
   managing devices on SCSI buses are defined here.
 
-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2006 - 2019, 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
@@ -49,8 +49,11 @@ typedef struct _EFI_SCSI_IO_PROTOCOL EFI_SCSI_IO_PROTOCOL;
 #define MFI_SCSI_IO_TYPE_OCRW                                  0x0F    ///< 
Optical card reader/writer device
 #define MFI_SCSI_IO_TYPE_BRIDGE                                0x10    ///< 
Bridge Controller Commands
 #define MFI_SCSI_IO_TYPE_OSD                                   0x11    ///< 
Object-based Storage Device
-#define EFI_SCSI_IO_TYPE_RESERVED_LOW                          0x12    ///< 
Reserved (low)
-#define EFI_SCSI_IO_TYPE_RESERVED_HIGH                         0x1E    ///< 
Reserved (high)
+#define MFI_SCSI_IO_TYPE_AUTOMATION                            0x12    ///< 
Automation/Drive Interface
+#define MFI_SCSI_IO_TYPE_SECURITYMANAGER                       0x13    ///< 
Security manager device
+#define EFI_SCSI_IO_TYPE_RESERVED_LOW                          0x14    ///< 
Reserved (low)
+#define EFI_SCSI_IO_TYPE_RESERVED_HIGH                         0x1D    ///< 
Reserved (high)
+#define EFI_SCSI_IO_TYPE_WLUN                                  0x1E    ///< 
Well known logical unit
 #define EFI_SCSI_IO_TYPE_UNKNOWN                               0x1F    ///< 
Unknown no device type
 
 //
diff --git a/MdePkg/Library/UefiScsiLib/UefiScsiLib.c 
b/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
index 62a73e2773..b7b83a7ab6 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>
   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
@@ -29,6 +29,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
 
 //
@@ -1286,6 +1287,208 @@ 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.  The StartLba and SectorSize parameters are used to 
construct
+  the CDB for this SCSI command.
+  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 DataLength 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]      TransferLength       The size in bytes of the data 
allocation.
+  @param[in, out] DataBuffer           A pointer to a data buffer.
+  @param[in, out] DataLength           The length of 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
+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     UINT32                TransferLength,
+  IN OUT VOID                  *DataBuffer,  OPTIONAL
+  IN OUT UINT32                *DataLength
+  )
+{
+  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 (DataLength != NULL);
+  ASSERT (ScsiIo != NULL);
+
+  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  = TransferLength;
+  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 (TransferLength));
+
+  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;
+  *DataLength                   = 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.  The StartLba and SectorSize parameters are used to 
construct
+  the CDB for this SCSI command.
+  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 DataLength 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]      TransferLength       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     UINT32                TransferLength,
+  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);
+
+  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 = TransferLength;
+  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 (TransferLength));
+
+  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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to