From 9909e7b10ab9c2e1fd9b81eaac59fbaec76b9613 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 17 Apr 2013 19:36:03 +0100 Subject: [PATCH 01/45] [bios] Fix screen clearing on buggy BIOSes The implementation of INT 10,06 on some BIOSes (observed with both Hyper-V and a Dell OptiPlex 7010) seems to treat %dx=0xffff as a special value meaning "do absolutely nothing". Fix by using %dx=0xfefe, which should still be sufficient to cover any realistic screen size. Reported-by: John Clark Tested-by: John Clark Signed-off-by: Michael Brown --- src/arch/i386/firmware/pcbios/bios_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/i386/firmware/pcbios/bios_console.c b/src/arch/i386/firmware/pcbios/bios_console.c index 25c8dad2..213ebd92 100644 --- a/src/arch/i386/firmware/pcbios/bios_console.c +++ b/src/arch/i386/firmware/pcbios/bios_console.c @@ -97,7 +97,7 @@ static void bios_handle_ed ( unsigned int count __unused, "int $0x10\n\t" "cli\n\t" ) : : "a" ( 0x0600 ), "b" ( bios_attr << 8 ), - "c" ( 0 ), "d" ( 0xffff ) ); + "c" ( 0 ), "d" ( 0xfefe ) ); } /** From c2ba57e517031c751b93ffc59fa30ffa4d03ba0d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 3 Apr 2013 15:20:55 +0100 Subject: [PATCH 02/45] [intel] Remove hardcoded offsets for descriptor ring registers The Intel 10 Gigabit NICs use the same simplified (aka "legacy") descriptor format and the same layout for descriptor register blocks as the Intel 1 Gigabit NICs. The offsets of the descriptor register blocks are not the same. Simplify reuse of the existing code by removing all hardcoded offsets for registers within descriptor register blocks, and ensuring that all offsets are calculated using the descriptor register block base address provided via intel_init_ring(). Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 12 ++++++------ src/drivers/net/intel.h | 12 ------------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index ce17e9f2..2533fbee 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -248,10 +248,10 @@ static int intel_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) { static void __attribute__ (( unused )) intel_diag ( struct intel_nic *intel ) { DBGC ( intel, "INTEL %p TDH=%04x TDT=%04x RDH=%04x RDT=%04x\n", intel, - readl ( intel->regs + INTEL_TDH ), - readl ( intel->regs + INTEL_TDT ), - readl ( intel->regs + INTEL_RDH ), - readl ( intel->regs + INTEL_RDT ) ); + readl ( intel->regs + intel->tx.reg + INTEL_xDH ), + readl ( intel->regs + intel->tx.reg + INTEL_xDT ), + readl ( intel->regs + intel->rx.reg + INTEL_xDH ), + readl ( intel->regs + intel->rx.reg + INTEL_xDT ) ); } /****************************************************************************** @@ -468,7 +468,7 @@ static void intel_refill_rx ( struct intel_nic *intel ) { intel->rx_iobuf[rx_idx] = iobuf; /* Push descriptor to card */ - writel ( rx_tail, intel->regs + INTEL_RDT ); + writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT ); DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx, ( ( unsigned long long ) address ), @@ -599,7 +599,7 @@ static int intel_transmit ( struct net_device *netdev, wmb(); /* Notify card that there are packets ready to transmit */ - writel ( tx_tail, intel->regs + INTEL_TDT ); + writel ( tx_tail, intel->regs + intel->tx.reg + INTEL_xDT ); DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx, ( ( unsigned long long ) address ), diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h index e9e9052b..18a86ea3 100644 --- a/src/drivers/net/intel.h +++ b/src/drivers/net/intel.h @@ -175,18 +175,6 @@ enum intel_descriptor_status { #define INTEL_xDCTL 0x28 #define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */ -/** Receive Descriptor Head */ -#define INTEL_RDH ( INTEL_RD + INTEL_xDH ) - -/** Receive Descriptor Tail */ -#define INTEL_RDT ( INTEL_RD + INTEL_xDT ) - -/** Transmit Descriptor Head */ -#define INTEL_TDH ( INTEL_TD + INTEL_xDH ) - -/** Transmit Descriptor Tail */ -#define INTEL_TDT ( INTEL_TD + INTEL_xDT ) - /** Receive Address Low */ #define INTEL_RAL0 0x05400UL From 1dd4e510632ed08130890b6eab9a17ff5fb06d37 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 3 Apr 2013 15:21:03 +0100 Subject: [PATCH 03/45] [intel] Expose functionality to be shared with intelx driver The Intel 10 Gigabit NICs have a datapath that is almost register-compatible with the Intel 1 Gigabit NICs. Expose common functionality to avoid duplication of code in the new "intelx" driver. Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 37 ++++++++++++++++++++++--------------- src/drivers/net/intel.h | 11 +++++++++++ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 2533fbee..c3a7d407 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -360,8 +360,7 @@ static void intel_check_link ( struct net_device *netdev ) { * @v ring Descriptor ring * @ret rc Return status code */ -static int intel_create_ring ( struct intel_nic *intel, - struct intel_ring *ring ) { +int intel_create_ring ( struct intel_nic *intel, struct intel_ring *ring ) { physaddr_t address; uint32_t dctl; @@ -412,8 +411,7 @@ static int intel_create_ring ( struct intel_nic *intel, * @v intel Intel device * @v ring Descriptor ring */ -static void intel_destroy_ring ( struct intel_nic *intel, - struct intel_ring *ring ) { +void intel_destroy_ring ( struct intel_nic *intel, struct intel_ring *ring ) { /* Clear ring length */ writel ( 0, ( intel->regs + ring->reg + INTEL_xDLEN ) ); @@ -434,7 +432,7 @@ static void intel_destroy_ring ( struct intel_nic *intel, * * @v intel Intel device */ -static void intel_refill_rx ( struct intel_nic *intel ) { +void intel_refill_rx ( struct intel_nic *intel ) { struct intel_descriptor *rx; struct io_buffer *iobuf; unsigned int rx_idx; @@ -476,6 +474,21 @@ static void intel_refill_rx ( struct intel_nic *intel ) { } } +/** + * Discard unused receive I/O buffers + * + * @v intel Intel device + */ +void intel_empty_rx ( struct intel_nic *intel ) { + unsigned int i; + + for ( i = 0 ; i < INTEL_NUM_RX_DESC ; i++ ) { + if ( intel->rx_iobuf[i] ) + free_iob ( intel->rx_iobuf[i] ); + intel->rx_iobuf[i] = NULL; + } +} + /** * Open network device * @@ -540,7 +553,6 @@ static int intel_open ( struct net_device *netdev ) { */ static void intel_close ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; - unsigned int i; /* Disable receiver */ writel ( 0, intel->regs + INTEL_RCTL ); @@ -552,11 +564,7 @@ static void intel_close ( struct net_device *netdev ) { intel_destroy_ring ( intel, &intel->rx ); /* Discard any unused receive buffers */ - for ( i = 0 ; i < INTEL_NUM_RX_DESC ; i++ ) { - if ( intel->rx_iobuf[i] ) - free_iob ( intel->rx_iobuf[i] ); - intel->rx_iobuf[i] = NULL; - } + intel_empty_rx ( intel ); /* Destroy transmit descriptor ring */ intel_destroy_ring ( intel, &intel->tx ); @@ -572,8 +580,7 @@ static void intel_close ( struct net_device *netdev ) { * @v iobuf I/O buffer * @ret rc Return status code */ -static int intel_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { +int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct intel_nic *intel = netdev->priv; struct intel_descriptor *tx; unsigned int tx_idx; @@ -613,7 +620,7 @@ static int intel_transmit ( struct net_device *netdev, * * @v netdev Network device */ -static void intel_poll_tx ( struct net_device *netdev ) { +void intel_poll_tx ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; struct intel_descriptor *tx; unsigned int tx_idx; @@ -642,7 +649,7 @@ static void intel_poll_tx ( struct net_device *netdev ) { * * @v netdev Network device */ -static void intel_poll_rx ( struct net_device *netdev ) { +void intel_poll_rx ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; struct intel_descriptor *rx; struct io_buffer *iobuf; diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h index 18a86ea3..20b4255e 100644 --- a/src/drivers/net/intel.h +++ b/src/drivers/net/intel.h @@ -242,4 +242,15 @@ struct intel_nic { struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC]; }; +extern int intel_create_ring ( struct intel_nic *intel, + struct intel_ring *ring ); +extern void intel_destroy_ring ( struct intel_nic *intel, + struct intel_ring *ring ); +extern void intel_refill_rx ( struct intel_nic *intel ); +extern void intel_empty_rx ( struct intel_nic *intel ); +extern int intel_transmit ( struct net_device *netdev, + struct io_buffer *iobuf ); +extern void intel_poll_tx ( struct net_device *netdev ); +extern void intel_poll_rx ( struct net_device *netdev ); + #endif /* _INTEL_H */ From cdca99f06841a58bfb796ea98b5926e1549eeb36 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 3 Apr 2013 15:21:08 +0100 Subject: [PATCH 04/45] [intel] Add intelx driver for Intel 10 Gigabit Ethernet NICs Signed-off-by: Michael Brown --- src/drivers/net/intelx.c | 465 +++++++++++++++++++++++++++++++++++++ src/drivers/net/intelx.h | 114 +++++++++ src/include/ipxe/errfile.h | 1 + 3 files changed, 580 insertions(+) create mode 100644 src/drivers/net/intelx.c create mode 100644 src/drivers/net/intelx.h diff --git a/src/drivers/net/intelx.c b/src/drivers/net/intelx.c new file mode 100644 index 00000000..e60f36b6 --- /dev/null +++ b/src/drivers/net/intelx.c @@ -0,0 +1,465 @@ +/* + * Copyright (C) 2013 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "intelx.h" + +/** @file + * + * Intel 10 Gigabit Ethernet network card driver + * + */ + +/****************************************************************************** + * + * MAC address + * + ****************************************************************************** + */ + +/** + * Try to fetch initial MAC address + * + * @v intel Intel device + * @v ral0 RAL0 register address + * @v hw_addr Hardware address to fill in + * @ret rc Return status code + */ +static int intelx_try_fetch_mac ( struct intel_nic *intel, unsigned int ral0, + uint8_t *hw_addr ) { + union intel_receive_address mac; + + /* Read current address from RAL0/RAH0 */ + mac.reg.low = cpu_to_le32 ( readl ( intel->regs + ral0 ) ); + mac.reg.high = cpu_to_le32 ( readl ( intel->regs + ral0 + + ( INTELX_RAH0 - INTELX_RAL0 ) ) ); + + /* Use current address if valid */ + if ( is_valid_ether_addr ( mac.raw ) ) { + DBGC ( intel, "INTEL %p has autoloaded MAC address %s at " + "%#05x\n", intel, eth_ntoa ( mac.raw ), ral0 ); + memcpy ( hw_addr, mac.raw, ETH_ALEN ); + return 0; + } + + return -ENOENT; +} + +/** + * Fetch initial MAC address + * + * @v intel Intel device + * @v hw_addr Hardware address to fill in + * @ret rc Return status code + */ +static int intelx_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) { + int rc; + + /* Try to fetch address from INTELX_RAL0 */ + if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0, + hw_addr ) ) == 0 ) { + return 0; + } + + /* Try to fetch address from INTELX_RAL0_ALT */ + if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0_ALT, + hw_addr ) ) == 0 ) { + return 0; + } + + DBGC ( intel, "INTEL %p has no MAC address to use\n", intel ); + return -ENOENT; +} + +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ + +/** + * Reset hardware + * + * @v intel Intel device + * @ret rc Return status code + */ +static int intelx_reset ( struct intel_nic *intel ) { + uint32_t ctrl; + + /* Perform a global software reset */ + ctrl = readl ( intel->regs + INTELX_CTRL ); + writel ( ( ctrl | INTELX_CTRL_RST | INTELX_CTRL_LRST ), + intel->regs + INTELX_CTRL ); + mdelay ( INTELX_RESET_DELAY_MS ); + + DBGC ( intel, "INTEL %p reset (ctrl %08x)\n", intel, ctrl ); + return 0; +} + +/****************************************************************************** + * + * Link state + * + ****************************************************************************** + */ + +/** + * Check link state + * + * @v netdev Network device + */ +static void intelx_check_link ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t links; + + /* Read link status */ + links = readl ( intel->regs + INTELX_LINKS ); + DBGC ( intel, "INTEL %p link status is %08x\n", intel, links ); + + /* Update network device */ + if ( links & INTELX_LINKS_UP ) { + netdev_link_up ( netdev ); + } else { + netdev_link_down ( netdev ); + } +} + +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int intelx_open ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + union intel_receive_address mac; + uint32_t ral0; + uint32_t rah0; + uint32_t dmatxctl; + uint32_t fctrl; + uint32_t srrctl; + uint32_t hlreg0; + uint32_t maxfrs; + uint32_t rdrxctl; + uint32_t rxctrl; + uint32_t dca_rxctrl; + int rc; + + /* Create transmit descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 ) + goto err_create_tx; + + /* Create receive descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 ) + goto err_create_rx; + + /* Program MAC address */ + memset ( &mac, 0, sizeof ( mac ) ); + memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) ); + ral0 = le32_to_cpu ( mac.reg.low ); + rah0 = ( le32_to_cpu ( mac.reg.high ) | INTELX_RAH0_AV ); + writel ( ral0, intel->regs + INTELX_RAL0 ); + writel ( rah0, intel->regs + INTELX_RAH0 ); + writel ( ral0, intel->regs + INTELX_RAL0_ALT ); + writel ( rah0, intel->regs + INTELX_RAH0_ALT ); + + /* Allocate interrupt vectors */ + writel ( ( INTELX_IVAR_RX0_DEFAULT | INTELX_IVAR_RX0_VALID | + INTELX_IVAR_TX0_DEFAULT | INTELX_IVAR_TX0_VALID ), + intel->regs + INTELX_IVAR ); + + /* Enable transmitter */ + dmatxctl = readl ( intel->regs + INTELX_DMATXCTL ); + dmatxctl |= INTELX_DMATXCTL_TE; + writel ( dmatxctl, intel->regs + INTELX_DMATXCTL ); + + /* Configure receive filter */ + fctrl = readl ( intel->regs + INTELX_FCTRL ); + fctrl |= ( INTELX_FCTRL_BAM | INTELX_FCTRL_UPE | INTELX_FCTRL_MPE ); + writel ( fctrl, intel->regs + INTELX_FCTRL ); + + /* Configure receive buffer sizes */ + srrctl = readl ( intel->regs + INTELX_SRRCTL ); + srrctl &= ~INTELX_SRRCTL_BSIZE_MASK; + srrctl |= INTELX_SRRCTL_BSIZE_DEFAULT; + writel ( srrctl, intel->regs + INTELX_SRRCTL ); + + /* Configure jumbo frames. Required to allow the extra 4-byte + * headroom for VLANs, since we don't use the hardware's + * native VLAN offload. + */ + hlreg0 = readl ( intel->regs + INTELX_HLREG0 ); + hlreg0 |= INTELX_HLREG0_JUMBOEN; + writel ( hlreg0, intel->regs + INTELX_HLREG0 ); + + /* Configure frame size */ + maxfrs = readl ( intel->regs + INTELX_MAXFRS ); + maxfrs &= ~INTELX_MAXFRS_MFS_MASK; + maxfrs |= INTELX_MAXFRS_MFS_DEFAULT; + writel ( maxfrs, intel->regs + INTELX_MAXFRS ); + + /* Configure receive DMA */ + rdrxctl = readl ( intel->regs + INTELX_RDRXCTL ); + rdrxctl |= INTELX_RDRXCTL_SECRC; + writel ( rdrxctl, intel->regs + INTELX_RDRXCTL ); + + /* Clear "must-be-zero" bit for direct cache access (DCA). We + * leave DCA disabled anyway, but if we do not clear this bit + * then the received packets contain garbage data. + */ + dca_rxctrl = readl ( intel->regs + INTELX_DCA_RXCTRL ); + dca_rxctrl &= ~INTELX_DCA_RXCTRL_MUST_BE_ZERO; + writel ( dca_rxctrl, intel->regs + INTELX_DCA_RXCTRL ); + + /* Enable receiver */ + rxctrl = readl ( intel->regs + INTELX_RXCTRL ); + rxctrl |= INTELX_RXCTRL_RXEN; + writel ( rxctrl, intel->regs + INTELX_RXCTRL ); + + /* Fill receive ring */ + intel_refill_rx ( intel ); + + /* Update link state */ + intelx_check_link ( netdev ); + + return 0; + + intel_destroy_ring ( intel, &intel->rx ); + err_create_rx: + intel_destroy_ring ( intel, &intel->tx ); + err_create_tx: + return rc; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void intelx_close ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t rxctrl; + uint32_t dmatxctl; + + /* Disable receiver */ + rxctrl = readl ( intel->regs + INTELX_RXCTRL ); + rxctrl &= ~INTELX_RXCTRL_RXEN; + writel ( rxctrl, intel->regs + INTELX_RXCTRL ); + + /* Disable transmitter */ + dmatxctl = readl ( intel->regs + INTELX_DMATXCTL ); + dmatxctl &= ~INTELX_DMATXCTL_TE; + writel ( dmatxctl, intel->regs + INTELX_DMATXCTL ); + + /* Destroy receive descriptor ring */ + intel_destroy_ring ( intel, &intel->rx ); + + /* Discard any unused receive buffers */ + intel_empty_rx ( intel ); + + /* Destroy transmit descriptor ring */ + intel_destroy_ring ( intel, &intel->tx ); + + /* Reset the NIC, to flush the transmit and receive FIFOs */ + intelx_reset ( intel ); +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void intelx_poll ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t eicr; + + /* Check for and acknowledge interrupts */ + eicr = readl ( intel->regs + INTELX_EICR ); + if ( ! eicr ) + return; + + /* Poll for TX completions, if applicable */ + if ( eicr & INTELX_EIRQ_TX0 ) + intel_poll_tx ( netdev ); + + /* Poll for RX completions, if applicable */ + if ( eicr & ( INTELX_EIRQ_RX0 | INTELX_EIRQ_RXO ) ) + intel_poll_rx ( netdev ); + + /* Report receive overruns */ + if ( eicr & INTELX_EIRQ_RXO ) + netdev_rx_err ( netdev, NULL, -ENOBUFS ); + + /* Check link state, if applicable */ + if ( eicr & INTELX_EIRQ_LSC ) + intelx_check_link ( netdev ); + + /* Refill RX ring */ + intel_refill_rx ( intel ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void intelx_irq ( struct net_device *netdev, int enable ) { + struct intel_nic *intel = netdev->priv; + uint32_t mask; + + mask = ( INTELX_EIRQ_LSC | INTELX_EIRQ_RXO | INTELX_EIRQ_TX0 | + INTELX_EIRQ_RX0 ); + if ( enable ) { + writel ( mask, intel->regs + INTELX_EIMS ); + } else { + writel ( mask, intel->regs + INTELX_EIMC ); + } +} + +/** Network device operations */ +static struct net_device_operations intelx_operations = { + .open = intelx_open, + .close = intelx_close, + .transmit = intel_transmit, + .poll = intelx_poll, + .irq = intelx_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + +/** + * Probe PCI device + * + * @v pci PCI device + * @ret rc Return status code + */ +static int intelx_probe ( struct pci_device *pci ) { + struct net_device *netdev; + struct intel_nic *intel; + int rc; + + /* Allocate and initialise net device */ + netdev = alloc_etherdev ( sizeof ( *intel ) ); + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } + netdev_init ( netdev, &intelx_operations ); + intel = netdev->priv; + pci_set_drvdata ( pci, netdev ); + netdev->dev = &pci->dev; + memset ( intel, 0, sizeof ( *intel ) ); + intel->port = PCI_FUNC ( pci->busdevfn ); + intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELX_TD ); + intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELX_RD ); + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE ); + + /* Reset the NIC */ + if ( ( rc = intelx_reset ( intel ) ) != 0 ) + goto err_reset; + + /* Fetch MAC address */ + if ( ( rc = intelx_fetch_mac ( intel, netdev->hw_addr ) ) != 0 ) + goto err_fetch_mac; + + /* Register network device */ + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register_netdev; + + /* Set initial link state */ + intelx_check_link ( netdev ); + + return 0; + + unregister_netdev ( netdev ); + err_register_netdev: + err_fetch_mac: + intelx_reset ( intel ); + err_reset: + iounmap ( intel->regs ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void intelx_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct intel_nic *intel = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset the NIC */ + intelx_reset ( intel ); + + /* Free network device */ + iounmap ( intel->regs ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** PCI device IDs */ +static struct pci_device_id intelx_nics[] = { + PCI_ROM ( 0x8086, 0x10fb, "82599", "82599", 0 ), +}; + +/** PCI driver */ +struct pci_driver intelx_driver __pci_driver = { + .ids = intelx_nics, + .id_count = ( sizeof ( intelx_nics ) / sizeof ( intelx_nics[0] ) ), + .probe = intelx_probe, + .remove = intelx_remove, +}; diff --git a/src/drivers/net/intelx.h b/src/drivers/net/intelx.h new file mode 100644 index 00000000..60bb294d --- /dev/null +++ b/src/drivers/net/intelx.h @@ -0,0 +1,114 @@ +#ifndef _INTELX_H +#define _INTELX_H + +/** @file + * + * Intel 10 Gigabit Ethernet network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include "intel.h" + +/** Device Control Register */ +#define INTELX_CTRL 0x00000UL +#define INTELX_CTRL_LRST 0x00000008UL /**< Link reset */ +#define INTELX_CTRL_RST 0x04000000UL /**< Device reset */ + +/** Time to delay for device reset, in milliseconds */ +#define INTELX_RESET_DELAY_MS 20 + +/** Extended Interrupt Cause Read Register */ +#define INTELX_EICR 0x00800UL +#define INTELX_EIRQ_RX0 0x00000001UL /**< RX0 (via IVAR) */ +#define INTELX_EIRQ_TX0 0x00000002UL /**< RX0 (via IVAR) */ +#define INTELX_EIRQ_RXO 0x00020000UL /**< Receive overrun */ +#define INTELX_EIRQ_LSC 0x00100000UL /**< Link status change */ + +/** Interrupt Mask Set/Read Register */ +#define INTELX_EIMS 0x00880UL + +/** Interrupt Mask Clear Register */ +#define INTELX_EIMC 0x00888UL + +/** Interrupt Vector Allocation Register */ +#define INTELX_IVAR 0x00900UL +#define INTELX_IVAR_RX0(bit) ( (bit) << 0 ) /**< RX queue 0 allocation */ +#define INTELX_IVAR_RX0_DEFAULT INTELX_IVAR_RX0 ( 0x00 ) +#define INTELX_IVAR_RX0_MASK INTELX_IVAR_RX0 ( 0x3f ) +#define INTELX_IVAR_RX0_VALID 0x00000080UL /**< RX queue 0 valid */ +#define INTELX_IVAR_TX0(bit) ( (bit) << 8 ) /**< TX queue 0 allocation */ +#define INTELX_IVAR_TX0_DEFAULT INTELX_IVAR_TX0 ( 0x01 ) +#define INTELX_IVAR_TX0_MASK INTELX_IVAR_TX0 ( 0x3f ) +#define INTELX_IVAR_TX0_VALID 0x00008000UL /**< TX queue 0 valid */ + +/** Receive Filter Control Register */ +#define INTELX_FCTRL 0x05080UL +#define INTELX_FCTRL_MPE 0x00000100UL /**< Multicast promiscuous */ +#define INTELX_FCTRL_UPE 0x00000200UL /**< Unicast promiscuous mode */ +#define INTELX_FCTRL_BAM 0x00000400UL /**< Broadcast accept mode */ + +/** Receive Address Low + * + * The MAC address registers RAL0/RAH0 exist at address 0x05400 for + * the 82598 and 0x0a200 for the 82599, according to the datasheet. + * In practice, the 82599 seems to also provide a copy of these + * registers at 0x05400. To aim for maximum compatibility, we try + * both addresses when reading the initial MAC address, and set both + * addresses when setting the MAC address. + */ +#define INTELX_RAL0 0x05400UL +#define INTELX_RAL0_ALT 0x0a200UL + +/** Receive Address High */ +#define INTELX_RAH0 0x05404UL +#define INTELX_RAH0_ALT 0x0a204UL +#define INTELX_RAH0_AV 0x80000000UL /**< Address valid */ + +/** Receive Descriptor register block */ +#define INTELX_RD 0x01000UL + +/** Split Receive Control Register */ +#define INTELX_SRRCTL 0x02100UL +#define INTELX_SRRCTL_BSIZE(kb) ( (kb) << 0 ) /**< Receive buffer size */ +#define INTELX_SRRCTL_BSIZE_DEFAULT INTELX_SRRCTL_BSIZE ( 0x02 ) +#define INTELX_SRRCTL_BSIZE_MASK INTELX_SRRCTL_BSIZE ( 0x1f ) + +/** Receive DMA Control Register */ +#define INTELX_RDRXCTL 0x02f00UL +#define INTELX_RDRXCTL_SECRC 0x00000001UL /**< Strip CRC */ + +/** Receive Control Register */ +#define INTELX_RXCTRL 0x03000UL +#define INTELX_RXCTRL_RXEN 0x00000001UL /**< Receive enable */ + +/** Transmit DMA Control Register */ +#define INTELX_DMATXCTL 0x04a80UL +#define INTELX_DMATXCTL_TE 0x00000001UL /**< Transmit enable */ + +/** Transmit Descriptor register block */ +#define INTELX_TD 0x06000UL + +/** RX DCA Control Register */ +#define INTELX_DCA_RXCTRL 0x02200UL +#define INTELX_DCA_RXCTRL_MUST_BE_ZERO 0x00001000UL /**< Must be zero */ + +/** MAC Core Control 0 Register */ +#define INTELX_HLREG0 0x04240UL +#define INTELX_HLREG0_JUMBOEN 0x00000004UL /**< Jumbo frame enable */ + +/** Maximum Frame Size Register */ +#define INTELX_MAXFRS 0x04268UL +#define INTELX_MAXFRS_MFS(len) ( (len) << 16 ) /**< Maximum frame size */ +#define INTELX_MAXFRS_MFS_DEFAULT \ + INTELX_MAXFRS_MFS ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ ) +#define INTELX_MAXFRS_MFS_MASK INTELX_MAXFRS_MFS ( 0xffff ) + +/** Link Status Register */ +#define INTELX_LINKS 0x042a4UL +#define INTELX_LINKS_UP 0x40000000UL /**< Link up */ + +#endif /* _INTELX_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 514e1f8a..f906dbd5 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -148,6 +148,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_skeleton ( ERRFILE_DRIVER | 0x00640000 ) #define ERRFILE_intel ( ERRFILE_DRIVER | 0x00650000 ) #define ERRFILE_myson ( ERRFILE_DRIVER | 0x00660000 ) +#define ERRFILE_intelx ( ERRFILE_DRIVER | 0x00670000 ) #define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 ) #define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 ) From 0f7b3fa6f959d10c6fd0237d4c9f2accd6d85190 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 18 Apr 2013 16:50:13 +0100 Subject: [PATCH 05/45] [efi] Remove obsolete EFI I/O implementation using EFI_CPU_IO_PROTOCOL Signed-off-by: Michael Brown --- src/include/ipxe/efi/Protocol/CpuIo.h | 48 ------ src/include/ipxe/efi/Protocol/CpuIo2.h | 144 ---------------- src/include/ipxe/efi/efi_io.h | 180 -------------------- src/include/ipxe/io.h | 1 - src/interface/efi/efi_io.c | 218 ------------------------- 5 files changed, 591 deletions(-) delete mode 100644 src/include/ipxe/efi/Protocol/CpuIo.h delete mode 100644 src/include/ipxe/efi/Protocol/CpuIo2.h delete mode 100644 src/include/ipxe/efi/efi_io.h delete mode 100644 src/interface/efi/efi_io.c diff --git a/src/include/ipxe/efi/Protocol/CpuIo.h b/src/include/ipxe/efi/Protocol/CpuIo.h deleted file mode 100644 index 39b82b3b..00000000 --- a/src/include/ipxe/efi/Protocol/CpuIo.h +++ /dev/null @@ -1,48 +0,0 @@ -/** @file - This code abstracts the CPU IO Protocol which installed by some platform or chipset-specific - PEIM that abstracts the processor-visible I/O operations. - - Note: This is a runtime protocol and can be used by runtime drivers after ExitBootServices(). - It is different from the PI 1.2 CPU I/O 2 Protocol, which is a boot services only protocol - and may not be used by runtime drivers after ExitBootServices(). - -Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - @par Revision Reference: - CPU IO Protocol is defined in Framework of EFI CPU IO Protocol Spec - Version 0.9. - -**/ - -#ifndef _CPUIO_H_ -#define _CPUIO_H_ - -FILE_LICENCE ( BSD3 ); - -#include - -#define EFI_CPU_IO_PROTOCOL_GUID \ - { \ - 0xB0732526, 0x38C8, 0x4b40, {0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } \ - } - -// -// Framework CPU IO protocol structure is the same as CPU IO 2 protocol defined in PI 1.2 spec. -// However, there is a significant different between the Framework CPU I/O -// Protocol and the PI 1.2 CPU I/O 2 Protocol. The Framework one is a runtime -// protocol, which means it can be used by runtime drivers after ExitBootServices(). -// The PI one is not runtime safe, so it is a boot services only protocol and may -// not be used by runtime drivers after ExitBootServices(). -// -typedef EFI_CPU_IO2_PROTOCOL EFI_CPU_IO_PROTOCOL; - -extern EFI_GUID gEfiCpuIoProtocolGuid; - -#endif diff --git a/src/include/ipxe/efi/Protocol/CpuIo2.h b/src/include/ipxe/efi/Protocol/CpuIo2.h deleted file mode 100644 index aef8157d..00000000 --- a/src/include/ipxe/efi/Protocol/CpuIo2.h +++ /dev/null @@ -1,144 +0,0 @@ -/** @file - This files describes the CPU I/O 2 Protocol. - - This protocol provides an I/O abstraction for a system processor. This protocol - is used by a PCI root bridge I/O driver to perform memory-mapped I/O and I/O transactions. - The I/O or memory primitives can be used by the consumer of the protocol to materialize - bus-specific configuration cycles, such as the transitional configuration address and data - ports for PCI. Only drivers that require direct access to the entire system should use this - protocol. - - Note: This is a boot-services only protocol and it may not be used by runtime drivers after - ExitBootServices(). It is different from the Framework CPU I/O Protocol, which is a runtime - protocol and can be used by runtime drivers after ExitBootServices(). - - Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - @par Revision Reference: - This Protocol is defined in UEFI Platform Initialization Specification 1.2 - Volume 5: Standards - -**/ - -#ifndef __CPU_IO2_H__ -#define __CPU_IO2_H__ - -FILE_LICENCE ( BSD3 ); - -#define EFI_CPU_IO2_PROTOCOL_GUID \ - { \ - 0xad61f191, 0xae5f, 0x4c0e, {0xb9, 0xfa, 0xe8, 0x69, 0xd2, 0x88, 0xc6, 0x4f} \ - } - -typedef struct _EFI_CPU_IO2_PROTOCOL EFI_CPU_IO2_PROTOCOL; - -/// -/// Enumeration that defines the width of the I/O operation. -/// -typedef enum { - EfiCpuIoWidthUint8, - EfiCpuIoWidthUint16, - EfiCpuIoWidthUint32, - EfiCpuIoWidthUint64, - EfiCpuIoWidthFifoUint8, - EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, - EfiCpuIoWidthFifoUint64, - EfiCpuIoWidthFillUint8, - EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, - EfiCpuIoWidthFillUint64, - EfiCpuIoWidthMaximum -} EFI_CPU_IO_PROTOCOL_WIDTH; - -/** - Enables a driver to access registers in the PI CPU I/O space. - - The Io.Read() and Io.Write() functions enable a driver to access PCI controller - registers in the PI CPU I/O space. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number - of bytes moved is Width size * Count, starting at Address. - @param[in, out] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM)( - IN EFI_CPU_IO2_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -/// -/// Service for read and write accesses. -/// -typedef struct { - /// - /// This service provides the various modalities of memory and I/O read. - /// - EFI_CPU_IO_PROTOCOL_IO_MEM Read; - /// - /// This service provides the various modalities of memory and I/O write. - /// - EFI_CPU_IO_PROTOCOL_IO_MEM Write; -} EFI_CPU_IO_PROTOCOL_ACCESS; - -/// -/// Provides the basic memory and I/O interfaces that are used to abstract -/// accesses to devices in a system. -/// -struct _EFI_CPU_IO2_PROTOCOL { - /// - /// Enables a driver to access memory-mapped registers in the EFI system memory space. - /// - EFI_CPU_IO_PROTOCOL_ACCESS Mem; - /// - /// Enables a driver to access registers in the EFI CPU I/O space. - /// - EFI_CPU_IO_PROTOCOL_ACCESS Io; -}; - -extern EFI_GUID gEfiCpuIo2ProtocolGuid; - -#endif diff --git a/src/include/ipxe/efi/efi_io.h b/src/include/ipxe/efi/efi_io.h deleted file mode 100644 index 2ed96e10..00000000 --- a/src/include/ipxe/efi/efi_io.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef _IPXE_EFI_IO_H -#define _IPXE_EFI_IO_H - -/** @file - * - * iPXE I/O API for EFI - * - * EFI runs with flat physical addressing, so the various mappings - * between virtual addresses, I/O addresses and bus addresses are all - * no-ops. I/O is handled using the EFI_CPU_IO_PROTOCOL. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef IOAPI_EFI -#define IOAPI_PREFIX_efi -#else -#define IOAPI_PREFIX_efi __efi_ -#endif - -extern unsigned long long efi_ioread ( volatile void *io_addr, - size_t size ); -extern void efi_iowrite ( unsigned long long data, volatile void *io_addr, - size_t size ); -extern void efi_ioreads ( volatile void *io_addr, void *data, - size_t size, unsigned int count ); -extern void efi_iowrites ( volatile void *io_addr, const void *data, - size_t size, unsigned int count ); - -/* - * Physical<->Bus and Bus<->I/O address mappings - * - * EFI runs with flat physical addressing, so these are all no-ops. - * - */ - -static inline __always_inline unsigned long -IOAPI_INLINE ( efi, phys_to_bus ) ( unsigned long phys_addr ) { - return phys_addr; -} - -static inline __always_inline unsigned long -IOAPI_INLINE ( efi, bus_to_phys ) ( unsigned long bus_addr ) { - return bus_addr; -} - -static inline __always_inline void * -IOAPI_INLINE ( efi, ioremap ) ( unsigned long bus_addr, size_t len __unused ) { - return ( ( void * ) bus_addr ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, iounmap ) ( volatile const void *io_addr __unused ) { - /* Nothing to do */ -} - -static inline __always_inline unsigned long -IOAPI_INLINE ( efi, io_to_bus ) ( volatile const void *io_addr ) { - return ( ( unsigned long ) io_addr ); -} - -/* - * I/O functions - * - */ - -static inline __always_inline uint8_t -IOAPI_INLINE ( efi, readb ) ( volatile uint8_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint16_t -IOAPI_INLINE ( efi, readw ) ( volatile uint16_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint32_t -IOAPI_INLINE ( efi, readl ) ( volatile uint32_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint64_t -IOAPI_INLINE ( efi, readq ) ( volatile uint64_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writeb ) ( uint8_t data, volatile uint8_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writew ) ( uint16_t data, volatile uint16_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writel ) ( uint32_t data, volatile uint32_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writeq ) ( uint64_t data, volatile uint64_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint8_t -IOAPI_INLINE ( efi, inb ) ( volatile uint8_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint16_t -IOAPI_INLINE ( efi, inw ) ( volatile uint16_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint32_t -IOAPI_INLINE ( efi, inl ) ( volatile uint32_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outb ) ( uint8_t data, volatile uint8_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outw ) ( uint16_t data, volatile uint16_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outl ) ( uint32_t data, volatile uint32_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, insb ) ( volatile uint8_t *io_addr, uint8_t *data, - unsigned int count ) { - efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, insw ) ( volatile uint16_t *io_addr, uint16_t *data, - unsigned int count ) { - efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, insl ) ( volatile uint32_t *io_addr, uint32_t *data, - unsigned int count ) { - efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outsb ) ( volatile uint8_t *io_addr, const uint8_t *data, - unsigned int count ) { - efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outsw ) ( volatile uint16_t *io_addr, const uint16_t *data, - unsigned int count ) { - efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outsl ) ( volatile uint32_t *io_addr, const uint32_t *data, - unsigned int count ) { - efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, mb ) ( void ) { - /* Do nothing; EFI readl()/writel() calls already act as - * memory barriers. - */ -} - -#endif /* _IPXE_EFI_IO_H */ diff --git a/src/include/ipxe/io.h b/src/include/ipxe/io.h index b4d88fe8..b8b8aa31 100644 --- a/src/include/ipxe/io.h +++ b/src/include/ipxe/io.h @@ -53,7 +53,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func ) /* Include all architecture-independent I/O API headers */ -#include /* Include all architecture-dependent I/O API headers */ #include diff --git a/src/interface/efi/efi_io.c b/src/interface/efi/efi_io.c deleted file mode 100644 index a620d6e4..00000000 --- a/src/interface/efi/efi_io.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include -#include -#include -#include - -/** @file - * - * iPXE I/O API for EFI - * - */ - -/** CPU I/O protocol */ -static EFI_CPU_IO_PROTOCOL *cpu_io; -EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io ); - -/** Maximum address that can be used for port I/O */ -#define MAX_PORT_ADDRESS 0xffff - -/** - * Determine whether or not address is a port I/O address - * - * @v io_addr I/O address - * @v is_port I/O address is a port I/O address - */ -#define IS_PORT_ADDRESS(io_addr) \ - ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS ) - -/** - * Determine EFI CPU I/O width code - * - * @v size Size of value - * @ret width EFI width code - * - * Someone at Intel clearly gets paid by the number of lines of code - * they write. No-one should ever be able to make I/O this - * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite - * idiocy. - */ -static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) { - switch ( size ) { - case 1 : return EfiCpuIoWidthFifoUint8; - case 2 : return EfiCpuIoWidthFifoUint16; - case 4 : return EfiCpuIoWidthFifoUint32; - case 8 : return EfiCpuIoWidthFifoUint64; - default : - assert ( 0 ); - /* I wonder what this will actually do... */ - return EfiCpuIoWidthMaximum; - } -} - -/** - * Read from device - * - * @v io_addr I/O address - * @v size Size of value - * @ret data Value read - */ -unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) { - EFI_CPU_IO_PROTOCOL_IO_MEM read; - unsigned long long data = 0; - EFI_STATUS efirc; - - read = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Read : cpu_io->Mem.Read ); - - if ( ( efirc = read ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, 1, - ( void * ) &data ) ) != 0 ) { - DBG ( "EFI I/O read at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - return -1ULL; - } - - return data; -} - -/** - * Write to device - * - * @v data Value to write - * @v io_addr I/O address - * @v size Size of value - */ -void efi_iowrite ( unsigned long long data, volatile void *io_addr, - size_t size ) { - EFI_CPU_IO_PROTOCOL_IO_MEM write; - EFI_STATUS efirc; - - write = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Write : cpu_io->Mem.Write ); - - if ( ( efirc = write ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, 1, - ( void * ) &data ) ) != 0 ) { - DBG ( "EFI I/O write at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - } -} - -/** - * String read from device - * - * @v io_addr I/O address - * @v data Data buffer - * @v size Size of values - * @v count Number of values to read - */ -void efi_ioreads ( volatile void *io_addr, void *data, - size_t size, unsigned int count ) { - EFI_CPU_IO_PROTOCOL_IO_MEM read; - EFI_STATUS efirc; - - read = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Read : cpu_io->Mem.Read ); - - if ( ( efirc = read ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, count, - ( void * ) data ) ) != 0 ) { - DBG ( "EFI I/O string read at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - } -} - -/** - * String write to device - * - * @v io_addr I/O address - * @v data Data buffer - * @v size Size of values - * @v count Number of values to write - */ -void efi_iowrites ( volatile void *io_addr, const void *data, - size_t size, unsigned int count ) { - EFI_CPU_IO_PROTOCOL_IO_MEM write; - EFI_STATUS efirc; - - write = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Write : cpu_io->Mem.Write ); - - if ( ( efirc = write ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, count, - ( void * ) data ) ) != 0 ) { - DBG ( "EFI I/O write at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - } -} - -/** - * Wait for I/O-mapped operation to complete - * - */ -static void efi_iodelay ( void ) { - /* Write to non-existent port. Probably x86-only. */ - outb ( 0, 0x80 ); -} - -/** - * Get memory map - * - * Can't be done on EFI so return an empty map - * - * @v memmap Memory map to fill in - */ -static void efi_get_memmap ( struct memory_map *memmap ) { - memmap->count = 0; -} - -PROVIDE_IOAPI_INLINE ( efi, phys_to_bus ); -PROVIDE_IOAPI_INLINE ( efi, bus_to_phys ); -PROVIDE_IOAPI_INLINE ( efi, ioremap ); -PROVIDE_IOAPI_INLINE ( efi, iounmap ); -PROVIDE_IOAPI_INLINE ( efi, io_to_bus ); -PROVIDE_IOAPI_INLINE ( efi, readb ); -PROVIDE_IOAPI_INLINE ( efi, readw ); -PROVIDE_IOAPI_INLINE ( efi, readl ); -PROVIDE_IOAPI_INLINE ( efi, readq ); -PROVIDE_IOAPI_INLINE ( efi, writeb ); -PROVIDE_IOAPI_INLINE ( efi, writew ); -PROVIDE_IOAPI_INLINE ( efi, writel ); -PROVIDE_IOAPI_INLINE ( efi, writeq ); -PROVIDE_IOAPI_INLINE ( efi, inb ); -PROVIDE_IOAPI_INLINE ( efi, inw ); -PROVIDE_IOAPI_INLINE ( efi, inl ); -PROVIDE_IOAPI_INLINE ( efi, outb ); -PROVIDE_IOAPI_INLINE ( efi, outw ); -PROVIDE_IOAPI_INLINE ( efi, outl ); -PROVIDE_IOAPI_INLINE ( efi, insb ); -PROVIDE_IOAPI_INLINE ( efi, insw ); -PROVIDE_IOAPI_INLINE ( efi, insl ); -PROVIDE_IOAPI_INLINE ( efi, outsb ); -PROVIDE_IOAPI_INLINE ( efi, outsw ); -PROVIDE_IOAPI_INLINE ( efi, outsl ); -PROVIDE_IOAPI ( efi, iodelay, efi_iodelay ); -PROVIDE_IOAPI_INLINE ( efi, mb ); -PROVIDE_IOAPI ( efi, get_memmap, efi_get_memmap ); From e42bc3aa37698941be20cccde599af39c69227e2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 18 Apr 2013 01:05:32 +0100 Subject: [PATCH 06/45] [libc] Use __einfo() tuple as first argument to EUNIQ() Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 2 +- src/drivers/block/scsi.c | 2 +- src/drivers/block/srp.c | 2 +- src/include/errno.h | 11 +-- src/include/ipxe/net80211_err.h | 148 ++++++++++++++++---------------- src/net/80211/sec80211.c | 4 +- 6 files changed, 86 insertions(+), 83 deletions(-) diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index ab75dea3..185605b4 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -84,7 +84,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED, \ "Request unauthorized" ) #define EPROTO_STATUS( status ) \ - EUNIQ ( EPROTO, (status), EPROTO_MALFORMED_REQUEST, \ + EUNIQ ( EINFO_EPROTO, (status), EPROTO_MALFORMED_REQUEST, \ EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER, \ EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED ) diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c index b45ae630..4245f019 100644 --- a/src/drivers/block/scsi.c +++ b/src/drivers/block/scsi.c @@ -89,7 +89,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_EIO_COMPLETED \ __einfo_uniqify ( EINFO_EIO, 0x0f, "Completed" ) #define EIO_SENSE( key ) \ - EUNIQ ( EIO, (key), EIO_NO_SENSE, EIO_RECOVERED_ERROR, \ + EUNIQ ( EINFO_EIO, (key), EIO_NO_SENSE, EIO_RECOVERED_ERROR, \ EIO_NOT_READY, EIO_MEDIUM_ERROR, EIO_HARDWARE_ERROR, \ EIO_ILLEGAL_REQUEST, EIO_UNIT_ATTENTION, \ EIO_DATA_PROTECT, EIO_BLANK_CHECK, EIO_VENDOR_SPECIFIC, \ diff --git a/src/drivers/block/srp.c b/src/drivers/block/srp.c index 098a973e..70a97b2f 100644 --- a/src/drivers/block/srp.c +++ b/src/drivers/block/srp.c @@ -93,7 +93,7 @@ FEATURE ( FEATURE_PROTOCOL, "SRP", DHCP_EB_FEATURE_SRP, 1 ); SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS, \ "RDMA channel limit reached for this initiator" ) #define EPERM_LOGIN_REJ( reason_nibble ) \ - EUNIQ ( EPERM, (reason_nibble), EPERM_UNKNOWN, \ + EUNIQ ( EINFO_EPERM, (reason_nibble), EPERM_UNKNOWN, \ EPERM_INSUFFICIENT_RESOURCES, EPERM_BAD_MAX_I_T_IU_LEN, \ EPERM_CANNOT_ASSOCIATE, EPERM_UNSUPPORTED_BUFFER_FORMAT, \ EPERM_NO_MULTIPLE_CHANNELS, EPERM_NO_MORE_CHANNELS ) diff --git a/src/include/errno.h b/src/include/errno.h index bd4ddaf4..bb70136b 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -187,8 +187,8 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); /** * Disambiguate a base error based on non-constant information * - * @v error_base Base error - * @v uniq Error disambiguator + * @v einfo_base Base error information + * @v uniq Error disambiguator (0x00-0x1f) * @v ... List of expected possible disambiguated errors * @ret error Error * @@ -200,9 +200,10 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); * EUNIQ() should not be used for constant error disambiguators; use * __einfo_uniqify() instead. */ -#define EUNIQ( errno, uniq, ... ) ( { \ - euniq_discard ( 0, ##__VA_ARGS__); \ - ( ( int ) ( (errno) | ( (uniq) << 8 ) ) ); } ) +#define EUNIQ( einfo_base, uniq, ... ) ( { \ + euniq_discard ( 0, ##__VA_ARGS__ ); \ + ( ( int ) ( __einfo_error ( einfo_base ) | \ + ( (uniq) << 8 ) ) ); } ) static inline void euniq_discard ( int dummy __unused, ... ) {} /** diff --git a/src/include/ipxe/net80211_err.h b/src/include/ipxe/net80211_err.h index 2175b143..7df3d0d8 100644 --- a/src/include/ipxe/net80211_err.h +++ b/src/include/ipxe/net80211_err.h @@ -553,81 +553,83 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Make return status code from 802.11 status code */ #define E80211_STATUS( stat ) \ - EUNIQ ( ( ( stat & 0x20 ) ? EHOSTUNREACH : ECONNREFUSED ), \ - ( stat &0x1f ), \ - ECONNREFUSED_FAILURE, \ - ECONNREFUSED_CAPAB_UNSUPP, \ - ECONNREFUSED_REASSOC_INVALID, \ - ECONNREFUSED_ASSOC_DENIED, \ - ECONNREFUSED_AUTH_ALGO_UNSUPP, \ - ECONNREFUSED_AUTH_SEQ_INVALID, \ - ECONNREFUSED_AUTH_CHALL_INVALID, \ - ECONNREFUSED_AUTH_TIMEOUT, \ - ECONNREFUSED_ASSOC_NO_ROOM, \ - ECONNREFUSED_ASSOC_NEED_RATE, \ - ECONNREFUSED_ASSOC_NEED_SHORT_PMBL, \ - ECONNREFUSED_ASSOC_NEED_PBCC, \ - ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY, \ - ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT, \ - ECONNREFUSED_ASSOC_BAD_POWER, \ - ECONNREFUSED_ASSOC_BAD_CHANNELS, \ - ECONNREFUSED_ASSOC_NEED_SHORT_SLOT, \ - ECONNREFUSED_ASSOC_NEED_DSSS_OFDM, \ - EHOSTUNREACH_QOS_FAILURE, \ - EHOSTUNREACH_QOS_NO_ROOM, \ - EHOSTUNREACH_LINK_IS_HORRIBLE, \ - EHOSTUNREACH_ASSOC_NEED_QOS, \ - EHOSTUNREACH_REQUEST_DECLINED, \ - EHOSTUNREACH_REQUEST_INVALID, \ - EHOSTUNREACH_TS_NOT_CREATED_AGAIN, \ - EHOSTUNREACH_INVALID_IE, \ - EHOSTUNREACH_GROUP_CIPHER_INVALID, \ - EHOSTUNREACH_PAIR_CIPHER_INVALID, \ - EHOSTUNREACH_AKMP_INVALID, \ - EHOSTUNREACH_RSN_VERSION_UNSUPP, \ - EHOSTUNREACH_RSN_CAPAB_INVALID, \ - EHOSTUNREACH_CIPHER_REJECTED, \ - EHOSTUNREACH_TS_NOT_CREATED_WAIT, \ - EHOSTUNREACH_DIRECT_LINK_FORBIDDEN, \ - EHOSTUNREACH_DEST_NOT_PRESENT, \ - EHOSTUNREACH_DEST_NOT_QOS, \ - EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ) + ( ( (stat) & 0x20 ) ? \ + EUNIQ ( EINFO_EHOSTUNREACH, ( (stat) & 0x1f ), \ + EHOSTUNREACH_QOS_FAILURE, \ + EHOSTUNREACH_QOS_NO_ROOM, \ + EHOSTUNREACH_LINK_IS_HORRIBLE, \ + EHOSTUNREACH_ASSOC_NEED_QOS, \ + EHOSTUNREACH_REQUEST_DECLINED, \ + EHOSTUNREACH_REQUEST_INVALID, \ + EHOSTUNREACH_TS_NOT_CREATED_AGAIN, \ + EHOSTUNREACH_INVALID_IE, \ + EHOSTUNREACH_GROUP_CIPHER_INVALID, \ + EHOSTUNREACH_PAIR_CIPHER_INVALID, \ + EHOSTUNREACH_AKMP_INVALID, \ + EHOSTUNREACH_RSN_VERSION_UNSUPP, \ + EHOSTUNREACH_RSN_CAPAB_INVALID, \ + EHOSTUNREACH_CIPHER_REJECTED, \ + EHOSTUNREACH_TS_NOT_CREATED_WAIT, \ + EHOSTUNREACH_DIRECT_LINK_FORBIDDEN, \ + EHOSTUNREACH_DEST_NOT_PRESENT, \ + EHOSTUNREACH_DEST_NOT_QOS, \ + EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ) : \ + EUNIQ ( EINFO_ECONNREFUSED, ( (stat) & 0x1f ), \ + ECONNREFUSED_FAILURE, \ + ECONNREFUSED_CAPAB_UNSUPP, \ + ECONNREFUSED_REASSOC_INVALID, \ + ECONNREFUSED_ASSOC_DENIED, \ + ECONNREFUSED_AUTH_ALGO_UNSUPP, \ + ECONNREFUSED_AUTH_SEQ_INVALID, \ + ECONNREFUSED_AUTH_CHALL_INVALID, \ + ECONNREFUSED_AUTH_TIMEOUT, \ + ECONNREFUSED_ASSOC_NO_ROOM, \ + ECONNREFUSED_ASSOC_NEED_RATE, \ + ECONNREFUSED_ASSOC_NEED_SHORT_PMBL, \ + ECONNREFUSED_ASSOC_NEED_PBCC, \ + ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY, \ + ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT, \ + ECONNREFUSED_ASSOC_BAD_POWER, \ + ECONNREFUSED_ASSOC_BAD_CHANNELS, \ + ECONNREFUSED_ASSOC_NEED_SHORT_SLOT, \ + ECONNREFUSED_ASSOC_NEED_DSSS_OFDM ) ) /** Make return status code from 802.11 reason code */ #define E80211_REASON( reas ) \ - EUNIQ ( ( ( reas & 0x20 ) ? ENETRESET : ECONNRESET ), \ - ( reas & 0x1f ), \ - ECONNRESET_UNSPECIFIED, \ - ECONNRESET_AUTH_NO_LONGER_VALID, \ - ECONNRESET_LEAVING, \ - ECONNRESET_INACTIVITY, \ - ECONNRESET_OUT_OF_RESOURCES, \ - ECONNRESET_NEED_AUTH, \ - ECONNRESET_NEED_ASSOC, \ - ECONNRESET_LEAVING_TO_ROAM, \ - ECONNRESET_REASSOC_INVALID, \ - ECONNRESET_BAD_POWER, \ - ECONNRESET_BAD_CHANNELS, \ - ECONNRESET_INVALID_IE, \ - ECONNRESET_MIC_FAILURE, \ - ECONNRESET_4WAY_TIMEOUT, \ - ECONNRESET_GROUPKEY_TIMEOUT, \ - ECONNRESET_4WAY_INVALID, \ - ECONNRESET_GROUP_CIPHER_INVALID, \ - ECONNRESET_PAIR_CIPHER_INVALID, \ - ECONNRESET_AKMP_INVALID, \ - ECONNRESET_RSN_VERSION_INVALID, \ - ECONNRESET_RSN_CAPAB_INVALID, \ - ECONNRESET_8021X_FAILURE, \ - ECONNRESET_CIPHER_REJECTED, \ - ENETRESET_QOS_UNSPECIFIED, \ - ENETRESET_QOS_OUT_OF_RESOURCES, \ - ENETRESET_LINK_IS_HORRIBLE, \ - ENETRESET_INVALID_TXOP, \ - ENETRESET_REQUESTED_LEAVING, \ - ENETRESET_REQUESTED_NO_USE, \ - ENETRESET_REQUESTED_NEED_SETUP, \ - ENETRESET_REQUESTED_TIMEOUT, \ - ENETRESET_CIPHER_UNSUPPORTED ) + ( ( (reas) & 0x20 ) ? \ + EUNIQ ( EINFO_ENETRESET, ( (reas) & 0x1f ), \ + ENETRESET_QOS_UNSPECIFIED, \ + ENETRESET_QOS_OUT_OF_RESOURCES, \ + ENETRESET_LINK_IS_HORRIBLE, \ + ENETRESET_INVALID_TXOP, \ + ENETRESET_REQUESTED_LEAVING, \ + ENETRESET_REQUESTED_NO_USE, \ + ENETRESET_REQUESTED_NEED_SETUP, \ + ENETRESET_REQUESTED_TIMEOUT, \ + ENETRESET_CIPHER_UNSUPPORTED ) : \ + EUNIQ ( EINFO_ECONNRESET, ( (reas) & 0x1f ), \ + ECONNRESET_UNSPECIFIED, \ + ECONNRESET_AUTH_NO_LONGER_VALID, \ + ECONNRESET_LEAVING, \ + ECONNRESET_INACTIVITY, \ + ECONNRESET_OUT_OF_RESOURCES, \ + ECONNRESET_NEED_AUTH, \ + ECONNRESET_NEED_ASSOC, \ + ECONNRESET_LEAVING_TO_ROAM, \ + ECONNRESET_REASSOC_INVALID, \ + ECONNRESET_BAD_POWER, \ + ECONNRESET_BAD_CHANNELS, \ + ECONNRESET_INVALID_IE, \ + ECONNRESET_MIC_FAILURE, \ + ECONNRESET_4WAY_TIMEOUT, \ + ECONNRESET_GROUPKEY_TIMEOUT, \ + ECONNRESET_4WAY_INVALID, \ + ECONNRESET_GROUP_CIPHER_INVALID, \ + ECONNRESET_PAIR_CIPHER_INVALID, \ + ECONNRESET_AKMP_INVALID, \ + ECONNRESET_RSN_VERSION_INVALID, \ + ECONNRESET_RSN_CAPAB_INVALID, \ + ECONNRESET_8021X_FAILURE, \ + ECONNRESET_CIPHER_REJECTED ) ) #endif /* _IPXE_NET80211_ERR_H */ diff --git a/src/net/80211/sec80211.c b/src/net/80211/sec80211.c index d159edbd..d1bc75e9 100644 --- a/src/net/80211/sec80211.c +++ b/src/net/80211/sec80211.c @@ -45,8 +45,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ENOTSUP_CCMP __einfo_error ( EINFO_ENOTSUP_CCMP ) #define EINFO_ENOTSUP_CCMP __einfo_uniqify ( EINFO_ENOTSUP, \ ( 0x10 | NET80211_CRYPT_CCMP ), "CCMP not supported" ) -#define ENOTSUP_CRYPT( crypt ) \ - EUNIQ ( ENOTSUP, ( 0x10 | (crypt) ), \ +#define ENOTSUP_CRYPT( crypt ) \ + EUNIQ ( EINFO_ENOTSUP, ( 0x10 | (crypt) ), \ ENOTSUP_WEP, ENOTSUP_TKIP, ENOTSUP_CCMP ) /** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */ From 73480352315a12fdef467402ea41be9ac285e4e7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 19 Apr 2013 13:34:13 +0100 Subject: [PATCH 07/45] [libc] Redefine low 8 bits of error code as "platform error code" The low 8 bits of an iPXE error code are currently defined as the closest equivalent PXE error code. Generalise this scheme to platforms other than PC-BIOS by extending this definition to "closest equivalent platform error code". This allows for the possibility of returning meaningful errors via EFI APIs. Signed-off-by: Michael Brown --- src/arch/i386/include/ipxe/errno/pcbios.h | 115 +++++++ src/arch/i386/include/pxe.h | 1 + src/arch/i386/include/pxe_error.h | 123 +++++++ src/include/errno.h | 396 +++++++++------------- src/include/ipxe/errno/efi.h | 129 +++++++ src/include/ipxe/errno/linux.h | 113 ++++++ src/util/einfo.c | 5 + 7 files changed, 648 insertions(+), 234 deletions(-) create mode 100644 src/arch/i386/include/ipxe/errno/pcbios.h create mode 100644 src/arch/i386/include/pxe_error.h create mode 100644 src/include/ipxe/errno/efi.h create mode 100644 src/include/ipxe/errno/linux.h diff --git a/src/arch/i386/include/ipxe/errno/pcbios.h b/src/arch/i386/include/ipxe/errno/pcbios.h new file mode 100644 index 00000000..3a9eb249 --- /dev/null +++ b/src/arch/i386/include/ipxe/errno/pcbios.h @@ -0,0 +1,115 @@ +#ifndef _IPXE_ERRNO_PCBIOS_H +#define _IPXE_ERRNO_PCBIOS_H + +/** + * @file + * + * PC-BIOS platform error codes + * + * We use the PXE-specified error codes as the platform error codes + * for the PC-BIOS platform. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** + * Convert platform error code to platform component of iPXE error code + * + * @v platform Platform error code + * @ret errno Platform component of iPXE error code + */ +#define PLATFORM_TO_ERRNO( platform ) ( (platform) & 0xff ) + +/** + * Convert iPXE error code to platform error code + * + * @v errno iPXE error code + * @ret platform Platform error code + */ +#define ERRNO_TO_PLATFORM( errno ) ( (errno) & 0xff ) + +/* Platform-specific error codes */ +#define PLATFORM_ENOERR PXENV_STATUS_SUCCESS +#define PLATFORM_E2BIG PXENV_STATUS_BAD_FUNC +#define PLATFORM_EACCES PXENV_STATUS_TFTP_ACCESS_VIOLATION +#define PLATFORM_EADDRINUSE PXENV_STATUS_UDP_OPEN +#define PLATFORM_EADDRNOTAVAIL PXENV_STATUS_UDP_OPEN +#define PLATFORM_EAFNOSUPPORT PXENV_STATUS_UNSUPPORTED +#define PLATFORM_EAGAIN PXENV_STATUS_FAILURE +#define PLATFORM_EALREADY PXENV_STATUS_UDP_OPEN +#define PLATFORM_EBADF PXENV_STATUS_TFTP_CLOSED +#define PLATFORM_EBADMSG PXENV_STATUS_FAILURE +#define PLATFORM_EBUSY PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ECANCELED PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE +#define PLATFORM_ECHILD PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ECONNABORTED PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION +#define PLATFORM_ECONNREFUSED PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION +#define PLATFORM_ECONNRESET PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION +#define PLATFORM_EDEADLK PXENV_STATUS_FAILURE +#define PLATFORM_EDESTADDRREQ PXENV_STATUS_BAD_FUNC +#define PLATFORM_EDOM PXENV_STATUS_FAILURE +#define PLATFORM_EDQUOT PXENV_STATUS_FAILURE +#define PLATFORM_EEXIST PXENV_STATUS_FAILURE +#define PLATFORM_EFAULT PXENV_STATUS_MCOPY_PROBLEM +#define PLATFORM_EFBIG PXENV_STATUS_MCOPY_PROBLEM +#define PLATFORM_EHOSTUNREACH PXENV_STATUS_ARP_TIMEOUT +#define PLATFORM_EIDRM PXENV_STATUS_FAILURE +#define PLATFORM_EILSEQ PXENV_STATUS_FAILURE +#define PLATFORM_EINPROGRESS PXENV_STATUS_FAILURE +#define PLATFORM_EINTR PXENV_STATUS_FAILURE +#define PLATFORM_EINVAL PXENV_STATUS_BAD_FUNC +#define PLATFORM_EIO PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION +#define PLATFORM_EISCONN PXENV_STATUS_UDP_OPEN +#define PLATFORM_EISDIR PXENV_STATUS_FAILURE +#define PLATFORM_ELOOP PXENV_STATUS_FAILURE +#define PLATFORM_EMFILE PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_EMLINK PXENV_STATUS_FAILURE +#define PLATFORM_EMSGSIZE PXENV_STATUS_BAD_FUNC +#define PLATFORM_EMULTIHOP PXENV_STATUS_FAILURE +#define PLATFORM_ENAMETOOLONG PXENV_STATUS_FAILURE +#define PLATFORM_ENETDOWN PXENV_STATUS_ARP_TIMEOUT +#define PLATFORM_ENETRESET PXENV_STATUS_FAILURE +#define PLATFORM_ENETUNREACH PXENV_STATUS_ARP_TIMEOUT +#define PLATFORM_ENFILE PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOBUFS PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENODATA PXENV_STATUS_FAILURE +#define PLATFORM_ENODEV PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ENOENT PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ENOEXEC PXENV_STATUS_FAILURE +#define PLATFORM_ENOLCK PXENV_STATUS_FAILURE +#define PLATFORM_ENOLINK PXENV_STATUS_FAILURE +#define PLATFORM_ENOMEM PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOMSG PXENV_STATUS_FAILURE +#define PLATFORM_ENOPROTOOPT PXENV_STATUS_UNSUPPORTED +#define PLATFORM_ENOSPC PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOSR PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOSTR PXENV_STATUS_FAILURE +#define PLATFORM_ENOSYS PXENV_STATUS_UNSUPPORTED +#define PLATFORM_ENOTCONN PXENV_STATUS_FAILURE +#define PLATFORM_ENOTDIR PXENV_STATUS_FAILURE +#define PLATFORM_ENOTEMPTY PXENV_STATUS_FAILURE +#define PLATFORM_ENOTSOCK PXENV_STATUS_FAILURE +#define PLATFORM_ENOTSUP PXENV_STATUS_UNSUPPORTED +#define PLATFORM_ENOTTY PXENV_STATUS_FAILURE +#define PLATFORM_ENXIO PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_EOPNOTSUPP PXENV_STATUS_UNSUPPORTED +#define PLATFORM_EOVERFLOW PXENV_STATUS_FAILURE +#define PLATFORM_EPERM PXENV_STATUS_TFTP_ACCESS_VIOLATION +#define PLATFORM_EPIPE PXENV_STATUS_FAILURE +#define PLATFORM_EPROTO PXENV_STATUS_FAILURE +#define PLATFORM_EPROTONOSUPPORT PXENV_STATUS_UNSUPPORTED +#define PLATFORM_EPROTOTYPE PXENV_STATUS_FAILURE +#define PLATFORM_ERANGE PXENV_STATUS_FAILURE +#define PLATFORM_EROFS PXENV_STATUS_FAILURE +#define PLATFORM_ESPIPE PXENV_STATUS_FAILURE +#define PLATFORM_ESRCH PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ESTALE PXENV_STATUS_FAILURE +#define PLATFORM_ETIME PXENV_STATUS_FAILURE +#define PLATFORM_ETIMEDOUT PXENV_STATUS_TFTP_READ_TIMEOUT +#define PLATFORM_ETXTBSY PXENV_STATUS_FAILURE +#define PLATFORM_EWOULDBLOCK PXENV_STATUS_TFTP_OPEN +#define PLATFORM_EXDEV PXENV_STATUS_FAILURE + +#endif /* _IPXE_ERRNO_PCBIOS_H */ diff --git a/src/arch/i386/include/pxe.h b/src/arch/i386/include/pxe.h index 0206f683..b95b0cce 100644 --- a/src/arch/i386/include/pxe.h +++ b/src/arch/i386/include/pxe.h @@ -4,6 +4,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include "pxe_types.h" +#include "pxe_error.h" #include "pxe_api.h" #include #include diff --git a/src/arch/i386/include/pxe_error.h b/src/arch/i386/include/pxe_error.h new file mode 100644 index 00000000..a1398cbd --- /dev/null +++ b/src/arch/i386/include/pxe_error.h @@ -0,0 +1,123 @@ +#ifndef PXE_ERROR_H +#define PXE_ERROR_H + +/** @file + * + * Preboot eXecution Environment (PXE) error definitions + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @defgroup pxeerrors PXE error codes + * + * @{ + */ + +/* Generic errors */ +#define PXENV_STATUS_SUCCESS 0x0000 +#define PXENV_STATUS_FAILURE 0x0001 +#define PXENV_STATUS_BAD_FUNC 0x0002 +#define PXENV_STATUS_UNSUPPORTED 0x0003 +#define PXENV_STATUS_KEEP_UNDI 0x0004 +#define PXENV_STATUS_KEEP_ALL 0x0005 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006 + +/* ARP errors (0x0010 to 0x001f) */ +#define PXENV_STATUS_ARP_TIMEOUT 0x0011 + +/* Base-Code state errors */ +#define PXENV_STATUS_UDP_CLOSED 0x0018 +#define PXENV_STATUS_UDP_OPEN 0x0019 +#define PXENV_STATUS_TFTP_CLOSED 0x001a +#define PXENV_STATUS_TFTP_OPEN 0x001b + +/* BIOS/system errors (0x0020 to 0x002f) */ +#define PXENV_STATUS_MCOPY_PROBLEM 0x0020 +#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021 +#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022 +#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023 +#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024 +#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025 +#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026 +#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027 +#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028 + +/* TFTP/MTFTP errors (0x0030 to 0x003f) */ +#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030 +#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032 +#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033 +#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035 +#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036 +#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038 +#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039 +#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a +#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b +#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c +#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d +#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e +#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f + +/* Reserved errors 0x0040 to 0x004f) */ + +/* DHCP/BOOTP errors (0x0050 to 0x005f) */ +#define PXENV_STATUS_DHCP_TIMEOUT 0x0051 +#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052 +#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053 +#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054 + +/* Driver errors (0x0060 to 0x006f) */ +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c + +/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */ +#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074 +#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076 +#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077 +#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078 +#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079 + +/* Environment NBP errors (0x0080 to 0x008f) */ + +/* Reserved errors (0x0090 to 0x009f) */ + +/* Miscellaneous errors (0x00a0 to 0x00af) */ +#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0 +#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1 +#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2 +#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3 + +/* BUSD errors (0x00b0 to 0x00bf) */ +#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0 + +/* Loader errors (0x00c0 to 0x00cf) */ +#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0 +#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1 +#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2 +#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3 +#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4 +#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5 +#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6 +#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8 +#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9 +#define PXENV_STATUS_LOADER_UNDI_START 0x00ca +#define PXENV_STATUS_LOADER_BC_START 0x00cb + +/** @} */ + +/** Derive PXENV_STATUS code from iPXE error number */ +#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff ) + +#endif /* PXE_ERROR_H */ diff --git a/src/include/errno.h b/src/include/errno.h index bb70136b..bcc4a881 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -30,16 +30,16 @@ FILE_LICENCE ( GPL2_OR_LATER ); * maximum visibility into the source of an error even in an end-user * build with no debugging. They are constructed as follows: * - * Bits 7-0 : PXE error code + * Bits 7-0 : Platform-specific error code * - * This is the closest equivalent PXE error code - * (e.g. PXENV_STATUS_OUT_OF_RESOURCES), and is the only part of the - * error that will be returned via the PXE API, since PXE has - * predefined error codes. + * This is a losslessly compressed representation of the closest + * equivalent error code defined by the platform (e.g. BIOS/PXE or + * EFI). It is used to generate errors to be returned to external + * code. * * Bits 12-8 : Per-file disambiguator * - * When the same error number can be generated from multiple points + * When the same error code can be generated from multiple points * within a file, this field can be used to identify the unique * instance. * @@ -54,7 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * Bit 31 : Reserved * - * Errors are usually return as negative error numbers (e.g. -EINVAL); + * Errors are usually return as negative error codes (e.g. -EINVAL); * bit 31 is therefore unusable. * * @@ -63,9 +63,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * return -EINVAL; * - * By various bits of preprocessor magic, the PXE error code and file - * identifier are already incorporated into the definition of the - * POSIX error macro, which keeps the code relatively clean. + * By various bits of preprocessor magic, the platform-specific error + * code and file identifier are already incorporated into the + * definition of the POSIX error macro, which keeps the code + * relatively clean. * * * Functions that wish to return failures should be declared as @@ -99,6 +100,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Get definitions for platform-specific error codes */ +#define PLATFORM_ERRNO(_platform) +#include PLATFORM_ERRNO(PLATFORM) + /* Get definitions for file identifiers */ #include @@ -110,37 +115,37 @@ FILE_LICENCE ( GPL2_OR_LATER ); #if ! ERRFILE extern char missing_errfile_declaration[] __attribute__ (( deprecated )); #undef ERRFILE -#define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) ) +#define ERRFILE ( ( int ) ( 0 * ( ( intptr_t ) missing_errfile_declaration ) ) ) #endif /** * Declare error information * - * @v pxe PXE error number (0x00-0xff) - * @v posix POSIX error number (0x00-0x7f) + * @v platform Platform error code (uncompressed) + * @v posix POSIX error code (0x00-0x7f) * @v uniq Error disambiguator (0x00-0x1f) * @v desc Error description * @ret einfo Error information */ -#define __einfo( pxe, posix, uniq, desc ) ( pxe, posix, uniq, desc ) +#define __einfo( platform, posix, uniq, desc ) ( platform, posix, uniq, desc ) /** - * Get PXE error number + * Get platform error code * * @v einfo Error information - * @ret pxe PXE error number + * @ret platform Platform error code (uncompressed) */ -#define __einfo_pxe( einfo ) __einfo_extract_pxe einfo -#define __einfo_extract_pxe( pxe, posix, uniq, desc ) pxe +#define __einfo_platform( einfo ) __einfo_extract_platform einfo +#define __einfo_extract_platform( platform, posix, uniq, desc ) platform /** - * Get POSIX error number + * Get POSIX error code * * @v einfo Error information - * @ret posix POSIX error number + * @ret posix POSIX error code */ #define __einfo_posix( einfo ) __einfo_extract_posix einfo -#define __einfo_extract_posix( pxe, posix, uniq, desc ) posix +#define __einfo_extract_posix( platform, posix, uniq, desc ) posix /** * Get error disambiguator @@ -149,7 +154,7 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); * @ret uniq Error disambiguator */ #define __einfo_uniq( einfo ) __einfo_extract_uniq einfo -#define __einfo_extract_uniq( pxe, posix, uniq, desc ) uniq +#define __einfo_extract_uniq( platform, posix, uniq, desc ) uniq /** * Get error description @@ -158,31 +163,44 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); * @ret desc Error description */ #define __einfo_desc( einfo ) __einfo_extract_desc einfo -#define __einfo_extract_desc( pxe, posix, uniq, desc ) desc +#define __einfo_extract_desc( platform, posix, uniq, desc ) desc /** * Declare disambiguated error * * @v einfo_base Base error information - * @v uniq Error disambiguator + * @v uniq Error disambiguator (0x00-0x1f) * @v desc Error description * @ret einfo Error information */ #define __einfo_uniqify( einfo_base, uniq, desc ) \ - __einfo ( __einfo_pxe ( einfo_base ), \ + __einfo ( __einfo_platform ( einfo_base ), \ __einfo_posix ( einfo_base ), \ uniq, desc ) /** - * Get error number + * Declare platform-generated error + * + * @v einfo_base Base error information + * @v platform Platform error code (uncompressed) + * @v desc Error description + * @ret einfo Error information + */ +#define __einfo_platformify( einfo_base, platform, desc ) \ + __einfo ( platform, __einfo_posix ( einfo_base ), \ + __einfo_uniq ( einfo_base ), desc ) + +/** + * Get error code * * @v einfo Error information - * @ret errno Error number + * @ret errno Error code */ #define __einfo_errno( einfo ) \ - ( ( __einfo_posix ( einfo ) << 24 ) | ( ERRFILE ) | \ - ( __einfo_uniq ( einfo ) << 8 ) | \ - ( __einfo_pxe ( einfo ) << 0 ) ) + ( ( int ) \ + ( ( __einfo_posix ( einfo ) << 24 ) | ( ERRFILE ) | \ + ( __einfo_uniq ( einfo ) << 8 ) | \ + ( PLATFORM_TO_ERRNO ( __einfo_platform ( einfo ) ) << 0 ) ) ) /** * Disambiguate a base error based on non-constant information @@ -206,6 +224,29 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); ( (uniq) << 8 ) ) ); } ) static inline void euniq_discard ( int dummy __unused, ... ) {} +/** + * Generate an error based on an external platform error code + * + * @v einfo_base Base error information + * @v platform Platform error code (uncompressed) + * @v ... List of expected possible platform-generated errors + * @ret error Error + * + * EPLATFORM() should be used when a platform error code resulting + * from an external platform API call is being incorporated into an + * error. For example, EFI code uses EPLATFORM() to generate errors + * resulting from calls to EFI APIs such as + * InstallMultipleProtocolInterfaces(). + * + * EPLATFORM() should not be used for constant platform-generated + * errors; use __einfo_platformify() instead. + */ +#define EPLATFORM( einfo_base, platform, ... ) ( { \ + eplatform_discard ( 0, ##__VA_ARGS__ ); \ + ( ( int ) ( __einfo_error ( einfo_base ) | \ + PLATFORM_TO_ERRNO ( platform ) ) ); } ) +static inline void eplatform_discard ( int dummy __unused, ... ) {} + /** * Declare error * @@ -226,124 +267,10 @@ static inline void euniq_discard ( int dummy __unused, ... ) {} ".align 8\n\t" \ "\n4:\n\t" \ ".previous\n\t" : : \ - "i" ( __einfo_errno ( einfo) ), \ + "i" ( __einfo_errno ( einfo ) ), \ "i" ( __LINE__ ) ); \ __einfo_errno ( einfo ); } ) -/** - * @defgroup pxeerrors PXE error codes - * - * The names, meanings and values of these error codes are defined by - * the PXE specification. - * - * @{ - */ - -/* Generic errors */ -#define PXENV_STATUS_SUCCESS 0x0000 -#define PXENV_STATUS_FAILURE 0x0001 -#define PXENV_STATUS_BAD_FUNC 0x0002 -#define PXENV_STATUS_UNSUPPORTED 0x0003 -#define PXENV_STATUS_KEEP_UNDI 0x0004 -#define PXENV_STATUS_KEEP_ALL 0x0005 -#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006 - -/* ARP errors (0x0010 to 0x001f) */ -#define PXENV_STATUS_ARP_TIMEOUT 0x0011 - -/* Base-Code state errors */ -#define PXENV_STATUS_UDP_CLOSED 0x0018 -#define PXENV_STATUS_UDP_OPEN 0x0019 -#define PXENV_STATUS_TFTP_CLOSED 0x001a -#define PXENV_STATUS_TFTP_OPEN 0x001b - -/* BIOS/system errors (0x0020 to 0x002f) */ -#define PXENV_STATUS_MCOPY_PROBLEM 0x0020 -#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021 -#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022 -#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023 -#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024 -#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025 -#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026 -#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027 -#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028 - -/* TFTP/MTFTP errors (0x0030 to 0x003f) */ -#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030 -#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032 -#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033 -#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035 -#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036 -#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038 -#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039 -#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a -#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b -#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c -#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d -#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e -#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f - -/* Reserved errors 0x0040 to 0x004f) */ - -/* DHCP/BOOTP errors (0x0050 to 0x005f) */ -#define PXENV_STATUS_DHCP_TIMEOUT 0x0051 -#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052 -#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053 -#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054 - -/* Driver errors (0x0060 to 0x006f) */ -#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060 -#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061 -#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064 -#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065 -#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066 -#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067 -#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068 -#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069 -#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a -#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b -#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c - -/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */ -#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074 -#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076 -#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077 -#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078 -#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079 - -/* Environment NBP errors (0x0080 to 0x008f) */ - -/* Reserved errors (0x0090 to 0x009f) */ - -/* Miscellaneous errors (0x00a0 to 0x00af) */ -#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0 -#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1 -#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2 -#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3 - -/* BUSD errors (0x00b0 to 0x00bf) */ -#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0 - -/* Loader errors (0x00c0 to 0x00cf) */ -#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0 -#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1 -#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2 -#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3 -#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4 -#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5 -#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6 -#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8 -#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9 -#define PXENV_STATUS_LOADER_UNDI_START 0x00ca -#define PXENV_STATUS_LOADER_BC_START 0x00cb - -/** @} */ - -/** Derive PXENV_STATUS code from iPXE error number */ -#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff ) - /** * @defgroup posixerrors POSIX error codes * @@ -355,409 +282,410 @@ static inline void euniq_discard ( int dummy __unused, ... ) {} /** Operation completed successfully */ #define ENOERR __einfo_error ( EINFO_ENOERR ) -#define EINFO_ENOERR __einfo ( PXENV_STATUS_SUCCESS, 0x00, 0, \ +#define EINFO_ENOERR __einfo ( PLATFORM_ENOERR, 0x00, 0, \ "Operation completed successfully" ) /** Argument list too long */ #define E2BIG __einfo_error ( EINFO_E2BIG ) -#define EINFO_E2BIG __einfo ( PXENV_STATUS_BAD_FUNC, 0x01, 0, \ +#define EINFO_E2BIG __einfo ( PLATFORM_E2BIG, 0x01, 0, \ "Argument list too long" ) /** Permission denied */ #define EACCES __einfo_error ( EINFO_EACCES ) -#define EINFO_EACCES __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x02, 0, \ +#define EINFO_EACCES __einfo ( PLATFORM_EACCES, 0x02, 0, \ "Permission denied" ) /** Address already in use */ #define EADDRINUSE __einfo_error ( EINFO_EADDRINUSE ) -#define EINFO_EADDRINUSE __einfo ( PXENV_STATUS_UDP_OPEN, 0x03, 0, \ +#define EINFO_EADDRINUSE __einfo ( PLATFORM_EADDRINUSE, 0x03, 0, \ "Address already in use" ) /** Address not available */ #define EADDRNOTAVAIL __einfo_error ( EINFO_EADDRNOTAVAIL ) -#define EINFO_EADDRNOTAVAIL __einfo ( PXENV_STATUS_UDP_OPEN, 0x04, 0, \ +#define EINFO_EADDRNOTAVAIL __einfo ( PLATFORM_EADDRNOTAVAIL, 0x04, 0, \ "Address not available" ) /** Address family not supported */ #define EAFNOSUPPORT __einfo_error ( EINFO_EAFNOSUPPORT ) -#define EINFO_EAFNOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x05, 0, \ +#define EINFO_EAFNOSUPPORT __einfo ( PLATFORM_EAFNOSUPPORT, 0x05, 0, \ "Address family not supported" ) /** Resource temporarily unavailable */ #define EAGAIN __einfo_error ( EINFO_EAGAIN ) -#define EINFO_EAGAIN __einfo ( PXENV_STATUS_FAILURE, 0x06, 0, \ +#define EINFO_EAGAIN __einfo ( PLATFORM_EAGAIN, 0x06, 0, \ "Resource temporarily unavailable" ) /** Connection already in progress */ #define EALREADY __einfo_error ( EINFO_EALREADY ) -#define EINFO_EALREADY __einfo ( PXENV_STATUS_UDP_OPEN, 0x07, 0, \ +#define EINFO_EALREADY __einfo ( PLATFORM_EALREADY, 0x07, 0, \ "Connection already in progress" ) /** Bad file descriptor */ #define EBADF __einfo_error ( EINFO_EBADF ) -#define EINFO_EBADF __einfo ( PXENV_STATUS_TFTP_CLOSED, 0x08, 0, \ +#define EINFO_EBADF __einfo ( PLATFORM_EBADF, 0x08, 0, \ "Bad file descriptor" ) /** Bad message */ #define EBADMSG __einfo_error ( EINFO_EBADMSG ) -#define EINFO_EBADMSG __einfo ( PXENV_STATUS_FAILURE, 0x09, 0, \ +#define EINFO_EBADMSG __einfo ( PLATFORM_EBADMSG, 0x09, 0, \ "Bad message" ) /** Device or resource busy */ #define EBUSY __einfo_error ( EINFO_EBUSY ) -#define EINFO_EBUSY __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x0a, 0, \ +#define EINFO_EBUSY __einfo ( PLATFORM_EBUSY, 0x0a, 0, \ "Device or resource busy" ) /** Operation canceled */ #define ECANCELED __einfo_error ( EINFO_ECANCELED ) -#define EINFO_ECANCELED __einfo ( PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE, \ - 0x0b, 0, "Operation canceled" ) +#define EINFO_ECANCELED __einfo ( PLATFORM_ECANCELED, 0x0b, 0, \ + "Operation canceled" ) /** No child processes */ #define ECHILD __einfo_error ( EINFO_ECHILD ) -#define EINFO_ECHILD __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x0c, 0, \ +#define EINFO_ECHILD __einfo ( PLATFORM_ECHILD, 0x0c, 0, \ "No child processes" ) /** Connection aborted */ #define ECONNABORTED __einfo_error ( EINFO_ECONNABORTED ) -#define EINFO_ECONNABORTED \ - __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0d, 0, \ - "Connection aborted" ) +#define EINFO_ECONNABORTED __einfo ( PLATFORM_ECONNABORTED, 0x0d, 0, \ + "Connection aborted" ) /** Connection refused */ #define ECONNREFUSED __einfo_error ( EINFO_ECONNREFUSED ) -#define EINFO_ECONNREFUSED __einfo ( PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION, \ - 0x0e, 0, "Connection refused" ) +#define EINFO_ECONNREFUSED __einfo ( PLATFORM_ECONNREFUSED, 0x0e, 0, \ + "Connection refused" ) /** Connection reset */ #define ECONNRESET __einfo_error ( EINFO_ECONNRESET ) -#define EINFO_ECONNRESET \ - __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0f, 0, \ - "Connection reset" ) +#define EINFO_ECONNRESET __einfo ( PLATFORM_ECONNRESET, 0x0f, 0, \ + "Connection reset" ) /** Resource deadlock avoided */ #define EDEADLK __einfo_error ( EINFO_EDEADLK ) -#define EINFO_EDEADLK __einfo ( PXENV_STATUS_FAILURE, 0x10, 0, \ +#define EINFO_EDEADLK __einfo ( PLATFORM_EDEADLK, 0x10, 0, \ "Resource deadlock avoided" ) /** Destination address required */ #define EDESTADDRREQ __einfo_error ( EINFO_EDESTADDRREQ ) -#define EINFO_EDESTADDRREQ __einfo ( PXENV_STATUS_BAD_FUNC, 0x11, 0, \ +#define EINFO_EDESTADDRREQ __einfo ( PLATFORM_EDESTADDRREQ, 0x11, 0, \ "Destination address required" ) /** Mathematics argument out of domain of function */ #define EDOM __einfo_error ( EINFO_EDOM ) -#define EINFO_EDOM __einfo ( PXENV_STATUS_FAILURE, 0x12, 0, \ +#define EINFO_EDOM __einfo ( PLATFORM_EDOM, 0x12, 0, \ "Mathematics argument out of domain of function" ) /** Disk quota exceeded */ #define EDQUOT __einfo_error ( EINFO_EDQUOT ) -#define EINFO_EDQUOT __einfo ( PXENV_STATUS_FAILURE, 0x13, 0, \ +#define EINFO_EDQUOT __einfo ( PLATFORM_EDQUOT, 0x13, 0, \ "Disk quote exceeded" ) /** File exists */ #define EEXIST __einfo_error ( EINFO_EEXIST ) -#define EINFO_EEXIST __einfo ( PXENV_STATUS_FAILURE, 0x14, 0, \ +#define EINFO_EEXIST __einfo ( PLATFORM_EEXIST, 0x14, 0, \ "File exists" ) /** Bad address */ #define EFAULT __einfo_error ( EINFO_EFAULT ) -#define EINFO_EFAULT __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x15, 0, \ +#define EINFO_EFAULT __einfo ( PLATFORM_EFAULT, 0x15, 0, \ "Bad address" ) /** File too large */ #define EFBIG __einfo_error ( EINFO_EFBIG ) -#define EINFO_EFBIG __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x16, 0, \ +#define EINFO_EFBIG __einfo ( PLATFORM_EFBIG, 0x16, 0, \ "File too large" ) /** Host is unreachable */ #define EHOSTUNREACH __einfo_error ( EINFO_EHOSTUNREACH ) -#define EINFO_EHOSTUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x17, 0, \ +#define EINFO_EHOSTUNREACH __einfo ( PLATFORM_EHOSTUNREACH, 0x17, 0, \ "Host is unreachable" ) /** Identifier removed */ #define EIDRM __einfo_error ( EINFO_EIDRM ) -#define EINFO_EIDRM __einfo ( PXENV_STATUS_FAILURE, 0x18, 0, \ +#define EINFO_EIDRM __einfo ( PLATFORM_EIDRM, 0x18, 0, \ "Identifier removed" ) /** Illegal byte sequence */ #define EILSEQ __einfo_error ( EINFO_EILSEQ ) -#define EINFO_EILSEQ __einfo ( PXENV_STATUS_FAILURE, 0x19, 0, \ +#define EINFO_EILSEQ __einfo ( PLATFORM_EILSEQ, 0x19, 0, \ "Illegal byte sequence" ) /** Operation in progress */ #define EINPROGRESS __einfo_error ( EINFO_EINPROGRESS ) -#define EINFO_EINPROGRESS __einfo ( PXENV_STATUS_FAILURE, 0x1a, 0, \ +#define EINFO_EINPROGRESS __einfo ( PLATFORM_EINPROGRESS, 0x1a, 0, \ "Operation in progress" ) /** Interrupted function call */ #define EINTR __einfo_error ( EINFO_EINTR ) -#define EINFO_EINTR __einfo ( PXENV_STATUS_FAILURE, 0x1b, 0, \ +#define EINFO_EINTR __einfo ( PLATFORM_EINTR, 0x1b, 0, \ "Interrupted function call" ) /** Invalid argument */ #define EINVAL __einfo_error ( EINFO_EINVAL ) -#define EINFO_EINVAL __einfo ( PXENV_STATUS_BAD_FUNC, 0x1c, 0, \ +#define EINFO_EINVAL __einfo ( PLATFORM_EINVAL, 0x1c, 0, \ "Invalid argument" ) /** Input/output error */ #define EIO __einfo_error ( EINFO_EIO ) -#define EINFO_EIO __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, \ - 0x1d, 0, "Input/output error" ) +#define EINFO_EIO __einfo ( PLATFORM_EIO, 0x1d, 0, \ + "Input/output error" ) /** Socket is connected */ #define EISCONN __einfo_error ( EINFO_EISCONN ) -#define EINFO_EISCONN __einfo ( PXENV_STATUS_UDP_OPEN, 0x1e, 0, \ +#define EINFO_EISCONN __einfo ( PLATFORM_EISCONN, 0x1e, 0, \ "Socket is connected" ) /** Is a directory */ #define EISDIR __einfo_error ( EINFO_EISDIR ) -#define EINFO_EISDIR __einfo ( PXENV_STATUS_FAILURE, 0x1f, 0, \ +#define EINFO_EISDIR __einfo ( PLATFORM_EISDIR, 0x1f, 0, \ "Is a directory" ) /** Too many levels of symbolic links */ #define ELOOP __einfo_error ( EINFO_ELOOP ) -#define EINFO_ELOOP __einfo ( PXENV_STATUS_FAILURE, 0x20, 0, \ +#define EINFO_ELOOP __einfo ( PLATFORM_ELOOP, 0x20, 0, \ "Too many levels of symbolic links" ) /** Too many open files */ #define EMFILE __einfo_error ( EINFO_EMFILE ) -#define EINFO_EMFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x21, 0, \ +#define EINFO_EMFILE __einfo ( PLATFORM_EMFILE, 0x21, 0, \ "Too many open files" ) /** Too many links */ #define EMLINK __einfo_error ( EINFO_EMLINK ) -#define EINFO_EMLINK __einfo ( PXENV_STATUS_FAILURE, 0x22, 0, \ +#define EINFO_EMLINK __einfo ( PLATFORM_EMLINK, 0x22, 0, \ "Too many links" ) /** Message too long */ #define EMSGSIZE __einfo_error ( EINFO_EMSGSIZE ) -#define EINFO_EMSGSIZE __einfo ( PXENV_STATUS_BAD_FUNC, 0x23, 0, \ +#define EINFO_EMSGSIZE __einfo ( PLATFORM_EMSGSIZE, 0x23, 0, \ "Message too long" ) /** Multihop attempted */ #define EMULTIHOP __einfo_error ( EINFO_EMULTIHOP ) -#define EINFO_EMULTIHOP __einfo ( PXENV_STATUS_FAILURE, 0x24, 0, \ +#define EINFO_EMULTIHOP __einfo ( PLATFORM_EMULTIHOP, 0x24, 0, \ "Multihop attempted" ) /** Filename too long */ #define ENAMETOOLONG __einfo_error ( EINFO_ENAMETOOLONG ) -#define EINFO_ENAMETOOLONG __einfo ( PXENV_STATUS_FAILURE, 0x25, 0, \ +#define EINFO_ENAMETOOLONG __einfo ( PLATFORM_ENAMETOOLONG, 0x25, 0, \ "Filename too long" ) /** Network is down */ #define ENETDOWN __einfo_error ( EINFO_ENETDOWN ) -#define EINFO_ENETDOWN __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x26, 0, \ +#define EINFO_ENETDOWN __einfo ( PLATFORM_ENETDOWN, 0x26, 0, \ "Network is down" ) /** Connection aborted by network */ #define ENETRESET __einfo_error ( EINFO_ENETRESET ) -#define EINFO_ENETRESET __einfo ( PXENV_STATUS_FAILURE, 0x27, 0, \ +#define EINFO_ENETRESET __einfo ( PLATFORM_ENETRESET, 0x27, 0, \ "Connection aborted by network" ) /** Network unreachable */ #define ENETUNREACH __einfo_error ( EINFO_ENETUNREACH ) -#define EINFO_ENETUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x28, 0, \ +#define EINFO_ENETUNREACH __einfo ( PLATFORM_ENETUNREACH, 0x28, 0, \ "Network unreachable" ) /** Too many open files in system */ #define ENFILE __einfo_error ( EINFO_ENFILE ) -#define EINFO_ENFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x29, 0, \ +#define EINFO_ENFILE __einfo ( PLATFORM_ENFILE, 0x29, 0, \ "Too many open files in system" ) /** No buffer space available */ #define ENOBUFS __einfo_error ( EINFO_ENOBUFS ) -#define EINFO_ENOBUFS __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x2a, 0, \ +#define EINFO_ENOBUFS __einfo ( PLATFORM_ENOBUFS, 0x2a, 0, \ "No buffer space available" ) /** No message is available on the STREAM head read queue */ #define ENODATA __einfo_error ( EINFO_ENODATA ) -#define EINFO_ENODATA \ - __einfo ( PXENV_STATUS_FAILURE, 0x2b, 0, \ - "No message is available on the STREAM head read queue" ) +#define EINFO_ENODATA __einfo ( PLATFORM_ENODATA, 0x2b, 0, \ + "No message is available on the STREAM " \ + "head read queue" ) /** No such device */ #define ENODEV __einfo_error ( EINFO_ENODEV ) -#define EINFO_ENODEV __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2c, 0, \ +#define EINFO_ENODEV __einfo ( PLATFORM_ENODEV, 0x2c, 0, \ "No such device" ) /** No such file or directory */ #define ENOENT __einfo_error ( EINFO_ENOENT ) -#define EINFO_ENOENT __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2d, 0, \ +#define EINFO_ENOENT __einfo ( PLATFORM_ENOENT, 0x2d, 0, \ "No such file or directory" ) /** Exec format error */ #define ENOEXEC __einfo_error ( EINFO_ENOEXEC ) -#define EINFO_ENOEXEC __einfo ( PXENV_STATUS_FAILURE, 0x2e, 0, \ +#define EINFO_ENOEXEC __einfo ( PLATFORM_ENOEXEC, 0x2e, 0, \ "Exec format error" ) /** No locks available */ #define ENOLCK __einfo_error ( EINFO_ENOLCK ) -#define EINFO_ENOLCK __einfo ( PXENV_STATUS_FAILURE, 0x2f, 0, \ +#define EINFO_ENOLCK __einfo ( PLATFORM_ENOLCK, 0x2f, 0, \ "No locks available" ) /** Link has been severed */ #define ENOLINK __einfo_error ( EINFO_ENOLINK ) -#define EINFO_ENOLINK __einfo ( PXENV_STATUS_FAILURE, 0x30, 0, \ +#define EINFO_ENOLINK __einfo ( PLATFORM_ENOLINK, 0x30, 0, \ "Link has been severed" ) /** Not enough space */ #define ENOMEM __einfo_error ( EINFO_ENOMEM ) -#define EINFO_ENOMEM __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x31, 0, \ +#define EINFO_ENOMEM __einfo ( PLATFORM_ENOMEM, 0x31, 0, \ "Not enough space" ) /** No message of the desired type */ #define ENOMSG __einfo_error ( EINFO_ENOMSG ) -#define EINFO_ENOMSG __einfo ( PXENV_STATUS_FAILURE, 0x32, 0, \ +#define EINFO_ENOMSG __einfo ( PLATFORM_ENOMSG, 0x32, 0, \ "No message of the desired type" ) /** Protocol not available */ #define ENOPROTOOPT __einfo_error ( EINFO_ENOPROTOOPT ) -#define EINFO_ENOPROTOOPT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x33, 0, \ +#define EINFO_ENOPROTOOPT __einfo ( PLATFORM_ENOPROTOOPT, 0x33, 0, \ "Protocol not available" ) /** No space left on device */ #define ENOSPC __einfo_error ( EINFO_ENOSPC ) -#define EINFO_ENOSPC __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x34, 0, \ +#define EINFO_ENOSPC __einfo ( PLATFORM_ENOSPC, 0x34, 0, \ "No space left on device" ) /** No STREAM resources */ #define ENOSR __einfo_error ( EINFO_ENOSR ) -#define EINFO_ENOSR __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x35, 0, \ +#define EINFO_ENOSR __einfo ( PLATFORM_ENOSR, 0x35, 0, \ "No STREAM resources" ) /** Not a STREAM */ #define ENOSTR __einfo_error ( EINFO_ENOSTR ) -#define EINFO_ENOSTR __einfo ( PXENV_STATUS_FAILURE, 0x36, 0, \ +#define EINFO_ENOSTR __einfo ( PLATFORM_ENOSTR, 0x36, 0, \ "Not a STREAM" ) /** Function not implemented */ #define ENOSYS __einfo_error ( EINFO_ENOSYS ) -#define EINFO_ENOSYS __einfo ( PXENV_STATUS_UNSUPPORTED, 0x37, 0, \ +#define EINFO_ENOSYS __einfo ( PLATFORM_ENOSYS, 0x37, 0, \ "Function not implemented" ) /** The socket is not connected */ #define ENOTCONN __einfo_error ( EINFO_ENOTCONN ) -#define EINFO_ENOTCONN __einfo ( PXENV_STATUS_FAILURE, 0x38, 0, \ +#define EINFO_ENOTCONN __einfo ( PLATFORM_ENOTCONN, 0x38, 0, \ "The socket is not connected" ) /** Not a directory */ #define ENOTDIR __einfo_error ( EINFO_ENOTDIR ) -#define EINFO_ENOTDIR __einfo ( PXENV_STATUS_FAILURE, 0x39, 0, \ +#define EINFO_ENOTDIR __einfo ( PLATFORM_ENOTDIR, 0x39, 0, \ "Not a directory" ) /** Directory not empty */ #define ENOTEMPTY __einfo_error ( EINFO_ENOTEMPTY ) -#define EINFO_ENOTEMPTY __einfo ( PXENV_STATUS_FAILURE, 0x3a, 0, \ +#define EINFO_ENOTEMPTY __einfo ( PLATFORM_ENOTEMPTY, 0x3a, 0, \ "Directory not empty" ) /** Not a socket */ #define ENOTSOCK __einfo_error ( EINFO_ENOTSOCK ) -#define EINFO_ENOTSOCK __einfo ( PXENV_STATUS_FAILURE, 0x3b, 0, \ +#define EINFO_ENOTSOCK __einfo ( PLATFORM_ENOTSOCK, 0x3b, 0, \ "Not a socket" ) /** Operation not supported */ #define ENOTSUP __einfo_error ( EINFO_ENOTSUP ) -#define EINFO_ENOTSUP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3c, 0, \ +#define EINFO_ENOTSUP __einfo ( PLATFORM_ENOTSUP, 0x3c, 0, \ "Operation not supported" ) /** Inappropriate I/O control operation */ #define ENOTTY __einfo_error ( EINFO_ENOTTY ) -#define EINFO_ENOTTY __einfo ( PXENV_STATUS_FAILURE, 0x3d, 0, \ +#define EINFO_ENOTTY __einfo ( PLATFORM_ENOTTY, 0x3d, 0, \ "Inappropriate I/O control operation" ) /** No such device or address */ #define ENXIO __einfo_error ( EINFO_ENXIO ) -#define EINFO_ENXIO __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x3e, 0, \ +#define EINFO_ENXIO __einfo ( PLATFORM_ENXIO, 0x3e, 0, \ "No such device or address" ) /** Operation not supported on socket */ #define EOPNOTSUPP __einfo_error ( EINFO_EOPNOTSUPP ) -#define EINFO_EOPNOTSUPP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3f, 0, \ +#define EINFO_EOPNOTSUPP __einfo ( PLATFORM_EOPNOTSUPP, 0x3f, 0, \ "Operation not supported on socket" ) /** Value too large to be stored in data type */ #define EOVERFLOW __einfo_error ( EINFO_EOVERFLOW ) -#define EINFO_EOVERFLOW __einfo ( PXENV_STATUS_FAILURE, 0x40, 0, \ +#define EINFO_EOVERFLOW __einfo ( PLATFORM_EOVERFLOW, 0x40, 0, \ "Value too large to be stored in data type" ) /** Operation not permitted */ #define EPERM __einfo_error ( EINFO_EPERM ) -#define EINFO_EPERM __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x41, 0, \ +#define EINFO_EPERM __einfo ( PLATFORM_EPERM, 0x41, 0, \ "Operation not permitted" ) /** Broken pipe */ #define EPIPE __einfo_error ( EINFO_EPIPE ) -#define EINFO_EPIPE __einfo ( PXENV_STATUS_FAILURE, 0x42, 0, \ +#define EINFO_EPIPE __einfo ( PLATFORM_EPIPE, 0x42, 0, \ "Broken pipe" ) /** Protocol error */ #define EPROTO __einfo_error ( EINFO_EPROTO ) -#define EINFO_EPROTO __einfo ( PXENV_STATUS_FAILURE, 0x43, 0, \ +#define EINFO_EPROTO __einfo ( PLATFORM_EPROTO, 0x43, 0, \ "Protocol error" ) /** Protocol not supported */ #define EPROTONOSUPPORT __einfo_error ( EINFO_EPROTONOSUPPORT ) -#define EINFO_EPROTONOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x44, 0, \ +#define EINFO_EPROTONOSUPPORT __einfo ( PLATFORM_EPROTONOSUPPORT, 0x44, 0, \ "Protocol not supported" ) /** Protocol wrong type for socket */ #define EPROTOTYPE __einfo_error ( EINFO_EPROTOTYPE ) -#define EINFO_EPROTOTYPE __einfo ( PXENV_STATUS_FAILURE, 0x45, 0, \ +#define EINFO_EPROTOTYPE __einfo ( PLATFORM_EPROTOTYPE, 0x45, 0, \ "Protocol wrong type for socket" ) /** Result too large */ #define ERANGE __einfo_error ( EINFO_ERANGE ) -#define EINFO_ERANGE __einfo ( PXENV_STATUS_FAILURE, 0x46, 0, \ +#define EINFO_ERANGE __einfo ( PLATFORM_ERANGE, 0x46, 0, \ "Result too large" ) /** Read-only file system */ #define EROFS __einfo_error ( EINFO_EROFS ) -#define EINFO_EROFS __einfo ( PXENV_STATUS_FAILURE, 0x47, 0, \ +#define EINFO_EROFS __einfo ( PLATFORM_EROFS, 0x47, 0, \ "Read-only file system" ) /** Invalid seek */ #define ESPIPE __einfo_error ( EINFO_ESPIPE ) -#define EINFO_ESPIPE __einfo ( PXENV_STATUS_FAILURE, 0x48, 0, \ +#define EINFO_ESPIPE __einfo ( PLATFORM_ESPIPE, 0x48, 0, \ "Invalid seek" ) /** No such process */ #define ESRCH __einfo_error ( EINFO_ESRCH ) -#define EINFO_ESRCH __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x49, 0, \ +#define EINFO_ESRCH __einfo ( PLATFORM_ESRCH, 0x49, 0, \ "No such process" ) /** Stale file handle */ #define ESTALE __einfo_error ( EINFO_ESTALE ) -#define EINFO_ESTALE __einfo ( PXENV_STATUS_FAILURE, 0x4a, 0, \ +#define EINFO_ESTALE __einfo ( PLATFORM_ESTALE, 0x4a, 0, \ "Stale file handle" ) /** Timer expired */ #define ETIME __einfo_error ( EINFO_ETIME ) -#define EINFO_ETIME __einfo ( PXENV_STATUS_FAILURE, 0x4b, 0, \ +#define EINFO_ETIME __einfo ( PLATFORM_ETIME, 0x4b, 0, \ "Timer expired" ) /** Connection timed out */ #define ETIMEDOUT __einfo_error ( EINFO_ETIMEDOUT ) -#define EINFO_ETIMEDOUT __einfo ( PXENV_STATUS_TFTP_READ_TIMEOUT, 0x4c, 0, \ +#define EINFO_ETIMEDOUT __einfo ( PLATFORM_ETIMEDOUT, 0x4c, 0, \ "Connection timed out" ) /** Text file busy */ #define ETXTBSY __einfo_error ( EINFO_ETXTBSY ) -#define EINFO_ETXTBSY __einfo ( PXENV_STATUS_FAILURE, 0x4d, 0, \ +#define EINFO_ETXTBSY __einfo ( PLATFORM_ETXTBSY, 0x4d, 0, \ "Text file busy" ) /** Operation would block */ #define EWOULDBLOCK __einfo_error ( EINFO_EWOULDBLOCK ) -#define EINFO_EWOULDBLOCK __einfo ( PXENV_STATUS_TFTP_OPEN, 0x4e, 0, \ +#define EINFO_EWOULDBLOCK __einfo ( PLATFORM_EWOULDBLOCK, 0x4e, 0, \ "Operation would block" ) /** Improper link */ #define EXDEV __einfo_error ( EINFO_EXDEV ) -#define EINFO_EXDEV __einfo ( PXENV_STATUS_FAILURE, 0x4f, 0, \ +#define EINFO_EXDEV __einfo ( PLATFORM_EXDEV, 0x4f, 0, \ "Improper link" ) /** @} */ +/** Platform-generated base error */ +#define EINFO_EPLATFORM __einfo ( 0, 0x7f, 0, "Platform-generated error" ) + extern int errno; #endif /* ERRNO_H */ diff --git a/src/include/ipxe/errno/efi.h b/src/include/ipxe/errno/efi.h new file mode 100644 index 00000000..e4f9e5fe --- /dev/null +++ b/src/include/ipxe/errno/efi.h @@ -0,0 +1,129 @@ +#ifndef _IPXE_ERRNO_EFI_H +#define _IPXE_ERRNO_EFI_H + +/** + * @file + * + * EFI platform error codes + * + * We derive our platform error codes from the possible values for + * EFI_STATUS defined in the UEFI specification. + * + * EFI_STATUS codes are 32-bit values consisting of a top bit which is + * set for errors and clear for warnings, and a mildly undefined + * code of low bits indicating the precise error/warning code. + * Errors and warnings have completely separate namespaces. + * + * We assume that no EFI_STATUS code will ever be defined which uses + * more than bits 0-6 of the low bits. We then choose to encode our + * platform-specific error by mapping bit 31 of the EFI_STATUS to bit + * 7 of the platform-specific error code, and preserving bits 0-6 + * as-is. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** + * Convert platform error code to platform component of iPXE error code + * + * @v platform Platform error code + * @ret errno Platform component of iPXE error code + */ +#define PLATFORM_TO_ERRNO( platform ) \ + ( ( (platform) | ( (platform) >> 24 ) ) & 0xff ) + +/** + * Convert iPXE error code to platform error code + * + * @v errno iPXE error code + * @ret platform Platform error code + */ +#define ERRNO_TO_PLATFORM( errno ) \ + ( ( ( (errno) << 24 ) | (errno) ) & 0x8000007f ) + +/* Platform-specific error codes */ +#define PLATFORM_ENOERR EFI_SUCCESS +#define PLATFORM_E2BIG EFI_BUFFER_TOO_SMALL +#define PLATFORM_EACCES EFI_ACCESS_DENIED +#define PLATFORM_EADDRINUSE EFI_ALREADY_STARTED +#define PLATFORM_EADDRNOTAVAIL EFI_NOT_READY +#define PLATFORM_EAFNOSUPPORT EFI_UNSUPPORTED +#define PLATFORM_EAGAIN EFI_NOT_READY +#define PLATFORM_EALREADY EFI_ALREADY_STARTED +#define PLATFORM_EBADF EFI_INVALID_PARAMETER +#define PLATFORM_EBADMSG EFI_PROTOCOL_ERROR +#define PLATFORM_EBUSY EFI_NO_RESPONSE +#define PLATFORM_ECANCELED EFI_ABORTED +#define PLATFORM_ECHILD EFI_NOT_FOUND +#define PLATFORM_ECONNABORTED EFI_ABORTED +#define PLATFORM_ECONNREFUSED EFI_NO_RESPONSE +#define PLATFORM_ECONNRESET EFI_ABORTED +#define PLATFORM_EDEADLK EFI_NOT_READY +#define PLATFORM_EDESTADDRREQ EFI_PROTOCOL_ERROR +#define PLATFORM_EDOM EFI_INVALID_PARAMETER +#define PLATFORM_EDQUOT EFI_VOLUME_FULL +#define PLATFORM_EEXIST EFI_WRITE_PROTECTED +#define PLATFORM_EFAULT EFI_INVALID_PARAMETER +#define PLATFORM_EFBIG EFI_END_OF_MEDIA +#define PLATFORM_EHOSTUNREACH EFI_NO_RESPONSE +#define PLATFORM_EIDRM EFI_INVALID_PARAMETER +#define PLATFORM_EILSEQ EFI_INVALID_PARAMETER +#define PLATFORM_EINPROGRESS EFI_ALREADY_STARTED +#define PLATFORM_EINTR EFI_NOT_READY +#define PLATFORM_EINVAL EFI_INVALID_PARAMETER +#define PLATFORM_EIO EFI_PROTOCOL_ERROR +#define PLATFORM_EISCONN EFI_ALREADY_STARTED +#define PLATFORM_EISDIR EFI_PROTOCOL_ERROR +#define PLATFORM_ELOOP EFI_VOLUME_CORRUPTED +#define PLATFORM_EMFILE EFI_OUT_OF_RESOURCES +#define PLATFORM_EMLINK EFI_OUT_OF_RESOURCES +#define PLATFORM_EMSGSIZE EFI_BAD_BUFFER_SIZE +#define PLATFORM_EMULTIHOP EFI_INVALID_PARAMETER +#define PLATFORM_ENAMETOOLONG EFI_INVALID_PARAMETER +#define PLATFORM_ENETDOWN EFI_NO_RESPONSE +#define PLATFORM_ENETRESET EFI_ABORTED +#define PLATFORM_ENETUNREACH EFI_NO_RESPONSE +#define PLATFORM_ENFILE EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOBUFS EFI_OUT_OF_RESOURCES +#define PLATFORM_ENODATA EFI_NO_RESPONSE +#define PLATFORM_ENODEV EFI_DEVICE_ERROR +#define PLATFORM_ENOENT EFI_NOT_FOUND +#define PLATFORM_ENOEXEC EFI_LOAD_ERROR +#define PLATFORM_ENOLCK EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOLINK EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOMEM EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOMSG EFI_PROTOCOL_ERROR +#define PLATFORM_ENOPROTOOPT EFI_UNSUPPORTED +#define PLATFORM_ENOSPC EFI_VOLUME_FULL +#define PLATFORM_ENOSR EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOSTR EFI_PROTOCOL_ERROR +#define PLATFORM_ENOSYS EFI_UNSUPPORTED +#define PLATFORM_ENOTCONN EFI_NOT_STARTED +#define PLATFORM_ENOTDIR EFI_VOLUME_CORRUPTED +#define PLATFORM_ENOTEMPTY EFI_VOLUME_CORRUPTED +#define PLATFORM_ENOTSOCK EFI_INVALID_PARAMETER +#define PLATFORM_ENOTSUP EFI_UNSUPPORTED +#define PLATFORM_ENOTTY EFI_UNSUPPORTED +#define PLATFORM_ENXIO EFI_NOT_FOUND +#define PLATFORM_EOPNOTSUPP EFI_UNSUPPORTED +#define PLATFORM_EOVERFLOW EFI_BUFFER_TOO_SMALL +#define PLATFORM_EPERM EFI_ACCESS_DENIED +#define PLATFORM_EPIPE EFI_ABORTED +#define PLATFORM_EPROTO EFI_PROTOCOL_ERROR +#define PLATFORM_EPROTONOSUPPORT EFI_UNSUPPORTED +#define PLATFORM_EPROTOTYPE EFI_INVALID_PARAMETER +#define PLATFORM_ERANGE EFI_BUFFER_TOO_SMALL +#define PLATFORM_EROFS EFI_WRITE_PROTECTED +#define PLATFORM_ESPIPE EFI_END_OF_FILE +#define PLATFORM_ESRCH EFI_NOT_STARTED +#define PLATFORM_ESTALE EFI_PROTOCOL_ERROR +#define PLATFORM_ETIME EFI_TIMEOUT +#define PLATFORM_ETIMEDOUT EFI_TIMEOUT +#define PLATFORM_ETXTBSY EFI_MEDIA_CHANGED +#define PLATFORM_EWOULDBLOCK EFI_NOT_READY +#define PLATFORM_EXDEV EFI_VOLUME_CORRUPTED + +#endif /* _IPXE_ERRNO_EFI_H */ diff --git a/src/include/ipxe/errno/linux.h b/src/include/ipxe/errno/linux.h new file mode 100644 index 00000000..11309b4a --- /dev/null +++ b/src/include/ipxe/errno/linux.h @@ -0,0 +1,113 @@ +#ifndef _IPXE_ERRNO_LINUX_H +#define _IPXE_ERRNO_LINUX_H + +/** + * @file + * + * Linux platform error codes + * + * Linux error codes all fit inside 8 bits, so we just use them + * directly as our platform error codes. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * Convert platform error code to platform component of iPXE error code + * + * @v platform Platform error code + * @ret errno Platform component of iPXE error code + */ +#define PLATFORM_TO_ERRNO( platform ) ( (platform) & 0xff ) + +/** + * Convert iPXE error code to platform error code + * + * @v errno iPXE error code + * @ret platform Platform error code + */ +#define ERRNO_TO_PLATFORM( errno ) ( (errno) & 0xff ) + +/* Platform-specific error codes */ +#define PLATFORM_ENOERR 0 +#define PLATFORM_E2BIG 7 +#define PLATFORM_EACCES 13 +#define PLATFORM_EADDRINUSE 98 +#define PLATFORM_EADDRNOTAVAIL 99 +#define PLATFORM_EAFNOSUPPORT 97 +#define PLATFORM_EAGAIN 11 +#define PLATFORM_EALREADY 114 +#define PLATFORM_EBADF 9 +#define PLATFORM_EBADMSG 74 +#define PLATFORM_EBUSY 16 +#define PLATFORM_ECANCELED 125 +#define PLATFORM_ECHILD 10 +#define PLATFORM_ECONNABORTED 103 +#define PLATFORM_ECONNREFUSED 111 +#define PLATFORM_ECONNRESET 104 +#define PLATFORM_EDEADLK 35 +#define PLATFORM_EDESTADDRREQ 89 +#define PLATFORM_EDOM 33 +#define PLATFORM_EDQUOT 122 +#define PLATFORM_EEXIST 17 +#define PLATFORM_EFAULT 14 +#define PLATFORM_EFBIG 27 +#define PLATFORM_EHOSTUNREACH 113 +#define PLATFORM_EIDRM 43 +#define PLATFORM_EILSEQ 84 +#define PLATFORM_EINPROGRESS 115 +#define PLATFORM_EINTR 4 +#define PLATFORM_EINVAL 22 +#define PLATFORM_EIO 5 +#define PLATFORM_EISCONN 106 +#define PLATFORM_EISDIR 21 +#define PLATFORM_ELOOP 40 +#define PLATFORM_EMFILE 24 +#define PLATFORM_EMLINK 31 +#define PLATFORM_EMSGSIZE 90 +#define PLATFORM_EMULTIHOP 72 +#define PLATFORM_ENAMETOOLONG 36 +#define PLATFORM_ENETDOWN 100 +#define PLATFORM_ENETRESET 102 +#define PLATFORM_ENETUNREACH 101 +#define PLATFORM_ENFILE 23 +#define PLATFORM_ENOBUFS 105 +#define PLATFORM_ENODATA 61 +#define PLATFORM_ENODEV 19 +#define PLATFORM_ENOENT 2 +#define PLATFORM_ENOEXEC 8 +#define PLATFORM_ENOLCK 37 +#define PLATFORM_ENOLINK 67 +#define PLATFORM_ENOMEM 12 +#define PLATFORM_ENOMSG 42 +#define PLATFORM_ENOPROTOOPT 92 +#define PLATFORM_ENOSPC 28 +#define PLATFORM_ENOSR 63 +#define PLATFORM_ENOSTR 60 +#define PLATFORM_ENOSYS 38 +#define PLATFORM_ENOTCONN 107 +#define PLATFORM_ENOTDIR 20 +#define PLATFORM_ENOTEMPTY 39 +#define PLATFORM_ENOTSOCK 88 +#define PLATFORM_ENOTSUP PLATFORM_EOPNOTSUPP +#define PLATFORM_ENOTTY 25 +#define PLATFORM_ENXIO 6 +#define PLATFORM_EOPNOTSUPP 95 +#define PLATFORM_EOVERFLOW 75 +#define PLATFORM_EPERM 1 +#define PLATFORM_EPIPE 32 +#define PLATFORM_EPROTO 71 +#define PLATFORM_EPROTONOSUPPORT 93 +#define PLATFORM_EPROTOTYPE 91 +#define PLATFORM_ERANGE 34 +#define PLATFORM_EROFS 30 +#define PLATFORM_ESPIPE 29 +#define PLATFORM_ESRCH 3 +#define PLATFORM_ESTALE 116 +#define PLATFORM_ETIME 62 +#define PLATFORM_ETIMEDOUT 110 +#define PLATFORM_ETXTBSY 26 +#define PLATFORM_EWOULDBLOCK PLATFORM_EAGAIN +#define PLATFORM_EXDEV 18 + +#endif /* _IPXE_ERRNO_LINUX_H */ diff --git a/src/util/einfo.c b/src/util/einfo.c index 354d475f..d2155898 100644 --- a/src/util/einfo.c +++ b/src/util/einfo.c @@ -38,10 +38,15 @@ struct options { /** Error usage information */ struct einfo { + /** Size of error information record */ uint32_t size; + /** Error number */ uint32_t error; + /** Offset to error description (NUL-terminated) */ uint32_t desc; + /** Offset to file name (NUL-terminated) */ uint32_t file; + /** Line number */ uint32_t line; } __attribute__ (( packed )); From 54409583e29c481556e94a99dc73316d18aafc74 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 18 Apr 2013 21:29:53 +0100 Subject: [PATCH 08/45] [efi] Perform meaningful error code conversions Exploit the redefinition of iPXE error codes to include a "platform error code" to allow for meaningful conversion of EFI_STATUS values to iPXE errors and vice versa. Signed-off-by: Michael Brown --- src/arch/x86/prefix/efiprefix.c | 3 +- src/drivers/net/efi/snpnet.c | 83 +++++++++++++++++-------------- src/image/efi_image.c | 19 ++++--- src/include/ipxe/efi/efi.h | 22 ++++---- src/include/ipxe/efi/efi_driver.h | 2 +- src/include/ipxe/efi/efi_pci.h | 6 +-- src/include/ipxe/errfile.h | 9 ++++ src/interface/efi/efi_bofm.c | 32 ++++++------ src/interface/efi/efi_console.c | 7 ++- src/interface/efi/efi_debug.c | 5 +- src/interface/efi/efi_download.c | 27 +++++++--- src/interface/efi/efi_driver.c | 10 ++-- src/interface/efi/efi_file.c | 7 ++- src/interface/efi/efi_init.c | 11 ++-- src/interface/efi/efi_pci.c | 47 +++++++++-------- src/interface/efi/efi_snp.c | 42 +++++++--------- src/interface/efi/efi_snp_hii.c | 14 +++--- src/interface/efi/efi_strerror.c | 46 ----------------- src/interface/efi/efi_timer.c | 11 ++-- src/interface/efi/efi_umalloc.c | 9 +++- 20 files changed, 212 insertions(+), 200 deletions(-) delete mode 100644 src/interface/efi/efi_strerror.c diff --git a/src/arch/x86/prefix/efiprefix.c b/src/arch/x86/prefix/efiprefix.c index bfa94d40..a847045a 100644 --- a/src/arch/x86/prefix/efiprefix.c +++ b/src/arch/x86/prefix/efiprefix.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include /** @@ -38,5 +39,5 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle, return efirc; /* Call to main() */ - return RC_TO_EFIRC ( main () ); + return EFIRC ( main () ); } diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c index 97790815..cd9e7e38 100644 --- a/src/drivers/net/efi/snpnet.c +++ b/src/drivers/net/efi/snpnet.c @@ -56,20 +56,21 @@ static int snpnet_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; - EFI_STATUS efirc; void *txbuf=NULL; size_t len = iob_len ( iobuf ); + EFI_STATUS efirc; + int rc; - efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, NULL ); - if (efirc) { - return EFIRC_TO_RC ( efirc ); + if ( ( efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, + NULL ) ) != 0 ) { + return -EEFI ( efirc ); } /* since GetStatus is so inconsistent, don't try more than one outstanding transmit at a time */ while ( txbuf == NULL ) { - efirc = snp->GetStatus ( snp, NULL, &txbuf ); - if ( efirc ) { + if ( ( efirc = snp->GetStatus ( snp, NULL, &txbuf ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not get status %s\n", snp, - efi_strerror ( efirc ) ); + strerror ( rc ) ); break; } @@ -86,9 +87,10 @@ static int snpnet_transmit ( struct net_device *netdev, static void snpnet_poll ( struct net_device *netdev ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; - EFI_STATUS efirc; struct io_buffer *iobuf = NULL; UINTN len; + EFI_STATUS efirc; + int rc; /* Process received packets */ while ( 1 ) { @@ -115,12 +117,13 @@ static void snpnet_poll ( struct net_device *netdev ) { } /* Other error? */ - if ( efirc ) { + if ( efirc != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p receive packet error: %s " "(len was %zd, is now %zd)\n", - snp, efi_strerror ( efirc ), iob_len(iobuf), + snp, strerror ( rc ), iob_len(iobuf), (size_t)len ); - netdev_rx_err ( netdev, iobuf, efirc ); + netdev_rx_err ( netdev, iobuf, rc ); break; } @@ -139,25 +142,27 @@ static void snpnet_poll ( struct net_device *netdev ) { static int snpnet_open ( struct net_device *netdev ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; - EFI_STATUS efirc; + EFI_MAC_ADDRESS *mac; UINT32 enableFlags, disableFlags; + EFI_STATUS efirc; + int rc; snpnetdev->close_state = snp->Mode->State; if ( snp->Mode->State != EfiSimpleNetworkInitialized ) { - efirc = snp->Initialize ( snp, 0, 0 ); - if ( efirc ) { + if ( ( efirc = snp->Initialize ( snp, 0, 0 ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not initialize: %s\n", - snp, efi_strerror ( efirc ) ); - return EFIRC_TO_RC ( efirc ); + snp, strerror ( rc ) ); + return rc; } } /* Use the default MAC address */ - efirc = snp->StationAddress ( snp, FALSE, - (EFI_MAC_ADDRESS *)netdev->ll_addr ); - if ( efirc ) { + mac = ( ( void * ) netdev->ll_addr ); + if ( ( efirc = snp->StationAddress ( snp, FALSE, mac ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not reset station address: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } /* Set up receive filters to receive unicast and broadcast packets @@ -179,11 +184,11 @@ static int snpnet_open ( struct net_device *netdev ) { enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; } disableFlags &= ~enableFlags; - efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags, - FALSE, 0, NULL ); - if ( efirc ) { + if ( ( efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags, + FALSE, 0, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not set receive filters: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } DBGC ( snp, "SNP %p opened\n", snp ); @@ -199,12 +204,13 @@ static void snpnet_close ( struct net_device *netdev ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; EFI_STATUS efirc; + int rc; if ( snpnetdev->close_state != EfiSimpleNetworkInitialized ) { - efirc = snp->Shutdown ( snp ); - if ( efirc ) { + if ( ( efirc = snp->Shutdown ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not shut down: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } } } @@ -264,11 +270,10 @@ int snpnet_probe ( struct snp_device *snpdev ) { /* Start the interface */ if ( snp->Mode->State == EfiSimpleNetworkStopped ) { - efirc = snp->Start ( snp ); - if ( efirc ) { + if ( ( efirc = snp->Start ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not start: %s\n", snp, - efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + strerror ( rc ) ); goto err_start; } } @@ -310,25 +315,27 @@ err_start: */ void snpnet_remove ( struct snp_device *snpdev ) { EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp; - EFI_STATUS efirc; struct net_device *netdev = snpdev->netdev; + EFI_STATUS efirc; + int rc; if ( snp->Mode->State == EfiSimpleNetworkInitialized && snpdev->removal_state != EfiSimpleNetworkInitialized ) { DBGC ( snp, "SNP %p shutting down\n", snp ); - efirc = snp->Shutdown ( snp ); - if ( efirc ) { + if ( ( efirc = snp->Shutdown ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not shut down: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } } if ( snp->Mode->State == EfiSimpleNetworkStarted && snpdev->removal_state == EfiSimpleNetworkStopped ) { DBGC ( snp, "SNP %p stopping\n", snp ); - efirc = snp->Stop ( snp ); - if ( efirc ) { - DBGC ( snp, "SNP %p could not be stopped\n", snp ); + if ( ( efirc = snp->Stop ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); + DBGC ( snp, "SNP %p could not be stopped: %s\n", + snp, strerror ( rc ) ); } } diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 0368b82c..0e90954b 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -176,9 +176,9 @@ static int efi_image_exec ( struct image *image ) { user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ + rc = -EEFI ( efirc ); DBGC ( image, "EFIIMAGE %p could not load: %s\n", - image, efi_strerror ( efirc ) ); - rc = -ENOEXEC; + image, strerror ( rc ) ); goto err_load_image; } @@ -188,7 +188,7 @@ static int efi_image_exec ( struct image *image ) { NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( efirc ) { /* Should never happen */ - rc = EFIRC_TO_RC ( efirc ); + rc = -EEFI ( efirc ); goto err_open_protocol; } @@ -205,9 +205,9 @@ static int efi_image_exec ( struct image *image ) { /* Start the image */ if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( image, "EFIIMAGE %p returned with status %s\n", - image, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + image, strerror ( rc ) ); goto err_start_image; } @@ -220,8 +220,9 @@ static int efi_image_exec ( struct image *image ) { * have no "unload" operation. */ if ( ( efirc = bs->UnloadImage ( handle ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( image, "EFIIMAGE %p could not unload: %s\n", - image, efi_strerror ( efirc ) ); + image, strerror ( rc ) ); } err_load_image: free ( cmdline ); @@ -246,15 +247,17 @@ static int efi_image_probe ( struct image *image ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_HANDLE handle; EFI_STATUS efirc; + int rc; /* Attempt loading image */ if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL, user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ + rc = -EEFI ( efirc ); DBGC ( image, "EFIIMAGE %p could not load: %s\n", - image, efi_strerror ( efirc ) ); - return -ENOEXEC; + image, strerror ( rc ) ); + return rc; } /* Unload the image. We can't leave it loaded, because we diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 3aaac60e..0a21c6e7 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -108,29 +108,27 @@ struct efi_config_table { .required = (_required), \ } -/** Convert a iPXE status code to an EFI status code +/** + * Convert an iPXE status code to an EFI status code * - * FIXME: actually perform some kind of conversion. iPXE error codes - * will be detected as EFI error codes; both have the top bit set, and - * the success return code is zero for both. Anything that just - * reports a numerical error will be OK, anything attempting to - * interpret the value or to display a text equivalent will be - * screwed. + * @v rc iPXE status code + * @ret efirc EFI status code */ -#define RC_TO_EFIRC( rc ) (rc) +#define EFIRC( rc ) ERRNO_TO_PLATFORM ( -(rc) ) -/** Convert an EFI status code to a iPXE status code +/** + * Convert an EFI status code to an iPXE status code * - * FIXME: as above + * @v efirc EFI status code + * @ret rc iPXE status code (before negation) */ -#define EFIRC_TO_RC( efirc ) (efirc) +#define EEFI( efirc ) EPLATFORM ( EINFO_EPLATFORM, efirc ) extern EFI_HANDLE efi_image_handle; extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; extern EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path; extern EFI_SYSTEM_TABLE *efi_systab; -extern const char * efi_strerror ( EFI_STATUS efirc ); extern const char * efi_guid_ntoa ( EFI_GUID *guid ); extern void dbg_efi_protocols ( EFI_HANDLE handle ); diff --git a/src/include/ipxe/efi/efi_driver.h b/src/include/ipxe/efi/efi_driver.h index e5872ced..d7eec964 100644 --- a/src/include/ipxe/efi/efi_driver.h +++ b/src/include/ipxe/efi/efi_driver.h @@ -44,6 +44,6 @@ struct efi_driver { extern EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ); -extern EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ); +extern int efi_driver_install ( struct efi_driver *efidrv ); #endif /* _IPXE_EFI_DRIVER_H */ diff --git a/src/include/ipxe/efi/efi_pci.h b/src/include/ipxe/efi/efi_pci.h index 6429f210..e6b31970 100644 --- a/src/include/ipxe/efi/efi_pci.h +++ b/src/include/ipxe/efi/efi_pci.h @@ -38,11 +38,11 @@ struct efi_pci_device { extern struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, EFI_HANDLE device ); -extern EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ); +extern int efipci_enable ( struct efi_pci_device *efipci ); extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ); extern struct efi_pci_device * efipci_find ( struct device *dev ); -extern EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, - EFI_HANDLE device ); +extern int efipci_child_add ( struct efi_pci_device *efipci, + EFI_HANDLE device ); extern void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ); extern void efipci_destroy ( struct efi_driver *efidrv, diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index f906dbd5..67edcc93 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -266,6 +266,15 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 ) #define ERRFILE_efi_snp_hii ( ERRFILE_OTHER | 0x00310000 ) #define ERRFILE_readline ( ERRFILE_OTHER | 0x00320000 ) +#define ERRFILE_efi_bofm ( ERRFILE_OTHER | 0x00330000 ) +#define ERRFILE_efi_console ( ERRFILE_OTHER | 0x00340000 ) +#define ERRFILE_efi_debug ( ERRFILE_OTHER | 0x00350000 ) +#define ERRFILE_efi_download ( ERRFILE_OTHER | 0x00360000 ) +#define ERRFILE_efi_driver ( ERRFILE_OTHER | 0x00370000 ) +#define ERRFILE_efi_file ( ERRFILE_OTHER | 0x00380000 ) +#define ERRFILE_efi_init ( ERRFILE_OTHER | 0x00390000 ) +#define ERRFILE_efi_timer ( ERRFILE_OTHER | 0x003a0000 ) +#define ERRFILE_efi_umalloc ( ERRFILE_OTHER | 0x003b0000 ) /** @} */ diff --git a/src/interface/efi/efi_bofm.c b/src/interface/efi/efi_bofm.c index c313d2e9..8a8489bd 100644 --- a/src/interface/efi/efi_bofm.c +++ b/src/interface/efi/efi_bofm.c @@ -181,7 +181,7 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, /* Create corresponding PCI device, if any */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { - efirc = EFI_UNSUPPORTED; + rc = -ENOTSUP; goto err_not_pci; } @@ -189,16 +189,15 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) { DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); - efirc = EFI_UNSUPPORTED; goto err_no_driver; } /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " "protocol\n", PCI_ARGS ( &efipci->pci ) ); - efirc = EFI_UNSUPPORTED; goto err_not_bofm; } @@ -207,9 +206,10 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, 0x04 /* Can change MAC */, 0x00 /* No iSCSI */, 0x02 /* Version */ ))!=0){ + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register " "support: %s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); + strerror ( rc ) ); goto err_cannot_register; } @@ -226,7 +226,7 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, err_no_driver: efipci_destroy ( efidrv, efipci ); err_not_pci: - return efirc; + return EFIRC ( rc ); } /** @@ -254,25 +254,27 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, struct efi_pci_device *efipci; IBM_BOFM_TABLE *bofmtab; IBM_BOFM_TABLE *bofmtab2; - EFI_STATUS efirc; int bofmrc; + EFI_STATUS efirc; + int rc; DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child ); /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { - efirc = EFI_OUT_OF_RESOURCES; + rc = -ENOMEM; goto err_create; } /* Enable PCI device */ - if ( ( efirc = efipci_enable ( efipci ) ) != 0 ) + if ( ( rc = efipci_enable ( efipci ) ) != 0 ) goto err_enable; /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " "protocol\n", PCI_ARGS ( &efipci->pci ) ); goto err_locate_bofm; @@ -324,17 +326,19 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, if ( bofmtab2 ) { if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device, FALSE, bofmrc ) ) != 0){ + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set " "BOFM2 status: %s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); + strerror ( rc ) ); goto err_set_status; } } else { if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device, FALSE, bofmrc ) ) != 0){ + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set " "BOFM status: %s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); + strerror ( rc ) ); goto err_set_status; } } @@ -350,7 +354,7 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, err_enable: efipci_destroy ( efidrv, efipci ); err_create: - return efirc; + return EFIRC ( rc ); } /** @@ -385,12 +389,12 @@ static struct efi_driver efi_bofm_driver = */ static void efi_bofm_driver_init ( void ) { struct efi_driver *efidrv = &efi_bofm_driver; - EFI_STATUS efirc; + int rc; /* Install driver */ - if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { + if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) { DBGC ( efidrv, "EFIBOFM could not install driver: %s\n", - efi_strerror ( efirc ) ); + strerror ( rc ) ); return; } diff --git a/src/interface/efi/efi_console.c b/src/interface/efi/efi_console.c index a30ca301..d86d30c9 100644 --- a/src/interface/efi/efi_console.c +++ b/src/interface/efi/efi_console.c @@ -20,6 +20,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include +#include #include #include #include @@ -227,6 +229,7 @@ static int efi_getchar ( void ) { const char *ansi_seq; EFI_INPUT_KEY key; EFI_STATUS efirc; + int rc; /* If we are mid-sequence, pass out the next byte */ if ( *ansi_input ) @@ -234,8 +237,8 @@ static int efi_getchar ( void ) { /* Read key from real EFI console */ if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) { - DBG ( "EFI could not read keystroke: %s\n", - efi_strerror ( efirc ) ); + rc = -EEFI ( efirc ); + DBG ( "EFI could not read keystroke: %s\n", strerror ( rc ) ); return 0; } DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n", diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c index a7ba7e2e..4ed66607 100644 --- a/src/interface/efi/efi_debug.c +++ b/src/interface/efi/efi_debug.c @@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -67,12 +68,14 @@ void dbg_efi_protocols ( EFI_HANDLE handle ) { UINTN count; unsigned int i; EFI_STATUS efirc; + int rc; /* Retrieve list of protocols */ if ( ( efirc = bs->ProtocolsPerHandle ( handle, &protocols, &count ) ) != 0 ) { + rc = -EEFI ( efirc ); printf ( "EFI could not retrieve protocols for %p: %s\n", - handle, efi_strerror ( efirc ) ); + handle, strerror ( rc ) ); return; } diff --git a/src/interface/efi/efi_download.c b/src/interface/efi/efi_download.c index 7b19ad3a..80279f7f 100644 --- a/src/interface/efi/efi_download.c +++ b/src/interface/efi/efi_download.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -59,7 +60,7 @@ struct efi_download_file { */ static void efi_download_close ( struct efi_download_file *file, int rc ) { - file->finish_callback ( file->context, RC_TO_EFIRC ( rc ) ); + file->finish_callback ( file->context, EFIRC ( rc ) ); intf_shutdown ( &file->xfer, rc ); } @@ -77,6 +78,7 @@ static int efi_download_deliver_iob ( struct efi_download_file *file, struct xfer_metadata *meta ) { EFI_STATUS efirc; size_t len = iob_len ( iobuf ); + int rc; /* Calculate new buffer position */ if ( meta->flags & XFER_FL_ABS_OFFSET ) @@ -84,14 +86,21 @@ static int efi_download_deliver_iob ( struct efi_download_file *file, file->pos += meta->offset; /* Call out to the data handler */ - efirc = file->data_callback ( file->context, iobuf->data, - len, file->pos ); + if ( ( efirc = file->data_callback ( file->context, iobuf->data, + len, file->pos ) ) != 0 ) { + rc = -EEFI ( efirc ); + goto err_callback; + } /* Update current buffer position */ file->pos += len; + /* Success */ + rc = 0; + + err_callback: free_iob ( iobuf ); - return EFIRC_TO_RC ( efirc ); + return rc; } /** Data transfer interface operations */ @@ -135,7 +144,7 @@ efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused, rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url ); if ( rc ) { free ( file ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } file->pos = 0; @@ -162,7 +171,7 @@ efi_download_abort ( IPXE_DOWNLOAD_PROTOCOL *This __unused, EFI_STATUS Status ) { struct efi_download_file *file = File; - efi_download_close ( file, EFIRC_TO_RC ( Status ) ); + efi_download_close ( file, -EEFI ( Status ) ); return EFI_SUCCESS; } @@ -195,6 +204,7 @@ static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = { int efi_download_install ( EFI_HANDLE *handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; + int rc; efirc = bs->InstallMultipleProtocolInterfaces ( handle, @@ -202,9 +212,10 @@ int efi_download_install ( EFI_HANDLE *handle ) { &ipxe_download_protocol_interface, NULL ); if ( efirc ) { + rc = -EEFI ( efirc ); DBG ( "Could not install download protocol: %s\n", - efi_strerror ( efirc ) ); - return EFIRC_TO_RC ( efirc ); + strerror ( rc ) ); + return rc; } return 0; diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c index deb3cf2c..13ed1f50 100644 --- a/src/interface/efi/efi_driver.c +++ b/src/interface/efi/efi_driver.c @@ -21,6 +21,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include +#include #include #include #include @@ -122,11 +124,12 @@ efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, * @v efidrv EFI driver * @ret efirc EFI status code */ -EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) { +int efi_driver_install ( struct efi_driver *efidrv ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_DRIVER_BINDING_PROTOCOL *driver = &efidrv->driver; EFI_COMPONENT_NAME2_PROTOCOL *wtf = &efidrv->wtf; EFI_STATUS efirc; + int rc; /* Configure driver binding protocol */ driver->ImageHandle = efi_image_handle; @@ -148,9 +151,10 @@ EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) { &efi_driver_binding_protocol_guid, driver, &efi_component_name2_protocol_guid, wtf, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIDRV %s could not install protocol: %s\n", - efidrv->name, efi_strerror ( efirc ) ); - return efirc; + efidrv->name, strerror ( rc ) ); + return rc; } DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name ); diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c index 6f9d44f8..4c482d2e 100644 --- a/src/interface/efi/efi_file.c +++ b/src/interface/efi/efi_file.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -549,6 +550,7 @@ static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = { int efi_file_install ( EFI_HANDLE *handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; + int rc; /* Install the simple file system protocol and the block I/O * protocol. We don't have a block device, but large parts of @@ -563,9 +565,10 @@ int efi_file_install ( EFI_HANDLE *handle ) { &efi_block_io_protocol, &efi_simple_file_system_protocol_guid, &efi_simple_file_system_protocol, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( handle, "Could not install simple file system protocol: " - "%s\n", efi_strerror ( efirc ) ); - return EFIRC_TO_RC ( efirc ); + "%s\n", strerror ( rc ) ); + return rc; } return 0; diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index e40de4dd..2f6ca89c 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -94,6 +95,7 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, void *loaded_image; void *loaded_image_path; EFI_STATUS efirc; + int rc; /* Store image handle and system table pointer for future use */ efi_image_handle = image_handle; @@ -149,8 +151,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, &efi_loaded_image_protocol_guid, &loaded_image, image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( systab, "EFI could not get loaded image protocol: %s", - efi_strerror ( efirc ) ); + strerror ( rc ) ); return efirc; } efi_loaded_image = loaded_image; @@ -162,8 +165,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, &efi_loaded_image_device_path_protocol_guid, &loaded_image_path, image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( systab, "EFI could not get loaded image device path " - "protocol: %s", efi_strerror ( efirc ) ); + "protocol: %s", strerror ( rc ) ); return efirc; } efi_loaded_image_path = loaded_image_path; @@ -179,8 +183,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, efi_shutdown_hook, NULL, &efi_shutdown_event ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( systab, "EFI could not create ExitBootServices event: " - "%s\n", efi_strerror ( efirc ) ); + "%s\n", strerror ( rc ) ); return efirc; } diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index 0288cf32..d6095d3e 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -57,13 +57,15 @@ static unsigned long efipci_address ( struct pci_device *pci, int efipci_read ( struct pci_device *pci, unsigned long location, void *value ) { EFI_STATUS efirc; + int rc; if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ), efipci_address ( pci, location ), 1, value ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFIPCI config read from " PCI_FMT " offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), - EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) ); + EFIPCI_OFFSET ( location ), strerror ( rc ) ); return -EIO; } @@ -73,13 +75,15 @@ int efipci_read ( struct pci_device *pci, unsigned long location, int efipci_write ( struct pci_device *pci, unsigned long location, unsigned long value ) { EFI_STATUS efirc; + int rc; if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ), efipci_address ( pci, location ), 1, &value ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), - EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) ); + EFIPCI_OFFSET ( location ), strerror ( rc ) ); return -EIO; } @@ -149,6 +153,7 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){ + rc = -EEFI ( efirc ); DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n", device ); goto err_open_protocol; @@ -160,8 +165,9 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, &pci_segment, &pci_bus, &pci_dev, &pci_fn ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efipci, "EFIPCI device %p could not get PCI " - "location: %s\n", device, efi_strerror ( efirc ) ); + "location: %s\n", device, strerror ( rc ) ); goto err_get_location; } DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n", @@ -185,6 +191,7 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){ + rc = -EEFI ( efirc ); DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n", PCI_ARGS ( &efipci->pci ) ); goto err_no_device_path; @@ -213,9 +220,9 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, * Enable EFI PCI device * * @v efipci EFI PCI device - * @ret efirc EFI status code + * @ret rc Return status code */ -EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) { +int efipci_enable ( struct efi_pci_device *efipci ) { EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io; /* Try to enable I/O cycles, memory cycles, and bus mastering. @@ -273,8 +280,7 @@ struct efi_pci_device * efipci_find ( struct device *dev ) { * @v device EFI child device * @ret efirc EFI status code */ -EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, - EFI_HANDLE device ) { +int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_driver *efidrv = efipci->efidrv; union { @@ -282,6 +288,7 @@ EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, void *interface; } pci_io; EFI_STATUS efirc; + int rc; /* Re-open the PCI_IO_PROTOCOL */ if ( ( efirc = bs->OpenProtocol ( efipci->device, @@ -291,9 +298,10 @@ EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, device, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n", - PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); - return efirc; + PCI_ARGS ( &efipci->pci ), strerror ( rc ) ); + return rc; } return 0; @@ -355,7 +363,6 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; - EFI_STATUS efirc; int rc; DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child ); @@ -364,7 +371,7 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { /* Non-PCI devices are simply unsupported */ - efirc = EFI_UNSUPPORTED; + rc = -ENOTSUP; goto err_not_pci; } @@ -372,7 +379,6 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) { DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); - efirc = EFI_UNSUPPORTED; goto err_no_driver; } @@ -387,7 +393,7 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, err_no_driver: efipci_destroy ( efidrv, efipci ); err_not_pci: - return efirc; + return EFIRC ( rc ); } /** @@ -404,7 +410,6 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; - EFI_STATUS efirc; int rc; DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child ); @@ -412,7 +417,7 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { - efirc = EFI_OUT_OF_RESOURCES; + rc = -ENOMEM; goto err_create; } @@ -420,12 +425,11 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_find_driver; } /* Enable PCI device */ - if ( ( efirc = efipci_enable ( efipci ) ) != 0 ) + if ( ( rc = efipci_enable ( efipci ) ) != 0 ) goto err_enable; /* Probe driver */ @@ -433,7 +437,6 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver " "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ), efipci->pci.id->name, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_probe; } @@ -445,7 +448,7 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, err_find_driver: efipci_destroy ( efidrv, efipci ); err_create: - return efirc; + return EFIRC ( rc ); } /** @@ -494,12 +497,12 @@ static struct efi_driver efipci_driver = */ static void efipci_driver_startup ( void ) { struct efi_driver *efidrv = &efipci_driver; - EFI_STATUS efirc; + int rc; /* Install driver */ - if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { + if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) { DBGC ( efidrv, "EFIPCI could not install driver: %s\n", - efi_strerror ( efirc ) ); + strerror ( rc ) ); return; } diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 95e39b7d..adeb38de 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -177,7 +177,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } snpdev->mode.State = EfiSimpleNetworkInitialized; @@ -206,7 +206,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } snpdev->mode.State = EfiSimpleNetworkInitialized; @@ -366,7 +366,7 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6, ip, mac ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n", snpdev, ip_str, strerror ( rc ) ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } return 0; @@ -490,7 +490,6 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, struct io_buffer *iobuf; size_t payload_len; int rc; - EFI_STATUS efirc; DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data, ( ( unsigned long ) len ) ); @@ -515,25 +514,25 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, DBGC ( snpdev, "SNPDEV %p TX invalid header length " "%ld\n", snpdev, ( ( unsigned long ) ll_header_len ) ); - efirc = EFI_INVALID_PARAMETER; + rc = -EINVAL; goto err_sanity; } if ( len < ll_header_len ) { DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n", snpdev, ( ( unsigned long ) len ) ); - efirc = EFI_BUFFER_TOO_SMALL; + rc = -EINVAL; goto err_sanity; } if ( ! ll_dest ) { DBGC ( snpdev, "SNPDEV %p TX missing destination " "address\n", snpdev ); - efirc = EFI_INVALID_PARAMETER; + rc = -EINVAL; goto err_sanity; } if ( ! net_proto ) { DBGC ( snpdev, "SNPDEV %p TX missing network " "protocol\n", snpdev ); - efirc = EFI_INVALID_PARAMETER; + rc = -EINVAL; goto err_sanity; } if ( ! ll_src ) @@ -547,7 +546,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( ! iobuf ) { DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte " "buffer\n", snpdev, ( ( unsigned long ) len ) ); - efirc = EFI_DEVICE_ERROR; + rc = -ENOMEM; goto err_alloc_iob; } iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN - @@ -562,7 +561,6 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, htons ( *net_proto ) )) != 0 ){ DBGC ( snpdev, "SNPDEV %p TX could not construct " "header: %s\n", snpdev, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_ll_push; } } @@ -571,7 +569,6 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){ DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n", snpdev, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_tx; } @@ -586,7 +583,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, free_iob ( iobuf ); err_alloc_iob: err_sanity: - return efirc; + return EFIRC ( rc ); } /** @@ -615,7 +612,6 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, uint16_t iob_net_proto; unsigned int iob_flags; int rc; - EFI_STATUS efirc; DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data, ( ( unsigned long ) *len ) ); @@ -627,7 +623,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, iobuf = netdev_rx_dequeue ( snpdev->netdev ); if ( ! iobuf ) { DBGC2 ( snpdev, "\n" ); - efirc = EFI_NOT_READY; + rc = -EAGAIN; goto out_no_packet; } DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) ); @@ -642,7 +638,6 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, &iob_flags ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n", snpdev, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto out_bad_ll_header; } @@ -656,12 +651,12 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( net_proto ) *net_proto = ntohs ( iob_net_proto ); - efirc = 0; + rc = 0; out_bad_ll_header: free_iob ( iobuf ); out_no_packet: - return efirc; + return EFIRC ( rc ); } /** @@ -879,9 +874,9 @@ static int efi_snp_probe ( struct net_device *netdev ) { if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, efi_snp_wait_for_packet, snpdev, &snpdev->snp.WaitForPacket ) ) != 0 ){ + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not create event: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + snpdev, strerror ( rc ) ); goto err_create_event; } @@ -944,18 +939,17 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_component_name2_protocol_guid, &snpdev->name2, &efi_load_file_protocol_guid, &snpdev->load_file, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not install protocols: " - "%s\n", snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + "%s\n", snpdev, strerror ( rc ) ); goto err_install_protocol_interface; } /* Add as child of PCI device */ - if ( ( efirc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) { + if ( ( rc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not become child of " PCI_FMT ": %s\n", snpdev, PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + strerror ( rc ) ); goto err_efipci_child_add; } diff --git a/src/interface/efi/efi_snp_hii.c b/src/interface/efi/efi_snp_hii.c index 3a1193a3..9ea15a62 100644 --- a/src/interface/efi/efi_snp_hii.c +++ b/src/interface/efi/efi_snp_hii.c @@ -544,7 +544,7 @@ efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, results, &have_setting, efi_snp_hii_fetch ) ) != 0 ) { - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } } @@ -558,7 +558,7 @@ efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name, NULL, results, NULL ) ) != 0 ) { - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } } } @@ -592,7 +592,7 @@ efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, NULL, NULL, efi_snp_hii_store ) ) != 0 ) { - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } } @@ -657,9 +657,9 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list, snpdev->handle, &snpdev->hii_handle ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + snpdev, strerror ( rc ) ); goto err_new_package_list; } @@ -668,9 +668,9 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { &snpdev->handle, &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + snpdev, strerror ( rc ) ); goto err_install_protocol; } diff --git a/src/interface/efi/efi_strerror.c b/src/interface/efi/efi_strerror.c deleted file mode 100644 index 46bfbbb5..00000000 --- a/src/interface/efi/efi_strerror.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include - -/** @file - * - * iPXE error message formatting for EFI - * - */ - -/** - * Format EFI status code - * - * @v efirc EFI status code - * @v efi_strerror EFI status code string - */ -const char * efi_strerror ( EFI_STATUS efirc ) { - static char errbuf[32]; - - if ( ! efirc ) - return "No error"; - - snprintf ( errbuf, sizeof ( errbuf ), "Error %lld", - ( unsigned long long ) ( efirc ^ MAX_BIT ) ); - return errbuf; -} diff --git a/src/interface/efi/efi_timer.c b/src/interface/efi/efi_timer.c index b110cae2..7a1ff786 100644 --- a/src/interface/efi/efi_timer.c +++ b/src/interface/efi/efi_timer.c @@ -19,6 +19,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include +#include #include #include #include @@ -54,10 +56,12 @@ EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch ); static void efi_udelay ( unsigned long usecs ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; + int rc; if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFI could not delay for %ldus: %s\n", - usecs, efi_strerror ( efirc ) ); + usecs, strerror ( rc ) ); /* Probably screwed */ } } @@ -70,12 +74,13 @@ static void efi_udelay ( unsigned long usecs ) { static unsigned long efi_currticks ( void ) { UINT64 time; EFI_STATUS efirc; + int rc; /* Read CPU timer 0 (TSC) */ if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time, NULL ) ) != 0 ) { - DBG ( "EFI could not read CPU timer: %s\n", - efi_strerror ( efirc ) ); + rc = -EEFI ( efirc ); + DBG ( "EFI could not read CPU timer: %s\n", strerror ( rc ) ); /* Probably screwed */ return -1UL; } diff --git a/src/interface/efi/efi_umalloc.c b/src/interface/efi/efi_umalloc.c index b4994932..356efaa6 100644 --- a/src/interface/efi/efi_umalloc.c +++ b/src/interface/efi/efi_umalloc.c @@ -19,6 +19,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include +#include #include #include #include @@ -49,6 +51,7 @@ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { userptr_t new_ptr = UNOWHERE; size_t old_size; EFI_STATUS efirc; + int rc; /* Allocate new memory if necessary. If allocation fails, * return without touching the old block. @@ -59,8 +62,9 @@ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { EfiBootServicesData, new_pages, &phys_addr ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFI could not allocate %d pages: %s\n", - new_pages, efi_strerror ( efirc ) ); + new_pages, strerror ( rc ) ); return UNULL; } assert ( phys_addr != 0 ); @@ -84,8 +88,9 @@ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 ); phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE ); if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){ + rc = -EEFI ( efirc ); DBG ( "EFI could not free %d pages at %llx: %s\n", - old_pages, phys_addr, efi_strerror ( efirc ) ); + old_pages, phys_addr, strerror ( rc ) ); /* Not fatal; we have leaked memory but successfully * allocated (if asked to do so). */ From 9cb60c8a213e1431163b4fdbe5baba3e1ace4431 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 19 Apr 2013 13:29:22 +0100 Subject: [PATCH 09/45] [efi] Add sample platform-generated error disambiguations Add disambiguated errors for LoadImage() and StartImage(), primarily to demonstrate how to use __einfo_uniqify() and __einfo_platformify() in the context of EFI platform errors. Signed-off-by: Michael Brown --- src/image/efi_image.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 0e90954b..1c1ee0c3 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -35,6 +35,22 @@ FILE_LICENCE ( GPL2_OR_LATER ); FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 ); +/* Disambiguate the various error causes */ +#define EINFO_EEFI_LOAD \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "Could not load image" ) +#define EINFO_EEFI_LOAD_PROHIBITED \ + __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION, \ + "Image prohibited by security policy" ) +#define EEFI_LOAD_PROHIBITED \ + __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED ) +#define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \ + EEFI_LOAD_PROHIBITED ) +#define EINFO_EEFI_START \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x02, \ + "Could not start image" ) +#define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc ) + /** EFI loaded image protocol GUID */ static EFI_GUID efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; @@ -176,7 +192,7 @@ static int efi_image_exec ( struct image *image ) { user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ - rc = -EEFI ( efirc ); + rc = -EEFI_LOAD ( efirc ); DBGC ( image, "EFIIMAGE %p could not load: %s\n", image, strerror ( rc ) ); goto err_load_image; @@ -205,7 +221,7 @@ static int efi_image_exec ( struct image *image ) { /* Start the image */ if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) { - rc = -EEFI ( efirc ); + rc = -EEFI_START ( efirc ); DBGC ( image, "EFIIMAGE %p returned with status %s\n", image, strerror ( rc ) ); goto err_start_image; @@ -254,7 +270,7 @@ static int efi_image_probe ( struct image *image ) { user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ - rc = -EEFI ( efirc ); + rc = -EEFI_LOAD ( efirc ); DBGC ( image, "EFIIMAGE %p could not load: %s\n", image, strerror ( rc ) ); return rc; From 445ac9fbdc1df64451821aa65b9aace765d1313e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 19 Apr 2013 14:26:12 +0100 Subject: [PATCH 10/45] [netdevice] Use link-layer address as part of RNG seed iPXE currently seeds the random number generator using the system timer tick count. When large numbers of machines are booted simultaneously, multiple machines may end up choosing the same DHCP transaction ID (XID) value; this can cause problems. Fix by using the least significant (and hence most variable) bits of each network device's link-layer address to perturb the random number generator. This introduces some per-machine unique data into the random number generator's seed, and so reduces the chances of DHCP XID collisions. This does not affect the ANS X9.82-compatible random bit generator used by TLS and other cryptography code, which uses an entirely separate source of entropy. Originally-implemented-by: Bernhard Kohl Signed-off-by: Michael Brown --- src/net/netdevice.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/net/netdevice.c b/src/net/netdevice.c index e9cbb9e9..88ca93f9 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -442,7 +442,9 @@ struct net_device * alloc_netdev ( size_t priv_size ) { */ int register_netdev ( struct net_device *netdev ) { static unsigned int ifindex = 0; + struct ll_protocol *ll_protocol = netdev->ll_protocol; struct net_driver *driver; + uint32_t seed; int rc; /* Create device name */ @@ -453,10 +455,17 @@ int register_netdev ( struct net_device *netdev ) { /* Set initial link-layer address, if not already set */ if ( ! netdev_has_ll_addr ( netdev ) ) { - netdev->ll_protocol->init_addr ( netdev->hw_addr, - netdev->ll_addr ); + ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr ); } + /* Use least significant bits of the link-layer address to + * improve the randomness of the (non-cryptographic) random + * number generator. + */ + memcpy ( &seed, ( netdev->ll_addr + ll_protocol->ll_addr_len + - sizeof ( seed ) ), sizeof ( seed ) ); + srand ( rand() ^ seed ); + /* Add to device list */ netdev_get ( netdev ); list_add_tail ( &netdev->list, &net_devices ); From 5b9ce33c5cb046cc740467e56c5e05944b4d7e54 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 25 Apr 2013 13:45:41 +0100 Subject: [PATCH 11/45] [build] Allow sparse to find compiler.h sparse seems to have problems finding compiler.h when specified as "-include compiler.h"; one possible explanation is that it ignores the include path. Fix by using "-include include/compiler.h". Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index d40f226f..99de917a 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -475,7 +475,7 @@ LDFLAGS += --gc-sections # compiler.h is needed for our linking and debugging system # -CFLAGS += -include compiler.h +CFLAGS += -include include/compiler.h # CFLAGS for specific object types # From f85af68ac50d1cda4d68b11bf102e93245be57b3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 25 Apr 2013 14:51:33 +0100 Subject: [PATCH 12/45] [build] Define __WINT_TYPE__ if necessary sparse does not define __WCHAR_TYPE__ or __WINT_TYPE__. We already define __WCHAR_TYPE__ if the compiler does not do so; do the same for __WINT_TYPE__. Signed-off-by: Michael Brown --- src/include/stddef.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/include/stddef.h b/src/include/stddef.h index 83a0f0ed..20419bdf 100644 --- a/src/include/stddef.h +++ b/src/include/stddef.h @@ -25,6 +25,9 @@ FILE_LICENCE ( GPL2_ONLY ); #ifndef __WCHAR_TYPE__ #define __WCHAR_TYPE__ long int #endif +#ifndef __WINT_TYPE__ +#define __WINT_TYPE__ long int +#endif typedef __WCHAR_TYPE__ wchar_t; typedef __WINT_TYPE__ wint_t; From 39ab88ac09e1fd2eb8f971df5d9f7c55b2c1eeb3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 25 Apr 2013 14:56:48 +0100 Subject: [PATCH 13/45] [build] Allow sparse to be invoked via "make C=1" Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 99de917a..6e9178a1 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -200,6 +200,15 @@ Q := @ QM := @ endif +############################################################################### +# +# Checker +# +ifeq ($(C),1) +export REAL_CC := $(CC) +CC := cgcc +endif + ############################################################################### # # Set BIN according to whatever was specified on the command line as From eaa0f47dc2d59a09c764773e44b6415fc1f507af Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 25 Apr 2013 15:14:59 +0100 Subject: [PATCH 14/45] [build] Avoid sparse undeclared symbol warning for PROVIDE_SYMBOL() Signed-off-by: Michael Brown --- src/include/compiler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/compiler.h b/src/include/compiler.h index ed9af237..e5559245 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -64,6 +64,7 @@ .comm _sym, 0 #else /* ASSEMBLY */ #define PROVIDE_SYMBOL( _sym ) \ + extern char _sym[]; \ char _sym[0] #endif /* ASSEMBLY */ From d91ccde9e53b5401b3436caec885e0be36722365 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 25 Apr 2013 15:15:43 +0100 Subject: [PATCH 15/45] [process] Mark process descriptor as static in PERMANENT_PROCESS There is no need for the process descriptor to be a global variable. Signed-off-by: Michael Brown --- src/include/ipxe/process.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/ipxe/process.h b/src/include/ipxe/process.h index 9b757981..2c76ff26 100644 --- a/src/include/ipxe/process.h +++ b/src/include/ipxe/process.h @@ -174,7 +174,7 @@ process_running ( struct process *process ) { * */ #define PERMANENT_PROCESS( name, step ) \ -struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \ +static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \ struct process name __permanent_process = { \ .list = LIST_HEAD_INIT ( name.list ), \ .desc = & name ## _desc, \ From 2e54c4b52e347a49df0c08357ece3e326a0b5e09 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 27 Apr 2013 21:24:10 +0100 Subject: [PATCH 16/45] [realtek] Print bad MAC address in debug message when inferring no EEPROM Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 76fa47bb..011822ec 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -1060,7 +1060,8 @@ static int realtek_probe ( struct pci_device *pci ) { * hopefully have been programmed by the platform firmware. */ if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) { - DBGC ( rtl, "REALTEK %p seems to have no EEPROM\n", rtl ); + DBGC ( rtl, "REALTEK %p seems to have no EEPROM (MAC %s)\n", + rtl, eth_ntoa ( netdev->hw_addr ) ); for ( i = 0 ; i < ETH_ALEN ; i++ ) netdev->hw_addr[i] = readb ( rtl->regs + RTL_IDR0 + i ); } From e5cbfefdf3dc337afc71ccd2fbe4126ee5976bfc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 28 Apr 2013 16:43:32 +0100 Subject: [PATCH 17/45] [build] Use -Wno-decl when running sparse Linker table entries must be non-static in order to avoid being completely optimised away by some versions of gcc. Use -Wno-decl to prevent sparse from warning about these, since the alternative would be to litter the code with otherwise unnecessary "extern" declarations. Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 6e9178a1..4dfaf7ab 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -207,6 +207,7 @@ endif ifeq ($(C),1) export REAL_CC := $(CC) CC := cgcc +CFLAGS += -Wno-decl endif ############################################################################### From b9663b80497d8954a2195789c91ba2f27c8e2d6b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 28 Apr 2013 16:51:05 +0100 Subject: [PATCH 18/45] [build] Fix uses of literal 0 as a NULL pointer Detected using sparse. Signed-off-by: Michael Brown --- src/drivers/net/3c515.c | 2 +- src/drivers/net/3c595.c | 4 ++-- src/drivers/net/bnx2.c | 3 --- src/drivers/net/etherfabric.c | 3 ++- src/drivers/net/ns8390.c | 2 +- src/drivers/net/prism2.c | 4 +--- src/drivers/net/sis900.c | 2 +- src/drivers/net/tlan.c | 4 ++-- src/drivers/net/tulip.c | 8 ++++---- src/drivers/net/via-velocity.c | 2 +- src/hci/linux_args.c | 6 +++--- src/hci/mucurses/kb.c | 2 +- src/net/udp/dns.c | 2 +- 13 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c index 0aa68b1a..1591e061 100644 --- a/src/drivers/net/3c515.c +++ b/src/drivers/net/3c515.c @@ -389,7 +389,7 @@ static void t515_reset(struct nic *nic) outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold); /* Room for a packet. */ /* Clear the Tx ring. */ for (i = 0; i < TX_RING_SIZE; i++) - vp->tx_skbuff[i] = 0; + vp->tx_skbuff[i] = NULL; outl(0, nic->ioaddr + DownListPtr); } /* Set receiver mode: presumably accept b-case and phys addr only. */ diff --git a/src/drivers/net/3c595.c b/src/drivers/net/3c595.c index 1aa8ed64..2338c54b 100644 --- a/src/drivers/net/3c595.c +++ b/src/drivers/net/3c595.c @@ -399,7 +399,7 @@ vxsetlink(void) i = vx_connector; /* default in EEPROM */ reason = "default"; - warning = 0; + warning = NULL; if ((vx_connectors & conn_tab[vx_connector].bit) == 0) { warning = "strange connector type in EEPROM."; @@ -407,7 +407,7 @@ vxsetlink(void) i = CONNECTOR_UTP; } - if (warning != 0) { + if (warning) { printf("warning: %s\n", warning); } printf("selected %s. (%s)\n", conn_tab[i].name, reason); diff --git a/src/drivers/net/bnx2.c b/src/drivers/net/bnx2.c index a986bdef..4ebcc52a 100644 --- a/src/drivers/net/bnx2.c +++ b/src/drivers/net/bnx2.c @@ -2617,9 +2617,6 @@ bnx2_probe(struct nic *nic, struct pci_device *pdev) struct bnx2 *bp = &bnx2; int i, rc; - if (pdev == 0) - return 0; - memset(bp, 0, sizeof(*bp)); rc = bnx2_init_board(pdev, nic); diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c index 6036d321..5e0efb1e 100644 --- a/src/drivers/net/etherfabric.c +++ b/src/drivers/net/etherfabric.c @@ -3798,7 +3798,8 @@ falcon_clear_interrupts ( struct efab_nic *efab ) } else { /* write to the INT_ACK register */ - falcon_writel ( efab, 0, FCN_INT_ACK_KER_REG_A1 ); + EFAB_ZERO_DWORD ( reg ); + falcon_writel ( efab, ®, FCN_INT_ACK_KER_REG_A1 ); mb(); falcon_readl ( efab, ®, WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 ); diff --git a/src/drivers/net/ns8390.c b/src/drivers/net/ns8390.c index a30f9361..0ffc6216 100644 --- a/src/drivers/net/ns8390.c +++ b/src/drivers/net/ns8390.c @@ -895,7 +895,7 @@ static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused) #endif 0 }; /* if no addresses supplied, fall back on defaults */ - if (probe_addrs == 0 || probe_addrs[0] == 0) + if (probe_addrs == NULL || probe_addrs[0] == 0) probe_addrs = base; eth_bmem = 0; /* No shared memory */ for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) { diff --git a/src/drivers/net/prism2.c b/src/drivers/net/prism2.c index ad388074..ab974264 100644 --- a/src/drivers/net/prism2.c +++ b/src/drivers/net/prism2.c @@ -130,9 +130,7 @@ typedef struct hfa384x } hfa384x_t; /* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */ -static hfa384x_t hw_global = { - 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0} -}; +static hfa384x_t hw_global; /* * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP) diff --git a/src/drivers/net/sis900.c b/src/drivers/net/sis900.c index 75e9ef96..72451567 100644 --- a/src/drivers/net/sis900.c +++ b/src/drivers/net/sis900.c @@ -111,7 +111,7 @@ static struct mii_chip_info { // {"NS 83851 PHY",0x2000, 0x5C20, MIX }, {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode}, {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode}, - {0,0,0,0} + {NULL,0,0,NULL} }; static struct mii_phy { diff --git a/src/drivers/net/tlan.c b/src/drivers/net/tlan.c index 74398df4..7742f6d8 100644 --- a/src/drivers/net/tlan.c +++ b/src/drivers/net/tlan.c @@ -94,7 +94,7 @@ static void TLan_MiiWriteReg(struct nic *nic __unused, u16, u16, u16); static const char *media[] = { "10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ", - "100baseTx-FD", "100baseT4", 0 + "100baseTx-FD", "100baseT4", NULL }; /* This much match tlan_pci_tbl[]! */ @@ -164,7 +164,7 @@ static const struct pci_id_info tlan_pci_tbl[] = { {"Compaq NetFlex-3/E", 0, /* EISA card */ {0, 0, 0, 0, 0, 0}, TLAN_ADAPTER_ACTIVITY_LED, 0x83}, - {0, 0, + {NULL, 0, {0, 0, 0, 0, 0, 0}, 0, 0}, }; diff --git a/src/drivers/net/tulip.c b/src/drivers/net/tulip.c index 7a23b7e9..e4e6ffa8 100644 --- a/src/drivers/net/tulip.c +++ b/src/drivers/net/tulip.c @@ -228,7 +228,7 @@ static const struct pci_id_info pci_id_tbl[] = { TULIP_IOTYPE, TULIP_SIZE, COMET }, { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 }, TULIP_IOTYPE, 256, COMET }, /*Ramesh Chander*/ - { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 }, + { NULL, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 }, }; enum tbl_flag { @@ -264,7 +264,7 @@ static struct tulip_chip_table { { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_PWRDWN | HAS_NWAY }, { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY }, /*Ramesh Chander*/ - { 0, 0 }, + { NULL, 0 }, }; /* A full-duplex map for media types. */ @@ -475,7 +475,7 @@ static struct fixups { 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */ 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */ }}, - {0, 0, 0, 0, {}}}; + {NULL, 0, 0, 0, {}}}; static const char * block_name[] = {"21140 non-MII", "21140 MII PHY", "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"}; @@ -720,7 +720,7 @@ static void parse_eeprom(struct nic *nic) whereami("parse_eeprom\n"); - tp->mtable = 0; + tp->mtable = NULL; /* Detect an old-style (SA only) EEPROM layout: memcmp(ee_data, ee_data+16, 8). */ for (i = 0; i < 8; i ++) diff --git a/src/drivers/net/via-velocity.c b/src/drivers/net/via-velocity.c index 9ba0b093..e98e81a2 100644 --- a/src/drivers/net/via-velocity.c +++ b/src/drivers/net/via-velocity.c @@ -1230,7 +1230,7 @@ static int velocity_open(struct nic *nic, struct pci_device *pci __unused) u32 TxPhyAddr, RxPhyAddr; u32 TxBufPhyAddr, RxBufPhyAddr; vptr->TxDescArrays = tx_ring; - if (vptr->TxDescArrays == 0) + if (vptr->TxDescArrays == NULL) printf("Allot Error"); /* Tx Descriptor needs 64 bytes alignment; */ diff --git a/src/hci/linux_args.c b/src/hci/linux_args.c index 0bce4af9..58eeb063 100644 --- a/src/hci/linux_args.c +++ b/src/hci/linux_args.c @@ -45,9 +45,9 @@ __asmcall void save_args(int argc, char **argv) /** Supported command-line options */ static struct option options[] = { - {"net", 1, 0, 'n'}, - {"settings", 1, 0, 's'}, - {0, 0, 0, 0} + {"net", 1, NULL, 'n'}, + {"settings", 1, NULL, 's'}, + {NULL, 0, NULL, 0} }; /** diff --git a/src/hci/mucurses/kb.c b/src/hci/mucurses/kb.c index cada7291..b38c8c14 100644 --- a/src/hci/mucurses/kb.c +++ b/src/hci/mucurses/kb.c @@ -88,7 +88,7 @@ int wgetnstr ( WINDOW *win, char *str, int n ) { int c; if ( n == 0 ) { - str = '\0'; + *str = '\0'; return OK; } diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index 613541f5..45f0f07c 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -205,7 +205,7 @@ static char * dns_qualify_name ( const char *string ) { char *fqdn; /* Leave unchanged if already fully-qualified or no local domain */ - if ( ( ! localdomain ) || ( strchr ( string, '.' ) != 0 ) ) + if ( ( ! localdomain ) || ( strchr ( string, '.' ) != NULL ) ) return strdup ( string ); /* Append local domain to name */ From 4678864ce65d5f3f3ae6399e152448d848bd8027 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 28 Apr 2013 17:30:01 +0100 Subject: [PATCH 19/45] [build] Fix dubious uses of bitwise operators Detected by sparse. Signed-off-by: Michael Brown --- src/drivers/net/rtl818x/rtl8185_rtl8225.c | 2 +- src/net/fcoe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/net/rtl818x/rtl8185_rtl8225.c b/src/drivers/net/rtl818x/rtl8185_rtl8225.c index 50cc84ad..ae92531c 100644 --- a/src/drivers/net/rtl818x/rtl8185_rtl8225.c +++ b/src/drivers/net/rtl818x/rtl8185_rtl8225.c @@ -71,7 +71,7 @@ static void rtl8225_write(struct net80211_device *dev, u8 addr, u16 data) udelay(10); for (i = 15; i >= 0; i--) { - u16 reg = reg80 | !!(bangdata & (1 << i)); + u16 reg = ( reg80 | ( ( bangdata >> i ) & 1 ) ); if (i & 1) rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); diff --git a/src/net/fcoe.c b/src/net/fcoe.c index d1130425..e9e404ec 100644 --- a/src/net/fcoe.c +++ b/src/net/fcoe.c @@ -1011,7 +1011,7 @@ static void fcoe_expired ( struct retry_timer *timer, int over __unused ) { /* Increment the timeout counter */ fcoe->timeouts++; - if ( vlan_can_be_trunk ( fcoe->netdev ) & + if ( vlan_can_be_trunk ( fcoe->netdev ) && ! ( fcoe->flags & FCOE_VLAN_TIMED_OUT ) ) { /* If we have already found a VLAN, send infrequent From 1aca99f3cf46fc8551895b30d974ade52a2ba489 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 28 Apr 2013 17:43:37 +0100 Subject: [PATCH 20/45] [build] Default to short wchar_t in stddef.h sparse does not understand -fshort-wchar. Default to using uint16_t as a wchar_t if not explicitly specified by the compiler, to avoid large numbers of spurious warnings from sparse. Signed-off-by: Michael Brown --- src/include/stddef.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/stddef.h b/src/include/stddef.h index 20419bdf..bf792771 100644 --- a/src/include/stddef.h +++ b/src/include/stddef.h @@ -23,10 +23,10 @@ FILE_LICENCE ( GPL2_ONLY ); /* __WCHAR_TYPE__ is defined by gcc and will change if -fshort-wchar is used */ #ifndef __WCHAR_TYPE__ -#define __WCHAR_TYPE__ long int +#define __WCHAR_TYPE__ uint16_t #endif #ifndef __WINT_TYPE__ -#define __WINT_TYPE__ long int +#define __WINT_TYPE__ int #endif typedef __WCHAR_TYPE__ wchar_t; typedef __WINT_TYPE__ wint_t; From d90fc3156c57ba90156ceb4e33fda4a6a19ca382 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 28 Apr 2013 18:50:10 +0100 Subject: [PATCH 21/45] [realtek] Use ID word to detect EEPROM presence Some onboard RTL8169 NICs seem to leave the EEPROM pins disconnected. The existing is_valid_ether_addr() test will not necessarily catch this, since it expects a missing EEPROM to show up as a MAC address of 00:00:00:00:00:00 or ff:ff:ff:ff:ff:ff. When the EEPROM pins are floating the MAC address may read as e.g. 00:00:00:00:0f:00, which will not be detected as invalid. Check the ID word in the first two bytes of the EEPROM (which should have the value 0x8129 for all RTL8139 and RTL8169 chips), and use this to determine whether or not an EEPROM is present. Reported-by: Carl Karsten Tested-by: Carl Karsten Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 52 +++++++++++++++++++++++++++------------ src/drivers/net/realtek.h | 6 +++++ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 011822ec..d7c4d29d 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -144,9 +144,12 @@ static struct bit_basher_operations realtek_basher_ops = { * Initialise EEPROM * * @v netdev Network device + * @ret rc Return status code */ -static void realtek_init_eeprom ( struct net_device *netdev ) { +static int realtek_init_eeprom ( struct net_device *netdev ) { struct realtek_nic *rtl = netdev->priv; + uint16_t id; + int rc; /* Initialise SPI bit-bashing interface */ rtl->spibit.basher.op = &realtek_basher_ops; @@ -163,6 +166,22 @@ static void realtek_init_eeprom ( struct net_device *netdev ) { } rtl->eeprom.bus = &rtl->spibit.bus; + /* Check for EEPROM presence. Some onboard NICs will have no + * EEPROM connected, with the BIOS being responsible for + * programming the initial register values. + */ + if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_ID, + &id, sizeof ( id ) ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not read EEPROM ID: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + if ( id != cpu_to_le16 ( RTL_EEPROM_ID_MAGIC ) ) { + DBGC ( rtl, "REALTEK %p EEPROM ID incorrect (%#04x); assuming " + "no EEPROM\n", rtl, le16_to_cpu ( id ) ); + return -ENODEV; + } + /* Initialise space for non-volatile options, if available * * We use offset 0x40 (i.e. address 0x20), length 0x40. This @@ -176,6 +195,8 @@ static void realtek_init_eeprom ( struct net_device *netdev ) { nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, RTL_EEPROM_VPD, RTL_EEPROM_VPD_LEN, NULL, &netdev->refcnt ); } + + return 0; } /****************************************************************************** @@ -1045,23 +1066,22 @@ static int realtek_probe ( struct pci_device *pci ) { realtek_detect ( rtl ); /* Initialise EEPROM */ - realtek_init_eeprom ( netdev ); + if ( ( rc = realtek_init_eeprom ( netdev ) ) == 0 ) { - /* Read MAC address from EEPROM */ - if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_MAC, - netdev->hw_addr, ETH_ALEN ) ) != 0 ) { - DBGC ( rtl, "REALTEK %p could not read MAC address: %s\n", - rtl, strerror ( rc ) ); - goto err_nvs_read; - } + /* Read MAC address from EEPROM */ + if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_MAC, + netdev->hw_addr, ETH_ALEN ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not read MAC address: " + "%s\n", rtl, strerror ( rc ) ); + goto err_nvs_read; + } - /* The EEPROM may not be present for onboard NICs. Fall back - * to reading the current ID register value, which will - * hopefully have been programmed by the platform firmware. - */ - if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) { - DBGC ( rtl, "REALTEK %p seems to have no EEPROM (MAC %s)\n", - rtl, eth_ntoa ( netdev->hw_addr ) ); + } else { + + /* EEPROM not present. Fall back to reading the + * current ID register value, which will hopefully + * have been programmed by the platform firmware. + */ for ( i = 0 ; i < ETH_ALEN ; i++ ) netdev->hw_addr[i] = readb ( rtl->regs + RTL_IDR0 + i ); } diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h index 6a7b10a9..1cd85d95 100644 --- a/src/drivers/net/realtek.h +++ b/src/drivers/net/realtek.h @@ -166,6 +166,12 @@ enum realtek_legacy_status { #define RTL_9346CR_EEDI 0x02 /**< Data in */ #define RTL_9346CR_EEDO 0x01 /**< Data out */ +/** Word offset of ID code word within EEPROM */ +#define RTL_EEPROM_ID ( 0x00 / 2 ) + +/** EEPROM code word magic value */ +#define RTL_EEPROM_ID_MAGIC 0x8129 + /** Word offset of MAC address within EEPROM */ #define RTL_EEPROM_MAC ( 0x0e / 2 ) From de1fafd2f80dc9b08304cf5b66d281ef6771b1f9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 29 Apr 2013 15:36:32 +0100 Subject: [PATCH 22/45] [errdb] Strip platform error code for non-platform-generated errors Signed-off-by: Michael Brown --- contrib/errdb/errdb.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/errdb/errdb.pl b/contrib/errdb/errdb.pl index fc1919f6..6423d834 100755 --- a/contrib/errdb/errdb.pl +++ b/contrib/errdb/errdb.pl @@ -73,6 +73,7 @@ my $xrefs = {}; while ( <> ) { chomp; ( my $errno, my $filename, my $line, my $description ) = split ( /\t/ ); + $errno = substr ( $errno, 0, 6 ) unless $errno =~ /^7f/; $errors->{$errno} = $description; $xrefs->{$errno} ||= {}; $xrefs->{$errno}->{$filename} ||= {}; From e411b37eb1f1fdeca6e80db3ab2f74fd6373887d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 29 Apr 2013 19:58:25 +0100 Subject: [PATCH 23/45] [pxe] Convert external PXE API errors into iPXE platform-generated errors Signed-off-by: Michael Brown --- src/arch/i386/drivers/net/undiload.c | 10 +++++++--- src/arch/i386/interface/pxe/pxe_call.c | 14 +++++++++++--- src/arch/i386/interface/pxeparent/pxeparent.c | 18 ++++++++---------- src/arch/x86/include/bits/errfile.h | 1 + 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/arch/i386/drivers/net/undiload.c b/src/arch/i386/drivers/net/undiload.c index 0edfa35d..f0f15e6a 100644 --- a/src/arch/i386/drivers/net/undiload.c +++ b/src/arch/i386/drivers/net/undiload.c @@ -38,6 +38,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Disambiguate the various error causes */ +#define EINFO_EUNDILOAD \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "UNDI loader error" ) +#define EUNDILOAD( status ) EPLATFORM ( EINFO_EUNDILOAD, status ) + /** Parameter block for calling UNDI loader */ static struct s_UNDI_LOADER __bss16 ( undi_loader ); #define undi_loader __use_data16 ( undi_loader ) @@ -109,9 +115,7 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) { /* Clear entry point */ memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) ); - rc = -undi_loader.Status; - if ( rc == 0 ) /* Paranoia */ - rc = -EIO; + rc = -EUNDILOAD ( undi_loader.Status ); DBGC ( undi, "UNDI %p loader failed: %s\n", undi, strerror ( rc ) ); return rc; diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c index b8e73a06..7fce75a9 100644 --- a/src/arch/i386/interface/pxe/pxe_call.c +++ b/src/arch/i386/interface/pxe/pxe_call.c @@ -32,6 +32,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * PXE API entry point */ +/* Disambiguate the various error causes */ +#define EINFO_EPXENBP \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "External PXE NBP error" ) +#define EPXENBP( status ) EPLATFORM ( EINFO_EPXENBP, status ) + /** Vector for chaining INT 1A */ extern struct segoff __text16 ( pxe_int_1a_vector ); #define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector ) @@ -257,7 +263,7 @@ rmjmp_buf pxe_restart_nbp; int pxe_start_nbp ( void ) { int jmp; int discard_b, discard_c, discard_d, discard_D; - uint16_t rc; + uint16_t status; /* Allow restarting NBP via PXENV_RESTART_TFTP */ jmp = rmsetjmp ( pxe_restart_nbp ); @@ -271,7 +277,7 @@ int pxe_start_nbp ( void ) { "sti\n\t" "lcall $0, $0x7c00\n\t" "addw $4, %%sp\n\t" ) - : "=a" ( rc ), "=b" ( discard_b ), + : "=a" ( status ), "=b" ( discard_b ), "=c" ( discard_c ), "=d" ( discard_d ), "=D" ( discard_D ) : "a" ( 0 ), "b" ( __from_text16 ( &pxenv ) ), @@ -279,8 +285,10 @@ int pxe_start_nbp ( void ) { "d" ( virt_to_phys ( &pxenv ) ), "D" ( __from_text16 ( &ppxe ) ) : "esi", "ebp", "memory" ); + if ( status ) + return -EPXENBP ( status ); - return rc; + return 0; } REQUIRE_OBJECT ( pxe_preboot ); diff --git a/src/arch/i386/interface/pxeparent/pxeparent.c b/src/arch/i386/interface/pxeparent/pxeparent.c index 8b2a2c88..b2c6ffba 100644 --- a/src/arch/i386/interface/pxeparent/pxeparent.c +++ b/src/arch/i386/interface/pxeparent/pxeparent.c @@ -31,6 +31,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Disambiguate the various error causes */ +#define EINFO_EPXECALL \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "External PXE API error" ) +#define EPXECALL( status ) EPLATFORM ( EINFO_EPXECALL, status ) + /** * Name PXE API call * @@ -151,16 +157,8 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function, /* Determine return status code based on PXENV_EXIT and * PXENV_STATUS */ - if ( exit == PXENV_EXIT_SUCCESS ) { - rc = 0; - } else { - rc = -pxeparent_params.Status; - /* Paranoia; don't return success for the combination - * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS - */ - if ( rc == 0 ) - rc = -EIO; - } + rc = ( ( exit == PXENV_EXIT_SUCCESS ) ? + 0 : -EPXECALL ( pxeparent_params.Status ) ); /* If anything goes wrong, print as much debug information as * it's possible to give. diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index 7b9f3702..5f676c87 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 ) #define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 ) #define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 ) +#define ERRFILE_pxe_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000d0000 ) #define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) #define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) From 592755eccf51c87ca727c2044eee7ffc3266e290 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 30 Apr 2013 13:36:04 +0100 Subject: [PATCH 24/45] [realtek] Allow reaction time between writing RTL_CAPR and reading RTL_CR Some older RTL8139 chips seem to not immediately update the RTL_CR.BUFE bit in response to a write to RTL_CAPR. This results in iPXE seeing a spurious zero-length received packet, and thereafter being out of sync with the hardware's RX ring offset. Fix by inserting an extra PCI read cycle after writing to RTL_CAPR, to give the chip time to react before we next read RTL_CR. Reported-by: Gelip Tested-by: Gelip Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index d7c4d29d..70c0ac1c 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -861,6 +861,9 @@ static void realtek_legacy_poll_rx ( struct net_device *netdev ) { rtl->rx_offset = ( ( rtl->rx_offset + 3 ) & ~3 ); rtl->rx_offset = ( rtl->rx_offset % RTL_RXBUF_LEN ); writew ( ( rtl->rx_offset - 16 ), rtl->regs + RTL_CAPR ); + + /* Give chip time to react before rechecking RTL_CR */ + readw ( rtl->regs + RTL_CAPR ); } } From c6375a85be0573c12fc89d55009d2905521d78c4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 30 Apr 2013 14:31:39 +0100 Subject: [PATCH 25/45] [romprefix] Report failure cause when unable to open payload Report the cause of the failure when we are unable to open the .mrom payload. There are two possible failure cases: - Unable to find a suitable memory BAR to borrow (e.g. if the NIC doesn't have a memory BAR that is at least as large as the expansion ROM BAR, or if the memory BAR has been assigned a 64-bit address which won't fit into the 32-bit expansion ROM BAR). This will be reported as "BABABABA". - Unable to find correct ROM image within the BAR. This will be reported as the address (within the borrowed BAR) at which we first fail to find a valid 55AA signature. Signed-off-by: Michael Brown --- src/arch/i386/prefix/mromprefix.S | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/arch/i386/prefix/mromprefix.S b/src/arch/i386/prefix/mromprefix.S index 058663c4..0f0847e5 100644 --- a/src/arch/i386/prefix/mromprefix.S +++ b/src/arch/i386/prefix/mromprefix.S @@ -98,6 +98,7 @@ find_mem_bar: cmpw $PCI_BAR_5, %di jle 1f stc + movl $0xbabababa, %esi /* Report "No suitable BAR" */ jmp 99f 1: movw $4, %bp @@ -157,15 +158,17 @@ find_mem_bar: /* Locate our ROM image */ 1: addr32 es cmpw $0xaa55, (%eax) - stc - jne 99f - addr32 es cmpl $_build_id, build_id(%eax) je 2f + stc + movl %eax, %esi /* Report failure address */ + jmp 99f +2: addr32 es cmpl $_build_id, build_id(%eax) + je 3f addr32 es movzbl 2(%eax), %ecx shll $9, %ecx addl %ecx, %eax jmp 1b -2: +3: /* Copy payload to buffer, or set buffer address to BAR address */ testl %esi, %esi From 9b1ec3132fed94c644c77a5e59a8ba2112110455 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 09:15:51 +0100 Subject: [PATCH 26/45] [realtek] Ensure EEPROM writes reach chip before starting udelay() On some systems, it appears to be possible for writes to the EEPROM registers to be delayed for long enough that the EEPROM's setup and hold times are violated, resulting in invalid data being read from the EEPROM. Fix by inserting a PCI read cycle immediately after writes to RTL_9346CR, to ensure that the write has completed before starting the udelay() used to time the SPI bus transitions. Reported-by: Gelip Tested-by: Gelip Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 70c0ac1c..f7b5ec58 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -74,6 +74,7 @@ static void realtek_spi_open_bit ( struct bit_basher *basher ) { /* Enable EEPROM access */ writeb ( RTL_9346CR_EEM_EEPROM, rtl->regs + RTL_9346CR ); + readb ( rtl->regs + RTL_9346CR ); /* Ensure write reaches chip */ } /** @@ -87,6 +88,7 @@ static void realtek_spi_close_bit ( struct bit_basher *basher ) { /* Disable EEPROM access */ writeb ( RTL_9346CR_EEM_NORMAL, rtl->regs + RTL_9346CR ); + readb ( rtl->regs + RTL_9346CR ); /* Ensure write reaches chip */ } /** @@ -129,6 +131,7 @@ static void realtek_spi_write_bit ( struct bit_basher *basher, reg &= ~mask; reg |= ( data & mask ); writeb ( reg, rtl->regs + RTL_9346CR ); + readb ( rtl->regs + RTL_9346CR ); /* Ensure write reaches chip */ DBG_ENABLE ( DBGLVL_IO ); } From ab1e3ce0d700842e28ff99b37581a2e7b8b3671a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 10:17:15 +0100 Subject: [PATCH 27/45] [dhcp] Remove obsolete bootp.h header Reported-by: Christian Helmuth Signed-off-by: Michael Brown --- src/include/bootp.h | 230 -------------------------------------------- 1 file changed, 230 deletions(-) delete mode 100644 src/include/bootp.h diff --git a/src/include/bootp.h b/src/include/bootp.h deleted file mode 100644 index 0e65477a..00000000 --- a/src/include/bootp.h +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef _BOOTP_H -#define _BOOTP_H - -#ifdef ALTERNATE_DHCP_PORTS_1067_1068 -#undef NON_STANDARD_BOOTP_SERVER -#define NON_STANDARD_BOOTP_SERVER 1067 -#undef NON_STANDARD_BOOTP_CLIENT -#define NON_STANDARD_BOOTP_CLIENT 1068 -#endif - -#ifdef NON_STANDARD_BOOTP_SERVER -#define BOOTP_SERVER NON_STANDARD_BOOTP_SERVER -#else -#define BOOTP_SERVER 67 -#endif -#ifdef NON_STANDARD_BOOTP_CLIENT -#define BOOTP_CLIENT NON_STANDARD_BOOTP_CLIENT -#else -#define BOOTP_CLIENT 68 -#endif -#define PROXYDHCP_SERVER 4011 /* For PXE */ - -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -#define TAG_LEN(p) (*((p)+1)) -#define RFC1533_COOKIE 99, 130, 83, 99 -#define RFC1533_PAD 0 -#define RFC1533_NETMASK 1 -#define RFC1533_TIMEOFFSET 2 -#define RFC1533_GATEWAY 3 -#define RFC1533_TIMESERVER 4 -#define RFC1533_IEN116NS 5 -#define RFC1533_DNS 6 -#define RFC1533_LOGSERVER 7 -#define RFC1533_COOKIESERVER 8 -#define RFC1533_LPRSERVER 9 -#define RFC1533_IMPRESSSERVER 10 -#define RFC1533_RESOURCESERVER 11 -#define RFC1533_HOSTNAME 12 -#define RFC1533_BOOTFILESIZE 13 -#define RFC1533_MERITDUMPFILE 14 -#define RFC1533_DOMAINNAME 15 -#define RFC1533_SWAPSERVER 16 -#define RFC1533_ROOTPATH 17 -#define RFC1533_EXTENSIONPATH 18 -#define RFC1533_IPFORWARDING 19 -#define RFC1533_IPSOURCEROUTING 20 -#define RFC1533_IPPOLICYFILTER 21 -#define RFC1533_IPMAXREASSEMBLY 22 -#define RFC1533_IPTTL 23 -#define RFC1533_IPMTU 24 -#define RFC1533_IPMTUPLATEAU 25 -#define RFC1533_INTMTU 26 -#define RFC1533_INTLOCALSUBNETS 27 -#define RFC1533_INTBROADCAST 28 -#define RFC1533_INTICMPDISCOVER 29 -#define RFC1533_INTICMPRESPOND 30 -#define RFC1533_INTROUTEDISCOVER 31 -#define RFC1533_INTROUTESOLICIT 32 -#define RFC1533_INTSTATICROUTES 33 -#define RFC1533_LLTRAILERENCAP 34 -#define RFC1533_LLARPCACHETMO 35 -#define RFC1533_LLETHERNETENCAP 36 -#define RFC1533_TCPTTL 37 -#define RFC1533_TCPKEEPALIVETMO 38 -#define RFC1533_TCPKEEPALIVEGB 39 -#define RFC1533_NISDOMAIN 40 -#define RFC1533_NISSERVER 41 -#define RFC1533_NTPSERVER 42 -#define RFC1533_VENDOR 43 -#define RFC1533_NBNS 44 -#define RFC1533_NBDD 45 -#define RFC1533_NBNT 46 -#define RFC1533_NBSCOPE 47 -#define RFC1533_XFS 48 -#define RFC1533_XDM 49 -#ifndef NO_DHCP_SUPPORT -#define RFC2132_REQ_ADDR 50 -#define RFC2132_MSG_TYPE 53 -#define RFC2132_SRV_ID 54 -#define RFC2132_PARAM_LIST 55 -#define RFC2132_MAX_SIZE 57 -#define RFC2132_VENDOR_CLASS_ID 60 -#define RFC2132_CLIENT_ID 61 -#define RFC2132_TFTP_SERVER_NAME 66 -#define RFC2132_BOOTFILE_NAME 67 -#define RFC3004_USER_CLASS 77 - -#ifdef PXE_DHCP_STRICT -/* - * The following options are acknowledged in RFC3679 because they are - * widely used by PXE implementations, but have never been properly - * allocated. Despite other PXE options being correctly packed in a - * vendor encapsulated field, these are exposed. Sigh. Note that the - * client UUID (option 97) is also noted in the PXE spec as using - * option 61. - */ -#define RFC3679_PXE_CLIENT_ARCH 93 -#define RFC3679_PXE_CLIENT_NDI 94 -#define RFC3679_PXE_CLIENT_UUID 97 - -/* The lengths are fixed. */ -#define RFC3679_PXE_CLIENT_ARCH_LENGTH 2 -#define RFC3679_PXE_CLIENT_NDI_LENGTH 3 -#define RFC3679_PXE_CLIENT_UUID_LENGTH 17 - -/* - * Values of RFC3679_PXE_CLIENT_ARCH can apparently be one of the - * following, according to the PXE spec. The spec only actually - * described the 2nd octet, not the first. Duh... assume 0. - */ -#define RFC3679_PXE_CLIENT_ARCH_IAX86PC 0,0 -#define RFC3679_PXE_CLIENT_ARCH_NECPC98 0,1 -#define RFC3679_PXE_CLIENT_ARCH_IA64PC 0,2 -#define RFC3679_PXE_CLIENT_ARCH_DECALPHA 0,3 -#define RFC3679_PXE_CLIENT_ARCH_ARCX86 0,4 -#define RFC3679_PXE_CLIENT_ARCH_INTELLEAN 0,5 - -/* - * Only one valid value of NDI type (must be 1) and UNDI version (must - * be 2.1) - */ -#define RFC3679_PXE_CLIENT_NDI_21 1,2,1 - -/* - * UUID - type must be 1 and then 16 octets of UID, as with the client ID. - * The value is a default for testing only - */ -#define RFC3679_PXE_CLIENT_UUID_TYPE 0 -#warning "UUID is a default for testing ONLY!" -#define RFC3679_PXE_CLIENT_UUID_DEFAULT \ - RFC3679_PXE_CLIENT_UUID_TYPE, \ - 0xDE,0xAD,0xBE,0xEF, \ - 0xDE,0xAD,0xBE,0xEF, \ - 0xDE,0xAD,0xBE,0xEF, \ - 0xDE,0xAD,0xBE,0xEF -/* - * The Vendor Class ID. Note that the Arch and UNDI version numbers - * are fixed and must be same as the ARCH and NDI above. - */ -#define RFC2132_VENDOR_CLASS_ID_PXE_LENGTH 32 -#define RFC2132_VENDOR_CLASS_ID_PXE \ - 'P','X','E','C','l','i','e','n','t',':', \ - 'A','r','c','h',':','0','0','0','0','0',':', \ - 'U','N','D','I',':','0','0','2','0','0','1' - -/* - * The following vendor options are required in the PXE spec to pull - * options for the *next* image. The PXE spec doesn't help us with - * this (like explaining why). - */ -#define RFC1533_VENDOR_PXE_OPT128 128 -#define RFC1533_VENDOR_PXE_OPT129 129 -#define RFC1533_VENDOR_PXE_OPT130 130 -#define RFC1533_VENDOR_PXE_OPT131 131 -#define RFC1533_VENDOR_PXE_OPT132 132 -#define RFC1533_VENDOR_PXE_OPT133 133 -#define RFC1533_VENDOR_PXE_OPT134 134 -#define RFC1533_VENDOR_PXE_OPT135 135 - -#endif /* PXE_DHCP_STRICT */ - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPACK 5 -#endif /* NO_DHCP_SUPPORT */ - -#define RFC1533_VENDOR_MAJOR 0 -#define RFC1533_VENDOR_MINOR 0 - -#define RFC1533_VENDOR_MAGIC 128 -#define RFC1533_VENDOR_ADDPARM 129 -#define RFC1533_VENDOR_ETHDEV 130 -/* We should really apply for an official Etherboot encap option */ -#define RFC1533_VENDOR_ETHERBOOT_ENCAP 150 -/* I'll leave it to FREEBSD to decide if they want to renumber */ -#ifdef IMAGE_FREEBSD -#define RFC1533_VENDOR_HOWTO 132 -#define RFC1533_VENDOR_KERNEL_ENV 133 -#endif -#define RFC1533_VENDOR_NIC_DEV_ID 175 -#define RFC1533_VENDOR_ARCH 177 - -#define RFC1533_END 255 - -#define BOOTP_VENDOR_LEN 64 -#ifndef NO_DHCP_SUPPORT -#define DHCP_OPT_LEN 312 -#endif /* NO_DHCP_SUPPORT */ - -/* Format of a bootp packet */ -struct bootp_t { - uint8_t bp_op; - uint8_t bp_htype; - uint8_t bp_hlen; - uint8_t bp_hops; - uint32_t bp_xid; - uint16_t bp_secs; - uint16_t unused; - in_addr bp_ciaddr; - in_addr bp_yiaddr; - in_addr bp_siaddr; - in_addr bp_giaddr; - uint8_t bp_hwaddr[16]; - uint8_t bp_sname[64]; - char bp_file[128]; -#ifdef NO_DHCP_SUPPORT - uint8_t bp_vend[BOOTP_VENDOR_LEN]; -#else - uint8_t bp_vend[DHCP_OPT_LEN]; -#endif /* NO_DHCP_SUPPORT */ -}; - -/* Format of a bootp IP packet */ -struct bootpip_t -{ - struct iphdr ip; - struct udphdr udp; - struct bootp_t bp; -}; - -/* Format of bootp packet with extensions */ -struct bootpd_t { - struct bootp_t bootp_reply; - uint8_t bootp_extension[MAX_BOOTP_EXTLEN]; -}; - -#endif /* _BOOTP_H */ From 2095ed413ec213e2b3874575004eee24f62c2ff4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 14:05:42 +0100 Subject: [PATCH 28/45] [netdevice] Add netdev_tx_defer() to allow drivers to defer transmissions Devices with small transmit descriptor rings may temporarily run out of space. Provide netdev_tx_defer() to allow drivers to defer packets for retransmission as soon as a descriptor becomes available. Signed-off-by: Michael Brown --- src/include/ipxe/netdevice.h | 4 ++ src/net/netdevice.c | 90 ++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index e5dbd996..21754fe6 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -346,6 +346,8 @@ struct net_device { size_t max_pkt_len; /** TX packet queue */ struct list_head tx_queue; + /** Deferred TX packet queue */ + struct list_head tx_deferred; /** RX packet queue */ struct list_head rx_queue; /** TX statistics */ @@ -605,6 +607,8 @@ netdev_rx_frozen ( struct net_device *netdev ) { extern void netdev_link_err ( struct net_device *netdev, int rc ); extern void netdev_link_down ( struct net_device *netdev ); extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); +extern void netdev_tx_defer ( struct net_device *netdev, + struct io_buffer *iobuf ); extern void netdev_tx_err ( struct net_device *netdev, struct io_buffer *iobuf, int rc ); extern void netdev_tx_complete_err ( struct net_device *netdev, diff --git a/src/net/netdevice.c b/src/net/netdevice.c index 88ca93f9..1191ebc1 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -212,6 +213,43 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) { return rc; } +/** + * Defer transmitted packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * + * Drivers may call netdev_tx_defer() if there is insufficient space + * in the transmit descriptor ring. Any packets deferred in this way + * will be automatically retransmitted as soon as space becomes + * available (i.e. as soon as the driver calls netdev_tx_complete()). + * + * The packet must currently be in the network device's TX queue. + * + * Drivers utilising netdev_tx_defer() must ensure that space in the + * transmit descriptor ring is freed up @b before calling + * netdev_tx_complete(). For example, if the ring is modelled using a + * producer counter and a consumer counter, then the consumer counter + * must be incremented before the call to netdev_tx_complete(). + * Failure to do this will cause the retransmitted packet to be + * immediately redeferred (which will result in out-of-order + * transmissions and other nastiness). + */ +void netdev_tx_defer ( struct net_device *netdev, struct io_buffer *iobuf ) { + + /* Catch data corruption as early as possible */ + list_check_contains_entry ( iobuf, &netdev->tx_queue, list ); + + /* Remove from transmit queue */ + list_del ( &iobuf->list ); + + /* Add to deferred transmit queue */ + list_add_tail ( &iobuf->list, &netdev->tx_deferred ); + + /* Record "out of space" statistic */ + netdev_tx_err ( netdev, NULL, -ENOBUFS ); +} + /** * Discard transmitted packet * @@ -257,6 +295,13 @@ void netdev_tx_complete_err ( struct net_device *netdev, /* Dequeue and free I/O buffer */ list_del ( &iobuf->list ); netdev_tx_err ( netdev, iobuf, rc ); + + /* Transmit first pending packet, if any */ + if ( ( iobuf = list_first_entry ( &netdev->tx_deferred, + struct io_buffer, list ) ) != NULL ) { + list_del ( &iobuf->list ); + netdev_tx ( netdev, iobuf ); + } } /** @@ -270,9 +315,9 @@ void netdev_tx_complete_err ( struct net_device *netdev, void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) { struct io_buffer *iobuf; - list_for_each_entry ( iobuf, &netdev->tx_queue, list ) { + if ( ( iobuf = list_first_entry ( &netdev->tx_queue, struct io_buffer, + list ) ) != NULL ) { netdev_tx_complete_err ( netdev, iobuf, rc ); - return; } } @@ -283,10 +328,15 @@ void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) { */ static void netdev_tx_flush ( struct net_device *netdev ) { - /* Discard any packets in the TX queue */ + /* Discard any packets in the TX queue. This will also cause + * any packets in the deferred TX queue to be discarded + * automatically. + */ while ( ! list_empty ( &netdev->tx_queue ) ) { netdev_tx_complete_next_err ( netdev, -ECANCELED ); } + assert ( list_empty ( &netdev->tx_queue ) ); + assert ( list_empty ( &netdev->tx_deferred ) ); } /** @@ -424,6 +474,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) { ref_init ( &netdev->refcnt, free_netdev ); netdev->link_rc = -EUNKNOWN_LINK_STATUS; INIT_LIST_HEAD ( &netdev->tx_queue ); + INIT_LIST_HEAD ( &netdev->tx_deferred ); INIT_LIST_HEAD ( &netdev->rx_queue ); netdev_settings_init ( netdev ); netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) ); @@ -817,3 +868,36 @@ __weak struct net_device * vlan_find ( struct net_device *trunk __unused, /** Networking stack process */ PERMANENT_PROCESS ( net_process, net_step ); + +/** + * Discard some cached network device data + * + * @ret discarded Number of cached items discarded + */ +static unsigned int net_discard ( void ) { + struct net_device *netdev; + struct io_buffer *iobuf; + unsigned int discarded = 0; + + /* Try to drop one deferred TX packet from each network device */ + for_each_netdev ( netdev ) { + if ( ( iobuf = list_first_entry ( &netdev->tx_deferred, + struct io_buffer, + list ) ) != NULL ) { + + /* Discard first deferred packet */ + list_del ( &iobuf->list ); + free ( iobuf ); + + /* Report discard */ + discarded++; + } + } + + return discarded; +} + +/** Network device cache discarder */ +struct cache_discarder net_discarder __cache_discarder ( CACHE_NORMAL ) = { + .discard = net_discard, +}; From b4ec6a6a687bd6e714e0dddcb8422cfe0d4195a1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 14:07:51 +0100 Subject: [PATCH 29/45] [realtek] Defer packets when no transmit descriptors are available Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index f7b5ec58..1fd3931b 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -724,8 +724,8 @@ static int realtek_transmit ( struct net_device *netdev, /* Get next transmit descriptor */ if ( ( rtl->tx.prod - rtl->tx.cons ) >= RTL_NUM_TX_DESC ) { - DBGC ( rtl, "REALTEK %p out of transmit descriptors\n", rtl ); - return -ENOBUFS; + netdev_tx_defer ( netdev, iobuf ); + return 0; } tx_idx = ( rtl->tx.prod++ % RTL_NUM_TX_DESC ); @@ -809,8 +809,8 @@ static void realtek_poll_tx ( struct net_device *netdev ) { DBGC2 ( rtl, "REALTEK %p TX %d complete\n", rtl, tx_idx ); /* Complete TX descriptor */ - netdev_tx_complete_next ( netdev ); rtl->tx.cons++; + netdev_tx_complete_next ( netdev ); } } From 15d2f947f51a0ea72e9938f5648fd5133950ecdb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 17:20:39 +0100 Subject: [PATCH 30/45] [settings] Eliminate settings "tag magic" Create an explicit concept of "settings scope" and eliminate the magic values used for numerical setting tags. Signed-off-by: Michael Brown --- src/arch/i386/interface/vmware/guestinfo.c | 2 +- src/core/nvo.c | 6 +- src/core/settings.c | 44 ++++--------- src/drivers/net/phantom/phantom.c | 13 ++-- src/include/ipxe/net80211.h | 21 ------ src/include/ipxe/netdevice.h | 32 --------- src/include/ipxe/settings.h | 75 +++++++++++++--------- src/interface/smbios/smbios_settings.c | 32 ++++----- src/net/80211/net80211.c | 3 - src/net/dhcppkt.c | 7 +- src/net/netdev_settings.c | 17 ----- 11 files changed, 82 insertions(+), 170 deletions(-) diff --git a/src/arch/i386/interface/vmware/guestinfo.c b/src/arch/i386/interface/vmware/guestinfo.c index 5e08d947..da013ca2 100644 --- a/src/arch/i386/interface/vmware/guestinfo.c +++ b/src/arch/i386/interface/vmware/guestinfo.c @@ -224,7 +224,7 @@ static int guestinfo_net_probe ( struct net_device *netdev ) { rc = -ENOMEM; goto err_alloc; } - settings_init ( settings, &guestinfo_settings_operations, NULL, 0 ); + settings_init ( settings, &guestinfo_settings_operations, NULL, NULL ); /* Register settings */ if ( ( rc = register_settings ( settings, netdev_settings ( netdev ), diff --git a/src/core/nvo.c b/src/core/nvo.c index 5383fe5c..4c871b2f 100644 --- a/src/core/nvo.c +++ b/src/core/nvo.c @@ -195,7 +195,8 @@ static int nvo_save ( struct nvo_block *nvo ) { int nvo_applies ( struct settings *settings __unused, struct setting *setting ) { - return dhcpopt_applies ( setting->tag ); + return ( ( setting->scope == NULL ) && + dhcpopt_applies ( setting->tag ) ); } /** @@ -274,7 +275,8 @@ void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs, nvo->len = len; nvo->resize = resize; dhcpopt_init ( &nvo->dhcpopts, NULL, 0, nvo_realloc_dhcpopt ); - settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 ); + settings_init ( &nvo->settings, &nvo_settings_operations, + refcnt, NULL ); } /** diff --git a/src/core/settings.c b/src/core/settings.c index 43715fbd..54d48d32 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -984,7 +984,7 @@ void clear_settings ( struct settings *settings ) { int setting_cmp ( struct setting *a, struct setting *b ) { /* If the settings have tags, compare them */ - if ( a->tag && ( a->tag == b->tag ) ) + if ( a->tag && ( a->tag == b->tag ) && ( a->scope == b->scope ) ) return 0; /* Otherwise, if the settings have names, compare them */ @@ -1099,19 +1099,17 @@ struct setting * find_setting ( const char *name ) { /** * Parse setting name as tag number * - * @v settings Settings block * @v name Name * @ret tag Tag number, or 0 if not a valid number */ -static unsigned int parse_setting_tag ( struct settings *settings, - const char *name ) { +static unsigned int parse_setting_tag ( const char *name ) { char *tmp = ( ( char * ) name ); unsigned int tag = 0; while ( 1 ) { tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) ); if ( *tmp == 0 ) - return ( tag | settings->tag_magic ); + return tag; if ( *tmp != '.' ) return 0; tmp++; @@ -1193,7 +1191,8 @@ parse_setting_name ( const char *name, } /* Identify setting */ - setting->tag = parse_setting_tag ( *settings, setting_name ); + setting->tag = parse_setting_tag ( setting_name ); + setting->scope = (*settings)->default_scope; setting->name = setting_name; for_each_table_entry ( named_setting, SETTINGS ) { /* Matches a defined named setting; use that setting */ @@ -1998,26 +1997,15 @@ struct builtin_setting_operation { int ( * fetch ) ( void *data, size_t len ); }; -/** Built-in setting tag magic */ -#define BUILTIN_SETTING_TAG_MAGIC 0xb1 - -/** - * Construct built-in setting tag - * - * @v id Unique identifier - * @ret tag Setting tag - */ -#define BUILTIN_SETTING_TAG( id ) ( ( BUILTIN_SETTING_TAG_MAGIC << 24 ) | (id) ) - -/** "errno" setting tag */ -#define BUILTIN_SETTING_TAG_ERRNO BUILTIN_SETTING_TAG ( 0x01 ) +/** Built-in setting scope */ +static struct settings_scope builtin_scope; /** Error number setting */ struct setting errno_setting __setting ( SETTING_MISC ) = { .name = "errno", .description = "Last error", - .tag = BUILTIN_SETTING_TAG_ERRNO, .type = &setting_type_uint32, + .scope = &builtin_scope, }; /** @@ -2038,15 +2026,12 @@ static int errno_fetch ( void *data, size_t len ) { return sizeof ( content ); } -/** "buildarch" setting tag */ -#define BUILTIN_SETTING_TAG_BUILDARCH BUILTIN_SETTING_TAG ( 0x02 ) - /** Build architecture setting */ struct setting buildarch_setting __setting ( SETTING_MISC ) = { .name = "buildarch", .description = "Build architecture", - .tag = BUILTIN_SETTING_TAG_BUILDARCH, .type = &setting_type_string, + .scope = &builtin_scope, }; /** @@ -2063,15 +2048,12 @@ static int buildarch_fetch ( void *data, size_t len ) { return ( sizeof ( buildarch ) - 1 /* NUL */ ); } -/** "platform" setting tag */ -#define BUILTIN_SETTING_TAG_PLATFORM BUILTIN_SETTING_TAG ( 0x03 ) - /** Platform setting */ struct setting platform_setting __setting ( SETTING_MISC ) = { .name = "platform", .description = "Platform", - .tag = BUILTIN_SETTING_TAG_PLATFORM, .type = &setting_type_string, + .scope = &builtin_scope, }; /** @@ -2128,11 +2110,8 @@ static int builtin_fetch ( struct settings *settings __unused, */ static int builtin_applies ( struct settings *settings __unused, struct setting *setting ) { - unsigned int tag_magic; - /* Check tag magic */ - tag_magic = ( setting->tag >> 24 ); - return ( tag_magic == BUILTIN_SETTING_TAG_MAGIC ); + return ( setting->scope == &builtin_scope ); } /** Built-in settings operations */ @@ -2144,7 +2123,6 @@ static struct settings_operations builtin_settings_operations = { /** Built-in settings */ static struct settings builtin_settings = { .refcnt = NULL, - .tag_magic = BUILTIN_SETTING_TAG ( 0 ), .siblings = LIST_HEAD_INIT ( builtin_settings.siblings ), .children = LIST_HEAD_INIT ( builtin_settings.children ), .op = &builtin_settings_operations, diff --git a/src/drivers/net/phantom/phantom.c b/src/drivers/net/phantom/phantom.c index 1c798e04..7f2fe0b6 100644 --- a/src/drivers/net/phantom/phantom.c +++ b/src/drivers/net/phantom/phantom.c @@ -1454,11 +1454,8 @@ static struct net_device_operations phantom_operations = { * */ -/** Phantom CLP settings tag magic */ -#define PHN_CLP_TAG_MAGIC 0xc19c1900UL - -/** Phantom CLP settings tag magic mask */ -#define PHN_CLP_TAG_MAGIC_MASK 0xffffff00UL +/** Phantom CLP settings scope */ +static struct settings_scope phantom_settings_scope; /** Phantom CLP data * @@ -1689,8 +1686,8 @@ phantom_clp_setting ( struct phantom_nic *phantom, struct setting *setting ) { } /* Allow for use of numbered settings */ - if ( ( setting->tag & PHN_CLP_TAG_MAGIC_MASK ) == PHN_CLP_TAG_MAGIC ) - return ( setting->tag & ~PHN_CLP_TAG_MAGIC_MASK ); + if ( setting->scope == &phantom_settings_scope ) + return setting->tag; DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n", phantom, setting->name ); @@ -2075,7 +2072,7 @@ static int phantom_probe ( struct pci_device *pci ) { assert ( phantom->port < PHN_MAX_NUM_PORTS ); settings_init ( &phantom->settings, &phantom_settings_operations, - &netdev->refcnt, PHN_CLP_TAG_MAGIC ); + &netdev->refcnt, &phantom_settings_scope ); /* Fix up PCI device */ adjust_pci_device ( pci ); diff --git a/src/include/ipxe/net80211.h b/src/include/ipxe/net80211.h index 771872c8..dd8bd228 100644 --- a/src/include/ipxe/net80211.h +++ b/src/include/ipxe/net80211.h @@ -1183,25 +1183,4 @@ static inline u16 net80211_cts_duration ( struct net80211_device *dev, net80211_duration ( dev, size, dev->rates[dev->rate] ) ); } -/** 802.11 device setting tag magic */ -#define NET80211_SETTING_TAG_MAGIC 0x8211 - -/** - * Construct 802.11 setting tag - * - * @v id Unique identifier - * @ret tag Setting tag - */ -#define NET80211_SETTING_TAG( id ) \ - NETDEV_SETTING_TAG ( ( NET80211_SETTING_TAG_MAGIC << 8 ) | (id) ) - -/** SSID setting tag */ -#define NET80211_SETTING_TAG_SSID NET80211_SETTING_TAG ( 0x01 ) - -/** Active scanning setting tag */ -#define NET80211_SETTING_TAG_ACTIVE_SCAN NET80211_SETTING_TAG ( 0x02 ) - -/** Wireless key setting tag */ -#define NET80211_SETTING_TAG_KEY NET80211_SETTING_TAG ( 0x03 ) - #endif diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index 21754fe6..0daa1d62 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -411,38 +411,6 @@ struct net_driver { /** Declare a network driver */ #define __net_driver __table_entry ( NET_DRIVERS, 01 ) -/** Network device setting tag magic - * - * All DHCP option settings are deemed to be valid as network device - * settings. There are also some extra non-DHCP settings (such as - * "mac"), which are marked as being valid network device settings by - * using a magic tag value. - */ -#define NETDEV_SETTING_TAG_MAGIC 0xeb - -/** - * Construct network device setting tag - * - * @v id Unique identifier - * @ret tag Setting tag - */ -#define NETDEV_SETTING_TAG( id ) ( ( NETDEV_SETTING_TAG_MAGIC << 24 ) | (id) ) - -/** - * Check if tag is a network device setting tag - * - * @v tag Setting tag - * @ret is_ours Tag is a network device setting tag - */ -#define IS_NETDEV_SETTING_TAG( tag ) \ - ( ( (tag) >> 24 ) == NETDEV_SETTING_TAG_MAGIC ) - -/** MAC address setting tag */ -#define NETDEV_SETTING_TAG_MAC NETDEV_SETTING_TAG ( 0x01 ) - -/** Bus ID setting tag */ -#define NETDEV_SETTING_TAG_BUS_ID NETDEV_SETTING_TAG ( 0x02 ) - extern struct list_head net_devices; extern struct net_device_operations null_netdev_operations; extern struct settings_operations netdev_settings_operations; diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index 3f887602..9b7404ac 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -38,27 +38,14 @@ struct setting { * The setting tag is a numerical description of the setting * (such as a DHCP option number, or an SMBIOS structure and * field number). - * - * Users can construct tags for settings that are not - * explicitly known to iPXE using the generic syntax for - * numerical settings. For example, the setting name "60" - * will be interpreted as referring to DHCP option 60 (the - * vendor class identifier). - * - * This creates a potential for namespace collisions, since - * the interpretation of the numerical description will vary - * according to the settings block. When a user attempts to - * fetch a generic numerical setting, we need to ensure that - * only the intended settings block interprets the numerical - * description. (For example, we do not want to attempt to - * retrieve the subnet mask from SMBIOS, or the system UUID - * from DHCP.) - * - * This potential problem is resolved by allowing the setting - * tag to include a "magic" value indicating the - * interpretation to be placed upon the numerical description. */ unsigned int tag; + /** Setting scope (or NULL) + * + * For historic reasons, a NULL scope with a non-zero tag + * indicates a DHCPv4 option setting. + */ + struct settings_scope *scope; }; /** Configuration setting table */ @@ -134,12 +121,6 @@ struct settings { struct refcnt *refcnt; /** Name */ const char *name; - /** Tag magic - * - * This value will be ORed in to any numerical tags - * constructed by parse_setting_name(). - */ - unsigned int tag_magic; /** Parent settings block */ struct settings *parent; /** Sibling settings blocks */ @@ -148,8 +129,44 @@ struct settings { struct list_head children; /** Settings block operations */ struct settings_operations *op; + /** Default scope for numerical settings constructed for this block */ + struct settings_scope *default_scope; }; +/** + * A setting scope + * + * Users can construct tags for settings that are not explicitly known + * to iPXE using the generic syntax for numerical settings. For + * example, the setting name "60" will be interpreted as referring to + * DHCP option 60 (the vendor class identifier). + * + * This creates a potential for namespace collisions, since the + * interpretation of the numerical description will vary according to + * the settings block. When a user attempts to fetch a generic + * numerical setting, we need to ensure that only the intended + * settings blocks interpret this numerical description. (For + * example, we do not want to attempt to retrieve the subnet mask from + * SMBIOS, or the system UUID from DHCP.) + * + * This potential problem is resolved by including a user-invisible + * "scope" within the definition of each setting. Settings blocks may + * use this to determine whether or not the setting is applicable. + * Any settings constructed from a numerical description + * (e.g. "smbios/1.4.0") will be assigned the default scope of the + * settings block specified in the description (e.g. "smbios"); this + * provides behaviour matching the user's expectations in most + * circumstances. + */ +struct settings_scope { + /** Dummy field + * + * This is included only to ensure that pointers to different + * scopes always compare differently. + */ + uint8_t dummy; +} __attribute__ (( packed )); + /** * A setting type * @@ -329,17 +346,17 @@ extern struct setting busid_setting __setting ( SETTING_NETDEV ); * @v settings Settings block * @v op Settings block operations * @v refcnt Containing object reference counter, or NULL - * @v tag_magic Tag magic + * @v default_scope Default scope */ static inline void settings_init ( struct settings *settings, struct settings_operations *op, struct refcnt *refcnt, - unsigned int tag_magic ) { + struct settings_scope *default_scope ) { INIT_LIST_HEAD ( &settings->siblings ); INIT_LIST_HEAD ( &settings->children ); settings->op = op; settings->refcnt = refcnt; - settings->tag_magic = tag_magic; + settings->default_scope = default_scope; } /** @@ -351,7 +368,7 @@ static inline void settings_init ( struct settings *settings, static inline void generic_settings_init ( struct generic_settings *generics, struct refcnt *refcnt ) { settings_init ( &generics->settings, &generic_settings_operations, - refcnt, 0 ); + refcnt, NULL ); INIT_LIST_HEAD ( &generics->list ); } diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 663da968..7b2efcd7 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -27,15 +27,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include -/** SMBIOS settings tag magic number */ -#define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */ - -/** - * Construct SMBIOS empty tag - * - * @ret tag SMBIOS setting tag - */ -#define SMBIOS_EMPTY_TAG ( SMBIOS_TAG_MAGIC << 24 ) +/** SMBIOS settings scope */ +static struct settings_scope smbios_settings_scope; /** * Construct SMBIOS raw-data tag @@ -46,8 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @ret tag SMBIOS setting tag */ #define SMBIOS_RAW_TAG( _type, _structure, _field ) \ - ( ( SMBIOS_TAG_MAGIC << 24 ) | \ - ( (_type) << 16 ) | \ + ( ( (_type) << 16 ) | \ ( offsetof ( _structure, _field ) << 8 ) | \ ( sizeof ( ( ( _structure * ) 0 )->_field ) ) ) @@ -60,8 +52,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @ret tag SMBIOS setting tag */ #define SMBIOS_STRING_TAG( _type, _structure, _field ) \ - ( ( SMBIOS_TAG_MAGIC << 24 ) | \ - ( (_type) << 16 ) | \ + ( ( (_type) << 16 ) | \ ( offsetof ( _structure, _field ) << 8 ) ) /** @@ -73,11 +64,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ static int smbios_applies ( struct settings *settings __unused, struct setting *setting ) { - unsigned int tag_magic; - /* Check tag magic */ - tag_magic = ( setting->tag >> 24 ); - return ( tag_magic == SMBIOS_TAG_MAGIC ); + return ( setting->scope == &smbios_settings_scope ); } /** @@ -93,18 +81,15 @@ static int smbios_fetch ( struct settings *settings __unused, struct setting *setting, void *data, size_t len ) { struct smbios_structure structure; - unsigned int tag_magic; unsigned int tag_type; unsigned int tag_offset; unsigned int tag_len; int rc; /* Split tag into type, offset and length */ - tag_magic = ( setting->tag >> 24 ); tag_type = ( ( setting->tag >> 16 ) & 0xff ); tag_offset = ( ( setting->tag >> 8 ) & 0xff ); tag_len = ( setting->tag & 0xff ); - assert ( tag_magic == SMBIOS_TAG_MAGIC ); /* Find SMBIOS structure */ if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 ) @@ -170,10 +155,10 @@ static struct settings_operations smbios_settings_operations = { /** SMBIOS settings */ static struct settings smbios_settings = { .refcnt = NULL, - .tag_magic = SMBIOS_EMPTY_TAG, .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ), .children = LIST_HEAD_INIT ( smbios_settings.children ), .op = &smbios_settings_operations, + .default_scope = &smbios_settings_scope, }; /** Initialise SMBIOS settings */ @@ -200,6 +185,7 @@ struct setting uuid_setting __setting ( SETTING_HOST ) = { .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, struct smbios_system_information, uuid ), .type = &setting_type_uuid, + .scope = &smbios_settings_scope, }; /** Other SMBIOS named settings */ @@ -211,6 +197,7 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_system_information, manufacturer ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, { .name = "product", @@ -219,6 +206,7 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_system_information, product ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, { .name = "serial", @@ -227,6 +215,7 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_system_information, serial ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, { .name = "asset", @@ -235,5 +224,6 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_enclosure_information, asset_tag ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, }; diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c index 2181fc4a..54df7905 100644 --- a/src/net/80211/net80211.c +++ b/src/net/80211/net80211.c @@ -208,7 +208,6 @@ struct setting net80211_ssid_setting __setting ( SETTING_NETDEV_EXTRA ) = { .name = "ssid", .description = "Wireless SSID", .type = &setting_type_string, - .tag = NET80211_SETTING_TAG_SSID, }; /** Whether to use active scanning @@ -221,7 +220,6 @@ struct setting net80211_active_setting __setting ( SETTING_NETDEV_EXTRA ) = { .name = "active-scan", .description = "Actively scan for wireless networks", .type = &setting_type_int8, - .tag = NET80211_SETTING_TAG_ACTIVE_SCAN, }; /** The cryptographic key to use @@ -234,7 +232,6 @@ struct setting net80211_key_setting __setting ( SETTING_NETDEV_EXTRA ) = { .name = "key", .description = "Wireless encryption key", .type = &setting_type_string, - .tag = NET80211_SETTING_TAG_KEY, }; /** @} */ diff --git a/src/net/dhcppkt.c b/src/net/dhcppkt.c index 528f9003..3722c09e 100644 --- a/src/net/dhcppkt.c +++ b/src/net/dhcppkt.c @@ -230,7 +230,8 @@ static int dhcppkt_settings_applies ( struct settings *settings, struct dhcp_packet *dhcppkt = container_of ( settings, struct dhcp_packet, settings ); - return dhcppkt_applies ( dhcppkt, setting->tag ); + return ( ( setting->scope == NULL ) && + dhcppkt_applies ( dhcppkt, setting->tag ) ); } /** @@ -299,6 +300,6 @@ void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct dhcphdr *data, dhcpopt_init ( &dhcppkt->options, &dhcppkt->dhcphdr->options, ( len - offsetof ( struct dhcphdr, options ) ), dhcpopt_no_realloc ); - settings_init ( &dhcppkt->settings, - &dhcppkt_settings_operations, &dhcppkt->refcnt, 0 ); + settings_init ( &dhcppkt->settings, &dhcppkt_settings_operations, + &dhcppkt->refcnt, NULL ); } diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 9efe6811..8758e980 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -39,29 +39,13 @@ struct setting mac_setting __setting ( SETTING_NETDEV ) = { .name = "mac", .description = "MAC address", .type = &setting_type_hex, - .tag = NETDEV_SETTING_TAG_MAC, }; struct setting busid_setting __setting ( SETTING_NETDEV ) = { .name = "busid", .description = "Bus ID", .type = &setting_type_hex, - .tag = NETDEV_SETTING_TAG_BUS_ID, }; -/** - * Check applicability of network device setting - * - * @v settings Settings block - * @v setting Setting - * @ret applies Setting applies within this settings block - */ -static int netdev_applies ( struct settings *settings __unused, - struct setting *setting ) { - - return ( IS_NETDEV_SETTING_TAG ( setting->tag ) || - dhcpopt_applies ( setting->tag ) ); -} - /** * Store value of network device setting * @@ -134,7 +118,6 @@ static void netdev_clear ( struct settings *settings ) { /** Network device configuration settings operations */ struct settings_operations netdev_settings_operations = { - .applies = netdev_applies, .store = netdev_store, .fetch = netdev_fetch, .clear = netdev_clear, From a352fde45ef58ed4766c074d772c3cf9f4410fd7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 22:00:51 +0100 Subject: [PATCH 31/45] [smbios] Allow access to unreferenced SMBIOS strings iPXE allows access to general SMBIOS settings using the syntax: smbios/.. This provides access to any fixed-offset field within an SMBIOS structure. This syntax is currently overloaded to interpret a zero as meaning that the byte at contains a string index; this provides access to SMBIOS strings (which are not located at fixed offsets). The "OEM Strings" SMBIOS structure contains strings which are not referenced by any fixed string index field within the structure. iPXE currently provides no way to access these strings. Fix by overloading the syntax for numerical SMBIOS settings to interpret an of zero as implying that contains a literal string index. The OEM Strings can then be accessed using: smbios/11.0.1 smbios/11.0.2 smbios/11.0.3 ... The actual byte at offset zero will always contain the structure type, which is already known since it must be specified in order to access the structure. There is thus no plausible existing use case for an offset of zero; overloading the syntax in this way should therefore not break compatibility with any existing scripts. The corner case where both and are zero is undefined (and, for now, will simply return a "not found" error). Signed-off-by: Michael Brown --- src/interface/smbios/smbios_settings.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 7b2efcd7..17f9a48e 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -99,16 +99,22 @@ static int smbios_fetch ( struct settings *settings __unused, uint8_t buf[structure.header.len]; const void *raw; union uuid uuid; + unsigned int index; /* Read SMBIOS structure */ if ( ( rc = read_smbios_structure ( &structure, buf, sizeof ( buf ) ) ) != 0 ) return rc; - /* A tag length of zero indicates a string */ - if ( tag_len == 0 ) { - if ( ( rc = read_smbios_string ( &structure, - buf[tag_offset], + /* A of zero indicates that the byte at + * contains a string index. An of + * zero indicates that the contains a literal + * string index. + */ + if ( ( tag_len == 0 ) || ( tag_offset == 0 ) ) { + index = ( ( tag_offset == 0 ) ? + tag_len : buf[tag_offset] ); + if ( ( rc = read_smbios_string ( &structure, index, data, len ) ) < 0 ) { return rc; } From 8bc20c1aa09ec521476f4b35b0a09c21e2e1e5f3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 20:42:57 +0100 Subject: [PATCH 32/45] [smbios] Allow access to multiple instances of SMBIOS structures Extend the syntax for numerical SMBIOS settings from smbios/.. to smbios/[.].. Where SMBIOS provides multiple structures with the same , this extended syntax allows for access to structures other than the first. If is omitted then it will default to zero, giving access to the first instance (and so matching existing behaviour). The 16-bit SMBIOS handle (which is an alternative way to disambiguate multiple instances of the same type of structure) can be accessed, if required, using smbios/..2.2:uint16 Signed-off-by: Michael Brown --- src/include/ipxe/smbios.h | 2 +- src/interface/smbios/smbios.c | 6 ++++-- src/interface/smbios/smbios_settings.c | 7 +++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/include/ipxe/smbios.h b/src/include/ipxe/smbios.h index 0765c4e4..aaba6cb1 100644 --- a/src/include/ipxe/smbios.h +++ b/src/include/ipxe/smbios.h @@ -162,7 +162,7 @@ struct smbios { #define SMBIOS_VERSION( major, minor ) ( ( (major) << 8 ) | (minor) ) extern int find_smbios ( struct smbios *smbios ); -extern int find_smbios_structure ( unsigned int type, +extern int find_smbios_structure ( unsigned int type, unsigned int instance, struct smbios_structure *structure ); extern int read_smbios_structure ( struct smbios_structure *structure, void *data, size_t len ); diff --git a/src/interface/smbios/smbios.c b/src/interface/smbios/smbios.c index 2adaa53d..90907e18 100644 --- a/src/interface/smbios/smbios.c +++ b/src/interface/smbios/smbios.c @@ -59,10 +59,11 @@ static size_t find_strings_terminator ( size_t offset ) { * Find specific structure type within SMBIOS * * @v type Structure type to search for + * @v instance Instance of this type of structure * @v structure SMBIOS structure descriptor to fill in * @ret rc Return status code */ -int find_smbios_structure ( unsigned int type, +int find_smbios_structure ( unsigned int type, unsigned int instance, struct smbios_structure *structure ) { unsigned int count = 0; size_t offset = 0; @@ -105,7 +106,8 @@ int find_smbios_structure ( unsigned int type, structure->header.len, structure->strings_len ); /* If this is the structure we want, return */ - if ( structure->header.type == type ) { + if ( ( structure->header.type == type ) && + ( instance-- == 0 ) ) { structure->offset = offset; return 0; } diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 17f9a48e..d2975df4 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -81,18 +81,21 @@ static int smbios_fetch ( struct settings *settings __unused, struct setting *setting, void *data, size_t len ) { struct smbios_structure structure; + unsigned int tag_instance; unsigned int tag_type; unsigned int tag_offset; unsigned int tag_len; int rc; - /* Split tag into type, offset and length */ + /* Split tag into instance, type, offset and length */ + tag_instance = ( ( setting->tag >> 24 ) & 0xff ); tag_type = ( ( setting->tag >> 16 ) & 0xff ); tag_offset = ( ( setting->tag >> 8 ) & 0xff ); tag_len = ( setting->tag & 0xff ); /* Find SMBIOS structure */ - if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 ) + if ( ( rc = find_smbios_structure ( tag_type, tag_instance, + &structure ) ) != 0 ) return rc; { From cb29cd4298f07c35ac2099f56bd9895a9160e3a2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 10 May 2013 10:03:56 +0100 Subject: [PATCH 33/45] [crypto] Report meaningful error when certificate chain validation fails If a certificate chain contains no certificate which can be validated as a standalone certificate (i.e. contains no trusted root certificates or previously-validated certificates) then iPXE will currently return a fixed error EACCES_UNTRUSTED. This masks the actual errors obtained when attempting to validate each certificate as a standalone certificate, and so makes troubleshooting difficult for the end user. Fix by instead returning the error obtained when attempting to validate the final certificate in the chain as a standalone certificate. This error is most likely (though not guaranteed) to represent the "real" problem. Reported-by: Sven Dreyer Signed-off-by: Michael Brown --- src/crypto/x509.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/crypto/x509.c b/src/crypto/x509.c index df3c5c0d..d54124c5 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -1552,11 +1552,8 @@ int x509_validate_chain ( struct x509_chain *chain, time_t time, struct x509_link *link; int rc; - /* Sanity check */ - if ( list_empty ( &chain->links ) ) { - DBGC ( chain, "X509 chain %p is empty\n", chain ); - return -EACCES_EMPTY; - } + /* Error to be used if chain contains no certifictes */ + rc = -EACCES_EMPTY; /* Find first certificate that can be validated as a * standalone (i.e. is already valid, or can be validated as @@ -1586,6 +1583,7 @@ int x509_validate_chain ( struct x509_chain *chain, time_t time, return 0; } - DBGC ( chain, "X509 chain %p found no valid certificates\n", chain ); - return -EACCES_UNTRUSTED; + DBGC ( chain, "X509 chain %p found no valid certificates: %s\n", + chain, strerror ( rc ) ); + return rc; } From 05d11b7337489d692690e049f15c1d7ada43c722 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 14 May 2013 14:28:30 +0100 Subject: [PATCH 34/45] [build] Use $(eval) if available When the $(eval) function is available (in GNU make >= 3.80), we can evaluate many of the dynamically-generated Makefile rules directly. This avoids generating a few hundred Makefile fragments in the filesystem, and so speeds up the build process. Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 155 ++++++++++++++++++++++++---------- src/arch/i386/Makefile.pcbios | 10 +-- 2 files changed, 115 insertions(+), 50 deletions(-) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 4dfaf7ab..00646047 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -113,6 +113,18 @@ $(warning Use GNU ld instead) $(error Unsuitable build environment found) endif +############################################################################### +# +# Check if $(eval ...) is available to use +# + +HAVE_EVAL := +ifndef NO_EVAL +$(eval HAVE_EVAL := yes) +endif +eval : + @$(ECHO) $(HAVE_EVAL) + ############################################################################### # # Check for various tool workarounds @@ -128,6 +140,11 @@ WORKAROUND_LDFLAGS := COMMA := , EMPTY := SPACE := $(EMPTY) $(EMPTY) +HASH := \# +define NEWLINE + + +endef # Check for an old version of gas (binutils 2.9.1) # @@ -675,84 +692,119 @@ $(BIN)/version.o : ../.git/index endif # We automatically generate rules for any file mentioned in AUTO_SRCS -# using the following set of templates. It would be cleaner to use -# $(eval ...), but this function exists only in GNU make >= 3.80. +# using the following set of templates. We use $(eval ...) if +# available, otherwise we generate separate Makefile fragments and +# include them. # deps_template : generate dependency list for a given source file # # $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# +define deps_template_file +$(call deps_template_parts,$(1),$(subst .,,$(suffix $(1))),$(basename $(notdir $(1)))) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") # $(2) is the source type (e.g. "c") # $(3) is the source base name (e.g. "rtl8139") # -define deps_template +define deps_template_parts @$(ECHO) " [DEPS] $(1)" @$(MKDIR) -p $(BIN)/deps/$(dir $(1)) $(Q)$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ -Wno-error -M $(1) -MG -MP | \ sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d + $(Q)$(if $(findstring drivers/,$(1)),\ + $(PERL) $(PARSEROM) $(1) >> $(BIN)/deps/$(1).d) endef # rules_template : generate rules for a given source file # # $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# +define rules_template +$(call rules_template_parts,$(1),$(subst .,,$(suffix $(1))),$(basename $(notdir $(1)))) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") # $(2) is the source type (e.g. "c") # $(3) is the source base name (e.g. "rtl8139") # -define rules_template +define rules_template_parts +$$(BIN)/$(3).o : $(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS) + $$(QM)$(ECHO) " [BUILD] $$@" + $$(RULE_$(2)) +BOBJS += $$(BIN)/$(3).o +$(foreach TGT,$(DEBUG_TARGETS),$(if $(RULE_$(2)_to_$(TGT)),$(NEWLINE)$(call rules_template_target,$(1),$(2),$(3),$(TGT)))) +$$(BIN)/deps/$(1).d : $$($(3)_DEPS) +TAGS : $$($(3)_DEPS) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# $(2) is the source type (e.g. "c") +# $(3) is the source base name (e.g. "rtl8139") +# $(4) is the destination type (e.g. "dbg%.o") +# +define rules_template_target +$$(BIN)/$(3).$(4) : $(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS) + $$(QM)$(ECHO) " [BUILD] $$@" + $$(RULE_$(2)_to_$(4)) +$(TGT)_OBJS += $$(BIN)/$(3).$(4) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# +define rules_template_file @$(ECHO) " [RULES] $(1)" @$(MKDIR) -p $(BIN)/rules/$(dir $(1)) - @$(ECHO_E) '\n$$(BIN)/$(3).o :' \ - '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS)' \ - '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \ - '\n\t$$(RULE_$(2))\n' \ - '\nBOBJS += $$(BIN)/$(3).o\n' \ - $(foreach TGT,$(DEBUG_TARGETS), \ - $(if $(RULE_$(2)_to_$(TGT)), \ - '\n$$(BIN)/$(3).$(TGT) :' \ - '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS)' \ - '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \ - '\n\t$$(RULE_$(2)_to_$(TGT))\n' \ - '\n$(TGT)_OBJS += $$(BIN)/$(3).$(TGT)\n' ) ) \ - '\n$(BIN)/deps/$(1).d : $$($(3)_DEPS)\n' \ - '\nTAGS : $$($(3)_DEPS)\n' > $(BIN)/rules/$(1).r - @$(if $(findstring drivers/,$(1)),\ - $(PERL) $(PARSEROM) $(1) >> $(BIN)/rules/$(1).r) + @$(ECHO_E) '$(subst $(NEWLINE),\n,$(call rules_template,$(1)))' \ + > $(BIN)/rules/$(1).r endef -# Rule to generate the dependency list file +# Generate the dependency files # -$(BIN)/deps/%.d : % $(MAKEDEPS) - $(call deps_template,$<,$(subst .,,$(suffix $<)),$(basename $(notdir $<))) +$(BIN)/deps/%.d : % $(MAKEDEPS) $(PARSEROM) + $(call deps_template_file,$<) -# Calculate and include the list of dependency list files +# Calculate list of dependency files # AUTO_DEPS = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS)) +autodeps : + @$(ECHO) $(AUTO_DEPS) +VERYCLEANUP += $(BIN)/deps + +# Include dependency files +# ifdef NEED_DEPS ifneq ($(AUTO_DEPS),) -include $(AUTO_DEPS) endif endif -autodeps : - @$(ECHO) $(AUTO_DEPS) -VERYCLEANUP += $(BIN)/deps -# Rule to generate the rules file +# Generate the rules files # -$(BIN)/rules/%.r : % $(MAKEDEPS) $(PARSEROM) - $(call rules_template,$<,$(subst .,,$(suffix $<)),$(basename $(notdir $<))) +$(BIN)/rules/%.r : % $(MAKEDEPS) + $(call rules_template_file,$<) -# Calculate and include the list of rules files +# Calculate list of rules files # AUTO_RULES = $(patsubst %,$(BIN)/rules/%.r,$(AUTO_SRCS)) -ifdef NEED_DEPS -ifneq ($(AUTO_RULES),) --include $(AUTO_RULES) -endif -endif autorules : @$(ECHO) $(AUTO_RULES) VERYCLEANUP += $(BIN)/rules +# Evaluate rules (or include rules files) +# +ifdef NEED_DEPS +ifneq ($(AUTO_RULES),) +ifneq ($(HAVE_EVAL),) +$(foreach SRC,$(AUTO_SRCS),$(eval $(call rules_template,$(SRC)))) +else +-include $(AUTO_RULES) +endif +endif +endif + # The following variables are created by the rules files # bobjs : @@ -1028,36 +1080,49 @@ AUTO_MEDIA = $(filter-out $(NON_AUTO_MEDIA),$(MEDIA)) automedia : @$(ECHO) $(AUTO_MEDIA) -# media_template : create Makefile rules for specified media +# media_template : create media rules # # $(1) is the media name (e.g. "rom") # define media_template +$$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin + $$(QM)echo " [FINISH] $$@" + $$(Q)$$(CP) $$< $$@ + $$(Q)$$(if $$(PAD_$(1)),$$(PAD_$(1)) $$@) + $$(Q)$$(if $$(FINALISE_$(1)),$$(FINALISE_$(1)) $$@) +endef +# +# $(1) is the media name (e.g. "rom") +# +define media_template_file @$(ECHO) " [MEDIARULES] $(1)" @$(MKDIR) -p $(BIN)/rules/$(dir $(1)) - @$(ECHO_E) '$$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin' \ - '\n\t$$(QM)$(ECHO) " [FINISH] $$@"' \ - '\n\t$$(Q)$$(CP) $$< $$@' \ - '\n\t$$(Q)$$(PAD_$(1))' \ - '\n\t$$(Q)$$(FINALISE_$(1))' \ + @$(ECHO_E) '$(subst $(NEWLINE),\n,$(call media_template,$(1)))' \ > $(BIN)/rules/$(1).media.r endef -# Rule to generate the Makefile rules to be included +# Generate media rules files # $(BIN)/rules/%.media.r : $(MAKEDEPS) - $(call media_template,$*) + $(call media_template_file,$*) -# Calculate and include the list of Makefile rules files +# Calculate list of media rules files # MEDIA_RULES = $(patsubst %,$(BIN)/rules/%.media.r,$(AUTO_MEDIA)) mediarules : @$(ECHO) $(MEDIA_RULES) + +# Evaluate media rules (or include media rules files) +# ifdef NEED_DEPS ifneq ($(MEDIA_RULES),) +ifneq ($(HAVE_EVAL),) +$(foreach MEDIUM,$(AUTO_MEDIA),$(eval $(call media_template,$(MEDIUM)))) +else -include $(MEDIA_RULES) endif endif +endif # Wrap up binary blobs (for embedded images) # diff --git a/src/arch/i386/Makefile.pcbios b/src/arch/i386/Makefile.pcbios index e1b226f5..35790069 100644 --- a/src/arch/i386/Makefile.pcbios +++ b/src/arch/i386/Makefile.pcbios @@ -29,15 +29,15 @@ MEDIA += exe # Padding rules # -PAD_rom = $(PERL) $(PADIMG) --blksize=512 --byte=0xff $@ +PAD_rom = $(PERL) $(PADIMG) --blksize=512 --byte=0xff PAD_mrom = $(PAD_rom) -PAD_dsk = $(PERL) $(PADIMG) --blksize=512 $@ -PAD_hd = $(PERL) $(PADIMG) --blksize=32768 $@ -PAD_exe = $(PERL) $(PADIMG) --blksize=512 $@ +PAD_dsk = $(PERL) $(PADIMG) --blksize=512 +PAD_hd = $(PERL) $(PADIMG) --blksize=32768 +PAD_exe = $(PERL) $(PADIMG) --blksize=512 # Finalisation rules # -FINALISE_rom = $(PERL) $(FIXROM) $@ +FINALISE_rom = $(PERL) $(FIXROM) FINALISE_mrom = $(FINALISE_rom) # rule to make a non-emulation ISO boot image From 9df238a8aa1c6074f98280d9dfa08c4ea7e1ff86 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Tue, 14 May 2013 14:06:25 +0100 Subject: [PATCH 35/45] [romprefix] Fix incorrect pointer offset in undiloader.S Commit 2422647 ("[prefix] Allow prefix to specify an arbitrary maximum address for relocation") introduced a regression into the UNDI ROM loader by preserving an extra register on the stack without modifying the %sp-relative addresses used in the routine. Fix by correcting the %sp-relative addresses to allow for the extra preserved variable. Signed-off-by: Frediano Ziglio Signed-off-by: Michael Brown --- src/arch/i386/prefix/undiloader.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/i386/prefix/undiloader.S b/src/arch/i386/prefix/undiloader.S index ccdd816e..74bb5904 100644 --- a/src/arch/i386/prefix/undiloader.S +++ b/src/arch/i386/prefix/undiloader.S @@ -23,8 +23,8 @@ undiloader: popw %ds /* UNDI loader parameter structure address into %es:%di */ movw %sp, %bx - movw %ss:18(%bx), %di - movw %ss:20(%bx), %es + movw %ss:22(%bx), %di + movw %ss:24(%bx), %es /* Install to specified real-mode addresses */ pushw %di movw %es:12(%di), %bx From 640ab792a41f20b468aafae7576e756adc50e9cb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 14 May 2013 16:18:44 +0100 Subject: [PATCH 36/45] [build] Provide "allXXXs" targets for all media on all platforms Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 20 ++++++++++++-------- src/arch/i386/Makefile.pcbios | 7 +++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 00646047..b4023ac6 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -1085,6 +1085,16 @@ automedia : # $(1) is the media name (e.g. "rom") # define media_template +$(if $(filter $(1),$(AUTO_MEDIA)),$(call auto_media_template,$(1))) +$$(BIN)/all$(1)s : $$(foreach DRIVER,$$(DRIVERS),$$(BIN)/$$(DRIVER).$(1)) +$$(BIN)/allall : $$(BIN)/all$(1)s +all$(1)s : $$(BIN)/all$(1)s +allall : $$(BIN)/allall +endef +# +# $(1) is the media name (e.g. "rom") +# +define auto_media_template $$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin $$(QM)echo " [FINISH] $$@" $$(Q)$$(CP) $$< $$@ @@ -1108,7 +1118,7 @@ $(BIN)/rules/%.media.r : $(MAKEDEPS) # Calculate list of media rules files # -MEDIA_RULES = $(patsubst %,$(BIN)/rules/%.media.r,$(AUTO_MEDIA)) +MEDIA_RULES = $(patsubst %,$(BIN)/rules/%.media.r,$(MEDIA)) mediarules : @$(ECHO) $(MEDIA_RULES) @@ -1117,7 +1127,7 @@ mediarules : ifdef NEED_DEPS ifneq ($(MEDIA_RULES),) ifneq ($(HAVE_EVAL),) -$(foreach MEDIUM,$(AUTO_MEDIA),$(eval $(call media_template,$(MEDIUM)))) +$(foreach MEDIUM,$(MEDIA),$(eval $(call media_template,$(MEDIUM)))) else -include $(MEDIA_RULES) endif @@ -1133,12 +1143,6 @@ $(BIN)/%.o : payload/%.img BOBJS += $(patsubst payload/%.img,$(BIN)/%.o,$(wildcard payload/*.img)) -# The "allXXXs" targets for each suffix -# -allall: allroms allmroms allpxes allisos alldsks -allroms allmroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%) -allpxes allisos alldsks : all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%) - # Alias for ipxe.% # $(BIN)/etherboot.% : $(BIN)/ipxe.% diff --git a/src/arch/i386/Makefile.pcbios b/src/arch/i386/Makefile.pcbios index 35790069..32800cde 100644 --- a/src/arch/i386/Makefile.pcbios +++ b/src/arch/i386/Makefile.pcbios @@ -40,6 +40,13 @@ PAD_exe = $(PERL) $(PADIMG) --blksize=512 FINALISE_rom = $(PERL) $(FIXROM) FINALISE_mrom = $(FINALISE_rom) +# Add per-ROM targets for "allroms" +# +$(BIN)/allroms : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).rom) +$(BIN)/allmroms : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).mrom) +allroms : $(BIN)/allroms +allmroms : $(BIN)/allmroms + # rule to make a non-emulation ISO boot image NON_AUTO_MEDIA += iso %iso: %lkrn util/geniso From dbea47ce7d61f253b58aa7268b0261922a6b1a22 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 14 May 2013 20:08:26 +0100 Subject: [PATCH 37/45] [build] Add efidrv.cab target for UEFI Secure Boot signing Signed-off-by: Michael Brown --- src/Makefile | 1 + src/Makefile.housekeeping | 4 +++- src/arch/i386/Makefile.pcbios | 8 +++----- src/arch/x86/Makefile.efi | 10 ++++++++++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Makefile b/src/Makefile index 207369a9..c6f090d9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,6 +49,7 @@ ICCFIX := ./util/iccfix EINFO := ./util/einfo GENKEYMAP := ./util/genkeymap.pl DOXYGEN := doxygen +LCAB := lcab BINUTILS_DIR := /usr BFD_DIR := $(BINUTILS_DIR) ZLIB_DIR := /usr diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index b4023ac6..80b70f5c 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -1086,7 +1086,9 @@ automedia : # define media_template $(if $(filter $(1),$(AUTO_MEDIA)),$(call auto_media_template,$(1))) -$$(BIN)/all$(1)s : $$(foreach DRIVER,$$(DRIVERS),$$(BIN)/$$(DRIVER).$(1)) +LIST_$(1) := $$(if $$(LIST_NAME_$(1)),$$($$(LIST_NAME_$(1))),$$(DRIVERS)) +ALL_$(1) = $$(foreach ITEM,$$(LIST_$(1)),$$(BIN)/$$(ITEM).$(1)) +$$(BIN)/all$(1)s : $$(ALL_$(1)) $$(BIN)/allall : $$(BIN)/all$(1)s all$(1)s : $$(BIN)/all$(1)s allall : $$(BIN)/allall diff --git a/src/arch/i386/Makefile.pcbios b/src/arch/i386/Makefile.pcbios index 32800cde..d3fe8b9e 100644 --- a/src/arch/i386/Makefile.pcbios +++ b/src/arch/i386/Makefile.pcbios @@ -40,12 +40,10 @@ PAD_exe = $(PERL) $(PADIMG) --blksize=512 FINALISE_rom = $(PERL) $(FIXROM) FINALISE_mrom = $(FINALISE_rom) -# Add per-ROM targets for "allroms" +# Use $(ROMS) rather than $(DRIVERS) for "allroms" and "allmroms" # -$(BIN)/allroms : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).rom) -$(BIN)/allmroms : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).mrom) -allroms : $(BIN)/allroms -allmroms : $(BIN)/allmroms +LIST_NAME_rom := ROMS +LIST_NAME_mrom := ROMS # rule to make a non-emulation ISO boot image NON_AUTO_MEDIA += iso diff --git a/src/arch/x86/Makefile.efi b/src/arch/x86/Makefile.efi index bef8d59d..3e3fbe3c 100644 --- a/src/arch/x86/Makefile.efi +++ b/src/arch/x86/Makefile.efi @@ -12,6 +12,8 @@ LDFLAGS += -q -S # NON_AUTO_MEDIA += efi NON_AUTO_MEDIA += efidrv +NON_AUTO_MEDIA += drv.efi +NON_AUTO_MEDIA += efirom # Rules for building EFI files # @@ -23,6 +25,14 @@ $(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI) $(QM)$(ECHO) " [FINISH] $@" $(Q)$(ELF2EFI) --subsystem=11 $< $@ +$(BIN)/%.drv.efi : $(BIN)/%.efidrv + $(QM)$(ECHO) " [FINISH] $@" + $(Q)$(CP) $< $@ + $(BIN)/%.efirom : $(BIN)/%.efidrv $(EFIROM) $(QM)$(ECHO) " [FINISH] $@" $(Q)$(EFIROM) -v $(TGT_PCI_VENDOR) -d $(TGT_PCI_DEVICE) $< $@ + +$(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined + $(QM)$(ECHO) " [CAB] $@" + $(Q)$(LCAB) -n -q $(ALL_drv.efi) $@ From 08bf79582a281d303842ee11951033d2c532f1f3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 16 May 2013 15:32:17 +0100 Subject: [PATCH 38/45] [netdevice] Add "chip" setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Robin Smidsrød Signed-off-by: Michael Brown --- src/net/netdev_settings.c | 157 +++++++++++++++++++++++++++++++------- 1 file changed, 131 insertions(+), 26 deletions(-) diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 8758e980..8f66c553 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -45,6 +45,113 @@ struct setting busid_setting __setting ( SETTING_NETDEV ) = { .description = "Bus ID", .type = &setting_type_hex, }; +struct setting chip_setting __setting ( SETTING_NETDEV ) = { + .name = "chip", + .description = "Chip", + .type = &setting_type_string, +}; + +/** + * Store MAC address setting + * + * @v netdev Network device + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ +static int netdev_store_mac ( struct net_device *netdev, + const void *data, size_t len ) { + + if ( len != netdev->ll_protocol->ll_addr_len ) + return -EINVAL; + memcpy ( netdev->ll_addr, data, len ); + return 0; +} + +/** + * Fetch MAC address setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_mac ( struct net_device *netdev, void *data, + size_t len ) { + + if ( len > netdev->ll_protocol->ll_addr_len ) + len = netdev->ll_protocol->ll_addr_len; + memcpy ( data, netdev->ll_addr, len ); + return netdev->ll_protocol->ll_addr_len; +} + +/** + * Fetch bus ID setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_busid ( struct net_device *netdev, void *data, + size_t len ) { + struct device_description *desc = &netdev->dev->desc; + struct dhcp_netdev_desc dhcp_desc; + + dhcp_desc.type = desc->bus_type; + dhcp_desc.vendor = htons ( desc->vendor ); + dhcp_desc.device = htons ( desc->device ); + if ( len > sizeof ( dhcp_desc ) ) + len = sizeof ( dhcp_desc ); + memcpy ( data, &dhcp_desc, len ); + return sizeof ( dhcp_desc ); +} + +/** + * Fetch chip setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_chip ( struct net_device *netdev, void *data, + size_t len ) { + const char *chip = netdev->dev->driver_name; + + strncpy ( data, chip, len ); + return strlen ( chip ); +} + +/** A network device setting operation */ +struct netdev_setting_operation { + /** Setting */ + struct setting *setting; + /** Store setting (or NULL if not supported) + * + * @v netdev Network device + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ + int ( * store ) ( struct net_device *netdev, const void *data, + size_t len ); + /** Fetch setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ + int ( * fetch ) ( struct net_device *netdev, void *data, size_t len ); +}; + +/** Network device settings */ +static struct netdev_setting_operation netdev_setting_operations[] = { + { &mac_setting, netdev_store_mac, netdev_fetch_mac }, + { &busid_setting, NULL, netdev_fetch_busid }, + { &chip_setting, NULL, netdev_fetch_chip }, +}; /** * Store value of network device setting @@ -59,15 +166,21 @@ static int netdev_store ( struct settings *settings, struct setting *setting, const void *data, size_t len ) { struct net_device *netdev = container_of ( settings, struct net_device, settings.settings ); + struct netdev_setting_operation *op; + unsigned int i; - if ( setting_cmp ( setting, &mac_setting ) == 0 ) { - if ( len != netdev->ll_protocol->ll_addr_len ) - return -EINVAL; - memcpy ( netdev->ll_addr, data, len ); - return 0; + /* Handle network device-specific settings */ + for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) / + sizeof ( netdev_setting_operations[0] ) ) ; i++ ) { + op = &netdev_setting_operations[i]; + if ( setting_cmp ( setting, op->setting ) == 0 ) { + if ( op->store ) { + return op->store ( netdev, data, len ); + } else { + return -ENOTSUP; + } + } } - if ( setting_cmp ( setting, &busid_setting ) == 0 ) - return -ENOTSUP; return generic_settings_store ( settings, setting, data, len ); } @@ -77,31 +190,23 @@ static int netdev_store ( struct settings *settings, struct setting *setting, * * @v settings Settings block * @v setting Setting to fetch - * @v data Setting data, or NULL to clear setting - * @v len Length of setting data - * @ret rc Return status code + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error */ static int netdev_fetch ( struct settings *settings, struct setting *setting, void *data, size_t len ) { struct net_device *netdev = container_of ( settings, struct net_device, settings.settings ); - struct device_description *desc = &netdev->dev->desc; - struct dhcp_netdev_desc dhcp_desc; + struct netdev_setting_operation *op; + unsigned int i; - if ( setting_cmp ( setting, &mac_setting ) == 0 ) { - if ( len > netdev->ll_protocol->ll_addr_len ) - len = netdev->ll_protocol->ll_addr_len; - memcpy ( data, netdev->ll_addr, len ); - return netdev->ll_protocol->ll_addr_len; - } - if ( setting_cmp ( setting, &busid_setting ) == 0 ) { - dhcp_desc.type = desc->bus_type; - dhcp_desc.vendor = htons ( desc->vendor ); - dhcp_desc.device = htons ( desc->device ); - if ( len > sizeof ( dhcp_desc ) ) - len = sizeof ( dhcp_desc ); - memcpy ( data, &dhcp_desc, len ); - return sizeof ( dhcp_desc ); + /* Handle network device-specific settings */ + for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) / + sizeof ( netdev_setting_operations[0] ) ) ; i++ ) { + op = &netdev_setting_operations[i]; + if ( setting_cmp ( setting, op->setting ) == 0 ) + return op->fetch ( netdev, data, len ); } return generic_settings_fetch ( settings, setting, data, len ); From c4bce43c3c4d3c5ebb2d926b58ad16dc9642c19d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 16 May 2013 15:40:44 +0100 Subject: [PATCH 39/45] [netdevice] Reset MAC address when asked to clear the "mac" setting Signed-off-by: Michael Brown --- src/net/netdev_settings.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 8f66c553..028a62ca 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -61,10 +61,18 @@ struct setting chip_setting __setting ( SETTING_NETDEV ) = { */ static int netdev_store_mac ( struct net_device *netdev, const void *data, size_t len ) { + struct ll_protocol *ll_protocol = netdev->ll_protocol; + + /* Record new MAC address */ + if ( data ) { + if ( len != netdev->ll_protocol->ll_addr_len ) + return -EINVAL; + memcpy ( netdev->ll_addr, data, len ); + } else { + /* Reset MAC address if clearing setting */ + ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr ); + } - if ( len != netdev->ll_protocol->ll_addr_len ) - return -EINVAL; - memcpy ( netdev->ll_addr, data, len ); return 0; } From 5d3d62d8d72bfd84122fb89e1ee5f9e4c65f46c7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 26 May 2013 18:26:48 +0100 Subject: [PATCH 40/45] [realtek] Fix reopening of legacy-mode 8139 NIC realtek_destroy_ring() currently does nothing if the card is operating in legacy (pre-RTL8139C+) mode. In particular, the producer and consumer counters are incorrectly left holding their current values. Virtual hardware (e.g. the emulated RTL8139 in qemu and similar VMs) is tolerant of this behaviour, but real hardware will fail to transmit if the descriptors are not used in the correct order. Fix by resetting the producer and consumer counters in realtek_destroy_ring() even if the card is operating in legacy mode. Reported-by: Gelip Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 1fd3931b..498c233f 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -549,7 +549,11 @@ static int realtek_create_ring ( struct realtek_nic *rtl, static void realtek_destroy_ring ( struct realtek_nic *rtl, struct realtek_ring *ring ) { - /* Do nothing in legacy mode */ + /* Reset producer and consumer counters */ + ring->prod = 0; + ring->cons = 0; + + /* Do nothing more if in legacy mode */ if ( rtl->legacy ) return; @@ -560,8 +564,6 @@ static void realtek_destroy_ring ( struct realtek_nic *rtl, /* Free descriptor ring */ free_dma ( ring->desc, ring->len ); ring->desc = NULL; - ring->prod = 0; - ring->cons = 0; } /** From 0036fdd5c5a232662d07c6d1310241f4c5b6ab83 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 29 May 2013 16:41:58 +0100 Subject: [PATCH 41/45] [crypto] Accept OCSP responses containing multiple certificates RFC2560 mandates that a valid OCSP response will contain exactly one relevant certificate. However, some OCSP responders include extraneous certificates. iPXE currently assumes that the first certificate in the OCSP response is the relevant certificate; OCSP checks will therefore fail if the responder includes the extraneous certificates before the relevant certificate. Fix by using the responder ID to identify the relevant certificate. Reported-by: Christian Stroehmeier Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 147 ++++++++++++++++++++++++++++++++++++---- src/include/ipxe/ocsp.h | 19 ++++++ 2 files changed, 152 insertions(+), 14 deletions(-) diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index 185605b4..20287c0b 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -58,6 +58,21 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_EACCES_STALE \ __einfo_uniqify ( EINFO_EACCES, 0x04, \ "Stale (or premature) OCSP repsonse" ) +#define EACCES_NO_RESPONDER \ + __einfo_error ( EINFO_EACCES_NO_RESPONDER ) +#define EINFO_EACCES_NO_RESPONDER \ + __einfo_uniqify ( EINFO_EACCES, 0x05, \ + "Missing OCSP responder certificate" ) +#define ENOTSUP_RESPONSE_TYPE \ + __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE ) +#define EINFO_ENOTSUP_RESPONSE_TYPE \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ + "Unsupported OCSP response type" ) +#define ENOTSUP_RESPONDER_ID \ + __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID ) +#define EINFO_ENOTSUP_RESPONDER_ID \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \ + "Unsupported OCSP responder ID" ) #define EPROTO_MALFORMED_REQUEST \ __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST ) #define EINFO_EPROTO_MALFORMED_REQUEST \ @@ -355,12 +370,94 @@ static int ocsp_parse_response_type ( struct ocsp_check *ocsp, DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n", ocsp, ocsp->cert->subject.name ); DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return -ENOTSUP; + return -ENOTSUP_RESPONSE_TYPE; } return 0; } +/** + * Compare responder's certificate name + * + * @v ocsp OCSP check + * @v cert Certificate + * @ret difference Difference as returned by memcmp() + */ +static int ocsp_compare_responder_name ( struct ocsp_check *ocsp, + struct x509_certificate *cert ) { + struct ocsp_responder *responder = &ocsp->response.responder; + + /* Compare responder ID with certificate's subject */ + return asn1_compare ( &responder->id, &cert->subject.raw ); +} + +/** + * Compare responder's certificate public key hash + * + * @v ocsp OCSP check + * @v cert Certificate + * @ret difference Difference as returned by memcmp() + */ +static int ocsp_compare_responder_key_hash ( struct ocsp_check *ocsp, + struct x509_certificate *cert ) { + struct ocsp_responder *responder = &ocsp->response.responder; + uint8_t ctx[SHA1_CTX_SIZE]; + uint8_t digest[SHA1_DIGEST_SIZE]; + int difference; + + /* Sanity check */ + difference = ( sizeof ( digest ) - responder->id.len ); + if ( difference ) + return difference; + + /* Generate SHA1 hash of certificate's public key */ + digest_init ( &sha1_algorithm, ctx ); + digest_update ( &sha1_algorithm, ctx, + cert->subject.public_key.raw_bits.data, + cert->subject.public_key.raw_bits.len ); + digest_final ( &sha1_algorithm, ctx, digest ); + + /* Compare responder ID with SHA1 hash of certificate's public key */ + return memcmp ( digest, responder->id.data, sizeof ( digest ) ); +} + +/** + * Parse OCSP responder ID + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_responder_id ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct ocsp_responder *responder = &ocsp->response.responder; + struct asn1_cursor *responder_id = &responder->id; + unsigned int type; + + /* Enter responder ID */ + memcpy ( responder_id, raw, sizeof ( *responder_id ) ); + type = asn1_type ( responder_id ); + asn1_enter_any ( responder_id ); + + /* Identify responder ID type */ + switch ( type ) { + case ASN1_EXPLICIT_TAG ( 1 ) : + DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n", + ocsp, ocsp->cert->subject.name ); + responder->compare = ocsp_compare_responder_name; + return 0; + case ASN1_EXPLICIT_TAG ( 2 ) : + DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key " + "hash\n", ocsp, ocsp->cert->subject.name ); + responder->compare = ocsp_compare_responder_key_hash; + return 0; + default: + DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type " + "%d\n", ocsp, ocsp->cert->subject.name, type ); + return -ENOTSUP_RESPONDER_ID; + } +} + /** * Parse OCSP certificate ID * @@ -484,7 +581,9 @@ static int ocsp_parse_tbs_response_data ( struct ocsp_check *ocsp, /* Skip version, if present */ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - /* Skip responderID */ + /* Parse responderID */ + if ( ( rc = ocsp_parse_responder_id ( ocsp, &cursor ) ) != 0 ) + return rc; asn1_skip_any ( &cursor ); /* Skip producedAt */ @@ -508,6 +607,7 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp, const struct asn1_cursor *raw ) { struct ocsp_response *response = &ocsp->response; struct asn1_cursor cursor; + struct x509_certificate *cert; int rc; /* Enter certs */ @@ -519,20 +619,39 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp, * multiple certificates, but the protocol requires that the * OCSP signing certificate must either be the issuer itself, * or must be directly issued by the issuer (see RFC2560 - * section 4.2.2.2 "Authorized Responders"). + * section 4.2.2.2 "Authorized Responders"). We therefore + * need to identify only the single certificate matching the + * Responder ID. */ - if ( ( cursor.len != 0 ) && - ( ( rc = x509_certificate ( cursor.data, cursor.len, - &response->signer ) ) != 0 ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not parse certificate: " - "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return rc; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by \"%s\"\n", ocsp, - ocsp->cert->subject.name, response->signer->subject.name ); + while ( cursor.len ) { - return 0; + /* Parse certificate */ + if ( ( rc = x509_certificate ( cursor.data, cursor.len, + &cert ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not parse " + "certificate: %s\n", ocsp, + ocsp->cert->subject.name, strerror ( rc ) ); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return rc; + } + + /* Use if this certificate matches the responder ID */ + if ( response->responder.compare ( ocsp, cert ) == 0 ) { + response->signer = cert; + DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by " + "\"%s\"\n", ocsp, ocsp->cert->subject.name, + response->signer->subject.name ); + return 0; + } + + /* Otherwise, discard this certificate */ + x509_put ( cert ); + asn1_skip_any ( &cursor ); + } + + DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n", + ocsp, ocsp->cert->subject.name ); + return -EACCES_NO_RESPONDER; } /** diff --git a/src/include/ipxe/ocsp.h b/src/include/ipxe/ocsp.h index fe825fd0..387e28f8 100644 --- a/src/include/ipxe/ocsp.h +++ b/src/include/ipxe/ocsp.h @@ -28,6 +28,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define OCSP_STATUS_SIG_REQUIRED 0x05 #define OCSP_STATUS_UNAUTHORIZED 0x06 +struct ocsp_check; + /** An OCSP request */ struct ocsp_request { /** Request builder */ @@ -36,12 +38,29 @@ struct ocsp_request { struct asn1_cursor cert_id; }; +/** An OCSP responder */ +struct ocsp_responder { + /** + * Check if certificate is the responder's certificate + * + * @v ocsp OCSP check + * @v cert Certificate + * @ret difference Difference as returned by memcmp() + */ + int ( * compare ) ( struct ocsp_check *ocsp, + struct x509_certificate *cert ); + /** Responder ID */ + struct asn1_cursor id; +}; + /** An OCSP response */ struct ocsp_response { /** Raw response */ void *data; /** Raw tbsResponseData */ struct asn1_cursor tbs; + /** Responder */ + struct ocsp_responder responder; /** Time at which status is known to be correct */ time_t this_update; /** Time at which newer status information will be available */ From c825a9b39dddcdc8e403435f9984ef8be11967bc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 5 Jun 2013 14:01:40 +0100 Subject: [PATCH 42/45] [bzimage] Align initrd images to page boundary Some versions of Linux apparently complain if initrds are not aligned to a page boundary. Fix by changing INITRD_ALIGN from 4 bytes to 4096 bytes. The amount of padding at the end of each initrd will now often be sufficient to allow the cpio header to be prepended without crossing an alignment boundary. The final location of the initrd may therefore end up being slightly higher than the post-shuffle location. bzimage_load_initrd() must therefore now copy the initrd body prior to copying the cpio header, otherwise the start of the initrd body may be overwritten by the cpio header. (Note that the guarantee that an initrd will never need to overwrite an initrd at a higher location still holds, since the overall length of each initrd cannot decrease as a result of adding a cpio header.) Reported-by: Dave Hansen Signed-off-by: Michael Brown --- src/arch/i386/image/bzimage.c | 30 +++++++++++++----------------- src/arch/i386/include/initrd.h | 5 +++-- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 12be1779..3b484b17 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -360,7 +360,7 @@ static size_t bzimage_load_initrd ( struct image *image, char *filename = initrd->cmdline; char *cmdline; struct cpio_header cpio; - size_t offset = 0; + size_t offset; size_t name_len; size_t pad_len; @@ -368,7 +368,7 @@ static size_t bzimage_load_initrd ( struct image *image, if ( initrd == image ) return 0; - /* Create cpio header before non-prebuilt images */ + /* Create cpio header for non-prebuilt images */ if ( filename && filename[0] ) { cmdline = strchr ( filename, ' ' ); name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) @@ -383,24 +383,20 @@ static size_t bzimage_load_initrd ( struct image *image, bzimage_parse_cpio_cmdline ( image, &cpio, ( cmdline + 1 /* ' ' */ )); } - if ( address ) { - copy_to_user ( address, offset, &cpio, - sizeof ( cpio ) ); - } - offset += sizeof ( cpio ); - if ( address ) { - memset_user ( address, offset, 0, name_len ); - copy_to_user ( address, offset, filename, - ( name_len - 1 /* NUL (or space) */ ) ); - } - offset += name_len; - offset = ( ( offset + 0x03 ) & ~0x03 ); + offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 ); + } else { + offset = 0; } - /* Copy in initrd image body */ - if ( address ) - memmove_user ( address, offset, initrd->data, 0, initrd->len ); + /* Copy in initrd image body (and cpio header if applicable) */ if ( address ) { + memmove_user ( address, offset, initrd->data, 0, initrd->len ); + if ( offset ) { + memset_user ( address, 0, 0, offset ); + copy_to_user ( address, 0, &cpio, sizeof ( cpio ) ); + copy_to_user ( address, sizeof ( cpio ), filename, + ( name_len - 1 /* NUL (or space) */ ) ); + } DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)" "%s%s\n", image, initrd, user_to_phys ( address, 0 ), user_to_phys ( address, offset ), diff --git a/src/arch/i386/include/initrd.h b/src/arch/i386/include/initrd.h index c25d0924..a5659f43 100644 --- a/src/arch/i386/include/initrd.h +++ b/src/arch/i386/include/initrd.h @@ -13,9 +13,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Minimum alignment for initrds * - * Chosen to maximise memcpy() speeds + * Some versions of Linux complain about initrds that are not + * page-aligned. */ -#define INITRD_ALIGN 4 +#define INITRD_ALIGN 4096 /** Minimum free space required to reshuffle initrds * From e3dd10edc4916da53fc257f172ba85bbe2f85fa0 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 5 Jun 2013 15:54:42 +0100 Subject: [PATCH 43/45] [bzimage] Fix spurious uninitialised-variable warning on some gcc versions Reported-by: Matthew Helton Signed-off-by: Michael Brown --- src/arch/i386/image/bzimage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 3b484b17..0618dbf4 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -386,6 +386,7 @@ static size_t bzimage_load_initrd ( struct image *image, offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 ); } else { offset = 0; + name_len = 0; } /* Copy in initrd image body (and cpio header if applicable) */ From 238050dfd46e3c4a87329da1d48b4d8dde5af8a1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 7 Jun 2013 13:46:27 +0100 Subject: [PATCH 44/45] [build] Work around bug in gcc >= 4.8 gcc 4.8 and 4.9 fail to compile pxe_call.c with the error "bp cannot be used in asm here". Other points in the codebase which use "ebp" in the asm clobber list do not seem to be affected. Unfortunately gcc provides no way to specify %ebp as an output register, so we cannot use this as a workaround. The only viable solution is to explicitly push/pop %ebp within the asm itself. This is ugly for two reasons: firstly, it may be unnecessary; secondly, it may cause gcc to generate invalid %esp-relative addresses if the asm happens to use memory operands. This specific block of asm uses no memory operands and so will not generate invalid code. Reported-by: Daniel P. Berrange Reported-by: Christian Hesse Originally-fixed-by: Christian Hesse Signed-off-by: Michael Brown --- src/arch/i386/interface/pxe/pxe_call.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c index 7fce75a9..a0743336 100644 --- a/src/arch/i386/interface/pxe/pxe_call.c +++ b/src/arch/i386/interface/pxe/pxe_call.c @@ -271,12 +271,14 @@ int pxe_start_nbp ( void ) { DBG ( "Restarting NBP (%x)\n", jmp ); /* Far call to PXE NBP */ - __asm__ __volatile__ ( REAL_CODE ( "movw %%cx, %%es\n\t" + __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */ + "movw %%cx, %%es\n\t" "pushw %%es\n\t" "pushw %%di\n\t" "sti\n\t" "lcall $0, $0x7c00\n\t" - "addw $4, %%sp\n\t" ) + "popl %%ebp\n\t" /* discard */ + "popl %%ebp\n\t" /* gcc bug */ ) : "=a" ( status ), "=b" ( discard_b ), "=c" ( discard_c ), "=d" ( discard_d ), "=D" ( discard_D ) @@ -284,7 +286,7 @@ int pxe_start_nbp ( void ) { "c" ( rm_cs ), "d" ( virt_to_phys ( &pxenv ) ), "D" ( __from_text16 ( &ppxe ) ) - : "esi", "ebp", "memory" ); + : "esi", "memory" ); if ( status ) return -EPXENBP ( status ); From 936134ed460618e18cc05d677a442d43d5e739a1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 24 Jun 2013 16:14:36 +0100 Subject: [PATCH 45/45] [autoboot] Use next-server from filename's settings block Locate the settings block containing the filename, and search only that settings block for the next-server address. This avoids problems caused by misconfigured DHCP servers which provide a next-server address (often defaulting to the DHCP server's own IP address) even when not providing a filename. Originally-implemented-by: Alex Williamson Signed-off-by: Michael Brown --- src/usr/autoboot.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index b2d288ea..70f883a5 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -251,31 +251,42 @@ static void close_all_netdevs ( void ) { * @ret uri URI, or NULL on failure */ struct uri * fetch_next_server_and_filename ( struct settings *settings ) { - struct in_addr next_server; - char buf[256]; + struct in_addr next_server = { 0 }; + char *raw_filename = NULL; + struct uri *uri = NULL; char *filename; - struct uri *uri; - /* Fetch next-server setting */ - fetch_ipv4_setting ( settings, &next_server_setting, &next_server ); - if ( next_server.s_addr ) - printf ( "Next server: %s\n", inet_ntoa ( next_server ) ); + /* Determine settings block containing the filename, if any */ + settings = fetch_setting_origin ( settings, &filename_setting ); - /* Fetch filename setting */ - fetch_string_setting ( settings, &filename_setting, - buf, sizeof ( buf ) ); - if ( buf[0] ) - printf ( "Filename: %s\n", buf ); + /* If we have a filename, fetch it along with next-server */ + if ( settings ) { + fetch_ipv4_setting ( settings, &next_server_setting, + &next_server ); + if ( fetch_string_setting_copy ( settings, &filename_setting, + &raw_filename ) < 0 ) + goto err_fetch; + } /* Expand filename setting */ - filename = expand_settings ( buf ); + filename = expand_settings ( raw_filename ? raw_filename : "" ); if ( ! filename ) - return NULL; + goto err_expand; /* Parse next server and filename */ + if ( next_server.s_addr ) + printf ( "Next server: %s\n", inet_ntoa ( next_server ) ); + if ( filename[0] ) + printf ( "Filename: %s\n", filename ); uri = parse_next_server_and_filename ( next_server, filename ); + if ( ! uri ) + goto err_parse; + err_parse: free ( filename ); + err_expand: + free ( raw_filename ); + err_fetch: return uri; }