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

Reply via email to