Hi Michael et. al Gentle ping.
Regards, Pankaj Bansal > -----Original Message----- > From: Pankaj Bansal (OSS) > Sent: Tuesday, May 12, 2020 6:29 PM > To: Michael Brown <mc...@ipxe.org> > Cc: ipxe-devel@lists.ipxe.org > Subject: [PATCH] [efi] implement api to convert pci address to host address > > From: Pankaj Bansal <pankaj.ban...@nxp.com> > > The PCI device address may not be same as host address (CPU view address) > To read/write directly to PCI device's BARs (without using > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Mem.Read() and > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Mem.Write()) we need to convert PCI > device address to host address. > > The UEFI specifications 2.7 provide a method to translate the PCI device > address to host address and vice versa. > > device address = host address + translation offset > > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Configuration() method can provide us > with > the translation offset and host address range. > > Using this we can convert the PCI device address to host address. > > Signed-off-by: Pankaj Bansal <pankaj.ban...@nxp.com> > --- > src/include/ipxe/pci_io.h | 10 ++++ > src/interface/efi/efi_pci.c | 60 ++++++++++++++++++++ > 2 files changed, 70 insertions(+) > > diff --git a/src/include/ipxe/pci_io.h b/src/include/ipxe/pci_io.h > index 10e69763..5806390d 100644 > --- a/src/include/ipxe/pci_io.h > +++ b/src/include/ipxe/pci_io.h > @@ -122,4 +122,14 @@ int pci_write_config_word ( struct pci_device *pci, > unsigned int where, > int pci_write_config_dword ( struct pci_device *pci, unsigned int where, > uint32_t value ); > > +/** > + * retrieve Host Address corresponding to pci bus address > + * > + * @v pci PCI device > + * @v bus_addr PCI Bus address > + * @v len Length of region > + * @ret io_addr Host address > + */ > +uint64_t pci_ioremap ( struct pci_device *pci, uint64_t bus_addr, size_t len > ); > + > #endif /* _IPXE_PCI_IO_H */ > diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c > index c1f451c9..b688210e 100644 > --- a/src/interface/efi/efi_pci.c > +++ b/src/interface/efi/efi_pci.c > @@ -215,6 +215,66 @@ int efipci_write ( struct pci_device *pci, unsigned long > location, > return rc; > } > > +/** > + * retrieve Host Address corresponding to pci bus address > + * > + * @v pci PCI device > + * @v bus_addr PCI Bus address > + * @v len Length of region > + * @ret io_addr Host address > + */ > +static uint64_t efi_pci_ioremap ( struct pci_device *pci, uint64_t bus_addr, > + size_t len ) { > + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *config; > + EFI_HANDLE handle; > + EFI_STATUS efirc; > + uint64_t bus_addr_start; > + int rc; > + > + /* Identify root bridge */ > + if ( ( rc = efipci_root ( pci, &handle, &root ) ) != 0 ) > + goto err_root; > + > + /* Retrieves the current resource settings of this PCI root bridge */ > + efirc = root->Configuration ( root, (void **) &config); > + if (efirc != 0) { > + rc = -EEFI ( efirc ); > + DBGC ( pci, "EFIPCI " PCI_FMT "Retrieval of current resource " > + "settings of PCI root bridge failed: %s\n", > + PCI_ARGS ( pci ), strerror ( rc ) ); > + goto err_configuration; > + } > + > + /* According to UEFI 2.7, > + * EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration() > + * returns host address instead of device address, > + * while AddrTranslationOffset is not zero, and > + * device address = host address + AddrTranslationOffset, so > + * we convert host address to device address for range compare. > + */ > + while ( config->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR ) { > + bus_addr_start = config->AddrRangeMin + > + config->AddrTranslationOffset; > + if ( ( config->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM ) > && > + ( bus_addr_start <= bus_addr ) && > + ( bus_addr_start + config->AddrLen >= bus_addr + len ) ) { > + return ( bus_addr - config->AddrTranslationOffset ); > + } > + config++; > + } > + > + return bus_addr; > + > +err_configuration: > + bs->CloseProtocol ( handle, &efi_pci_root_bridge_io_protocol_guid, > + efi_image_handle, handle ); > +err_root: > + return rc; > +} > + > +PROVIDE_PCIAPI (efi, pci_ioremap, efi_pci_ioremap); > PROVIDE_PCIAPI_INLINE ( efi, pci_num_bus ); > PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte ); > PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word ); > -- > 2.17.1 _______________________________________________ ipxe-devel mailing list ipxe-devel@lists.ipxe.org https://lists.ipxe.org/mailman/listinfo/ipxe-devel