public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers
@ 2020-04-24 17:59 Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 01/12] OvmfPkg/MptScsiDxe: Create empty driver Nikita Leshenko
                   ` (11 more replies)
  0 siblings, 12 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

This series adds driver support for:
- LSI53C1030
- SAS1068
- SAS1068E

These controllers are widely supported by QEMU, VirtualBox and VMWare.
This work is part of the more general agenda of enhancing OVMF boot
device support to have feature parity with SeaBIOS.

I pushed a copy of these patches to
https://github.com/nikital/edk2/tree/mptscsi_v5
Previous versions:
https://github.com/nikital/edk2/tree/mptscsi_v4
https://github.com/nikital/edk2/tree/mptscsi_v3
https://github.com/nikital/edk2/tree/mptscsi (v2)

v4->v5:
- Sort maintainers and protocols
- Fix bug when restoring PCI attributes (Use Set instead of Enable)
- Separate packed structs and aligned unions
- STATIC_ASSERT for init request size
- Add support for multiple targets from the beginning
- Use PCI_BAR_IDX0 in door bell
- Code convention improvements
- Add DEBUG_VERBOSE message seen in PvScsiExitBoot
- Return EFI_INVALID_PARAMETER in GetNextTarget
- STATIC_ASSERT for MaxTarget
- Move PCD near PvScsi
- A lot of fixes for PassThru (comments, error handling, casting)
- Support 64-bit DMA

v3->v4:
- Add ExitBootServices
- Rework error handling in PassThru
- SPDX license
- Made compilation conditional
- Squash GetTargetLun and BuildDevicePath commits
- Added #include <Uefi/UefiSpec.h>
- Use PCI_BAR_IDX0
- Code convention improvements

v2->v3:
- Change error handling style
- Add comments about target size and zero unused target bytes
- Remove internal Reviewed-by
- Fix problems reported by PatchCheck.py
- Use SetupGit.py

v1->v2:
- Map() DMAed buffers
- Fixed various code convention issues
- Newer debug macros
- Updated INF version

Thanks,
Nikita

Nikita Leshenko (12):
  OvmfPkg/MptScsiDxe: Create empty driver
  OvmfPkg/MptScsiDxe: Install DriverBinding Protocol
  OvmfPkg/MptScsiDxe: Report name of driver
  OvmfPkg/MptScsiDxe: Probe PCI devices and look for MptScsi
  OvmfPkg/MptScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
  OvmfPkg/MptScsiDxe: Report targets and one LUN
  OvmfPkg/MptScsiDxe: Build and decode DevicePath
  OvmfPkg/MptScsiDxe: Open PciIo protocol for later use
  OvmfPkg/MptScsiDxe: Set and restore PCI attributes
  OvmfPkg/MptScsiDxe: Initialize hardware
  OvmfPkg/MptScsiDxe: Implement the PassThru method
  OvmfPkg/MptScsiDxe: Reset device on ExitBootServices()

 Maintainers.txt                               |    3 +-
 .../Include/IndustryStandard/FusionMptScsi.h  |  160 +++
 OvmfPkg/MptScsiDxe/MptScsi.c                  | 1199 +++++++++++++++++
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf             |   42 +
 OvmfPkg/OvmfPkg.dec                           |    7 +
 OvmfPkg/OvmfPkgIa32.dsc                       |    4 +
 OvmfPkg/OvmfPkgIa32.fdf                       |    3 +
 OvmfPkg/OvmfPkgIa32X64.dsc                    |    4 +
 OvmfPkg/OvmfPkgIa32X64.fdf                    |    3 +
 OvmfPkg/OvmfPkgX64.dsc                        |    4 +
 OvmfPkg/OvmfPkgX64.fdf                        |    3 +
 11 files changed, 1431 insertions(+), 1 deletion(-)
 create mode 100644 OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
 create mode 100644 OvmfPkg/MptScsiDxe/MptScsi.c
 create mode 100644 OvmfPkg/MptScsiDxe/MptScsiDxe.inf

-- 
2.20.1


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

* [PATCH v5 01/12] OvmfPkg/MptScsiDxe: Create empty driver
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 02/12] OvmfPkg/MptScsiDxe: Install DriverBinding Protocol Nikita Leshenko
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

In preparation for implementing LSI Fusion MPT SCSI devices, create a
basic scaffolding for a driver.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 Maintainers.txt                   |  3 ++-
 OvmfPkg/MptScsiDxe/MptScsi.c      | 26 ++++++++++++++++++++++++++
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf | 26 ++++++++++++++++++++++++++
 OvmfPkg/OvmfPkgIa32.dsc           |  4 ++++
 OvmfPkg/OvmfPkgIa32.fdf           |  3 +++
 OvmfPkg/OvmfPkgIa32X64.dsc        |  4 ++++
 OvmfPkg/OvmfPkgIa32X64.fdf        |  3 +++
 OvmfPkg/OvmfPkgX64.dsc            |  4 ++++
 OvmfPkg/OvmfPkgX64.fdf            |  3 +++
 9 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 OvmfPkg/MptScsiDxe/MptScsi.c
 create mode 100644 OvmfPkg/MptScsiDxe/MptScsiDxe.inf

diff --git a/Maintainers.txt b/Maintainers.txt
index 1733225722b6..896ac5821fc6 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -435,7 +435,8 @@ OvmfPkg: CSM modules
 F: OvmfPkg/Csm/
 R: David Woodhouse <dwmw2@infradead.org>
 
-OvmfPkg: PVSCSI driver
+OvmfPkg: MptScsi and PVSCSI driver
+F: OvmfPkg/MptScsiDxe/
 F: OvmfPkg/PvScsiDxe/
 R: Liran Alon <liran.alon@oracle.com>
 R: Nikita Leshenko <nikita.leshchenko@oracle.com>
diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
new file mode 100644
index 000000000000..c6c8142dfde6
--- /dev/null
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -0,0 +1,26 @@
+/** @file
+
+  This driver produces Extended SCSI Pass Thru Protocol instances for
+  LSI Fusion MPT SCSI devices.
+
+  Copyright (C) 2020, Oracle and/or its affiliates.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiSpec.h>
+
+//
+// Entry Point
+//
+
+EFI_STATUS
+EFIAPI
+MptScsiEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
new file mode 100644
index 000000000000..b4006a7c2d97
--- /dev/null
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -0,0 +1,26 @@
+## @file
+# This driver produces Extended SCSI Pass Thru Protocol instances for
+# LSI Fusion MPT SCSI devices.
+#
+# Copyright (C) 2020, Oracle and/or its affiliates.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = MptScsiDxe
+  FILE_GUID                      = 2B3DB5DD-B315-4961-8454-0AFF3C811B19
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MptScsiEntryPoint
+
+[Sources]
+  MptScsi.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index cbc5f0e583bc..158a5e9f39bd 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -49,6 +49,7 @@ [Defines]
   # Device drivers
   #
   DEFINE PVSCSI_ENABLE           = TRUE
+  DEFINE MPT_SCSI_ENABLE         = TRUE
 
   #
   # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -744,6 +745,9 @@ [Components]
   OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 !if $(PVSCSI_ENABLE) == TRUE
   OvmfPkg/PvScsiDxe/PvScsiDxe.inf
+!endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 8e43f4264ecc..fd81b6fa8bed 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -233,6 +233,9 @@ [FV.DXEFV]
 !if $(PVSCSI_ENABLE) == TRUE
 INF  OvmfPkg/PvScsiDxe/PvScsiDxe.inf
 !endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 6d69cc6cb56f..a6c5a1d9d050 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -48,6 +48,7 @@ [Defines]
   # Device drivers
   #
   DEFINE PVSCSI_ENABLE           = TRUE
+  DEFINE MPT_SCSI_ENABLE         = TRUE
 
   #
   # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -756,6 +757,9 @@ [Components.X64]
   OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 !if $(PVSCSI_ENABLE) == TRUE
   OvmfPkg/PvScsiDxe/PvScsiDxe.inf
+!endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 25af9fbed48a..f71134a65931 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -234,6 +234,9 @@ [FV.DXEFV]
 !if $(PVSCSI_ENABLE) == TRUE
 INF  OvmfPkg/PvScsiDxe/PvScsiDxe.inf
 !endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 5ad4f461ce52..9aa8dd9e5fe1 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -48,6 +48,7 @@ [Defines]
   # Device drivers
   #
   DEFINE PVSCSI_ENABLE           = TRUE
+  DEFINE MPT_SCSI_ENABLE         = TRUE
 
   #
   # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -754,6 +755,9 @@ [Components]
   OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 !if $(PVSCSI_ENABLE) == TRUE
   OvmfPkg/PvScsiDxe/PvScsiDxe.inf
+!endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 25af9fbed48a..f71134a65931 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -234,6 +234,9 @@ [FV.DXEFV]
 !if $(PVSCSI_ENABLE) == TRUE
 INF  OvmfPkg/PvScsiDxe/PvScsiDxe.inf
 !endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
-- 
2.20.1


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

* [PATCH v5 02/12] OvmfPkg/MptScsiDxe: Install DriverBinding Protocol
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 01/12] OvmfPkg/MptScsiDxe: Create empty driver Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver Nikita Leshenko
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

In order to probe and connect to the MptScsi device we need this
protocol. Currently it does nothing.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c      | 67 ++++++++++++++++++++++++++++++-
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf |  1 +
 2 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index c6c8142dfde6..581d3909b84d 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -9,8 +9,66 @@
 
 **/
 
+#include <Library/UefiLib.h>
 #include <Uefi/UefiSpec.h>
 
+//
+// Higher versions will be used before lower, 0x10-0xffffffef is the version
+// range for IVH (Indie Hardware Vendors)
+//
+#define MPT_SCSI_BINDING_VERSION 0x10
+
+//
+// Driver Binding
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiControllerSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL            *This,
+  IN EFI_HANDLE                             ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL               *RemainingDevicePath OPTIONAL
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiControllerStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL            *This,
+  IN EFI_HANDLE                             ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL               *RemainingDevicePath OPTIONAL
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiControllerStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL            *This,
+  IN  EFI_HANDLE                            ControllerHandle,
+  IN  UINTN                                 NumberOfChildren,
+  IN  EFI_HANDLE                            *ChildHandleBuffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding = {
+  &MptScsiControllerSupported,
+  &MptScsiControllerStart,
+  &MptScsiControllerStop,
+  MPT_SCSI_BINDING_VERSION,
+  NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2
+  NULL, // DriverBindingHandle, filled as well
+};
+
 //
 // Entry Point
 //
@@ -22,5 +80,12 @@ MptScsiEntryPoint (
   IN EFI_SYSTEM_TABLE *SystemTable
   )
 {
-  return EFI_UNSUPPORTED;
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,
+           &mMptScsiDriverBinding,
+           ImageHandle, // The handle to install onto
+           NULL, // TODO Component name
+           NULL // TODO Component name
+           );
 }
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index b4006a7c2d97..53585068684f 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -24,3 +24,4 @@ [Packages]
 
 [LibraryClasses]
   UefiDriverEntryPoint
+  UefiLib
-- 
2.20.1


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

* [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 01/12] OvmfPkg/MptScsiDxe: Create empty driver Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 02/12] OvmfPkg/MptScsiDxe: Install DriverBinding Protocol Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-24 18:02   ` [edk2-devel] " Carsey, Jaben
  2020-04-24 17:59 ` [PATCH v5 04/12] OvmfPkg/MptScsiDxe: Probe PCI devices and look for MptScsi Nikita Leshenko
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel, Jaben Carsey

Install Component Name protocols to have a nice display name for the
driver in places such as UEFI shell.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c | 61 ++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 581d3909b84d..64949a809022 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -69,6 +69,63 @@ EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding = {
   NULL, // DriverBindingHandle, filled as well
 };
 
+//
+// Component Name
+//
+
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+  { "eng;en", L"LSI Fusion MPT SCSI Driver" },
+  { NULL,     NULL                   }
+};
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL mComponentName;
+
+EFI_STATUS
+EFIAPI
+MptScsiGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &mComponentName) // Iso639Language
+           );
+}
+
+EFI_STATUS
+EFIAPI
+MptScsiGetDeviceName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  EFI_HANDLE                  DeviceHandle,
+  IN  EFI_HANDLE                  ChildHandle,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
+  &MptScsiGetDriverName,
+  &MptScsiGetDeviceName,
+  "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+STATIC
+EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &MptScsiGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &MptScsiGetDeviceName,
+  "en" // SupportedLanguages, RFC 4646 language codes
+};
+
 //
 // Entry Point
 //
@@ -85,7 +142,7 @@ MptScsiEntryPoint (
            SystemTable,
            &mMptScsiDriverBinding,
            ImageHandle, // The handle to install onto
-           NULL, // TODO Component name
-           NULL // TODO Component name
+           &mComponentName,
+           &mComponentName2
            );
 }
-- 
2.20.1


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

* [PATCH v5 04/12] OvmfPkg/MptScsiDxe: Probe PCI devices and look for MptScsi
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (2 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 05/12] OvmfPkg/MptScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Nikita Leshenko
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

The MptScsiControllerSupported function is called on handles passed in
by the ConnectController() boot service and if the handle is the
lsi53c1030 controller the function would return success. A successful
return value will attach our driver to the device.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
---
 .../Include/IndustryStandard/FusionMptScsi.h  | 23 +++++++++
 OvmfPkg/MptScsiDxe/MptScsi.c                  | 49 ++++++++++++++++++-
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf             |  5 ++
 3 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100644 OvmfPkg/Include/IndustryStandard/FusionMptScsi.h

diff --git a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
new file mode 100644
index 000000000000..df9bdc2f0348
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
@@ -0,0 +1,23 @@
+/** @file
+
+  Macros and type definitions for LSI Fusion MPT SCSI devices.
+
+  Copyright (C) 2020, Oracle and/or its affiliates.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FUSION_MPT_SCSI_H__
+#define __FUSION_MPT_SCSI_H__
+
+//
+// Device offsets and constants
+//
+
+#define LSI_LOGIC_PCI_VENDOR_ID 0x1000
+#define LSI_53C1030_PCI_DEVICE_ID 0x0030
+#define LSI_SAS1068_PCI_DEVICE_ID 0x0054
+#define LSI_SAS1068E_PCI_DEVICE_ID 0x0058
+
+#endif // __FUSION_MPT_SCSI_H__
diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 64949a809022..4e2f8f2296fb 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -9,7 +9,11 @@
 
 **/
 
+#include <IndustryStandard/FusionMptScsi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
+#include <Protocol/PciIo.h>
 #include <Uefi/UefiSpec.h>
 
 //
@@ -31,7 +35,50 @@ MptScsiControllerSupported (
   IN EFI_DEVICE_PATH_PROTOCOL               *RemainingDevicePath OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS          Status;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  PCI_TYPE00          Pci;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **)&PciIo,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint32,
+                        0,
+                        sizeof (Pci) / sizeof (UINT32),
+                        &Pci
+                        );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
+      (Pci.Hdr.DeviceId == LSI_53C1030_PCI_DEVICE_ID ||
+       Pci.Hdr.DeviceId == LSI_SAS1068_PCI_DEVICE_ID ||
+       Pci.Hdr.DeviceId == LSI_SAS1068E_PCI_DEVICE_ID)) {
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_UNSUPPORTED;
+  }
+
+Done:
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+  return Status;
 }
 
 STATIC
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index 53585068684f..414b96e5a248 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -21,7 +21,12 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
+  UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
+
+[Protocols]
+  gEfiPciIoProtocolGuid        ## TO_START
-- 
2.20.1


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

* [PATCH v5 05/12] OvmfPkg/MptScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (3 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 04/12] OvmfPkg/MptScsiDxe: Probe PCI devices and look for MptScsi Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN Nikita Leshenko
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

Support dynamic insertion and removal of the protocol

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c      | 181 +++++++++++++++++++++++++++++-
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf |   5 +-
 2 files changed, 183 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 4e2f8f2296fb..40d392c2346f 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -11,9 +11,12 @@
 
 #include <IndustryStandard/FusionMptScsi.h>
 #include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Protocol/PciIo.h>
+#include <Protocol/ScsiPassThruExt.h>
 #include <Uefi/UefiSpec.h>
 
 //
@@ -22,6 +25,109 @@
 //
 #define MPT_SCSI_BINDING_VERSION 0x10
 
+//
+// 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
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiGetNextTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
+  IN OUT UINT8                                      **Target,
+  IN OUT UINT64                                     *Lun
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiGetNextTarget (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This,
+  IN OUT UINT8                                     **Target
+  )
+{
+  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
+  )
+{
+  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
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiResetChannel (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+MptScsiResetTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL               *This,
+  IN UINT8                                         *Target,
+  IN UINT64                                        Lun
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
 //
 // Driver Binding
 //
@@ -90,7 +196,49 @@ MptScsiControllerStart (
   IN EFI_DEVICE_PATH_PROTOCOL               *RemainingDevicePath OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS           Status;
+  MPT_SCSI_DEV         *Dev;
+
+  Dev = AllocateZeroPool (sizeof (*Dev));
+  if (Dev == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
+
+  //
+  // Host adapter channel, doesn't exist
+  //
+  Dev->PassThruMode.AdapterId = MAX_UINT32;
+  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 FreePool;
+  }
+
+  return EFI_SUCCESS;
+
+FreePool:
+  FreePool (Dev);
+
+  return Status;
 }
 
 STATIC
@@ -103,7 +251,36 @@ MptScsiControllerStop (
   IN  EFI_HANDLE                            *ChildHandleBuffer
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS                      Status;
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
+  MPT_SCSI_DEV                    *Dev;
+
+  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);
+
+  Status = gBS->UninstallProtocolInterface (
+                  ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid,
+                  &Dev->PassThru
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  FreePool (Dev);
+
+  return Status;
 }
 
 STATIC
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index 414b96e5a248..9f7c98829ee1 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -24,9 +24,12 @@ [Packages]
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
+  DebugLib
+  MemoryAllocationLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
 
 [Protocols]
-  gEfiPciIoProtocolGuid        ## TO_START
+  gEfiExtScsiPassThruProtocolGuid        ## BY_START
+  gEfiPciIoProtocolGuid                  ## TO_START
-- 
2.20.1


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

* [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (4 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 05/12] OvmfPkg/MptScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-29 13:38   ` [edk2-devel] " Laszlo Ersek
  2020-04-24 17:59 ` [PATCH v5 07/12] OvmfPkg/MptScsiDxe: Build and decode DevicePath Nikita Leshenko
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

The controller supports up to 8 targets in practice (Not reported by the
controller, but based on the implementation of the virtual device),
report them in GetNextTarget and GetNextTargetLun. The firmware will
then try to communicate with them and create a block device for each one
that responds.

Support for multiple LUNs will be implemented in another series.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c      | 62 ++++++++++++++++++++++++++++++-
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf |  4 ++
 OvmfPkg/OvmfPkg.dec               |  4 ++
 3 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 40d392c2346f..5e0544c8d9d2 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -11,6 +11,7 @@
 
 #include <IndustryStandard/FusionMptScsi.h>
 #include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
@@ -34,6 +35,7 @@ typedef struct {
   UINT32                          Signature;
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
+  UINT8                           MaxTarget;
 } MPT_SCSI_DEV;
 
 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
@@ -57,6 +59,22 @@ MptScsiPassThru (
   return EFI_UNSUPPORTED;
 }
 
+STATIC
+BOOLEAN
+IsTargetInitialized (
+  IN UINT8                                          *Target
+  )
+{
+  UINTN Idx;
+
+  for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
+    if (Target[Idx] != 0xFF) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
 STATIC
 EFI_STATUS
 EFIAPI
@@ -66,7 +84,28 @@ MptScsiGetNextTargetLun (
   IN OUT UINT64                                     *Lun
   )
 {
-  return EFI_UNSUPPORTED;
+  MPT_SCSI_DEV *Dev;
+
+  Dev = MPT_SCSI_FROM_PASS_THRU (This);
+  //
+  // Currently support only LUN 0, so hardcode it
+  //
+  if (!IsTargetInitialized (*Target)) {
+    ZeroMem (*Target, TARGET_MAX_BYTES);
+    *Lun = 0;
+  } else if (**Target > Dev->MaxTarget || *Lun > 0) {
+    return EFI_INVALID_PARAMETER;
+  } else if (**Target < Dev->MaxTarget) {
+    //
+    // This device interface support 256 targets only, so it's enough to
+    // increment the LSB of Target, as it will never overflow.
+    //
+    **Target += 1;
+  } else {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
 }
 
 STATIC
@@ -77,7 +116,24 @@ MptScsiGetNextTarget (
   IN OUT UINT8                                     **Target
   )
 {
-  return EFI_UNSUPPORTED;
+  MPT_SCSI_DEV *Dev;
+
+  Dev = MPT_SCSI_FROM_PASS_THRU (This);
+  if (!IsTargetInitialized (*Target)) {
+    ZeroMem (*Target, TARGET_MAX_BYTES);
+  } else if (**Target > Dev->MaxTarget) {
+    return EFI_INVALID_PARAMETER;
+  } else if (**Target < Dev->MaxTarget) {
+    //
+    // This device interface support 256 targets only, so it's enough to
+    // increment the LSB of Target, as it will never overflow.
+    //
+    **Target += 1;
+  } else {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
 }
 
 STATIC
@@ -206,6 +262,8 @@ MptScsiControllerStart (
 
   Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
 
+  Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
+
   //
   // Host adapter channel, doesn't exist
   //
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index 9f7c98829ee1..4862ff9dd497 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -24,6 +24,7 @@ [Packages]
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
+  BaseMemoryLib
   DebugLib
   MemoryAllocationLib
   UefiBootServicesTableLib
@@ -33,3 +34,6 @@ [LibraryClasses]
 [Protocols]
   gEfiExtScsiPassThruProtocolGuid        ## BY_START
   gEfiPciIoProtocolGuid                  ## TO_START
+
+[FixedPcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 28030391cff2..2d09444bbb16 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -163,6 +163,10 @@ [PcdsFixedAtBuild]
   #  polling loop iteration.
   gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiWaitForCmpStallInUsecs|5|UINT32|0x38
 
+  ## Set the *inclusive* number of targets that MptScsi exposes for scan
+  #  by ScsiBusDxe.
+  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
+
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
-- 
2.20.1


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

* [PATCH v5 07/12] OvmfPkg/MptScsiDxe: Build and decode DevicePath
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (5 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-29 13:44   ` [edk2-devel] " Laszlo Ersek
  2020-04-24 17:59 ` [PATCH v5 08/12] OvmfPkg/MptScsiDxe: Open PciIo protocol for later use Nikita Leshenko
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

Used to identify the individual disks in the hardware tree.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c | 61 ++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 5e0544c8d9d2..dc4b854659f9 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -146,7 +146,36 @@ MptScsiBuildDevicePath (
   IN OUT EFI_DEVICE_PATH_PROTOCOL                  **DevicePath
   )
 {
-  return EFI_UNSUPPORTED;
+  MPT_SCSI_DEV     *Dev;
+  SCSI_DEVICE_PATH *ScsiDevicePath;
+
+  if (DevicePath == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // This device support 256 targets only, so it's enough to dereference
+  // the LSB of Target.
+  //
+  Dev = MPT_SCSI_FROM_PASS_THRU (This);
+  if (*Target > Dev->MaxTarget || Lun > 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  ScsiDevicePath = AllocateZeroPool (sizeof (*ScsiDevicePath));
+  if (ScsiDevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ScsiDevicePath->Header.Type      = MESSAGING_DEVICE_PATH;
+  ScsiDevicePath->Header.SubType   = MSG_SCSI_DP;
+  ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);
+  ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);
+  ScsiDevicePath->Pun              = *Target;
+  ScsiDevicePath->Lun              = (UINT16)Lun;
+
+  *DevicePath = &ScsiDevicePath->Header;
+  return EFI_SUCCESS;
 }
 
 STATIC
@@ -159,7 +188,35 @@ MptScsiGetTargetLun (
   OUT UINT64                                       *Lun
   )
 {
-  return EFI_UNSUPPORTED;
+  MPT_SCSI_DEV     *Dev;
+  SCSI_DEVICE_PATH *ScsiDevicePath;
+
+  if (DevicePath == NULL ||
+      Target == NULL || *Target == NULL || Lun == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (DevicePath->Type    != MESSAGING_DEVICE_PATH ||
+      DevicePath->SubType != MSG_SCSI_DP) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Dev = MPT_SCSI_FROM_PASS_THRU (This);
+  ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;
+  if (ScsiDevicePath->Pun > Dev->MaxTarget ||
+      ScsiDevicePath->Lun > 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  ZeroMem (*Target, TARGET_MAX_BYTES);
+  //
+  // This device support 256 targets only, so it's enough to set the LSB
+  // of Target.
+  //
+  **Target = (UINT8)ScsiDevicePath->Pun;
+  *Lun = ScsiDevicePath->Lun;
+
+  return EFI_SUCCESS;
 }
 
 STATIC
-- 
2.20.1


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

* [PATCH v5 08/12] OvmfPkg/MptScsiDxe: Open PciIo protocol for later use
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (6 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 07/12] OvmfPkg/MptScsiDxe: Build and decode DevicePath Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 09/12] OvmfPkg/MptScsiDxe: Set and restore PCI attributes Nikita Leshenko
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

This will give us an exclusive access to the PciIo of this device
after it was started and until is will be stopped.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index dc4b854659f9..ed7fabf8b471 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -36,6 +36,7 @@ typedef struct {
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
   UINT8                           MaxTarget;
+  EFI_PCI_IO_PROTOCOL             *PciIo;
 } MPT_SCSI_DEV;
 
 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
@@ -321,6 +322,18 @@ MptScsiControllerStart (
 
   Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
 
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **)&Dev->PciIo,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FreePool;
+  }
+
   //
   // Host adapter channel, doesn't exist
   //
@@ -345,11 +358,19 @@ MptScsiControllerStart (
                   &Dev->PassThru
                   );
   if (EFI_ERROR (Status)) {
-    goto FreePool;
+    goto CloseProtocol;
   }
 
   return EFI_SUCCESS;
 
+CloseProtocol:
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+
 FreePool:
   FreePool (Dev);
 
@@ -393,6 +414,13 @@ MptScsiControllerStop (
     return Status;
   }
 
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+
   FreePool (Dev);
 
   return Status;
-- 
2.20.1


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

* [PATCH v5 09/12] OvmfPkg/MptScsiDxe: Set and restore PCI attributes
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (7 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 08/12] OvmfPkg/MptScsiDxe: Open PciIo protocol for later use Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-29 13:50   ` [edk2-devel] " Laszlo Ersek
  2020-04-24 17:59 ` [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware Nikita Leshenko
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

Enable the IO Space and Bus Mastering and restore the original values
when the device is stopped. This is a standard procedure in PCI
drivers.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c | 65 +++++++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index ed7fabf8b471..e88ac2867a75 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -37,6 +37,7 @@ typedef struct {
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
   UINT8                           MaxTarget;
   EFI_PCI_IO_PROTOCOL             *PciIo;
+  UINT64                          OriginalPciAttributes;
 } MPT_SCSI_DEV;
 
 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
@@ -334,6 +335,53 @@ MptScsiControllerStart (
     goto FreePool;
   }
 
+  Status = Dev->PciIo->Attributes (
+                         Dev->PciIo,
+                         EfiPciIoAttributeOperationGet,
+                         0,
+                         &Dev->OriginalPciAttributes
+                         );
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocol;
+  }
+
+  //
+  // Enable I/O Space & Bus-Mastering
+  //
+  Status = Dev->PciIo->Attributes (
+                         Dev->PciIo,
+                         EfiPciIoAttributeOperationEnable,
+                         (EFI_PCI_IO_ATTRIBUTE_IO |
+                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+                         NULL
+                         );
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocol;
+  }
+
+  //
+  // Signal device supports 64-bit DMA addresses
+  //
+  Status = Dev->PciIo->Attributes (
+                         Dev->PciIo,
+                         EfiPciIoAttributeOperationEnable,
+                         EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
+                         NULL
+                         );
+  if (EFI_ERROR (Status)) {
+    //
+    // Warn user that device will only be using 32-bit DMA addresses.
+    //
+    // Note that this does not prevent the device/driver from working
+    // and therefore we only warn and continue as usual.
+    //
+    DEBUG ((
+      DEBUG_WARN,
+      "%a: failed to enable 64-bit DMA addresses\n",
+      __FUNCTION__
+      ));
+  }
+
   //
   // Host adapter channel, doesn't exist
   //
@@ -358,11 +406,19 @@ MptScsiControllerStart (
                   &Dev->PassThru
                   );
   if (EFI_ERROR (Status)) {
-    goto CloseProtocol;
+    goto RestoreAttributes;
   }
 
   return EFI_SUCCESS;
 
+RestoreAttributes:
+  Dev->PciIo->Attributes (
+                Dev->PciIo,
+                EfiPciIoAttributeOperationSet,
+                Dev->OriginalPciAttributes,
+                NULL
+                );
+
 CloseProtocol:
   gBS->CloseProtocol (
          ControllerHandle,
@@ -414,6 +470,13 @@ MptScsiControllerStop (
     return Status;
   }
 
+  Dev->PciIo->Attributes (
+                Dev->PciIo,
+                EfiPciIoAttributeOperationSet,
+                Dev->OriginalPciAttributes,
+                NULL
+                );
+
   gBS->CloseProtocol (
          ControllerHandle,
          &gEfiPciIoProtocolGuid,
-- 
2.20.1


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

* [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (8 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 09/12] OvmfPkg/MptScsiDxe: Set and restore PCI attributes Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-29 14:55   ` [edk2-devel] " Laszlo Ersek
  2020-04-24 17:59 ` [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method Nikita Leshenko
  2020-04-24 17:59 ` [PATCH v5 12/12] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices() Nikita Leshenko
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

Reset and send the IO controller initialization request. The reply is
read back to complete the doorbell function but it isn't useful to us
because it doesn't contain relevant data or status codes.

See "LSI53C1030 PCI-X to Dual Channel Ultra320 SCSI Multifunction
Controller" technical manual for more information.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
---
 .../Include/IndustryStandard/FusionMptScsi.h  | 128 ++++++++++++
 OvmfPkg/MptScsiDxe/MptScsi.c                  | 187 +++++++++++++++++-
 2 files changed, 314 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
index df9bdc2f0348..655d629d902e 100644
--- a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
@@ -20,4 +20,132 @@
 #define LSI_SAS1068_PCI_DEVICE_ID 0x0054
 #define LSI_SAS1068E_PCI_DEVICE_ID 0x0058
 
+#define MPT_REG_DOORBELL  0x00
+#define MPT_REG_WRITE_SEQ 0x04
+#define MPT_REG_HOST_DIAG 0x08
+#define MPT_REG_TEST      0x0c
+#define MPT_REG_DIAG_DATA 0x10
+#define MPT_REG_DIAG_ADDR 0x14
+#define MPT_REG_ISTATUS   0x30
+#define MPT_REG_IMASK     0x34
+#define MPT_REG_REQ_Q     0x40
+#define MPT_REG_REP_Q     0x44
+
+#define MPT_DOORBELL_RESET     0x40
+#define MPT_DOORBELL_HANDSHAKE 0x42
+
+#define MPT_IMASK_DOORBELL 0x01
+#define MPT_IMASK_REPLY    0x08
+
+#define MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST 0x00
+#define MPT_MESSAGE_HDR_FUNCTION_IOC_INIT        0x02
+
+#define MPT_SG_ENTRY_TYPE_SIMPLE 0x01
+
+#define MPT_IOC_WHOINIT_ROM_BIOS 0x02
+
+//
+// Device structures
+//
+
+#pragma pack (1)
+typedef struct {
+  UINT8     WhoInit;
+  UINT8     Reserved1;
+  UINT8     ChainOffset;
+  UINT8     Function;
+  UINT8     Flags;
+  UINT8     MaxDevices;
+  UINT8     MaxBuses;
+  UINT8     MessageFlags;
+  UINT32    MessageContext;
+  UINT16    ReplyFrameSize;
+  UINT16    Reserved2;
+  UINT32    HostMfaHighAddr;
+  UINT32    SenseBufferHighAddr;
+} MPT_IO_CONTROLLER_INIT_REQUEST;
+
+typedef struct {
+  UINT8     WhoInit;
+  UINT8     Reserved1;
+  UINT8     MessageLength;
+  UINT8     Function;
+  UINT8     Flags;
+  UINT8     MaxDevices;
+  UINT8     MaxBuses;
+  UINT8     MessageFlags;
+  UINT32    MessageContext;
+  UINT16    Reserved2;
+  UINT16    IocStatus;
+  UINT32    IocLogInfo;
+} MPT_IO_CONTROLLER_INIT_REPLY;
+
+typedef struct {
+  UINT8     TargetId;
+  UINT8     Bus;
+  UINT8     ChainOffset;
+  UINT8     Function;
+  UINT8     CdbLength;
+  UINT8     SenseBufferLength;
+  UINT8     Reserved;
+  UINT8     MessageFlags;
+  UINT32    MessageContext;
+  UINT8     Lun[8];
+  UINT32    Control;
+  UINT8     Cdb[16];
+  UINT32    DataLength;
+  UINT32    SenseBufferLowAddress;
+} MPT_SCSI_IO_REQUEST;
+
+typedef struct {
+  UINT32    Length:             24;
+  UINT32    EndOfList:          1;
+  UINT32    Is64BitAddress:     1;
+  //
+  // True when the buffer contains data to be transfered. Otherwise it's the
+  // destination buffer
+  //
+  UINT32    BufferContainsData: 1;
+  UINT32    LocalAddress:       1;
+  UINT32    ElementType:        2;
+  UINT32    EndOfBuffer:        1;
+  UINT32    LastElement:        1;
+  UINT64    DataBufferAddress;
+} MPT_SG_ENTRY_SIMPLE;
+
+typedef struct {
+  UINT8     TargetId;
+  UINT8     Bus;
+  UINT8     MessageLength;
+  UINT8     Function;
+  UINT8     CdbLength;
+  UINT8     SenseBufferLength;
+  UINT8     Reserved;
+  UINT8     MessageFlags;
+  UINT32    MessageContext;
+  UINT8     ScsiStatus;
+  UINT8     ScsiState;
+  UINT16    IocStatus;
+  UINT32    IocLogInfo;
+  UINT32    TransferCount;
+  UINT32    SenseCount;
+  UINT32    ResponseInfo;
+} MPT_SCSI_IO_REPLY;
+
+typedef struct {
+  MPT_SCSI_IO_REQUEST Header;
+  MPT_SG_ENTRY_SIMPLE Sg;
+} MPT_SCSI_REQUEST_WITH_SG;
+#pragma pack ()
+
+typedef union {
+  MPT_SCSI_IO_REPLY        Data;
+  UINT64                   Uint64; // 8 byte alignment required by HW
+} MPT_SCSI_IO_REPLY_ALIGNED;
+
+typedef union {
+  MPT_SCSI_REQUEST_WITH_SG Data;
+  UINT64                   Uint64; // 8 byte alignment required by HW
+} MPT_SCSI_REQUEST_ALIGNED;
+
 #endif // __FUSION_MPT_SCSI_H__
diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index e88ac2867a75..15d671b544c2 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -43,6 +43,181 @@ typedef struct {
 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
   CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
 
+//
+// Hardware functions
+//
+
+STATIC
+EFI_STATUS
+Out32 (
+  IN MPT_SCSI_DEV       *Dev,
+  IN UINT32             Addr,
+  IN UINT32             Data
+  )
+{
+  return Dev->PciIo->Io.Write (
+                          Dev->PciIo,
+                          EfiPciIoWidthUint32,
+                          PCI_BAR_IDX0,
+                          Addr,
+                          1,
+                          &Data
+                          );
+}
+
+STATIC
+EFI_STATUS
+In32 (
+  IN  MPT_SCSI_DEV       *Dev,
+  IN  UINT32             Addr,
+  OUT UINT32             *Data
+  )
+{
+  return Dev->PciIo->Io.Read (
+                          Dev->PciIo,
+                          EfiPciIoWidthUint32,
+                          PCI_BAR_IDX0,
+                          Addr,
+                          1,
+                          Data
+                          );
+}
+
+STATIC
+EFI_STATUS
+MptDoorbell (
+  IN MPT_SCSI_DEV       *Dev,
+  IN UINT8              DoorbellFunc,
+  IN UINT8              DoorbellArg
+  )
+{
+  return Out32 (
+           Dev,
+           MPT_REG_DOORBELL,
+           (((UINT32)DoorbellFunc) << 24) | (DoorbellArg << 16)
+           );
+}
+
+STATIC
+EFI_STATUS
+MptScsiReset (
+  IN MPT_SCSI_DEV       *Dev
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Reset hardware
+  //
+  Status = MptDoorbell (Dev, MPT_DOORBELL_RESET, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Mask interrupts
+  //
+  Status = Out32 (Dev, MPT_REG_IMASK, MPT_IMASK_DOORBELL | MPT_IMASK_REPLY);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Clear interrupt status
+  //
+  Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiInit (
+  IN MPT_SCSI_DEV       *Dev
+  )
+{
+  EFI_STATUS                     Status;
+  MPT_IO_CONTROLLER_INIT_REQUEST Req;
+  MPT_IO_CONTROLLER_INIT_REPLY   Reply;
+  UINT8                          *ReplyBytes;
+  UINT32                         ReplyWord;
+
+  Status = MptScsiReset (Dev);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ZeroMem (&Req, sizeof (Req));
+  ZeroMem (&Reply, sizeof (Reply));
+  Req.WhoInit = MPT_IOC_WHOINIT_ROM_BIOS;
+  Req.Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;
+  STATIC_ASSERT(
+    FixedPcdGet8 (PcdMptScsiMaxTargetLimit) < 255,
+    "Req supports 255 targets only (max target is 254)");
+  Req.MaxDevices = Dev->MaxTarget + 1;
+  Req.MaxBuses = 1;
+
+  //
+  // Send controller init through doorbell
+  //
+  STATIC_ASSERT (
+    sizeof (Req) % sizeof (UINT32) == 0,
+    "Req must be multiple of UINT32"
+    );
+  STATIC_ASSERT (
+    sizeof (Req) / sizeof (UINT32) <= MAX_UINT8,
+    "Req must bit in MAX_UINT8 Dwords"
+    );
+  Status = MptDoorbell (
+             Dev,
+             MPT_DOORBELL_HANDSHAKE,
+             (UINT8)(sizeof (Req) / sizeof (UINT32))
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  Status = Dev->PciIo->Io.Write (
+                            Dev->PciIo,
+                            EfiPciIoWidthFifoUint32,
+                            PCI_BAR_IDX0,
+                            MPT_REG_DOORBELL,
+                            sizeof (Req) / sizeof (UINT32),
+                            &Req
+                            );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Read reply through doorbell
+  // Each 32bit (Dword) read produces 16bit (Word) of data
+  //
+  // The reply is read back to complete the doorbell function but it
+  // isn't useful because it doesn't contain relevant data or status
+  // codes.
+  //
+  ReplyBytes = (UINT8 *)&Reply;
+  while (ReplyBytes != (UINT8 *)(&Reply + 1)) {
+    Status = In32 (Dev, MPT_REG_DOORBELL, &ReplyWord);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    CopyMem (ReplyBytes, &ReplyWord, sizeof (UINT16));
+    ReplyBytes += sizeof (UINT16);
+  }
+
+  //
+  // Clear interrupts generated by doorbell reply
+  //
+  Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
 //
 // Ext SCSI Pass Thru
 //
@@ -382,6 +557,11 @@ MptScsiControllerStart (
       ));
   }
 
+  Status = MptScsiInit (Dev);
+  if (EFI_ERROR (Status)) {
+    goto RestoreAttributes;
+  }
+
   //
   // Host adapter channel, doesn't exist
   //
@@ -406,11 +586,14 @@ MptScsiControllerStart (
                   &Dev->PassThru
                   );
   if (EFI_ERROR (Status)) {
-    goto RestoreAttributes;
+    goto UninitDev;
   }
 
   return EFI_SUCCESS;
 
+UninitDev:
+  MptScsiReset (Dev);
+
 RestoreAttributes:
   Dev->PciIo->Attributes (
                 Dev->PciIo,
@@ -470,6 +653,8 @@ MptScsiControllerStop (
     return Status;
   }
 
+  MptScsiReset (Dev);
+
   Dev->PciIo->Attributes (
                 Dev->PciIo,
                 EfiPciIoAttributeOperationSet,
-- 
2.20.1


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

* [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (9 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-30  9:47   ` [edk2-devel] " Laszlo Ersek
  2020-04-24 17:59 ` [PATCH v5 12/12] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices() Nikita Leshenko
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

Machines should be able to boot after this commit. Tested with different
Linux distributions (Ubuntu, CentOS) and different Windows
versions (Windows 7, Windows 10, Server 2016).

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
---
 .../Include/IndustryStandard/FusionMptScsi.h  |   9 +
 OvmfPkg/MptScsiDxe/MptScsi.c                  | 409 +++++++++++++++++-
 OvmfPkg/MptScsiDxe/MptScsiDxe.inf             |   3 +
 OvmfPkg/OvmfPkg.dec                           |   3 +
 4 files changed, 422 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
index 655d629d902e..99778d1537da 100644
--- a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
@@ -44,6 +44,15 @@
 
 #define MPT_IOC_WHOINIT_ROM_BIOS 0x02
 
+#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE  (0x00 << 24)
+#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE (0x01 << 24)
+#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ  (0x02 << 24)
+
+#define MPT_SCSI_IOCSTATUS_SUCCESS          0x0000
+#define MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE 0x0043
+#define MPT_SCSI_IOCSTATUS_DATA_OVERRUN     0x0044
+#define MPT_SCSI_IOCSTATUS_DATA_UNDERRUN    0x0045
+
 //
 // Device structures
 //
diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 15d671b544c2..9cb5088bfbf9 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -17,6 +17,7 @@
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
 #include <Protocol/ScsiPassThruExt.h>
 #include <Uefi/UefiSpec.h>
 
@@ -30,19 +31,50 @@
 // Runtime Structures
 //
 
+typedef struct {
+  MPT_SCSI_REQUEST_ALIGNED        IoRequest;
+  MPT_SCSI_IO_REPLY_ALIGNED       IoReply;
+  //
+  // As EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.SenseDataLength is defined
+  // as UINT8, defining here SenseData size to MAX_UINT8 will guarantee it
+  // cannot overflow when passed to device.
+  //
+  UINT8                           Sense[MAX_UINT8];
+  //
+  // This size of the data is arbitrarily chosen.
+  // It seems to be sufficient for all I/O requests sent through
+  // EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() for common boot scenarios.
+  //
+  UINT8                           Data[0x2000];
+} MPT_SCSI_DMA_BUFFER;
+
 #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;
   UINT8                           MaxTarget;
+  UINT32                          StallPerPollUsec;
   EFI_PCI_IO_PROTOCOL             *PciIo;
   UINT64                          OriginalPciAttributes;
+  MPT_SCSI_DMA_BUFFER             *Dma;
+  EFI_PHYSICAL_ADDRESS            DmaPhysical;
+  VOID                            *DmaMapping;
+  BOOLEAN                         IoReplyEnqueued;
 } MPT_SCSI_DEV;
 
 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
   CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
 
+#define MPT_SCSI_DMA_ADDR(Dev, MemberName) \
+  (Dev->DmaPhysical + OFFSET_OF (MPT_SCSI_DMA_BUFFER, MemberName))
+
+#define MPT_SCSI_DMA_ADDR_HIGH(Dev, MemberName) \
+  ((UINT32)(MPT_SCSI_DMA_ADDR (Dev, MemberName) >> 32))
+
+#define MPT_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
+  ((UINT32)MPT_SCSI_DMA_ADDR (Dev, MemberName))
+
 //
 // Hardware functions
 //
@@ -157,6 +189,9 @@ MptScsiInit (
     "Req supports 255 targets only (max target is 254)");
   Req.MaxDevices = Dev->MaxTarget + 1;
   Req.MaxBuses = 1;
+  Req.ReplyFrameSize = sizeof Dev->Dma->IoReply.Data;
+  Req.HostMfaHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, IoRequest);
+  Req.SenseBufferHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, Sense);
 
   //
   // Send controller init through doorbell
@@ -218,6 +253,289 @@ MptScsiInit (
   return EFI_SUCCESS;
 }
 
+STATIC
+EFI_STATUS
+ReportHostAdapterError (
+  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  DEBUG ((DEBUG_ERROR, "%a: fatal error in scsi request\n", __FUNCTION__));
+  Packet->InTransferLength  = 0;
+  Packet->OutTransferLength = 0;
+  Packet->SenseDataLength   = 0;
+  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+  Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
+  return EFI_DEVICE_ERROR;
+}
+
+STATIC
+EFI_STATUS
+ReportHostAdapterOverrunError (
+  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  Packet->SenseDataLength = 0;
+  Packet->HostAdapterStatus =
+            EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+  Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+  return EFI_BAD_BUFFER_SIZE;
+}
+
+STATIC
+EFI_STATUS
+MptScsiPopulateRequest (
+  IN MPT_SCSI_DEV                                   *Dev,
+  IN UINT8                                          Target,
+  IN UINT64                                         Lun,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  MPT_SCSI_REQUEST_WITH_SG *Request;
+
+  Request = &Dev->Dma->IoRequest.Data;
+
+  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+      (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
+      Packet->CdbLength > sizeof (Request->Header.Cdb)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (Target > Dev->MaxTarget || Lun > 0 ||
+      Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+      //
+      // Trying to receive, but destination pointer is NULL, or contradicting
+      // transfer direction
+      //
+      (Packet->InTransferLength > 0 &&
+       (Packet->InDataBuffer == NULL ||
+        Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE
+         )
+        ) ||
+
+      //
+      // Trying to send, but source pointer is NULL, or contradicting transfer
+      // direction
+      //
+      (Packet->OutTransferLength > 0 &&
+       (Packet->OutDataBuffer == NULL ||
+        Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ
+         )
+        )
+    ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Packet->InTransferLength > sizeof (Dev->Dma->Data)) {
+    Packet->InTransferLength = sizeof (Dev->Dma->Data);
+    return ReportHostAdapterOverrunError (Packet);
+  }
+  if (Packet->OutTransferLength > sizeof (Dev->Dma->Data)) {
+    Packet->OutTransferLength = sizeof (Dev->Dma->Data);
+    return ReportHostAdapterOverrunError (Packet);
+  }
+
+  ZeroMem (Request, sizeof (*Request));
+  Request->Header.TargetId = Target;
+  //
+  // Only LUN 0 is currently supported, hence the cast is safe
+  //
+  Request->Header.Lun[1] = (UINT8)Lun;
+  Request->Header.Function = MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST;
+  Request->Header.MessageContext = 1; // We handle one request at a time
+
+  Request->Header.CdbLength = Packet->CdbLength;
+  CopyMem (Request->Header.Cdb, Packet->Cdb, Packet->CdbLength);
+
+  //
+  // SenseDataLength is UINT8, Sense[] is MAX_UINT8, so we can't overflow
+  //
+  ZeroMem (Dev->Dma->Sense, Packet->SenseDataLength);
+  Request->Header.SenseBufferLength = Packet->SenseDataLength;
+  Request->Header.SenseBufferLowAddress = MPT_SCSI_DMA_ADDR_LOW (Dev, Sense);
+
+  Request->Sg.EndOfList = 1;
+  Request->Sg.EndOfBuffer = 1;
+  Request->Sg.LastElement = 1;
+  Request->Sg.ElementType = MPT_SG_ENTRY_TYPE_SIMPLE;
+  Request->Sg.Is64BitAddress = 1;
+  Request->Sg.DataBufferAddress = MPT_SCSI_DMA_ADDR (Dev, Data);
+
+  //
+  // "MPT_SG_ENTRY_SIMPLE.Length" is a 24-bit quantity.
+  //
+  STATIC_ASSERT (
+    sizeof (Dev->Dma->Data) < SIZE_16MB,
+    "MPT_SCSI_DMA_BUFFER.Data must be smaller than 16MB"
+    );
+
+  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+    Request->Header.DataLength = Packet->InTransferLength;
+    Request->Sg.Length = Packet->InTransferLength;
+    Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ;
+  } else {
+    Request->Header.DataLength = Packet->OutTransferLength;
+    Request->Sg.Length = Packet->OutTransferLength;
+    Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE;
+
+    CopyMem (Dev->Dma->Data, Packet->OutDataBuffer, Packet->OutTransferLength);
+    Request->Sg.BufferContainsData = 1;
+  }
+
+  if (Request->Header.DataLength == 0) {
+    Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiSendRequest (
+  IN MPT_SCSI_DEV                                   *Dev,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  EFI_STATUS Status;
+
+  if (!Dev->IoReplyEnqueued) {
+    //
+    // Put one free reply frame on the reply queue, the hardware may use it to
+    // report an error to us.
+    //
+    Status = Out32 (Dev, MPT_REG_REP_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoReply));
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    }
+    Dev->IoReplyEnqueued = TRUE;
+  }
+
+  Status = Out32 (Dev, MPT_REG_REQ_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoRequest));
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiGetReply (
+  IN MPT_SCSI_DEV                                   *Dev,
+  OUT UINT32                                        *Reply
+  )
+{
+  EFI_STATUS Status;
+  UINT32     Istatus;
+  UINT32     EmptyReply;
+
+  //
+  // Timeouts are not supported for
+  // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() in this implementation.
+  //
+  for (;;) {
+    Status = In32 (Dev, MPT_REG_ISTATUS, &Istatus);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Interrupt raised
+    //
+    if (Istatus & MPT_IMASK_REPLY) {
+      break;
+    }
+
+    gBS->Stall (Dev->StallPerPollUsec);
+  }
+
+  Status = In32 (Dev, MPT_REG_REP_Q, Reply);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // The driver is supposed to fetch replies until 0xffffffff is returned, which
+  // will reset the interrupt status. We put only one request, so we expect the
+  // next read reply to be the last.
+  //
+  Status = In32 (Dev, MPT_REG_REP_Q, &EmptyReply);
+  if (EFI_ERROR (Status) || EmptyReply != MAX_UINT32) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiHandleReply (
+  IN MPT_SCSI_DEV                                   *Dev,
+  IN UINT32                                         Reply,
+  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet
+  )
+{
+  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+    CopyMem (Packet->InDataBuffer, Dev->Dma->Data, Packet->InTransferLength);
+  }
+
+  if (Reply == Dev->Dma->IoRequest.Data.Header.MessageContext) {
+    //
+    // This is a turbo reply, everything is good
+    //
+    Packet->SenseDataLength = 0;
+    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+    Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+
+  } else if ((Reply & BIT31) != 0) {
+    DEBUG ((DEBUG_INFO, "%a: Full reply returned\n", __FUNCTION__));
+    //
+    // When reply MSB is set, we got a full reply. Since we submitted only one
+    // reply frame, we know it's IoReply.
+    //
+    Dev->IoReplyEnqueued = FALSE;
+
+    Packet->TargetStatus = Dev->Dma->IoReply.Data.ScsiStatus;
+    //
+    // Make sure device only lowers SenseDataLength before copying sense
+    //
+    ASSERT (Dev->Dma->IoReply.Data.SenseCount <= Packet->SenseDataLength);
+    Packet->SenseDataLength =
+      (UINT8)MIN (Dev->Dma->IoReply.Data.SenseCount, Packet->SenseDataLength);
+    CopyMem (Packet->SenseData, Dev->Dma->Sense, Packet->SenseDataLength);
+
+    if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+      Packet->InTransferLength = Dev->Dma->IoReply.Data.TransferCount;
+    } else {
+      Packet->OutTransferLength = Dev->Dma->IoReply.Data.TransferCount;
+    }
+
+    switch (Dev->Dma->IoReply.Data.IocStatus) {
+    case MPT_SCSI_IOCSTATUS_SUCCESS:
+      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+      break;
+    case MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE:
+      Packet->HostAdapterStatus =
+        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
+      return EFI_TIMEOUT;
+    case MPT_SCSI_IOCSTATUS_DATA_UNDERRUN:
+    case MPT_SCSI_IOCSTATUS_DATA_OVERRUN:
+      Packet->HostAdapterStatus =
+        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+      break;
+    default:
+      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+      return EFI_DEVICE_ERROR;
+    }
+
+  } else {
+    DEBUG ((DEBUG_ERROR, "%a: unexpected reply (%x)\n", __FUNCTION__, Reply));
+    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
 //
 // Ext SCSI Pass Thru
 //
@@ -233,7 +551,33 @@ MptScsiPassThru (
   IN EFI_EVENT                                      Event     OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS   Status;
+  MPT_SCSI_DEV *Dev;
+  UINT32       Reply;
+
+  Dev = MPT_SCSI_FROM_PASS_THRU (This);
+  //
+  // We only use first byte of target identifer
+  //
+  Status = MptScsiPopulateRequest (Dev, *Target, Lun, Packet);
+  if (EFI_ERROR (Status)) {
+    //
+    // MptScsiPopulateRequest modified packet according to the error
+    //
+    return Status;
+  }
+
+  Status = MptScsiSendRequest (Dev, Packet);
+  if (EFI_ERROR (Status)) {
+    return ReportHostAdapterError (Packet);
+  }
+
+  Status = MptScsiGetReply (Dev, &Reply);
+  if (EFI_ERROR (Status)) {
+    return ReportHostAdapterError (Packet);
+  }
+
+  return MptScsiHandleReply (Dev, Reply, Packet);
 }
 
 STATIC
@@ -488,6 +832,8 @@ MptScsiControllerStart (
 {
   EFI_STATUS           Status;
   MPT_SCSI_DEV         *Dev;
+  UINTN                Pages;
+  UINTN                BytesMapped;
 
   Dev = AllocateZeroPool (sizeof (*Dev));
   if (Dev == NULL) {
@@ -497,6 +843,7 @@ MptScsiControllerStart (
   Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
 
   Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
+  Dev->StallPerPollUsec = PcdGet32 (PcdMptScsiStallPerPollUsec);
 
   Status = gBS->OpenProtocol (
                   ControllerHandle,
@@ -557,11 +904,45 @@ MptScsiControllerStart (
       ));
   }
 
-  Status = MptScsiInit (Dev);
+  //
+  // Create buffers for data transfer
+  //
+  Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
+  Status = Dev->PciIo->AllocateBuffer (
+                         Dev->PciIo,
+                         AllocateAnyPages,
+                         EfiBootServicesData,
+                         Pages,
+                         (VOID **)&Dev->Dma,
+                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
+                         );
   if (EFI_ERROR (Status)) {
     goto RestoreAttributes;
   }
 
+  BytesMapped = EFI_PAGES_TO_SIZE (Pages);
+  Status = Dev->PciIo->Map (
+                         Dev->PciIo,
+                         EfiPciIoOperationBusMasterCommonBuffer,
+                         Dev->Dma,
+                         &BytesMapped,
+                         &Dev->DmaPhysical,
+                         &Dev->DmaMapping
+                         );
+  if (EFI_ERROR (Status)) {
+    goto FreeBuffer;
+  }
+
+  if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Unmap;
+  }
+
+  Status = MptScsiInit (Dev);
+  if (EFI_ERROR (Status)) {
+    goto Unmap;
+  }
+
   //
   // Host adapter channel, doesn't exist
   //
@@ -594,6 +975,19 @@ MptScsiControllerStart (
 UninitDev:
   MptScsiReset (Dev);
 
+Unmap:
+  Dev->PciIo->Unmap (
+                Dev->PciIo,
+                Dev->DmaMapping
+                );
+
+FreeBuffer:
+  Dev->PciIo->FreeBuffer (
+                Dev->PciIo,
+                EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
+                Dev->Dma
+                );
+
 RestoreAttributes:
   Dev->PciIo->Attributes (
                 Dev->PciIo,
@@ -655,6 +1049,17 @@ MptScsiControllerStop (
 
   MptScsiReset (Dev);
 
+  Dev->PciIo->Unmap (
+                Dev->PciIo,
+                Dev->DmaMapping
+                );
+
+  Dev->PciIo->FreeBuffer (
+                Dev->PciIo,
+                EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
+                Dev->Dma
+                );
+
   Dev->PciIo->Attributes (
                 Dev->PciIo,
                 EfiPciIoAttributeOperationSet,
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index 4862ff9dd497..bb89e50e08f0 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -37,3 +37,6 @@ [Protocols]
 
 [FixedPcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 2d09444bbb16..3bf26e8df82d 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -167,6 +167,9 @@ [PcdsFixedAtBuild]
   #  by ScsiBusDxe.
   gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
 
+  ## Microseconds to stall between polling for MptScsi request result
+  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
+
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
-- 
2.20.1


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

* [PATCH v5 12/12] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices()
  2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
                   ` (10 preceding siblings ...)
  2020-04-24 17:59 ` [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method Nikita Leshenko
@ 2020-04-24 17:59 ` Nikita Leshenko
  2020-04-30  9:48   ` [edk2-devel] " Laszlo Ersek
  11 siblings, 1 reply; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-24 17:59 UTC (permalink / raw)
  To: devel
  Cc: Nikita Leshenko, liran.alon, aaron.young, Jordan Justen,
	Laszlo Ersek, Ard Biesheuvel

This causes the device to forget about the reply frame. We allocated the
reply frame in EfiBootServicesData type memory, and code executing after
ExitBootServices() is permitted to overwrite it.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/MptScsiDxe/MptScsi.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 9cb5088bfbf9..d8649cf45541 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -57,6 +57,7 @@ typedef struct {
   UINT32                          StallPerPollUsec;
   EFI_PCI_IO_PROTOCOL             *PciIo;
   UINT64                          OriginalPciAttributes;
+  EFI_EVENT                       ExitBoot;
   MPT_SCSI_DMA_BUFFER             *Dma;
   EFI_PHYSICAL_ADDRESS            DmaPhysical;
   VOID                            *DmaMapping;
@@ -750,6 +751,20 @@ MptScsiResetChannel (
   return EFI_UNSUPPORTED;
 }
 
+STATIC
+VOID
+EFIAPI
+MptScsiExitBoot (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  MPT_SCSI_DEV *Dev;
+
+  Dev = Context;
+  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
+  MptScsiReset (Dev);
+}
 STATIC
 EFI_STATUS
 EFIAPI
@@ -943,6 +958,17 @@ MptScsiControllerStart (
     goto Unmap;
   }
 
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
+                  TPL_CALLBACK,
+                  &MptScsiExitBoot,
+                  Dev,
+                  &Dev->ExitBoot
+                  );
+  if (EFI_ERROR (Status)) {
+    goto UninitDev;
+  }
+
   //
   // Host adapter channel, doesn't exist
   //
@@ -967,11 +993,14 @@ MptScsiControllerStart (
                   &Dev->PassThru
                   );
   if (EFI_ERROR (Status)) {
-    goto UninitDev;
+    goto CloseExitBoot;
   }
 
   return EFI_SUCCESS;
 
+CloseExitBoot:
+  gBS->CloseEvent (Dev->ExitBoot);
+
 UninitDev:
   MptScsiReset (Dev);
 
@@ -1047,6 +1076,8 @@ MptScsiControllerStop (
     return Status;
   }
 
+  gBS->CloseEvent (Dev->ExitBoot);
+
   MptScsiReset (Dev);
 
   Dev->PciIo->Unmap (
-- 
2.20.1


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

* Re: [edk2-devel] [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver
  2020-04-24 17:59 ` [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver Nikita Leshenko
@ 2020-04-24 18:02   ` Carsey, Jaben
  2020-04-25 10:44     ` Nikita Leshenko
  0 siblings, 1 reply; 26+ messages in thread
From: Carsey, Jaben @ 2020-04-24 18:02 UTC (permalink / raw)
  To: devel@edk2.groups.io, nikita.leshchenko@oracle.com
  Cc: liran.alon@oracle.com, aaron.young@oracle.com, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel

I don't remember reviewing this previously (not recently at least), maybe the RB should be CC?

One comment inline below.

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Nikita
> Leshenko
> Sent: Friday, April 24, 2020 10:59 AM
> To: devel@edk2.groups.io
> Cc: Nikita Leshenko <nikita.leshchenko@oracle.com>;
> liran.alon@oracle.com; aaron.young@oracle.com; Justen, Jordan L
> <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard
> Biesheuvel <ard.biesheuvel@arm.com>; Carsey, Jaben
> <jaben.carsey@intel.com>
> Subject: [edk2-devel] [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name
> of driver
> 
> Install Component Name protocols to have a nice display name for the driver
> in places such as UEFI shell.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
> Reviewed-by: Liran Alon <liran.alon@oracle.com>
> ---
>  OvmfPkg/MptScsiDxe/MptScsi.c | 61
> ++++++++++++++++++++++++++++++++++--
>  1 file changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index 581d3909b84d..64949a809022 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -69,6 +69,63 @@ EFI_DRIVER_BINDING_PROTOCOL
> mMptScsiDriverBinding = {
>    NULL, // DriverBindingHandle, filled as well  };
> 
> +//
> +// Component Name
> +//
> +
> +STATIC
> +EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
> +  { "eng;en", L"LSI Fusion MPT SCSI Driver" },
> +  { NULL,     NULL                   }
> +};
> +
> +STATIC
> +EFI_COMPONENT_NAME_PROTOCOL mComponentName;
> +
> +EFI_STATUS
> +EFIAPI
> +MptScsiGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mDriverNameTable,
> +           DriverName,
> +           (BOOLEAN)(This == &mComponentName) // Iso639Language
> +           );
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +MptScsiGetDeviceName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  EFI_HANDLE                  DeviceHandle,
> +  IN  EFI_HANDLE                  ChildHandle,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **ControllerName
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
> +  &MptScsiGetDriverName,
> +  &MptScsiGetDeviceName,
> +  "eng" // SupportedLanguages, ISO 639-2 language codes };
> +
> +STATIC
> +EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
> &MptScsiGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> &MptScsiGetDeviceName,
> +  "en" // SupportedLanguages, RFC 4646 language codes };

I think that the }; needs to be outside of the comment for both of these structures.

> +
>  //
>  // Entry Point
>  //
> @@ -85,7 +142,7 @@ MptScsiEntryPoint (
>             SystemTable,
>             &mMptScsiDriverBinding,
>             ImageHandle, // The handle to install onto
> -           NULL, // TODO Component name
> -           NULL // TODO Component name
> +           &mComponentName,
> +           &mComponentName2
>             );
>  }
> --
> 2.20.1
> 
> 
> 


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

* Re: [edk2-devel] [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver
  2020-04-24 18:02   ` [edk2-devel] " Carsey, Jaben
@ 2020-04-25 10:44     ` Nikita Leshenko
  0 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-04-25 10:44 UTC (permalink / raw)
  To: devel, jaben.carsey
  Cc: liran.alon@oracle.com, aaron.young@oracle.com, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel



> On 24 Apr 2020, at 21:02, Carsey, Jaben <jaben.carsey@intel.com> wrote:
> 
> I don't remember reviewing this previously (not recently at least), maybe the RB should be CC?
The version that you reviewed was submitted more than a year ago, indeed
a long time ago: https://edk2.groups.io/g/devel/message/36232

> 
> One comment inline below.
> 
>> -----Original Message-----
>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Nikita
>> Leshenko
>> Sent: Friday, April 24, 2020 10:59 AM
>> To: devel@edk2.groups.io
>> Cc: Nikita Leshenko <nikita.leshchenko@oracle.com>;
>> liran.alon@oracle.com; aaron.young@oracle.com; Justen, Jordan L
>> <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard
>> Biesheuvel <ard.biesheuvel@arm.com>; Carsey, Jaben
>> <jaben.carsey@intel.com>
>> Subject: [edk2-devel] [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name
>> of driver
>> 
>> [...]
>> +EFI_STATUS
>> +EFIAPI
>> +MptScsiGetDeviceName (
>> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
>> +  IN  EFI_HANDLE                  DeviceHandle,
>> +  IN  EFI_HANDLE                  ChildHandle,
>> +  IN  CHAR8                       *Language,
>> +  OUT CHAR16                      **ControllerName
>> +  )
>> +{
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
>> +  &MptScsiGetDriverName,
>> +  &MptScsiGetDeviceName,
>> +  "eng" // SupportedLanguages, ISO 639-2 language codes };
>> +
>> +STATIC
>> +EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
>> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
>> &MptScsiGetDriverName,
>> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
>> &MptScsiGetDeviceName,
>> +  "en" // SupportedLanguages, RFC 4646 language codes };
> 
> I think that the }; needs to be outside of the comment for both of these structures.
I don't know why your copy of the mail doesn't have a newline, but that wasn't
my intention. (And my copy of the mail seems to have it, strange...)

The patch looks like intended on the mailing list archive and of Github:
Here is this patch on the mailing list archive:
https://www.mail-archive.com/devel@edk2.groups.io/msg18861.html
And here is this patch on Github:
https://github.com/nikital/edk2/commit/41855cc48125321fce3323473379edcf098c3c01

Thanks,
Nikita


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

* Re: [edk2-devel] [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN
  2020-04-24 17:59 ` [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN Nikita Leshenko
@ 2020-04-29 13:38   ` Laszlo Ersek
  2020-04-29 13:39     ` Laszlo Ersek
  0 siblings, 1 reply; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-29 13:38 UTC (permalink / raw)
  To: devel, nikita.leshchenko
  Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel

On 04/24/20 19:59, Nikita Leshenko wrote:
> The controller supports up to 8 targets in practice (Not reported by the
> controller, but based on the implementation of the virtual device),
> report them in GetNextTarget and GetNextTargetLun. The firmware will
> then try to communicate with them and create a block device for each one
> that responds.
> 
> Support for multiple LUNs will be implemented in another series.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> ---
>  OvmfPkg/MptScsiDxe/MptScsi.c      | 62 ++++++++++++++++++++++++++++++-
>  OvmfPkg/MptScsiDxe/MptScsiDxe.inf |  4 ++
>  OvmfPkg/OvmfPkg.dec               |  4 ++
>  3 files changed, 68 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index 40d392c2346f..5e0544c8d9d2 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -11,6 +11,7 @@
>  
>  #include <IndustryStandard/FusionMptScsi.h>
>  #include <IndustryStandard/Pci.h>
> +#include <Library/BaseMemoryLib.h>
>  #include <Library/DebugLib.h>
>  #include <Library/MemoryAllocationLib.h>
>  #include <Library/UefiBootServicesTableLib.h>
> @@ -34,6 +35,7 @@ typedef struct {
>    UINT32                          Signature;
>    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
> +  UINT8                           MaxTarget;
>  } MPT_SCSI_DEV;
>  
>  #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
> @@ -57,6 +59,22 @@ MptScsiPassThru (
>    return EFI_UNSUPPORTED;
>  }
>  
> +STATIC
> +BOOLEAN
> +IsTargetInitialized (
> +  IN UINT8                                          *Target
> +  )
> +{
> +  UINTN Idx;
> +
> +  for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
> +    if (Target[Idx] != 0xFF) {
> +      return TRUE;
> +    }
> +  }
> +  return FALSE;
> +}
> +
>  STATIC
>  EFI_STATUS
>  EFIAPI
> @@ -66,7 +84,28 @@ MptScsiGetNextTargetLun (
>    IN OUT UINT64                                     *Lun
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  MPT_SCSI_DEV *Dev;
> +
> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
> +  //
> +  // Currently support only LUN 0, so hardcode it
> +  //
> +  if (!IsTargetInitialized (*Target)) {
> +    ZeroMem (*Target, TARGET_MAX_BYTES);
> +    *Lun = 0;
> +  } else if (**Target > Dev->MaxTarget || *Lun > 0) {
> +    return EFI_INVALID_PARAMETER;
> +  } else if (**Target < Dev->MaxTarget) {
> +    //
> +    // This device interface support 256 targets only, so it's enough to
> +    // increment the LSB of Target, as it will never overflow.
> +    //
> +    **Target += 1;
> +  } else {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  return EFI_SUCCESS;
>  }
>  
>  STATIC
> @@ -77,7 +116,24 @@ MptScsiGetNextTarget (
>    IN OUT UINT8                                     **Target
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  MPT_SCSI_DEV *Dev;
> +
> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
> +  if (!IsTargetInitialized (*Target)) {
> +    ZeroMem (*Target, TARGET_MAX_BYTES);
> +  } else if (**Target > Dev->MaxTarget) {
> +    return EFI_INVALID_PARAMETER;
> +  } else if (**Target < Dev->MaxTarget) {
> +    //
> +    // This device interface support 256 targets only, so it's enough to
> +    // increment the LSB of Target, as it will never overflow.
> +    //
> +    **Target += 1;
> +  } else {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  return EFI_SUCCESS;
>  }
>  
>  STATIC
> @@ -206,6 +262,8 @@ MptScsiControllerStart (
>  
>    Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
>  
> +  Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> index 9f7c98829ee1..4862ff9dd497 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> +++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> @@ -24,6 +24,7 @@ [Packages]
>    OvmfPkg/OvmfPkg.dec
>  
>  [LibraryClasses]
> +  BaseMemoryLib
>    DebugLib
>    MemoryAllocationLib
>    UefiBootServicesTableLib
> @@ -33,3 +34,6 @@ [LibraryClasses]
>  [Protocols]
>    gEfiExtScsiPassThruProtocolGuid        ## BY_START
>    gEfiPciIoProtocolGuid                  ## TO_START
> +
> +[FixedPcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 28030391cff2..2d09444bbb16 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -163,6 +163,10 @@ [PcdsFixedAtBuild]
>    #  polling loop iteration.
>    gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiWaitForCmpStallInUsecs|5|UINT32|0x38
>  
> +  ## Set the *inclusive* number of targets that MptScsi exposes for scan
> +  #  by ScsiBusDxe.
> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
> +
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
> 

(1) <PcdLib.h> should be #include'd in this patch, and PcdLib should be
listed under [LibraryClasses].

On one hand, that's a minor wart. The driver (and the OVMF platform(s))
build OK at this stage, in practice. (I tested that.) So this, per se,
does not justify a v6.

On the other hand, even at the end of the series, the module does not
spell out the PcdLib dependency (neither #include nor [LibraryClasses]).
That's not so nice.

But, I'll fix that up for you, if there's not going to be another reason
for a v6.

With (1) addressed (by you, or by me):

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks,
Laszlo


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

* Re: [edk2-devel] [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN
  2020-04-29 13:38   ` [edk2-devel] " Laszlo Ersek
@ 2020-04-29 13:39     ` Laszlo Ersek
  2020-04-29 14:45       ` Liran Alon
  0 siblings, 1 reply; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-29 13:39 UTC (permalink / raw)
  To: devel, nikita.leshchenko, liran.alon
  Cc: aaron.young, Jordan Justen, Ard Biesheuvel

On 04/29/20 15:38, Laszlo Ersek wrote:
> On 04/24/20 19:59, Nikita Leshenko wrote:
>> The controller supports up to 8 targets in practice (Not reported by the
>> controller, but based on the implementation of the virtual device),
>> report them in GetNextTarget and GetNextTargetLun. The firmware will
>> then try to communicate with them and create a block device for each one
>> that responds.
>>
>> Support for multiple LUNs will be implemented in another series.
>>
>> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
>> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
>> ---
>>  OvmfPkg/MptScsiDxe/MptScsi.c      | 62 ++++++++++++++++++++++++++++++-
>>  OvmfPkg/MptScsiDxe/MptScsiDxe.inf |  4 ++
>>  OvmfPkg/OvmfPkg.dec               |  4 ++
>>  3 files changed, 68 insertions(+), 2 deletions(-)
>>
>> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
>> index 40d392c2346f..5e0544c8d9d2 100644
>> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
>> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
>> @@ -11,6 +11,7 @@
>>  
>>  #include <IndustryStandard/FusionMptScsi.h>
>>  #include <IndustryStandard/Pci.h>
>> +#include <Library/BaseMemoryLib.h>
>>  #include <Library/DebugLib.h>
>>  #include <Library/MemoryAllocationLib.h>
>>  #include <Library/UefiBootServicesTableLib.h>
>> @@ -34,6 +35,7 @@ typedef struct {
>>    UINT32                          Signature;
>>    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
>>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
>> +  UINT8                           MaxTarget;
>>  } MPT_SCSI_DEV;
>>  
>>  #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
>> @@ -57,6 +59,22 @@ MptScsiPassThru (
>>    return EFI_UNSUPPORTED;
>>  }
>>  
>> +STATIC
>> +BOOLEAN
>> +IsTargetInitialized (
>> +  IN UINT8                                          *Target
>> +  )
>> +{
>> +  UINTN Idx;
>> +
>> +  for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
>> +    if (Target[Idx] != 0xFF) {
>> +      return TRUE;
>> +    }
>> +  }
>> +  return FALSE;
>> +}
>> +
>>  STATIC
>>  EFI_STATUS
>>  EFIAPI
>> @@ -66,7 +84,28 @@ MptScsiGetNextTargetLun (
>>    IN OUT UINT64                                     *Lun
>>    )
>>  {
>> -  return EFI_UNSUPPORTED;
>> +  MPT_SCSI_DEV *Dev;
>> +
>> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
>> +  //
>> +  // Currently support only LUN 0, so hardcode it
>> +  //
>> +  if (!IsTargetInitialized (*Target)) {
>> +    ZeroMem (*Target, TARGET_MAX_BYTES);
>> +    *Lun = 0;
>> +  } else if (**Target > Dev->MaxTarget || *Lun > 0) {
>> +    return EFI_INVALID_PARAMETER;
>> +  } else if (**Target < Dev->MaxTarget) {
>> +    //
>> +    // This device interface support 256 targets only, so it's enough to
>> +    // increment the LSB of Target, as it will never overflow.
>> +    //
>> +    **Target += 1;
>> +  } else {
>> +    return EFI_NOT_FOUND;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>>  }
>>  
>>  STATIC
>> @@ -77,7 +116,24 @@ MptScsiGetNextTarget (
>>    IN OUT UINT8                                     **Target
>>    )
>>  {
>> -  return EFI_UNSUPPORTED;
>> +  MPT_SCSI_DEV *Dev;
>> +
>> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
>> +  if (!IsTargetInitialized (*Target)) {
>> +    ZeroMem (*Target, TARGET_MAX_BYTES);
>> +  } else if (**Target > Dev->MaxTarget) {
>> +    return EFI_INVALID_PARAMETER;
>> +  } else if (**Target < Dev->MaxTarget) {
>> +    //
>> +    // This device interface support 256 targets only, so it's enough to
>> +    // increment the LSB of Target, as it will never overflow.
>> +    //
>> +    **Target += 1;
>> +  } else {
>> +    return EFI_NOT_FOUND;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>>  }
>>  
>>  STATIC
>> @@ -206,6 +262,8 @@ MptScsiControllerStart (
>>  
>>    Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
>>  
>> +  Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
>> +
>>    //
>>    // Host adapter channel, doesn't exist
>>    //
>> diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>> index 9f7c98829ee1..4862ff9dd497 100644
>> --- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>> +++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>> @@ -24,6 +24,7 @@ [Packages]
>>    OvmfPkg/OvmfPkg.dec
>>  
>>  [LibraryClasses]
>> +  BaseMemoryLib
>>    DebugLib
>>    MemoryAllocationLib
>>    UefiBootServicesTableLib
>> @@ -33,3 +34,6 @@ [LibraryClasses]
>>  [Protocols]
>>    gEfiExtScsiPassThruProtocolGuid        ## BY_START
>>    gEfiPciIoProtocolGuid                  ## TO_START
>> +
>> +[FixedPcd]
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
>> index 28030391cff2..2d09444bbb16 100644
>> --- a/OvmfPkg/OvmfPkg.dec
>> +++ b/OvmfPkg/OvmfPkg.dec
>> @@ -163,6 +163,10 @@ [PcdsFixedAtBuild]
>>    #  polling loop iteration.
>>    gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiWaitForCmpStallInUsecs|5|UINT32|0x38
>>  
>> +  ## Set the *inclusive* number of targets that MptScsi exposes for scan
>> +  #  by ScsiBusDxe.
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
>> +
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
>>
> 
> (1) <PcdLib.h> should be #include'd in this patch, and PcdLib should be
> listed under [LibraryClasses].
> 
> On one hand, that's a minor wart. The driver (and the OVMF platform(s))
> build OK at this stage, in practice. (I tested that.) So this, per se,
> does not justify a v6.
> 
> On the other hand, even at the end of the series, the module does not
> spell out the PcdLib dependency (neither #include nor [LibraryClasses]).
> That's not so nice.
> 
> But, I'll fix that up for you, if there's not going to be another reason
> for a v6.
> 
> With (1) addressed (by you, or by me):
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> Thanks,
> Laszlo
> 

... BTW I missed the same in the PvScsiDxe driver :/

Liran, can you post a patch for that, please?

Thanks,
Laszlo


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

* Re: [edk2-devel] [PATCH v5 07/12] OvmfPkg/MptScsiDxe: Build and decode DevicePath
  2020-04-24 17:59 ` [PATCH v5 07/12] OvmfPkg/MptScsiDxe: Build and decode DevicePath Nikita Leshenko
@ 2020-04-29 13:44   ` Laszlo Ersek
  0 siblings, 0 replies; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-29 13:44 UTC (permalink / raw)
  To: devel, nikita.leshchenko
  Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel

On 04/24/20 19:59, Nikita Leshenko wrote:
> Used to identify the individual disks in the hardware tree.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> Reviewed-by: Liran Alon <liran.alon@oracle.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  OvmfPkg/MptScsiDxe/MptScsi.c | 61 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 59 insertions(+), 2 deletions(-)

The updates look good, my R-b stands.

Thanks
Laszlo

> 
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index 5e0544c8d9d2..dc4b854659f9 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -146,7 +146,36 @@ MptScsiBuildDevicePath (
>    IN OUT EFI_DEVICE_PATH_PROTOCOL                  **DevicePath
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  MPT_SCSI_DEV     *Dev;
> +  SCSI_DEVICE_PATH *ScsiDevicePath;
> +
> +  if (DevicePath == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // This device support 256 targets only, so it's enough to dereference
> +  // the LSB of Target.
> +  //
> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
> +  if (*Target > Dev->MaxTarget || Lun > 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  ScsiDevicePath = AllocateZeroPool (sizeof (*ScsiDevicePath));
> +  if (ScsiDevicePath == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  ScsiDevicePath->Header.Type      = MESSAGING_DEVICE_PATH;
> +  ScsiDevicePath->Header.SubType   = MSG_SCSI_DP;
> +  ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);
> +  ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);
> +  ScsiDevicePath->Pun              = *Target;
> +  ScsiDevicePath->Lun              = (UINT16)Lun;
> +
> +  *DevicePath = &ScsiDevicePath->Header;
> +  return EFI_SUCCESS;
>  }
>  
>  STATIC
> @@ -159,7 +188,35 @@ MptScsiGetTargetLun (
>    OUT UINT64                                       *Lun
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  MPT_SCSI_DEV     *Dev;
> +  SCSI_DEVICE_PATH *ScsiDevicePath;
> +
> +  if (DevicePath == NULL ||
> +      Target == NULL || *Target == NULL || Lun == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (DevicePath->Type    != MESSAGING_DEVICE_PATH ||
> +      DevicePath->SubType != MSG_SCSI_DP) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
> +  ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;
> +  if (ScsiDevicePath->Pun > Dev->MaxTarget ||
> +      ScsiDevicePath->Lun > 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  ZeroMem (*Target, TARGET_MAX_BYTES);
> +  //
> +  // This device support 256 targets only, so it's enough to set the LSB
> +  // of Target.
> +  //
> +  **Target = (UINT8)ScsiDevicePath->Pun;
> +  *Lun = ScsiDevicePath->Lun;
> +
> +  return EFI_SUCCESS;
>  }
>  
>  STATIC
> 


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

* Re: [edk2-devel] [PATCH v5 09/12] OvmfPkg/MptScsiDxe: Set and restore PCI attributes
  2020-04-24 17:59 ` [PATCH v5 09/12] OvmfPkg/MptScsiDxe: Set and restore PCI attributes Nikita Leshenko
@ 2020-04-29 13:50   ` Laszlo Ersek
  0 siblings, 0 replies; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-29 13:50 UTC (permalink / raw)
  To: devel, nikita.leshchenko
  Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel

On 04/24/20 19:59, Nikita Leshenko wrote:
> Enable the IO Space and Bus Mastering and restore the original values
> when the device is stopped. This is a standard procedure in PCI
> drivers.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> Reviewed-by: Liran Alon <liran.alon@oracle.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  OvmfPkg/MptScsiDxe/MptScsi.c | 65 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 64 insertions(+), 1 deletion(-)

This patch has undergone (since v4) more changes than what I had tied my
R-b to, in the v4 review. So I think including the R-b upfront, in v5,
is not justified.

However, the updates all look good, in the end. Therefore:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo


> 
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index ed7fabf8b471..e88ac2867a75 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -37,6 +37,7 @@ typedef struct {
>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
>    UINT8                           MaxTarget;
>    EFI_PCI_IO_PROTOCOL             *PciIo;
> +  UINT64                          OriginalPciAttributes;
>  } MPT_SCSI_DEV;
>  
>  #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
> @@ -334,6 +335,53 @@ MptScsiControllerStart (
>      goto FreePool;
>    }
>  
> +  Status = Dev->PciIo->Attributes (
> +                         Dev->PciIo,
> +                         EfiPciIoAttributeOperationGet,
> +                         0,
> +                         &Dev->OriginalPciAttributes
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    goto CloseProtocol;
> +  }
> +
> +  //
> +  // Enable I/O Space & Bus-Mastering
> +  //
> +  Status = Dev->PciIo->Attributes (
> +                         Dev->PciIo,
> +                         EfiPciIoAttributeOperationEnable,
> +                         (EFI_PCI_IO_ATTRIBUTE_IO |
> +                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
> +                         NULL
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    goto CloseProtocol;
> +  }
> +
> +  //
> +  // Signal device supports 64-bit DMA addresses
> +  //
> +  Status = Dev->PciIo->Attributes (
> +                         Dev->PciIo,
> +                         EfiPciIoAttributeOperationEnable,
> +                         EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
> +                         NULL
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    //
> +    // Warn user that device will only be using 32-bit DMA addresses.
> +    //
> +    // Note that this does not prevent the device/driver from working
> +    // and therefore we only warn and continue as usual.
> +    //
> +    DEBUG ((
> +      DEBUG_WARN,
> +      "%a: failed to enable 64-bit DMA addresses\n",
> +      __FUNCTION__
> +      ));
> +  }
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> @@ -358,11 +406,19 @@ MptScsiControllerStart (
>                    &Dev->PassThru
>                    );
>    if (EFI_ERROR (Status)) {
> -    goto CloseProtocol;
> +    goto RestoreAttributes;
>    }
>  
>    return EFI_SUCCESS;
>  
> +RestoreAttributes:
> +  Dev->PciIo->Attributes (
> +                Dev->PciIo,
> +                EfiPciIoAttributeOperationSet,
> +                Dev->OriginalPciAttributes,
> +                NULL
> +                );
> +
>  CloseProtocol:
>    gBS->CloseProtocol (
>           ControllerHandle,
> @@ -414,6 +470,13 @@ MptScsiControllerStop (
>      return Status;
>    }
>  
> +  Dev->PciIo->Attributes (
> +                Dev->PciIo,
> +                EfiPciIoAttributeOperationSet,
> +                Dev->OriginalPciAttributes,
> +                NULL
> +                );
> +
>    gBS->CloseProtocol (
>           ControllerHandle,
>           &gEfiPciIoProtocolGuid,
> 


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

* Re: [edk2-devel] [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN
  2020-04-29 13:39     ` Laszlo Ersek
@ 2020-04-29 14:45       ` Liran Alon
  2020-04-29 18:10         ` Laszlo Ersek
  0 siblings, 1 reply; 26+ messages in thread
From: Liran Alon @ 2020-04-29 14:45 UTC (permalink / raw)
  To: Laszlo Ersek, devel, nikita.leshchenko
  Cc: aaron.young, Jordan Justen, Ard Biesheuvel


On 29/04/2020 16:39, Laszlo Ersek wrote:
> On 04/29/20 15:38, Laszlo Ersek wrote:
>> On 04/24/20 19:59, Nikita Leshenko wrote:
>>> diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>> index 9f7c98829ee1..4862ff9dd497 100644
>>> --- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>> +++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>> @@ -24,6 +24,7 @@ [Packages]
>>>     OvmfPkg/OvmfPkg.dec
>>>   
>>>   [LibraryClasses]
>>> +  BaseMemoryLib
>>>     DebugLib
>>>     MemoryAllocationLib
>>>     UefiBootServicesTableLib
>>> @@ -33,3 +34,6 @@ [LibraryClasses]
>>>   [Protocols]
>>>     gEfiExtScsiPassThruProtocolGuid        ## BY_START
>>>     gEfiPciIoProtocolGuid                  ## TO_START
>>> +
>>> +[FixedPcd]
>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
>>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
>>> index 28030391cff2..2d09444bbb16 100644
>>> --- a/OvmfPkg/OvmfPkg.dec
>>> +++ b/OvmfPkg/OvmfPkg.dec
>>> @@ -163,6 +163,10 @@ [PcdsFixedAtBuild]
>>>     #  polling loop iteration.
>>>     gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiWaitForCmpStallInUsecs|5|UINT32|0x38
>>>   
>>> +  ## Set the *inclusive* number of targets that MptScsi exposes for scan
>>> +  #  by ScsiBusDxe.
>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
>>> +
>>>     gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>>>     gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>>>     gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
>>>
>> (1) <PcdLib.h> should be #include'd in this patch, and PcdLib should be
>> listed under [LibraryClasses].
>>
>> On one hand, that's a minor wart. The driver (and the OVMF platform(s))
>> build OK at this stage, in practice. (I tested that.) So this, per se,
>> does not justify a v6.
>>
>> On the other hand, even at the end of the series, the module does not
>> spell out the PcdLib dependency (neither #include nor [LibraryClasses]).
>> That's not so nice.
>>
>> But, I'll fix that up for you, if there's not going to be another reason
>> for a v6.
>>
>> With (1) addressed (by you, or by me):
>>
>> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>>
>> Thanks,
>> Laszlo
>>
> ... BTW I missed the same in the PvScsiDxe driver :/
>
> Liran, can you post a patch for that, please?
>
> Thanks,
> Laszlo


Sure. Will do. Quite surprised it builds successfully without it.
BTW, VirtioScsi DXE driver also seems to be missing PcdLib dependency 
both in #include and [LibraryClasses] as-well.
I can submit a patch for that as-well if you like.

-Liran



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

* Re: [edk2-devel] [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware
  2020-04-24 17:59 ` [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware Nikita Leshenko
@ 2020-04-29 14:55   ` Laszlo Ersek
  2020-05-04 19:35     ` Nikita Leshenko
  0 siblings, 1 reply; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-29 14:55 UTC (permalink / raw)
  To: devel, nikita.leshchenko
  Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel

On 04/24/20 19:59, Nikita Leshenko wrote:
> Reset and send the IO controller initialization request. The reply is
> read back to complete the doorbell function but it isn't useful to us
> because it doesn't contain relevant data or status codes.
> 
> See "LSI53C1030 PCI-X to Dual Channel Ultra320 SCSI Multifunction
> Controller" technical manual for more information.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> ---
>  .../Include/IndustryStandard/FusionMptScsi.h  | 128 ++++++++++++
>  OvmfPkg/MptScsiDxe/MptScsi.c                  | 187 +++++++++++++++++-
>  2 files changed, 314 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
> index df9bdc2f0348..655d629d902e 100644
> --- a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
> +++ b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
> @@ -20,4 +20,132 @@
>  #define LSI_SAS1068_PCI_DEVICE_ID 0x0054
>  #define LSI_SAS1068E_PCI_DEVICE_ID 0x0058
>  
> +#define MPT_REG_DOORBELL  0x00
> +#define MPT_REG_WRITE_SEQ 0x04
> +#define MPT_REG_HOST_DIAG 0x08
> +#define MPT_REG_TEST      0x0c
> +#define MPT_REG_DIAG_DATA 0x10
> +#define MPT_REG_DIAG_ADDR 0x14
> +#define MPT_REG_ISTATUS   0x30
> +#define MPT_REG_IMASK     0x34
> +#define MPT_REG_REQ_Q     0x40
> +#define MPT_REG_REP_Q     0x44
> +
> +#define MPT_DOORBELL_RESET     0x40
> +#define MPT_DOORBELL_HANDSHAKE 0x42
> +
> +#define MPT_IMASK_DOORBELL 0x01
> +#define MPT_IMASK_REPLY    0x08
> +
> +#define MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST 0x00
> +#define MPT_MESSAGE_HDR_FUNCTION_IOC_INIT        0x02
> +
> +#define MPT_SG_ENTRY_TYPE_SIMPLE 0x01
> +
> +#define MPT_IOC_WHOINIT_ROM_BIOS 0x02
> +
> +//
> +// Device structures
> +//
> +
> +#pragma pack (1)
> +typedef struct {
> +  UINT8     WhoInit;
> +  UINT8     Reserved1;
> +  UINT8     ChainOffset;
> +  UINT8     Function;
> +  UINT8     Flags;
> +  UINT8     MaxDevices;
> +  UINT8     MaxBuses;
> +  UINT8     MessageFlags;
> +  UINT32    MessageContext;
> +  UINT16    ReplyFrameSize;
> +  UINT16    Reserved2;
> +  UINT32    HostMfaHighAddr;
> +  UINT32    SenseBufferHighAddr;
> +} MPT_IO_CONTROLLER_INIT_REQUEST;
> +
> +typedef struct {
> +  UINT8     WhoInit;
> +  UINT8     Reserved1;
> +  UINT8     MessageLength;
> +  UINT8     Function;
> +  UINT8     Flags;
> +  UINT8     MaxDevices;
> +  UINT8     MaxBuses;
> +  UINT8     MessageFlags;
> +  UINT32    MessageContext;
> +  UINT16    Reserved2;
> +  UINT16    IocStatus;
> +  UINT32    IocLogInfo;
> +} MPT_IO_CONTROLLER_INIT_REPLY;
> +
> +typedef struct {
> +  UINT8     TargetId;
> +  UINT8     Bus;
> +  UINT8     ChainOffset;
> +  UINT8     Function;
> +  UINT8     CdbLength;
> +  UINT8     SenseBufferLength;
> +  UINT8     Reserved;
> +  UINT8     MessageFlags;
> +  UINT32    MessageContext;
> +  UINT8     Lun[8];
> +  UINT32    Control;
> +  UINT8     Cdb[16];
> +  UINT32    DataLength;
> +  UINT32    SenseBufferLowAddress;
> +} MPT_SCSI_IO_REQUEST;
> +
> +typedef struct {
> +  UINT32    Length:             24;
> +  UINT32    EndOfList:          1;
> +  UINT32    Is64BitAddress:     1;
> +  //
> +  // True when the buffer contains data to be transfered. Otherwise it's the
> +  // destination buffer
> +  //
> +  UINT32    BufferContainsData: 1;
> +  UINT32    LocalAddress:       1;
> +  UINT32    ElementType:        2;
> +  UINT32    EndOfBuffer:        1;
> +  UINT32    LastElement:        1;
> +  UINT64    DataBufferAddress;
> +} MPT_SG_ENTRY_SIMPLE;
> +
> +typedef struct {
> +  UINT8     TargetId;
> +  UINT8     Bus;
> +  UINT8     MessageLength;
> +  UINT8     Function;
> +  UINT8     CdbLength;
> +  UINT8     SenseBufferLength;
> +  UINT8     Reserved;
> +  UINT8     MessageFlags;
> +  UINT32    MessageContext;
> +  UINT8     ScsiStatus;
> +  UINT8     ScsiState;
> +  UINT16    IocStatus;
> +  UINT32    IocLogInfo;
> +  UINT32    TransferCount;
> +  UINT32    SenseCount;
> +  UINT32    ResponseInfo;
> +} MPT_SCSI_IO_REPLY;
> +
> +typedef struct {
> +  MPT_SCSI_IO_REQUEST Header;
> +  MPT_SG_ENTRY_SIMPLE Sg;
> +} MPT_SCSI_REQUEST_WITH_SG;
> +#pragma pack ()
> +
> +typedef union {
> +  MPT_SCSI_IO_REPLY        Data;
> +  UINT64                   Uint64; // 8 byte alignment required by HW
> +} MPT_SCSI_IO_REPLY_ALIGNED;
> +
> +typedef union {
> +  MPT_SCSI_REQUEST_WITH_SG Data;
> +  UINT64                   Uint64; // 8 byte alignment required by HW
> +} MPT_SCSI_REQUEST_ALIGNED;
> +
>  #endif // __FUSION_MPT_SCSI_H__
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index e88ac2867a75..15d671b544c2 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -43,6 +43,181 @@ typedef struct {
>  #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
>    CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
>  
> +//
> +// Hardware functions
> +//
> +
> +STATIC
> +EFI_STATUS
> +Out32 (
> +  IN MPT_SCSI_DEV       *Dev,
> +  IN UINT32             Addr,
> +  IN UINT32             Data
> +  )
> +{
> +  return Dev->PciIo->Io.Write (
> +                          Dev->PciIo,
> +                          EfiPciIoWidthUint32,
> +                          PCI_BAR_IDX0,
> +                          Addr,
> +                          1,
> +                          &Data
> +                          );
> +}
> +
> +STATIC
> +EFI_STATUS
> +In32 (
> +  IN  MPT_SCSI_DEV       *Dev,
> +  IN  UINT32             Addr,
> +  OUT UINT32             *Data
> +  )
> +{
> +  return Dev->PciIo->Io.Read (
> +                          Dev->PciIo,
> +                          EfiPciIoWidthUint32,
> +                          PCI_BAR_IDX0,
> +                          Addr,
> +                          1,
> +                          Data
> +                          );
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptDoorbell (
> +  IN MPT_SCSI_DEV       *Dev,
> +  IN UINT8              DoorbellFunc,
> +  IN UINT8              DoorbellArg
> +  )
> +{
> +  return Out32 (
> +           Dev,
> +           MPT_REG_DOORBELL,
> +           (((UINT32)DoorbellFunc) << 24) | (DoorbellArg << 16)
> +           );
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptScsiReset (
> +  IN MPT_SCSI_DEV       *Dev
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  //
> +  // Reset hardware
> +  //
> +  Status = MptDoorbell (Dev, MPT_DOORBELL_RESET, 0);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  //
> +  // Mask interrupts
> +  //
> +  Status = Out32 (Dev, MPT_REG_IMASK, MPT_IMASK_DOORBELL | MPT_IMASK_REPLY);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  //
> +  // Clear interrupt status
> +  //
> +  Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptScsiInit (
> +  IN MPT_SCSI_DEV       *Dev
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  MPT_IO_CONTROLLER_INIT_REQUEST Req;

(1) Unfortunately, "Req" is not aligned to any particular boundary any
more. From your response at

http://mid.mail-archive.com/DFF6CD19-C013-44B1-8B0E-DE1C1A891BBF@oracle.com

https://edk2.groups.io/g/devel/message/57471

under my then-remark (4), you seemed to agree that the alignment was
still necessary, only the size should be lowered from 8 bytes to 4 bytes.

Below we use Dev->PciIo->Io.Write() for sending the request, with
"EfiPciIoWidthFifoUint32". And the code flow that's internal to that
call is similar to what I described in the following message, in the
PvScsiDxe review (see the end of the message):

http://mid.mail-archive.com/5833e06c-bb10-5c8c-1827-25e723b5834e@redhat.com

https://edk2.groups.io/g/devel/message/56326

So you get

PciIoIoWrite() -> RootBridgeIoIoWrite() -> CpuIoServiceWrite() ->
CpuIoCheckParameter()

and the last function in that chain will reject an un-aligned request.

That means we still need a union here, just with a Uint32 field as the
"other" member.

And we will still need to send "Req.Data" (not "Req") to the device.

You can either introduce a new typedef for the alignment / union under
IndustryStandard, or just define an ad-hoc union here in this function,
like PvScsiDxe does.


> +  MPT_IO_CONTROLLER_INIT_REPLY   Reply;
> +  UINT8                          *ReplyBytes;
> +  UINT32                         ReplyWord;
> +
> +  Status = MptScsiReset (Dev);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ZeroMem (&Req, sizeof (Req));
> +  ZeroMem (&Reply, sizeof (Reply));
> +  Req.WhoInit = MPT_IOC_WHOINIT_ROM_BIOS;
> +  Req.Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;
> +  STATIC_ASSERT(

(2) Missing space character.

> +    FixedPcdGet8 (PcdMptScsiMaxTargetLimit) < 255,
> +    "Req supports 255 targets only (max target is 254)");

(3) The closing paren should be broken off to a separate line.

> +  Req.MaxDevices = Dev->MaxTarget + 1;
> +  Req.MaxBuses = 1;

The assignment to "ReplyFrameSize" is lost in v5 -- did you remove it
intentionally? ...Hmm, no, it's been moved to the next patch. OK.

> +
> +  //
> +  // Send controller init through doorbell
> +  //
> +  STATIC_ASSERT (
> +    sizeof (Req) % sizeof (UINT32) == 0,
> +    "Req must be multiple of UINT32"
> +    );
> +  STATIC_ASSERT (
> +    sizeof (Req) / sizeof (UINT32) <= MAX_UINT8,
> +    "Req must bit in MAX_UINT8 Dwords"
> +    );

(4) s/bit/fit/

> +  Status = MptDoorbell (
> +             Dev,
> +             MPT_DOORBELL_HANDSHAKE,
> +             (UINT8)(sizeof (Req) / sizeof (UINT32))
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  Status = Dev->PciIo->Io.Write (
> +                            Dev->PciIo,
> +                            EfiPciIoWidthFifoUint32,
> +                            PCI_BAR_IDX0,
> +                            MPT_REG_DOORBELL,
> +                            sizeof (Req) / sizeof (UINT32),
> +                            &Req
> +                            );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Read reply through doorbell
> +  // Each 32bit (Dword) read produces 16bit (Word) of data
> +  //

(5) You missed my v4 request (10), at:

http://mid.mail-archive.com/034ffcb9-e11b-4b31-8d62-2eba4eaef08f@redhat.com

https://edk2.groups.io/g/devel/message/57464

Namely:

"Please use another STATIC_ASSERT here for expressing that the response
structure size is an integer multiple of sizeof (UINT16)."

> +  // The reply is read back to complete the doorbell function but it
> +  // isn't useful because it doesn't contain relevant data or status
> +  // codes.
> +  //
> +  ReplyBytes = (UINT8 *)&Reply;
> +  while (ReplyBytes != (UINT8 *)(&Reply + 1)) {
> +    Status = In32 (Dev, MPT_REG_DOORBELL, &ReplyWord);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +    CopyMem (ReplyBytes, &ReplyWord, sizeof (UINT16));
> +    ReplyBytes += sizeof (UINT16);
> +  }
> +
> +  //
> +  // Clear interrupts generated by doorbell reply
> +  //
> +  Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
>  //
>  // Ext SCSI Pass Thru
>  //
> @@ -382,6 +557,11 @@ MptScsiControllerStart (
>        ));
>    }
>  
> +  Status = MptScsiInit (Dev);
> +  if (EFI_ERROR (Status)) {
> +    goto RestoreAttributes;

Hmmm, git-range-diff flags this as a v4->v5 change, and I don't
understand why...

Ah, OK. In v4, we jumped to "RestorePciAttributes" -- which was a
non-existent label. So I think the v4 variant of this patch didn't
compile. I hope that's fixed now, with the above. :)

The rest of the updates / patch look fine to me.

Thanks!
Laszlo


> +  }
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> @@ -406,11 +586,14 @@ MptScsiControllerStart (
>                    &Dev->PassThru
>                    );
>    if (EFI_ERROR (Status)) {
> -    goto RestoreAttributes;
> +    goto UninitDev;
>    }
>  
>    return EFI_SUCCESS;
>  
> +UninitDev:
> +  MptScsiReset (Dev);
> +
>  RestoreAttributes:
>    Dev->PciIo->Attributes (
>                  Dev->PciIo,
> @@ -470,6 +653,8 @@ MptScsiControllerStop (
>      return Status;
>    }
>  
> +  MptScsiReset (Dev);
> +
>    Dev->PciIo->Attributes (
>                  Dev->PciIo,
>                  EfiPciIoAttributeOperationSet,
> 


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

* Re: [edk2-devel] [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN
  2020-04-29 14:45       ` Liran Alon
@ 2020-04-29 18:10         ` Laszlo Ersek
  0 siblings, 0 replies; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-29 18:10 UTC (permalink / raw)
  To: Liran Alon, devel, nikita.leshchenko
  Cc: aaron.young, Jordan Justen, Ard Biesheuvel

On 04/29/20 16:45, Liran Alon wrote:
> 
> On 29/04/2020 16:39, Laszlo Ersek wrote:
>> On 04/29/20 15:38, Laszlo Ersek wrote:
>>> On 04/24/20 19:59, Nikita Leshenko wrote:
>>>> diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>>> b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>>> index 9f7c98829ee1..4862ff9dd497 100644
>>>> --- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>>> +++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>>>> @@ -24,6 +24,7 @@ [Packages]
>>>>     OvmfPkg/OvmfPkg.dec
>>>>     [LibraryClasses]
>>>> +  BaseMemoryLib
>>>>     DebugLib
>>>>     MemoryAllocationLib
>>>>     UefiBootServicesTableLib
>>>> @@ -33,3 +34,6 @@ [LibraryClasses]
>>>>   [Protocols]
>>>>     gEfiExtScsiPassThruProtocolGuid        ## BY_START
>>>>     gEfiPciIoProtocolGuid                  ## TO_START
>>>> +
>>>> +[FixedPcd]
>>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
>>>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
>>>> index 28030391cff2..2d09444bbb16 100644
>>>> --- a/OvmfPkg/OvmfPkg.dec
>>>> +++ b/OvmfPkg/OvmfPkg.dec
>>>> @@ -163,6 +163,10 @@ [PcdsFixedAtBuild]
>>>>     #  polling loop iteration.
>>>>    
>>>> gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiWaitForCmpStallInUsecs|5|UINT32|0x38
>>>>
>>>>   +  ## Set the *inclusive* number of targets that MptScsi exposes
>>>> for scan
>>>> +  #  by ScsiBusDxe.
>>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
>>>> +
>>>>    
>>>> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>>>>
>>>>    
>>>> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>>>>
>>>>     gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
>>>>
>>> (1) <PcdLib.h> should be #include'd in this patch, and PcdLib should be
>>> listed under [LibraryClasses].
>>>
>>> On one hand, that's a minor wart. The driver (and the OVMF platform(s))
>>> build OK at this stage, in practice. (I tested that.) So this, per se,
>>> does not justify a v6.
>>>
>>> On the other hand, even at the end of the series, the module does not
>>> spell out the PcdLib dependency (neither #include nor [LibraryClasses]).
>>> That's not so nice.
>>>
>>> But, I'll fix that up for you, if there's not going to be another reason
>>> for a v6.
>>>
>>> With (1) addressed (by you, or by me):
>>>
>>> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>>>
>>> Thanks,
>>> Laszlo
>>>
>> ... BTW I missed the same in the PvScsiDxe driver :/
>>
>> Liran, can you post a patch for that, please?
>>
>> Thanks,
>> Laszlo
> 
> 
> Sure. Will do. Quite surprised it builds successfully without it.
> BTW, VirtioScsi DXE driver also seems to be missing PcdLib dependency
> both in #include and [LibraryClasses] as-well.
> I can submit a patch for that as-well if you like.

Yes please!

Such dependencies are easy to miss, on commonly used / low-level lib
classes. Usually one of the higher-level lib class headers pulls in the
lib class header in question. And the [LibraryClasses] part remains
hidden because a lib instance already (explicitly or imlicitly) consumed
makes the consumer module inherit the [LibraryClasses] dependency too.

Thanks
Laszlo


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

* Re: [edk2-devel] [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method
  2020-04-24 17:59 ` [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method Nikita Leshenko
@ 2020-04-30  9:47   ` Laszlo Ersek
  2020-05-04 20:08     ` Nikita Leshenko
  0 siblings, 1 reply; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-30  9:47 UTC (permalink / raw)
  To: devel, nikita.leshchenko
  Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel

On 04/24/20 19:59, Nikita Leshenko wrote:
> Machines should be able to boot after this commit. Tested with different
> Linux distributions (Ubuntu, CentOS) and different Windows
> versions (Windows 7, Windows 10, Server 2016).
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> ---
>  .../Include/IndustryStandard/FusionMptScsi.h  |   9 +
>  OvmfPkg/MptScsiDxe/MptScsi.c                  | 409 +++++++++++++++++-
>  OvmfPkg/MptScsiDxe/MptScsiDxe.inf             |   3 +
>  OvmfPkg/OvmfPkg.dec                           |   3 +
>  4 files changed, 422 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
> index 655d629d902e..99778d1537da 100644
> --- a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
> +++ b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
> @@ -44,6 +44,15 @@
>  
>  #define MPT_IOC_WHOINIT_ROM_BIOS 0x02
>  
> +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE  (0x00 << 24)
> +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE (0x01 << 24)
> +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ  (0x02 << 24)
> +
> +#define MPT_SCSI_IOCSTATUS_SUCCESS          0x0000
> +#define MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE 0x0043
> +#define MPT_SCSI_IOCSTATUS_DATA_OVERRUN     0x0044
> +#define MPT_SCSI_IOCSTATUS_DATA_UNDERRUN    0x0045
> +
>  //
>  // Device structures
>  //
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index 15d671b544c2..9cb5088bfbf9 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -17,6 +17,7 @@
>  #include <Library/UefiBootServicesTableLib.h>
>  #include <Library/UefiLib.h>
>  #include <Protocol/PciIo.h>
> +#include <Protocol/PciRootBridgeIo.h>
>  #include <Protocol/ScsiPassThruExt.h>
>  #include <Uefi/UefiSpec.h>
>  
> @@ -30,19 +31,50 @@
>  // Runtime Structures
>  //
>  
> +typedef struct {
> +  MPT_SCSI_REQUEST_ALIGNED        IoRequest;
> +  MPT_SCSI_IO_REPLY_ALIGNED       IoReply;
> +  //
> +  // As EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.SenseDataLength is defined
> +  // as UINT8, defining here SenseData size to MAX_UINT8 will guarantee it
> +  // cannot overflow when passed to device.
> +  //
> +  UINT8                           Sense[MAX_UINT8];
> +  //
> +  // This size of the data is arbitrarily chosen.
> +  // It seems to be sufficient for all I/O requests sent through
> +  // EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() for common boot scenarios.
> +  //
> +  UINT8                           Data[0x2000];
> +} MPT_SCSI_DMA_BUFFER;
> +
>  #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;
>    UINT8                           MaxTarget;
> +  UINT32                          StallPerPollUsec;
>    EFI_PCI_IO_PROTOCOL             *PciIo;
>    UINT64                          OriginalPciAttributes;
> +  MPT_SCSI_DMA_BUFFER             *Dma;
> +  EFI_PHYSICAL_ADDRESS            DmaPhysical;
> +  VOID                            *DmaMapping;
> +  BOOLEAN                         IoReplyEnqueued;
>  } MPT_SCSI_DEV;
>  
>  #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
>    CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
>  
> +#define MPT_SCSI_DMA_ADDR(Dev, MemberName) \
> +  (Dev->DmaPhysical + OFFSET_OF (MPT_SCSI_DMA_BUFFER, MemberName))
> +
> +#define MPT_SCSI_DMA_ADDR_HIGH(Dev, MemberName) \
> +  ((UINT32)(MPT_SCSI_DMA_ADDR (Dev, MemberName) >> 32))

(1) Please use the RShiftU64() from BaseLib.

> +
> +#define MPT_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
> +  ((UINT32)MPT_SCSI_DMA_ADDR (Dev, MemberName))
> +
>  //
>  // Hardware functions
>  //
> @@ -157,6 +189,9 @@ MptScsiInit (
>      "Req supports 255 targets only (max target is 254)");
>    Req.MaxDevices = Dev->MaxTarget + 1;
>    Req.MaxBuses = 1;
> +  Req.ReplyFrameSize = sizeof Dev->Dma->IoReply.Data;
> +  Req.HostMfaHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, IoRequest);
> +  Req.SenseBufferHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, Sense);
>  
>    //
>    // Send controller init through doorbell
> @@ -218,6 +253,289 @@ MptScsiInit (
>    return EFI_SUCCESS;
>  }
>  
> +STATIC
> +EFI_STATUS
> +ReportHostAdapterError (
> +  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  DEBUG ((DEBUG_ERROR, "%a: fatal error in scsi request\n", __FUNCTION__));
> +  Packet->InTransferLength  = 0;
> +  Packet->OutTransferLength = 0;
> +  Packet->SenseDataLength   = 0;
> +  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> +  Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +STATIC
> +EFI_STATUS
> +ReportHostAdapterOverrunError (
> +  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  Packet->SenseDataLength = 0;
> +  Packet->HostAdapterStatus =
> +            EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
> +  Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> +  return EFI_BAD_BUFFER_SIZE;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptScsiPopulateRequest (
> +  IN MPT_SCSI_DEV                                   *Dev,
> +  IN UINT8                                          Target,
> +  IN UINT64                                         Lun,
> +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  MPT_SCSI_REQUEST_WITH_SG *Request;
> +
> +  Request = &Dev->Dma->IoRequest.Data;
> +
> +  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
> +      (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
> +      Packet->CdbLength > sizeof (Request->Header.Cdb)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (Target > Dev->MaxTarget || Lun > 0 ||
> +      Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
> +      //
> +      // Trying to receive, but destination pointer is NULL, or contradicting
> +      // transfer direction
> +      //
> +      (Packet->InTransferLength > 0 &&
> +       (Packet->InDataBuffer == NULL ||
> +        Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE
> +         )
> +        ) ||
> +
> +      //
> +      // Trying to send, but source pointer is NULL, or contradicting transfer
> +      // direction
> +      //
> +      (Packet->OutTransferLength > 0 &&
> +       (Packet->OutDataBuffer == NULL ||
> +        Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ
> +         )
> +        )
> +    ) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Packet->InTransferLength > sizeof (Dev->Dma->Data)) {
> +    Packet->InTransferLength = sizeof (Dev->Dma->Data);
> +    return ReportHostAdapterOverrunError (Packet);
> +  }
> +  if (Packet->OutTransferLength > sizeof (Dev->Dma->Data)) {
> +    Packet->OutTransferLength = sizeof (Dev->Dma->Data);
> +    return ReportHostAdapterOverrunError (Packet);
> +  }
> +
> +  ZeroMem (Request, sizeof (*Request));
> +  Request->Header.TargetId = Target;
> +  //
> +  // Only LUN 0 is currently supported, hence the cast is safe
> +  //
> +  Request->Header.Lun[1] = (UINT8)Lun;
> +  Request->Header.Function = MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST;
> +  Request->Header.MessageContext = 1; // We handle one request at a time
> +
> +  Request->Header.CdbLength = Packet->CdbLength;
> +  CopyMem (Request->Header.Cdb, Packet->Cdb, Packet->CdbLength);
> +
> +  //
> +  // SenseDataLength is UINT8, Sense[] is MAX_UINT8, so we can't overflow
> +  //
> +  ZeroMem (Dev->Dma->Sense, Packet->SenseDataLength);
> +  Request->Header.SenseBufferLength = Packet->SenseDataLength;
> +  Request->Header.SenseBufferLowAddress = MPT_SCSI_DMA_ADDR_LOW (Dev, Sense);
> +
> +  Request->Sg.EndOfList = 1;
> +  Request->Sg.EndOfBuffer = 1;
> +  Request->Sg.LastElement = 1;
> +  Request->Sg.ElementType = MPT_SG_ENTRY_TYPE_SIMPLE;
> +  Request->Sg.Is64BitAddress = 1;
> +  Request->Sg.DataBufferAddress = MPT_SCSI_DMA_ADDR (Dev, Data);
> +
> +  //
> +  // "MPT_SG_ENTRY_SIMPLE.Length" is a 24-bit quantity.
> +  //
> +  STATIC_ASSERT (
> +    sizeof (Dev->Dma->Data) < SIZE_16MB,
> +    "MPT_SCSI_DMA_BUFFER.Data must be smaller than 16MB"
> +    );
> +
> +  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> +    Request->Header.DataLength = Packet->InTransferLength;
> +    Request->Sg.Length = Packet->InTransferLength;
> +    Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ;
> +  } else {
> +    Request->Header.DataLength = Packet->OutTransferLength;
> +    Request->Sg.Length = Packet->OutTransferLength;
> +    Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE;
> +
> +    CopyMem (Dev->Dma->Data, Packet->OutDataBuffer, Packet->OutTransferLength);
> +    Request->Sg.BufferContainsData = 1;
> +  }
> +
> +  if (Request->Header.DataLength == 0) {
> +    Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptScsiSendRequest (
> +  IN MPT_SCSI_DEV                                   *Dev,
> +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  if (!Dev->IoReplyEnqueued) {
> +    //
> +    // Put one free reply frame on the reply queue, the hardware may use it to
> +    // report an error to us.
> +    //
> +    Status = Out32 (Dev, MPT_REG_REP_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoReply));
> +    if (EFI_ERROR (Status)) {
> +      return EFI_DEVICE_ERROR;
> +    }
> +    Dev->IoReplyEnqueued = TRUE;
> +  }
> +
> +  Status = Out32 (Dev, MPT_REG_REQ_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoRequest));
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptScsiGetReply (
> +  IN MPT_SCSI_DEV                                   *Dev,
> +  OUT UINT32                                        *Reply
> +  )
> +{
> +  EFI_STATUS Status;
> +  UINT32     Istatus;
> +  UINT32     EmptyReply;
> +
> +  //
> +  // Timeouts are not supported for
> +  // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() in this implementation.
> +  //
> +  for (;;) {
> +    Status = In32 (Dev, MPT_REG_ISTATUS, &Istatus);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    //
> +    // Interrupt raised
> +    //
> +    if (Istatus & MPT_IMASK_REPLY) {
> +      break;
> +    }
> +
> +    gBS->Stall (Dev->StallPerPollUsec);
> +  }
> +
> +  Status = In32 (Dev, MPT_REG_REP_Q, Reply);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // The driver is supposed to fetch replies until 0xffffffff is returned, which
> +  // will reset the interrupt status. We put only one request, so we expect the
> +  // next read reply to be the last.
> +  //
> +  Status = In32 (Dev, MPT_REG_REP_Q, &EmptyReply);
> +  if (EFI_ERROR (Status) || EmptyReply != MAX_UINT32) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MptScsiHandleReply (
> +  IN MPT_SCSI_DEV                                   *Dev,
> +  IN UINT32                                         Reply,
> +  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet
> +  )
> +{
> +  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> +    CopyMem (Packet->InDataBuffer, Dev->Dma->Data, Packet->InTransferLength);
> +  }
> +
> +  if (Reply == Dev->Dma->IoRequest.Data.Header.MessageContext) {
> +    //
> +    // This is a turbo reply, everything is good
> +    //
> +    Packet->SenseDataLength = 0;
> +    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
> +    Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> +
> +  } else if ((Reply & BIT31) != 0) {
> +    DEBUG ((DEBUG_INFO, "%a: Full reply returned\n", __FUNCTION__));

(2) Is this a frequent event? If we expect this to happen frequently,
then it should be DEBUG_VERBOSE. Otherwise (= infrequent event),
DEBUG_INFO is fine.

> +    //
> +    // When reply MSB is set, we got a full reply. Since we submitted only one
> +    // reply frame, we know it's IoReply.
> +    //
> +    Dev->IoReplyEnqueued = FALSE;
> +
> +    Packet->TargetStatus = Dev->Dma->IoReply.Data.ScsiStatus;
> +    //
> +    // Make sure device only lowers SenseDataLength before copying sense
> +    //
> +    ASSERT (Dev->Dma->IoReply.Data.SenseCount <= Packet->SenseDataLength);
> +    Packet->SenseDataLength =
> +      (UINT8)MIN (Dev->Dma->IoReply.Data.SenseCount, Packet->SenseDataLength);
> +    CopyMem (Packet->SenseData, Dev->Dma->Sense, Packet->SenseDataLength);
> +
> +    if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> +      Packet->InTransferLength = Dev->Dma->IoReply.Data.TransferCount;
> +    } else {
> +      Packet->OutTransferLength = Dev->Dma->IoReply.Data.TransferCount;
> +    }
> +
> +    switch (Dev->Dma->IoReply.Data.IocStatus) {
> +    case MPT_SCSI_IOCSTATUS_SUCCESS:
> +      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
> +      break;
> +    case MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE:
> +      Packet->HostAdapterStatus =
> +        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
> +      return EFI_TIMEOUT;
> +    case MPT_SCSI_IOCSTATUS_DATA_UNDERRUN:
> +    case MPT_SCSI_IOCSTATUS_DATA_OVERRUN:
> +      Packet->HostAdapterStatus =
> +        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
> +      break;
> +    default:
> +      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +  } else {
> +    DEBUG ((DEBUG_ERROR, "%a: unexpected reply (%x)\n", __FUNCTION__, Reply));
> +    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> +    return EFI_DEVICE_ERROR;
> +  }

I'm really pleased with the updates to this function. In both the "turbo
reply" and "full reply" cases, we make sure that all 6 of the following
are correctly set on output:

- InTransferLength
- OutTransferLength
- HostAdapterStatus
- TargetStatus
- SenseDataLength
- SenseData

(3) I do have a question about the last branch ("unexpected reply")
though -- would you agree that we should call ReportHostAdapterError()
there, rather than only setting HostAdapterStatus?

Because, per EFI_DEVICE_ERROR, the caller will first consult
HostAdapterStatus, yes, but then (upon seeing "OTHER") it will likely
proceed to TargetStatus and Sense. And we currently leave garbage in
those fields.

(I guess I could have made the same comment under v4, but there I was
hung up on the other output fields in the more common branches. All of
those have been nicely covered in v5, so I've arrived at this last branch.)


> +
> +  return EFI_SUCCESS;
> +}
> +
>  //
>  // Ext SCSI Pass Thru
>  //
> @@ -233,7 +551,33 @@ MptScsiPassThru (
>    IN EFI_EVENT                                      Event     OPTIONAL
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  EFI_STATUS   Status;
> +  MPT_SCSI_DEV *Dev;
> +  UINT32       Reply;
> +
> +  Dev = MPT_SCSI_FROM_PASS_THRU (This);
> +  //
> +  // We only use first byte of target identifer
> +  //
> +  Status = MptScsiPopulateRequest (Dev, *Target, Lun, Packet);
> +  if (EFI_ERROR (Status)) {
> +    //
> +    // MptScsiPopulateRequest modified packet according to the error
> +    //
> +    return Status;
> +  }
> +
> +  Status = MptScsiSendRequest (Dev, Packet);
> +  if (EFI_ERROR (Status)) {
> +    return ReportHostAdapterError (Packet);
> +  }
> +
> +  Status = MptScsiGetReply (Dev, &Reply);
> +  if (EFI_ERROR (Status)) {
> +    return ReportHostAdapterError (Packet);
> +  }
> +
> +  return MptScsiHandleReply (Dev, Reply, Packet);
>  }
>  
>  STATIC
> @@ -488,6 +832,8 @@ MptScsiControllerStart (
>  {
>    EFI_STATUS           Status;
>    MPT_SCSI_DEV         *Dev;
> +  UINTN                Pages;
> +  UINTN                BytesMapped;
>  
>    Dev = AllocateZeroPool (sizeof (*Dev));
>    if (Dev == NULL) {
> @@ -497,6 +843,7 @@ MptScsiControllerStart (
>    Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
>  
>    Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
> +  Dev->StallPerPollUsec = PcdGet32 (PcdMptScsiStallPerPollUsec);
>  
>    Status = gBS->OpenProtocol (
>                    ControllerHandle,
> @@ -557,11 +904,45 @@ MptScsiControllerStart (
>        ));
>    }
>  
> -  Status = MptScsiInit (Dev);
> +  //
> +  // Create buffers for data transfer
> +  //
> +  Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
> +  Status = Dev->PciIo->AllocateBuffer (
> +                         Dev->PciIo,
> +                         AllocateAnyPages,
> +                         EfiBootServicesData,
> +                         Pages,
> +                         (VOID **)&Dev->Dma,
> +                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
> +                         );
>    if (EFI_ERROR (Status)) {
>      goto RestoreAttributes;
>    }
>  
> +  BytesMapped = EFI_PAGES_TO_SIZE (Pages);
> +  Status = Dev->PciIo->Map (
> +                         Dev->PciIo,
> +                         EfiPciIoOperationBusMasterCommonBuffer,
> +                         Dev->Dma,
> +                         &BytesMapped,
> +                         &Dev->DmaPhysical,
> +                         &Dev->DmaMapping
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeBuffer;
> +  }
> +
> +  if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Unmap;
> +  }
> +
> +  Status = MptScsiInit (Dev);
> +  if (EFI_ERROR (Status)) {
> +    goto Unmap;
> +  }
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> @@ -594,6 +975,19 @@ MptScsiControllerStart (
>  UninitDev:
>    MptScsiReset (Dev);
>  
> +Unmap:
> +  Dev->PciIo->Unmap (
> +                Dev->PciIo,
> +                Dev->DmaMapping
> +                );
> +
> +FreeBuffer:
> +  Dev->PciIo->FreeBuffer (
> +                Dev->PciIo,
> +                EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),

(4) Not wrong, but still, please simplify this function call by passing
the local variable "Pages" here.

> +                Dev->Dma
> +                );
> +
>  RestoreAttributes:
>    Dev->PciIo->Attributes (
>                  Dev->PciIo,
> @@ -655,6 +1049,17 @@ MptScsiControllerStop (
>  
>    MptScsiReset (Dev);
>  
> +  Dev->PciIo->Unmap (
> +                Dev->PciIo,
> +                Dev->DmaMapping
> +                );
> +
> +  Dev->PciIo->FreeBuffer (
> +                Dev->PciIo,
> +                EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
> +                Dev->Dma
> +                );
> +
>    Dev->PciIo->Attributes (
>                  Dev->PciIo,
>                  EfiPciIoAttributeOperationSet,
> diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> index 4862ff9dd497..bb89e50e08f0 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> +++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> @@ -37,3 +37,6 @@ [Protocols]
>  
>  [FixedPcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit   ## CONSUMES
> +
> +[Pcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec ## CONSUMES
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 2d09444bbb16..3bf26e8df82d 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -167,6 +167,9 @@ [PcdsFixedAtBuild]
>    #  by ScsiBusDxe.
>    gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
>  
> +  ## Microseconds to stall between polling for MptScsi request result
> +  gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
> +
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
> 

With (1) through (4) addressed:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

(Well, (1) is a must, (2) through (4) are open for discussion, of course.)

Thanks!
Laszlo


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

* Re: [edk2-devel] [PATCH v5 12/12] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices()
  2020-04-24 17:59 ` [PATCH v5 12/12] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices() Nikita Leshenko
@ 2020-04-30  9:48   ` Laszlo Ersek
  0 siblings, 0 replies; 26+ messages in thread
From: Laszlo Ersek @ 2020-04-30  9:48 UTC (permalink / raw)
  To: devel, nikita.leshchenko
  Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel

On 04/24/20 19:59, Nikita Leshenko wrote:
> This causes the device to forget about the reply frame. We allocated the
> reply frame in EfiBootServicesData type memory, and code executing after
> ExitBootServices() is permitted to overwrite it.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  OvmfPkg/MptScsiDxe/MptScsi.c | 33 ++++++++++++++++++++++++++++++++-
>  1 file changed, 32 insertions(+), 1 deletion(-)

Thanks for the update, my R-b stands.

Laszlo

> 
> diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
> index 9cb5088bfbf9..d8649cf45541 100644
> --- a/OvmfPkg/MptScsiDxe/MptScsi.c
> +++ b/OvmfPkg/MptScsiDxe/MptScsi.c
> @@ -57,6 +57,7 @@ typedef struct {
>    UINT32                          StallPerPollUsec;
>    EFI_PCI_IO_PROTOCOL             *PciIo;
>    UINT64                          OriginalPciAttributes;
> +  EFI_EVENT                       ExitBoot;
>    MPT_SCSI_DMA_BUFFER             *Dma;
>    EFI_PHYSICAL_ADDRESS            DmaPhysical;
>    VOID                            *DmaMapping;
> @@ -750,6 +751,20 @@ MptScsiResetChannel (
>    return EFI_UNSUPPORTED;
>  }
>  
> +STATIC
> +VOID
> +EFIAPI
> +MptScsiExitBoot (
> +  IN  EFI_EVENT Event,
> +  IN  VOID      *Context
> +  )
> +{
> +  MPT_SCSI_DEV *Dev;
> +
> +  Dev = Context;
> +  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
> +  MptScsiReset (Dev);
> +}
>  STATIC
>  EFI_STATUS
>  EFIAPI
> @@ -943,6 +958,17 @@ MptScsiControllerStart (
>      goto Unmap;
>    }
>  
> +  Status = gBS->CreateEvent (
> +                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
> +                  TPL_CALLBACK,
> +                  &MptScsiExitBoot,
> +                  Dev,
> +                  &Dev->ExitBoot
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto UninitDev;
> +  }
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> @@ -967,11 +993,14 @@ MptScsiControllerStart (
>                    &Dev->PassThru
>                    );
>    if (EFI_ERROR (Status)) {
> -    goto UninitDev;
> +    goto CloseExitBoot;
>    }
>  
>    return EFI_SUCCESS;
>  
> +CloseExitBoot:
> +  gBS->CloseEvent (Dev->ExitBoot);
> +
>  UninitDev:
>    MptScsiReset (Dev);
>  
> @@ -1047,6 +1076,8 @@ MptScsiControllerStop (
>      return Status;
>    }
>  
> +  gBS->CloseEvent (Dev->ExitBoot);
> +
>    MptScsiReset (Dev);
>  
>    Dev->PciIo->Unmap (
> 


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

* Re: [edk2-devel] [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware
  2020-04-29 14:55   ` [edk2-devel] " Laszlo Ersek
@ 2020-05-04 19:35     ` Nikita Leshenko
  0 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-05-04 19:35 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: devel, liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel



> On 29 Apr 2020, at 17:55, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> On 04/24/20 19:59, Nikita Leshenko wrote:
>> [...]
>> +STATIC
>> +EFI_STATUS
>> +MptScsiInit (
>> +  IN MPT_SCSI_DEV       *Dev
>> +  )
>> +{
>> +  EFI_STATUS                     Status;
>> +  MPT_IO_CONTROLLER_INIT_REQUEST Req;
> 
> [...]
> 
> You can either introduce a new typedef for the alignment / union under
> IndustryStandard, or just define an ad-hoc union here in this function,
> like PvScsiDxe does.
Yes you're right, I missed that, sorry.

> 
> [...]
> "Please use another STATIC_ASSERT here for expressing that the response
> structure size is an integer multiple of sizeof (UINT16)."
Missed that too, sorry
> 
>> [...]
>> //
>> // Ext SCSI Pass Thru
>> //
>> @@ -382,6 +557,11 @@ MptScsiControllerStart (
>>       ));
>>   }
>> 
>> +  Status = MptScsiInit (Dev);
>> +  if (EFI_ERROR (Status)) {
>> +    goto RestoreAttributes;
> 
> Hmmm, git-range-diff flags this as a v4->v5 change, and I don't
> understand why...
> 
> Ah, OK. In v4, we jumped to "RestorePciAttributes" -- which was a
> non-existent label. So I think the v4 variant of this patch didn't
> compile. I hope that's fixed now, with the above. :)
Yes, I ran `git rebase --exec` to make sure that all patches compiled and I noticed that.

Nikita
> 
> The rest of the updates / patch look fine to me.
> 
> Thanks!
> Laszlo
> 
> 
>> +  }
>> +
>>   //
>>   // Host adapter channel, doesn't exist
>>   //
>> @@ -406,11 +586,14 @@ MptScsiControllerStart (
>>                   &Dev->PassThru
>>                   );
>>   if (EFI_ERROR (Status)) {
>> -    goto RestoreAttributes;
>> +    goto UninitDev;
>>   }
>> 
>>   return EFI_SUCCESS;
>> 
>> +UninitDev:
>> +  MptScsiReset (Dev);
>> +
>> RestoreAttributes:
>>   Dev->PciIo->Attributes (
>>                 Dev->PciIo,
>> @@ -470,6 +653,8 @@ MptScsiControllerStop (
>>     return Status;
>>   }
>> 
>> +  MptScsiReset (Dev);
>> +
>>   Dev->PciIo->Attributes (
>>                 Dev->PciIo,
>>                 EfiPciIoAttributeOperationSet,
>> 
> 


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

* Re: [edk2-devel] [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method
  2020-04-30  9:47   ` [edk2-devel] " Laszlo Ersek
@ 2020-05-04 20:08     ` Nikita Leshenko
  0 siblings, 0 replies; 26+ messages in thread
From: Nikita Leshenko @ 2020-05-04 20:08 UTC (permalink / raw)
  To: devel, lersek; +Cc: liran.alon, aaron.young, Jordan Justen, Ard Biesheuvel



> On 30 Apr 2020, at 12:47, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> On 04/24/20 19:59, Nikita Leshenko wrote:
>> Machines should be able to boot after this commit. Tested with different
>> Linux distributions (Ubuntu, CentOS) and different Windows
>> versions (Windows 7, Windows 10, Server 2016).
>> 
>> Ref: https://urldefense.com/v3/__https://bugzilla.tianocore.org/show_bug.cgi?id=2390__;!!GqivPVa7Brio!NV5JGxsOY-LMe9c_r7p1Ks4Jy755ybGf-hewsLI7texgoPDpsKmcin6UpzFlRxCc3tuWtA$ 
>> Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
>> [..]
>> +
>> +  } else if ((Reply & BIT31) != 0) {
>> +    DEBUG ((DEBUG_INFO, "%a: Full reply returned\n", __FUNCTION__));
> 
> (2) Is this a frequent event? If we expect this to happen frequently,
> then it should be DEBUG_VERBOSE. Otherwise (= infrequent event),
> DEBUG_INFO is fine.
In practice this event happens on IO errors, so I assume it won't be frequent,
that's why I put it in INFO.
> 
>> [...]
>>   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>>   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>>   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
>> 
> 
> With (1) through (4) addressed:
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> (Well, (1) is a must, (2) through (4) are open for discussion, of course.)
Agree with (3) and (4). I think that the DEBUG_INFO is fine, but I don't mind
changing it to VERBOSE.

Nikita
> 
> Thanks!
> Laszlo
> 
> 
> 
> 


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

end of thread, other threads:[~2020-05-04 20:08 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-24 17:59 [PATCH v5 00/12] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 01/12] OvmfPkg/MptScsiDxe: Create empty driver Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 02/12] OvmfPkg/MptScsiDxe: Install DriverBinding Protocol Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 03/12] OvmfPkg/MptScsiDxe: Report name of driver Nikita Leshenko
2020-04-24 18:02   ` [edk2-devel] " Carsey, Jaben
2020-04-25 10:44     ` Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 04/12] OvmfPkg/MptScsiDxe: Probe PCI devices and look for MptScsi Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 05/12] OvmfPkg/MptScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 06/12] OvmfPkg/MptScsiDxe: Report targets and one LUN Nikita Leshenko
2020-04-29 13:38   ` [edk2-devel] " Laszlo Ersek
2020-04-29 13:39     ` Laszlo Ersek
2020-04-29 14:45       ` Liran Alon
2020-04-29 18:10         ` Laszlo Ersek
2020-04-24 17:59 ` [PATCH v5 07/12] OvmfPkg/MptScsiDxe: Build and decode DevicePath Nikita Leshenko
2020-04-29 13:44   ` [edk2-devel] " Laszlo Ersek
2020-04-24 17:59 ` [PATCH v5 08/12] OvmfPkg/MptScsiDxe: Open PciIo protocol for later use Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 09/12] OvmfPkg/MptScsiDxe: Set and restore PCI attributes Nikita Leshenko
2020-04-29 13:50   ` [edk2-devel] " Laszlo Ersek
2020-04-24 17:59 ` [PATCH v5 10/12] OvmfPkg/MptScsiDxe: Initialize hardware Nikita Leshenko
2020-04-29 14:55   ` [edk2-devel] " Laszlo Ersek
2020-05-04 19:35     ` Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 11/12] OvmfPkg/MptScsiDxe: Implement the PassThru method Nikita Leshenko
2020-04-30  9:47   ` [edk2-devel] " Laszlo Ersek
2020-05-04 20:08     ` Nikita Leshenko
2020-04-24 17:59 ` [PATCH v5 12/12] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices() Nikita Leshenko
2020-04-30  9:48   ` [edk2-devel] " Laszlo Ersek

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