iPXE
snpnet.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 FILE_LICENCE ( GPL2_OR_LATER );
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <ipxe/iobuf.h>
27 #include <ipxe/netdevice.h>
28 #include <ipxe/ethernet.h>
29 #include <ipxe/if_ether.h>
30 #include <ipxe/vsprintf.h>
31 #include <ipxe/timer.h>
32 #include <ipxe/efi/efi.h>
34 #include <ipxe/efi/efi_driver.h>
35 #include <ipxe/efi/efi_utils.h>
36 #include <ipxe/efi/efi_snp.h>
37 #include "snpnet.h"
38 
39 /** @file
40  *
41  * SNP NIC driver
42  *
43  */
44 
45 /** An SNP NIC */
46 struct snp_nic {
47  /** EFI device */
48  struct efi_device *efidev;
49  /** Simple network protocol */
51  /** Generic device */
52  struct device dev;
53 
54  /** Maximum packet size
55  *
56  * This is calculated as the sum of MediaHeaderSize and
57  * MaxPacketSize, and may therefore be an overestimate.
58  */
59  size_t mtu;
60 
61  /** Current transmit buffer */
62  struct io_buffer *txbuf;
63  /** Current receive buffer */
64  struct io_buffer *rxbuf;
65 };
66 
67 /** Maximum number of received packets per poll */
68 #define SNP_RX_QUOTA 4
69 
70 /** Maximum initialisation retry count */
71 #define SNP_INITIALIZE_RETRY_MAX 10
72 
73 /** Delay between each initialisation retry */
74 #define SNP_INITIALIZE_RETRY_DELAY_MS 10
75 
76 /** Additional padding for receive buffers
77  *
78  * Some SNP implementations seem to require additional space in the
79  * allocated receive buffers, otherwise full-length packets will be
80  * silently dropped.
81  *
82  * The EDK2 MnpDxe driver happens to allocate an additional 8 bytes of
83  * padding (4 for a VLAN tag, 4 for the Ethernet frame checksum).
84  * Match this behaviour since drivers are very likely to have been
85  * tested against MnpDxe.
86  */
87 #define SNP_RX_PAD 8
88 
89 /** An SNP interface patch to inhibit shutdown for insomniac devices */
91  /** Original Shutdown() method */
93  /** Original Stop() method */
95 };
96 
97 /**
98  * Format SNP MAC address (for debugging)
99  *
100  * @v mac MAC address
101  * @v len Length of MAC address
102  * @ret text MAC address as text
103  */
104 static const char * snpnet_mac_text ( EFI_MAC_ADDRESS *mac, size_t len ) {
105  static char buf[ sizeof ( *mac ) * 3 /* "xx:" or "xx\0" */ ];
106  size_t used = 0;
107  unsigned int i;
108 
109  for ( i = 0 ; i < len ; i++ ) {
110  used += ssnprintf ( &buf[used], ( sizeof ( buf ) - used ),
111  "%s%02x", ( used ? ":" : "" ),
112  mac->Addr[i] );
113  }
114  return buf;
115 }
116 
117 /**
118  * Dump SNP mode information (for debugging)
119  *
120  * @v netdev Network device
121  */
122 static void snpnet_dump_mode ( struct net_device *netdev ) {
123  struct snp_nic *snp = netdev->priv;
125  size_t mac_len = mode->HwAddressSize;
126  unsigned int i;
127 
128  /* Do nothing unless debugging is enabled */
129  if ( ! DBG_EXTRA )
130  return;
131 
132  DBGC2 ( snp, "SNP %s st %d type %d hdr %d pkt %d rxflt %#x/%#x%s "
133  "nvram %d acc %d mcast %d/%d\n", netdev->name, mode->State,
134  mode->IfType, mode->MediaHeaderSize, mode->MaxPacketSize,
135  mode->ReceiveFilterSetting, mode->ReceiveFilterMask,
136  ( mode->MultipleTxSupported ? " multitx" : "" ),
137  mode->NvRamSize, mode->NvRamAccessSize,
138  mode->MCastFilterCount, mode->MaxMCastFilterCount );
139  DBGC2 ( snp, "SNP %s hw %s", netdev->name,
140  snpnet_mac_text ( &mode->PermanentAddress, mac_len ) );
141  DBGC2 ( snp, " addr %s%s",
142  snpnet_mac_text ( &mode->CurrentAddress, mac_len ),
143  ( mode->MacAddressChangeable ? "" : "(f)" ) );
144  DBGC2 ( snp, " bcast %s\n",
145  snpnet_mac_text ( &mode->BroadcastAddress, mac_len ) );
146  for ( i = 0 ; i < mode->MCastFilterCount ; i++ ) {
147  DBGC2 ( snp, "SNP %s mcast %s\n", netdev->name,
148  snpnet_mac_text ( &mode->MCastFilter[i], mac_len ) );
149  }
150  DBGC2 ( snp, "SNP %s media %s\n", netdev->name,
151  ( mode->MediaPresentSupported ?
152  ( mode->MediaPresent ? "present" : "not present" ) :
153  "presence not supported" ) );
154 }
155 
156 /**
157  * Check link state
158  *
159  * @v netdev Network device
160  */
161 static void snpnet_check_link ( struct net_device *netdev ) {
162  struct snp_nic *snp = netdev->priv;
164 
165  /* Do nothing unless media presence detection is supported */
166  if ( ! mode->MediaPresentSupported )
167  return;
168 
169  /* Report any link status change */
170  if ( mode->MediaPresent && ( ! netdev_link_ok ( netdev ) ) ) {
172  } else if ( ( ! mode->MediaPresent ) && netdev_link_ok ( netdev ) ) {
174  }
175 }
176 
177 /**
178  * Transmit packet
179  *
180  * @v netdev Network device
181  * @v iobuf I/O buffer
182  * @ret rc Return status code
183  */
184 static int snpnet_transmit ( struct net_device *netdev,
185  struct io_buffer *iobuf ) {
186  struct snp_nic *snp = netdev->priv;
187  EFI_STATUS efirc;
188  int rc;
189 
190  /* Do nothing if shutdown is in progress */
192  return -ECANCELED;
193 
194  /* Defer the packet if there is already a transmission in progress */
195  if ( snp->txbuf ) {
196  netdev_tx_defer ( netdev, iobuf );
197  return 0;
198  }
199 
200  /* Pad to minimum Ethernet length, to work around underlying
201  * drivers that do not correctly handle frame padding
202  * themselves.
203  */
204  iob_pad ( iobuf, ETH_ZLEN );
205 
206  /* Transmit packet */
207  if ( ( efirc = snp->snp->Transmit ( snp->snp, 0, iob_len ( iobuf ),
208  iobuf->data, NULL, NULL,
209  NULL ) ) != 0 ) {
210  rc = -EEFI ( efirc );
211  DBGC ( snp, "SNP %s could not transmit: %s\n",
212  netdev->name, strerror ( rc ) );
213  return rc;
214  }
215  snp->txbuf = iobuf;
216 
217  return 0;
218 }
219 
220 /**
221  * Poll for completed packets
222  *
223  * @v netdev Network device
224  */
225 static void snpnet_poll_tx ( struct net_device *netdev ) {
226  struct snp_nic *snp = netdev->priv;
227  struct io_buffer *iobuf;
228  UINT32 irq;
229  VOID *txbuf;
230  EFI_STATUS efirc;
231  int rc;
232 
233  /* Get status */
234  txbuf = NULL;
235  if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) {
236  rc = -EEFI ( efirc );
237  DBGC ( snp, "SNP %s could not get status: %s\n",
238  netdev->name, strerror ( rc ) );
239  netdev_rx_err ( netdev, NULL, rc );
240  return;
241  }
242 
243  /* Do nothing unless we have a completion */
244  if ( ! txbuf )
245  return;
246 
247  /* Sanity check */
248  if ( ! snp->txbuf ) {
249  DBGC ( snp, "SNP %s reported spurious TX completion\n",
250  netdev->name );
252  return;
253  }
254 
255  /* Complete transmission */
256  iobuf = snp->txbuf;
257  snp->txbuf = NULL;
258  netdev_tx_complete ( netdev, iobuf );
259 }
260 
261 /**
262  * Poll for received packets
263  *
264  * @v netdev Network device
265  */
266 static void snpnet_poll_rx ( struct net_device *netdev ) {
267  struct snp_nic *snp = netdev->priv;
268  UINTN len;
269  unsigned int quota;
270  EFI_STATUS efirc;
271  int rc;
272 
273  /* Retrieve up to SNP_RX_QUOTA packets */
274  for ( quota = SNP_RX_QUOTA ; quota ; quota-- ) {
275 
276  /* Allocate buffer, if required */
277  if ( ! snp->rxbuf ) {
278  snp->rxbuf = alloc_iob ( snp->mtu + SNP_RX_PAD );
279  if ( ! snp->rxbuf ) {
280  /* Leave for next poll */
281  break;
282  }
283  }
284 
285  /* Receive packet */
286  len = iob_tailroom ( snp->rxbuf );
287  if ( ( efirc = snp->snp->Receive ( snp->snp, NULL, &len,
288  snp->rxbuf->data, NULL,
289  NULL, NULL ) ) != 0 ) {
290 
291  /* EFI_NOT_READY is just the usual "no packet"
292  * status indication; ignore it.
293  */
294  if ( efirc == EFI_NOT_READY )
295  break;
296 
297  /* Anything else is an error */
298  rc = -EEFI ( efirc );
299  DBGC ( snp, "SNP %s could not receive: %s\n",
300  netdev->name, strerror ( rc ) );
301  netdev_rx_err ( netdev, NULL, rc );
302  break;
303  }
304 
305  /* Hand off to network stack */
306  iob_put ( snp->rxbuf, len );
307  netdev_rx ( netdev, snp->rxbuf );
308  snp->rxbuf = NULL;
309  }
310 }
311 
312 /**
313  * Poll for completed packets
314  *
315  * @v netdev Network device
316  */
317 static void snpnet_poll ( struct net_device *netdev ) {
318 
319  /* Do nothing if shutdown is in progress */
321  return;
322 
323  /* Process any TX completions */
325 
326  /* Process any RX completions */
328 
329  /* Check for link state changes */
331 }
332 
333 /**
334  * Set receive filters
335  *
336  * @v netdev Network device
337  * @ret rc Return status code
338  */
339 static int snpnet_rx_filters ( struct net_device *netdev ) {
340  struct snp_nic *snp = netdev->priv;
341  UINT32 filters[] = {
342  snp->snp->Mode->ReceiveFilterMask,
352  };
353  unsigned int i;
354  EFI_STATUS efirc;
355  int rc;
356 
357  /* Try possible receive filters in turn */
358  for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) {
359  efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i],
361  0, NULL );
362  if ( efirc == 0 )
363  return 0;
364  rc = -EEFI ( efirc );
365  DBGC ( snp, "SNP %s could not set receive filters %#02x (have "
366  "%#02x): %s\n", netdev->name, filters[i],
367  snp->snp->Mode->ReceiveFilterSetting, strerror ( rc ) );
368  }
369 
370  return rc;
371 }
372 
373 /**
374  * Open network device
375  *
376  * @v netdev Network device
377  * @ret rc Return status code
378  */
379 static int snpnet_open ( struct net_device *netdev ) {
380  struct snp_nic *snp = netdev->priv;
381  EFI_MAC_ADDRESS *mac = ( ( void * ) netdev->ll_addr );
383  EFI_STATUS efirc;
384  unsigned int retry;
385  int rc;
386 
387  /* Try setting MAC address (before initialising) */
388  if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
389  rc = -EEFI ( efirc );
390  DBGC ( snp, "SNP %s could not set station address before "
391  "initialising: %s\n", netdev->name, strerror ( rc ) );
392  /* Ignore error */
393  }
394 
395  /* Initialise NIC, retrying multiple times if link stays down */
396  for ( retry = 0 ; ; ) {
397 
398  /* Initialise NIC, if not already initialised */
399  if ( ( mode->State != EfiSimpleNetworkInitialized ) &&
400  ( ( efirc = snp->snp->Initialize ( snp->snp,
401  0, 0 ) ) != 0 ) ) {
402  rc = -EEFI ( efirc );
404  DBGC ( snp, "SNP %s could not initialise: %s\n",
405  netdev->name, strerror ( rc ) );
406  return rc;
407  }
408 
409  /* Stop if we have link up (or no link detection capability) */
410  if ( ( ! mode->MediaPresentSupported ) || mode->MediaPresent )
411  break;
412 
413  /* Stop if we have exceeded our retry count. This is
414  * not a failure; it is plausible that we genuinely do
415  * not have link up.
416  */
417  if ( ++retry >= SNP_INITIALIZE_RETRY_MAX )
418  break;
419  DBGC ( snp, "SNP %s retrying initialisation (retry %d)\n",
420  netdev->name, retry );
421 
422  /* Delay to allow time for link to establish */
424 
425  /* Shut down and retry (unless device is insomniac);
426  * this is sometimes necessary in order to persuade
427  * the underlying SNP driver to actually update the
428  * link state.
429  */
430  if ( ( ! netdev_insomniac ( netdev ) ) &&
431  ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
432  rc = -EEFI ( efirc );
434  DBGC ( snp, "SNP %s could not shut down: %s\n",
435  netdev->name, strerror ( rc ) );
436  return rc;
437  }
438  }
439 
440  /* Try setting MAC address (after initialising) */
441  if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
442  rc = -EEFI ( efirc );
443  DBGC ( snp, "SNP %s could not set station address after "
444  "initialising: %s\n", netdev->name, strerror ( rc ) );
445  /* Ignore error */
446  }
447 
448  /* Set receive filters */
449  if ( ( rc = snpnet_rx_filters ( netdev ) ) != 0 ) {
450  /* Ignore error */
451  }
452 
453  /* Dump mode information (for debugging) */
455 
456  return 0;
457 }
458 
459 /**
460  * Close network device
461  *
462  * @v netdev Network device
463  */
464 static void snpnet_close ( struct net_device *netdev ) {
465  struct snp_nic *snp = netdev->priv;
466  EFI_STATUS efirc;
467  int rc;
468 
469  /* Shut down NIC (unless whole system shutdown is in progress,
470  * or device is insomniac).
471  */
472  if ( ( ! efi_shutdown_in_progress ) &&
473  ( ! netdev_insomniac ( netdev ) ) &&
474  ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
475  rc = -EEFI ( efirc );
476  DBGC ( snp, "SNP %s could not shut down: %s\n",
477  netdev->name, strerror ( rc ) );
478  /* Nothing we can do about this */
479  }
480 
481  /* Discard transmit buffer, if applicable */
482  if ( snp->txbuf ) {
484  snp->txbuf = NULL;
485  }
486 
487  /* Discard receive buffer, if applicable */
488  if ( snp->rxbuf ) {
489  free_iob ( snp->rxbuf );
490  snp->rxbuf = NULL;
491  }
492 }
493 
494 /** SNP network device operations */
496  .open = snpnet_open,
497  .close = snpnet_close,
498  .transmit = snpnet_transmit,
499  .poll = snpnet_poll,
500 };
501 
502 /**
503  * Check to see if driver supports a device
504  *
505  * @v device EFI device handle
506  * @v protocol Protocol GUID
507  * @v inhibit_wifi Inhibit wireless devices
508  * @ret rc Return status code
509  */
511  int inhibit_wifi ) {
512  EFI_HANDLE parent;
513  int rc;
514 
515  /* Check that this is not a device we are providing ourselves */
516  if ( find_snpdev ( device ) != NULL ) {
517  DBGCP ( device, "HANDLE %s is provided by this binary\n",
518  efi_handle_name ( device ) );
519  return -ENOTTY;
520  }
521 
522  /* Test for presence of protocol */
523  if ( ( rc = efi_test ( device, protocol ) ) != 0 ) {
524  DBGCP ( device, "HANDLE %s is not a %s device\n",
526  efi_guid_ntoa ( protocol ) );
527  return rc;
528  }
529 
530  /* Check that there are no instances of this protocol further
531  * up this device path.
532  */
533  if ( ( rc = efi_locate_device ( device, protocol,
534  &parent, 1 ) ) == 0 ) {
535  DBGC2 ( device, "HANDLE %s has %s-supporting parent ",
537  efi_guid_ntoa ( protocol ) );
538  DBGC2 ( device, "%s\n", efi_handle_name ( parent ) );
539  return -ENOTTY;
540  }
541  DBGC ( device, "HANDLE %s is a %s device\n",
543 
544  /* Check for wireless devices, if applicable */
545  if ( inhibit_wifi &&
546  ( ( efi_test ( device, &efi_wifi2_protocol_guid ) ) == 0 ) ) {
547  DBGC ( device, "HANDLE %s is wireless: assuming vendor %s "
548  "driver is too unreliable to use\n",
550  efi_guid_ntoa ( protocol ) );
551  return -ENOTTY;
552  }
553 
554  return 0;
555 }
556 
557 /**
558  * Check if device must be insomniac
559  *
560  * @v device EFI device handle
561  * @v is_insomniac Device must be insomniac
562  */
564  int rc;
565 
566  /* Check for wireless devices
567  *
568  * The UEFI model for wireless network configuration is
569  * somewhat underdefined. At the time of writing, the EDK2
570  * "UEFI WiFi Connection Manager" driver provides only one way
571  * to configure wireless network credentials, which is to
572  * enter them interactively via an HII form. Credentials are
573  * not stored (or exposed via any protocol interface), and so
574  * any temporary disconnection from the wireless network will
575  * inevitably leave the interface in an unusable state that
576  * cannot be recovered without user intervention.
577  *
578  * Experimentation shows that at least some wireless network
579  * drivers will disconnect from the wireless network when the
580  * SNP Shutdown() method is called, or if the device is not
581  * polled sufficiently frequently to maintain its association
582  * to the network. We therefore inhibit calls to Shutdown()
583  * and Stop() for any such SNP protocol interfaces, and mark
584  * our network device as insomniac so that it will be polled
585  * even when closed.
586  */
587  if ( ( rc = efi_test ( device, &efi_wifi2_protocol_guid ) ) == 0 ) {
588  DBGC ( device, "SNP %s is wireless: assuming insomniac\n",
589  efi_handle_name ( device ) );
590  return 1;
591  }
592 
593  return 0;
594 }
595 
596 /**
597  * Ignore shutdown attempt
598  *
599  * @v snp SNP interface
600  * @ret efirc EFI status code
601  */
602 static EFI_STATUS EFIAPI
604 
605  return 0;
606 }
607 
608 /**
609  * Patch SNP protocol interface to prevent shutdown
610  *
611  * @v device EFI device handle
612  * @v patch Interface patch
613  * @ret rc Return status code
614  */
616  struct snp_insomniac_patch *patch ) {
618  int rc;
619 
620  /* Open interface for ephemeral use */
622  &interface ) ) != 0 ) {
623  DBGC ( device, "SNP %s cannot open SNP protocol for patching: "
624  "%s\n", efi_handle_name ( device ), strerror ( rc ) );
625  return rc;
626  }
627 
628  /* Record original Shutdown() and Stop() methods */
629  patch->shutdown = interface->Shutdown;
630  patch->stop = interface->Stop;
631 
632  /* Inhibit other UEFI drivers' calls to Shutdown() and Stop()
633  *
634  * This is necessary since disconnecting the MnpDxe driver
635  * will attempt to shut down the SNP device, which would leave
636  * us with an unusable device.
637  */
638  interface->Shutdown = snpnet_do_nothing;
640  DBGC ( device, "SNP %s patched to inhibit shutdown\n",
641  efi_handle_name ( device ) );
642 
643  return 0;
644 }
645 
646 /**
647  * Restore patched SNP protocol interface
648  *
649  * @v device EFI device handle
650  * @v patch Interface patch to fill in
651  * @ret rc Return status code
652  */
654  struct snp_insomniac_patch *patch ) {
656  int rc;
657 
658  /* Avoid returning uninitialised data on error */
659  memset ( patch, 0, sizeof ( *patch ) );
660 
661  /* Open interface for ephemeral use */
663  &interface ) ) != 0 ) {
664  DBGC ( device, "SNP %s cannot open patched SNP protocol: %s\n",
665  efi_handle_name ( device ), strerror ( rc ) );
666  return rc;
667  }
668 
669  /* Restore original Shutdown() and Stop() methods, if possible */
670  if ( interface->Shutdown == snpnet_do_nothing )
671  interface->Shutdown = patch->shutdown;
672  if ( interface->Stop == snpnet_do_nothing )
673  interface->Stop = patch->stop;
674 
675  /* Check that original methods were restored (by us or others) */
676  if ( ( interface->Shutdown != patch->shutdown ) ||
677  ( interface->Stop != patch->stop ) ) {
678  DBGC ( device, "SNP %s could not restore patched SNP "
679  "protocol\n", efi_handle_name ( device ) );
680  return -EBUSY;
681  }
682 
683  return 0;
684 }
685 
686 /**
687  * Exclude existing drivers
688  *
689  * @v device EFI device handle
690  * @ret rc Return status code
691  */
694  struct snp_insomniac_patch patch;
695  int insomniac;
696  int rc;
697 
698  /* Check if this is a device that must not ever be shut down */
699  insomniac = snpnet_is_insomniac ( device );
700 
701  /* Inhibit calls to Shutdown() and Stop(), if applicable */
702  if ( insomniac &&
703  ( ( rc = snpnet_insomniac_patch ( device, &patch ) ) != 0 ) ) {
704  goto err_patch;
705  }
706 
707  /* Exclude existing SNP drivers */
708  if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) {
709  DBGC ( device, "SNP %s could not exclude drivers: %s\n",
710  efi_handle_name ( device ), strerror ( rc ) );
711  goto err_exclude;
712  }
713 
714  err_exclude:
715  if ( insomniac )
716  snpnet_insomniac_restore ( device, &patch );
717  err_patch:
718  return rc;
719 }
720 
721 /**
722  * Attach driver to device
723  *
724  * @v efidev EFI device
725  * @ret rc Return status code
726  */
727 int snpnet_start ( struct efi_device *efidev ) {
728  EFI_HANDLE device = efidev->device;
731  struct net_device *netdev;
732  struct snp_nic *snp;
733  EFI_STATUS efirc;
734  int rc;
735 
736  /* Open SNP protocol */
737  if ( ( rc = efi_open_by_driver ( device,
739  &interface ) ) != 0 ) {
740  DBGC ( device, "SNP %s cannot open SNP protocol: %s\n",
741  efi_handle_name ( device ), strerror ( rc ) );
744  goto err_open_protocol;
745  }
746 
747  /* Allocate and initialise structure */
748  netdev = alloc_etherdev ( sizeof ( *snp ) );
749  if ( ! netdev ) {
750  rc = -ENOMEM;
751  goto err_alloc;
752  }
754  snp = netdev->priv;
755  snp->efidev = efidev;
756  snp->snp = interface;
757  mode = snp->snp->Mode;
759 
760  /* Populate underlying device information */
761  efi_device_info ( device, "SNP", &snp->dev );
762  snp->dev.driver_name = "SNP";
763  snp->dev.parent = &efidev->dev;
764  list_add ( &snp->dev.siblings, &efidev->dev.children );
765  INIT_LIST_HEAD ( &snp->dev.children );
766  netdev->dev = &snp->dev;
767 
768  /* Check if device is insomniac */
769  if ( snpnet_is_insomniac ( device ) )
771 
772  /* Bring to the correct state for a closed interface */
773  if ( ( mode->State == EfiSimpleNetworkStopped ) &&
774  ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) {
775  rc = -EEFI ( efirc );
776  DBGC ( device, "SNP %s could not start: %s\n",
777  efi_handle_name ( device ), strerror ( rc ) );
778  goto err_start;
779  }
780  if ( ( mode->State == EfiSimpleNetworkInitialized ) &&
781  ( ! netdev_insomniac ( netdev ) ) &&
782  ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
783  rc = -EEFI ( efirc );
784  DBGC ( device, "SNP %s could not shut down: %s\n",
785  efi_handle_name ( device ), strerror ( rc ) );
786  goto err_shutdown;
787  }
788 
789  /* Populate network device parameters */
790  if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) {
791  DBGC ( device, "SNP %s has invalid hardware address length "
792  "%d\n", efi_handle_name ( device ), mode->HwAddressSize);
793  rc = -ENOTSUP;
794  goto err_hw_addr_len;
795  }
796  memcpy ( netdev->hw_addr, &mode->PermanentAddress,
798  if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) {
799  DBGC ( device, "SNP %s has invalid link-layer address length "
800  "%d\n", efi_handle_name ( device ), mode->HwAddressSize);
801  rc = -ENOTSUP;
802  goto err_ll_addr_len;
803  }
804  memcpy ( netdev->ll_addr, &mode->CurrentAddress,
806  snp->mtu = ( snp->snp->Mode->MaxPacketSize +
807  snp->snp->Mode->MediaHeaderSize );
808 
809  /* Register network device */
810  if ( ( rc = register_netdev ( netdev ) ) != 0 )
811  goto err_register_netdev;
812  DBGC ( device, "SNP %s registered as %s\n",
814 
815  /* Set initial link state */
816  if ( snp->snp->Mode->MediaPresentSupported ) {
818  } else {
820  }
821 
822  return 0;
823 
825  err_register_netdev:
826  err_ll_addr_len:
827  err_hw_addr_len:
828  err_shutdown:
829  err_start:
830  list_del ( &snp->dev.siblings );
832  netdev_put ( netdev );
833  err_alloc:
835  err_open_protocol:
836  return rc;
837 }
838 
839 /**
840  * Detach driver from device
841  *
842  * @v efidev EFI device
843  */
844 void snpnet_stop ( struct efi_device *efidev ) {
845  struct net_device *netdev = efidev_get_drvdata ( efidev );
846  struct snp_nic *snp = netdev->priv;
848  EFI_STATUS efirc;
849  int rc;
850 
851  /* Unregister network device */
853 
854  /* Stop SNP protocol (unless whole system shutdown is in progress) */
855  if ( ( ! efi_shutdown_in_progress ) &&
856  ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) ) {
857  rc = -EEFI ( efirc );
858  DBGC ( device, "SNP %s could not stop: %s\n",
859  efi_handle_name ( device ), strerror ( rc ) );
860  /* Nothing we can do about this */
861  }
862 
863  /* Free network device */
864  list_del ( &snp->dev.siblings );
866  netdev_put ( netdev );
867 
868  /* Close SNP protocol */
870 }
EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition: netdevice.h:766
#define iob_put(iobuf, len)
Definition: iobuf.h:124
static void snpnet_dump_mode(struct net_device *netdev)
Dump SNP mode information (for debugging)
Definition: snpnet.c:122
static void snpnet_poll(struct net_device *netdev)
Poll for completed packets.
Definition: snpnet.c:317
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition: netdevice.c:586
The EFI_SIMPLE_NETWORK_PROTOCOL protocol is used to initialize access to a network adapter.
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:174
void netdev_tx_defer(struct net_device *netdev, struct io_buffer *iobuf)
Defer transmitted packet.
Definition: netdevice.c:412
#define SNP_RX_PAD
Additional padding for receive buffers.
Definition: snpnet.c:87
#define EBUSY
Device or resource busy.
Definition: errno.h:338
uint8_t ll_addr_len
Link-layer address length.
Definition: netdevice.h:198
EFI driver interface.
UINT32 MediaHeaderSize
The size, in bytes, of the network interface's media header.
int(* open)(struct net_device *netdev)
Open network device.
Definition: netdevice.h:222
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
void netdev_tx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard transmitted packet.
Definition: netdevice.c:440
128 bit buffer containing a unique identifier value.
Definition: Base.h:215
EFI_SIMPLE_NETWORK_PROTOCOL * snp
Simple network protocol.
Definition: snpnet.c:50
Error codes.
32-byte buffer containing a network Media Access Control address.
Definition: UefiBaseType.h:97
void snpnet_stop(struct efi_device *efidev)
Detach driver from device.
Definition: snpnet.c:844
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:152
uint16_t mode
Acceleration mode.
Definition: ena.h:26
static int snpnet_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet.
Definition: snpnet.c:184
#define EPIPE
Broken pipe.
Definition: errno.h:619
static int netdev_insomniac(struct net_device *netdev)
Check whether or not network device must be polled even while closed.
Definition: netdevice.h:706
printf() and friends
#define efi_test(handle, protocol)
Test protocol existence.
Definition: efi.h:432
EFI_GUID efi_simple_network_protocol_guid
Simple network protocol GUID.
Definition: efi_guid.c:340
#define DBGC(...)
Definition: compiler.h:505
#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
unsigned int UINT32
Definition: ProcessorBind.h:98
static int snpnet_insomniac_restore(EFI_HANDLE device, struct snp_insomniac_patch *patch)
Restore patched SNP protocol interface.
Definition: snpnet.c:653
unsigned int state
Current device state.
Definition: netdevice.h:395
BOOLEAN MediaPresentSupported
TRUE if the presence of media can be determined; otherwise FALSE.
void netdev_link_down(struct net_device *netdev)
Mark network device as having link down.
Definition: netdevice.c:230
iPXE timers
#define DBGC_EFI_OPENERS(...)
Definition: efi.h:344
EFI_HANDLE device
EFI device handle.
Definition: efi_driver.h:21
An SNP interface patch to inhibit shutdown for insomniac devices.
Definition: snpnet.c:90
uint8_t mac[ETH_ALEN]
MAC address.
Definition: ena.h:24
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:130
struct io_buffer * rxbuf
Current receive buffer.
Definition: snpnet.c:64
#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
EFI utilities.
#define ECANCELED
Operation canceled.
Definition: errno.h:343
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
EFI_SIMPLE_NETWORK_MODE * Mode
Pointer to the EFI_SIMPLE_NETWORK_MODE data for the device.
int snpnet_start(struct efi_device *efidev)
Attach driver to device.
Definition: snpnet.c:727
static const char * snpnet_mac_text(EFI_MAC_ADDRESS *mac, size_t len)
Format SNP MAC address (for debugging)
Definition: snpnet.c:104
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition: vsprintf.c:420
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition: netdevice.h:518
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
UINT32 MaxPacketSize
The maximum size, in bytes, of the packets supported by the network interface.
#define ENOMEM
Not enough space.
Definition: errno.h:534
A hardware device.
Definition: device.h:76
EFI_SIMPLE_NETWORK_STOP stop
Original Stop() method.
Definition: snpnet.c:94
void * memcpy(void *dest, const void *src, size_t len) __nonnull
FILE_LICENCE(GPL2_OR_LATER)
UINT32 ReceiveFilterSetting
The current multicast receive filter settings.
EFI_SIMPLE_NETWORK_INITIALIZE Initialize
struct io_buffer * txbuf
Current transmit buffer.
Definition: snpnet.c:62
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:575
Ethernet protocol.
An object interface.
Definition: interface.h:124
void efi_close_by_driver(EFI_HANDLE handle, EFI_GUID *protocol)
Close protocol opened for persistent use by a driver.
Definition: efi_open.c:278
uint8_t hw_addr_len
Hardware address length.
Definition: netdevice.h:196
void * priv
Driver private data.
Definition: netdevice.h:431
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown
EFI_SIMPLE_NETWORK_SHUTDOWN shutdown
Original Shutdown() method.
Definition: snpnet.c:92
EFI_SIMPLE_NETWORK_GET_STATUS GetStatus
#define efi_open_by_driver(handle, protocol, interface)
Open protocol for persistent use by a driver.
Definition: efi.h:473
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition: netdevice.h:788
ring len
Length.
Definition: dwmac.h:231
The EFI_SIMPLE_NETWORK_PROTOCOL provides services to initialize a network interface,...
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition: netdevice.h:639
static struct net_device * netdev
Definition: gdbudp.c:52
static void snpnet_check_link(struct net_device *netdev)
Check link state.
Definition: snpnet.c:161
EFI_SIMPLE_NETWORK_TRANSMIT Transmit
static void snpnet_close(struct net_device *netdev)
Close network device.
Definition: snpnet.c:464
static int snpnet_is_insomniac(EFI_HANDLE device)
Check if device must be insomniac.
Definition: snpnet.c:563
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition: netdevice.c:941
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition: efi_debug.c:652
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
int snpnet_supported(EFI_HANDLE device, EFI_GUID *protocol, int inhibit_wifi)
Check to see if driver supports a device.
Definition: snpnet.c:510
#define EFIAPI
static EFI_STATUS EFIAPI snpnet_do_nothing(EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused)
Ignore shutdown attempt.
Definition: snpnet.c:603
int register_netdev(struct net_device *netdev)
Register network device.
Definition: netdevice.c:759
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:159
static void * efidev_get_drvdata(struct efi_device *efidev)
Get EFI driver-private data.
Definition: efi_driver.h:94
A network device.
Definition: netdevice.h:352
An SNP NIC.
Definition: snpnet.c:46
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:179
#define efi_open(handle, protocol, interface)
Open protocol for ephemeral use.
Definition: efi.h:443
int efi_driver_exclude(EFI_HANDLE device, EFI_GUID *protocol)
Try to disconnect an existing EFI driver.
Definition: efi_driver.c:437
struct device dev
Generic device.
Definition: snpnet.c:52
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:531
SNP NIC driver.
UINT64 UINTN
Unsigned value of native width.
#define EFI_NOT_READY
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:120
An EFI device.
Definition: efi_driver.h:17
#define SNP_RX_QUOTA
Maximum number of received packets per poll.
Definition: snpnet.c:68
static int snpnet_open(struct net_device *netdev)
Open network device.
Definition: snpnet.c:379
static int snpnet_rx_filters(struct net_device *netdev)
Set receive filters.
Definition: snpnet.c:339
static void snpnet_poll_tx(struct net_device *netdev)
Poll for completed packets.
Definition: snpnet.c:225
#define ETH_ZLEN
Definition: if_ether.h:10
#define SNP_INITIALIZE_RETRY_MAX
Maximum initialisation retry count.
Definition: snpnet.c:71
int efi_locate_device(EFI_HANDLE device, EFI_GUID *protocol, EFI_HANDLE *parent, unsigned int skip)
Locate parent device supporting a given protocol.
Definition: efi_utils.c:45
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_guid.c:725
EFI_SIMPLE_NETWORK_START Start
#define VOID
Undeclared type.
Definition: Base.h:271
EFI_STATUS(EFIAPI * EFI_SIMPLE_NETWORK_STOP)(IN EFI_SIMPLE_NETWORK_PROTOCOL *This)
Changes the state of a network interface from "started" to "stopped".
struct efi_device * efidev
EFI device.
Definition: snpnet.c:48
#define TRUE
Definition: tlan.h:46
EFI API.
Network device operations.
Definition: netdevice.h:213
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition: netdevice.c:548
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
static int snpnet_insomniac_patch(EFI_HANDLE device, struct snp_insomniac_patch *patch)
Patch SNP protocol interface to prevent shutdown.
Definition: snpnet.c:615
EFI_SIMPLE_NETWORK_RECEIVE Receive
Network device management.
EFI_GUID efi_wifi2_protocol_guid
WiFi 2 protocol GUID.
Definition: efi_guid.c:436
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
struct efi_snp_device * find_snpdev(EFI_HANDLE handle)
Find SNP device by EFI device handle.
Definition: efi_snp.c:2103
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
void netdev_tx_complete_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Complete network transmission.
Definition: netdevice.c:470
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
#define DBGC2(...)
Definition: compiler.h:522
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
void * data
Start of data.
Definition: iobuf.h:52
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:31
struct list_head children
Devices attached to this device.
Definition: device.h:86
UINT32 ReceiveFilterMask
The multicast receive filter settings supported by the network interface.
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition: ethernet.c:264
EFI_STATUS(EFIAPI * EFI_SIMPLE_NETWORK_SHUTDOWN)(IN EFI_SIMPLE_NETWORK_PROTOCOL *This)
Resets a network adapter and leaves it in a state that is safe for another driver to initialize.
#define DBGCP(...)
Definition: compiler.h:539
static void snpnet_poll_rx(struct net_device *netdev)
Poll for received packets.
Definition: snpnet.c:266
#define FALSE
Definition: tlan.h:45
#define SNP_INITIALIZE_RETRY_DELAY_MS
Delay between each initialisation retry.
Definition: snpnet.c:74
EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters
uint16_t protocol
Protocol ID.
Definition: stp.h:18
int snpnet_exclude(EFI_HANDLE device)
Exclude existing drivers.
Definition: snpnet.c:692
iPXE EFI SNP interface
EFI_SIMPLE_NETWORK_STOP Stop
#define DBG_EXTRA
Definition: compiler.h:319
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
static void efidev_set_drvdata(struct efi_device *efidev, void *priv)
Set EFI driver-private data.
Definition: efi_driver.h:83
struct device dev
Generic device.
Definition: efi_driver.h:19
#define NETDEV_INSOMNIAC
Network device must be polled even when closed.
Definition: netdevice.h:461
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:381
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
void iob_pad(struct io_buffer *iobuf, size_t min_len)
Pad I/O buffer.
Definition: iobpad.c:49
static struct net_device_operations snpnet_operations
SNP network device operations.
Definition: snpnet.c:495
Definition: efi.h:61
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
size_t mtu
Maximum packet size.
Definition: snpnet.c:59
void efi_device_info(EFI_HANDLE device, const char *prefix, struct device *dev)
Get underlying device information.
Definition: efi_utils.c:188
void * memset(void *dest, int character, size_t len) __nonnull
int efi_shutdown_in_progress
EFI shutdown is in progress.
Definition: efi_init.c:59
A persistent I/O buffer.
Definition: iobuf.h:37