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_utils.h>
37 #include <ipxe/efi/efi_watchdog.h>
38 #include <ipxe/efi/efi_snp.h>
39 #include <usr/autoboot.h>
40 #include <config/general.h>
41 
42 /** List of SNP devices */
43 static LIST_HEAD ( efi_snp_devices );
44 
45 /** Network devices are currently claimed for use by iPXE */
46 static int efi_snp_claimed;
47 
48 /** TPL prior to network devices being claimed */
50 
51 /* Downgrade user experience if configured to do so
52  *
53  * The default UEFI user experience for network boot is somewhat
54  * excremental: only TFTP is available as a download protocol, and if
55  * anything goes wrong the user will be shown just a dot on an
56  * otherwise blank screen. (Some programmer was clearly determined to
57  * win a bet that they could outshine Apple at producing uninformative
58  * error messages.)
59  *
60  * For comparison, the default iPXE user experience provides the
61  * option to use protocols designed more recently than 1980 (such as
62  * HTTP and iSCSI), and if anything goes wrong the the user will be
63  * shown one of over 1200 different error messages, complete with a
64  * link to a wiki page describing that specific error.
65  *
66  * We default to upgrading the user experience to match that available
67  * in a "legacy" BIOS environment, by installing our own instance of
68  * EFI_LOAD_FILE_PROTOCOL.
69  *
70  * Note that unfortunately we can't sensibly provide the choice of
71  * both options to the user in the same build, because the UEFI boot
72  * menu ignores the multitude of ways in which a network device handle
73  * can be described and opaquely labels both menu entries as just "EFI
74  * Network".
75  */
76 #ifdef EFI_DOWNGRADE_UX
77 static EFI_GUID dummy_load_file_protocol_guid = {
78  0x6f6c7323, 0x2077, 0x7523,
79  { 0x6e, 0x68, 0x65, 0x6c, 0x70, 0x66, 0x75, 0x6c }
80 };
81 #define efi_load_file_protocol_guid dummy_load_file_protocol_guid
82 #endif
83 
84 /**
85  * Set EFI SNP mode state
86  *
87  * @v snp SNP interface
88  */
89 static void efi_snp_set_state ( struct efi_snp_device *snpdev ) {
90  struct net_device *netdev = snpdev->netdev;
91  EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
92 
93  /* Calculate state */
94  if ( ! snpdev->started ) {
95  /* Start() method not called; report as Stopped */
97  } else if ( ! netdev_is_open ( netdev ) ) {
98  /* Network device not opened; report as Started */
100  } else if ( efi_snp_claimed ) {
101  /* Network device opened but claimed for use by iPXE; report
102  * as Started to inhibit receive polling.
103  */
105  } else {
106  /* Network device opened and available for use via SNP; report
107  * as Initialized.
108  */
110  }
111 }
112 
113 /**
114  * Set EFI SNP mode based on iPXE net device parameters
115  *
116  * @v snp SNP interface
117  */
118 static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
119  struct net_device *netdev = snpdev->netdev;
120  EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
122  unsigned int ll_addr_len = ll_protocol->ll_addr_len;
123 
124  mode->HwAddressSize = ll_addr_len;
126  mode->MaxPacketSize = netdev->mtu;
130  assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
134  mode->IfType = ntohs ( ll_protocol->ll_proto );
135  mode->MacAddressChangeable = TRUE;
136  mode->MediaPresentSupported = TRUE;
137  mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
138 }
139 
140 /**
141  * Flush transmit ring and receive queue
142  *
143  * @v snpdev SNP device
144  */
145 static void efi_snp_flush ( struct efi_snp_device *snpdev ) {
146  struct io_buffer *iobuf;
147  struct io_buffer *tmp;
148 
149  /* Reset transmit completion ring */
150  snpdev->tx_prod = 0;
151  snpdev->tx_cons = 0;
152 
153  /* Discard any queued receive buffers */
154  list_for_each_entry_safe ( iobuf, tmp, &snpdev->rx, list ) {
155  list_del ( &iobuf->list );
156  free_iob ( iobuf );
157  }
158 }
159 
160 /**
161  * Poll net device and count received packets
162  *
163  * @v snpdev SNP device
164  */
165 static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
167  struct io_buffer *iobuf;
168 
169  /* Poll network device */
170  netdev_poll ( snpdev->netdev );
171 
172  /* Retrieve any received packets */
173  while ( ( iobuf = netdev_rx_dequeue ( snpdev->netdev ) ) ) {
174  list_add_tail ( &iobuf->list, &snpdev->rx );
176  bs->SignalEvent ( &snpdev->snp.WaitForPacket );
177  }
178 }
179 
180 /**
181  * Change SNP state from "stopped" to "started"
182  *
183  * @v snp SNP interface
184  * @ret efirc EFI status code
185  */
186 static EFI_STATUS EFIAPI
188  struct efi_snp_device *snpdev =
189  container_of ( snp, struct efi_snp_device, snp );
190 
191  DBGC ( snpdev, "SNPDEV %p START\n", snpdev );
192 
193  /* Fail if net device is currently claimed for use by iPXE */
194  if ( efi_snp_claimed )
195  return EFI_NOT_READY;
196 
197  snpdev->started = 1;
198  efi_snp_set_state ( snpdev );
199  return 0;
200 }
201 
202 /**
203  * Change SNP state from "started" to "stopped"
204  *
205  * @v snp SNP interface
206  * @ret efirc EFI status code
207  */
208 static EFI_STATUS EFIAPI
210  struct efi_snp_device *snpdev =
211  container_of ( snp, struct efi_snp_device, snp );
212 
213  DBGC ( snpdev, "SNPDEV %p STOP\n", snpdev );
214 
215  /* Fail if net device is currently claimed for use by iPXE */
216  if ( efi_snp_claimed )
217  return EFI_NOT_READY;
218 
219  snpdev->started = 0;
220  efi_snp_set_state ( snpdev );
221 
222  return 0;
223 }
224 
225 /**
226  * Open the network device
227  *
228  * @v snp SNP interface
229  * @v extra_rx_bufsize Extra RX buffer size, in bytes
230  * @v extra_tx_bufsize Extra TX buffer size, in bytes
231  * @ret efirc EFI status code
232  */
233 static EFI_STATUS EFIAPI
235  UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
237  struct efi_snp_device *snpdev =
238  container_of ( snp, struct efi_snp_device, snp );
239  EFI_TPL saved_tpl;
240  int rc;
241 
242  DBGC ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
243  snpdev, ( ( unsigned long ) extra_rx_bufsize ),
244  ( ( unsigned long ) extra_tx_bufsize ) );
245 
246  /* Fail if net device is currently claimed for use by iPXE */
247  if ( efi_snp_claimed ) {
248  rc = -EAGAIN;
249  goto err_claimed;
250  }
251 
252  /* Raise TPL */
253  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
254 
255  /* Open network device */
256  if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
257  DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
258  snpdev, snpdev->netdev->name, strerror ( rc ) );
259  goto err_open;
260  }
261  efi_snp_set_state ( snpdev );
262 
263  err_open:
264  bs->RestoreTPL ( saved_tpl );
265  err_claimed:
266  return EFIRC ( rc );
267 }
268 
269 /**
270  * Reset the network device
271  *
272  * @v snp SNP interface
273  * @v ext_verify Extended verification required
274  * @ret efirc EFI status code
275  */
276 static EFI_STATUS EFIAPI
279  struct efi_snp_device *snpdev =
280  container_of ( snp, struct efi_snp_device, snp );
281  EFI_TPL saved_tpl;
282  int rc;
283 
284  DBGC ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
285  snpdev, ( ext_verify ? "with" : "without" ) );
286 
287  /* Fail if net device is currently claimed for use by iPXE */
288  if ( efi_snp_claimed ) {
289  rc = -EAGAIN;
290  goto err_claimed;
291  }
292 
293  /* Raise TPL */
294  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
295 
296  /* Close network device */
297  netdev_close ( snpdev->netdev );
298  efi_snp_set_state ( snpdev );
299  efi_snp_flush ( snpdev );
300 
301  /* Reopen network device */
302  if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
303  DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
304  snpdev, snpdev->netdev->name, strerror ( rc ) );
305  goto err_open;
306  }
307  efi_snp_set_state ( snpdev );
308 
309  err_open:
310  bs->RestoreTPL ( saved_tpl );
311  err_claimed:
312  return EFIRC ( rc );
313 }
314 
315 /**
316  * Shut down the network device
317  *
318  * @v snp SNP interface
319  * @ret efirc EFI status code
320  */
321 static EFI_STATUS EFIAPI
324  struct efi_snp_device *snpdev =
325  container_of ( snp, struct efi_snp_device, snp );
326  EFI_TPL saved_tpl;
327 
328  DBGC ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
329 
330  /* Fail if net device is currently claimed for use by iPXE */
331  if ( efi_snp_claimed )
332  return EFI_NOT_READY;
333 
334  /* Raise TPL */
335  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
336 
337  /* Close network device */
338  netdev_close ( snpdev->netdev );
339  efi_snp_set_state ( snpdev );
340  efi_snp_flush ( snpdev );
341 
342  /* Restore TPL */
343  bs->RestoreTPL ( saved_tpl );
344 
345  return 0;
346 }
347 
348 /**
349  * Manage receive filters
350  *
351  * @v snp SNP interface
352  * @v enable Receive filters to enable
353  * @v disable Receive filters to disable
354  * @v mcast_reset Reset multicast filters
355  * @v mcast_count Number of multicast filters
356  * @v mcast Multicast filters
357  * @ret efirc EFI status code
358  */
359 static EFI_STATUS EFIAPI
361  UINT32 disable, BOOLEAN mcast_reset,
362  UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
363  struct efi_snp_device *snpdev =
364  container_of ( snp, struct efi_snp_device, snp );
365  unsigned int i;
366 
367  DBGC ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
368  snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
369  ( ( unsigned long ) mcast_count ) );
370  for ( i = 0 ; i < mcast_count ; i++ ) {
371  DBGC2_HDA ( snpdev, i, &mcast[i],
372  snpdev->netdev->ll_protocol->ll_addr_len );
373  }
374 
375  /* Lie through our teeth, otherwise MNP refuses to accept us.
376  *
377  * Return success even if the SNP device is currently claimed
378  * for use by iPXE, since otherwise Windows Deployment
379  * Services refuses to attempt to receive further packets via
380  * our EFI PXE Base Code protocol.
381  */
382  return 0;
383 }
384 
385 /**
386  * Set station address
387  *
388  * @v snp SNP interface
389  * @v reset Reset to permanent address
390  * @v new New station address
391  * @ret efirc EFI status code
392  */
393 static EFI_STATUS EFIAPI
395  EFI_MAC_ADDRESS *new ) {
396  struct efi_snp_device *snpdev =
397  container_of ( snp, struct efi_snp_device, snp );
398  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
399 
400  DBGC ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
401  ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
402 
403  /* Fail if net device is currently claimed for use by iPXE */
404  if ( efi_snp_claimed )
405  return EFI_NOT_READY;
406 
407  /* Set the MAC address */
408  if ( reset )
409  new = &snpdev->mode.PermanentAddress;
410  memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
411 
412  /* MAC address changes take effect only on netdev_open() */
413  if ( netdev_is_open ( snpdev->netdev ) ) {
414  DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
415  "device open\n", snpdev );
416  }
417 
418  return 0;
419 }
420 
421 /**
422  * Get (or reset) statistics
423  *
424  * @v snp SNP interface
425  * @v reset Reset statistics
426  * @v stats_len Size of statistics table
427  * @v stats Statistics table
428  * @ret efirc EFI status code
429  */
430 static EFI_STATUS EFIAPI
432  UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
433  struct efi_snp_device *snpdev =
434  container_of ( snp, struct efi_snp_device, snp );
435  EFI_NETWORK_STATISTICS stats_buf;
436 
437  DBGC ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
438  ( reset ? " reset" : "" ) );
439 
440  /* Fail if net device is currently claimed for use by iPXE */
441  if ( efi_snp_claimed )
442  return EFI_NOT_READY;
443 
444  /* Gather statistics */
445  memset ( &stats_buf, 0, sizeof ( stats_buf ) );
446  stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
447  stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
448  stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
449  snpdev->netdev->tx_stats.bad );
450  stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
451  stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
452  stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
453  snpdev->netdev->rx_stats.bad );
454  if ( *stats_len > sizeof ( stats_buf ) )
455  *stats_len = sizeof ( stats_buf );
456  if ( stats )
457  memcpy ( stats, &stats_buf, *stats_len );
458 
459  /* Reset statistics if requested to do so */
460  if ( reset ) {
461  memset ( &snpdev->netdev->tx_stats, 0,
462  sizeof ( snpdev->netdev->tx_stats ) );
463  memset ( &snpdev->netdev->rx_stats, 0,
464  sizeof ( snpdev->netdev->rx_stats ) );
465  }
466 
467  return 0;
468 }
469 
470 /**
471  * Convert multicast IP address to MAC address
472  *
473  * @v snp SNP interface
474  * @v ipv6 Address is IPv6
475  * @v ip IP address
476  * @v mac MAC address
477  * @ret efirc EFI status code
478  */
479 static EFI_STATUS EFIAPI
482  struct efi_snp_device *snpdev =
483  container_of ( snp, struct efi_snp_device, snp );
484  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
485  const char *ip_str;
486  int rc;
487 
488  ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
489  inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
490  DBGC ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
491 
492  /* Fail if net device is currently claimed for use by iPXE */
493  if ( efi_snp_claimed )
494  return EFI_NOT_READY;
495 
496  /* Try to hash the address */
497  if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
498  ip, mac ) ) != 0 ) {
499  DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
500  snpdev, ip_str, strerror ( rc ) );
501  return EFIRC ( rc );
502  }
503 
504  return 0;
505 }
506 
507 /**
508  * Read or write non-volatile storage
509  *
510  * @v snp SNP interface
511  * @v read Operation is a read
512  * @v offset Starting offset within NVRAM
513  * @v len Length of data buffer
514  * @v data Data buffer
515  * @ret efirc EFI status code
516  */
517 static EFI_STATUS EFIAPI
519  UINTN offset, UINTN len, VOID *data ) {
520  struct efi_snp_device *snpdev =
521  container_of ( snp, struct efi_snp_device, snp );
522 
523  DBGC ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
524  ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
525  ( ( unsigned long ) len ) );
526  if ( ! read )
527  DBGC2_HDA ( snpdev, offset, data, len );
528 
529  /* Fail if net device is currently claimed for use by iPXE */
530  if ( efi_snp_claimed )
531  return EFI_NOT_READY;
532 
533  return EFI_UNSUPPORTED;
534 }
535 
536 /**
537  * Read interrupt status and TX recycled buffer status
538  *
539  * @v snp SNP interface
540  * @v interrupts Interrupt status, or NULL
541  * @v txbuf Recycled transmit buffer address, or NULL
542  * @ret efirc EFI status code
543  */
544 static EFI_STATUS EFIAPI
546  UINT32 *interrupts, VOID **txbuf ) {
548  struct efi_snp_device *snpdev =
549  container_of ( snp, struct efi_snp_device, snp );
550  EFI_TPL saved_tpl;
551 
552  DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
553 
554  /* Fail if net device is currently claimed for use by iPXE */
555  if ( efi_snp_claimed ) {
556  DBGC2 ( snpdev, "\n" );
557  return EFI_NOT_READY;
558  }
559 
560  /* Raise TPL */
561  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
562 
563  /* Poll the network device */
564  efi_snp_poll ( snpdev );
565 
566  /* Interrupt status. In practice, this seems to be used only
567  * to detect TX completions.
568  */
569  if ( interrupts ) {
570  *interrupts = snpdev->interrupts;
571  DBGC2 ( snpdev, " INTS:%02x", *interrupts );
572  snpdev->interrupts = 0;
573  }
574 
575  /* TX completions */
576  if ( txbuf ) {
577  if ( snpdev->tx_prod != snpdev->tx_cons ) {
578  *txbuf = snpdev->tx[snpdev->tx_cons++ % EFI_SNP_NUM_TX];
579  } else {
580  *txbuf = NULL;
581  }
582  DBGC2 ( snpdev, " TX:%p", *txbuf );
583  }
584 
585  /* Restore TPL */
586  bs->RestoreTPL ( saved_tpl );
587 
588  DBGC2 ( snpdev, "\n" );
589  return 0;
590 }
591 
592 /**
593  * Start packet transmission
594  *
595  * @v snp SNP interface
596  * @v ll_header_len Link-layer header length, if to be filled in
597  * @v len Length of data buffer
598  * @v data Data buffer
599  * @v ll_src Link-layer source address, if specified
600  * @v ll_dest Link-layer destination address, if specified
601  * @v net_proto Network-layer protocol (in host order)
602  * @ret efirc EFI status code
603  */
604 static EFI_STATUS EFIAPI
606  UINTN ll_header_len, UINTN len, VOID *data,
607  EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
608  UINT16 *net_proto ) {
610  struct efi_snp_device *snpdev =
611  container_of ( snp, struct efi_snp_device, snp );
612  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
613  struct io_buffer *iobuf;
614  size_t payload_len;
615  unsigned int tx_fill;
616  EFI_TPL saved_tpl;
617  int rc;
618 
619  DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
620  ( ( unsigned long ) len ) );
621  if ( ll_header_len ) {
622  if ( ll_src ) {
623  DBGC2 ( snpdev, " src %s",
624  ll_protocol->ntoa ( ll_src ) );
625  }
626  if ( ll_dest ) {
627  DBGC2 ( snpdev, " dest %s",
628  ll_protocol->ntoa ( ll_dest ) );
629  }
630  if ( net_proto ) {
631  DBGC2 ( snpdev, " proto %04x", *net_proto );
632  }
633  }
634  DBGC2 ( snpdev, "\n" );
635 
636  /* Fail if net device is currently claimed for use by iPXE */
637  if ( efi_snp_claimed ) {
638  rc = -EAGAIN;
639  goto err_claimed;
640  }
641 
642  /* Raise TPL */
643  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
644 
645  /* Sanity checks */
646  if ( ll_header_len ) {
647  if ( ll_header_len != ll_protocol->ll_header_len ) {
648  DBGC ( snpdev, "SNPDEV %p TX invalid header length "
649  "%ld\n", snpdev,
650  ( ( unsigned long ) ll_header_len ) );
651  rc = -EINVAL;
652  goto err_sanity;
653  }
654  if ( len < ll_header_len ) {
655  DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
656  snpdev, ( ( unsigned long ) len ) );
657  rc = -EINVAL;
658  goto err_sanity;
659  }
660  if ( ! ll_dest ) {
661  DBGC ( snpdev, "SNPDEV %p TX missing destination "
662  "address\n", snpdev );
663  rc = -EINVAL;
664  goto err_sanity;
665  }
666  if ( ! net_proto ) {
667  DBGC ( snpdev, "SNPDEV %p TX missing network "
668  "protocol\n", snpdev );
669  rc = -EINVAL;
670  goto err_sanity;
671  }
672  if ( ! ll_src )
673  ll_src = &snpdev->mode.CurrentAddress;
674  }
675 
676  /* Allocate buffer */
677  payload_len = ( len - ll_protocol->ll_header_len );
678  iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ?
679  payload_len : IOB_ZLEN ) );
680  if ( ! iobuf ) {
681  DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
682  "buffer\n", snpdev, ( ( unsigned long ) len ) );
683  rc = -ENOMEM;
684  goto err_alloc_iob;
685  }
686  iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN -
688  memcpy ( iob_put ( iobuf, len ), data, len );
689 
690  /* Create link-layer header, if specified */
691  if ( ll_header_len ) {
692  iob_pull ( iobuf, ll_protocol->ll_header_len );
693  if ( ( rc = ll_protocol->push ( snpdev->netdev,
694  iobuf, ll_dest, ll_src,
695  htons ( *net_proto ) )) != 0 ){
696  DBGC ( snpdev, "SNPDEV %p TX could not construct "
697  "header: %s\n", snpdev, strerror ( rc ) );
698  goto err_ll_push;
699  }
700  }
701 
702  /* Transmit packet */
703  if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
704  DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
705  snpdev, strerror ( rc ) );
706  goto err_tx;
707  }
708 
709  /* Record in transmit completion ring. If we run out of
710  * space, report the failure even though we have already
711  * transmitted the packet.
712  *
713  * This allows us to report completions only for packets for
714  * which we had reported successfully initiating transmission,
715  * while continuing to support clients that never poll for
716  * transmit completions.
717  */
718  tx_fill = ( snpdev->tx_prod - snpdev->tx_cons );
719  if ( tx_fill >= EFI_SNP_NUM_TX ) {
720  DBGC ( snpdev, "SNPDEV %p TX completion ring full\n", snpdev );
721  rc = -ENOBUFS;
722  goto err_ring_full;
723  }
724  snpdev->tx[ snpdev->tx_prod++ % EFI_SNP_NUM_TX ] = data;
726 
727  /* Restore TPL */
728  bs->RestoreTPL ( saved_tpl );
729 
730  return 0;
731 
732  err_ring_full:
733  err_tx:
734  err_ll_push:
735  free_iob ( iobuf );
736  err_alloc_iob:
737  err_sanity:
738  bs->RestoreTPL ( saved_tpl );
739  err_claimed:
740  return EFIRC ( rc );
741 }
742 
743 /**
744  * Receive packet
745  *
746  * @v snp SNP interface
747  * @v ll_header_len Link-layer header length, if to be filled in
748  * @v len Length of data buffer
749  * @v data Data buffer
750  * @v ll_src Link-layer source address, if specified
751  * @v ll_dest Link-layer destination address, if specified
752  * @v net_proto Network-layer protocol (in host order)
753  * @ret efirc EFI status code
754  */
755 static EFI_STATUS EFIAPI
757  UINTN *ll_header_len, UINTN *len, VOID *data,
758  EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
759  UINT16 *net_proto ) {
761  struct efi_snp_device *snpdev =
762  container_of ( snp, struct efi_snp_device, snp );
763  struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
764  struct io_buffer *iobuf;
765  const void *iob_ll_dest;
766  const void *iob_ll_src;
767  uint16_t iob_net_proto;
768  unsigned int iob_flags;
769  size_t copy_len;
770  EFI_TPL saved_tpl;
771  int rc;
772 
773  DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
774  ( ( unsigned long ) *len ) );
775 
776  /* Fail if net device is currently claimed for use by iPXE */
777  if ( efi_snp_claimed ) {
778  rc = -EAGAIN;
779  goto err_claimed;
780  }
781 
782  /* Raise TPL */
783  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
784 
785  /* Poll the network device */
786  efi_snp_poll ( snpdev );
787 
788  /* Check for an available packet */
789  iobuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
790  if ( ! iobuf ) {
791  DBGC2 ( snpdev, "\n" );
792  rc = -EAGAIN;
793  goto out_no_packet;
794  }
795  DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
796 
797  /* Dequeue packet */
798  list_del ( &iobuf->list );
799 
800  /* Return packet to caller, truncating to buffer length */
801  copy_len = iob_len ( iobuf );
802  if ( copy_len > *len )
803  copy_len = *len;
804  memcpy ( data, iobuf->data, copy_len );
805  *len = iob_len ( iobuf );
806 
807  /* Attempt to decode link-layer header */
808  if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
809  &iob_ll_src, &iob_net_proto,
810  &iob_flags ) ) != 0 ) {
811  DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
812  snpdev, strerror ( rc ) );
813  goto out_bad_ll_header;
814  }
815 
816  /* Return link-layer header parameters to caller, if required */
817  if ( ll_header_len )
818  *ll_header_len = ll_protocol->ll_header_len;
819  if ( ll_src )
820  memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
821  if ( ll_dest )
822  memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
823  if ( net_proto )
824  *net_proto = ntohs ( iob_net_proto );
825 
826  /* Check buffer length */
827  rc = ( ( copy_len == *len ) ? 0 : -ERANGE );
828 
829  out_bad_ll_header:
830  free_iob ( iobuf );
831  out_no_packet:
832  bs->RestoreTPL ( saved_tpl );
833  err_claimed:
834  return EFIRC ( rc );
835 }
836 
837 /**
838  * Poll event
839  *
840  * @v event Event
841  * @v context Event context
842  */
844  VOID *context ) {
846  struct efi_snp_device *snpdev = context;
847  EFI_TPL saved_tpl;
848 
849  DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
850 
851  /* Do nothing unless the net device is open */
852  if ( ! netdev_is_open ( snpdev->netdev ) )
853  return;
854 
855  /* Do nothing if net device is currently claimed for use by iPXE */
856  if ( efi_snp_claimed )
857  return;
858 
859  /* Raise TPL */
860  saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
861 
862  /* Poll the network device */
863  efi_snp_poll ( snpdev );
864 
865  /* Restore TPL */
866  bs->RestoreTPL ( saved_tpl );
867 }
868 
869 /** SNP interface */
872  .Start = efi_snp_start,
873  .Stop = efi_snp_stop,
874  .Initialize = efi_snp_initialize,
875  .Reset = efi_snp_reset,
876  .Shutdown = efi_snp_shutdown,
877  .ReceiveFilters = efi_snp_receive_filters,
878  .StationAddress = efi_snp_station_address,
879  .Statistics = efi_snp_statistics,
880  .MCastIpToMac = efi_snp_mcast_ip_to_mac,
881  .NvData = efi_snp_nvdata,
882  .GetStatus = efi_snp_get_status,
883  .Transmit = efi_snp_transmit,
884  .Receive = efi_snp_receive,
885 };
886 
887 /******************************************************************************
888  *
889  * UNDI protocol
890  *
891  ******************************************************************************
892  */
893 
894 /** Union type for command parameter blocks */
895 typedef union {
901 } PXE_CPB_ANY;
902 
903 /** Union type for data blocks */
904 typedef union {
909 } PXE_DB_ANY;
910 
911 /**
912  * Calculate UNDI byte checksum
913  *
914  * @v data Data
915  * @v len Length of data
916  * @ret sum Checksum
917  */
918 static uint8_t efi_undi_checksum ( void *data, size_t len ) {
919  uint8_t *bytes = data;
920  uint8_t sum = 0;
921 
922  while ( len-- )
923  sum += *bytes++;
924  return sum;
925 }
926 
927 /**
928  * Get UNDI SNP device interface number
929  *
930  * @v snpdev SNP device
931  * @ret ifnum UNDI interface number
932  */
933 static unsigned int efi_undi_ifnum ( struct efi_snp_device *snpdev ) {
934 
935  /* iPXE network device indexes are one-based (leaving zero
936  * meaning "unspecified"). UNDI interface numbers are
937  * zero-based.
938  */
939  return ( snpdev->netdev->index - 1 );
940 }
941 
942 /**
943  * Identify UNDI SNP device
944  *
945  * @v ifnum Interface number
946  * @ret snpdev SNP device, or NULL if not found
947  */
948 static struct efi_snp_device * efi_undi_snpdev ( unsigned int ifnum ) {
949  struct efi_snp_device *snpdev;
950 
951  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
952  if ( efi_undi_ifnum ( snpdev ) == ifnum )
953  return snpdev;
954  }
955  return NULL;
956 }
957 
958 /**
959  * Convert EFI status code to UNDI status code
960  *
961  * @v efirc EFI status code
962  * @ret statcode UNDI status code
963  */
965 
966  switch ( efirc ) {
971  case EFI_NOT_READY: return PXE_STATCODE_NO_DATA;
972  default:
974  }
975 }
976 
977 /**
978  * Get state
979  *
980  * @v snpdev SNP device
981  * @v cdb Command description block
982  * @ret efirc EFI status code
983  */
985  PXE_CDB *cdb ) {
986  EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
987 
988  DBGC ( snpdev, "UNDI %p GET STATE\n", snpdev );
989 
990  /* Return current state */
993  } else if ( mode->State == EfiSimpleNetworkStarted ) {
995  } else {
997  }
998 
999  return 0;
1000 }
1001 
1002 /**
1003  * Start
1004  *
1005  * @v snpdev SNP device
1006  * @ret efirc EFI status code
1007  */
1008 static EFI_STATUS efi_undi_start ( struct efi_snp_device *snpdev ) {
1009  EFI_STATUS efirc;
1010 
1011  DBGC ( snpdev, "UNDI %p START\n", snpdev );
1012 
1013  /* Start SNP device */
1014  if ( ( efirc = efi_snp_start ( &snpdev->snp ) ) != 0 )
1015  return efirc;
1016 
1017  return 0;
1018 }
1019 
1020 /**
1021  * Stop
1022  *
1023  * @v snpdev SNP device
1024  * @ret efirc EFI status code
1025  */
1026 static EFI_STATUS efi_undi_stop ( struct efi_snp_device *snpdev ) {
1027  EFI_STATUS efirc;
1028 
1029  DBGC ( snpdev, "UNDI %p STOP\n", snpdev );
1030 
1031  /* Stop SNP device */
1032  if ( ( efirc = efi_snp_stop ( &snpdev->snp ) ) != 0 )
1033  return efirc;
1034 
1035  return 0;
1036 }
1037 
1038 /**
1039  * Get initialisation information
1040  *
1041  * @v snpdev SNP device
1042  * @v cdb Command description block
1043  * @v db Data block
1044  * @ret efirc EFI status code
1045  */
1047  PXE_CDB *cdb,
1049  struct net_device *netdev = snpdev->netdev;
1051 
1052  DBGC ( snpdev, "UNDI %p GET INIT INFO\n", snpdev );
1053 
1054  /* Populate structure */
1055  memset ( db, 0, sizeof ( *db ) );
1056  db->FrameDataLen = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
1057  db->MediaHeaderLen = ll_protocol->ll_header_len;
1058  db->HWaddrLen = ll_protocol->ll_addr_len;
1059  db->IFtype = ntohs ( ll_protocol->ll_proto );
1062 
1063  return 0;
1064 }
1065 
1066 /**
1067  * Initialise
1068  *
1069  * @v snpdev SNP device
1070  * @v cdb Command description block
1071  * @v efirc EFI status code
1072  */
1074  PXE_CDB *cdb ) {
1075  struct net_device *netdev = snpdev->netdev;
1076  EFI_STATUS efirc;
1077 
1078  DBGC ( snpdev, "UNDI %p INITIALIZE\n", snpdev );
1079 
1080  /* Reset SNP device */
1081  if ( ( efirc = efi_snp_initialize ( &snpdev->snp, 0, 0 ) ) != 0 )
1082  return efirc;
1083 
1084  /* Report link state */
1085  if ( ! netdev_link_ok ( netdev ) )
1087 
1088  return 0;
1089 }
1090 
1091 /**
1092  * Reset
1093  *
1094  * @v snpdev SNP device
1095  * @v efirc EFI status code
1096  */
1097 static EFI_STATUS efi_undi_reset ( struct efi_snp_device *snpdev ) {
1098  EFI_STATUS efirc;
1099 
1100  DBGC ( snpdev, "UNDI %p RESET\n", snpdev );
1101 
1102  /* Reset SNP device */
1103  if ( ( efirc = efi_snp_reset ( &snpdev->snp, 0 ) ) != 0 )
1104  return efirc;
1105 
1106  return 0;
1107 }
1108 
1109 /**
1110  * Shutdown
1111  *
1112  * @v snpdev SNP device
1113  * @v efirc EFI status code
1114  */
1115 static EFI_STATUS efi_undi_shutdown ( struct efi_snp_device *snpdev ) {
1116  EFI_STATUS efirc;
1117 
1118  DBGC ( snpdev, "UNDI %p SHUTDOWN\n", snpdev );
1119 
1120  /* Reset SNP device */
1121  if ( ( efirc = efi_snp_shutdown ( &snpdev->snp ) ) != 0 )
1122  return efirc;
1123 
1124  return 0;
1125 }
1126 
1127 /**
1128  * Get/set receive filters
1129  *
1130  * @v snpdev SNP device
1131  * @v cdb Command description block
1132  * @v efirc EFI status code
1133  */
1135  PXE_CDB *cdb ) {
1136 
1137  DBGC ( snpdev, "UNDI %p RECEIVE FILTERS\n", snpdev );
1138 
1139  /* Mark everything as supported */
1144 
1145  return 0;
1146 }
1147 
1148 /**
1149  * Get/set station address
1150  *
1151  * @v snpdev SNP device
1152  * @v cdb Command description block
1153  * @v cpb Command parameter block
1154  * @v efirc EFI status code
1155  */
1157  PXE_CDB *cdb,
1160  struct net_device *netdev = snpdev->netdev;
1162  void *mac;
1163  int reset;
1164  EFI_STATUS efirc;
1165 
1166  DBGC ( snpdev, "UNDI %p STATION ADDRESS\n", snpdev );
1167 
1168  /* Update address if applicable */
1169  reset = ( cdb->OpFlags & PXE_OPFLAGS_STATION_ADDRESS_RESET );
1170  mac = ( cpb ? &cpb->StationAddr : NULL );
1171  if ( ( reset || mac ) &&
1172  ( ( efirc = efi_snp_station_address ( &snpdev->snp, reset,
1173  mac ) ) != 0 ) )
1174  return efirc;
1175 
1176  /* Fill in current addresses, if applicable */
1177  if ( db ) {
1178  memset ( db, 0, sizeof ( *db ) );
1179  memcpy ( &db->StationAddr, netdev->ll_addr,
1181  memcpy ( &db->BroadcastAddr, netdev->ll_broadcast,
1183  memcpy ( &db->PermanentAddr, netdev->hw_addr,
1185  }
1186 
1187  return 0;
1188 }
1189 
1190 /**
1191  * Get interrupt status
1192  *
1193  * @v snpdev SNP device
1194  * @v cdb Command description block
1195  * @v db Data block
1196  * @v efirc EFI status code
1197  */
1199  PXE_CDB *cdb, PXE_DB_GET_STATUS *db ) {
1200  UINT32 interrupts;
1201  VOID *txbuf;
1202  struct io_buffer *rxbuf;
1203  EFI_STATUS efirc;
1204 
1205  DBGC2 ( snpdev, "UNDI %p GET STATUS\n", snpdev );
1206 
1207  /* Get status */
1208  if ( ( efirc = efi_snp_get_status ( &snpdev->snp, &interrupts,
1209  &txbuf ) ) != 0 )
1210  return efirc;
1211 
1212  /* Report status */
1213  memset ( db, 0, sizeof ( *db ) );
1214  if ( interrupts & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT )
1216  if ( interrupts & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT )
1218  if ( txbuf ) {
1219  db->TxBuffer[0] = ( ( intptr_t ) txbuf );
1220  } else {
1222  /* The specification states clearly that UNDI drivers
1223  * should set TXBUF_QUEUE_EMPTY if all completed
1224  * buffer addresses are written into the returned data
1225  * block. However, SnpDxe chooses to interpret
1226  * TXBUF_QUEUE_EMPTY as a synonym for
1227  * NO_TXBUFS_WRITTEN, thereby rendering it entirely
1228  * pointless. Work around this UEFI stupidity, as per
1229  * usual.
1230  */
1231  if ( snpdev->tx_prod == snpdev->tx_cons )
1232  cdb->StatFlags |=
1234  }
1235  rxbuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
1236  if ( rxbuf )
1237  db->RxFrameLen = iob_len ( rxbuf );
1238  if ( ! netdev_link_ok ( snpdev->netdev ) )
1240 
1241  return 0;
1242 }
1243 
1244 /**
1245  * Fill header
1246  *
1247  * @v snpdev SNP device
1248  * @v cdb Command description block
1249  * @v cpb Command parameter block
1250  * @v efirc EFI status code
1251  */
1253  PXE_CDB *cdb, PXE_CPB_ANY *cpb ) {
1254  struct net_device *netdev = snpdev->netdev;
1256  PXE_CPB_FILL_HEADER *whole = &cpb->fill_header;
1258  VOID *data;
1259  void *dest;
1260  void *src;
1261  uint16_t proto;
1262  struct io_buffer iobuf;
1263  int rc;
1264 
1265  /* SnpDxe will (pointlessly) use PXE_CPB_FILL_HEADER_FRAGMENTED
1266  * even though we choose to explicitly not claim support for
1267  * fragments via PXE_ROMID_IMP_FRAG_SUPPORTED.
1268  */
1270  data = ( ( void * ) ( intptr_t ) fragged->FragDesc[0].FragAddr);
1271  dest = &fragged->DestAddr;
1272  src = &fragged->SrcAddr;
1273  proto = fragged->Protocol;
1274  } else {
1275  data = ( ( void * ) ( intptr_t ) whole->MediaHeader );
1276  dest = &whole->DestAddr;
1277  src = &whole->SrcAddr;
1278  proto = whole->Protocol;
1279  }
1280 
1281  /* Construct link-layer header */
1282  iob_populate ( &iobuf, data, 0, ll_protocol->ll_header_len );
1283  iob_reserve ( &iobuf, ll_protocol->ll_header_len );
1284  if ( ( rc = ll_protocol->push ( netdev, &iobuf, dest, src,
1285  proto ) ) != 0 )
1286  return EFIRC ( rc );
1287 
1288  return 0;
1289 }
1290 
1291 /**
1292  * Transmit
1293  *
1294  * @v snpdev SNP device
1295  * @v cpb Command parameter block
1296  * @v efirc EFI status code
1297  */
1299  PXE_CPB_TRANSMIT *cpb ) {
1300  VOID *data = ( ( void * ) ( intptr_t ) cpb->FrameAddr );
1301  EFI_STATUS efirc;
1302 
1303  DBGC2 ( snpdev, "UNDI %p TRANSMIT\n", snpdev );
1304 
1305  /* Transmit packet */
1306  if ( ( efirc = efi_snp_transmit ( &snpdev->snp, 0, cpb->DataLen,
1307  data, NULL, NULL, NULL ) ) != 0 )
1308  return efirc;
1309 
1310  return 0;
1311 }
1312 
1313 /**
1314  * Receive
1315  *
1316  * @v snpdev SNP device
1317  * @v cpb Command parameter block
1318  * @v efirc EFI status code
1319  */
1321  PXE_CPB_RECEIVE *cpb,
1322  PXE_DB_RECEIVE *db ) {
1323  struct net_device *netdev = snpdev->netdev;
1325  VOID *data = ( ( void * ) ( intptr_t ) cpb->BufferAddr );
1326  UINTN hdr_len;
1327  UINTN len = cpb->BufferLen;
1330  UINT16 proto;
1331  EFI_STATUS efirc;
1332 
1333  DBGC2 ( snpdev, "UNDI %p RECEIVE\n", snpdev );
1334 
1335  /* Receive packet */
1336  if ( ( efirc = efi_snp_receive ( &snpdev->snp, &hdr_len, &len, data,
1337  &src, &dest, &proto ) ) != 0 )
1338  return efirc;
1339 
1340  /* Describe frame */
1341  memset ( db, 0, sizeof ( *db ) );
1342  memcpy ( &db->SrcAddr, &src, ll_protocol->ll_addr_len );
1343  memcpy ( &db->DestAddr, &dest, ll_protocol->ll_addr_len );
1344  db->FrameLen = len;
1345  db->Protocol = proto;
1346  db->MediaHeaderLen = ll_protocol->ll_header_len;
1348 
1349  return 0;
1350 }
1351 
1352 /** UNDI entry point */
1353 static EFIAPI VOID efi_undi_issue ( UINT64 cdb_phys ) {
1354  PXE_CDB *cdb = ( ( void * ) ( intptr_t ) cdb_phys );
1355  PXE_CPB_ANY *cpb = ( ( void * ) ( intptr_t ) cdb->CPBaddr );
1356  PXE_DB_ANY *db = ( ( void * ) ( intptr_t ) cdb->DBaddr );
1357  struct efi_snp_device *snpdev;
1358  EFI_STATUS efirc;
1359 
1360  /* Identify device */
1361  snpdev = efi_undi_snpdev ( cdb->IFnum );
1362  if ( ! snpdev ) {
1363  DBGC ( cdb, "UNDI invalid interface number %d\n", cdb->IFnum );
1366  return;
1367  }
1368 
1369  /* Fail if net device is currently claimed for use by iPXE */
1370  if ( efi_snp_claimed ) {
1371  cdb->StatCode = PXE_STATCODE_BUSY;
1373  return;
1374  }
1375 
1376  /* Handle opcode */
1379  switch ( cdb->OpCode ) {
1380 
1381  case PXE_OPCODE_GET_STATE:
1382  efirc = efi_undi_get_state ( snpdev, cdb );
1383  break;
1384 
1385  case PXE_OPCODE_START:
1386  efirc = efi_undi_start ( snpdev );
1387  break;
1388 
1389  case PXE_OPCODE_STOP:
1390  efirc = efi_undi_stop ( snpdev );
1391  break;
1392 
1394  efirc = efi_undi_get_init_info ( snpdev, cdb,
1395  &db->get_init_info );
1396  break;
1397 
1398  case PXE_OPCODE_INITIALIZE:
1399  efirc = efi_undi_initialize ( snpdev, cdb );
1400  break;
1401 
1402  case PXE_OPCODE_RESET:
1403  efirc = efi_undi_reset ( snpdev );
1404  break;
1405 
1406  case PXE_OPCODE_SHUTDOWN:
1407  efirc = efi_undi_shutdown ( snpdev );
1408  break;
1409 
1411  efirc = efi_undi_receive_filters ( snpdev, cdb );
1412  break;
1413 
1415  efirc = efi_undi_station_address ( snpdev, cdb,
1416  &cpb->station_address,
1417  &db->station_address );
1418  break;
1419 
1420  case PXE_OPCODE_GET_STATUS:
1421  efirc = efi_undi_get_status ( snpdev, cdb, &db->get_status );
1422  break;
1423 
1425  efirc = efi_undi_fill_header ( snpdev, cdb, cpb );
1426  break;
1427 
1428  case PXE_OPCODE_TRANSMIT:
1429  efirc = efi_undi_transmit ( snpdev, &cpb->transmit );
1430  break;
1431 
1432  case PXE_OPCODE_RECEIVE:
1433  efirc = efi_undi_receive ( snpdev, &cpb->receive,
1434  &db->receive );
1435  break;
1436 
1437  default:
1438  DBGC ( snpdev, "UNDI %p unsupported opcode %#04x\n",
1439  snpdev, cdb->OpCode );
1440  efirc = EFI_UNSUPPORTED;
1441  break;
1442  }
1443 
1444  /* Convert EFI status code to UNDI status code */
1445  if ( efirc != 0 ) {
1448  cdb->StatCode = efi_undi_statcode ( efirc );
1449  }
1450 }
1451 
1452 /** UNDI interface
1453  *
1454  * Must be aligned on a 16-byte boundary, for no particularly good
1455  * reason.
1456  */
1457 static PXE_SW_UNDI efi_snp_undi __attribute__ (( aligned ( 16 ) )) = {
1458  .Signature = PXE_ROMID_SIGNATURE,
1459  .Len = sizeof ( efi_snp_undi ),
1460  .Rev = PXE_ROMID_REV,
1461  .MajorVer = PXE_ROMID_MAJORVER,
1462  .MinorVer = PXE_ROMID_MINORVER,
1463  .Implementation = ( PXE_ROMID_IMP_SW_VIRT_ADDR |
1470  /* SnpDxe checks that BusCnt is non-zero. It makes no further
1471  * use of BusCnt, and never looks as BusType[]. As with much
1472  * of the EDK2 code, this check seems to serve no purpose
1473  * whatsoever but must nonetheless be humoured.
1474  */
1475  .BusCnt = 1,
1476  .BusType[0] = PXE_BUSTYPE ( 'i', 'P', 'X', 'E' ),
1477 };
1478 
1479 /** Network Identification Interface (NII) */
1482  .StringId = "UNDI",
1483  .Type = EfiNetworkInterfaceUndi,
1484  .MajorVer = 3,
1485  .MinorVer = 1,
1486  .Ipv6Supported = TRUE, /* This is a raw packet interface, FFS! */
1487 };
1488 
1489 /******************************************************************************
1490  *
1491  * Component name protocol
1492  *
1493  ******************************************************************************
1494  */
1495 
1496 /**
1497  * Look up driver name
1498  *
1499  * @v name2 Component name protocol
1500  * @v language Language to use
1501  * @v driver_name Driver name to fill in
1502  * @ret efirc EFI status code
1503  */
1504 static EFI_STATUS EFIAPI
1506  CHAR8 *language __unused, CHAR16 **driver_name ) {
1507  struct efi_snp_device *snpdev =
1508  container_of ( name2, struct efi_snp_device, name2 );
1509 
1510  *driver_name = snpdev->driver_name;
1511  return 0;
1512 }
1513 
1514 /**
1515  * Look up controller name
1516  *
1517  * @v name2 Component name protocol
1518  * @v device Device
1519  * @v child Child device, or NULL
1520  * @v language Language to use
1521  * @v driver_name Device name to fill in
1522  * @ret efirc EFI status code
1523  */
1524 static EFI_STATUS EFIAPI
1527  EFI_HANDLE child __unused,
1528  CHAR8 *language __unused,
1529  CHAR16 **controller_name ) {
1530  struct efi_snp_device *snpdev =
1531  container_of ( name2, struct efi_snp_device, name2 );
1532 
1533  *controller_name = snpdev->controller_name;
1534  return 0;
1535 }
1536 
1537 /******************************************************************************
1538  *
1539  * Load file protocol
1540  *
1541  ******************************************************************************
1542  */
1543 
1544 /**
1545  * Load file
1546  *
1547  * @v loadfile Load file protocol
1548  * @v path File path
1549  * @v booting Loading as part of a boot attempt
1550  * @ret efirc EFI status code
1551  */
1552 static EFI_STATUS EFIAPI
1555  BOOLEAN booting, UINTN *len __unused,
1556  VOID *data __unused ) {
1557  struct efi_snp_device *snpdev =
1559  struct net_device *netdev = snpdev->netdev;
1560  int rc;
1561 
1562  /* Fail unless this is a boot attempt */
1563  if ( ! booting ) {
1564  DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
1565  snpdev );
1566  return EFI_UNSUPPORTED;
1567  }
1568 
1569  /* Claim network devices for use by iPXE */
1570  efi_snp_claim();
1571 
1572  /* Start watchdog holdoff timer */
1574 
1575  /* Boot from network device */
1576  if ( ( rc = ipxe ( netdev ) ) != 0 )
1577  goto err_ipxe;
1578 
1579  /* Reset console */
1580  console_reset();
1581 
1582  err_ipxe:
1584  efi_snp_release();
1585  return EFIRC ( rc );
1586 }
1587 
1588 /** Load file protocol */
1591 };
1592 
1593 /******************************************************************************
1594  *
1595  * iPXE network driver
1596  *
1597  ******************************************************************************
1598  */
1599 
1600 /**
1601  * Locate SNP device corresponding to network device
1602  *
1603  * @v netdev Network device
1604  * @ret snp SNP device, or NULL if not found
1605  */
1606 static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
1607  struct efi_snp_device *snpdev;
1608 
1609  list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
1610  if ( snpdev->netdev == netdev )
1611  return snpdev;
1612  }
1613  return NULL;
1614 }
1615 
1616 /**
1617  * Create SNP device
1618  *
1619  * @v netdev Network device
1620  * @ret rc Return status code
1621  */
1622 static int efi_snp_probe ( struct net_device *netdev ) {
1624  struct efi_device *efidev;
1625  struct efi_snp_device *snpdev;
1626  EFI_DEVICE_PATH_PROTOCOL *path_end;
1627  MAC_ADDR_DEVICE_PATH *macpath;
1628  VLAN_DEVICE_PATH *vlanpath;
1629  size_t path_prefix_len = 0;
1630  unsigned int ifcnt;
1631  unsigned int tag;
1632  void *interface;
1633  EFI_STATUS efirc;
1634  int rc;
1635 
1636  /* Find parent EFI device */
1637  efidev = efidev_parent ( netdev->dev );
1638  if ( ! efidev ) {
1639  DBG ( "SNP skipping non-EFI device %s\n", netdev->name );
1640  rc = 0;
1641  goto err_no_efidev;
1642  }
1643 
1644  /* Allocate the SNP device */
1645  snpdev = zalloc ( sizeof ( *snpdev ) );
1646  if ( ! snpdev ) {
1647  rc = -ENOMEM;
1648  goto err_alloc_snp;
1649  }
1650  snpdev->netdev = netdev_get ( netdev );
1651  snpdev->efidev = efidev;
1652  INIT_LIST_HEAD ( &snpdev->rx );
1653 
1654  /* Sanity check */
1655  if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
1656  DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
1657  "length %d for %s\n", snpdev,
1659  rc = -ENOTSUP;
1660  goto err_ll_addr_len;
1661  }
1662 
1663  /* Populate the SNP structure */
1664  memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
1665  snpdev->snp.Mode = &snpdev->mode;
1666  if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
1667  efi_snp_wait_for_packet, snpdev,
1668  &snpdev->snp.WaitForPacket ) ) != 0 ){
1669  rc = -EEFI ( efirc );
1670  DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
1671  snpdev, strerror ( rc ) );
1672  goto err_create_event;
1673  }
1674 
1675  /* Populate the SNP mode structure */
1677  efi_snp_set_mode ( snpdev );
1678 
1679  /* Populate the NII structure */
1680  memcpy ( &snpdev->nii, &efi_snp_device_nii, sizeof ( snpdev->nii ) );
1681  snpdev->nii.Id = ( ( intptr_t ) &efi_snp_undi );
1682  snpdev->nii.IfNum = efi_undi_ifnum ( snpdev );
1684  ifcnt = ( ( efi_snp_undi.IFcntExt << 8 ) | efi_snp_undi.IFcnt );
1685  if ( ifcnt < snpdev->nii.IfNum )
1686  ifcnt = snpdev->nii.IfNum;
1687  efi_snp_undi.IFcnt = ( ifcnt & 0xff );
1688  efi_snp_undi.IFcntExt = ( ifcnt >> 8 );
1690  sizeof ( efi_snp_undi ) );
1691 
1692  /* Populate the component name structure */
1693  efi_snprintf ( snpdev->driver_name,
1694  ( sizeof ( snpdev->driver_name ) /
1695  sizeof ( snpdev->driver_name[0] ) ),
1696  "%s %s", product_short_name, netdev->dev->driver_name );
1697  efi_snprintf ( snpdev->controller_name,
1698  ( sizeof ( snpdev->controller_name ) /
1699  sizeof ( snpdev->controller_name[0] ) ),
1700  "%s %s (%s, %s)", product_short_name,
1702  netdev_addr ( netdev ) );
1705  snpdev->name2.SupportedLanguages = "en";
1706 
1707  /* Populate the load file protocol structure */
1709  sizeof ( snpdev->load_file ) );
1710 
1711  /* Populate the device name */
1712  efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
1713  sizeof ( snpdev->name[0] ) ),
1714  "%s", netdev->name );
1715 
1716  /* Allocate the new device path */
1717  path_prefix_len = efi_devpath_len ( efidev->path );
1718  snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) +
1719  sizeof ( *vlanpath ) + sizeof ( *path_end ) );
1720  if ( ! snpdev->path ) {
1721  rc = -ENOMEM;
1722  goto err_alloc_device_path;
1723  }
1724 
1725  /* Populate the device path */
1726  memcpy ( snpdev->path, efidev->path, path_prefix_len );
1727  macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len );
1728  memset ( macpath, 0, sizeof ( *macpath ) );
1729  macpath->Header.Type = MESSAGING_DEVICE_PATH;
1730  macpath->Header.SubType = MSG_MAC_ADDR_DP;
1731  macpath->Header.Length[0] = sizeof ( *macpath );
1732  memcpy ( &macpath->MacAddress, netdev->ll_addr,
1734  macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
1735  if ( ( tag = vlan_tag ( netdev ) ) ) {
1736  vlanpath = ( ( ( void * ) macpath ) + sizeof ( *macpath ) );
1737  memset ( vlanpath, 0, sizeof ( *vlanpath ) );
1738  vlanpath->Header.Type = MESSAGING_DEVICE_PATH;
1739  vlanpath->Header.SubType = MSG_VLAN_DP;
1740  vlanpath->Header.Length[0] = sizeof ( *vlanpath );
1741  vlanpath->VlanId = tag;
1742  path_end = ( ( ( void * ) vlanpath ) + sizeof ( *vlanpath ) );
1743  } else {
1744  path_end = ( ( ( void * ) macpath ) + sizeof ( *macpath ) );
1745  }
1746  memset ( path_end, 0, sizeof ( *path_end ) );
1747  path_end->Type = END_DEVICE_PATH_TYPE;
1749  path_end->Length[0] = sizeof ( *path_end );
1750 
1751  /* Install the SNP */
1752  if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1753  &snpdev->handle,
1756  &efi_nii_protocol_guid, &snpdev->nii,
1757  &efi_nii31_protocol_guid, &snpdev->nii,
1760  NULL ) ) != 0 ) {
1761  rc = -EEFI ( efirc );
1762  DBGC ( snpdev, "SNPDEV %p could not install protocols: %s\n",
1763  snpdev, strerror ( rc ) );
1764  goto err_install_protocol_interface;
1765  }
1766 
1767  /* SnpDxe will repeatedly start up and shut down our NII/UNDI
1768  * interface (in order to obtain the MAC address) before
1769  * discovering that it cannot install another SNP on the same
1770  * handle. This causes the underlying network device to be
1771  * unexpectedly closed.
1772  *
1773  * Prevent this by opening our own NII (and NII31) protocol
1774  * instances to prevent SnpDxe from attempting to bind to
1775  * them.
1776  */
1777  if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
1779  efi_image_handle, snpdev->handle,
1782  rc = -EEFI ( efirc );
1783  DBGC ( snpdev, "SNPDEV %p could not open NII protocol: %s\n",
1784  snpdev, strerror ( rc ) );
1785  goto err_open_nii;
1786  }
1787  if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
1789  efi_image_handle, snpdev->handle,
1792  rc = -EEFI ( efirc );
1793  DBGC ( snpdev, "SNPDEV %p could not open NII31 protocol: %s\n",
1794  snpdev, strerror ( rc ) );
1795  goto err_open_nii31;
1796  }
1797 
1798  /* Add as child of EFI parent device */
1799  if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) {
1800  DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n",
1801  snpdev, efi_handle_name ( efidev->device ),
1802  strerror ( rc ) );
1803  goto err_efi_child_add;
1804  }
1805 
1806  /* Install HII */
1807  if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
1808  DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
1809  snpdev, strerror ( rc ) );
1810  /* HII fails on several platforms. It's
1811  * non-essential, so treat this as a non-fatal
1812  * error.
1813  */
1814  }
1815 
1816  /* Add to list of SNP devices */
1817  list_add ( &snpdev->list, &efi_snp_devices );
1818 
1819  /* Close device path */
1822 
1823  DBGC ( snpdev, "SNPDEV %p installed for %s as device %s\n",
1824  snpdev, netdev->name, efi_handle_name ( snpdev->handle ) );
1825  return 0;
1826 
1827  list_del ( &snpdev->list );
1828  if ( snpdev->package_list )
1829  efi_snp_hii_uninstall ( snpdev );
1830  efi_child_del ( efidev->device, snpdev->handle );
1831  err_efi_child_add:
1833  efi_image_handle, snpdev->handle );
1834  err_open_nii31:
1835  bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
1836  efi_image_handle, snpdev->handle );
1837  err_open_nii:
1839  snpdev->handle,
1842  &efi_nii_protocol_guid, &snpdev->nii,
1843  &efi_nii31_protocol_guid, &snpdev->nii,
1846  NULL );
1847  err_install_protocol_interface:
1848  free ( snpdev->path );
1849  err_alloc_device_path:
1850  bs->CloseEvent ( snpdev->snp.WaitForPacket );
1851  err_create_event:
1852  err_ll_addr_len:
1853  netdev_put ( netdev );
1854  free ( snpdev );
1855  err_alloc_snp:
1856  err_no_efidev:
1857  return rc;
1858 }
1859 
1860 /**
1861  * Handle SNP device or link state change
1862  *
1863  * @v netdev Network device
1864  */
1865 static void efi_snp_notify ( struct net_device *netdev ) {
1866  struct efi_snp_device *snpdev;
1867 
1868  /* Locate SNP device */
1869  snpdev = efi_snp_demux ( netdev );
1870  if ( ! snpdev ) {
1871  DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
1872  return;
1873  }
1874 
1875  /* Update link state */
1876  snpdev->mode.MediaPresent =
1877  ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
1878  DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
1879  ( snpdev->mode.MediaPresent ? "up" : "down" ) );
1880 
1881  /* Update mode state */
1882  efi_snp_set_state ( snpdev );
1883 }
1884 
1885 /**
1886  * Destroy SNP device
1887  *
1888  * @v netdev Network device
1889  */
1890 static void efi_snp_remove ( struct net_device *netdev ) {
1892  struct efi_snp_device *snpdev;
1893 
1894  /* Locate SNP device */
1895  snpdev = efi_snp_demux ( netdev );
1896  if ( ! snpdev ) {
1897  DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
1898  return;
1899  }
1900 
1901  /* Uninstall the SNP */
1902  list_del ( &snpdev->list );
1903  if ( snpdev->package_list )
1904  efi_snp_hii_uninstall ( snpdev );
1905  efi_child_del ( snpdev->efidev->device, snpdev->handle );
1906  bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
1907  efi_image_handle, snpdev->handle );
1909  efi_image_handle, snpdev->handle );
1911  snpdev->handle,
1914  &efi_nii_protocol_guid, &snpdev->nii,
1915  &efi_nii31_protocol_guid, &snpdev->nii,
1918  NULL );
1919  free ( snpdev->path );
1920  bs->CloseEvent ( snpdev->snp.WaitForPacket );
1921  netdev_put ( snpdev->netdev );
1922  free ( 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 ) {
1971  struct efi_snp_device *snpdev;
1972 
1973  /* Raise TPL if we are about to claim devices */
1974  if ( ! efi_snp_claimed )
1976 
1977  /* Claim SNP devices */
1978  efi_snp_claimed += delta;
1979  assert ( efi_snp_claimed >= 0 );
1980 
1981  /* Update SNP mode state for each interface */
1982  list_for_each_entry ( snpdev, &efi_snp_devices, list )
1983  efi_snp_set_state ( snpdev );
1984 
1985  /* Restore TPL if we have released devices */
1986  if ( ! efi_snp_claimed )
1987  bs->RestoreTPL ( efi_snp_old_tpl );
1988 }
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:1115
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:234
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:964
#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:984
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:157
#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:187
EFI_RAISE_TPL RaiseTPL
Definition: UefiSpec.h:1845
#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:145
#define PXE_ROMID_SIGNATURE
Signature of !PXE structure.
Definition: UefiPxe.h:841
#define END_DEVICE_PATH_TYPE
Definition: DevicePath.h:1327
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:1134
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.
UINT8 IfType
Network interface type(i.e.
Definition: DevicePath.h:554
static EFI_STATUS efi_undi_transmit(struct efi_snp_device *snpdev, PXE_CPB_TRANSMIT *cpb)
Transmit.
Definition: efi_snp.c:1298
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
EFI_MAC_ADDRESS MacAddress
The MAC address for a network interface padded with 0s.
Definition: DevicePath.h:550
#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:1457
char name[40]
Name.
Definition: device.h:75
PXE_DB_RECEIVE receive
Definition: efi_snp.c:908
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:89
#define MSG_MAC_ADDR_DP
MAC Address Device Path SubType.
Definition: DevicePath.h:544
size_t efi_devpath_len(EFI_DEVICE_PATH_PROTOCOL *path)
Find length of device path (excluding terminator)
Definition: efi_utils.c:59
#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:394
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:933
#define ntohs(value)
Definition: byteswap.h:136
#define PXE_OPCODE_INITIALIZE
Changed UNDI operational state from Started to Initialized.
Definition: UefiPxe.h:119
EFI_DEVICE_PATH_PROTOCOL Header
Definition: DevicePath.h:546
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:1046
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:124
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:360
static int efi_snp_claimed
Network devices are currently claimed for use by iPXE.
Definition: efi_snp.c:46
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
#define MESSAGING_DEVICE_PATH
Messaging Device Paths.
Definition: DevicePath.h:315
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:900
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:870
#define PXE_STATFLAGS_GET_STATUS_RECEIVE
If set, at least one receive interrupt occurred.
Definition: UefiPxe.h:551
void efi_snp_hii_uninstall(struct efi_snp_device *snpdev)
Uninstall HII protocol and package for SNP device.
Definition: efi_snp_hii.c:779
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:1026
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:1865
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:1156
PXE_DB_GET_INIT_INFO get_init_info
Definition: efi_snp.c:905
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:1097
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:1505
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:518
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:158
#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_install(struct efi_snp_device *snpdev)
Install HII protocol and packages for SNP device.
Definition: efi_snp_hii.c:655
#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:756
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:898
#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:209
Assertions.
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:109
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:907
UINT64 TxTotalFrames
Transmit statistics.
EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName
PXE_DB_STATION_ADDRESS station_address
Definition: efi_snp.c:906
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:480
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
UINT16 VlanId
VLAN identifier (0-4094).
Definition: DevicePath.h:916
#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
Definition: UefiPxe.h:446
static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol
Load file protocol.
Definition: efi_snp.c:1589
#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:605
#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
static __always_inline void off_t userptr_t src
Definition: efi_uaccess.h:66
PXE_CPB_STATION_ADDRESS station_address
Definition: efi_snp.c:896
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:1353
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
#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:1320
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:948
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:30
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:118
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:904
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:897
#define TPL_CALLBACK
Definition: UefiSpec.h:591
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
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:431
#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:899
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:1553
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:918
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:1480
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:322
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:1252
#define MSG_VLAN_DP
VLAN Device Path SubType.
Definition: DevicePath.h:910
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:1198
#define iob_reserve(iobuf, len)
Definition: iobuf.h:63
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
#define END_ENTIRE_DEVICE_PATH_SUBTYPE
Definition: DevicePath.h:1328
#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
__weak unsigned int vlan_tag(struct net_device *netdev __unused)
Get the VLAN tag (when VLAN support is not present)
Definition: netdevice.c:1124
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
UINTN EFI_TPL
Task priority level.
Definition: UefiBaseType.h:47
EFI_DEVICE_PATH_PROTOCOL Header
Definition: DevicePath.h:912
#define PXE_STATCODE_NO_DATA
Definition: UefiPxe.h:631
General configuration.
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
UINT8 Length[2]
Specific Device Path data.
Definition: DevicePath.h:64
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:545
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
struct s_pxe_cpb_fill_header_fragmented::@517 FragDesc[MAX_XMIT_FRAGMENTS]
Array of packet fragment descriptors.
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
UINT8 SubType
Varies by Type 0xFF End Entire Device Path, or 0x01 End This Instance of a Device Path and start a ne...
Definition: DevicePath.h:59
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:165
#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
#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
UINT8 Type
0x01 Hardware Device Path.
Definition: DevicePath.h:52
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
EFI_DEVICE_PATH_PROTOCOL * path
EFI device path copy.
Definition: efi_driver.h:23
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:1890
#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
EFI_RESTORE_TPL RestoreTPL
Definition: UefiSpec.h:1846
#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:1073
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:1622
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
uint64_t tag
Identity tag.
Definition: edd.h:30
Simple Network Protocol data structures.
Definition: SimpleNetwork.h:47
static EFI_TPL efi_snp_old_tpl
TPL prior to network devices being claimed.
Definition: efi_snp.c:49
#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:843
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:375
#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:1606
#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:277
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
#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:149
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:895
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:1525
#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:1008
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