[efi] Use address offset as reported by EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL

Retrieve the address windows and translation offsets for the
appropriate PCI root bridge and use them to adjust the PCI BAR address
prior to calling ioremap().

Originally-implemented-by: Pankaj Bansal <pankaj.bansal@nxp.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2020-09-24 21:41:35 +01:00
parent eecb75ba48
commit 27e886c67b
3 changed files with 206 additions and 14 deletions

View File

@@ -19,6 +19,138 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/api.h>
#include <config/general.h>
/** An ACPI small resource descriptor header */
struct acpi_small_resource {
/** Tag byte */
uint8_t tag;
} __attribute__ (( packed ));
/** ACPI small resource length mask */
#define ACPI_SMALL_LEN_MASK 0x03
/** An ACPI end resource descriptor */
#define ACPI_END_RESOURCE 0x78
/** An ACPI end resource descriptor */
struct acpi_end_resource {
/** Header */
struct acpi_small_resource hdr;
/** Checksum */
uint8_t checksum;
} __attribute__ (( packed ));
/** An ACPI large resource descriptor header */
struct acpi_large_resource {
/** Tag byte */
uint8_t tag;
/** Length of data items */
uint16_t len;
} __attribute__ (( packed ));
/** ACPI large resource flag */
#define ACPI_LARGE 0x80
/** An ACPI QWORD address space resource descriptor */
#define ACPI_QWORD_ADDRESS_SPACE_RESOURCE 0x8a
/** An ACPI QWORD address space resource descriptor */
struct acpi_qword_address_space_resource {
/** Header */
struct acpi_large_resource hdr;
/** Resource type */
uint8_t type;
/** General flags */
uint8_t general;
/** Type-specific flags */
uint8_t specific;
/** Granularity */
uint64_t granularity;
/** Minimum address */
uint64_t min;
/** Maximum address */
uint64_t max;
/** Translation offset */
uint64_t offset;
/** Length */
uint64_t len;
} __attribute__ (( packed ));
/** A memory address space type */
#define ACPI_ADDRESS_TYPE_MEM 0x00
/** An ACPI resource descriptor */
union acpi_resource {
/** Tag byte */
uint8_t tag;
/** Small resource descriptor */
struct acpi_small_resource small;
/** End resource descriptor */
struct acpi_end_resource end;
/** Large resource descriptor */
struct acpi_large_resource large;
/** QWORD address space resource descriptor */
struct acpi_qword_address_space_resource qword;
};
/**
* Get ACPI resource tag
*
* @v res ACPI resource descriptor
* @ret tag Resource tag
*/
static inline unsigned int acpi_resource_tag ( union acpi_resource *res ) {
return ( ( res->tag & ACPI_LARGE ) ?
res->tag : ( res->tag & ~ACPI_SMALL_LEN_MASK ) );
}
/**
* Get length of ACPI small resource descriptor
*
* @v res Small resource descriptor
* @ret len Length of descriptor
*/
static inline size_t acpi_small_len ( struct acpi_small_resource *res ) {
return ( sizeof ( *res ) + ( res->tag & ACPI_SMALL_LEN_MASK ) );
}
/**
* Get length of ACPI large resource descriptor
*
* @v res Large resource descriptor
* @ret len Length of descriptor
*/
static inline size_t acpi_large_len ( struct acpi_large_resource *res ) {
return ( sizeof ( *res ) + le16_to_cpu ( res->len ) );
}
/**
* Get length of ACPI resource descriptor
*
* @v res ACPI resource descriptor
* @ret len Length of descriptor
*/
static inline size_t acpi_resource_len ( union acpi_resource *res ) {
return ( ( res->tag & ACPI_LARGE ) ?
acpi_large_len ( &res->large ) :
acpi_small_len ( &res->small ) );
}
/**
* Get next ACPI resource descriptor
*
* @v res ACPI resource descriptor
* @ret next Next ACPI resource descriptor
*/
static inline union acpi_resource *
acpi_resource_next ( union acpi_resource *res ) {
return ( ( ( void * ) res ) + acpi_resource_len ( res ) );
}
/**
* An ACPI description header
*

View File

@@ -148,17 +148,4 @@ PCIAPI_INLINE ( efi, pci_write_config_dword ) ( struct pci_device *pci,
value );
}
/**
* Map PCI bus address as an I/O address
*
* @v bus_addr PCI bus address
* @v len Length of region
* @ret io_addr I/O address, or NULL on error
*/
static inline __always_inline void *
PCIAPI_INLINE ( efi, pci_ioremap ) ( struct pci_device *pci __unused,
unsigned long bus_addr, size_t len ) {
return ioremap ( bus_addr, len );
}
#endif /* _IPXE_EFI_PCI_API_H */