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 indexes are one-based (leaving zero
938  * meaning "unspecified"). UNDI interface numbers are
939  * zero-based.
940  */
941  return ( snpdev->netdev->index - 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  * Component name protocol
1494  *
1495  ******************************************************************************
1496  */
1497 
1498 /**
1499  * Look up driver name
1500  *
1501  * @v name2 Component name protocol
1502  * @v language Language to use
1503  * @v driver_name Driver name to fill in
1504  * @ret efirc EFI status code
1505  */
1506 static EFI_STATUS EFIAPI
1508  CHAR8 *language __unused, CHAR16 **driver_name ) {
1509  struct efi_snp_device *snpdev =
1510  container_of ( name2, struct efi_snp_device, name2 );
1511 
1512  *driver_name = snpdev->driver_name;
1513  return 0;
1514 }
1515 
1516 /**
1517  * Look up controller name
1518  *
1519  * @v name2 Component name protocol
1520  * @v device Device
1521  * @v child Child device, or NULL
1522  * @v language Language to use
1523  * @v driver_name Device name to fill in
1524  * @ret efirc EFI status code
1525  */
1526 static EFI_STATUS EFIAPI
1529  EFI_HANDLE child __unused,
1530  CHAR8 *language __unused,
1531  CHAR16 **controller_name ) {
1532  struct efi_snp_device *snpdev =
1533  container_of ( name2, struct efi_snp_device, name2 );
1534 
1535  *controller_name = snpdev->controller_name;
1536  return 0;
1537 }
1538 
1539 /******************************************************************************
1540  *
1541  * Load file protocol
1542  *
1543  ******************************************************************************
1544  */
1545 
1546 /**
1547  * Load file
1548  *
1549  * @v loadfile Load file protocol
1550  * @v path File path
1551  * @v booting Loading as part of a boot attempt
1552  * @ret efirc EFI status code
1553  */
1554 static EFI_STATUS EFIAPI
1557  BOOLEAN booting, UINTN *len __unused,
1558  VOID *data __unused ) {
1559  struct efi_snp_device *snpdev =
1561  struct net_device *netdev = snpdev->netdev;
1562  int rc;
1563 
1564  /* Fail unless this is a boot attempt */
1565  if ( ! booting ) {
1566  DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
1567  snpdev );
1568  return EFI_UNSUPPORTED;
1569  }
1570 
1571  /* Claim network devices for use by iPXE */
1572  efi_snp_claim();
1573 
1574  /* Start watchdog holdoff timer */
1576 
1577  /* Boot from network device */
1578  if ( ( rc = ipxe ( netdev ) ) != 0 )
1579  goto err_ipxe;
1580 
1581  /* Reset console */
1582  console_reset();
1583 
1584  err_ipxe:
1586  efi_snp_release();
1587  return EFIRC ( rc );
1588 }
1589 
1590 /** Load file protocol */
1593 };
1594 
1595 /******************************************************************************
1596  *
1597  * iPXE network driver
1598  *
1599  ******************************************************************************
1600  */
1601 
1602 /**
1603  * Locate SNP device corresponding to network device
1604  *
1605  * @v netdev Network device
1606  * @ret snp SNP device, or NULL if not found
1607  */
1608 static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
1609  struct efi_snp_device *snpdev;
1610 
1611  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
1612  if ( snpdev->netdev == netdev )
1613  return snpdev;
1614  }
1615  return NULL;
1616 }
1617 
1618 /**
1619  * Create SNP device
1620  *
1621  * @v netdev Network device
1622  * @ret rc Return status code
1623  */
1624 static int efi_snp_probe ( struct net_device *netdev ) {
1626  struct efi_device *efidev;
1627  struct efi_snp_device *snpdev;
1628  unsigned int ifcnt;
1629  void *interface;
1630  int leak = 0;
1631  EFI_STATUS efirc;
1632  int rc;
1633 
1634  /* Find parent EFI device */
1635  efidev = efidev_parent ( netdev->dev );
1636  if ( ! efidev ) {
1637  DBG ( "SNP skipping non-EFI device %s\n", netdev->name );
1638  rc = 0;
1639  goto err_no_efidev;
1640  }
1641 
1642  /* Allocate the SNP device */
1643  snpdev = zalloc ( sizeof ( *snpdev ) );
1644  if ( ! snpdev ) {
1645  rc = -ENOMEM;
1646  goto err_alloc_snp;
1647  }
1648  snpdev->netdev = netdev_get ( netdev );
1649  snpdev->efidev = efidev;
1650  INIT_LIST_HEAD ( &snpdev->rx );
1651 
1652  /* Sanity check */
1653  if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
1654  DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
1655  "length %d for %s\n", snpdev,
1657  rc = -ENOTSUP;
1658  goto err_ll_addr_len;
1659  }
1660 
1661  /* Populate the SNP structure */
1662  memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
1663  snpdev->snp.Mode = &snpdev->mode;
1664  if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
1665  efi_snp_wait_for_packet, snpdev,
1666  &snpdev->snp.WaitForPacket ) ) != 0 ){
1667  rc = -EEFI ( efirc );
1668  DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
1669  snpdev, strerror ( rc ) );
1670  goto err_create_event;
1671  }
1672 
1673  /* Populate the SNP mode structure */
1675  efi_snp_set_mode ( snpdev );
1676 
1677  /* Populate the NII structure */
1678  memcpy ( &snpdev->nii, &efi_snp_device_nii, sizeof ( snpdev->nii ) );
1679  snpdev->nii.Id = ( ( intptr_t ) &efi_snp_undi );
1680  snpdev->nii.IfNum = efi_undi_ifnum ( snpdev );
1682  ifcnt = ( ( efi_snp_undi.IFcntExt << 8 ) | efi_snp_undi.IFcnt );
1683  if ( ifcnt < snpdev->nii.IfNum )
1684  ifcnt = snpdev->nii.IfNum;
1685  efi_snp_undi.IFcnt = ( ifcnt & 0xff );
1686  efi_snp_undi.IFcntExt = ( ifcnt >> 8 );
1688  sizeof ( efi_snp_undi ) );
1689 
1690  /* Populate the component name structure */
1691  efi_snprintf ( snpdev->driver_name,
1692  ( sizeof ( snpdev->driver_name ) /
1693  sizeof ( snpdev->driver_name[0] ) ),
1694  "%s %s", product_short_name, netdev->dev->driver_name );
1695  efi_snprintf ( snpdev->controller_name,
1696  ( sizeof ( snpdev->controller_name ) /
1697  sizeof ( snpdev->controller_name[0] ) ),
1698  "%s %s (%s, %s)", product_short_name,
1700  netdev_addr ( netdev ) );
1703  snpdev->name2.SupportedLanguages = "en";
1704 
1705  /* Populate the load file protocol structure */
1707  sizeof ( snpdev->load_file ) );
1708 
1709  /* Populate the device name */
1710  efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
1711  sizeof ( snpdev->name[0] ) ),
1712  "%s", netdev->name );
1713 
1714  /* Construct device path */
1715  snpdev->path = efi_netdev_path ( netdev );
1716  if ( ! snpdev->path ) {
1717  rc = -ENOMEM;
1718  goto err_path;
1719  }
1720 
1721  /* Install the SNP */
1722  if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1723  &snpdev->handle,
1726  &efi_nii_protocol_guid, &snpdev->nii,
1727  &efi_nii31_protocol_guid, &snpdev->nii,
1730  NULL ) ) != 0 ) {
1731  rc = -EEFI ( efirc );
1732  DBGC ( snpdev, "SNPDEV %p could not install protocols: %s\n",
1733  snpdev, strerror ( rc ) );
1734  goto err_install_protocol_interface;
1735  }
1736 
1737  /* SnpDxe will repeatedly start up and shut down our NII/UNDI
1738  * interface (in order to obtain the MAC address) before
1739  * discovering that it cannot install another SNP on the same
1740  * handle. This causes the underlying network device to be
1741  * unexpectedly closed.
1742  *
1743  * Prevent this by opening our own NII (and NII31) protocol
1744  * instances to prevent SnpDxe from attempting to bind to
1745  * them.
1746  */
1747  if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
1749  efi_image_handle, snpdev->handle,
1752  rc = -EEFI ( efirc );
1753  DBGC ( snpdev, "SNPDEV %p could not open NII protocol: %s\n",
1754  snpdev, strerror ( rc ) );
1755  goto err_open_nii;
1756  }
1757  if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
1759  efi_image_handle, snpdev->handle,
1762  rc = -EEFI ( efirc );
1763  DBGC ( snpdev, "SNPDEV %p could not open NII31 protocol: %s\n",
1764  snpdev, strerror ( rc ) );
1765  goto err_open_nii31;
1766  }
1767 
1768  /* Add as child of EFI parent device */
1769  if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) {
1770  DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n",
1771  snpdev, efi_handle_name ( efidev->device ),
1772  strerror ( rc ) );
1773  goto err_efi_child_add;
1774  }
1775 
1776  /* Install HII */
1777  if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
1778  DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
1779  snpdev, strerror ( rc ) );
1780  /* HII fails on several platforms. It's
1781  * non-essential, so treat this as a non-fatal
1782  * error.
1783  */
1784  }
1785 
1786  /* Add to list of SNP devices */
1787  list_add ( &snpdev->list, &efi_snp_devices );
1788 
1789  /* Close device path */
1792 
1793  DBGC ( snpdev, "SNPDEV %p installed for %s as device %s\n",
1794  snpdev, netdev->name, efi_handle_name ( snpdev->handle ) );
1795  return 0;
1796 
1797  list_del ( &snpdev->list );
1798  if ( snpdev->package_list )
1799  leak |= efi_snp_hii_uninstall ( snpdev );
1800  efi_child_del ( efidev->device, snpdev->handle );
1801  err_efi_child_add:
1803  efi_image_handle, snpdev->handle );
1804  err_open_nii31:
1805  bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
1806  efi_image_handle, snpdev->handle );
1807  err_open_nii:
1808  if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1809  snpdev->handle,
1812  &efi_nii_protocol_guid, &snpdev->nii,
1813  &efi_nii31_protocol_guid, &snpdev->nii,
1816  NULL ) ) != 0 ) {
1817  DBGC ( snpdev, "SNPDEV %p could not uninstall: %s\n",
1818  snpdev, strerror ( -EEFI ( efirc ) ) );
1819  efi_nullify_snp ( &snpdev->snp );
1820  efi_nullify_nii ( &snpdev->nii );
1821  efi_nullify_name2 ( &snpdev->name2 );
1822  efi_nullify_load_file ( &snpdev->load_file );
1823  leak = 1;
1824  }
1825  err_install_protocol_interface:
1826  if ( ! leak )
1827  free ( snpdev->path );
1828  err_path:
1829  bs->CloseEvent ( snpdev->snp.WaitForPacket );
1830  err_create_event:
1831  err_ll_addr_len:
1832  if ( ! leak ) {
1833  netdev_put ( netdev );
1834  free ( snpdev );
1835  }
1836  err_alloc_snp:
1837  err_no_efidev:
1838  if ( leak )
1839  DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
1840  return rc;
1841 }
1842 
1843 /**
1844  * Handle SNP device or link state change
1845  *
1846  * @v netdev Network device
1847  */
1848 static void efi_snp_notify ( struct net_device *netdev ) {
1849  struct efi_snp_device *snpdev;
1850 
1851  /* Locate SNP device */
1852  snpdev = efi_snp_demux ( netdev );
1853  if ( ! snpdev ) {
1854  DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
1855  return;
1856  }
1857 
1858  /* Update link state */
1859  snpdev->mode.MediaPresent =
1860  ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
1861  DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
1862  ( snpdev->mode.MediaPresent ? "up" : "down" ) );
1863 
1864  /* Update mode state */
1865  efi_snp_set_state ( snpdev );
1866 }
1867 
1868 /**
1869  * Destroy SNP device
1870  *
1871  * @v netdev Network device
1872  */
1873 static void efi_snp_remove ( struct net_device *netdev ) {
1875  struct efi_snp_device *snpdev;
1876  int leak = 0;
1877  EFI_STATUS efirc;
1878 
1879  /* Locate SNP device */
1880  snpdev = efi_snp_demux ( netdev );
1881  if ( ! snpdev ) {
1882  DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
1883  return;
1884  }
1885 
1886  /* Uninstall the SNP */
1887  list_del ( &snpdev->list );
1888  if ( snpdev->package_list )
1889  leak |= efi_snp_hii_uninstall ( snpdev );
1890  efi_child_del ( snpdev->efidev->device, snpdev->handle );
1891  bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
1892  efi_image_handle, snpdev->handle );
1894  efi_image_handle, snpdev->handle );
1895  if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1896  snpdev->handle,
1899  &efi_nii_protocol_guid, &snpdev->nii,
1900  &efi_nii31_protocol_guid, &snpdev->nii,
1903  NULL ) ) != 0 ) {
1904  DBGC ( snpdev, "SNPDEV %p could not uninstall: %s\n",
1905  snpdev, strerror ( -EEFI ( efirc ) ) );
1906  efi_nullify_snp ( &snpdev->snp );
1907  efi_nullify_nii ( &snpdev->nii );
1908  efi_nullify_name2 ( &snpdev->name2 );
1909  efi_nullify_load_file ( &snpdev->load_file );
1910  leak = 1;
1911  }
1912  if ( ! leak )
1913  free ( snpdev->path );
1914  bs->CloseEvent ( snpdev->snp.WaitForPacket );
1915  if ( ! leak ) {
1916  netdev_put ( snpdev->netdev );
1917  free ( snpdev );
1918  }
1919 
1920  /* Report leakage, if applicable */
1921  if ( leak )
1922  DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
1923 }
1924 
1925 /** SNP driver */
1926 struct net_driver efi_snp_driver __net_driver = {
1927  .name = "SNP",
1928  .probe = efi_snp_probe,
1929  .notify = efi_snp_notify,
1930  .remove = efi_snp_remove,
1931 };
1932 
1933 /**
1934  * Find SNP device by EFI device handle
1935  *
1936  * @v handle EFI device handle
1937  * @ret snpdev SNP device, or NULL
1938  */
1940  struct efi_snp_device *snpdev;
1941 
1942  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
1943  if ( snpdev->handle == handle )
1944  return snpdev;
1945  }
1946  return NULL;
1947 }
1948 
1949 /**
1950  * Get most recently opened SNP device
1951  *
1952  * @ret snpdev Most recently opened SNP device, or NULL
1953  */
1955  struct net_device *netdev;
1956 
1958  if ( ! netdev )
1959  return NULL;
1960 
1961  return efi_snp_demux ( netdev );
1962 }
1963 
1964 /**
1965  * Add to SNP claimed/released count
1966  *
1967  * @v delta Claim count change
1968  */
1969 void efi_snp_add_claim ( int delta ) {
1970  struct efi_snp_device *snpdev;
1971 
1972  /* Raise TPL if we are about to claim devices */
1973  if ( ! efi_snp_claimed )
1975 
1976  /* Claim SNP devices */
1977  efi_snp_claimed += delta;
1978  assert ( efi_snp_claimed >= 0 );
1979 
1980  /* Update SNP mode state for each interface */
1981  list_for_each_entry ( snpdev, &efi_snp_devices, list )
1982  efi_snp_set_state ( snpdev );
1983 
1984  /* Restore TPL if we have released devices */
1985  if ( ! efi_snp_claimed )
1987 }
EFI_GUID efi_nii31_protocol_guid
Network interface identifier protocol GUID (new version)
Definition: efi_guid.c:212
const char product_short_name[]
Product short name string.
Definition: version.c:75
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:98
#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
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
#define EINVAL
Invalid argument.
Definition: errno.h:428
#define EFI_UNSUPPORTED
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:123
PXE_UINT16 Protocol
Protocol type.
Definition: UefiPxe.h:1603
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:116
PXE_UINT32 BufferLen
Length of receive buffer.
Definition: UefiPxe.h:1748
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:129
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:167
#define AF_INET6
IPv6 Internet addresses.
Definition: socket.h:64
PXE_STATCODE StatCode
Definition: UefiPxe.h:889
static EFI_STATUS EFIAPI efi_snp_start(EFI_SIMPLE_NETWORK_PROTOCOL *snp)
Change SNP state from "stopped" to "started".
Definition: efi_snp.c:189
#define PXE_ROMID_MAJORVER
UNDI command interface revision.
Definition: UefiPxe.h:853
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:1620
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
#define PXE_ROMID_SIGNATURE
Signature of !PXE structure.
Definition: UefiPxe.h:841
PXE_UINT16 PXE_STATCODE
UNDI Fill Header.
Definition: UefiPxe.h:603
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
128 bit buffer containing a unique identifier value.
Definition: Base.h:263
#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED
Definition: UefiPxe.h:879
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii
The network interface identifier.
Definition: efi_snp.h:53
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 TPL_CALLBACK.
Definition: efi_init.c:373
EFI_COMPONENT_NAME2_PROTOCOL name2
Component name protocol.
Definition: efi_snp.h:55
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:102
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
VOID * EFI_EVENT
Handle to an event structure.
Definition: UefiBaseType.h:43
EFI strings.
int started
Started flag.
Definition: efi_snp.h:41
#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
Definition: UefiPxe.h:875
unsigned char BOOLEAN
Definition: ProcessorBind.h:61
PXE_UINT32 DataLen
Length of the data portion of the frame buffer in bytes.
Definition: UefiPxe.h:1684
size_t mtu
Maximum transmission unit length.
Definition: netdevice.h:409
#define PXE_BUSTYPE(a, b, c, d)
Definition: UefiPxe.h:28
PXE_OPFLAGS OpFlags
Definition: UefiPxe.h:884
#define EFI_PROTOCOL_ERROR
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:144
EFI_GUID efi_simple_network_protocol_guid
Simple network protocol GUID.
Definition: efi_guid.c:236
#define PXE_STATFLAGS_GET_STATE_STARTED
Definition: UefiPxe.h:432
#define DBGC(...)
Definition: compiler.h:505
#define PXE_STATFLAGS_COMMAND_FAILED
Definition: UefiPxe.h:424
#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:578
#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
PXE_DB_RECEIVE receive
Definition: efi_snp.c:910
const uint8_t * ll_broadcast
Link-layer broadcast address.
Definition: netdevice.h:383
#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE
Definition: UefiPxe.h:872
unsigned int UINT32
Definition: ProcessorBind.h:56
#define EFI_OPEN_PROTOCOL_BY_DRIVER
Definition: UefiSpec.h:1274
#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA
UNDI Initialize.
Definition: UefiPxe.h:455
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces
Definition: UefiSpec.h:1915
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:1275
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
Definition: ProcessorBind.h:59
EFI_CLOSE_EVENT CloseEvent
Definition: UefiSpec.h:1864
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
#define PXE_OPCODE_INITIALIZE
Changed UNDI operational state from Started to Initialized.
Definition: UefiPxe.h:119
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:51
#define PXE_STATCODE_BUSY
Definition: UefiPxe.h:615
static void efi_snp_claim(void)
Claim network devices for use by iPXE.
Definition: efi_snp.h:88
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:1347
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:186
int efi_child_add(EFI_HANDLE parent, EFI_HANDLE child)
Add EFI device as child of another EFI device.
Definition: efi_utils.c:94
unsigned long intptr_t
Definition: stdint.h:21
#define PXE_OPCODE_FILL_HEADER
Fill media header in packet for transmit.
Definition: UefiPxe.h:169
#define EFI_SNP_NUM_TX
SNP transmit completion ring size.
Definition: efi_snp.h:24
#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY
This flag is set if the transmitted buffer queue is empty.
Definition: UefiPxe.h:572
PXE_MAC_ADDR DestAddr
Definition: UefiPxe.h:1585
wchar_t controller_name[64]
Controller name.
Definition: efi_snp.h:73
EFI_CLOSE_PROTOCOL CloseProtocol
Definition: UefiSpec.h:1906
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:128
static const char * netdev_addr(struct net_device *netdev)
Get printable network device link-layer address.
Definition: netdevice.h:521
struct net_device_stats tx_stats
TX statistics.
Definition: netdevice.h:417
PXE_CPB_RECEIVE receive
Definition: efi_snp.c:902
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:461
PXE_MAC_ADDR SrcAddr
Source and destination MAC addresses.
Definition: UefiPxe.h:1584
EFI_HANDLE handle
EFI device handle.
Definition: efi_snp.h:35
#define TPL_NOTIFY
Definition: UefiSpec.h:592
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:551
A link-layer protocol.
Definition: netdevice.h:114
EFI_MAC_ADDRESS CurrentAddress
The current HW MAC address for the network interface.
#define EFI_OUT_OF_RESOURCES
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:129
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:144
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
static void efi_snp_notify(struct net_device *netdev)
Handle SNP device or link state change.
Definition: efi_snp.c:1848
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:1507
int ipxe(struct net_device *netdev)
Main iPXE flow of execution.
Definition: autoboot.c:567
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:31
EFI_MAC_ADDRESS BroadcastAddress
The current HW MAC address for broadcast packets.
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:57
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition: list.h:333
void efi_child_del(EFI_HANDLE parent, EFI_HANDLE child)
Remove EFI device as child of another EFI device.
Definition: efi_utils.c:128
#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:1678
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:1954
#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:208
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * name
Name.
Definition: netdevice.h:463
#define PXE_OPCODE_RESET
Re-initialize the NIC H/W.
Definition: UefiPxe.h:124
unsigned int tx_cons
Transmit completion ring consumer counter.
Definition: efi_snp.h:49
int efi_snp_hii_uninstall(struct efi_snp_device *snpdev)
Uninstall HII protocol and package for SNP device.
Definition: efi_snp_hii.c:798
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:174
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:652
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:61
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.
struct s_pxe_cpb_fill_header_fragmented::@518 FragDesc[MAX_XMIT_FRAGMENTS]
Array of packet fragment descriptors.
The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from arbitrary devices.
Definition: LoadFile.h:84
#define PXE_STATFLAGS_STATUS_MASK
Common StatFlags that can be returned by all commands.
Definition: UefiPxe.h:422
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:555
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:1633
16-byte buffer aligned on a 4-byte boundary.
Definition: UefiBaseType.h:110
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
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:622
PXE_DB_GET_STATUS get_status
Definition: efi_snp.c:909
UINT64 TxTotalFrames
Transmit statistics.
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:630
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:973
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
Definition: efi_strings.c:104
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition: netdevice.h:45
EFI_CREATE_EVENT CreateEvent
Definition: UefiSpec.h:1860
UINT64 RxDroppedFrames
Valid frames that were dropped because receive buffers were full.
Definition: SimpleNetwork.h:74
VOID * tx[EFI_SNP_NUM_TX]
Transmit completion ring.
Definition: efi_snp.h:45
#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
Definition: UefiPxe.h:446
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:1591
#define PXE_ROMID_MINORVER
Definition: UefiPxe.h:854
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:1969
User interaction.
#define PXE_ROMID_IMP_SW_VIRT_ADDR
Definition: UefiPxe.h:860
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:447
EFI null interfaces.
static __always_inline void off_t userptr_t src
Definition: efi_uaccess.h:66
PXE_CPB_STATION_ADDRESS station_address
Definition: efi_snp.c:898
unsigned short UINT16
Definition: ProcessorBind.h:58
wchar_t name[sizeof(((struct net_device *) NULL) ->name)]
Device name.
Definition: efi_snp.h:69
#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:713
EFI_SIGNAL_EVENT SignalEvent
Definition: UefiSpec.h:1863
PXE_UINT64 CPBaddr
Definition: UefiPxe.h:887
EFI_SIMPLE_NETWORK_PROTOCOL snp
The SNP structure itself.
Definition: efi_snp.h:37
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:523
#define ERANGE
Result too large.
Definition: errno.h:639
PXE_UINT64 BufferAddr
Address of first byte of receive buffer.
Definition: UefiPxe.h:1741
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:133
#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
device device nvs read
Definition: threewire.h:60
#define EFIAPI
UINT64 Revision
The revision of the EFI_NETWORK_INTERFACE_IDENTIFIER protocol.
static struct efi_snp_device * efi_undi_snpdev(unsigned int ifnum)
Identify UNDI SNP device.
Definition: efi_snp.c:950
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
EFI Boot Services Table.
Definition: UefiSpec.h:1836
IP address structure.
Definition: in.h:39
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:33
UINT64 RxTotalFrames
Total number of frames received.
Definition: SimpleNetwork.h:52
#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED
Definition: UefiPxe.h:382
#define PXE_ROMID_REV
!PXE structure format revision
Definition: UefiPxe.h:846
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:151
struct net_device_stats rx_stats
RX statistics.
Definition: netdevice.h:419
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
uint8_t * tmp
Definition: entropy.h:156
unsigned int bad
Count of error completions.
Definition: netdevice.h:291
#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
Definition: UefiPxe.h:874
#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA
This flag is set if there is no media detected.
Definition: UefiPxe.h:583
#define PXE_STATCODE_UNSUPPORTED
Definition: UefiPxe.h:624
A network device.
Definition: netdevice.h:348
Union type for data blocks.
Definition: efi_snp.c:906
struct net_driver efi_snp_driver __net_driver
SNP driver.
Definition: efi_snp.c:1926
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces
Definition: UefiSpec.h:1916
An SNP device.
Definition: efi_snp.h:27
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:96
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:290
PXE_UINT8 Fudge
makes 8-bit cksum zero.
Definition: UefiPxe.h:819
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:33
#define EVT_NOTIFY_WAIT
Definition: UefiSpec.h:393
UINT64 UINTN
Unsigned value of native width.
Definition: ProcessorBind.h:71
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:450
An EFI device.
Definition: efi_driver.h:17
#define EFI_NOT_READY
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:126
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:544
#define PXE_OPCODE_STOP
Change UNDI operational state from Started to Stopped.
Definition: UefiPxe.h:104
#define PXE_OPCODE_GET_STATUS
Get & clear interrupt status.
Definition: UefiPxe.h:164
#define EFI_INVALID_PARAMETER
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:122
EFI_GUID efi_device_path_protocol_guid
Device path protocol GUID.
Definition: efi_guid.c:132
Version number.
EFI_GUID efi_component_name2_protocol_guid
Component name 2 protocol GUID.
Definition: efi_guid.c:124
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:1555
uint16_t ll_proto
Link-layer protocol.
Definition: netdevice.h:194
#define VOID
Undeclared type.
Definition: Base.h:319
unsigned long long UINT64
Definition: ProcessorBind.h:54
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:324
#define EAGAIN
Resource temporarily unavailable.
Definition: errno.h:318
EFI API.
#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST
UNDI Receive Filters.
Definition: UefiPxe.h:492
struct list_head rx
Receive queue.
Definition: efi_snp.h:51
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:47
wchar_t driver_name[16]
Driver name.
Definition: efi_snp.h:71
struct device * dev
Underlying hardware device.
Definition: netdevice.h:360
EFI_GUID efi_nii_protocol_guid
Network interface identifier protocol GUID (old version)
Definition: efi_guid.c:208
void netdev_close(struct net_device *netdev)
Close network device.
Definition: netdevice.c:801
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:230
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:1939
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:63
#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:289
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:358
#define PXE_STATCODE_NO_DATA
Definition: UefiPxe.h:631
An EFI saved task priority level.
Definition: efi.h:72
General configuration.
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
uint32_t len
Length.
Definition: ena.h:14
unsigned int index
Index of this network device.
Definition: netdevice.h:356
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:824
#define DBGC2(...)
Definition: compiler.h:522
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:57
PXE_UINT64 EntryPoint
API entry point.
Definition: UefiPxe.h:827
EFI_LOAD_FILE LoadFile
Definition: LoadFile.h:85
char CHAR8
Definition: ProcessorBind.h:63
#define IOB_ZLEN
Minimum I/O buffer length.
Definition: iobuf.h:23
void * data
Start of data.
Definition: iobuf.h:44
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
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:821
static void efi_snp_poll(struct efi_snp_device *snpdev)
Poll net device and count received packets.
Definition: efi_snp.c:167
#define PXE_STATCODE_BUFFER_FULL
Definition: UefiPxe.h:625
#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST
If set, all multicast packets will be received.
Definition: UefiPxe.h:513
PXE_UINT64 MediaHeader
Address of first byte of media header.
Definition: UefiPxe.h:1591
PXE_STATFLAGS StatFlags
Definition: UefiPxe.h:890
void efi_nullify_load_file(EFI_LOAD_FILE_PROTOCOL *load_file)
Nullify Load File Protocol interface.
Definition: efi_null.c:255
#define PXE_OPCODE_RECEIVE
Receive packet.
Definition: UefiPxe.h:179
Virtual LANs.
#define PXE_OPCODE_RECEIVE_FILTERS
Read & change state of packet receive filters.
Definition: UefiPxe.h:139
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
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
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:613
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:873
static void efi_snp_remove(struct net_device *netdev)
Destroy SNP device.
Definition: efi_snp.c:1873
#define PXE_OPCODE_GET_STATE
Return UNDI operational state.
Definition: UefiPxe.h:94
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
size_t max_pkt_len
Maximum packet length.
Definition: netdevice.h:403
#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED
Definition: UefiPxe.h:878
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define PXE_OPCODE_GET_INIT_INFO
Get UNDI initialization information.
Definition: UefiPxe.h:109
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:176
#define PXE_FRAME_TYPE_PROMISCUOUS
Definition: UefiPxe.h:673
static int efi_snp_probe(struct net_device *netdev)
Create SNP device.
Definition: efi_snp.c:1624
EFI_DEVICE_PATH_PROTOCOL * path
The device path.
Definition: efi_snp.h:75
#define PXE_STATFLAGS_GET_STATE_STOPPED
Definition: UefiPxe.h:433
uint8_t bytes[64]
Definition: ib_mad.h:16
Simple Network Protocol data structures.
Definition: SimpleNetwork.h:47
#define PXE_STATCODE_INVALID_PARAMETER
Definition: UefiPxe.h:626
uint16_t handle
Handle.
Definition: smbios.h:16
EFI_SIMPLE_NETWORK_MODE mode
The SNP "mode" (parameters)
Definition: efi_snp.h:39
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:375
void efi_restore_tpl(struct efi_saved_tpl *tpl)
Restore task priority level.
Definition: efi_init.c:389
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
static struct efi_snp_device * efi_snp_demux(struct net_device *netdev)
Locate SNP device corresponding to network device.
Definition: efi_snp.c:1608
#define PXE_STATFLAGS_GET_STATUS_TRANSMIT
If set, at least one transmit interrupt occurred.
Definition: UefiPxe.h:556
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:891
#define PXE_OPCODE_START
Change UNDI operational state from Stopped to Started.
Definition: UefiPxe.h:99
String functions.
#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST
If set, broadcast packets will be received.
Definition: UefiPxe.h:497
#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:767
#define htons(value)
Definition: byteswap.h:135
PXE_OPCODE OpCode
Definition: UefiPxe.h:883
#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:423
struct list_head list
List of SNP devices.
Definition: efi_snp.h:29
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition: efi.h:159
Definition: efi.h:55
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:366
Union type for command parameter blocks.
Definition: efi_snp.c:897
unsigned int interrupts
Pending interrupt status.
Definition: efi_snp.h:43
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:508
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:1527
#define PXE_STATFLAGS_GET_STATE_INITIALIZED
Definition: UefiPxe.h:431
PXE_UINT64 DBaddr
Definition: UefiPxe.h:888
PXE_UINT64 FragAddr
Address of this packet fragment.
Definition: UefiPxe.h:1658
#define PXE_STATCODE_SUCCESS
Common StatCodes returned by all UNDI commands, UNDI protocol functions and BC protocol functions.
Definition: UefiPxe.h:611
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
struct io_buffer * netdev_rx_dequeue(struct net_device *netdev)
Remove packet from device's receive queue.
Definition: netdevice.c:538
A persistent I/O buffer.
Definition: iobuf.h:32