#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_device * | efi_snp_netdev (EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device) |
| Locate net device corresponding to EFI device. | |
| static struct efi_snp_device * | efi_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. | |
Definition in file efi_snp.c.
| 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.
| 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.
| 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".
| snp | SNP interface |
| 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".
| snp | SNP interface |
| 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.
| snp | SNP interface | |
| extra_rx_bufsize | Extra RX buffer size, in bytes | |
| extra_tx_bufsize | Extra TX buffer size, in bytes |
| 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.
| snp | SNP interface | |
| ext_verify | Extended verification required |
| 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.
| snp | SNP interface |
| 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.
| 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 |
| 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.
| snp | SNP interface | |
| reset | Reset to permanent address | |
| new | New station address |
| 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.
| snp | SNP interface | |
| reset | Reset statistics | |
| stats_len | Size of statistics table | |
| stats | Statistics table |
| 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.
| snp | SNP interface | |
| ipv6 | Address is IPv6 | |
| ip | IP address | |
| mac | MAC address |
| 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.
| snp | SNP interface | |
| read | Operation is a read | |
| offset | Starting offset within NVRAM | |
| len | Length of data buffer | |
| data | Data buffer |
| 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.
| snp | SNP interface | |
| interrupts | Interrupt status, or NULL | |
| txbufs | Recycled transmit buffer address, or NULL |
| 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.
| 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) |
| 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.
| 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) |
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| driver | EFI driver | |
| device | EFI device | |
| num_children | Number of child devices | |
| children | List of child devices |
| 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.
| wtf | Component name protocol | |
| language | Language to use | |
| driver_name | Driver name to fill in |
| 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.
| wtf | Component name protocol | |
| device | Device | |
| child | Child device, or NULL | |
| language | Language to use | |
| driver_name | Device name to fill in |
| 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.
| 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 }
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().
EFI_GUID efi_nii31_protocol_guid [static] |
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,
}
Initial value:
{
efi_snp_driver_supported,
efi_snp_driver_start,
efi_snp_driver_stop,
0x10,
NULL,
NULL
}
EFI_COMPONENT_NAME2_PROTOCOL efi_snp_name [static] |
Initial value:
EFI SNP component name protocol.
1.5.7.1