efi_snp.c File Reference

gPXE EFI SNP interface More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <gpxe/netdevice.h>
#include <gpxe/iobuf.h>
#include <gpxe/in.h>
#include <gpxe/pci.h>
#include <gpxe/efi/efi.h>
#include <gpxe/efi/Protocol/DriverBinding.h>
#include <gpxe/efi/Protocol/PciIo.h>
#include <gpxe/efi/Protocol/SimpleNetwork.h>
#include <gpxe/efi/Protocol/ComponentName2.h>
#include <gpxe/efi/Protocol/NetworkInterfaceIdentifier.h>
#include <config/general.h>

Go to the source code of this file.

Data Structures

struct  efi_snp_device
 An SNP device. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void efi_snp_set_mode (struct efi_snp_device *snpdev)
 Set EFI SNP mode based on gPXE net device parameters.
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 **txbufs)
 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, VOID *context)
 Poll event.
static struct net_deviceefi_snp_netdev (EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device)
 Locate net device corresponding to EFI device.
static struct efi_snp_deviceefi_snp_snpdev (EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device)
 Locate SNP corresponding to EFI device.
static EFI_STATUS EFIAPI efi_snp_driver_supported (EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child)
 Check to see if driver supports a device.
static EFI_STATUS EFIAPI efi_snp_driver_start (EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child)
 Attach driver to device.
static EFI_STATUS EFIAPI efi_snp_driver_stop (EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, UINTN num_children, EFI_HANDLE *children)
 Detach driver from device.
static EFI_STATUS EFIAPI efi_snp_get_driver_name (EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, CHAR8 *language __unused, CHAR16 **driver_name)
 Look up driver name.
static EFI_STATUS EFIAPI efi_snp_get_controller_name (EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, EFI_HANDLE device __unused, EFI_HANDLE child __unused, CHAR8 *language __unused, CHAR16 **controller_name __unused)
 Look up controller name.
int efi_snp_install (void)
 Install EFI SNP driver.

Variables

static EFI_GUID efi_simple_network_protocol_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID
 EFI simple network protocol GUID.
static EFI_GUID efi_driver_binding_protocol_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID
 EFI driver binding protocol GUID.
static EFI_GUID efi_component_name2_protocol_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID
 EFI component name protocol GUID.
static EFI_GUID efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID
 EFI device path protocol GUID.
static EFI_GUID efi_nii_protocol_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID
 EFI network interface identifier GUID.
static EFI_GUID efi_nii31_protocol_guid
 EFI network interface identifier GUID (extra special version).
static EFI_GUID efi_pci_io_protocol_guid = EFI_PCI_IO_PROTOCOL_GUID
 EFI PCI I/O protocol GUID.
static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp
 SNP interface.
static EFI_DRIVER_BINDING_PROTOCOL efi_snp_binding
 EFI SNP driver binding.
static EFI_COMPONENT_NAME2_PROTOCOL efi_snp_name
 EFI SNP component name protocol.


Detailed Description

gPXE EFI SNP interface

Definition in file efi_snp.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static void efi_snp_set_mode ( struct efi_snp_device snpdev  )  [static]

Set EFI SNP mode based on gPXE net device parameters.

Parameters:
snp SNP interface

Definition at line 119 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, net_device::max_pkt_len, 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, 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_driver_start().

00119                                                                {
00120         struct net_device *netdev = snpdev->netdev;
00121         EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
00122         struct ll_protocol *ll_protocol = netdev->ll_protocol;
00123         unsigned int ll_addr_len = ll_protocol->ll_addr_len;
00124 
00125         mode->HwAddressSize = ll_addr_len;
00126         mode->MediaHeaderSize = ll_protocol->ll_header_len;
00127         mode->MaxPacketSize = netdev->max_pkt_len;
00128         mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
00129                                     EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
00130                                     EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
00131         assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
00132         memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
00133         memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
00134         ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
00135         mode->IfType = ntohs ( ll_protocol->ll_proto );
00136         mode->MacAddressChangeable = TRUE;
00137         mode->MediaPresentSupported = TRUE;
00138         mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
00139 }

static void efi_snp_poll ( struct efi_snp_device snpdev  )  [static]

Poll net device and count received packets.

Parameters:
snpdev SNP device

Definition at line 146 of file efi_snp.c.

References io_buffer::list, list_for_each_entry, efi_snp_device::netdev, netdev_poll(), efi_snp_device::rx_count_events, efi_snp_device::rx_count_interrupts, and net_device::rx_queue.

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

00146                                                            {
00147         struct io_buffer *iobuf;
00148         unsigned int before = 0;
00149         unsigned int after = 0;
00150         unsigned int arrived;
00151 
00152         /* We have to report packet arrivals, and this is the easiest
00153          * way to fake it.
00154          */
00155         list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
00156                 before++;
00157         netdev_poll ( snpdev->netdev );
00158         list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
00159                 after++;
00160         arrived = ( after - before );
00161 
00162         snpdev->rx_count_interrupts += arrived;
00163         snpdev->rx_count_events += arrived;
00164 }

static EFI_STATUS EFIAPI efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL snp  )  [static]

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

Parameters:
snp SNP interface
Return values:
efirc EFI status code

Definition at line 173 of file efi_snp.c.

References container_of, DBGC2, EfiSimpleNetworkStarted, efi_snp_device::mode, and EFI_SIMPLE_NETWORK_MODE::State.

00173                                                    {
00174         struct efi_snp_device *snpdev =
00175                 container_of ( snp, struct efi_snp_device, snp );
00176 
00177         DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
00178 
00179         snpdev->mode.State = EfiSimpleNetworkStarted;
00180         return 0;
00181 }

static EFI_STATUS EFIAPI efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL snp  )  [static]

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

Parameters:
snp SNP interface
Return values:
efirc EFI status code

Definition at line 190 of file efi_snp.c.

References container_of, DBGC2, EfiSimpleNetworkStopped, efi_snp_device::mode, and EFI_SIMPLE_NETWORK_MODE::State.

00190                                                   {
00191         struct efi_snp_device *snpdev =
00192                 container_of ( snp, struct efi_snp_device, snp );
00193 
00194         DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
00195 
00196         snpdev->mode.State = EfiSimpleNetworkStopped;
00197         return 0;
00198 }

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:
snp SNP interface
extra_rx_bufsize Extra RX buffer size, in bytes
extra_tx_bufsize Extra TX buffer size, in bytes
Return values:
efirc EFI status code

Definition at line 209 of file efi_snp.c.

References container_of, DBGC, DBGC2, EfiSimpleNetworkInitialized, efi_snp_device::mode, net_device::name, efi_snp_device::netdev, netdev_open(), RC_TO_EFIRC, EFI_SIMPLE_NETWORK_MODE::State, and strerror().

00210                                                                       {
00211         struct efi_snp_device *snpdev =
00212                 container_of ( snp, struct efi_snp_device, snp );
00213         int rc;
00214 
00215         DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
00216                 snpdev, ( ( unsigned long ) extra_rx_bufsize ),
00217                 ( ( unsigned long ) extra_tx_bufsize ) );
00218 
00219         if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
00220                 DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
00221                        snpdev, snpdev->netdev->name, strerror ( rc ) );
00222                 return RC_TO_EFIRC ( rc );
00223         }
00224 
00225         snpdev->mode.State = EfiSimpleNetworkInitialized;
00226         return 0;
00227 }

static EFI_STATUS EFIAPI efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
BOOLEAN  ext_verify 
) [static]

Reset the network device.

Parameters:
snp SNP interface
ext_verify Extended verification required
Return values:
efirc EFI status code

Definition at line 237 of file efi_snp.c.

References container_of, DBGC, DBGC2, EfiSimpleNetworkInitialized, EfiSimpleNetworkStarted, efi_snp_device::mode, net_device::name, efi_snp_device::netdev, netdev_close(), netdev_open(), RC_TO_EFIRC, EFI_SIMPLE_NETWORK_MODE::State, and strerror().

00237                                                                        {
00238         struct efi_snp_device *snpdev =
00239                 container_of ( snp, struct efi_snp_device, snp );
00240         int rc;
00241 
00242         DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
00243                 snpdev, ( ext_verify ? "with" : "without" ) );
00244 
00245         netdev_close ( snpdev->netdev );
00246         snpdev->mode.State = EfiSimpleNetworkStarted;
00247 
00248         if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
00249                 DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
00250                        snpdev, snpdev->netdev->name, strerror ( rc ) );
00251                 return RC_TO_EFIRC ( rc );
00252         }
00253 
00254         snpdev->mode.State = EfiSimpleNetworkInitialized;
00255         return 0;
00256 }

static EFI_STATUS EFIAPI efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL snp  )  [static]

Shut down the network device.

Parameters:
snp SNP interface
Return values:
efirc EFI status code

Definition at line 265 of file efi_snp.c.

References container_of, DBGC2, EfiSimpleNetworkStarted, efi_snp_device::mode, efi_snp_device::netdev, netdev_close(), and EFI_SIMPLE_NETWORK_MODE::State.

00265                                                       {
00266         struct efi_snp_device *snpdev =
00267                 container_of ( snp, struct efi_snp_device, snp );
00268 
00269         DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
00270 
00271         netdev_close ( snpdev->netdev );
00272         snpdev->mode.State = EfiSimpleNetworkStarted;
00273         return 0;
00274 }

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:
snp SNP interface
enable Receive filters to enable
disable Receive filters to disable
mcast_reset Reset multicast filters
mcast_count Number of multicast filters
mcast Multicast filters
Return values:
efirc EFI status code

Definition at line 288 of file efi_snp.c.

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

00290                                                                       {
00291         struct efi_snp_device *snpdev =
00292                 container_of ( snp, struct efi_snp_device, snp );
00293         unsigned int i;
00294 
00295         DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
00296                 snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
00297                 ( ( unsigned long ) mcast_count ) );
00298         for ( i = 0 ; i < mcast_count ; i++ ) {
00299                 DBGC2_HDA ( snpdev, i, &mcast[i],
00300                             snpdev->netdev->ll_protocol->ll_addr_len );
00301         }
00302 
00303         /* Lie through our teeth, otherwise MNP refuses to accept us */
00304         return 0;
00305 }

static EFI_STATUS EFIAPI efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
BOOLEAN  reset,
EFI_MAC_ADDRESS new 
) [static]

Set station address.

Parameters:
snp SNP interface
reset Reset to permanent address
new New station address
Return values:
efirc EFI status code

Definition at line 316 of file efi_snp.c.

References container_of, DBGC, DBGC2, 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.

00317                                                  {
00318         struct efi_snp_device *snpdev =
00319                 container_of ( snp, struct efi_snp_device, snp );
00320         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00321 
00322         DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
00323                 ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
00324 
00325         /* Set the MAC address */
00326         if ( reset )
00327                 new = &snpdev->mode.PermanentAddress;
00328         memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
00329 
00330         /* MAC address changes take effect only on netdev_open() */
00331         if ( netdev_is_open ( snpdev->netdev ) ) {
00332                 DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
00333                        "devive open\n", snpdev );
00334         }
00335 
00336         return 0;
00337 }

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:
snp SNP interface
reset Reset statistics
stats_len Size of statistics table
stats Statistics table
Return values:
efirc EFI status code

Definition at line 349 of file efi_snp.c.

References net_device_stats::bad, container_of, DBGC2, 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.

00350                                                                        {
00351         struct efi_snp_device *snpdev =
00352                 container_of ( snp, struct efi_snp_device, snp );
00353         EFI_NETWORK_STATISTICS stats_buf;
00354 
00355         DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
00356                 ( reset ? " reset" : "" ) );
00357 
00358         /* Gather statistics */
00359         memset ( &stats_buf, 0, sizeof ( stats_buf ) );
00360         stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
00361         stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
00362         stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
00363                                     snpdev->netdev->tx_stats.bad );
00364         stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
00365         stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
00366         stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
00367                                     snpdev->netdev->rx_stats.bad );
00368         if ( *stats_len > sizeof ( stats_buf ) )
00369                 *stats_len = sizeof ( stats_buf );
00370         if ( stats )
00371                 memcpy ( stats, &stats_buf, *stats_len );
00372 
00373         /* Reset statistics if requested to do so */
00374         if ( reset ) {
00375                 memset ( &snpdev->netdev->tx_stats, 0,
00376                          sizeof ( snpdev->netdev->tx_stats ) );
00377                 memset ( &snpdev->netdev->rx_stats, 0,
00378                          sizeof ( snpdev->netdev->rx_stats ) );
00379         }
00380 
00381         return 0;
00382 }

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 
) [static]

Convert multicast IP address to MAC address.

Parameters:
snp SNP interface
ipv6 Address is IPv6
ip IP address
mac MAC address
Return values:
efirc EFI status code

Definition at line 394 of file efi_snp.c.

References AF_INET, AF_INET6, container_of, DBGC, DBGC2, inet_ntoa(), net_device::ll_protocol, ll_protocol::mc_hash, efi_snp_device::netdev, RC_TO_EFIRC, and strerror().

00395                                                                      {
00396         struct efi_snp_device *snpdev =
00397                 container_of ( snp, struct efi_snp_device, snp );
00398         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00399         const char *ip_str;
00400         int rc;
00401 
00402         ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
00403                    inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
00404         DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
00405 
00406         /* Try to hash the address */
00407         if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
00408                                            ip, mac ) ) != 0 ) {
00409                 DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
00410                        snpdev, ip_str, strerror ( rc ) );
00411                 return RC_TO_EFIRC ( rc );
00412         }
00413 
00414         return 0;
00415 }

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:
snp SNP interface
read Operation is a read
offset Starting offset within NVRAM
len Length of data buffer
data Data buffer
Return values:
efirc EFI status code

Definition at line 428 of file efi_snp.c.

References container_of, DBGC2, DBGC2_HDA, and EFI_UNSUPPORTED.

00429                                                        {
00430         struct efi_snp_device *snpdev =
00431                 container_of ( snp, struct efi_snp_device, snp );
00432 
00433         DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
00434                 ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
00435                 ( ( unsigned long ) len ) );
00436         if ( ! read )
00437                 DBGC2_HDA ( snpdev, offset, data, len );
00438 
00439         return EFI_UNSUPPORTED;
00440 }

static EFI_STATUS EFIAPI efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL snp,
UINT32 interrupts,
VOID **  txbufs 
) [static]

Read interrupt status and TX recycled buffer status.

Parameters:
snp SNP interface
interrupts Interrupt status, or NULL
txbufs Recycled transmit buffer address, or NULL
Return values:
efirc EFI status code

Definition at line 451 of file efi_snp.c.

References container_of, DBGC2, EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT, EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT, efi_snp_poll(), list_empty(), efi_snp_device::netdev, NULL, efi_snp_device::rx_count_interrupts, efi_snp_device::tx_count_interrupts, efi_snp_device::tx_count_txbufs, and net_device::tx_queue.

00452                                                          {
00453         struct efi_snp_device *snpdev =
00454                 container_of ( snp, struct efi_snp_device, snp );
00455 
00456         DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
00457 
00458         /* Poll the network device */
00459         efi_snp_poll ( snpdev );
00460 
00461         /* Interrupt status.  In practice, this seems to be used only
00462          * to detect TX completions.
00463          */
00464         if ( interrupts ) {
00465                 *interrupts = 0;
00466                 /* Report TX completions once queue is empty; this
00467                  * avoids having to add hooks in the net device layer.
00468                  */
00469                 if ( snpdev->tx_count_interrupts &&
00470                      list_empty ( &snpdev->netdev->tx_queue ) ) {
00471                         *interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
00472                         snpdev->tx_count_interrupts--;
00473                 }
00474                 /* Report RX */
00475                 if ( snpdev->rx_count_interrupts ) {
00476                         *interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
00477                         snpdev->rx_count_interrupts--;
00478                 }
00479                 DBGC2 ( snpdev, " INTS:%02x", *interrupts );
00480         }
00481 
00482         /* TX completions.  It would be possible to design a more
00483          * idiotic scheme for this, but it would be a challenge.
00484          * According to the UEFI header file, txbufs will be filled in
00485          * with a list of "recycled transmit buffers" (i.e. completed
00486          * TX buffers).  Observant readers may care to note that
00487          * *txbufs is a void pointer.  Precisely how a list of
00488          * completed transmit buffers is meant to be represented as an
00489          * array of voids is left as an exercise for the reader.
00490          *
00491          * The only users of this interface (MnpDxe/MnpIo.c and
00492          * PxeBcDxe/Bc.c within the EFI dev kit) both just poll until
00493          * seeing a non-NULL result return in txbufs.  This is valid
00494          * provided that they do not ever attempt to transmit more
00495          * than one packet concurrently (and that TX never times out).
00496          */
00497         if ( txbufs ) {
00498                 if ( snpdev->tx_count_txbufs &&
00499                      list_empty ( &snpdev->netdev->tx_queue ) ) {
00500                         *txbufs = "Which idiot designed this API?";
00501                         snpdev->tx_count_txbufs--;
00502                 } else {
00503                         *txbufs = NULL;
00504                 }
00505                 DBGC2 ( snpdev, " TX:%s", ( *txbufs ? "some" : "none" ) );
00506         }
00507 
00508         DBGC2 ( snpdev, "\n" );
00509         return 0;
00510 }

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:
snp SNP interface
ll_header_len Link-layer header length, if to be filled in
len Length of data buffer
data Data buffer
ll_src Link-layer source address, if specified
ll_dest Link-layer destination address, if specified
net_proto Network-layer protocol (in host order)
Return values:
efirc EFI status code

Definition at line 525 of file efi_snp.c.

References alloc_iob(), container_of, EFI_SIMPLE_NETWORK_MODE::CurrentAddress, DBGC, DBGC2, EFI_BUFFER_TOO_SMALL, EFI_DEVICE_ERROR, EFI_INVALID_PARAMETER, free_iob(), htons, iob_disown, iob_pull, iob_put, ll_protocol::ll_header_len, net_device::ll_protocol, memcpy, efi_snp_device::mode, efi_snp_device::netdev, netdev_tx(), ll_protocol::ntoa, ll_protocol::push, RC_TO_EFIRC, strerror(), efi_snp_device::tx_count_interrupts, and efi_snp_device::tx_count_txbufs.

00528                                        {
00529         struct efi_snp_device *snpdev =
00530                 container_of ( snp, struct efi_snp_device, snp );
00531         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00532         struct io_buffer *iobuf;
00533         int rc;
00534         EFI_STATUS efirc;
00535 
00536         DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
00537                 ( ( unsigned long ) len ) );
00538         if ( ll_header_len ) {
00539                 if ( ll_src ) {
00540                         DBGC2 ( snpdev, " src %s",
00541                                 ll_protocol->ntoa ( ll_src ) );
00542                 }
00543                 if ( ll_dest ) {
00544                         DBGC2 ( snpdev, " dest %s",
00545                                 ll_protocol->ntoa ( ll_dest ) );
00546                 }
00547                 if ( net_proto ) {
00548                         DBGC2 ( snpdev, " proto %04x", *net_proto );
00549                 }
00550         }
00551         DBGC2 ( snpdev, "\n" );
00552 
00553         /* Sanity checks */
00554         if ( ll_header_len ) {
00555                 if ( ll_header_len != ll_protocol->ll_header_len ) {
00556                         DBGC ( snpdev, "SNPDEV %p TX invalid header length "
00557                                "%ld\n", snpdev,
00558                                ( ( unsigned long ) ll_header_len ) );
00559                         efirc = EFI_INVALID_PARAMETER;
00560                         goto err_sanity;
00561                 }
00562                 if ( len < ll_header_len ) {
00563                         DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
00564                                snpdev, ( ( unsigned long ) len ) );
00565                         efirc = EFI_BUFFER_TOO_SMALL;
00566                         goto err_sanity;
00567                 }
00568                 if ( ! ll_dest ) {
00569                         DBGC ( snpdev, "SNPDEV %p TX missing destination "
00570                                "address\n", snpdev );
00571                         efirc = EFI_INVALID_PARAMETER;
00572                         goto err_sanity;
00573                 }
00574                 if ( ! net_proto ) {
00575                         DBGC ( snpdev, "SNPDEV %p TX missing network "
00576                                "protocol\n", snpdev );
00577                         efirc = EFI_INVALID_PARAMETER;
00578                         goto err_sanity;
00579                 }
00580                 if ( ! ll_src )
00581                         ll_src = &snpdev->mode.CurrentAddress;
00582         }
00583 
00584         /* Allocate buffer */
00585         iobuf = alloc_iob ( len );
00586         if ( ! iobuf ) {
00587                 DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
00588                        "buffer\n", snpdev, ( ( unsigned long ) len ) );
00589                 efirc = EFI_DEVICE_ERROR;
00590                 goto err_alloc_iob;
00591         }
00592         memcpy ( iob_put ( iobuf, len ), data, len );
00593 
00594         /* Create link-layer header, if specified */
00595         if ( ll_header_len ) {
00596                 iob_pull ( iobuf, ll_header_len );
00597                 if ( ( rc = ll_protocol->push ( snpdev->netdev,
00598                                                 iobuf, ll_dest, ll_src,
00599                                                 htons ( *net_proto ) )) != 0 ){
00600                         DBGC ( snpdev, "SNPDEV %p TX could not construct "
00601                                "header: %s\n", snpdev, strerror ( rc ) );
00602                         efirc = RC_TO_EFIRC ( rc );
00603                         goto err_ll_push;
00604                 }
00605         }
00606 
00607         /* Transmit packet */
00608         if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
00609                 DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
00610                        snpdev, strerror ( rc ) );
00611                 efirc = RC_TO_EFIRC ( rc );
00612                 goto err_tx;
00613         }
00614 
00615         /* Record transmission as outstanding */
00616         snpdev->tx_count_interrupts++;
00617         snpdev->tx_count_txbufs++;
00618 
00619         return 0;
00620 
00621  err_tx:
00622  err_ll_push:
00623         free_iob ( iobuf );
00624  err_alloc_iob:
00625  err_sanity:
00626         return efirc;
00627 }

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:
snp SNP interface
ll_header_len Link-layer header length, if to be filled in
len Length of data buffer
data Data buffer
ll_src Link-layer source address, if specified
ll_dest Link-layer destination address, if specified
net_proto Network-layer protocol (in host order)
Return values:
efirc EFI status code

Definition at line 642 of file efi_snp.c.

References container_of, io_buffer::data, DBGC, DBGC2, EFI_NOT_READY, efi_snp_poll(), free_iob(), iob_len(), ll_protocol::ll_addr_len, ll_protocol::ll_header_len, net_device::ll_protocol, memcpy, efi_snp_device::netdev, netdev_rx_dequeue(), ntohs, ll_protocol::pull, RC_TO_EFIRC, and strerror().

00645                                       {
00646         struct efi_snp_device *snpdev =
00647                 container_of ( snp, struct efi_snp_device, snp );
00648         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00649         struct io_buffer *iobuf;
00650         const void *iob_ll_dest;
00651         const void *iob_ll_src;
00652         uint16_t iob_net_proto;
00653         int rc;
00654         EFI_STATUS efirc;
00655 
00656         DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
00657                 ( ( unsigned long ) *len ) );
00658 
00659         /* Poll the network device */
00660         efi_snp_poll ( snpdev );
00661 
00662         /* Dequeue a packet, if one is available */
00663         iobuf = netdev_rx_dequeue ( snpdev->netdev );
00664         if ( ! iobuf ) {
00665                 DBGC2 ( snpdev, "\n" );
00666                 efirc = EFI_NOT_READY;
00667                 goto out_no_packet;
00668         }
00669         DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
00670 
00671         /* Return packet to caller */
00672         memcpy ( data, iobuf->data, iob_len ( iobuf ) );
00673         *len = iob_len ( iobuf );
00674 
00675         /* Attempt to decode link-layer header */
00676         if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
00677                                         &iob_ll_src, &iob_net_proto ) ) != 0 ){
00678                 DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
00679                        snpdev, strerror ( rc ) );
00680                 efirc = RC_TO_EFIRC ( rc );
00681                 goto out_bad_ll_header;
00682         }
00683 
00684         /* Return link-layer header parameters to caller, if required */
00685         if ( ll_header_len )
00686                 *ll_header_len = ll_protocol->ll_header_len;
00687         if ( ll_src )
00688                 memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
00689         if ( ll_dest )
00690                 memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
00691         if ( net_proto )
00692                 *net_proto = ntohs ( iob_net_proto );
00693 
00694         efirc = 0;
00695 
00696  out_bad_ll_header:
00697         free_iob ( iobuf );
00698 out_no_packet:
00699         return efirc;
00700 }

static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT  event,
VOID *  context 
) [static]

Poll event.

Parameters:
event Event
context Event context

Definition at line 708 of file efi_snp.c.

References _EFI_SYSTEM_TABLE::BootServices, DBGC2, DBGCP, efi_snp_poll(), efi_systab, efi_snp_device::netdev, netdev_is_open(), efi_snp_device::rx_count_events, and EFI_BOOT_SERVICES::SignalEvent.

Referenced by efi_snp_driver_start().

00709                                                              {
00710         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00711         struct efi_snp_device *snpdev = context;
00712 
00713         DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
00714 
00715         /* Do nothing unless the net device is open */
00716         if ( ! netdev_is_open ( snpdev->netdev ) )
00717                 return;
00718 
00719         /* Poll the network device */
00720         efi_snp_poll ( snpdev );
00721 
00722         /* Fire event if packets have been received */
00723         if ( snpdev->rx_count_events != 0 ) {
00724                 DBGC2 ( snpdev, "SNPDEV %p firing WaitForPacket event\n",
00725                         snpdev );
00726                 bs->SignalEvent ( event );
00727                 snpdev->rx_count_events--;
00728         }
00729 }

static struct net_device* efi_snp_netdev ( EFI_DRIVER_BINDING_PROTOCOL driver,
EFI_HANDLE  device 
) [static, read]

Locate net device corresponding to EFI device.

Parameters:
driver EFI driver
device EFI device
Return values:
netdev Net device, or NULL if not found

Definition at line 757 of file efi_snp.c.

References _EFI_SYSTEM_TABLE::BootServices, BUS_TYPE_PCI, EFI_BOOT_SERVICES::CloseProtocol, DBGC, DBGCP, _EFI_DRIVER_BINDING_PROTOCOL::DriverBindingHandle, EFI_OPEN_PROTOCOL_BY_DRIVER, efi_pci_io_protocol_guid, efi_strerror(), efi_systab, find_netdev_by_location(), net_device::name, netdev, NULL, EFI_BOOT_SERVICES::OpenProtocol, PCI_BUSDEVFN, and PCI_DEVFN.

Referenced by efi_snp_driver_start(), and efi_snp_driver_supported().

00757                                                                           {
00758         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00759         union {
00760                 EFI_PCI_IO_PROTOCOL *pci;
00761                 void *interface;
00762         } u;
00763         UINTN pci_segment, pci_bus, pci_dev, pci_fn;
00764         unsigned int pci_busdevfn;
00765         struct net_device *netdev = NULL;
00766         EFI_STATUS efirc;
00767 
00768         /* See if device is a PCI device */
00769         if ( ( efirc = bs->OpenProtocol ( device,
00770                                           &efi_pci_io_protocol_guid,
00771                                           &u.interface,
00772                                           driver->DriverBindingHandle,
00773                                           device,
00774                                           EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
00775                 DBGCP ( driver, "SNPDRV %p device %p is not a PCI device\n",
00776                         driver, device );
00777                 goto out_no_pci_io;
00778         }
00779 
00780         /* Get PCI bus:dev.fn address */
00781         if ( ( efirc = u.pci->GetLocation ( u.pci, &pci_segment, &pci_bus,
00782                                             &pci_dev, &pci_fn ) ) != 0 ) {
00783                 DBGC ( driver, "SNPDRV %p device %p could not get PCI "
00784                        "location: %s\n",
00785                        driver, device, efi_strerror ( efirc ) );
00786                 goto out_no_pci_location;
00787         }
00788         DBGCP ( driver, "SNPDRV %p device %p is PCI %04lx:%02lx:%02lx.%lx\n",
00789                 driver, device, ( ( unsigned long ) pci_segment ),
00790                 ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
00791                 ( ( unsigned long ) pci_fn ) );
00792 
00793         /* Look up corresponding network device */
00794         pci_busdevfn = PCI_BUSDEVFN ( pci_bus, PCI_DEVFN ( pci_dev, pci_fn ) );
00795         if ( ( netdev = find_netdev_by_location ( BUS_TYPE_PCI,
00796                                                   pci_busdevfn ) ) == NULL ) {
00797                 DBGCP ( driver, "SNPDRV %p device %p is not a gPXE network "
00798                         "device\n", driver, device );
00799                 goto out_no_netdev;
00800         }
00801         DBGC ( driver, "SNPDRV %p device %p is %s\n",
00802                driver, device, netdev->name );
00803 
00804  out_no_netdev:
00805  out_no_pci_location:
00806         bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
00807                             driver->DriverBindingHandle, device );
00808  out_no_pci_io:
00809         return netdev;
00810 }

static struct efi_snp_device* efi_snp_snpdev ( EFI_DRIVER_BINDING_PROTOCOL driver,
EFI_HANDLE  device 
) [static, read]

Locate SNP corresponding to EFI device.

Parameters:
driver EFI driver
device EFI device
Return values:
snp EFI SNP, or NULL if not found

Definition at line 820 of file efi_snp.c.

References _EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, container_of, DBGC, DBGCP, _EFI_DRIVER_BINDING_PROTOCOL::DriverBindingHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL, efi_simple_network_protocol_guid, efi_strerror(), efi_systab, NULL, EFI_BOOT_SERVICES::OpenProtocol, and efi_snp_device::snp.

Referenced by efi_snp_driver_stop().

00820                                                                           {
00821         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00822         union {
00823                 EFI_SIMPLE_NETWORK_PROTOCOL *snp;
00824                 void *interface;
00825         } u;
00826         struct efi_snp_device *snpdev = NULL;
00827         EFI_STATUS efirc;
00828 
00829         if ( ( efirc = bs->OpenProtocol ( device,
00830                                           &efi_simple_network_protocol_guid,
00831                                           &u.interface,
00832                                           driver->DriverBindingHandle,
00833                                           device,
00834                                           EFI_OPEN_PROTOCOL_GET_PROTOCOL))!=0){
00835                 DBGC ( driver, "SNPDRV %p device %p could not locate SNP: "
00836                        "%s\n", driver, device, efi_strerror ( efirc ) );
00837                 goto err_no_snp;
00838         }
00839 
00840         snpdev =  container_of ( u.snp, struct efi_snp_device, snp );
00841         DBGCP ( driver, "SNPDRV %p device %p is SNPDEV %p\n",
00842                 driver, device, snpdev );
00843 
00844         bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
00845                             driver->DriverBindingHandle, device );
00846  err_no_snp:
00847         return snpdev;
00848 }

static EFI_STATUS EFIAPI efi_snp_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL driver,
EFI_HANDLE  device,
EFI_DEVICE_PATH_PROTOCOL child 
) [static]

Check to see if driver supports a device.

Parameters:
driver EFI driver
device EFI device
child Path to child device, if any
Return values:
efirc EFI status code

Definition at line 859 of file efi_snp.c.

References DBGCP, efi_snp_netdev(), EFI_UNSUPPORTED, and netdev.

00861                                                              {
00862         struct net_device *netdev;
00863 
00864         DBGCP ( driver, "SNPDRV %p DRIVER_SUPPORTED %p (%p)\n",
00865                 driver, device, child );
00866 
00867         netdev = efi_snp_netdev ( driver, device );
00868         return ( netdev ? 0 : EFI_UNSUPPORTED );
00869 }

static EFI_STATUS EFIAPI efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL driver,
EFI_HANDLE  device,
EFI_DEVICE_PATH_PROTOCOL child 
) [static]

Attach driver to device.

Parameters:
driver EFI driver
device EFI device
child Path to child device, if any
Return values:
efirc EFI status code

Definition at line 880 of file efi_snp.c.

References assert, _EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseEvent, EFI_BOOT_SERVICES::CloseProtocol, EFI_BOOT_SERVICES::CreateEvent, DBGC, DBGCP, _EFI_DRIVER_BINDING_PROTOCOL::DriverBindingHandle, efi_device_path_protocol_guid, EFI_INVALID_PARAMETER, EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION, efi_nii_protocol_guid, EFI_OPEN_PROTOCOL_BY_DRIVER, EFI_OUT_OF_RESOURCES, efi_simple_network_protocol_guid, efi_snp_netdev(), efi_snp_set_mode(), efi_snp_wait_for_packet(), efi_strerror(), efi_systab, EFI_UNSUPPORTED, EfiSimpleNetworkStopped, END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, EVT_NOTIFY_WAIT, free(), efi_snp_device::handle, MAC_ADDR_DEVICE_PATH::Header, MAC_ADDR_DEVICE_PATH::IfType, EFI_BOOT_SERVICES::InstallMultipleProtocolInterfaces, EFI_DEVICE_PATH_PROTOCOL::Length, net_device::ll_addr, ll_protocol::ll_addr_len, ll_protocol::ll_proto, net_device::ll_protocol, MAC_ADDR_DEVICE_PATH::MacAddress, memcpy, memset(), MESSAGING_DEVICE_PATH, efi_snp_device::mode, _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, MSG_MAC_ADDR_DP, efi_snp_device::name, net_device::name, efi_snp_device::netdev, netdev, netdev_get(), netdev_put(), efi_snp_device::nii, ntohs, NULL, EFI_BOOT_SERVICES::OpenProtocol, efi_snp_device::path, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::Revision, efi_snp_device::snp, EFI_SIMPLE_NETWORK_MODE::State, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::StringId, strncpy(), EFI_DEVICE_PATH_PROTOCOL::SubType, TPL_NOTIFY, EFI_DEVICE_PATH_PROTOCOL::Type, EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces, _EFI_SIMPLE_NETWORK_PROTOCOL::WaitForPacket, and zalloc().

00882                                                          {
00883         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00884         EFI_DEVICE_PATH_PROTOCOL *path;
00885         EFI_DEVICE_PATH_PROTOCOL *subpath;
00886         MAC_ADDR_DEVICE_PATH *macpath;
00887         struct efi_snp_device *snpdev;
00888         struct net_device *netdev;
00889         size_t subpath_len;
00890         size_t path_prefix_len = 0;
00891         unsigned int i;
00892         EFI_STATUS efirc;
00893 
00894         DBGCP ( driver, "SNPDRV %p DRIVER_START %p (%p)\n",
00895                 driver, device, child );
00896 
00897         /* Determine device path prefix length */
00898         if ( ( efirc = bs->OpenProtocol ( device,
00899                                           &efi_device_path_protocol_guid,
00900                                           ( void * ) &path,
00901                                           driver->DriverBindingHandle,
00902                                           device,
00903                                           EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
00904                 DBGCP ( driver, "SNPDRV %p device %p has no device path\n",
00905                         driver, device );
00906                 goto err_no_device_path;
00907         }
00908         subpath = path;
00909         while ( subpath->Type != END_DEVICE_PATH_TYPE ) {
00910                 subpath_len = ( ( subpath->Length[1] << 8 ) |
00911                                 subpath->Length[0] );
00912                 path_prefix_len += subpath_len;
00913                 subpath = ( ( ( void * ) subpath ) + subpath_len );
00914         }
00915 
00916         /* Allocate the SNP device */
00917         snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
00918                           sizeof ( *macpath ) );
00919         if ( ! snpdev ) {
00920                 efirc = EFI_OUT_OF_RESOURCES;
00921                 goto err_alloc_snp;
00922         }
00923 
00924         /* Identify the net device */
00925         netdev = efi_snp_netdev ( driver, device );
00926         if ( ! netdev ) {
00927                 DBGC ( snpdev, "SNPDEV %p cannot find netdev for device %p\n",
00928                        snpdev, device );
00929                 efirc = EFI_UNSUPPORTED;
00930                 goto err_no_netdev;
00931         }
00932         snpdev->netdev = netdev_get ( netdev );
00933 
00934         /* Sanity check */
00935         if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
00936                 DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
00937                        "length %d for %s\n", snpdev,
00938                        netdev->ll_protocol->ll_addr_len, netdev->name );
00939                 efirc = EFI_INVALID_PARAMETER;
00940                 goto err_ll_addr_len;
00941         }
00942 
00943         /* Populate the SNP structure */
00944         memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
00945         snpdev->snp.Mode = &snpdev->mode;
00946         if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
00947                                          efi_snp_wait_for_packet, snpdev,
00948                                          &snpdev->snp.WaitForPacket ) ) != 0 ){
00949                 DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
00950                        snpdev, efi_strerror ( efirc ) );
00951                 goto err_create_event;
00952         }
00953 
00954         /* Populate the SNP mode structure */
00955         snpdev->mode.State = EfiSimpleNetworkStopped;
00956         efi_snp_set_mode ( snpdev );
00957 
00958         /* Populate the NII structure */
00959         snpdev->nii.Revision =
00960                 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
00961         strncpy ( snpdev->nii.StringId, "gPXE",
00962                   sizeof ( snpdev->nii.StringId ) );
00963 
00964         /* Populate the device name */
00965         for ( i = 0 ; i < sizeof ( netdev->name ) ; i++ ) {
00966                 /* Damn Unicode names */
00967                 assert ( i < ( sizeof ( snpdev->name ) /
00968                                sizeof ( snpdev->name[0] ) ) );
00969                 snpdev->name[i] = netdev->name[i];
00970         }
00971 
00972         /* Populate the device path */
00973         memcpy ( &snpdev->path, path, path_prefix_len );
00974         macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
00975         subpath = ( ( void * ) ( macpath + 1 ) );
00976         memset ( macpath, 0, sizeof ( *macpath ) );
00977         macpath->Header.Type = MESSAGING_DEVICE_PATH;
00978         macpath->Header.SubType = MSG_MAC_ADDR_DP;
00979         macpath->Header.Length[0] = sizeof ( *macpath );
00980         memcpy ( &macpath->MacAddress, netdev->ll_addr,
00981                  sizeof ( macpath->MacAddress ) );
00982         macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
00983         memset ( subpath, 0, sizeof ( *subpath ) );
00984         subpath->Type = END_DEVICE_PATH_TYPE;
00985         subpath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
00986         subpath->Length[0] = sizeof ( *subpath );
00987 
00988         /* Install the SNP */
00989         if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
00990                         &snpdev->handle,
00991                         &efi_simple_network_protocol_guid, &snpdev->snp,
00992                         &efi_device_path_protocol_guid, &snpdev->path,
00993                         &efi_nii_protocol_guid, &snpdev->nii,
00994                         &efi_nii31_protocol_guid, &snpdev->nii,
00995                         NULL ) ) != 0 ) {
00996                 DBGC ( snpdev, "SNPDEV %p could not install protocols: "
00997                        "%s\n", snpdev, efi_strerror ( efirc ) );
00998                 goto err_install_protocol_interface;
00999         }
01000 
01001         DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
01002                snpdev, netdev->name, snpdev->handle );
01003         return 0;
01004 
01005         bs->UninstallMultipleProtocolInterfaces (
01006                         snpdev->handle,
01007                         &efi_simple_network_protocol_guid, &snpdev->snp,
01008                         &efi_device_path_protocol_guid, &snpdev->path,
01009                         &efi_nii_protocol_guid, &snpdev->nii,
01010                         &efi_nii31_protocol_guid, &snpdev->nii,
01011                         NULL );
01012  err_install_protocol_interface:
01013         bs->CloseEvent ( snpdev->snp.WaitForPacket );
01014  err_create_event:
01015  err_ll_addr_len:
01016         netdev_put ( netdev );
01017  err_no_netdev:
01018         free ( snpdev );
01019  err_alloc_snp:
01020         bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
01021                             driver->DriverBindingHandle, device );
01022  err_no_device_path:
01023         return efirc;
01024 }

static EFI_STATUS EFIAPI efi_snp_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL driver,
EFI_HANDLE  device,
UINTN  num_children,
EFI_HANDLE children 
) [static]

Detach driver from device.

Parameters:
driver EFI driver
device EFI device
num_children Number of child devices
children List of child devices
Return values:
efirc EFI status code

Definition at line 1036 of file efi_snp.c.

References _EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseEvent, EFI_BOOT_SERVICES::CloseProtocol, DBGC, DBGCP, _EFI_DRIVER_BINDING_PROTOCOL::DriverBindingHandle, EFI_DEVICE_ERROR, efi_device_path_protocol_guid, efi_nii_protocol_guid, efi_simple_network_protocol_guid, efi_snp_snpdev(), efi_systab, free(), efi_snp_device::handle, efi_snp_device::netdev, netdev_put(), efi_snp_device::nii, NULL, efi_snp_device::path, efi_snp_device::snp, EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces, and _EFI_SIMPLE_NETWORK_PROTOCOL::WaitForPacket.

01039                                              {
01040         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
01041         struct efi_snp_device *snpdev;
01042 
01043         DBGCP ( driver, "SNPDRV %p DRIVER_STOP %p (%ld %p)\n",
01044                 driver, device, ( ( unsigned long ) num_children ), children );
01045 
01046         /* Locate SNP device */
01047         snpdev = efi_snp_snpdev ( driver, device );
01048         if ( ! snpdev ) {
01049                 DBGC ( driver, "SNPDRV %p device %p could not find SNPDEV\n",
01050                        driver, device );
01051                 return EFI_DEVICE_ERROR;
01052         }
01053 
01054         /* Uninstall the SNP */
01055         bs->UninstallMultipleProtocolInterfaces (
01056                         snpdev->handle,
01057                         &efi_simple_network_protocol_guid, &snpdev->snp,
01058                         &efi_device_path_protocol_guid, &snpdev->path,
01059                         &efi_nii_protocol_guid, &snpdev->nii,
01060                         &efi_nii31_protocol_guid, &snpdev->nii,
01061                         NULL );
01062         bs->CloseEvent ( snpdev->snp.WaitForPacket );
01063         netdev_put ( snpdev->netdev );
01064         free ( snpdev );
01065         bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
01066                             driver->DriverBindingHandle, device );
01067         return 0;
01068 }

static EFI_STATUS EFIAPI efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf  __unused,
CHAR8 *language  __unused,
CHAR16 **  driver_name 
) [static]

Look up driver name.

Parameters:
wtf Component name protocol
language Language to use
driver_name Driver name to fill in
Return values:
efirc EFI status code

Definition at line 1089 of file efi_snp.c.

References PRODUCT_SHORT_NAME.

01090                                                                            {
01091 
01092         *driver_name = L"" PRODUCT_SHORT_NAME " Driver";
01093         return 0;
01094 }

static EFI_STATUS EFIAPI efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf  __unused,
EFI_HANDLE device  __unused,
EFI_HANDLE child  __unused,
CHAR8 *language  __unused,
CHAR16 **controller_name  __unused 
) [static]

Look up controller name.

Parameters:
wtf Component name protocol
device Device
child Child device, or NULL
language Language to use
driver_name Device name to fill in
Return values:
efirc EFI status code

Definition at line 1107 of file efi_snp.c.

References EFI_UNSUPPORTED.

01111                                                                   {
01112 
01113         /* Just let EFI use the default Device Path Name */
01114         return EFI_UNSUPPORTED;
01115 }

int efi_snp_install ( void   ) 

Install EFI SNP driver.

Return values:
rc Return status code

Definition at line 1129 of file efi_snp.c.

References _EFI_SYSTEM_TABLE::BootServices, DBGC, _EFI_DRIVER_BINDING_PROTOCOL::DriverBindingHandle, efi_component_name2_protocol_guid, efi_driver_binding_protocol_guid, efi_image_handle, efi_strerror(), efi_systab, EFIRC_TO_RC, _EFI_DRIVER_BINDING_PROTOCOL::ImageHandle, EFI_BOOT_SERVICES::InstallMultipleProtocolInterfaces, and NULL.

Referenced by _start().

01129                              {
01130         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
01131         EFI_DRIVER_BINDING_PROTOCOL *driver = &efi_snp_binding;
01132         EFI_STATUS efirc;
01133 
01134         driver->ImageHandle = efi_image_handle;
01135         if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
01136                         &driver->DriverBindingHandle,
01137                         &efi_driver_binding_protocol_guid, driver,
01138                         &efi_component_name2_protocol_guid, &efi_snp_name,
01139                         NULL ) ) != 0 ) {
01140                 DBGC ( driver, "SNPDRV %p could not install protocols: "
01141                        "%s\n", driver, efi_strerror ( efirc ) );
01142                 return EFIRC_TO_RC ( efirc );
01143         }
01144 
01145         DBGC ( driver, "SNPDRV %p driver binding installed as %p\n",
01146                driver, driver->DriverBindingHandle );
01147         return 0;
01148 }


Variable Documentation

EFI_GUID efi_simple_network_protocol_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID [static]

EFI simple network protocol GUID.

Definition at line 82 of file efi_snp.c.

Referenced by efi_snp_driver_start(), efi_snp_driver_stop(), and efi_snp_snpdev().

EFI_GUID efi_driver_binding_protocol_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID [static]

EFI driver binding protocol GUID.

Definition at line 86 of file efi_snp.c.

Referenced by efi_snp_install().

EFI_GUID efi_component_name2_protocol_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID [static]

EFI component name protocol GUID.

Definition at line 90 of file efi_snp.c.

Referenced by efi_snp_install().

EFI_GUID efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID [static]

EFI device path protocol GUID.

Definition at line 94 of file efi_snp.c.

Referenced by efi_snp_driver_start(), and efi_snp_driver_stop().

EFI_GUID efi_nii_protocol_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID [static]

EFI network interface identifier GUID.

Definition at line 98 of file efi_snp.c.

Referenced by efi_snp_driver_start(), and efi_snp_driver_stop().

Initial value:

 {
        
        0x1ACED566, 0x76ED, 0x4218,
        { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
}
EFI network interface identifier GUID (extra special version).

Definition at line 101 of file efi_snp.c.

EFI_GUID efi_pci_io_protocol_guid = EFI_PCI_IO_PROTOCOL_GUID [static]

EFI PCI I/O protocol GUID.

Definition at line 112 of file efi_snp.c.

Referenced by efi_snp_netdev().

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 732 of file efi_snp.c.

Initial value:

EFI SNP driver binding.

Definition at line 1071 of file efi_snp.c.

Initial value:

EFI SNP component name protocol.

Definition at line 1118 of file efi_snp.c.


Generated on Tue Apr 6 20:01:54 2010 for gPXE by  doxygen 1.5.7.1