iPXE
efi_snp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 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 <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <byteswap.h>
28 #include <ipxe/netdevice.h>
29 #include <ipxe/vlan.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/in.h>
32 #include <ipxe/version.h>
33 #include <ipxe/console.h>
34 #include <ipxe/efi/efi.h>
35 #include <ipxe/efi/efi_driver.h>
36 #include <ipxe/efi/efi_strings.h>
37 #include <ipxe/efi/efi_path.h>
38 #include <ipxe/efi/efi_utils.h>
39 #include <ipxe/efi/efi_watchdog.h>
40 #include <ipxe/efi/efi_null.h>
41 #include <ipxe/efi/efi_snp.h>
42 #include <usr/autoboot.h>
43 #include <config/general.h>
44 
45 /** List of SNP devices */
46 static LIST_HEAD ( efi_snp_devices );
47 
48 /** Network devices are currently claimed for use by iPXE */
49 static int efi_snp_claimed;
50 
51 /** TPL prior to network devices being claimed */
53 
54 /* Downgrade user experience if configured to do so
55  *
56  * The default UEFI user experience for network boot is somewhat
57  * excremental: only TFTP is available as a download protocol, and if
58  * anything goes wrong the user will be shown just a dot on an
59  * otherwise blank screen. (Some programmer was clearly determined to
60  * win a bet that they could outshine Apple at producing uninformative
61  * error messages.)
62  *
63  * For comparison, the default iPXE user experience provides the
64  * option to use protocols designed more recently than 1980 (such as
65  * HTTP and iSCSI), and if anything goes wrong the the user will be
66  * shown one of over 1200 different error messages, complete with a
67  * link to a wiki page describing that specific error.
68  *
69  * We default to upgrading the user experience to match that available
70  * in a "legacy" BIOS environment, by installing our own instance of
71  * EFI_LOAD_FILE_PROTOCOL.
72  *
73  * Note that unfortunately we can't sensibly provide the choice of
74  * both options to the user in the same build, because the UEFI boot
75  * menu ignores the multitude of ways in which a network device handle
76  * can be described and opaquely labels both menu entries as just "EFI
77  * Network".
78  */
79 #ifdef EFI_DOWNGRADE_UX
80 static EFI_GUID dummy_load_file_protocol_guid = {
81  0x6f6c7323, 0x2077, 0x7523,
82  { 0x6e, 0x68, 0x65, 0x6c, 0x70, 0x66, 0x75, 0x6c }
83 };
84 #define efi_load_file_protocol_guid dummy_load_file_protocol_guid
85 #endif
86 
87 /**
88  * Set EFI SNP mode state
89  *
90  * @v snp SNP interface
91  */
92 static void efi_snp_set_state ( struct efi_snp_device *snpdev ) {
93  struct net_device *netdev = snpdev->netdev;
94  EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
95 
96  /* Calculate state */
97  if ( ! snpdev->started ) {
98  /* Start() method not called; report as Stopped */
100  } else if ( ! netdev_is_open ( netdev ) ) {
101  /* Network device not opened; report as Started */
102  mode->State = EfiSimpleNetworkStarted;
103  } else if ( efi_snp_claimed ) {
104  /* Network device opened but claimed for use by iPXE; report
105  * as Started to inhibit receive polling.
106  */
107  mode->State = EfiSimpleNetworkStarted;
108  } else {
109  /* Network device opened and available for use via SNP; report
110  * as Initialized.
111  */
113  }
114 }
115 
116 /**
117  * Set EFI SNP mode based on iPXE net device parameters
118  *
119  * @v snp SNP interface
120  */
121 static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
122  struct net_device *netdev = snpdev->netdev;
123  EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
125  unsigned int ll_addr_len = ll_protocol->ll_addr_len;
126 
127  mode->HwAddressSize = ll_addr_len;
128  mode->MediaHeaderSize = ll_protocol->ll_header_len;
129  mode->MaxPacketSize = netdev->mtu;
130  mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
133  assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
134  memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
135  memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
136  ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
137  mode->IfType = ntohs ( ll_protocol->ll_proto );
138  mode->MacAddressChangeable = TRUE;
139  mode->MediaPresentSupported = TRUE;
140  mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
141 }
142 
143 /**
144  * Flush transmit ring and receive queue
145  *
146  * @v snpdev SNP device
147  */
148 static void efi_snp_flush ( struct efi_snp_device *snpdev ) {
149  struct io_buffer *iobuf;
150  struct io_buffer *tmp;
151 
152  /* Reset transmit completion ring */
153  snpdev->tx_prod = 0;
154  snpdev->tx_cons = 0;
155 
156  /* Discard any queued receive buffers */
157  list_for_each_entry_safe ( iobuf, tmp, &snpdev->rx, list ) {
158  list_del ( &iobuf->list );
159  free_iob ( iobuf );
160  }
161 }
162 
163 /**
164  * Poll net device and count received packets
165  *
166  * @v snpdev SNP device
167  */
168 static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
170  struct io_buffer *iobuf;
171 
172  /* Poll network device */
173  netdev_poll ( snpdev->netdev );
174 
175  /* Retrieve any received packets */
176  while ( ( iobuf = netdev_rx_dequeue ( snpdev->netdev ) ) ) {
177  list_add_tail ( &iobuf->list, &snpdev->rx );
179  bs->SignalEvent ( snpdev->snp.WaitForPacket );
180  }
181 }
182 
183 /**
184  * Change SNP state from "stopped" to "started"
185  *
186  * @v snp SNP interface
187  * @ret efirc EFI status code
188  */
189 static EFI_STATUS EFIAPI
191  struct efi_snp_device *snpdev =
192  container_of ( snp, struct efi_snp_device, snp );
193 
194  DBGC ( snpdev, "SNPDEV %p START\n", snpdev );
195 
196  /* Allow start even if net device is currently claimed by iPXE */
197  if ( efi_snp_claimed ) {
198  DBGC ( snpdev, "SNPDEV %p allowing start while claimed\n",
199  snpdev );
200  }
201 
202  snpdev->started = 1;
203  efi_snp_set_state ( snpdev );
204  return 0;
205 }
206 
207 /**
208  * Change SNP state from "started" to "stopped"
209  *
210  * @v snp SNP interface
211  * @ret efirc EFI status code
212  */
213 static EFI_STATUS EFIAPI
215  struct efi_snp_device *snpdev =
216  container_of ( snp, struct efi_snp_device, snp );
217 
218  DBGC ( snpdev, "SNPDEV %p STOP\n", snpdev );
219 
220  /* Fail if net device is currently claimed for use by iPXE */
221  if ( efi_snp_claimed )
222  return EFI_NOT_READY;
223 
224  snpdev->started = 0;
225  efi_snp_set_state ( snpdev );
226 
227  return 0;
228 }
229 
230 /**
231  * Open the network device
232  *
233  * @v snp SNP interface
234  * @v extra_rx_bufsize Extra RX buffer size, in bytes
235  * @v extra_tx_bufsize Extra TX buffer size, in bytes
236  * @ret efirc EFI status code
237  */
238 static EFI_STATUS EFIAPI
240  UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
241  struct efi_snp_device *snpdev =
242  container_of ( snp, struct efi_snp_device, snp );
243  struct efi_saved_tpl tpl;
244  int rc;
245 
246  DBGC ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
247  snpdev, ( ( unsigned long ) extra_rx_bufsize ),
248  ( ( unsigned long ) extra_tx_bufsize ) );
249 
250  /* Do nothing if net device is currently claimed for use by
251  * iPXE. Do not return an error, because this will cause
252  * MnpDxe et al to fail to install the relevant child handles
253  * and to leave behind a partially initialised device handle
254  * that can cause a later system crash.
255  */
256  if ( efi_snp_claimed ) {
257  DBGC ( snpdev, "SNPDEV %p ignoring initialization while "
258  "claimed\n", snpdev );
259  return 0;
260  }
261 
262  /* Raise TPL */
263  efi_raise_tpl ( &tpl );
264 
265  /* Open network device */
266  if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
267  DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
268  snpdev, snpdev->netdev->name, strerror ( rc ) );
269  goto err_open;
270  }
271  efi_snp_set_state ( snpdev );
272 
273  err_open:
274  efi_restore_tpl ( &tpl );
275  return EFIRC ( rc );
276 }
277 
278 /**
279  * Reset the network device
280  *
281  * @v snp SNP interface
282  * @v ext_verify Extended verification required
283  * @ret efirc EFI status code
284  */
285 static EFI_STATUS EFIAPI
287  struct efi_snp_device *snpdev =
288  container_of ( snp, struct efi_snp_device, snp );
289  struct efi_saved_tpl tpl;
290  int rc;
291 
292  DBGC ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
293  snpdev, ( ext_verify ? "with" : "without" ) );
294 
295  /* Fail if net device is currently claimed for use by iPXE */
296  if ( efi_snp_claimed ) {
297  rc = -EAGAIN;
298  goto err_claimed;
299  }
300 
301  /* Raise TPL */
302  efi_raise_tpl ( &tpl );
303 
304  /* Close network device */
305  netdev_close ( snpdev->netdev );
306  efi_snp_set_state ( snpdev );
307  efi_snp_flush ( snpdev );
308 
309  /* Reopen network device */
310  if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
311  DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
312  snpdev, snpdev->netdev->name, strerror ( rc ) );
313  goto err_open;
314  }
315  efi_snp_set_state ( snpdev );
316 
317  err_open:
318  efi_restore_tpl ( &tpl );
319  err_claimed:
320  return EFIRC ( rc );
321 }
322 
323 /**
324  * Shut down the network device
325  *
326  * @v snp SNP interface
327  * @ret efirc EFI status code
328  */
329 static EFI_STATUS EFIAPI
331  struct efi_snp_device *snpdev =
332  container_of ( snp, struct efi_snp_device, snp );
333  struct efi_saved_tpl tpl;
334 
335  DBGC ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
336 
337  /* Fail if net device is currently claimed for use by iPXE */
338  if ( efi_snp_claimed )
339  return EFI_NOT_READY;
340 
341  /* Raise TPL */
342  efi_raise_tpl ( &tpl );
343 
344  /* Close network device */
345  netdev_close ( snpdev->netdev );
346  efi_snp_set_state ( snpdev );
347  efi_snp_flush ( snpdev );
348 
349  /* Restore TPL */
350  efi_restore_tpl ( &tpl );
351 
352  return 0;
353 }
354 
355 /**
356  * Manage receive filters
357  *
358  * @v snp SNP interface
359  * @v enable Receive filters to enable
360  * @v disable Receive filters to disable
361  * @v mcast_reset Reset multicast filters
362  * @v mcast_count Number of multicast filters
363  * @v mcast Multicast filters
364  * @ret efirc EFI status code
365  */
366 static EFI_STATUS EFIAPI
368  UINT32 disable, BOOLEAN mcast_reset,
369  UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
370  struct efi_snp_device *snpdev =
371  container_of ( snp, struct efi_snp_device, snp );
372  unsigned int i;
373 
374  DBGC ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
375  snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
376  ( ( unsigned long ) mcast_count ) );
377  for ( i = 0 ; i < mcast_count ; i++ ) {
378  DBGC2_HDA ( snpdev, i, &mcast[i],
379  snpdev->netdev->ll_protocol->ll_addr_len );
380  }
381 
382  /* Lie through our teeth, otherwise MNP refuses to accept us.
383  *
384  * Return success even if the SNP device is currently claimed
385  * for use by iPXE, since otherwise Windows Deployment
386  * Services refuses to attempt to receive further packets via
387  * our EFI PXE Base Code protocol.
388  */
389  return 0;
390 }
391 
392 /**
393  * Set station address
394  *
395  * @v snp SNP interface
396  * @v reset Reset to permanent address
397  * @v new New station address
398  * @ret efirc EFI status code
399  */
400 static EFI_STATUS EFIAPI
402  EFI_MAC_ADDRESS *new ) {
403  struct efi_snp_device *snpdev =
404  container_of ( snp, struct efi_snp_device, snp );
405  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
406 
407  DBGC ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
408  ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
409 
410  /* Fail if net device is currently claimed for use by iPXE */
411  if ( efi_snp_claimed )
412  return EFI_NOT_READY;
413 
414  /* Set the MAC address */
415  if ( reset )
416  new = &snpdev->mode.PermanentAddress;
417  memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
418 
419  /* MAC address changes take effect only on netdev_open() */
420  if ( netdev_is_open ( snpdev->netdev ) ) {
421  DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
422  "device open\n", snpdev );
423  }
424 
425  return 0;
426 }
427 
428 /**
429  * Get (or reset) statistics
430  *
431  * @v snp SNP interface
432  * @v reset Reset statistics
433  * @v stats_len Size of statistics table
434  * @v stats Statistics table
435  * @ret efirc EFI status code
436  */
437 static EFI_STATUS EFIAPI
439  UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
440  struct efi_snp_device *snpdev =
441  container_of ( snp, struct efi_snp_device, snp );
442  EFI_NETWORK_STATISTICS stats_buf;
443 
444  DBGC ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
445  ( reset ? " reset" : "" ) );
446 
447  /* Fail if net device is currently claimed for use by iPXE */
448  if ( efi_snp_claimed )
449  return EFI_NOT_READY;
450 
451  /* Gather statistics */
452  memset ( &stats_buf, 0, sizeof ( stats_buf ) );
453  stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
454  stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
455  stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
456  snpdev->netdev->tx_stats.bad );
457  stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
458  stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
459  stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
460  snpdev->netdev->rx_stats.bad );
461  if ( *stats_len > sizeof ( stats_buf ) )
462  *stats_len = sizeof ( stats_buf );
463  if ( stats )
464  memcpy ( stats, &stats_buf, *stats_len );
465 
466  /* Reset statistics if requested to do so */
467  if ( reset ) {
468  memset ( &snpdev->netdev->tx_stats, 0,
469  sizeof ( snpdev->netdev->tx_stats ) );
470  memset ( &snpdev->netdev->rx_stats, 0,
471  sizeof ( snpdev->netdev->rx_stats ) );
472  }
473 
474  return 0;
475 }
476 
477 /**
478  * Convert multicast IP address to MAC address
479  *
480  * @v snp SNP interface
481  * @v ipv6 Address is IPv6
482  * @v ip IP address
483  * @v mac MAC address
484  * @ret efirc EFI status code
485  */
486 static EFI_STATUS EFIAPI
489  struct efi_snp_device *snpdev =
490  container_of ( snp, struct efi_snp_device, snp );
491  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
492  const char *ip_str;
493  int rc;
494 
495  ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
496  inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
497  DBGC ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
498 
499  /* Fail if net device is currently claimed for use by iPXE */
500  if ( efi_snp_claimed )
501  return EFI_NOT_READY;
502 
503  /* Try to hash the address */
504  if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
505  ip, mac ) ) != 0 ) {
506  DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
507  snpdev, ip_str, strerror ( rc ) );
508  return EFIRC ( rc );
509  }
510 
511  return 0;
512 }
513 
514 /**
515  * Read or write non-volatile storage
516  *
517  * @v snp SNP interface
518  * @v read Operation is a read
519  * @v offset Starting offset within NVRAM
520  * @v len Length of data buffer
521  * @v data Data buffer
522  * @ret efirc EFI status code
523  */
524 static EFI_STATUS EFIAPI
526  UINTN offset, UINTN len, VOID *data ) {
527  struct efi_snp_device *snpdev =
528  container_of ( snp, struct efi_snp_device, snp );
529 
530  DBGC ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
531  ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
532  ( ( unsigned long ) len ) );
533  if ( ! read )
534  DBGC2_HDA ( snpdev, offset, data, len );
535 
536  /* Fail if net device is currently claimed for use by iPXE */
537  if ( efi_snp_claimed )
538  return EFI_NOT_READY;
539 
540  return EFI_UNSUPPORTED;
541 }
542 
543 /**
544  * Read interrupt status and TX recycled buffer status
545  *
546  * @v snp SNP interface
547  * @v interrupts Interrupt status, or NULL
548  * @v txbuf Recycled transmit buffer address, or NULL
549  * @ret efirc EFI status code
550  */
551 static EFI_STATUS EFIAPI
553  UINT32 *interrupts, VOID **txbuf ) {
554  struct efi_snp_device *snpdev =
555  container_of ( snp, struct efi_snp_device, snp );
556  struct efi_saved_tpl tpl;
557 
558  DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
559 
560  /* Fail if net device is currently claimed for use by iPXE */
561  if ( efi_snp_claimed ) {
562  DBGC2 ( snpdev, "\n" );
563  return EFI_NOT_READY;
564  }
565 
566  /* Raise TPL */
567  efi_raise_tpl ( &tpl );
568 
569  /* Poll the network device */
570  efi_snp_poll ( snpdev );
571 
572  /* Interrupt status. In practice, this seems to be used only
573  * to detect TX completions.
574  */
575  if ( interrupts ) {
576  *interrupts = snpdev->interrupts;
577  DBGC2 ( snpdev, " INTS:%02x", *interrupts );
578  snpdev->interrupts = 0;
579  }
580 
581  /* TX completions */
582  if ( txbuf ) {
583  if ( snpdev->tx_prod != snpdev->tx_cons ) {
584  *txbuf = snpdev->tx[snpdev->tx_cons++ % EFI_SNP_NUM_TX];
585  } else {
586  *txbuf = NULL;
587  }
588  DBGC2 ( snpdev, " TX:%p", *txbuf );
589  }
590 
591  /* Restore TPL */
592  efi_restore_tpl ( &tpl );
593 
594  DBGC2 ( snpdev, "\n" );
595  return 0;
596 }
597 
598 /**
599  * Start packet transmission
600  *
601  * @v snp SNP interface
602  * @v ll_header_len Link-layer header length, if to be filled in
603  * @v len Length of data buffer
604  * @v data Data buffer
605  * @v ll_src Link-layer source address, if specified
606  * @v ll_dest Link-layer destination address, if specified
607  * @v net_proto Network-layer protocol (in host order)
608  * @ret efirc EFI status code
609  */
610 static EFI_STATUS EFIAPI
612  UINTN ll_header_len, UINTN len, VOID *data,
613  EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
614  UINT16 *net_proto ) {
615  struct efi_snp_device *snpdev =
616  container_of ( snp, struct efi_snp_device, snp );
617  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
618  struct efi_saved_tpl tpl;
619  struct io_buffer *iobuf;
620  size_t payload_len;
621  unsigned int tx_fill;
622  int rc;
623 
624  DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
625  ( ( unsigned long ) len ) );
626  if ( ll_header_len ) {
627  if ( ll_src ) {
628  DBGC2 ( snpdev, " src %s",
629  ll_protocol->ntoa ( ll_src ) );
630  }
631  if ( ll_dest ) {
632  DBGC2 ( snpdev, " dest %s",
633  ll_protocol->ntoa ( ll_dest ) );
634  }
635  if ( net_proto ) {
636  DBGC2 ( snpdev, " proto %04x", *net_proto );
637  }
638  }
639  DBGC2 ( snpdev, "\n" );
640 
641  /* Fail if net device is currently claimed for use by iPXE */
642  if ( efi_snp_claimed ) {
643  rc = -EAGAIN;
644  goto err_claimed;
645  }
646 
647  /* Raise TPL */
648  efi_raise_tpl ( &tpl );
649 
650  /* Sanity checks */
651  if ( ll_header_len ) {
652  if ( ll_header_len != ll_protocol->ll_header_len ) {
653  DBGC ( snpdev, "SNPDEV %p TX invalid header length "
654  "%ld\n", snpdev,
655  ( ( unsigned long ) ll_header_len ) );
656  rc = -EINVAL;
657  goto err_sanity;
658  }
659  if ( len < ll_header_len ) {
660  DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
661  snpdev, ( ( unsigned long ) len ) );
662  rc = -EINVAL;
663  goto err_sanity;
664  }
665  if ( ! ll_dest ) {
666  DBGC ( snpdev, "SNPDEV %p TX missing destination "
667  "address\n", snpdev );
668  rc = -EINVAL;
669  goto err_sanity;
670  }
671  if ( ! net_proto ) {
672  DBGC ( snpdev, "SNPDEV %p TX missing network "
673  "protocol\n", snpdev );
674  rc = -EINVAL;
675  goto err_sanity;
676  }
677  if ( ! ll_src )
678  ll_src = &snpdev->mode.CurrentAddress;
679  }
680 
681  /* Allocate buffer */
682  payload_len = ( len - ll_protocol->ll_header_len );
683  iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ?
684  payload_len : IOB_ZLEN ) );
685  if ( ! iobuf ) {
686  DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
687  "buffer\n", snpdev, ( ( unsigned long ) len ) );
688  rc = -ENOMEM;
689  goto err_alloc_iob;
690  }
691  iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN -
693  memcpy ( iob_put ( iobuf, len ), data, len );
694 
695  /* Create link-layer header, if specified */
696  if ( ll_header_len ) {
697  iob_pull ( iobuf, ll_protocol->ll_header_len );
698  if ( ( rc = ll_protocol->push ( snpdev->netdev,
699  iobuf, ll_dest, ll_src,
700  htons ( *net_proto ) )) != 0 ){
701  DBGC ( snpdev, "SNPDEV %p TX could not construct "
702  "header: %s\n", snpdev, strerror ( rc ) );
703  goto err_ll_push;
704  }
705  }
706 
707  /* Transmit packet */
708  if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
709  DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
710  snpdev, strerror ( rc ) );
711  goto err_tx;
712  }
713 
714  /* Record in transmit completion ring. If we run out of
715  * space, report the failure even though we have already
716  * transmitted the packet.
717  *
718  * This allows us to report completions only for packets for
719  * which we had reported successfully initiating transmission,
720  * while continuing to support clients that never poll for
721  * transmit completions.
722  */
723  tx_fill = ( snpdev->tx_prod - snpdev->tx_cons );
724  if ( tx_fill >= EFI_SNP_NUM_TX ) {
725  DBGC ( snpdev, "SNPDEV %p TX completion ring full\n", snpdev );
726  rc = -ENOBUFS;
727  goto err_ring_full;
728  }
729  snpdev->tx[ snpdev->tx_prod++ % EFI_SNP_NUM_TX ] = data;
731 
732  /* Restore TPL */
733  efi_restore_tpl ( &tpl );
734 
735  return 0;
736 
737  err_ring_full:
738  err_tx:
739  err_ll_push:
740  free_iob ( iobuf );
741  err_alloc_iob:
742  err_sanity:
743  efi_restore_tpl ( &tpl );
744  err_claimed:
745  return EFIRC ( rc );
746 }
747 
748 /**
749  * Receive packet
750  *
751  * @v snp SNP interface
752  * @v ll_header_len Link-layer header length, if to be filled in
753  * @v len Length of data buffer
754  * @v data Data buffer
755  * @v ll_src Link-layer source address, if specified
756  * @v ll_dest Link-layer destination address, if specified
757  * @v net_proto Network-layer protocol (in host order)
758  * @ret efirc EFI status code
759  */
760 static EFI_STATUS EFIAPI
762  UINTN *ll_header_len, UINTN *len, VOID *data,
763  EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
764  UINT16 *net_proto ) {
765  struct efi_snp_device *snpdev =
766  container_of ( snp, struct efi_snp_device, snp );
767  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
768  struct efi_saved_tpl tpl;
769  struct io_buffer *iobuf;
770  const void *iob_ll_dest;
771  const void *iob_ll_src;
772  uint16_t iob_net_proto;
773  unsigned int iob_flags;
774  size_t copy_len;
775  int rc;
776 
777  DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
778  ( ( unsigned long ) *len ) );
779 
780  /* Fail if net device is currently claimed for use by iPXE */
781  if ( efi_snp_claimed ) {
782  rc = -EAGAIN;
783  goto err_claimed;
784  }
785 
786  /* Raise TPL */
787  efi_raise_tpl ( &tpl );
788 
789  /* Poll the network device */
790  efi_snp_poll ( snpdev );
791 
792  /* Check for an available packet */
793  iobuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
794  if ( ! iobuf ) {
795  DBGC2 ( snpdev, "\n" );
796  rc = -EAGAIN;
797  goto out_no_packet;
798  }
799  DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
800 
801  /* Dequeue packet */
802  list_del ( &iobuf->list );
803 
804  /* Return packet to caller, truncating to buffer length */
805  copy_len = iob_len ( iobuf );
806  if ( copy_len > *len )
807  copy_len = *len;
808  memcpy ( data, iobuf->data, copy_len );
809  *len = iob_len ( iobuf );
810 
811  /* Attempt to decode link-layer header */
812  if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
813  &iob_ll_src, &iob_net_proto,
814  &iob_flags ) ) != 0 ) {
815  DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
816  snpdev, strerror ( rc ) );
817  goto out_bad_ll_header;
818  }
819 
820  /* Return link-layer header parameters to caller, if required */
821  if ( ll_header_len )
822  *ll_header_len = ll_protocol->ll_header_len;
823  if ( ll_src )
824  memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
825  if ( ll_dest )
826  memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
827  if ( net_proto )
828  *net_proto = ntohs ( iob_net_proto );
829 
830  /* Check buffer length */
831  rc = ( ( copy_len == *len ) ? 0 : -ERANGE );
832 
833  out_bad_ll_header:
834  free_iob ( iobuf );
835  out_no_packet:
836  efi_restore_tpl ( &tpl );
837  err_claimed:
838  return EFIRC ( rc );
839 }
840 
841 /**
842  * Poll event
843  *
844  * @v event Event
845  * @v context Event context
846  */
848  VOID *context ) {
849  struct efi_snp_device *snpdev = context;
850  struct efi_saved_tpl tpl;
851 
852  DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
853 
854  /* Do nothing unless the net device is open */
855  if ( ! netdev_is_open ( snpdev->netdev ) )
856  return;
857 
858  /* Do nothing if net device is currently claimed for use by iPXE */
859  if ( efi_snp_claimed )
860  return;
861 
862  /* Raise TPL */
863  efi_raise_tpl ( &tpl );
864 
865  /* Poll the network device */
866  efi_snp_poll ( snpdev );
867 
868  /* Restore TPL */
869  efi_restore_tpl ( &tpl );
870 }
871 
872 /** SNP interface */
875  .Start = efi_snp_start,
876  .Stop = efi_snp_stop,
877  .Initialize = efi_snp_initialize,
878  .Reset = efi_snp_reset,
879  .Shutdown = efi_snp_shutdown,
880  .ReceiveFilters = efi_snp_receive_filters,
881  .StationAddress = efi_snp_station_address,
882  .Statistics = efi_snp_statistics,
883  .MCastIpToMac = efi_snp_mcast_ip_to_mac,
884  .NvData = efi_snp_nvdata,
885  .GetStatus = efi_snp_get_status,
886  .Transmit = efi_snp_transmit,
887  .Receive = efi_snp_receive,
888 };
889 
890 /******************************************************************************
891  *
892  * UNDI protocol
893  *
894  ******************************************************************************
895  */
896 
897 /** Union type for command parameter blocks */
898 typedef union {
904 } PXE_CPB_ANY;
905 
906 /** Union type for data blocks */
907 typedef union {
912 } PXE_DB_ANY;
913 
914 /**
915  * Calculate UNDI byte checksum
916  *
917  * @v data Data
918  * @v len Length of data
919  * @ret sum Checksum
920  */
921 static uint8_t efi_undi_checksum ( void *data, size_t len ) {
922  uint8_t *bytes = data;
923  uint8_t sum = 0;
924 
925  while ( len-- )
926  sum += *bytes++;
927  return sum;
928 }
929 
930 /**
931  * Get UNDI SNP device interface number
932  *
933  * @v snpdev SNP device
934  * @ret ifnum UNDI interface number
935  */
936 static unsigned int efi_undi_ifnum ( struct efi_snp_device *snpdev ) {
937 
938  /* iPXE network device scope IDs are one-based (leaving zero
939  * meaning "unspecified"). UNDI interface numbers are
940  * zero-based.
941  */
942  return ( snpdev->netdev->scope_id - 1 );
943 }
944 
945 /**
946  * Identify UNDI SNP device
947  *
948  * @v ifnum Interface number
949  * @ret snpdev SNP device, or NULL if not found
950  */
951 static struct efi_snp_device * efi_undi_snpdev ( unsigned int ifnum ) {
952  struct efi_snp_device *snpdev;
953 
954  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
955  if ( efi_undi_ifnum ( snpdev ) == ifnum )
956  return snpdev;
957  }
958  return NULL;
959 }
960 
961 /**
962  * Convert EFI status code to UNDI status code
963  *
964  * @v efirc EFI status code
965  * @ret statcode UNDI status code
966  */
968 
969  switch ( efirc ) {
974  case EFI_NOT_READY: return PXE_STATCODE_NO_DATA;
975  default:
977  }
978 }
979 
980 /**
981  * Get state
982  *
983  * @v snpdev SNP device
984  * @v cdb Command description block
985  * @ret efirc EFI status code
986  */
988  PXE_CDB *cdb ) {
989  EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
990 
991  DBGC ( snpdev, "UNDI %p GET STATE\n", snpdev );
992 
993  /* Return current state */
994  if ( mode->State == EfiSimpleNetworkInitialized ) {
996  } else if ( mode->State == EfiSimpleNetworkStarted ) {
998  } else {
1000  }
1001 
1002  return 0;
1003 }
1004 
1005 /**
1006  * Start
1007  *
1008  * @v snpdev SNP device
1009  * @ret efirc EFI status code
1010  */
1011 static EFI_STATUS efi_undi_start ( struct efi_snp_device *snpdev ) {
1012  EFI_STATUS efirc;
1013 
1014  DBGC ( snpdev, "UNDI %p START\n", snpdev );
1015 
1016  /* Start SNP device */
1017  if ( ( efirc = efi_snp_start ( &snpdev->snp ) ) != 0 )
1018  return efirc;
1019 
1020  return 0;
1021 }
1022 
1023 /**
1024  * Stop
1025  *
1026  * @v snpdev SNP device
1027  * @ret efirc EFI status code
1028  */
1029 static EFI_STATUS efi_undi_stop ( struct efi_snp_device *snpdev ) {
1030  EFI_STATUS efirc;
1031 
1032  DBGC ( snpdev, "UNDI %p STOP\n", snpdev );
1033 
1034  /* Stop SNP device */
1035  if ( ( efirc = efi_snp_stop ( &snpdev->snp ) ) != 0 )
1036  return efirc;
1037 
1038  return 0;
1039 }
1040 
1041 /**
1042  * Get initialisation information
1043  *
1044  * @v snpdev SNP device
1045  * @v cdb Command description block
1046  * @v db Data block
1047  * @ret efirc EFI status code
1048  */
1050  PXE_CDB *cdb,
1052  struct net_device *netdev = snpdev->netdev;
1054 
1055  DBGC ( snpdev, "UNDI %p GET INIT INFO\n", snpdev );
1056 
1057  /* Populate structure */
1058  memset ( db, 0, sizeof ( *db ) );
1059  db->FrameDataLen = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
1060  db->MediaHeaderLen = ll_protocol->ll_header_len;
1061  db->HWaddrLen = ll_protocol->ll_addr_len;
1062  db->IFtype = ntohs ( ll_protocol->ll_proto );
1065 
1066  return 0;
1067 }
1068 
1069 /**
1070  * Initialise
1071  *
1072  * @v snpdev SNP device
1073  * @v cdb Command description block
1074  * @v efirc EFI status code
1075  */
1077  PXE_CDB *cdb ) {
1078  struct net_device *netdev = snpdev->netdev;
1079  EFI_STATUS efirc;
1080 
1081  DBGC ( snpdev, "UNDI %p INITIALIZE\n", snpdev );
1082 
1083  /* Reset SNP device */
1084  if ( ( efirc = efi_snp_initialize ( &snpdev->snp, 0, 0 ) ) != 0 )
1085  return efirc;
1086 
1087  /* Report link state */
1088  if ( ! netdev_link_ok ( netdev ) )
1090 
1091  return 0;
1092 }
1093 
1094 /**
1095  * Reset
1096  *
1097  * @v snpdev SNP device
1098  * @v efirc EFI status code
1099  */
1100 static EFI_STATUS efi_undi_reset ( struct efi_snp_device *snpdev ) {
1101  EFI_STATUS efirc;
1102 
1103  DBGC ( snpdev, "UNDI %p RESET\n", snpdev );
1104 
1105  /* Reset SNP device */
1106  if ( ( efirc = efi_snp_reset ( &snpdev->snp, 0 ) ) != 0 )
1107  return efirc;
1108 
1109  return 0;
1110 }
1111 
1112 /**
1113  * Shutdown
1114  *
1115  * @v snpdev SNP device
1116  * @v efirc EFI status code
1117  */
1118 static EFI_STATUS efi_undi_shutdown ( struct efi_snp_device *snpdev ) {
1119  EFI_STATUS efirc;
1120 
1121  DBGC ( snpdev, "UNDI %p SHUTDOWN\n", snpdev );
1122 
1123  /* Reset SNP device */
1124  if ( ( efirc = efi_snp_shutdown ( &snpdev->snp ) ) != 0 )
1125  return efirc;
1126 
1127  return 0;
1128 }
1129 
1130 /**
1131  * Get/set receive filters
1132  *
1133  * @v snpdev SNP device
1134  * @v cdb Command description block
1135  * @v efirc EFI status code
1136  */
1138  PXE_CDB *cdb ) {
1139 
1140  DBGC ( snpdev, "UNDI %p RECEIVE FILTERS\n", snpdev );
1141 
1142  /* Mark everything as supported */
1147 
1148  return 0;
1149 }
1150 
1151 /**
1152  * Get/set station address
1153  *
1154  * @v snpdev SNP device
1155  * @v cdb Command description block
1156  * @v cpb Command parameter block
1157  * @v efirc EFI status code
1158  */
1160  PXE_CDB *cdb,
1163  struct net_device *netdev = snpdev->netdev;
1165  void *mac;
1166  int reset;
1167  EFI_STATUS efirc;
1168 
1169  DBGC ( snpdev, "UNDI %p STATION ADDRESS\n", snpdev );
1170 
1171  /* Update address if applicable */
1172  reset = ( cdb->OpFlags & PXE_OPFLAGS_STATION_ADDRESS_RESET );
1173  mac = ( cpb ? &cpb->StationAddr : NULL );
1174  if ( ( reset || mac ) &&
1175  ( ( efirc = efi_snp_station_address ( &snpdev->snp, reset,
1176  mac ) ) != 0 ) )
1177  return efirc;
1178 
1179  /* Fill in current addresses, if applicable */
1180  if ( db ) {
1181  memset ( db, 0, sizeof ( *db ) );
1182  memcpy ( &db->StationAddr, netdev->ll_addr,
1184  memcpy ( &db->BroadcastAddr, netdev->ll_broadcast,
1186  memcpy ( &db->PermanentAddr, netdev->hw_addr,
1188  }
1189 
1190  return 0;
1191 }
1192 
1193 /**
1194  * Get interrupt status
1195  *
1196  * @v snpdev SNP device
1197  * @v cdb Command description block
1198  * @v db Data block
1199  * @v efirc EFI status code
1200  */
1202  PXE_CDB *cdb, PXE_DB_GET_STATUS *db ) {
1203  UINT32 interrupts;
1204  VOID *txbuf;
1205  struct io_buffer *rxbuf;
1206  EFI_STATUS efirc;
1207 
1208  DBGC2 ( snpdev, "UNDI %p GET STATUS\n", snpdev );
1209 
1210  /* Get status */
1211  if ( ( efirc = efi_snp_get_status ( &snpdev->snp, &interrupts,
1212  &txbuf ) ) != 0 )
1213  return efirc;
1214 
1215  /* Report status */
1216  memset ( db, 0, sizeof ( *db ) );
1217  if ( interrupts & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT )
1219  if ( interrupts & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT )
1221  if ( txbuf ) {
1222  db->TxBuffer[0] = ( ( intptr_t ) txbuf );
1223  } else {
1225  /* The specification states clearly that UNDI drivers
1226  * should set TXBUF_QUEUE_EMPTY if all completed
1227  * buffer addresses are written into the returned data
1228  * block. However, SnpDxe chooses to interpret
1229  * TXBUF_QUEUE_EMPTY as a synonym for
1230  * NO_TXBUFS_WRITTEN, thereby rendering it entirely
1231  * pointless. Work around this UEFI stupidity, as per
1232  * usual.
1233  */
1234  if ( snpdev->tx_prod == snpdev->tx_cons )
1235  cdb->StatFlags |=
1237  }
1238  rxbuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
1239  if ( rxbuf )
1240  db->RxFrameLen = iob_len ( rxbuf );
1241  if ( ! netdev_link_ok ( snpdev->netdev ) )
1243 
1244  return 0;
1245 }
1246 
1247 /**
1248  * Fill header
1249  *
1250  * @v snpdev SNP device
1251  * @v cdb Command description block
1252  * @v cpb Command parameter block
1253  * @v efirc EFI status code
1254  */
1256  PXE_CDB *cdb, PXE_CPB_ANY *cpb ) {
1257  struct net_device *netdev = snpdev->netdev;
1259  PXE_CPB_FILL_HEADER *whole = &cpb->fill_header;
1261  VOID *data;
1262  void *dest;
1263  void *src;
1264  uint16_t proto;
1265  struct io_buffer iobuf;
1266  int rc;
1267 
1268  /* SnpDxe will (pointlessly) use PXE_CPB_FILL_HEADER_FRAGMENTED
1269  * even though we choose to explicitly not claim support for
1270  * fragments via PXE_ROMID_IMP_FRAG_SUPPORTED.
1271  */
1273  data = ( ( void * ) ( intptr_t ) fragged->FragDesc[0].FragAddr);
1274  dest = &fragged->DestAddr;
1275  src = &fragged->SrcAddr;
1276  proto = fragged->Protocol;
1277  } else {
1278  data = ( ( void * ) ( intptr_t ) whole->MediaHeader );
1279  dest = &whole->DestAddr;
1280  src = &whole->SrcAddr;
1281  proto = whole->Protocol;
1282  }
1283 
1284  /* Construct link-layer header */
1285  iob_populate ( &iobuf, data, 0, ll_protocol->ll_header_len );
1286  iob_reserve ( &iobuf, ll_protocol->ll_header_len );
1287  if ( ( rc = ll_protocol->push ( netdev, &iobuf, dest, src,
1288  proto ) ) != 0 )
1289  return EFIRC ( rc );
1290 
1291  return 0;
1292 }
1293 
1294 /**
1295  * Transmit
1296  *
1297  * @v snpdev SNP device
1298  * @v cpb Command parameter block
1299  * @v efirc EFI status code
1300  */
1302  PXE_CPB_TRANSMIT *cpb ) {
1303  VOID *data = ( ( void * ) ( intptr_t ) cpb->FrameAddr );
1304  EFI_STATUS efirc;
1305 
1306  DBGC2 ( snpdev, "UNDI %p TRANSMIT\n", snpdev );
1307 
1308  /* Transmit packet */
1309  if ( ( efirc = efi_snp_transmit ( &snpdev->snp, 0, cpb->DataLen,
1310  data, NULL, NULL, NULL ) ) != 0 )
1311  return efirc;
1312 
1313  return 0;
1314 }
1315 
1316 /**
1317  * Receive
1318  *
1319  * @v snpdev SNP device
1320  * @v cpb Command parameter block
1321  * @v efirc EFI status code
1322  */
1324  PXE_CPB_RECEIVE *cpb,
1325  PXE_DB_RECEIVE *db ) {
1326  struct net_device *netdev = snpdev->netdev;
1328  VOID *data = ( ( void * ) ( intptr_t ) cpb->BufferAddr );
1329  UINTN hdr_len;
1330  UINTN len = cpb->BufferLen;
1333  UINT16 proto;
1334  EFI_STATUS efirc;
1335 
1336  DBGC2 ( snpdev, "UNDI %p RECEIVE\n", snpdev );
1337 
1338  /* Receive packet */
1339  if ( ( efirc = efi_snp_receive ( &snpdev->snp, &hdr_len, &len, data,
1340  &src, &dest, &proto ) ) != 0 )
1341  return efirc;
1342 
1343  /* Describe frame */
1344  memset ( db, 0, sizeof ( *db ) );
1345  memcpy ( &db->SrcAddr, &src, ll_protocol->ll_addr_len );
1346  memcpy ( &db->DestAddr, &dest, ll_protocol->ll_addr_len );
1347  db->FrameLen = len;
1348  db->Protocol = proto;
1349  db->MediaHeaderLen = ll_protocol->ll_header_len;
1351 
1352  return 0;
1353 }
1354 
1355 /** UNDI entry point */
1356 static EFIAPI VOID efi_undi_issue ( UINT64 cdb_phys ) {
1357  PXE_CDB *cdb = ( ( void * ) ( intptr_t ) cdb_phys );
1358  PXE_CPB_ANY *cpb = ( ( void * ) ( intptr_t ) cdb->CPBaddr );
1359  PXE_DB_ANY *db = ( ( void * ) ( intptr_t ) cdb->DBaddr );
1360  struct efi_snp_device *snpdev;
1361  EFI_STATUS efirc;
1362 
1363  /* Identify device */
1364  snpdev = efi_undi_snpdev ( cdb->IFnum );
1365  if ( ! snpdev ) {
1366  DBGC ( cdb, "UNDI invalid interface number %d\n", cdb->IFnum );
1369  return;
1370  }
1371 
1372  /* Fail if net device is currently claimed for use by iPXE */
1373  if ( efi_snp_claimed ) {
1374  cdb->StatCode = PXE_STATCODE_BUSY;
1376  return;
1377  }
1378 
1379  /* Handle opcode */
1382  switch ( cdb->OpCode ) {
1383 
1384  case PXE_OPCODE_GET_STATE:
1385  efirc = efi_undi_get_state ( snpdev, cdb );
1386  break;
1387 
1388  case PXE_OPCODE_START:
1389  efirc = efi_undi_start ( snpdev );
1390  break;
1391 
1392  case PXE_OPCODE_STOP:
1393  efirc = efi_undi_stop ( snpdev );
1394  break;
1395 
1397  efirc = efi_undi_get_init_info ( snpdev, cdb,
1398  &db->get_init_info );
1399  break;
1400 
1401  case PXE_OPCODE_INITIALIZE:
1402  efirc = efi_undi_initialize ( snpdev, cdb );
1403  break;
1404 
1405  case PXE_OPCODE_RESET:
1406  efirc = efi_undi_reset ( snpdev );
1407  break;
1408 
1409  case PXE_OPCODE_SHUTDOWN:
1410  efirc = efi_undi_shutdown ( snpdev );
1411  break;
1412 
1414  efirc = efi_undi_receive_filters ( snpdev, cdb );
1415  break;
1416 
1418  efirc = efi_undi_station_address ( snpdev, cdb,
1419  &cpb->station_address,
1420  &db->station_address );
1421  break;
1422 
1423  case PXE_OPCODE_GET_STATUS:
1424  efirc = efi_undi_get_status ( snpdev, cdb, &db->get_status );
1425  break;
1426 
1428  efirc = efi_undi_fill_header ( snpdev, cdb, cpb );
1429  break;
1430 
1431  case PXE_OPCODE_TRANSMIT:
1432  efirc = efi_undi_transmit ( snpdev, &cpb->transmit );
1433  break;
1434 
1435  case PXE_OPCODE_RECEIVE:
1436  efirc = efi_undi_receive ( snpdev, &cpb->receive,
1437  &db->receive );
1438  break;
1439 
1440  default:
1441  DBGC ( snpdev, "UNDI %p unsupported opcode %#04x\n",
1442  snpdev, cdb->OpCode );
1443  efirc = EFI_UNSUPPORTED;
1444  break;
1445  }
1446 
1447  /* Convert EFI status code to UNDI status code */
1448  if ( efirc != 0 ) {
1451  cdb->StatCode = efi_undi_statcode ( efirc );
1452  }
1453 }
1454 
1455 /** UNDI interface
1456  *
1457  * Must be aligned on a 16-byte boundary, for no particularly good
1458  * reason.
1459  */
1460 static PXE_SW_UNDI efi_snp_undi __attribute__ (( aligned ( 16 ) )) = {
1461  .Signature = PXE_ROMID_SIGNATURE,
1462  .Len = sizeof ( efi_snp_undi ),
1463  .Rev = PXE_ROMID_REV,
1464  .MajorVer = PXE_ROMID_MAJORVER,
1465  .MinorVer = PXE_ROMID_MINORVER,
1466  .Implementation = ( PXE_ROMID_IMP_SW_VIRT_ADDR |
1473  /* SnpDxe checks that BusCnt is non-zero. It makes no further
1474  * use of BusCnt, and never looks as BusType[]. As with much
1475  * of the EDK2 code, this check seems to serve no purpose
1476  * whatsoever but must nonetheless be humoured.
1477  */
1478  .BusCnt = 1,
1479  .BusType[0] = PXE_BUSTYPE ( 'i', 'P', 'X', 'E' ),
1480 };
1481 
1482 /** Network Identification Interface (NII) */
1485  .StringId = "UNDI",
1486  .Type = EfiNetworkInterfaceUndi,
1487  .MajorVer = 3,
1488  .MinorVer = 1,
1489  .Ipv6Supported = TRUE, /* This is a raw packet interface, FFS! */
1490 };
1491 
1492 /******************************************************************************
1493  *
1494  * VLAN configuration protocol
1495  *
1496  ******************************************************************************
1497  */
1498 
1499 /**
1500  * Create or modify VLAN device
1501  *
1502  * @v vcfg VLAN configuration protocol
1503  * @v tag VLAN tag
1504  * @v priority Default VLAN priority
1505  * @ret efirc EFI status code
1506  */
1508  UINT16 tag, UINT8 priority ) {
1509  struct efi_snp_device *snpdev =
1510  container_of ( vcfg, struct efi_snp_device, vcfg );
1511  struct net_device *trunk = snpdev->netdev;
1512  struct efi_saved_tpl tpl;
1513  int rc;
1514 
1515  /* Raise TPL */
1516  efi_raise_tpl ( &tpl );
1517 
1518  /* Create or modify VLAN device */
1519  if ( ( rc = vlan_create ( trunk, tag, priority ) ) != 0 ) {
1520  DBGC ( snpdev, "SNPDEV %p could not create VLAN tag %d: %s\n",
1521  snpdev, tag, strerror ( rc ) );
1522  goto err_create;
1523  }
1524  DBGC ( snpdev, "SNPDEV %p created VLAN tag %d priority %d\n",
1525  snpdev, tag, priority );
1526 
1527  err_create:
1528  efi_restore_tpl ( &tpl );
1529  return EFIRC ( rc );
1530 }
1531 
1532 /**
1533  * Find VLAN device(s)
1534  *
1535  * @v vcfg VLAN configuration protocol
1536  * @v filter VLAN tag, or NULL to find all VLANs
1537  * @v count Number of VLANs
1538  * @v entries List of VLANs
1539  * @ret efirc EFI status code
1540  */
1543  EFI_VLAN_FIND_DATA **entries ) {
1545  struct efi_snp_device *snpdev =
1546  container_of ( vcfg, struct efi_snp_device, vcfg );
1547  struct net_device *trunk = snpdev->netdev;
1548  struct net_device *vlan;
1549  struct efi_saved_tpl tpl;
1550  EFI_VLAN_FIND_DATA *entry;
1551  VOID *buffer;
1552  unsigned int tag;
1553  unsigned int tci;
1554  size_t len;
1555  EFI_STATUS efirc;
1556  int rc;
1557 
1558  /* Raise TPL */
1559  efi_raise_tpl ( &tpl );
1560 
1561  /* Count number of matching VLANs */
1562  *count = 0;
1563  for ( tag = 1 ; VLAN_TAG_IS_VALID ( tag ) ; tag++ ) {
1564  if ( filter && ( tag != *filter ) )
1565  continue;
1566  if ( ! ( vlan = vlan_find ( trunk, tag ) ) )
1567  continue;
1568  (*count)++;
1569  }
1570 
1571  /* Allocate buffer to hold results */
1572  len = ( (*count) * sizeof ( *entry ) );
1573  if ( ( efirc = bs->AllocatePool ( EfiBootServicesData, len,
1574  &buffer ) ) != 0 ) {
1575  rc = -EEFI ( efirc );
1576  goto err_alloc;
1577  }
1578 
1579  /* Fill in buffer */
1580  *entries = buffer;
1581  entry = *entries;
1582  for ( tag = 1 ; VLAN_TAG_IS_VALID ( tag ) ; tag++ ) {
1583  if ( filter && ( tag != *filter ) )
1584  continue;
1585  if ( ! ( vlan = vlan_find ( trunk, tag ) ) )
1586  continue;
1587  tci = vlan_tci ( vlan );
1588  entry->VlanId = VLAN_TAG ( tci );
1589  entry->Priority = VLAN_PRIORITY ( tci );
1590  assert ( entry->VlanId == tag );
1591  entry++;
1592  }
1593  assert ( entry == &(*entries)[*count] );
1594 
1595  /* Success */
1596  rc = 0;
1597 
1598  err_alloc:
1599  efi_restore_tpl ( &tpl );
1600  return EFIRC ( rc );
1601 }
1602 
1603 /**
1604  * Remove VLAN device
1605  *
1606  * @v vcfg VLAN configuration protocol
1607  * @v tag VLAN tag
1608  * @ret efirc EFI status code
1609  */
1611  UINT16 tag ) {
1612  struct efi_snp_device *snpdev =
1613  container_of ( vcfg, struct efi_snp_device, vcfg );
1614  struct net_device *trunk = snpdev->netdev;
1615  struct net_device *vlan;
1616  struct efi_saved_tpl tpl;
1617  int rc;
1618 
1619  /* Raise TPL */
1620  efi_raise_tpl ( &tpl );
1621 
1622  /* Identify VLAN device */
1623  vlan = vlan_find ( trunk, tag );
1624  if ( ! vlan ) {
1625  DBGC ( snpdev, "SNPDEV %p could not find VLAN tag %d\n",
1626  snpdev, tag );
1627  rc = -ENOENT;
1628  goto err_find;
1629  }
1630 
1631  /* Remove VLAN device */
1632  vlan_destroy ( vlan );
1633  DBGC ( snpdev, "SNPDEV %p removed VLAN tag %d\n", snpdev, tag );
1634 
1635  /* Success */
1636  rc = 0;
1637 
1638  err_find:
1639  efi_restore_tpl ( &tpl );
1640  return EFIRC ( rc );
1641 }
1642 
1643 /** VLAN configuration protocol */
1645  .Set = efi_vlan_set,
1646  .Find = efi_vlan_find,
1647  .Remove = efi_vlan_remove,
1648 };
1649 
1650 /******************************************************************************
1651  *
1652  * Component name protocol
1653  *
1654  ******************************************************************************
1655  */
1656 
1657 /**
1658  * Look up driver name
1659  *
1660  * @v name2 Component name protocol
1661  * @v language Language to use
1662  * @v driver_name Driver name to fill in
1663  * @ret efirc EFI status code
1664  */
1665 static EFI_STATUS EFIAPI
1667  CHAR8 *language __unused, CHAR16 **driver_name ) {
1668  struct efi_snp_device *snpdev =
1669  container_of ( name2, struct efi_snp_device, name2 );
1670 
1671  *driver_name = snpdev->driver_name;
1672  return 0;
1673 }
1674 
1675 /**
1676  * Look up controller name
1677  *
1678  * @v name2 Component name protocol
1679  * @v device Device
1680  * @v child Child device, or NULL
1681  * @v language Language to use
1682  * @v driver_name Device name to fill in
1683  * @ret efirc EFI status code
1684  */
1685 static EFI_STATUS EFIAPI
1688  EFI_HANDLE child __unused,
1689  CHAR8 *language __unused,
1690  CHAR16 **controller_name ) {
1691  struct efi_snp_device *snpdev =
1692  container_of ( name2, struct efi_snp_device, name2 );
1693 
1694  *controller_name = snpdev->controller_name;
1695  return 0;
1696 }
1697 
1698 /******************************************************************************
1699  *
1700  * Load file protocol
1701  *
1702  ******************************************************************************
1703  */
1704 
1705 /**
1706  * Load file
1707  *
1708  * @v loadfile Load file protocol
1709  * @v path File path
1710  * @v booting Loading as part of a boot attempt
1711  * @ret efirc EFI status code
1712  */
1713 static EFI_STATUS EFIAPI
1716  BOOLEAN booting, UINTN *len __unused,
1717  VOID *data __unused ) {
1718  struct efi_snp_device *snpdev =
1720  struct net_device *netdev = snpdev->netdev;
1721  int rc;
1722 
1723  /* Fail unless this is a boot attempt */
1724  if ( ! booting ) {
1725  DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
1726  snpdev );
1727  return EFI_UNSUPPORTED;
1728  }
1729 
1730  /* Claim network devices for use by iPXE */
1731  efi_snp_claim();
1732 
1733  /* Start watchdog holdoff timer */
1735 
1736  /* Boot from network device */
1737  if ( ( rc = ipxe ( netdev ) ) != 0 )
1738  goto err_ipxe;
1739 
1740  /* Reset console */
1741  console_reset();
1742 
1743  err_ipxe:
1745  efi_snp_release();
1746  return EFIRC ( rc );
1747 }
1748 
1749 /** Load file protocol */
1752 };
1753 
1754 /******************************************************************************
1755  *
1756  * iPXE network driver
1757  *
1758  ******************************************************************************
1759  */
1760 
1761 /**
1762  * Locate SNP device corresponding to network device
1763  *
1764  * @v netdev Network device
1765  * @ret snp SNP device, or NULL if not found
1766  */
1767 static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
1768  struct efi_snp_device *snpdev;
1769 
1770  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
1771  if ( snpdev->netdev == netdev )
1772  return snpdev;
1773  }
1774  return NULL;
1775 }
1776 
1777 /**
1778  * Create SNP device
1779  *
1780  * @v netdev Network device
1781  * @v priv Private data
1782  * @ret rc Return status code
1783  */
1784 static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) {
1786  struct efi_device *efidev;
1787  struct efi_snp_device *snpdev;
1788  unsigned int ifcnt;
1789  void *interface;
1790  unsigned int tci;
1791  char vlan_name[ 12 /* ", VLAN xxxx" + NUL */ ];
1792  int leak = 0;
1793  EFI_STATUS efirc;
1794  int rc;
1795 
1796  /* Allocate the SNP device */
1797  snpdev = zalloc ( sizeof ( *snpdev ) );
1798  if ( ! snpdev ) {
1799  rc = -ENOMEM;
1800  goto err_alloc_snp;
1801  }
1802  snpdev->netdev = netdev_get ( netdev );
1803  INIT_LIST_HEAD ( &snpdev->rx );
1804 
1805  /* Find parent EFI device, if any */
1806  efidev = efidev_parent ( netdev->dev );
1807  if ( efidev )
1808  snpdev->parent = efidev->device;
1809 
1810  /* Sanity check */
1811  if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
1812  DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
1813  "length %d for %s\n", snpdev,
1815  rc = -ENOTSUP;
1816  goto err_ll_addr_len;
1817  }
1818 
1819  /* Populate the SNP structure */
1820  memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
1821  snpdev->snp.Mode = &snpdev->mode;
1822  if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
1823  efi_snp_wait_for_packet, snpdev,
1824  &snpdev->snp.WaitForPacket ) ) != 0 ){
1825  rc = -EEFI ( efirc );
1826  DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
1827  snpdev, strerror ( rc ) );
1828  goto err_create_event;
1829  }
1830 
1831  /* Populate the SNP mode structure */
1833  efi_snp_set_mode ( snpdev );
1834 
1835  /* Populate the NII structure */
1836  memcpy ( &snpdev->nii, &efi_snp_device_nii, sizeof ( snpdev->nii ) );
1837  snpdev->nii.Id = ( ( intptr_t ) &efi_snp_undi );
1838  snpdev->nii.IfNum = efi_undi_ifnum ( snpdev );
1840  ifcnt = ( ( efi_snp_undi.IFcntExt << 8 ) | efi_snp_undi.IFcnt );
1841  if ( ifcnt < snpdev->nii.IfNum )
1842  ifcnt = snpdev->nii.IfNum;
1843  efi_snp_undi.IFcnt = ( ifcnt & 0xff );
1844  efi_snp_undi.IFcntExt = ( ifcnt >> 8 );
1846  sizeof ( efi_snp_undi ) );
1847 
1848  /* Populate the VLAN configuration protocol */
1849  memcpy ( &snpdev->vcfg, &efi_vlan, sizeof ( snpdev->vcfg ) );
1850 
1851  /* Populate the component name structure */
1852  efi_snprintf ( snpdev->driver_name,
1853  ( sizeof ( snpdev->driver_name ) /
1854  sizeof ( snpdev->driver_name[0] ) ),
1855  "%s %s", product_short_name, netdev->dev->driver_name );
1856  tci = vlan_tci ( netdev );
1857  if ( tci ) {
1858  snprintf ( vlan_name, sizeof ( vlan_name ), ", VLAN %d",
1859  VLAN_TAG ( tci ) );
1860  } else {
1861  vlan_name[0] = '\0';
1862  }
1863  efi_snprintf ( snpdev->controller_name,
1864  ( sizeof ( snpdev->controller_name ) /
1865  sizeof ( snpdev->controller_name[0] ) ),
1866  "%s %s (%s, %s%s)", product_short_name,
1868  netdev_addr ( netdev ), vlan_name );
1871  snpdev->name2.SupportedLanguages = "en";
1872 
1873  /* Populate the load file protocol structure */
1875  sizeof ( snpdev->load_file ) );
1876 
1877  /* Populate the device name */
1878  efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
1879  sizeof ( snpdev->name[0] ) ),
1880  "%s", netdev->name );
1881 
1882  /* Construct device path */
1883  snpdev->path = efi_netdev_path ( netdev );
1884  if ( ! snpdev->path ) {
1885  rc = -ENOMEM;
1886  goto err_path;
1887  }
1888 
1889  /* Install the SNP */
1890  if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1891  &snpdev->handle,
1894  &efi_nii_protocol_guid, &snpdev->nii,
1895  &efi_nii31_protocol_guid, &snpdev->nii,
1899  NULL ) ) != 0 ) {
1900  rc = -EEFI ( efirc );
1901  DBGC ( snpdev, "SNPDEV %p could not install protocols: %s\n",
1902  snpdev, strerror ( rc ) );
1903  goto err_install_protocol_interface;
1904  }
1905 
1906  /* SnpDxe will repeatedly start up and shut down our NII/UNDI
1907  * interface (in order to obtain the MAC address) before
1908  * discovering that it cannot install another SNP on the same
1909  * handle. This causes the underlying network device to be
1910  * unexpectedly closed.
1911  *
1912  * Prevent this by opening our own NII (and NII31) protocol
1913  * instances to prevent SnpDxe from attempting to bind to
1914  * them.
1915  */
1916  if ( ( rc = efi_open_by_driver ( snpdev->handle,
1918  &interface ) ) != 0 ) {
1919  DBGC ( snpdev, "SNPDEV %p could not open NII protocol: %s\n",
1920  snpdev, strerror ( rc ) );
1921  goto err_open_nii;
1922  }
1923  if ( ( rc = efi_open_by_driver ( snpdev->handle,
1925  &interface ) ) != 0 ) {
1926  DBGC ( snpdev, "SNPDEV %p could not open NII31 protocol: %s\n",
1927  snpdev, strerror ( rc ) );
1928  goto err_open_nii31;
1929  }
1930 
1931  /* Add as child of EFI parent device, if applicable */
1932  if ( snpdev->parent &&
1933  ( ( rc = efi_child_add ( snpdev->parent,
1934  snpdev->handle ) ) != 0 ) ) {
1935  DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n",
1936  snpdev, efi_handle_name ( efidev->device ),
1937  strerror ( rc ) );
1938  goto err_efi_child_add;
1939  }
1940 
1941  /* Install HII */
1942  if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
1943  DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
1944  snpdev, strerror ( rc ) );
1945  /* HII fails on several platforms. It's
1946  * non-essential, so treat this as a non-fatal
1947  * error.
1948  */
1949  }
1950 
1951  /* Add to list of SNP devices */
1952  list_add ( &snpdev->list, &efi_snp_devices );
1953 
1954  DBGC ( snpdev, "SNPDEV %p installed for %s as device %s\n",
1955  snpdev, netdev->name, efi_handle_name ( snpdev->handle ) );
1956  return 0;
1957 
1958  list_del ( &snpdev->list );
1959  if ( snpdev->package_list )
1960  leak |= efi_snp_hii_uninstall ( snpdev );
1961  if ( snpdev->parent )
1962  efi_child_del ( snpdev->parent, snpdev->handle );
1963  err_efi_child_add:
1965  err_open_nii31:
1967  err_open_nii:
1968  if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1969  snpdev->handle,
1972  &efi_nii_protocol_guid, &snpdev->nii,
1973  &efi_nii31_protocol_guid, &snpdev->nii,
1977  NULL ) ) != 0 ) {
1978  DBGC ( snpdev, "SNPDEV %p could not uninstall: %s\n",
1979  snpdev, strerror ( -EEFI ( efirc ) ) );
1980  leak = 1;
1981  }
1982  efi_nullify_snp ( &snpdev->snp );
1983  efi_nullify_nii ( &snpdev->nii );
1984  efi_nullify_vlan ( &snpdev->vcfg );
1985  efi_nullify_name2 ( &snpdev->name2 );
1986  efi_nullify_load_file ( &snpdev->load_file );
1987  err_install_protocol_interface:
1988  if ( ! leak )
1989  free ( snpdev->path );
1990  err_path:
1991  bs->CloseEvent ( snpdev->snp.WaitForPacket );
1992  err_create_event:
1993  err_ll_addr_len:
1994  if ( ! leak ) {
1995  netdev_put ( netdev );
1996  free ( snpdev );
1997  }
1998  err_alloc_snp:
1999  if ( leak )
2000  DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
2001  return rc;
2002 }
2003 
2004 /**
2005  * Handle SNP device or link state change
2006  *
2007  * @v netdev Network device
2008  * @v priv Private data
2009  */
2010 static void efi_snp_notify ( struct net_device *netdev, void *priv __unused ) {
2011  struct efi_snp_device *snpdev;
2012 
2013  /* Locate SNP device */
2014  snpdev = efi_snp_demux ( netdev );
2015  if ( ! snpdev ) {
2016  DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
2017  return;
2018  }
2019 
2020  /* Update link state */
2021  snpdev->mode.MediaPresent =
2022  ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
2023  DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
2024  ( snpdev->mode.MediaPresent ? "up" : "down" ) );
2025 
2026  /* Update mode state */
2027  efi_snp_set_state ( snpdev );
2028 }
2029 
2030 /**
2031  * Destroy SNP device
2032  *
2033  * @v netdev Network device
2034  * @v priv Private data
2035  */
2036 static void efi_snp_remove ( struct net_device *netdev, void *priv __unused ) {
2038  struct efi_snp_device *snpdev;
2039  int leak = efi_shutdown_in_progress;
2040  EFI_STATUS efirc;
2041 
2042  /* Locate SNP device */
2043  snpdev = efi_snp_demux ( netdev );
2044  if ( ! snpdev ) {
2045  DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
2046  return;
2047  }
2048 
2049  /* Uninstall the SNP */
2050  list_del ( &snpdev->list );
2051  if ( snpdev->package_list )
2052  leak |= efi_snp_hii_uninstall ( snpdev );
2053  if ( snpdev->parent )
2054  efi_child_del ( snpdev->parent, snpdev->handle );
2057  if ( ( ! efi_shutdown_in_progress ) &&
2058  ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
2059  snpdev->handle,
2062  &efi_nii_protocol_guid, &snpdev->nii,
2063  &efi_nii31_protocol_guid, &snpdev->nii,
2067  NULL ) ) != 0 ) ) {
2068  DBGC ( snpdev, "SNPDEV %p could not uninstall: %s\n",
2069  snpdev, strerror ( -EEFI ( efirc ) ) );
2070  leak = 1;
2071  }
2072  efi_nullify_snp ( &snpdev->snp );
2073  efi_nullify_nii ( &snpdev->nii );
2074  efi_nullify_vlan ( &snpdev->vcfg );
2075  efi_nullify_name2 ( &snpdev->name2 );
2076  efi_nullify_load_file ( &snpdev->load_file );
2077  if ( ! leak )
2078  free ( snpdev->path );
2079  bs->CloseEvent ( snpdev->snp.WaitForPacket );
2080  if ( ! leak ) {
2081  netdev_put ( snpdev->netdev );
2082  free ( snpdev );
2083  }
2084 
2085  /* Report leakage, if applicable */
2086  if ( leak && ( ! efi_shutdown_in_progress ) )
2087  DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
2088 }
2089 
2090 /** SNP driver */
2091 struct net_driver efi_snp_driver __net_driver = {
2092  .name = "SNP",
2093  .probe = efi_snp_probe,
2094  .notify = efi_snp_notify,
2095  .remove = efi_snp_remove,
2096 };
2097 
2098 /**
2099  * Find SNP device by EFI device handle
2100  *
2101  * @v handle EFI device handle
2102  * @ret snpdev SNP device, or NULL
2103  */
2105  struct efi_snp_device *snpdev;
2106 
2107  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
2108  if ( snpdev->handle == handle )
2109  return snpdev;
2110  }
2111  return NULL;
2112 }
2113 
2114 /**
2115  * Get most recently opened SNP device
2116  *
2117  * @ret snpdev Most recently opened SNP device, or NULL
2118  */
2120  struct net_device *netdev;
2121 
2123  if ( ! netdev )
2124  return NULL;
2125 
2126  return efi_snp_demux ( netdev );
2127 }
2128 
2129 /**
2130  * Add to SNP claimed/released count
2131  *
2132  * @v delta Claim count change
2133  */
2134 void efi_snp_add_claim ( int delta ) {
2135  struct efi_snp_device *snpdev;
2136 
2137  /* Raise TPL if we are about to claim devices */
2138  if ( ! efi_snp_claimed )
2140 
2141  /* Claim SNP devices */
2142  efi_snp_claimed += delta;
2143  assert ( efi_snp_claimed >= 0 );
2144 
2145  /* Update SNP mode state for each interface */
2146  list_for_each_entry ( snpdev, &efi_snp_devices, list )
2147  efi_snp_set_state ( snpdev );
2148 
2149  /* Restore TPL if we have released devices */
2150  if ( ! efi_snp_claimed )
2152 }
EFI_GUID efi_nii31_protocol_guid
Network interface identifier protocol GUID (new version)
Definition: efi_guid.c:309
const char product_short_name[]
Product short name string.
Definition: version.c:77
static EFI_STATUS efi_undi_shutdown(struct efi_snp_device *snpdev)
Shutdown.
Definition: efi_snp.c:1118
static LIST_HEAD(efi_snp_devices)
List of SNP devices.
#define iob_pull(iobuf, len)
Definition: iobuf.h:107
#define __attribute__(x)
Definition: compiler.h:10
static EFI_STATUS EFIAPI efi_snp_initialize(EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN extra_rx_bufsize, UINTN extra_tx_bufsize)
Open the network device.
Definition: efi_snp.c:239
#define VLAN_TAG(tci)
Extract VLAN tag from tag control information.
Definition: vlan.h:30
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2099
#define EINVAL
Invalid argument.
Definition: errno.h:429
struct option_descriptor read[1]
Definition: nvo_cmd.c:116
#define EFI_UNSUPPORTED
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:118
PXE_UINT16 Protocol
Protocol type.
Definition: UefiPxe.h:1595
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
static PXE_STATCODE efi_undi_statcode(EFI_STATUS efirc)
Convert EFI status code to UNDI status code.
Definition: efi_snp.c:967
#define iob_put(iobuf, len)
Definition: iobuf.h:125
PXE_UINT32 BufferLen
Length of receive buffer.
Definition: UefiPxe.h:1738
static EFI_STATUS efi_undi_get_state(struct efi_snp_device *snpdev, PXE_CDB *cdb)
Get state.
Definition: efi_snp.c:987
The EFI_SIMPLE_NETWORK_PROTOCOL protocol is used to initialize access to a network adapter.
#define PXE_OPCODE_SHUTDOWN
Change the UNDI operational state from Initialized to Started.
Definition: UefiPxe.h:123
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:175
#define AF_INET6
IPv6 Internet addresses.
Definition: socket.h:65
PXE_STATCODE StatCode
Definition: UefiPxe.h:883
static EFI_STATUS EFIAPI efi_snp_start(EFI_SIMPLE_NETWORK_PROTOCOL *snp)
Change SNP state from "stopped" to "started".
Definition: efi_snp.c:190
#define PXE_ROMID_MAJORVER
UNDI command interface revision.
Definition: UefiPxe.h:847
uint8_t ll_header_len
Link-layer header length.
Definition: netdevice.h:201
PXE_MAC_ADDR SrcAddr
Source and destination MAC addresses.
Definition: UefiPxe.h:1612
This protocol is used to retrieve user readable names of drivers and controllers managed by UEFI Driv...
uint8_t ll_addr_len
Link-layer address length.
Definition: netdevice.h:199
EFI driver interface.
static void efi_snp_flush(struct efi_snp_device *snpdev)
Flush transmit ring and receive queue.
Definition: efi_snp.c:148
EFI_VLAN_CONFIG_PROTOCOL vcfg
VLAN configuration protocol.
Definition: efi_snp.h:57
#define PXE_ROMID_SIGNATURE
Signature of !PXE structure.
Definition: UefiPxe.h:835
PXE_UINT16 PXE_STATCODE
UNDI Fill Header.
Definition: UefiPxe.h:597
static EFI_STATUS efi_undi_receive_filters(struct efi_snp_device *snpdev, PXE_CDB *cdb)
Get/set receive filters.
Definition: efi_snp.c:1137
BOOLEAN MediaPresent
TRUE if media are connected to the network interface; otherwise FALSE.
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:70
static void efi_snp_notify(struct net_device *netdev, void *priv __unused)
Handle SNP device or link state change.
Definition: efi_snp.c:2010
128 bit buffer containing a unique identifier value.
Definition: Base.h:216
#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED
Definition: UefiPxe.h:873
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii
The network interface identifier.
Definition: efi_snp.h:55
UINT8_t filter
Receive packet filter.
Definition: pxe_api.h:68
Error codes.
Definition: efi.h:63
static EFI_STATUS efi_undi_transmit(struct efi_snp_device *snpdev, PXE_CPB_TRANSMIT *cpb)
Transmit.
Definition: efi_snp.c:1301
void efi_raise_tpl(struct efi_saved_tpl *tpl)
Raise task priority level to internal level.
Definition: efi_init.c:383
EFI_COMPONENT_NAME2_PROTOCOL name2
Component name protocol.
Definition: efi_snp.h:59
An optional protocol that is used to describe details about the software layer that is used to produc...
32-byte buffer containing a network Media Access Control address.
Definition: UefiBaseType.h:98
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
EFI strings.
int started
Started flag.
Definition: efi_snp.h:43
uint16_t mode
Acceleration mode.
Definition: ena.h:26
#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
Definition: UefiPxe.h:869
unsigned char BOOLEAN
PXE_UINT32 DataLen
Length of the data portion of the frame buffer in bytes.
Definition: UefiPxe.h:1675
size_t mtu
Maximum transmission unit length.
Definition: netdevice.h:416
static void efi_snp_remove(struct net_device *netdev, void *priv __unused)
Destroy SNP device.
Definition: efi_snp.c:2036
#define PXE_BUSTYPE(a, b, c, d)
Definition: UefiPxe.h:23
PXE_OPFLAGS OpFlags
Definition: UefiPxe.h:878
#define EFI_PROTOCOL_ERROR
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:139
EFI_GUID efi_simple_network_protocol_guid
Simple network protocol GUID.
Definition: efi_guid.c:341
#define PXE_STATFLAGS_GET_STATE_STARTED
Definition: UefiPxe.h:426
#define DBGC(...)
Definition: compiler.h:505
#define PXE_STATFLAGS_COMMAND_FAILED
Definition: UefiPxe.h:418
#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN
This flag is set if no transmitted buffer addresses were written into the DB.
Definition: UefiPxe.h:572
#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
static PXE_SW_UNDI efi_snp_undi
UNDI interface.
Definition: efi_snp.c:1460
char name[40]
Name.
Definition: device.h:79
#define ENOENT
No such file or directory.
Definition: errno.h:515
PXE_DB_RECEIVE receive
Definition: efi_snp.c:911
const uint8_t * ll_broadcast
Link-layer broadcast address.
Definition: netdevice.h:390
#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE
Definition: UefiPxe.h:866
unsigned int UINT32
Definition: ProcessorBind.h:99
#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA
UNDI Initialize.
Definition: UefiPxe.h:449
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces
Definition: UefiSpec.h:2010
static void efi_snp_set_state(struct efi_snp_device *snpdev)
Set EFI SNP mode state.
Definition: efi_snp.c:92
EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName
static EFI_STATUS EFIAPI efi_snp_station_address(EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, EFI_MAC_ADDRESS *new)
Set station address.
Definition: efi_snp.c:401
unsigned short CHAR16
EFI_CLOSE_EVENT CloseEvent
Definition: UefiSpec.h:1959
static unsigned int efi_undi_ifnum(struct efi_snp_device *snpdev)
Get UNDI SNP device interface number.
Definition: efi_snp.c:936
#define ntohs(value)
Definition: byteswap.h:137
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
#define PXE_OPCODE_INITIALIZE
Changed UNDI operational state from Started to Initialized.
Definition: UefiPxe.h:113
EFI_HANDLE device
EFI device handle.
Definition: efi_driver.h:22
static EFI_STATUS efi_undi_get_init_info(struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_DB_GET_INIT_INFO *db)
Get initialisation information.
Definition: efi_snp.c:1049
UINT32 State
Reports the current state of the network interface.
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:46
#define PXE_STATCODE_BUSY
Definition: UefiPxe.h:609
#define VLAN_TAG_IS_VALID(tag)
Check VLAN tag is valid.
Definition: vlan.h:55
static void efi_snp_claim(void)
Claim network devices for use by iPXE.
Definition: efi_snp.h:92
uint8_t mac[ETH_ALEN]
MAC address.
Definition: ena.h:24
Automatic booting.
PXE_MAC_ADDR StationAddr
If supplied and supported, the current station MAC address will be changed.
Definition: UefiPxe.h:1339
static void iob_populate(struct io_buffer *iobuf, void *data, size_t len, size_t max_len)
Create a temporary I/O buffer.
Definition: iobuf.h:195
int efi_child_add(EFI_HANDLE parent, EFI_HANDLE child)
Add EFI device as child of another EFI device.
Definition: efi_utils.c:111
unsigned long intptr_t
Definition: stdint.h:21
#define PXE_OPCODE_FILL_HEADER
Fill media header in packet for transmit.
Definition: UefiPxe.h:163
#define EFI_SNP_NUM_TX
SNP transmit completion ring size.
Definition: efi_snp.h:26
#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY
This flag is set if the transmitted buffer queue is empty.
Definition: UefiPxe.h:566
PXE_MAC_ADDR DestAddr
Definition: UefiPxe.h:1577
wchar_t controller_name[64]
Controller name.
Definition: efi_snp.h:77
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.
Definition: efi_snp.c:367
static int efi_snp_claimed
Network devices are currently claimed for use by iPXE.
Definition: efi_snp.c:49
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:131
unsigned char UINT8
static const char * netdev_addr(struct net_device *netdev)
Get printable network device link-layer address.
Definition: netdevice.h:542
struct net_device_stats tx_stats
TX statistics.
Definition: netdevice.h:424
PXE_CPB_RECEIVE receive
Definition: efi_snp.c:903
unsigned int scope_id
Scope ID.
Definition: netdevice.h:361
void(* init_addr)(const void *hw_addr, void *ll_addr)
Initialise link-layer address.
Definition: netdevice.h:151
A network upper-layer driver.
Definition: netdevice.h:477
PXE_MAC_ADDR SrcAddr
Source and destination MAC addresses.
Definition: UefiPxe.h:1576
EFI_HANDLE handle
EFI device handle.
Definition: efi_snp.h:37
#define TPL_NOTIFY
Definition: UefiSpec.h:650
static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp
SNP interface.
Definition: efi_snp.c:873
#define PXE_STATFLAGS_GET_STATUS_RECEIVE
If set, at least one receive interrupt occurred.
Definition: UefiPxe.h:545
A link-layer protocol.
Definition: netdevice.h:115
EFI_MAC_ADDRESS CurrentAddress
The current HW MAC address for the network interface.
int vlan_create(struct net_device *trunk, unsigned int tag, unsigned int priority)
Create VLAN device.
Definition: vlan.c:344
#define EFI_OUT_OF_RESOURCES
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:124
static EFI_STATUS efi_undi_stop(struct efi_snp_device *snpdev)
Stop.
Definition: efi_snp.c:1029
EFI utilities.
#define PXE_OPCODE_STATION_ADDRESS
Read & change station MAC address.
Definition: UefiPxe.h:138
struct net_device * vlan_find(struct net_device *trunk, unsigned int tag)
Identify VLAN device.
Definition: vlan.c:209
#define ENOTSUP
Operation not supported.
Definition: errno.h:590
static EFI_STATUS efi_undi_station_address(struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_CPB_STATION_ADDRESS *cpb, PXE_DB_STATION_ADDRESS *db)
Get/set station address.
Definition: efi_snp.c:1159
PXE_DB_GET_INIT_INFO get_init_info
Definition: efi_snp.c:908
UINT64 Id
The address of the first byte of the identifying structure for this network interface.
int(* push)(struct net_device *netdev, struct io_buffer *iobuf, const void *ll_dest, const void *ll_source, uint16_t net_proto)
Add link-layer header.
Definition: netdevice.h:128
static EFI_STATUS efi_undi_reset(struct efi_snp_device *snpdev)
Reset.
Definition: efi_snp.c:1100
static EFI_STATUS EFIAPI efi_snp_get_driver_name(EFI_COMPONENT_NAME2_PROTOCOL *name2, CHAR8 *language __unused, CHAR16 **driver_name)
Look up driver name.
Definition: efi_snp.c:1666
int ipxe(struct net_device *netdev)
Main iPXE flow of execution.
Definition: autoboot.c:586
EFI_SIMPLE_NETWORK_MODE * Mode
Pointer to the EFI_SIMPLE_NETWORK_MODE data for the device.
struct net_device * netdev
The underlying iPXE network device.
Definition: efi_snp.h:33
unsigned long tmp
Definition: linux_pci.h:65
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.
Definition: efi_snp.c:525
UINT64 RxGoodFrames
Number of valid frames received and copied into receive buffers.
Definition: SimpleNetwork.h:51
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition: list.h:334
EFI_VLAN_CONFIG_SET Set
Definition: VlanConfig.h:130
void efi_child_del(EFI_HANDLE parent, EFI_HANDLE child)
Remove EFI device as child of another EFI device.
Definition: efi_utils.c:138
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
PXE_UINT64 FrameAddr
Address of first byte of frame buffer.
Definition: UefiPxe.h:1669
struct efi_snp_device * last_opened_snpdev(void)
Get most recently opened SNP device.
Definition: efi_snp.c:2119
#define ENOMEM
Not enough space.
Definition: errno.h:535
A hardware device.
Definition: device.h:77
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:217
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * name
Name.
Definition: netdevice.h:479
#define PXE_OPCODE_RESET
Re-initialize the NIC H/W.
Definition: UefiPxe.h:118
unsigned int tx_cons
Transmit completion ring consumer counter.
Definition: efi_snp.h:51
int efi_snp_hii_uninstall(struct efi_snp_device *snpdev)
Uninstall HII protocol and package for SNP device.
Definition: efi_snp_hii.c:797
int efi_snp_hii_install(struct efi_snp_device *snpdev)
Install HII protocol and packages for SNP device.
Definition: efi_snp_hii.c:659
#define PXE_OPCODE_TRANSMIT
Transmit packet(s).
Definition: UefiPxe.h:168
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:662
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.
Definition: efi_snp.c:761
EFI_HII_PACKAGE_LIST_HEADER * package_list
HII package list.
Definition: efi_snp.h:65
PXE_CPB_FILL_HEADER_FRAGMENTED fill_header_fragmented
Definition: efi_snp.c:901
#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
static EFI_STATUS EFIAPI efi_snp_stop(EFI_SIMPLE_NETWORK_PROTOCOL *snp)
Change SNP state from "started" to "stopped".
Definition: efi_snp.c:214
Assertions.
The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from arbitrary devices.
Definition: LoadFile.h:79
#define PXE_STATFLAGS_STATUS_MASK
Common StatFlags that can be returned by all commands.
Definition: UefiPxe.h:416
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:576
UINT8_t Rev
PCI revision.
Definition: pxe_api.h:62
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
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
static const void * src
Definition: string.h:48
uint8_t hw_addr_len
Hardware address length.
Definition: netdevice.h:197
PXE_MEDIA_PROTOCOL Protocol
Protocol type.
Definition: UefiPxe.h:1625
16-byte buffer aligned on a 4-byte boundary.
Definition: UefiBaseType.h:106
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
static void efi_watchdog_start(void)
Start EFI watchdog holdoff timer.
Definition: efi_watchdog.h:18
FILE_LICENCE(GPL2_OR_LATER)
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:94
#define PXE_STATCODE_DEVICE_FAILURE
Definition: UefiPxe.h:616
PXE_DB_GET_STATUS get_status
Definition: efi_snp.c:910
#define efi_open_by_driver(handle, protocol, interface)
Open protocol for persistent use by a driver.
Definition: efi.h:474
ring len
Length.
Definition: dwmac.h:231
UINT64 TxTotalFrames
Transmit statistics.
Definition: SimpleNetwork.h:99
EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName
PXE_DB_STATION_ADDRESS station_address
Definition: efi_snp.c:909
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition: netdevice.h:640
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.
Definition: efi_snp.c:487
static struct net_device * netdev
Definition: gdbudp.c:53
struct net_device * last_opened_netdev(void)
Get most recently opened network device.
Definition: netdevice.c:1048
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
Definition: efi_strings.c:107
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition: netdevice.h:46
static EFI_STATUS EFIAPI efi_vlan_remove(EFI_VLAN_CONFIG_PROTOCOL *vcfg, UINT16 tag)
Remove VLAN device.
Definition: efi_snp.c:1610
EFI_CREATE_EVENT CreateEvent
Definition: UefiSpec.h:1955
static unsigned int count
Number of entries.
Definition: dwmac.h:225
UINT64 RxDroppedFrames
Valid frames that were dropped because receive buffers were full.
Definition: SimpleNetwork.h:68
VOID * tx[EFI_SNP_NUM_TX]
Transmit completion ring.
Definition: efi_snp.h:47
#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
static EFI_VLAN_CONFIG_PROTOCOL efi_vlan
VLAN configuration protocol.
Definition: efi_snp.c:1644
#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
Definition: UefiPxe.h:440
EFI_GUID efi_vlan_config_protocol_guid
VLAN configuration protocol GUID.
Definition: efi_guid.c:433
static struct efi_saved_tpl efi_snp_saved_tpl
TPL prior to network devices being claimed.
Definition: efi_snp.c:52
static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol
Load file protocol.
Definition: efi_snp.c:1750
#define PXE_ROMID_MINORVER
Definition: UefiPxe.h:848
const char * driver_name
Driver name.
Definition: device.h:81
void efi_snp_add_claim(int delta)
Add to SNP claimed/released count.
Definition: efi_snp.c:2134
User interaction.
#define PXE_ROMID_IMP_SW_VIRT_ADDR
Definition: UefiPxe.h:854
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.
Definition: efi_snp.c:611
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:459
EFI null interfaces.
PXE_CPB_STATION_ADDRESS station_address
Definition: efi_snp.c:899
unsigned short UINT16
wchar_t name[sizeof(((struct net_device *) NULL) ->name)]
Device name.
Definition: efi_snp.h:73
#define DBGC2_HDA(...)
Definition: compiler.h:523
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition: efi_debug.c:652
EFI_SIGNAL_EVENT SignalEvent
Definition: UefiSpec.h:1958
PXE_UINT64 CPBaddr
Definition: UefiPxe.h:881
EFI_SIMPLE_NETWORK_PROTOCOL snp
The SNP structure itself.
Definition: efi_snp.h:39
static EFIAPI VOID efi_undi_issue(UINT64 cdb_phys)
UNDI entry point.
Definition: efi_snp.c:1356
void netdev_poll(struct net_device *netdev)
Poll for completed and received packets on network device.
Definition: netdevice.c:613
#define ERANGE
Result too large.
Definition: errno.h:640
PXE_UINT64 BufferAddr
Address of first byte of receive buffer.
Definition: UefiPxe.h:1731
static void efi_watchdog_stop(void)
Stop EFI watchdog holdoff timer.
Definition: efi_watchdog.h:27
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path(struct net_device *netdev)
Construct EFI device path for network device.
Definition: efi_path.c:411
#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
static EFI_STATUS efi_undi_receive(struct efi_snp_device *snpdev, PXE_CPB_RECEIVE *cpb, PXE_DB_RECEIVE *db)
Receive.
Definition: efi_snp.c:1323
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
#define EFIAPI
UINT64 Revision
The revision of the EFI_NETWORK_INTERFACE_IDENTIFIER protocol.
static struct efi_snp_device * efi_undi_snpdev(unsigned int ifnum)
Identify UNDI SNP device.
Definition: efi_snp.c:951
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
EFI Boot Services Table.
Definition: UefiSpec.h:1931
IP address structure.
Definition: in.h:42
UINT64 RxTotalFrames
Total number of frames received.
Definition: SimpleNetwork.h:46
#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED
Definition: UefiPxe.h:376
EFI_VLAN_CONFIG_PROTOCOL provide manageability interface for VLAN setting.
Definition: VlanConfig.h:129
#define PXE_ROMID_REV
!PXE structure format revision
Definition: UefiPxe.h:840
EFI watchdog holdoff timer.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
struct net_device_stats rx_stats
RX statistics.
Definition: netdevice.h:426
static void efi_snp_set_mode(struct efi_snp_device *snpdev)
Set EFI SNP mode based on iPXE net device parameters.
Definition: efi_snp.c:121
unsigned int bad
Count of error completions.
Definition: netdevice.h:296
#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
Definition: UefiPxe.h:868
EFI_VLAN_FIND_DATA.
Definition: VlanConfig.h:28
#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA
This flag is set if there is no media detected.
Definition: UefiPxe.h:577
#define PXE_STATCODE_UNSUPPORTED
Definition: UefiPxe.h:618
A network device.
Definition: netdevice.h:353
Union type for data blocks.
Definition: efi_snp.c:907
struct net_driver efi_snp_driver __net_driver
SNP driver.
Definition: efi_snp.c:2091
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces
Definition: UefiSpec.h:2011
An SNP device.
Definition: efi_snp.h:29
PXE_CPB_FILL_HEADER fill_header
Definition: efi_snp.c:900
static void efi_snp_release(void)
Release network devices for use via SNP.
Definition: efi_snp.h:100
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:814
IP4_t ip
Destination IP address.
Definition: pxe_api.h:58
int netdev_tx(struct net_device *netdev, struct io_buffer *iobuf)
Transmit raw packet via network device.
Definition: netdevice.c:335
PXE_UINT8 Fudge
makes 8-bit cksum zero.
Definition: UefiPxe.h:813
unsigned char uint8_t
Definition: stdint.h:10
static void console_reset(void)
Reset console.
Definition: console.h:215
EFI device paths.
#define EVT_NOTIFY_WAIT
Definition: UefiSpec.h:453
UINT64 UINTN
Unsigned value of native width.
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.
Definition: efi_snp.c:438
#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED
Definition: UefiPxe.h:444
An EFI device.
Definition: efi_driver.h:18
#define EFI_NOT_READY
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:121
PXE_CPB_TRANSMIT transmit
Definition: efi_snp.c:902
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:565
#define PXE_OPCODE_STOP
Change UNDI operational state from Started to Stopped.
Definition: UefiPxe.h:98
#define PXE_OPCODE_GET_STATUS
Get & clear interrupt status.
Definition: UefiPxe.h:158
#define EFI_INVALID_PARAMETER
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:117
void efi_nullify_vlan(EFI_VLAN_CONFIG_PROTOCOL *vcfg)
Nullify VLAN configuration interface.
Definition: efi_null.c:234
EFI_GUID efi_device_path_protocol_guid
Device path protocol GUID.
Definition: efi_guid.c:169
Version number.
int vlan_destroy(struct net_device *netdev)
Destroy VLAN device.
Definition: vlan.c:434
EFI_GUID efi_component_name2_protocol_guid
Component name 2 protocol GUID.
Definition: efi_guid.c:161
static EFI_STATUS EFIAPI efi_snp_load_file(EFI_LOAD_FILE_PROTOCOL *load_file, EFI_DEVICE_PATH_PROTOCOL *path __unused, BOOLEAN booting, UINTN *len __unused, VOID *data __unused)
Load file.
Definition: efi_snp.c:1714
uint16_t ll_proto
Link-layer protocol.
Definition: netdevice.h:195
#define VOID
Undeclared type.
Definition: Base.h:272
unsigned long long UINT64
Definition: ProcessorBind.h:97
static uint8_t efi_undi_checksum(void *data, size_t len)
Calculate UNDI byte checksum.
Definition: efi_snp.c:921
int(* mc_hash)(unsigned int af, const void *net_addr, void *ll_addr)
Hash multicast address.
Definition: netdevice.h:173
#define TRUE
Definition: tlan.h:46
#define PXE_OPFLAGS_STATION_ADDRESS_RESET
Definition: UefiPxe.h:318
#define EAGAIN
Resource temporarily unavailable.
Definition: errno.h:319
EFI API.
#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST
UNDI Receive Filters.
Definition: UefiPxe.h:486
struct list_head rx
Receive queue.
Definition: efi_snp.h:53
static EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL efi_snp_device_nii
Network Identification Interface (NII)
Definition: efi_snp.c:1483
unsigned int tx_prod
Transmit completion ring producer counter.
Definition: efi_snp.h:49
wchar_t driver_name[16]
Driver name.
Definition: efi_snp.h:75
struct device * dev
Underlying hardware device.
Definition: netdevice.h:365
EFI_GUID efi_nii_protocol_guid
Network interface identifier protocol GUID (old version)
Definition: efi_guid.c:305
void netdev_close(struct net_device *netdev)
Close network device.
Definition: netdevice.c:896
static EFI_STATUS EFIAPI efi_snp_shutdown(EFI_SIMPLE_NETWORK_PROTOCOL *snp)
Shut down the network device.
Definition: efi_snp.c:330
void efi_nullify_name2(EFI_COMPONENT_NAME2_PROTOCOL *name2)
Nullify Component Name Protocol interface.
Definition: efi_null.c:273
Network device management.
static struct dmfe_private * db
Definition: dmfe.c:177
static EFI_STATUS efi_undi_fill_header(struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_CPB_ANY *cpb)
Fill header.
Definition: efi_snp.c:1255
struct efi_snp_device * find_snpdev(EFI_HANDLE handle)
Find SNP device by EFI device handle.
Definition: efi_snp.c:2104
static EFI_STATUS efi_undi_get_status(struct efi_snp_device *snpdev, PXE_CDB *cdb, PXE_DB_GET_STATUS *db)
Get interrupt status.
Definition: efi_snp.c:1201
#define iob_reserve(iobuf, len)
Definition: iobuf.h:72
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:46
#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
unsigned int good
Count of successful completions.
Definition: netdevice.h:294
int(* pull)(struct net_device *netdev, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
Remove link-layer header.
Definition: netdevice.h:142
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:363
#define PXE_STATCODE_NO_DATA
Definition: UefiPxe.h:625
An EFI saved task priority level.
Definition: efi.h:80
General configuration.
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:45
CHAR8 * SupportedLanguages
A Null-terminated ASCII string array that contains one or more supported language codes.
#define ENOBUFS
No buffer space available.
Definition: errno.h:499
PXE_UINT8 IFcntExt
physical connector count upper byte.
Definition: UefiPxe.h:818
#define DBGC2(...)
Definition: compiler.h:522
static struct tlan_private * priv
Definition: tlan.c:225
static EFI_STATUS EFIAPI efi_snp_get_status(EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 *interrupts, VOID **txbuf)
Read interrupt status and TX recycled buffer status.
Definition: efi_snp.c:552
EFI_LOAD_FILE_PROTOCOL load_file
Load file protocol handle.
Definition: efi_snp.h:61
uint16_t priority
Priotity.
Definition: stp.h:13
FILE_SECBOOT(PERMITTED)
PXE_UINT64 EntryPoint
API entry point.
Definition: UefiPxe.h:821
EFI_LOAD_FILE LoadFile
Definition: LoadFile.h:80
char CHAR8
#define IOB_ZLEN
Minimum I/O buffer length and alignment.
Definition: iobuf.h:29
void * data
Start of data.
Definition: iobuf.h:53
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:32
UINT64 Revision
Revision of the EFI_SIMPLE_NETWORK_PROTOCOL.
PXE_UINT8 IFcnt
physical connector count lower byte.
Definition: UefiPxe.h:815
static void efi_snp_poll(struct efi_snp_device *snpdev)
Poll net device and count received packets.
Definition: efi_snp.c:168
#define PXE_STATCODE_BUFFER_FULL
Definition: UefiPxe.h:619
#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST
If set, all multicast packets will be received.
Definition: UefiPxe.h:507
PXE_UINT64 MediaHeader
Address of first byte of media header.
Definition: UefiPxe.h:1583
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151
PXE_STATFLAGS StatFlags
Definition: UefiPxe.h:884
void efi_nullify_load_file(EFI_LOAD_FILE_PROTOCOL *load_file)
Nullify Load File Protocol interface.
Definition: efi_null.c:298
#define PXE_OPCODE_RECEIVE
Receive packet.
Definition: UefiPxe.h:173
uint8_t data[48]
Additional event data.
Definition: ena.h:22
Virtual LANs.
#define PXE_OPCODE_RECEIVE_FILTERS
Read & change state of packet receive filters.
Definition: UefiPxe.h:133
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition: netdevice.h:164
#define DBGCP(...)
Definition: compiler.h:539
#define FALSE
Definition: tlan.h:45
#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION
__weak unsigned int vlan_tci(struct net_device *netdev __unused)
Get the VLAN tag control information (when VLAN support is not present)
Definition: netdevice.c:1199
static EFI_STATUS EFIAPI efi_vlan_find(EFI_VLAN_CONFIG_PROTOCOL *vcfg, UINT16 *filter, UINT16 *count, EFI_VLAN_FIND_DATA **entries)
Find VLAN device(s)
Definition: efi_snp.c:1541
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:383
EFI_SYSTEM_TABLE * efi_systab
void efi_nullify_nii(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii)
Nullify NII interface.
Definition: efi_null.c:192
iPXE EFI SNP interface
#define PXE_STATCODE_INVALID_CDB
Definition: UefiPxe.h:607
struct efi_device * efidev_parent(struct device *dev)
Get parent EFI device.
Definition: efi_driver.c:129
UINT16 IfNum
The network interface number that is being identified by this Network Interface Identifier Protocol.
#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
Definition: UefiPxe.h:867
#define PXE_OPCODE_GET_STATE
Return UNDI operational state.
Definition: UefiPxe.h:88
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:388
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
size_t max_pkt_len
Maximum packet length.
Definition: netdevice.h:410
#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED
Definition: UefiPxe.h:872
The data portions of a loaded Boot Serves Driver, and the default data allocation type used by a Boot...
static int efi_snp_probe(struct net_device *netdev, void *priv __unused)
Create SNP device.
Definition: efi_snp.c:1784
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define PXE_OPCODE_GET_INIT_INFO
Get UNDI initialization information.
Definition: UefiPxe.h:103
static EFI_STATUS efi_undi_initialize(struct efi_snp_device *snpdev, PXE_CDB *cdb)
Initialise.
Definition: efi_snp.c:1076
EFI_GUID efi_load_file_protocol_guid
Load file protocol GUID.
Definition: efi_guid.c:265
#define PXE_FRAME_TYPE_PROMISCUOUS
Definition: UefiPxe.h:667
EFI_DEVICE_PATH_PROTOCOL * path
The device path.
Definition: efi_snp.h:79
#define PXE_STATFLAGS_GET_STATE_STOPPED
Definition: UefiPxe.h:427
uint8_t bytes[64]
Definition: ib_mad.h:17
uint64_t tag
Identity tag.
Definition: edd.h:31
Simple Network Protocol data structures.
Definition: SimpleNetwork.h:41
#define PXE_STATCODE_INVALID_PARAMETER
Definition: UefiPxe.h:620
uint16_t handle
Handle.
Definition: smbios.h:17
EFI_SIMPLE_NETWORK_MODE mode
The SNP "mode" (parameters)
Definition: efi_snp.h:41
static VOID EFIAPI efi_snp_wait_for_packet(EFI_EVENT event __unused, VOID *context)
Poll event.
Definition: efi_snp.c:847
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:382
void efi_restore_tpl(struct efi_saved_tpl *tpl)
Restore task priority level.
Definition: efi_init.c:399
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
static struct efi_snp_device * efi_snp_demux(struct net_device *netdev)
Locate SNP device corresponding to network device.
Definition: efi_snp.c:1767
#define PXE_STATFLAGS_GET_STATUS_TRANSMIT
If set, at least one transmit interrupt occurred.
Definition: UefiPxe.h:550
EFI_EVENT WaitForPacket
Event used with WaitForEvent() to wait for a packet to be received.
static EFI_STATUS EFIAPI efi_snp_reset(EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify)
Reset the network device.
Definition: efi_snp.c:286
PXE_UINT16 IFnum
Definition: UefiPxe.h:885
struct s_pxe_cpb_fill_header_fragmented::@607 FragDesc[MAX_XMIT_FRAGMENTS]
Array of packet fragment descriptors.
#define PXE_OPCODE_START
Change UNDI operational state from Stopped to Started.
Definition: UefiPxe.h:93
String functions.
#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST
If set, broadcast packets will be received.
Definition: UefiPxe.h:491
#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:862
#define htons(value)
Definition: byteswap.h:136
#define VLAN_PRIORITY(tci)
Extract VLAN priority from tag control information.
Definition: vlan.h:38
PXE_OPCODE OpCode
Definition: UefiPxe.h:877
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:64
void efi_nullify_snp(EFI_SIMPLE_NETWORK_PROTOCOL *snp)
Nullify SNP interface.
Definition: efi_null.c:157
#define PXE_STATFLAGS_COMMAND_COMPLETE
Definition: UefiPxe.h:417
struct list_head list
List of SNP devices.
Definition: efi_snp.h:31
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition: efi.h:167
static EFI_STATUS EFIAPI efi_vlan_set(EFI_VLAN_CONFIG_PROTOCOL *vcfg, UINT16 tag, UINT8 priority)
Create or modify VLAN device.
Definition: efi_snp.c:1507
Definition: efi.h:62
EFI_HANDLE parent
EFI parent device handle (if any)
Definition: efi_snp.h:35
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:373
Union type for command parameter blocks.
Definition: efi_snp.c:898
unsigned int interrupts
Pending interrupt status.
Definition: efi_snp.h:45
EFI_MAC_ADDRESS PermanentAddress
The permanent HW MAC address for the network interface.
#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS
If set, all packets will be received.
Definition: UefiPxe.h:502
static EFI_STATUS EFIAPI efi_snp_get_controller_name(EFI_COMPONENT_NAME2_PROTOCOL *name2, EFI_HANDLE device __unused, EFI_HANDLE child __unused, CHAR8 *language __unused, CHAR16 **controller_name)
Look up controller name.
Definition: efi_snp.c:1686
#define PXE_STATFLAGS_GET_STATE_INITIALIZED
Definition: UefiPxe.h:425
EFI_ALLOCATE_POOL AllocatePool
Definition: UefiSpec.h:1949
PXE_UINT64 DBaddr
Definition: UefiPxe.h:882
PXE_UINT64 FragAddr
Address of this packet fragment.
Definition: UefiPxe.h:1650
#define PXE_STATCODE_SUCCESS
Common StatCodes returned by all UNDI commands, UNDI protocol functions and BC protocol functions.
Definition: UefiPxe.h:605
void * memset(void *dest, int character, size_t len) __nonnull
static EFI_STATUS efi_undi_start(struct efi_snp_device *snpdev)
Start.
Definition: efi_snp.c:1011
int efi_shutdown_in_progress
EFI shutdown is in progress.
Definition: efi_init.c:60
struct io_buffer * netdev_rx_dequeue(struct net_device *netdev)
Remove packet from device's receive queue.
Definition: netdevice.c:638
A persistent I/O buffer.
Definition: iobuf.h:38