Support dynamic insertion and removal of the protocol

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Nikita Leshenko <nikita.leshche...@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
Reviewed-by: Aaron Young <aaron.yo...@oracle.com>
Reviewed-by: Liran Alon <liran.a...@oracle.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c      | 204 +++++++++++++++++++++++++++++-
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf |   5 +-
 2 files changed, 205 insertions(+), 4 deletions(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 57a17ca0cb..6b655d9fe8 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -16,10 +16,13 @@
 **/
 
 #include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
 #include <Library/UefiLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Protocol/PciIo.h>
+#include <Protocol/ScsiPassThruExt.h>
 
 //
 // Device offsets and constants
@@ -30,6 +33,118 @@
 #define LSI_SAS1068_PCI_DEVICE_ID 0x0054
 #define LSI_SAS1068E_PCI_DEVICE_ID 0x0058
 
+//
+// Runtime Structures
+//
+
+#define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')
+typedef struct {
+  UINT32                          Signature;
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
+  EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
+} MPT_SCSI_DEV;
+
+#define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
+  CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
+
+//
+// Ext SCSI Pass Thru
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiPassThru (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
+  IN UINT8                                          *Target,
+  IN UINT64                                         Lun,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+  IN EFI_EVENT                                      Event     OPTIONAL
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiPassThru Direction %d In %d Out %d\n",
+          Packet->DataDirection,
+          Packet->InTransferLength, Packet->OutTransferLength));
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiGetNextTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
+  IN OUT UINT8                                      **Target,
+  IN OUT UINT64                                     *Lun
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiGetNextTargetLun %d %d\n", **Target, *Lun));
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiGetNextTarget (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This,
+  IN OUT UINT8                                     **Target
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiGetNextTarget\n"));
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiBuildDevicePath (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This,
+  IN UINT8                                         *Target,
+  IN UINT64                                        Lun,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL                  **DevicePath
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiBuildDevicePath %d %d\n", *Target, Lun));
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiGetTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This,
+  IN EFI_DEVICE_PATH_PROTOCOL                      *DevicePath,
+  OUT UINT8                                        **Target,
+  OUT UINT64                                       *Lun
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiGetTargetLun\n"));
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiResetChannel (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiResetChannel\n"));
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiResetTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This,
+  IN UINT8                                         *Target,
+  IN UINT64                                        Lun
+  )
+{
+  DEBUG ((EFI_D_INFO, "MptScsiResetTargetLun\n"));
+  return EFI_UNSUPPORTED;
+}
+
 //
 // Driver Binding
 //
@@ -94,8 +209,65 @@ MptScsiControllerStart (
   IN EFI_DEVICE_PATH_PROTOCOL               *RemainingDevicePath OPTIONAL
   )
 {
-  DEBUG ((EFI_D_INFO, "Attempted to start MptScsi\n"));
-  return EFI_UNSUPPORTED;
+  EFI_STATUS           Status;
+  EFI_PHYSICAL_ADDRESS PhysicalAddress;
+  MPT_SCSI_DEV         *Dev;
+
+  DEBUG ((EFI_D_INFO, "Starting MptScsi\n"));
+
+  //
+  // MPT_SCSI_DEV contains descriptors that are passed to the controller. The
+  // controller doesn't easily support addresses larger than 4GB, so we 
allocate
+  // the struct below 4GB. (Technically we can use HostMfaHighAddr and make 
sure
+  // all descriptors have the same high address but it's more complicated than
+  // just allocating below 4GB. Also, we allocate it only once per device so 
the
+  // overhead of allocating a whole page is minimal.)
+  //
+  PhysicalAddress = MAX_UINT32;
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiRuntimeServicesData,
+                  EFI_SIZE_TO_PAGES (sizeof (*Dev)),
+                  &PhysicalAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // PhysicalAddress is page aligned, so MPT_SCSI_DEV alignment is correct
+  Dev = (MPT_SCSI_DEV *) (UINTN) PhysicalAddress;
+  ZeroMem (Dev, sizeof (*Dev));
+  Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
+
+  Dev->PassThruMode.AdapterId = MAX_UINT32; // Host adapter channel, doesn't 
exist
+  Dev->PassThruMode.Attributes =
+    EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL
+    | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
+
+  Dev->PassThru.Mode = &Dev->PassThruMode;
+  Dev->PassThru.PassThru = &MptScsiPassThru;
+  Dev->PassThru.GetNextTargetLun = &MptScsiGetNextTargetLun;
+  Dev->PassThru.BuildDevicePath = &MptScsiBuildDevicePath;
+  Dev->PassThru.GetTargetLun = &MptScsiGetTargetLun;
+  Dev->PassThru.ResetChannel = &MptScsiResetChannel;
+  Dev->PassThru.ResetTargetLun = &MptScsiResetTargetLun;
+  Dev->PassThru.GetNextTarget = &MptScsiGetNextTarget;
+
+  Status = gBS->InstallProtocolInterface (
+                  &ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,
+                  &Dev->PassThru);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  DEBUG ((EFI_D_INFO, "MptScsi Installed\n"));
+Done:
+  if (EFI_ERROR (Status)) {
+    gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Dev, EFI_SIZE_TO_PAGES 
(sizeof (*Dev)));
+  }
+
+  return Status;
 }
 
 STATIC
@@ -108,7 +280,33 @@ MptScsiControllerStop (
   IN  EFI_HANDLE                            *ChildHandleBuffer
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS Status;
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
+  MPT_SCSI_DEV *Dev = NULL;
+
+  DEBUG ((EFI_D_INFO, "Stopping MptScsi\n"));
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid,
+                  (VOID **)&PassThru,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL); // Lookup only
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Dev = MPT_SCSI_FROM_PASS_THRU (PassThru);
+
+  gBS->UninstallProtocolInterface (
+                  ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid,
+                  &Dev->PassThru);
+
+  gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Dev, EFI_SIZE_TO_PAGES 
(sizeof (*Dev)));
+
+  return Status;
 }
 
 // Higher versions will be used before lower, 0x10-0xffffffef is the version
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf 
b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index 3608cecaab..5d424606a5 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -30,10 +30,13 @@
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
+  BaseMemoryLib
   DebugLib
+  MemoryAllocationLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
 
 [Protocols]
-  gEfiPciIoProtocolGuid        ## TO_START
\ No newline at end of file
+  gEfiPciIoProtocolGuid                  ## TO_START
+  gEfiExtScsiPassThruProtocolGuid        ## BY_START
-- 
2.20.1

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

Reply via email to