From 134d76379e22d1554476cac3ef7baee14a3c27d3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 9 May 2025 14:25:59 +0100 Subject: [build] Formalise mechanism for accessing absolute symbols In a position-dependent executable, where all addresses are fixed at link time, we can use the standard technique as documented by GNU ld to get the value of an absolute symbol, e.g.: extern char _my_symbol[]; printf ( "Absolute symbol value is %x\n", ( ( int ) _my_symbol ) ); This technique may not work in a position-independent executable. When dynamic relocations are applied, the runtime addresses will no longer be equal to the link-time addresses. If the code to obtain the address of _my_symbol uses PC-relative addressing, then it will calculate the runtime "address" of the absolute symbol, which will no longer be equal the the link-time "address" (i.e. the correct value) of the absolute symbol. Define macros ABS_SYMBOL(), ABS_VALUE_INIT(), and ABS_VALUE() that provide access to the correct values of absolute symbols even in position-independent code, and use these macros wherever absolute symbols are accessed. Signed-off-by: Michael Brown --- src/include/compiler.h | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'src/include/compiler.h') diff --git a/src/include/compiler.h b/src/include/compiler.h index 5685ab154..ec03f6f96 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -662,6 +662,97 @@ char __debug_disable(OBJECT) = ( DBGLVL_MAX & ~DBGLVL_DFLT ); #define ARRAY_SIZE(array) ( sizeof (array) / sizeof ( (array)[0] ) ) #endif /* ASSEMBLY */ +/** @defgroup abs Absolute symbols + * @{ + */ +#ifndef ASSEMBLY + +/** Declare an absolute symbol (e.g. a value defined by a linker script) + * + * Use as e.g.: + * + * extern int ABS_SYMBOL ( _my_symbol ); + * + */ +#define ABS_SYMBOL( name ) name[] + +/** Get value of an absolute symbol for use in a static initializer + * + * Use as e.g.: + * + * extern int ABS_SYMBOL ( _my_symbol ); + * static int my_symbol = ABS_VALUE_INIT ( _my_symbol ); + * + * Note that the declared type must be at least as large as a pointer + * type, since the compiler sees the absolute symbol as being an + * address. + */ +#define ABS_VALUE_INIT( name ) ( ( typeof ( name[0] ) ) name ) + +/** Get value of an absolute symbol + * + * In a position-dependent executable, where all addresses are fixed + * at link time, we can use the standard technique as documented by + * GNU ld, e.g.: + * + * extern char _my_symbol[]; + * + * printf ( "Absolute symbol value is %x\n", ( ( int ) _my_symbol ) ); + * + * This technique may not work in a position-independent executable. + * When dynamic relocations are applied, the runtime addresses will no + * longer be equal to the link-time addresses. If the code to obtain + * the address of _my_symbol uses PC-relative addressing, then it + * will calculate the runtime "address" of the absolute symbol, which + * will no longer be equal the the link-time "address" (i.e. the + * correct value) of the absolute symbol. + * + * We can work around this by instead declaring a static variable to + * contain the absolute value, and returning the contents of this + * static variable: + * + * extern char _my_symbol[]; + * static void * volatile my_symbol = _my_symbol; + * + * printf ( "Absolute symbol value is %x\n", ( ( int ) my_symbol ) ); + * + * The value of the static variable cannot possibly use PC-relative + * addressing (since there is no applicable program counter for + * non-code), and so will instead be filled in with the correct + * absolute value at link time. (No dynamic relocation will be + * generated that might change its value, since the symbol providing + * the value is an absolute symbol.) + * + * This second technique will work for both position-dependent and + * position-independent code, but incurs the unnecssary overhead of an + * additional static variable in position-dependent code. The + * ABS_VALUE() macro abstracts away these differences, using the most + * efficient available technique. Use as e.g.: + * + * extern int ABS_SYMBOL ( _my_symbol ); + * #define my_symbol ABS_VALUE ( _my_symbol ) + * + * printf ( "Absolute symbol value is %x\n", my_symbol ); + * + * The ABS_VALUE() macro uses the (otherwise redundant) type declared + * on the ABS_SYMBOL() array to automatically determine the correct + * type for the ABS_VALUE() expression. + * + * Unlike ABS_VALUE_INIT(), there is no restriction that the type must + * be at least as large as a pointer type. + */ +#ifndef __pie__ +#define ABS_VALUE( name ) ( ( typeof ( name[0] ) ) ( intptr_t ) name ) +#else +#define ABS_VALUE( name ) ( { \ + static void * volatile static_ ## name = name; \ + ( ( typeof ( name[0] ) ) ( intptr_t ) static_ ## name ); \ + } ) +#endif + +#endif /* ASSEMBLY */ +/** @} */ + /** * @defgroup licences Licence declarations * -- cgit v1.2.3-55-g7522 From d3e10ebd354928d56ba660cd2ea14af1663702a2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 24 Jun 2025 13:17:19 +0100 Subject: [legacy] Allocate legacy driver .bss-like segments at probe time Some legacy drivers use large static allocations for transmit and receive buffers. To avoid bloating the .bss segment, we currently implement these as a single common symbol named "_shared_bss" (which is permissible since only one legacy driver may be active at any one time). Switch to dynamic allocation of these .bss-like segments, to avoid the requirement for using common symbols. Signed-off-by: Michael Brown --- src/drivers/net/3c509-eisa.c | 2 +- src/drivers/net/3c509.c | 2 +- src/drivers/net/3c515.c | 4 ++-- src/drivers/net/3c529.c | 2 +- src/drivers/net/3c595.c | 2 +- src/drivers/net/amd8111e.c | 5 ++--- src/drivers/net/bnx2.c | 8 +++++--- src/drivers/net/cs89x0.c | 2 +- src/drivers/net/davicom.c | 7 ++++--- src/drivers/net/depca.c | 2 +- src/drivers/net/dmfe.c | 7 ++++--- src/drivers/net/eepro.c | 2 +- src/drivers/net/epic100.c | 7 ++++--- src/drivers/net/legacy.c | 33 +++++++++++++++++++++++++++------ src/drivers/net/ne2k_isa.c | 2 +- src/drivers/net/ns8390.c | 2 +- src/drivers/net/prism2_pci.c | 2 +- src/drivers/net/prism2_plx.c | 3 +-- src/drivers/net/sis900.c | 7 ++++--- src/drivers/net/smc9000.c | 2 +- src/drivers/net/sundance.c | 7 ++++--- src/drivers/net/tlan.c | 7 ++++--- src/drivers/net/tulip.c | 7 ++++--- src/drivers/net/w89c840.c | 7 ++++--- src/include/compiler.h | 22 ---------------------- src/include/nic.h | 27 ++++++++++++++++++++------- 26 files changed, 100 insertions(+), 80 deletions(-) (limited to 'src/include/compiler.h') diff --git a/src/drivers/net/3c509-eisa.c b/src/drivers/net/3c509-eisa.c index 81c60ee91..ada34a6b9 100644 --- a/src/drivers/net/3c509-eisa.c +++ b/src/drivers/net/3c509-eisa.c @@ -35,7 +35,7 @@ static struct eisa_device_id el3_eisa_adapters[] = { EISA_DRIVER ( el3_eisa_driver, el3_eisa_adapters ); DRIVER ( "3c509 (EISA)", nic_driver, eisa_driver, el3_eisa_driver, - el3_eisa_probe, el3_eisa_disable ); + el3_eisa_probe, el3_eisa_disable, no_fake_bss ); ISA_ROM ( "3c509-eisa","3c509 (EISA)" ); diff --git a/src/drivers/net/3c509.c b/src/drivers/net/3c509.c index 4326a835c..0f721315d 100644 --- a/src/drivers/net/3c509.c +++ b/src/drivers/net/3c509.c @@ -316,7 +316,7 @@ static int t509_probe ( struct t509_device *t509 ) { DBG ( "Adding 3c509 device %02x (I/O %04x)\n", t509->tag, t509->ioaddr ); return legacy_probe ( t509, legacy_t509_set_drvdata, &t509->dev, - legacy_t509_probe, legacy_t509_disable ); + legacy_t509_probe, legacy_t509_disable, 0 ); } /** diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c index 1591e0617..353d45794 100644 --- a/src/drivers/net/3c515.c +++ b/src/drivers/net/3c515.c @@ -64,7 +64,6 @@ static void t3c515_wait(unsigned int nticks) /* TJL definations */ #define HZ 100 static int if_port; -static struct corkscrew_private *vp; /* Brought directly from 3c515.c by Becker */ #define CORKSCREW 1 @@ -237,6 +236,7 @@ struct corkscrew_private { full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */ tx_full:1; }; +#define vp NIC_FAKE_BSS_PTR ( struct corkscrew_private ) /* The action to take with a media selection timer tick. Note that we deviate from the 3Com order by checking 10base2 before AUI. @@ -759,6 +759,6 @@ static struct isapnp_device_id t515_adapters[] = { ISAPNP_DRIVER ( t515_driver, t515_adapters ); DRIVER ( "3c515", nic_driver, isapnp_driver, t515_driver, - t515_probe, t515_disable ); + t515_probe, t515_disable, *vp ); ISA_ROM ( "3c515", "3c515 Fast EtherLink ISAPnP" ); diff --git a/src/drivers/net/3c529.c b/src/drivers/net/3c529.c index d68f28ec1..8b408f255 100644 --- a/src/drivers/net/3c529.c +++ b/src/drivers/net/3c529.c @@ -49,7 +49,7 @@ static struct mca_device_id el3_mca_adapters[] = { MCA_DRIVER ( t529_driver, el3_mca_adapters ); DRIVER ( "3c529", nic_driver, mca_driver, t529_driver, - t529_probe, t529_disable ); + t529_probe, t529_disable, no_fake_bss ); ISA_ROM( "3c529", "3c529 == MCA 3c509" ); diff --git a/src/drivers/net/3c595.c b/src/drivers/net/3c595.c index 7792c17d6..58cfc41ae 100644 --- a/src/drivers/net/3c595.c +++ b/src/drivers/net/3c595.c @@ -541,7 +541,7 @@ PCI_ROM(0x10b7, 0x9805, "3c9805-1", "3Com9805", 0), /* Dual Port Server PCI_DRIVER ( t595_driver, t595_nics, PCI_NO_CLASS ); DRIVER ( "3C595", nic_driver, pci_driver, t595_driver, - t595_probe, t595_disable ); + t595_probe, t595_disable, no_fake_bss ); /* * Local variables: diff --git a/src/drivers/net/amd8111e.c b/src/drivers/net/amd8111e.c index 213c4f44b..c21c11835 100644 --- a/src/drivers/net/amd8111e.c +++ b/src/drivers/net/amd8111e.c @@ -105,8 +105,7 @@ struct amd8111e_priv { struct nic *nic; void *mmio; }; - -static struct amd8111e_priv amd8111e; +#define amd8111e NIC_FAKE_BSS ( struct amd8111e_priv ) /******************************************************** @@ -683,7 +682,7 @@ static struct pci_device_id amd8111e_nics[] = { PCI_DRIVER ( amd8111e_driver, amd8111e_nics, PCI_NO_CLASS ); DRIVER ( "AMD8111E", nic_driver, pci_driver, amd8111e_driver, - amd8111e_probe, amd8111e_disable ); + amd8111e_probe, amd8111e_disable, amd8111e ); /* * Local variables: diff --git a/src/drivers/net/bnx2.c b/src/drivers/net/bnx2.c index 186cc17d4..ae94c9bed 100644 --- a/src/drivers/net/bnx2.c +++ b/src/drivers/net/bnx2.c @@ -36,13 +36,14 @@ FILE_LICENCE ( GPL_ANY ); /* The bnx2 seems to be picky about the alignment of the receive buffers * and possibly the status block. */ -static struct bss { +struct bss { struct tx_bd tx_desc_ring[TX_DESC_CNT]; struct rx_bd rx_desc_ring[RX_DESC_CNT]; unsigned char rx_buf[RX_BUF_CNT][RX_BUF_SIZE]; struct status_block status_blk; struct statistics_block stats_blk; -} bnx2_bss; +}; +#define bnx2_bss NIC_FAKE_BSS ( struct bss ) static struct bnx2 bnx2; @@ -2686,7 +2687,8 @@ static struct pci_device_id bnx2_nics[] = { PCI_DRIVER ( bnx2_driver, bnx2_nics, PCI_NO_CLASS ); -DRIVER ( "BNX2", nic_driver, pci_driver, bnx2_driver, bnx2_probe, bnx2_remove ); +DRIVER ( "BNX2", nic_driver, pci_driver, bnx2_driver, + bnx2_probe, bnx2_remove, bnx2_bss ); /* static struct pci_driver bnx2_driver __pci_driver = { diff --git a/src/drivers/net/cs89x0.c b/src/drivers/net/cs89x0.c index 17b7157a1..fc311a18a 100644 --- a/src/drivers/net/cs89x0.c +++ b/src/drivers/net/cs89x0.c @@ -725,7 +725,7 @@ ISA_DRIVER ( cs89x0_driver, cs89x0_probe_addrs, cs89x0_probe_addr, ISAPNP_VENDOR('C','S','C'), 0x0007 ); DRIVER ( "cs89x0", nic_driver, isa_driver, cs89x0_driver, - cs89x0_probe, cs89x0_disable ); + cs89x0_probe, cs89x0_disable, no_fake_bss ); ISA_ROM ( "cs89x0", "Crystal Semiconductor CS89x0" ); diff --git a/src/drivers/net/davicom.c b/src/drivers/net/davicom.c index 307ae9811..2b063ad1b 100644 --- a/src/drivers/net/davicom.c +++ b/src/drivers/net/davicom.c @@ -134,12 +134,13 @@ static unsigned long ioaddr; /* transmit descriptor and buffer */ #define NTXD 2 #define NRXD 4 -struct { +struct davicom_bss { struct txdesc txd[NTXD] __attribute__ ((aligned(4))); unsigned char txb[BUFLEN] __attribute__ ((aligned(4))); struct rxdesc rxd[NRXD] __attribute__ ((aligned(4))); unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4))); -} davicom_bufs __shared; +}; +#define davicom_bufs NIC_FAKE_BSS ( struct davicom_bss ) #define txd davicom_bufs.txd #define txb davicom_bufs.txb #define rxd davicom_bufs.rxd @@ -698,7 +699,7 @@ PCI_ROM(0x1282, 0x9132, "davicom9132", "Davicom 9132", 0), /* Needs probably som PCI_DRIVER ( davicom_driver, davicom_nics, PCI_NO_CLASS ); DRIVER ( "DAVICOM", nic_driver, pci_driver, davicom_driver, - davicom_probe, davicom_disable ); + davicom_probe, davicom_disable, davicom_bufs ); /* * Local variables: diff --git a/src/drivers/net/depca.c b/src/drivers/net/depca.c index 30e2fcb0a..335928667 100644 --- a/src/drivers/net/depca.c +++ b/src/drivers/net/depca.c @@ -789,7 +789,7 @@ ISA_DRIVER ( depca_driver, depca_probe_addrs, depca_probe1, GENERIC_ISAPNP_VENDOR, 0x80f7 ); DRIVER ( "depce", nic_driver, isa_driver, depca_driver, - depca_probe, depca_disable ); + depca_probe, depca_disable, no_fake_bss ); ISA_ROM ( "depca", "Digital DE100 and DE200" ); diff --git a/src/drivers/net/dmfe.c b/src/drivers/net/dmfe.c index a76dd792d..2ed108e8c 100644 --- a/src/drivers/net/dmfe.c +++ b/src/drivers/net/dmfe.c @@ -209,14 +209,15 @@ static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control /********************************************** * Descriptor Ring and Buffer defination ***********************************************/ -struct { +struct dmfe_bss { struct tx_desc txd[TX_DESC_CNT] __attribute__ ((aligned(32))); unsigned char txb[TX_BUF_ALLOC * TX_DESC_CNT] __attribute__ ((aligned(32))); struct rx_desc rxd[RX_DESC_CNT] __attribute__ ((aligned(32))); unsigned char rxb[RX_ALLOC_SIZE * RX_DESC_CNT] __attribute__ ((aligned(32))); -} dmfe_bufs __shared; +}; +#define dmfe_bufs NIC_FAKE_BSS ( struct dmfe_bss ) #define txd dmfe_bufs.txd #define txb dmfe_bufs.txb #define rxd dmfe_bufs.rxd @@ -1217,7 +1218,7 @@ static struct pci_device_id dmfe_nics[] = { PCI_DRIVER ( dmfe_driver, dmfe_nics, PCI_NO_CLASS ); DRIVER ( "DMFE/PCI", nic_driver, pci_driver, dmfe_driver, - dmfe_probe, dmfe_disable ); + dmfe_probe, dmfe_disable, dmfe_bufs ); /* * Local variables: diff --git a/src/drivers/net/eepro.c b/src/drivers/net/eepro.c index 97b4c4061..3863553fa 100644 --- a/src/drivers/net/eepro.c +++ b/src/drivers/net/eepro.c @@ -635,7 +635,7 @@ ISA_DRIVER ( eepro_driver, eepro_probe_addrs, eepro_probe1, GENERIC_ISAPNP_VENDOR, 0x828a ); DRIVER ( "eepro", nic_driver, isa_driver, eepro_driver, - eepro_probe, eepro_disable ); + eepro_probe, eepro_disable, no_fake_bss ); ISA_ROM ( "eepro", "Intel Etherexpress Pro/10" ); diff --git a/src/drivers/net/epic100.c b/src/drivers/net/epic100.c index 01c0c43c9..03b394e6b 100644 --- a/src/drivers/net/epic100.c +++ b/src/drivers/net/epic100.c @@ -86,14 +86,15 @@ static unsigned int cur_rx, cur_tx; /* The next free ring entry */ static unsigned short eeprom[64]; #endif static signed char phys[4]; /* MII device addresses. */ -struct { +struct epic100_bss { struct epic_rx_desc rx_ring[RX_RING_SIZE] __attribute__ ((aligned(4))); struct epic_tx_desc tx_ring[TX_RING_SIZE] __attribute__ ((aligned(4))); unsigned char rx_packet[PKT_BUF_SZ * RX_RING_SIZE]; unsigned char tx_packet[PKT_BUF_SZ * TX_RING_SIZE]; -} epic100_bufs __shared; +}; +#define epic100_bufs NIC_FAKE_BSS ( struct epic100_bss ) #define rx_ring epic100_bufs.rx_ring #define tx_ring epic100_bufs.tx_ring #define rx_packet epic100_bufs.rx_packet @@ -525,7 +526,7 @@ PCI_ROM(0x10b8, 0x0006, "smc-83c175", "SMC EPIC/C 83c175", 0), PCI_DRIVER ( epic100_driver, epic100_nics, PCI_NO_CLASS ); DRIVER ( "EPIC100", nic_driver, pci_driver, epic100_driver, - epic100_probe, epic100_disable ); + epic100_probe, epic100_disable, epic100_bufs ); /* * Local variables: diff --git a/src/drivers/net/legacy.c b/src/drivers/net/legacy.c index 3b208a28b..b86f77fc8 100644 --- a/src/drivers/net/legacy.c +++ b/src/drivers/net/legacy.c @@ -84,17 +84,22 @@ int legacy_probe ( void *hwdev, void ( * set_drvdata ) ( void *hwdev, void *priv ), struct device *dev, int ( * probe ) ( struct nic *nic, void *hwdev ), - void ( * disable ) ( struct nic *nic, void *hwdev ) ) { + void ( * disable ) ( struct nic *nic, void *hwdev ), + size_t fake_bss_len ) { struct net_device *netdev; struct nic *nic; int rc; - if ( legacy_registered ) - return -EBUSY; - + if ( legacy_registered ) { + rc = -EBUSY; + goto err_registered; + } + netdev = alloc_etherdev ( 0 ); - if ( ! netdev ) - return -ENOMEM; + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } netdev_init ( netdev, &legacy_operations ); nic = &legacy_nic; netdev->priv = nic; @@ -105,6 +110,15 @@ int legacy_probe ( void *hwdev, nic->node_addr = netdev->hw_addr; nic->irqno = dev->desc.irq; + if ( fake_bss_len ) { + nic->fake_bss = malloc_phys ( fake_bss_len, PAGE_SIZE ); + if ( ! nic->fake_bss ) { + rc = -ENOMEM; + goto err_fake_bss; + } + } + nic->fake_bss_len = fake_bss_len; + if ( ! probe ( nic, hwdev ) ) { rc = -ENODEV; goto err_probe; @@ -133,8 +147,13 @@ int legacy_probe ( void *hwdev, err_register: disable ( nic, hwdev ); err_probe: + if ( fake_bss_len ) + free_phys ( nic->fake_bss, fake_bss_len ); + err_fake_bss: netdev_nullify ( netdev ); netdev_put ( netdev ); + err_alloc: + err_registered: return rc; } @@ -146,6 +165,8 @@ void legacy_remove ( void *hwdev, unregister_netdev ( netdev ); disable ( nic, hwdev ); + if ( nic->fake_bss_len ) + free_phys ( nic->fake_bss, nic->fake_bss_len ); netdev_nullify ( netdev ); netdev_put ( netdev ); legacy_registered = 0; diff --git a/src/drivers/net/ne2k_isa.c b/src/drivers/net/ne2k_isa.c index a923fd3c5..8c8188af3 100644 --- a/src/drivers/net/ne2k_isa.c +++ b/src/drivers/net/ne2k_isa.c @@ -370,6 +370,6 @@ ISA_DRIVER ( ne_driver, ne_probe_addrs, ne_probe1, GENERIC_ISAPNP_VENDOR, 0x0600 ); DRIVER ( "ne", nic_driver, isapnp_driver, ne_driver, - ne_probe, ne_disable ); + ne_probe, ne_disable, no_fake_bss ); ISA_ROM("ne","NE1000/2000 and clones"); diff --git a/src/drivers/net/ns8390.c b/src/drivers/net/ns8390.c index a81ec6eea..bc94aabe3 100644 --- a/src/drivers/net/ns8390.c +++ b/src/drivers/net/ns8390.c @@ -1022,7 +1022,7 @@ PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0), PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS ); DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver, - nepci_probe, ns8390_disable ); + nepci_probe, ns8390_disable, no_fake_bss ); #endif /* INCLUDE_NS8390 */ diff --git a/src/drivers/net/prism2_pci.c b/src/drivers/net/prism2_pci.c index 9940f76a7..128bdedc1 100644 --- a/src/drivers/net/prism2_pci.c +++ b/src/drivers/net/prism2_pci.c @@ -55,7 +55,7 @@ PCI_ROM(0x1260, 0x3873, "prism2_pci", "Harris Semiconductor Prism2.5 clone", 0), PCI_DRIVER ( prism2_pci_driver, prism2_pci_nics, PCI_NO_CLASS ); DRIVER ( "Prism2/PCI", nic_driver, pci_driver, prism2_pci_driver, - prism2_pci_probe, prism2_pci_disable ); + prism2_pci_probe, prism2_pci_disable, no_fake_bss ); /* * Local variables: diff --git a/src/drivers/net/prism2_plx.c b/src/drivers/net/prism2_plx.c index f3200e89c..dac63ba9f 100644 --- a/src/drivers/net/prism2_plx.c +++ b/src/drivers/net/prism2_plx.c @@ -119,9 +119,8 @@ PCI_ROM(0xec80, 0xec00, "f5d6000", "Belkin F5D6000", 0), PCI_DRIVER ( prism2_plx_driver, prism2_plx_nics, PCI_NO_CLASS ); - DRIVER ( "Prism2/PLX", nic_driver, pci_driver, prism2_plx_driver, - prism2_plx_probe, prism2_plx_disable ); + prism2_plx_probe, prism2_plx_disable, no_fake_bss ); /* * Local variables: diff --git a/src/drivers/net/sis900.c b/src/drivers/net/sis900.c index c8fd3e9b5..59deb8df9 100644 --- a/src/drivers/net/sis900.c +++ b/src/drivers/net/sis900.c @@ -65,12 +65,13 @@ static unsigned int cur_phy; static unsigned int cur_rx; -struct { +struct sis900_bss { BufferDesc txd; BufferDesc rxd[NUM_RX_DESC]; unsigned char txb[TX_BUF_SIZE]; unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]; -} sis900_bufs __shared; +}; +#define sis900_bufs NIC_FAKE_BSS ( struct sis900_bss ) #define txd sis900_bufs.txd #define rxd sis900_bufs.rxd #define txb sis900_bufs.txb @@ -1291,7 +1292,7 @@ PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0), PCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS ); DRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver, - sis900_probe, sis900_disable ); + sis900_probe, sis900_disable, sis900_bufs ); /* * Local variables: diff --git a/src/drivers/net/smc9000.c b/src/drivers/net/smc9000.c index c9762d580..420aca9bd 100644 --- a/src/drivers/net/smc9000.c +++ b/src/drivers/net/smc9000.c @@ -939,7 +939,7 @@ ISA_DRIVER ( smc9000_driver, smc9000_probe_addrs, smc9000_probe_addr, GENERIC_ISAPNP_VENDOR, 0x8228 ); DRIVER ( "SMC9000", nic_driver, isa_driver, smc9000_driver, - smc9000_probe, smc9000_disable ); + smc9000_probe, smc9000_disable, no_fake_bss ); ISA_ROM ( "smc9000", "SMC9000" ); diff --git a/src/drivers/net/sundance.c b/src/drivers/net/sundance.c index 0439c983f..964365ef6 100644 --- a/src/drivers/net/sundance.c +++ b/src/drivers/net/sundance.c @@ -233,10 +233,11 @@ static struct netdev_desc rx_ring[RX_RING_SIZE]; /* Create a static buffer of size PKT_BUF_SZ for each RX and TX descriptor. All descriptors point to a part of this buffer */ -struct { +struct sundance_bss { unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE]; unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ]; -} rx_tx_buf __shared; +}; +#define rx_tx_buf NIC_FAKE_BSS ( struct sundance_bss ) #define rxb rx_tx_buf.rxb #define txb rx_tx_buf.txb @@ -888,7 +889,7 @@ static struct pci_device_id sundance_nics[] = { PCI_DRIVER ( sundance_driver, sundance_nics, PCI_NO_CLASS ); DRIVER ( "SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver, - sundance_probe, sundance_disable ); + sundance_probe, sundance_disable, rx_tx_buf ); /* * Local variables: diff --git a/src/drivers/net/tlan.c b/src/drivers/net/tlan.c index 245766a87..01193006f 100644 --- a/src/drivers/net/tlan.c +++ b/src/drivers/net/tlan.c @@ -179,12 +179,13 @@ struct TLanList { } buffer[TLAN_BUFFERS_PER_LIST]; }; -struct { +struct tlan_bss { struct TLanList tx_ring[TLAN_NUM_TX_LISTS]; unsigned char txb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_TX_LISTS]; struct TLanList rx_ring[TLAN_NUM_RX_LISTS]; unsigned char rxb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_RX_LISTS]; -} tlan_buffers __shared; +}; +#define tlan_buffers NIC_FAKE_BSS ( struct tlan_bss ) #define tx_ring tlan_buffers.tx_ring #define txb tlan_buffers.txb #define rx_ring tlan_buffers.rx_ring @@ -1715,7 +1716,7 @@ static struct pci_device_id tlan_nics[] = { PCI_DRIVER ( tlan_driver, tlan_nics, PCI_NO_CLASS ); DRIVER ( "TLAN/PCI", nic_driver, pci_driver, tlan_driver, - tlan_probe, tlan_disable ); + tlan_probe, tlan_disable, tlan_buffers ); /* * Local variables: diff --git a/src/drivers/net/tulip.c b/src/drivers/net/tulip.c index c01bc208e..1030e3698 100644 --- a/src/drivers/net/tulip.c +++ b/src/drivers/net/tulip.c @@ -426,13 +426,14 @@ struct tulip_private { #define TX_RING_SIZE 2 #define RX_RING_SIZE 4 -struct { +struct tulip_bss { struct tulip_tx_desc tx_ring[TX_RING_SIZE]; unsigned char txb[BUFLEN]; struct tulip_rx_desc rx_ring[RX_RING_SIZE]; unsigned char rxb[RX_RING_SIZE * BUFLEN]; struct tulip_private tpx; -} tulip_bss __shared __attribute__ ((aligned(4))); +}; +#define tulip_bss NIC_FAKE_BSS ( struct tulip_bss ) #define tx_ring tulip_bss.tx_ring #define txb tulip_bss.txb #define rx_ring tulip_bss.rx_ring @@ -1958,7 +1959,7 @@ PCI_ROM(0x8086, 0x0039, "intel21145", "Intel Tulip", 0), PCI_DRIVER ( tulip_driver, tulip_nics, PCI_NO_CLASS ); DRIVER ( "Tulip", nic_driver, pci_driver, tulip_driver, - tulip_probe, tulip_disable ); + tulip_probe, tulip_disable, tulip_bss ); /* * Local variables: diff --git a/src/drivers/net/w89c840.c b/src/drivers/net/w89c840.c index 0c222214e..33a6658d2 100644 --- a/src/drivers/net/w89c840.c +++ b/src/drivers/net/w89c840.c @@ -254,10 +254,11 @@ static struct winbond_private static int ioaddr; static unsigned short eeprom [0x40]; -struct { +struct w89c840_bss { char rx_packet[PKT_BUF_SZ * RX_RING_SIZE]; char tx_packet[PKT_BUF_SZ * TX_RING_SIZE]; -} w89c840_buf __shared; +}; +#define w89c840_buf NIC_FAKE_BSS ( struct w89c840_bss ) static int eeprom_read(long ioaddr, int location); static int mdio_read(int base_address, int phy_id, int location); @@ -956,7 +957,7 @@ static void init_ring(void) DRIVER ( "W89C840F", nic_driver, pci_driver, w89c840_driver, - w89c840_probe, w89c840_disable ); + w89c840_probe, w89c840_disable, w89c840_buf ); /* * Local variables: diff --git a/src/include/compiler.h b/src/include/compiler.h index ec03f6f96..f8e948829 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -623,28 +623,6 @@ char __debug_disable(OBJECT) = ( DBGLVL_MAX & ~DBGLVL_DFLT ); */ #define inline inline __attribute__ (( no_instrument_function )) -/** - * Shared data. - * - * To save space in the binary when multiple-driver images are - * compiled, uninitialised data areas can be shared between drivers. - * This will typically be used to share statically-allocated receive - * and transmit buffers between drivers. - * - * Use as e.g. - * - * @code - * - * struct { - * char rx_buf[NUM_RX_BUF][RX_BUF_SIZE]; - * char tx_buf[TX_BUF_SIZE]; - * } my_static_data __shared; - * - * @endcode - * - */ -#define __shared __asm__ ( "_shared_bss" ) __aligned - #endif /* ASSEMBLY */ /** @} */ diff --git a/src/include/nic.h b/src/include/nic.h index 678e23075..779d1d394 100644 --- a/src/include/nic.h +++ b/src/include/nic.h @@ -57,8 +57,14 @@ struct nic { unsigned int mbps; duplex_t duplex; void *priv_data; /* driver private data */ + void *fake_bss; + size_t fake_bss_len; }; +#define NIC_FAKE_BSS_PTR( type ) ( ( type * ) legacy_nic.fake_bss ) +#define NIC_FAKE_BSS( type ) ( * NIC_FAKE_BSS_PTR ( type ) ) +extern struct {} no_fake_bss; + struct nic_operations { int ( *connect ) ( struct nic * ); int ( *poll ) ( struct nic *, int retrieve ); @@ -90,7 +96,8 @@ extern int legacy_probe ( void *hwdev, void ( * set_drvdata ) ( void *hwdev, void *priv ), struct device *dev, int ( * probe ) ( struct nic *nic, void *hwdev ), - void ( * disable ) ( struct nic *nic, void *hwdev )); + void ( * disable ) ( struct nic *nic, void *hwdev ), + size_t fake_bss_len ); void legacy_remove ( void *hwdev, void * ( * get_drvdata ) ( void *hwdev ), void ( * disable ) ( struct nic *nic, void *hwdev ) ); @@ -210,7 +217,8 @@ static inline void * legacy_isa_get_drvdata ( void *hwdev ) { } #undef DRIVER -#define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable) \ +#define DRIVER( _name_text, _unused2, _unused3, _name, _probe, _disable, \ + _fake_bss ) \ static __attribute__ (( unused )) const char \ _name ## _text[] = _name_text; \ static inline int \ @@ -225,7 +233,8 @@ static inline void * legacy_isa_get_drvdata ( void *hwdev ) { _name ## _pci_legacy_probe ( struct pci_device *pci ) { \ return legacy_probe ( pci, legacy_pci_set_drvdata, \ &pci->dev, _name ## _probe, \ - _name ## _disable ); \ + _name ## _disable, \ + sizeof ( _fake_bss ) ); \ } \ static inline void \ _name ## _pci_legacy_remove ( struct pci_device *pci ) { \ @@ -237,7 +246,8 @@ static inline void * legacy_isa_get_drvdata ( void *hwdev ) { const struct isapnp_device_id *id __unused ) { \ return legacy_probe ( isapnp, legacy_isapnp_set_drvdata, \ &isapnp->dev, _name ## _probe, \ - _name ## _disable ); \ + _name ## _disable, \ + sizeof ( _fake_bss ) ); \ } \ static inline void \ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \ @@ -249,7 +259,8 @@ static inline void * legacy_isa_get_drvdata ( void *hwdev ) { const struct eisa_device_id *id __unused ) { \ return legacy_probe ( eisa, legacy_eisa_set_drvdata, \ &eisa->dev, _name ## _probe, \ - _name ## _disable ); \ + _name ## _disable, \ + sizeof ( _fake_bss ) ); \ } \ static inline void \ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ) { \ @@ -261,7 +272,8 @@ static inline void * legacy_isa_get_drvdata ( void *hwdev ) { const struct mca_device_id *id __unused ) { \ return legacy_probe ( mca, legacy_mca_set_drvdata, \ &mca->dev, _name ## _probe, \ - _name ## _disable ); \ + _name ## _disable, \ + sizeof ( _fake_bss ) ); \ } \ static inline void \ _name ## _mca_legacy_remove ( struct mca_device *mca ) { \ @@ -272,7 +284,8 @@ static inline void * legacy_isa_get_drvdata ( void *hwdev ) { _name ## _isa_legacy_probe ( struct isa_device *isa ) { \ return legacy_probe ( isa, legacy_isa_set_drvdata, \ &isa->dev, _name ## _probe, \ - _name ## _disable ); \ + _name ## _disable, \ + sizeof ( _fake_bss ) ); \ } \ static inline void \ _name ## _isa_legacy_remove ( struct isa_device *isa ) { \ -- cgit v1.2.3-55-g7522 From e61c636bf358a2c8b53290bacf16f73e0c548781 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 13 Jan 2026 13:49:27 +0000 Subject: [build] Define a mechanism for marking Secure Boot permissibility Not all files within the iPXE codebase are allowed to be included in UEFI Secure Boot signed builds. Following the pattern used by the existing FILE_LICENCE() macro and licensing check: define a FILE_SECBOOT() macro that can be used to declare a file as being permitted (or forbidden) in a UEFI Secure Boot signed build, and a corresponding build target to perform the check. Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 41 +++++++++++++++++++++++++++++++++-------- src/include/compiler.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) (limited to 'src/include/compiler.h') diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 7a965130e..f56766cd6 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -1299,15 +1299,17 @@ endef $(BIN)/%.nodeps : $(BIN)/%.tmp $(Q)$(ECHO) $(call nodeps_list,$<) -# Get licensing verdict for the specified target -# -define licensable_deps_list +# Get annotated dependency list for the specified target +define annotated_deps_list $(filter-out config/local/%.h,\ $(filter-out $(BIN)/.%.list,\ $(call deps_list,$(1)))) endef + +# Get licensing verdict for the specified target +# define unlicensed_deps_list - $(shell grep -L FILE_LICENCE $(call licensable_deps_list,$(1))) + $(shell grep -L FILE_LICENCE $(call annotated_deps_list,$(1))) endef define licence_list $(sort $(foreach LICENCE,\ @@ -1319,11 +1321,34 @@ $(BIN)/%.licence_list : $(BIN)/%.tmp $(BIN)/%.licence : $(BIN)/%.tmp $(QM)$(ECHO) " [LICENCE] $@" $(Q)$(if $(strip $(call unlicensed_deps_list,$<)),\ - echo -n "Unable to determine licence because the following " ;\ - echo "files are missing a licence declaration:" ;\ + echo -n "The following files are missing a FILE_LICENCE() " ;\ + echo "declaration:" ;\ echo $(call unlicensed_deps_list,$<);\ - exit 1,\ - $(PERL) $(LICENCE) $(call licence_list,$<)) + exit 1) + $(PERL) $(LICENCE) $(call licence_list,$<) + +# Get Secure Boot permissibility verdict for the specified target +# +define nosecboot_deps_list + $(shell grep -L FILE_SECBOOT $(call annotated_deps_list,$(1))) +endef +define secboot_list + $(sort $(foreach SECBOOT,\ + $(filter __secboot__%,$(shell $(NM) $(1) | cut -d" " -f3)),\ + $(word 2,$(subst __, ,$(SECBOOT))))) +endef +$(BIN)/%.secboot : $(BIN)/%.tmp + $(QM)$(ECHO) " [SECBOOT] $@" + $(Q)$(if $(strip $(call nosecboot_deps_list,$<)),\ + echo -n "The following files are missing a FILE_SECBOOT() " ;\ + echo "declaration:" ;\ + echo $(call nosecboot_deps_list,$<);\ + exit 1) + echo $(call secboot_list,$<) + $(Q)$(if $(strip $(filter-out permitted,$(call secboot_list,$<))),\ + echo -n "This build includes files that are not permitted " ;\ + echo "to be signed for UEFI Secure Boot" ;\ + exit 1) # Extract compression information from intermediate object file # diff --git a/src/include/compiler.h b/src/include/compiler.h index f8e948829..f6d0aa67d 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -900,6 +900,36 @@ char __debug_disable(OBJECT) = ( DBGLVL_MAX & ~DBGLVL_DFLT ); /* This file itself is under GPLv2+/UBDL */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +/** + * @defgroup secboot UEFI Secure Boot restrictions + * + * Not all files within the iPXE codebase are allowed to be included + * in UEFI Secure Boot signed builds. + * + * Files that are permitted in a UEFI Secure Boot build are subject to + * stricter code review requirements. In particular, contributions + * from third parties may not be marked as permitted unless they have + * passed an approved security review. + * + * @{ + */ + +/** Declare a file as being permitted in a UEFI Secure Boot build */ +#define FILE_SECBOOT_PERMITTED \ + PROVIDE_SYMBOL ( PREFIX_OBJECT ( __secboot__permitted__ ) ) + +/** Declare a file as being forbidden in a UEFI Secure Boot build */ +#define FILE_SECBOOT_FORBIDDEN \ + PROVIDE_SYMBOL ( PREFIX_OBJECT ( __secboot__forbidden__ ) ) + +/** Declare a file's UEFI Secure Boot permission status */ +#define FILE_SECBOOT( _status ) FILE_SECBOOT_ ## _status + +/** @} */ + +/* This file itself is permitted in a Secure Boot build */ +FILE_SECBOOT ( PERMITTED ); + #include #endif /* COMPILER_H */ -- cgit v1.2.3-55-g7522