On Thu, 2016-02-18 at 10:33 +0800, Ruiyu Ni wrote: > Some platform doesn't use CPU(HOST)/Device 1:1 mapping for PCI Bus. > But PCI IO doesn't have interface to tell caller (device driver) > whether the address returned by GetBarAttributes() is HOST address > or device address. > UEFI Spec 2.6 addresses this issue by clarifying the address returned > is HOST address and caller can use AddrTranslationOffset to calculate > the device address.
Hi ! I had implemented that a bit differently mostly for code clarity (see below pasted from github) Ie, make it a sub function. Otherwise I think the principle is ok. Note that I haven't been able to work on my EDK2 port for a while now due to other commitments. I will eventually get back to it and test your patch. You can browse my monster-patch on github, I need to split/clean it into a proper patch series, it also contains some updates of a couple of drivers to actually use that offset properly https://github.com/ozbenh/edk2/commits/master + Finds the root bridge resource corresponding to the BAR whose address + space descritpor is passes as an argument and copy the translation offset + over from it into the BAR descriptor + + @param RootBridge A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. + @param BarAddressSpace A pointer to the ACPI 2.0 resource descriptors that describe the current + configuration of this BAR of the PCI controller that is to be updated. + + @retval EFI_SUCCESS The descriptor was successfully updated. + @retval EFI_UNSUPPORTED No resource in the root bridge matches the BAR region + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate + Resources. + +**/ +STATIC +EFI_STATUS +PciBarUpdateTranslationOffset( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridge, + IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarAddressSpace) +{ + EFI_STATUS Status; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *RootDescriptors; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; + UINT8 *Temp; + + Status = RootBridge->Configuration (RootBridge, (VOID **) &RootDescriptors); + if (EFI_ERROR (Status)) { + return Status; + } + + Temp = (UINT8 *) RootDescriptors; + while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { + Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; + + // + // Do we have the right type of descriptor ? + // + if (Desc->ResType == BarAddressSpace->ResType) { + // + // Check if the BAR base fits + // + if (BarAddressSpace->AddrRangeMin >= Desc->AddrRangeMin && + BarAddressSpace->AddrRangeMin < (Desc->AddrRangeMin + Desc->AddrLen)) { + // + // Found it, update offset and return + // + BarAddressSpace->AddrTranslationOffset = Desc->AddrTranslationOffset; + return EFI_SUCCESS; + } + } + Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + } + return EFI_UNSUPPORTED; +} + +/** Gets the attributes that this PCI controller supports setting on a BAR using SetBarAttributes(), and retrieves the list of resource descriptors for a BAR. @@ -1778,6 +1834,7 @@ PciIoGetBarAttributes ( PCI_IO_DEVICE *PciIoDevice; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace; EFI_ACPI_END_TAG_DESCRIPTOR *End; + EFI_STATUS Status; PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); @@ -1878,6 +1935,15 @@ PciIoGetBarAttributes ( } // + // Update the AddrTranslationOffset field + // + Status = PciBarUpdateTranslationOffset(PciIoDevice->PciRootBridgeIo, AddressSpace); + if (EFI_ERROR (Status)) { + FreePool(AddressSpace); + return Status; + } + + // // put the checksum // End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1); View > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ruiyu Ni <[email protected]> > Cc: Benjamin Herrenschmidt <[email protected]> > Cc: Andrew Fish <[email protected]> > Cc: Jeff Fan <[email protected]> > --- > MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 37 > ++++++++++++++++++++++++++++++++++ > 1 file changed, 37 insertions(+) > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c > index 50ed866..5cee8ca 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c > @@ -1774,8 +1774,10 @@ PciIoGetBarAttributes ( > OUT VOID **Resources OPTIONAL > ) > { > + EFI_STATUS Status; > PCI_IO_DEVICE *PciIoDevice; > EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; > EFI_ACPI_END_TAG_DESCRIPTOR *End; > > PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > @@ -1863,6 +1865,41 @@ PciIoGetBarAttributes ( > End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + > 1); > End->Desc = ACPI_END_TAG_DESCRIPTOR; > End->Checksum = 0; > + > + // > + // Get the Address Translation Offset > + // > + if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { > + Status = PciIoDevice->PciRootBridgeIo->Configuration ( > + PciIoDevice- > > PciRootBridgeIo, > + (VOID **) > &Configuration > + ); > + if (!EFI_ERROR (Status)) { > + while (Configuration->Desc == Descriptor->Desc) { > + if ((Configuration->ResType == Descriptor->ResType) && > + (Configuration->AddrRangeMin <= Descriptor- > > AddrRangeMin) && > + (Configuration->AddrRangeMin + Configuration->AddrLen > > = Descriptor->AddrRangeMin + Descriptor->AddrLen) > + ) { > + Descriptor->AddrTranslationOffset = Configuration- > > AddrTranslationOffset; > + break; > + } > + Configuration++; > + } > + > + // > + // The resource occupied by BAR should be in the range > reported by RootBridge. > + // > + ASSERT (Configuration->Desc == Descriptor->Desc); > + if (Configuration->Desc != Descriptor->Desc) { > + Status = EFI_UNSUPPORTED; > + } > + } > + > + if (EFI_ERROR (Status)) { > + FreePool (Descriptor); > + return Status; > + } > + } > } > > return EFI_SUCCESS; _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

