[edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding

Jeff Brasen via groups.io posted 1 patch 10 months ago
Failed in applying to current master (apply log)
5 files changed, 562 insertions(+), 129 deletions(-)
[edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
Posted by Jeff Brasen via groups.io 10 months ago
If the platform does not support any PCIe devices using the library

method allow devices to connect to host bridge via driver binding.



Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>

---

 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 649 ++++++++++++++----

 .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   1 +

 .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h  |  13 +

 .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    |  24 +

 MdeModulePkg/MdeModulePkg.dec                 |   4 +

 5 files changed, 562 insertions(+), 129 deletions(-)



diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c

index d573e532ba..506c6660ae 100644

--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c

+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c

@@ -422,167 +422,320 @@ IoMmuProtocolCallback (

 }

 

 /**

+  PCI Root Bridge Memory setup.

 

-  Entry point of this driver.

+  @param  RootBridge            Root Bridge instance.

 

-  @param ImageHandle  Image handle of this driver.

-  @param SystemTable  Pointer to standard EFI system table.

-

-  @retval EFI_SUCCESS       Succeed.

-  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.

+  @retval EFI_SUCCESS           Memory was setup correctly

+  @retval others                Error in setup

 

 **/

 EFI_STATUS

 EFIAPI

-InitializePciHostBridge (

-  IN EFI_HANDLE        ImageHandle,

-  IN EFI_SYSTEM_TABLE  *SystemTable

+PciRootBridgeMemorySetup (

+  IN PCI_ROOT_BRIDGE  *RootBridge

   )

 {

   EFI_STATUS                Status;

-  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;

-  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;

-  PCI_ROOT_BRIDGE           *RootBridges;

-  UINTN                     RootBridgeCount;

-  UINTN                     Index;

+  UINT64                    HostAddress;

   PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];

   UINTN                     MemApertureIndex;

-  BOOLEAN                   ResourceAssigned;

-  LIST_ENTRY                *Link;

-  UINT64                    HostAddress;

 

-  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);

-  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {

-    return EFI_UNSUPPORTED;

-  }

-

-  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);

-  ASSERT_EFI_ERROR (Status);

-

-  //

-  // Most systems in the world including complex servers have only one Host Bridge.

-  //

-  HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));

-  ASSERT (HostBridge != NULL);

-

-  HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;

-  HostBridge->CanRestarted = TRUE;

-  InitializeListHead (&HostBridge->RootBridges);

-  ResourceAssigned = FALSE;

-

-  //

-  // Create Root Bridge Device Handle in this Host Bridge

-  //

-  for (Index = 0; Index < RootBridgeCount; Index++) {

+  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {

     //

-    // Create Root Bridge Handle Instance

+    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.

+    // For GCD resource manipulation, we need to use host address.

     //

-    RootBridge = CreateRootBridge (&RootBridges[Index]);

-    ASSERT (RootBridge != NULL);

-    if (RootBridge == NULL) {

-      continue;

+    HostAddress = TO_HOST_ADDRESS (

+                    RootBridge->Io.Base,

+                    RootBridge->Io.Translation

+                    );

+

+    Status = AddIoSpace (

+               HostAddress,

+               RootBridge->Io.Limit - RootBridge->Io.Base + 1

+               );

+    ASSERT_EFI_ERROR (Status);

+    if (EFI_ERROR (Status)) {

+      return Status;

     }

 

-    //

-    // Make sure all root bridges share the same ResourceAssigned value.

-    //

-    if (Index == 0) {

-      ResourceAssigned = RootBridges[Index].ResourceAssigned;

-    } else {

-      ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);

+    if (RootBridge->ResourceAssigned) {

+      Status = gDS->AllocateIoSpace (

+                      EfiGcdAllocateAddress,

+                      EfiGcdIoTypeIo,

+                      0,

+                      RootBridge->Io.Limit - RootBridge->Io.Base + 1,

+                      &HostAddress,

+                      gImageHandle,

+                      NULL

+                      );

+      ASSERT_EFI_ERROR (Status);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

     }

+  }

+

+  //

+  // Add all the Mem/PMem aperture to GCD

+  // Mem/PMem shouldn't overlap with each other

+  // Root bridge which needs to combine MEM and PMEM should only report

+  // the MEM aperture in Mem

+  //

+  MemApertures[0] = &RootBridge->Mem;

+  MemApertures[1] = &RootBridge->MemAbove4G;

+  MemApertures[2] = &RootBridge->PMem;

+  MemApertures[3] = &RootBridge->PMemAbove4G;

 

-    if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {

+  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {

+    if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {

       //

       // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.

       // For GCD resource manipulation, we need to use host address.

       //

       HostAddress = TO_HOST_ADDRESS (

-                      RootBridges[Index].Io.Base,

-                      RootBridges[Index].Io.Translation

+                      MemApertures[MemApertureIndex]->Base,

+                      MemApertures[MemApertureIndex]->Translation

                       );

-

-      Status = AddIoSpace (

+      Status = AddMemoryMappedIoSpace (

                  HostAddress,

-                 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1

+                 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,

+                 EFI_MEMORY_UC

                  );

       ASSERT_EFI_ERROR (Status);

-      if (ResourceAssigned) {

-        Status = gDS->AllocateIoSpace (

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+

+      Status = gDS->SetMemorySpaceAttributes (

+                      HostAddress,

+                      MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,

+                      EFI_MEMORY_UC

+                      );

+      if (EFI_ERROR (Status)) {

+        DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));

+      }

+

+      if (RootBridge->ResourceAssigned) {

+        Status = gDS->AllocateMemorySpace (

                         EfiGcdAllocateAddress,

-                        EfiGcdIoTypeIo,

+                        EfiGcdMemoryTypeMemoryMappedIo,

                         0,

-                        RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,

+                        MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,

                         &HostAddress,

                         gImageHandle,

                         NULL

                         );

         ASSERT_EFI_ERROR (Status);

+        if (EFI_ERROR (Status)) {

+          return Status;

+        }

       }

     }

+  }

+

+  return EFI_SUCCESS;

+}

 

+/**

+  PCI Root Bridge Memory free.

+

+  @param  RootBridge            Root Bridge instance.

+

+  @retval EFI_SUCCESS           Memory was setup correctly

+  @retval others                Error in setup

+

+**/

+EFI_STATUS

+EFIAPI

+PciRootBridgeMemoryFree (

+  IN PCI_ROOT_BRIDGE  *RootBridge

+  )

+{

+  EFI_STATUS                Status;

+  UINT64                    HostAddress;

+  PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];

+  UINTN                     MemApertureIndex;

+

+  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {

     //

-    // Add all the Mem/PMem aperture to GCD

-    // Mem/PMem shouldn't overlap with each other

-    // Root bridge which needs to combine MEM and PMEM should only report

-    // the MEM aperture in Mem

+    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.

+    // For GCD resource manipulation, we need to use host address.

     //

-    MemApertures[0] = &RootBridges[Index].Mem;

-    MemApertures[1] = &RootBridges[Index].MemAbove4G;

-    MemApertures[2] = &RootBridges[Index].PMem;

-    MemApertures[3] = &RootBridges[Index].PMemAbove4G;

-

-    for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {

-      if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {

-        //

-        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.

-        // For GCD resource manipulation, we need to use host address.

-        //

-        HostAddress = TO_HOST_ADDRESS (

-                        MemApertures[MemApertureIndex]->Base,

-                        MemApertures[MemApertureIndex]->Translation

-                        );

-        Status = AddMemoryMappedIoSpace (

-                   HostAddress,

-                   MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,

-                   EFI_MEMORY_UC

-                   );

+    HostAddress = TO_HOST_ADDRESS (

+                    RootBridge->Io.Base,

+                    RootBridge->Io.Translation

+                    );

+

+    if (RootBridge->ResourceAssigned) {

+      Status = gDS->FreeIoSpace (HostAddress, RootBridge->Io.Limit - RootBridge->Io.Base + 1);

+      ASSERT_EFI_ERROR (Status);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+    }

+  }

+

+  //

+  // Add all the Mem/PMem aperture to GCD

+  // Mem/PMem shouldn't overlap with each other

+  // Root bridge which needs to combine MEM and PMEM should only report

+  // the MEM aperture in Mem

+  //

+  MemApertures[0] = &RootBridge->Mem;

+  MemApertures[1] = &RootBridge->MemAbove4G;

+  MemApertures[2] = &RootBridge->PMem;

+  MemApertures[3] = &RootBridge->PMemAbove4G;

+

+  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {

+    if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {

+      //

+      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.

+      // For GCD resource manipulation, we need to use host address.

+      //

+      HostAddress = TO_HOST_ADDRESS (

+                      MemApertures[MemApertureIndex]->Base,

+                      MemApertures[MemApertureIndex]->Translation

+                      );

+      if (RootBridge->ResourceAssigned) {

+        Status = gDS->FreeMemorySpace (HostAddress, RootBridge->Io.Limit - RootBridge->Io.Base + 1);

         ASSERT_EFI_ERROR (Status);

-        Status = gDS->SetMemorySpaceAttributes (

-                        HostAddress,

-                        MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,

-                        EFI_MEMORY_UC

-                        );

         if (EFI_ERROR (Status)) {

-          DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));

-        }

-

-        if (ResourceAssigned) {

-          Status = gDS->AllocateMemorySpace (

-                          EfiGcdAllocateAddress,

-                          EfiGcdMemoryTypeMemoryMappedIo,

-                          0,

-                          MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,

-                          &HostAddress,

-                          gImageHandle,

-                          NULL

-                          );

-          ASSERT_EFI_ERROR (Status);

+          return Status;

         }

       }

     }

+  }

 

-    //

-    // Insert Root Bridge Handle Instance

-    //

-    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);

+  return EFI_SUCCESS;

+}

+

+/**

+  Test to see if this driver supports ControllerHandle. Any ControllerHandle

+  than contains a gEdkiiPciHostBridgeProtocolGuid protocol can be supported.

+

+  @param  This                Protocol instance pointer.

+  @param  Controller          Handle of device to test.

+  @param  RemainingDevicePath Optional parameter use to pick a specific child

+                              device to start.

+

+  @retval EFI_SUCCESS         This driver supports this device.

+  @retval EFI_ALREADY_STARTED This driver is already running on this device.

+  @retval other               This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+PciHostBrigeDriverBindingSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+{

+  EFI_STATUS       Status;

+  PCI_ROOT_BRIDGE  *PciRootBridge;

+

+  //

+  // Check if Pci Host Bridge protocol is installed by platform

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEdkiiPciHostBridgeProtocolGuid,

+                  (VOID **)&PciRootBridge,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

   }

 

   //

-  // When resources were assigned, it's not needed to expose

-  // PciHostBridgeResourceAllocation protocol.

+  // Close the protocol used to perform the supported test

+  //

+  gBS->CloseProtocol (

+         Controller,

+         &gEdkiiPciHostBridgeProtocolGuid,

+         This->DriverBindingHandle,

+         Controller

+         );

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Start this driver on ControllerHandle and enumerate Pci bus and start

+  all device under PCI bus.

+

+  @param  This                 Protocol instance pointer.

+  @param  Controller           Handle of device to bind driver to.

+  @param  RemainingDevicePath  Optional parameter use to pick a specific child

+                               device to start.

+

+  @retval EFI_SUCCESS          This driver is added to ControllerHandle.

+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.

+  @retval other                This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+PciHostBrigeDriverBindingStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+{

+  EFI_STATUS                Status;

+  PCI_ROOT_BRIDGE           *PciRootBridge;

+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;

+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;

+  BOOLEAN                   MemorySetupDone;

+

+  MemorySetupDone = FALSE;

+  //

+  // Check if Pci Host Bridge protocol is installed by platform

   //

-  if (!ResourceAssigned) {

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEdkiiPciHostBridgeProtocolGuid,

+                  (VOID **)&PciRootBridge,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  RootBridge = CreateRootBridge (PciRootBridge);

+  ASSERT (RootBridge != NULL);

+  if (RootBridge == NULL) {

+    Status = EFI_DEVICE_ERROR;

+    goto ErrorExit;

+  }

+

+  Status = PciRootBridgeMemorySetup (PciRootBridge);

+  if (EFI_ERROR (Status)) {

+    goto ErrorExit;

+  }

+

+  MemorySetupDone = TRUE;

+

+  if (!PciRootBridge->ResourceAssigned) {

+    // Create host bridge

+    HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));

+    ASSERT (HostBridge != NULL);

+    if (HostBridge == NULL) {

+      Status = EFI_OUT_OF_RESOURCES;

+      goto ErrorExit;

+    }

+

+    HostBridge->Handle       = 0;

+    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;

+    HostBridge->CanRestarted = TRUE;

+    InitializeListHead (&HostBridge->RootBridges);

+

     HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;

     HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;

     HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;

@@ -599,28 +752,266 @@ InitializePciHostBridge (

                     NULL

                     );

     ASSERT_EFI_ERROR (Status);

-  }

+    if (EFI_ERROR (Status)) {

+      goto ErrorExit;

+    }

 

-  for (Link = GetFirstNode (&HostBridge->RootBridges)

-       ; !IsNull (&HostBridge->RootBridges, Link)

-       ; Link = GetNextNode (&HostBridge->RootBridges, Link)

-       )

-  {

-    RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);

+    //

+    // Insert Root Bridge Handle Instance

+    //

+    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);

     RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;

+  } else {

+    RootBridge->RootBridgeIo.ParentHandle = 0;

+  }

 

-    Status = gBS->InstallMultipleProtocolInterfaces (

-                    &RootBridge->Handle,

-                    &gEfiDevicePathProtocolGuid,

-                    RootBridge->DevicePath,

-                    &gEfiPciRootBridgeIoProtocolGuid,

-                    &RootBridge->RootBridgeIo,

-                    NULL

-                    );

-    ASSERT_EFI_ERROR (Status);

+  RootBridge->Handle = Controller;

+  Status             = gBS->InstallMultipleProtocolInterfaces (

+                              &RootBridge->Handle,

+                              &gEfiPciRootBridgeIoProtocolGuid,

+                              &RootBridge->RootBridgeIo,

+                              NULL

+                              );

+

+ErrorExit:

+  if (EFI_ERROR (Status)) {

+    if (MemorySetupDone) {

+      PciRootBridgeMemoryFree (PciRootBridge);

+    }

+

+    if (RootBridge != NULL) {

+      if (!IsListEmpty (&RootBridge->Link)) {

+        RemoveEntryList (&RootBridge->Link);

+      }

+

+      FreeRootBridge (RootBridge);

+    }

+

+    gBS->CloseProtocol (

+           Controller,

+           &gEdkiiPciHostBridgeProtocolGuid,

+           This->DriverBindingHandle,

+           Controller

+           );

   }

 

-  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);

+  return Status;

+}

+

+/**

+  Stop this driver on ControllerHandle. Support stopping any child handles

+  created by this driver.

+

+  @param  This              Protocol instance pointer.

+  @param  Controller        Handle of device to stop driver on.

+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of

+                            children is zero stop the entire bus driver.

+  @param  ChildHandleBuffer List of Child Handles to Stop.

+

+  @retval EFI_SUCCESS       This driver is removed ControllerHandle.

+  @retval other             This driver was not removed from this device.

+

+**/

+EFI_STATUS

+EFIAPI

+PciHostBrigeDriverBindingStop (

+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN  EFI_HANDLE                   Controller,

+  IN  UINTN                        NumberOfChildren,

+  IN  EFI_HANDLE                   *ChildHandleBuffer

+  )

+{

+  EFI_STATUS                       Status;

+  PCI_ROOT_BRIDGE                  *PciRootBridge;

+  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;

+

+  Status = gBS->HandleProtocol (

+                  Controller,

+                  &gEfiPciRootBridgeIoProtocolGuid,

+                  (VOID **)&RootBridgeIo

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  RootBridge = ROOT_BRIDGE_FROM_THIS (RootBridgeIo);

+

+  Status = gBS->HandleProtocol (

+                  Controller,

+                  &gEdkiiPciHostBridgeProtocolGuid,

+                  (VOID **)&PciRootBridge

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->UninstallMultipleProtocolInterfaces (

+                  Controller,

+                  &gEfiPciRootBridgeIoProtocolGuid,

+                  (VOID **)&PciRootBridge

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  if (!IsListEmpty (&RootBridge->Link)) {

+    RemoveEntryList (&RootBridge->Link);

+  }

+

+  PciRootBridgeMemoryFree (PciRootBridge);

+

+  FreeRootBridge (RootBridge);

+  gBS->CloseProtocol (

+         Controller,

+         &gEdkiiPciHostBridgeProtocolGuid,

+         This->DriverBindingHandle,

+         Controller

+         );

+  return EFI_SUCCESS;

+}

+

+//

+// PCI Bus Driver Global Variables

+//

+EFI_DRIVER_BINDING_PROTOCOL  gPciHostBrigeDriverBinding = {

+  PciHostBrigeDriverBindingSupported,

+  PciHostBrigeDriverBindingStart,

+  PciHostBrigeDriverBindingStop,

+  0xa,

+  NULL,

+  NULL

+};

+

+/**

+

+  Entry point of this driver.

+

+  @param ImageHandle  Image handle of this driver.

+  @param SystemTable  Pointer to standard EFI system table.

+

+  @retval EFI_SUCCESS       Succeed.

+  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.

+

+**/

+EFI_STATUS

+EFIAPI

+InitializePciHostBridge (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS                Status;

+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;

+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;

+  PCI_ROOT_BRIDGE           *RootBridges;

+  UINTN                     RootBridgeCount;

+  UINTN                     Index;

+  BOOLEAN                   ResourceAssigned;

+  LIST_ENTRY                *Link;

+

+  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);

+  ASSERT_EFI_ERROR (Status);

+

+  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);

+  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {

+    // Register for binding protocol if library enumeration is not used

+    Status = EfiLibInstallDriverBinding (

+               ImageHandle,

+               SystemTable,

+               &gPciHostBrigeDriverBinding,

+               ImageHandle

+               );

+    ASSERT_EFI_ERROR (Status);

+  } else {

+    //

+    // Most systems in the world including complex servers have only one Host Bridge.

+    //

+    HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));

+    ASSERT (HostBridge != NULL);

+

+    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;

+    HostBridge->CanRestarted = TRUE;

+    InitializeListHead (&HostBridge->RootBridges);

+    ResourceAssigned = FALSE;

+

+    //

+    // Create Root Bridge Device Handle in this Host Bridge

+    //

+    for (Index = 0; Index < RootBridgeCount; Index++) {

+      //

+      // Create Root Bridge Handle Instance

+      //

+      RootBridge = CreateRootBridge (&RootBridges[Index]);

+      ASSERT (RootBridge != NULL);

+      if (RootBridge == NULL) {

+        continue;

+      }

+

+      //

+      // Make sure all root bridges share the same ResourceAssigned value.

+      //

+      if (Index == 0) {

+        ResourceAssigned = RootBridges[Index].ResourceAssigned;

+      } else {

+        ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);

+      }

+

+      Status = PciRootBridgeMemorySetup (&RootBridges[Index]);

+      if (EFI_ERROR (Status)) {

+        continue;

+      }

+

+      //

+      // Insert Root Bridge Handle Instance

+      //

+      InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);

+    }

+

+    //

+    // When resources were assigned, it's not needed to expose

+    // PciHostBridgeResourceAllocation protocol.

+    //

+    if (!ResourceAssigned) {

+      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;

+      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;

+      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;

+      HostBridge->ResAlloc.StartBusEnumeration  = StartBusEnumeration;

+      HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;

+      HostBridge->ResAlloc.SubmitResources      = SubmitResources;

+      HostBridge->ResAlloc.GetProposedResources = GetProposedResources;

+      HostBridge->ResAlloc.PreprocessController = PreprocessController;

+

+      Status = gBS->InstallMultipleProtocolInterfaces (

+                      &HostBridge->Handle,

+                      &gEfiPciHostBridgeResourceAllocationProtocolGuid,

+                      &HostBridge->ResAlloc,

+                      NULL

+                      );

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    for (Link = GetFirstNode (&HostBridge->RootBridges)

+         ; !IsNull (&HostBridge->RootBridges, Link)

+         ; Link = GetNextNode (&HostBridge->RootBridges, Link)

+         )

+    {

+      RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);

+      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;

+

+      Status = gBS->InstallMultipleProtocolInterfaces (

+                      &RootBridge->Handle,

+                      &gEfiDevicePathProtocolGuid,

+                      RootBridge->DevicePath,

+                      &gEfiPciRootBridgeIoProtocolGuid,

+                      &RootBridge->RootBridgeIo,

+                      NULL

+                      );

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);

+  }

 

   if (!EFI_ERROR (Status)) {

     mIoMmuEvent = EfiCreateProtocolNotifyEvent (

diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf

index 9c24cacc30..ee4740b14f 100644

--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf

+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf

@@ -46,6 +46,7 @@

   gEfiPciRootBridgeIoProtocolGuid                 ## BY_START

   gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START

   gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES

+  gEdkiiPciHostBridgeProtocolGuid                 ## SOMETIMES_CONSUMES

 

 [Depex]

   gEfiCpuIo2ProtocolGuid AND

diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h

index 10a6200719..7923c4677b 100644

--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h

+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h

@@ -93,6 +93,19 @@ CreateRootBridge (

   IN PCI_ROOT_BRIDGE  *Bridge

   );

 

+/**

+  Free the Pci Root Bridge instance.

+

+  @param Bridge            The root bridge instance.

+

+  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created

+          or NULL if creation fails.

+**/

+VOID

+FreeRootBridge (

+  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge

+  );

+

 //

 // Protocol Member Function Prototypes

 //

diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

index 157a0ada80..f0eb465a9d 100644

--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

@@ -286,6 +286,30 @@ CreateRootBridge (

   return RootBridge;

 }

 

+/**

+  Free the Pci Root Bridge instance.

+

+  @param Bridge            The root bridge instance.

+

+  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created

+          or NULL if creation fails.

+**/

+VOID

+FreeRootBridge (

+  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge

+  )

+{

+  if (Bridge->ConfigBuffer != NULL) {

+    FreePool (Bridge->ConfigBuffer);

+  }

+

+  if (Bridge->DevicePath != NULL) {

+    FreePool (Bridge->DevicePath);

+  }

+

+  FreePool (Bridge);

+}

+

 /**

   Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.

 

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec

index d65dae18aa..24700fa797 100644

--- a/MdeModulePkg/MdeModulePkg.dec

+++ b/MdeModulePkg/MdeModulePkg.dec

@@ -692,6 +692,10 @@

   ## Include/Protocol/VariablePolicy.h

   gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }

 

+  ## Include/Library/PciHostBridgeLib.h

+  # Exposes a PCI_HOST_BRIDGE structure for driver binding usage

+  gEdkiiPciHostBridgeProtocolGuid = { 0xaff2b72d, 0x202e, 0x40e3, { 0x82, 0xd5, 0x9f, 0x6f, 0x61, 0xaf, 0x2a, 0x0b } }

+

 [PcdsFeatureFlag]

   ## Indicates if the platform can support update capsule across a system reset.<BR><BR>

   #   TRUE  - Supports update capsule across a system reset.<BR>

-- 

2.25.1





-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106532): https://edk2.groups.io/g/devel/message/106532
Mute This Topic: https://groups.io/mt/99859311/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
Posted by Ni, Ray 10 months ago
I failed to apply the patch in my local tree.

It seems you invented a new EdkiiRootBridgeIo protocol and a certain proprietary  driver would produce this protocol instance.
Then the open source PciHostBridge driver starts on that.

Then, why not implement your own PciHostBridgeLib and let it depends on some "AllRootBridgeIoInformationIsReady" protocol.
So that the PciHostBridge driver could still call PciHostBridgeLib and all your implementation in this patch can be in that lib.

Thanks,
Ray

> -----Original Message-----
> From: Jeff Brasen <jbrasen@nvidia.com>
> Sent: Friday, June 30, 2023 4:54 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray
> <ray.ni@intel.com>; Jeff Brasen <jbrasen@nvidia.com>
> Subject: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
> 
> If the platform does not support any PCIe devices using the library
> 
> method allow devices to connect to host bridge via driver binding.
> 
> 
> 
> Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
> 
> ---
> 
>  .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 649 ++++++++++++++----
> 
>  .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   1 +
> 
>  .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h  |  13 +
> 
>  .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    |  24 +
> 
>  MdeModulePkg/MdeModulePkg.dec                 |   4 +
> 
>  5 files changed, 562 insertions(+), 129 deletions(-)
> 
> 
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> 
> index d573e532ba..506c6660ae 100644
> 
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> 
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> 
> @@ -422,167 +422,320 @@ IoMmuProtocolCallback (
> 
>  }
> 
> 
> 
>  /**
> 
> +  PCI Root Bridge Memory setup.
> 
> 
> 
> -  Entry point of this driver.
> 
> +  @param  RootBridge            Root Bridge instance.
> 
> 
> 
> -  @param ImageHandle  Image handle of this driver.
> 
> -  @param SystemTable  Pointer to standard EFI system table.
> 
> -
> 
> -  @retval EFI_SUCCESS       Succeed.
> 
> -  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
> 
> +  @retval EFI_SUCCESS           Memory was setup correctly
> 
> +  @retval others                Error in setup
> 
> 
> 
>  **/
> 
>  EFI_STATUS
> 
>  EFIAPI
> 
> -InitializePciHostBridge (
> 
> -  IN EFI_HANDLE        ImageHandle,
> 
> -  IN EFI_SYSTEM_TABLE  *SystemTable
> 
> +PciRootBridgeMemorySetup (
> 
> +  IN PCI_ROOT_BRIDGE  *RootBridge
> 
>    )
> 
>  {
> 
>    EFI_STATUS                Status;
> 
> -  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> 
> -  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> 
> -  PCI_ROOT_BRIDGE           *RootBridges;
> 
> -  UINTN                     RootBridgeCount;
> 
> -  UINTN                     Index;
> 
> +  UINT64                    HostAddress;
> 
>    PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> 
>    UINTN                     MemApertureIndex;
> 
> -  BOOLEAN                   ResourceAssigned;
> 
> -  LIST_ENTRY                *Link;
> 
> -  UINT64                    HostAddress;
> 
> 
> 
> -  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> 
> -  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> 
> -    return EFI_UNSUPPORTED;
> 
> -  }
> 
> -
> 
> -  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID
> **)&mCpuIo);
> 
> -  ASSERT_EFI_ERROR (Status);
> 
> -
> 
> -  //
> 
> -  // Most systems in the world including complex servers have only one Host
> Bridge.
> 
> -  //
> 
> -  HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
> 
> -  ASSERT (HostBridge != NULL);
> 
> -
> 
> -  HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> 
> -  HostBridge->CanRestarted = TRUE;
> 
> -  InitializeListHead (&HostBridge->RootBridges);
> 
> -  ResourceAssigned = FALSE;
> 
> -
> 
> -  //
> 
> -  // Create Root Bridge Device Handle in this Host Bridge
> 
> -  //
> 
> -  for (Index = 0; Index < RootBridgeCount; Index++) {
> 
> +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> 
>      //
> 
> -    // Create Root Bridge Handle Instance
> 
> +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> 
> +    // For GCD resource manipulation, we need to use host address.
> 
>      //
> 
> -    RootBridge = CreateRootBridge (&RootBridges[Index]);
> 
> -    ASSERT (RootBridge != NULL);
> 
> -    if (RootBridge == NULL) {
> 
> -      continue;
> 
> +    HostAddress = TO_HOST_ADDRESS (
> 
> +                    RootBridge->Io.Base,
> 
> +                    RootBridge->Io.Translation
> 
> +                    );
> 
> +
> 
> +    Status = AddIoSpace (
> 
> +               HostAddress,
> 
> +               RootBridge->Io.Limit - RootBridge->Io.Base + 1
> 
> +               );
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    if (EFI_ERROR (Status)) {
> 
> +      return Status;
> 
>      }
> 
> 
> 
> -    //
> 
> -    // Make sure all root bridges share the same ResourceAssigned value.
> 
> -    //
> 
> -    if (Index == 0) {
> 
> -      ResourceAssigned = RootBridges[Index].ResourceAssigned;
> 
> -    } else {
> 
> -      ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
> 
> +    if (RootBridge->ResourceAssigned) {
> 
> +      Status = gDS->AllocateIoSpace (
> 
> +                      EfiGcdAllocateAddress,
> 
> +                      EfiGcdIoTypeIo,
> 
> +                      0,
> 
> +                      RootBridge->Io.Limit - RootBridge->Io.Base + 1,
> 
> +                      &HostAddress,
> 
> +                      gImageHandle,
> 
> +                      NULL
> 
> +                      );
> 
> +      ASSERT_EFI_ERROR (Status);
> 
> +      if (EFI_ERROR (Status)) {
> 
> +        return Status;
> 
> +      }
> 
>      }
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Add all the Mem/PMem aperture to GCD
> 
> +  // Mem/PMem shouldn't overlap with each other
> 
> +  // Root bridge which needs to combine MEM and PMEM should only report
> 
> +  // the MEM aperture in Mem
> 
> +  //
> 
> +  MemApertures[0] = &RootBridge->Mem;
> 
> +  MemApertures[1] = &RootBridge->MemAbove4G;
> 
> +  MemApertures[2] = &RootBridge->PMem;
> 
> +  MemApertures[3] = &RootBridge->PMemAbove4G;
> 
> 
> 
> -    if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
> 
> +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> (MemApertures); MemApertureIndex++) {
> 
> +    if (MemApertures[MemApertureIndex]->Base <=
> MemApertures[MemApertureIndex]->Limit) {
> 
>        //
> 
>        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> 
>        // For GCD resource manipulation, we need to use host address.
> 
>        //
> 
>        HostAddress = TO_HOST_ADDRESS (
> 
> -                      RootBridges[Index].Io.Base,
> 
> -                      RootBridges[Index].Io.Translation
> 
> +                      MemApertures[MemApertureIndex]->Base,
> 
> +                      MemApertures[MemApertureIndex]->Translation
> 
>                        );
> 
> -
> 
> -      Status = AddIoSpace (
> 
> +      Status = AddMemoryMappedIoSpace (
> 
>                   HostAddress,
> 
> -                 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
> 
> +                 MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
> 
> +                 EFI_MEMORY_UC
> 
>                   );
> 
>        ASSERT_EFI_ERROR (Status);
> 
> -      if (ResourceAssigned) {
> 
> -        Status = gDS->AllocateIoSpace (
> 
> +      if (EFI_ERROR (Status)) {
> 
> +        return Status;
> 
> +      }
> 
> +
> 
> +      Status = gDS->SetMemorySpaceAttributes (
> 
> +                      HostAddress,
> 
> +                      MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
> 
> +                      EFI_MEMORY_UC
> 
> +                      );
> 
> +      if (EFI_ERROR (Status)) {
> 
> +        DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> 
> +      }
> 
> +
> 
> +      if (RootBridge->ResourceAssigned) {
> 
> +        Status = gDS->AllocateMemorySpace (
> 
>                          EfiGcdAllocateAddress,
> 
> -                        EfiGcdIoTypeIo,
> 
> +                        EfiGcdMemoryTypeMemoryMappedIo,
> 
>                          0,
> 
> -                        RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
> 
> +                        MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
> 
>                          &HostAddress,
> 
>                          gImageHandle,
> 
>                          NULL
> 
>                          );
> 
>          ASSERT_EFI_ERROR (Status);
> 
> +        if (EFI_ERROR (Status)) {
> 
> +          return Status;
> 
> +        }
> 
>        }
> 
>      }
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> 
> 
> +/**
> 
> +  PCI Root Bridge Memory free.
> 
> +
> 
> +  @param  RootBridge            Root Bridge instance.
> 
> +
> 
> +  @retval EFI_SUCCESS           Memory was setup correctly
> 
> +  @retval others                Error in setup
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PciRootBridgeMemoryFree (
> 
> +  IN PCI_ROOT_BRIDGE  *RootBridge
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINT64                    HostAddress;
> 
> +  PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> 
> +  UINTN                     MemApertureIndex;
> 
> +
> 
> +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> 
>      //
> 
> -    // Add all the Mem/PMem aperture to GCD
> 
> -    // Mem/PMem shouldn't overlap with each other
> 
> -    // Root bridge which needs to combine MEM and PMEM should only report
> 
> -    // the MEM aperture in Mem
> 
> +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> 
> +    // For GCD resource manipulation, we need to use host address.
> 
>      //
> 
> -    MemApertures[0] = &RootBridges[Index].Mem;
> 
> -    MemApertures[1] = &RootBridges[Index].MemAbove4G;
> 
> -    MemApertures[2] = &RootBridges[Index].PMem;
> 
> -    MemApertures[3] = &RootBridges[Index].PMemAbove4G;
> 
> -
> 
> -    for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> (MemApertures); MemApertureIndex++) {
> 
> -      if (MemApertures[MemApertureIndex]->Base <=
> MemApertures[MemApertureIndex]->Limit) {
> 
> -        //
> 
> -        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> 
> -        // For GCD resource manipulation, we need to use host address.
> 
> -        //
> 
> -        HostAddress = TO_HOST_ADDRESS (
> 
> -                        MemApertures[MemApertureIndex]->Base,
> 
> -                        MemApertures[MemApertureIndex]->Translation
> 
> -                        );
> 
> -        Status = AddMemoryMappedIoSpace (
> 
> -                   HostAddress,
> 
> -                   MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
> 
> -                   EFI_MEMORY_UC
> 
> -                   );
> 
> +    HostAddress = TO_HOST_ADDRESS (
> 
> +                    RootBridge->Io.Base,
> 
> +                    RootBridge->Io.Translation
> 
> +                    );
> 
> +
> 
> +    if (RootBridge->ResourceAssigned) {
> 
> +      Status = gDS->FreeIoSpace (HostAddress, RootBridge->Io.Limit - RootBridge-
> >Io.Base + 1);
> 
> +      ASSERT_EFI_ERROR (Status);
> 
> +      if (EFI_ERROR (Status)) {
> 
> +        return Status;
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Add all the Mem/PMem aperture to GCD
> 
> +  // Mem/PMem shouldn't overlap with each other
> 
> +  // Root bridge which needs to combine MEM and PMEM should only report
> 
> +  // the MEM aperture in Mem
> 
> +  //
> 
> +  MemApertures[0] = &RootBridge->Mem;
> 
> +  MemApertures[1] = &RootBridge->MemAbove4G;
> 
> +  MemApertures[2] = &RootBridge->PMem;
> 
> +  MemApertures[3] = &RootBridge->PMemAbove4G;
> 
> +
> 
> +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> (MemApertures); MemApertureIndex++) {
> 
> +    if (MemApertures[MemApertureIndex]->Base <=
> MemApertures[MemApertureIndex]->Limit) {
> 
> +      //
> 
> +      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> 
> +      // For GCD resource manipulation, we need to use host address.
> 
> +      //
> 
> +      HostAddress = TO_HOST_ADDRESS (
> 
> +                      MemApertures[MemApertureIndex]->Base,
> 
> +                      MemApertures[MemApertureIndex]->Translation
> 
> +                      );
> 
> +      if (RootBridge->ResourceAssigned) {
> 
> +        Status = gDS->FreeMemorySpace (HostAddress, RootBridge->Io.Limit -
> RootBridge->Io.Base + 1);
> 
>          ASSERT_EFI_ERROR (Status);
> 
> -        Status = gDS->SetMemorySpaceAttributes (
> 
> -                        HostAddress,
> 
> -                        MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
> 
> -                        EFI_MEMORY_UC
> 
> -                        );
> 
>          if (EFI_ERROR (Status)) {
> 
> -          DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> 
> -        }
> 
> -
> 
> -        if (ResourceAssigned) {
> 
> -          Status = gDS->AllocateMemorySpace (
> 
> -                          EfiGcdAllocateAddress,
> 
> -                          EfiGcdMemoryTypeMemoryMappedIo,
> 
> -                          0,
> 
> -                          MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
> 
> -                          &HostAddress,
> 
> -                          gImageHandle,
> 
> -                          NULL
> 
> -                          );
> 
> -          ASSERT_EFI_ERROR (Status);
> 
> +          return Status;
> 
>          }
> 
>        }
> 
>      }
> 
> +  }
> 
> 
> 
> -    //
> 
> -    // Insert Root Bridge Handle Instance
> 
> -    //
> 
> -    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test to see if this driver supports ControllerHandle. Any ControllerHandle
> 
> +  than contains a gEdkiiPciHostBridgeProtocolGuid protocol can be supported.
> 
> +
> 
> +  @param  This                Protocol instance pointer.
> 
> +  @param  Controller          Handle of device to test.
> 
> +  @param  RemainingDevicePath Optional parameter use to pick a specific child
> 
> +                              device to start.
> 
> +
> 
> +  @retval EFI_SUCCESS         This driver supports this device.
> 
> +  @retval EFI_ALREADY_STARTED This driver is already running on this device.
> 
> +  @retval other               This driver does not support this device.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PciHostBrigeDriverBindingSupported (
> 
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> 
> +  IN EFI_HANDLE                   Controller,
> 
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS       Status;
> 
> +  PCI_ROOT_BRIDGE  *PciRootBridge;
> 
> +
> 
> +  //
> 
> +  // Check if Pci Host Bridge protocol is installed by platform
> 
> +  //
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEdkiiPciHostBridgeProtocolGuid,
> 
> +                  (VOID **)&PciRootBridge,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    return Status;
> 
>    }
> 
> 
> 
>    //
> 
> -  // When resources were assigned, it's not needed to expose
> 
> -  // PciHostBridgeResourceAllocation protocol.
> 
> +  // Close the protocol used to perform the supported test
> 
> +  //
> 
> +  gBS->CloseProtocol (
> 
> +         Controller,
> 
> +         &gEdkiiPciHostBridgeProtocolGuid,
> 
> +         This->DriverBindingHandle,
> 
> +         Controller
> 
> +         );
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Start this driver on ControllerHandle and enumerate Pci bus and start
> 
> +  all device under PCI bus.
> 
> +
> 
> +  @param  This                 Protocol instance pointer.
> 
> +  @param  Controller           Handle of device to bind driver to.
> 
> +  @param  RemainingDevicePath  Optional parameter use to pick a specific child
> 
> +                               device to start.
> 
> +
> 
> +  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
> 
> +  @retval EFI_ALREADY_STARTED  This driver is already running on
> ControllerHandle.
> 
> +  @retval other                This driver does not support this device.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PciHostBrigeDriverBindingStart (
> 
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> 
> +  IN EFI_HANDLE                   Controller,
> 
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  PCI_ROOT_BRIDGE           *PciRootBridge;
> 
> +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> 
> +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> 
> +  BOOLEAN                   MemorySetupDone;
> 
> +
> 
> +  MemorySetupDone = FALSE;
> 
> +  //
> 
> +  // Check if Pci Host Bridge protocol is installed by platform
> 
>    //
> 
> -  if (!ResourceAssigned) {
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEdkiiPciHostBridgeProtocolGuid,
> 
> +                  (VOID **)&PciRootBridge,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  RootBridge = CreateRootBridge (PciRootBridge);
> 
> +  ASSERT (RootBridge != NULL);
> 
> +  if (RootBridge == NULL) {
> 
> +    Status = EFI_DEVICE_ERROR;
> 
> +    goto ErrorExit;
> 
> +  }
> 
> +
> 
> +  Status = PciRootBridgeMemorySetup (PciRootBridge);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    goto ErrorExit;
> 
> +  }
> 
> +
> 
> +  MemorySetupDone = TRUE;
> 
> +
> 
> +  if (!PciRootBridge->ResourceAssigned) {
> 
> +    // Create host bridge
> 
> +    HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
> 
> +    ASSERT (HostBridge != NULL);
> 
> +    if (HostBridge == NULL) {
> 
> +      Status = EFI_OUT_OF_RESOURCES;
> 
> +      goto ErrorExit;
> 
> +    }
> 
> +
> 
> +    HostBridge->Handle       = 0;
> 
> +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> 
> +    HostBridge->CanRestarted = TRUE;
> 
> +    InitializeListHead (&HostBridge->RootBridges);
> 
> +
> 
>      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> 
>      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> 
>      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> 
> @@ -599,28 +752,266 @@ InitializePciHostBridge (
> 
>                      NULL
> 
>                      );
> 
>      ASSERT_EFI_ERROR (Status);
> 
> -  }
> 
> +    if (EFI_ERROR (Status)) {
> 
> +      goto ErrorExit;
> 
> +    }
> 
> 
> 
> -  for (Link = GetFirstNode (&HostBridge->RootBridges)
> 
> -       ; !IsNull (&HostBridge->RootBridges, Link)
> 
> -       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> 
> -       )
> 
> -  {
> 
> -    RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> 
> +    //
> 
> +    // Insert Root Bridge Handle Instance
> 
> +    //
> 
> +    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> 
>      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> 
> +  } else {
> 
> +    RootBridge->RootBridgeIo.ParentHandle = 0;
> 
> +  }
> 
> 
> 
> -    Status = gBS->InstallMultipleProtocolInterfaces (
> 
> -                    &RootBridge->Handle,
> 
> -                    &gEfiDevicePathProtocolGuid,
> 
> -                    RootBridge->DevicePath,
> 
> -                    &gEfiPciRootBridgeIoProtocolGuid,
> 
> -                    &RootBridge->RootBridgeIo,
> 
> -                    NULL
> 
> -                    );
> 
> -    ASSERT_EFI_ERROR (Status);
> 
> +  RootBridge->Handle = Controller;
> 
> +  Status             = gBS->InstallMultipleProtocolInterfaces (
> 
> +                              &RootBridge->Handle,
> 
> +                              &gEfiPciRootBridgeIoProtocolGuid,
> 
> +                              &RootBridge->RootBridgeIo,
> 
> +                              NULL
> 
> +                              );
> 
> +
> 
> +ErrorExit:
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    if (MemorySetupDone) {
> 
> +      PciRootBridgeMemoryFree (PciRootBridge);
> 
> +    }
> 
> +
> 
> +    if (RootBridge != NULL) {
> 
> +      if (!IsListEmpty (&RootBridge->Link)) {
> 
> +        RemoveEntryList (&RootBridge->Link);
> 
> +      }
> 
> +
> 
> +      FreeRootBridge (RootBridge);
> 
> +    }
> 
> +
> 
> +    gBS->CloseProtocol (
> 
> +           Controller,
> 
> +           &gEdkiiPciHostBridgeProtocolGuid,
> 
> +           This->DriverBindingHandle,
> 
> +           Controller
> 
> +           );
> 
>    }
> 
> 
> 
> -  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Stop this driver on ControllerHandle. Support stopping any child handles
> 
> +  created by this driver.
> 
> +
> 
> +  @param  This              Protocol instance pointer.
> 
> +  @param  Controller        Handle of device to stop driver on.
> 
> +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If
> number of
> 
> +                            children is zero stop the entire bus driver.
> 
> +  @param  ChildHandleBuffer List of Child Handles to Stop.
> 
> +
> 
> +  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
> 
> +  @retval other             This driver was not removed from this device.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PciHostBrigeDriverBindingStop (
> 
> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
> 
> +  IN  EFI_HANDLE                   Controller,
> 
> +  IN  UINTN                        NumberOfChildren,
> 
> +  IN  EFI_HANDLE                   *ChildHandleBuffer
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                       Status;
> 
> +  PCI_ROOT_BRIDGE                  *PciRootBridge;
> 
> +  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;
> 
> +  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;
> 
> +
> 
> +  Status = gBS->HandleProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiPciRootBridgeIoProtocolGuid,
> 
> +                  (VOID **)&RootBridgeIo
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (RootBridgeIo);
> 
> +
> 
> +  Status = gBS->HandleProtocol (
> 
> +                  Controller,
> 
> +                  &gEdkiiPciHostBridgeProtocolGuid,
> 
> +                  (VOID **)&PciRootBridge
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> 
> +                  Controller,
> 
> +                  &gEfiPciRootBridgeIoProtocolGuid,
> 
> +                  (VOID **)&PciRootBridge
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  if (!IsListEmpty (&RootBridge->Link)) {
> 
> +    RemoveEntryList (&RootBridge->Link);
> 
> +  }
> 
> +
> 
> +  PciRootBridgeMemoryFree (PciRootBridge);
> 
> +
> 
> +  FreeRootBridge (RootBridge);
> 
> +  gBS->CloseProtocol (
> 
> +         Controller,
> 
> +         &gEdkiiPciHostBridgeProtocolGuid,
> 
> +         This->DriverBindingHandle,
> 
> +         Controller
> 
> +         );
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +//
> 
> +// PCI Bus Driver Global Variables
> 
> +//
> 
> +EFI_DRIVER_BINDING_PROTOCOL  gPciHostBrigeDriverBinding = {
> 
> +  PciHostBrigeDriverBindingSupported,
> 
> +  PciHostBrigeDriverBindingStart,
> 
> +  PciHostBrigeDriverBindingStop,
> 
> +  0xa,
> 
> +  NULL,
> 
> +  NULL
> 
> +};
> 
> +
> 
> +/**
> 
> +
> 
> +  Entry point of this driver.
> 
> +
> 
> +  @param ImageHandle  Image handle of this driver.
> 
> +  @param SystemTable  Pointer to standard EFI system table.
> 
> +
> 
> +  @retval EFI_SUCCESS       Succeed.
> 
> +  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +InitializePciHostBridge (
> 
> +  IN EFI_HANDLE        ImageHandle,
> 
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> 
> +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> 
> +  PCI_ROOT_BRIDGE           *RootBridges;
> 
> +  UINTN                     RootBridgeCount;
> 
> +  UINTN                     Index;
> 
> +  BOOLEAN                   ResourceAssigned;
> 
> +  LIST_ENTRY                *Link;
> 
> +
> 
> +  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID
> **)&mCpuIo);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> 
> +  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> 
> +    // Register for binding protocol if library enumeration is not used
> 
> +    Status = EfiLibInstallDriverBinding (
> 
> +               ImageHandle,
> 
> +               SystemTable,
> 
> +               &gPciHostBrigeDriverBinding,
> 
> +               ImageHandle
> 
> +               );
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +  } else {
> 
> +    //
> 
> +    // Most systems in the world including complex servers have only one Host
> Bridge.
> 
> +    //
> 
> +    HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
> 
> +    ASSERT (HostBridge != NULL);
> 
> +
> 
> +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> 
> +    HostBridge->CanRestarted = TRUE;
> 
> +    InitializeListHead (&HostBridge->RootBridges);
> 
> +    ResourceAssigned = FALSE;
> 
> +
> 
> +    //
> 
> +    // Create Root Bridge Device Handle in this Host Bridge
> 
> +    //
> 
> +    for (Index = 0; Index < RootBridgeCount; Index++) {
> 
> +      //
> 
> +      // Create Root Bridge Handle Instance
> 
> +      //
> 
> +      RootBridge = CreateRootBridge (&RootBridges[Index]);
> 
> +      ASSERT (RootBridge != NULL);
> 
> +      if (RootBridge == NULL) {
> 
> +        continue;
> 
> +      }
> 
> +
> 
> +      //
> 
> +      // Make sure all root bridges share the same ResourceAssigned value.
> 
> +      //
> 
> +      if (Index == 0) {
> 
> +        ResourceAssigned = RootBridges[Index].ResourceAssigned;
> 
> +      } else {
> 
> +        ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
> 
> +      }
> 
> +
> 
> +      Status = PciRootBridgeMemorySetup (&RootBridges[Index]);
> 
> +      if (EFI_ERROR (Status)) {
> 
> +        continue;
> 
> +      }
> 
> +
> 
> +      //
> 
> +      // Insert Root Bridge Handle Instance
> 
> +      //
> 
> +      InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // When resources were assigned, it's not needed to expose
> 
> +    // PciHostBridgeResourceAllocation protocol.
> 
> +    //
> 
> +    if (!ResourceAssigned) {
> 
> +      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> 
> +      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> 
> +      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> 
> +      HostBridge->ResAlloc.StartBusEnumeration  = StartBusEnumeration;
> 
> +      HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
> 
> +      HostBridge->ResAlloc.SubmitResources      = SubmitResources;
> 
> +      HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
> 
> +      HostBridge->ResAlloc.PreprocessController = PreprocessController;
> 
> +
> 
> +      Status = gBS->InstallMultipleProtocolInterfaces (
> 
> +                      &HostBridge->Handle,
> 
> +                      &gEfiPciHostBridgeResourceAllocationProtocolGuid,
> 
> +                      &HostBridge->ResAlloc,
> 
> +                      NULL
> 
> +                      );
> 
> +      ASSERT_EFI_ERROR (Status);
> 
> +    }
> 
> +
> 
> +    for (Link = GetFirstNode (&HostBridge->RootBridges)
> 
> +         ; !IsNull (&HostBridge->RootBridges, Link)
> 
> +         ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> 
> +         )
> 
> +    {
> 
> +      RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> 
> +      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> 
> +
> 
> +      Status = gBS->InstallMultipleProtocolInterfaces (
> 
> +                      &RootBridge->Handle,
> 
> +                      &gEfiDevicePathProtocolGuid,
> 
> +                      RootBridge->DevicePath,
> 
> +                      &gEfiPciRootBridgeIoProtocolGuid,
> 
> +                      &RootBridge->RootBridgeIo,
> 
> +                      NULL
> 
> +                      );
> 
> +      ASSERT_EFI_ERROR (Status);
> 
> +    }
> 
> +
> 
> +    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> 
> +  }
> 
> 
> 
>    if (!EFI_ERROR (Status)) {
> 
>      mIoMmuEvent = EfiCreateProtocolNotifyEvent (
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> 
> index 9c24cacc30..ee4740b14f 100644
> 
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> 
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> 
> @@ -46,6 +46,7 @@
> 
>    gEfiPciRootBridgeIoProtocolGuid                 ## BY_START
> 
>    gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
> 
>    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> 
> +  gEdkiiPciHostBridgeProtocolGuid                 ## SOMETIMES_CONSUMES
> 
> 
> 
>  [Depex]
> 
>    gEfiCpuIo2ProtocolGuid AND
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> 
> index 10a6200719..7923c4677b 100644
> 
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> 
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> 
> @@ -93,6 +93,19 @@ CreateRootBridge (
> 
>    IN PCI_ROOT_BRIDGE  *Bridge
> 
>    );
> 
> 
> 
> +/**
> 
> +  Free the Pci Root Bridge instance.
> 
> +
> 
> +  @param Bridge            The root bridge instance.
> 
> +
> 
> +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> 
> +          or NULL if creation fails.
> 
> +**/
> 
> +VOID
> 
> +FreeRootBridge (
> 
> +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> 
> +  );
> 
> +
> 
>  //
> 
>  // Protocol Member Function Prototypes
> 
>  //
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> 
> index 157a0ada80..f0eb465a9d 100644
> 
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> 
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> 
> @@ -286,6 +286,30 @@ CreateRootBridge (
> 
>    return RootBridge;
> 
>  }
> 
> 
> 
> +/**
> 
> +  Free the Pci Root Bridge instance.
> 
> +
> 
> +  @param Bridge            The root bridge instance.
> 
> +
> 
> +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> 
> +          or NULL if creation fails.
> 
> +**/
> 
> +VOID
> 
> +FreeRootBridge (
> 
> +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> 
> +  )
> 
> +{
> 
> +  if (Bridge->ConfigBuffer != NULL) {
> 
> +    FreePool (Bridge->ConfigBuffer);
> 
> +  }
> 
> +
> 
> +  if (Bridge->DevicePath != NULL) {
> 
> +    FreePool (Bridge->DevicePath);
> 
> +  }
> 
> +
> 
> +  FreePool (Bridge);
> 
> +}
> 
> +
> 
>  /**
> 
>    Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
> 
> 
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> 
> index d65dae18aa..24700fa797 100644
> 
> --- a/MdeModulePkg/MdeModulePkg.dec
> 
> +++ b/MdeModulePkg/MdeModulePkg.dec
> 
> @@ -692,6 +692,10 @@
> 
>    ## Include/Protocol/VariablePolicy.h
> 
>    gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD,
> 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
> 
> 
> 
> +  ## Include/Library/PciHostBridgeLib.h
> 
> +  # Exposes a PCI_HOST_BRIDGE structure for driver binding usage
> 
> +  gEdkiiPciHostBridgeProtocolGuid = { 0xaff2b72d, 0x202e, 0x40e3, { 0x82, 0xd5,
> 0x9f, 0x6f, 0x61, 0xaf, 0x2a, 0x0b } }
> 
> +
> 
>  [PcdsFeatureFlag]
> 
>    ## Indicates if the platform can support update capsule across a system
> reset.<BR><BR>
> 
>    #   TRUE  - Supports update capsule across a system reset.<BR>
> 
> --
> 
> 2.25.1
> 
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106552): https://edk2.groups.io/g/devel/message/106552
Mute This Topic: https://groups.io/mt/99859311/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
Posted by Jeff Brasen via groups.io 10 months ago
Not sure why the patch failed to apply I'll see if there is something wrong with my gitconfig tomorrow. The path you suggested below is exactly what our current implementation does. However, I am trying to make our pcie controller driver do async initialization so that using a depex is less ideal as we may have to postpone driver load to after end of dxe instead of just the connection. It seemed that a driver binding type approach was a good approach for this.

On a less important implementation if the pieces that live under the library are driver binding we have to reject any stop requests as there is no driver linkage between the two layers.

-Jeff


-----Original Message-----
From: Ni, Ray <ray.ni@intel.com> 
Sent: Thursday, June 29, 2023 8:29 PM
To: Jeff Brasen <jbrasen@nvidia.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding

External email: Use caution opening links or attachments


I failed to apply the patch in my local tree.

It seems you invented a new EdkiiRootBridgeIo protocol and a certain proprietary  driver would produce this protocol instance.
Then the open source PciHostBridge driver starts on that.

Then, why not implement your own PciHostBridgeLib and let it depends on some "AllRootBridgeIoInformationIsReady" protocol.
So that the PciHostBridge driver could still call PciHostBridgeLib and all your implementation in this patch can be in that lib.

Thanks,
Ray

> -----Original Message-----
> From: Jeff Brasen <jbrasen@nvidia.com>
> Sent: Friday, June 30, 2023 4:54 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming 
> <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray 
> <ray.ni@intel.com>; Jeff Brasen <jbrasen@nvidia.com>
> Subject: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver 
> binding
>
> If the platform does not support any PCIe devices using the library
>
> method allow devices to connect to host bridge via driver binding.
>
>
>
> Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
>
> ---
>
>  .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 649 
> ++++++++++++++----
>
>  .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   1 +
>
>  .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h  |  13 +
>
>  .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    |  24 +
>
>  MdeModulePkg/MdeModulePkg.dec                 |   4 +
>
>  5 files changed, 562 insertions(+), 129 deletions(-)
>
>
>
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
>
> index d573e532ba..506c6660ae 100644
>
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
>
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
>
> @@ -422,167 +422,320 @@ IoMmuProtocolCallback (
>
>  }
>
>
>
>  /**
>
> +  PCI Root Bridge Memory setup.
>
>
>
> -  Entry point of this driver.
>
> +  @param  RootBridge            Root Bridge instance.
>
>
>
> -  @param ImageHandle  Image handle of this driver.
>
> -  @param SystemTable  Pointer to standard EFI system table.
>
> -
>
> -  @retval EFI_SUCCESS       Succeed.
>
> -  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
>
> +  @retval EFI_SUCCESS           Memory was setup correctly
>
> +  @retval others                Error in setup
>
>
>
>  **/
>
>  EFI_STATUS
>
>  EFIAPI
>
> -InitializePciHostBridge (
>
> -  IN EFI_HANDLE        ImageHandle,
>
> -  IN EFI_SYSTEM_TABLE  *SystemTable
>
> +PciRootBridgeMemorySetup (
>
> +  IN PCI_ROOT_BRIDGE  *RootBridge
>
>    )
>
>  {
>
>    EFI_STATUS                Status;
>
> -  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
>
> -  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
>
> -  PCI_ROOT_BRIDGE           *RootBridges;
>
> -  UINTN                     RootBridgeCount;
>
> -  UINTN                     Index;
>
> +  UINT64                    HostAddress;
>
>    PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
>
>    UINTN                     MemApertureIndex;
>
> -  BOOLEAN                   ResourceAssigned;
>
> -  LIST_ENTRY                *Link;
>
> -  UINT64                    HostAddress;
>
>
>
> -  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
>
> -  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
>
> -    return EFI_UNSUPPORTED;
>
> -  }
>
> -
>
> -  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID 
> **)&mCpuIo);
>
> -  ASSERT_EFI_ERROR (Status);
>
> -
>
> -  //
>
> -  // Most systems in the world including complex servers have only 
> one Host Bridge.
>
> -  //
>
> -  HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
>
> -  ASSERT (HostBridge != NULL);
>
> -
>
> -  HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
>
> -  HostBridge->CanRestarted = TRUE;
>
> -  InitializeListHead (&HostBridge->RootBridges);
>
> -  ResourceAssigned = FALSE;
>
> -
>
> -  //
>
> -  // Create Root Bridge Device Handle in this Host Bridge
>
> -  //
>
> -  for (Index = 0; Index < RootBridgeCount; Index++) {
>
> +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
>
>      //
>
> -    // Create Root Bridge Handle Instance
>
> +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
>
> +    // For GCD resource manipulation, we need to use host address.
>
>      //
>
> -    RootBridge = CreateRootBridge (&RootBridges[Index]);
>
> -    ASSERT (RootBridge != NULL);
>
> -    if (RootBridge == NULL) {
>
> -      continue;
>
> +    HostAddress = TO_HOST_ADDRESS (
>
> +                    RootBridge->Io.Base,
>
> +                    RootBridge->Io.Translation
>
> +                    );
>
> +
>
> +    Status = AddIoSpace (
>
> +               HostAddress,
>
> +               RootBridge->Io.Limit - RootBridge->Io.Base + 1
>
> +               );
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    if (EFI_ERROR (Status)) {
>
> +      return Status;
>
>      }
>
>
>
> -    //
>
> -    // Make sure all root bridges share the same ResourceAssigned value.
>
> -    //
>
> -    if (Index == 0) {
>
> -      ResourceAssigned = RootBridges[Index].ResourceAssigned;
>
> -    } else {
>
> -      ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
>
> +    if (RootBridge->ResourceAssigned) {
>
> +      Status = gDS->AllocateIoSpace (
>
> +                      EfiGcdAllocateAddress,
>
> +                      EfiGcdIoTypeIo,
>
> +                      0,
>
> +                      RootBridge->Io.Limit - RootBridge->Io.Base + 1,
>
> +                      &HostAddress,
>
> +                      gImageHandle,
>
> +                      NULL
>
> +                      );
>
> +      ASSERT_EFI_ERROR (Status);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
>      }
>
> +  }
>
> +
>
> +  //
>
> +  // Add all the Mem/PMem aperture to GCD
>
> +  // Mem/PMem shouldn't overlap with each other
>
> +  // Root bridge which needs to combine MEM and PMEM should only 
> + report
>
> +  // the MEM aperture in Mem
>
> +  //
>
> +  MemApertures[0] = &RootBridge->Mem;
>
> +  MemApertures[1] = &RootBridge->MemAbove4G;
>
> +  MemApertures[2] = &RootBridge->PMem;
>
> +  MemApertures[3] = &RootBridge->PMemAbove4G;
>
>
>
> -    if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
>
> +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> (MemApertures); MemApertureIndex++) {
>
> +    if (MemApertures[MemApertureIndex]->Base <=
> MemApertures[MemApertureIndex]->Limit) {
>
>        //
>
>        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
>
>        // For GCD resource manipulation, we need to use host address.
>
>        //
>
>        HostAddress = TO_HOST_ADDRESS (
>
> -                      RootBridges[Index].Io.Base,
>
> -                      RootBridges[Index].Io.Translation
>
> +                      MemApertures[MemApertureIndex]->Base,
>
> +                      MemApertures[MemApertureIndex]->Translation
>
>                        );
>
> -
>
> -      Status = AddIoSpace (
>
> +      Status = AddMemoryMappedIoSpace (
>
>                   HostAddress,
>
> -                 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
>
> +                 MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
>
> +                 EFI_MEMORY_UC
>
>                   );
>
>        ASSERT_EFI_ERROR (Status);
>
> -      if (ResourceAssigned) {
>
> -        Status = gDS->AllocateIoSpace (
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +
>
> +      Status = gDS->SetMemorySpaceAttributes (
>
> +                      HostAddress,
>
> +                      MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
>
> +                      EFI_MEMORY_UC
>
> +                      );
>
> +      if (EFI_ERROR (Status)) {
>
> +        DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
>
> +      }
>
> +
>
> +      if (RootBridge->ResourceAssigned) {
>
> +        Status = gDS->AllocateMemorySpace (
>
>                          EfiGcdAllocateAddress,
>
> -                        EfiGcdIoTypeIo,
>
> +                        EfiGcdMemoryTypeMemoryMappedIo,
>
>                          0,
>
> -                        RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
>
> +                        MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
>
>                          &HostAddress,
>
>                          gImageHandle,
>
>                          NULL
>
>                          );
>
>          ASSERT_EFI_ERROR (Status);
>
> +        if (EFI_ERROR (Status)) {
>
> +          return Status;
>
> +        }
>
>        }
>
>      }
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
>
>
> +/**
>
> +  PCI Root Bridge Memory free.
>
> +
>
> +  @param  RootBridge            Root Bridge instance.
>
> +
>
> +  @retval EFI_SUCCESS           Memory was setup correctly
>
> +  @retval others                Error in setup
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PciRootBridgeMemoryFree (
>
> +  IN PCI_ROOT_BRIDGE  *RootBridge
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  UINT64                    HostAddress;
>
> +  PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
>
> +  UINTN                     MemApertureIndex;
>
> +
>
> +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
>
>      //
>
> -    // Add all the Mem/PMem aperture to GCD
>
> -    // Mem/PMem shouldn't overlap with each other
>
> -    // Root bridge which needs to combine MEM and PMEM should only report
>
> -    // the MEM aperture in Mem
>
> +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
>
> +    // For GCD resource manipulation, we need to use host address.
>
>      //
>
> -    MemApertures[0] = &RootBridges[Index].Mem;
>
> -    MemApertures[1] = &RootBridges[Index].MemAbove4G;
>
> -    MemApertures[2] = &RootBridges[Index].PMem;
>
> -    MemApertures[3] = &RootBridges[Index].PMemAbove4G;
>
> -
>
> -    for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> (MemApertures); MemApertureIndex++) {
>
> -      if (MemApertures[MemApertureIndex]->Base <=
> MemApertures[MemApertureIndex]->Limit) {
>
> -        //
>
> -        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
>
> -        // For GCD resource manipulation, we need to use host address.
>
> -        //
>
> -        HostAddress = TO_HOST_ADDRESS (
>
> -                        MemApertures[MemApertureIndex]->Base,
>
> -                        MemApertures[MemApertureIndex]->Translation
>
> -                        );
>
> -        Status = AddMemoryMappedIoSpace (
>
> -                   HostAddress,
>
> -                   MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
>
> -                   EFI_MEMORY_UC
>
> -                   );
>
> +    HostAddress = TO_HOST_ADDRESS (
>
> +                    RootBridge->Io.Base,
>
> +                    RootBridge->Io.Translation
>
> +                    );
>
> +
>
> +    if (RootBridge->ResourceAssigned) {
>
> +      Status = gDS->FreeIoSpace (HostAddress, RootBridge->Io.Limit - 
> + RootBridge-
> >Io.Base + 1);
>
> +      ASSERT_EFI_ERROR (Status);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return Status;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Add all the Mem/PMem aperture to GCD
>
> +  // Mem/PMem shouldn't overlap with each other
>
> +  // Root bridge which needs to combine MEM and PMEM should only 
> + report
>
> +  // the MEM aperture in Mem
>
> +  //
>
> +  MemApertures[0] = &RootBridge->Mem;
>
> +  MemApertures[1] = &RootBridge->MemAbove4G;
>
> +  MemApertures[2] = &RootBridge->PMem;
>
> +  MemApertures[3] = &RootBridge->PMemAbove4G;
>
> +
>
> +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> (MemApertures); MemApertureIndex++) {
>
> +    if (MemApertures[MemApertureIndex]->Base <=
> MemApertures[MemApertureIndex]->Limit) {
>
> +      //
>
> +      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
>
> +      // For GCD resource manipulation, we need to use host address.
>
> +      //
>
> +      HostAddress = TO_HOST_ADDRESS (
>
> +                      MemApertures[MemApertureIndex]->Base,
>
> +                      MemApertures[MemApertureIndex]->Translation
>
> +                      );
>
> +      if (RootBridge->ResourceAssigned) {
>
> +        Status = gDS->FreeMemorySpace (HostAddress, 
> + RootBridge->Io.Limit -
> RootBridge->Io.Base + 1);
>
>          ASSERT_EFI_ERROR (Status);
>
> -        Status = gDS->SetMemorySpaceAttributes (
>
> -                        HostAddress,
>
> -                        MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
>
> -                        EFI_MEMORY_UC
>
> -                        );
>
>          if (EFI_ERROR (Status)) {
>
> -          DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
>
> -        }
>
> -
>
> -        if (ResourceAssigned) {
>
> -          Status = gDS->AllocateMemorySpace (
>
> -                          EfiGcdAllocateAddress,
>
> -                          EfiGcdMemoryTypeMemoryMappedIo,
>
> -                          0,
>
> -                          MemApertures[MemApertureIndex]->Limit -
> MemApertures[MemApertureIndex]->Base + 1,
>
> -                          &HostAddress,
>
> -                          gImageHandle,
>
> -                          NULL
>
> -                          );
>
> -          ASSERT_EFI_ERROR (Status);
>
> +          return Status;
>
>          }
>
>        }
>
>      }
>
> +  }
>
>
>
> -    //
>
> -    // Insert Root Bridge Handle Instance
>
> -    //
>
> -    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Test to see if this driver supports ControllerHandle. Any 
> + ControllerHandle
>
> +  than contains a gEdkiiPciHostBridgeProtocolGuid protocol can be supported.
>
> +
>
> +  @param  This                Protocol instance pointer.
>
> +  @param  Controller          Handle of device to test.
>
> +  @param  RemainingDevicePath Optional parameter use to pick a 
> + specific child
>
> +                              device to start.
>
> +
>
> +  @retval EFI_SUCCESS         This driver supports this device.
>
> +  @retval EFI_ALREADY_STARTED This driver is already running on this device.
>
> +  @retval other               This driver does not support this device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PciHostBrigeDriverBindingSupported (
>
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
>
> +  IN EFI_HANDLE                   Controller,
>
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
>
> +  )
>
> +{
>
> +  EFI_STATUS       Status;
>
> +  PCI_ROOT_BRIDGE  *PciRootBridge;
>
> +
>
> +  //
>
> +  // Check if Pci Host Bridge protocol is installed by platform
>
> +  //
>
> +  Status = gBS->OpenProtocol (
>
> +                  Controller,
>
> +                  &gEdkiiPciHostBridgeProtocolGuid,
>
> +                  (VOID **)&PciRootBridge,
>
> +                  This->DriverBindingHandle,
>
> +                  Controller,
>
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
>    }
>
>
>
>    //
>
> -  // When resources were assigned, it's not needed to expose
>
> -  // PciHostBridgeResourceAllocation protocol.
>
> +  // Close the protocol used to perform the supported test
>
> +  //
>
> +  gBS->CloseProtocol (
>
> +         Controller,
>
> +         &gEdkiiPciHostBridgeProtocolGuid,
>
> +         This->DriverBindingHandle,
>
> +         Controller
>
> +         );
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Start this driver on ControllerHandle and enumerate Pci bus and 
> + start
>
> +  all device under PCI bus.
>
> +
>
> +  @param  This                 Protocol instance pointer.
>
> +  @param  Controller           Handle of device to bind driver to.
>
> +  @param  RemainingDevicePath  Optional parameter use to pick a 
> + specific child
>
> +                               device to start.
>
> +
>
> +  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
>
> +  @retval EFI_ALREADY_STARTED  This driver is already running on
> ControllerHandle.
>
> +  @retval other                This driver does not support this device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PciHostBrigeDriverBindingStart (
>
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
>
> +  IN EFI_HANDLE                   Controller,
>
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  PCI_ROOT_BRIDGE           *PciRootBridge;
>
> +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
>
> +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
>
> +  BOOLEAN                   MemorySetupDone;
>
> +
>
> +  MemorySetupDone = FALSE;
>
> +  //
>
> +  // Check if Pci Host Bridge protocol is installed by platform
>
>    //
>
> -  if (!ResourceAssigned) {
>
> +  Status = gBS->OpenProtocol (
>
> +                  Controller,
>
> +                  &gEdkiiPciHostBridgeProtocolGuid,
>
> +                  (VOID **)&PciRootBridge,
>
> +                  This->DriverBindingHandle,
>
> +                  Controller,
>
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  RootBridge = CreateRootBridge (PciRootBridge);
>
> +  ASSERT (RootBridge != NULL);
>
> +  if (RootBridge == NULL) {
>
> +    Status = EFI_DEVICE_ERROR;
>
> +    goto ErrorExit;
>
> +  }
>
> +
>
> +  Status = PciRootBridgeMemorySetup (PciRootBridge);
>
> +  if (EFI_ERROR (Status)) {
>
> +    goto ErrorExit;
>
> +  }
>
> +
>
> +  MemorySetupDone = TRUE;
>
> +
>
> +  if (!PciRootBridge->ResourceAssigned) {
>
> +    // Create host bridge
>
> +    HostBridge = AllocateZeroPool (sizeof 
> + (PCI_HOST_BRIDGE_INSTANCE));
>
> +    ASSERT (HostBridge != NULL);
>
> +    if (HostBridge == NULL) {
>
> +      Status = EFI_OUT_OF_RESOURCES;
>
> +      goto ErrorExit;
>
> +    }
>
> +
>
> +    HostBridge->Handle       = 0;
>
> +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
>
> +    HostBridge->CanRestarted = TRUE;
>
> +    InitializeListHead (&HostBridge->RootBridges);
>
> +
>
>      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
>
>      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
>
>      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
>
> @@ -599,28 +752,266 @@ InitializePciHostBridge (
>
>                      NULL
>
>                      );
>
>      ASSERT_EFI_ERROR (Status);
>
> -  }
>
> +    if (EFI_ERROR (Status)) {
>
> +      goto ErrorExit;
>
> +    }
>
>
>
> -  for (Link = GetFirstNode (&HostBridge->RootBridges)
>
> -       ; !IsNull (&HostBridge->RootBridges, Link)
>
> -       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
>
> -       )
>
> -  {
>
> -    RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
>
> +    //
>
> +    // Insert Root Bridge Handle Instance
>
> +    //
>
> +    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
>
>      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
>
> +  } else {
>
> +    RootBridge->RootBridgeIo.ParentHandle = 0;
>
> +  }
>
>
>
> -    Status = gBS->InstallMultipleProtocolInterfaces (
>
> -                    &RootBridge->Handle,
>
> -                    &gEfiDevicePathProtocolGuid,
>
> -                    RootBridge->DevicePath,
>
> -                    &gEfiPciRootBridgeIoProtocolGuid,
>
> -                    &RootBridge->RootBridgeIo,
>
> -                    NULL
>
> -                    );
>
> -    ASSERT_EFI_ERROR (Status);
>
> +  RootBridge->Handle = Controller;
>
> +  Status             = gBS->InstallMultipleProtocolInterfaces (
>
> +                              &RootBridge->Handle,
>
> +                              &gEfiPciRootBridgeIoProtocolGuid,
>
> +                              &RootBridge->RootBridgeIo,
>
> +                              NULL
>
> +                              );
>
> +
>
> +ErrorExit:
>
> +  if (EFI_ERROR (Status)) {
>
> +    if (MemorySetupDone) {
>
> +      PciRootBridgeMemoryFree (PciRootBridge);
>
> +    }
>
> +
>
> +    if (RootBridge != NULL) {
>
> +      if (!IsListEmpty (&RootBridge->Link)) {
>
> +        RemoveEntryList (&RootBridge->Link);
>
> +      }
>
> +
>
> +      FreeRootBridge (RootBridge);
>
> +    }
>
> +
>
> +    gBS->CloseProtocol (
>
> +           Controller,
>
> +           &gEdkiiPciHostBridgeProtocolGuid,
>
> +           This->DriverBindingHandle,
>
> +           Controller
>
> +           );
>
>    }
>
>
>
> -  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Stop this driver on ControllerHandle. Support stopping any child 
> + handles
>
> +  created by this driver.
>
> +
>
> +  @param  This              Protocol instance pointer.
>
> +  @param  Controller        Handle of device to stop driver on.
>
> +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. 
> + If
> number of
>
> +                            children is zero stop the entire bus driver.
>
> +  @param  ChildHandleBuffer List of Child Handles to Stop.
>
> +
>
> +  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
>
> +  @retval other             This driver was not removed from this device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PciHostBrigeDriverBindingStop (
>
> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
>
> +  IN  EFI_HANDLE                   Controller,
>
> +  IN  UINTN                        NumberOfChildren,
>
> +  IN  EFI_HANDLE                   *ChildHandleBuffer
>
> +  )
>
> +{
>
> +  EFI_STATUS                       Status;
>
> +  PCI_ROOT_BRIDGE                  *PciRootBridge;
>
> +  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;
>
> +  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;
>
> +
>
> +  Status = gBS->HandleProtocol (
>
> +                  Controller,
>
> +                  &gEfiPciRootBridgeIoProtocolGuid,
>
> +                  (VOID **)&RootBridgeIo
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (RootBridgeIo);
>
> +
>
> +  Status = gBS->HandleProtocol (
>
> +                  Controller,
>
> +                  &gEdkiiPciHostBridgeProtocolGuid,
>
> +                  (VOID **)&PciRootBridge
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
>
> +                  Controller,
>
> +                  &gEfiPciRootBridgeIoProtocolGuid,
>
> +                  (VOID **)&PciRootBridge
>
> +                  );
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (!IsListEmpty (&RootBridge->Link)) {
>
> +    RemoveEntryList (&RootBridge->Link);
>
> +  }
>
> +
>
> +  PciRootBridgeMemoryFree (PciRootBridge);
>
> +
>
> +  FreeRootBridge (RootBridge);
>
> +  gBS->CloseProtocol (
>
> +         Controller,
>
> +         &gEdkiiPciHostBridgeProtocolGuid,
>
> +         This->DriverBindingHandle,
>
> +         Controller
>
> +         );
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +//
>
> +// PCI Bus Driver Global Variables
>
> +//
>
> +EFI_DRIVER_BINDING_PROTOCOL  gPciHostBrigeDriverBinding = {
>
> +  PciHostBrigeDriverBindingSupported,
>
> +  PciHostBrigeDriverBindingStart,
>
> +  PciHostBrigeDriverBindingStop,
>
> +  0xa,
>
> +  NULL,
>
> +  NULL
>
> +};
>
> +
>
> +/**
>
> +
>
> +  Entry point of this driver.
>
> +
>
> +  @param ImageHandle  Image handle of this driver.
>
> +  @param SystemTable  Pointer to standard EFI system table.
>
> +
>
> +  @retval EFI_SUCCESS       Succeed.
>
> +  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InitializePciHostBridge (
>
> +  IN EFI_HANDLE        ImageHandle,
>
> +  IN EFI_SYSTEM_TABLE  *SystemTable
>
> +  )
>
> +{
>
> +  EFI_STATUS                Status;
>
> +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
>
> +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
>
> +  PCI_ROOT_BRIDGE           *RootBridges;
>
> +  UINTN                     RootBridgeCount;
>
> +  UINTN                     Index;
>
> +  BOOLEAN                   ResourceAssigned;
>
> +  LIST_ENTRY                *Link;
>
> +
>
> +  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID
> **)&mCpuIo);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
>
> +  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
>
> +    // Register for binding protocol if library enumeration is not 
> + used
>
> +    Status = EfiLibInstallDriverBinding (
>
> +               ImageHandle,
>
> +               SystemTable,
>
> +               &gPciHostBrigeDriverBinding,
>
> +               ImageHandle
>
> +               );
>
> +    ASSERT_EFI_ERROR (Status);
>
> +  } else {
>
> +    //
>
> +    // Most systems in the world including complex servers have only 
> + one Host
> Bridge.
>
> +    //
>
> +    HostBridge = AllocateZeroPool (sizeof 
> + (PCI_HOST_BRIDGE_INSTANCE));
>
> +    ASSERT (HostBridge != NULL);
>
> +
>
> +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
>
> +    HostBridge->CanRestarted = TRUE;
>
> +    InitializeListHead (&HostBridge->RootBridges);
>
> +    ResourceAssigned = FALSE;
>
> +
>
> +    //
>
> +    // Create Root Bridge Device Handle in this Host Bridge
>
> +    //
>
> +    for (Index = 0; Index < RootBridgeCount; Index++) {
>
> +      //
>
> +      // Create Root Bridge Handle Instance
>
> +      //
>
> +      RootBridge = CreateRootBridge (&RootBridges[Index]);
>
> +      ASSERT (RootBridge != NULL);
>
> +      if (RootBridge == NULL) {
>
> +        continue;
>
> +      }
>
> +
>
> +      //
>
> +      // Make sure all root bridges share the same ResourceAssigned value.
>
> +      //
>
> +      if (Index == 0) {
>
> +        ResourceAssigned = RootBridges[Index].ResourceAssigned;
>
> +      } else {
>
> +        ASSERT (ResourceAssigned == 
> + RootBridges[Index].ResourceAssigned);
>
> +      }
>
> +
>
> +      Status = PciRootBridgeMemorySetup (&RootBridges[Index]);
>
> +      if (EFI_ERROR (Status)) {
>
> +        continue;
>
> +      }
>
> +
>
> +      //
>
> +      // Insert Root Bridge Handle Instance
>
> +      //
>
> +      InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
>
> +    }
>
> +
>
> +    //
>
> +    // When resources were assigned, it's not needed to expose
>
> +    // PciHostBridgeResourceAllocation protocol.
>
> +    //
>
> +    if (!ResourceAssigned) {
>
> +      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
>
> +      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
>
> +      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
>
> +      HostBridge->ResAlloc.StartBusEnumeration  = 
> + StartBusEnumeration;
>
> +      HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
>
> +      HostBridge->ResAlloc.SubmitResources      = SubmitResources;
>
> +      HostBridge->ResAlloc.GetProposedResources = 
> + GetProposedResources;
>
> +      HostBridge->ResAlloc.PreprocessController = 
> + PreprocessController;
>
> +
>
> +      Status = gBS->InstallMultipleProtocolInterfaces (
>
> +                      &HostBridge->Handle,
>
> +                      
> + &gEfiPciHostBridgeResourceAllocationProtocolGuid,
>
> +                      &HostBridge->ResAlloc,
>
> +                      NULL
>
> +                      );
>
> +      ASSERT_EFI_ERROR (Status);
>
> +    }
>
> +
>
> +    for (Link = GetFirstNode (&HostBridge->RootBridges)
>
> +         ; !IsNull (&HostBridge->RootBridges, Link)
>
> +         ; Link = GetNextNode (&HostBridge->RootBridges, Link)
>
> +         )
>
> +    {
>
> +      RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
>
> +      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
>
> +
>
> +      Status = gBS->InstallMultipleProtocolInterfaces (
>
> +                      &RootBridge->Handle,
>
> +                      &gEfiDevicePathProtocolGuid,
>
> +                      RootBridge->DevicePath,
>
> +                      &gEfiPciRootBridgeIoProtocolGuid,
>
> +                      &RootBridge->RootBridgeIo,
>
> +                      NULL
>
> +                      );
>
> +      ASSERT_EFI_ERROR (Status);
>
> +    }
>
> +
>
> +    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
>
> +  }
>
>
>
>    if (!EFI_ERROR (Status)) {
>
>      mIoMmuEvent = EfiCreateProtocolNotifyEvent (
>
> diff --git 
> a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>
> index 9c24cacc30..ee4740b14f 100644
>
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>
> @@ -46,6 +46,7 @@
>
>    gEfiPciRootBridgeIoProtocolGuid                 ## BY_START
>
>    gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
>
>    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
>
> +  gEdkiiPciHostBridgeProtocolGuid                 ## SOMETIMES_CONSUMES
>
>
>
>  [Depex]
>
>    gEfiCpuIo2ProtocolGuid AND
>
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
>
> index 10a6200719..7923c4677b 100644
>
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
>
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
>
> @@ -93,6 +93,19 @@ CreateRootBridge (
>
>    IN PCI_ROOT_BRIDGE  *Bridge
>
>    );
>
>
>
> +/**
>
> +  Free the Pci Root Bridge instance.
>
> +
>
> +  @param Bridge            The root bridge instance.
>
> +
>
> +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
>
> +          or NULL if creation fails.
>
> +**/
>
> +VOID
>
> +FreeRootBridge (
>
> +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
>
> +  );
>
> +
>
>  //
>
>  // Protocol Member Function Prototypes
>
>  //
>
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
>
> index 157a0ada80..f0eb465a9d 100644
>
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
>
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
>
> @@ -286,6 +286,30 @@ CreateRootBridge (
>
>    return RootBridge;
>
>  }
>
>
>
> +/**
>
> +  Free the Pci Root Bridge instance.
>
> +
>
> +  @param Bridge            The root bridge instance.
>
> +
>
> +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
>
> +          or NULL if creation fails.
>
> +**/
>
> +VOID
>
> +FreeRootBridge (
>
> +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
>
> +  )
>
> +{
>
> +  if (Bridge->ConfigBuffer != NULL) {
>
> +    FreePool (Bridge->ConfigBuffer);
>
> +  }
>
> +
>
> +  if (Bridge->DevicePath != NULL) {
>
> +    FreePool (Bridge->DevicePath);
>
> +  }
>
> +
>
> +  FreePool (Bridge);
>
> +}
>
> +
>
>  /**
>
>    Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
>
>
>
> diff --git a/MdeModulePkg/MdeModulePkg.dec 
> b/MdeModulePkg/MdeModulePkg.dec
>
> index d65dae18aa..24700fa797 100644
>
> --- a/MdeModulePkg/MdeModulePkg.dec
>
> +++ b/MdeModulePkg/MdeModulePkg.dec
>
> @@ -692,6 +692,10 @@
>
>    ## Include/Protocol/VariablePolicy.h
>
>    gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 
> 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
>
>
>
> +  ## Include/Library/PciHostBridgeLib.h
>
> +  # Exposes a PCI_HOST_BRIDGE structure for driver binding usage
>
> +  gEdkiiPciHostBridgeProtocolGuid = { 0xaff2b72d, 0x202e, 0x40e3, { 
> + 0x82, 0xd5,
> 0x9f, 0x6f, 0x61, 0xaf, 0x2a, 0x0b } }
>
> +
>
>  [PcdsFeatureFlag]
>
>    ## Indicates if the platform can support update capsule across a 
> system reset.<BR><BR>
>
>    #   TRUE  - Supports update capsule across a system reset.<BR>
>
> --
>
> 2.25.1
>
>



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106555): https://edk2.groups.io/g/devel/message/106555
Mute This Topic: https://groups.io/mt/99859311/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
Posted by Ni, Ray 10 months ago

> -----Original Message-----
> From: Jeff Brasen <jbrasen@nvidia.com>
> Sent: Friday, June 30, 2023 11:21 AM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver
> binding
> 
> Not sure why the patch failed to apply I'll see if there is something wrong with my
> gitconfig tomorrow. The path you suggested below is exactly what our current
> implementation does. However, I am trying to make our pcie controller driver do
> async initialization so that using a depex is less ideal as we may have to postpone
> driver load to after end of dxe instead of just the connection. It seemed that a
> driver binding type approach was a good approach for this.

I am curious how the pcie root (root complex) initialization is done in async way?
Does it use a timer callback to poll the initialization status every certain interval?

On the other hand, even you make PciHostBridge as a UEFI driver-model driver, you still
require some code to initiate the "ConnectController()". How is that done?

Comparing the two paths (today's = my proposal, new way = your patch), both require
some code to explicitly call "ConnectController()".

> 
> On a less important implementation if the pieces that live under the library are
> driver binding we have to reject any stop requests as there is no driver linkage
> between the two layers.

In x86, root complex (pcie root) is almost the root of all peripherals. I cannot see a value to Stop () the pcie root.
If you check the PciBus implementation, it supports Stop() but the Stop() only succeeds when all upper layer drivers
succeed to Stop(). (usually it's not the case.)
And even PciBus.Stop() succeeds, the resource(MMIO/IO/BUS) allocation is not un-done. It's only the PciIo
handles that are destroyed in software level.

Thanks,
Ray


> 
> -Jeff
> 
> 
> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Thursday, June 29, 2023 8:29 PM
> To: Jeff Brasen <jbrasen@nvidia.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver
> binding
> 
> External email: Use caution opening links or attachments
> 
> 
> I failed to apply the patch in my local tree.
> 
> It seems you invented a new EdkiiRootBridgeIo protocol and a certain proprietary
> driver would produce this protocol instance.
> Then the open source PciHostBridge driver starts on that.
> 
> Then, why not implement your own PciHostBridgeLib and let it depends on some
> "AllRootBridgeIoInformationIsReady" protocol.
> So that the PciHostBridge driver could still call PciHostBridgeLib and all your
> implementation in this patch can be in that lib.
> 
> Thanks,
> Ray
> 
> > -----Original Message-----
> > From: Jeff Brasen <jbrasen@nvidia.com>
> > Sent: Friday, June 30, 2023 4:54 AM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray
> > <ray.ni@intel.com>; Jeff Brasen <jbrasen@nvidia.com>
> > Subject: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver
> > binding
> >
> > If the platform does not support any PCIe devices using the library
> >
> > method allow devices to connect to host bridge via driver binding.
> >
> >
> >
> > Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
> >
> > ---
> >
> >  .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 649
> > ++++++++++++++----
> >
> >  .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   1 +
> >
> >  .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h  |  13 +
> >
> >  .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    |  24 +
> >
> >  MdeModulePkg/MdeModulePkg.dec                 |   4 +
> >
> >  5 files changed, 562 insertions(+), 129 deletions(-)
> >
> >
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> >
> > index d573e532ba..506c6660ae 100644
> >
> > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> >
> > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> >
> > @@ -422,167 +422,320 @@ IoMmuProtocolCallback (
> >
> >  }
> >
> >
> >
> >  /**
> >
> > +  PCI Root Bridge Memory setup.
> >
> >
> >
> > -  Entry point of this driver.
> >
> > +  @param  RootBridge            Root Bridge instance.
> >
> >
> >
> > -  @param ImageHandle  Image handle of this driver.
> >
> > -  @param SystemTable  Pointer to standard EFI system table.
> >
> > -
> >
> > -  @retval EFI_SUCCESS       Succeed.
> >
> > -  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
> >
> > +  @retval EFI_SUCCESS           Memory was setup correctly
> >
> > +  @retval others                Error in setup
> >
> >
> >
> >  **/
> >
> >  EFI_STATUS
> >
> >  EFIAPI
> >
> > -InitializePciHostBridge (
> >
> > -  IN EFI_HANDLE        ImageHandle,
> >
> > -  IN EFI_SYSTEM_TABLE  *SystemTable
> >
> > +PciRootBridgeMemorySetup (
> >
> > +  IN PCI_ROOT_BRIDGE  *RootBridge
> >
> >    )
> >
> >  {
> >
> >    EFI_STATUS                Status;
> >
> > -  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> >
> > -  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> >
> > -  PCI_ROOT_BRIDGE           *RootBridges;
> >
> > -  UINTN                     RootBridgeCount;
> >
> > -  UINTN                     Index;
> >
> > +  UINT64                    HostAddress;
> >
> >    PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> >
> >    UINTN                     MemApertureIndex;
> >
> > -  BOOLEAN                   ResourceAssigned;
> >
> > -  LIST_ENTRY                *Link;
> >
> > -  UINT64                    HostAddress;
> >
> >
> >
> > -  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> >
> > -  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> >
> > -    return EFI_UNSUPPORTED;
> >
> > -  }
> >
> > -
> >
> > -  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID
> > **)&mCpuIo);
> >
> > -  ASSERT_EFI_ERROR (Status);
> >
> > -
> >
> > -  //
> >
> > -  // Most systems in the world including complex servers have only
> > one Host Bridge.
> >
> > -  //
> >
> > -  HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
> >
> > -  ASSERT (HostBridge != NULL);
> >
> > -
> >
> > -  HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> >
> > -  HostBridge->CanRestarted = TRUE;
> >
> > -  InitializeListHead (&HostBridge->RootBridges);
> >
> > -  ResourceAssigned = FALSE;
> >
> > -
> >
> > -  //
> >
> > -  // Create Root Bridge Device Handle in this Host Bridge
> >
> > -  //
> >
> > -  for (Index = 0; Index < RootBridgeCount; Index++) {
> >
> > +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> >
> >      //
> >
> > -    // Create Root Bridge Handle Instance
> >
> > +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >
> > +    // For GCD resource manipulation, we need to use host address.
> >
> >      //
> >
> > -    RootBridge = CreateRootBridge (&RootBridges[Index]);
> >
> > -    ASSERT (RootBridge != NULL);
> >
> > -    if (RootBridge == NULL) {
> >
> > -      continue;
> >
> > +    HostAddress = TO_HOST_ADDRESS (
> >
> > +                    RootBridge->Io.Base,
> >
> > +                    RootBridge->Io.Translation
> >
> > +                    );
> >
> > +
> >
> > +    Status = AddIoSpace (
> >
> > +               HostAddress,
> >
> > +               RootBridge->Io.Limit - RootBridge->Io.Base + 1
> >
> > +               );
> >
> > +    ASSERT_EFI_ERROR (Status);
> >
> > +    if (EFI_ERROR (Status)) {
> >
> > +      return Status;
> >
> >      }
> >
> >
> >
> > -    //
> >
> > -    // Make sure all root bridges share the same ResourceAssigned value.
> >
> > -    //
> >
> > -    if (Index == 0) {
> >
> > -      ResourceAssigned = RootBridges[Index].ResourceAssigned;
> >
> > -    } else {
> >
> > -      ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
> >
> > +    if (RootBridge->ResourceAssigned) {
> >
> > +      Status = gDS->AllocateIoSpace (
> >
> > +                      EfiGcdAllocateAddress,
> >
> > +                      EfiGcdIoTypeIo,
> >
> > +                      0,
> >
> > +                      RootBridge->Io.Limit - RootBridge->Io.Base + 1,
> >
> > +                      &HostAddress,
> >
> > +                      gImageHandle,
> >
> > +                      NULL
> >
> > +                      );
> >
> > +      ASSERT_EFI_ERROR (Status);
> >
> > +      if (EFI_ERROR (Status)) {
> >
> > +        return Status;
> >
> > +      }
> >
> >      }
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Add all the Mem/PMem aperture to GCD
> >
> > +  // Mem/PMem shouldn't overlap with each other
> >
> > +  // Root bridge which needs to combine MEM and PMEM should only
> > + report
> >
> > +  // the MEM aperture in Mem
> >
> > +  //
> >
> > +  MemApertures[0] = &RootBridge->Mem;
> >
> > +  MemApertures[1] = &RootBridge->MemAbove4G;
> >
> > +  MemApertures[2] = &RootBridge->PMem;
> >
> > +  MemApertures[3] = &RootBridge->PMemAbove4G;
> >
> >
> >
> > -    if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
> >
> > +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > (MemApertures); MemApertureIndex++) {
> >
> > +    if (MemApertures[MemApertureIndex]->Base <=
> > MemApertures[MemApertureIndex]->Limit) {
> >
> >        //
> >
> >        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >
> >        // For GCD resource manipulation, we need to use host address.
> >
> >        //
> >
> >        HostAddress = TO_HOST_ADDRESS (
> >
> > -                      RootBridges[Index].Io.Base,
> >
> > -                      RootBridges[Index].Io.Translation
> >
> > +                      MemApertures[MemApertureIndex]->Base,
> >
> > +                      MemApertures[MemApertureIndex]->Translation
> >
> >                        );
> >
> > -
> >
> > -      Status = AddIoSpace (
> >
> > +      Status = AddMemoryMappedIoSpace (
> >
> >                   HostAddress,
> >
> > -                 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
> >
> > +                 MemApertures[MemApertureIndex]->Limit -
> > MemApertures[MemApertureIndex]->Base + 1,
> >
> > +                 EFI_MEMORY_UC
> >
> >                   );
> >
> >        ASSERT_EFI_ERROR (Status);
> >
> > -      if (ResourceAssigned) {
> >
> > -        Status = gDS->AllocateIoSpace (
> >
> > +      if (EFI_ERROR (Status)) {
> >
> > +        return Status;
> >
> > +      }
> >
> > +
> >
> > +      Status = gDS->SetMemorySpaceAttributes (
> >
> > +                      HostAddress,
> >
> > +                      MemApertures[MemApertureIndex]->Limit -
> > MemApertures[MemApertureIndex]->Base + 1,
> >
> > +                      EFI_MEMORY_UC
> >
> > +                      );
> >
> > +      if (EFI_ERROR (Status)) {
> >
> > +        DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> > EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> >
> > +      }
> >
> > +
> >
> > +      if (RootBridge->ResourceAssigned) {
> >
> > +        Status = gDS->AllocateMemorySpace (
> >
> >                          EfiGcdAllocateAddress,
> >
> > -                        EfiGcdIoTypeIo,
> >
> > +                        EfiGcdMemoryTypeMemoryMappedIo,
> >
> >                          0,
> >
> > -                        RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
> >
> > +                        MemApertures[MemApertureIndex]->Limit -
> > MemApertures[MemApertureIndex]->Base + 1,
> >
> >                          &HostAddress,
> >
> >                          gImageHandle,
> >
> >                          NULL
> >
> >                          );
> >
> >          ASSERT_EFI_ERROR (Status);
> >
> > +        if (EFI_ERROR (Status)) {
> >
> > +          return Status;
> >
> > +        }
> >
> >        }
> >
> >      }
> >
> > +  }
> >
> > +
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> >
> >
> > +/**
> >
> > +  PCI Root Bridge Memory free.
> >
> > +
> >
> > +  @param  RootBridge            Root Bridge instance.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           Memory was setup correctly
> >
> > +  @retval others                Error in setup
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EFIAPI
> >
> > +PciRootBridgeMemoryFree (
> >
> > +  IN PCI_ROOT_BRIDGE  *RootBridge
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                Status;
> >
> > +  UINT64                    HostAddress;
> >
> > +  PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> >
> > +  UINTN                     MemApertureIndex;
> >
> > +
> >
> > +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> >
> >      //
> >
> > -    // Add all the Mem/PMem aperture to GCD
> >
> > -    // Mem/PMem shouldn't overlap with each other
> >
> > -    // Root bridge which needs to combine MEM and PMEM should only report
> >
> > -    // the MEM aperture in Mem
> >
> > +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >
> > +    // For GCD resource manipulation, we need to use host address.
> >
> >      //
> >
> > -    MemApertures[0] = &RootBridges[Index].Mem;
> >
> > -    MemApertures[1] = &RootBridges[Index].MemAbove4G;
> >
> > -    MemApertures[2] = &RootBridges[Index].PMem;
> >
> > -    MemApertures[3] = &RootBridges[Index].PMemAbove4G;
> >
> > -
> >
> > -    for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > (MemApertures); MemApertureIndex++) {
> >
> > -      if (MemApertures[MemApertureIndex]->Base <=
> > MemApertures[MemApertureIndex]->Limit) {
> >
> > -        //
> >
> > -        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >
> > -        // For GCD resource manipulation, we need to use host address.
> >
> > -        //
> >
> > -        HostAddress = TO_HOST_ADDRESS (
> >
> > -                        MemApertures[MemApertureIndex]->Base,
> >
> > -                        MemApertures[MemApertureIndex]->Translation
> >
> > -                        );
> >
> > -        Status = AddMemoryMappedIoSpace (
> >
> > -                   HostAddress,
> >
> > -                   MemApertures[MemApertureIndex]->Limit -
> > MemApertures[MemApertureIndex]->Base + 1,
> >
> > -                   EFI_MEMORY_UC
> >
> > -                   );
> >
> > +    HostAddress = TO_HOST_ADDRESS (
> >
> > +                    RootBridge->Io.Base,
> >
> > +                    RootBridge->Io.Translation
> >
> > +                    );
> >
> > +
> >
> > +    if (RootBridge->ResourceAssigned) {
> >
> > +      Status = gDS->FreeIoSpace (HostAddress, RootBridge->Io.Limit -
> > + RootBridge-
> > >Io.Base + 1);
> >
> > +      ASSERT_EFI_ERROR (Status);
> >
> > +      if (EFI_ERROR (Status)) {
> >
> > +        return Status;
> >
> > +      }
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Add all the Mem/PMem aperture to GCD
> >
> > +  // Mem/PMem shouldn't overlap with each other
> >
> > +  // Root bridge which needs to combine MEM and PMEM should only
> > + report
> >
> > +  // the MEM aperture in Mem
> >
> > +  //
> >
> > +  MemApertures[0] = &RootBridge->Mem;
> >
> > +  MemApertures[1] = &RootBridge->MemAbove4G;
> >
> > +  MemApertures[2] = &RootBridge->PMem;
> >
> > +  MemApertures[3] = &RootBridge->PMemAbove4G;
> >
> > +
> >
> > +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > (MemApertures); MemApertureIndex++) {
> >
> > +    if (MemApertures[MemApertureIndex]->Base <=
> > MemApertures[MemApertureIndex]->Limit) {
> >
> > +      //
> >
> > +      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >
> > +      // For GCD resource manipulation, we need to use host address.
> >
> > +      //
> >
> > +      HostAddress = TO_HOST_ADDRESS (
> >
> > +                      MemApertures[MemApertureIndex]->Base,
> >
> > +                      MemApertures[MemApertureIndex]->Translation
> >
> > +                      );
> >
> > +      if (RootBridge->ResourceAssigned) {
> >
> > +        Status = gDS->FreeMemorySpace (HostAddress,
> > + RootBridge->Io.Limit -
> > RootBridge->Io.Base + 1);
> >
> >          ASSERT_EFI_ERROR (Status);
> >
> > -        Status = gDS->SetMemorySpaceAttributes (
> >
> > -                        HostAddress,
> >
> > -                        MemApertures[MemApertureIndex]->Limit -
> > MemApertures[MemApertureIndex]->Base + 1,
> >
> > -                        EFI_MEMORY_UC
> >
> > -                        );
> >
> >          if (EFI_ERROR (Status)) {
> >
> > -          DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> > EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> >
> > -        }
> >
> > -
> >
> > -        if (ResourceAssigned) {
> >
> > -          Status = gDS->AllocateMemorySpace (
> >
> > -                          EfiGcdAllocateAddress,
> >
> > -                          EfiGcdMemoryTypeMemoryMappedIo,
> >
> > -                          0,
> >
> > -                          MemApertures[MemApertureIndex]->Limit -
> > MemApertures[MemApertureIndex]->Base + 1,
> >
> > -                          &HostAddress,
> >
> > -                          gImageHandle,
> >
> > -                          NULL
> >
> > -                          );
> >
> > -          ASSERT_EFI_ERROR (Status);
> >
> > +          return Status;
> >
> >          }
> >
> >        }
> >
> >      }
> >
> > +  }
> >
> >
> >
> > -    //
> >
> > -    // Insert Root Bridge Handle Instance
> >
> > -    //
> >
> > -    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Test to see if this driver supports ControllerHandle. Any
> > + ControllerHandle
> >
> > +  than contains a gEdkiiPciHostBridgeProtocolGuid protocol can be supported.
> >
> > +
> >
> > +  @param  This                Protocol instance pointer.
> >
> > +  @param  Controller          Handle of device to test.
> >
> > +  @param  RemainingDevicePath Optional parameter use to pick a
> > + specific child
> >
> > +                              device to start.
> >
> > +
> >
> > +  @retval EFI_SUCCESS         This driver supports this device.
> >
> > +  @retval EFI_ALREADY_STARTED This driver is already running on this device.
> >
> > +  @retval other               This driver does not support this device.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EFIAPI
> >
> > +PciHostBrigeDriverBindingSupported (
> >
> > +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> >
> > +  IN EFI_HANDLE                   Controller,
> >
> > +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS       Status;
> >
> > +  PCI_ROOT_BRIDGE  *PciRootBridge;
> >
> > +
> >
> > +  //
> >
> > +  // Check if Pci Host Bridge protocol is installed by platform
> >
> > +  //
> >
> > +  Status = gBS->OpenProtocol (
> >
> > +                  Controller,
> >
> > +                  &gEdkiiPciHostBridgeProtocolGuid,
> >
> > +                  (VOID **)&PciRootBridge,
> >
> > +                  This->DriverBindingHandle,
> >
> > +                  Controller,
> >
> > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> >
> > +                  );
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    return Status;
> >
> >    }
> >
> >
> >
> >    //
> >
> > -  // When resources were assigned, it's not needed to expose
> >
> > -  // PciHostBridgeResourceAllocation protocol.
> >
> > +  // Close the protocol used to perform the supported test
> >
> > +  //
> >
> > +  gBS->CloseProtocol (
> >
> > +         Controller,
> >
> > +         &gEdkiiPciHostBridgeProtocolGuid,
> >
> > +         This->DriverBindingHandle,
> >
> > +         Controller
> >
> > +         );
> >
> > +
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Start this driver on ControllerHandle and enumerate Pci bus and
> > + start
> >
> > +  all device under PCI bus.
> >
> > +
> >
> > +  @param  This                 Protocol instance pointer.
> >
> > +  @param  Controller           Handle of device to bind driver to.
> >
> > +  @param  RemainingDevicePath  Optional parameter use to pick a
> > + specific child
> >
> > +                               device to start.
> >
> > +
> >
> > +  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
> >
> > +  @retval EFI_ALREADY_STARTED  This driver is already running on
> > ControllerHandle.
> >
> > +  @retval other                This driver does not support this device.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EFIAPI
> >
> > +PciHostBrigeDriverBindingStart (
> >
> > +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> >
> > +  IN EFI_HANDLE                   Controller,
> >
> > +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                Status;
> >
> > +  PCI_ROOT_BRIDGE           *PciRootBridge;
> >
> > +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> >
> > +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> >
> > +  BOOLEAN                   MemorySetupDone;
> >
> > +
> >
> > +  MemorySetupDone = FALSE;
> >
> > +  //
> >
> > +  // Check if Pci Host Bridge protocol is installed by platform
> >
> >    //
> >
> > -  if (!ResourceAssigned) {
> >
> > +  Status = gBS->OpenProtocol (
> >
> > +                  Controller,
> >
> > +                  &gEdkiiPciHostBridgeProtocolGuid,
> >
> > +                  (VOID **)&PciRootBridge,
> >
> > +                  This->DriverBindingHandle,
> >
> > +                  Controller,
> >
> > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> >
> > +                  );
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    return Status;
> >
> > +  }
> >
> > +
> >
> > +  RootBridge = CreateRootBridge (PciRootBridge);
> >
> > +  ASSERT (RootBridge != NULL);
> >
> > +  if (RootBridge == NULL) {
> >
> > +    Status = EFI_DEVICE_ERROR;
> >
> > +    goto ErrorExit;
> >
> > +  }
> >
> > +
> >
> > +  Status = PciRootBridgeMemorySetup (PciRootBridge);
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    goto ErrorExit;
> >
> > +  }
> >
> > +
> >
> > +  MemorySetupDone = TRUE;
> >
> > +
> >
> > +  if (!PciRootBridge->ResourceAssigned) {
> >
> > +    // Create host bridge
> >
> > +    HostBridge = AllocateZeroPool (sizeof
> > + (PCI_HOST_BRIDGE_INSTANCE));
> >
> > +    ASSERT (HostBridge != NULL);
> >
> > +    if (HostBridge == NULL) {
> >
> > +      Status = EFI_OUT_OF_RESOURCES;
> >
> > +      goto ErrorExit;
> >
> > +    }
> >
> > +
> >
> > +    HostBridge->Handle       = 0;
> >
> > +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> >
> > +    HostBridge->CanRestarted = TRUE;
> >
> > +    InitializeListHead (&HostBridge->RootBridges);
> >
> > +
> >
> >      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> >
> >      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> >
> >      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> >
> > @@ -599,28 +752,266 @@ InitializePciHostBridge (
> >
> >                      NULL
> >
> >                      );
> >
> >      ASSERT_EFI_ERROR (Status);
> >
> > -  }
> >
> > +    if (EFI_ERROR (Status)) {
> >
> > +      goto ErrorExit;
> >
> > +    }
> >
> >
> >
> > -  for (Link = GetFirstNode (&HostBridge->RootBridges)
> >
> > -       ; !IsNull (&HostBridge->RootBridges, Link)
> >
> > -       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> >
> > -       )
> >
> > -  {
> >
> > -    RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> >
> > +    //
> >
> > +    // Insert Root Bridge Handle Instance
> >
> > +    //
> >
> > +    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> >
> >      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> >
> > +  } else {
> >
> > +    RootBridge->RootBridgeIo.ParentHandle = 0;
> >
> > +  }
> >
> >
> >
> > -    Status = gBS->InstallMultipleProtocolInterfaces (
> >
> > -                    &RootBridge->Handle,
> >
> > -                    &gEfiDevicePathProtocolGuid,
> >
> > -                    RootBridge->DevicePath,
> >
> > -                    &gEfiPciRootBridgeIoProtocolGuid,
> >
> > -                    &RootBridge->RootBridgeIo,
> >
> > -                    NULL
> >
> > -                    );
> >
> > -    ASSERT_EFI_ERROR (Status);
> >
> > +  RootBridge->Handle = Controller;
> >
> > +  Status             = gBS->InstallMultipleProtocolInterfaces (
> >
> > +                              &RootBridge->Handle,
> >
> > +                              &gEfiPciRootBridgeIoProtocolGuid,
> >
> > +                              &RootBridge->RootBridgeIo,
> >
> > +                              NULL
> >
> > +                              );
> >
> > +
> >
> > +ErrorExit:
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    if (MemorySetupDone) {
> >
> > +      PciRootBridgeMemoryFree (PciRootBridge);
> >
> > +    }
> >
> > +
> >
> > +    if (RootBridge != NULL) {
> >
> > +      if (!IsListEmpty (&RootBridge->Link)) {
> >
> > +        RemoveEntryList (&RootBridge->Link);
> >
> > +      }
> >
> > +
> >
> > +      FreeRootBridge (RootBridge);
> >
> > +    }
> >
> > +
> >
> > +    gBS->CloseProtocol (
> >
> > +           Controller,
> >
> > +           &gEdkiiPciHostBridgeProtocolGuid,
> >
> > +           This->DriverBindingHandle,
> >
> > +           Controller
> >
> > +           );
> >
> >    }
> >
> >
> >
> > -  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Stop this driver on ControllerHandle. Support stopping any child
> > + handles
> >
> > +  created by this driver.
> >
> > +
> >
> > +  @param  This              Protocol instance pointer.
> >
> > +  @param  Controller        Handle of device to stop driver on.
> >
> > +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer.
> > + If
> > number of
> >
> > +                            children is zero stop the entire bus driver.
> >
> > +  @param  ChildHandleBuffer List of Child Handles to Stop.
> >
> > +
> >
> > +  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
> >
> > +  @retval other             This driver was not removed from this device.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EFIAPI
> >
> > +PciHostBrigeDriverBindingStop (
> >
> > +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
> >
> > +  IN  EFI_HANDLE                   Controller,
> >
> > +  IN  UINTN                        NumberOfChildren,
> >
> > +  IN  EFI_HANDLE                   *ChildHandleBuffer
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                       Status;
> >
> > +  PCI_ROOT_BRIDGE                  *PciRootBridge;
> >
> > +  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;
> >
> > +  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;
> >
> > +
> >
> > +  Status = gBS->HandleProtocol (
> >
> > +                  Controller,
> >
> > +                  &gEfiPciRootBridgeIoProtocolGuid,
> >
> > +                  (VOID **)&RootBridgeIo
> >
> > +                  );
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    return Status;
> >
> > +  }
> >
> > +
> >
> > +  RootBridge = ROOT_BRIDGE_FROM_THIS (RootBridgeIo);
> >
> > +
> >
> > +  Status = gBS->HandleProtocol (
> >
> > +                  Controller,
> >
> > +                  &gEdkiiPciHostBridgeProtocolGuid,
> >
> > +                  (VOID **)&PciRootBridge
> >
> > +                  );
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    return Status;
> >
> > +  }
> >
> > +
> >
> > +  Status = gBS->UninstallMultipleProtocolInterfaces (
> >
> > +                  Controller,
> >
> > +                  &gEfiPciRootBridgeIoProtocolGuid,
> >
> > +                  (VOID **)&PciRootBridge
> >
> > +                  );
> >
> > +  if (EFI_ERROR (Status)) {
> >
> > +    return Status;
> >
> > +  }
> >
> > +
> >
> > +  if (!IsListEmpty (&RootBridge->Link)) {
> >
> > +    RemoveEntryList (&RootBridge->Link);
> >
> > +  }
> >
> > +
> >
> > +  PciRootBridgeMemoryFree (PciRootBridge);
> >
> > +
> >
> > +  FreeRootBridge (RootBridge);
> >
> > +  gBS->CloseProtocol (
> >
> > +         Controller,
> >
> > +         &gEdkiiPciHostBridgeProtocolGuid,
> >
> > +         This->DriverBindingHandle,
> >
> > +         Controller
> >
> > +         );
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +//
> >
> > +// PCI Bus Driver Global Variables
> >
> > +//
> >
> > +EFI_DRIVER_BINDING_PROTOCOL  gPciHostBrigeDriverBinding = {
> >
> > +  PciHostBrigeDriverBindingSupported,
> >
> > +  PciHostBrigeDriverBindingStart,
> >
> > +  PciHostBrigeDriverBindingStop,
> >
> > +  0xa,
> >
> > +  NULL,
> >
> > +  NULL
> >
> > +};
> >
> > +
> >
> > +/**
> >
> > +
> >
> > +  Entry point of this driver.
> >
> > +
> >
> > +  @param ImageHandle  Image handle of this driver.
> >
> > +  @param SystemTable  Pointer to standard EFI system table.
> >
> > +
> >
> > +  @retval EFI_SUCCESS       Succeed.
> >
> > +  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EFIAPI
> >
> > +InitializePciHostBridge (
> >
> > +  IN EFI_HANDLE        ImageHandle,
> >
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                Status;
> >
> > +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> >
> > +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> >
> > +  PCI_ROOT_BRIDGE           *RootBridges;
> >
> > +  UINTN                     RootBridgeCount;
> >
> > +  UINTN                     Index;
> >
> > +  BOOLEAN                   ResourceAssigned;
> >
> > +  LIST_ENTRY                *Link;
> >
> > +
> >
> > +  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID
> > **)&mCpuIo);
> >
> > +  ASSERT_EFI_ERROR (Status);
> >
> > +
> >
> > +  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> >
> > +  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> >
> > +    // Register for binding protocol if library enumeration is not
> > + used
> >
> > +    Status = EfiLibInstallDriverBinding (
> >
> > +               ImageHandle,
> >
> > +               SystemTable,
> >
> > +               &gPciHostBrigeDriverBinding,
> >
> > +               ImageHandle
> >
> > +               );
> >
> > +    ASSERT_EFI_ERROR (Status);
> >
> > +  } else {
> >
> > +    //
> >
> > +    // Most systems in the world including complex servers have only
> > + one Host
> > Bridge.
> >
> > +    //
> >
> > +    HostBridge = AllocateZeroPool (sizeof
> > + (PCI_HOST_BRIDGE_INSTANCE));
> >
> > +    ASSERT (HostBridge != NULL);
> >
> > +
> >
> > +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> >
> > +    HostBridge->CanRestarted = TRUE;
> >
> > +    InitializeListHead (&HostBridge->RootBridges);
> >
> > +    ResourceAssigned = FALSE;
> >
> > +
> >
> > +    //
> >
> > +    // Create Root Bridge Device Handle in this Host Bridge
> >
> > +    //
> >
> > +    for (Index = 0; Index < RootBridgeCount; Index++) {
> >
> > +      //
> >
> > +      // Create Root Bridge Handle Instance
> >
> > +      //
> >
> > +      RootBridge = CreateRootBridge (&RootBridges[Index]);
> >
> > +      ASSERT (RootBridge != NULL);
> >
> > +      if (RootBridge == NULL) {
> >
> > +        continue;
> >
> > +      }
> >
> > +
> >
> > +      //
> >
> > +      // Make sure all root bridges share the same ResourceAssigned value.
> >
> > +      //
> >
> > +      if (Index == 0) {
> >
> > +        ResourceAssigned = RootBridges[Index].ResourceAssigned;
> >
> > +      } else {
> >
> > +        ASSERT (ResourceAssigned ==
> > + RootBridges[Index].ResourceAssigned);
> >
> > +      }
> >
> > +
> >
> > +      Status = PciRootBridgeMemorySetup (&RootBridges[Index]);
> >
> > +      if (EFI_ERROR (Status)) {
> >
> > +        continue;
> >
> > +      }
> >
> > +
> >
> > +      //
> >
> > +      // Insert Root Bridge Handle Instance
> >
> > +      //
> >
> > +      InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> >
> > +    }
> >
> > +
> >
> > +    //
> >
> > +    // When resources were assigned, it's not needed to expose
> >
> > +    // PciHostBridgeResourceAllocation protocol.
> >
> > +    //
> >
> > +    if (!ResourceAssigned) {
> >
> > +      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> >
> > +      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> >
> > +      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> >
> > +      HostBridge->ResAlloc.StartBusEnumeration  =
> > + StartBusEnumeration;
> >
> > +      HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
> >
> > +      HostBridge->ResAlloc.SubmitResources      = SubmitResources;
> >
> > +      HostBridge->ResAlloc.GetProposedResources =
> > + GetProposedResources;
> >
> > +      HostBridge->ResAlloc.PreprocessController =
> > + PreprocessController;
> >
> > +
> >
> > +      Status = gBS->InstallMultipleProtocolInterfaces (
> >
> > +                      &HostBridge->Handle,
> >
> > +
> > + &gEfiPciHostBridgeResourceAllocationProtocolGuid,
> >
> > +                      &HostBridge->ResAlloc,
> >
> > +                      NULL
> >
> > +                      );
> >
> > +      ASSERT_EFI_ERROR (Status);
> >
> > +    }
> >
> > +
> >
> > +    for (Link = GetFirstNode (&HostBridge->RootBridges)
> >
> > +         ; !IsNull (&HostBridge->RootBridges, Link)
> >
> > +         ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> >
> > +         )
> >
> > +    {
> >
> > +      RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> >
> > +      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> >
> > +
> >
> > +      Status = gBS->InstallMultipleProtocolInterfaces (
> >
> > +                      &RootBridge->Handle,
> >
> > +                      &gEfiDevicePathProtocolGuid,
> >
> > +                      RootBridge->DevicePath,
> >
> > +                      &gEfiPciRootBridgeIoProtocolGuid,
> >
> > +                      &RootBridge->RootBridgeIo,
> >
> > +                      NULL
> >
> > +                      );
> >
> > +      ASSERT_EFI_ERROR (Status);
> >
> > +    }
> >
> > +
> >
> > +    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> >
> > +  }
> >
> >
> >
> >    if (!EFI_ERROR (Status)) {
> >
> >      mIoMmuEvent = EfiCreateProtocolNotifyEvent (
> >
> > diff --git
> > a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> >
> > index 9c24cacc30..ee4740b14f 100644
> >
> > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> >
> > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> >
> > @@ -46,6 +46,7 @@
> >
> >    gEfiPciRootBridgeIoProtocolGuid                 ## BY_START
> >
> >    gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
> >
> >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> >
> > +  gEdkiiPciHostBridgeProtocolGuid                 ## SOMETIMES_CONSUMES
> >
> >
> >
> >  [Depex]
> >
> >    gEfiCpuIo2ProtocolGuid AND
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> >
> > index 10a6200719..7923c4677b 100644
> >
> > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> >
> > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> >
> > @@ -93,6 +93,19 @@ CreateRootBridge (
> >
> >    IN PCI_ROOT_BRIDGE  *Bridge
> >
> >    );
> >
> >
> >
> > +/**
> >
> > +  Free the Pci Root Bridge instance.
> >
> > +
> >
> > +  @param Bridge            The root bridge instance.
> >
> > +
> >
> > +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> >
> > +          or NULL if creation fails.
> >
> > +**/
> >
> > +VOID
> >
> > +FreeRootBridge (
> >
> > +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> >
> > +  );
> >
> > +
> >
> >  //
> >
> >  // Protocol Member Function Prototypes
> >
> >  //
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> >
> > index 157a0ada80..f0eb465a9d 100644
> >
> > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> >
> > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> >
> > @@ -286,6 +286,30 @@ CreateRootBridge (
> >
> >    return RootBridge;
> >
> >  }
> >
> >
> >
> > +/**
> >
> > +  Free the Pci Root Bridge instance.
> >
> > +
> >
> > +  @param Bridge            The root bridge instance.
> >
> > +
> >
> > +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> >
> > +          or NULL if creation fails.
> >
> > +**/
> >
> > +VOID
> >
> > +FreeRootBridge (
> >
> > +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> >
> > +  )
> >
> > +{
> >
> > +  if (Bridge->ConfigBuffer != NULL) {
> >
> > +    FreePool (Bridge->ConfigBuffer);
> >
> > +  }
> >
> > +
> >
> > +  if (Bridge->DevicePath != NULL) {
> >
> > +    FreePool (Bridge->DevicePath);
> >
> > +  }
> >
> > +
> >
> > +  FreePool (Bridge);
> >
> > +}
> >
> > +
> >
> >  /**
> >
> >    Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
> >
> >
> >
> > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > b/MdeModulePkg/MdeModulePkg.dec
> >
> > index d65dae18aa..24700fa797 100644
> >
> > --- a/MdeModulePkg/MdeModulePkg.dec
> >
> > +++ b/MdeModulePkg/MdeModulePkg.dec
> >
> > @@ -692,6 +692,10 @@
> >
> >    ## Include/Protocol/VariablePolicy.h
> >
> >    gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, {
> > 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
> >
> >
> >
> > +  ## Include/Library/PciHostBridgeLib.h
> >
> > +  # Exposes a PCI_HOST_BRIDGE structure for driver binding usage
> >
> > +  gEdkiiPciHostBridgeProtocolGuid = { 0xaff2b72d, 0x202e, 0x40e3, {
> > + 0x82, 0xd5,
> > 0x9f, 0x6f, 0x61, 0xaf, 0x2a, 0x0b } }
> >
> > +
> >
> >  [PcdsFeatureFlag]
> >
> >    ## Indicates if the platform can support update capsule across a
> > system reset.<BR><BR>
> >
> >    #   TRUE  - Supports update capsule across a system reset.<BR>
> >
> > --
> >
> > 2.25.1
> >
> >



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106558): https://edk2.groups.io/g/devel/message/106558
Mute This Topic: https://groups.io/mt/99859311/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
Posted by Jeff Brasen via groups.io 10 months ago

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Thursday, June 29, 2023 9:59 PM
> To: Jeff Brasen <jbrasen@nvidia.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver
> binding
> 
> External email: Use caution opening links or attachments
> 
> 
> > -----Original Message-----
> > From: Jeff Brasen <jbrasen@nvidia.com>
> > Sent: Friday, June 30, 2023 11:21 AM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for
> > driver binding
> >
> > Not sure why the patch failed to apply I'll see if there is something
> > wrong with my gitconfig tomorrow. The path you suggested below is
> > exactly what our current implementation does. However, I am trying to
> > make our pcie controller driver do async initialization so that using
> > a depex is less ideal as we may have to postpone driver load to after
> > end of dxe instead of just the connection. It seemed that a driver binding
> type approach was a good approach for this.
> 
> I am curious how the pcie root (root complex) initialization is done in async
> way?
> Does it use a timer callback to poll the initialization status every certain
> interval?
> 

[JB] That is correct, we use a timer when we expect sleeps or polling loops.

> On the other hand, even you make PciHostBridge as a UEFI driver-model
> driver, you still require some code to initiate the "ConnectController()". How is
> that done?
> 
> Comparing the two paths (today's = my proposal, new way = your patch),
> both require some code to explicitly call "ConnectController()".
> 

[JB] We have a sync point in BDS prior to the ConnectController call that is made. I could put that and a dispatch call prior to EndOfDxe signal but was hoping to not trigger any of the driver seen but not loaded debug messages from the main dispatch loop if possible as that can be a useful message to trigger something might be wrong. 

> >
> > On a less important implementation if the pieces that live under the
> > library are driver binding we have to reject any stop requests as
> > there is no driver linkage between the two layers.
> 
> In x86, root complex (pcie root) is almost the root of all peripherals. I cannot
> see a value to Stop () the pcie root.
> If you check the PciBus implementation, it supports Stop() but the Stop() only
> succeeds when all upper layer drivers succeed to Stop(). (usually it's not the
> case.) And even PciBus.Stop() succeeds, the resource(MMIO/IO/BUS)
> allocation is not un-done. It's only the PciIo handles that are destroyed in
> software level.
> 

[JB] Yeah, not allowing stop to work on this isn't a big deal (and what we currently have implemented) but it was something we noticed a while ago is that we couldn't implement this even if we wanted to as there was no way to stop the host bridge driver.

> Thanks,
> Ray
> 
> 
> >
> > -Jeff
> >
> >
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Thursday, June 29, 2023 8:29 PM
> > To: Jeff Brasen <jbrasen@nvidia.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for
> > driver binding
> >
> > External email: Use caution opening links or attachments
> >
> >
> > I failed to apply the patch in my local tree.
> >
> > It seems you invented a new EdkiiRootBridgeIo protocol and a certain
> > proprietary driver would produce this protocol instance.
> > Then the open source PciHostBridge driver starts on that.
> >
> > Then, why not implement your own PciHostBridgeLib and let it depends
> > on some "AllRootBridgeIoInformationIsReady" protocol.
> > So that the PciHostBridge driver could still call PciHostBridgeLib and
> > all your implementation in this patch can be in that lib.
> >
> > Thanks,
> > Ray
> >
> > > -----Original Message-----
> > > From: Jeff Brasen <jbrasen@nvidia.com>
> > > Sent: Friday, June 30, 2023 4:54 AM
> > > To: devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray
> > > <ray.ni@intel.com>; Jeff Brasen <jbrasen@nvidia.com>
> > > Subject: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver
> > > binding
> > >
> > > If the platform does not support any PCIe devices using the library
> > >
> > > method allow devices to connect to host bridge via driver binding.
> > >
> > >
> > >
> > > Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
> > >
> > > ---
> > >
> > >  .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 649
> > > ++++++++++++++----
> > >
> > >  .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   1 +
> > >
> > >  .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h  |  13 +
> > >
> > >  .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    |  24 +
> > >
> > >  MdeModulePkg/MdeModulePkg.dec                 |   4 +
> > >
> > >  5 files changed, 562 insertions(+), 129 deletions(-)
> > >
> > >
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > >
> > > index d573e532ba..506c6660ae 100644
> > >
> > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > >
> > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > >
> > > @@ -422,167 +422,320 @@ IoMmuProtocolCallback (
> > >
> > >  }
> > >
> > >
> > >
> > >  /**
> > >
> > > +  PCI Root Bridge Memory setup.
> > >
> > >
> > >
> > > -  Entry point of this driver.
> > >
> > > +  @param  RootBridge            Root Bridge instance.
> > >
> > >
> > >
> > > -  @param ImageHandle  Image handle of this driver.
> > >
> > > -  @param SystemTable  Pointer to standard EFI system table.
> > >
> > > -
> > >
> > > -  @retval EFI_SUCCESS       Succeed.
> > >
> > > -  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO
> protocol.
> > >
> > > +  @retval EFI_SUCCESS           Memory was setup correctly
> > >
> > > +  @retval others                Error in setup
> > >
> > >
> > >
> > >  **/
> > >
> > >  EFI_STATUS
> > >
> > >  EFIAPI
> > >
> > > -InitializePciHostBridge (
> > >
> > > -  IN EFI_HANDLE        ImageHandle,
> > >
> > > -  IN EFI_SYSTEM_TABLE  *SystemTable
> > >
> > > +PciRootBridgeMemorySetup (
> > >
> > > +  IN PCI_ROOT_BRIDGE  *RootBridge
> > >
> > >    )
> > >
> > >  {
> > >
> > >    EFI_STATUS                Status;
> > >
> > > -  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> > >
> > > -  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> > >
> > > -  PCI_ROOT_BRIDGE           *RootBridges;
> > >
> > > -  UINTN                     RootBridgeCount;
> > >
> > > -  UINTN                     Index;
> > >
> > > +  UINT64                    HostAddress;
> > >
> > >    PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> > >
> > >    UINTN                     MemApertureIndex;
> > >
> > > -  BOOLEAN                   ResourceAssigned;
> > >
> > > -  LIST_ENTRY                *Link;
> > >
> > > -  UINT64                    HostAddress;
> > >
> > >
> > >
> > > -  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> > >
> > > -  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> > >
> > > -    return EFI_UNSUPPORTED;
> > >
> > > -  }
> > >
> > > -
> > >
> > > -  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL,
> > > (VOID **)&mCpuIo);
> > >
> > > -  ASSERT_EFI_ERROR (Status);
> > >
> > > -
> > >
> > > -  //
> > >
> > > -  // Most systems in the world including complex servers have only
> > > one Host Bridge.
> > >
> > > -  //
> > >
> > > -  HostBridge = AllocateZeroPool (sizeof
> > > (PCI_HOST_BRIDGE_INSTANCE));
> > >
> > > -  ASSERT (HostBridge != NULL);
> > >
> > > -
> > >
> > > -  HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> > >
> > > -  HostBridge->CanRestarted = TRUE;
> > >
> > > -  InitializeListHead (&HostBridge->RootBridges);
> > >
> > > -  ResourceAssigned = FALSE;
> > >
> > > -
> > >
> > > -  //
> > >
> > > -  // Create Root Bridge Device Handle in this Host Bridge
> > >
> > > -  //
> > >
> > > -  for (Index = 0; Index < RootBridgeCount; Index++) {
> > >
> > > +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> > >
> > >      //
> > >
> > > -    // Create Root Bridge Handle Instance
> > >
> > > +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > >
> > > +    // For GCD resource manipulation, we need to use host address.
> > >
> > >      //
> > >
> > > -    RootBridge = CreateRootBridge (&RootBridges[Index]);
> > >
> > > -    ASSERT (RootBridge != NULL);
> > >
> > > -    if (RootBridge == NULL) {
> > >
> > > -      continue;
> > >
> > > +    HostAddress = TO_HOST_ADDRESS (
> > >
> > > +                    RootBridge->Io.Base,
> > >
> > > +                    RootBridge->Io.Translation
> > >
> > > +                    );
> > >
> > > +
> > >
> > > +    Status = AddIoSpace (
> > >
> > > +               HostAddress,
> > >
> > > +               RootBridge->Io.Limit - RootBridge->Io.Base + 1
> > >
> > > +               );
> > >
> > > +    ASSERT_EFI_ERROR (Status);
> > >
> > > +    if (EFI_ERROR (Status)) {
> > >
> > > +      return Status;
> > >
> > >      }
> > >
> > >
> > >
> > > -    //
> > >
> > > -    // Make sure all root bridges share the same ResourceAssigned value.
> > >
> > > -    //
> > >
> > > -    if (Index == 0) {
> > >
> > > -      ResourceAssigned = RootBridges[Index].ResourceAssigned;
> > >
> > > -    } else {
> > >
> > > -      ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
> > >
> > > +    if (RootBridge->ResourceAssigned) {
> > >
> > > +      Status = gDS->AllocateIoSpace (
> > >
> > > +                      EfiGcdAllocateAddress,
> > >
> > > +                      EfiGcdIoTypeIo,
> > >
> > > +                      0,
> > >
> > > +                      RootBridge->Io.Limit - RootBridge->Io.Base +
> > > + 1,
> > >
> > > +                      &HostAddress,
> > >
> > > +                      gImageHandle,
> > >
> > > +                      NULL
> > >
> > > +                      );
> > >
> > > +      ASSERT_EFI_ERROR (Status);
> > >
> > > +      if (EFI_ERROR (Status)) {
> > >
> > > +        return Status;
> > >
> > > +      }
> > >
> > >      }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Add all the Mem/PMem aperture to GCD
> > >
> > > +  // Mem/PMem shouldn't overlap with each other
> > >
> > > +  // Root bridge which needs to combine MEM and PMEM should only
> > > + report
> > >
> > > +  // the MEM aperture in Mem
> > >
> > > +  //
> > >
> > > +  MemApertures[0] = &RootBridge->Mem;
> > >
> > > +  MemApertures[1] = &RootBridge->MemAbove4G;
> > >
> > > +  MemApertures[2] = &RootBridge->PMem;
> > >
> > > +  MemApertures[3] = &RootBridge->PMemAbove4G;
> > >
> > >
> > >
> > > -    if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
> > >
> > > +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > > (MemApertures); MemApertureIndex++) {
> > >
> > > +    if (MemApertures[MemApertureIndex]->Base <=
> > > MemApertures[MemApertureIndex]->Limit) {
> > >
> > >        //
> > >
> > >        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > >
> > >        // For GCD resource manipulation, we need to use host address.
> > >
> > >        //
> > >
> > >        HostAddress = TO_HOST_ADDRESS (
> > >
> > > -                      RootBridges[Index].Io.Base,
> > >
> > > -                      RootBridges[Index].Io.Translation
> > >
> > > +                      MemApertures[MemApertureIndex]->Base,
> > >
> > > +                      MemApertures[MemApertureIndex]->Translation
> > >
> > >                        );
> > >
> > > -
> > >
> > > -      Status = AddIoSpace (
> > >
> > > +      Status = AddMemoryMappedIoSpace (
> > >
> > >                   HostAddress,
> > >
> > > -                 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
> > >
> > > +                 MemApertures[MemApertureIndex]->Limit -
> > > MemApertures[MemApertureIndex]->Base + 1,
> > >
> > > +                 EFI_MEMORY_UC
> > >
> > >                   );
> > >
> > >        ASSERT_EFI_ERROR (Status);
> > >
> > > -      if (ResourceAssigned) {
> > >
> > > -        Status = gDS->AllocateIoSpace (
> > >
> > > +      if (EFI_ERROR (Status)) {
> > >
> > > +        return Status;
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      Status = gDS->SetMemorySpaceAttributes (
> > >
> > > +                      HostAddress,
> > >
> > > +                      MemApertures[MemApertureIndex]->Limit -
> > > MemApertures[MemApertureIndex]->Base + 1,
> > >
> > > +                      EFI_MEMORY_UC
> > >
> > > +                      );
> > >
> > > +      if (EFI_ERROR (Status)) {
> > >
> > > +        DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> > > EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      if (RootBridge->ResourceAssigned) {
> > >
> > > +        Status = gDS->AllocateMemorySpace (
> > >
> > >                          EfiGcdAllocateAddress,
> > >
> > > -                        EfiGcdIoTypeIo,
> > >
> > > +                        EfiGcdMemoryTypeMemoryMappedIo,
> > >
> > >                          0,
> > >
> > > -                        RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
> > >
> > > +                        MemApertures[MemApertureIndex]->Limit -
> > > MemApertures[MemApertureIndex]->Base + 1,
> > >
> > >                          &HostAddress,
> > >
> > >                          gImageHandle,
> > >
> > >                          NULL
> > >
> > >                          );
> > >
> > >          ASSERT_EFI_ERROR (Status);
> > >
> > > +        if (EFI_ERROR (Status)) {
> > >
> > > +          return Status;
> > >
> > > +        }
> > >
> > >        }
> > >
> > >      }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > >
> > >
> > > +/**
> > >
> > > +  PCI Root Bridge Memory free.
> > >
> > > +
> > >
> > > +  @param  RootBridge            Root Bridge instance.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           Memory was setup correctly
> > >
> > > +  @retval others                Error in setup
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EFIAPI
> > >
> > > +PciRootBridgeMemoryFree (
> > >
> > > +  IN PCI_ROOT_BRIDGE  *RootBridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                Status;
> > >
> > > +  UINT64                    HostAddress;
> > >
> > > +  PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> > >
> > > +  UINTN                     MemApertureIndex;
> > >
> > > +
> > >
> > > +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> > >
> > >      //
> > >
> > > -    // Add all the Mem/PMem aperture to GCD
> > >
> > > -    // Mem/PMem shouldn't overlap with each other
> > >
> > > -    // Root bridge which needs to combine MEM and PMEM should only
> report
> > >
> > > -    // the MEM aperture in Mem
> > >
> > > +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > >
> > > +    // For GCD resource manipulation, we need to use host address.
> > >
> > >      //
> > >
> > > -    MemApertures[0] = &RootBridges[Index].Mem;
> > >
> > > -    MemApertures[1] = &RootBridges[Index].MemAbove4G;
> > >
> > > -    MemApertures[2] = &RootBridges[Index].PMem;
> > >
> > > -    MemApertures[3] = &RootBridges[Index].PMemAbove4G;
> > >
> > > -
> > >
> > > -    for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > > (MemApertures); MemApertureIndex++) {
> > >
> > > -      if (MemApertures[MemApertureIndex]->Base <=
> > > MemApertures[MemApertureIndex]->Limit) {
> > >
> > > -        //
> > >
> > > -        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > >
> > > -        // For GCD resource manipulation, we need to use host address.
> > >
> > > -        //
> > >
> > > -        HostAddress = TO_HOST_ADDRESS (
> > >
> > > -                        MemApertures[MemApertureIndex]->Base,
> > >
> > > -                        MemApertures[MemApertureIndex]->Translation
> > >
> > > -                        );
> > >
> > > -        Status = AddMemoryMappedIoSpace (
> > >
> > > -                   HostAddress,
> > >
> > > -                   MemApertures[MemApertureIndex]->Limit -
> > > MemApertures[MemApertureIndex]->Base + 1,
> > >
> > > -                   EFI_MEMORY_UC
> > >
> > > -                   );
> > >
> > > +    HostAddress = TO_HOST_ADDRESS (
> > >
> > > +                    RootBridge->Io.Base,
> > >
> > > +                    RootBridge->Io.Translation
> > >
> > > +                    );
> > >
> > > +
> > >
> > > +    if (RootBridge->ResourceAssigned) {
> > >
> > > +      Status = gDS->FreeIoSpace (HostAddress, RootBridge->Io.Limit
> > > + -
> > > + RootBridge-
> > > >Io.Base + 1);
> > >
> > > +      ASSERT_EFI_ERROR (Status);
> > >
> > > +      if (EFI_ERROR (Status)) {
> > >
> > > +        return Status;
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Add all the Mem/PMem aperture to GCD
> > >
> > > +  // Mem/PMem shouldn't overlap with each other
> > >
> > > +  // Root bridge which needs to combine MEM and PMEM should only
> > > + report
> > >
> > > +  // the MEM aperture in Mem
> > >
> > > +  //
> > >
> > > +  MemApertures[0] = &RootBridge->Mem;
> > >
> > > +  MemApertures[1] = &RootBridge->MemAbove4G;
> > >
> > > +  MemApertures[2] = &RootBridge->PMem;
> > >
> > > +  MemApertures[3] = &RootBridge->PMemAbove4G;
> > >
> > > +
> > >
> > > +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > > (MemApertures); MemApertureIndex++) {
> > >
> > > +    if (MemApertures[MemApertureIndex]->Base <=
> > > MemApertures[MemApertureIndex]->Limit) {
> > >
> > > +      //
> > >
> > > +      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > >
> > > +      // For GCD resource manipulation, we need to use host address.
> > >
> > > +      //
> > >
> > > +      HostAddress = TO_HOST_ADDRESS (
> > >
> > > +                      MemApertures[MemApertureIndex]->Base,
> > >
> > > +                      MemApertures[MemApertureIndex]->Translation
> > >
> > > +                      );
> > >
> > > +      if (RootBridge->ResourceAssigned) {
> > >
> > > +        Status = gDS->FreeMemorySpace (HostAddress,
> > > + RootBridge->Io.Limit -
> > > RootBridge->Io.Base + 1);
> > >
> > >          ASSERT_EFI_ERROR (Status);
> > >
> > > -        Status = gDS->SetMemorySpaceAttributes (
> > >
> > > -                        HostAddress,
> > >
> > > -                        MemApertures[MemApertureIndex]->Limit -
> > > MemApertures[MemApertureIndex]->Base + 1,
> > >
> > > -                        EFI_MEMORY_UC
> > >
> > > -                        );
> > >
> > >          if (EFI_ERROR (Status)) {
> > >
> > > -          DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> > > EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> > >
> > > -        }
> > >
> > > -
> > >
> > > -        if (ResourceAssigned) {
> > >
> > > -          Status = gDS->AllocateMemorySpace (
> > >
> > > -                          EfiGcdAllocateAddress,
> > >
> > > -                          EfiGcdMemoryTypeMemoryMappedIo,
> > >
> > > -                          0,
> > >
> > > -                          MemApertures[MemApertureIndex]->Limit -
> > > MemApertures[MemApertureIndex]->Base + 1,
> > >
> > > -                          &HostAddress,
> > >
> > > -                          gImageHandle,
> > >
> > > -                          NULL
> > >
> > > -                          );
> > >
> > > -          ASSERT_EFI_ERROR (Status);
> > >
> > > +          return Status;
> > >
> > >          }
> > >
> > >        }
> > >
> > >      }
> > >
> > > +  }
> > >
> > >
> > >
> > > -    //
> > >
> > > -    // Insert Root Bridge Handle Instance
> > >
> > > -    //
> > >
> > > -    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Test to see if this driver supports ControllerHandle. Any
> > > + ControllerHandle
> > >
> > > +  than contains a gEdkiiPciHostBridgeProtocolGuid protocol can be
> supported.
> > >
> > > +
> > >
> > > +  @param  This                Protocol instance pointer.
> > >
> > > +  @param  Controller          Handle of device to test.
> > >
> > > +  @param  RemainingDevicePath Optional parameter use to pick a
> > > + specific child
> > >
> > > +                              device to start.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS         This driver supports this device.
> > >
> > > +  @retval EFI_ALREADY_STARTED This driver is already running on this
> device.
> > >
> > > +  @retval other               This driver does not support this device.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EFIAPI
> > >
> > > +PciHostBrigeDriverBindingSupported (
> > >
> > > +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> > >
> > > +  IN EFI_HANDLE                   Controller,
> > >
> > > +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS       Status;
> > >
> > > +  PCI_ROOT_BRIDGE  *PciRootBridge;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Check if Pci Host Bridge protocol is installed by platform
> > >
> > > +  //
> > >
> > > +  Status = gBS->OpenProtocol (
> > >
> > > +                  Controller,
> > >
> > > +                  &gEdkiiPciHostBridgeProtocolGuid,
> > >
> > > +                  (VOID **)&PciRootBridge,
> > >
> > > +                  This->DriverBindingHandle,
> > >
> > > +                  Controller,
> > >
> > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > >
> > > +                  );
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    return Status;
> > >
> > >    }
> > >
> > >
> > >
> > >    //
> > >
> > > -  // When resources were assigned, it's not needed to expose
> > >
> > > -  // PciHostBridgeResourceAllocation protocol.
> > >
> > > +  // Close the protocol used to perform the supported test
> > >
> > > +  //
> > >
> > > +  gBS->CloseProtocol (
> > >
> > > +         Controller,
> > >
> > > +         &gEdkiiPciHostBridgeProtocolGuid,
> > >
> > > +         This->DriverBindingHandle,
> > >
> > > +         Controller
> > >
> > > +         );
> > >
> > > +
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Start this driver on ControllerHandle and enumerate Pci bus and
> > > + start
> > >
> > > +  all device under PCI bus.
> > >
> > > +
> > >
> > > +  @param  This                 Protocol instance pointer.
> > >
> > > +  @param  Controller           Handle of device to bind driver to.
> > >
> > > +  @param  RemainingDevicePath  Optional parameter use to pick a
> > > + specific child
> > >
> > > +                               device to start.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
> > >
> > > +  @retval EFI_ALREADY_STARTED  This driver is already running on
> > > ControllerHandle.
> > >
> > > +  @retval other                This driver does not support this device.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EFIAPI
> > >
> > > +PciHostBrigeDriverBindingStart (
> > >
> > > +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> > >
> > > +  IN EFI_HANDLE                   Controller,
> > >
> > > +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                Status;
> > >
> > > +  PCI_ROOT_BRIDGE           *PciRootBridge;
> > >
> > > +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> > >
> > > +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> > >
> > > +  BOOLEAN                   MemorySetupDone;
> > >
> > > +
> > >
> > > +  MemorySetupDone = FALSE;
> > >
> > > +  //
> > >
> > > +  // Check if Pci Host Bridge protocol is installed by platform
> > >
> > >    //
> > >
> > > -  if (!ResourceAssigned) {
> > >
> > > +  Status = gBS->OpenProtocol (
> > >
> > > +                  Controller,
> > >
> > > +                  &gEdkiiPciHostBridgeProtocolGuid,
> > >
> > > +                  (VOID **)&PciRootBridge,
> > >
> > > +                  This->DriverBindingHandle,
> > >
> > > +                  Controller,
> > >
> > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > >
> > > +                  );
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    return Status;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  RootBridge = CreateRootBridge (PciRootBridge);
> > >
> > > +  ASSERT (RootBridge != NULL);
> > >
> > > +  if (RootBridge == NULL) {
> > >
> > > +    Status = EFI_DEVICE_ERROR;
> > >
> > > +    goto ErrorExit;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  Status = PciRootBridgeMemorySetup (PciRootBridge);
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    goto ErrorExit;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  MemorySetupDone = TRUE;
> > >
> > > +
> > >
> > > +  if (!PciRootBridge->ResourceAssigned) {
> > >
> > > +    // Create host bridge
> > >
> > > +    HostBridge = AllocateZeroPool (sizeof
> > > + (PCI_HOST_BRIDGE_INSTANCE));
> > >
> > > +    ASSERT (HostBridge != NULL);
> > >
> > > +    if (HostBridge == NULL) {
> > >
> > > +      Status = EFI_OUT_OF_RESOURCES;
> > >
> > > +      goto ErrorExit;
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    HostBridge->Handle       = 0;
> > >
> > > +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> > >
> > > +    HostBridge->CanRestarted = TRUE;
> > >
> > > +    InitializeListHead (&HostBridge->RootBridges);
> > >
> > > +
> > >
> > >      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> > >
> > >      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> > >
> > >      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> > >
> > > @@ -599,28 +752,266 @@ InitializePciHostBridge (
> > >
> > >                      NULL
> > >
> > >                      );
> > >
> > >      ASSERT_EFI_ERROR (Status);
> > >
> > > -  }
> > >
> > > +    if (EFI_ERROR (Status)) {
> > >
> > > +      goto ErrorExit;
> > >
> > > +    }
> > >
> > >
> > >
> > > -  for (Link = GetFirstNode (&HostBridge->RootBridges)
> > >
> > > -       ; !IsNull (&HostBridge->RootBridges, Link)
> > >
> > > -       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> > >
> > > -       )
> > >
> > > -  {
> > >
> > > -    RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> > >
> > > +    //
> > >
> > > +    // Insert Root Bridge Handle Instance
> > >
> > > +    //
> > >
> > > +    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> > >
> > >      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> > >
> > > +  } else {
> > >
> > > +    RootBridge->RootBridgeIo.ParentHandle = 0;
> > >
> > > +  }
> > >
> > >
> > >
> > > -    Status = gBS->InstallMultipleProtocolInterfaces (
> > >
> > > -                    &RootBridge->Handle,
> > >
> > > -                    &gEfiDevicePathProtocolGuid,
> > >
> > > -                    RootBridge->DevicePath,
> > >
> > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > >
> > > -                    &RootBridge->RootBridgeIo,
> > >
> > > -                    NULL
> > >
> > > -                    );
> > >
> > > -    ASSERT_EFI_ERROR (Status);
> > >
> > > +  RootBridge->Handle = Controller;
> > >
> > > +  Status             = gBS->InstallMultipleProtocolInterfaces (
> > >
> > > +                              &RootBridge->Handle,
> > >
> > > +                              &gEfiPciRootBridgeIoProtocolGuid,
> > >
> > > +                              &RootBridge->RootBridgeIo,
> > >
> > > +                              NULL
> > >
> > > +                              );
> > >
> > > +
> > >
> > > +ErrorExit:
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    if (MemorySetupDone) {
> > >
> > > +      PciRootBridgeMemoryFree (PciRootBridge);
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    if (RootBridge != NULL) {
> > >
> > > +      if (!IsListEmpty (&RootBridge->Link)) {
> > >
> > > +        RemoveEntryList (&RootBridge->Link);
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      FreeRootBridge (RootBridge);
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    gBS->CloseProtocol (
> > >
> > > +           Controller,
> > >
> > > +           &gEdkiiPciHostBridgeProtocolGuid,
> > >
> > > +           This->DriverBindingHandle,
> > >
> > > +           Controller
> > >
> > > +           );
> > >
> > >    }
> > >
> > >
> > >
> > > -  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Stop this driver on ControllerHandle. Support stopping any child
> > > + handles
> > >
> > > +  created by this driver.
> > >
> > > +
> > >
> > > +  @param  This              Protocol instance pointer.
> > >
> > > +  @param  Controller        Handle of device to stop driver on.
> > >
> > > +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer.
> > > + If
> > > number of
> > >
> > > +                            children is zero stop the entire bus driver.
> > >
> > > +  @param  ChildHandleBuffer List of Child Handles to Stop.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
> > >
> > > +  @retval other             This driver was not removed from this device.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EFIAPI
> > >
> > > +PciHostBrigeDriverBindingStop (
> > >
> > > +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
> > >
> > > +  IN  EFI_HANDLE                   Controller,
> > >
> > > +  IN  UINTN                        NumberOfChildren,
> > >
> > > +  IN  EFI_HANDLE                   *ChildHandleBuffer
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                       Status;
> > >
> > > +  PCI_ROOT_BRIDGE                  *PciRootBridge;
> > >
> > > +  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;
> > >
> > > +  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;
> > >
> > > +
> > >
> > > +  Status = gBS->HandleProtocol (
> > >
> > > +                  Controller,
> > >
> > > +                  &gEfiPciRootBridgeIoProtocolGuid,
> > >
> > > +                  (VOID **)&RootBridgeIo
> > >
> > > +                  );
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    return Status;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  RootBridge = ROOT_BRIDGE_FROM_THIS (RootBridgeIo);
> > >
> > > +
> > >
> > > +  Status = gBS->HandleProtocol (
> > >
> > > +                  Controller,
> > >
> > > +                  &gEdkiiPciHostBridgeProtocolGuid,
> > >
> > > +                  (VOID **)&PciRootBridge
> > >
> > > +                  );
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    return Status;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  Status = gBS->UninstallMultipleProtocolInterfaces (
> > >
> > > +                  Controller,
> > >
> > > +                  &gEfiPciRootBridgeIoProtocolGuid,
> > >
> > > +                  (VOID **)&PciRootBridge
> > >
> > > +                  );
> > >
> > > +  if (EFI_ERROR (Status)) {
> > >
> > > +    return Status;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (!IsListEmpty (&RootBridge->Link)) {
> > >
> > > +    RemoveEntryList (&RootBridge->Link);
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  PciRootBridgeMemoryFree (PciRootBridge);
> > >
> > > +
> > >
> > > +  FreeRootBridge (RootBridge);
> > >
> > > +  gBS->CloseProtocol (
> > >
> > > +         Controller,
> > >
> > > +         &gEdkiiPciHostBridgeProtocolGuid,
> > >
> > > +         This->DriverBindingHandle,
> > >
> > > +         Controller
> > >
> > > +         );
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +//
> > >
> > > +// PCI Bus Driver Global Variables
> > >
> > > +//
> > >
> > > +EFI_DRIVER_BINDING_PROTOCOL  gPciHostBrigeDriverBinding = {
> > >
> > > +  PciHostBrigeDriverBindingSupported,
> > >
> > > +  PciHostBrigeDriverBindingStart,
> > >
> > > +  PciHostBrigeDriverBindingStop,
> > >
> > > +  0xa,
> > >
> > > +  NULL,
> > >
> > > +  NULL
> > >
> > > +};
> > >
> > > +
> > >
> > > +/**
> > >
> > > +
> > >
> > > +  Entry point of this driver.
> > >
> > > +
> > >
> > > +  @param ImageHandle  Image handle of this driver.
> > >
> > > +  @param SystemTable  Pointer to standard EFI system table.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS       Succeed.
> > >
> > > +  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO
> protocol.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EFIAPI
> > >
> > > +InitializePciHostBridge (
> > >
> > > +  IN EFI_HANDLE        ImageHandle,
> > >
> > > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                Status;
> > >
> > > +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> > >
> > > +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> > >
> > > +  PCI_ROOT_BRIDGE           *RootBridges;
> > >
> > > +  UINTN                     RootBridgeCount;
> > >
> > > +  UINTN                     Index;
> > >
> > > +  BOOLEAN                   ResourceAssigned;
> > >
> > > +  LIST_ENTRY                *Link;
> > >
> > > +
> > >
> > > +  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL,
> > > + (VOID
> > > **)&mCpuIo);
> > >
> > > +  ASSERT_EFI_ERROR (Status);
> > >
> > > +
> > >
> > > +  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> > >
> > > +  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> > >
> > > +    // Register for binding protocol if library enumeration is not
> > > + used
> > >
> > > +    Status = EfiLibInstallDriverBinding (
> > >
> > > +               ImageHandle,
> > >
> > > +               SystemTable,
> > >
> > > +               &gPciHostBrigeDriverBinding,
> > >
> > > +               ImageHandle
> > >
> > > +               );
> > >
> > > +    ASSERT_EFI_ERROR (Status);
> > >
> > > +  } else {
> > >
> > > +    //
> > >
> > > +    // Most systems in the world including complex servers have
> > > + only one Host
> > > Bridge.
> > >
> > > +    //
> > >
> > > +    HostBridge = AllocateZeroPool (sizeof
> > > + (PCI_HOST_BRIDGE_INSTANCE));
> > >
> > > +    ASSERT (HostBridge != NULL);
> > >
> > > +
> > >
> > > +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> > >
> > > +    HostBridge->CanRestarted = TRUE;
> > >
> > > +    InitializeListHead (&HostBridge->RootBridges);
> > >
> > > +    ResourceAssigned = FALSE;
> > >
> > > +
> > >
> > > +    //
> > >
> > > +    // Create Root Bridge Device Handle in this Host Bridge
> > >
> > > +    //
> > >
> > > +    for (Index = 0; Index < RootBridgeCount; Index++) {
> > >
> > > +      //
> > >
> > > +      // Create Root Bridge Handle Instance
> > >
> > > +      //
> > >
> > > +      RootBridge = CreateRootBridge (&RootBridges[Index]);
> > >
> > > +      ASSERT (RootBridge != NULL);
> > >
> > > +      if (RootBridge == NULL) {
> > >
> > > +        continue;
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      //
> > >
> > > +      // Make sure all root bridges share the same ResourceAssigned value.
> > >
> > > +      //
> > >
> > > +      if (Index == 0) {
> > >
> > > +        ResourceAssigned = RootBridges[Index].ResourceAssigned;
> > >
> > > +      } else {
> > >
> > > +        ASSERT (ResourceAssigned ==
> > > + RootBridges[Index].ResourceAssigned);
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      Status = PciRootBridgeMemorySetup (&RootBridges[Index]);
> > >
> > > +      if (EFI_ERROR (Status)) {
> > >
> > > +        continue;
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      //
> > >
> > > +      // Insert Root Bridge Handle Instance
> > >
> > > +      //
> > >
> > > +      InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    //
> > >
> > > +    // When resources were assigned, it's not needed to expose
> > >
> > > +    // PciHostBridgeResourceAllocation protocol.
> > >
> > > +    //
> > >
> > > +    if (!ResourceAssigned) {
> > >
> > > +      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> > >
> > > +      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> > >
> > > +      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> > >
> > > +      HostBridge->ResAlloc.StartBusEnumeration  =
> > > + StartBusEnumeration;
> > >
> > > +      HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
> > >
> > > +      HostBridge->ResAlloc.SubmitResources      = SubmitResources;
> > >
> > > +      HostBridge->ResAlloc.GetProposedResources =
> > > + GetProposedResources;
> > >
> > > +      HostBridge->ResAlloc.PreprocessController =
> > > + PreprocessController;
> > >
> > > +
> > >
> > > +      Status = gBS->InstallMultipleProtocolInterfaces (
> > >
> > > +                      &HostBridge->Handle,
> > >
> > > +
> > > + &gEfiPciHostBridgeResourceAllocationProtocolGuid,
> > >
> > > +                      &HostBridge->ResAlloc,
> > >
> > > +                      NULL
> > >
> > > +                      );
> > >
> > > +      ASSERT_EFI_ERROR (Status);
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    for (Link = GetFirstNode (&HostBridge->RootBridges)
> > >
> > > +         ; !IsNull (&HostBridge->RootBridges, Link)
> > >
> > > +         ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> > >
> > > +         )
> > >
> > > +    {
> > >
> > > +      RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> > >
> > > +      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> > >
> > > +
> > >
> > > +      Status = gBS->InstallMultipleProtocolInterfaces (
> > >
> > > +                      &RootBridge->Handle,
> > >
> > > +                      &gEfiDevicePathProtocolGuid,
> > >
> > > +                      RootBridge->DevicePath,
> > >
> > > +                      &gEfiPciRootBridgeIoProtocolGuid,
> > >
> > > +                      &RootBridge->RootBridgeIo,
> > >
> > > +                      NULL
> > >
> > > +                      );
> > >
> > > +      ASSERT_EFI_ERROR (Status);
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> > >
> > > +  }
> > >
> > >
> > >
> > >    if (!EFI_ERROR (Status)) {
> > >
> > >      mIoMmuEvent = EfiCreateProtocolNotifyEvent (
> > >
> > > diff --git
> > > a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > >
> > > index 9c24cacc30..ee4740b14f 100644
> > >
> > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > >
> > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > >
> > > @@ -46,6 +46,7 @@
> > >
> > >    gEfiPciRootBridgeIoProtocolGuid                 ## BY_START
> > >
> > >    gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
> > >
> > >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> > >
> > > +  gEdkiiPciHostBridgeProtocolGuid                 ## SOMETIMES_CONSUMES
> > >
> > >
> > >
> > >  [Depex]
> > >
> > >    gEfiCpuIo2ProtocolGuid AND
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > >
> > > index 10a6200719..7923c4677b 100644
> > >
> > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > >
> > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > >
> > > @@ -93,6 +93,19 @@ CreateRootBridge (
> > >
> > >    IN PCI_ROOT_BRIDGE  *Bridge
> > >
> > >    );
> > >
> > >
> > >
> > > +/**
> > >
> > > +  Free the Pci Root Bridge instance.
> > >
> > > +
> > >
> > > +  @param Bridge            The root bridge instance.
> > >
> > > +
> > >
> > > +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> > >
> > > +          or NULL if creation fails.
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +FreeRootBridge (
> > >
> > > +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> > >
> > > +  );
> > >
> > > +
> > >
> > >  //
> > >
> > >  // Protocol Member Function Prototypes
> > >
> > >  //
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > >
> > > index 157a0ada80..f0eb465a9d 100644
> > >
> > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > >
> > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > >
> > > @@ -286,6 +286,30 @@ CreateRootBridge (
> > >
> > >    return RootBridge;
> > >
> > >  }
> > >
> > >
> > >
> > > +/**
> > >
> > > +  Free the Pci Root Bridge instance.
> > >
> > > +
> > >
> > > +  @param Bridge            The root bridge instance.
> > >
> > > +
> > >
> > > +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> > >
> > > +          or NULL if creation fails.
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +FreeRootBridge (
> > >
> > > +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  if (Bridge->ConfigBuffer != NULL) {
> > >
> > > +    FreePool (Bridge->ConfigBuffer);
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (Bridge->DevicePath != NULL) {
> > >
> > > +    FreePool (Bridge->DevicePath);
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  FreePool (Bridge);
> > >
> > > +}
> > >
> > > +
> > >
> > >  /**
> > >
> > >    Check parameters for IO,MMIO,PCI read/write services of PCI Root
> Bridge IO.
> > >
> > >
> > >
> > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > b/MdeModulePkg/MdeModulePkg.dec
> > >
> > > index d65dae18aa..24700fa797 100644
> > >
> > > --- a/MdeModulePkg/MdeModulePkg.dec
> > >
> > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > >
> > > @@ -692,6 +692,10 @@
> > >
> > >    ## Include/Protocol/VariablePolicy.h
> > >
> > >    gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF,
> > > { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
> > >
> > >
> > >
> > > +  ## Include/Library/PciHostBridgeLib.h
> > >
> > > +  # Exposes a PCI_HOST_BRIDGE structure for driver binding usage
> > >
> > > +  gEdkiiPciHostBridgeProtocolGuid = { 0xaff2b72d, 0x202e, 0x40e3, {
> > > + 0x82, 0xd5,
> > > 0x9f, 0x6f, 0x61, 0xaf, 0x2a, 0x0b } }
> > >
> > > +
> > >
> > >  [PcdsFeatureFlag]
> > >
> > >    ## Indicates if the platform can support update capsule across a
> > > system reset.<BR><BR>
> > >
> > >    #   TRUE  - Supports update capsule across a system reset.<BR>
> > >
> > > --
> > >
> > > 2.25.1
> > >
> > >



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106569): https://edk2.groups.io/g/devel/message/106569
Mute This Topic: https://groups.io/mt/99859311/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding
Posted by Jeff Brasen via groups.io 9 months, 3 weeks ago
Ray,

  Would you prefer this sort of use would be done by an extra dispatch after the wait for everything being completed and the connect controller call in BDS as opposed to the driver binding approach?  Basically using a depex on the library as we are currently doing. 

-Jeff


> -----Original Message-----
> From: Jeff Brasen <jbrasen@nvidia.com>
> Sent: Friday, June 30, 2023 9:57 AM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for driver
> binding
> 
> 
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Thursday, June 29, 2023 9:59 PM
> > To: Jeff Brasen <jbrasen@nvidia.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for
> > driver binding
> >
> > External email: Use caution opening links or attachments
> >
> >
> > > -----Original Message-----
> > > From: Jeff Brasen <jbrasen@nvidia.com>
> > > Sent: Friday, June 30, 2023 11:21 AM
> > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> > > Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for
> > > driver binding
> > >
> > > Not sure why the patch failed to apply I'll see if there is
> > > something wrong with my gitconfig tomorrow. The path you suggested
> > > below is exactly what our current implementation does. However, I am
> > > trying to make our pcie controller driver do async initialization so
> > > that using a depex is less ideal as we may have to postpone driver
> > > load to after end of dxe instead of just the connection. It seemed
> > > that a driver binding
> > type approach was a good approach for this.
> >
> > I am curious how the pcie root (root complex) initialization is done
> > in async way?
> > Does it use a timer callback to poll the initialization status every
> > certain interval?
> >
> 
> [JB] That is correct, we use a timer when we expect sleeps or polling loops.
> 
> > On the other hand, even you make PciHostBridge as a UEFI driver-model
> > driver, you still require some code to initiate the
> > "ConnectController()". How is that done?
> >
> > Comparing the two paths (today's = my proposal, new way = your patch),
> > both require some code to explicitly call "ConnectController()".
> >
> 
> [JB] We have a sync point in BDS prior to the ConnectController call that is
> made. I could put that and a dispatch call prior to EndOfDxe signal but was
> hoping to not trigger any of the driver seen but not loaded debug messages
> from the main dispatch loop if possible as that can be a useful message to
> trigger something might be wrong.
> 
> > >
> > > On a less important implementation if the pieces that live under the
> > > library are driver binding we have to reject any stop requests as
> > > there is no driver linkage between the two layers.
> >
> > In x86, root complex (pcie root) is almost the root of all
> > peripherals. I cannot see a value to Stop () the pcie root.
> > If you check the PciBus implementation, it supports Stop() but the
> > Stop() only succeeds when all upper layer drivers succeed to Stop().
> > (usually it's not the
> > case.) And even PciBus.Stop() succeeds, the resource(MMIO/IO/BUS)
> > allocation is not un-done. It's only the PciIo handles that are
> > destroyed in software level.
> >
> 
> [JB] Yeah, not allowing stop to work on this isn't a big deal (and what we
> currently have implemented) but it was something we noticed a while ago is
> that we couldn't implement this even if we wanted to as there was no way to
> stop the host bridge driver.
> 
> > Thanks,
> > Ray
> >
> >
> > >
> > > -Jeff
> > >
> > >
> > > -----Original Message-----
> > > From: Ni, Ray <ray.ni@intel.com>
> > > Sent: Thursday, June 29, 2023 8:29 PM
> > > To: Jeff Brasen <jbrasen@nvidia.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>
> > > Subject: RE: [PATCH] MdeModulePkg/PciHostBridge: Add support for
> > > driver binding
> > >
> > > External email: Use caution opening links or attachments
> > >
> > >
> > > I failed to apply the patch in my local tree.
> > >
> > > It seems you invented a new EdkiiRootBridgeIo protocol and a certain
> > > proprietary driver would produce this protocol instance.
> > > Then the open source PciHostBridge driver starts on that.
> > >
> > > Then, why not implement your own PciHostBridgeLib and let it depends
> > > on some "AllRootBridgeIoInformationIsReady" protocol.
> > > So that the PciHostBridge driver could still call PciHostBridgeLib
> > > and all your implementation in this patch can be in that lib.
> > >
> > > Thanks,
> > > Ray
> > >
> > > > -----Original Message-----
> > > > From: Jeff Brasen <jbrasen@nvidia.com>
> > > > Sent: Friday, June 30, 2023 4:54 AM
> > > > To: devel@edk2.groups.io
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > > > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Ni,
> > > > Ray <ray.ni@intel.com>; Jeff Brasen <jbrasen@nvidia.com>
> > > > Subject: [PATCH] MdeModulePkg/PciHostBridge: Add support for
> > > > driver binding
> > > >
> > > > If the platform does not support any PCIe devices using the
> > > > library
> > > >
> > > > method allow devices to connect to host bridge via driver binding.
> > > >
> > > >
> > > >
> > > > Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
> > > >
> > > > ---
> > > >
> > > >  .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 649
> > > > ++++++++++++++----
> > > >
> > > >  .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   1 +
> > > >
> > > >  .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h  |  13 +
> > > >
> > > >  .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    |  24 +
> > > >
> > > >  MdeModulePkg/MdeModulePkg.dec                 |   4 +
> > > >
> > > >  5 files changed, 562 insertions(+), 129 deletions(-)
> > > >
> > > >
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > > >
> > > > index d573e532ba..506c6660ae 100644
> > > >
> > > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > > >
> > > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> > > >
> > > > @@ -422,167 +422,320 @@ IoMmuProtocolCallback (
> > > >
> > > >  }
> > > >
> > > >
> > > >
> > > >  /**
> > > >
> > > > +  PCI Root Bridge Memory setup.
> > > >
> > > >
> > > >
> > > > -  Entry point of this driver.
> > > >
> > > > +  @param  RootBridge            Root Bridge instance.
> > > >
> > > >
> > > >
> > > > -  @param ImageHandle  Image handle of this driver.
> > > >
> > > > -  @param SystemTable  Pointer to standard EFI system table.
> > > >
> > > > -
> > > >
> > > > -  @retval EFI_SUCCESS       Succeed.
> > > >
> > > > -  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO
> > protocol.
> > > >
> > > > +  @retval EFI_SUCCESS           Memory was setup correctly
> > > >
> > > > +  @retval others                Error in setup
> > > >
> > > >
> > > >
> > > >  **/
> > > >
> > > >  EFI_STATUS
> > > >
> > > >  EFIAPI
> > > >
> > > > -InitializePciHostBridge (
> > > >
> > > > -  IN EFI_HANDLE        ImageHandle,
> > > >
> > > > -  IN EFI_SYSTEM_TABLE  *SystemTable
> > > >
> > > > +PciRootBridgeMemorySetup (
> > > >
> > > > +  IN PCI_ROOT_BRIDGE  *RootBridge
> > > >
> > > >    )
> > > >
> > > >  {
> > > >
> > > >    EFI_STATUS                Status;
> > > >
> > > > -  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> > > >
> > > > -  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> > > >
> > > > -  PCI_ROOT_BRIDGE           *RootBridges;
> > > >
> > > > -  UINTN                     RootBridgeCount;
> > > >
> > > > -  UINTN                     Index;
> > > >
> > > > +  UINT64                    HostAddress;
> > > >
> > > >    PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> > > >
> > > >    UINTN                     MemApertureIndex;
> > > >
> > > > -  BOOLEAN                   ResourceAssigned;
> > > >
> > > > -  LIST_ENTRY                *Link;
> > > >
> > > > -  UINT64                    HostAddress;
> > > >
> > > >
> > > >
> > > > -  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> > > >
> > > > -  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> > > >
> > > > -    return EFI_UNSUPPORTED;
> > > >
> > > > -  }
> > > >
> > > > -
> > > >
> > > > -  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL,
> > > > (VOID **)&mCpuIo);
> > > >
> > > > -  ASSERT_EFI_ERROR (Status);
> > > >
> > > > -
> > > >
> > > > -  //
> > > >
> > > > -  // Most systems in the world including complex servers have
> > > > only one Host Bridge.
> > > >
> > > > -  //
> > > >
> > > > -  HostBridge = AllocateZeroPool (sizeof
> > > > (PCI_HOST_BRIDGE_INSTANCE));
> > > >
> > > > -  ASSERT (HostBridge != NULL);
> > > >
> > > > -
> > > >
> > > > -  HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> > > >
> > > > -  HostBridge->CanRestarted = TRUE;
> > > >
> > > > -  InitializeListHead (&HostBridge->RootBridges);
> > > >
> > > > -  ResourceAssigned = FALSE;
> > > >
> > > > -
> > > >
> > > > -  //
> > > >
> > > > -  // Create Root Bridge Device Handle in this Host Bridge
> > > >
> > > > -  //
> > > >
> > > > -  for (Index = 0; Index < RootBridgeCount; Index++) {
> > > >
> > > > +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> > > >
> > > >      //
> > > >
> > > > -    // Create Root Bridge Handle Instance
> > > >
> > > > +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > > >
> > > > +    // For GCD resource manipulation, we need to use host address.
> > > >
> > > >      //
> > > >
> > > > -    RootBridge = CreateRootBridge (&RootBridges[Index]);
> > > >
> > > > -    ASSERT (RootBridge != NULL);
> > > >
> > > > -    if (RootBridge == NULL) {
> > > >
> > > > -      continue;
> > > >
> > > > +    HostAddress = TO_HOST_ADDRESS (
> > > >
> > > > +                    RootBridge->Io.Base,
> > > >
> > > > +                    RootBridge->Io.Translation
> > > >
> > > > +                    );
> > > >
> > > > +
> > > >
> > > > +    Status = AddIoSpace (
> > > >
> > > > +               HostAddress,
> > > >
> > > > +               RootBridge->Io.Limit - RootBridge->Io.Base + 1
> > > >
> > > > +               );
> > > >
> > > > +    ASSERT_EFI_ERROR (Status);
> > > >
> > > > +    if (EFI_ERROR (Status)) {
> > > >
> > > > +      return Status;
> > > >
> > > >      }
> > > >
> > > >
> > > >
> > > > -    //
> > > >
> > > > -    // Make sure all root bridges share the same ResourceAssigned value.
> > > >
> > > > -    //
> > > >
> > > > -    if (Index == 0) {
> > > >
> > > > -      ResourceAssigned = RootBridges[Index].ResourceAssigned;
> > > >
> > > > -    } else {
> > > >
> > > > -      ASSERT (ResourceAssigned ==
> RootBridges[Index].ResourceAssigned);
> > > >
> > > > +    if (RootBridge->ResourceAssigned) {
> > > >
> > > > +      Status = gDS->AllocateIoSpace (
> > > >
> > > > +                      EfiGcdAllocateAddress,
> > > >
> > > > +                      EfiGcdIoTypeIo,
> > > >
> > > > +                      0,
> > > >
> > > > +                      RootBridge->Io.Limit - RootBridge->Io.Base
> > > > + + 1,
> > > >
> > > > +                      &HostAddress,
> > > >
> > > > +                      gImageHandle,
> > > >
> > > > +                      NULL
> > > >
> > > > +                      );
> > > >
> > > > +      ASSERT_EFI_ERROR (Status);
> > > >
> > > > +      if (EFI_ERROR (Status)) {
> > > >
> > > > +        return Status;
> > > >
> > > > +      }
> > > >
> > > >      }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Add all the Mem/PMem aperture to GCD
> > > >
> > > > +  // Mem/PMem shouldn't overlap with each other
> > > >
> > > > +  // Root bridge which needs to combine MEM and PMEM should only
> > > > + report
> > > >
> > > > +  // the MEM aperture in Mem
> > > >
> > > > +  //
> > > >
> > > > +  MemApertures[0] = &RootBridge->Mem;
> > > >
> > > > +  MemApertures[1] = &RootBridge->MemAbove4G;
> > > >
> > > > +  MemApertures[2] = &RootBridge->PMem;
> > > >
> > > > +  MemApertures[3] = &RootBridge->PMemAbove4G;
> > > >
> > > >
> > > >
> > > > -    if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
> > > >
> > > > +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > > > (MemApertures); MemApertureIndex++) {
> > > >
> > > > +    if (MemApertures[MemApertureIndex]->Base <=
> > > > MemApertures[MemApertureIndex]->Limit) {
> > > >
> > > >        //
> > > >
> > > >        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device
> address.
> > > >
> > > >        // For GCD resource manipulation, we need to use host address.
> > > >
> > > >        //
> > > >
> > > >        HostAddress = TO_HOST_ADDRESS (
> > > >
> > > > -                      RootBridges[Index].Io.Base,
> > > >
> > > > -                      RootBridges[Index].Io.Translation
> > > >
> > > > +                      MemApertures[MemApertureIndex]->Base,
> > > >
> > > > +                      MemApertures[MemApertureIndex]->Translation
> > > >
> > > >                        );
> > > >
> > > > -
> > > >
> > > > -      Status = AddIoSpace (
> > > >
> > > > +      Status = AddMemoryMappedIoSpace (
> > > >
> > > >                   HostAddress,
> > > >
> > > > -                 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
> > > >
> > > > +                 MemApertures[MemApertureIndex]->Limit -
> > > > MemApertures[MemApertureIndex]->Base + 1,
> > > >
> > > > +                 EFI_MEMORY_UC
> > > >
> > > >                   );
> > > >
> > > >        ASSERT_EFI_ERROR (Status);
> > > >
> > > > -      if (ResourceAssigned) {
> > > >
> > > > -        Status = gDS->AllocateIoSpace (
> > > >
> > > > +      if (EFI_ERROR (Status)) {
> > > >
> > > > +        return Status;
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      Status = gDS->SetMemorySpaceAttributes (
> > > >
> > > > +                      HostAddress,
> > > >
> > > > +                      MemApertures[MemApertureIndex]->Limit -
> > > > MemApertures[MemApertureIndex]->Base + 1,
> > > >
> > > > +                      EFI_MEMORY_UC
> > > >
> > > > +                      );
> > > >
> > > > +      if (EFI_ERROR (Status)) {
> > > >
> > > > +        DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> > > > EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      if (RootBridge->ResourceAssigned) {
> > > >
> > > > +        Status = gDS->AllocateMemorySpace (
> > > >
> > > >                          EfiGcdAllocateAddress,
> > > >
> > > > -                        EfiGcdIoTypeIo,
> > > >
> > > > +                        EfiGcdMemoryTypeMemoryMappedIo,
> > > >
> > > >                          0,
> > > >
> > > > -                        RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base +
> 1,
> > > >
> > > > +                        MemApertures[MemApertureIndex]->Limit -
> > > > MemApertures[MemApertureIndex]->Base + 1,
> > > >
> > > >                          &HostAddress,
> > > >
> > > >                          gImageHandle,
> > > >
> > > >                          NULL
> > > >
> > > >                          );
> > > >
> > > >          ASSERT_EFI_ERROR (Status);
> > > >
> > > > +        if (EFI_ERROR (Status)) {
> > > >
> > > > +          return Status;
> > > >
> > > > +        }
> > > >
> > > >        }
> > > >
> > > >      }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > >
> > > >
> > > > +/**
> > > >
> > > > +  PCI Root Bridge Memory free.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge            Root Bridge instance.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           Memory was setup correctly
> > > >
> > > > +  @retval others                Error in setup
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EFIAPI
> > > >
> > > > +PciRootBridgeMemoryFree (
> > > >
> > > > +  IN PCI_ROOT_BRIDGE  *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                Status;
> > > >
> > > > +  UINT64                    HostAddress;
> > > >
> > > > +  PCI_ROOT_BRIDGE_APERTURE  *MemApertures[4];
> > > >
> > > > +  UINTN                     MemApertureIndex;
> > > >
> > > > +
> > > >
> > > > +  if (RootBridge->Io.Base <= RootBridge->Io.Limit) {
> > > >
> > > >      //
> > > >
> > > > -    // Add all the Mem/PMem aperture to GCD
> > > >
> > > > -    // Mem/PMem shouldn't overlap with each other
> > > >
> > > > -    // Root bridge which needs to combine MEM and PMEM should only
> > report
> > > >
> > > > -    // the MEM aperture in Mem
> > > >
> > > > +    // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> > > >
> > > > +    // For GCD resource manipulation, we need to use host address.
> > > >
> > > >      //
> > > >
> > > > -    MemApertures[0] = &RootBridges[Index].Mem;
> > > >
> > > > -    MemApertures[1] = &RootBridges[Index].MemAbove4G;
> > > >
> > > > -    MemApertures[2] = &RootBridges[Index].PMem;
> > > >
> > > > -    MemApertures[3] = &RootBridges[Index].PMemAbove4G;
> > > >
> > > > -
> > > >
> > > > -    for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > > > (MemApertures); MemApertureIndex++) {
> > > >
> > > > -      if (MemApertures[MemApertureIndex]->Base <=
> > > > MemApertures[MemApertureIndex]->Limit) {
> > > >
> > > > -        //
> > > >
> > > > -        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device
> address.
> > > >
> > > > -        // For GCD resource manipulation, we need to use host address.
> > > >
> > > > -        //
> > > >
> > > > -        HostAddress = TO_HOST_ADDRESS (
> > > >
> > > > -                        MemApertures[MemApertureIndex]->Base,
> > > >
> > > > -                        MemApertures[MemApertureIndex]->Translation
> > > >
> > > > -                        );
> > > >
> > > > -        Status = AddMemoryMappedIoSpace (
> > > >
> > > > -                   HostAddress,
> > > >
> > > > -                   MemApertures[MemApertureIndex]->Limit -
> > > > MemApertures[MemApertureIndex]->Base + 1,
> > > >
> > > > -                   EFI_MEMORY_UC
> > > >
> > > > -                   );
> > > >
> > > > +    HostAddress = TO_HOST_ADDRESS (
> > > >
> > > > +                    RootBridge->Io.Base,
> > > >
> > > > +                    RootBridge->Io.Translation
> > > >
> > > > +                    );
> > > >
> > > > +
> > > >
> > > > +    if (RootBridge->ResourceAssigned) {
> > > >
> > > > +      Status = gDS->FreeIoSpace (HostAddress,
> > > > + RootBridge->Io.Limit
> > > > + -
> > > > + RootBridge-
> > > > >Io.Base + 1);
> > > >
> > > > +      ASSERT_EFI_ERROR (Status);
> > > >
> > > > +      if (EFI_ERROR (Status)) {
> > > >
> > > > +        return Status;
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Add all the Mem/PMem aperture to GCD
> > > >
> > > > +  // Mem/PMem shouldn't overlap with each other
> > > >
> > > > +  // Root bridge which needs to combine MEM and PMEM should only
> > > > + report
> > > >
> > > > +  // the MEM aperture in Mem
> > > >
> > > > +  //
> > > >
> > > > +  MemApertures[0] = &RootBridge->Mem;
> > > >
> > > > +  MemApertures[1] = &RootBridge->MemAbove4G;
> > > >
> > > > +  MemApertures[2] = &RootBridge->PMem;
> > > >
> > > > +  MemApertures[3] = &RootBridge->PMemAbove4G;
> > > >
> > > > +
> > > >
> > > > +  for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE
> > > > (MemApertures); MemApertureIndex++) {
> > > >
> > > > +    if (MemApertures[MemApertureIndex]->Base <=
> > > > MemApertures[MemApertureIndex]->Limit) {
> > > >
> > > > +      //
> > > >
> > > > +      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device
> address.
> > > >
> > > > +      // For GCD resource manipulation, we need to use host address.
> > > >
> > > > +      //
> > > >
> > > > +      HostAddress = TO_HOST_ADDRESS (
> > > >
> > > > +                      MemApertures[MemApertureIndex]->Base,
> > > >
> > > > +                      MemApertures[MemApertureIndex]->Translation
> > > >
> > > > +                      );
> > > >
> > > > +      if (RootBridge->ResourceAssigned) {
> > > >
> > > > +        Status = gDS->FreeMemorySpace (HostAddress,
> > > > + RootBridge->Io.Limit -
> > > > RootBridge->Io.Base + 1);
> > > >
> > > >          ASSERT_EFI_ERROR (Status);
> > > >
> > > > -        Status = gDS->SetMemorySpaceAttributes (
> > > >
> > > > -                        HostAddress,
> > > >
> > > > -                        MemApertures[MemApertureIndex]->Limit -
> > > > MemApertures[MemApertureIndex]->Base + 1,
> > > >
> > > > -                        EFI_MEMORY_UC
> > > >
> > > > -                        );
> > > >
> > > >          if (EFI_ERROR (Status)) {
> > > >
> > > > -          DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set
> > > > EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
> > > >
> > > > -        }
> > > >
> > > > -
> > > >
> > > > -        if (ResourceAssigned) {
> > > >
> > > > -          Status = gDS->AllocateMemorySpace (
> > > >
> > > > -                          EfiGcdAllocateAddress,
> > > >
> > > > -                          EfiGcdMemoryTypeMemoryMappedIo,
> > > >
> > > > -                          0,
> > > >
> > > > -                          MemApertures[MemApertureIndex]->Limit -
> > > > MemApertures[MemApertureIndex]->Base + 1,
> > > >
> > > > -                          &HostAddress,
> > > >
> > > > -                          gImageHandle,
> > > >
> > > > -                          NULL
> > > >
> > > > -                          );
> > > >
> > > > -          ASSERT_EFI_ERROR (Status);
> > > >
> > > > +          return Status;
> > > >
> > > >          }
> > > >
> > > >        }
> > > >
> > > >      }
> > > >
> > > > +  }
> > > >
> > > >
> > > >
> > > > -    //
> > > >
> > > > -    // Insert Root Bridge Handle Instance
> > > >
> > > > -    //
> > > >
> > > > -    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Test to see if this driver supports ControllerHandle. Any
> > > > + ControllerHandle
> > > >
> > > > +  than contains a gEdkiiPciHostBridgeProtocolGuid protocol can be
> > supported.
> > > >
> > > > +
> > > >
> > > > +  @param  This                Protocol instance pointer.
> > > >
> > > > +  @param  Controller          Handle of device to test.
> > > >
> > > > +  @param  RemainingDevicePath Optional parameter use to pick a
> > > > + specific child
> > > >
> > > > +                              device to start.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS         This driver supports this device.
> > > >
> > > > +  @retval EFI_ALREADY_STARTED This driver is already running on
> > > > + this
> > device.
> > > >
> > > > +  @retval other               This driver does not support this device.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EFIAPI
> > > >
> > > > +PciHostBrigeDriverBindingSupported (
> > > >
> > > > +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> > > >
> > > > +  IN EFI_HANDLE                   Controller,
> > > >
> > > > +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS       Status;
> > > >
> > > > +  PCI_ROOT_BRIDGE  *PciRootBridge;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Check if Pci Host Bridge protocol is installed by platform
> > > >
> > > > +  //
> > > >
> > > > +  Status = gBS->OpenProtocol (
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  &gEdkiiPciHostBridgeProtocolGuid,
> > > >
> > > > +                  (VOID **)&PciRootBridge,
> > > >
> > > > +                  This->DriverBindingHandle,
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > > >
> > > > +                  );
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    return Status;
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > >    //
> > > >
> > > > -  // When resources were assigned, it's not needed to expose
> > > >
> > > > -  // PciHostBridgeResourceAllocation protocol.
> > > >
> > > > +  // Close the protocol used to perform the supported test
> > > >
> > > > +  //
> > > >
> > > > +  gBS->CloseProtocol (
> > > >
> > > > +         Controller,
> > > >
> > > > +         &gEdkiiPciHostBridgeProtocolGuid,
> > > >
> > > > +         This->DriverBindingHandle,
> > > >
> > > > +         Controller
> > > >
> > > > +         );
> > > >
> > > > +
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Start this driver on ControllerHandle and enumerate Pci bus and
> > > > + start
> > > >
> > > > +  all device under PCI bus.
> > > >
> > > > +
> > > >
> > > > +  @param  This                 Protocol instance pointer.
> > > >
> > > > +  @param  Controller           Handle of device to bind driver to.
> > > >
> > > > +  @param  RemainingDevicePath  Optional parameter use to pick a
> > > > + specific child
> > > >
> > > > +                               device to start.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
> > > >
> > > > +  @retval EFI_ALREADY_STARTED  This driver is already running on
> > > > ControllerHandle.
> > > >
> > > > +  @retval other                This driver does not support this device.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EFIAPI
> > > >
> > > > +PciHostBrigeDriverBindingStart (
> > > >
> > > > +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> > > >
> > > > +  IN EFI_HANDLE                   Controller,
> > > >
> > > > +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                Status;
> > > >
> > > > +  PCI_ROOT_BRIDGE           *PciRootBridge;
> > > >
> > > > +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> > > >
> > > > +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> > > >
> > > > +  BOOLEAN                   MemorySetupDone;
> > > >
> > > > +
> > > >
> > > > +  MemorySetupDone = FALSE;
> > > >
> > > > +  //
> > > >
> > > > +  // Check if Pci Host Bridge protocol is installed by platform
> > > >
> > > >    //
> > > >
> > > > -  if (!ResourceAssigned) {
> > > >
> > > > +  Status = gBS->OpenProtocol (
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  &gEdkiiPciHostBridgeProtocolGuid,
> > > >
> > > > +                  (VOID **)&PciRootBridge,
> > > >
> > > > +                  This->DriverBindingHandle,
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > > >
> > > > +                  );
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    return Status;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  RootBridge = CreateRootBridge (PciRootBridge);
> > > >
> > > > +  ASSERT (RootBridge != NULL);
> > > >
> > > > +  if (RootBridge == NULL) {
> > > >
> > > > +    Status = EFI_DEVICE_ERROR;
> > > >
> > > > +    goto ErrorExit;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  Status = PciRootBridgeMemorySetup (PciRootBridge);
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    goto ErrorExit;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  MemorySetupDone = TRUE;
> > > >
> > > > +
> > > >
> > > > +  if (!PciRootBridge->ResourceAssigned) {
> > > >
> > > > +    // Create host bridge
> > > >
> > > > +    HostBridge = AllocateZeroPool (sizeof
> > > > + (PCI_HOST_BRIDGE_INSTANCE));
> > > >
> > > > +    ASSERT (HostBridge != NULL);
> > > >
> > > > +    if (HostBridge == NULL) {
> > > >
> > > > +      Status = EFI_OUT_OF_RESOURCES;
> > > >
> > > > +      goto ErrorExit;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    HostBridge->Handle       = 0;
> > > >
> > > > +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> > > >
> > > > +    HostBridge->CanRestarted = TRUE;
> > > >
> > > > +    InitializeListHead (&HostBridge->RootBridges);
> > > >
> > > > +
> > > >
> > > >      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> > > >
> > > >      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> > > >
> > > >      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> > > >
> > > > @@ -599,28 +752,266 @@ InitializePciHostBridge (
> > > >
> > > >                      NULL
> > > >
> > > >                      );
> > > >
> > > >      ASSERT_EFI_ERROR (Status);
> > > >
> > > > -  }
> > > >
> > > > +    if (EFI_ERROR (Status)) {
> > > >
> > > > +      goto ErrorExit;
> > > >
> > > > +    }
> > > >
> > > >
> > > >
> > > > -  for (Link = GetFirstNode (&HostBridge->RootBridges)
> > > >
> > > > -       ; !IsNull (&HostBridge->RootBridges, Link)
> > > >
> > > > -       ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> > > >
> > > > -       )
> > > >
> > > > -  {
> > > >
> > > > -    RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> > > >
> > > > +    //
> > > >
> > > > +    // Insert Root Bridge Handle Instance
> > > >
> > > > +    //
> > > >
> > > > +    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
> > > >
> > > >      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> > > >
> > > > +  } else {
> > > >
> > > > +    RootBridge->RootBridgeIo.ParentHandle = 0;
> > > >
> > > > +  }
> > > >
> > > >
> > > >
> > > > -    Status = gBS->InstallMultipleProtocolInterfaces (
> > > >
> > > > -                    &RootBridge->Handle,
> > > >
> > > > -                    &gEfiDevicePathProtocolGuid,
> > > >
> > > > -                    RootBridge->DevicePath,
> > > >
> > > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > > >
> > > > -                    &RootBridge->RootBridgeIo,
> > > >
> > > > -                    NULL
> > > >
> > > > -                    );
> > > >
> > > > -    ASSERT_EFI_ERROR (Status);
> > > >
> > > > +  RootBridge->Handle = Controller;
> > > >
> > > > +  Status             = gBS->InstallMultipleProtocolInterfaces (
> > > >
> > > > +                              &RootBridge->Handle,
> > > >
> > > > +                              &gEfiPciRootBridgeIoProtocolGuid,
> > > >
> > > > +                              &RootBridge->RootBridgeIo,
> > > >
> > > > +                              NULL
> > > >
> > > > +                              );
> > > >
> > > > +
> > > >
> > > > +ErrorExit:
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    if (MemorySetupDone) {
> > > >
> > > > +      PciRootBridgeMemoryFree (PciRootBridge);
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    if (RootBridge != NULL) {
> > > >
> > > > +      if (!IsListEmpty (&RootBridge->Link)) {
> > > >
> > > > +        RemoveEntryList (&RootBridge->Link);
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      FreeRootBridge (RootBridge);
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    gBS->CloseProtocol (
> > > >
> > > > +           Controller,
> > > >
> > > > +           &gEdkiiPciHostBridgeProtocolGuid,
> > > >
> > > > +           This->DriverBindingHandle,
> > > >
> > > > +           Controller
> > > >
> > > > +           );
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > > -  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Stop this driver on ControllerHandle. Support stopping any
> > > > + child handles
> > > >
> > > > +  created by this driver.
> > > >
> > > > +
> > > >
> > > > +  @param  This              Protocol instance pointer.
> > > >
> > > > +  @param  Controller        Handle of device to stop driver on.
> > > >
> > > > +  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer.
> > > > + If
> > > > number of
> > > >
> > > > +                            children is zero stop the entire bus driver.
> > > >
> > > > +  @param  ChildHandleBuffer List of Child Handles to Stop.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
> > > >
> > > > +  @retval other             This driver was not removed from this device.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EFIAPI
> > > >
> > > > +PciHostBrigeDriverBindingStop (
> > > >
> > > > +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
> > > >
> > > > +  IN  EFI_HANDLE                   Controller,
> > > >
> > > > +  IN  UINTN                        NumberOfChildren,
> > > >
> > > > +  IN  EFI_HANDLE                   *ChildHandleBuffer
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                       Status;
> > > >
> > > > +  PCI_ROOT_BRIDGE                  *PciRootBridge;
> > > >
> > > > +  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;
> > > >
> > > > +  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;
> > > >
> > > > +
> > > >
> > > > +  Status = gBS->HandleProtocol (
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  &gEfiPciRootBridgeIoProtocolGuid,
> > > >
> > > > +                  (VOID **)&RootBridgeIo
> > > >
> > > > +                  );
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    return Status;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  RootBridge = ROOT_BRIDGE_FROM_THIS (RootBridgeIo);
> > > >
> > > > +
> > > >
> > > > +  Status = gBS->HandleProtocol (
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  &gEdkiiPciHostBridgeProtocolGuid,
> > > >
> > > > +                  (VOID **)&PciRootBridge
> > > >
> > > > +                  );
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    return Status;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  Status = gBS->UninstallMultipleProtocolInterfaces (
> > > >
> > > > +                  Controller,
> > > >
> > > > +                  &gEfiPciRootBridgeIoProtocolGuid,
> > > >
> > > > +                  (VOID **)&PciRootBridge
> > > >
> > > > +                  );
> > > >
> > > > +  if (EFI_ERROR (Status)) {
> > > >
> > > > +    return Status;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (!IsListEmpty (&RootBridge->Link)) {
> > > >
> > > > +    RemoveEntryList (&RootBridge->Link);
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  PciRootBridgeMemoryFree (PciRootBridge);
> > > >
> > > > +
> > > >
> > > > +  FreeRootBridge (RootBridge);
> > > >
> > > > +  gBS->CloseProtocol (
> > > >
> > > > +         Controller,
> > > >
> > > > +         &gEdkiiPciHostBridgeProtocolGuid,
> > > >
> > > > +         This->DriverBindingHandle,
> > > >
> > > > +         Controller
> > > >
> > > > +         );
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// PCI Bus Driver Global Variables
> > > >
> > > > +//
> > > >
> > > > +EFI_DRIVER_BINDING_PROTOCOL  gPciHostBrigeDriverBinding = {
> > > >
> > > > +  PciHostBrigeDriverBindingSupported,
> > > >
> > > > +  PciHostBrigeDriverBindingStart,
> > > >
> > > > +  PciHostBrigeDriverBindingStop,
> > > >
> > > > +  0xa,
> > > >
> > > > +  NULL,
> > > >
> > > > +  NULL
> > > >
> > > > +};
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +
> > > >
> > > > +  Entry point of this driver.
> > > >
> > > > +
> > > >
> > > > +  @param ImageHandle  Image handle of this driver.
> > > >
> > > > +  @param SystemTable  Pointer to standard EFI system table.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS       Succeed.
> > > >
> > > > +  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO
> > protocol.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EFIAPI
> > > >
> > > > +InitializePciHostBridge (
> > > >
> > > > +  IN EFI_HANDLE        ImageHandle,
> > > >
> > > > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                Status;
> > > >
> > > > +  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
> > > >
> > > > +  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
> > > >
> > > > +  PCI_ROOT_BRIDGE           *RootBridges;
> > > >
> > > > +  UINTN                     RootBridgeCount;
> > > >
> > > > +  UINTN                     Index;
> > > >
> > > > +  BOOLEAN                   ResourceAssigned;
> > > >
> > > > +  LIST_ENTRY                *Link;
> > > >
> > > > +
> > > >
> > > > +  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL,
> > > > + (VOID
> > > > **)&mCpuIo);
> > > >
> > > > +  ASSERT_EFI_ERROR (Status);
> > > >
> > > > +
> > > >
> > > > +  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> > > >
> > > > +  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> > > >
> > > > +    // Register for binding protocol if library enumeration is
> > > > + not used
> > > >
> > > > +    Status = EfiLibInstallDriverBinding (
> > > >
> > > > +               ImageHandle,
> > > >
> > > > +               SystemTable,
> > > >
> > > > +               &gPciHostBrigeDriverBinding,
> > > >
> > > > +               ImageHandle
> > > >
> > > > +               );
> > > >
> > > > +    ASSERT_EFI_ERROR (Status);
> > > >
> > > > +  } else {
> > > >
> > > > +    //
> > > >
> > > > +    // Most systems in the world including complex servers have
> > > > + only one Host
> > > > Bridge.
> > > >
> > > > +    //
> > > >
> > > > +    HostBridge = AllocateZeroPool (sizeof
> > > > + (PCI_HOST_BRIDGE_INSTANCE));
> > > >
> > > > +    ASSERT (HostBridge != NULL);
> > > >
> > > > +
> > > >
> > > > +    HostBridge->Signature    = PCI_HOST_BRIDGE_SIGNATURE;
> > > >
> > > > +    HostBridge->CanRestarted = TRUE;
> > > >
> > > > +    InitializeListHead (&HostBridge->RootBridges);
> > > >
> > > > +    ResourceAssigned = FALSE;
> > > >
> > > > +
> > > >
> > > > +    //
> > > >
> > > > +    // Create Root Bridge Device Handle in this Host Bridge
> > > >
> > > > +    //
> > > >
> > > > +    for (Index = 0; Index < RootBridgeCount; Index++) {
> > > >
> > > > +      //
> > > >
> > > > +      // Create Root Bridge Handle Instance
> > > >
> > > > +      //
> > > >
> > > > +      RootBridge = CreateRootBridge (&RootBridges[Index]);
> > > >
> > > > +      ASSERT (RootBridge != NULL);
> > > >
> > > > +      if (RootBridge == NULL) {
> > > >
> > > > +        continue;
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      //
> > > >
> > > > +      // Make sure all root bridges share the same ResourceAssigned value.
> > > >
> > > > +      //
> > > >
> > > > +      if (Index == 0) {
> > > >
> > > > +        ResourceAssigned = RootBridges[Index].ResourceAssigned;
> > > >
> > > > +      } else {
> > > >
> > > > +        ASSERT (ResourceAssigned ==
> > > > + RootBridges[Index].ResourceAssigned);
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      Status = PciRootBridgeMemorySetup (&RootBridges[Index]);
> > > >
> > > > +      if (EFI_ERROR (Status)) {
> > > >
> > > > +        continue;
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      //
> > > >
> > > > +      // Insert Root Bridge Handle Instance
> > > >
> > > > +      //
> > > >
> > > > +      InsertTailList (&HostBridge->RootBridges,
> > > > + &RootBridge->Link);
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    //
> > > >
> > > > +    // When resources were assigned, it's not needed to expose
> > > >
> > > > +    // PciHostBridgeResourceAllocation protocol.
> > > >
> > > > +    //
> > > >
> > > > +    if (!ResourceAssigned) {
> > > >
> > > > +      HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
> > > >
> > > > +      HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
> > > >
> > > > +      HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
> > > >
> > > > +      HostBridge->ResAlloc.StartBusEnumeration  =
> > > > + StartBusEnumeration;
> > > >
> > > > +      HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
> > > >
> > > > +      HostBridge->ResAlloc.SubmitResources      = SubmitResources;
> > > >
> > > > +      HostBridge->ResAlloc.GetProposedResources =
> > > > + GetProposedResources;
> > > >
> > > > +      HostBridge->ResAlloc.PreprocessController =
> > > > + PreprocessController;
> > > >
> > > > +
> > > >
> > > > +      Status = gBS->InstallMultipleProtocolInterfaces (
> > > >
> > > > +                      &HostBridge->Handle,
> > > >
> > > > +
> > > > + &gEfiPciHostBridgeResourceAllocationProtocolGuid,
> > > >
> > > > +                      &HostBridge->ResAlloc,
> > > >
> > > > +                      NULL
> > > >
> > > > +                      );
> > > >
> > > > +      ASSERT_EFI_ERROR (Status);
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    for (Link = GetFirstNode (&HostBridge->RootBridges)
> > > >
> > > > +         ; !IsNull (&HostBridge->RootBridges, Link)
> > > >
> > > > +         ; Link = GetNextNode (&HostBridge->RootBridges, Link)
> > > >
> > > > +         )
> > > >
> > > > +    {
> > > >
> > > > +      RootBridge                            = ROOT_BRIDGE_FROM_LINK (Link);
> > > >
> > > > +      RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
> > > >
> > > > +
> > > >
> > > > +      Status = gBS->InstallMultipleProtocolInterfaces (
> > > >
> > > > +                      &RootBridge->Handle,
> > > >
> > > > +                      &gEfiDevicePathProtocolGuid,
> > > >
> > > > +                      RootBridge->DevicePath,
> > > >
> > > > +                      &gEfiPciRootBridgeIoProtocolGuid,
> > > >
> > > > +                      &RootBridge->RootBridgeIo,
> > > >
> > > > +                      NULL
> > > >
> > > > +                      );
> > > >
> > > > +      ASSERT_EFI_ERROR (Status);
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
> > > >
> > > > +  }
> > > >
> > > >
> > > >
> > > >    if (!EFI_ERROR (Status)) {
> > > >
> > > >      mIoMmuEvent = EfiCreateProtocolNotifyEvent (
> > > >
> > > > diff --git
> > > > a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > > >
> > > > index 9c24cacc30..ee4740b14f 100644
> > > >
> > > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > > >
> > > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > > >
> > > > @@ -46,6 +46,7 @@
> > > >
> > > >    gEfiPciRootBridgeIoProtocolGuid                 ## BY_START
> > > >
> > > >    gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
> > > >
> > > >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> > > >
> > > > +  gEdkiiPciHostBridgeProtocolGuid                 ## SOMETIMES_CONSUMES
> > > >
> > > >
> > > >
> > > >  [Depex]
> > > >
> > > >    gEfiCpuIo2ProtocolGuid AND
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > > >
> > > > index 10a6200719..7923c4677b 100644
> > > >
> > > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > > >
> > > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h
> > > >
> > > > @@ -93,6 +93,19 @@ CreateRootBridge (
> > > >
> > > >    IN PCI_ROOT_BRIDGE  *Bridge
> > > >
> > > >    );
> > > >
> > > >
> > > >
> > > > +/**
> > > >
> > > > +  Free the Pci Root Bridge instance.
> > > >
> > > > +
> > > >
> > > > +  @param Bridge            The root bridge instance.
> > > >
> > > > +
> > > >
> > > > +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> > > >
> > > > +          or NULL if creation fails.
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +FreeRootBridge (
> > > >
> > > > +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > >  //
> > > >
> > > >  // Protocol Member Function Prototypes
> > > >
> > > >  //
> > > >
> > > > diff --git
> > > > a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > > > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > > >
> > > > index 157a0ada80..f0eb465a9d 100644
> > > >
> > > > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > > >
> > > > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> > > >
> > > > @@ -286,6 +286,30 @@ CreateRootBridge (
> > > >
> > > >    return RootBridge;
> > > >
> > > >  }
> > > >
> > > >
> > > >
> > > > +/**
> > > >
> > > > +  Free the Pci Root Bridge instance.
> > > >
> > > > +
> > > >
> > > > +  @param Bridge            The root bridge instance.
> > > >
> > > > +
> > > >
> > > > +  @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
> > > >
> > > > +          or NULL if creation fails.
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +FreeRootBridge (
> > > >
> > > > +  IN PCI_ROOT_BRIDGE_INSTANCE  *Bridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  if (Bridge->ConfigBuffer != NULL) {
> > > >
> > > > +    FreePool (Bridge->ConfigBuffer);
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (Bridge->DevicePath != NULL) {
> > > >
> > > > +    FreePool (Bridge->DevicePath);
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  FreePool (Bridge);
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > >  /**
> > > >
> > > >    Check parameters for IO,MMIO,PCI read/write services of PCI
> > > > Root
> > Bridge IO.
> > > >
> > > >
> > > >
> > > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > > b/MdeModulePkg/MdeModulePkg.dec
> > > >
> > > > index d65dae18aa..24700fa797 100644
> > > >
> > > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > >
> > > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > >
> > > > @@ -692,6 +692,10 @@
> > > >
> > > >    ## Include/Protocol/VariablePolicy.h
> > > >
> > > >    gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6,
> > > > 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
> > > >
> > > >
> > > >
> > > > +  ## Include/Library/PciHostBridgeLib.h
> > > >
> > > > +  # Exposes a PCI_HOST_BRIDGE structure for driver binding usage
> > > >
> > > > +  gEdkiiPciHostBridgeProtocolGuid = { 0xaff2b72d, 0x202e, 0x40e3,
> > > > + { 0x82, 0xd5,
> > > > 0x9f, 0x6f, 0x61, 0xaf, 0x2a, 0x0b } }
> > > >
> > > > +
> > > >
> > > >  [PcdsFeatureFlag]
> > > >
> > > >    ## Indicates if the platform can support update capsule across
> > > > a system reset.<BR><BR>
> > > >
> > > >    #   TRUE  - Supports update capsule across a system reset.<BR>
> > > >
> > > > --
> > > >
> > > > 2.25.1
> > > >
> > > >



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106821): https://edk2.groups.io/g/devel/message/106821
Mute This Topic: https://groups.io/mt/99859311/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-