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