public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
@ 2019-06-13  2:04 Zurcher, Christopher J
  2019-06-13  2:04 ` [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out Zurcher, Christopher J
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Zurcher, Christopher J @ 2019-06-13  2:04 UTC (permalink / raw)
  To: devel; +Cc: Michael D Kinney, Jiewen Yao, Jian J Wang, Liming Gao

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546

V4 changes:
Add SSC Protocol in addition to BlockIo instead of in place of BlockIo.
Add error handling for (BlockSize == 0) in Read and WriteBlocks commands
to handle partitions that do not support ReadCapacity().

V3 changes:
Initialize AlignedBuffer variable in ScsiDiskReceiveData and
ScsiDiskSendData functions. Remove redundant input validation and debug
message in ScsiDiskSendData.

V2 changes:
Split the patch into separate commits for separate packages.

To support RPMB access on UFS devices, support must be added to
the ScsiDiskDxe driver for the Storage Security Command Protocol.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>

Christopher J Zurcher (2):
  MdePkg: Implement SCSI commands for Security Protocol In/Out
  MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol

 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
 MdePkg/Include/IndustryStandard/Scsi.h            |  48 +-
 MdePkg/Include/Library/UefiScsiLib.h              | 126 ++++-
 MdePkg/Include/Protocol/ScsiIo.h                  |   9 +-
 MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522 +++++++++++++++++++-
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
 MdePkg/Library/UefiScsiLib/UefiScsiLib.c          | 205 +++++++-
 9 files changed, 1064 insertions(+), 44 deletions(-)

-- 
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out
  2019-06-13  2:04 [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol Zurcher, Christopher J
@ 2019-06-13  2:04 ` Zurcher, Christopher J
  2019-06-13 12:54   ` Liming Gao
  2019-06-13  2:04 ` [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol Zurcher, Christopher J
  2019-06-13 12:58 ` [PATCH v4 0/2] Add SCSI Support for " Liming Gao
  2 siblings, 1 reply; 13+ messages in thread
From: Zurcher, Christopher J @ 2019-06-13  2:04 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Jian J Wang, Liming Gao

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>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@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 cbe5709fe5..10d7b49ba7 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_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 10dd81902b..a0d99e703a 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,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 05e46bda9c..27c31fe7f9 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>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -43,8 +43,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 c7491d1436..7584d717ad 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,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


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
  2019-06-13  2:04 [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol Zurcher, Christopher J
  2019-06-13  2:04 ` [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out Zurcher, Christopher J
@ 2019-06-13  2:04 ` Zurcher, Christopher J
  2019-06-18  2:12   ` [edk2-devel] " Wu, Hao A
  2019-06-13 12:58 ` [PATCH v4 0/2] Add SCSI Support for " Liming Gao
  2 siblings, 1 reply; 13+ messages in thread
From: Zurcher, Christopher J @ 2019-06-13  2:04 UTC (permalink / raw)
  To: devel; +Cc: Michael D Kinney, Jiewen Yao, Jian J Wang, Liming Gao

This patch implements the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL in the
ScsiDiskDxe driver.

Support is currently limited to the RPMB Well-known LUN for UFS devices.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
---
 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
 MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522 +++++++++++++++++++-
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
 5 files changed, 698 insertions(+), 22 deletions(-)

diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
index 5500d828e9..40818e669b 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
@@ -3,7 +3,7 @@
 #  It detects the SCSI disk media and installs Block I/O and Block I/O2 Protocol on
 #  the device handle.
 #
-#  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
 #
 ##
@@ -52,6 +52,7 @@
   gEfiBlockIoProtocolGuid                       ## BY_START
   gEfiBlockIo2ProtocolGuid                      ## BY_START
   gEfiEraseBlockProtocolGuid                    ## BY_START
+  gEfiStorageSecurityCommandProtocolGuid        ## BY_START
   gEfiScsiIoProtocolGuid                        ## TO_START
   gEfiScsiPassThruProtocolGuid                  ## TO_START
   gEfiExtScsiPassThruProtocolGuid               ## TO_START
diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
index 42c0aaaa95..2d8679ec6f 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
@@ -1,7 +1,7 @@
 /** @file
   Header file for SCSI Disk Driver.
 
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -22,6 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/ScsiPassThruExt.h>
 #include <Protocol/ScsiPassThru.h>
 #include <Protocol/DiskInfo.h>
+#include <Protocol/StorageSecurityCommand.h>
 
 
 #include <Library/DebugLib.h>
@@ -38,6 +39,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #define IS_DEVICE_FIXED(a)        (a)->FixedDevice ? 1 : 0
 
+#define IS_ALIGNED(addr, size)    (((UINTN) (addr) & (size - 1)) == 0)
+
+#define UFS_WLUN_RPMB 0xC4
+
 typedef struct {
   UINT32                    MaxLbaCnt;
   UINT32                    MaxBlkDespCnt;
@@ -51,6 +56,8 @@ typedef struct {
 
   EFI_HANDLE                Handle;
 
+  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL   StorageSecurity;
+
   EFI_BLOCK_IO_PROTOCOL     BlkIo;
   EFI_BLOCK_IO2_PROTOCOL    BlkIo2;
   EFI_BLOCK_IO_MEDIA        BlkIoMedia;
@@ -95,6 +102,7 @@ typedef struct {
 #define SCSI_DISK_DEV_FROM_BLKIO(a)  CR (a, SCSI_DISK_DEV, BlkIo, SCSI_DISK_DEV_SIGNATURE)
 #define SCSI_DISK_DEV_FROM_BLKIO2(a)  CR (a, SCSI_DISK_DEV, BlkIo2, SCSI_DISK_DEV_SIGNATURE)
 #define SCSI_DISK_DEV_FROM_ERASEBLK(a)  CR (a, SCSI_DISK_DEV, EraseBlock, SCSI_DISK_DEV_SIGNATURE)
+#define SCSI_DISK_DEV_FROM_STORSEC(a)  CR (a, SCSI_DISK_DEV, StorageSecurity, SCSI_DISK_DEV_SIGNATURE)
 
 #define SCSI_DISK_DEV_FROM_DISKINFO(a) CR (a, SCSI_DISK_DEV, DiskInfo, SCSI_DISK_DEV_SIGNATURE)
 
@@ -638,6 +646,151 @@ ScsiDiskEraseBlocks (
   );
 
 
+/**
+  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.
+
+  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
+ScsiDiskReceiveData (
+  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
+  IN UINT32                                   MediaId   OPTIONAL,
+  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.
+
+  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
+ScsiDiskSendData (
+  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
+  IN UINT32                                   MediaId   OPTIONAL,
+  IN UINT64                                   Timeout,
+  IN UINT8                                    SecurityProtocolId,
+  IN UINT16                                   SecurityProtocolSpecificData,
+  IN UINTN                                    PayloadBufferSize,
+  OUT VOID                                    *PayloadBuffer
+  );
+
+
 /**
   Provides inquiry information for the controller type.
 
@@ -1428,4 +1581,20 @@ DetermineInstallEraseBlock (
   IN  EFI_HANDLE             ChildHandle
   );
 
+/**
+  Determine if EFI Storage Security Command Protocol should be produced.
+
+  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
+  @param   ChildHandle       Handle of device.
+
+  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
+  @retval  FALSE   Should not produce EFI Storage Security Command Protocol.
+
+**/
+BOOLEAN
+DetermineInstallStorageSecurity (
+  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
+  IN  EFI_HANDLE             ChildHandle
+  );
+
 #endif
diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
index c4069aec0f..1caffd38cd 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
@@ -2,7 +2,7 @@
   SCSI Bus driver that layers on every SCSI Pass Thru and
   Extended SCSI Pass Thru protocol in the system.
 
-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
 
 **/
@@ -1368,7 +1368,8 @@ DiscoverScsiDevice (
     goto Done;
   }
 
-  if (0x1e >= InquiryData->Peripheral_Type && InquiryData->Peripheral_Type >= 0xa) {
+  if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW) &&
+      (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH)) {
     ScsiDeviceFound = FALSE;
     goto Done;
   }
diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
index fbdf927a11..01d5ad4969 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
@@ -1,7 +1,7 @@
 /** @file
   SCSI disk driver that layers on every SCSI IO protocol in the system.
 
-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
 
 **/
@@ -151,7 +151,9 @@ ScsiDiskDriverBindingSupported (
 
   Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType);
   if (!EFI_ERROR (Status)) {
-    if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType == EFI_SCSI_TYPE_CDROM)) {
+    if ((DeviceType == EFI_SCSI_TYPE_DISK) ||
+        (DeviceType == EFI_SCSI_TYPE_CDROM) ||
+        (DeviceType == EFI_SCSI_TYPE_WLUN)) {
       Status = EFI_SUCCESS;
     } else {
       Status = EFI_UNSUPPORTED;
@@ -238,6 +240,8 @@ ScsiDiskDriverBindingStart (
   ScsiDiskDevice->BlkIo2.ReadBlocksEx               = ScsiDiskReadBlocksEx;
   ScsiDiskDevice->BlkIo2.WriteBlocksEx              = ScsiDiskWriteBlocksEx;
   ScsiDiskDevice->BlkIo2.FlushBlocksEx              = ScsiDiskFlushBlocksEx;
+  ScsiDiskDevice->StorageSecurity.ReceiveData       = ScsiDiskReceiveData;
+  ScsiDiskDevice->StorageSecurity.SendData          = ScsiDiskSendData;
   ScsiDiskDevice->EraseBlock.Revision               = EFI_ERASE_BLOCK_PROTOCOL_REVISION;
   ScsiDiskDevice->EraseBlock.EraseLengthGranularity = 1;
   ScsiDiskDevice->EraseBlock.EraseBlocks            = ScsiDiskEraseBlocks;
@@ -258,6 +262,10 @@ ScsiDiskDriverBindingStart (
     ScsiDiskDevice->BlkIo.Media->ReadOnly  = TRUE;
     MustReadCapacity = FALSE;
     break;
+
+  case EFI_SCSI_TYPE_WLUN:
+    MustReadCapacity = FALSE;
+    break;
   }
   //
   // The Sense Data Array's initial size is 6
@@ -309,8 +317,8 @@ ScsiDiskDriverBindingStart (
     // Determine if Block IO & Block IO2 should be produced on this controller
     // handle
     //
-    if (DetermineInstallBlockIo(Controller)) {
-      InitializeInstallDiskInfo(ScsiDiskDevice, Controller);
+    if (DetermineInstallBlockIo (Controller)) {
+      InitializeInstallDiskInfo (ScsiDiskDevice, Controller);
       Status = gBS->InstallMultipleProtocolInterfaces (
                       &Controller,
                       &gEfiBlockIoProtocolGuid,
@@ -321,16 +329,27 @@ ScsiDiskDriverBindingStart (
                       &ScsiDiskDevice->DiskInfo,
                       NULL
                       );
-      if (!EFI_ERROR(Status)) {
-        if (DetermineInstallEraseBlock(ScsiDiskDevice, Controller)) {
+      if (!EFI_ERROR (Status)) {
+        if (DetermineInstallEraseBlock (ScsiDiskDevice, Controller)) {
           Status = gBS->InstallProtocolInterface (
                           &Controller,
                           &gEfiEraseBlockProtocolGuid,
                           EFI_NATIVE_INTERFACE,
                           &ScsiDiskDevice->EraseBlock
                           );
-          if (EFI_ERROR(Status)) {
-            DEBUG ((EFI_D_ERROR, "ScsiDisk: Failed to install the Erase Block Protocol! Status = %r\n", Status));
+          if (EFI_ERROR (Status)) {
+            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Erase Block Protocol! Status = %r\n", Status));
+          }
+        }
+        if (DetermineInstallStorageSecurity (ScsiDiskDevice, Controller)) {
+          Status = gBS->InstallProtocolInterface (
+                          &Controller,
+                          &gEfiStorageSecurityCommandProtocolGuid,
+                          EFI_NATIVE_INTERFACE,
+                          &ScsiDiskDevice->StorageSecurity
+                          );
+          if (EFI_ERROR (Status)) {
+            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Storage Security Command Protocol! Status = %r\n", Status));
           }
         }
         ScsiDiskDevice->ControllerNameTable = NULL;
@@ -606,6 +625,11 @@ ScsiDiskReadBlocks (
   //
   BlockSize       = Media->BlockSize;
 
+  if (BlockSize == 0) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
   NumberOfBlocks  = BufferSize / BlockSize;
 
   if (!(Media->MediaPresent)) {
@@ -742,6 +766,11 @@ ScsiDiskWriteBlocks (
   //
   BlockSize       = Media->BlockSize;
 
+  if (BlockSize == 0) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
   NumberOfBlocks  = BufferSize / BlockSize;
 
   if (!(Media->MediaPresent)) {
@@ -968,6 +997,11 @@ ScsiDiskReadBlocksEx (
   //
   BlockSize       = Media->BlockSize;
 
+  if (BlockSize == 0) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
   NumberOfBlocks  = BufferSize / BlockSize;
 
   if (!(Media->MediaPresent)) {
@@ -1131,6 +1165,11 @@ ScsiDiskWriteBlocksEx (
   //
   BlockSize       = Media->BlockSize;
 
+  if (BlockSize == 0) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
   NumberOfBlocks  = BufferSize / BlockSize;
 
   if (!(Media->MediaPresent)) {
@@ -1708,6 +1747,393 @@ Done:
   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.
+
+  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
+ScsiDiskReceiveData (
+  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
+  IN UINT32                                   MediaId   OPTIONAL,
+  IN UINT64                                   Timeout,
+  IN UINT8                                    SecurityProtocolId,
+  IN UINT16                                   SecurityProtocolSpecificData,
+  IN UINTN                                    PayloadBufferSize,
+  OUT VOID                                    *PayloadBuffer,
+  OUT UINTN                                   *PayloadTransferSize
+  )
+{
+  SCSI_DISK_DEV       *ScsiDiskDevice;
+  EFI_BLOCK_IO_MEDIA  *Media;
+  EFI_STATUS          Status;
+  BOOLEAN             MediaChange;
+  EFI_TPL             OldTpl;
+  UINT8               SenseDataLength;
+  UINT8               HostAdapterStatus;
+  UINT8               TargetStatus;
+  VOID                *AlignedBuffer;
+  BOOLEAN             AlignedBufferAllocated;
+
+  AlignedBuffer           = NULL;
+  MediaChange             = FALSE;
+  AlignedBufferAllocated  = FALSE;
+  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
+  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
+  Media                   = ScsiDiskDevice->BlkIo.Media;
+
+  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
+
+  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice->Handle)) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
+    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
+    if (EFI_ERROR (Status)) {
+      Status = EFI_DEVICE_ERROR;
+      goto Done;
+    }
+
+    if (MediaChange) {
+      gBS->ReinstallProtocolInterface (
+              ScsiDiskDevice->Handle,
+              &gEfiStorageSecurityCommandProtocolGuid,
+              &ScsiDiskDevice->StorageSecurity,
+              &ScsiDiskDevice->StorageSecurity
+              );
+      if (Media->MediaPresent) {
+        Status = EFI_MEDIA_CHANGED;
+      } else {
+        Status = EFI_NO_MEDIA;
+      }
+      goto Done;
+    }
+  }
+
+  //
+  // Validate Media
+  //
+  if (!(Media->MediaPresent)) {
+    Status = EFI_NO_MEDIA;
+    goto Done;
+  }
+
+  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
+    Status = EFI_MEDIA_CHANGED;
+    goto Done;
+  }
+
+  if (PayloadBufferSize != 0) {
+    if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto Done;
+    }
+
+    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer, ScsiDiskDevice->ScsiIo->IoAlign)) {
+      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice, PayloadBufferSize);
+      if (AlignedBuffer == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Done;
+      }
+      ZeroMem (AlignedBuffer, PayloadBufferSize);
+      AlignedBufferAllocated = TRUE;
+    } else {
+      AlignedBuffer = PayloadBuffer;
+    }
+  }
+
+  Status = ScsiSecurityProtocolInCommand (
+            ScsiDiskDevice->ScsiIo,
+            Timeout,
+            ScsiDiskDevice->SenseData,
+            &SenseDataLength,
+            &HostAdapterStatus,
+            &TargetStatus,
+            SecurityProtocolId,
+            SecurityProtocolSpecificData,
+            (UINT32) PayloadBufferSize,
+            AlignedBuffer,
+            (UINT32 *) PayloadTransferSize
+          );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  if (AlignedBufferAllocated) {
+    CopyMem (PayloadBuffer, AlignedBuffer, PayloadBufferSize);
+  }
+
+  if (PayloadBufferSize < *PayloadTransferSize) {
+    Status = EFI_WARN_BUFFER_TOO_SMALL;
+    goto Done;
+  }
+
+  Status = CheckHostAdapterStatus (HostAdapterStatus);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = CheckTargetStatus (TargetStatus);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+Done:
+  if (AlignedBufferAllocated) {
+    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
+  }
+  gBS->RestoreTPL (OldTpl);
+  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.
+
+  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
+ScsiDiskSendData (
+  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
+  IN UINT32                                   MediaId   OPTIONAL,
+  IN UINT64                                   Timeout,
+  IN UINT8                                    SecurityProtocolId,
+  IN UINT16                                   SecurityProtocolSpecificData,
+  IN UINTN                                    PayloadBufferSize,
+  OUT VOID                                    *PayloadBuffer
+  )
+{
+  SCSI_DISK_DEV       *ScsiDiskDevice;
+  EFI_BLOCK_IO_MEDIA  *Media;
+  EFI_STATUS          Status;
+  BOOLEAN             MediaChange;
+  EFI_TPL             OldTpl;
+  UINT8               SenseDataLength;
+  UINT8               HostAdapterStatus;
+  UINT8               TargetStatus;
+  VOID                *AlignedBuffer;
+  BOOLEAN             AlignedBufferAllocated;
+
+  AlignedBuffer           = NULL;
+  MediaChange             = FALSE;
+  AlignedBufferAllocated  = FALSE;
+  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
+  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
+  Media                   = ScsiDiskDevice->BlkIo.Media;
+
+  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
+
+  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice->Handle)) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
+    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
+    if (EFI_ERROR (Status)) {
+      Status = EFI_DEVICE_ERROR;
+      goto Done;
+    }
+
+    if (MediaChange) {
+      gBS->ReinstallProtocolInterface (
+              ScsiDiskDevice->Handle,
+              &gEfiStorageSecurityCommandProtocolGuid,
+              &ScsiDiskDevice->StorageSecurity,
+              &ScsiDiskDevice->StorageSecurity
+              );
+      if (Media->MediaPresent) {
+        Status = EFI_MEDIA_CHANGED;
+      } else {
+        Status = EFI_NO_MEDIA;
+      }
+      goto Done;
+    }
+  }
+
+  //
+  // Validate Media
+  //
+  if (!(Media->MediaPresent)) {
+    Status = EFI_NO_MEDIA;
+    goto Done;
+  }
+
+  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
+    Status = EFI_MEDIA_CHANGED;
+    goto Done;
+  }
+
+  if (Media->ReadOnly) {
+    Status = EFI_WRITE_PROTECTED;
+    goto Done;
+  }
+
+  if (PayloadBufferSize != 0) {
+    if (PayloadBuffer == NULL) {
+      Status = EFI_INVALID_PARAMETER;
+      goto Done;
+    }
+
+    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer, ScsiDiskDevice->ScsiIo->IoAlign)) {
+      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice, PayloadBufferSize);
+      if (AlignedBuffer == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Done;
+      }
+      CopyMem (AlignedBuffer, PayloadBuffer, PayloadBufferSize);
+      AlignedBufferAllocated = TRUE;
+    } else {
+      AlignedBuffer = PayloadBuffer;
+    }
+  }
+
+  Status = ScsiSecurityProtocolOutCommand (
+            ScsiDiskDevice->ScsiIo,
+            Timeout,
+            ScsiDiskDevice->SenseData,
+            &SenseDataLength,
+            &HostAdapterStatus,
+            &TargetStatus,
+            SecurityProtocolId,
+            SecurityProtocolSpecificData,
+            (UINT32) PayloadBufferSize,
+            AlignedBuffer
+          );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = CheckHostAdapterStatus (HostAdapterStatus);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = CheckTargetStatus (TargetStatus);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+Done:
+  if (AlignedBufferAllocated) {
+    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
+  }
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
 
 /**
   Detect Device and read out capacity ,if error occurs, parse the sense key.
@@ -2261,6 +2687,8 @@ ScsiDiskTestUnitReady (
     return EFI_DEVICE_ERROR;
   }
 
+  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
+
   if (SenseDataLength != 0) {
     *NumberOfSenseKeys = SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA);
     *SenseDataArray    = ScsiDiskDevice->SenseData;
@@ -2315,13 +2743,12 @@ DetectMediaParsingSenseKeys (
   BOOLEAN RetryLater;
 
   //
-  // Default is to read capacity, unless..
+  // Default is no action
   //
-  *Action = ACTION_READ_CAPACITY;
+  *Action = ACTION_NO_ACTION;
 
   if (NumberOfSenseKeys == 0) {
     if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
-      *Action = ACTION_NO_ACTION;
     }
     return EFI_SUCCESS;
   }
@@ -2331,7 +2758,6 @@ DetectMediaParsingSenseKeys (
     // No Sense Key returned from last submitted command
     //
     if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
-      *Action = ACTION_NO_ACTION;
     }
     return EFI_SUCCESS;
   }
@@ -2339,13 +2765,13 @@ DetectMediaParsingSenseKeys (
   if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
     ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
     ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
-    *Action = ACTION_NO_ACTION;
     DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
     return EFI_SUCCESS;
   }
 
   if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
     ScsiDiskDevice->BlkIo.Media->MediaId++;
+    *Action = ACTION_READ_CAPACITY;
     DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaChange!\n"));
     return EFI_SUCCESS;
   }
@@ -2374,7 +2800,6 @@ DetectMediaParsingSenseKeys (
       DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
       return EFI_SUCCESS;
     }
-    *Action = ACTION_NO_ACTION;
     return EFI_DEVICE_ERROR;
   }
 
@@ -2808,8 +3233,6 @@ GetMediaInfo (
       }
     }
   }
-
-  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
 }
 
 /**
@@ -5358,6 +5781,14 @@ DetermineInstallEraseBlock (
   RetVal         = TRUE;
   CapacityData16 = NULL;
 
+  //
+  // UNMAP command is not supported by any of the UFS WLUNs.
+  //
+  if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_WLUN) {
+    RetVal = FALSE;
+    goto Done;
+  }
+
   Status = gBS->HandleProtocol (
                   ChildHandle,
                   &gEfiDevicePathProtocolGuid,
@@ -5460,6 +5891,65 @@ Done:
   return RetVal;
 }
 
+/**
+  Determine if EFI Storage Security Command Protocol should be produced.
+
+  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
+  @param   ChildHandle       Handle of device.
+
+  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
+  @retval  FALSE   Should not produce EFI Storage Security Command Protocol.
+
+**/
+BOOLEAN
+DetermineInstallStorageSecurity (
+  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
+  IN  EFI_HANDLE             ChildHandle
+  )
+{
+  EFI_STATUS                      Status;
+  UFS_DEVICE_PATH                 *UfsDevice;
+  BOOLEAN                         RetVal;
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePathNode;
+
+  UfsDevice      = NULL;
+  RetVal         = TRUE;
+
+  Status = gBS->HandleProtocol (
+                  ChildHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &DevicePathNode
+                  );
+  //
+  // Device Path protocol must be installed on the device handle.
+  //
+  ASSERT_EFI_ERROR (Status);
+
+  while (!IsDevicePathEndType (DevicePathNode)) {
+    //
+    // For now, only support Storage Security Command Protocol on UFS devices.
+    //
+    if ((DevicePathNode->Type == MESSAGING_DEVICE_PATH) &&
+        (DevicePathNode->SubType == MSG_UFS_DP)) {
+      UfsDevice = (UFS_DEVICE_PATH *) DevicePathNode;
+      break;
+    }
+
+    DevicePathNode = NextDevicePathNode (DevicePathNode);
+  }
+  if (UfsDevice == NULL) {
+    RetVal = FALSE;
+    goto Done;
+  }
+
+  if (UfsDevice->Lun != UFS_WLUN_RPMB) {
+    RetVal = FALSE;
+  }
+
+Done:
+  return RetVal;
+}
+
 /**
   Provides inquiry information for the controller type.
 
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
index 1518b251d8..0bb67f2ddc 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -819,7 +819,9 @@ UfsPassThruDriverBindingStart (
   UINTN                                 UfsHcBase;
   UINT32                                Index;
   UFS_UNIT_DESC                         UnitDescriptor;
+  UFS_DEV_DESC                          DeviceDescriptor;
   UINT32                                UnitDescriptorSize;
+  UINT32                                DeviceDescriptorSize;
 
   Status    = EFI_SUCCESS;
   UfsHc     = NULL;
@@ -894,7 +896,6 @@ UfsPassThruDriverBindingStart (
 
   //
   // Check if 8 common luns are active and set corresponding bit mask.
-  // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.
   //
   UnitDescriptorSize = sizeof (UFS_UNIT_DESC);
   for (Index = 0; Index < 8; Index++) {
@@ -909,6 +910,20 @@ UfsPassThruDriverBindingStart (
     }
   }
 
+  //
+  // Check if RPMB WLUN is supported and set corresponding bit mask.
+  //
+  DeviceDescriptorSize = sizeof (UFS_DEV_DESC);
+  Status = UfsRwDeviceDesc (Private, TRUE, UfsDeviceDesc, 0, 0, &DeviceDescriptor, &DeviceDescriptorSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to read device descriptor, status = %r\n", Status));
+  } else {
+    if (DeviceDescriptor.SecurityLun == 0x1) {
+      DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
+      Private->Luns.BitMask |= BIT11;
+    }
+  }
+
   //
   // Start the asynchronous interrupt monitor
   //
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out
  2019-06-13  2:04 ` [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out Zurcher, Christopher J
@ 2019-06-13 12:54   ` Liming Gao
  2019-06-13 21:39     ` Zurcher, Christopher J
  0 siblings, 1 reply; 13+ messages in thread
From: Liming Gao @ 2019-06-13 12:54 UTC (permalink / raw)
  To: Zurcher, Christopher J, devel@edk2.groups.io; +Cc: Yao, Jiewen, Wang, Jian J


> -----Original Message-----
> From: Zurcher, Christopher J
> Sent: Thursday, June 13, 2019 10:05 AM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <liming.gao@intel.com>
> Subject: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out
> 
> 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>
> Cc: Liming Gao <liming.gao@intel.com>
> Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@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 cbe5709fe5..10d7b49ba7 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)

Why remove ASCIT8_1 & ASCIT8_2? Can we keep them for compatibility?

> -//
> -// 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 10dd81902b..a0d99e703a 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,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 05e46bda9c..27c31fe7f9 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>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -43,8 +43,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 c7491d1436..7584d717ad 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,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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
  2019-06-13  2:04 [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol Zurcher, Christopher J
  2019-06-13  2:04 ` [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out Zurcher, Christopher J
  2019-06-13  2:04 ` [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol Zurcher, Christopher J
@ 2019-06-13 12:58 ` Liming Gao
  2019-06-13 22:25   ` Zurcher, Christopher J
  2 siblings, 1 reply; 13+ messages in thread
From: Liming Gao @ 2019-06-13 12:58 UTC (permalink / raw)
  To: Zurcher, Christopher J, devel@edk2.groups.io
  Cc: Kinney, Michael D, Yao, Jiewen, Wang, Jian J

Zurcher:
  Can you share what test has been done for this feature?

Thanks
Liming
> -----Original Message-----
> From: Zurcher, Christopher J
> Sent: Thursday, June 13, 2019 10:05 AM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao,
> Liming <liming.gao@intel.com>
> Subject: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546
> 
> V4 changes:
> Add SSC Protocol in addition to BlockIo instead of in place of BlockIo.
> Add error handling for (BlockSize == 0) in Read and WriteBlocks commands
> to handle partitions that do not support ReadCapacity().
> 
> V3 changes:
> Initialize AlignedBuffer variable in ScsiDiskReceiveData and
> ScsiDiskSendData functions. Remove redundant input validation and debug
> message in ScsiDiskSendData.
> 
> V2 changes:
> Split the patch into separate commits for separate packages.
> 
> To support RPMB access on UFS devices, support must be added to
> the ScsiDiskDxe driver for the Storage Security Command Protocol.
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> 
> Christopher J Zurcher (2):
>   MdePkg: Implement SCSI commands for Security Protocol In/Out
>   MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
> 
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
>  MdePkg/Include/IndustryStandard/Scsi.h            |  48 +-
>  MdePkg/Include/Library/UefiScsiLib.h              | 126 ++++-
>  MdePkg/Include/Protocol/ScsiIo.h                  |   9 +-
>  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522 +++++++++++++++++++-
>  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
>  MdePkg/Library/UefiScsiLib/UefiScsiLib.c          | 205 +++++++-
>  9 files changed, 1064 insertions(+), 44 deletions(-)
> 
> --
> 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out
  2019-06-13 12:54   ` Liming Gao
@ 2019-06-13 21:39     ` Zurcher, Christopher J
  2019-06-18  2:12       ` [edk2-devel] " Wu, Hao A
  0 siblings, 1 reply; 13+ messages in thread
From: Zurcher, Christopher J @ 2019-06-13 21:39 UTC (permalink / raw)
  To: Gao, Liming, devel@edk2.groups.io; +Cc: Yao, Jiewen, Wang, Jian J

> Why remove ASCIT8_1 & ASCIT8_2? Can we keep them for compatibility?

If that's preferred, I can add them back in. They were only removed as they are marked obsolete in SPC-5.

--
Christopher Zurcher

-----Original Message-----
From: Gao, Liming 
Sent: Thursday, June 13, 2019 05:54
To: Zurcher, Christopher J <christopher.j.zurcher@intel.com>; devel@edk2.groups.io
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
Subject: RE: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out


> -----Original Message-----
> From: Zurcher, Christopher J
> Sent: Thursday, June 13, 2019 10:05 AM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <liming.gao@intel.com>
> Subject: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out
> 
> 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>
> Cc: Liming Gao <liming.gao@intel.com>
> Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@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 cbe5709fe5..10d7b49ba7 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)

Why remove ASCIT8_1 & ASCIT8_2? Can we keep them for compatibility?

> -//
> -// 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 10dd81902b..a0d99e703a 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,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 05e46bda9c..27c31fe7f9 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>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -43,8 +43,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 c7491d1436..7584d717ad 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,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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
  2019-06-13 12:58 ` [PATCH v4 0/2] Add SCSI Support for " Liming Gao
@ 2019-06-13 22:25   ` Zurcher, Christopher J
  2019-06-13 22:31     ` Yao, Jiewen
  0 siblings, 1 reply; 13+ messages in thread
From: Zurcher, Christopher J @ 2019-06-13 22:25 UTC (permalink / raw)
  To: Gao, Liming, devel@edk2.groups.io
  Cc: Kinney, Michael D, Yao, Jiewen, Wang, Jian J

A unit test has been run which provisions RPMB key, writes data, and verifies it after reading on the following boot.
Further, this code is being exercised for secure storage on multiple platforms as part of standard boot flow.

Unit test files emailed separately.

Thanks,
Christopher Zurcher


-----Original Message-----
From: Gao, Liming 
Sent: Thursday, June 13, 2019 05:59
To: Zurcher, Christopher J <christopher.j.zurcher@intel.com>; devel@edk2.groups.io
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
Subject: RE: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol

Zurcher:
  Can you share what test has been done for this feature?

Thanks
Liming
> -----Original Message-----
> From: Zurcher, Christopher J
> Sent: Thursday, June 13, 2019 10:05 AM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao,
> Liming <liming.gao@intel.com>
> Subject: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546
> 
> V4 changes:
> Add SSC Protocol in addition to BlockIo instead of in place of BlockIo.
> Add error handling for (BlockSize == 0) in Read and WriteBlocks commands
> to handle partitions that do not support ReadCapacity().
> 
> V3 changes:
> Initialize AlignedBuffer variable in ScsiDiskReceiveData and
> ScsiDiskSendData functions. Remove redundant input validation and debug
> message in ScsiDiskSendData.
> 
> V2 changes:
> Split the patch into separate commits for separate packages.
> 
> To support RPMB access on UFS devices, support must be added to
> the ScsiDiskDxe driver for the Storage Security Command Protocol.
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> 
> Christopher J Zurcher (2):
>   MdePkg: Implement SCSI commands for Security Protocol In/Out
>   MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
> 
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
>  MdePkg/Include/IndustryStandard/Scsi.h            |  48 +-
>  MdePkg/Include/Library/UefiScsiLib.h              | 126 ++++-
>  MdePkg/Include/Protocol/ScsiIo.h                  |   9 +-
>  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522 +++++++++++++++++++-
>  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
>  MdePkg/Library/UefiScsiLib/UefiScsiLib.c          | 205 +++++++-
>  9 files changed, 1064 insertions(+), 44 deletions(-)
> 
> --
> 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
  2019-06-13 22:25   ` Zurcher, Christopher J
@ 2019-06-13 22:31     ` Yao, Jiewen
  2019-06-14  0:14       ` Wu, Hao A
  0 siblings, 1 reply; 13+ messages in thread
From: Yao, Jiewen @ 2019-06-13 22:31 UTC (permalink / raw)
  To: Zurcher, Christopher J, Gao, Liming, devel@edk2.groups.io
  Cc: Kinney, Michael D, Wang, Jian J, Ni, Ray, Wu, Hao A

Thank you Christopher.
Your code looks good to me.

I also recommend MdeModulePkg/SCSI owner take a look and give r-b.

Ray or Hao
Can you help on that?

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zurcher, Christopher J
> Sent: Friday, June 14, 2019 6:26 AM
> To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> Subject: RE: [PATCH v4 0/2] Add SCSI Support for Storage Security Command
> Protocol
> 
> A unit test has been run which provisions RPMB key, writes data, and verifies
> it after reading on the following boot.
> Further, this code is being exercised for secure storage on multiple platforms
> as part of standard boot flow.
> 
> Unit test files emailed separately.
> 
> Thanks,
> Christopher Zurcher
> 
> 
> -----Original Message-----
> From: Gao, Liming
> Sent: Thursday, June 13, 2019 05:59
> To: Zurcher, Christopher J <christopher.j.zurcher@intel.com>;
> devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> Subject: RE: [PATCH v4 0/2] Add SCSI Support for Storage Security Command
> Protocol
> 
> Zurcher:
>   Can you share what test has been done for this feature?
> 
> Thanks
> Liming
> > -----Original Message-----
> > From: Zurcher, Christopher J
> > Sent: Thursday, June 13, 2019 10:05 AM
> > To: devel@edk2.groups.io
> > Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao,
> > Liming <liming.gao@intel.com>
> > Subject: [PATCH v4 0/2] Add SCSI Support for Storage Security Command
> Protocol
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546
> >
> > V4 changes:
> > Add SSC Protocol in addition to BlockIo instead of in place of BlockIo.
> > Add error handling for (BlockSize == 0) in Read and WriteBlocks commands
> > to handle partitions that do not support ReadCapacity().
> >
> > V3 changes:
> > Initialize AlignedBuffer variable in ScsiDiskReceiveData and
> > ScsiDiskSendData functions. Remove redundant input validation and debug
> > message in ScsiDiskSendData.
> >
> > V2 changes:
> > Split the patch into separate commits for separate packages.
> >
> > To support RPMB access on UFS devices, support must be added to
> > the ScsiDiskDxe driver for the Storage Security Command Protocol.
> >
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> >
> > Christopher J Zurcher (2):
> >   MdePkg: Implement SCSI commands for Security Protocol In/Out
> >   MdeModulePkg/ScsiDiskDxe: Support Storage Security Command
> Protocol
> >
> >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
> >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
> >  MdePkg/Include/IndustryStandard/Scsi.h            |  48 +-
> >  MdePkg/Include/Library/UefiScsiLib.h              | 126 ++++-
> >  MdePkg/Include/Protocol/ScsiIo.h                  |   9 +-
> >  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
> >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522
> +++++++++++++++++++-
> >  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
> >  MdePkg/Library/UefiScsiLib/UefiScsiLib.c          | 205 +++++++-
> >  9 files changed, 1064 insertions(+), 44 deletions(-)
> >
> > --
> > 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol
  2019-06-13 22:31     ` Yao, Jiewen
@ 2019-06-14  0:14       ` Wu, Hao A
  0 siblings, 0 replies; 13+ messages in thread
From: Wu, Hao A @ 2019-06-14  0:14 UTC (permalink / raw)
  To: Yao, Jiewen, Zurcher, Christopher J, Gao, Liming,
	devel@edk2.groups.io
  Cc: Kinney, Michael D, Wang, Jian J, Ni, Ray

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, June 14, 2019 6:32 AM
> To: Zurcher, Christopher J; Gao, Liming; devel@edk2.groups.io
> Cc: Kinney, Michael D; Wang, Jian J; Ni, Ray; Wu, Hao A
> Subject: RE: [PATCH v4 0/2] Add SCSI Support for Storage Security Command
> Protocol
> 
> Thank you Christopher.
> Your code looks good to me.
> 
> I also recommend MdeModulePkg/SCSI owner take a look and give r-b.
> 
> Ray or Hao
> Can you help on that?


Yes, I will take a look.
Please grant me some time, will give my feedbacks early next week.

Best Regards,
Hao Wu


> 
> Thank you
> Yao Jiewen
> 
> > -----Original Message-----
> > From: Zurcher, Christopher J
> > Sent: Friday, June 14, 2019 6:26 AM
> > To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io
> > Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> > Subject: RE: [PATCH v4 0/2] Add SCSI Support for Storage Security
> Command
> > Protocol
> >
> > A unit test has been run which provisions RPMB key, writes data, and
> verifies
> > it after reading on the following boot.
> > Further, this code is being exercised for secure storage on multiple
> platforms
> > as part of standard boot flow.
> >
> > Unit test files emailed separately.
> >
> > Thanks,
> > Christopher Zurcher
> >
> >
> > -----Original Message-----
> > From: Gao, Liming
> > Sent: Thursday, June 13, 2019 05:59
> > To: Zurcher, Christopher J <christopher.j.zurcher@intel.com>;
> > devel@edk2.groups.io
> > Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> > Subject: RE: [PATCH v4 0/2] Add SCSI Support for Storage Security
> Command
> > Protocol
> >
> > Zurcher:
> >   Can you share what test has been done for this feature?
> >
> > Thanks
> > Liming
> > > -----Original Message-----
> > > From: Zurcher, Christopher J
> > > Sent: Thursday, June 13, 2019 10:05 AM
> > > To: devel@edk2.groups.io
> > > Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao,
> > > Liming <liming.gao@intel.com>
> > > Subject: [PATCH v4 0/2] Add SCSI Support for Storage Security Command
> > Protocol
> > >
> > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546
> > >
> > > V4 changes:
> > > Add SSC Protocol in addition to BlockIo instead of in place of BlockIo.
> > > Add error handling for (BlockSize == 0) in Read and WriteBlocks
> commands
> > > to handle partitions that do not support ReadCapacity().
> > >
> > > V3 changes:
> > > Initialize AlignedBuffer variable in ScsiDiskReceiveData and
> > > ScsiDiskSendData functions. Remove redundant input validation and
> debug
> > > message in ScsiDiskSendData.
> > >
> > > V2 changes:
> > > Split the patch into separate commits for separate packages.
> > >
> > > To support RPMB access on UFS devices, support must be added to
> > > the ScsiDiskDxe driver for the Storage Security Command Protocol.
> > >
> > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > Cc: Liming Gao <liming.gao@intel.com>
> > >
> > > Christopher J Zurcher (2):
> > >   MdePkg: Implement SCSI commands for Security Protocol In/Out
> > >   MdeModulePkg/ScsiDiskDxe: Support Storage Security Command
> > Protocol
> > >
> > >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
> > >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
> > >  MdePkg/Include/IndustryStandard/Scsi.h            |  48 +-
> > >  MdePkg/Include/Library/UefiScsiLib.h              | 126 ++++-
> > >  MdePkg/Include/Protocol/ScsiIo.h                  |   9 +-
> > >  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
> > >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522
> > +++++++++++++++++++-
> > >  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
> > >  MdePkg/Library/UefiScsiLib/UefiScsiLib.c          | 205 +++++++-
> > >  9 files changed, 1064 insertions(+), 44 deletions(-)
> > >
> > > --
> > > 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out
  2019-06-13 21:39     ` Zurcher, Christopher J
@ 2019-06-18  2:12       ` Wu, Hao A
  0 siblings, 0 replies; 13+ messages in thread
From: Wu, Hao A @ 2019-06-18  2:12 UTC (permalink / raw)
  To: devel@edk2.groups.io, Zurcher, Christopher J, Gao, Liming
  Cc: Yao, Jiewen, Wang, Jian J

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Zurcher, Christopher J
> Sent: Friday, June 14, 2019 5:39 AM
> To: Gao, Liming; devel@edk2.groups.io
> Cc: Yao, Jiewen; Wang, Jian J
> Subject: Re: [edk2-devel] [PATCH v4 1/2] MdePkg: Implement SCSI
> commands for Security Protocol In/Out
> 
> > Why remove ASCIT8_1 & ASCIT8_2? Can we keep them for compatibility?
> 
> If that's preferred, I can add them back in. They were only removed as they
> are marked obsolete in SPC-5.


I prefer to keep them for compatibility consideration as well.
You can append the comments to mark them as deprecated in spc5 spec.

Also, I suggest to add a parameter called 'Inc512' for both new APIs:
ScsiSecurityProtocolInCommand
ScsiSecurityProtocolOutCommand

Though UFS spec requires the INC_512 field of a CDB to be set to 0, but
for other devices, setting this field to 1 may be a valid configuration.

Some inline comments below:


> 
> --
> Christopher Zurcher
> 
> -----Original Message-----
> From: Gao, Liming
> Sent: Thursday, June 13, 2019 05:54
> To: Zurcher, Christopher J <christopher.j.zurcher@intel.com>;
> devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>
> Subject: RE: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security
> Protocol In/Out
> 
> 
> > -----Original Message-----
> > From: Zurcher, Christopher J
> > Sent: Thursday, June 13, 2019 10:05 AM
> > To: devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Gao, Liming <liming.gao@intel.com>
> > Subject: [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security
> Protocol In/Out
> >
> > 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>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@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 cbe5709fe5..10d7b49ba7 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)
> 
> Why remove ASCIT8_1 & ASCIT8_2? Can we keep them for compatibility?
> 
> > -//
> > -// 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 10dd81902b..a0d99e703a 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,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


There is no 'StartLba' & 'SectorSize' parameters for APIs:

ScsiSecurityProtocolInCommand
ScsiSecurityProtocolOutCommand

Could you help to update the comments to address this?


> > +  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.


Referring to the implementation of the library (changes made in
MdePkg/Library/UefiScsiLib/UefiScsiLib.c):

'TransferLength' (input) specifies the length of content in 'DataBuffer';
'DataLength' (input & output) reflects the actual number of bytes
transferred.

How about swapping their names and changing the description comments to:

  @param[in]      DataLength           The size in bytes of the 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 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
> > +  );


Suggest the below parameter type changes to match with the services
definition of the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL (including the
name swap mentioned above):

IN     UINT32                TransferLength,
to
IN     UINTN                 DataLength,

IN OUT UINT32                *DataLength
to
   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.  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.


Suggest to rename 'TransferLength' to 'DataLength' so that it may be a bit
more clear for users to know 'DataLength' reflects the size of 'DataBuffer'.


> > +  @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,


Suggest the below parameter type changes to match with the services
definition of the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL (including the
name change mentioned above):

IN     UINT32                TransferLength
to
IN     UINTN                 DataLength

Best Regards,
Hao Wu


> > +  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 05e46bda9c..27c31fe7f9 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>
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> > @@ -43,8 +43,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 c7491d1436..7584d717ad 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,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
> 
> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
  2019-06-13  2:04 ` [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol Zurcher, Christopher J
@ 2019-06-18  2:12   ` Wu, Hao A
  2019-08-16 20:22     ` Zurcher, Christopher J
  0 siblings, 1 reply; 13+ messages in thread
From: Wu, Hao A @ 2019-06-18  2:12 UTC (permalink / raw)
  To: devel@edk2.groups.io, Zurcher, Christopher J
  Cc: Kinney, Michael D, Yao, Jiewen, Wang, Jian J, Gao, Liming

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Zurcher, Christopher J
> Sent: Thursday, June 13, 2019 10:05 AM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D; Yao, Jiewen; Wang, Jian J; Gao, Liming
> Subject: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support
> Storage Security Command Protocol
> 
> This patch implements the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> in the
> ScsiDiskDxe driver.
> 
> Support is currently limited to the RPMB Well-known LUN for UFS devices.


Hello,

Some general level comments:
1. CDROM device issue
This patch will bring an issue to the CDROM devices that CD/DVD will not
be recognized properly.

I think the cause of the issue is the relocation of the below logic:
  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
from GetMediaInfo() to ScsiDiskTestUnitReady(). It will lead to the read
capacity command being skipped for CDROM devices, which results into the
LastBlock for the device equals to 0.

We may need to find out a better approach to handle the case for UFS RPMB.

2. Split this patch into three commits
Besides adding the Storage Security Command Protocol support in ScsiDisk
driver, the patch also:
* Updates the ScsiBus driver to recognize the Well known logical unit
* Updates the UfsPassThruDxe driver to expose the RPMB WLUN

Please help to split the patch into 3 separate commits.

3. Updates for the BlockIO(2) services
For functions ScsiDiskReadBlocks(Ex) & ScsiDiskWriteBlocks(Ex), below codes
are added for the dummy BlockIO(2) protocol instance on the UFS RPMB Lun:

  if (BlockSize == 0) {
    Status = EFI_UNSUPPORTED;
    goto Done;
  }

I suggest to use status 'EFI_DEVICE_ERROR' for such case, since
'EFI_UNSUPPORTED' is not listed as an expected return status in the UEFI
spec.

4. Reinstallation of the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
For the reinstallation of the SSC protocol to handle media change, I saw
this is only handled within ScsiDiskReceiveData() & ScsiDiskSendData().
The below functions should be considered as well:

ScsiDiskReadBlocks(Ex)
ScsiDiskWriteBlocks(Ex)
ScsiDiskFlushBlocksEx
ScsiDiskEraseBlocks


Some inline comments below:


> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
> ---
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
>  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522
> +++++++++++++++++++-
>  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
>  5 files changed, 698 insertions(+), 22 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> index 5500d828e9..40818e669b 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> @@ -3,7 +3,7 @@
>  #  It detects the SCSI disk media and installs Block I/O and Block I/O2 Protocol
> on
>  #  the device handle.
>  #
> -#  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
>  #
>  ##
> @@ -52,6 +52,7 @@
>    gEfiBlockIoProtocolGuid                       ## BY_START
>    gEfiBlockIo2ProtocolGuid                      ## BY_START
>    gEfiEraseBlockProtocolGuid                    ## BY_START
> +  gEfiStorageSecurityCommandProtocolGuid        ## BY_START
>    gEfiScsiIoProtocolGuid                        ## TO_START
>    gEfiScsiPassThruProtocolGuid                  ## TO_START
>    gEfiExtScsiPassThruProtocolGuid               ## TO_START
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> index 42c0aaaa95..2d8679ec6f 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Header file for SCSI Disk Driver.
> 
> -Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -22,6 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Protocol/ScsiPassThruExt.h>
>  #include <Protocol/ScsiPassThru.h>
>  #include <Protocol/DiskInfo.h>
> +#include <Protocol/StorageSecurityCommand.h>
> 
> 
>  #include <Library/DebugLib.h>
> @@ -38,6 +39,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #define IS_DEVICE_FIXED(a)        (a)->FixedDevice ? 1 : 0
> 
> +#define IS_ALIGNED(addr, size)    (((UINTN) (addr) & (size - 1)) == 0)
> +
> +#define UFS_WLUN_RPMB 0xC4
> +
>  typedef struct {
>    UINT32                    MaxLbaCnt;
>    UINT32                    MaxBlkDespCnt;
> @@ -51,6 +56,8 @@ typedef struct {
> 
>    EFI_HANDLE                Handle;
> 
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL   StorageSecurity;
> +
>    EFI_BLOCK_IO_PROTOCOL     BlkIo;
>    EFI_BLOCK_IO2_PROTOCOL    BlkIo2;
>    EFI_BLOCK_IO_MEDIA        BlkIoMedia;
> @@ -95,6 +102,7 @@ typedef struct {
>  #define SCSI_DISK_DEV_FROM_BLKIO(a)  CR (a, SCSI_DISK_DEV, BlkIo,
> SCSI_DISK_DEV_SIGNATURE)
>  #define SCSI_DISK_DEV_FROM_BLKIO2(a)  CR (a, SCSI_DISK_DEV, BlkIo2,
> SCSI_DISK_DEV_SIGNATURE)
>  #define SCSI_DISK_DEV_FROM_ERASEBLK(a)  CR (a, SCSI_DISK_DEV,
> EraseBlock, SCSI_DISK_DEV_SIGNATURE)
> +#define SCSI_DISK_DEV_FROM_STORSEC(a)  CR (a, SCSI_DISK_DEV,
> StorageSecurity, SCSI_DISK_DEV_SIGNATURE)
> 
>  #define SCSI_DISK_DEV_FROM_DISKINFO(a) CR (a, SCSI_DISK_DEV,
> DiskInfo, SCSI_DISK_DEV_SIGNATURE)
> 
> @@ -638,6 +646,151 @@ ScsiDiskEraseBlocks (
>    );
> 
> 
> +/**
> +  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.
> +
> +  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
> +ScsiDiskReceiveData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  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.
> +
> +  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
> +ScsiDiskSendData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16                                   SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  OUT VOID                                    *PayloadBuffer
> +  );
> +
> +
>  /**
>    Provides inquiry information for the controller type.
> 
> @@ -1428,4 +1581,20 @@ DetermineInstallEraseBlock (
>    IN  EFI_HANDLE             ChildHandle
>    );
> 
> +/**
> +  Determine if EFI Storage Security Command Protocol should be produced.
> +
> +  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
> +  @param   ChildHandle       Handle of device.
> +
> +  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
> +  @retval  FALSE   Should not produce EFI Storage Security Command
> Protocol.
> +
> +**/
> +BOOLEAN
> +DetermineInstallStorageSecurity (
> +  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
> +  IN  EFI_HANDLE             ChildHandle
> +  );
> +
>  #endif
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> index c4069aec0f..1caffd38cd 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> +++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> @@ -2,7 +2,7 @@
>    SCSI Bus driver that layers on every SCSI Pass Thru and
>    Extended SCSI Pass Thru protocol in the system.
> 
> -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
> 
>  **/
> @@ -1368,7 +1368,8 @@ DiscoverScsiDevice (
>      goto Done;
>    }
> 
> -  if (0x1e >= InquiryData->Peripheral_Type && InquiryData-
> >Peripheral_Type >= 0xa) {
> +  if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW) &&
> +      (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH)) {
>      ScsiDeviceFound = FALSE;
>      goto Done;
>    }
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> index fbdf927a11..01d5ad4969 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> @@ -1,7 +1,7 @@
>  /** @file
>    SCSI disk driver that layers on every SCSI IO protocol in the system.
> 
> -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
> 
>  **/
> @@ -151,7 +151,9 @@ ScsiDiskDriverBindingSupported (
> 
>    Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType);
>    if (!EFI_ERROR (Status)) {
> -    if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType ==
> EFI_SCSI_TYPE_CDROM)) {
> +    if ((DeviceType == EFI_SCSI_TYPE_DISK) ||
> +        (DeviceType == EFI_SCSI_TYPE_CDROM) ||
> +        (DeviceType == EFI_SCSI_TYPE_WLUN)) {
>        Status = EFI_SUCCESS;
>      } else {
>        Status = EFI_UNSUPPORTED;
> @@ -238,6 +240,8 @@ ScsiDiskDriverBindingStart (
>    ScsiDiskDevice->BlkIo2.ReadBlocksEx               = ScsiDiskReadBlocksEx;
>    ScsiDiskDevice->BlkIo2.WriteBlocksEx              = ScsiDiskWriteBlocksEx;
>    ScsiDiskDevice->BlkIo2.FlushBlocksEx              = ScsiDiskFlushBlocksEx;
> +  ScsiDiskDevice->StorageSecurity.ReceiveData       = ScsiDiskReceiveData;
> +  ScsiDiskDevice->StorageSecurity.SendData          = ScsiDiskSendData;
>    ScsiDiskDevice->EraseBlock.Revision               =
> EFI_ERASE_BLOCK_PROTOCOL_REVISION;
>    ScsiDiskDevice->EraseBlock.EraseLengthGranularity = 1;
>    ScsiDiskDevice->EraseBlock.EraseBlocks            = ScsiDiskEraseBlocks;
> @@ -258,6 +262,10 @@ ScsiDiskDriverBindingStart (
>      ScsiDiskDevice->BlkIo.Media->ReadOnly  = TRUE;
>      MustReadCapacity = FALSE;
>      break;
> +
> +  case EFI_SCSI_TYPE_WLUN:
> +    MustReadCapacity = FALSE;
> +    break;
>    }
>    //
>    // The Sense Data Array's initial size is 6
> @@ -309,8 +317,8 @@ ScsiDiskDriverBindingStart (
>      // Determine if Block IO & Block IO2 should be produced on this controller
>      // handle
>      //
> -    if (DetermineInstallBlockIo(Controller)) {
> -      InitializeInstallDiskInfo(ScsiDiskDevice, Controller);
> +    if (DetermineInstallBlockIo (Controller)) {
> +      InitializeInstallDiskInfo (ScsiDiskDevice, Controller);
>        Status = gBS->InstallMultipleProtocolInterfaces (
>                        &Controller,
>                        &gEfiBlockIoProtocolGuid,
> @@ -321,16 +329,27 @@ ScsiDiskDriverBindingStart (
>                        &ScsiDiskDevice->DiskInfo,
>                        NULL
>                        );
> -      if (!EFI_ERROR(Status)) {
> -        if (DetermineInstallEraseBlock(ScsiDiskDevice, Controller)) {
> +      if (!EFI_ERROR (Status)) {
> +        if (DetermineInstallEraseBlock (ScsiDiskDevice, Controller)) {
>            Status = gBS->InstallProtocolInterface (
>                            &Controller,
>                            &gEfiEraseBlockProtocolGuid,
>                            EFI_NATIVE_INTERFACE,
>                            &ScsiDiskDevice->EraseBlock
>                            );
> -          if (EFI_ERROR(Status)) {
> -            DEBUG ((EFI_D_ERROR, "ScsiDisk: Failed to install the Erase Block
> Protocol! Status = %r\n", Status));
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Erase Block
> Protocol! Status = %r\n", Status));
> +          }
> +        }
> +        if (DetermineInstallStorageSecurity (ScsiDiskDevice, Controller)) {
> +          Status = gBS->InstallProtocolInterface (
> +                          &Controller,
> +                          &gEfiStorageSecurityCommandProtocolGuid,
> +                          EFI_NATIVE_INTERFACE,
> +                          &ScsiDiskDevice->StorageSecurity
> +                          );
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Storage
> Security Command Protocol! Status = %r\n", Status));
>            }
>          }
>          ScsiDiskDevice->ControllerNameTable = NULL;
> @@ -606,6 +625,11 @@ ScsiDiskReadBlocks (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -742,6 +766,11 @@ ScsiDiskWriteBlocks (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -968,6 +997,11 @@ ScsiDiskReadBlocksEx (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -1131,6 +1165,11 @@ ScsiDiskWriteBlocksEx (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -1708,6 +1747,393 @@ Done:
>    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.
> +
> +  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
> +ScsiDiskReceiveData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16                                   SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  OUT VOID                                    *PayloadBuffer,
> +  OUT UINTN                                   *PayloadTransferSize
> +  )
> +{
> +  SCSI_DISK_DEV       *ScsiDiskDevice;
> +  EFI_BLOCK_IO_MEDIA  *Media;
> +  EFI_STATUS          Status;
> +  BOOLEAN             MediaChange;
> +  EFI_TPL             OldTpl;
> +  UINT8               SenseDataLength;
> +  UINT8               HostAdapterStatus;
> +  UINT8               TargetStatus;
> +  VOID                *AlignedBuffer;
> +  BOOLEAN             AlignedBufferAllocated;
> +
> +  AlignedBuffer           = NULL;
> +  MediaChange             = FALSE;
> +  AlignedBufferAllocated  = FALSE;
> +  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
> +  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
> +  Media                   = ScsiDiskDevice->BlkIo.Media;
> +
> +  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof
> (EFI_SCSI_SENSE_DATA));
> +
> +  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice-
> >Handle)) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }


I think the above 'if' statement is not needed, and should be placed
within the below 'if' statement when handling media change:

  if (MediaChange) {...}

(Similar case to ScsiDiskSendData().)

> +
> +  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
> +    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
> +    if (EFI_ERROR (Status)) {
> +      Status = EFI_DEVICE_ERROR;
> +      goto Done;
> +    }
> +
> +    if (MediaChange) {
> +      gBS->ReinstallProtocolInterface (
> +              ScsiDiskDevice->Handle,
> +              &gEfiStorageSecurityCommandProtocolGuid,
> +              &ScsiDiskDevice->StorageSecurity,
> +              &ScsiDiskDevice->StorageSecurity
> +              );


The BlockIO(2) & EraseBlocks (if supported) should be reinstalled as well.

(Similar case to ScsiDiskSendData().)


> +      if (Media->MediaPresent) {
> +        Status = EFI_MEDIA_CHANGED;
> +      } else {
> +        Status = EFI_NO_MEDIA;
> +      }
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Validate Media
> +  //
> +  if (!(Media->MediaPresent)) {
> +    Status = EFI_NO_MEDIA;
> +    goto Done;
> +  }
> +
> +  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
> +    Status = EFI_MEDIA_CHANGED;
> +    goto Done;
> +  }
> +
> +  if (PayloadBufferSize != 0) {
> +    if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto Done;
> +    }
> +
> +    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer,
> ScsiDiskDevice->ScsiIo->IoAlign)) {
> +      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice,
> PayloadBufferSize);
> +      if (AlignedBuffer == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto Done;
> +      }
> +      ZeroMem (AlignedBuffer, PayloadBufferSize);
> +      AlignedBufferAllocated = TRUE;
> +    } else {
> +      AlignedBuffer = PayloadBuffer;
> +    }
> +  }
> +
> +  Status = ScsiSecurityProtocolInCommand (
> +            ScsiDiskDevice->ScsiIo,
> +            Timeout,
> +            ScsiDiskDevice->SenseData,
> +            &SenseDataLength,
> +            &HostAdapterStatus,
> +            &TargetStatus,
> +            SecurityProtocolId,
> +            SecurityProtocolSpecificData,
> +            (UINT32) PayloadBufferSize,
> +            AlignedBuffer,
> +            (UINT32 *) PayloadTransferSize
> +          );
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  if (AlignedBufferAllocated) {
> +    CopyMem (PayloadBuffer, AlignedBuffer, PayloadBufferSize);
> +  }
> +
> +  if (PayloadBufferSize < *PayloadTransferSize) {
> +    Status = EFI_WARN_BUFFER_TOO_SMALL;
> +    goto Done;
> +  }
> +
> +  Status = CheckHostAdapterStatus (HostAdapterStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = CheckTargetStatus (TargetStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +Done:
> +  if (AlignedBufferAllocated) {


IMO, the content in 'AlignedBuffer' should be wiped out, since it might
contain sensitive information. SSC protocol user can control the data in
'PayloadBuffer' but not in 'AlignedBuffer'.


> +    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
> +  }
> +  gBS->RestoreTPL (OldTpl);
> +  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.
> +
> +  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
> +ScsiDiskSendData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16                                   SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  OUT VOID                                    *PayloadBuffer
> +  )
> +{
> +  SCSI_DISK_DEV       *ScsiDiskDevice;
> +  EFI_BLOCK_IO_MEDIA  *Media;
> +  EFI_STATUS          Status;
> +  BOOLEAN             MediaChange;
> +  EFI_TPL             OldTpl;
> +  UINT8               SenseDataLength;
> +  UINT8               HostAdapterStatus;
> +  UINT8               TargetStatus;
> +  VOID                *AlignedBuffer;
> +  BOOLEAN             AlignedBufferAllocated;
> +
> +  AlignedBuffer           = NULL;
> +  MediaChange             = FALSE;
> +  AlignedBufferAllocated  = FALSE;
> +  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
> +  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
> +  Media                   = ScsiDiskDevice->BlkIo.Media;
> +
> +  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof
> (EFI_SCSI_SENSE_DATA));
> +
> +  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice-
> >Handle)) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
> +  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
> +    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
> +    if (EFI_ERROR (Status)) {
> +      Status = EFI_DEVICE_ERROR;
> +      goto Done;
> +    }
> +
> +    if (MediaChange) {
> +      gBS->ReinstallProtocolInterface (
> +              ScsiDiskDevice->Handle,
> +              &gEfiStorageSecurityCommandProtocolGuid,
> +              &ScsiDiskDevice->StorageSecurity,
> +              &ScsiDiskDevice->StorageSecurity
> +              );
> +      if (Media->MediaPresent) {
> +        Status = EFI_MEDIA_CHANGED;
> +      } else {
> +        Status = EFI_NO_MEDIA;
> +      }
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Validate Media
> +  //
> +  if (!(Media->MediaPresent)) {
> +    Status = EFI_NO_MEDIA;
> +    goto Done;
> +  }
> +
> +  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
> +    Status = EFI_MEDIA_CHANGED;
> +    goto Done;
> +  }
> +
> +  if (Media->ReadOnly) {
> +    Status = EFI_WRITE_PROTECTED;
> +    goto Done;
> +  }
> +
> +  if (PayloadBufferSize != 0) {
> +    if (PayloadBuffer == NULL) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto Done;
> +    }
> +
> +    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer,
> ScsiDiskDevice->ScsiIo->IoAlign)) {
> +      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice,
> PayloadBufferSize);
> +      if (AlignedBuffer == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto Done;
> +      }
> +      CopyMem (AlignedBuffer, PayloadBuffer, PayloadBufferSize);
> +      AlignedBufferAllocated = TRUE;
> +    } else {
> +      AlignedBuffer = PayloadBuffer;
> +    }
> +  }
> +
> +  Status = ScsiSecurityProtocolOutCommand (
> +            ScsiDiskDevice->ScsiIo,
> +            Timeout,
> +            ScsiDiskDevice->SenseData,
> +            &SenseDataLength,
> +            &HostAdapterStatus,
> +            &TargetStatus,
> +            SecurityProtocolId,
> +            SecurityProtocolSpecificData,
> +            (UINT32) PayloadBufferSize,
> +            AlignedBuffer
> +          );
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = CheckHostAdapterStatus (HostAdapterStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = CheckTargetStatus (TargetStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +Done:
> +  if (AlignedBufferAllocated) {


IMO, the content in 'AlignedBuffer' should be wiped out, since it might
contain sensitive information. SSC protocol user can control the data in
'PayloadBuffer' but not in 'AlignedBuffer'.


> +    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
> +  }
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> +
> 
>  /**
>    Detect Device and read out capacity ,if error occurs, parse the sense key.
> @@ -2261,6 +2687,8 @@ ScsiDiskTestUnitReady (
>      return EFI_DEVICE_ERROR;
>    }
> 
> +  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
> +
>    if (SenseDataLength != 0) {
>      *NumberOfSenseKeys = SenseDataLength / sizeof
> (EFI_SCSI_SENSE_DATA);
>      *SenseDataArray    = ScsiDiskDevice->SenseData;
> @@ -2315,13 +2743,12 @@ DetectMediaParsingSenseKeys (
>    BOOLEAN RetryLater;
> 
>    //
> -  // Default is to read capacity, unless..
> +  // Default is no action
>    //
> -  *Action = ACTION_READ_CAPACITY;
> +  *Action = ACTION_NO_ACTION;
> 
>    if (NumberOfSenseKeys == 0) {
>      if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
> -      *Action = ACTION_NO_ACTION;
>      }


I do not think the behavior is the same after the patch.
Can it be:

  if (NumberOfSenseKeys == 0) {
    if (!ScsiDiskDevice->BlkIo.Media->MediaPresent) {
      *Action = ACTION_READ_CAPACITY;
    }
    return EFI_SUCCESS;
  }


>      return EFI_SUCCESS;
>    }
> @@ -2331,7 +2758,6 @@ DetectMediaParsingSenseKeys (
>      // No Sense Key returned from last submitted command
>      //
>      if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
> -      *Action = ACTION_NO_ACTION;
>      }


I do not think the behavior is the same after the patch.
Can it be:

  if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
    //
    // No Sense Key returned from last submitted command
    //
    if (!ScsiDiskDevice->BlkIo.Media->MediaPresent) {
      *Action = ACTION_READ_CAPACITY;
    }
    return EFI_SUCCESS;
  }


Best Regards,
Hao Wu


>      return EFI_SUCCESS;
>    }
> @@ -2339,13 +2765,13 @@ DetectMediaParsingSenseKeys (
>    if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
>      ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
>      ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
> -    *Action = ACTION_NO_ACTION;
>      DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
>      return EFI_SUCCESS;
>    }
> 
>    if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
>      ScsiDiskDevice->BlkIo.Media->MediaId++;
> +    *Action = ACTION_READ_CAPACITY;
>      DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaChange!\n"));
>      return EFI_SUCCESS;
>    }
> @@ -2374,7 +2800,6 @@ DetectMediaParsingSenseKeys (
>        DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
>        return EFI_SUCCESS;
>      }
> -    *Action = ACTION_NO_ACTION;
>      return EFI_DEVICE_ERROR;
>    }
> 
> @@ -2808,8 +3233,6 @@ GetMediaInfo (
>        }
>      }
>    }
> -
> -  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
>  }
> 
>  /**
> @@ -5358,6 +5781,14 @@ DetermineInstallEraseBlock (
>    RetVal         = TRUE;
>    CapacityData16 = NULL;
> 
> +  //
> +  // UNMAP command is not supported by any of the UFS WLUNs.
> +  //
> +  if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_WLUN) {
> +    RetVal = FALSE;
> +    goto Done;
> +  }
> +
>    Status = gBS->HandleProtocol (
>                    ChildHandle,
>                    &gEfiDevicePathProtocolGuid,
> @@ -5460,6 +5891,65 @@ Done:
>    return RetVal;
>  }
> 
> +/**
> +  Determine if EFI Storage Security Command Protocol should be produced.
> +
> +  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
> +  @param   ChildHandle       Handle of device.
> +
> +  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
> +  @retval  FALSE   Should not produce EFI Storage Security Command
> Protocol.
> +
> +**/
> +BOOLEAN
> +DetermineInstallStorageSecurity (
> +  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
> +  IN  EFI_HANDLE             ChildHandle
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UFS_DEVICE_PATH                 *UfsDevice;
> +  BOOLEAN                         RetVal;
> +  EFI_DEVICE_PATH_PROTOCOL        *DevicePathNode;
> +
> +  UfsDevice      = NULL;
> +  RetVal         = TRUE;
> +
> +  Status = gBS->HandleProtocol (
> +                  ChildHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID **) &DevicePathNode
> +                  );
> +  //
> +  // Device Path protocol must be installed on the device handle.
> +  //
> +  ASSERT_EFI_ERROR (Status);
> +
> +  while (!IsDevicePathEndType (DevicePathNode)) {
> +    //
> +    // For now, only support Storage Security Command Protocol on UFS
> devices.
> +    //
> +    if ((DevicePathNode->Type == MESSAGING_DEVICE_PATH) &&
> +        (DevicePathNode->SubType == MSG_UFS_DP)) {
> +      UfsDevice = (UFS_DEVICE_PATH *) DevicePathNode;
> +      break;
> +    }
> +
> +    DevicePathNode = NextDevicePathNode (DevicePathNode);
> +  }
> +  if (UfsDevice == NULL) {
> +    RetVal = FALSE;
> +    goto Done;
> +  }
> +
> +  if (UfsDevice->Lun != UFS_WLUN_RPMB) {
> +    RetVal = FALSE;
> +  }
> +
> +Done:
> +  return RetVal;
> +}
> +
>  /**
>    Provides inquiry information for the controller type.
> 
> diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> index 1518b251d8..0bb67f2ddc 100644
> --- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> +++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> @@ -1,6 +1,6 @@
>  /** @file
> 
> -  Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -819,7 +819,9 @@ UfsPassThruDriverBindingStart (
>    UINTN                                 UfsHcBase;
>    UINT32                                Index;
>    UFS_UNIT_DESC                         UnitDescriptor;
> +  UFS_DEV_DESC                          DeviceDescriptor;
>    UINT32                                UnitDescriptorSize;
> +  UINT32                                DeviceDescriptorSize;
> 
>    Status    = EFI_SUCCESS;
>    UfsHc     = NULL;
> @@ -894,7 +896,6 @@ UfsPassThruDriverBindingStart (
> 
>    //
>    // Check if 8 common luns are active and set corresponding bit mask.
> -  // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper
> layer for authentication access.
>    //
>    UnitDescriptorSize = sizeof (UFS_UNIT_DESC);
>    for (Index = 0; Index < 8; Index++) {
> @@ -909,6 +910,20 @@ UfsPassThruDriverBindingStart (
>      }
>    }
> 
> +  //
> +  // Check if RPMB WLUN is supported and set corresponding bit mask.
> +  //
> +  DeviceDescriptorSize = sizeof (UFS_DEV_DESC);
> +  Status = UfsRwDeviceDesc (Private, TRUE, UfsDeviceDesc, 0, 0,
> &DeviceDescriptor, &DeviceDescriptorSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to read device descriptor, status = %r\n",
> Status));
> +  } else {
> +    if (DeviceDescriptor.SecurityLun == 0x1) {
> +      DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
> +      Private->Luns.BitMask |= BIT11;
> +    }
> +  }
> +
>    //
>    // Start the asynchronous interrupt monitor
>    //
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
  2019-06-18  2:12   ` [edk2-devel] " Wu, Hao A
@ 2019-08-16 20:22     ` Zurcher, Christopher J
  2019-08-19  8:10       ` Wu, Hao A
  0 siblings, 1 reply; 13+ messages in thread
From: Zurcher, Christopher J @ 2019-08-16 20:22 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io
  Cc: Kinney, Michael D, Yao, Jiewen, Wang, Jian J, Gao, Liming

Hao,
Why will this cause CDROM devices to fail to be recognized? If they require a capacity read, I can change the MustReadCapacity flag to TRUE. On subsequent media change, the sense key parsing will set Action to ACTION_READ_CAPACITY so that case is covered as well. Is there a reason the MustReadCapacity flag was originally set to FALSE for CDROM devices? With the default action being to read capacity anyway, the existing implementation seems to make the flag mostly useless.

I have implemented the rest of the suggestions.

Thanks,
Christopher Zurcher

-----Original Message-----
From: Wu, Hao A 
Sent: Monday, June 17, 2019 19:12
To: devel@edk2.groups.io; Zurcher, Christopher J <christopher.j.zurcher@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <liming.gao@intel.com>
Subject: RE: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Zurcher, Christopher J
> Sent: Thursday, June 13, 2019 10:05 AM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D; Yao, Jiewen; Wang, Jian J; Gao, Liming
> Subject: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support
> Storage Security Command Protocol
> 
> This patch implements the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> in the
> ScsiDiskDxe driver.
> 
> Support is currently limited to the RPMB Well-known LUN for UFS devices.


Hello,

Some general level comments:
1. CDROM device issue
This patch will bring an issue to the CDROM devices that CD/DVD will not
be recognized properly.

I think the cause of the issue is the relocation of the below logic:
  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
from GetMediaInfo() to ScsiDiskTestUnitReady(). It will lead to the read
capacity command being skipped for CDROM devices, which results into the
LastBlock for the device equals to 0.

We may need to find out a better approach to handle the case for UFS RPMB.

2. Split this patch into three commits
Besides adding the Storage Security Command Protocol support in ScsiDisk
driver, the patch also:
* Updates the ScsiBus driver to recognize the Well known logical unit
* Updates the UfsPassThruDxe driver to expose the RPMB WLUN

Please help to split the patch into 3 separate commits.

3. Updates for the BlockIO(2) services
For functions ScsiDiskReadBlocks(Ex) & ScsiDiskWriteBlocks(Ex), below codes
are added for the dummy BlockIO(2) protocol instance on the UFS RPMB Lun:

  if (BlockSize == 0) {
    Status = EFI_UNSUPPORTED;
    goto Done;
  }

I suggest to use status 'EFI_DEVICE_ERROR' for such case, since
'EFI_UNSUPPORTED' is not listed as an expected return status in the UEFI
spec.

4. Reinstallation of the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
For the reinstallation of the SSC protocol to handle media change, I saw
this is only handled within ScsiDiskReceiveData() & ScsiDiskSendData().
The below functions should be considered as well:

ScsiDiskReadBlocks(Ex)
ScsiDiskWriteBlocks(Ex)
ScsiDiskFlushBlocksEx
ScsiDiskEraseBlocks


Some inline comments below:


> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
> ---
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
>  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522
> +++++++++++++++++++-
>  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
>  5 files changed, 698 insertions(+), 22 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> index 5500d828e9..40818e669b 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> @@ -3,7 +3,7 @@
>  #  It detects the SCSI disk media and installs Block I/O and Block I/O2 Protocol
> on
>  #  the device handle.
>  #
> -#  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
>  #
>  ##
> @@ -52,6 +52,7 @@
>    gEfiBlockIoProtocolGuid                       ## BY_START
>    gEfiBlockIo2ProtocolGuid                      ## BY_START
>    gEfiEraseBlockProtocolGuid                    ## BY_START
> +  gEfiStorageSecurityCommandProtocolGuid        ## BY_START
>    gEfiScsiIoProtocolGuid                        ## TO_START
>    gEfiScsiPassThruProtocolGuid                  ## TO_START
>    gEfiExtScsiPassThruProtocolGuid               ## TO_START
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> index 42c0aaaa95..2d8679ec6f 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Header file for SCSI Disk Driver.
> 
> -Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -22,6 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Protocol/ScsiPassThruExt.h>
>  #include <Protocol/ScsiPassThru.h>
>  #include <Protocol/DiskInfo.h>
> +#include <Protocol/StorageSecurityCommand.h>
> 
> 
>  #include <Library/DebugLib.h>
> @@ -38,6 +39,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #define IS_DEVICE_FIXED(a)        (a)->FixedDevice ? 1 : 0
> 
> +#define IS_ALIGNED(addr, size)    (((UINTN) (addr) & (size - 1)) == 0)
> +
> +#define UFS_WLUN_RPMB 0xC4
> +
>  typedef struct {
>    UINT32                    MaxLbaCnt;
>    UINT32                    MaxBlkDespCnt;
> @@ -51,6 +56,8 @@ typedef struct {
> 
>    EFI_HANDLE                Handle;
> 
> +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL   StorageSecurity;
> +
>    EFI_BLOCK_IO_PROTOCOL     BlkIo;
>    EFI_BLOCK_IO2_PROTOCOL    BlkIo2;
>    EFI_BLOCK_IO_MEDIA        BlkIoMedia;
> @@ -95,6 +102,7 @@ typedef struct {
>  #define SCSI_DISK_DEV_FROM_BLKIO(a)  CR (a, SCSI_DISK_DEV, BlkIo,
> SCSI_DISK_DEV_SIGNATURE)
>  #define SCSI_DISK_DEV_FROM_BLKIO2(a)  CR (a, SCSI_DISK_DEV, BlkIo2,
> SCSI_DISK_DEV_SIGNATURE)
>  #define SCSI_DISK_DEV_FROM_ERASEBLK(a)  CR (a, SCSI_DISK_DEV,
> EraseBlock, SCSI_DISK_DEV_SIGNATURE)
> +#define SCSI_DISK_DEV_FROM_STORSEC(a)  CR (a, SCSI_DISK_DEV,
> StorageSecurity, SCSI_DISK_DEV_SIGNATURE)
> 
>  #define SCSI_DISK_DEV_FROM_DISKINFO(a) CR (a, SCSI_DISK_DEV,
> DiskInfo, SCSI_DISK_DEV_SIGNATURE)
> 
> @@ -638,6 +646,151 @@ ScsiDiskEraseBlocks (
>    );
> 
> 
> +/**
> +  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.
> +
> +  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
> +ScsiDiskReceiveData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  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.
> +
> +  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
> +ScsiDiskSendData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16                                   SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  OUT VOID                                    *PayloadBuffer
> +  );
> +
> +
>  /**
>    Provides inquiry information for the controller type.
> 
> @@ -1428,4 +1581,20 @@ DetermineInstallEraseBlock (
>    IN  EFI_HANDLE             ChildHandle
>    );
> 
> +/**
> +  Determine if EFI Storage Security Command Protocol should be produced.
> +
> +  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
> +  @param   ChildHandle       Handle of device.
> +
> +  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
> +  @retval  FALSE   Should not produce EFI Storage Security Command
> Protocol.
> +
> +**/
> +BOOLEAN
> +DetermineInstallStorageSecurity (
> +  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
> +  IN  EFI_HANDLE             ChildHandle
> +  );
> +
>  #endif
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> index c4069aec0f..1caffd38cd 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> +++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> @@ -2,7 +2,7 @@
>    SCSI Bus driver that layers on every SCSI Pass Thru and
>    Extended SCSI Pass Thru protocol in the system.
> 
> -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
> 
>  **/
> @@ -1368,7 +1368,8 @@ DiscoverScsiDevice (
>      goto Done;
>    }
> 
> -  if (0x1e >= InquiryData->Peripheral_Type && InquiryData-
> >Peripheral_Type >= 0xa) {
> +  if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW) &&
> +      (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH)) {
>      ScsiDeviceFound = FALSE;
>      goto Done;
>    }
> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> index fbdf927a11..01d5ad4969 100644
> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> @@ -1,7 +1,7 @@
>  /** @file
>    SCSI disk driver that layers on every SCSI IO protocol in the system.
> 
> -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
> 
>  **/
> @@ -151,7 +151,9 @@ ScsiDiskDriverBindingSupported (
> 
>    Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType);
>    if (!EFI_ERROR (Status)) {
> -    if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType ==
> EFI_SCSI_TYPE_CDROM)) {
> +    if ((DeviceType == EFI_SCSI_TYPE_DISK) ||
> +        (DeviceType == EFI_SCSI_TYPE_CDROM) ||
> +        (DeviceType == EFI_SCSI_TYPE_WLUN)) {
>        Status = EFI_SUCCESS;
>      } else {
>        Status = EFI_UNSUPPORTED;
> @@ -238,6 +240,8 @@ ScsiDiskDriverBindingStart (
>    ScsiDiskDevice->BlkIo2.ReadBlocksEx               = ScsiDiskReadBlocksEx;
>    ScsiDiskDevice->BlkIo2.WriteBlocksEx              = ScsiDiskWriteBlocksEx;
>    ScsiDiskDevice->BlkIo2.FlushBlocksEx              = ScsiDiskFlushBlocksEx;
> +  ScsiDiskDevice->StorageSecurity.ReceiveData       = ScsiDiskReceiveData;
> +  ScsiDiskDevice->StorageSecurity.SendData          = ScsiDiskSendData;
>    ScsiDiskDevice->EraseBlock.Revision               =
> EFI_ERASE_BLOCK_PROTOCOL_REVISION;
>    ScsiDiskDevice->EraseBlock.EraseLengthGranularity = 1;
>    ScsiDiskDevice->EraseBlock.EraseBlocks            = ScsiDiskEraseBlocks;
> @@ -258,6 +262,10 @@ ScsiDiskDriverBindingStart (
>      ScsiDiskDevice->BlkIo.Media->ReadOnly  = TRUE;
>      MustReadCapacity = FALSE;
>      break;
> +
> +  case EFI_SCSI_TYPE_WLUN:
> +    MustReadCapacity = FALSE;
> +    break;
>    }
>    //
>    // The Sense Data Array's initial size is 6
> @@ -309,8 +317,8 @@ ScsiDiskDriverBindingStart (
>      // Determine if Block IO & Block IO2 should be produced on this controller
>      // handle
>      //
> -    if (DetermineInstallBlockIo(Controller)) {
> -      InitializeInstallDiskInfo(ScsiDiskDevice, Controller);
> +    if (DetermineInstallBlockIo (Controller)) {
> +      InitializeInstallDiskInfo (ScsiDiskDevice, Controller);
>        Status = gBS->InstallMultipleProtocolInterfaces (
>                        &Controller,
>                        &gEfiBlockIoProtocolGuid,
> @@ -321,16 +329,27 @@ ScsiDiskDriverBindingStart (
>                        &ScsiDiskDevice->DiskInfo,
>                        NULL
>                        );
> -      if (!EFI_ERROR(Status)) {
> -        if (DetermineInstallEraseBlock(ScsiDiskDevice, Controller)) {
> +      if (!EFI_ERROR (Status)) {
> +        if (DetermineInstallEraseBlock (ScsiDiskDevice, Controller)) {
>            Status = gBS->InstallProtocolInterface (
>                            &Controller,
>                            &gEfiEraseBlockProtocolGuid,
>                            EFI_NATIVE_INTERFACE,
>                            &ScsiDiskDevice->EraseBlock
>                            );
> -          if (EFI_ERROR(Status)) {
> -            DEBUG ((EFI_D_ERROR, "ScsiDisk: Failed to install the Erase Block
> Protocol! Status = %r\n", Status));
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Erase Block
> Protocol! Status = %r\n", Status));
> +          }
> +        }
> +        if (DetermineInstallStorageSecurity (ScsiDiskDevice, Controller)) {
> +          Status = gBS->InstallProtocolInterface (
> +                          &Controller,
> +                          &gEfiStorageSecurityCommandProtocolGuid,
> +                          EFI_NATIVE_INTERFACE,
> +                          &ScsiDiskDevice->StorageSecurity
> +                          );
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Storage
> Security Command Protocol! Status = %r\n", Status));
>            }
>          }
>          ScsiDiskDevice->ControllerNameTable = NULL;
> @@ -606,6 +625,11 @@ ScsiDiskReadBlocks (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -742,6 +766,11 @@ ScsiDiskWriteBlocks (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -968,6 +997,11 @@ ScsiDiskReadBlocksEx (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -1131,6 +1165,11 @@ ScsiDiskWriteBlocksEx (
>    //
>    BlockSize       = Media->BlockSize;
> 
> +  if (BlockSize == 0) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
>    NumberOfBlocks  = BufferSize / BlockSize;
> 
>    if (!(Media->MediaPresent)) {
> @@ -1708,6 +1747,393 @@ Done:
>    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.
> +
> +  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
> +ScsiDiskReceiveData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16                                   SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  OUT VOID                                    *PayloadBuffer,
> +  OUT UINTN                                   *PayloadTransferSize
> +  )
> +{
> +  SCSI_DISK_DEV       *ScsiDiskDevice;
> +  EFI_BLOCK_IO_MEDIA  *Media;
> +  EFI_STATUS          Status;
> +  BOOLEAN             MediaChange;
> +  EFI_TPL             OldTpl;
> +  UINT8               SenseDataLength;
> +  UINT8               HostAdapterStatus;
> +  UINT8               TargetStatus;
> +  VOID                *AlignedBuffer;
> +  BOOLEAN             AlignedBufferAllocated;
> +
> +  AlignedBuffer           = NULL;
> +  MediaChange             = FALSE;
> +  AlignedBufferAllocated  = FALSE;
> +  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
> +  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
> +  Media                   = ScsiDiskDevice->BlkIo.Media;
> +
> +  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof
> (EFI_SCSI_SENSE_DATA));
> +
> +  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice-
> >Handle)) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }


I think the above 'if' statement is not needed, and should be placed
within the below 'if' statement when handling media change:

  if (MediaChange) {...}

(Similar case to ScsiDiskSendData().)

> +
> +  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
> +    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
> +    if (EFI_ERROR (Status)) {
> +      Status = EFI_DEVICE_ERROR;
> +      goto Done;
> +    }
> +
> +    if (MediaChange) {
> +      gBS->ReinstallProtocolInterface (
> +              ScsiDiskDevice->Handle,
> +              &gEfiStorageSecurityCommandProtocolGuid,
> +              &ScsiDiskDevice->StorageSecurity,
> +              &ScsiDiskDevice->StorageSecurity
> +              );


The BlockIO(2) & EraseBlocks (if supported) should be reinstalled as well.

(Similar case to ScsiDiskSendData().)


> +      if (Media->MediaPresent) {
> +        Status = EFI_MEDIA_CHANGED;
> +      } else {
> +        Status = EFI_NO_MEDIA;
> +      }
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Validate Media
> +  //
> +  if (!(Media->MediaPresent)) {
> +    Status = EFI_NO_MEDIA;
> +    goto Done;
> +  }
> +
> +  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
> +    Status = EFI_MEDIA_CHANGED;
> +    goto Done;
> +  }
> +
> +  if (PayloadBufferSize != 0) {
> +    if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto Done;
> +    }
> +
> +    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer,
> ScsiDiskDevice->ScsiIo->IoAlign)) {
> +      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice,
> PayloadBufferSize);
> +      if (AlignedBuffer == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto Done;
> +      }
> +      ZeroMem (AlignedBuffer, PayloadBufferSize);
> +      AlignedBufferAllocated = TRUE;
> +    } else {
> +      AlignedBuffer = PayloadBuffer;
> +    }
> +  }
> +
> +  Status = ScsiSecurityProtocolInCommand (
> +            ScsiDiskDevice->ScsiIo,
> +            Timeout,
> +            ScsiDiskDevice->SenseData,
> +            &SenseDataLength,
> +            &HostAdapterStatus,
> +            &TargetStatus,
> +            SecurityProtocolId,
> +            SecurityProtocolSpecificData,
> +            (UINT32) PayloadBufferSize,
> +            AlignedBuffer,
> +            (UINT32 *) PayloadTransferSize
> +          );
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  if (AlignedBufferAllocated) {
> +    CopyMem (PayloadBuffer, AlignedBuffer, PayloadBufferSize);
> +  }
> +
> +  if (PayloadBufferSize < *PayloadTransferSize) {
> +    Status = EFI_WARN_BUFFER_TOO_SMALL;
> +    goto Done;
> +  }
> +
> +  Status = CheckHostAdapterStatus (HostAdapterStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = CheckTargetStatus (TargetStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +Done:
> +  if (AlignedBufferAllocated) {


IMO, the content in 'AlignedBuffer' should be wiped out, since it might
contain sensitive information. SSC protocol user can control the data in
'PayloadBuffer' but not in 'AlignedBuffer'.


> +    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
> +  }
> +  gBS->RestoreTPL (OldTpl);
> +  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.
> +
> +  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
> +ScsiDiskSendData (
> +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> +  IN UINT32                                   MediaId   OPTIONAL,
> +  IN UINT64                                   Timeout,
> +  IN UINT8                                    SecurityProtocolId,
> +  IN UINT16                                   SecurityProtocolSpecificData,
> +  IN UINTN                                    PayloadBufferSize,
> +  OUT VOID                                    *PayloadBuffer
> +  )
> +{
> +  SCSI_DISK_DEV       *ScsiDiskDevice;
> +  EFI_BLOCK_IO_MEDIA  *Media;
> +  EFI_STATUS          Status;
> +  BOOLEAN             MediaChange;
> +  EFI_TPL             OldTpl;
> +  UINT8               SenseDataLength;
> +  UINT8               HostAdapterStatus;
> +  UINT8               TargetStatus;
> +  VOID                *AlignedBuffer;
> +  BOOLEAN             AlignedBufferAllocated;
> +
> +  AlignedBuffer           = NULL;
> +  MediaChange             = FALSE;
> +  AlignedBufferAllocated  = FALSE;
> +  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
> +  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
> +  Media                   = ScsiDiskDevice->BlkIo.Media;
> +
> +  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof
> (EFI_SCSI_SENSE_DATA));
> +
> +  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice-
> >Handle)) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Done;
> +  }
> +
> +  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
> +    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
> +    if (EFI_ERROR (Status)) {
> +      Status = EFI_DEVICE_ERROR;
> +      goto Done;
> +    }
> +
> +    if (MediaChange) {
> +      gBS->ReinstallProtocolInterface (
> +              ScsiDiskDevice->Handle,
> +              &gEfiStorageSecurityCommandProtocolGuid,
> +              &ScsiDiskDevice->StorageSecurity,
> +              &ScsiDiskDevice->StorageSecurity
> +              );
> +      if (Media->MediaPresent) {
> +        Status = EFI_MEDIA_CHANGED;
> +      } else {
> +        Status = EFI_NO_MEDIA;
> +      }
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Validate Media
> +  //
> +  if (!(Media->MediaPresent)) {
> +    Status = EFI_NO_MEDIA;
> +    goto Done;
> +  }
> +
> +  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
> +    Status = EFI_MEDIA_CHANGED;
> +    goto Done;
> +  }
> +
> +  if (Media->ReadOnly) {
> +    Status = EFI_WRITE_PROTECTED;
> +    goto Done;
> +  }
> +
> +  if (PayloadBufferSize != 0) {
> +    if (PayloadBuffer == NULL) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto Done;
> +    }
> +
> +    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer,
> ScsiDiskDevice->ScsiIo->IoAlign)) {
> +      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice,
> PayloadBufferSize);
> +      if (AlignedBuffer == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto Done;
> +      }
> +      CopyMem (AlignedBuffer, PayloadBuffer, PayloadBufferSize);
> +      AlignedBufferAllocated = TRUE;
> +    } else {
> +      AlignedBuffer = PayloadBuffer;
> +    }
> +  }
> +
> +  Status = ScsiSecurityProtocolOutCommand (
> +            ScsiDiskDevice->ScsiIo,
> +            Timeout,
> +            ScsiDiskDevice->SenseData,
> +            &SenseDataLength,
> +            &HostAdapterStatus,
> +            &TargetStatus,
> +            SecurityProtocolId,
> +            SecurityProtocolSpecificData,
> +            (UINT32) PayloadBufferSize,
> +            AlignedBuffer
> +          );
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = CheckHostAdapterStatus (HostAdapterStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = CheckTargetStatus (TargetStatus);
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +Done:
> +  if (AlignedBufferAllocated) {


IMO, the content in 'AlignedBuffer' should be wiped out, since it might
contain sensitive information. SSC protocol user can control the data in
'PayloadBuffer' but not in 'AlignedBuffer'.


> +    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
> +  }
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> +
> 
>  /**
>    Detect Device and read out capacity ,if error occurs, parse the sense key.
> @@ -2261,6 +2687,8 @@ ScsiDiskTestUnitReady (
>      return EFI_DEVICE_ERROR;
>    }
> 
> +  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
> +
>    if (SenseDataLength != 0) {
>      *NumberOfSenseKeys = SenseDataLength / sizeof
> (EFI_SCSI_SENSE_DATA);
>      *SenseDataArray    = ScsiDiskDevice->SenseData;
> @@ -2315,13 +2743,12 @@ DetectMediaParsingSenseKeys (
>    BOOLEAN RetryLater;
> 
>    //
> -  // Default is to read capacity, unless..
> +  // Default is no action
>    //
> -  *Action = ACTION_READ_CAPACITY;
> +  *Action = ACTION_NO_ACTION;
> 
>    if (NumberOfSenseKeys == 0) {
>      if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
> -      *Action = ACTION_NO_ACTION;
>      }


I do not think the behavior is the same after the patch.
Can it be:

  if (NumberOfSenseKeys == 0) {
    if (!ScsiDiskDevice->BlkIo.Media->MediaPresent) {
      *Action = ACTION_READ_CAPACITY;
    }
    return EFI_SUCCESS;
  }


>      return EFI_SUCCESS;
>    }
> @@ -2331,7 +2758,6 @@ DetectMediaParsingSenseKeys (
>      // No Sense Key returned from last submitted command
>      //
>      if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
> -      *Action = ACTION_NO_ACTION;
>      }


I do not think the behavior is the same after the patch.
Can it be:

  if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
    //
    // No Sense Key returned from last submitted command
    //
    if (!ScsiDiskDevice->BlkIo.Media->MediaPresent) {
      *Action = ACTION_READ_CAPACITY;
    }
    return EFI_SUCCESS;
  }


Best Regards,
Hao Wu


>      return EFI_SUCCESS;
>    }
> @@ -2339,13 +2765,13 @@ DetectMediaParsingSenseKeys (
>    if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
>      ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
>      ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
> -    *Action = ACTION_NO_ACTION;
>      DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
>      return EFI_SUCCESS;
>    }
> 
>    if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
>      ScsiDiskDevice->BlkIo.Media->MediaId++;
> +    *Action = ACTION_READ_CAPACITY;
>      DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaChange!\n"));
>      return EFI_SUCCESS;
>    }
> @@ -2374,7 +2800,6 @@ DetectMediaParsingSenseKeys (
>        DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
>        return EFI_SUCCESS;
>      }
> -    *Action = ACTION_NO_ACTION;
>      return EFI_DEVICE_ERROR;
>    }
> 
> @@ -2808,8 +3233,6 @@ GetMediaInfo (
>        }
>      }
>    }
> -
> -  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
>  }
> 
>  /**
> @@ -5358,6 +5781,14 @@ DetermineInstallEraseBlock (
>    RetVal         = TRUE;
>    CapacityData16 = NULL;
> 
> +  //
> +  // UNMAP command is not supported by any of the UFS WLUNs.
> +  //
> +  if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_WLUN) {
> +    RetVal = FALSE;
> +    goto Done;
> +  }
> +
>    Status = gBS->HandleProtocol (
>                    ChildHandle,
>                    &gEfiDevicePathProtocolGuid,
> @@ -5460,6 +5891,65 @@ Done:
>    return RetVal;
>  }
> 
> +/**
> +  Determine if EFI Storage Security Command Protocol should be produced.
> +
> +  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
> +  @param   ChildHandle       Handle of device.
> +
> +  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
> +  @retval  FALSE   Should not produce EFI Storage Security Command
> Protocol.
> +
> +**/
> +BOOLEAN
> +DetermineInstallStorageSecurity (
> +  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
> +  IN  EFI_HANDLE             ChildHandle
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UFS_DEVICE_PATH                 *UfsDevice;
> +  BOOLEAN                         RetVal;
> +  EFI_DEVICE_PATH_PROTOCOL        *DevicePathNode;
> +
> +  UfsDevice      = NULL;
> +  RetVal         = TRUE;
> +
> +  Status = gBS->HandleProtocol (
> +                  ChildHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID **) &DevicePathNode
> +                  );
> +  //
> +  // Device Path protocol must be installed on the device handle.
> +  //
> +  ASSERT_EFI_ERROR (Status);
> +
> +  while (!IsDevicePathEndType (DevicePathNode)) {
> +    //
> +    // For now, only support Storage Security Command Protocol on UFS
> devices.
> +    //
> +    if ((DevicePathNode->Type == MESSAGING_DEVICE_PATH) &&
> +        (DevicePathNode->SubType == MSG_UFS_DP)) {
> +      UfsDevice = (UFS_DEVICE_PATH *) DevicePathNode;
> +      break;
> +    }
> +
> +    DevicePathNode = NextDevicePathNode (DevicePathNode);
> +  }
> +  if (UfsDevice == NULL) {
> +    RetVal = FALSE;
> +    goto Done;
> +  }
> +
> +  if (UfsDevice->Lun != UFS_WLUN_RPMB) {
> +    RetVal = FALSE;
> +  }
> +
> +Done:
> +  return RetVal;
> +}
> +
>  /**
>    Provides inquiry information for the controller type.
> 
> diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> index 1518b251d8..0bb67f2ddc 100644
> --- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> +++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> @@ -1,6 +1,6 @@
>  /** @file
> 
> -  Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -819,7 +819,9 @@ UfsPassThruDriverBindingStart (
>    UINTN                                 UfsHcBase;
>    UINT32                                Index;
>    UFS_UNIT_DESC                         UnitDescriptor;
> +  UFS_DEV_DESC                          DeviceDescriptor;
>    UINT32                                UnitDescriptorSize;
> +  UINT32                                DeviceDescriptorSize;
> 
>    Status    = EFI_SUCCESS;
>    UfsHc     = NULL;
> @@ -894,7 +896,6 @@ UfsPassThruDriverBindingStart (
> 
>    //
>    // Check if 8 common luns are active and set corresponding bit mask.
> -  // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper
> layer for authentication access.
>    //
>    UnitDescriptorSize = sizeof (UFS_UNIT_DESC);
>    for (Index = 0; Index < 8; Index++) {
> @@ -909,6 +910,20 @@ UfsPassThruDriverBindingStart (
>      }
>    }
> 
> +  //
> +  // Check if RPMB WLUN is supported and set corresponding bit mask.
> +  //
> +  DeviceDescriptorSize = sizeof (UFS_DEV_DESC);
> +  Status = UfsRwDeviceDesc (Private, TRUE, UfsDeviceDesc, 0, 0,
> &DeviceDescriptor, &DeviceDescriptorSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to read device descriptor, status = %r\n",
> Status));
> +  } else {
> +    if (DeviceDescriptor.SecurityLun == 0x1) {
> +      DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
> +      Private->Luns.BitMask |= BIT11;
> +    }
> +  }
> +
>    //
>    // Start the asynchronous interrupt monitor
>    //
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
  2019-08-16 20:22     ` Zurcher, Christopher J
@ 2019-08-19  8:10       ` Wu, Hao A
  0 siblings, 0 replies; 13+ messages in thread
From: Wu, Hao A @ 2019-08-19  8:10 UTC (permalink / raw)
  To: Zurcher, Christopher J, devel@edk2.groups.io
  Cc: Kinney, Michael D, Yao, Jiewen, Wang, Jian J, Gao, Liming

> -----Original Message-----
> From: Zurcher, Christopher J
> Sent: Saturday, August 17, 2019 4:22 AM
> To: Wu, Hao A; devel@edk2.groups.io
> Cc: Kinney, Michael D; Yao, Jiewen; Wang, Jian J; Gao, Liming
> Subject: RE: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe:
> Support Storage Security Command Protocol
> 
> Hao,
> Why will this cause CDROM devices to fail to be recognized? If they require a


Hello,

My observation is that after the patch, the below assignment:
"ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;"
is moved from GetMediaInfo() to ScsiDiskTestUnitReady().

The flow for CD-ROM devices is that:
ScsiDiskDriverBindingStart()
|
└-> ScsiDiskDetectMedia()
    |
    └-> ScsiDiskTestUnitReady()
    |
    └-> DetectMediaParsingSenseKeys() - Outputs 'Action'
    |
    └-> If Action is READ_CAPACITY, ScsiDiskReadCapacity()

Now, 'MediaPresent' is set to TRUE in ScsiDiskTestUnitReady(), which leads to
DetectMediaParsingSenseKeys() returning NO_ACTION:

  *Action = ACTION_NO_ACTION;

  ...

  if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
    //
    // No Sense Key returned from last submitted command
    //
    if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
    }
    return EFI_SUCCESS;
  }


> capacity read, I can change the MustReadCapacity flag to TRUE. On
> subsequent media change, the sense key parsing will set Action to
> ACTION_READ_CAPACITY so that case is covered as well. Is there a reason
> the MustReadCapacity flag was originally set to FALSE for CDROM devices?


I think setting 'MustReadCapacity' to FALSE for CD-ROM devices is for the
performance consideration.

Before the patch, logic in DetectMediaParsingSenseKeys():

  if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
    ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
    ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
    *Action = ACTION_NO_ACTION;
    DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
    return EFI_SUCCESS;
  }

will decide whether there is media within the CD-ROM devices after parsing the
sense data returned from the device. If the media does not exist, the
Read Capacity command will not be sent.

Setting 'MustReadCapacity' to TRUE will then always require a Read Capacity
command be sent.

Best Regards,
Hao Wu


> With the default action being to read capacity anyway, the existing
> implementation seems to make the flag mostly useless.
> 
> I have implemented the rest of the suggestions.
> 
> Thanks,
> Christopher Zurcher
> 
> -----Original Message-----
> From: Wu, Hao A
> Sent: Monday, June 17, 2019 19:12
> To: devel@edk2.groups.io; Zurcher, Christopher J
> <christopher.j.zurcher@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <liming.gao@intel.com>
> Subject: RE: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe:
> Support Storage Security Command Protocol
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > Zurcher, Christopher J
> > Sent: Thursday, June 13, 2019 10:05 AM
> > To: devel@edk2.groups.io
> > Cc: Kinney, Michael D; Yao, Jiewen; Wang, Jian J; Gao, Liming
> > Subject: [edk2-devel] [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe:
> Support
> > Storage Security Command Protocol
> >
> > This patch implements the
> EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> > in the
> > ScsiDiskDxe driver.
> >
> > Support is currently limited to the RPMB Well-known LUN for UFS devices.
> 
> 
> Hello,
> 
> Some general level comments:
> 1. CDROM device issue
> This patch will bring an issue to the CDROM devices that CD/DVD will not
> be recognized properly.
> 
> I think the cause of the issue is the relocation of the below logic:
>   ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
> from GetMediaInfo() to ScsiDiskTestUnitReady(). It will lead to the read
> capacity command being skipped for CDROM devices, which results into the
> LastBlock for the device equals to 0.
> 
> We may need to find out a better approach to handle the case for UFS RPMB.
> 
> 2. Split this patch into three commits
> Besides adding the Storage Security Command Protocol support in ScsiDisk
> driver, the patch also:
> * Updates the ScsiBus driver to recognize the Well known logical unit
> * Updates the UfsPassThruDxe driver to expose the RPMB WLUN
> 
> Please help to split the patch into 3 separate commits.
> 
> 3. Updates for the BlockIO(2) services
> For functions ScsiDiskReadBlocks(Ex) & ScsiDiskWriteBlocks(Ex), below codes
> are added for the dummy BlockIO(2) protocol instance on the UFS RPMB Lun:
> 
>   if (BlockSize == 0) {
>     Status = EFI_UNSUPPORTED;
>     goto Done;
>   }
> 
> I suggest to use status 'EFI_DEVICE_ERROR' for such case, since
> 'EFI_UNSUPPORTED' is not listed as an expected return status in the UEFI
> spec.
> 
> 4. Reinstallation of the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
> For the reinstallation of the SSC protocol to handle media change, I saw
> this is only handled within ScsiDiskReceiveData() & ScsiDiskSendData().
> The below functions should be considered as well:
> 
> ScsiDiskReadBlocks(Ex)
> ScsiDiskWriteBlocks(Ex)
> ScsiDiskFlushBlocksEx
> ScsiDiskEraseBlocks
> 
> 
> Some inline comments below:
> 
> 
> >
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
> > ---
> >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
> >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 ++++++-
> >  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
> >  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 522
> > +++++++++++++++++++-
> >  MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
> >  5 files changed, 698 insertions(+), 22 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> > b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> > index 5500d828e9..40818e669b 100644
> > --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> > +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
> > @@ -3,7 +3,7 @@
> >  #  It detects the SCSI disk media and installs Block I/O and Block I/O2
> Protocol
> > on
> >  #  the device handle.
> >  #
> > -#  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
> >  #
> >  ##
> > @@ -52,6 +52,7 @@
> >    gEfiBlockIoProtocolGuid                       ## BY_START
> >    gEfiBlockIo2ProtocolGuid                      ## BY_START
> >    gEfiEraseBlockProtocolGuid                    ## BY_START
> > +  gEfiStorageSecurityCommandProtocolGuid        ## BY_START
> >    gEfiScsiIoProtocolGuid                        ## TO_START
> >    gEfiScsiPassThruProtocolGuid                  ## TO_START
> >    gEfiExtScsiPassThruProtocolGuid               ## TO_START
> > diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> > b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> > index 42c0aaaa95..2d8679ec6f 100644
> > --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> > +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    Header file for SCSI Disk Driver.
> >
> > -Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> > @@ -22,6 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >  #include <Protocol/ScsiPassThruExt.h>
> >  #include <Protocol/ScsiPassThru.h>
> >  #include <Protocol/DiskInfo.h>
> > +#include <Protocol/StorageSecurityCommand.h>
> >
> >
> >  #include <Library/DebugLib.h>
> > @@ -38,6 +39,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #define IS_DEVICE_FIXED(a)        (a)->FixedDevice ? 1 : 0
> >
> > +#define IS_ALIGNED(addr, size)    (((UINTN) (addr) & (size - 1)) == 0)
> > +
> > +#define UFS_WLUN_RPMB 0xC4
> > +
> >  typedef struct {
> >    UINT32                    MaxLbaCnt;
> >    UINT32                    MaxBlkDespCnt;
> > @@ -51,6 +56,8 @@ typedef struct {
> >
> >    EFI_HANDLE                Handle;
> >
> > +  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL   StorageSecurity;
> > +
> >    EFI_BLOCK_IO_PROTOCOL     BlkIo;
> >    EFI_BLOCK_IO2_PROTOCOL    BlkIo2;
> >    EFI_BLOCK_IO_MEDIA        BlkIoMedia;
> > @@ -95,6 +102,7 @@ typedef struct {
> >  #define SCSI_DISK_DEV_FROM_BLKIO(a)  CR (a, SCSI_DISK_DEV, BlkIo,
> > SCSI_DISK_DEV_SIGNATURE)
> >  #define SCSI_DISK_DEV_FROM_BLKIO2(a)  CR (a, SCSI_DISK_DEV, BlkIo2,
> > SCSI_DISK_DEV_SIGNATURE)
> >  #define SCSI_DISK_DEV_FROM_ERASEBLK(a)  CR (a, SCSI_DISK_DEV,
> > EraseBlock, SCSI_DISK_DEV_SIGNATURE)
> > +#define SCSI_DISK_DEV_FROM_STORSEC(a)  CR (a, SCSI_DISK_DEV,
> > StorageSecurity, SCSI_DISK_DEV_SIGNATURE)
> >
> >  #define SCSI_DISK_DEV_FROM_DISKINFO(a) CR (a, SCSI_DISK_DEV,
> > DiskInfo, SCSI_DISK_DEV_SIGNATURE)
> >
> > @@ -638,6 +646,151 @@ ScsiDiskEraseBlocks (
> >    );
> >
> >
> > +/**
> > +  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.
> > +
> > +  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
> > +ScsiDiskReceiveData (
> > +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> > +  IN UINT32                                   MediaId   OPTIONAL,
> > +  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.
> > +
> > +  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
> > +ScsiDiskSendData (
> > +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> > +  IN UINT32                                   MediaId   OPTIONAL,
> > +  IN UINT64                                   Timeout,
> > +  IN UINT8                                    SecurityProtocolId,
> > +  IN UINT16                                   SecurityProtocolSpecificData,
> > +  IN UINTN                                    PayloadBufferSize,
> > +  OUT VOID                                    *PayloadBuffer
> > +  );
> > +
> > +
> >  /**
> >    Provides inquiry information for the controller type.
> >
> > @@ -1428,4 +1581,20 @@ DetermineInstallEraseBlock (
> >    IN  EFI_HANDLE             ChildHandle
> >    );
> >
> > +/**
> > +  Determine if EFI Storage Security Command Protocol should be produced.
> > +
> > +  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
> > +  @param   ChildHandle       Handle of device.
> > +
> > +  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
> > +  @retval  FALSE   Should not produce EFI Storage Security Command
> > Protocol.
> > +
> > +**/
> > +BOOLEAN
> > +DetermineInstallStorageSecurity (
> > +  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
> > +  IN  EFI_HANDLE             ChildHandle
> > +  );
> > +
> >  #endif
> > diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> > b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> > index c4069aec0f..1caffd38cd 100644
> > --- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> > +++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
> > @@ -2,7 +2,7 @@
> >    SCSI Bus driver that layers on every SCSI Pass Thru and
> >    Extended SCSI Pass Thru protocol in the system.
> >
> > -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
> >
> >  **/
> > @@ -1368,7 +1368,8 @@ DiscoverScsiDevice (
> >      goto Done;
> >    }
> >
> > -  if (0x1e >= InquiryData->Peripheral_Type && InquiryData-
> > >Peripheral_Type >= 0xa) {
> > +  if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW)
> &&
> > +      (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH)) {
> >      ScsiDeviceFound = FALSE;
> >      goto Done;
> >    }
> > diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> > b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> > index fbdf927a11..01d5ad4969 100644
> > --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> > +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    SCSI disk driver that layers on every SCSI IO protocol in the system.
> >
> > -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
> >
> >  **/
> > @@ -151,7 +151,9 @@ ScsiDiskDriverBindingSupported (
> >
> >    Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType);
> >    if (!EFI_ERROR (Status)) {
> > -    if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType ==
> > EFI_SCSI_TYPE_CDROM)) {
> > +    if ((DeviceType == EFI_SCSI_TYPE_DISK) ||
> > +        (DeviceType == EFI_SCSI_TYPE_CDROM) ||
> > +        (DeviceType == EFI_SCSI_TYPE_WLUN)) {
> >        Status = EFI_SUCCESS;
> >      } else {
> >        Status = EFI_UNSUPPORTED;
> > @@ -238,6 +240,8 @@ ScsiDiskDriverBindingStart (
> >    ScsiDiskDevice->BlkIo2.ReadBlocksEx               = ScsiDiskReadBlocksEx;
> >    ScsiDiskDevice->BlkIo2.WriteBlocksEx              = ScsiDiskWriteBlocksEx;
> >    ScsiDiskDevice->BlkIo2.FlushBlocksEx              = ScsiDiskFlushBlocksEx;
> > +  ScsiDiskDevice->StorageSecurity.ReceiveData       = ScsiDiskReceiveData;
> > +  ScsiDiskDevice->StorageSecurity.SendData          = ScsiDiskSendData;
> >    ScsiDiskDevice->EraseBlock.Revision               =
> > EFI_ERASE_BLOCK_PROTOCOL_REVISION;
> >    ScsiDiskDevice->EraseBlock.EraseLengthGranularity = 1;
> >    ScsiDiskDevice->EraseBlock.EraseBlocks            = ScsiDiskEraseBlocks;
> > @@ -258,6 +262,10 @@ ScsiDiskDriverBindingStart (
> >      ScsiDiskDevice->BlkIo.Media->ReadOnly  = TRUE;
> >      MustReadCapacity = FALSE;
> >      break;
> > +
> > +  case EFI_SCSI_TYPE_WLUN:
> > +    MustReadCapacity = FALSE;
> > +    break;
> >    }
> >    //
> >    // The Sense Data Array's initial size is 6
> > @@ -309,8 +317,8 @@ ScsiDiskDriverBindingStart (
> >      // Determine if Block IO & Block IO2 should be produced on this
> controller
> >      // handle
> >      //
> > -    if (DetermineInstallBlockIo(Controller)) {
> > -      InitializeInstallDiskInfo(ScsiDiskDevice, Controller);
> > +    if (DetermineInstallBlockIo (Controller)) {
> > +      InitializeInstallDiskInfo (ScsiDiskDevice, Controller);
> >        Status = gBS->InstallMultipleProtocolInterfaces (
> >                        &Controller,
> >                        &gEfiBlockIoProtocolGuid,
> > @@ -321,16 +329,27 @@ ScsiDiskDriverBindingStart (
> >                        &ScsiDiskDevice->DiskInfo,
> >                        NULL
> >                        );
> > -      if (!EFI_ERROR(Status)) {
> > -        if (DetermineInstallEraseBlock(ScsiDiskDevice, Controller)) {
> > +      if (!EFI_ERROR (Status)) {
> > +        if (DetermineInstallEraseBlock (ScsiDiskDevice, Controller)) {
> >            Status = gBS->InstallProtocolInterface (
> >                            &Controller,
> >                            &gEfiEraseBlockProtocolGuid,
> >                            EFI_NATIVE_INTERFACE,
> >                            &ScsiDiskDevice->EraseBlock
> >                            );
> > -          if (EFI_ERROR(Status)) {
> > -            DEBUG ((EFI_D_ERROR, "ScsiDisk: Failed to install the Erase Block
> > Protocol! Status = %r\n", Status));
> > +          if (EFI_ERROR (Status)) {
> > +            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Erase Block
> > Protocol! Status = %r\n", Status));
> > +          }
> > +        }
> > +        if (DetermineInstallStorageSecurity (ScsiDiskDevice, Controller)) {
> > +          Status = gBS->InstallProtocolInterface (
> > +                          &Controller,
> > +                          &gEfiStorageSecurityCommandProtocolGuid,
> > +                          EFI_NATIVE_INTERFACE,
> > +                          &ScsiDiskDevice->StorageSecurity
> > +                          );
> > +          if (EFI_ERROR (Status)) {
> > +            DEBUG ((DEBUG_ERROR, "ScsiDisk: Failed to install the Storage
> > Security Command Protocol! Status = %r\n", Status));
> >            }
> >          }
> >          ScsiDiskDevice->ControllerNameTable = NULL;
> > @@ -606,6 +625,11 @@ ScsiDiskReadBlocks (
> >    //
> >    BlockSize       = Media->BlockSize;
> >
> > +  if (BlockSize == 0) {
> > +    Status = EFI_UNSUPPORTED;
> > +    goto Done;
> > +  }
> > +
> >    NumberOfBlocks  = BufferSize / BlockSize;
> >
> >    if (!(Media->MediaPresent)) {
> > @@ -742,6 +766,11 @@ ScsiDiskWriteBlocks (
> >    //
> >    BlockSize       = Media->BlockSize;
> >
> > +  if (BlockSize == 0) {
> > +    Status = EFI_UNSUPPORTED;
> > +    goto Done;
> > +  }
> > +
> >    NumberOfBlocks  = BufferSize / BlockSize;
> >
> >    if (!(Media->MediaPresent)) {
> > @@ -968,6 +997,11 @@ ScsiDiskReadBlocksEx (
> >    //
> >    BlockSize       = Media->BlockSize;
> >
> > +  if (BlockSize == 0) {
> > +    Status = EFI_UNSUPPORTED;
> > +    goto Done;
> > +  }
> > +
> >    NumberOfBlocks  = BufferSize / BlockSize;
> >
> >    if (!(Media->MediaPresent)) {
> > @@ -1131,6 +1165,11 @@ ScsiDiskWriteBlocksEx (
> >    //
> >    BlockSize       = Media->BlockSize;
> >
> > +  if (BlockSize == 0) {
> > +    Status = EFI_UNSUPPORTED;
> > +    goto Done;
> > +  }
> > +
> >    NumberOfBlocks  = BufferSize / BlockSize;
> >
> >    if (!(Media->MediaPresent)) {
> > @@ -1708,6 +1747,393 @@ Done:
> >    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.
> > +
> > +  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
> > +ScsiDiskReceiveData (
> > +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> > +  IN UINT32                                   MediaId   OPTIONAL,
> > +  IN UINT64                                   Timeout,
> > +  IN UINT8                                    SecurityProtocolId,
> > +  IN UINT16                                   SecurityProtocolSpecificData,
> > +  IN UINTN                                    PayloadBufferSize,
> > +  OUT VOID                                    *PayloadBuffer,
> > +  OUT UINTN                                   *PayloadTransferSize
> > +  )
> > +{
> > +  SCSI_DISK_DEV       *ScsiDiskDevice;
> > +  EFI_BLOCK_IO_MEDIA  *Media;
> > +  EFI_STATUS          Status;
> > +  BOOLEAN             MediaChange;
> > +  EFI_TPL             OldTpl;
> > +  UINT8               SenseDataLength;
> > +  UINT8               HostAdapterStatus;
> > +  UINT8               TargetStatus;
> > +  VOID                *AlignedBuffer;
> > +  BOOLEAN             AlignedBufferAllocated;
> > +
> > +  AlignedBuffer           = NULL;
> > +  MediaChange             = FALSE;
> > +  AlignedBufferAllocated  = FALSE;
> > +  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
> > +  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
> > +  Media                   = ScsiDiskDevice->BlkIo.Media;
> > +
> > +  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof
> > (EFI_SCSI_SENSE_DATA));
> > +
> > +  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice-
> > >Handle)) {
> > +    Status = EFI_UNSUPPORTED;
> > +    goto Done;
> > +  }
> 
> 
> I think the above 'if' statement is not needed, and should be placed
> within the below 'if' statement when handling media change:
> 
>   if (MediaChange) {...}
> 
> (Similar case to ScsiDiskSendData().)
> 
> > +
> > +  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
> > +    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
> > +    if (EFI_ERROR (Status)) {
> > +      Status = EFI_DEVICE_ERROR;
> > +      goto Done;
> > +    }
> > +
> > +    if (MediaChange) {
> > +      gBS->ReinstallProtocolInterface (
> > +              ScsiDiskDevice->Handle,
> > +              &gEfiStorageSecurityCommandProtocolGuid,
> > +              &ScsiDiskDevice->StorageSecurity,
> > +              &ScsiDiskDevice->StorageSecurity
> > +              );
> 
> 
> The BlockIO(2) & EraseBlocks (if supported) should be reinstalled as well.
> 
> (Similar case to ScsiDiskSendData().)
> 
> 
> > +      if (Media->MediaPresent) {
> > +        Status = EFI_MEDIA_CHANGED;
> > +      } else {
> > +        Status = EFI_NO_MEDIA;
> > +      }
> > +      goto Done;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Validate Media
> > +  //
> > +  if (!(Media->MediaPresent)) {
> > +    Status = EFI_NO_MEDIA;
> > +    goto Done;
> > +  }
> > +
> > +  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
> > +    Status = EFI_MEDIA_CHANGED;
> > +    goto Done;
> > +  }
> > +
> > +  if (PayloadBufferSize != 0) {
> > +    if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL)) {
> > +      Status = EFI_INVALID_PARAMETER;
> > +      goto Done;
> > +    }
> > +
> > +    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer,
> > ScsiDiskDevice->ScsiIo->IoAlign)) {
> > +      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice,
> > PayloadBufferSize);
> > +      if (AlignedBuffer == NULL) {
> > +        Status = EFI_OUT_OF_RESOURCES;
> > +        goto Done;
> > +      }
> > +      ZeroMem (AlignedBuffer, PayloadBufferSize);
> > +      AlignedBufferAllocated = TRUE;
> > +    } else {
> > +      AlignedBuffer = PayloadBuffer;
> > +    }
> > +  }
> > +
> > +  Status = ScsiSecurityProtocolInCommand (
> > +            ScsiDiskDevice->ScsiIo,
> > +            Timeout,
> > +            ScsiDiskDevice->SenseData,
> > +            &SenseDataLength,
> > +            &HostAdapterStatus,
> > +            &TargetStatus,
> > +            SecurityProtocolId,
> > +            SecurityProtocolSpecificData,
> > +            (UINT32) PayloadBufferSize,
> > +            AlignedBuffer,
> > +            (UINT32 *) PayloadTransferSize
> > +          );
> > +  if (EFI_ERROR (Status)) {
> > +    goto Done;
> > +  }
> > +
> > +  if (AlignedBufferAllocated) {
> > +    CopyMem (PayloadBuffer, AlignedBuffer, PayloadBufferSize);
> > +  }
> > +
> > +  if (PayloadBufferSize < *PayloadTransferSize) {
> > +    Status = EFI_WARN_BUFFER_TOO_SMALL;
> > +    goto Done;
> > +  }
> > +
> > +  Status = CheckHostAdapterStatus (HostAdapterStatus);
> > +  if (EFI_ERROR (Status)) {
> > +    goto Done;
> > +  }
> > +
> > +  Status = CheckTargetStatus (TargetStatus);
> > +  if (EFI_ERROR (Status)) {
> > +    goto Done;
> > +  }
> > +
> > +Done:
> > +  if (AlignedBufferAllocated) {
> 
> 
> IMO, the content in 'AlignedBuffer' should be wiped out, since it might
> contain sensitive information. SSC protocol user can control the data in
> 'PayloadBuffer' but not in 'AlignedBuffer'.
> 
> 
> > +    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
> > +  }
> > +  gBS->RestoreTPL (OldTpl);
> > +  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.
> > +
> > +  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
> > +ScsiDiskSendData (
> > +  IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
> > +  IN UINT32                                   MediaId   OPTIONAL,
> > +  IN UINT64                                   Timeout,
> > +  IN UINT8                                    SecurityProtocolId,
> > +  IN UINT16                                   SecurityProtocolSpecificData,
> > +  IN UINTN                                    PayloadBufferSize,
> > +  OUT VOID                                    *PayloadBuffer
> > +  )
> > +{
> > +  SCSI_DISK_DEV       *ScsiDiskDevice;
> > +  EFI_BLOCK_IO_MEDIA  *Media;
> > +  EFI_STATUS          Status;
> > +  BOOLEAN             MediaChange;
> > +  EFI_TPL             OldTpl;
> > +  UINT8               SenseDataLength;
> > +  UINT8               HostAdapterStatus;
> > +  UINT8               TargetStatus;
> > +  VOID                *AlignedBuffer;
> > +  BOOLEAN             AlignedBufferAllocated;
> > +
> > +  AlignedBuffer           = NULL;
> > +  MediaChange             = FALSE;
> > +  AlignedBufferAllocated  = FALSE;
> > +  OldTpl                  = gBS->RaiseTPL (TPL_CALLBACK);
> > +  ScsiDiskDevice          = SCSI_DISK_DEV_FROM_STORSEC (This);
> > +  Media                   = ScsiDiskDevice->BlkIo.Media;
> > +
> > +  SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof
> > (EFI_SCSI_SENSE_DATA));
> > +
> > +  if (!DetermineInstallStorageSecurity (ScsiDiskDevice, ScsiDiskDevice-
> > >Handle)) {
> > +    Status = EFI_UNSUPPORTED;
> > +    goto Done;
> > +  }
> > +
> > +  if (!IS_DEVICE_FIXED (ScsiDiskDevice)) {
> > +    Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
> > +    if (EFI_ERROR (Status)) {
> > +      Status = EFI_DEVICE_ERROR;
> > +      goto Done;
> > +    }
> > +
> > +    if (MediaChange) {
> > +      gBS->ReinstallProtocolInterface (
> > +              ScsiDiskDevice->Handle,
> > +              &gEfiStorageSecurityCommandProtocolGuid,
> > +              &ScsiDiskDevice->StorageSecurity,
> > +              &ScsiDiskDevice->StorageSecurity
> > +              );
> > +      if (Media->MediaPresent) {
> > +        Status = EFI_MEDIA_CHANGED;
> > +      } else {
> > +        Status = EFI_NO_MEDIA;
> > +      }
> > +      goto Done;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Validate Media
> > +  //
> > +  if (!(Media->MediaPresent)) {
> > +    Status = EFI_NO_MEDIA;
> > +    goto Done;
> > +  }
> > +
> > +  if ((MediaId != 0) && (MediaId != Media->MediaId)) {
> > +    Status = EFI_MEDIA_CHANGED;
> > +    goto Done;
> > +  }
> > +
> > +  if (Media->ReadOnly) {
> > +    Status = EFI_WRITE_PROTECTED;
> > +    goto Done;
> > +  }
> > +
> > +  if (PayloadBufferSize != 0) {
> > +    if (PayloadBuffer == NULL) {
> > +      Status = EFI_INVALID_PARAMETER;
> > +      goto Done;
> > +    }
> > +
> > +    if ((ScsiDiskDevice->ScsiIo->IoAlign > 1) && !IS_ALIGNED (PayloadBuffer,
> > ScsiDiskDevice->ScsiIo->IoAlign)) {
> > +      AlignedBuffer = AllocateAlignedBuffer (ScsiDiskDevice,
> > PayloadBufferSize);
> > +      if (AlignedBuffer == NULL) {
> > +        Status = EFI_OUT_OF_RESOURCES;
> > +        goto Done;
> > +      }
> > +      CopyMem (AlignedBuffer, PayloadBuffer, PayloadBufferSize);
> > +      AlignedBufferAllocated = TRUE;
> > +    } else {
> > +      AlignedBuffer = PayloadBuffer;
> > +    }
> > +  }
> > +
> > +  Status = ScsiSecurityProtocolOutCommand (
> > +            ScsiDiskDevice->ScsiIo,
> > +            Timeout,
> > +            ScsiDiskDevice->SenseData,
> > +            &SenseDataLength,
> > +            &HostAdapterStatus,
> > +            &TargetStatus,
> > +            SecurityProtocolId,
> > +            SecurityProtocolSpecificData,
> > +            (UINT32) PayloadBufferSize,
> > +            AlignedBuffer
> > +          );
> > +  if (EFI_ERROR (Status)) {
> > +    goto Done;
> > +  }
> > +
> > +  Status = CheckHostAdapterStatus (HostAdapterStatus);
> > +  if (EFI_ERROR (Status)) {
> > +    goto Done;
> > +  }
> > +
> > +  Status = CheckTargetStatus (TargetStatus);
> > +  if (EFI_ERROR (Status)) {
> > +    goto Done;
> > +  }
> > +
> > +Done:
> > +  if (AlignedBufferAllocated) {
> 
> 
> IMO, the content in 'AlignedBuffer' should be wiped out, since it might
> contain sensitive information. SSC protocol user can control the data in
> 'PayloadBuffer' but not in 'AlignedBuffer'.
> 
> 
> > +    FreeAlignedBuffer (AlignedBuffer, PayloadBufferSize);
> > +  }
> > +  gBS->RestoreTPL (OldTpl);
> > +  return Status;
> > +}
> > +
> >
> >  /**
> >    Detect Device and read out capacity ,if error occurs, parse the sense key.
> > @@ -2261,6 +2687,8 @@ ScsiDiskTestUnitReady (
> >      return EFI_DEVICE_ERROR;
> >    }
> >
> > +  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
> > +
> >    if (SenseDataLength != 0) {
> >      *NumberOfSenseKeys = SenseDataLength / sizeof
> > (EFI_SCSI_SENSE_DATA);
> >      *SenseDataArray    = ScsiDiskDevice->SenseData;
> > @@ -2315,13 +2743,12 @@ DetectMediaParsingSenseKeys (
> >    BOOLEAN RetryLater;
> >
> >    //
> > -  // Default is to read capacity, unless..
> > +  // Default is no action
> >    //
> > -  *Action = ACTION_READ_CAPACITY;
> > +  *Action = ACTION_NO_ACTION;
> >
> >    if (NumberOfSenseKeys == 0) {
> >      if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
> > -      *Action = ACTION_NO_ACTION;
> >      }
> 
> 
> I do not think the behavior is the same after the patch.
> Can it be:
> 
>   if (NumberOfSenseKeys == 0) {
>     if (!ScsiDiskDevice->BlkIo.Media->MediaPresent) {
>       *Action = ACTION_READ_CAPACITY;
>     }
>     return EFI_SUCCESS;
>   }
> 
> 
> >      return EFI_SUCCESS;
> >    }
> > @@ -2331,7 +2758,6 @@ DetectMediaParsingSenseKeys (
> >      // No Sense Key returned from last submitted command
> >      //
> >      if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
> > -      *Action = ACTION_NO_ACTION;
> >      }
> 
> 
> I do not think the behavior is the same after the patch.
> Can it be:
> 
>   if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
>     //
>     // No Sense Key returned from last submitted command
>     //
>     if (!ScsiDiskDevice->BlkIo.Media->MediaPresent) {
>       *Action = ACTION_READ_CAPACITY;
>     }
>     return EFI_SUCCESS;
>   }
> 
> 
> Best Regards,
> Hao Wu
> 
> 
> >      return EFI_SUCCESS;
> >    }
> > @@ -2339,13 +2765,13 @@ DetectMediaParsingSenseKeys (
> >    if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
> >      ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
> >      ScsiDiskDevice->BlkIo.Media->LastBlock    = 0;
> > -    *Action = ACTION_NO_ACTION;
> >      DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
> >      return EFI_SUCCESS;
> >    }
> >
> >    if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
> >      ScsiDiskDevice->BlkIo.Media->MediaId++;
> > +    *Action = ACTION_READ_CAPACITY;
> >      DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaChange!\n"));
> >      return EFI_SUCCESS;
> >    }
> > @@ -2374,7 +2800,6 @@ DetectMediaParsingSenseKeys (
> >        DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
> >        return EFI_SUCCESS;
> >      }
> > -    *Action = ACTION_NO_ACTION;
> >      return EFI_DEVICE_ERROR;
> >    }
> >
> > @@ -2808,8 +3233,6 @@ GetMediaInfo (
> >        }
> >      }
> >    }
> > -
> > -  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
> >  }
> >
> >  /**
> > @@ -5358,6 +5781,14 @@ DetermineInstallEraseBlock (
> >    RetVal         = TRUE;
> >    CapacityData16 = NULL;
> >
> > +  //
> > +  // UNMAP command is not supported by any of the UFS WLUNs.
> > +  //
> > +  if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_WLUN) {
> > +    RetVal = FALSE;
> > +    goto Done;
> > +  }
> > +
> >    Status = gBS->HandleProtocol (
> >                    ChildHandle,
> >                    &gEfiDevicePathProtocolGuid,
> > @@ -5460,6 +5891,65 @@ Done:
> >    return RetVal;
> >  }
> >
> > +/**
> > +  Determine if EFI Storage Security Command Protocol should be produced.
> > +
> > +  @param   ScsiDiskDevice    The pointer of SCSI_DISK_DEV.
> > +  @param   ChildHandle       Handle of device.
> > +
> > +  @retval  TRUE    Should produce EFI Storage Security Command Protocol.
> > +  @retval  FALSE   Should not produce EFI Storage Security Command
> > Protocol.
> > +
> > +**/
> > +BOOLEAN
> > +DetermineInstallStorageSecurity (
> > +  IN  SCSI_DISK_DEV          *ScsiDiskDevice,
> > +  IN  EFI_HANDLE             ChildHandle
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  UFS_DEVICE_PATH                 *UfsDevice;
> > +  BOOLEAN                         RetVal;
> > +  EFI_DEVICE_PATH_PROTOCOL        *DevicePathNode;
> > +
> > +  UfsDevice      = NULL;
> > +  RetVal         = TRUE;
> > +
> > +  Status = gBS->HandleProtocol (
> > +                  ChildHandle,
> > +                  &gEfiDevicePathProtocolGuid,
> > +                  (VOID **) &DevicePathNode
> > +                  );
> > +  //
> > +  // Device Path protocol must be installed on the device handle.
> > +  //
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  while (!IsDevicePathEndType (DevicePathNode)) {
> > +    //
> > +    // For now, only support Storage Security Command Protocol on UFS
> > devices.
> > +    //
> > +    if ((DevicePathNode->Type == MESSAGING_DEVICE_PATH) &&
> > +        (DevicePathNode->SubType == MSG_UFS_DP)) {
> > +      UfsDevice = (UFS_DEVICE_PATH *) DevicePathNode;
> > +      break;
> > +    }
> > +
> > +    DevicePathNode = NextDevicePathNode (DevicePathNode);
> > +  }
> > +  if (UfsDevice == NULL) {
> > +    RetVal = FALSE;
> > +    goto Done;
> > +  }
> > +
> > +  if (UfsDevice->Lun != UFS_WLUN_RPMB) {
> > +    RetVal = FALSE;
> > +  }
> > +
> > +Done:
> > +  return RetVal;
> > +}
> > +
> >  /**
> >    Provides inquiry information for the controller type.
> >
> > diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> > b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> > index 1518b251d8..0bb67f2ddc 100644
> > --- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> > +++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
> > @@ -1,6 +1,6 @@
> >  /** @file
> >
> > -  Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> > @@ -819,7 +819,9 @@ UfsPassThruDriverBindingStart (
> >    UINTN                                 UfsHcBase;
> >    UINT32                                Index;
> >    UFS_UNIT_DESC                         UnitDescriptor;
> > +  UFS_DEV_DESC                          DeviceDescriptor;
> >    UINT32                                UnitDescriptorSize;
> > +  UINT32                                DeviceDescriptorSize;
> >
> >    Status    = EFI_SUCCESS;
> >    UfsHc     = NULL;
> > @@ -894,7 +896,6 @@ UfsPassThruDriverBindingStart (
> >
> >    //
> >    // Check if 8 common luns are active and set corresponding bit mask.
> > -  // TODO: Parse device descriptor to decide if exposing RPMB LUN to
> upper
> > layer for authentication access.
> >    //
> >    UnitDescriptorSize = sizeof (UFS_UNIT_DESC);
> >    for (Index = 0; Index < 8; Index++) {
> > @@ -909,6 +910,20 @@ UfsPassThruDriverBindingStart (
> >      }
> >    }
> >
> > +  //
> > +  // Check if RPMB WLUN is supported and set corresponding bit mask.
> > +  //
> > +  DeviceDescriptorSize = sizeof (UFS_DEV_DESC);
> > +  Status = UfsRwDeviceDesc (Private, TRUE, UfsDeviceDesc, 0, 0,
> > &DeviceDescriptor, &DeviceDescriptorSize);
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR, "Failed to read device descriptor, status
> = %r\n",
> > Status));
> > +  } else {
> > +    if (DeviceDescriptor.SecurityLun == 0x1) {
> > +      DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
> > +      Private->Luns.BitMask |= BIT11;
> > +    }
> > +  }
> > +
> >    //
> >    // Start the asynchronous interrupt monitor
> >    //
> > --
> > 2.16.2.windows.1
> >
> >
> > 


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-08-19  8:13 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-13  2:04 [PATCH v4 0/2] Add SCSI Support for Storage Security Command Protocol Zurcher, Christopher J
2019-06-13  2:04 ` [PATCH v4 1/2] MdePkg: Implement SCSI commands for Security Protocol In/Out Zurcher, Christopher J
2019-06-13 12:54   ` Liming Gao
2019-06-13 21:39     ` Zurcher, Christopher J
2019-06-18  2:12       ` [edk2-devel] " Wu, Hao A
2019-06-13  2:04 ` [PATCH v4 2/2] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol Zurcher, Christopher J
2019-06-18  2:12   ` [edk2-devel] " Wu, Hao A
2019-08-16 20:22     ` Zurcher, Christopher J
2019-08-19  8:10       ` Wu, Hao A
2019-06-13 12:58 ` [PATCH v4 0/2] Add SCSI Support for " Liming Gao
2019-06-13 22:25   ` Zurcher, Christopher J
2019-06-13 22:31     ` Yao, Jiewen
2019-06-14  0:14       ` Wu, Hao A

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox