Not sure if this has been merged yet, but if not, try to add it as a
pull request on the github repo, then it'll get more visibility.

-- Robin

On 2020-05-26 16:17, Pankaj Bansal wrote:
> 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
> 
_______________________________________________
ipxe-devel mailing list
ipxe-devel@lists.ipxe.org
https://lists.ipxe.org/mailman/listinfo/ipxe-devel

Reply via email to