From: Michael Brown Date: Mon, 24 Nov 2025 20:18:52 +0000 (+0000) Subject: [pci] Use linker tables for runtime selectable PCI APIs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ff1a17dc7e5d764b905559fdc623249741d173dd;p=thirdparty%2Fipxe.git [pci] Use linker tables for runtime selectable PCI APIs Use the linker table mechanism to enumerate the underlying PCI I/O APIs, to allow PCIAPI_CLOUD to become architecture-independent code. Signed-off-by: Michael Brown --- diff --git a/src/arch/x86/core/pcidirect.c b/src/arch/x86/core/pcidirect.c index 90d4623b3..887b78a0b 100644 --- a/src/arch/x86/core/pcidirect.c +++ b/src/arch/x86/core/pcidirect.c @@ -54,5 +54,4 @@ PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte ); PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word ); PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword ); PROVIDE_PCIAPI_INLINE ( direct, pci_ioremap ); - -struct pci_api pcidirect_api = PCIAPI_RUNTIME ( direct ); +PROVIDE_PCIAPI_RUNTIME ( direct, PCIAPI_PRIORITY_DIRECT ); diff --git a/src/arch/x86/include/bits/pci_io.h b/src/arch/x86/include/bits/pci_io.h index a074d3370..b41e562ee 100644 --- a/src/arch/x86/include/bits/pci_io.h +++ b/src/arch/x86/include/bits/pci_io.h @@ -11,6 +11,5 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include -#include #endif /* _BITS_PCI_IO_H */ diff --git a/src/arch/x86/include/ipxe/pcibios.h b/src/arch/x86/include/ipxe/pcibios.h index ef9585654..87b403555 100644 --- a/src/arch/x86/include/ipxe/pcibios.h +++ b/src/arch/x86/include/ipxe/pcibios.h @@ -155,6 +155,4 @@ PCIAPI_INLINE ( pcbios, pci_ioremap ) ( struct pci_device *pci __unused, return ioremap ( bus_addr, len ); } -extern struct pci_api pcibios_api; - #endif /* _IPXE_PCIBIOS_H */ diff --git a/src/arch/x86/include/ipxe/pcidirect.h b/src/arch/x86/include/ipxe/pcidirect.h index 999b52763..501576582 100644 --- a/src/arch/x86/include/ipxe/pcidirect.h +++ b/src/arch/x86/include/ipxe/pcidirect.h @@ -165,6 +165,4 @@ PCIAPI_INLINE ( direct, pci_ioremap ) ( struct pci_device *pci __unused, return ioremap ( bus_addr, len ); } -extern struct pci_api pcidirect_api; - #endif /* _PCIDIRECT_H */ diff --git a/src/arch/x86/interface/pcbios/pcibios.c b/src/arch/x86/interface/pcbios/pcibios.c index ebe40ba7d..6b88ee907 100644 --- a/src/arch/x86/interface/pcbios/pcibios.c +++ b/src/arch/x86/interface/pcbios/pcibios.c @@ -129,5 +129,4 @@ PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte ); PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word ); PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword ); PROVIDE_PCIAPI_INLINE ( pcbios, pci_ioremap ); - -struct pci_api pcibios_api = PCIAPI_RUNTIME ( pcbios ); +PROVIDE_PCIAPI_RUNTIME ( pcbios, PCIAPI_PRIORITY_PCBIOS ); diff --git a/src/config/cloud/ioapi.h b/src/config/cloud/ioapi.h index ba0896a9a..bcd245981 100644 --- a/src/config/cloud/ioapi.h +++ b/src/config/cloud/ioapi.h @@ -4,4 +4,7 @@ #ifdef PLATFORM_pcbios #undef PCIAPI_PCBIOS #define PCIAPI_CLOUD +#define PCIAPI_RUNTIME_ECAM +#define PCIAPI_RUNTIME_PCBIOS +#define PCIAPI_RUNTIME_DIRECT #endif diff --git a/src/config/config_pci.c b/src/config/config_pci.c index cb8df712a..8ed9f6603 100644 --- a/src/config/config_pci.c +++ b/src/config/config_pci.c @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include +#include /** @file * @@ -34,3 +35,13 @@ PROVIDE_REQUIRING_SYMBOL(); #ifdef PCI_SETTINGS REQUIRE_OBJECT ( pci_settings ); #endif + +#ifdef PCIAPI_RUNTIME_ECAM +REQUIRE_OBJECT ( ecam ); +#endif +#ifdef PCIAPI_RUNTIME_PCBIOS +REQUIRE_OBJECT ( pcibios ); +#endif +#ifdef PCIAPI_RUNTIME_DIRECT +REQUIRE_OBJECT ( pcidirect ); +#endif diff --git a/src/drivers/bus/ecam.c b/src/drivers/bus/ecam.c index 976254c18..602f7bd8a 100644 --- a/src/drivers/bus/ecam.c +++ b/src/drivers/bus/ecam.c @@ -279,5 +279,4 @@ PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_byte ); PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_word ); PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_dword ); PROVIDE_PCIAPI_INLINE ( ecam, pci_ioremap ); - -struct pci_api ecam_api = PCIAPI_RUNTIME ( ecam ); +PROVIDE_PCIAPI_RUNTIME ( ecam, PCIAPI_PRIORITY_ECAM ); diff --git a/src/arch/x86/interface/pcbios/pcicloud.c b/src/drivers/bus/pcicloud.c similarity index 94% rename from src/arch/x86/interface/pcbios/pcicloud.c rename to src/drivers/bus/pcicloud.c index 284cd078c..9e1fd32b2 100644 --- a/src/arch/x86/interface/pcbios/pcicloud.c +++ b/src/drivers/bus/pcicloud.c @@ -26,9 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include -#include -#include -#include #include /** @file @@ -37,11 +34,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ -/** Underlying PCI configuration space access APIs */ -static struct pci_api *pcicloud_apis[] = { - &ecam_api, &pcibios_api, &pcidirect_api -}; - /** Cached PCI configuration space access API */ static struct { /** PCI bus:dev.fn address range */ @@ -65,17 +57,14 @@ static struct pci_api * pcicloud_find ( uint32_t busdevfn, uint32_t index; uint32_t first; uint32_t last; - unsigned int i; /* Return empty range on error */ range->count = 0; /* Try discovery via all known APIs */ - for ( i = 0 ; i < ( sizeof ( pcicloud_apis ) / - sizeof ( pcicloud_apis[0] ) ) ; i++ ) { + for_each_table_entry ( api, PCI_APIS ) { /* Discover via this API */ - api = pcicloud_apis[i]; api->pci_discover ( busdevfn, &candidate ); /* Check for a matching or new closest allocation */ @@ -135,8 +124,7 @@ static struct pci_api * pcicloud_api ( struct pci_device *pci ) { /* Fall back to lowest priority API for any unclaimed gaps in ranges */ if ( ! api ) { - api = pcicloud_apis[ ( sizeof ( pcicloud_apis ) / - sizeof ( pcicloud_apis[0] ) ) - 1 ]; + api = ( table_end ( PCI_APIS ) - 1 ); range->count = ( range->start - pci->busdevfn ); range->start = pci->busdevfn; first = range->start; diff --git a/src/include/ipxe/ecam.h b/src/include/ipxe/ecam.h index ff08aee5a..856a673c5 100644 --- a/src/include/ipxe/ecam.h +++ b/src/include/ipxe/ecam.h @@ -54,6 +54,4 @@ struct ecam_mapping { int rc; }; -extern struct pci_api ecam_api; - #endif /* _IPXE_ECAM_H */ diff --git a/src/include/ipxe/pci_io.h b/src/include/ipxe/pci_io.h index 9b4cbcab4..456e29e6e 100644 --- a/src/include/ipxe/pci_io.h +++ b/src/include/ipxe/pci_io.h @@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include +#include #include #include @@ -61,6 +62,7 @@ struct pci_range { /* Include all architecture-independent I/O API headers */ #include #include +#include #include #include @@ -171,23 +173,45 @@ struct pci_api { typeof ( pci_ioremap ) ( * pci_ioremap ); }; +/** Runtime selectable PCI API table */ +#define PCI_APIS __table ( struct pci_api, "pci_apis" ) + +/** + * Declare a runtime selectable PCI API + * + * In the common case of a non-runtime-selectable PCI I/O API, allow + * the runtime API code to be garbage-collected at link time to save + * space. + */ +#ifdef PCIAPI_CLOUD +#define __pci_api( priority ) __table_entry ( PCI_APIS, priority ) +#else +#define __pci_api( priority ) +#endif + +/* PCI runtime selectable API priorities */ +#define PCIAPI_PRIORITY_ECAM 01 /**< ACPI ECAM */ +#define PCIAPI_PRIORITY_PCBIOS 02 /**< PCI BIOS calls */ +#define PCIAPI_PRIORITY_DIRECT 03 /**< Direct Type 1 accesses */ + /** Provide a runtime selectable PCI I/O API */ -#define PCIAPI_RUNTIME( _subsys ) { \ - .name = #_subsys, \ - .pci_discover = PCIAPI_INLINE ( _subsys, pci_discover ), \ - .pci_read_config_byte = \ - PCIAPI_INLINE ( _subsys, pci_read_config_byte ), \ - .pci_read_config_word = \ - PCIAPI_INLINE ( _subsys, pci_read_config_word ), \ - .pci_read_config_dword = \ - PCIAPI_INLINE ( _subsys, pci_read_config_dword ), \ - .pci_write_config_byte = \ - PCIAPI_INLINE ( _subsys, pci_write_config_byte ), \ - .pci_write_config_word = \ - PCIAPI_INLINE ( _subsys, pci_write_config_word ), \ - .pci_write_config_dword = \ - PCIAPI_INLINE ( _subsys, pci_write_config_dword ), \ - .pci_ioremap = PCIAPI_INLINE ( _subsys, pci_ioremap ), \ +#define PROVIDE_PCIAPI_RUNTIME( subsys, priority ) \ + struct pci_api pciapi_ ## subsys __pci_api ( priority ) = { \ + .name = #subsys, \ + .pci_discover = PCIAPI_INLINE ( subsys, pci_discover ), \ + .pci_read_config_byte = \ + PCIAPI_INLINE ( subsys, pci_read_config_byte ), \ + .pci_read_config_word = \ + PCIAPI_INLINE ( subsys, pci_read_config_word ), \ + .pci_read_config_dword = \ + PCIAPI_INLINE ( subsys, pci_read_config_dword ), \ + .pci_write_config_byte = \ + PCIAPI_INLINE ( subsys, pci_write_config_byte ), \ + .pci_write_config_word = \ + PCIAPI_INLINE ( subsys, pci_write_config_word ), \ + .pci_write_config_dword = \ + PCIAPI_INLINE ( subsys, pci_write_config_dword ), \ + .pci_ioremap = PCIAPI_INLINE ( subsys, pci_ioremap ), \ } #endif /* _IPXE_PCI_IO_H */ diff --git a/src/arch/x86/include/ipxe/pcicloud.h b/src/include/ipxe/pcicloud.h similarity index 100% rename from src/arch/x86/include/ipxe/pcicloud.h rename to src/include/ipxe/pcicloud.h