]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[pci] Separate permission to probe buses from bus:dev.fn range discovery
authorMichael Brown <mcb30@ipxe.org>
Thu, 15 Aug 2024 07:46:41 +0000 (08:46 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 15 Aug 2024 08:31:14 +0000 (09:31 +0100)
The UEFI device model requires us to not probe the PCI bus directly,
but instead to wait to be offered the opportunity to drive devices via
our driver service binding handle.

We currently inhibit PCI bus probing by having pci_discover() return
an empty range when using the EFI PCI I/O API.  This has the unwanted
side effect that scanning the bus manually using the "pciscan" command
will also fail to discover any devices.

Separate out the concept of being allowed to probe PCI buses from the
mechanism for discovering PCI bus:dev.fn address ranges, so that this
limitation may be removed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
14 files changed:
src/arch/x86/core/pcidirect.c
src/arch/x86/include/ipxe/pcibios.h
src/arch/x86/include/ipxe/pcicloud.h
src/arch/x86/include/ipxe/pcidirect.h
src/arch/x86/interface/pcbios/pcibios.c
src/arch/x86/interface/pcbios/pcicloud.c
src/drivers/bus/ecam.c
src/drivers/bus/pci.c
src/include/ipxe/ecam.h
src/include/ipxe/efi/efi_pci_api.h
src/include/ipxe/linux/linux_pci.h
src/include/ipxe/pci_io.h
src/interface/efi/efi_pci.c
src/interface/linux/linux_pci.c

index f4659a1acd19ecc3004ceeb2a1213f47da03f83d..90d4623b3d72dd700817bf9dec2191bd19cef514 100644 (file)
@@ -45,6 +45,7 @@ void pcidirect_prepare ( struct pci_device *pci, int where ) {
               PCIDIRECT_CONFIG_ADDRESS );
 }
 
+PROVIDE_PCIAPI_INLINE ( direct, pci_can_probe );
 PROVIDE_PCIAPI_INLINE ( direct, pci_discover );
 PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte );
 PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word );
index 3caea1cfebede24fac145cc54ad1e844364eb01c..ef958565479754ae6e3b1415334469c3fe2137fb 100644 (file)
@@ -32,6 +32,16 @@ extern int pcibios_read ( struct pci_device *pci, uint32_t command,
 extern int pcibios_write ( struct pci_device *pci, uint32_t command,
                           uint32_t value );
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_can_probe ) ( void ) {
+       return 1;
+}
+
 /**
  * Read byte from PCI configuration space via PCI BIOS
  *
index 52268908c901ce8a0344af30f9ddd8e06dc7b6d6..1feef56cb8bc9a3c50d575b3aeb66ea3685d9656 100644 (file)
@@ -15,4 +15,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define PCIAPI_PREFIX_cloud __cloud_
 #endif
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( cloud, pci_can_probe ) ( void ) {
+       return 1;
+}
+
 #endif /* _IPXE_PCICLOUD_H */
index 98c6a2bbb188b4b8805046d5603184dde01c37d2..999b52763ec042a8321f77adb3c3f886a16b30d3 100644 (file)
@@ -25,6 +25,16 @@ struct pci_device;
 
 extern void pcidirect_prepare ( struct pci_device *pci, int where );
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_can_probe ) ( void ) {
+       return 1;
+}
+
 /**
  * Find next PCI bus:dev.fn address range in system
  *
index 7b7a769e30f85e22f4a92e6016db479e295d2c6d..ebe40ba7df2b70bc9732f00810de3d60eed8042e 100644 (file)
@@ -120,6 +120,7 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
        return ( status >> 8 );
 }
 
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_can_probe );
 PROVIDE_PCIAPI ( pcbios, pci_discover, pcibios_discover );
 PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
 PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
index 98ba38b3193bf1ddb559c97b0f2e80a19c5faf05..f7d4a2da15af8ce1281c5a8d1da7eb7a6641fa69 100644 (file)
@@ -148,6 +148,7 @@ static void * pcicloud_ioremap ( struct pci_device *pci,
        return pcicloud->pci_ioremap ( pci, bus_addr, len );
 }
 
+PROVIDE_PCIAPI_INLINE ( cloud, pci_can_probe );
 PROVIDE_PCIAPI ( cloud, pci_discover, pcicloud_discover );
 PROVIDE_PCIAPI ( cloud, pci_read_config_byte, pcicloud_read_config_byte );
 PROVIDE_PCIAPI ( cloud, pci_read_config_word, pcicloud_read_config_word );
index 5e3debdddc72e70e6cef3a40eece1e9fbe3e3467..cde5952b80ed48d7acef545e3f446ba962fad472 100644 (file)
@@ -276,6 +276,7 @@ int ecam_write ( struct pci_device *pci, unsigned int location,
        return 0;
 }
 
+PROVIDE_PCIAPI_INLINE ( ecam, pci_can_probe );
 PROVIDE_PCIAPI ( ecam, pci_discover, ecam_discover );
 PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_byte );
 PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_word );
index 92b389641d81ebe39f9727cae694cf080ea8f406..05c9a5c26eddb0e825406dc0dbd8398c1e3d7edd 100644 (file)
@@ -361,6 +361,10 @@ static int pcibus_probe ( struct root_device *rootdev ) {
        uint32_t busdevfn = 0;
        int rc;
 
+       /* Skip automatic probing if prohibited */
+       if ( ! pci_can_probe() )
+               return 0;
+
        do {
                /* Allocate struct pci_device */
                if ( ! pci )
index ff08aee5a5c9357204832b7093f5655522af6ad2..f656083f79191a508c6a6ef3bddf1d5a0289edb7 100644 (file)
@@ -54,6 +54,16 @@ struct ecam_mapping {
        int rc;
 };
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( ecam, pci_can_probe ) ( void ) {
+       return 1;
+}
+
 extern struct pci_api ecam_api;
 
 #endif /* _IPXE_ECAM_H */
index cf5e1d0200a5260ce358b0eb5ae47866da4d6cf0..0c4c1b72c1434af243c4c45d5075d0ca1945ccca 100644 (file)
@@ -32,6 +32,16 @@ extern int efipci_read ( struct pci_device *pci, unsigned long location,
 extern int efipci_write ( struct pci_device *pci, unsigned long location,
                          unsigned long value );
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_can_probe ) ( void ) {
+       return 0;
+}
+
 /**
  * Find next PCI bus:dev.fn address range in system
  *
index ec6ff8b1c6a57bd202574dd9a1996e4a8d41c040..2b19e13c325918bfd2bcb6dd158445f6dd370303 100644 (file)
@@ -22,6 +22,16 @@ extern int linux_pci_read ( struct pci_device *pci, unsigned long where,
 extern int linux_pci_write ( struct pci_device *pci, unsigned long where,
                             unsigned long value, size_t len );
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( linux, pci_can_probe ) ( void ) {
+       return 1;
+}
+
 /**
  * Find next PCI bus:dev.fn address range in system
  *
index 4c035b18bd64929494af306345a9a8fc09fc02d9..322fdbb24cbefa1701e94316935e8583fd55168b 100644 (file)
@@ -66,6 +66,13 @@ struct pci_range {
 /* Include all architecture-dependent I/O API headers */
 #include <bits/pci_io.h>
 
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok             Bus probing is allowed
+ */
+int pci_can_probe ( void );
+
 /**
  * Find next PCI bus:dev.fn address range in system
  *
index e2eeeb34465f520f3e55a3b90163f83bf96560c4..61071d8a4bb12c4a2bd00612c91afc8da90b1a6e 100644 (file)
@@ -362,6 +362,7 @@ void * efipci_ioremap ( struct pci_device *pci, unsigned long bus_addr,
        return ioremap ( bus_addr, len );
 }
 
+PROVIDE_PCIAPI_INLINE ( efi, pci_can_probe );
 PROVIDE_PCIAPI_INLINE ( efi, pci_discover );
 PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte );
 PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word );
index 3008447375a6ca19d686ec9f7905ea98e5e8d198..a3a0828c160aaebd53415a6d01fdb3257d086605 100644 (file)
@@ -188,6 +188,7 @@ int linux_pci_write ( struct pci_device *pci, unsigned long where,
        return rc;
 }
 
+PROVIDE_PCIAPI_INLINE ( linux, pci_can_probe );
 PROVIDE_PCIAPI_INLINE ( linux, pci_discover );
 PROVIDE_PCIAPI_INLINE ( linux, pci_read_config_byte );
 PROVIDE_PCIAPI_INLINE ( linux, pci_read_config_word );