iPXE
Data Structures | Functions | Variables
efi_snp.c File Reference
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/netdevice.h>
#include <ipxe/vlan.h>
#include <ipxe/iobuf.h>
#include <ipxe/in.h>
#include <ipxe/version.h>
#include <ipxe/console.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_utils.h>
#include <ipxe/efi/efi_watchdog.h>
#include <ipxe/efi/efi_snp.h>
#include <usr/autoboot.h>
#include <config/general.h>

Go to the source code of this file.

Data Structures

union  PXE_CPB_ANY
 Union type for command parameter blocks. More...
union  PXE_DB_ANY
 Union type for data blocks. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static LIST_HEAD (efi_snp_devices)
 List of SNP devices.
static void efi_snp_set_state (struct efi_snp_device *snpdev)
 Set EFI SNP mode state.
static void efi_snp_set_mode (struct efi_snp_device *snpdev)
 Set EFI SNP mode based on iPXE net device parameters.
static void efi_snp_flush (struct efi_snp_device *snpdev)
 Flush transmit ring and receive queue.
static void efi_snp_poll (struct efi_snp_device *snpdev)
 Poll net device and count received packets.
static EFI_STATUS EFIAPI efi_snp_start (EFI_SIMPLE_NETWORK_PROTOCOL *snp)
 Change SNP state from "stopped" to "started".
static EFI_STATUS EFIAPI efi_snp_stop (EFI_SIMPLE_NETWORK_PROTOCOL *snp)
 Change SNP state from "started" to "stopped".
static EFI_STATUS EFIAPI efi_snp_initialize (EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN extra_rx_bufsize, UINTN extra_tx_bufsize)
 Open the network device.
static EFI_STATUS EFIAPI efi_snp_reset (EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify)
 Reset the network device.
static EFI_STATUS EFIAPI efi_snp_shutdown (EFI_SIMPLE_NETWORK_PROTOCOL *snp)
 Shut down the network device.
static EFI_STATUS EFIAPI efi_snp_receive_filters (EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable, UINT32 disable, BOOLEAN mcast_reset, UINTN mcast_count, EFI_MAC_ADDRESS *mcast)
 Manage receive filters.
static EFI_STATUS EFIAPI efi_snp_station_address (EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, EFI_MAC_ADDRESS *new)
 Set station address.
static EFI_STATUS EFIAPI efi_snp_statistics (EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, UINTN *stats_len, EFI_NETWORK_STATISTICS *stats)
 Get (or reset) statistics.
static EFI_STATUS EFIAPI efi_snp_mcast_ip_to_mac (EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6, EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac)
 Convert multicast IP address to MAC address.
static EFI_STATUS EFIAPI efi_snp_nvdata (EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read, UINTN offset, UINTN len, VOID *data)
 Read or write non-volatile storage.
static EFI_STATUS EFIAPI efi_snp_get_status (EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 *interrupts, VOID **txbuf)
 Read interrupt status and TX recycled buffer status.
static EFI_STATUS EFIAPI efi_snp_transmit (EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN ll_header_len, UINTN len, VOID *data, EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, UINT16 *net_proto)
 Start packet transmission.
static EFI_STATUS EFIAPI efi_snp_receive (EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN *ll_header_len, UINTN *len, VOID *data, EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, UINT16 *net_proto)
 Receive packet.
static VOID EFIAPI efi_snp_wait_for_packet (EFI_EVENT event __unused, VOID *context)
 Poll event.
static uint8_t efi_undi_checksum (void *data, size_t len)
 Calculate UNDI byte checksum.
static unsigned int efi_undi_ifnum (struct efi_snp_device *snpdev)
 Get UNDI SNP device interface number.
static struct efi_snp_deviceefi_undi_snpdev (unsigned int ifnum)
 Identify UNDI SNP device.
static PXE_STATCODE efi_undi_statcode (EFI_STATUS efirc)
 Convert EFI status code to UNDI status code.
static EFI_STATUS efi_undi_get_state (struct efi_snp_device *snpdev, PXE_CDB *cdb)
 Get state.
static EFI_STATUS efi_undi_start (struct efi_snp_device *snpdev)
 Start.
static EFI_STATUS efi_undi_stop (struct efi_snp_device *snpdev)
 Stop.
static EFI_STATUS efi_undi_get_init_info (struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_DB_GET_INIT_INFO *db)
 Get initialisation information.
static EFI_STATUS efi_undi_initialize (struct efi_snp_device *snpdev, PXE_CDB *cdb)
 Initialise.
static EFI_STATUS efi_undi_reset (struct efi_snp_device *snpdev)
 Reset.
static EFI_STATUS efi_undi_shutdown (struct efi_snp_device *snpdev)
 Shutdown.
static EFI_STATUS efi_undi_receive_filters (struct efi_snp_device *snpdev, PXE_CDB *cdb)
 Get/set receive filters.
static EFI_STATUS efi_undi_station_address (struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_CPB_STATION_ADDRESS *cpb, PXE_DB_STATION_ADDRESS *db)
 Get/set station address.
static EFI_STATUS efi_undi_get_status (struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_DB_GET_STATUS *db)
 Get interrupt status.
static EFI_STATUS efi_undi_fill_header (struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_CPB_ANY *cpb)
 Fill header.
static EFI_STATUS efi_undi_transmit (struct efi_snp_device *snpdev, PXE_CPB_TRANSMIT *cpb)
 Transmit.
static EFI_STATUS efi_undi_receive (struct efi_snp_device *snpdev, PXE_CPB_RECEIVE *cpb, PXE_DB_RECEIVE *db)
 Receive.
static EFIAPI VOID efi_undi_issue (UINT64 cdb_phys)
 UNDI entry point.
static EFI_STATUS EFIAPI efi_snp_get_driver_name (EFI_COMPONENT_NAME2_PROTOCOL *name2, CHAR8 *language __unused, CHAR16 **driver_name)
 Look up driver name.
static EFI_STATUS EFIAPI efi_snp_get_controller_name (EFI_COMPONENT_NAME2_PROTOCOL *name2, EFI_HANDLE device __unused, EFI_HANDLE child __unused, CHAR8 *language __unused, CHAR16 **controller_name)
 Look up controller name.
static EFI_STATUS EFIAPI efi_snp_load_file (EFI_LOAD_FILE_PROTOCOL *load_file, EFI_DEVICE_PATH_PROTOCOL *path __unused, BOOLEAN booting, UINTN *len __unused, VOID *data __unused)
 Load file.
static struct efi_snp_deviceefi_snp_demux (struct net_device *netdev)
 Locate SNP device corresponding to network device.
static int efi_snp_probe (struct net_device *netdev)
 Create SNP device.
static void efi_snp_notify (struct net_device *netdev)
 Handle SNP device or link state change.
static void efi_snp_remove (struct net_device *netdev)
 Destroy SNP device.
struct efi_snp_devicefind_snpdev (EFI_HANDLE handle)
 Find SNP device by EFI device handle.
struct efi_snp_devicelast_opened_snpdev (void)
 Get most recently opened SNP device.
void efi_snp_add_claim (int delta)
 Add to SNP claimed/released count.

Variables

static int efi_snp_claimed
 Network devices are currently claimed for use by iPXE.
static EFI_TPL efi_snp_old_tpl
 TPL prior to network devices being claimed.
static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp
 SNP interface.
static PXE_SW_UNDI efi_snp_undi
 UNDI interface.
static
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL 
efi_snp_device_nii
 Network Identification Interface (NII)
static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol
 Load file protocol.
struct net_driver efi_snp_driver __net_driver
 SNP driver.

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static LIST_HEAD ( efi_snp_devices  ) [static]

List of SNP devices.

static void efi_snp_set_state ( struct efi_snp_device snpdev) [static]

Set EFI SNP mode state.

Parameters:
snpSNP interface

Definition at line 89 of file efi_snp.c.

References efi_snp_claimed, EfiSimpleNetworkInitialized, EfiSimpleNetworkStarted, EfiSimpleNetworkStopped, efi_snp_device::mode, efi_snp_device::netdev, netdev, netdev_is_open(), efi_snp_device::started, and EFI_SIMPLE_NETWORK_MODE::State.

Referenced by efi_snp_add_claim(), efi_snp_initialize(), efi_snp_notify(), efi_snp_reset(), efi_snp_shutdown(), efi_snp_start(), and efi_snp_stop().

                                                                {
        struct net_device *netdev = snpdev->netdev;
        EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;

        /* Calculate state */
        if ( ! snpdev->started ) {
                /* Start() method not called; report as Stopped */
                mode->State = EfiSimpleNetworkStopped;
        } else if ( ! netdev_is_open ( netdev ) ) {
                /* Network device not opened; report as Started */
                mode->State = EfiSimpleNetworkStarted;
        } else if ( efi_snp_claimed ) {
                /* Network device opened but claimed for use by iPXE; report
                 * as Started to inhibit receive polling.
                 */
                mode->State = EfiSimpleNetworkStarted;
        } else {
                /* Network device opened and available for use via SNP; report
                 * as Initialized.
                 */
                mode->State = EfiSimpleNetworkInitialized;
        }
}
static void efi_snp_set_mode ( struct efi_snp_device snpdev) [static]

Set EFI SNP mode based on iPXE net device parameters.

Parameters:
snpSNP interface

Definition at line 118 of file efi_snp.c.

References assert, EFI_SIMPLE_NETWORK_MODE::BroadcastAddress, EFI_SIMPLE_NETWORK_MODE::CurrentAddress, EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST, EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, EFI_SIMPLE_NETWORK_RECEIVE_UNICAST, FALSE, net_device::hw_addr, EFI_SIMPLE_NETWORK_MODE::HwAddressSize, EFI_SIMPLE_NETWORK_MODE::IfType, ll_protocol::init_addr, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_broadcast, ll_protocol::ll_header_len, ll_protocol::ll_proto, net_device::ll_protocol, EFI_SIMPLE_NETWORK_MODE::MacAddressChangeable, EFI_SIMPLE_NETWORK_MODE::MaxPacketSize, EFI_SIMPLE_NETWORK_MODE::MediaHeaderSize, EFI_SIMPLE_NETWORK_MODE::MediaPresent, EFI_SIMPLE_NETWORK_MODE::MediaPresentSupported, memcpy(), efi_snp_device::mode, net_device::mtu, efi_snp_device::netdev, netdev, netdev_link_ok(), ntohs, EFI_SIMPLE_NETWORK_MODE::PermanentAddress, EFI_SIMPLE_NETWORK_MODE::ReceiveFilterMask, and TRUE.

Referenced by efi_snp_probe().

                                                               {
        struct net_device *netdev = snpdev->netdev;
        EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        unsigned int ll_addr_len = ll_protocol->ll_addr_len;

        mode->HwAddressSize = ll_addr_len;
        mode->MediaHeaderSize = ll_protocol->ll_header_len;
        mode->MaxPacketSize = netdev->mtu;
        mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
                                    EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
                                    EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
        assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
        memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
        memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
        ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
        mode->IfType = ntohs ( ll_protocol->ll_proto );
        mode->MacAddressChangeable = TRUE;
        mode->MediaPresentSupported = TRUE;
        mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
}
static void efi_snp_flush ( struct efi_snp_device snpdev) [static]

Flush transmit ring and receive queue.

Parameters:
snpdevSNP device

Definition at line 145 of file efi_snp.c.

References free_iob(), io_buffer::list, list_del, list_for_each_entry_safe, efi_snp_device::rx, efi_snp_device::tx_cons, and efi_snp_device::tx_prod.

Referenced by efi_snp_reset(), and efi_snp_shutdown().

                                                            {
        struct io_buffer *iobuf;
        struct io_buffer *tmp;

        /* Reset transmit completion ring */
        snpdev->tx_prod = 0;
        snpdev->tx_cons = 0;

        /* Discard any queued receive buffers */
        list_for_each_entry_safe ( iobuf, tmp, &snpdev->rx, list ) {
                list_del ( &iobuf->list );
                free_iob ( iobuf );
        }
}
static void efi_snp_poll ( struct efi_snp_device snpdev) [static]

Poll net device and count received packets.

Parameters:
snpdevSNP device

Definition at line 165 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT, efi_systab, efi_snp_device::interrupts, io_buffer::list, list_add_tail, efi_snp_device::netdev, netdev_poll(), netdev_rx_dequeue(), efi_snp_device::rx, EFI_BOOT_SERVICES::SignalEvent, efi_snp_device::snp, and _EFI_SIMPLE_NETWORK_PROTOCOL::WaitForPacket.

Referenced by efi_snp_get_status(), efi_snp_receive(), and efi_snp_wait_for_packet().

                                                           {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct io_buffer *iobuf;

        /* Poll network device */
        netdev_poll ( snpdev->netdev );

        /* Retrieve any received packets */
        while ( ( iobuf = netdev_rx_dequeue ( snpdev->netdev ) ) ) {
                list_add_tail ( &iobuf->list, &snpdev->rx );
                snpdev->interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
                bs->SignalEvent ( &snpdev->snp.WaitForPacket );
        }
}

Change SNP state from "stopped" to "started".

Parameters:
snpSNP interface
Return values:
efircEFI status code

Definition at line 187 of file efi_snp.c.

References container_of, DBGC, EFI_NOT_READY, efi_snp_claimed, efi_snp_set_state(), and efi_snp_device::started.

Referenced by efi_undi_start().

                                                   {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );

        DBGC ( snpdev, "SNPDEV %p START\n", snpdev );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        snpdev->started = 1;
        efi_snp_set_state ( snpdev );
        return 0;
}

Change SNP state from "started" to "stopped".

Parameters:
snpSNP interface
Return values:
efircEFI status code

Definition at line 209 of file efi_snp.c.

References container_of, DBGC, EFI_NOT_READY, efi_snp_claimed, efi_snp_set_state(), and efi_snp_device::started.

Referenced by efi_undi_stop().

                                                  {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );

        DBGC ( snpdev, "SNPDEV %p STOP\n", snpdev );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        snpdev->started = 0;
        efi_snp_set_state ( snpdev );

        return 0;
}
static EFI_STATUS EFIAPI efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
UINTN  extra_rx_bufsize,
UINTN  extra_tx_bufsize 
) [static]

Open the network device.

Parameters:
snpSNP interface
extra_rx_bufsizeExtra RX buffer size, in bytes
extra_tx_bufsizeExtra TX buffer size, in bytes
Return values:
efircEFI status code

Definition at line 234 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, container_of, DBGC, EAGAIN, efi_snp_claimed, efi_snp_set_state(), efi_systab, EFIRC, net_device::name, efi_snp_device::netdev, netdev_open(), EFI_BOOT_SERVICES::RaiseTPL, rc, EFI_BOOT_SERVICES::RestoreTPL, strerror(), and TPL_CALLBACK.

Referenced by efi_undi_initialize().

                                                                      {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        EFI_TPL saved_tpl;
        int rc;

        DBGC ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
               snpdev, ( ( unsigned long ) extra_rx_bufsize ),
               ( ( unsigned long ) extra_tx_bufsize ) );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed ) {
                rc = -EAGAIN;
                goto err_claimed;
        }

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Open network device */
        if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
                       snpdev, snpdev->netdev->name, strerror ( rc ) );
                goto err_open;
        }
        efi_snp_set_state ( snpdev );

 err_open:
        bs->RestoreTPL ( saved_tpl );
 err_claimed:
        return EFIRC ( rc );
}
static EFI_STATUS EFIAPI efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
BOOLEAN  ext_verify 
) [static]

Reset the network device.

Parameters:
snpSNP interface
ext_verifyExtended verification required
Return values:
efircEFI status code

Definition at line 277 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, container_of, DBGC, EAGAIN, efi_snp_claimed, efi_snp_flush(), efi_snp_set_state(), efi_systab, EFIRC, net_device::name, efi_snp_device::netdev, netdev_close(), netdev_open(), EFI_BOOT_SERVICES::RaiseTPL, rc, EFI_BOOT_SERVICES::RestoreTPL, strerror(), and TPL_CALLBACK.

Referenced by efi_undi_reset().

                                                                       {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        EFI_TPL saved_tpl;
        int rc;

        DBGC ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
               snpdev, ( ext_verify ? "with" : "without" ) );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed ) {
                rc = -EAGAIN;
                goto err_claimed;
        }

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Close network device */
        netdev_close ( snpdev->netdev );
        efi_snp_set_state ( snpdev );
        efi_snp_flush ( snpdev );

        /* Reopen network device */
        if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
                       snpdev, snpdev->netdev->name, strerror ( rc ) );
                goto err_open;
        }
        efi_snp_set_state ( snpdev );

 err_open:
        bs->RestoreTPL ( saved_tpl );
 err_claimed:
        return EFIRC ( rc );
}

Shut down the network device.

Parameters:
snpSNP interface
Return values:
efircEFI status code

Definition at line 322 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, container_of, DBGC, EFI_NOT_READY, efi_snp_claimed, efi_snp_flush(), efi_snp_set_state(), efi_systab, efi_snp_device::netdev, netdev_close(), EFI_BOOT_SERVICES::RaiseTPL, EFI_BOOT_SERVICES::RestoreTPL, and TPL_CALLBACK.

Referenced by efi_undi_shutdown().

                                                      {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        EFI_TPL saved_tpl;

        DBGC ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Close network device */
        netdev_close ( snpdev->netdev );
        efi_snp_set_state ( snpdev );
        efi_snp_flush ( snpdev );

        /* Restore TPL */
        bs->RestoreTPL ( saved_tpl );

        return 0;
}
static EFI_STATUS EFIAPI efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
UINT32  enable,
UINT32  disable,
BOOLEAN  mcast_reset,
UINTN  mcast_count,
EFI_MAC_ADDRESS mcast 
) [static]

Manage receive filters.

Parameters:
snpSNP interface
enableReceive filters to enable
disableReceive filters to disable
mcast_resetReset multicast filters
mcast_countNumber of multicast filters
mcastMulticast filters
Return values:
efircEFI status code

Definition at line 360 of file efi_snp.c.

References container_of, DBGC, DBGC2_HDA, ll_protocol::ll_addr_len, net_device::ll_protocol, and efi_snp_device::netdev.

                                                                      {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        unsigned int i;

        DBGC ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
               snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
               ( ( unsigned long ) mcast_count ) );
        for ( i = 0 ; i < mcast_count ; i++ ) {
                DBGC2_HDA ( snpdev, i, &mcast[i],
                            snpdev->netdev->ll_protocol->ll_addr_len );
        }

        /* Lie through our teeth, otherwise MNP refuses to accept us.
         *
         * Return success even if the SNP device is currently claimed
         * for use by iPXE, since otherwise Windows Deployment
         * Services refuses to attempt to receive further packets via
         * our EFI PXE Base Code protocol.
         */
        return 0;
}

Set station address.

Parameters:
snpSNP interface
resetReset to permanent address
newNew station address
Return values:
efircEFI status code

Definition at line 394 of file efi_snp.c.

References container_of, DBGC, EFI_NOT_READY, efi_snp_claimed, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, memcpy(), efi_snp_device::mode, efi_snp_device::netdev, netdev_is_open(), ll_protocol::ntoa, and EFI_SIMPLE_NETWORK_MODE::PermanentAddress.

Referenced by efi_undi_station_address().

                                                 {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;

        DBGC ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
               ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        /* Set the MAC address */
        if ( reset )
                new = &snpdev->mode.PermanentAddress;
        memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );

        /* MAC address changes take effect only on netdev_open() */
        if ( netdev_is_open ( snpdev->netdev ) ) {
                DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
                       "device open\n", snpdev );
        }

        return 0;
}
static EFI_STATUS EFIAPI efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
BOOLEAN  reset,
UINTN stats_len,
EFI_NETWORK_STATISTICS stats 
) [static]

Get (or reset) statistics.

Parameters:
snpSNP interface
resetReset statistics
stats_lenSize of statistics table
statsStatistics table
Return values:
efircEFI status code

Definition at line 431 of file efi_snp.c.

References net_device_stats::bad, container_of, DBGC, EFI_NOT_READY, efi_snp_claimed, net_device_stats::good, memcpy(), memset(), efi_snp_device::netdev, net_device::rx_stats, EFI_NETWORK_STATISTICS::RxDroppedFrames, EFI_NETWORK_STATISTICS::RxGoodFrames, EFI_NETWORK_STATISTICS::RxTotalFrames, net_device::tx_stats, EFI_NETWORK_STATISTICS::TxDroppedFrames, EFI_NETWORK_STATISTICS::TxGoodFrames, and EFI_NETWORK_STATISTICS::TxTotalFrames.

                                                                       {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        EFI_NETWORK_STATISTICS stats_buf;

        DBGC ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
               ( reset ? " reset" : "" ) );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        /* Gather statistics */
        memset ( &stats_buf, 0, sizeof ( stats_buf ) );
        stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
        stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
        stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
                                    snpdev->netdev->tx_stats.bad );
        stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
        stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
        stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
                                    snpdev->netdev->rx_stats.bad );
        if ( *stats_len > sizeof ( stats_buf ) )
                *stats_len = sizeof ( stats_buf );
        if ( stats )
                memcpy ( stats, &stats_buf, *stats_len );

        /* Reset statistics if requested to do so */
        if ( reset ) {
                memset ( &snpdev->netdev->tx_stats, 0,
                         sizeof ( snpdev->netdev->tx_stats ) );
                memset ( &snpdev->netdev->rx_stats, 0,
                         sizeof ( snpdev->netdev->rx_stats ) );
        }

        return 0;
}

Convert multicast IP address to MAC address.

Parameters:
snpSNP interface
ipv6Address is IPv6
ipIP address
macMAC address
Return values:
efircEFI status code

Definition at line 480 of file efi_snp.c.

References AF_INET, AF_INET6, container_of, DBGC, EFI_NOT_READY, efi_snp_claimed, EFIRC, inet_ntoa(), net_device::ll_protocol, ll_protocol::mc_hash, efi_snp_device::netdev, rc, and strerror().

                                                                     {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
        const char *ip_str;
        int rc;

        ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
                   inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
        DBGC ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        /* Try to hash the address */
        if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
                                           ip, mac ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
                       snpdev, ip_str, strerror ( rc ) );
                return EFIRC ( rc );
        }

        return 0;
}
static EFI_STATUS EFIAPI efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
BOOLEAN  read,
UINTN  offset,
UINTN  len,
VOID data 
) [static]

Read or write non-volatile storage.

Parameters:
snpSNP interface
readOperation is a read
offsetStarting offset within NVRAM
lenLength of data buffer
dataData buffer
Return values:
efircEFI status code

Definition at line 518 of file efi_snp.c.

References container_of, DBGC, DBGC2_HDA, EFI_NOT_READY, efi_snp_claimed, and EFI_UNSUPPORTED.

                                                       {
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );

        DBGC ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
               ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
               ( ( unsigned long ) len ) );
        if ( ! read )
                DBGC2_HDA ( snpdev, offset, data, len );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return EFI_NOT_READY;

        return EFI_UNSUPPORTED;
}
static EFI_STATUS EFIAPI efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
UINT32 interrupts,
VOID **  txbuf 
) [static]

Read interrupt status and TX recycled buffer status.

Parameters:
snpSNP interface
interruptsInterrupt status, or NULL
txbufRecycled transmit buffer address, or NULL
Return values:
efircEFI status code

Definition at line 545 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, container_of, DBGC2, EFI_NOT_READY, efi_snp_claimed, EFI_SNP_NUM_TX, efi_snp_poll(), efi_systab, efi_snp_device::interrupts, NULL, EFI_BOOT_SERVICES::RaiseTPL, EFI_BOOT_SERVICES::RestoreTPL, TPL_CALLBACK, efi_snp_device::tx, efi_snp_device::tx_cons, and efi_snp_device::tx_prod.

Referenced by efi_undi_get_status().

                                                        {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        EFI_TPL saved_tpl;

        DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed ) {
                DBGC2 ( snpdev, "\n" );
                return EFI_NOT_READY;
        }

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Poll the network device */
        efi_snp_poll ( snpdev );

        /* Interrupt status.  In practice, this seems to be used only
         * to detect TX completions.
         */
        if ( interrupts ) {
                *interrupts = snpdev->interrupts;
                DBGC2 ( snpdev, " INTS:%02x", *interrupts );
                snpdev->interrupts = 0;
        }

        /* TX completions */
        if ( txbuf ) {
                if ( snpdev->tx_prod != snpdev->tx_cons ) {
                        *txbuf = snpdev->tx[snpdev->tx_cons++ % EFI_SNP_NUM_TX];
                } else {
                        *txbuf = NULL;
                }
                DBGC2 ( snpdev, " TX:%p", *txbuf );
        }

        /* Restore TPL */
        bs->RestoreTPL ( saved_tpl );

        DBGC2 ( snpdev, "\n" );
        return 0;
}
static EFI_STATUS EFIAPI efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
UINTN  ll_header_len,
UINTN  len,
VOID data,
EFI_MAC_ADDRESS ll_src,
EFI_MAC_ADDRESS ll_dest,
UINT16 net_proto 
) [static]

Start packet transmission.

Parameters:
snpSNP interface
ll_header_lenLink-layer header length, if to be filled in
lenLength of data buffer
dataData buffer
ll_srcLink-layer source address, if specified
ll_destLink-layer destination address, if specified
net_protoNetwork-layer protocol (in host order)
Return values:
efircEFI status code

Definition at line 605 of file efi_snp.c.

References alloc_iob(), EFI_SYSTEM_TABLE::BootServices, container_of, EFI_SIMPLE_NETWORK_MODE::CurrentAddress, data, DBGC, DBGC2, EAGAIN, EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT, efi_snp_claimed, EFI_SNP_NUM_TX, efi_systab, EFIRC, EINVAL, ENOBUFS, ENOMEM, free_iob(), htons, efi_snp_device::interrupts, iob_disown, iob_pull, iob_put, iob_reserve, IOB_ZLEN, ll_protocol::ll_header_len, net_device::ll_protocol, MAX_LL_HEADER_LEN, memcpy(), efi_snp_device::mode, efi_snp_device::netdev, netdev_tx(), ll_protocol::ntoa, ll_protocol::push, EFI_BOOT_SERVICES::RaiseTPL, rc, EFI_BOOT_SERVICES::RestoreTPL, strerror(), TPL_CALLBACK, efi_snp_device::tx, efi_snp_device::tx_cons, and efi_snp_device::tx_prod.

Referenced by efi_undi_transmit().

                                       {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
        struct io_buffer *iobuf;
        size_t payload_len;
        unsigned int tx_fill;
        EFI_TPL saved_tpl;
        int rc;

        DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
                ( ( unsigned long ) len ) );
        if ( ll_header_len ) {
                if ( ll_src ) {
                        DBGC2 ( snpdev, " src %s",
                                ll_protocol->ntoa ( ll_src ) );
                }
                if ( ll_dest ) {
                        DBGC2 ( snpdev, " dest %s",
                                ll_protocol->ntoa ( ll_dest ) );
                }
                if ( net_proto ) {
                        DBGC2 ( snpdev, " proto %04x", *net_proto );
                }
        }
        DBGC2 ( snpdev, "\n" );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed ) {
                rc = -EAGAIN;
                goto err_claimed;
        }

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Sanity checks */
        if ( ll_header_len ) {
                if ( ll_header_len != ll_protocol->ll_header_len ) {
                        DBGC ( snpdev, "SNPDEV %p TX invalid header length "
                               "%ld\n", snpdev,
                               ( ( unsigned long ) ll_header_len ) );
                        rc = -EINVAL;
                        goto err_sanity;
                }
                if ( len < ll_header_len ) {
                        DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
                               snpdev, ( ( unsigned long ) len ) );
                        rc = -EINVAL;
                        goto err_sanity;
                }
                if ( ! ll_dest ) {
                        DBGC ( snpdev, "SNPDEV %p TX missing destination "
                               "address\n", snpdev );
                        rc = -EINVAL;
                        goto err_sanity;
                }
                if ( ! net_proto ) {
                        DBGC ( snpdev, "SNPDEV %p TX missing network "
                               "protocol\n", snpdev );
                        rc = -EINVAL;
                        goto err_sanity;
                }
                if ( ! ll_src )
                        ll_src = &snpdev->mode.CurrentAddress;
        }

        /* Allocate buffer */
        payload_len = ( len - ll_protocol->ll_header_len );
        iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ?
                                                  payload_len : IOB_ZLEN ) );
        if ( ! iobuf ) {
                DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
                       "buffer\n", snpdev, ( ( unsigned long ) len ) );
                rc = -ENOMEM;
                goto err_alloc_iob;
        }
        iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN -
                               ll_protocol->ll_header_len ) );
        memcpy ( iob_put ( iobuf, len ), data, len );

        /* Create link-layer header, if specified */
        if ( ll_header_len ) {
                iob_pull ( iobuf, ll_protocol->ll_header_len );
                if ( ( rc = ll_protocol->push ( snpdev->netdev,
                                                iobuf, ll_dest, ll_src,
                                                htons ( *net_proto ) )) != 0 ){
                        DBGC ( snpdev, "SNPDEV %p TX could not construct "
                               "header: %s\n", snpdev, strerror ( rc ) );
                        goto err_ll_push;
                }
        }

        /* Transmit packet */
        if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
                DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
                       snpdev, strerror ( rc ) );
                goto err_tx;
        }

        /* Record in transmit completion ring.  If we run out of
         * space, report the failure even though we have already
         * transmitted the packet.
         *
         * This allows us to report completions only for packets for
         * which we had reported successfully initiating transmission,
         * while continuing to support clients that never poll for
         * transmit completions.
         */
        tx_fill = ( snpdev->tx_prod - snpdev->tx_cons );
        if ( tx_fill >= EFI_SNP_NUM_TX ) {
                DBGC ( snpdev, "SNPDEV %p TX completion ring full\n", snpdev );
                rc = -ENOBUFS;
                goto err_ring_full;
        }
        snpdev->tx[ snpdev->tx_prod++ % EFI_SNP_NUM_TX ] = data;
        snpdev->interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;

        /* Restore TPL */
        bs->RestoreTPL ( saved_tpl );

        return 0;

 err_ring_full:
 err_tx:
 err_ll_push:
        free_iob ( iobuf );
 err_alloc_iob:
 err_sanity:
        bs->RestoreTPL ( saved_tpl );
 err_claimed:
        return EFIRC ( rc );
}
static EFI_STATUS EFIAPI efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
UINTN ll_header_len,
UINTN len,
VOID data,
EFI_MAC_ADDRESS ll_src,
EFI_MAC_ADDRESS ll_dest,
UINT16 net_proto 
) [static]

Receive packet.

Parameters:
snpSNP interface
ll_header_lenLink-layer header length, if to be filled in
lenLength of data buffer
dataData buffer
ll_srcLink-layer source address, if specified
ll_destLink-layer destination address, if specified
net_protoNetwork-layer protocol (in host order)
Return values:
efircEFI status code

Definition at line 756 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, container_of, io_buffer::data, DBGC, DBGC2, EAGAIN, efi_snp_claimed, efi_snp_poll(), efi_systab, EFIRC, ERANGE, free_iob(), iob_len(), len, io_buffer::list, list_del, list_first_entry, ll_protocol::ll_addr_len, ll_protocol::ll_header_len, net_device::ll_protocol, memcpy(), efi_snp_device::netdev, ntohs, ll_protocol::pull, EFI_BOOT_SERVICES::RaiseTPL, rc, EFI_BOOT_SERVICES::RestoreTPL, efi_snp_device::rx, strerror(), and TPL_CALLBACK.

Referenced by efi_undi_receive().

                                      {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev =
                container_of ( snp, struct efi_snp_device, snp );
        struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
        struct io_buffer *iobuf;
        const void *iob_ll_dest;
        const void *iob_ll_src;
        uint16_t iob_net_proto;
        unsigned int iob_flags;
        size_t copy_len;
        EFI_TPL saved_tpl;
        int rc;

        DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
                ( ( unsigned long ) *len ) );

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed ) {
                rc = -EAGAIN;
                goto err_claimed;
        }

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Poll the network device */
        efi_snp_poll ( snpdev );

        /* Check for an available packet */
        iobuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
        if ( ! iobuf ) {
                DBGC2 ( snpdev, "\n" );
                rc = -EAGAIN;
                goto out_no_packet;
        }
        DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );

        /* Dequeue packet */
        list_del ( &iobuf->list );

        /* Return packet to caller, truncating to buffer length */
        copy_len = iob_len ( iobuf );
        if ( copy_len > *len )
                copy_len = *len;
        memcpy ( data, iobuf->data, copy_len );
        *len = iob_len ( iobuf );

        /* Attempt to decode link-layer header */
        if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
                                        &iob_ll_src, &iob_net_proto,
                                        &iob_flags ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
                       snpdev, strerror ( rc ) );
                goto out_bad_ll_header;
        }

        /* Return link-layer header parameters to caller, if required */
        if ( ll_header_len )
                *ll_header_len = ll_protocol->ll_header_len;
        if ( ll_src )
                memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
        if ( ll_dest )
                memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
        if ( net_proto )
                *net_proto = ntohs ( iob_net_proto );

        /* Check buffer length */
        rc = ( ( copy_len == *len ) ? 0 : -ERANGE );

 out_bad_ll_header:
        free_iob ( iobuf );
 out_no_packet:
        bs->RestoreTPL ( saved_tpl );
 err_claimed:
        return EFIRC ( rc );
}
static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event  __unused,
VOID context 
) [static]

Poll event.

Parameters:
eventEvent
contextEvent context

Definition at line 843 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, context, DBGCP, efi_snp_claimed, efi_snp_poll(), efi_systab, efi_snp_device::netdev, netdev_is_open(), EFI_BOOT_SERVICES::RaiseTPL, EFI_BOOT_SERVICES::RestoreTPL, and TPL_CALLBACK.

Referenced by efi_snp_probe().

                                                             {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev = context;
        EFI_TPL saved_tpl;

        DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );

        /* Do nothing unless the net device is open */
        if ( ! netdev_is_open ( snpdev->netdev ) )
                return;

        /* Do nothing if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed )
                return;

        /* Raise TPL */
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Poll the network device */
        efi_snp_poll ( snpdev );

        /* Restore TPL */
        bs->RestoreTPL ( saved_tpl );
}
static uint8_t efi_undi_checksum ( void *  data,
size_t  len 
) [static]

Calculate UNDI byte checksum.

Parameters:
dataData
lenLength of data
Return values:
sumChecksum

Definition at line 918 of file efi_snp.c.

References bytes, and data.

Referenced by efi_snp_probe().

                                                            {
        uint8_t *bytes = data;
        uint8_t sum = 0;

        while ( len-- )
                sum += *bytes++;
        return sum;
}
static unsigned int efi_undi_ifnum ( struct efi_snp_device snpdev) [static]

Get UNDI SNP device interface number.

Parameters:
snpdevSNP device
Return values:
ifnumUNDI interface number

Definition at line 933 of file efi_snp.c.

References net_device::index, and efi_snp_device::netdev.

Referenced by efi_snp_probe(), and efi_undi_snpdev().

                                                                     {

        /* iPXE network device indexes are one-based (leaving zero
         * meaning "unspecified").  UNDI interface numbers are
         * zero-based.
         */
        return ( snpdev->netdev->index - 1 );
}
static struct efi_snp_device* efi_undi_snpdev ( unsigned int  ifnum) [static, read]

Identify UNDI SNP device.

Parameters:
ifnumInterface number
Return values:
snpdevSNP device, or NULL if not found

Definition at line 948 of file efi_snp.c.

References efi_undi_ifnum(), efi_snp_device::list, list_for_each_entry, and NULL.

Referenced by efi_undi_issue().

                                                                      {
        struct efi_snp_device *snpdev;

        list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
                if ( efi_undi_ifnum ( snpdev ) == ifnum )
                        return snpdev;
        }
        return NULL;
}
static PXE_STATCODE efi_undi_statcode ( EFI_STATUS  efirc) [static]
static EFI_STATUS efi_undi_get_state ( struct efi_snp_device snpdev,
PXE_CDB cdb 
) [static]

Get state.

Parameters:
snpdevSNP device
cdbCommand description block
Return values:
efircEFI status code

Definition at line 984 of file efi_snp.c.

References DBGC, EfiSimpleNetworkInitialized, EfiSimpleNetworkStarted, efi_snp_device::mode, PXE_STATFLAGS_GET_STATE_INITIALIZED, PXE_STATFLAGS_GET_STATE_STARTED, PXE_STATFLAGS_GET_STATE_STOPPED, EFI_SIMPLE_NETWORK_MODE::State, and s_pxe_cdb::StatFlags.

Referenced by efi_undi_issue().

                                                      {
        EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;

        DBGC ( snpdev, "UNDI %p GET STATE\n", snpdev );

        /* Return current state */
        if ( mode->State == EfiSimpleNetworkInitialized ) {
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATE_INITIALIZED;
        } else if ( mode->State == EfiSimpleNetworkStarted ) {
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATE_STARTED;
        } else {
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATE_STOPPED;
        }

        return 0;
}
static EFI_STATUS efi_undi_start ( struct efi_snp_device snpdev) [static]

Start.

Parameters:
snpdevSNP device
Return values:
efircEFI status code

Definition at line 1008 of file efi_snp.c.

References DBGC, efi_snp_start(), and efi_snp_device::snp.

Referenced by efi_undi_issue().

                                                                   {
        EFI_STATUS efirc;

        DBGC ( snpdev, "UNDI %p START\n", snpdev );

        /* Start SNP device */
        if ( ( efirc = efi_snp_start ( &snpdev->snp ) ) != 0 )
                return efirc;

        return 0;
}
static EFI_STATUS efi_undi_stop ( struct efi_snp_device snpdev) [static]

Stop.

Parameters:
snpdevSNP device
Return values:
efircEFI status code

Definition at line 1026 of file efi_snp.c.

References DBGC, efi_snp_stop(), and efi_snp_device::snp.

Referenced by efi_undi_issue().

                                                                  {
        EFI_STATUS efirc;

        DBGC ( snpdev, "UNDI %p STOP\n", snpdev );

        /* Stop SNP device */
        if ( ( efirc = efi_snp_stop ( &snpdev->snp ) ) != 0 )
                return efirc;

        return 0;
}
static EFI_STATUS efi_undi_get_init_info ( struct efi_snp_device snpdev,
PXE_CDB cdb,
PXE_DB_GET_INIT_INFO db 
) [static]

Get initialisation information.

Parameters:
snpdevSNP device
cdbCommand description block
dbData block
Return values:
efircEFI status code

Definition at line 1046 of file efi_snp.c.

References DBGC, s_pxe_db_get_init_info::FrameDataLen, s_pxe_db_get_init_info::HWaddrLen, s_pxe_db_get_init_info::IFtype, ll_protocol::ll_addr_len, ll_protocol::ll_header_len, ll_protocol::ll_proto, net_device::ll_protocol, net_device::max_pkt_len, s_pxe_db_get_init_info::MediaHeaderLen, memset(), efi_snp_device::netdev, netdev, ntohs, PXE_STATFLAGS_CABLE_DETECT_SUPPORTED, PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED, and s_pxe_cdb::StatFlags.

Referenced by efi_undi_issue().

                                                                      {
        struct net_device *netdev = snpdev->netdev;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;

        DBGC ( snpdev, "UNDI %p GET INIT INFO\n", snpdev );

        /* Populate structure */
        memset ( db, 0, sizeof ( *db ) );
        db->FrameDataLen = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
        db->MediaHeaderLen = ll_protocol->ll_header_len;
        db->HWaddrLen = ll_protocol->ll_addr_len;
        db->IFtype = ntohs ( ll_protocol->ll_proto );
        cdb->StatFlags |= ( PXE_STATFLAGS_CABLE_DETECT_SUPPORTED |
                            PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED );

        return 0;
}
static EFI_STATUS efi_undi_initialize ( struct efi_snp_device snpdev,
PXE_CDB cdb 
) [static]

Initialise.

Parameters:
snpdevSNP device
cdbCommand description block
efircEFI status code

Definition at line 1073 of file efi_snp.c.

References DBGC, efi_snp_initialize(), efi_snp_device::netdev, netdev, netdev_link_ok(), PXE_STATFLAGS_INITIALIZED_NO_MEDIA, efi_snp_device::snp, and s_pxe_cdb::StatFlags.

Referenced by efi_undi_issue().

                                                       {
        struct net_device *netdev = snpdev->netdev;
        EFI_STATUS efirc;

        DBGC ( snpdev, "UNDI %p INITIALIZE\n", snpdev );

        /* Reset SNP device */
        if ( ( efirc = efi_snp_initialize ( &snpdev->snp, 0, 0 ) ) != 0 )
                return efirc;

        /* Report link state */
        if ( ! netdev_link_ok ( netdev ) )
                cdb->StatFlags |= PXE_STATFLAGS_INITIALIZED_NO_MEDIA;

        return 0;
}
static EFI_STATUS efi_undi_reset ( struct efi_snp_device snpdev) [static]

Reset.

Parameters:
snpdevSNP device
efircEFI status code

Definition at line 1097 of file efi_snp.c.

References DBGC, efi_snp_reset(), and efi_snp_device::snp.

Referenced by efi_undi_issue().

                                                                   {
        EFI_STATUS efirc;

        DBGC ( snpdev, "UNDI %p RESET\n", snpdev );

        /* Reset SNP device */
        if ( ( efirc = efi_snp_reset ( &snpdev->snp, 0 ) ) != 0 )
                return efirc;

        return 0;
}
static EFI_STATUS efi_undi_shutdown ( struct efi_snp_device snpdev) [static]

Shutdown.

Parameters:
snpdevSNP device
efircEFI status code

Definition at line 1115 of file efi_snp.c.

References DBGC, efi_snp_shutdown(), and efi_snp_device::snp.

Referenced by efi_undi_issue().

                                                                      {
        EFI_STATUS efirc;

        DBGC ( snpdev, "UNDI %p SHUTDOWN\n", snpdev );

        /* Reset SNP device */
        if ( ( efirc = efi_snp_shutdown ( &snpdev->snp ) ) != 0 )
                return efirc;

        return 0;
}
static EFI_STATUS efi_undi_receive_filters ( struct efi_snp_device snpdev,
PXE_CDB cdb 
) [static]

Get/set receive filters.

Parameters:
snpdevSNP device
cdbCommand description block
efircEFI status code

Definition at line 1134 of file efi_snp.c.

References DBGC, PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST, PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST, PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS, PXE_STATFLAGS_RECEIVE_FILTER_UNICAST, and s_pxe_cdb::StatFlags.

Referenced by efi_undi_issue().

                                                            {

        DBGC ( snpdev, "UNDI %p RECEIVE FILTERS\n", snpdev );

        /* Mark everything as supported */
        cdb->StatFlags |= ( PXE_STATFLAGS_RECEIVE_FILTER_UNICAST |
                            PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST |
                            PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS |
                            PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST );

        return 0;
}
static EFI_STATUS efi_undi_station_address ( struct efi_snp_device snpdev,
PXE_CDB cdb,
PXE_CPB_STATION_ADDRESS cpb,
PXE_DB_STATION_ADDRESS db 
) [static]

Get/set station address.

Parameters:
snpdevSNP device
cdbCommand description block
cpbCommand parameter block
efircEFI status code

Definition at line 1156 of file efi_snp.c.

References s_pxe_dpb_station_address::BroadcastAddr, DBGC, efi_snp_station_address(), net_device::hw_addr, ll_protocol::hw_addr_len, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_broadcast, net_device::ll_protocol, mac, memcpy(), memset(), efi_snp_device::netdev, netdev, NULL, s_pxe_cdb::OpFlags, s_pxe_dpb_station_address::PermanentAddr, PXE_OPFLAGS_STATION_ADDRESS_RESET, efi_snp_device::snp, s_pxe_cpb_station_address::StationAddr, and s_pxe_dpb_station_address::StationAddr.

Referenced by efi_undi_issue().

                                                                          {
        struct net_device *netdev = snpdev->netdev;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        void *mac;
        int reset;
        EFI_STATUS efirc;

        DBGC ( snpdev, "UNDI %p STATION ADDRESS\n", snpdev );

        /* Update address if applicable */
        reset = ( cdb->OpFlags & PXE_OPFLAGS_STATION_ADDRESS_RESET );
        mac = ( cpb ? &cpb->StationAddr : NULL );
        if ( ( reset || mac ) &&
             ( ( efirc = efi_snp_station_address ( &snpdev->snp, reset,
                                                   mac ) ) != 0 ) )
                return efirc;

        /* Fill in current addresses, if applicable */
        if ( db ) {
                memset ( db, 0, sizeof ( *db ) );
                memcpy ( &db->StationAddr, netdev->ll_addr,
                         ll_protocol->ll_addr_len );
                memcpy ( &db->BroadcastAddr, netdev->ll_broadcast,
                         ll_protocol->ll_addr_len );
                memcpy ( &db->PermanentAddr, netdev->hw_addr,
                         ll_protocol->hw_addr_len );
        }

        return 0;
}
static EFI_STATUS efi_undi_get_status ( struct efi_snp_device snpdev,
PXE_CDB cdb,
PXE_DB_GET_STATUS db 
) [static]

Get interrupt status.

Parameters:
snpdevSNP device
cdbCommand description block
dbData block
efircEFI status code

Definition at line 1198 of file efi_snp.c.

References DBGC2, EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT, EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT, efi_snp_get_status(), iob_len(), io_buffer::list, list_first_entry, memset(), efi_snp_device::netdev, netdev_link_ok(), PXE_STATFLAGS_GET_STATUS_NO_MEDIA, PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN, PXE_STATFLAGS_GET_STATUS_RECEIVE, PXE_STATFLAGS_GET_STATUS_TRANSMIT, PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY, efi_snp_device::rx, s_pxe_db_get_status::RxFrameLen, efi_snp_device::snp, s_pxe_cdb::StatFlags, efi_snp_device::tx_cons, efi_snp_device::tx_prod, s_pxe_db_get_status::TxBuffer, and VOID.

Referenced by efi_undi_issue().

                                                                              {
        UINT32 interrupts;
        VOID *txbuf;
        struct io_buffer *rxbuf;
        EFI_STATUS efirc;

        DBGC2 ( snpdev, "UNDI %p GET STATUS\n", snpdev );

        /* Get status */
        if ( ( efirc = efi_snp_get_status ( &snpdev->snp, &interrupts,
                                            &txbuf ) ) != 0 )
                return efirc;

        /* Report status */
        memset ( db, 0, sizeof ( *db ) );
        if ( interrupts & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT )
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;
        if ( interrupts & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT )
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_TRANSMIT;
        if ( txbuf ) {
                db->TxBuffer[0] = ( ( intptr_t ) txbuf );
        } else {
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN;
                /* The specification states clearly that UNDI drivers
                 * should set TXBUF_QUEUE_EMPTY if all completed
                 * buffer addresses are written into the returned data
                 * block.  However, SnpDxe chooses to interpret
                 * TXBUF_QUEUE_EMPTY as a synonym for
                 * NO_TXBUFS_WRITTEN, thereby rendering it entirely
                 * pointless.  Work around this UEFI stupidity, as per
                 * usual.
                 */
                if ( snpdev->tx_prod == snpdev->tx_cons )
                        cdb->StatFlags |=
                                PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY;
        }
        rxbuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
        if ( rxbuf )
                db->RxFrameLen = iob_len ( rxbuf );
        if ( ! netdev_link_ok ( snpdev->netdev ) )
                cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA;

        return 0;
}
static EFI_STATUS efi_undi_fill_header ( struct efi_snp_device snpdev,
PXE_CDB cdb,
PXE_CPB_ANY cpb 
) [static]

Fill header.

Parameters:
snpdevSNP device
cdbCommand description block
cpbCommand parameter block
efircEFI status code

Definition at line 1252 of file efi_snp.c.

References data, dest, s_pxe_cpb_fill_header::DestAddr, s_pxe_cpb_fill_header_fragmented::DestAddr, EFIRC, PXE_CPB_ANY::fill_header, PXE_CPB_ANY::fill_header_fragmented, s_pxe_cpb_fill_header_fragmented::FragAddr, s_pxe_cpb_fill_header_fragmented::FragDesc, iob_populate(), iob_reserve, ll_protocol::ll_header_len, net_device::ll_protocol, s_pxe_cpb_fill_header::MediaHeader, efi_snp_device::netdev, netdev, s_pxe_cdb::OpFlags, s_pxe_cpb_fill_header::Protocol, s_pxe_cpb_fill_header_fragmented::Protocol, ll_protocol::push, PXE_OPFLAGS_FILL_HEADER_FRAGMENTED, rc, src, s_pxe_cpb_fill_header::SrcAddr, s_pxe_cpb_fill_header_fragmented::SrcAddr, and VOID.

Referenced by efi_undi_issue().

                                                                          {
        struct net_device *netdev = snpdev->netdev;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        PXE_CPB_FILL_HEADER *whole = &cpb->fill_header;
        PXE_CPB_FILL_HEADER_FRAGMENTED *fragged = &cpb->fill_header_fragmented;
        VOID *data;
        void *dest;
        void *src;
        uint16_t proto;
        struct io_buffer iobuf;
        int rc;

        /* SnpDxe will (pointlessly) use PXE_CPB_FILL_HEADER_FRAGMENTED
         * even though we choose to explicitly not claim support for
         * fragments via PXE_ROMID_IMP_FRAG_SUPPORTED.
         */
        if ( cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED ) {
                data = ( ( void * ) ( intptr_t ) fragged->FragDesc[0].FragAddr);
                dest = &fragged->DestAddr;
                src = &fragged->SrcAddr;
                proto = fragged->Protocol;
        } else {
                data = ( ( void * ) ( intptr_t ) whole->MediaHeader );
                dest = &whole->DestAddr;
                src = &whole->SrcAddr;
                proto = whole->Protocol;
        }

        /* Construct link-layer header */
        iob_populate ( &iobuf, data, 0, ll_protocol->ll_header_len );
        iob_reserve ( &iobuf, ll_protocol->ll_header_len );
        if ( ( rc = ll_protocol->push ( netdev, &iobuf, dest, src,
                                        proto ) ) != 0 )
                return EFIRC ( rc );

        return 0;
}
static EFI_STATUS efi_undi_transmit ( struct efi_snp_device snpdev,
PXE_CPB_TRANSMIT cpb 
) [static]

Transmit.

Parameters:
snpdevSNP device
cpbCommand parameter block
efircEFI status code

Definition at line 1298 of file efi_snp.c.

References data, s_pxe_cpb_transmit::DataLen, DBGC2, efi_snp_transmit(), s_pxe_cpb_transmit::FrameAddr, NULL, efi_snp_device::snp, and VOID.

Referenced by efi_undi_issue().

                                                              {
        VOID *data = ( ( void * ) ( intptr_t ) cpb->FrameAddr );
        EFI_STATUS efirc;

        DBGC2 ( snpdev, "UNDI %p TRANSMIT\n", snpdev );

        /* Transmit packet */
        if ( ( efirc = efi_snp_transmit ( &snpdev->snp, 0, cpb->DataLen,
                                          data, NULL, NULL, NULL ) ) != 0 )
                return efirc;

        return 0;
}
static EFI_STATUS efi_undi_receive ( struct efi_snp_device snpdev,
PXE_CPB_RECEIVE cpb,
PXE_DB_RECEIVE db 
) [static]

Receive.

Parameters:
snpdevSNP device
cpbCommand parameter block
efircEFI status code

Definition at line 1320 of file efi_snp.c.

References s_pxe_cpb_receive::BufferAddr, s_pxe_cpb_receive::BufferLen, data, DBGC2, dest, s_pxe_db_receive::DestAddr, efi_snp_receive(), s_pxe_db_receive::FrameLen, len, ll_protocol::ll_addr_len, ll_protocol::ll_header_len, net_device::ll_protocol, s_pxe_db_receive::MediaHeaderLen, memcpy(), memset(), efi_snp_device::netdev, netdev, s_pxe_db_receive::Protocol, PXE_FRAME_TYPE_PROMISCUOUS, efi_snp_device::snp, src, s_pxe_db_receive::SrcAddr, s_pxe_db_receive::Type, and VOID.

Referenced by efi_undi_issue().

                                                          {
        struct net_device *netdev = snpdev->netdev;
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        VOID *data = ( ( void * ) ( intptr_t ) cpb->BufferAddr );
        UINTN hdr_len;
        UINTN len = cpb->BufferLen;
        EFI_MAC_ADDRESS src;
        EFI_MAC_ADDRESS dest;
        UINT16 proto;
        EFI_STATUS efirc;

        DBGC2 ( snpdev, "UNDI %p RECEIVE\n", snpdev );

        /* Receive packet */
        if ( ( efirc = efi_snp_receive ( &snpdev->snp, &hdr_len, &len, data,
                                         &src, &dest, &proto ) ) != 0 )
                return efirc;

        /* Describe frame */
        memset ( db, 0, sizeof ( *db ) );
        memcpy ( &db->SrcAddr, &src, ll_protocol->ll_addr_len );
        memcpy ( &db->DestAddr, &dest, ll_protocol->ll_addr_len );
        db->FrameLen = len;
        db->Protocol = proto;
        db->MediaHeaderLen = ll_protocol->ll_header_len;
        db->Type = PXE_FRAME_TYPE_PROMISCUOUS;

        return 0;
}
static EFIAPI VOID efi_undi_issue ( UINT64  cdb_phys) [static]

UNDI entry point.

Definition at line 1353 of file efi_snp.c.

References s_pxe_cdb::CPBaddr, db, s_pxe_cdb::DBaddr, DBGC, efi_snp_claimed, efi_undi_fill_header(), efi_undi_get_init_info(), efi_undi_get_state(), efi_undi_get_status(), efi_undi_initialize(), efi_undi_receive(), efi_undi_receive_filters(), efi_undi_reset(), efi_undi_shutdown(), efi_undi_snpdev(), efi_undi_start(), efi_undi_statcode(), efi_undi_station_address(), efi_undi_stop(), efi_undi_transmit(), EFI_UNSUPPORTED, PXE_DB_ANY::get_init_info, PXE_DB_ANY::get_status, s_pxe_cdb::IFnum, s_pxe_cdb::OpCode, PXE_OPCODE_FILL_HEADER, PXE_OPCODE_GET_INIT_INFO, PXE_OPCODE_GET_STATE, PXE_OPCODE_GET_STATUS, PXE_OPCODE_INITIALIZE, PXE_OPCODE_RECEIVE, PXE_OPCODE_RECEIVE_FILTERS, PXE_OPCODE_RESET, PXE_OPCODE_SHUTDOWN, PXE_OPCODE_START, PXE_OPCODE_STATION_ADDRESS, PXE_OPCODE_STOP, PXE_OPCODE_TRANSMIT, PXE_STATCODE_BUSY, PXE_STATCODE_INVALID_CDB, PXE_STATCODE_SUCCESS, PXE_STATFLAGS_COMMAND_COMPLETE, PXE_STATFLAGS_COMMAND_FAILED, PXE_STATFLAGS_STATUS_MASK, PXE_CPB_ANY::receive, PXE_DB_ANY::receive, s_pxe_cdb::StatCode, s_pxe_cdb::StatFlags, PXE_CPB_ANY::station_address, PXE_DB_ANY::station_address, and PXE_CPB_ANY::transmit.

Referenced by efi_snp_probe().

                                                      {
        PXE_CDB *cdb = ( ( void * ) ( intptr_t ) cdb_phys );
        PXE_CPB_ANY *cpb = ( ( void * ) ( intptr_t ) cdb->CPBaddr );
        PXE_DB_ANY *db = ( ( void * ) ( intptr_t ) cdb->DBaddr );
        struct efi_snp_device *snpdev;
        EFI_STATUS efirc;

        /* Identify device */
        snpdev = efi_undi_snpdev ( cdb->IFnum );
        if ( ! snpdev ) {
                DBGC ( cdb, "UNDI invalid interface number %d\n", cdb->IFnum );
                cdb->StatCode = PXE_STATCODE_INVALID_CDB;
                cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
                return;
        }

        /* Fail if net device is currently claimed for use by iPXE */
        if ( efi_snp_claimed ) {
                cdb->StatCode = PXE_STATCODE_BUSY;
                cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
                return;
        }

        /* Handle opcode */
        cdb->StatCode = PXE_STATCODE_SUCCESS;
        cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
        switch ( cdb->OpCode ) {

        case PXE_OPCODE_GET_STATE:
                efirc = efi_undi_get_state ( snpdev, cdb );
                break;

        case PXE_OPCODE_START:
                efirc = efi_undi_start ( snpdev );
                break;

        case PXE_OPCODE_STOP:
                efirc = efi_undi_stop ( snpdev );
                break;

        case PXE_OPCODE_GET_INIT_INFO:
                efirc = efi_undi_get_init_info ( snpdev, cdb,
                                                 &db->get_init_info );
                break;

        case PXE_OPCODE_INITIALIZE:
                efirc = efi_undi_initialize ( snpdev, cdb );
                break;

        case PXE_OPCODE_RESET:
                efirc = efi_undi_reset ( snpdev );
                break;

        case PXE_OPCODE_SHUTDOWN:
                efirc = efi_undi_shutdown ( snpdev );
                break;

        case PXE_OPCODE_RECEIVE_FILTERS:
                efirc = efi_undi_receive_filters ( snpdev, cdb );
                break;

        case PXE_OPCODE_STATION_ADDRESS:
                efirc = efi_undi_station_address ( snpdev, cdb,
                                                   &cpb->station_address,
                                                   &db->station_address );
                break;

        case PXE_OPCODE_GET_STATUS:
                efirc = efi_undi_get_status ( snpdev, cdb, &db->get_status );
                break;

        case PXE_OPCODE_FILL_HEADER:
                efirc = efi_undi_fill_header ( snpdev, cdb, cpb );
                break;

        case PXE_OPCODE_TRANSMIT:
                efirc = efi_undi_transmit ( snpdev, &cpb->transmit );
                break;

        case PXE_OPCODE_RECEIVE:
                efirc = efi_undi_receive ( snpdev, &cpb->receive,
                                           &db->receive );
                break;

        default:
                DBGC ( snpdev, "UNDI %p unsupported opcode %#04x\n",
                       snpdev, cdb->OpCode );
                efirc = EFI_UNSUPPORTED;
                break;
        }

        /* Convert EFI status code to UNDI status code */
        if ( efirc != 0 ) {
                cdb->StatFlags &= ~PXE_STATFLAGS_STATUS_MASK;
                cdb->StatFlags |= PXE_STATFLAGS_COMMAND_FAILED;
                cdb->StatCode = efi_undi_statcode ( efirc );
        }
}
static EFI_STATUS EFIAPI efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL name2,
CHAR8 *language  __unused,
CHAR16 **  driver_name 
) [static]

Look up driver name.

Parameters:
name2Component name protocol
languageLanguage to use
driver_nameDriver name to fill in
Return values:
efircEFI status code

Definition at line 1505 of file efi_snp.c.

References container_of, and efi_snp_device::driver_name.

Referenced by efi_snp_probe().

                                                                           {
        struct efi_snp_device *snpdev =
                container_of ( name2, struct efi_snp_device, name2 );

        *driver_name = snpdev->driver_name;
        return 0;
}
static EFI_STATUS EFIAPI efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL name2,
EFI_HANDLE device  __unused,
EFI_HANDLE child  __unused,
CHAR8 *language  __unused,
CHAR16 **  controller_name 
) [static]

Look up controller name.

Parameters:
name2Component name protocol
deviceDevice
childChild device, or NULL
languageLanguage to use
driver_nameDevice name to fill in
Return values:
efircEFI status code

Definition at line 1525 of file efi_snp.c.

References container_of, and efi_snp_device::controller_name.

Referenced by efi_snp_probe().

                                                         {
        struct efi_snp_device *snpdev =
                container_of ( name2, struct efi_snp_device, name2 );

        *controller_name = snpdev->controller_name;
        return 0;
}
static EFI_STATUS EFIAPI efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL load_file,
EFI_DEVICE_PATH_PROTOCOL *path  __unused,
BOOLEAN  booting,
UINTN *len  __unused,
VOID *data  __unused 
) [static]

Load file.

Parameters:
loadfileLoad file protocol
pathFile path
bootingLoading as part of a boot attempt
Return values:
efircEFI status code

Definition at line 1553 of file efi_snp.c.

References console_reset(), container_of, DBGC, efi_snp_claim(), efi_snp_release(), EFI_UNSUPPORTED, efi_watchdog_start(), efi_watchdog_stop(), EFIRC, ipxe(), efi_snp_device::netdev, netdev, and rc.

                                          {
        struct efi_snp_device *snpdev =
                container_of ( load_file, struct efi_snp_device, load_file );
        struct net_device *netdev = snpdev->netdev;
        int rc;

        /* Fail unless this is a boot attempt */
        if ( ! booting ) {
                DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
                       snpdev );
                return EFI_UNSUPPORTED;
        }

        /* Claim network devices for use by iPXE */
        efi_snp_claim();

        /* Start watchdog holdoff timer */
        efi_watchdog_start();

        /* Boot from network device */
        if ( ( rc = ipxe ( netdev ) ) != 0 )
                goto err_ipxe;

        /* Reset console */
        console_reset();

 err_ipxe:
        efi_watchdog_stop();
        efi_snp_release();
        return EFIRC ( rc );
}
static struct efi_snp_device* efi_snp_demux ( struct net_device netdev) [static, read]

Locate SNP device corresponding to network device.

Parameters:
netdevNetwork device
Return values:
snpSNP device, or NULL if not found

Definition at line 1606 of file efi_snp.c.

References efi_snp_device::list, list_for_each_entry, efi_snp_device::netdev, and NULL.

Referenced by efi_snp_notify(), efi_snp_remove(), and last_opened_snpdev().

                                                                           {
        struct efi_snp_device *snpdev;

        list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
                if ( snpdev->netdev == netdev )
                        return snpdev;
        }
        return NULL;
}
static int efi_snp_probe ( struct net_device netdev) [static]

Create SNP device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 1622 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseEvent, EFI_BOOT_SERVICES::CloseProtocol, efi_snp_device::controller_name, EFI_BOOT_SERVICES::CreateEvent, DBG, DBGC, net_device::dev, efi_device::device, efi_snp_device::driver_name, device::driver_name, EEFI, efi_child_add(), efi_child_del(), efi_component_name2_protocol_guid, efi_device_path_protocol_guid, efi_devpath_len(), efi_handle_name(), efi_image_handle, efi_load_file_protocol_guid, efi_nii31_protocol_guid, efi_nii_protocol_guid, EFI_OPEN_PROTOCOL_BY_DRIVER, EFI_OPEN_PROTOCOL_EXCLUSIVE, efi_simple_network_protocol_guid, efi_snp_get_controller_name(), efi_snp_get_driver_name(), efi_snp_hii_install(), efi_snp_hii_uninstall(), efi_snp_set_mode(), efi_snp_undi, efi_snp_wait_for_packet(), efi_snprintf(), efi_systab, efi_undi_checksum(), efi_undi_ifnum(), efi_undi_issue(), efi_snp_device::efidev, efidev_parent(), EfiSimpleNetworkStopped, END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, ENOMEM, ENOTSUP, s_pxe_sw_undi::EntryPoint, EVT_NOTIFY_WAIT, free, s_pxe_sw_undi::Fudge, _EFI_COMPONENT_NAME2_PROTOCOL::GetControllerName, _EFI_COMPONENT_NAME2_PROTOCOL::GetDriverName, efi_snp_device::handle, MAC_ADDR_DEVICE_PATH::Header, VLAN_DEVICE_PATH::Header, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::Id, s_pxe_sw_undi::IFcnt, s_pxe_sw_undi::IFcntExt, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::IfNum, MAC_ADDR_DEVICE_PATH::IfType, INIT_LIST_HEAD, EFI_BOOT_SERVICES::InstallMultipleProtocolInterfaces, EFI_DEVICE_PATH_PROTOCOL::Length, efi_snp_device::list, list_add, list_del, net_device::ll_addr, ll_protocol::ll_addr_len, ll_protocol::ll_proto, net_device::ll_protocol, efi_snp_device::load_file, MAC_ADDR_DEVICE_PATH::MacAddress, memcpy(), memset(), MESSAGING_DEVICE_PATH, efi_snp_device::mode, _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, MSG_MAC_ADDR_DP, MSG_VLAN_DP, efi_snp_device::name, device::name, net_device::name, efi_snp_device::name2, efi_snp_device::netdev, netdev_addr(), netdev_get(), netdev_put(), efi_snp_device::nii, ntohs, NULL, EFI_BOOT_SERVICES::OpenProtocol, efi_snp_device::package_list, efi_device::path, efi_snp_device::path, product_short_name, rc, efi_snp_device::rx, efi_snp_device::snp, EFI_SIMPLE_NETWORK_MODE::State, strerror(), EFI_DEVICE_PATH_PROTOCOL::SubType, _EFI_COMPONENT_NAME2_PROTOCOL::SupportedLanguages, tag, TPL_NOTIFY, EFI_DEVICE_PATH_PROTOCOL::Type, EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces, vlan_tag(), VLAN_DEVICE_PATH::VlanId, _EFI_SIMPLE_NETWORK_PROTOCOL::WaitForPacket, and zalloc().

                                                       {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_device *efidev;
        struct efi_snp_device *snpdev;
        EFI_DEVICE_PATH_PROTOCOL *path_end;
        MAC_ADDR_DEVICE_PATH *macpath;
        VLAN_DEVICE_PATH *vlanpath;
        size_t path_prefix_len = 0;
        unsigned int ifcnt;
        unsigned int tag;
        void *interface;
        EFI_STATUS efirc;
        int rc;

        /* Find parent EFI device */
        efidev = efidev_parent ( netdev->dev );
        if ( ! efidev ) {
                DBG ( "SNP skipping non-EFI device %s\n", netdev->name );
                rc = 0;
                goto err_no_efidev;
        }

        /* Allocate the SNP device */
        snpdev = zalloc ( sizeof ( *snpdev ) );
        if ( ! snpdev ) {
                rc = -ENOMEM;
                goto err_alloc_snp;
        }
        snpdev->netdev = netdev_get ( netdev );
        snpdev->efidev = efidev;
        INIT_LIST_HEAD ( &snpdev->rx );

        /* Sanity check */
        if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
                DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
                       "length %d for %s\n", snpdev,
                       netdev->ll_protocol->ll_addr_len, netdev->name );
                rc = -ENOTSUP;
                goto err_ll_addr_len;
        }

        /* Populate the SNP structure */
        memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
        snpdev->snp.Mode = &snpdev->mode;
        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, strerror ( rc ) );
                goto err_create_event;
        }

        /* Populate the SNP mode structure */
        snpdev->mode.State = EfiSimpleNetworkStopped;
        efi_snp_set_mode ( snpdev );

        /* Populate the NII structure */
        memcpy ( &snpdev->nii, &efi_snp_device_nii, sizeof ( snpdev->nii ) );
        snpdev->nii.Id = ( ( intptr_t ) &efi_snp_undi );
        snpdev->nii.IfNum = efi_undi_ifnum ( snpdev );
        efi_snp_undi.EntryPoint = ( ( intptr_t ) efi_undi_issue );
        ifcnt = ( ( efi_snp_undi.IFcntExt << 8 ) | efi_snp_undi.IFcnt );
        if ( ifcnt < snpdev->nii.IfNum )
                ifcnt = snpdev->nii.IfNum;
        efi_snp_undi.IFcnt = ( ifcnt & 0xff );
        efi_snp_undi.IFcntExt = ( ifcnt >> 8 );
        efi_snp_undi.Fudge -= efi_undi_checksum ( &efi_snp_undi,
                                                  sizeof ( efi_snp_undi ) );

        /* Populate the component name structure */
        efi_snprintf ( snpdev->driver_name,
                       ( sizeof ( snpdev->driver_name ) /
                         sizeof ( snpdev->driver_name[0] ) ),
                       "%s %s", product_short_name, netdev->dev->driver_name );
        efi_snprintf ( snpdev->controller_name,
                       ( sizeof ( snpdev->controller_name ) /
                         sizeof ( snpdev->controller_name[0] ) ),
                       "%s %s (%s, %s)", product_short_name,
                       netdev->dev->driver_name, netdev->dev->name,
                       netdev_addr ( netdev ) );
        snpdev->name2.GetDriverName = efi_snp_get_driver_name;
        snpdev->name2.GetControllerName = efi_snp_get_controller_name;
        snpdev->name2.SupportedLanguages = "en";

        /* Populate the load file protocol structure */
        memcpy ( &snpdev->load_file, &efi_snp_load_file_protocol,
                 sizeof ( snpdev->load_file ) );

        /* Populate the device name */
        efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
                                       sizeof ( snpdev->name[0] ) ),
                       "%s", netdev->name );

        /* Allocate the new device path */
        path_prefix_len = efi_devpath_len ( efidev->path );
        snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) +
                                sizeof ( *vlanpath ) + sizeof ( *path_end ) );
        if ( ! snpdev->path ) {
                rc = -ENOMEM;
                goto err_alloc_device_path;
        }

        /* Populate the device path */
        memcpy ( snpdev->path, efidev->path, path_prefix_len );
        macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len );
        memset ( macpath, 0, sizeof ( *macpath ) );
        macpath->Header.Type = MESSAGING_DEVICE_PATH;
        macpath->Header.SubType = MSG_MAC_ADDR_DP;
        macpath->Header.Length[0] = sizeof ( *macpath );
        memcpy ( &macpath->MacAddress, netdev->ll_addr,
                 netdev->ll_protocol->ll_addr_len );
        macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
        if ( ( tag = vlan_tag ( netdev ) ) ) {
                vlanpath = ( ( ( void * ) macpath ) + sizeof ( *macpath ) );
                memset ( vlanpath, 0, sizeof ( *vlanpath ) );
                vlanpath->Header.Type = MESSAGING_DEVICE_PATH;
                vlanpath->Header.SubType = MSG_VLAN_DP;
                vlanpath->Header.Length[0] = sizeof ( *vlanpath );
                vlanpath->VlanId = tag;
                path_end = ( ( ( void * ) vlanpath ) + sizeof ( *vlanpath ) );
        } else {
                path_end = ( ( ( void * ) macpath ) + sizeof ( *macpath ) );
        }
        memset ( path_end, 0, sizeof ( *path_end ) );
        path_end->Type = END_DEVICE_PATH_TYPE;
        path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
        path_end->Length[0] = sizeof ( *path_end );

        /* Install the SNP */
        if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
                        &snpdev->handle,
                        &efi_simple_network_protocol_guid, &snpdev->snp,
                        &efi_device_path_protocol_guid, snpdev->path,
                        &efi_nii_protocol_guid, &snpdev->nii,
                        &efi_nii31_protocol_guid, &snpdev->nii,
                        &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, strerror ( rc ) );
                goto err_install_protocol_interface;
        }

        /* SnpDxe will repeatedly start up and shut down our NII/UNDI
         * interface (in order to obtain the MAC address) before
         * discovering that it cannot install another SNP on the same
         * handle.  This causes the underlying network device to be
         * unexpectedly closed.
         *
         * Prevent this by opening our own NII (and NII31) protocol
         * instances to prevent SnpDxe from attempting to bind to
         * them.
         */
        if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
                                          &efi_nii_protocol_guid, &interface,
                                          efi_image_handle, snpdev->handle,
                                          ( EFI_OPEN_PROTOCOL_BY_DRIVER |
                                            EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
                rc = -EEFI ( efirc );
                DBGC ( snpdev, "SNPDEV %p could not open NII protocol: %s\n",
                       snpdev, strerror ( rc ) );
                goto err_open_nii;
        }
        if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
                                          &efi_nii31_protocol_guid, &interface,
                                          efi_image_handle, snpdev->handle,
                                          ( EFI_OPEN_PROTOCOL_BY_DRIVER |
                                            EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
                rc = -EEFI ( efirc );
                DBGC ( snpdev, "SNPDEV %p could not open NII31 protocol: %s\n",
                       snpdev, strerror ( rc ) );
                goto err_open_nii31;
        }

        /* Add as child of EFI parent device */
        if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n",
                       snpdev, efi_handle_name ( efidev->device ),
                       strerror ( rc ) );
                goto err_efi_child_add;
        }

        /* Install HII */
        if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
                       snpdev, strerror ( rc ) );
                /* HII fails on several platforms.  It's
                 * non-essential, so treat this as a non-fatal
                 * error.
                 */
        }

        /* Add to list of SNP devices */
        list_add ( &snpdev->list, &efi_snp_devices );

        /* Close device path */
        bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid,
                            efi_image_handle, efidev->device );

        DBGC ( snpdev, "SNPDEV %p installed for %s as device %s\n",
               snpdev, netdev->name, efi_handle_name ( snpdev->handle ) );
        return 0;

        list_del ( &snpdev->list );
        if ( snpdev->package_list )
                efi_snp_hii_uninstall ( snpdev );
        efi_child_del ( efidev->device, snpdev->handle );
 err_efi_child_add:
        bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
                            efi_image_handle, snpdev->handle );
 err_open_nii:
        bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
                            efi_image_handle, snpdev->handle );
 err_open_nii31:
        bs->UninstallMultipleProtocolInterfaces (
                        snpdev->handle,
                        &efi_simple_network_protocol_guid, &snpdev->snp,
                        &efi_device_path_protocol_guid, snpdev->path,
                        &efi_nii_protocol_guid, &snpdev->nii,
                        &efi_nii31_protocol_guid, &snpdev->nii,
                        &efi_component_name2_protocol_guid, &snpdev->name2,
                        &efi_load_file_protocol_guid, &snpdev->load_file,
                        NULL );
 err_install_protocol_interface:
        free ( snpdev->path );
 err_alloc_device_path:
        bs->CloseEvent ( snpdev->snp.WaitForPacket );
 err_create_event:
 err_ll_addr_len:
        netdev_put ( netdev );
        free ( snpdev );
 err_alloc_snp:
 err_no_efidev:
        return rc;
}
static void efi_snp_notify ( struct net_device netdev) [static]

Handle SNP device or link state change.

Parameters:
netdevNetwork device

Definition at line 1865 of file efi_snp.c.

References DBG, DBGC, efi_snp_demux(), efi_snp_set_state(), FALSE, EFI_SIMPLE_NETWORK_MODE::MediaPresent, efi_snp_device::mode, net_device::name, netdev_link_ok(), and TRUE.

                                                         {
        struct efi_snp_device *snpdev;

        /* Locate SNP device */
        snpdev = efi_snp_demux ( netdev );
        if ( ! snpdev ) {
                DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
                return;
        }

        /* Update link state */
        snpdev->mode.MediaPresent =
                ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
        DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
               ( snpdev->mode.MediaPresent ? "up" : "down" ) );

        /* Update mode state */
        efi_snp_set_state ( snpdev );
}
static void efi_snp_remove ( struct net_device netdev) [static]

Destroy SNP device.

Parameters:
netdevNetwork device

Definition at line 1890 of file efi_snp.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseEvent, EFI_BOOT_SERVICES::CloseProtocol, DBG, efi_device::device, efi_child_del(), efi_component_name2_protocol_guid, efi_device_path_protocol_guid, efi_image_handle, efi_load_file_protocol_guid, efi_nii31_protocol_guid, efi_nii_protocol_guid, efi_simple_network_protocol_guid, efi_snp_demux(), efi_snp_hii_uninstall(), efi_systab, efi_snp_device::efidev, free, efi_snp_device::handle, efi_snp_device::list, list_del, efi_snp_device::load_file, net_device::name, efi_snp_device::name2, efi_snp_device::netdev, netdev_put(), efi_snp_device::nii, NULL, efi_snp_device::package_list, efi_snp_device::path, efi_snp_device::snp, EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces, and _EFI_SIMPLE_NETWORK_PROTOCOL::WaitForPacket.

                                                         {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev;

        /* Locate SNP device */
        snpdev = efi_snp_demux ( netdev );
        if ( ! snpdev ) {
                DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
                return;
        }

        /* Uninstall the SNP */
        list_del ( &snpdev->list );
        if ( snpdev->package_list )
                efi_snp_hii_uninstall ( snpdev );
        efi_child_del ( snpdev->efidev->device, snpdev->handle );
        bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
                            efi_image_handle, snpdev->handle );
        bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
                            efi_image_handle, snpdev->handle );
        bs->UninstallMultipleProtocolInterfaces (
                        snpdev->handle,
                        &efi_simple_network_protocol_guid, &snpdev->snp,
                        &efi_device_path_protocol_guid, snpdev->path,
                        &efi_nii_protocol_guid, &snpdev->nii,
                        &efi_nii31_protocol_guid, &snpdev->nii,
                        &efi_component_name2_protocol_guid, &snpdev->name2,
                        &efi_load_file_protocol_guid, &snpdev->load_file,
                        NULL );
        free ( snpdev->path );
        bs->CloseEvent ( snpdev->snp.WaitForPacket );
        netdev_put ( snpdev->netdev );
        free ( snpdev );
}
struct efi_snp_device* find_snpdev ( EFI_HANDLE  handle) [read]

Find SNP device by EFI device handle.

Parameters:
handleEFI device handle
Return values:
snpdevSNP device, or NULL

Definition at line 1939 of file efi_snp.c.

References efi_snp_device::handle, efi_snp_device::list, list_for_each_entry, and NULL.

Referenced by nii_supported(), and snp_supported().

                                                          {
        struct efi_snp_device *snpdev;

        list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
                if ( snpdev->handle == handle )
                        return snpdev;
        }
        return NULL;
}
struct efi_snp_device* last_opened_snpdev ( void  ) [read]

Get most recently opened SNP device.

Return values:
snpdevMost recently opened SNP device, or NULL

Definition at line 1954 of file efi_snp.c.

References efi_snp_demux(), last_opened_netdev(), netdev, and NULL.

Referenced by efi_block_hook(), and efi_image_exec().

                                                    {
        struct net_device *netdev;

        netdev = last_opened_netdev();
        if ( ! netdev )
                return NULL;

        return efi_snp_demux ( netdev );
}
void efi_snp_add_claim ( int  delta)

Add to SNP claimed/released count.

Parameters:
deltaClaim count change

Definition at line 1969 of file efi_snp.c.

References assert, EFI_SYSTEM_TABLE::BootServices, efi_snp_claimed, efi_snp_old_tpl, efi_snp_set_state(), efi_systab, efi_snp_device::list, list_for_each_entry, EFI_BOOT_SERVICES::RaiseTPL, EFI_BOOT_SERVICES::RestoreTPL, and TPL_CALLBACK.

Referenced by efi_snp_claim(), and efi_snp_release().

                                     {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct efi_snp_device *snpdev;

        /* Raise TPL if we are about to claim devices */
        if ( ! efi_snp_claimed )
                efi_snp_old_tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* Claim SNP devices */
        efi_snp_claimed += delta;
        assert ( efi_snp_claimed >= 0 );

        /* Update SNP mode state for each interface */
        list_for_each_entry ( snpdev, &efi_snp_devices, list )
                efi_snp_set_state ( snpdev );

        /* Restore TPL if we have released devices */
        if ( ! efi_snp_claimed )
                bs->RestoreTPL ( efi_snp_old_tpl );
}

Variable Documentation

int efi_snp_claimed [static]

TPL prior to network devices being claimed.

Definition at line 49 of file efi_snp.c.

Referenced by efi_snp_add_claim().

Initial value:
 {
        .Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
        .Start          = efi_snp_start,
        .Stop           = efi_snp_stop,
        .Initialize     = efi_snp_initialize,
        .Reset          = efi_snp_reset,
        .Shutdown       = efi_snp_shutdown,
        .ReceiveFilters = efi_snp_receive_filters,
        .StationAddress = efi_snp_station_address,
        .Statistics     = efi_snp_statistics,
        .MCastIpToMac   = efi_snp_mcast_ip_to_mac,
        .NvData         = efi_snp_nvdata,
        .GetStatus      = efi_snp_get_status,
        .Transmit       = efi_snp_transmit,
        .Receive        = efi_snp_receive,
}

SNP interface.

Definition at line 870 of file efi_snp.c.

Initial value:

UNDI interface.

Must be aligned on a 16-byte boundary, for no particularly good reason.

Definition at line 1457 of file efi_snp.c.

Referenced by efi_snp_probe().

Initial value:
 {
        .Revision       = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION,
        .StringId       = "UNDI",
        .Type           = EfiNetworkInterfaceUndi,
        .MajorVer       = 3,
        .MinorVer       = 1,
        .Ipv6Supported  = TRUE, 
}

Network Identification Interface (NII)

Definition at line 1480 of file efi_snp.c.

Initial value:
 {
        .LoadFile       = efi_snp_load_file,
}

Load file protocol.

Definition at line 1589 of file efi_snp.c.

struct net_driver efi_snp_driver __net_driver
Initial value:
 {
        .name = "SNP",
        .probe = efi_snp_probe,
        .notify = efi_snp_notify,
        .remove = efi_snp_remove,
}

SNP driver.

Definition at line 1926 of file efi_snp.c.