2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
20 FILE_LICENCE ( GPL2_OR_LATER );
27 #include <ipxe/netdevice.h>
28 #include <ipxe/iobuf.h>
30 #include <ipxe/version.h>
31 #include <ipxe/efi/efi.h>
32 #include <ipxe/efi/efi_driver.h>
33 #include <ipxe/efi/efi_strings.h>
34 #include <ipxe/efi/efi_utils.h>
35 #include <ipxe/efi/efi_watchdog.h>
36 #include <ipxe/efi/efi_snp.h>
37 #include <usr/autoboot.h>
38 #include <config/general.h>
40 /** List of SNP devices */
41 static LIST_HEAD ( efi_snp_devices );
43 /** Network devices are currently claimed for use by iPXE */
44 static int efi_snp_claimed;
46 /* Downgrade user experience if configured to do so
48 * The default UEFI user experience for network boot is somewhat
49 * excremental: only TFTP is available as a download protocol, and if
50 * anything goes wrong the user will be shown just a dot on an
51 * otherwise blank screen. (Some programmer was clearly determined to
52 * win a bet that they could outshine Apple at producing uninformative
55 * For comparison, the default iPXE user experience provides the
56 * option to use protocols designed more recently than 1980 (such as
57 * HTTP and iSCSI), and if anything goes wrong the the user will be
58 * shown one of over 1200 different error messages, complete with a
59 * link to a wiki page describing that specific error.
61 * We default to upgrading the user experience to match that available
62 * in a "legacy" BIOS environment, by installing our own instance of
63 * EFI_LOAD_FILE_PROTOCOL.
65 * Note that unfortunately we can't sensibly provide the choice of
66 * both options to the user in the same build, because the UEFI boot
67 * menu ignores the multitude of ways in which a network device handle
68 * can be described and opaquely labels both menu entries as just "EFI
71 #ifdef EFI_DOWNGRADE_UX
72 static EFI_GUID dummy_load_file_protocol_guid = {
73 0x6f6c7323, 0x2077, 0x7523,
74 { 0x6e, 0x68, 0x65, 0x6c, 0x70, 0x66, 0x75, 0x6c }
76 #define efi_load_file_protocol_guid dummy_load_file_protocol_guid
80 * Set EFI SNP mode state
82 * @v snp SNP interface
84 static void efi_snp_set_state ( struct efi_snp_device *snpdev ) {
85 struct net_device *netdev = snpdev->netdev;
86 EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
89 if ( ! snpdev->started ) {
90 /* Start() method not called; report as Stopped */
91 mode->State = EfiSimpleNetworkStopped;
92 } else if ( ! netdev_is_open ( netdev ) ) {
93 /* Network device not opened; report as Started */
94 mode->State = EfiSimpleNetworkStarted;
95 } else if ( efi_snp_claimed ) {
96 /* Network device opened but claimed for use by iPXE; report
97 * as Started to inhibit receive polling.
99 mode->State = EfiSimpleNetworkStarted;
101 /* Network device opened and available for use via SNP; report
104 mode->State = EfiSimpleNetworkInitialized;
109 * Set EFI SNP mode based on iPXE net device parameters
111 * @v snp SNP interface
113 static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
114 struct net_device *netdev = snpdev->netdev;
115 EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
116 struct ll_protocol *ll_protocol = netdev->ll_protocol;
117 unsigned int ll_addr_len = ll_protocol->ll_addr_len;
119 mode->HwAddressSize = ll_addr_len;
120 mode->MediaHeaderSize = ll_protocol->ll_header_len;
121 mode->MaxPacketSize = netdev->max_pkt_len;
122 mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
123 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
124 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
125 assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
126 memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
127 memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
128 ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
129 mode->IfType = ntohs ( ll_protocol->ll_proto );
130 mode->MacAddressChangeable = TRUE;
131 mode->MediaPresentSupported = TRUE;
132 mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
136 * Flush transmit ring and receive queue
138 * @v snpdev SNP device
140 static void efi_snp_flush ( struct efi_snp_device *snpdev ) {
141 struct io_buffer *iobuf;
142 struct io_buffer *tmp;
144 /* Reset transmit completion ring */
148 /* Discard any queued receive buffers */
149 list_for_each_entry_safe ( iobuf, tmp, &snpdev->rx, list ) {
150 list_del ( &iobuf->list );
156 * Poll net device and count received packets
158 * @v snpdev SNP device
160 static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
161 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
162 struct io_buffer *iobuf;
164 /* Poll network device */
165 netdev_poll ( snpdev->netdev );
167 /* Retrieve any received packets */
168 while ( ( iobuf = netdev_rx_dequeue ( snpdev->netdev ) ) ) {
169 list_add_tail ( &iobuf->list, &snpdev->rx );
170 snpdev->interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
171 bs->SignalEvent ( &snpdev->snp.WaitForPacket );
176 * Change SNP state from "stopped" to "started"
178 * @v snp SNP interface
179 * @ret efirc EFI status code
181 static EFI_STATUS EFIAPI
182 efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
183 struct efi_snp_device *snpdev =
184 container_of ( snp, struct efi_snp_device, snp );
186 DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
188 /* Fail if net device is currently claimed for use by iPXE */
189 if ( efi_snp_claimed )
190 return EFI_NOT_READY;
193 efi_snp_set_state ( snpdev );
198 * Change SNP state from "started" to "stopped"
200 * @v snp SNP interface
201 * @ret efirc EFI status code
203 static EFI_STATUS EFIAPI
204 efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
205 struct efi_snp_device *snpdev =
206 container_of ( snp, struct efi_snp_device, snp );
208 DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
210 /* Fail if net device is currently claimed for use by iPXE */
211 if ( efi_snp_claimed )
212 return EFI_NOT_READY;
215 efi_snp_set_state ( snpdev );
220 * Open the network device
222 * @v snp SNP interface
223 * @v extra_rx_bufsize Extra RX buffer size, in bytes
224 * @v extra_tx_bufsize Extra TX buffer size, in bytes
225 * @ret efirc EFI status code
227 static EFI_STATUS EFIAPI
228 efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
229 UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
230 struct efi_snp_device *snpdev =
231 container_of ( snp, struct efi_snp_device, snp );
234 DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
235 snpdev, ( ( unsigned long ) extra_rx_bufsize ),
236 ( ( unsigned long ) extra_tx_bufsize ) );
238 /* Fail if net device is currently claimed for use by iPXE */
239 if ( efi_snp_claimed )
240 return EFI_NOT_READY;
242 if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
243 DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
244 snpdev, snpdev->netdev->name, strerror ( rc ) );
247 efi_snp_set_state ( snpdev );
253 * Reset the network device
255 * @v snp SNP interface
256 * @v ext_verify Extended verification required
257 * @ret efirc EFI status code
259 static EFI_STATUS EFIAPI
260 efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
261 struct efi_snp_device *snpdev =
262 container_of ( snp, struct efi_snp_device, snp );
265 DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
266 snpdev, ( ext_verify ? "with" : "without" ) );
268 /* Fail if net device is currently claimed for use by iPXE */
269 if ( efi_snp_claimed )
270 return EFI_NOT_READY;
272 netdev_close ( snpdev->netdev );
273 efi_snp_set_state ( snpdev );
274 efi_snp_flush ( snpdev );
276 if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
277 DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
278 snpdev, snpdev->netdev->name, strerror ( rc ) );
281 efi_snp_set_state ( snpdev );
287 * Shut down the network device
289 * @v snp SNP interface
290 * @ret efirc EFI status code
292 static EFI_STATUS EFIAPI
293 efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
294 struct efi_snp_device *snpdev =
295 container_of ( snp, struct efi_snp_device, snp );
297 DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
299 /* Fail if net device is currently claimed for use by iPXE */
300 if ( efi_snp_claimed )
301 return EFI_NOT_READY;
303 netdev_close ( snpdev->netdev );
304 efi_snp_set_state ( snpdev );
305 efi_snp_flush ( snpdev );
311 * Manage receive filters
313 * @v snp SNP interface
314 * @v enable Receive filters to enable
315 * @v disable Receive filters to disable
316 * @v mcast_reset Reset multicast filters
317 * @v mcast_count Number of multicast filters
318 * @v mcast Multicast filters
319 * @ret efirc EFI status code
321 static EFI_STATUS EFIAPI
322 efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
323 UINT32 disable, BOOLEAN mcast_reset,
324 UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
325 struct efi_snp_device *snpdev =
326 container_of ( snp, struct efi_snp_device, snp );
329 DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
330 snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
331 ( ( unsigned long ) mcast_count ) );
332 for ( i = 0 ; i < mcast_count ; i++ ) {
333 DBGC2_HDA ( snpdev, i, &mcast[i],
334 snpdev->netdev->ll_protocol->ll_addr_len );
337 /* Fail if net device is currently claimed for use by iPXE */
338 if ( efi_snp_claimed )
339 return EFI_NOT_READY;
341 /* Lie through our teeth, otherwise MNP refuses to accept us */
346 * Set station address
348 * @v snp SNP interface
349 * @v reset Reset to permanent address
350 * @v new New station address
351 * @ret efirc EFI status code
353 static EFI_STATUS EFIAPI
354 efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
355 EFI_MAC_ADDRESS *new ) {
356 struct efi_snp_device *snpdev =
357 container_of ( snp, struct efi_snp_device, snp );
358 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
360 DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
361 ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
363 /* Fail if net device is currently claimed for use by iPXE */
364 if ( efi_snp_claimed )
365 return EFI_NOT_READY;
367 /* Set the MAC address */
369 new = &snpdev->mode.PermanentAddress;
370 memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
372 /* MAC address changes take effect only on netdev_open() */
373 if ( netdev_is_open ( snpdev->netdev ) ) {
374 DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
375 "device open\n", snpdev );
382 * Get (or reset) statistics
384 * @v snp SNP interface
385 * @v reset Reset statistics
386 * @v stats_len Size of statistics table
387 * @v stats Statistics table
388 * @ret efirc EFI status code
390 static EFI_STATUS EFIAPI
391 efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
392 UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
393 struct efi_snp_device *snpdev =
394 container_of ( snp, struct efi_snp_device, snp );
395 EFI_NETWORK_STATISTICS stats_buf;
397 DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
398 ( reset ? " reset" : "" ) );
400 /* Fail if net device is currently claimed for use by iPXE */
401 if ( efi_snp_claimed )
402 return EFI_NOT_READY;
404 /* Gather statistics */
405 memset ( &stats_buf, 0, sizeof ( stats_buf ) );
406 stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
407 stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
408 stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
409 snpdev->netdev->tx_stats.bad );
410 stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
411 stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
412 stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
413 snpdev->netdev->rx_stats.bad );
414 if ( *stats_len > sizeof ( stats_buf ) )
415 *stats_len = sizeof ( stats_buf );
417 memcpy ( stats, &stats_buf, *stats_len );
419 /* Reset statistics if requested to do so */
421 memset ( &snpdev->netdev->tx_stats, 0,
422 sizeof ( snpdev->netdev->tx_stats ) );
423 memset ( &snpdev->netdev->rx_stats, 0,
424 sizeof ( snpdev->netdev->rx_stats ) );
431 * Convert multicast IP address to MAC address
433 * @v snp SNP interface
434 * @v ipv6 Address is IPv6
437 * @ret efirc EFI status code
439 static EFI_STATUS EFIAPI
440 efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
441 EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) {
442 struct efi_snp_device *snpdev =
443 container_of ( snp, struct efi_snp_device, snp );
444 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
448 ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
449 inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
450 DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
452 /* Fail if net device is currently claimed for use by iPXE */
453 if ( efi_snp_claimed )
454 return EFI_NOT_READY;
456 /* Try to hash the address */
457 if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
459 DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
460 snpdev, ip_str, strerror ( rc ) );
468 * Read or write non-volatile storage
470 * @v snp SNP interface
471 * @v read Operation is a read
472 * @v offset Starting offset within NVRAM
473 * @v len Length of data buffer
474 * @v data Data buffer
475 * @ret efirc EFI status code
477 static EFI_STATUS EFIAPI
478 efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
479 UINTN offset, UINTN len, VOID *data ) {
480 struct efi_snp_device *snpdev =
481 container_of ( snp, struct efi_snp_device, snp );
483 DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
484 ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
485 ( ( unsigned long ) len ) );
487 DBGC2_HDA ( snpdev, offset, data, len );
489 /* Fail if net device is currently claimed for use by iPXE */
490 if ( efi_snp_claimed )
491 return EFI_NOT_READY;
493 return EFI_UNSUPPORTED;
497 * Read interrupt status and TX recycled buffer status
499 * @v snp SNP interface
500 * @v interrupts Interrupt status, or NULL
501 * @v txbuf Recycled transmit buffer address, or NULL
502 * @ret efirc EFI status code
504 static EFI_STATUS EFIAPI
505 efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
506 UINT32 *interrupts, VOID **txbuf ) {
507 struct efi_snp_device *snpdev =
508 container_of ( snp, struct efi_snp_device, snp );
510 DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
512 /* Fail if net device is currently claimed for use by iPXE */
513 if ( efi_snp_claimed ) {
514 DBGC2 ( snpdev, "\n" );
515 return EFI_NOT_READY;
518 /* Poll the network device */
519 efi_snp_poll ( snpdev );
521 /* Interrupt status. In practice, this seems to be used only
522 * to detect TX completions.
525 *interrupts = snpdev->interrupts;
526 DBGC2 ( snpdev, " INTS:%02x", *interrupts );
527 snpdev->interrupts = 0;
532 if ( snpdev->tx_prod != snpdev->tx_cons ) {
533 *txbuf = snpdev->tx[snpdev->tx_cons++ % EFI_SNP_NUM_TX];
537 DBGC2 ( snpdev, " TX:%p", *txbuf );
540 DBGC2 ( snpdev, "\n" );
545 * Start packet transmission
547 * @v snp SNP interface
548 * @v ll_header_len Link-layer header length, if to be filled in
549 * @v len Length of data buffer
550 * @v data Data buffer
551 * @v ll_src Link-layer source address, if specified
552 * @v ll_dest Link-layer destination address, if specified
553 * @v net_proto Network-layer protocol (in host order)
554 * @ret efirc EFI status code
556 static EFI_STATUS EFIAPI
557 efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
558 UINTN ll_header_len, UINTN len, VOID *data,
559 EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
560 UINT16 *net_proto ) {
561 struct efi_snp_device *snpdev =
562 container_of ( snp, struct efi_snp_device, snp );
563 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
564 struct io_buffer *iobuf;
566 unsigned int tx_fill;
569 DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
570 ( ( unsigned long ) len ) );
571 if ( ll_header_len ) {
573 DBGC2 ( snpdev, " src %s",
574 ll_protocol->ntoa ( ll_src ) );
577 DBGC2 ( snpdev, " dest %s",
578 ll_protocol->ntoa ( ll_dest ) );
581 DBGC2 ( snpdev, " proto %04x", *net_proto );
584 DBGC2 ( snpdev, "\n" );
586 /* Fail if net device is currently claimed for use by iPXE */
587 if ( efi_snp_claimed )
588 return EFI_NOT_READY;
591 if ( ll_header_len ) {
592 if ( ll_header_len != ll_protocol->ll_header_len ) {
593 DBGC ( snpdev, "SNPDEV %p TX invalid header length "
595 ( ( unsigned long ) ll_header_len ) );
599 if ( len < ll_header_len ) {
600 DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
601 snpdev, ( ( unsigned long ) len ) );
606 DBGC ( snpdev, "SNPDEV %p TX missing destination "
607 "address\n", snpdev );
612 DBGC ( snpdev, "SNPDEV %p TX missing network "
613 "protocol\n", snpdev );
618 ll_src = &snpdev->mode.CurrentAddress;
621 /* Allocate buffer */
622 payload_len = ( len - ll_protocol->ll_header_len );
623 iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ?
624 payload_len : IOB_ZLEN ) );
626 DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
627 "buffer\n", snpdev, ( ( unsigned long ) len ) );
631 iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN -
632 ll_protocol->ll_header_len ) );
633 memcpy ( iob_put ( iobuf, len ), data, len );
635 /* Create link-layer header, if specified */
636 if ( ll_header_len ) {
637 iob_pull ( iobuf, ll_protocol->ll_header_len );
638 if ( ( rc = ll_protocol->push ( snpdev->netdev,
639 iobuf, ll_dest, ll_src,
640 htons ( *net_proto ) )) != 0 ){
641 DBGC ( snpdev, "SNPDEV %p TX could not construct "
642 "header: %s\n", snpdev, strerror ( rc ) );
647 /* Transmit packet */
648 if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
649 DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
650 snpdev, strerror ( rc ) );
654 /* Record in transmit completion ring. If we run out of
655 * space, report the failure even though we have already
656 * transmitted the packet.
658 * This allows us to report completions only for packets for
659 * which we had reported successfully initiating transmission,
660 * while continuing to support clients that never poll for
661 * transmit completions.
663 tx_fill = ( snpdev->tx_prod - snpdev->tx_cons );
664 if ( tx_fill >= EFI_SNP_NUM_TX ) {
665 DBGC ( snpdev, "SNPDEV %p TX completion ring full\n", snpdev );
669 snpdev->tx[ snpdev->tx_prod++ % EFI_SNP_NUM_TX ] = data;
670 snpdev->interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
686 * @v snp SNP interface
687 * @v ll_header_len Link-layer header length, if to be filled in
688 * @v len Length of data buffer
689 * @v data Data buffer
690 * @v ll_src Link-layer source address, if specified
691 * @v ll_dest Link-layer destination address, if specified
692 * @v net_proto Network-layer protocol (in host order)
693 * @ret efirc EFI status code
695 static EFI_STATUS EFIAPI
696 efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
697 UINTN *ll_header_len, UINTN *len, VOID *data,
698 EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
699 UINT16 *net_proto ) {
700 struct efi_snp_device *snpdev =
701 container_of ( snp, struct efi_snp_device, snp );
702 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
703 struct io_buffer *iobuf;
704 const void *iob_ll_dest;
705 const void *iob_ll_src;
706 uint16_t iob_net_proto;
707 unsigned int iob_flags;
710 DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
711 ( ( unsigned long ) *len ) );
713 /* Fail if net device is currently claimed for use by iPXE */
714 if ( efi_snp_claimed )
715 return EFI_NOT_READY;
717 /* Poll the network device */
718 efi_snp_poll ( snpdev );
720 /* Dequeue a packet, if one is available */
721 iobuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
723 DBGC2 ( snpdev, "\n" );
727 list_del ( &iobuf->list );
728 DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
730 /* Return packet to caller */
731 memcpy ( data, iobuf->data, iob_len ( iobuf ) );
732 *len = iob_len ( iobuf );
734 /* Attempt to decode link-layer header */
735 if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
736 &iob_ll_src, &iob_net_proto,
737 &iob_flags ) ) != 0 ) {
738 DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
739 snpdev, strerror ( rc ) );
740 goto out_bad_ll_header;
743 /* Return link-layer header parameters to caller, if required */
745 *ll_header_len = ll_protocol->ll_header_len;
747 memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
749 memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
751 *net_proto = ntohs ( iob_net_proto );
765 * @v context Event context
767 static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event __unused,
769 struct efi_snp_device *snpdev = context;
771 DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
773 /* Do nothing unless the net device is open */
774 if ( ! netdev_is_open ( snpdev->netdev ) )
777 /* Do nothing if net device is currently claimed for use by iPXE */
778 if ( efi_snp_claimed )
781 /* Poll the network device */
782 efi_snp_poll ( snpdev );
786 static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
787 .Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
788 .Start = efi_snp_start,
789 .Stop = efi_snp_stop,
790 .Initialize = efi_snp_initialize,
791 .Reset = efi_snp_reset,
792 .Shutdown = efi_snp_shutdown,
793 .ReceiveFilters = efi_snp_receive_filters,
794 .StationAddress = efi_snp_station_address,
795 .Statistics = efi_snp_statistics,
796 .MCastIpToMac = efi_snp_mcast_ip_to_mac,
797 .NvData = efi_snp_nvdata,
798 .GetStatus = efi_snp_get_status,
799 .Transmit = efi_snp_transmit,
800 .Receive = efi_snp_receive,
803 /******************************************************************************
805 * Component name protocol
807 ******************************************************************************
811 * Look up driver name
813 * @v name2 Component name protocol
814 * @v language Language to use
815 * @v driver_name Driver name to fill in
816 * @ret efirc EFI status code
818 static EFI_STATUS EFIAPI
819 efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
820 CHAR8 *language __unused, CHAR16 **driver_name ) {
821 struct efi_snp_device *snpdev =
822 container_of ( name2, struct efi_snp_device, name2 );
824 *driver_name = snpdev->driver_name;
829 * Look up controller name
831 * @v name2 Component name protocol
833 * @v child Child device, or NULL
834 * @v language Language to use
835 * @v driver_name Device name to fill in
836 * @ret efirc EFI status code
838 static EFI_STATUS EFIAPI
839 efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
840 EFI_HANDLE device __unused,
841 EFI_HANDLE child __unused,
842 CHAR8 *language __unused,
843 CHAR16 **controller_name ) {
844 struct efi_snp_device *snpdev =
845 container_of ( name2, struct efi_snp_device, name2 );
847 *controller_name = snpdev->controller_name;
851 /******************************************************************************
855 ******************************************************************************
861 * @v loadfile Load file protocol
863 * @v booting Loading as part of a boot attempt
864 * @ret efirc EFI status code
866 static EFI_STATUS EFIAPI
867 efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file,
868 EFI_DEVICE_PATH_PROTOCOL *path __unused,
869 BOOLEAN booting, UINTN *len __unused,
870 VOID *data __unused ) {
871 struct efi_snp_device *snpdev =
872 container_of ( load_file, struct efi_snp_device, load_file );
873 struct net_device *netdev = snpdev->netdev;
876 /* Fail unless this is a boot attempt */
878 DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
880 return EFI_UNSUPPORTED;
883 /* Claim network devices for use by iPXE */
886 /* Start watchdog holdoff timer */
887 efi_watchdog_start();
889 /* Boot from network device */
890 if ( ( rc = ipxe ( netdev ) ) != 0 )
899 /** Load file protocol */
900 static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol = {
901 .LoadFile = efi_snp_load_file,
904 /******************************************************************************
906 * iPXE network driver
908 ******************************************************************************
912 * Locate SNP device corresponding to network device
914 * @v netdev Network device
915 * @ret snp SNP device, or NULL if not found
917 static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
918 struct efi_snp_device *snpdev;
920 list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
921 if ( snpdev->netdev == netdev )
930 * @v netdev Network device
931 * @ret rc Return status code
933 static int efi_snp_probe ( struct net_device *netdev ) {
934 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
935 struct efi_device *efidev;
936 struct efi_snp_device *snpdev;
938 EFI_DEVICE_PATH_PROTOCOL *path;
941 EFI_DEVICE_PATH_PROTOCOL *path_end;
942 MAC_ADDR_DEVICE_PATH *macpath;
943 size_t path_prefix_len = 0;
947 /* Find parent EFI device */
948 efidev = efidev_parent ( netdev->dev );
950 DBG ( "SNP skipping non-EFI device %s\n", netdev->name );
955 /* Allocate the SNP device */
956 snpdev = zalloc ( sizeof ( *snpdev ) );
961 snpdev->netdev = netdev_get ( netdev );
962 snpdev->efidev = efidev;
963 INIT_LIST_HEAD ( &snpdev->rx );
966 if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
967 DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
968 "length %d for %s\n", snpdev,
969 netdev->ll_protocol->ll_addr_len, netdev->name );
971 goto err_ll_addr_len;
974 /* Populate the SNP structure */
975 memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
976 snpdev->snp.Mode = &snpdev->mode;
977 if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
978 efi_snp_wait_for_packet, snpdev,
979 &snpdev->snp.WaitForPacket ) ) != 0 ){
980 rc = -EEFI ( efirc );
981 DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
982 snpdev, strerror ( rc ) );
983 goto err_create_event;
986 /* Populate the SNP mode structure */
987 snpdev->mode.State = EfiSimpleNetworkStopped;
988 efi_snp_set_mode ( snpdev );
990 /* Populate the NII structure */
991 snpdev->nii.Revision =
992 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
993 strncpy ( snpdev->nii.StringId, "iPXE",
994 sizeof ( snpdev->nii.StringId ) );
996 /* Populate the component name structure */
997 efi_snprintf ( snpdev->driver_name,
998 ( sizeof ( snpdev->driver_name ) /
999 sizeof ( snpdev->driver_name[0] ) ),
1000 "%s %s", product_short_name, netdev->dev->driver_name );
1001 efi_snprintf ( snpdev->controller_name,
1002 ( sizeof ( snpdev->controller_name ) /
1003 sizeof ( snpdev->controller_name[0] ) ),
1004 "%s %s (%s, %s)", product_short_name,
1005 netdev->dev->driver_name, netdev->dev->name,
1006 netdev_addr ( netdev ) );
1007 snpdev->name2.GetDriverName = efi_snp_get_driver_name;
1008 snpdev->name2.GetControllerName = efi_snp_get_controller_name;
1009 snpdev->name2.SupportedLanguages = "en";
1011 /* Populate the load file protocol structure */
1012 memcpy ( &snpdev->load_file, &efi_snp_load_file_protocol,
1013 sizeof ( snpdev->load_file ) );
1015 /* Populate the device name */
1016 efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
1017 sizeof ( snpdev->name[0] ) ),
1018 "%s", netdev->name );
1020 /* Get the parent device path */
1021 if ( ( efirc = bs->OpenProtocol ( efidev->device,
1022 &efi_device_path_protocol_guid,
1023 &path.interface, efi_image_handle,
1025 EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
1026 rc = -EEFI ( efirc );
1027 DBGC ( snpdev, "SNPDEV %p cannot get %p %s device path: %s\n",
1028 snpdev, efidev->device,
1029 efi_handle_name ( efidev->device ), strerror ( rc ) );
1030 goto err_open_device_path;
1033 /* Allocate the new device path */
1034 path_end = efi_devpath_end ( path.path );
1035 path_prefix_len = ( ( ( void * ) path_end ) - ( ( void * ) path.path ));
1036 snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) +
1037 sizeof ( *path_end ) );
1038 if ( ! snpdev->path ) {
1040 goto err_alloc_device_path;
1043 /* Populate the device path */
1044 memcpy ( snpdev->path, path.path, path_prefix_len );
1045 macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len );
1046 path_end = ( ( void * ) ( macpath + 1 ) );
1047 memset ( macpath, 0, sizeof ( *macpath ) );
1048 macpath->Header.Type = MESSAGING_DEVICE_PATH;
1049 macpath->Header.SubType = MSG_MAC_ADDR_DP;
1050 macpath->Header.Length[0] = sizeof ( *macpath );
1051 memcpy ( &macpath->MacAddress, netdev->ll_addr,
1052 sizeof ( macpath->MacAddress ) );
1053 macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
1054 memset ( path_end, 0, sizeof ( *path_end ) );
1055 path_end->Type = END_DEVICE_PATH_TYPE;
1056 path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
1057 path_end->Length[0] = sizeof ( *path_end );
1059 /* Install the SNP */
1060 if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1062 &efi_simple_network_protocol_guid, &snpdev->snp,
1063 &efi_device_path_protocol_guid, snpdev->path,
1064 &efi_nii_protocol_guid, &snpdev->nii,
1065 &efi_nii31_protocol_guid, &snpdev->nii,
1066 &efi_component_name2_protocol_guid, &snpdev->name2,
1067 &efi_load_file_protocol_guid, &snpdev->load_file,
1069 rc = -EEFI ( efirc );
1070 DBGC ( snpdev, "SNPDEV %p could not install protocols: "
1071 "%s\n", snpdev, strerror ( rc ) );
1072 goto err_install_protocol_interface;
1075 /* Add as child of EFI parent device */
1076 if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) {
1077 DBGC ( snpdev, "SNPDEV %p could not become child of %p %s: "
1078 "%s\n", snpdev, efidev->device,
1079 efi_handle_name ( efidev->device ), strerror ( rc ) );
1080 goto err_efi_child_add;
1084 if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
1085 DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
1086 snpdev, strerror ( rc ) );
1087 /* HII fails on several platforms. It's
1088 * non-essential, so treat this as a non-fatal
1093 /* Add to list of SNP devices */
1094 list_add ( &snpdev->list, &efi_snp_devices );
1096 /* Close device path */
1097 bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid,
1098 efi_image_handle, efidev->device );
1100 DBGC ( snpdev, "SNPDEV %p installed for %s as device %p %s\n",
1101 snpdev, netdev->name, snpdev->handle,
1102 efi_handle_name ( snpdev->handle ) );
1105 if ( snpdev->package_list )
1106 efi_snp_hii_uninstall ( snpdev );
1107 efi_child_del ( efidev->device, snpdev->handle );
1109 bs->UninstallMultipleProtocolInterfaces (
1111 &efi_simple_network_protocol_guid, &snpdev->snp,
1112 &efi_device_path_protocol_guid, snpdev->path,
1113 &efi_nii_protocol_guid, &snpdev->nii,
1114 &efi_nii31_protocol_guid, &snpdev->nii,
1115 &efi_component_name2_protocol_guid, &snpdev->name2,
1116 &efi_load_file_protocol_guid, &snpdev->load_file,
1118 err_install_protocol_interface:
1119 free ( snpdev->path );
1120 err_alloc_device_path:
1121 bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid,
1122 efi_image_handle, efidev->device );
1123 err_open_device_path:
1124 bs->CloseEvent ( snpdev->snp.WaitForPacket );
1127 netdev_put ( netdev );
1135 * Handle SNP device or link state change
1137 * @v netdev Network device
1139 static void efi_snp_notify ( struct net_device *netdev ) {
1140 struct efi_snp_device *snpdev;
1142 /* Locate SNP device */
1143 snpdev = efi_snp_demux ( netdev );
1145 DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
1149 /* Update link state */
1150 snpdev->mode.MediaPresent =
1151 ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
1152 DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
1153 ( snpdev->mode.MediaPresent ? "up" : "down" ) );
1155 /* Update mode state */
1156 efi_snp_set_state ( snpdev );
1160 * Destroy SNP device
1162 * @v netdev Network device
1164 static void efi_snp_remove ( struct net_device *netdev ) {
1165 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1166 struct efi_snp_device *snpdev;
1168 /* Locate SNP device */
1169 snpdev = efi_snp_demux ( netdev );
1171 DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
1175 /* Uninstall the SNP */
1176 if ( snpdev->package_list )
1177 efi_snp_hii_uninstall ( snpdev );
1178 efi_child_del ( snpdev->efidev->device, snpdev->handle );
1179 list_del ( &snpdev->list );
1180 bs->UninstallMultipleProtocolInterfaces (
1182 &efi_simple_network_protocol_guid, &snpdev->snp,
1183 &efi_device_path_protocol_guid, snpdev->path,
1184 &efi_nii_protocol_guid, &snpdev->nii,
1185 &efi_nii31_protocol_guid, &snpdev->nii,
1186 &efi_component_name2_protocol_guid, &snpdev->name2,
1187 &efi_load_file_protocol_guid, &snpdev->load_file,
1189 free ( snpdev->path );
1190 bs->CloseEvent ( snpdev->snp.WaitForPacket );
1191 netdev_put ( snpdev->netdev );
1196 struct net_driver efi_snp_driver __net_driver = {
1198 .probe = efi_snp_probe,
1199 .notify = efi_snp_notify,
1200 .remove = efi_snp_remove,
1204 * Find SNP device by EFI device handle
1206 * @v handle EFI device handle
1207 * @ret snpdev SNP device, or NULL
1209 struct efi_snp_device * find_snpdev ( EFI_HANDLE handle ) {
1210 struct efi_snp_device *snpdev;
1212 list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
1213 if ( snpdev->handle == handle )
1220 * Get most recently opened SNP device
1222 * @ret snpdev Most recently opened SNP device, or NULL
1224 struct efi_snp_device * last_opened_snpdev ( void ) {
1225 struct net_device *netdev;
1227 netdev = last_opened_netdev();
1231 return efi_snp_demux ( netdev );
1235 * Set SNP claimed/released state
1237 * @v claimed Network devices are claimed for use by iPXE
1239 void efi_snp_set_claimed ( int claimed ) {
1240 struct efi_snp_device *snpdev;
1242 /* Claim SNP devices */
1243 efi_snp_claimed = claimed;
1245 /* Update SNP mode state for each interface */
1246 list_for_each_entry ( snpdev, &efi_snp_devices, list )
1247 efi_snp_set_state ( snpdev );