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