public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 0/1] Use PCI_DEVICE_PPI to manage Nvme device
@ 2022-08-30  5:46 chenxia1
  2022-08-30  5:46 ` [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: " chenxia1
  0 siblings, 1 reply; 4+ messages in thread
From: chenxia1 @ 2022-08-30  5:46 UTC (permalink / raw)
  To: devel; +Cc: Xiao X Chen

This change modifies NvmExpressPei library to allow usage EDKII_PCI_DEVICE_PPI to manage Nvme device.
For now, the part that performs the enumeration and creates EDKII_PCI_DEVICE_PPI will be implemented in the silicon code.
Sample code can be seen here: https://github.com/mczaj/edk2-platforms/commit/d443062e58f9fba228869b54f2546d9735b3b506

unit test:
 - verified the origin EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI flow in platform project, 
   Nvme controller can successful initialize.
 - merged https://github.com/mczaj/edk2-platforms/commit/d443062e58f9fba228869b54f2546d9735b3b506 to platform project
   to enumerate pcie device and create the EDKII_PCI_DEVICE_PPI for Nvme, 
   Nvme controller also can successful initialize by EDKII_PCI_DEVICE_PPI.
 
v1: https://edk2.groups.io/g/devel/topic/93340344

v2 changes:
 - add the unit test information for cover letter
 - refine the BAR type check for no.1 commit

Xiao X Chen (1):
  MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device

 .../Bus/Pci/NvmExpressPei/DevicePath.c        |  44 --
 .../Bus/Pci/NvmExpressPei/NvmExpressPei.c     | 639 ++++++++++++------
 .../Bus/Pci/NvmExpressPei/NvmExpressPei.h     |  54 ++
 .../Bus/Pci/NvmExpressPei/NvmExpressPei.inf   |   3 +-
 4 files changed, 488 insertions(+), 252 deletions(-)

-- 
2.37.0.windows.1


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

* [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
  2022-08-30  5:46 [PATCH v2 0/1] Use PCI_DEVICE_PPI to manage Nvme device chenxia1
@ 2022-08-30  5:46 ` chenxia1
  2022-08-30  6:27   ` Wu, Hao A
  0 siblings, 1 reply; 4+ messages in thread
From: chenxia1 @ 2022-08-30  5:46 UTC (permalink / raw)
  To: devel; +Cc: Xiao X Chen, Hao A Wu, Ray Ni

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

This change modifies NvmExpressPei library
to allow usage both EDKII_PCI_DEVICE_PPI and
EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI to manage Nvme device.

Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Xiao X Chen <xiao.x.chen@intel.com>
---
 .../Bus/Pci/NvmExpressPei/DevicePath.c        |  44 --
 .../Bus/Pci/NvmExpressPei/NvmExpressPei.c     | 639 ++++++++++++------
 .../Bus/Pci/NvmExpressPei/NvmExpressPei.h     |  54 ++
 .../Bus/Pci/NvmExpressPei/NvmExpressPei.inf   |   3 +-
 4 files changed, 488 insertions(+), 252 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
index 9b454a7dd8f4..307045be70ea 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
@@ -37,50 +37,6 @@ EFI_DEVICE_PATH_PROTOCOL  mNvmeEndDevicePathNodeTemplate = {
   }
 };
 
-/**
-  Returns the 16-bit Length field of a device path node.
-
-  Returns the 16-bit Length field of the device path node specified by Node.
-  Node is not required to be aligned on a 16-bit boundary, so it is recommended
-  that a function such as ReadUnaligned16() be used to extract the contents of
-  the Length field.
-
-  If Node is NULL, then ASSERT().
-
-  @param  Node      A pointer to a device path node data structure.
-
-  @return The 16-bit Length field of the device path node specified by Node.
-
-**/
-UINTN
-DevicePathNodeLength (
-  IN CONST VOID  *Node
-  )
-{
-  ASSERT (Node != NULL);
-  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
-}
-
-/**
-  Returns a pointer to the next node in a device path.
-
-  If Node is NULL, then ASSERT().
-
-  @param  Node    A pointer to a device path node data structure.
-
-  @return a pointer to the device path node that follows the device path node
-  specified by Node.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-NextDevicePathNode (
-  IN CONST VOID  *Node
-  )
-{
-  ASSERT (Node != NULL);
-  return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength (Node));
-}
-
 /**
   Get the size of the current device path instance.
 
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
index 2d6a79028fcd..0d02c2785da7 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
@@ -40,6 +40,18 @@ EFI_PEI_NOTIFY_DESCRIPTOR  mNvmeEndOfPeiNotifyListTemplate = {
   NvmePeimEndOfPei
 };
 
+EFI_PEI_NOTIFY_DESCRIPTOR  mNvmeHostControllerNotify = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiPeiNvmExpressHostControllerPpiGuid,
+  NvmeHostControllerPpiInstallationCallback
+};
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mPciDevicePpiNotify = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiPeiPciDevicePpiGuid,
+  NvmePciDevicePpiInstallationCallback
+};
+
 /**
   Check if the specified Nvm Express device namespace is active, and then get the Identify
   Namespace data.
@@ -212,30 +224,27 @@ NvmePeimEndOfPei (
 }
 
 /**
-  Entry point of the PEIM.
+  Initialize and install PrivateData PPIs.
 
-  @param[in] FileHandle     Handle of the file being invoked.
-  @param[in] PeiServices    Describes the list of possible PEI Services.
-
-  @retval EFI_SUCCESS    PPI successfully installed.
+  @param[in] MmioBase            MMIO base address of specific Nvme controller
+  @param[in] DevicePath          A pointer to the EFI_DEVICE_PATH_PROTOCOL
+                                 structure.
+  @param[in] DevicePathLength    Length of the device path.
 
+  @retval EFI_SUCCESS  Nvme controller initialized and PPIs installed
+  @retval others       Failed to initialize Nvme controller
 **/
 EFI_STATUS
-EFIAPI
-NvmExpressPeimEntry (
-  IN EFI_PEI_FILE_HANDLE     FileHandle,
-  IN CONST EFI_PEI_SERVICES  **PeiServices
+NvmeInitPrivateData (
+  IN UINTN                     MmioBase,
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+  IN UINTN                     DevicePathLength
   )
 {
-  EFI_STATUS                             Status;
-  EFI_BOOT_MODE                          BootMode;
-  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi;
-  UINT8                                  Controller;
-  UINTN                                  MmioBase;
-  UINTN                                  DevicePathLength;
-  EFI_DEVICE_PATH_PROTOCOL               *DevicePath;
-  PEI_NVME_CONTROLLER_PRIVATE_DATA       *Private;
-  EFI_PHYSICAL_ADDRESS                   DeviceAddress;
+  EFI_STATUS                        Status;
+  EFI_BOOT_MODE                     BootMode;
+  PEI_NVME_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PHYSICAL_ADDRESS              DeviceAddress;
 
   DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
 
@@ -249,19 +258,358 @@ NvmExpressPeimEntry (
   }
 
   //
-  // Locate the NVME host controller PPI
+  // Check validity of the device path of the NVM Express controller.
   //
-  Status = PeiServicesLocatePpi (
-             &gEdkiiPeiNvmExpressHostControllerPpiGuid,
-             0,
-             NULL,
-             (VOID **)&NvmeHcPpi
+  Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: The device path is invalid for Controller %d.\n",
+      __FUNCTION__
+      ));
+    return Status;
+  }
+
+  //
+  // For S3 resume performance consideration, not all NVM Express controllers
+  // will be initialized. The driver consumes the content within
+  // S3StorageDeviceInitList LockBox to see if a controller will be skipped
+  // during S3 resume.
+  //
+  if ((BootMode == BOOT_ON_S3_RESUME) &&
+      (NvmeS3SkipThisController (DevicePath, DevicePathLength)))
+  {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: skipped during S3.\n",
+      __FUNCTION__
+      ));
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Memory allocation for controller private data
+  //
+  Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
+  if (Private == NULL) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Fail to allocate private data.\n",
+      __FUNCTION__
+      ));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Memory allocation for transfer-related data
+  //
+  Status = IoMmuAllocateBuffer (
+             NVME_MEM_MAX_PAGES,
+             &Private->Buffer,
+             &DeviceAddress,
+             &Private->BufferMapping
              );
   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n", __FUNCTION__));
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Fail to allocate DMA buffers.\n",
+      __FUNCTION__
+      ));
+    return Status;
+  }
+
+  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
+  DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));
+
+  //
+  // Initialize controller private data
+  //
+  Private->Signature        = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
+  Private->MmioBase         = MmioBase;
+  Private->DevicePathLength = DevicePathLength;
+  Private->DevicePath       = DevicePath;
+
+  //
+  // Initialize the NVME controller
+  //
+  Status = NvmeControllerInit (Private);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Controller initialization fail with Status - %r.\n",
+      __FUNCTION__,
+      Status
+      ));
+    NvmeFreeDmaResource (Private);
+    return Status;
+  }
+
+  //
+  // Enumerate the NVME namespaces on the controller
+  //
+  Status = NvmeDiscoverNamespaces (Private);
+  if (EFI_ERROR (Status)) {
+    //
+    // No active namespace was found on the controller
+    //
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Namespaces discovery fail with Status - %r.\n",
+      __FUNCTION__,
+      Status
+      ));
+    NvmeFreeDmaResource (Private);
+    return Status;
+  }
+
+  //
+  // Nvm Express Pass Thru PPI
+  //
+  Private->PassThruMode.Attributes = EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
+                                     EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL |
+                                     EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
+  Private->PassThruMode.IoAlign             = sizeof (UINTN);
+  Private->PassThruMode.NvmeVersion         = EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
+  Private->NvmePassThruPpi.Mode             = &Private->PassThruMode;
+  Private->NvmePassThruPpi.GetDevicePath    = NvmePassThruGetDevicePath;
+  Private->NvmePassThruPpi.GetNextNameSpace = NvmePassThruGetNextNameSpace;
+  Private->NvmePassThruPpi.PassThru         = NvmePassThru;
+  CopyMem (
+    &Private->NvmePassThruPpiList,
+    &mNvmePassThruPpiListTemplate,
+    sizeof (EFI_PEI_PPI_DESCRIPTOR)
+    );
+  Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
+  PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
+
+  //
+  // Block Io PPI
+  //
+  Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;
+  Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
+  Private->BlkIoPpi.ReadBlocks              = NvmeBlockIoPeimReadBlocks;
+  CopyMem (
+    &Private->BlkIoPpiList,
+    &mNvmeBlkIoPpiListTemplate,
+    sizeof (EFI_PEI_PPI_DESCRIPTOR)
+    );
+  Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
+
+  Private->BlkIo2Ppi.Revision                = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
+  Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;
+  Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
+  Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
+  CopyMem (
+    &Private->BlkIo2PpiList,
+    &mNvmeBlkIo2PpiListTemplate,
+    sizeof (EFI_PEI_PPI_DESCRIPTOR)
+    );
+  Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
+  PeiServicesInstallPpi (&Private->BlkIoPpiList);
+
+  //
+  // Check if the NVME controller supports the Security Receive/Send commands
+  //
+  if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: Security Security Command PPI will be produced.\n",
+      __FUNCTION__
+      ));
+    Private->StorageSecurityPpi.Revision           = EDKII_STORAGE_SECURITY_PPI_REVISION;
+    Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;
+    Private->StorageSecurityPpi.GetDevicePath      = NvmeStorageSecurityGetDevicePath;
+    Private->StorageSecurityPpi.ReceiveData        = NvmeStorageSecurityReceiveData;
+    Private->StorageSecurityPpi.SendData           = NvmeStorageSecuritySendData;
+    CopyMem (
+      &Private->StorageSecurityPpiList,
+      &mNvmeStorageSecurityPpiListTemplate,
+      sizeof (EFI_PEI_PPI_DESCRIPTOR)
+      );
+    Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
+    PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
+  }
+
+  CopyMem (
+    &Private->EndOfPeiNotifyList,
+    &mNvmeEndOfPeiNotifyListTemplate,
+    sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
+    );
+  PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize Nvme controller from fiven PCI_DEVICE_PPI.
+
+  @param[in] PciDevice  Pointer to the PCI Device PPI instance.
+
+  @retval EFI_SUCCESS      The function completes successfully
+  @retval Others           Cannot initialize Nvme controller for given device
+**/
+EFI_STATUS
+NvmeInitControllerDataFromPciDevice (
+  EDKII_PCI_DEVICE_PPI  *PciDevice
+  )
+{
+  EFI_STATUS                Status;
+  PCI_TYPE00                PciData;
+  UINTN                     MmioBase;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     DevicePathLength;
+  UINT64                    EnabledPciAttributes;
+  UINT32                    MmioBaseH;
+
+  //
+  // Now further check the PCI header: Base Class (offset 0x0B), Sub Class (offset 0x0A) and
+  // Programming Interface (offset 0x09). This controller should be an Nvme controller
+  //
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint8,
+                                  PCI_CLASSCODE_OFFSET,
+                                  sizeof (PciData.Hdr.ClassCode),
+                                  PciData.Hdr.ClassCode
+                                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (!IS_PCI_NVMHCI (&PciData)) {
     return EFI_UNSUPPORTED;
   }
 
+  Status = PciDevice->PciIo.Attributes (
+                              &PciDevice->PciIo,
+                              EfiPciIoAttributeOperationSupported,
+                              0,
+                              &EnabledPciAttributes
+                              );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  } else {
+    EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+    Status                = PciDevice->PciIo.Attributes (
+                                               &PciDevice->PciIo,
+                                               EfiPciIoAttributeOperationEnable,
+                                               EnabledPciAttributes,
+                                               NULL
+                                               );
+    if (EFI_ERROR (Status)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint32,
+                                  PCI_BASE_ADDRESSREG_OFFSET,
+                                  1,
+                                  &MmioBase
+                                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  switch (MmioBase & 0x07) {
+    case 0x0:
+      //
+      // Memory space for 32 bit bar address
+      //
+      MmioBase = MmioBase & 0xFFFFFFF0;
+      break;
+    case 0x4:
+      //
+      // For 64 bit bar address, read the high 32bits of this 64 bit bar
+      //
+      Status = PciDevice->PciIo.Pci.Read (
+                                      &PciDevice->PciIo,
+                                      EfiPciIoWidthUint32,
+                                      PCI_BASE_ADDRESSREG_OFFSET + 4,
+                                      1,
+                                      &MmioBaseH
+                                      );
+      //
+      // For 32 bit environment, high 32bits of the bar should be zero.
+      //
+      if (  EFI_ERROR (Status)
+         || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
+      {
+        return EFI_UNSUPPORTED;
+      }
+
+      MmioBase  = MmioBase & 0xFFFFFFF0;
+      MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
+      break;
+    default:
+      //
+      // Unknown bar type
+      //
+      return EFI_UNSUPPORTED;
+  }
+
+  DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
+  DevicePath       = PciDevice->DevicePath;
+
+  Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: Failed to init controller, with Status - %r\n",
+      __FUNCTION__,
+      Status
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Callback for EDKII_PCI_DEVICE_PPI installation.
+
+  @param[in] PeiServices         Pointer to PEI Services Table.
+  @param[in] NotifyDescriptor    Pointer to the descriptor for the Notification
+                                 event that caused this function to execute.
+  @param[in] Ppi                 Pointer to the PPI data associated with this function.
+
+  @retval EFI_SUCCESS            The function completes successfully
+  @retval Others                 Cannot initialize Nvme controller from given PCI_DEVICE_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmePciDevicePpiInstallationCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EDKII_PCI_DEVICE_PPI  *PciDevice;
+
+  PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
+
+  return NvmeInitControllerDataFromPciDevice (PciDevice);
+}
+
+/**
+  Initialize Nvme controller from EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
+
+  @param[in] NvmeHcPpi  Pointer to the Nvme Host Controller PPI instance.
+
+  @retval EFI_SUCCESS   PPI successfully installed.
+**/
+EFI_STATUS
+NvmeInitControllerFromHostControllerPpi (
+  IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi
+  )
+{
+  UINT8                     Controller;
+  UINTN                     MmioBase;
+  UINTN                     DevicePathLength;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_STATUS                Status;
+
   Controller = 0;
   MmioBase   = 0;
   while (TRUE) {
@@ -293,88 +641,7 @@ NvmExpressPeimEntry (
       return Status;
     }
 
-    //
-    // Check validity of the device path of the NVM Express controller.
-    //
-    Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: The device path is invalid for Controller %d.\n",
-        __FUNCTION__,
-        Controller
-        ));
-      Controller++;
-      continue;
-    }
-
-    //
-    // For S3 resume performance consideration, not all NVM Express controllers
-    // will be initialized. The driver consumes the content within
-    // S3StorageDeviceInitList LockBox to see if a controller will be skipped
-    // during S3 resume.
-    //
-    if ((BootMode == BOOT_ON_S3_RESUME) &&
-        (NvmeS3SkipThisController (DevicePath, DevicePathLength)))
-    {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: Controller %d is skipped during S3.\n",
-        __FUNCTION__,
-        Controller
-        ));
-      Controller++;
-      continue;
-    }
-
-    //
-    // Memory allocation for controller private data
-    //
-    Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
-    if (Private == NULL) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: Fail to allocate private data for Controller %d.\n",
-        __FUNCTION__,
-        Controller
-        ));
-      return EFI_OUT_OF_RESOURCES;
-    }
-
-    //
-    // Memory allocation for transfer-related data
-    //
-    Status = IoMmuAllocateBuffer (
-               NVME_MEM_MAX_PAGES,
-               &Private->Buffer,
-               &DeviceAddress,
-               &Private->BufferMapping
-               );
-    if (EFI_ERROR (Status)) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: Fail to allocate DMA buffers for Controller %d.\n",
-        __FUNCTION__,
-        Controller
-        ));
-      return Status;
-    }
-
-    ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
-    DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));
-
-    //
-    // Initialize controller private data
-    //
-    Private->Signature        = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
-    Private->MmioBase         = MmioBase;
-    Private->DevicePathLength = DevicePathLength;
-    Private->DevicePath       = DevicePath;
-
-    //
-    // Initialize the NVME controller
-    //
-    Status = NvmeControllerInit (Private);
+    Status = NvmeInitPrivateData (MmioBase, DevicePath, DevicePathLength);
     if (EFI_ERROR (Status)) {
       DEBUG ((
         DEBUG_ERROR,
@@ -383,115 +650,73 @@ NvmExpressPeimEntry (
         Controller,
         Status
         ));
-      NvmeFreeDmaResource (Private);
-      Controller++;
-      continue;
-    }
-
-    //
-    // Enumerate the NVME namespaces on the controller
-    //
-    Status = NvmeDiscoverNamespaces (Private);
-    if (EFI_ERROR (Status)) {
-      //
-      // No active namespace was found on the controller
-      //
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
-        __FUNCTION__,
-        Controller,
-        Status
-        ));
-      NvmeFreeDmaResource (Private);
-      Controller++;
-      continue;
-    }
-
-    //
-    // Nvm Express Pass Thru PPI
-    //
-    Private->PassThruMode.Attributes = EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
-                                       EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL |
-                                       EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
-    Private->PassThruMode.IoAlign             = sizeof (UINTN);
-    Private->PassThruMode.NvmeVersion         = EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
-    Private->NvmePassThruPpi.Mode             = &Private->PassThruMode;
-    Private->NvmePassThruPpi.GetDevicePath    = NvmePassThruGetDevicePath;
-    Private->NvmePassThruPpi.GetNextNameSpace = NvmePassThruGetNextNameSpace;
-    Private->NvmePassThruPpi.PassThru         = NvmePassThru;
-    CopyMem (
-      &Private->NvmePassThruPpiList,
-      &mNvmePassThruPpiListTemplate,
-      sizeof (EFI_PEI_PPI_DESCRIPTOR)
-      );
-    Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
-    PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
-
-    //
-    // Block Io PPI
-    //
-    Private->BlkIoPpi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo;
-    Private->BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
-    Private->BlkIoPpi.ReadBlocks              = NvmeBlockIoPeimReadBlocks;
-    CopyMem (
-      &Private->BlkIoPpiList,
-      &mNvmeBlkIoPpiListTemplate,
-      sizeof (EFI_PEI_PPI_DESCRIPTOR)
-      );
-    Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
-
-    Private->BlkIo2Ppi.Revision                = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
-    Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;
-    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
-    Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
-    CopyMem (
-      &Private->BlkIo2PpiList,
-      &mNvmeBlkIo2PpiListTemplate,
-      sizeof (EFI_PEI_PPI_DESCRIPTOR)
-      );
-    Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
-    PeiServicesInstallPpi (&Private->BlkIoPpiList);
-
-    //
-    // Check if the NVME controller supports the Security Receive/Send commands
-    //
-    if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
+    } else {
       DEBUG ((
         DEBUG_INFO,
-        "%a: Security Security Command PPI will be produced for Controller %d.\n",
+        "%a: Controller %d has been successfully initialized.\n",
         __FUNCTION__,
         Controller
         ));
-      Private->StorageSecurityPpi.Revision           = EDKII_STORAGE_SECURITY_PPI_REVISION;
-      Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;
-      Private->StorageSecurityPpi.GetDevicePath      = NvmeStorageSecurityGetDevicePath;
-      Private->StorageSecurityPpi.ReceiveData        = NvmeStorageSecurityReceiveData;
-      Private->StorageSecurityPpi.SendData           = NvmeStorageSecuritySendData;
-      CopyMem (
-        &Private->StorageSecurityPpiList,
-        &mNvmeStorageSecurityPpiListTemplate,
-        sizeof (EFI_PEI_PPI_DESCRIPTOR)
-        );
-      Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
-      PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
     }
 
-    CopyMem (
-      &Private->EndOfPeiNotifyList,
-      &mNvmeEndOfPeiNotifyListTemplate,
-      sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
-      );
-    PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
-
-    DEBUG ((
-      DEBUG_INFO,
-      "%a: Controller %d has been successfully initialized.\n",
-      __FUNCTION__,
-      Controller
-      ));
     Controller++;
   }
 
   return EFI_SUCCESS;
 }
+
+/**
+  Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
+
+  @param[in] PeiServices         Pointer to PEI Services Table.
+  @param[in] NotifyDescriptor    Pointer to the descriptor for the Notification
+                                 event that caused this function to execute.
+  @param[in] Ppi                 Pointer to the PPI data associated with this function.
+
+  @retval EFI_SUCCESS            The function completes successfully
+  @retval Others                 Cannot initialize Nvme controller from given EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeHostControllerPpiInstallationCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi;
+
+  if (Ppi == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
+
+  return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi);
+}
+
+/**
+  Entry point of the PEIM.
+
+  @param[in] FileHandle     Handle of the file being invoked.
+  @param[in] PeiServices    Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS    PPI successfully installed.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressPeimEntry (
+  IN EFI_PEI_FILE_HANDLE     FileHandle,
+  IN CONST EFI_PEI_SERVICES  **PeiServices
+  )
+{
+  DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
+
+  PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
+
+  PeiServicesNotifyPpi (&mPciDevicePpiNotify);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
index 78a6b7016503..12a7624099c0 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
@@ -14,6 +14,7 @@
 #include <PiPei.h>
 
 #include <IndustryStandard/Nvme.h>
+#include <IndustryStandard/Pci.h>
 
 #include <Ppi/NvmExpressHostController.h>
 #include <Ppi/BlockIo.h>
@@ -22,6 +23,7 @@
 #include <Ppi/NvmExpressPassThru.h>
 #include <Ppi/IoMmu.h>
 #include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/PciDevice.h>
 
 #include <Library/DebugLib.h>
 #include <Library/PeiServicesLib.h>
@@ -29,6 +31,7 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/IoLib.h>
 #include <Library/TimerLib.h>
+#include <Library/DevicePathLib.h>
 
 //
 // Structure forward declarations
@@ -36,6 +39,17 @@
 typedef struct _PEI_NVME_NAMESPACE_INFO           PEI_NVME_NAMESPACE_INFO;
 typedef struct _PEI_NVME_CONTROLLER_PRIVATE_DATA  PEI_NVME_CONTROLLER_PRIVATE_DATA;
 
+/**
+  Macro that checks whether device is a NVMHCI Interface.
+
+  @param  _p      Specified device.
+
+  @retval TRUE    Device is a NVMHCI Interface.
+  @retval FALSE   Device is not a NVMHCI Interface.
+
+**/
+#define IS_PCI_NVMHCI(_p)  IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SOLID_STATE, PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI)
+
 #include "NvmExpressPeiHci.h"
 #include "NvmExpressPeiPassThru.h"
 #include "NvmExpressPeiBlockIo.h"
@@ -345,4 +359,44 @@ NvmeS3SkipThisController (
   IN  UINTN                     HcDevicePathLength
   );
 
+/**
+  Callback for EDKII_PCI_DEVICE_PPI installation.
+
+  @param[in] PeiServices         Pointer to PEI Services Table.
+  @param[in] NotifyDescriptor    Pointer to the descriptor for the Notification
+                                 event that caused this function to execute.
+  @param[in] Ppi                 Pointer to the PPI data associated with this function.
+
+  @retval EFI_SUCCESS            The function completes successfully
+  @retval Others                 Cannot initialize Nvme controller from given PCI_DEVICE_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmePciDevicePpiInstallationCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  );
+
+/**
+  Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
+
+  @param[in] PeiServices         Pointer to PEI Services Table.
+  @param[in] NotifyDescriptor    Pointer to the descriptor for the Notification
+                                 event that caused this function to execute.
+  @param[in] Ppi                 Pointer to the PPI data associated with this function.
+
+  @retval EFI_SUCCESS            The function completes successfully
+  @retval Others                 Cannot initialize Nvme controller from given EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeHostControllerPpiInstallationCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  );
+
 #endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
index 4dd6c5704fa3..ba6f1afbf168 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
@@ -44,6 +44,7 @@
 
 [LibraryClasses]
   DebugLib
+  DevicePathLib
   PeiServicesLib
   MemoryAllocationLib
   BaseMemoryLib
@@ -56,6 +57,7 @@
   gEdkiiPeiNvmExpressHostControllerPpiGuid       ## CONSUMES
   gEdkiiIoMmuPpiGuid                             ## CONSUMES
   gEfiEndOfPeiSignalPpiGuid                      ## CONSUMES
+  gEdkiiPeiPciDevicePpiGuid                      ## CONSUMES
   gEdkiiPeiNvmExpressPassThruPpiGuid             ## SOMETIMES_PRODUCES
   gEfiPeiVirtualBlockIoPpiGuid                   ## SOMETIMES_PRODUCES
   gEfiPeiVirtualBlockIo2PpiGuid                  ## SOMETIMES_PRODUCES
@@ -66,7 +68,6 @@
 
 [Depex]
   gEfiPeiMemoryDiscoveredPpiGuid AND
-  gEdkiiPeiNvmExpressHostControllerPpiGuid AND
   gEfiPeiMasterBootModePpiGuid
 
 [UserExtensions.TianoCore."ExtraFiles"]
-- 
2.37.0.windows.1


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

* Re: [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
  2022-08-30  5:46 ` [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: " chenxia1
@ 2022-08-30  6:27   ` Wu, Hao A
  2022-09-01  5:33     ` [edk2-devel] " Wu, Hao A
  0 siblings, 1 reply; 4+ messages in thread
From: Wu, Hao A @ 2022-08-30  6:27 UTC (permalink / raw)
  To: Chen, Xiao X, devel@edk2.groups.io; +Cc: Ni, Ray

Thanks.
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>

Will wait a couple of days before merging to see if comments from other reviewers.

Best Regards,
Hao Wu

> -----Original Message-----
> From: Chen, Xiao X <xiao.x.chen@intel.com>
> Sent: Tuesday, August 30, 2022 1:47 PM
> To: devel@edk2.groups.io
> Cc: Chen, Xiao X <xiao.x.chen@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> Subject: [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use
> PCI_DEVICE_PPI to manage Nvme device
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=4017
> 
> This change modifies NvmExpressPei library to allow usage both
> EDKII_PCI_DEVICE_PPI and EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> to manage Nvme device.
> 
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Signed-off-by: Xiao X Chen <xiao.x.chen@intel.com>
> ---
>  .../Bus/Pci/NvmExpressPei/DevicePath.c        |  44 --
>  .../Bus/Pci/NvmExpressPei/NvmExpressPei.c     | 639 ++++++++++++------
>  .../Bus/Pci/NvmExpressPei/NvmExpressPei.h     |  54 ++
>  .../Bus/Pci/NvmExpressPei/NvmExpressPei.inf   |   3 +-
>  4 files changed, 488 insertions(+), 252 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> index 9b454a7dd8f4..307045be70ea 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> @@ -37,50 +37,6 @@ EFI_DEVICE_PATH_PROTOCOL
> mNvmeEndDevicePathNodeTemplate = {
>    }
>  };
> 
> -/**
> -  Returns the 16-bit Length field of a device path node.
> -
> -  Returns the 16-bit Length field of the device path node specified by Node.
> -  Node is not required to be aligned on a 16-bit boundary, so it is
> recommended
> -  that a function such as ReadUnaligned16() be used to extract the contents
> of
> -  the Length field.
> -
> -  If Node is NULL, then ASSERT().
> -
> -  @param  Node      A pointer to a device path node data structure.
> -
> -  @return The 16-bit Length field of the device path node specified by Node.
> -
> -**/
> -UINTN
> -DevicePathNodeLength (
> -  IN CONST VOID  *Node
> -  )
> -{
> -  ASSERT (Node != NULL);
> -  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL
> *)(Node))->Length[0]); -}
> -
> -/**
> -  Returns a pointer to the next node in a device path.
> -
> -  If Node is NULL, then ASSERT().
> -
> -  @param  Node    A pointer to a device path node data structure.
> -
> -  @return a pointer to the device path node that follows the device path
> node
> -  specified by Node.
> -
> -**/
> -EFI_DEVICE_PATH_PROTOCOL *
> -NextDevicePathNode (
> -  IN CONST VOID  *Node
> -  )
> -{
> -  ASSERT (Node != NULL);
> -  return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) +
> DevicePathNodeLength (Node)); -}
> -
>  /**
>    Get the size of the current device path instance.
> 
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> index 2d6a79028fcd..0d02c2785da7 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> @@ -40,6 +40,18 @@ EFI_PEI_NOTIFY_DESCRIPTOR
> mNvmeEndOfPeiNotifyListTemplate = {
>    NvmePeimEndOfPei
>  };
> 
> +EFI_PEI_NOTIFY_DESCRIPTOR  mNvmeHostControllerNotify = {
> +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> +  NvmeHostControllerPpiInstallationCallback
> +};
> +
> +EFI_PEI_NOTIFY_DESCRIPTOR  mPciDevicePpiNotify = {
> +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEdkiiPeiPciDevicePpiGuid,
> +  NvmePciDevicePpiInstallationCallback
> +};
> +
>  /**
>    Check if the specified Nvm Express device namespace is active, and then
> get the Identify
>    Namespace data.
> @@ -212,30 +224,27 @@ NvmePeimEndOfPei (  }
> 
>  /**
> -  Entry point of the PEIM.
> +  Initialize and install PrivateData PPIs.
> 
> -  @param[in] FileHandle     Handle of the file being invoked.
> -  @param[in] PeiServices    Describes the list of possible PEI Services.
> -
> -  @retval EFI_SUCCESS    PPI successfully installed.
> +  @param[in] MmioBase            MMIO base address of specific Nvme
> controller
> +  @param[in] DevicePath          A pointer to the
> EFI_DEVICE_PATH_PROTOCOL
> +                                 structure.
> +  @param[in] DevicePathLength    Length of the device path.
> 
> +  @retval EFI_SUCCESS  Nvme controller initialized and PPIs installed
> +  @retval others       Failed to initialize Nvme controller
>  **/
>  EFI_STATUS
> -EFIAPI
> -NvmExpressPeimEntry (
> -  IN EFI_PEI_FILE_HANDLE     FileHandle,
> -  IN CONST EFI_PEI_SERVICES  **PeiServices
> +NvmeInitPrivateData (
> +  IN UINTN                     MmioBase,
> +  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
> +  IN UINTN                     DevicePathLength
>    )
>  {
> -  EFI_STATUS                             Status;
> -  EFI_BOOT_MODE                          BootMode;
> -  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi;
> -  UINT8                                  Controller;
> -  UINTN                                  MmioBase;
> -  UINTN                                  DevicePathLength;
> -  EFI_DEVICE_PATH_PROTOCOL               *DevicePath;
> -  PEI_NVME_CONTROLLER_PRIVATE_DATA       *Private;
> -  EFI_PHYSICAL_ADDRESS                   DeviceAddress;
> +  EFI_STATUS                        Status;
> +  EFI_BOOT_MODE                     BootMode;
> +  PEI_NVME_CONTROLLER_PRIVATE_DATA  *Private;
> +  EFI_PHYSICAL_ADDRESS              DeviceAddress;
> 
>    DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> 
> @@ -249,19 +258,358 @@ NvmExpressPeimEntry (
>    }
> 
>    //
> -  // Locate the NVME host controller PPI
> +  // Check validity of the device path of the NVM Express controller.
>    //
> -  Status = PeiServicesLocatePpi (
> -             &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> -             0,
> -             NULL,
> -             (VOID **)&NvmeHcPpi
> +  Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);  if
> + (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: The device path is invalid for Controller %d.\n",
> +      __FUNCTION__
> +      ));
> +    return Status;
> +  }
> +
> +  //
> +  // For S3 resume performance consideration, not all NVM Express
> + controllers  // will be initialized. The driver consumes the content
> + within  // S3StorageDeviceInitList LockBox to see if a controller will
> + be skipped  // during S3 resume.
> +  //
> +  if ((BootMode == BOOT_ON_S3_RESUME) &&
> +      (NvmeS3SkipThisController (DevicePath, DevicePathLength)))  {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: skipped during S3.\n",
> +      __FUNCTION__
> +      ));
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // Memory allocation for controller private data  //  Private =
> + AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> +  if (Private == NULL) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Fail to allocate private data.\n",
> +      __FUNCTION__
> +      ));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Memory allocation for transfer-related data  //  Status =
> + IoMmuAllocateBuffer (
> +             NVME_MEM_MAX_PAGES,
> +             &Private->Buffer,
> +             &DeviceAddress,
> +             &Private->BufferMapping
>               );
>    if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n",
> __FUNCTION__));
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Fail to allocate DMA buffers.\n",
> +      __FUNCTION__
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (DeviceAddress ==
> + ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
> +  DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> __FUNCTION__,
> + Private->Buffer));
> +
> +  //
> +  // Initialize controller private data  //
> +  Private->Signature        =
> NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> +  Private->MmioBase         = MmioBase;
> +  Private->DevicePathLength = DevicePathLength;
> +  Private->DevicePath       = DevicePath;
> +
> +  //
> +  // Initialize the NVME controller
> +  //
> +  Status = NvmeControllerInit (Private);  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Controller initialization fail with Status - %r.\n",
> +      __FUNCTION__,
> +      Status
> +      ));
> +    NvmeFreeDmaResource (Private);
> +    return Status;
> +  }
> +
> +  //
> +  // Enumerate the NVME namespaces on the controller  //  Status =
> + NvmeDiscoverNamespaces (Private);  if (EFI_ERROR (Status)) {
> +    //
> +    // No active namespace was found on the controller
> +    //
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Namespaces discovery fail with Status - %r.\n",
> +      __FUNCTION__,
> +      Status
> +      ));
> +    NvmeFreeDmaResource (Private);
> +    return Status;
> +  }
> +
> +  //
> +  // Nvm Express Pass Thru PPI
> +  //
> +  Private->PassThruMode.Attributes =
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> +                                     EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> |
> +
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> +  Private->PassThruMode.IoAlign             = sizeof (UINTN);
> +  Private->PassThruMode.NvmeVersion         =
> EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> +  Private->NvmePassThruPpi.Mode             = &Private->PassThruMode;
> +  Private->NvmePassThruPpi.GetDevicePath    =
> NvmePassThruGetDevicePath;
> +  Private->NvmePassThruPpi.GetNextNameSpace =
> NvmePassThruGetNextNameSpace;
> +  Private->NvmePassThruPpi.PassThru         = NvmePassThru;
> +  CopyMem (
> +    &Private->NvmePassThruPpiList,
> +    &mNvmePassThruPpiListTemplate,
> +    sizeof (EFI_PEI_PPI_DESCRIPTOR)
> +    );
> +  Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> + PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> +
> +  //
> +  // Block Io PPI
> +  //
> +  Private->BlkIoPpi.GetNumberOfBlockDevices =
> + NvmeBlockIoPeimGetDeviceNo;  Private-
> >BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
> +  Private->BlkIoPpi.ReadBlocks              = NvmeBlockIoPeimReadBlocks;
> +  CopyMem (
> +    &Private->BlkIoPpiList,
> +    &mNvmeBlkIoPpiListTemplate,
> +    sizeof (EFI_PEI_PPI_DESCRIPTOR)
> +    );
> +  Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> +
> +  Private->BlkIo2Ppi.Revision                =
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> +  Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> + NvmeBlockIoPeimGetDeviceNo2;  Private-
> >BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
> +  Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
> +  CopyMem (
> +    &Private->BlkIo2PpiList,
> +    &mNvmeBlkIo2PpiListTemplate,
> +    sizeof (EFI_PEI_PPI_DESCRIPTOR)
> +    );
> +  Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> + PeiServicesInstallPpi (&Private->BlkIoPpiList);
> +
> +  //
> +  // Check if the NVME controller supports the Security Receive/Send
> + commands  //  if ((Private->ControllerData->Oacs &
> + SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a: Security Security Command PPI will be produced.\n",
> +      __FUNCTION__
> +      ));
> +    Private->StorageSecurityPpi.Revision           =
> EDKII_STORAGE_SECURITY_PPI_REVISION;
> +    Private->StorageSecurityPpi.GetNumberofDevices =
> NvmeStorageSecurityGetDeviceNo;
> +    Private->StorageSecurityPpi.GetDevicePath      =
> NvmeStorageSecurityGetDevicePath;
> +    Private->StorageSecurityPpi.ReceiveData        =
> NvmeStorageSecurityReceiveData;
> +    Private->StorageSecurityPpi.SendData           =
> NvmeStorageSecuritySendData;
> +    CopyMem (
> +      &Private->StorageSecurityPpiList,
> +      &mNvmeStorageSecurityPpiListTemplate,
> +      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> +      );
> +    Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> +    PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> +  }
> +
> +  CopyMem (
> +    &Private->EndOfPeiNotifyList,
> +    &mNvmeEndOfPeiNotifyListTemplate,
> +    sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> +    );
> +  PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Initialize Nvme controller from fiven PCI_DEVICE_PPI.
> +
> +  @param[in] PciDevice  Pointer to the PCI Device PPI instance.
> +
> +  @retval EFI_SUCCESS      The function completes successfully
> +  @retval Others           Cannot initialize Nvme controller for given device
> +**/
> +EFI_STATUS
> +NvmeInitControllerDataFromPciDevice (
> +  EDKII_PCI_DEVICE_PPI  *PciDevice
> +  )
> +{
> +  EFI_STATUS                Status;
> +  PCI_TYPE00                PciData;
> +  UINTN                     MmioBase;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     DevicePathLength;
> +  UINT64                    EnabledPciAttributes;
> +  UINT32                    MmioBaseH;
> +
> +  //
> +  // Now further check the PCI header: Base Class (offset 0x0B), Sub
> + Class (offset 0x0A) and  // Programming Interface (offset 0x09). This
> + controller should be an Nvme controller  //  Status =
> + PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint8,
> +                                  PCI_CLASSCODE_OFFSET,
> +                                  sizeof (PciData.Hdr.ClassCode),
> +                                  PciData.Hdr.ClassCode
> +                                  );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (!IS_PCI_NVMHCI (&PciData)) {
>      return EFI_UNSUPPORTED;
>    }
> 
> +  Status = PciDevice->PciIo.Attributes (
> +                              &PciDevice->PciIo,
> +                              EfiPciIoAttributeOperationSupported,
> +                              0,
> +                              &EnabledPciAttributes
> +                              );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_UNSUPPORTED;
> +  } else {
> +    EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> +    Status                = PciDevice->PciIo.Attributes (
> +                                               &PciDevice->PciIo,
> +                                               EfiPciIoAttributeOperationEnable,
> +                                               EnabledPciAttributes,
> +                                               NULL
> +                                               );
> +    if (EFI_ERROR (Status)) {
> +      return EFI_UNSUPPORTED;
> +    }
> +  }
> +
> +  Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint32,
> +                                  PCI_BASE_ADDRESSREG_OFFSET,
> +                                  1,
> +                                  &MmioBase
> +                                  );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  switch (MmioBase & 0x07) {
> +    case 0x0:
> +      //
> +      // Memory space for 32 bit bar address
> +      //
> +      MmioBase = MmioBase & 0xFFFFFFF0;
> +      break;
> +    case 0x4:
> +      //
> +      // For 64 bit bar address, read the high 32bits of this 64 bit bar
> +      //
> +      Status = PciDevice->PciIo.Pci.Read (
> +                                      &PciDevice->PciIo,
> +                                      EfiPciIoWidthUint32,
> +                                      PCI_BASE_ADDRESSREG_OFFSET + 4,
> +                                      1,
> +                                      &MmioBaseH
> +                                      );
> +      //
> +      // For 32 bit environment, high 32bits of the bar should be zero.
> +      //
> +      if (  EFI_ERROR (Status)
> +         || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
> +      {
> +        return EFI_UNSUPPORTED;
> +      }
> +
> +      MmioBase  = MmioBase & 0xFFFFFFF0;
> +      MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
> +      break;
> +    default:
> +      //
> +      // Unknown bar type
> +      //
> +      return EFI_UNSUPPORTED;
> +  }
> +
> +  DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
> +  DevicePath       = PciDevice->DevicePath;
> +
> +  Status = NvmeInitPrivateData (MmioBase, DevicePath,
> + DevicePathLength);  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a: Failed to init controller, with Status - %r\n",
> +      __FUNCTION__,
> +      Status
> +      ));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Callback for EDKII_PCI_DEVICE_PPI installation.
> +
> +  @param[in] PeiServices         Pointer to PEI Services Table.
> +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> Notification
> +                                 event that caused this function to execute.
> +  @param[in] Ppi                 Pointer to the PPI data associated with this
> function.
> +
> +  @retval EFI_SUCCESS            The function completes successfully
> +  @retval Others                 Cannot initialize Nvme controller from given
> PCI_DEVICE_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmePciDevicePpiInstallationCallback (
> +  IN EFI_PEI_SERVICES           **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> +  IN VOID                       *Ppi
> +  )
> +{
> +  EDKII_PCI_DEVICE_PPI  *PciDevice;
> +
> +  PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
> +
> +  return NvmeInitControllerDataFromPciDevice (PciDevice); }
> +
> +/**
> +  Initialize Nvme controller from
> EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
> +
> +  @param[in] NvmeHcPpi  Pointer to the Nvme Host Controller PPI instance.
> +
> +  @retval EFI_SUCCESS   PPI successfully installed.
> +**/
> +EFI_STATUS
> +NvmeInitControllerFromHostControllerPpi (
> +  IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi
> +  )
> +{
> +  UINT8                     Controller;
> +  UINTN                     MmioBase;
> +  UINTN                     DevicePathLength;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  EFI_STATUS                Status;
> +
>    Controller = 0;
>    MmioBase   = 0;
>    while (TRUE) {
> @@ -293,88 +641,7 @@ NvmExpressPeimEntry (
>        return Status;
>      }
> 
> -    //
> -    // Check validity of the device path of the NVM Express controller.
> -    //
> -    Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "%a: The device path is invalid for Controller %d.\n",
> -        __FUNCTION__,
> -        Controller
> -        ));
> -      Controller++;
> -      continue;
> -    }
> -
> -    //
> -    // For S3 resume performance consideration, not all NVM Express
> controllers
> -    // will be initialized. The driver consumes the content within
> -    // S3StorageDeviceInitList LockBox to see if a controller will be skipped
> -    // during S3 resume.
> -    //
> -    if ((BootMode == BOOT_ON_S3_RESUME) &&
> -        (NvmeS3SkipThisController (DevicePath, DevicePathLength)))
> -    {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "%a: Controller %d is skipped during S3.\n",
> -        __FUNCTION__,
> -        Controller
> -        ));
> -      Controller++;
> -      continue;
> -    }
> -
> -    //
> -    // Memory allocation for controller private data
> -    //
> -    Private = AllocateZeroPool (sizeof
> (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> -    if (Private == NULL) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "%a: Fail to allocate private data for Controller %d.\n",
> -        __FUNCTION__,
> -        Controller
> -        ));
> -      return EFI_OUT_OF_RESOURCES;
> -    }
> -
> -    //
> -    // Memory allocation for transfer-related data
> -    //
> -    Status = IoMmuAllocateBuffer (
> -               NVME_MEM_MAX_PAGES,
> -               &Private->Buffer,
> -               &DeviceAddress,
> -               &Private->BufferMapping
> -               );
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "%a: Fail to allocate DMA buffers for Controller %d.\n",
> -        __FUNCTION__,
> -        Controller
> -        ));
> -      return Status;
> -    }
> -
> -    ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private-
> >Buffer));
> -    DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> __FUNCTION__, Private->Buffer));
> -
> -    //
> -    // Initialize controller private data
> -    //
> -    Private->Signature        =
> NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> -    Private->MmioBase         = MmioBase;
> -    Private->DevicePathLength = DevicePathLength;
> -    Private->DevicePath       = DevicePath;
> -
> -    //
> -    // Initialize the NVME controller
> -    //
> -    Status = NvmeControllerInit (Private);
> +    Status = NvmeInitPrivateData (MmioBase, DevicePath,
> + DevicePathLength);
>      if (EFI_ERROR (Status)) {
>        DEBUG ((
>          DEBUG_ERROR,
> @@ -383,115 +650,73 @@ NvmExpressPeimEntry (
>          Controller,
>          Status
>          ));
> -      NvmeFreeDmaResource (Private);
> -      Controller++;
> -      continue;
> -    }
> -
> -    //
> -    // Enumerate the NVME namespaces on the controller
> -    //
> -    Status = NvmeDiscoverNamespaces (Private);
> -    if (EFI_ERROR (Status)) {
> -      //
> -      // No active namespace was found on the controller
> -      //
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
> -        __FUNCTION__,
> -        Controller,
> -        Status
> -        ));
> -      NvmeFreeDmaResource (Private);
> -      Controller++;
> -      continue;
> -    }
> -
> -    //
> -    // Nvm Express Pass Thru PPI
> -    //
> -    Private->PassThruMode.Attributes =
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> -                                       EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> |
> -
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> -    Private->PassThruMode.IoAlign             = sizeof (UINTN);
> -    Private->PassThruMode.NvmeVersion         =
> EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> -    Private->NvmePassThruPpi.Mode             = &Private->PassThruMode;
> -    Private->NvmePassThruPpi.GetDevicePath    =
> NvmePassThruGetDevicePath;
> -    Private->NvmePassThruPpi.GetNextNameSpace =
> NvmePassThruGetNextNameSpace;
> -    Private->NvmePassThruPpi.PassThru         = NvmePassThru;
> -    CopyMem (
> -      &Private->NvmePassThruPpiList,
> -      &mNvmePassThruPpiListTemplate,
> -      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> -      );
> -    Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> -    PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> -
> -    //
> -    // Block Io PPI
> -    //
> -    Private->BlkIoPpi.GetNumberOfBlockDevices =
> NvmeBlockIoPeimGetDeviceNo;
> -    Private->BlkIoPpi.GetBlockDeviceMediaInfo =
> NvmeBlockIoPeimGetMediaInfo;
> -    Private->BlkIoPpi.ReadBlocks              = NvmeBlockIoPeimReadBlocks;
> -    CopyMem (
> -      &Private->BlkIoPpiList,
> -      &mNvmeBlkIoPpiListTemplate,
> -      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> -      );
> -    Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> -
> -    Private->BlkIo2Ppi.Revision                =
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> -    Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> NvmeBlockIoPeimGetDeviceNo2;
> -    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> NvmeBlockIoPeimGetMediaInfo2;
> -    Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
> -    CopyMem (
> -      &Private->BlkIo2PpiList,
> -      &mNvmeBlkIo2PpiListTemplate,
> -      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> -      );
> -    Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> -    PeiServicesInstallPpi (&Private->BlkIoPpiList);
> -
> -    //
> -    // Check if the NVME controller supports the Security Receive/Send
> commands
> -    //
> -    if ((Private->ControllerData->Oacs &
> SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> +    } else {
>        DEBUG ((
>          DEBUG_INFO,
> -        "%a: Security Security Command PPI will be produced for
> Controller %d.\n",
> +        "%a: Controller %d has been successfully initialized.\n",
>          __FUNCTION__,
>          Controller
>          ));
> -      Private->StorageSecurityPpi.Revision           =
> EDKII_STORAGE_SECURITY_PPI_REVISION;
> -      Private->StorageSecurityPpi.GetNumberofDevices =
> NvmeStorageSecurityGetDeviceNo;
> -      Private->StorageSecurityPpi.GetDevicePath      =
> NvmeStorageSecurityGetDevicePath;
> -      Private->StorageSecurityPpi.ReceiveData        =
> NvmeStorageSecurityReceiveData;
> -      Private->StorageSecurityPpi.SendData           =
> NvmeStorageSecuritySendData;
> -      CopyMem (
> -        &Private->StorageSecurityPpiList,
> -        &mNvmeStorageSecurityPpiListTemplate,
> -        sizeof (EFI_PEI_PPI_DESCRIPTOR)
> -        );
> -      Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> -      PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
>      }
> 
> -    CopyMem (
> -      &Private->EndOfPeiNotifyList,
> -      &mNvmeEndOfPeiNotifyListTemplate,
> -      sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> -      );
> -    PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> -
> -    DEBUG ((
> -      DEBUG_INFO,
> -      "%a: Controller %d has been successfully initialized.\n",
> -      __FUNCTION__,
> -      Controller
> -      ));
>      Controller++;
>    }
> 
>    return EFI_SUCCESS;
>  }
> +
> +/**
> +  Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> +
> +  @param[in] PeiServices         Pointer to PEI Services Table.
> +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> Notification
> +                                 event that caused this function to execute.
> +  @param[in] Ppi                 Pointer to the PPI data associated with this
> function.
> +
> +  @retval EFI_SUCCESS            The function completes successfully
> +  @retval Others                 Cannot initialize Nvme controller from given
> EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeHostControllerPpiInstallationCallback (
> +  IN EFI_PEI_SERVICES           **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> +  IN VOID                       *Ppi
> +  )
> +{
> +  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi;
> +
> +  if (Ppi == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
> +
> +  return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi); }
> +
> +/**
> +  Entry point of the PEIM.
> +
> +  @param[in] FileHandle     Handle of the file being invoked.
> +  @param[in] PeiServices    Describes the list of possible PEI Services.
> +
> +  @retval EFI_SUCCESS    PPI successfully installed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmExpressPeimEntry (
> +  IN EFI_PEI_FILE_HANDLE     FileHandle,
> +  IN CONST EFI_PEI_SERVICES  **PeiServices
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> +
> +  PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
> +
> +  PeiServicesNotifyPpi (&mPciDevicePpiNotify);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> index 78a6b7016503..12a7624099c0 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> @@ -14,6 +14,7 @@
>  #include <PiPei.h>
> 
>  #include <IndustryStandard/Nvme.h>
> +#include <IndustryStandard/Pci.h>
> 
>  #include <Ppi/NvmExpressHostController.h>  #include <Ppi/BlockIo.h> @@
> -22,6 +23,7 @@  #include <Ppi/NvmExpressPassThru.h>  #include
> <Ppi/IoMmu.h>  #include <Ppi/EndOfPeiPhase.h>
> +#include <Ppi/PciDevice.h>
> 
>  #include <Library/DebugLib.h>
>  #include <Library/PeiServicesLib.h>
> @@ -29,6 +31,7 @@
>  #include <Library/BaseMemoryLib.h>
>  #include <Library/IoLib.h>
>  #include <Library/TimerLib.h>
> +#include <Library/DevicePathLib.h>
> 
>  //
>  // Structure forward declarations
> @@ -36,6 +39,17 @@
>  typedef struct _PEI_NVME_NAMESPACE_INFO
> PEI_NVME_NAMESPACE_INFO;
>  typedef struct _PEI_NVME_CONTROLLER_PRIVATE_DATA
> PEI_NVME_CONTROLLER_PRIVATE_DATA;
> 
> +/**
> +  Macro that checks whether device is a NVMHCI Interface.
> +
> +  @param  _p      Specified device.
> +
> +  @retval TRUE    Device is a NVMHCI Interface.
> +  @retval FALSE   Device is not a NVMHCI Interface.
> +
> +**/
> +#define IS_PCI_NVMHCI(_p)  IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE,
> +PCI_CLASS_MASS_STORAGE_SOLID_STATE,
> +PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI)
> +
>  #include "NvmExpressPeiHci.h"
>  #include "NvmExpressPeiPassThru.h"
>  #include "NvmExpressPeiBlockIo.h"
> @@ -345,4 +359,44 @@ NvmeS3SkipThisController (
>    IN  UINTN                     HcDevicePathLength
>    );
> 
> +/**
> +  Callback for EDKII_PCI_DEVICE_PPI installation.
> +
> +  @param[in] PeiServices         Pointer to PEI Services Table.
> +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> Notification
> +                                 event that caused this function to execute.
> +  @param[in] Ppi                 Pointer to the PPI data associated with this
> function.
> +
> +  @retval EFI_SUCCESS            The function completes successfully
> +  @retval Others                 Cannot initialize Nvme controller from given
> PCI_DEVICE_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmePciDevicePpiInstallationCallback (
> +  IN EFI_PEI_SERVICES           **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> +  IN VOID                       *Ppi
> +  );
> +
> +/**
> +  Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> +
> +  @param[in] PeiServices         Pointer to PEI Services Table.
> +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> Notification
> +                                 event that caused this function to execute.
> +  @param[in] Ppi                 Pointer to the PPI data associated with this
> function.
> +
> +  @retval EFI_SUCCESS            The function completes successfully
> +  @retval Others                 Cannot initialize Nvme controller from given
> EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +NvmeHostControllerPpiInstallationCallback (
> +  IN EFI_PEI_SERVICES           **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> +  IN VOID                       *Ppi
> +  );
> +
>  #endif
> diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> index 4dd6c5704fa3..ba6f1afbf168 100644
> --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> @@ -44,6 +44,7 @@
> 
>  [LibraryClasses]
>    DebugLib
> +  DevicePathLib
>    PeiServicesLib
>    MemoryAllocationLib
>    BaseMemoryLib
> @@ -56,6 +57,7 @@
>    gEdkiiPeiNvmExpressHostControllerPpiGuid       ## CONSUMES
>    gEdkiiIoMmuPpiGuid                             ## CONSUMES
>    gEfiEndOfPeiSignalPpiGuid                      ## CONSUMES
> +  gEdkiiPeiPciDevicePpiGuid                      ## CONSUMES
>    gEdkiiPeiNvmExpressPassThruPpiGuid             ## SOMETIMES_PRODUCES
>    gEfiPeiVirtualBlockIoPpiGuid                   ## SOMETIMES_PRODUCES
>    gEfiPeiVirtualBlockIo2PpiGuid                  ## SOMETIMES_PRODUCES
> @@ -66,7 +68,6 @@
> 
>  [Depex]
>    gEfiPeiMemoryDiscoveredPpiGuid AND
> -  gEdkiiPeiNvmExpressHostControllerPpiGuid AND
>    gEfiPeiMasterBootModePpiGuid
> 
>  [UserExtensions.TianoCore."ExtraFiles"]
> --
> 2.37.0.windows.1


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

* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
  2022-08-30  6:27   ` Wu, Hao A
@ 2022-09-01  5:33     ` Wu, Hao A
  0 siblings, 0 replies; 4+ messages in thread
From: Wu, Hao A @ 2022-09-01  5:33 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wu, Hao A, Chen, Xiao X; +Cc: Ni, Ray

Patch merged via:
PR - https://github.com/tianocore/edk2/pull/3267
Commit - https://github.com/tianocore/edk2/commit/9ca7ece8b3b1743b6ee76f5f20f2c5eeed001d72

Best Regards,
Hao Wu

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Wu, Hao
> A
> Sent: Tuesday, August 30, 2022 2:27 PM
> To: Chen, Xiao X <xiao.x.chen@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg/NvmExpressPei:
> Use PCI_DEVICE_PPI to manage Nvme device
> 
> Thanks.
> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
> 
> Will wait a couple of days before merging to see if comments from other
> reviewers.
> 
> Best Regards,
> Hao Wu
> 
> > -----Original Message-----
> > From: Chen, Xiao X <xiao.x.chen@intel.com>
> > Sent: Tuesday, August 30, 2022 1:47 PM
> > To: devel@edk2.groups.io
> > Cc: Chen, Xiao X <xiao.x.chen@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: Use
> PCI_DEVICE_PPI
> > to manage Nvme device
> >
> > https://bugzilla.tianocore.org/show_bug.cgi?id=4017
> >
> > This change modifies NvmExpressPei library to allow usage both
> > EDKII_PCI_DEVICE_PPI and EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> > to manage Nvme device.
> >
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Signed-off-by: Xiao X Chen <xiao.x.chen@intel.com>
> > ---
> >  .../Bus/Pci/NvmExpressPei/DevicePath.c        |  44 --
> >  .../Bus/Pci/NvmExpressPei/NvmExpressPei.c     | 639 ++++++++++++------
> >  .../Bus/Pci/NvmExpressPei/NvmExpressPei.h     |  54 ++
> >  .../Bus/Pci/NvmExpressPei/NvmExpressPei.inf   |   3 +-
> >  4 files changed, 488 insertions(+), 252 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > index 9b454a7dd8f4..307045be70ea 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
> > @@ -37,50 +37,6 @@ EFI_DEVICE_PATH_PROTOCOL
> > mNvmeEndDevicePathNodeTemplate = {
> >    }
> >  };
> >
> > -/**
> > -  Returns the 16-bit Length field of a device path node.
> > -
> > -  Returns the 16-bit Length field of the device path node specified by Node.
> > -  Node is not required to be aligned on a 16-bit boundary, so it is
> > recommended
> > -  that a function such as ReadUnaligned16() be used to extract the
> > contents of
> > -  the Length field.
> > -
> > -  If Node is NULL, then ASSERT().
> > -
> > -  @param  Node      A pointer to a device path node data structure.
> > -
> > -  @return The 16-bit Length field of the device path node specified by
> Node.
> > -
> > -**/
> > -UINTN
> > -DevicePathNodeLength (
> > -  IN CONST VOID  *Node
> > -  )
> > -{
> > -  ASSERT (Node != NULL);
> > -  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL
> > *)(Node))->Length[0]); -}
> > -
> > -/**
> > -  Returns a pointer to the next node in a device path.
> > -
> > -  If Node is NULL, then ASSERT().
> > -
> > -  @param  Node    A pointer to a device path node data structure.
> > -
> > -  @return a pointer to the device path node that follows the device
> > path node
> > -  specified by Node.
> > -
> > -**/
> > -EFI_DEVICE_PATH_PROTOCOL *
> > -NextDevicePathNode (
> > -  IN CONST VOID  *Node
> > -  )
> > -{
> > -  ASSERT (Node != NULL);
> > -  return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) +
> > DevicePathNodeLength (Node)); -}
> > -
> >  /**
> >    Get the size of the current device path instance.
> >
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > index 2d6a79028fcd..0d02c2785da7 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
> > @@ -40,6 +40,18 @@ EFI_PEI_NOTIFY_DESCRIPTOR
> > mNvmeEndOfPeiNotifyListTemplate = {
> >    NvmePeimEndOfPei
> >  };
> >
> > +EFI_PEI_NOTIFY_DESCRIPTOR  mNvmeHostControllerNotify = {
> > +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > +  &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> > +  NvmeHostControllerPpiInstallationCallback
> > +};
> > +
> > +EFI_PEI_NOTIFY_DESCRIPTOR  mPciDevicePpiNotify = {
> > +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > +  &gEdkiiPeiPciDevicePpiGuid,
> > +  NvmePciDevicePpiInstallationCallback
> > +};
> > +
> >  /**
> >    Check if the specified Nvm Express device namespace is active, and
> > then get the Identify
> >    Namespace data.
> > @@ -212,30 +224,27 @@ NvmePeimEndOfPei (  }
> >
> >  /**
> > -  Entry point of the PEIM.
> > +  Initialize and install PrivateData PPIs.
> >
> > -  @param[in] FileHandle     Handle of the file being invoked.
> > -  @param[in] PeiServices    Describes the list of possible PEI Services.
> > -
> > -  @retval EFI_SUCCESS    PPI successfully installed.
> > +  @param[in] MmioBase            MMIO base address of specific Nvme
> > controller
> > +  @param[in] DevicePath          A pointer to the
> > EFI_DEVICE_PATH_PROTOCOL
> > +                                 structure.
> > +  @param[in] DevicePathLength    Length of the device path.
> >
> > +  @retval EFI_SUCCESS  Nvme controller initialized and PPIs installed
> > +  @retval others       Failed to initialize Nvme controller
> >  **/
> >  EFI_STATUS
> > -EFIAPI
> > -NvmExpressPeimEntry (
> > -  IN EFI_PEI_FILE_HANDLE     FileHandle,
> > -  IN CONST EFI_PEI_SERVICES  **PeiServices
> > +NvmeInitPrivateData (
> > +  IN UINTN                     MmioBase,
> > +  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
> > +  IN UINTN                     DevicePathLength
> >    )
> >  {
> > -  EFI_STATUS                             Status;
> > -  EFI_BOOT_MODE                          BootMode;
> > -  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi;
> > -  UINT8                                  Controller;
> > -  UINTN                                  MmioBase;
> > -  UINTN                                  DevicePathLength;
> > -  EFI_DEVICE_PATH_PROTOCOL               *DevicePath;
> > -  PEI_NVME_CONTROLLER_PRIVATE_DATA       *Private;
> > -  EFI_PHYSICAL_ADDRESS                   DeviceAddress;
> > +  EFI_STATUS                        Status;
> > +  EFI_BOOT_MODE                     BootMode;
> > +  PEI_NVME_CONTROLLER_PRIVATE_DATA  *Private;
> > +  EFI_PHYSICAL_ADDRESS              DeviceAddress;
> >
> >    DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> >
> > @@ -249,19 +258,358 @@ NvmExpressPeimEntry (
> >    }
> >
> >    //
> > -  // Locate the NVME host controller PPI
> > +  // Check validity of the device path of the NVM Express controller.
> >    //
> > -  Status = PeiServicesLocatePpi (
> > -             &gEdkiiPeiNvmExpressHostControllerPpiGuid,
> > -             0,
> > -             NULL,
> > -             (VOID **)&NvmeHcPpi
> > +  Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
> > + if (EFI_ERROR (Status)) {
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: The device path is invalid for Controller %d.\n",
> > +      __FUNCTION__
> > +      ));
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // For S3 resume performance consideration, not all NVM Express
> > + controllers  // will be initialized. The driver consumes the content
> > + within  // S3StorageDeviceInitList LockBox to see if a controller
> > + will be skipped  // during S3 resume.
> > +  //
> > +  if ((BootMode == BOOT_ON_S3_RESUME) &&
> > +      (NvmeS3SkipThisController (DevicePath, DevicePathLength)))  {
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: skipped during S3.\n",
> > +      __FUNCTION__
> > +      ));
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  //
> > +  // Memory allocation for controller private data  //  Private =
> > + AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> > +  if (Private == NULL) {
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: Fail to allocate private data.\n",
> > +      __FUNCTION__
> > +      ));
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  //
> > +  // Memory allocation for transfer-related data  //  Status =
> > + IoMmuAllocateBuffer (
> > +             NVME_MEM_MAX_PAGES,
> > +             &Private->Buffer,
> > +             &DeviceAddress,
> > +             &Private->BufferMapping
> >               );
> >    if (EFI_ERROR (Status)) {
> > -    DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n",
> > __FUNCTION__));
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: Fail to allocate DMA buffers.\n",
> > +      __FUNCTION__
> > +      ));
> > +    return Status;
> > +  }
> > +
> > +  ASSERT (DeviceAddress ==
> > + ((EFI_PHYSICAL_ADDRESS)(UINTN)Private->Buffer));
> > +  DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> > __FUNCTION__,
> > + Private->Buffer));
> > +
> > +  //
> > +  // Initialize controller private data  //
> > +  Private->Signature        =
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> > +  Private->MmioBase         = MmioBase;
> > +  Private->DevicePathLength = DevicePathLength;
> > +  Private->DevicePath       = DevicePath;
> > +
> > +  //
> > +  // Initialize the NVME controller
> > +  //
> > +  Status = NvmeControllerInit (Private);  if (EFI_ERROR (Status)) {
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: Controller initialization fail with Status - %r.\n",
> > +      __FUNCTION__,
> > +      Status
> > +      ));
> > +    NvmeFreeDmaResource (Private);
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Enumerate the NVME namespaces on the controller  //  Status =
> > + NvmeDiscoverNamespaces (Private);  if (EFI_ERROR (Status)) {
> > +    //
> > +    // No active namespace was found on the controller
> > +    //
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: Namespaces discovery fail with Status - %r.\n",
> > +      __FUNCTION__,
> > +      Status
> > +      ));
> > +    NvmeFreeDmaResource (Private);
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Nvm Express Pass Thru PPI
> > +  //
> > +  Private->PassThruMode.Attributes =
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> > +
> > + EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> > |
> > +
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> > +  Private->PassThruMode.IoAlign             = sizeof (UINTN);
> > +  Private->PassThruMode.NvmeVersion         =
> > EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> > +  Private->NvmePassThruPpi.Mode             = &Private->PassThruMode;
> > +  Private->NvmePassThruPpi.GetDevicePath    =
> > NvmePassThruGetDevicePath;
> > +  Private->NvmePassThruPpi.GetNextNameSpace =
> > NvmePassThruGetNextNameSpace;
> > +  Private->NvmePassThruPpi.PassThru         = NvmePassThru;
> > +  CopyMem (
> > +    &Private->NvmePassThruPpiList,
> > +    &mNvmePassThruPpiListTemplate,
> > +    sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +    );
> > +  Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> > + PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> > +
> > +  //
> > +  // Block Io PPI
> > +  //
> > +  Private->BlkIoPpi.GetNumberOfBlockDevices =
> > + NvmeBlockIoPeimGetDeviceNo;  Private-
> > >BlkIoPpi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo;
> > +  Private->BlkIoPpi.ReadBlocks              = NvmeBlockIoPeimReadBlocks;
> > +  CopyMem (
> > +    &Private->BlkIoPpiList,
> > +    &mNvmeBlkIoPpiListTemplate,
> > +    sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +    );
> > +  Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> > +
> > +  Private->BlkIo2Ppi.Revision                =
> > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> > +  Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> > + NvmeBlockIoPeimGetDeviceNo2;  Private-
> > >BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
> > +  Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
> > +  CopyMem (
> > +    &Private->BlkIo2PpiList,
> > +    &mNvmeBlkIo2PpiListTemplate,
> > +    sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +    );
> > +  Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> > + PeiServicesInstallPpi (&Private->BlkIoPpiList);
> > +
> > +  //
> > +  // Check if the NVME controller supports the Security Receive/Send
> > + commands  //  if ((Private->ControllerData->Oacs &
> > + SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> > +    DEBUG ((
> > +      DEBUG_INFO,
> > +      "%a: Security Security Command PPI will be produced.\n",
> > +      __FUNCTION__
> > +      ));
> > +    Private->StorageSecurityPpi.Revision           =
> > EDKII_STORAGE_SECURITY_PPI_REVISION;
> > +    Private->StorageSecurityPpi.GetNumberofDevices =
> > NvmeStorageSecurityGetDeviceNo;
> > +    Private->StorageSecurityPpi.GetDevicePath      =
> > NvmeStorageSecurityGetDevicePath;
> > +    Private->StorageSecurityPpi.ReceiveData        =
> > NvmeStorageSecurityReceiveData;
> > +    Private->StorageSecurityPpi.SendData           =
> > NvmeStorageSecuritySendData;
> > +    CopyMem (
> > +      &Private->StorageSecurityPpiList,
> > +      &mNvmeStorageSecurityPpiListTemplate,
> > +      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > +      );
> > +    Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> > +    PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> > +  }
> > +
> > +  CopyMem (
> > +    &Private->EndOfPeiNotifyList,
> > +    &mNvmeEndOfPeiNotifyListTemplate,
> > +    sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> > +    );
> > +  PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Initialize Nvme controller from fiven PCI_DEVICE_PPI.
> > +
> > +  @param[in] PciDevice  Pointer to the PCI Device PPI instance.
> > +
> > +  @retval EFI_SUCCESS      The function completes successfully
> > +  @retval Others           Cannot initialize Nvme controller for given device
> > +**/
> > +EFI_STATUS
> > +NvmeInitControllerDataFromPciDevice (
> > +  EDKII_PCI_DEVICE_PPI  *PciDevice
> > +  )
> > +{
> > +  EFI_STATUS                Status;
> > +  PCI_TYPE00                PciData;
> > +  UINTN                     MmioBase;
> > +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> > +  UINTN                     DevicePathLength;
> > +  UINT64                    EnabledPciAttributes;
> > +  UINT32                    MmioBaseH;
> > +
> > +  //
> > +  // Now further check the PCI header: Base Class (offset 0x0B), Sub
> > + Class (offset 0x0A) and  // Programming Interface (offset 0x09).
> > + This controller should be an Nvme controller  //  Status =
> > + PciDevice->PciIo.Pci.Read (
> > +                                  &PciDevice->PciIo,
> > +                                  EfiPciIoWidthUint8,
> > +                                  PCI_CLASSCODE_OFFSET,
> > +                                  sizeof (PciData.Hdr.ClassCode),
> > +                                  PciData.Hdr.ClassCode
> > +                                  );
> > +  if (EFI_ERROR (Status)) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  if (!IS_PCI_NVMHCI (&PciData)) {
> >      return EFI_UNSUPPORTED;
> >    }
> >
> > +  Status = PciDevice->PciIo.Attributes (
> > +                              &PciDevice->PciIo,
> > +                              EfiPciIoAttributeOperationSupported,
> > +                              0,
> > +                              &EnabledPciAttributes
> > +                              );
> > +  if (EFI_ERROR (Status)) {
> > +    return EFI_UNSUPPORTED;
> > +  } else {
> > +    EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > +    Status                = PciDevice->PciIo.Attributes (
> > +                                               &PciDevice->PciIo,
> > +                                               EfiPciIoAttributeOperationEnable,
> > +                                               EnabledPciAttributes,
> > +                                               NULL
> > +                                               );
> > +    if (EFI_ERROR (Status)) {
> > +      return EFI_UNSUPPORTED;
> > +    }
> > +  }
> > +
> > +  Status = PciDevice->PciIo.Pci.Read (
> > +                                  &PciDevice->PciIo,
> > +                                  EfiPciIoWidthUint32,
> > +                                  PCI_BASE_ADDRESSREG_OFFSET,
> > +                                  1,
> > +                                  &MmioBase
> > +                                  );
> > +  if (EFI_ERROR (Status)) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  switch (MmioBase & 0x07) {
> > +    case 0x0:
> > +      //
> > +      // Memory space for 32 bit bar address
> > +      //
> > +      MmioBase = MmioBase & 0xFFFFFFF0;
> > +      break;
> > +    case 0x4:
> > +      //
> > +      // For 64 bit bar address, read the high 32bits of this 64 bit bar
> > +      //
> > +      Status = PciDevice->PciIo.Pci.Read (
> > +                                      &PciDevice->PciIo,
> > +                                      EfiPciIoWidthUint32,
> > +                                      PCI_BASE_ADDRESSREG_OFFSET + 4,
> > +                                      1,
> > +                                      &MmioBaseH
> > +                                      );
> > +      //
> > +      // For 32 bit environment, high 32bits of the bar should be zero.
> > +      //
> > +      if (  EFI_ERROR (Status)
> > +         || ((MmioBaseH != 0) && (sizeof (UINTN) == sizeof (UINT32))))
> > +      {
> > +        return EFI_UNSUPPORTED;
> > +      }
> > +
> > +      MmioBase  = MmioBase & 0xFFFFFFF0;
> > +      MmioBase |= LShiftU64 ((UINT64)MmioBaseH, 32);
> > +      break;
> > +    default:
> > +      //
> > +      // Unknown bar type
> > +      //
> > +      return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  DevicePathLength = GetDevicePathSize (PciDevice->DevicePath);
> > +  DevicePath       = PciDevice->DevicePath;
> > +
> > +  Status = NvmeInitPrivateData (MmioBase, DevicePath,
> > + DevicePathLength);  if (EFI_ERROR (Status)) {
> > +    DEBUG ((
> > +      DEBUG_INFO,
> > +      "%a: Failed to init controller, with Status - %r\n",
> > +      __FUNCTION__,
> > +      Status
> > +      ));
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Callback for EDKII_PCI_DEVICE_PPI installation.
> > +
> > +  @param[in] PeiServices         Pointer to PEI Services Table.
> > +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> > Notification
> > +                                 event that caused this function to execute.
> > +  @param[in] Ppi                 Pointer to the PPI data associated with this
> > function.
> > +
> > +  @retval EFI_SUCCESS            The function completes successfully
> > +  @retval Others                 Cannot initialize Nvme controller from given
> > PCI_DEVICE_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmePciDevicePpiInstallationCallback (
> > +  IN EFI_PEI_SERVICES           **PeiServices,
> > +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> > +  IN VOID                       *Ppi
> > +  )
> > +{
> > +  EDKII_PCI_DEVICE_PPI  *PciDevice;
> > +
> > +  PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;
> > +
> > +  return NvmeInitControllerDataFromPciDevice (PciDevice); }
> > +
> > +/**
> > +  Initialize Nvme controller from
> > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI instance.
> > +
> > +  @param[in] NvmeHcPpi  Pointer to the Nvme Host Controller PPI
> instance.
> > +
> > +  @retval EFI_SUCCESS   PPI successfully installed.
> > +**/
> > +EFI_STATUS
> > +NvmeInitControllerFromHostControllerPpi (
> > +  IN EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi
> > +  )
> > +{
> > +  UINT8                     Controller;
> > +  UINTN                     MmioBase;
> > +  UINTN                     DevicePathLength;
> > +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> > +  EFI_STATUS                Status;
> > +
> >    Controller = 0;
> >    MmioBase   = 0;
> >    while (TRUE) {
> > @@ -293,88 +641,7 @@ NvmExpressPeimEntry (
> >        return Status;
> >      }
> >
> > -    //
> > -    // Check validity of the device path of the NVM Express controller.
> > -    //
> > -    Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
> > -    if (EFI_ERROR (Status)) {
> > -      DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: The device path is invalid for Controller %d.\n",
> > -        __FUNCTION__,
> > -        Controller
> > -        ));
> > -      Controller++;
> > -      continue;
> > -    }
> > -
> > -    //
> > -    // For S3 resume performance consideration, not all NVM Express
> > controllers
> > -    // will be initialized. The driver consumes the content within
> > -    // S3StorageDeviceInitList LockBox to see if a controller will be skipped
> > -    // during S3 resume.
> > -    //
> > -    if ((BootMode == BOOT_ON_S3_RESUME) &&
> > -        (NvmeS3SkipThisController (DevicePath, DevicePathLength)))
> > -    {
> > -      DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: Controller %d is skipped during S3.\n",
> > -        __FUNCTION__,
> > -        Controller
> > -        ));
> > -      Controller++;
> > -      continue;
> > -    }
> > -
> > -    //
> > -    // Memory allocation for controller private data
> > -    //
> > -    Private = AllocateZeroPool (sizeof
> > (PEI_NVME_CONTROLLER_PRIVATE_DATA));
> > -    if (Private == NULL) {
> > -      DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: Fail to allocate private data for Controller %d.\n",
> > -        __FUNCTION__,
> > -        Controller
> > -        ));
> > -      return EFI_OUT_OF_RESOURCES;
> > -    }
> > -
> > -    //
> > -    // Memory allocation for transfer-related data
> > -    //
> > -    Status = IoMmuAllocateBuffer (
> > -               NVME_MEM_MAX_PAGES,
> > -               &Private->Buffer,
> > -               &DeviceAddress,
> > -               &Private->BufferMapping
> > -               );
> > -    if (EFI_ERROR (Status)) {
> > -      DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: Fail to allocate DMA buffers for Controller %d.\n",
> > -        __FUNCTION__,
> > -        Controller
> > -        ));
> > -      return Status;
> > -    }
> > -
> > -    ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)Private-
> > >Buffer));
> > -    DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n",
> > __FUNCTION__, Private->Buffer));
> > -
> > -    //
> > -    // Initialize controller private data
> > -    //
> > -    Private->Signature        =
> > NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
> > -    Private->MmioBase         = MmioBase;
> > -    Private->DevicePathLength = DevicePathLength;
> > -    Private->DevicePath       = DevicePath;
> > -
> > -    //
> > -    // Initialize the NVME controller
> > -    //
> > -    Status = NvmeControllerInit (Private);
> > +    Status = NvmeInitPrivateData (MmioBase, DevicePath,
> > + DevicePathLength);
> >      if (EFI_ERROR (Status)) {
> >        DEBUG ((
> >          DEBUG_ERROR,
> > @@ -383,115 +650,73 @@ NvmExpressPeimEntry (
> >          Controller,
> >          Status
> >          ));
> > -      NvmeFreeDmaResource (Private);
> > -      Controller++;
> > -      continue;
> > -    }
> > -
> > -    //
> > -    // Enumerate the NVME namespaces on the controller
> > -    //
> > -    Status = NvmeDiscoverNamespaces (Private);
> > -    if (EFI_ERROR (Status)) {
> > -      //
> > -      // No active namespace was found on the controller
> > -      //
> > -      DEBUG ((
> > -        DEBUG_ERROR,
> > -        "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
> > -        __FUNCTION__,
> > -        Controller,
> > -        Status
> > -        ));
> > -      NvmeFreeDmaResource (Private);
> > -      Controller++;
> > -      continue;
> > -    }
> > -
> > -    //
> > -    // Nvm Express Pass Thru PPI
> > -    //
> > -    Private->PassThruMode.Attributes =
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
> > -
> EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
> > |
> > -
> > EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM;
> > -    Private->PassThruMode.IoAlign             = sizeof (UINTN);
> > -    Private->PassThruMode.NvmeVersion         =
> > EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI_REVISION;
> > -    Private->NvmePassThruPpi.Mode             = &Private->PassThruMode;
> > -    Private->NvmePassThruPpi.GetDevicePath    =
> > NvmePassThruGetDevicePath;
> > -    Private->NvmePassThruPpi.GetNextNameSpace =
> > NvmePassThruGetNextNameSpace;
> > -    Private->NvmePassThruPpi.PassThru         = NvmePassThru;
> > -    CopyMem (
> > -      &Private->NvmePassThruPpiList,
> > -      &mNvmePassThruPpiListTemplate,
> > -      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > -      );
> > -    Private->NvmePassThruPpiList.Ppi = &Private->NvmePassThruPpi;
> > -    PeiServicesInstallPpi (&Private->NvmePassThruPpiList);
> > -
> > -    //
> > -    // Block Io PPI
> > -    //
> > -    Private->BlkIoPpi.GetNumberOfBlockDevices =
> > NvmeBlockIoPeimGetDeviceNo;
> > -    Private->BlkIoPpi.GetBlockDeviceMediaInfo =
> > NvmeBlockIoPeimGetMediaInfo;
> > -    Private->BlkIoPpi.ReadBlocks              = NvmeBlockIoPeimReadBlocks;
> > -    CopyMem (
> > -      &Private->BlkIoPpiList,
> > -      &mNvmeBlkIoPpiListTemplate,
> > -      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > -      );
> > -    Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
> > -
> > -    Private->BlkIo2Ppi.Revision                =
> > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> > -    Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> > NvmeBlockIoPeimGetDeviceNo2;
> > -    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> > NvmeBlockIoPeimGetMediaInfo2;
> > -    Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
> > -    CopyMem (
> > -      &Private->BlkIo2PpiList,
> > -      &mNvmeBlkIo2PpiListTemplate,
> > -      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > -      );
> > -    Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
> > -    PeiServicesInstallPpi (&Private->BlkIoPpiList);
> > -
> > -    //
> > -    // Check if the NVME controller supports the Security Receive/Send
> > commands
> > -    //
> > -    if ((Private->ControllerData->Oacs &
> > SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
> > +    } else {
> >        DEBUG ((
> >          DEBUG_INFO,
> > -        "%a: Security Security Command PPI will be produced for
> > Controller %d.\n",
> > +        "%a: Controller %d has been successfully initialized.\n",
> >          __FUNCTION__,
> >          Controller
> >          ));
> > -      Private->StorageSecurityPpi.Revision           =
> > EDKII_STORAGE_SECURITY_PPI_REVISION;
> > -      Private->StorageSecurityPpi.GetNumberofDevices =
> > NvmeStorageSecurityGetDeviceNo;
> > -      Private->StorageSecurityPpi.GetDevicePath      =
> > NvmeStorageSecurityGetDevicePath;
> > -      Private->StorageSecurityPpi.ReceiveData        =
> > NvmeStorageSecurityReceiveData;
> > -      Private->StorageSecurityPpi.SendData           =
> > NvmeStorageSecuritySendData;
> > -      CopyMem (
> > -        &Private->StorageSecurityPpiList,
> > -        &mNvmeStorageSecurityPpiListTemplate,
> > -        sizeof (EFI_PEI_PPI_DESCRIPTOR)
> > -        );
> > -      Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
> > -      PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
> >      }
> >
> > -    CopyMem (
> > -      &Private->EndOfPeiNotifyList,
> > -      &mNvmeEndOfPeiNotifyListTemplate,
> > -      sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
> > -      );
> > -    PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
> > -
> > -    DEBUG ((
> > -      DEBUG_INFO,
> > -      "%a: Controller %d has been successfully initialized.\n",
> > -      __FUNCTION__,
> > -      Controller
> > -      ));
> >      Controller++;
> >    }
> >
> >    return EFI_SUCCESS;
> >  }
> > +
> > +/**
> > +  Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> > +
> > +  @param[in] PeiServices         Pointer to PEI Services Table.
> > +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> > Notification
> > +                                 event that caused this function to execute.
> > +  @param[in] Ppi                 Pointer to the PPI data associated with this
> > function.
> > +
> > +  @retval EFI_SUCCESS            The function completes successfully
> > +  @retval Others                 Cannot initialize Nvme controller from given
> > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeHostControllerPpiInstallationCallback (
> > +  IN EFI_PEI_SERVICES           **PeiServices,
> > +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> > +  IN VOID                       *Ppi
> > +  )
> > +{
> > +  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI  *NvmeHcPpi;
> > +
> > +  if (Ppi == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  NvmeHcPpi = (EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *)Ppi;
> > +
> > +  return NvmeInitControllerFromHostControllerPpi (NvmeHcPpi); }
> > +
> > +/**
> > +  Entry point of the PEIM.
> > +
> > +  @param[in] FileHandle     Handle of the file being invoked.
> > +  @param[in] PeiServices    Describes the list of possible PEI Services.
> > +
> > +  @retval EFI_SUCCESS    PPI successfully installed.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmExpressPeimEntry (
> > +  IN EFI_PEI_FILE_HANDLE     FileHandle,
> > +  IN CONST EFI_PEI_SERVICES  **PeiServices
> > +  )
> > +{
> > +  DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
> > +
> > +  PeiServicesNotifyPpi (&mNvmeHostControllerNotify);
> > +
> > +  PeiServicesNotifyPpi (&mPciDevicePpiNotify);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > index 78a6b7016503..12a7624099c0 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
> > @@ -14,6 +14,7 @@
> >  #include <PiPei.h>
> >
> >  #include <IndustryStandard/Nvme.h>
> > +#include <IndustryStandard/Pci.h>
> >
> >  #include <Ppi/NvmExpressHostController.h>  #include <Ppi/BlockIo.h>
> > @@
> > -22,6 +23,7 @@  #include <Ppi/NvmExpressPassThru.h>  #include
> > <Ppi/IoMmu.h>  #include <Ppi/EndOfPeiPhase.h>
> > +#include <Ppi/PciDevice.h>
> >
> >  #include <Library/DebugLib.h>
> >  #include <Library/PeiServicesLib.h>
> > @@ -29,6 +31,7 @@
> >  #include <Library/BaseMemoryLib.h>
> >  #include <Library/IoLib.h>
> >  #include <Library/TimerLib.h>
> > +#include <Library/DevicePathLib.h>
> >
> >  //
> >  // Structure forward declarations
> > @@ -36,6 +39,17 @@
> >  typedef struct _PEI_NVME_NAMESPACE_INFO
> PEI_NVME_NAMESPACE_INFO;
> > typedef struct _PEI_NVME_CONTROLLER_PRIVATE_DATA
> > PEI_NVME_CONTROLLER_PRIVATE_DATA;
> >
> > +/**
> > +  Macro that checks whether device is a NVMHCI Interface.
> > +
> > +  @param  _p      Specified device.
> > +
> > +  @retval TRUE    Device is a NVMHCI Interface.
> > +  @retval FALSE   Device is not a NVMHCI Interface.
> > +
> > +**/
> > +#define IS_PCI_NVMHCI(_p)  IS_CLASS3 (_p,
> PCI_CLASS_MASS_STORAGE,
> > +PCI_CLASS_MASS_STORAGE_SOLID_STATE,
> > +PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI)
> > +
> >  #include "NvmExpressPeiHci.h"
> >  #include "NvmExpressPeiPassThru.h"
> >  #include "NvmExpressPeiBlockIo.h"
> > @@ -345,4 +359,44 @@ NvmeS3SkipThisController (
> >    IN  UINTN                     HcDevicePathLength
> >    );
> >
> > +/**
> > +  Callback for EDKII_PCI_DEVICE_PPI installation.
> > +
> > +  @param[in] PeiServices         Pointer to PEI Services Table.
> > +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> > Notification
> > +                                 event that caused this function to execute.
> > +  @param[in] Ppi                 Pointer to the PPI data associated with this
> > function.
> > +
> > +  @retval EFI_SUCCESS            The function completes successfully
> > +  @retval Others                 Cannot initialize Nvme controller from given
> > PCI_DEVICE_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmePciDevicePpiInstallationCallback (
> > +  IN EFI_PEI_SERVICES           **PeiServices,
> > +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> > +  IN VOID                       *Ppi
> > +  );
> > +
> > +/**
> > +  Callback for EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI installation.
> > +
> > +  @param[in] PeiServices         Pointer to PEI Services Table.
> > +  @param[in] NotifyDescriptor    Pointer to the descriptor for the
> > Notification
> > +                                 event that caused this function to execute.
> > +  @param[in] Ppi                 Pointer to the PPI data associated with this
> > function.
> > +
> > +  @retval EFI_SUCCESS            The function completes successfully
> > +  @retval Others                 Cannot initialize Nvme controller from given
> > EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +NvmeHostControllerPpiInstallationCallback (
> > +  IN EFI_PEI_SERVICES           **PeiServices,
> > +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> > +  IN VOID                       *Ppi
> > +  );
> > +
> >  #endif
> > diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > index 4dd6c5704fa3..ba6f1afbf168 100644
> > --- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > +++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
> > @@ -44,6 +44,7 @@
> >
> >  [LibraryClasses]
> >    DebugLib
> > +  DevicePathLib
> >    PeiServicesLib
> >    MemoryAllocationLib
> >    BaseMemoryLib
> > @@ -56,6 +57,7 @@
> >    gEdkiiPeiNvmExpressHostControllerPpiGuid       ## CONSUMES
> >    gEdkiiIoMmuPpiGuid                             ## CONSUMES
> >    gEfiEndOfPeiSignalPpiGuid                      ## CONSUMES
> > +  gEdkiiPeiPciDevicePpiGuid                      ## CONSUMES
> >    gEdkiiPeiNvmExpressPassThruPpiGuid             ## SOMETIMES_PRODUCES
> >    gEfiPeiVirtualBlockIoPpiGuid                   ## SOMETIMES_PRODUCES
> >    gEfiPeiVirtualBlockIo2PpiGuid                  ## SOMETIMES_PRODUCES
> > @@ -66,7 +68,6 @@
> >
> >  [Depex]
> >    gEfiPeiMemoryDiscoveredPpiGuid AND
> > -  gEdkiiPeiNvmExpressHostControllerPpiGuid AND
> >    gEfiPeiMasterBootModePpiGuid
> >
> >  [UserExtensions.TianoCore."ExtraFiles"]
> > --
> > 2.37.0.windows.1
> 
> 
> 
> 
> 


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

end of thread, other threads:[~2022-09-01  5:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-30  5:46 [PATCH v2 0/1] Use PCI_DEVICE_PPI to manage Nvme device chenxia1
2022-08-30  5:46 ` [PATCH v2 1/1] MdeModulePkg/NvmExpressPei: " chenxia1
2022-08-30  6:27   ` Wu, Hao A
2022-09-01  5:33     ` [edk2-devel] " Wu, Hao A

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