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 <jbra...@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/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-



Reply via email to