From: "Ni, Ray" <ray.ni@intel.com>
To: Jeff Brasen <jbrasen@nvidia.com>,
"devel@edk2.groups.io" <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
Date: Fri, 30 Jun 2023 02:29:17 +0000 [thread overview]
Message-ID: <MN6PR11MB824436DF4C61D32B5CF1EB508C2AA@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <6add8a5bbb40cd1602acc09345496043ac47fc3e.1688071965.git.jbrasen@nvidia.com>
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
>
>
next prev parent reply other threads:[~2023-06-30 2:29 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-29 20:53 [PATCH] MdeModulePkg/PciHostBridge: Add support for driver binding Jeff Brasen
2023-06-30 2:29 ` Ni, Ray [this message]
2023-06-30 3:21 ` Jeff Brasen
2023-06-30 3:59 ` Ni, Ray
2023-06-30 15:57 ` Jeff Brasen
2023-07-11 21:49 ` Jeff Brasen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN6PR11MB824436DF4C61D32B5CF1EB508C2AA@MN6PR11MB8244.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox