public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Gao, Liming" <liming.gao@intel.com>
To: "Zurcher, Christopher J" <christopher.j.zurcher@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol
Date: Wed, 20 Feb 2019 23:59:14 +0000	[thread overview]
Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A14E3E2C80@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <8EE4873E19344F4DA986A2AC15D512AE46091D3A@CRSMSX103.amr.corp.intel.com>

Christopher:
  Please separate the patch per package. The patch can't cross the different packages. 

Thanks
Liming
>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>Zurcher, Christopher J
>Sent: Thursday, February 21, 2019 7:56 AM
>To: edk2-devel@lists.01.org
>Subject: [edk2] [PATCH] MdeModulePkg/ScsiDiskDxe: Support Storage
>Security Command Protocol
>
>BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1546
>
>This patch implements the EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
>in the
>ScsiDiskDxe driver (and supporting library, UefiScsiLib).
>
>Support is currently limited to the RPMB Well-known LUN for UFS devices.
>
>Cc: Jiewen Yao <jiewen.yao@intel.com>
>Cc: Jian J Wang <jian.j.wang@intel.com>
>Cc: Liming Gao <liming.gao@intel.com>
>Contributed-under: TianoCore Contribution Agreement 1.1
>Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
>---
> MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c        |   5 +-
> MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c |  14 +-
> MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c      | 510
>+++++++++++++++++++++-
> MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h      | 171 +++++++-
> MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf |   3 +-
> MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c |  19 +-
> MdePkg/Include/IndustryStandard/Scsi.h            |  48 +-
> MdePkg/Include/Library/UefiScsiLib.h              | 126 +++++-
> MdePkg/Include/Protocol/ScsiIo.h                  |   9 +-
> MdePkg/Library/UefiScsiLib/UefiScsiLib.c          | 205 ++++++++-
> 10 files changed, 1064 insertions(+), 46 deletions(-)
>
>diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
>b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
>index 11a7f2a927..0b4c51764e 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>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD
>License
> which accompanies this distribution.  The full text of the license may be found
>at
>@@ -1374,7 +1374,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/ComponentName.c
>b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c
>index f2da7af8fb..cba833d4ca 100644
>--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c
>+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c
>@@ -1,7 +1,7 @@
> /** @file
>   UEFI Component Name(2) protocol implementation for SCSI disk driver.
>
>-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
>+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD
>License
> which accompanies this distribution.  The full text of the license may be found
>at
>@@ -173,9 +173,9 @@ ScsiDiskComponentNameGetControllerName (
>   OUT CHAR16                                          **ControllerName
>   )
> {
>-  EFI_STATUS            Status;
>-  SCSI_DISK_DEV         *ScsiDiskDevice;
>-  EFI_BLOCK_IO_PROTOCOL *BlockIo;
>+  EFI_STATUS              Status;
>+  SCSI_DISK_DEV           *ScsiDiskDevice;
>+  EFI_DISK_INFO_PROTOCOL  *DiskInfo;
>
>   //
>   // This is a device driver, so ChildHandle must be NULL.
>@@ -200,8 +200,8 @@ ScsiDiskComponentNameGetControllerName (
>   //
>   Status = gBS->OpenProtocol (
>                   ControllerHandle,
>-                  &gEfiBlockIoProtocolGuid,
>-                  (VOID **) &BlockIo,
>+                  &gEfiDiskInfoProtocolGuid,
>+                  (VOID **) &DiskInfo,
>                   gScsiDiskDriverBinding.DriverBindingHandle,
>                   ControllerHandle,
>                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
>@@ -211,7 +211,7 @@ ScsiDiskComponentNameGetControllerName (
>     return Status;
>   }
>
>-  ScsiDiskDevice = SCSI_DISK_DEV_FROM_BLKIO (BlockIo);
>+  ScsiDiskDevice = SCSI_DISK_DEV_FROM_DISKINFO (DiskInfo);
>
>   return LookupUnicodeString2 (
>            Language,
>diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
>b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
>index 0d63c85e44..75eb13ca20 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>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD
>License
> which accompanies this distribution.  The full text of the license may be found
>at
>@@ -157,7 +157,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;
>@@ -244,6 +246,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;
>@@ -264,6 +268,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
>@@ -311,11 +319,45 @@ ScsiDiskDriverBindingStart (
>   //
>   Status = ScsiDiskDetectMedia (ScsiDiskDevice, MustReadCapacity, &Temp);
>   if (!EFI_ERROR (Status)) {
>+
>+    //
>+    // Determine if StorageSecurity should be produced on this controller
>+    //
>+    if (DetermineInstallStorageSecurity(ScsiDiskDevice, Controller) &&
>+        DetermineInstallBlockIo(Controller)) {
>+      InitializeInstallDiskInfo(ScsiDiskDevice, Controller);
>+      Status = gBS->InstallMultipleProtocolInterfaces (
>+                      &Controller,
>+                      &gEfiStorageSecurityCommandProtocolGuid,
>+                      &ScsiDiskDevice->StorageSecurity,
>+                      &gEfiDiskInfoProtocolGuid,
>+                      &ScsiDiskDevice->DiskInfo,
>+                      NULL
>+                      );
>+      if (!EFI_ERROR(Status)) {
>+        ScsiDiskDevice->ControllerNameTable = NULL;
>+        AddUnicodeString2 (
>+          "eng",
>+          gScsiDiskComponentName.SupportedLanguages,
>+          &ScsiDiskDevice->ControllerNameTable,
>+          L"SCSI Secure Disk Device",
>+          TRUE
>+          );
>+        AddUnicodeString2 (
>+          "en",
>+          gScsiDiskComponentName2.SupportedLanguages,
>+          &ScsiDiskDevice->ControllerNameTable,
>+          L"SCSI Secure Disk Device",
>+          FALSE
>+          );
>+        return EFI_SUCCESS;
>+      }
>+
>     //
>     // Determine if Block IO & Block IO2 should be produced on this controller
>     // handle
>     //
>-    if (DetermineInstallBlockIo(Controller)) {
>+    } else if (DetermineInstallBlockIo(Controller)) {
>       InitializeInstallDiskInfo(ScsiDiskDevice, Controller);
>       Status = gBS->InstallMultipleProtocolInterfaces (
>                       &Controller,
>@@ -1714,6 +1756,396 @@ 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;
>+
>+  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;
>+
>+  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 ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
>+    DEBUG ((DEBUG_ERROR, "ScsiDiskSendData: PayloadBuffer NULL!\n"));
>+    Status = EFI_INVALID_PARAMETER;
>+    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.
>@@ -2267,6 +2699,8 @@ ScsiDiskTestUnitReady (
>     return EFI_DEVICE_ERROR;
>   }
>
>+  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
>+
>   if (SenseDataLength != 0) {
>     *NumberOfSenseKeys = SenseDataLength / sizeof
>(EFI_SCSI_SENSE_DATA);
>     *SenseDataArray    = ScsiDiskDevice->SenseData;
>@@ -2321,13 +2755,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;
>   }
>@@ -2337,7 +2770,6 @@ DetectMediaParsingSenseKeys (
>     // No Sense Key returned from last submitted command
>     //
>     if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {
>-      *Action = ACTION_NO_ACTION;
>     }
>     return EFI_SUCCESS;
>   }
>@@ -2345,13 +2777,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;
>   }
>@@ -2380,7 +2812,6 @@ DetectMediaParsingSenseKeys (
>       DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
>       return EFI_SUCCESS;
>     }
>-    *Action = ACTION_NO_ACTION;
>     return EFI_DEVICE_ERROR;
>   }
>
>@@ -2814,8 +3245,6 @@ GetMediaInfo (
>       }
>     }
>   }
>-
>-  ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
> }
>
> /**
>@@ -5466,6 +5895,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/Scsi/ScsiDiskDxe/ScsiDisk.h
>b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
>index bb6232676d..4731258018 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>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD
>License
> which accompanies this distribution.  The full text of the license may be found
>at
>@@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
>KIND, EITHER EXPRESS OR IMPLIED.
> #include <Protocol/ScsiPassThruExt.h>
> #include <Protocol/ScsiPassThru.h>
> #include <Protocol/DiskInfo.h>
>+#include <Protocol/StorageSecurityCommand.h>
>
>
> #include <Library/DebugLib.h>
>@@ -44,6 +45,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
>KIND, EITHER EXPRESS OR IMPLIED.
>
> #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;
>@@ -57,6 +62,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;
>@@ -101,6 +108,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)
>
>@@ -644,6 +652,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.
>
>@@ -1434,4 +1587,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/ScsiDiskDxe/ScsiDiskDxe.inf
>b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
>index 14010802a8..2122aa4b01 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>
> #  This program and the accompanying materials
> #  are licensed and made available under the terms and conditions of the BSD
>License
> #  which accompanies this distribution.  The full text of the license may be
>found at
>@@ -58,6 +58,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/Ufs/UfsPassThruDxe/UfsPassThru.c
>b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
>index ea329618dc..6ed5da21fd 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>
>   This program and the accompanying materials
>   are licensed and made available under the terms and conditions of the BSD
>License
>   which accompanies this distribution.  The full text of the license may be
>found at
>@@ -825,7 +825,9 @@ UfsPassThruDriverBindingStart (
>   UINTN                                 UfsHcBase;
>   UINT32                                Index;
>   UFS_UNIT_DESC                         UnitDescriptor;
>+  UFS_DEV_DESC                          DeviceDescriptor;
>   UINT32                                UnitDescriptorSize;
>+  UINT32                                DeviceDescriptorSize;
>
>   Status    = EFI_SUCCESS;
>   UfsHc     = NULL;
>@@ -900,7 +902,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++) {
>@@ -915,6 +916,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
>   //
>diff --git a/MdePkg/Include/IndustryStandard/Scsi.h
>b/MdePkg/Include/IndustryStandard/Scsi.h
>index 213d8acc2d..59509a0256 100644
>--- a/MdePkg/Include/IndustryStandard/Scsi.h
>+++ b/MdePkg/Include/IndustryStandard/Scsi.h
>@@ -1,7 +1,7 @@
> /** @file
>   Support for SCSI-2 standard
>
>-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>   This program and the accompanying materials
>   are licensed and made available under the terms and conditions of the BSD
>License
>   which accompanies this distribution.  The full text of the license may be
>found at
>@@ -169,6 +169,12 @@
> #define EFI_SCSI_OP_SEND_MESSAGE10  0x2a
> #define EFI_SCSI_OP_SEND_MESSAGE12  0xaa
>
>+//
>+// Additional commands for Secure Transactions
>+//
>+#define EFI_SCSI_OP_SECURITY_PROTOCOL_IN  0xa2
>+#define EFI_SCSI_OP_SECURITY_PROTOCOL_OUT 0xb5
>+
> //
> // SCSI Data Transfer Direction
> //
>@@ -178,22 +184,30 @@
> //
> // Peripheral Device Type Definitions
> //
>-#define EFI_SCSI_TYPE_DISK          0x00  ///< Direct-access device (e.g.
>magnetic disk)
>-#define EFI_SCSI_TYPE_TAPE          0x01  ///< Sequential-access device (e.g.
>magnetic tape)
>-#define EFI_SCSI_TYPE_PRINTER       0x02  ///< Printer device
>-#define EFI_SCSI_TYPE_PROCESSOR     0x03  ///< Processor device
>-#define EFI_SCSI_TYPE_WORM          0x04  ///< Write-once device (e.g. some
>optical disks)
>-#define EFI_SCSI_TYPE_CDROM         0x05  ///< CD-ROM device
>-#define EFI_SCSI_TYPE_SCANNER       0x06  ///< Scanner device
>-#define EFI_SCSI_TYPE_OPTICAL       0x07  ///< Optical memory device (e.g.
>some optical disks)
>-#define EFI_SCSI_TYPE_MEDIUMCHANGER 0x08  ///< Medium changer
>device (e.g. jukeboxes)
>-#define EFI_SCSI_TYPE_COMMUNICATION 0x09  ///< Communications
>device
>-#define EFI_SCSI_TYPE_ASCIT8_1      0x0A  ///< Defined by ASC IT8 (Graphic
>arts pre-press devices)
>-#define EFI_SCSI_TYPE_ASCIT8_2      0x0B  ///< Defined by ASC IT8 (Graphic
>arts pre-press devices)
>-//
>-// 0Ch - 1Eh are reserved
>-//
>-#define EFI_SCSI_TYPE_UNKNOWN       0x1F  ///< Unknown or no device
>type
>+#define EFI_SCSI_TYPE_DISK            0x00  ///< Direct-access device (e.g.
>magnetic disk)
>+#define EFI_SCSI_TYPE_TAPE            0x01  ///< Sequential-access device (e.g.
>magnetic tape)
>+#define EFI_SCSI_TYPE_PRINTER         0x02  ///< Printer device
>+#define EFI_SCSI_TYPE_PROCESSOR       0x03  ///< Processor device
>+#define EFI_SCSI_TYPE_WORM            0x04  ///< Write-once device (e.g.
>some optical disks)
>+#define EFI_SCSI_TYPE_CDROM           0x05  ///< CD/DVD device
>+#define EFI_SCSI_TYPE_SCANNER         0x06  ///< Scanner device (obsolete)
>+#define EFI_SCSI_TYPE_OPTICAL         0x07  ///< Optical memory device (e.g.
>some optical disks)
>+#define EFI_SCSI_TYPE_MEDIUMCHANGER   0x08  ///< Medium changer
>device (e.g. jukeboxes)
>+#define EFI_SCSI_TYPE_COMMUNICATION   0x09  ///< Communications
>device (obsolete)
>+#define EFI_SCSI_TYPE_A               0x0A  ///< Obsolete
>+#define EFI_SCSI_TYPE_B               0x0B  ///< Obsolete
>+#define EFI_SCSI_TYPE_RAID            0x0C  ///< Storage array controller device
>(e.g., RAID)
>+#define EFI_SCSI_TYPE_SES             0x0D  ///< Enclosure services device
>+#define EFI_SCSI_TYPE_RBC             0x0E  ///< Simplified direct-access device
>(e.g., magnetic disk)
>+#define EFI_SCSI_TYPE_OCRW            0x0F  ///< Optical card reader/writer
>device
>+#define EFI_SCSI_TYPE_BRIDGE          0x10  ///< Bridge Controller Commands
>+#define EFI_SCSI_TYPE_OSD             0x11  ///< Object-based Storage Device
>+#define EFI_SCSI_TYPE_AUTOMATION      0x12  ///< Automation/Drive
>Interface
>+#define EFI_SCSI_TYPE_SECURITYMANAGER 0x13  ///< Security manager
>device
>+#define EFI_SCSI_TYPE_RESERVED_LOW    0x14  ///< Reserved (low)
>+#define EFI_SCSI_TYPE_RESERVED_HIGH   0x1D  ///< Reserved (high)
>+#define EFI_SCSI_TYPE_WLUN            0x1E  ///< Well known logical unit
>+#define EFI_SCSI_TYPE_UNKNOWN         0x1F  ///< Unknown or no device
>type
>
> //
> // Page Codes for INQUIRY command
>diff --git a/MdePkg/Include/Library/UefiScsiLib.h
>b/MdePkg/Include/Library/UefiScsiLib.h
>index dbb248972b..594f495d7d 100644
>--- a/MdePkg/Include/Library/UefiScsiLib.h
>+++ b/MdePkg/Include/Library/UefiScsiLib.h
>@@ -5,7 +5,7 @@
>   for hard drive, CD and DVD devices that are the most common SCSI boot
>targets used by UEFI platforms.
>   This library class depends on SCSI I/O Protocol defined in UEFI Specification
>and SCSI-2 industry standard.
>
>-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD
>License
> which accompanies this distribution.  The full text of the license may be found
>at
>@@ -819,6 +819,130 @@ ScsiWrite16Command (
>   );
>
>
>+/**
>+  Execute Security Protocol In SCSI command on a specific SCSI target.
>+
>+  Executes the SCSI Security Protocol In command on the SCSI target
>specified by ScsiIo.
>+  If Timeout is zero, then this function waits indefinitely for the command to
>complete.
>+  If Timeout is greater than zero, then the command is executed and will
>timeout after
>+  Timeout 100 ns units.  The StartLba and SectorSize parameters are used to
>construct
>+  the CDB for this SCSI command.
>+  If ScsiIo is NULL, then ASSERT().
>+  If SenseDataLength is NULL, then ASSERT().
>+  If HostAdapterStatus is NULL, then ASSERT().
>+  If TargetStatus is NULL, then ASSERT().
>+  If DataLength is NULL, then ASSERT().
>+
>+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  @param[in]      ScsiIo               SCSI IO Protocol to use.
>+  @param[in]      Timeout              The length of timeout period.
>+  @param[in, out] SenseData            A pointer to output sense data.
>+  @param[in, out] SenseDataLength      The length of output sense data.
>+  @param[out]     HostAdapterStatus    The status of Host Adapter.
>+  @param[out]     TargetStatus         The status of the target.
>+  @param[in]      SecurityProtocol     The Security Protocol to use.
>+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.
>+  @param[in]      TransferLength       The size in bytes of the data allocation.
>+  @param[in, out] DataBuffer           A pointer to a data buffer.
>+  @param[in, out] DataLength           The length of data buffer.
>+
>+  @retval  EFI_SUCCESS                 Command is executed successfully.
>+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed,
>but the entire DataBuffer could
>+                                       not be transferred. The actual number of bytes
>transferred is returned in DataLength.
>+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent
>because there are too many
>+                                       SCSI Command Packets already queued.
>+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting
>to send SCSI Request Packet.
>+  @retval  EFI_UNSUPPORTED             The command described by the SCSI
>Request Packet is not supported by
>+                                       the SCSI initiator(i.e., SCSI  Host Controller)
>+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the
>SCSI Request Packet to execute.
>+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request
>Packet are invalid.
>+
>+**/
>+EFI_STATUS
>+EFIAPI
>+ScsiSecurityProtocolInCommand (
>+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,
>+  IN     UINT64                Timeout,
>+  IN OUT VOID                  *SenseData,   OPTIONAL
>+  IN OUT UINT8                 *SenseDataLength,
>+     OUT UINT8                 *HostAdapterStatus,
>+     OUT UINT8                 *TargetStatus,
>+  IN     UINT8                 SecurityProtocol,
>+  IN     UINT16                SecurityProtocolSpecific,
>+  IN     UINT32                TransferLength,
>+  IN OUT VOID                  *DataBuffer,  OPTIONAL
>+  IN OUT UINT32                *DataLength
>+  );
>+
>+
>+/**
>+  Execute Security Protocol Out SCSI command on a specific SCSI target.
>+
>+  Executes the SCSI Security Protocol Out command on the SCSI target
>specified by ScsiIo.
>+  If Timeout is zero, then this function waits indefinitely for the command to
>complete.
>+  If Timeout is greater than zero, then the command is executed and will
>timeout after
>+  Timeout 100 ns units.  The StartLba and SectorSize parameters are used to
>construct
>+  the CDB for this SCSI command.
>+  If ScsiIo is NULL, then ASSERT().
>+  If SenseDataLength is NULL, then ASSERT().
>+  If HostAdapterStatus is NULL, then ASSERT().
>+  If TargetStatus is NULL, then ASSERT().
>+  If DataLength is NULL, then ASSERT().
>+
>+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  @param[in]      ScsiIo               SCSI IO Protocol to use.
>+  @param[in]      Timeout              The length of timeout period.
>+  @param[in, out] SenseData            A pointer to output sense data.
>+  @param[in, out] SenseDataLength      The length of output sense data.
>+  @param[out]     HostAdapterStatus    The status of Host Adapter.
>+  @param[out]     TargetStatus         The status of the target.
>+  @param[in]      SecurityProtocol     The Security Protocol to use.
>+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.
>+  @param[in]      TransferLength       The size in bytes of the transfer data.
>+  @param[in, out] DataBuffer           A pointer to a data buffer.
>+
>+  @retval  EFI_SUCCESS                 Command is executed successfully.
>+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed,
>but the entire DataBuffer could
>+                                       not be transferred. The actual number of bytes
>transferred is returned in DataLength.
>+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent
>because there are too many
>+                                       SCSI Command Packets already queued.
>+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting
>to send SCSI Request Packet.
>+  @retval  EFI_UNSUPPORTED             The command described by the SCSI
>Request Packet is not supported by
>+                                       the SCSI initiator(i.e., SCSI  Host Controller)
>+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the
>SCSI Request Packet to execute.
>+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request
>Packet are invalid.
>+
>+**/
>+EFI_STATUS
>+EFIAPI
>+ScsiSecurityProtocolOutCommand (
>+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,
>+  IN     UINT64                Timeout,
>+  IN OUT VOID                  *SenseData,   OPTIONAL
>+  IN OUT UINT8                 *SenseDataLength,
>+     OUT UINT8                 *HostAdapterStatus,
>+     OUT UINT8                 *TargetStatus,
>+  IN     UINT8                 SecurityProtocol,
>+  IN     UINT16                SecurityProtocolSpecific,
>+  IN     UINT32                TransferLength,
>+  IN OUT VOID                  *DataBuffer  OPTIONAL
>+  );
>+
>+
> /**
>   Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
>   target.
>diff --git a/MdePkg/Include/Protocol/ScsiIo.h
>b/MdePkg/Include/Protocol/ScsiIo.h
>index 1e7bc86b29..cddf395cb1 100644
>--- a/MdePkg/Include/Protocol/ScsiIo.h
>+++ b/MdePkg/Include/Protocol/ScsiIo.h
>@@ -4,7 +4,7 @@
>   services environment to access SCSI devices. In particular, functions for
>   managing devices on SCSI buses are defined here.
>
>-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>   This program and the accompanying materials
>   are licensed and made available under the terms and conditions of the BSD
>License
>   which accompanies this distribution.  The full text of the license may be
>found at
>@@ -49,8 +49,11 @@ typedef struct _EFI_SCSI_IO_PROTOCOL
>EFI_SCSI_IO_PROTOCOL;
> #define MFI_SCSI_IO_TYPE_OCRW                                  0x0F    ///< Optical card
>reader/writer device
> #define MFI_SCSI_IO_TYPE_BRIDGE                                0x10    ///< Bridge
>Controller Commands
> #define MFI_SCSI_IO_TYPE_OSD                                   0x11    ///< Object-based
>Storage Device
>-#define EFI_SCSI_IO_TYPE_RESERVED_LOW                          0x12    ///<
>Reserved (low)
>-#define EFI_SCSI_IO_TYPE_RESERVED_HIGH                         0x1E    ///<
>Reserved (high)
>+#define MFI_SCSI_IO_TYPE_AUTOMATION                            0x12    ///<
>Automation/Drive Interface
>+#define MFI_SCSI_IO_TYPE_SECURITYMANAGER                       0x13    ///<
>Security manager device
>+#define EFI_SCSI_IO_TYPE_RESERVED_LOW                          0x14    ///<
>Reserved (low)
>+#define EFI_SCSI_IO_TYPE_RESERVED_HIGH                         0x1D    ///<
>Reserved (high)
>+#define EFI_SCSI_IO_TYPE_WLUN                                  0x1E    ///< Well known
>logical unit
> #define EFI_SCSI_IO_TYPE_UNKNOWN                               0x1F    ///< Unknown
>no device type
>
> //
>diff --git a/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
>b/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
>index 62a73e2773..b7b83a7ab6 100644
>--- a/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
>+++ b/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
>@@ -1,7 +1,7 @@
> /** @file
>   UEFI SCSI Library implementation
>
>-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>   This program and the accompanying materials
>   are licensed and made available under the terms and conditions of the BSD
>License
>   which accompanies this distribution.  The full text of the license may be
>found at
>@@ -29,6 +29,7 @@
>   //
> #define EFI_SCSI_OP_LENGTH_SIX      0x6
> #define EFI_SCSI_OP_LENGTH_TEN      0xa
>+#define EFI_SCSI_OP_LENGTH_TWELVE   0xc
> #define EFI_SCSI_OP_LENGTH_SIXTEEN  0x10
>
> //
>@@ -1286,6 +1287,208 @@ ScsiWrite16Command (
> }
>
>
>+/**
>+  Execute Security Protocol In SCSI command on a specific SCSI target.
>+
>+  Executes the SCSI Security Protocol In command on the SCSI target
>specified by ScsiIo.
>+  If Timeout is zero, then this function waits indefinitely for the command to
>complete.
>+  If Timeout is greater than zero, then the command is executed and will
>timeout after
>+  Timeout 100 ns units.  The StartLba and SectorSize parameters are used to
>construct
>+  the CDB for this SCSI command.
>+  If ScsiIo is NULL, then ASSERT().
>+  If SenseDataLength is NULL, then ASSERT().
>+  If HostAdapterStatus is NULL, then ASSERT().
>+  If TargetStatus is NULL, then ASSERT().
>+  If DataLength is NULL, then ASSERT().
>+
>+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  @param[in]      ScsiIo               SCSI IO Protocol to use.
>+  @param[in]      Timeout              The length of timeout period.
>+  @param[in, out] SenseData            A pointer to output sense data.
>+  @param[in, out] SenseDataLength      The length of output sense data.
>+  @param[out]     HostAdapterStatus    The status of Host Adapter.
>+  @param[out]     TargetStatus         The status of the target.
>+  @param[in]      SecurityProtocol     The Security Protocol to use.
>+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.
>+  @param[in]      TransferLength       The size in bytes of the data allocation.
>+  @param[in, out] DataBuffer           A pointer to a data buffer.
>+  @param[in, out] DataLength           The length of data buffer.
>+
>+  @retval  EFI_SUCCESS                 Command is executed successfully.
>+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed,
>but the entire DataBuffer could
>+                                       not be transferred. The actual number of bytes
>transferred is returned in DataLength.
>+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent
>because there are too many
>+                                       SCSI Command Packets already queued.
>+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting
>to send SCSI Request Packet.
>+  @retval  EFI_UNSUPPORTED             The command described by the SCSI
>Request Packet is not supported by
>+                                       the SCSI initiator(i.e., SCSI  Host Controller)
>+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the
>SCSI Request Packet to execute.
>+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request
>Packet are invalid.
>+
>+**/
>+EFI_STATUS
>+EFIAPI
>+ScsiSecurityProtocolInCommand (
>+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,
>+  IN     UINT64                Timeout,
>+  IN OUT VOID                  *SenseData,   OPTIONAL
>+  IN OUT UINT8                 *SenseDataLength,
>+     OUT UINT8                 *HostAdapterStatus,
>+     OUT UINT8                 *TargetStatus,
>+  IN     UINT8                 SecurityProtocol,
>+  IN     UINT16                SecurityProtocolSpecific,
>+  IN     UINT32                TransferLength,
>+  IN OUT VOID                  *DataBuffer,  OPTIONAL
>+  IN OUT UINT32                *DataLength
>+  )
>+{
>+  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
>+  EFI_STATUS                      Status;
>+  UINT8                           Cdb[EFI_SCSI_OP_LENGTH_TWELVE];
>+
>+  ASSERT (SenseDataLength != NULL);
>+  ASSERT (HostAdapterStatus != NULL);
>+  ASSERT (TargetStatus != NULL);
>+  ASSERT (DataLength != NULL);
>+  ASSERT (ScsiIo != NULL);
>+
>+  ZeroMem (&CommandPacket, sizeof
>(EFI_SCSI_IO_SCSI_REQUEST_PACKET));
>+  ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);
>+
>+  CommandPacket.Timeout           = Timeout;
>+  CommandPacket.InDataBuffer      = DataBuffer;
>+  CommandPacket.SenseData         = SenseData;
>+  CommandPacket.InTransferLength  = TransferLength;
>+  CommandPacket.Cdb               = Cdb;
>+  //
>+  // Fill Cdb for Security Protocol In Command
>+  //
>+  Cdb[0]                        = EFI_SCSI_OP_SECURITY_PROTOCOL_IN;
>+  Cdb[1]                        = SecurityProtocol;
>+  WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16
>(SecurityProtocolSpecific));
>+  WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 (TransferLength));
>+
>+  CommandPacket.CdbLength       = EFI_SCSI_OP_LENGTH_TWELVE;
>+  CommandPacket.DataDirection   = EFI_SCSI_DATA_IN;
>+  CommandPacket.SenseDataLength = *SenseDataLength;
>+
>+  Status                        = ScsiIo->ExecuteScsiCommand (ScsiIo,
>&CommandPacket, NULL);
>+
>+  *HostAdapterStatus            = CommandPacket.HostAdapterStatus;
>+  *TargetStatus                 = CommandPacket.TargetStatus;
>+  *SenseDataLength              = CommandPacket.SenseDataLength;
>+  *DataLength                   = CommandPacket.InTransferLength;
>+
>+  return Status;
>+}
>+
>+
>+/**
>+  Execute Security Protocol Out SCSI command on a specific SCSI target.
>+
>+  Executes the SCSI Security Protocol Out command on the SCSI target
>specified by ScsiIo.
>+  If Timeout is zero, then this function waits indefinitely for the command to
>complete.
>+  If Timeout is greater than zero, then the command is executed and will
>timeout after
>+  Timeout 100 ns units.  The StartLba and SectorSize parameters are used to
>construct
>+  the CDB for this SCSI command.
>+  If ScsiIo is NULL, then ASSERT().
>+  If SenseDataLength is NULL, then ASSERT().
>+  If HostAdapterStatus is NULL, then ASSERT().
>+  If TargetStatus is NULL, then ASSERT().
>+  If DataLength is NULL, then ASSERT().
>+
>+  If SenseDataLength is non-zero and SenseData is not NULL, SenseData must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must
>meet buffer
>+  alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
>EFI_INVALID_PARAMETER
>+  gets returned.
>+
>+  @param[in]      ScsiIo               SCSI IO Protocol to use.
>+  @param[in]      Timeout              The length of timeout period.
>+  @param[in, out] SenseData            A pointer to output sense data.
>+  @param[in, out] SenseDataLength      The length of output sense data.
>+  @param[out]     HostAdapterStatus    The status of Host Adapter.
>+  @param[out]     TargetStatus         The status of the target.
>+  @param[in]      SecurityProtocol     The Security Protocol to use.
>+  @param[in]      SecurityProtocolSpecific  The Security Protocol Specific data.
>+  @param[in]      TransferLength       The size in bytes of the transfer data.
>+  @param[in, out] DataBuffer           A pointer to a data buffer.
>+
>+  @retval  EFI_SUCCESS                 Command is executed successfully.
>+  @retval  EFI_BAD_BUFFER_SIZE         The SCSI Request Packet was executed,
>but the entire DataBuffer could
>+                                       not be transferred. The actual number of bytes
>transferred is returned in DataLength.
>+  @retval  EFI_NOT_READY               The SCSI Request Packet could not be sent
>because there are too many
>+                                       SCSI Command Packets already queued.
>+  @retval  EFI_DEVICE_ERROR            A device error occurred while attempting
>to send SCSI Request Packet.
>+  @retval  EFI_UNSUPPORTED             The command described by the SCSI
>Request Packet is not supported by
>+                                       the SCSI initiator(i.e., SCSI  Host Controller)
>+  @retval  EFI_TIMEOUT                 A timeout occurred while waiting for the
>SCSI Request Packet to execute.
>+  @retval  EFI_INVALID_PARAMETER       The contents of the SCSI Request
>Packet are invalid.
>+
>+**/
>+EFI_STATUS
>+EFIAPI
>+ScsiSecurityProtocolOutCommand (
>+  IN     EFI_SCSI_IO_PROTOCOL  *ScsiIo,
>+  IN     UINT64                Timeout,
>+  IN OUT VOID                  *SenseData,   OPTIONAL
>+  IN OUT UINT8                 *SenseDataLength,
>+     OUT UINT8                 *HostAdapterStatus,
>+     OUT UINT8                 *TargetStatus,
>+  IN     UINT8                 SecurityProtocol,
>+  IN     UINT16                SecurityProtocolSpecific,
>+  IN     UINT32                TransferLength,
>+  IN OUT VOID                  *DataBuffer   OPTIONAL
>+  )
>+{
>+  EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
>+  EFI_STATUS                      Status;
>+  UINT8                           Cdb[EFI_SCSI_OP_LENGTH_TWELVE];
>+
>+  ASSERT (SenseDataLength != NULL);
>+  ASSERT (HostAdapterStatus != NULL);
>+  ASSERT (TargetStatus != NULL);
>+  ASSERT (ScsiIo != NULL);
>+
>+  ZeroMem (&CommandPacket, sizeof
>(EFI_SCSI_IO_SCSI_REQUEST_PACKET));
>+  ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);
>+
>+  CommandPacket.Timeout           = Timeout;
>+  CommandPacket.OutDataBuffer     = DataBuffer;
>+  CommandPacket.SenseData         = SenseData;
>+  CommandPacket.OutTransferLength = TransferLength;
>+  CommandPacket.Cdb               = Cdb;
>+  //
>+  // Fill Cdb for Security Protocol Out Command
>+  //
>+  Cdb[0]                        = EFI_SCSI_OP_SECURITY_PROTOCOL_OUT;
>+  Cdb[1]                        = SecurityProtocol;
>+  WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16
>(SecurityProtocolSpecific));
>+  WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 (TransferLength));
>+
>+  CommandPacket.CdbLength       = EFI_SCSI_OP_LENGTH_TWELVE;
>+  CommandPacket.DataDirection   = EFI_SCSI_DATA_OUT;
>+  CommandPacket.SenseDataLength = *SenseDataLength;
>+
>+  Status                        = ScsiIo->ExecuteScsiCommand (ScsiIo,
>&CommandPacket, NULL);
>+
>+  *HostAdapterStatus            = CommandPacket.HostAdapterStatus;
>+  *TargetStatus                 = CommandPacket.TargetStatus;
>+  *SenseDataLength              = CommandPacket.SenseDataLength;
>+
>+  return Status;
>+}
>+
>+
> /**
>   Internal helper notify function in which update the result of the
>   non-blocking SCSI Read/Write commands and signal caller event.
>--
>2.16.2.windows.1
>
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel


      reply	other threads:[~2019-02-21  0:03 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-20 23:55 [PATCH] MdeModulePkg/ScsiDiskDxe: Support Storage Security Command Protocol Zurcher, Christopher J
2019-02-20 23:59 ` Gao, Liming [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A89E2EF3DFEDB4C8BFDE51014F606A14E3E2C80@SHSMSX104.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox