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