]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
authorChen, Xiao X <xiao.x.chen@intel.com>
Tue, 30 Aug 2022 05:46:48 +0000 (13:46 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 1 Sep 2022 05:32:08 +0000 (05:32 +0000)
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>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf

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