iPXE
efi_pxe.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 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 (at your option) 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 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <errno.h>
29#include <ipxe/refcnt.h>
30#include <ipxe/list.h>
31#include <ipxe/netdevice.h>
32#include <ipxe/fakedhcp.h>
33#include <ipxe/process.h>
34#include <ipxe/uri.h>
35#include <ipxe/in.h>
36#include <ipxe/socket.h>
37#include <ipxe/tcpip.h>
38#include <ipxe/xferbuf.h>
39#include <ipxe/open.h>
40#include <ipxe/dhcppkt.h>
41#include <ipxe/udp.h>
42#include <ipxe/efi/efi.h>
43#include <ipxe/efi/efi_snp.h>
44#include <ipxe/efi/efi_pxe.h>
45#include <ipxe/efi/efi_null.h>
48#include <usr/ifmgmt.h>
49#include <config/general.h>
50
51/** @file
52 *
53 * EFI PXE base code protocol
54 *
55 */
56
57/* Downgrade user experience if configured to do so
58 *
59 * See comments in efi_snp.c
60 */
61#ifdef EFI_DOWNGRADE_UX
62static EFI_GUID dummy_pxe_base_code_protocol_guid = {
63 0x70647523, 0x2320, 0x7477,
64 { 0x66, 0x20, 0x23, 0x6d, 0x6f, 0x72, 0x6f, 0x6e }
65};
66#define efi_pxe_base_code_protocol_guid dummy_pxe_base_code_protocol_guid
67#endif
68
69/** A PXE base code */
70struct efi_pxe {
71 /** Reference count */
72 struct refcnt refcnt;
73 /** Underlying network device */
75 /** Name */
76 const char *name;
77 /** List of PXE base codes */
79
80 /** Installed handle */
82 /** PXE base code protocol */
84 /** PXE base code mode */
86 /** Apple NetBoot protocol */
88
89 /** TCP/IP network-layer protocol */
91 /** Network-layer protocol */
93
94 /** Data transfer buffer */
96
97 /** (M)TFTP download interface */
99 /** Opcode */
100 unsigned int opcode;
101 /** Block size (for TFTP) */
102 size_t blksize;
103 /** Overall return status */
104 int rc;
105
106 /** UDP interface */
108 /** List of received UDP packets */
110 /** UDP interface closer process */
112};
113
114/**
115 * Free PXE base code
116 *
117 * @v refcnt Reference count
118 */
119static void efi_pxe_free ( struct refcnt *refcnt ) {
120 struct efi_pxe *pxe = container_of ( refcnt, struct efi_pxe, refcnt );
121
122 netdev_put ( pxe->netdev );
123 free ( pxe );
124}
125
126/** List of PXE base codes */
127static LIST_HEAD ( efi_pxes );
128
129/**
130 * Locate PXE base code
131 *
132 * @v handle EFI handle
133 * @ret pxe PXE base code, or NULL
134 */
136 struct efi_pxe *pxe;
137
138 /* Locate base code */
139 list_for_each_entry ( pxe, &efi_pxes, list ) {
140 if ( pxe->handle == handle )
141 return pxe;
142 }
143
144 return NULL;
145}
146
147/******************************************************************************
148 *
149 * IP addresses
150 *
151 ******************************************************************************
152 */
153
154/**
155 * An EFI socket address
156 *
157 */
159 /** Socket address family (part of struct @c sockaddr) */
161 /** Flags (part of struct @c sockaddr_tcpip) */
163 /** TCP/IP port (part of struct @c sockaddr_tcpip) */
165 /** Scope ID (part of struct @c sockaddr_tcpip)
166 *
167 * For link-local or multicast addresses, this is the network
168 * device index.
169 */
171 /** IP address */
173 /** Padding
174 *
175 * This ensures that a struct @c sockaddr_tcpip is large
176 * enough to hold a socket address for any TCP/IP address
177 * family.
178 */
179 char pad[ sizeof ( struct sockaddr ) -
180 ( sizeof ( sa_family_t ) /* se_family */ +
181 sizeof ( uint16_t ) /* se_flags */ +
182 sizeof ( uint16_t ) /* se_port */ +
183 sizeof ( uint16_t ) /* se_scope_id */ +
184 sizeof ( EFI_IP_ADDRESS ) /* se_addr */ ) ];
185} __attribute__ (( packed, may_alias ));
186
187/**
188 * Populate socket address from EFI IP address
189 *
190 * @v pxe PXE base code
191 * @v ip EFI IP address
192 * @v sa Socket address to fill in
193 */
194static void efi_pxe_ip_sockaddr ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
195 struct sockaddr *sa ) {
196 union {
197 struct sockaddr sa;
198 struct sockaddr_efi se;
199 } *sockaddr = container_of ( sa, typeof ( *sockaddr ), sa );
200
201 /* Initialise socket address */
202 memset ( sockaddr, 0, sizeof ( *sockaddr ) );
203 sockaddr->sa.sa_family = pxe->tcpip->sa_family;
204 memcpy ( &sockaddr->se.se_addr, ip, pxe->net->net_addr_len );
205 sockaddr->se.se_scope_id = pxe->netdev->scope_id;
206}
207
208/**
209 * Transcribe EFI IP address (for debugging)
210 *
211 * @v pxe PXE base code
212 * @v ip EFI IP address
213 * @ret text Transcribed IP address
214 */
215static const char * efi_pxe_ip_ntoa ( struct efi_pxe *pxe,
216 EFI_IP_ADDRESS *ip ) {
217
218 return pxe->net->ntoa ( ip );
219}
220
221/**
222 * Populate local IP address
223 *
224 * @v pxe PXE base code
225 * @ret rc Return status code
226 */
227static int efi_pxe_ip ( struct efi_pxe *pxe ) {
229 struct in_addr address;
230 struct in_addr netmask;
231
232 /* It's unclear which of the potentially many IPv6 addresses
233 * is supposed to be used.
234 */
235 if ( mode->UsingIpv6 )
236 return -ENOTSUP;
237
238 /* Fetch IP address and subnet mask */
240 &address );
242 &netmask );
243
244 /* Populate IP address and subnet mask */
245 memset ( &mode->StationIp, 0, sizeof ( mode->StationIp ) );
246 memcpy ( &mode->StationIp, &address, sizeof ( address ) );
247 memset ( &mode->SubnetMask, 0, sizeof ( mode->SubnetMask ) );
248 memcpy ( &mode->SubnetMask, &netmask, sizeof ( netmask ) );
249
250 return 0;
251}
252
253/**
254 * Check if IP address matches filter
255 *
256 * @v pxe PXE base code
257 * @v ip EFI IP address
258 * @ret is_match IP address matches filter
259 */
260static int efi_pxe_ip_filter ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip ) {
263 uint8_t filters = filter->Filters;
264 union {
266 struct in_addr in;
267 struct in6_addr in6;
268 } *u = container_of ( ip, typeof ( *u ), ip );
269 size_t addr_len = pxe->net->net_addr_len;
270 unsigned int i;
271
272 /* Match everything, if applicable */
274 return 1;
275
276 /* Match all multicasts, if applicable */
278 if ( mode->UsingIpv6 ) {
279 if ( IN6_IS_ADDR_MULTICAST ( &u->in6 ) )
280 return 1;
281 } else {
282 if ( IN_IS_MULTICAST ( u->in.s_addr ) )
283 return 1;
284 }
285 }
286
287 /* Match IPv4 broadcasts, if applicable */
289 if ( ( ! mode->UsingIpv6 ) &&
290 ( u->in.s_addr == INADDR_BROADCAST ) )
291 return 1;
292 }
293
294 /* Match station address, if applicable */
296 if ( memcmp ( ip, &mode->StationIp, addr_len ) == 0 )
297 return 1;
298 }
299
300 /* Match explicit addresses, if applicable */
301 for ( i = 0 ; i < filter->IpCnt ; i++ ) {
302 if ( memcmp ( ip, &filter->IpList[i], addr_len ) == 0 )
303 return 1;
304 }
305
306 return 0;
307}
308
309/******************************************************************************
310 *
311 * (M)TFTP download interface
312 *
313 ******************************************************************************
314 */
315
316/**
317 * Close PXE (M)TFTP download interface
318 *
319 * @v pxe PXE base code
320 * @v rc Reason for close
321 */
322static void efi_pxe_tftp_close ( struct efi_pxe *pxe, int rc ) {
323
324 /* Restart interface */
325 intf_restart ( &pxe->tftp, rc );
326
327 /* Record overall status */
328 pxe->rc = rc;
329}
330
331/**
332 * Check PXE (M)TFTP download flow control window
333 *
334 * @v pxe PXE base code
335 * @ret len Length of window
336 */
337static size_t efi_pxe_tftp_window ( struct efi_pxe *pxe ) {
338
339 /* Return requested blocksize */
340 return pxe->blksize;
341}
342
343/**
344 * Receive new PXE (M)TFTP download data
345 *
346 * @v pxe PXE base code
347 * @v iobuf I/O buffer
348 * @v meta Transfer metadata
349 * @ret rc Return status code
350 */
351static int efi_pxe_tftp_deliver ( struct efi_pxe *pxe,
352 struct io_buffer *iobuf,
353 struct xfer_metadata *meta ) {
354 int rc;
355
356 /* Deliver to data transfer buffer */
357 if ( ( rc = xferbuf_deliver ( &pxe->buf, iob_disown ( iobuf ),
358 meta ) ) != 0 )
359 goto done;
360
361 /* Stop when filesize is known, if applicable */
363 ( meta->flags & XFER_FL_ABS_OFFSET ) ) {
364 goto done;
365 }
366
367 return 0;
368
369 done:
370 efi_pxe_tftp_close ( pxe, rc );
371 return rc;
372}
373
374/** PXE file data transfer interface operations */
380
381/** PXE file data transfer interface descriptor */
383 INTF_DESC ( struct efi_pxe, tftp, efi_pxe_tftp_operations );
384
385/**
386 * Open (M)TFTP download interface
387 *
388 * @v pxe PXE base code
389 * @v ip EFI IP address
390 * @v filename Filename
391 * @ret rc Return status code
392 */
393static int efi_pxe_tftp_open ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
394 const char *filename ) {
395 struct sockaddr server;
396 struct uri *uri;
397 int rc;
398
399 /* Parse server address and filename */
400 efi_pxe_ip_sockaddr ( pxe, ip, &server );
401 uri = pxe_uri ( &server, filename );
402 if ( ! uri ) {
403 DBGC ( pxe, "PXE %s could not parse %s:%s\n", pxe->name,
404 efi_pxe_ip_ntoa ( pxe, ip ), filename );
405 rc = -ENOTSUP;
406 goto err_parse;
407 }
408
409 /* Open URI */
410 if ( ( rc = xfer_open_uri ( &pxe->tftp, uri ) ) != 0 ) {
411 DBGC ( pxe, "PXE %s could not open: %s\n",
412 pxe->name, strerror ( rc ) );
413 goto err_open;
414 }
415
416 err_open:
417 uri_put ( uri );
418 err_parse:
419 return rc;
420}
421
422/******************************************************************************
423 *
424 * UDP interface
425 *
426 ******************************************************************************
427 */
428
429/** EFI UDP pseudo-header */
431 /** Network-layer protocol */
433 /** Destination port */
435 /** Source port */
437} __attribute__ (( packed ));
438
439/**
440 * Close UDP interface
441 *
442 * @v pxe PXE base code
443 * @v rc Reason for close
444 */
445static void efi_pxe_udp_close ( struct efi_pxe *pxe, int rc ) {
446 struct io_buffer *iobuf;
447 struct io_buffer *tmp;
448
449 /* Release our claim on SNP devices, if applicable */
450 if ( process_running ( &pxe->process ) )
452
453 /* Stop process */
454 process_del ( &pxe->process );
455
456 /* Restart UDP interface */
457 intf_restart ( &pxe->udp, rc );
458
459 /* Flush any received UDP packets */
460 list_for_each_entry_safe ( iobuf, tmp, &pxe->queue, list ) {
461 list_del ( &iobuf->list );
462 free_iob ( iobuf );
463 }
464}
465
466/**
467 * Receive UDP packet
468 *
469 * @v pxe PXE base code
470 * @v iobuf I/O buffer
471 * @v meta Data transfer metadata
472 * @ret rc Return status code
473 */
474static int efi_pxe_udp_deliver ( struct efi_pxe *pxe, struct io_buffer *iobuf,
475 struct xfer_metadata *meta ) {
476 struct sockaddr_efi *se_src;
477 struct sockaddr_efi *se_dest;
478 struct tcpip_net_protocol *tcpip;
479 struct net_protocol *net;
480 struct efi_pxe_udp_pseudo_header *pshdr;
481 size_t addr_len;
482 size_t pshdr_len;
483 int rc;
484
485 /* Sanity checks */
486 assert ( meta != NULL );
487 se_src = ( ( struct sockaddr_efi * ) meta->src );
488 assert ( se_src != NULL );
489 se_dest = ( ( struct sockaddr_efi * ) meta->dest );
490 assert ( se_dest != NULL );
491 assert ( se_src->se_family == se_dest->se_family );
492
493 /* Determine protocol */
494 tcpip = tcpip_net_protocol ( se_src->se_family );
495 if ( ! tcpip ) {
496 rc = -ENOTSUP;
497 goto err_unsupported;
498 }
499 net = tcpip->net_protocol;
500 addr_len = net->net_addr_len;
501
502 /* Construct pseudo-header */
503 pshdr_len = ( sizeof ( *pshdr ) + ( 2 * addr_len ) );
504 if ( ( rc = iob_ensure_headroom ( iobuf, pshdr_len ) ) != 0 )
505 goto err_headroom;
506 memcpy ( iob_push ( iobuf, addr_len ), &se_src->se_addr, addr_len );
507 memcpy ( iob_push ( iobuf, addr_len ), &se_dest->se_addr, addr_len );
508 pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
509 pshdr->net = net;
510 pshdr->dest_port = ntohs ( se_dest->se_port );
511 pshdr->src_port = ntohs ( se_src->se_port );
512
513 /* Add to queue */
514 list_add_tail ( &iobuf->list, &pxe->queue );
515
516 return 0;
517
518 err_unsupported:
519 err_headroom:
520 free_iob ( iobuf );
521 return rc;
522}
523
524/** PXE UDP interface operations */
529
530/** PXE UDP interface descriptor */
533
534/**
535 * Open UDP interface
536 *
537 * @v pxe PXE base code
538 * @ret rc Return status code
539 */
540static int efi_pxe_udp_open ( struct efi_pxe *pxe ) {
541 int rc;
542
543 /* If interface is already open, then cancel the scheduled close */
544 if ( process_running ( &pxe->process ) ) {
545 process_del ( &pxe->process );
546 return 0;
547 }
548
549 /* Open promiscuous UDP interface */
550 if ( ( rc = udp_open_promisc ( &pxe->udp ) ) != 0 ) {
551 DBGC ( pxe, "PXE %s could not open UDP connection: %s\n",
552 pxe->name, strerror ( rc ) );
553 return rc;
554 }
555
556 /* Claim network devices */
558
559 return 0;
560}
561
562/**
563 * Schedule close of UDP interface
564 *
565 * @v pxe PXE base code
566 */
567static void efi_pxe_udp_schedule_close ( struct efi_pxe *pxe ) {
568
569 /* The EFI PXE base code protocol does not provide any
570 * explicit UDP open/close methods. To avoid the overhead of
571 * reopening a socket for each read/write operation, we start
572 * a process which will close the socket immediately if the
573 * next call into iPXE is anything other than a UDP
574 * read/write.
575 */
576 process_add ( &pxe->process );
577}
578
579/**
580 * Scheduled close of UDP interface
581 *
582 * @v pxe PXE base code
583 */
584static void efi_pxe_udp_scheduled_close ( struct efi_pxe *pxe ) {
585
586 /* Close UDP interface */
587 efi_pxe_udp_close ( pxe, 0 );
588}
589
590/** UDP close process descriptor */
593
594/******************************************************************************
595 *
596 * Fake DHCP packets
597 *
598 ******************************************************************************
599 */
600
601/**
602 * Name fake DHCP packet
603 *
604 * @v pxe PXE base code
605 * @v packet Packet
606 * @ret name Name of packet
607 */
608static const char * efi_pxe_fake_name ( struct efi_pxe *pxe,
609 EFI_PXE_BASE_CODE_PACKET *packet ) {
611
612 if ( packet == &mode->DhcpDiscover ) {
613 return "DhcpDiscover";
614 } else if ( packet == &mode->DhcpAck ) {
615 return "DhcpAck";
616 } else if ( packet == &mode->ProxyOffer ) {
617 return "ProxyOffer";
618 } else if ( packet == &mode->PxeDiscover ) {
619 return "PxeDiscover";
620 } else if ( packet == &mode->PxeReply ) {
621 return "PxeReply";
622 } else if ( packet == &mode->PxeBisReply ) {
623 return "PxeBisReply";
624 } else {
625 return "<UNKNOWN>";
626 }
627}
628
629/**
630 * Construct fake DHCP packet and flag
631 *
632 * @v pxe PXE base code
633 * @v fake Fake packet constructor
634 * @v packet Packet to fill in
635 * @ret exists Packet existence flag
636 */
637static BOOLEAN efi_pxe_fake ( struct efi_pxe *pxe,
638 int ( * fake ) ( struct net_device *netdev,
639 void *data, size_t len ),
640 EFI_PXE_BASE_CODE_PACKET *packet ) {
642 struct dhcp_packet dhcppkt;
643 struct dhcphdr *dhcphdr;
644 unsigned int len;
645 int rc;
646
647 /* The fake packet constructors do not support IPv6 */
648 if ( mode->UsingIpv6 )
649 return FALSE;
650
651 /* Attempt to construct packet */
652 if ( ( rc = fake ( pxe->netdev, packet, sizeof ( *packet ) ) != 0 ) ) {
653 DBGC ( pxe, "PXE %s could not fake %s: %s\n", pxe->name,
654 efi_pxe_fake_name ( pxe, packet ), strerror ( rc ) );
655 return FALSE;
656 }
657
658 /* The WDS bootstrap wdsmgfw.efi has a buggy DHCPv4 packet
659 * parser which does not correctly handle DHCP padding bytes.
660 * Specifically, if a padding byte (i.e. a zero) is
661 * encountered, the parse will first increment the pointer by
662 * one to skip over the padding byte but will then drop into
663 * the code path for handling normal options, which increments
664 * the pointer by two to skip over the (already-skipped) type
665 * field and the (non-existent) length field.
666 *
667 * The upshot of this bug in WDS is that the parser will fail
668 * with an error 0xc0000023 if the number of spare bytes after
669 * the end of the options is not an exact multiple of three.
670 *
671 * Work around this buggy parser by adding an explicit
672 * DHCP_END tag.
673 */
675 struct dhcphdr, op );
676 dhcppkt_init ( &dhcppkt, dhcphdr, sizeof ( *packet ) );
677 len = dhcppkt_len ( &dhcppkt );
678 if ( len < sizeof ( *packet ) )
679 packet->Raw[len] = DHCP_END;
680
681 return TRUE;
682}
683
684/**
685 * Construct fake DHCP packets
686 *
687 * @v pxe PXE base code
688 */
689static void efi_pxe_fake_all ( struct efi_pxe *pxe ) {
691
692 /* Construct fake packets */
693 mode->DhcpDiscoverValid =
695 &mode->DhcpDiscover );
696 mode->DhcpAckReceived =
698 &mode->DhcpAck );
699 mode->PxeReplyReceived =
701 &mode->PxeReply );
702}
703
704/******************************************************************************
705 *
706 * Base code protocol
707 *
708 ******************************************************************************
709 */
710
711/**
712 * Start PXE base code
713 *
714 * @v base PXE base code protocol
715 * @v use_ipv6 Use IPv6
716 * @ret efirc EFI status code
717 */
719 BOOLEAN use_ipv6 ) {
720 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
723 sa_family_t family = ( use_ipv6 ? AF_INET6 : AF_INET );
724 int rc;
725
726 DBGC ( pxe, "PXE %s START %s\n",
727 pxe->name, ( use_ipv6 ? "IPv6" : "IPv4" ) );
728
729 /* Initialise mode structure */
730 memset ( mode, 0, sizeof ( *mode ) );
731 mode->AutoArp = TRUE;
732 mode->TTL = DEFAULT_TTL;
733 mode->ToS = DEFAULT_ToS;
734 mode->IpFilter.Filters =
739
740 /* Check for IPv4/IPv6 support */
741 mode->Ipv6Supported = ( ipv6 != NULL );
742 mode->Ipv6Available = ( ipv6 != NULL );
743 pxe->tcpip = tcpip_net_protocol ( family );
744 if ( ! pxe->tcpip ) {
745 DBGC ( pxe, "PXE %s has no support for %s\n",
746 pxe->name, socket_family_name ( family ) );
747 return EFI_UNSUPPORTED;
748 }
749 pxe->net = pxe->tcpip->net_protocol;
750 mode->UsingIpv6 = use_ipv6;
751
752 /* Populate station IP address */
753 if ( ( rc = efi_pxe_ip ( pxe ) ) != 0 )
754 return rc;
755
756 /* Construct fake DHCP packets */
757 efi_pxe_fake_all ( pxe );
758
759 /* Record that base code is started */
760 mode->Started = TRUE;
761 DBGC ( pxe, "PXE %s using %s\n",
762 pxe->name, pxe->net->ntoa ( &mode->StationIp ) );
763
764 return 0;
765}
766
767/**
768 * Stop PXE base code
769 *
770 * @v base PXE base code protocol
771 * @ret efirc EFI status code
772 */
774 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
776
777 DBGC ( pxe, "PXE %s STOP\n", pxe->name );
778
779 /* Record that base code is stopped */
780 mode->Started = FALSE;
781
782 /* Close TFTP */
783 efi_pxe_tftp_close ( pxe, 0 );
784
785 /* Close UDP */
786 efi_pxe_udp_close ( pxe, 0 );
787
788 return 0;
789}
790
791/**
792 * Perform DHCP
793 *
794 * @v base PXE base code protocol
795 * @v sort Offers should be sorted
796 * @ret efirc EFI status code
797 */
799 BOOLEAN sort ) {
800 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
801 struct net_device *netdev = pxe->netdev;
802 int rc;
803
804 DBGC ( pxe, "PXE %s DHCP %s\n",
805 pxe->name, ( sort ? "sorted" : "unsorted" ) );
806
807 /* Claim network devices */
809
810 /* Initiate configuration */
811 if ( ( rc = netdev_configure_all ( netdev ) ) != 0 ) {
812 DBGC ( pxe, "PXE %s could not initiate configuration: %s\n",
813 pxe->name, strerror ( rc ) );
814 goto err_configure;
815 }
816
817 /* Wait for configuration to complete (or time out) */
819 step();
820
821 /* Report timeout if configuration failed */
822 if ( ! netdev_configuration_ok ( netdev ) ) {
823 rc = -ETIMEDOUT;
824 goto err_timeout;
825 }
826
827 /* Update station IP address */
828 if ( ( rc = efi_pxe_ip ( pxe ) ) != 0 )
829 goto err_ip;
830
831 /* Update faked DHCP packets */
832 efi_pxe_fake_all ( pxe );
833
834 err_ip:
835 err_timeout:
836 err_configure:
838 return EFIRC ( rc );
839}
840
841/**
842 * Perform boot server discovery
843 *
844 * @v base PXE base code protocol
845 * @v type Boot server type
846 * @v layer Boot server layer
847 * @v bis Use boot integrity services
848 * @v info Additional information
849 * @ret efirc EFI status code
850 */
851static EFI_STATUS EFIAPI
854 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
856 unsigned int i;
857
858 DBGC ( pxe, "PXE %s DISCOVER type %d layer %d%s\n",
859 pxe->name, type, *layer, ( bis ? " bis" : "" ) );
860 if ( info ) {
861 DBGC ( pxe, "%s%s%s%s %s",
862 ( info->UseMCast ? " mcast" : "" ),
863 ( info->UseBCast ? " bcast" : "" ),
864 ( info->UseUCast ? " ucast" : "" ),
865 ( info->MustUseList ? " list" : "" ),
866 efi_pxe_ip_ntoa ( pxe, &info->ServerMCastIp ) );
867 for ( i = 0 ; i < info->IpCnt ; i++ ) {
868 ip = &info->SrvList[i].IpAddr;
869 DBGC ( pxe, " %d%s:%s", info->SrvList[i].Type,
870 ( info->SrvList[i].AcceptAnyResponse ?
871 ":any" : "" ), efi_pxe_ip_ntoa ( pxe, ip ) );
872 }
873 }
874 DBGC ( pxe, "\n" );
875
876 /* Not used by any bootstrap I can find to test with */
877 return EFI_UNSUPPORTED;
878}
879
880/**
881 * Perform (M)TFTP
882 *
883 * @v base PXE base code protocol
884 * @v opcode TFTP opcode
885 * @v data Data buffer
886 * @v overwrite Overwrite file
887 * @v len Length of data buffer
888 * @v blksize Block size
889 * @v ip Server address
890 * @v filename Filename
891 * @v info Additional information
892 * @v callback Pass packets to callback instead of data buffer
893 * @ret efirc EFI status code
894 */
895static EFI_STATUS EFIAPI
899 EFI_IP_ADDRESS *ip, UINT8 *filename,
901 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
902 int rc;
903
904 DBGC ( pxe, "PXE %s MTFTP %d%s %p+%llx", pxe->name, opcode,
905 ( overwrite ? " overwrite" : "" ), data, *len );
906 if ( blksize )
907 DBGC ( pxe, " blksize %zd", ( ( size_t ) *blksize ) );
908 DBGC ( pxe, " %s:%s", efi_pxe_ip_ntoa ( pxe, ip ), filename );
909 if ( info ) {
910 DBGC ( pxe, " %s:%d:%d:%d:%d",
911 efi_pxe_ip_ntoa ( pxe, &info->MCastIp ),
912 info->CPort, info->SPort, info->ListenTimeout,
913 info->TransmitTimeout );
914 }
915 DBGC ( pxe, "%s\n", ( callback ? " callback" : "" ) );
916
917 /* Fail unless operation is supported */
921 DBGC ( pxe, "PXE %s unsupported MTFTP opcode %d\n",
922 pxe->name, opcode );
923 rc = -ENOTSUP;
924 goto err_opcode;
925 }
926
927 /* Claim network devices */
929
930 /* Determine block size. Ignore the requested block size
931 * unless we are using callbacks, since limiting HTTP to a
932 * 512-byte TCP window is not sensible.
933 */
934 pxe->blksize = ( ( callback && blksize ) ? *blksize : -1UL );
935
936 /* Initialise data transfer buffer */
937 memset ( &pxe->buf, 0, sizeof ( pxe->buf ) );
939 xferbuf_void_init ( &pxe->buf );
940 } else {
941 xferbuf_fixed_init ( &pxe->buf, data, *len );
942 }
943
944 /* Open download */
945 if ( ( rc = efi_pxe_tftp_open ( pxe, ip,
946 ( ( const char * ) filename ) ) ) != 0 )
947 goto err_open;
948
949 /* Wait for download to complete */
950 pxe->opcode = opcode;
951 pxe->rc = -EINPROGRESS;
952 while ( pxe->rc == -EINPROGRESS )
953 step();
954 *len = pxe->buf.max;
955 if ( ( rc = pxe->rc ) != 0 ) {
956 DBGC ( pxe, "PXE %s MTFTP %d failed: %s\n",
957 pxe->name, opcode, strerror ( rc ) );
958 goto err_download;
959 }
960 DBGC ( pxe, "PXE %s MTFTP %d %p+%llx complete\n",
961 pxe->name, opcode, data, *len );
962
963 err_download:
964 efi_pxe_tftp_close ( pxe, rc );
965 err_open:
966 xferbuf_fixed_init ( &pxe->buf, NULL, 0 );
968 err_opcode:
969 return EFIRC ( rc );
970}
971
972/**
973 * Transmit UDP packet
974 *
975 * @v base PXE base code protocol
976 * @v flags Operation flags
977 * @v dest_ip Destination address
978 * @v dest_port Destination port
979 * @v gateway Gateway address
980 * @v src_ip Source address
981 * @v src_port Source port
982 * @v hdr_len Header length
983 * @v hdr Header data
984 * @v len Length
985 * @v data Data
986 * @ret efirc EFI status code
987 */
988static EFI_STATUS EFIAPI
994 UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data ) {
995 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
997 struct io_buffer *iobuf;
998 struct xfer_metadata meta;
999 union {
1000 struct sockaddr_tcpip st;
1001 struct sockaddr sa;
1002 } dest;
1003 union {
1004 struct sockaddr_tcpip st;
1005 struct sockaddr sa;
1006 } src;
1007 int rc;
1008
1009 DBGC2 ( pxe, "PXE %s UDP WRITE ", pxe->name );
1010 if ( src_ip )
1011 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, src_ip ) );
1012 DBGC2 ( pxe, ":" );
1013 if ( src_port &&
1015 DBGC2 ( pxe, "%d", *src_port );
1016 } else {
1017 DBGC2 ( pxe, "*" );
1018 }
1019 DBGC2 ( pxe, "->%s:%d", efi_pxe_ip_ntoa ( pxe, dest_ip ), *dest_port );
1020 if ( gateway )
1021 DBGC2 ( pxe, " via %s", efi_pxe_ip_ntoa ( pxe, gateway ) );
1022 if ( hdr_len )
1023 DBGC2 ( pxe, " %p+%zx", hdr, ( ( size_t ) *hdr_len ) );
1024 DBGC2 ( pxe, " %p+%zx", data, ( ( size_t ) *len ) );
1026 DBGC2 ( pxe, " frag" );
1027 DBGC2 ( pxe, "\n" );
1028
1029 /* Open UDP connection (if applicable) */
1030 if ( ( rc = efi_pxe_udp_open ( pxe ) ) != 0 )
1031 goto err_open;
1032
1033 /* Construct destination address */
1034 efi_pxe_ip_sockaddr ( pxe, dest_ip, &dest.sa );
1035 dest.st.st_port = htons ( *dest_port );
1036
1037 /* Construct source address */
1038 efi_pxe_ip_sockaddr ( pxe, ( src_ip ? src_ip : &mode->StationIp ),
1039 &src.sa );
1040 if ( src_port &&
1042 src.st.st_port = htons ( *src_port );
1043 } else {
1044 /* The API does not allow for a sensible concept of
1045 * binding to a local port, so just use a random value.
1046 */
1047 src.st.st_port = ( random() | htons ( 1024 ) );
1048 if ( src_port )
1049 *src_port = ntohs ( src.st.st_port );
1050 }
1051
1052 /* Allocate I/O buffer */
1053 iobuf = xfer_alloc_iob ( &pxe->udp,
1054 ( *len + ( hdr_len ? *hdr_len : 0 ) ) );
1055 if ( ! iobuf ) {
1056 rc = -ENOMEM;
1057 goto err_alloc;
1058 }
1059
1060 /* Populate I/O buffer */
1061 if ( hdr_len )
1062 memcpy ( iob_put ( iobuf, *hdr_len ), hdr, *hdr_len );
1063 memcpy ( iob_put ( iobuf, *len ), data, *len );
1064
1065 /* Construct metadata */
1066 memset ( &meta, 0, sizeof ( meta ) );
1067 meta.src = &src.sa;
1068 meta.dest = &dest.sa;
1069 meta.netdev = pxe->netdev;
1070
1071 /* Deliver I/O buffer */
1072 if ( ( rc = xfer_deliver ( &pxe->udp, iob_disown ( iobuf ),
1073 &meta ) ) != 0 ) {
1074 DBGC ( pxe, "PXE %s could not transmit: %s\n",
1075 pxe->name, strerror ( rc ) );
1076 goto err_deliver;
1077 }
1078
1079 err_deliver:
1080 free_iob ( iobuf );
1081 err_alloc:
1083 err_open:
1084 return EFIRC ( rc );
1085}
1086
1087/**
1088 * Receive UDP packet
1089 *
1090 * @v base PXE base code protocol
1091 * @v flags Operation flags
1092 * @v dest_ip Destination address
1093 * @v dest_port Destination port
1094 * @v src_ip Source address
1095 * @v src_port Source port
1096 * @v hdr_len Header length
1097 * @v hdr Header data
1098 * @v len Length
1099 * @v data Data
1100 * @ret efirc EFI status code
1101 */
1102static EFI_STATUS EFIAPI
1105 EFI_PXE_BASE_CODE_UDP_PORT *dest_port,
1108 UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data ) {
1109 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1110 struct io_buffer *iobuf;
1111 struct efi_pxe_udp_pseudo_header *pshdr;
1112 EFI_IP_ADDRESS *actual_dest_ip;
1113 EFI_IP_ADDRESS *actual_src_ip;
1114 size_t addr_len;
1115 size_t frag_len;
1116 int rc;
1117
1118 DBGC2 ( pxe, "PXE %s UDP READ ", pxe->name );
1120 DBGC2 ( pxe, "(filter)" );
1122 DBGC2 ( pxe, "*" );
1123 } else if ( dest_ip ) {
1124 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, dest_ip ) );
1125 }
1126 DBGC2 ( pxe, ":" );
1128 DBGC2 ( pxe, "*" );
1129 } else if ( dest_port ) {
1130 DBGC2 ( pxe, "%d", *dest_port );
1131 } else {
1132 DBGC2 ( pxe, "<NULL>" );
1133 }
1134 DBGC2 ( pxe, "<-" );
1136 DBGC2 ( pxe, "*" );
1137 } else if ( src_ip ) {
1138 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, src_ip ) );
1139 } else {
1140 DBGC2 ( pxe, "<NULL>" );
1141 }
1142 DBGC2 ( pxe, ":" );
1144 DBGC2 ( pxe, "*" );
1145 } else if ( src_port ) {
1146 DBGC2 ( pxe, "%d", *src_port );
1147 } else {
1148 DBGC2 ( pxe, "<NULL>" );
1149 }
1150 if ( hdr_len )
1151 DBGC2 ( pxe, " %p+%zx", hdr, ( ( size_t ) *hdr_len ) );
1152 DBGC2 ( pxe, " %p+%zx\n", data, ( ( size_t ) *len ) );
1153
1154 /* Open UDP connection (if applicable) */
1155 if ( ( rc = efi_pxe_udp_open ( pxe ) ) != 0 )
1156 goto err_open;
1157
1158 /* Try receiving a packet, if the queue is empty */
1159 if ( list_empty ( &pxe->queue ) )
1160 step();
1161
1162 /* Remove first packet from the queue */
1163 iobuf = list_first_entry ( &pxe->queue, struct io_buffer, list );
1164 if ( ! iobuf ) {
1165 rc = -ETIMEDOUT; /* "no packet" */
1166 goto err_empty;
1167 }
1168 list_del ( &iobuf->list );
1169
1170 /* Strip pseudo-header */
1171 pshdr = iobuf->data;
1172 addr_len = ( pshdr->net->net_addr_len );
1173 iob_pull ( iobuf, sizeof ( *pshdr ) );
1174 actual_dest_ip = iobuf->data;
1175 iob_pull ( iobuf, addr_len );
1176 actual_src_ip = iobuf->data;
1177 iob_pull ( iobuf, addr_len );
1178 DBGC2 ( pxe, "PXE %s UDP RX %s:%d", pxe->name,
1179 pshdr->net->ntoa ( actual_dest_ip ), pshdr->dest_port );
1180 DBGC2 ( pxe, "<-%s:%d len %#zx\n", pshdr->net->ntoa ( actual_src_ip ),
1181 pshdr->src_port, iob_len ( iobuf ) );
1182
1183 /* Filter based on network-layer protocol */
1184 if ( pshdr->net != pxe->net ) {
1185 DBGC2 ( pxe, "PXE %s filtered out %s packet\n",
1186 pxe->name, pshdr->net->name );
1187 rc = -ETIMEDOUT; /* "no packet" */
1188 goto err_filter;
1189 }
1190
1191 /* Filter based on port numbers */
1193 ( dest_port && ( *dest_port == pshdr->dest_port ) ) ) ) {
1194 DBGC2 ( pxe, "PXE %s filtered out destination port %d\n",
1195 pxe->name, pshdr->dest_port );
1196 rc = -ETIMEDOUT; /* "no packet" */
1197 goto err_filter;
1198 }
1200 ( src_port && ( *src_port == pshdr->src_port ) ) ) ) {
1201 DBGC2 ( pxe, "PXE %s filtered out source port %d\n",
1202 pxe->name, pshdr->src_port );
1203 rc = -ETIMEDOUT; /* "no packet" */
1204 goto err_filter;
1205 }
1206
1207 /* Filter based on source IP address */
1209 ( src_ip &&
1210 ( memcmp ( src_ip, actual_src_ip, addr_len ) == 0 ) ) ) ) {
1211 DBGC2 ( pxe, "PXE %s filtered out source IP %s\n",
1212 pxe->name, pshdr->net->ntoa ( actual_src_ip ) );
1213 rc = -ETIMEDOUT; /* "no packet" */
1214 goto err_filter;
1215 }
1216
1217 /* Filter based on destination IP address */
1219 efi_pxe_ip_filter ( pxe, actual_dest_ip ) ) ||
1222 ( dest_ip && ( memcmp ( dest_ip, actual_dest_ip,
1223 addr_len ) == 0 ) ) ) ) ) ) {
1224 DBGC2 ( pxe, "PXE %s filtered out destination IP %s\n",
1225 pxe->name, pshdr->net->ntoa ( actual_dest_ip ) );
1226 rc = -ETIMEDOUT; /* "no packet" */
1227 goto err_filter;
1228 }
1229
1230 /* Fill in addresses and port numbers */
1231 if ( dest_ip )
1232 memcpy ( dest_ip, actual_dest_ip, addr_len );
1233 if ( dest_port )
1234 *dest_port = pshdr->dest_port;
1235 if ( src_ip )
1236 memcpy ( src_ip, actual_src_ip, addr_len );
1237 if ( src_port )
1238 *src_port = pshdr->src_port;
1239
1240 /* Fill in header, if applicable */
1241 if ( hdr_len ) {
1242 frag_len = iob_len ( iobuf );
1243 if ( frag_len > *hdr_len )
1244 frag_len = *hdr_len;
1245 memcpy ( hdr, iobuf->data, frag_len );
1246 iob_pull ( iobuf, frag_len );
1247 *hdr_len = frag_len;
1248 }
1249
1250 /* Fill in data buffer */
1251 frag_len = iob_len ( iobuf );
1252 if ( frag_len > *len )
1253 frag_len = *len;
1254 memcpy ( data, iobuf->data, frag_len );
1255 iob_pull ( iobuf, frag_len );
1256 *len = frag_len;
1257
1258 /* Check for overflow */
1259 if ( iob_len ( iobuf ) ) {
1260 rc = -ERANGE;
1261 goto err_too_short;
1262 }
1263
1264 /* Success */
1265 rc = 0;
1266
1267 err_too_short:
1268 err_filter:
1269 free_iob ( iobuf );
1270 err_empty:
1272 err_open:
1273 return EFIRC ( rc );
1274}
1275
1276/**
1277 * Set receive filter
1278 *
1279 * @v base PXE base code protocol
1280 * @v filter Receive filter
1281 * @ret efirc EFI status code
1282 */
1283static EFI_STATUS EFIAPI
1286 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1288 unsigned int i;
1289
1290 DBGC ( pxe, "PXE %s SET IP FILTER %02x",
1291 pxe->name, filter->Filters );
1292 for ( i = 0 ; i < filter->IpCnt ; i++ ) {
1293 DBGC ( pxe, " %s",
1294 efi_pxe_ip_ntoa ( pxe, &filter->IpList[i] ) );
1295 }
1296 DBGC ( pxe, "\n" );
1297
1298 /* Update filter */
1299 memcpy ( &mode->IpFilter, filter, sizeof ( mode->IpFilter ) );
1300
1301 return 0;
1302}
1303
1304/**
1305 * Resolve MAC address
1306 *
1307 * @v base PXE base code protocol
1308 * @v ip IP address
1309 * @v mac MAC address to fill in
1310 * @ret efirc EFI status code
1311 */
1314 EFI_MAC_ADDRESS *mac ) {
1315 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1316
1317 DBGC ( pxe, "PXE %s ARP %s %p\n",
1318 pxe->name, efi_pxe_ip_ntoa ( pxe, ip ), mac );
1319
1320 /* Not used by any bootstrap I can find to test with */
1321 return EFI_UNSUPPORTED;
1322}
1323
1324/**
1325 * Set parameters
1326 *
1327 * @v base PXE base code protocol
1328 * @v autoarp Automatic ARP packet generation
1329 * @v sendguid Send GUID as client hardware address
1330 * @v ttl IP time to live
1331 * @v tos IP type of service
1332 * @v callback Make callbacks
1333 * @ret efirc EFI status code
1334 */
1335static EFI_STATUS EFIAPI
1337 BOOLEAN *autoarp, BOOLEAN *sendguid, UINT8 *ttl,
1338 UINT8 *tos, BOOLEAN *callback ) {
1339 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1341
1342 DBGC ( pxe, "PXE %s SET PARAMETERS", pxe->name );
1343 if ( autoarp )
1344 DBGC ( pxe, " %s", ( *autoarp ? "autoarp" : "noautoarp" ) );
1345 if ( sendguid )
1346 DBGC ( pxe, " %s", ( *sendguid ? "sendguid" : "sendmac" ) );
1347 if ( ttl )
1348 DBGC ( pxe, " ttl %d", *ttl );
1349 if ( tos )
1350 DBGC ( pxe, " tos %d", *tos );
1351 if ( callback ) {
1352 DBGC ( pxe, " %s",
1353 ( *callback ? "callback" : "nocallback" ) );
1354 }
1355 DBGC ( pxe, "\n" );
1356
1357 /* Update parameters */
1358 if ( autoarp )
1359 mode->AutoArp = *autoarp;
1360 if ( sendguid )
1361 mode->SendGUID = *sendguid;
1362 if ( ttl )
1363 mode->TTL = *ttl;
1364 if ( tos )
1365 mode->ToS = *tos;
1366 if ( callback )
1367 mode->MakeCallbacks = *callback;
1368
1369 return 0;
1370}
1371
1372/**
1373 * Set IP address
1374 *
1375 * @v base PXE base code protocol
1376 * @v ip IP address
1377 * @v netmask Subnet mask
1378 * @ret efirc EFI status code
1379 */
1380static EFI_STATUS EFIAPI
1382 EFI_IP_ADDRESS *ip, EFI_IP_ADDRESS *netmask ) {
1383 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1385
1386 DBGC ( pxe, "PXE %s SET STATION IP ", pxe->name );
1387 if ( ip )
1388 DBGC ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, ip ) );
1389 if ( netmask )
1390 DBGC ( pxe, "/%s", efi_pxe_ip_ntoa ( pxe, netmask ) );
1391 DBGC ( pxe, "\n" );
1392
1393 /* Update IP address and netmask */
1394 if ( ip )
1395 memcpy ( &mode->StationIp, ip, sizeof ( mode->StationIp ) );
1396 if ( netmask )
1397 memcpy ( &mode->SubnetMask, netmask, sizeof (mode->SubnetMask));
1398
1399 return 0;
1400}
1401
1402/**
1403 * Update cached DHCP packets
1404 *
1405 * @v base PXE base code protocol
1406 * @v dhcpdisc_ok DHCPDISCOVER is valid
1407 * @v dhcpack_ok DHCPACK received
1408 * @v proxyoffer_ok ProxyDHCPOFFER received
1409 * @v pxebsdisc_ok PxeBsDISCOVER valid
1410 * @v pxebsack_ok PxeBsACK received
1411 * @v pxebsbis_ok PxeBsBIS received
1412 * @v dhcpdisc DHCPDISCOVER packet
1413 * @v dhcpack DHCPACK packet
1414 * @v proxyoffer ProxyDHCPOFFER packet
1415 * @v pxebsdisc PxeBsDISCOVER packet
1416 * @v pxebsack PxeBsACK packet
1417 * @v pxebsbis PxeBsBIS packet
1418 * @ret efirc EFI status code
1419 */
1420static EFI_STATUS EFIAPI
1422 BOOLEAN *dhcpack_ok, BOOLEAN *proxyoffer_ok,
1423 BOOLEAN *pxebsdisc_ok, BOOLEAN *pxebsack_ok,
1424 BOOLEAN *pxebsbis_ok, EFI_PXE_BASE_CODE_PACKET *dhcpdisc,
1425 EFI_PXE_BASE_CODE_PACKET *dhcpack,
1426 EFI_PXE_BASE_CODE_PACKET *proxyoffer,
1427 EFI_PXE_BASE_CODE_PACKET *pxebsdisc,
1428 EFI_PXE_BASE_CODE_PACKET *pxebsack,
1429 EFI_PXE_BASE_CODE_PACKET *pxebsbis ) {
1430 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1432
1433 DBGC ( pxe, "PXE %s SET PACKETS\n", pxe->name );
1434
1435 /* Update fake packet flags */
1436 if ( dhcpdisc_ok )
1437 mode->DhcpDiscoverValid = *dhcpdisc_ok;
1438 if ( dhcpack_ok )
1439 mode->DhcpAckReceived = *dhcpack_ok;
1440 if ( proxyoffer_ok )
1441 mode->ProxyOfferReceived = *proxyoffer_ok;
1442 if ( pxebsdisc_ok )
1443 mode->PxeDiscoverValid = *pxebsdisc_ok;
1444 if ( pxebsack_ok )
1445 mode->PxeReplyReceived = *pxebsack_ok;
1446 if ( pxebsbis_ok )
1447 mode->PxeBisReplyReceived = *pxebsbis_ok;
1448
1449 /* Update fake packet contents */
1450 if ( dhcpdisc )
1451 memcpy ( &mode->DhcpDiscover, dhcpdisc, sizeof ( *dhcpdisc ) );
1452 if ( dhcpack )
1453 memcpy ( &mode->DhcpAck, dhcpack, sizeof ( *dhcpack ) );
1454 if ( proxyoffer )
1455 memcpy ( &mode->ProxyOffer, proxyoffer, sizeof ( *proxyoffer ));
1456 if ( pxebsdisc )
1457 memcpy ( &mode->PxeDiscover, pxebsdisc, sizeof ( *pxebsdisc ) );
1458 if ( pxebsack )
1459 memcpy ( &mode->PxeReply, pxebsack, sizeof ( *pxebsack ) );
1460 if ( pxebsbis )
1461 memcpy ( &mode->PxeBisReply, pxebsbis, sizeof ( *pxebsbis ) );
1462
1463 return 0;
1464}
1465
1466/** PXE base code protocol */
1469 .Start = efi_pxe_start,
1470 .Stop = efi_pxe_stop,
1471 .Dhcp = efi_pxe_dhcp,
1472 .Discover = efi_pxe_discover,
1473 .Mtftp = efi_pxe_mtftp,
1474 .UdpWrite = efi_pxe_udp_write,
1475 .UdpRead = efi_pxe_udp_read,
1476 .SetIpFilter = efi_pxe_set_ip_filter,
1477 .Arp = efi_pxe_arp,
1478 .SetParameters = efi_pxe_set_parameters,
1479 .SetStationIp = efi_pxe_set_station_ip,
1480 .SetPackets = efi_pxe_set_packets,
1481};
1482
1483/******************************************************************************
1484 *
1485 * Apple NetBoot protocol
1486 *
1487 ******************************************************************************
1488 */
1489
1490/**
1491 * Get DHCP/BSDP response
1492 *
1493 * @v packet Packet
1494 * @v len Length of data buffer
1495 * @v data Data buffer
1496 * @ret efirc EFI status code
1497 */
1498static EFI_STATUS EFIAPI
1500 VOID *data ) {
1501
1502 /* Check length */
1503 if ( *len < sizeof ( *packet ) ) {
1504 *len = sizeof ( *packet );
1505 return EFI_BUFFER_TOO_SMALL;
1506 }
1507
1508 /* Copy packet */
1509 memcpy ( data, packet, sizeof ( *packet ) );
1510 *len = sizeof ( *packet );
1511
1512 return EFI_SUCCESS;
1513}
1514
1515/**
1516 * Get DHCP response
1517 *
1518 * @v apple Apple NetBoot protocol
1519 * @v len Length of data buffer
1520 * @v data Data buffer
1521 * @ret efirc EFI status code
1522 */
1523static EFI_STATUS EFIAPI
1530
1531/**
1532 * Get BSDP response
1533 *
1534 * @v apple Apple NetBoot protocol
1535 * @v len Length of data buffer
1536 * @v data Data buffer
1537 * @ret efirc EFI status code
1538 */
1539static EFI_STATUS EFIAPI
1546
1547/** Apple NetBoot protocol */
1552
1553/******************************************************************************
1554 *
1555 * Installer
1556 *
1557 ******************************************************************************
1558 */
1559
1560/**
1561 * Install PXE base code protocol
1562 *
1563 * @v handle EFI handle
1564 * @v netdev Underlying network device
1565 * @ret rc Return status code
1566 */
1568 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1570 struct efi_pxe *pxe;
1571 struct in_addr ip;
1572 BOOLEAN use_ipv6;
1573 int leak = 0;
1574 EFI_STATUS efirc;
1575 int rc;
1576
1577 /* Allocate and initialise structure */
1578 pxe = zalloc ( sizeof ( *pxe ) );
1579 if ( ! pxe ) {
1580 rc = -ENOMEM;
1581 goto err_alloc;
1582 }
1583 ref_init ( &pxe->refcnt, efi_pxe_free );
1584 pxe->netdev = netdev_get ( netdev );
1585 pxe->name = netdev->name;
1586 pxe->handle = handle;
1587 memcpy ( &pxe->base, &efi_pxe_base_code_protocol, sizeof ( pxe->base ));
1588 pxe->base.Mode = &pxe->mode;
1590 sizeof ( pxe->apple ) );
1591 intf_init ( &pxe->tftp, &efi_pxe_tftp_desc, &pxe->refcnt );
1592 intf_init ( &pxe->udp, &efi_pxe_udp_desc, &pxe->refcnt );
1593 INIT_LIST_HEAD ( &pxe->queue );
1595 &pxe->refcnt );
1596
1597 /* Crude heuristic: assume that we prefer to use IPv4 if we
1598 * have an IPv4 address for the network device, otherwise
1599 * prefer IPv6 (if available).
1600 */
1602 use_ipv6 = ( ip.s_addr ? FALSE : ( ipv6 != NULL ) );
1603
1604 /* Start base code */
1605 efi_pxe_start ( &pxe->base, use_ipv6 );
1606
1607 /* Install PXE base code protocol */
1608 if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1609 &handle,
1612 NULL ) ) != 0 ) {
1613 rc = -EEFI ( efirc );
1614 DBGC ( pxe, "PXE %s could not install base code protocol: %s\n",
1615 pxe->name, strerror ( rc ) );
1616 goto err_install_protocol;
1617 }
1618
1619 /* Transfer reference to list and return */
1620 list_add_tail ( &pxe->list, &efi_pxes );
1621 DBGC ( pxe, "PXE %s installed for %s\n",
1622 pxe->name, efi_handle_name ( handle ) );
1623 return 0;
1624
1625 if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1626 handle,
1629 NULL ) ) != 0 ) {
1630 DBGC ( pxe, "PXE %s could not uninstall: %s\n",
1631 pxe->name, strerror ( -EEFI ( efirc ) ) );
1632 leak = 1;
1633 }
1634 efi_nullify_pxe ( &pxe->base );
1635 efi_nullify_apple ( &pxe->apple );
1636 err_install_protocol:
1637 if ( ! leak )
1638 ref_put ( &pxe->refcnt );
1639 err_alloc:
1640 if ( leak )
1641 DBGC ( pxe, "PXE %s nullified and leaked\n", pxe->name );
1642 return rc;
1643}
1644
1645/**
1646 * Uninstall PXE base code protocol
1647 *
1648 * @v handle EFI handle
1649 */
1651 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1652 struct efi_pxe *pxe;
1653 int leak = efi_shutdown_in_progress;
1654 EFI_STATUS efirc;
1655
1656 /* Locate PXE base code */
1657 pxe = efi_pxe_find ( handle );
1658 if ( ! pxe ) {
1659 DBG ( "PXE could not find base code for %s\n",
1660 efi_handle_name ( handle ) );
1661 return;
1662 }
1663
1664 /* Stop base code */
1665 efi_pxe_stop ( &pxe->base );
1666
1667 /* Uninstall PXE base code protocol */
1668 if ( ( ! efi_shutdown_in_progress ) &&
1669 ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1670 handle,
1673 NULL ) ) != 0 ) ) {
1674 DBGC ( pxe, "PXE %s could not uninstall: %s\n",
1675 pxe->name, strerror ( -EEFI ( efirc ) ) );
1676 leak = 1;
1677 }
1678 efi_nullify_pxe ( &pxe->base );
1679 efi_nullify_apple ( &pxe->apple );
1680
1681 /* Remove from list and drop list's reference */
1682 list_del ( &pxe->list );
1683 if ( ! leak )
1684 ref_put ( &pxe->refcnt );
1685
1686 /* Report leakage, if applicable */
1687 if ( leak && ( ! efi_shutdown_in_progress ) )
1688 DBGC ( pxe, "PXE %s nullified and leaked\n", pxe->name );
1689}
unsigned short UINT16
2-byte unsigned value.
unsigned char BOOLEAN
Logical Boolean.
UINT64 UINTN
Unsigned value of native width.
unsigned long long UINT64
8-byte unsigned value.
#define EFIAPI
unsigned char UINT8
1-byte unsigned value.
Apple Net Boot Protocol.
struct _EFI_APPLE_NET_BOOT_PROTOCOL EFI_APPLE_NET_BOOT_PROTOCOL
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define VOID
Undeclared type.
Definition Base.h:272
__be32 in[4]
Definition CIB_PRM.h:7
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
EFI PXE Base Code Protocol definitions, which is used to access PXE-compatible devices for network ac...
struct _EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE_PROTOCOL
Definition PxeBaseCode.h:30
#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
#define EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
Definition PxeBaseCode.h:86
#define EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
Definition PxeBaseCode.h:85
#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
EFI_PXE_BASE_CODE_TFTP_OPCODE
TFTP opcode definitions.
@ EFI_PXE_BASE_CODE_TFTP_READ_FILE
@ EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
@ EFI_PXE_BASE_CODE_MTFTP_READ_FILE
#define EFI_PXE_BASE_CODE_PROTOCOL_REVISION
#define DEFAULT_ToS
Definition PxeBaseCode.h:41
#define DEFAULT_TTL
Default IP TTL and ToS.
Definition PxeBaseCode.h:40
#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
Definition PxeBaseCode.h:87
UINT16 EFI_PXE_BASE_CODE_UDP_PORT
#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
Definition PxeBaseCode.h:88
#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
#define EFI_UNSUPPORTED
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_BUFFER_TOO_SMALL
Enumeration of EFI_STATUS.
#define EFI_SUCCESS
Enumeration of EFI_STATUS.
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
u32 info
Definition ar9003_mac.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
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
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
struct bofm_section_header done
Definition bofm_test.c:46
int overwrite(const WINDOW *, WINDOW *)
union @104331263140136355135267063077374276003064103115 u
void dhcppkt_init(struct dhcp_packet *dhcppkt, struct dhcphdr *data, size_t len)
Initialise DHCP packet.
Definition dhcppkt.c:301
DHCP packets.
static size_t dhcppkt_len(struct dhcp_packet *dhcppkt)
Get used length of DHCP packet.
Definition dhcppkt.h:60
ring len
Length.
Definition dwmac.h:226
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition efi_debug.c:652
EFI_GUID efi_pxe_base_code_protocol_guid
PXE base code protocol GUID.
Definition efi_guid.c:321
EFI_GUID efi_apple_net_boot_protocol_guid
Apple NetBoot protocol GUID.
Definition efi_guid.c:133
int efi_shutdown_in_progress
EFI shutdown is in progress.
Definition efi_init.c:60
void efi_nullify_pxe(EFI_PXE_BASE_CODE_PROTOCOL *pxe)
Nullify PXE base code protocol.
Definition efi_null.c:537
void efi_nullify_apple(EFI_APPLE_NET_BOOT_PROTOCOL *apple)
Nullify Apple Net Boot protocol.
Definition efi_null.c:572
EFI null interfaces.
const struct setting ip_setting
const struct setting netmask_setting
static int efi_pxe_ip(struct efi_pxe *pxe)
Populate local IP address.
Definition efi_pxe.c:227
void efi_pxe_uninstall(EFI_HANDLE handle)
Uninstall PXE base code protocol.
Definition efi_pxe.c:1650
static struct interface_descriptor efi_pxe_udp_desc
PXE UDP interface descriptor.
Definition efi_pxe.c:531
static EFI_STATUS EFIAPI efi_pxe_mtftp(EFI_PXE_BASE_CODE_PROTOCOL *base, EFI_PXE_BASE_CODE_TFTP_OPCODE opcode, VOID *data, BOOLEAN overwrite, UINT64 *len, UINTN *blksize, EFI_IP_ADDRESS *ip, UINT8 *filename, EFI_PXE_BASE_CODE_MTFTP_INFO *info, BOOLEAN callback)
Perform (M)TFTP.
Definition efi_pxe.c:896
static struct interface_operation efi_pxe_udp_operations[]
PXE UDP interface operations.
Definition efi_pxe.c:525
static EFI_STATUS EFIAPI efi_pxe_dhcp(EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN sort)
Perform DHCP.
Definition efi_pxe.c:798
static EFI_STATUS EFIAPI efi_apple_get_response(EFI_PXE_BASE_CODE_PACKET *packet, UINTN *len, VOID *data)
Get DHCP/BSDP response.
Definition efi_pxe.c:1499
static struct interface_descriptor efi_pxe_tftp_desc
PXE file data transfer interface descriptor.
Definition efi_pxe.c:382
static int efi_pxe_udp_open(struct efi_pxe *pxe)
Open UDP interface.
Definition efi_pxe.c:540
static EFI_STATUS EFIAPI efi_pxe_stop(EFI_PXE_BASE_CODE_PROTOCOL *base)
Stop PXE base code.
Definition efi_pxe.c:773
static void efi_pxe_free(struct refcnt *refcnt)
Free PXE base code.
Definition efi_pxe.c:119
static EFI_PXE_BASE_CODE_PROTOCOL efi_pxe_base_code_protocol
PXE base code protocol.
Definition efi_pxe.c:1467
static EFI_STATUS EFIAPI efi_pxe_set_ip_filter(EFI_PXE_BASE_CODE_PROTOCOL *base, EFI_PXE_BASE_CODE_IP_FILTER *filter)
Set receive filter.
Definition efi_pxe.c:1284
static void efi_pxe_fake_all(struct efi_pxe *pxe)
Construct fake DHCP packets.
Definition efi_pxe.c:689
static EFI_STATUS EFIAPI efi_pxe_udp_write(EFI_PXE_BASE_CODE_PROTOCOL *base, UINT16 flags, EFI_IP_ADDRESS *dest_ip, EFI_PXE_BASE_CODE_UDP_PORT *dest_port, EFI_IP_ADDRESS *gateway, EFI_IP_ADDRESS *src_ip, EFI_PXE_BASE_CODE_UDP_PORT *src_port, UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data)
Transmit UDP packet.
Definition efi_pxe.c:989
static EFI_STATUS EFIAPI efi_apple_get_bsdp_response(EFI_APPLE_NET_BOOT_PROTOCOL *apple, UINTN *len, VOID *data)
Get BSDP response.
Definition efi_pxe.c:1540
static int efi_pxe_udp_deliver(struct efi_pxe *pxe, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive UDP packet.
Definition efi_pxe.c:474
static struct efi_pxe * efi_pxe_find(EFI_HANDLE handle)
Locate PXE base code.
Definition efi_pxe.c:135
static const char * efi_pxe_fake_name(struct efi_pxe *pxe, EFI_PXE_BASE_CODE_PACKET *packet)
Name fake DHCP packet.
Definition efi_pxe.c:608
static void efi_pxe_udp_close(struct efi_pxe *pxe, int rc)
Close UDP interface.
Definition efi_pxe.c:445
static void efi_pxe_tftp_close(struct efi_pxe *pxe, int rc)
Close PXE (M)TFTP download interface.
Definition efi_pxe.c:322
static EFI_STATUS EFIAPI efi_pxe_set_packets(EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN *dhcpdisc_ok, BOOLEAN *dhcpack_ok, BOOLEAN *proxyoffer_ok, BOOLEAN *pxebsdisc_ok, BOOLEAN *pxebsack_ok, BOOLEAN *pxebsbis_ok, EFI_PXE_BASE_CODE_PACKET *dhcpdisc, EFI_PXE_BASE_CODE_PACKET *dhcpack, EFI_PXE_BASE_CODE_PACKET *proxyoffer, EFI_PXE_BASE_CODE_PACKET *pxebsdisc, EFI_PXE_BASE_CODE_PACKET *pxebsack, EFI_PXE_BASE_CODE_PACKET *pxebsbis)
Update cached DHCP packets.
Definition efi_pxe.c:1421
static EFI_STATUS EFIAPI efi_pxe_start(EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN use_ipv6)
Start PXE base code.
Definition efi_pxe.c:718
static int efi_pxe_ip_filter(struct efi_pxe *pxe, EFI_IP_ADDRESS *ip)
Check if IP address matches filter.
Definition efi_pxe.c:260
static struct interface_operation efi_pxe_tftp_operations[]
PXE file data transfer interface operations.
Definition efi_pxe.c:375
static void efi_pxe_ip_sockaddr(struct efi_pxe *pxe, EFI_IP_ADDRESS *ip, struct sockaddr *sa)
Populate socket address from EFI IP address.
Definition efi_pxe.c:194
static struct process_descriptor efi_pxe_process_desc
UDP close process descriptor.
Definition efi_pxe.c:591
static size_t efi_pxe_tftp_window(struct efi_pxe *pxe)
Check PXE (M)TFTP download flow control window.
Definition efi_pxe.c:337
static EFI_STATUS EFIAPI efi_pxe_set_station_ip(EFI_PXE_BASE_CODE_PROTOCOL *base, EFI_IP_ADDRESS *ip, EFI_IP_ADDRESS *netmask)
Set IP address.
Definition efi_pxe.c:1381
static int efi_pxe_tftp_deliver(struct efi_pxe *pxe, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive new PXE (M)TFTP download data.
Definition efi_pxe.c:351
static EFI_STATUS EFIAPI efi_pxe_discover(EFI_PXE_BASE_CODE_PROTOCOL *base, UINT16 type, UINT16 *layer, BOOLEAN bis, EFI_PXE_BASE_CODE_DISCOVER_INFO *info)
Perform boot server discovery.
Definition efi_pxe.c:852
static EFI_STATUS EFIAPI efi_apple_get_dhcp_response(EFI_APPLE_NET_BOOT_PROTOCOL *apple, UINTN *len, VOID *data)
Get DHCP response.
Definition efi_pxe.c:1524
static const char * efi_pxe_ip_ntoa(struct efi_pxe *pxe, EFI_IP_ADDRESS *ip)
Transcribe EFI IP address (for debugging)
Definition efi_pxe.c:215
static EFI_STATUS EFIAPI efi_pxe_arp(EFI_PXE_BASE_CODE_PROTOCOL *base, EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac)
Resolve MAC address.
Definition efi_pxe.c:1312
static BOOLEAN efi_pxe_fake(struct efi_pxe *pxe, int(*fake)(struct net_device *netdev, void *data, size_t len), EFI_PXE_BASE_CODE_PACKET *packet)
Construct fake DHCP packet and flag.
Definition efi_pxe.c:637
static void efi_pxe_udp_schedule_close(struct efi_pxe *pxe)
Schedule close of UDP interface.
Definition efi_pxe.c:567
static EFI_STATUS EFIAPI efi_pxe_set_parameters(EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN *autoarp, BOOLEAN *sendguid, UINT8 *ttl, UINT8 *tos, BOOLEAN *callback)
Set parameters.
Definition efi_pxe.c:1336
static int efi_pxe_tftp_open(struct efi_pxe *pxe, EFI_IP_ADDRESS *ip, const char *filename)
Open (M)TFTP download interface.
Definition efi_pxe.c:393
static EFI_STATUS EFIAPI efi_pxe_udp_read(EFI_PXE_BASE_CODE_PROTOCOL *base, UINT16 flags, EFI_IP_ADDRESS *dest_ip, EFI_PXE_BASE_CODE_UDP_PORT *dest_port, EFI_IP_ADDRESS *src_ip, EFI_PXE_BASE_CODE_UDP_PORT *src_port, UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data)
Receive UDP packet.
Definition efi_pxe.c:1103
static void efi_pxe_udp_scheduled_close(struct efi_pxe *pxe)
Scheduled close of UDP interface.
Definition efi_pxe.c:584
static EFI_APPLE_NET_BOOT_PROTOCOL efi_apple_net_boot_protocol
Apple NetBoot protocol.
Definition efi_pxe.c:1548
int efi_pxe_install(EFI_HANDLE handle, struct net_device *netdev)
Install PXE base code protocol.
Definition efi_pxe.c:1567
EFI PXE base code protocol.
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
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t flags
Flags.
Definition ena.h:7
uint8_t meta
Metadata flags.
Definition ena.h:3
uint64_t address
Base address.
Definition ena.h:13
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
uint8_t opcode
Opcode.
Definition ena.h:5
uint16_t mode
Acceleration mode.
Definition ena.h:15
Error codes.
int create_fakedhcpdiscover(struct net_device *netdev, void *data, size_t max_len)
Create fake DHCPDISCOVER packet.
Definition fakedhcp.c:110
int create_fakepxebsack(struct net_device *netdev, void *data, size_t max_len)
Create fake PXE Boot Server ACK packet.
Definition fakedhcp.c:179
int create_fakedhcpack(struct net_device *netdev, void *data, size_t max_len)
Create fake DHCPACK packet.
Definition fakedhcp.c:137
Fake DHCP packets.
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 DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define DHCP_END
End of options.
Definition dhcp.h:549
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EINPROGRESS
Operation in progress.
Definition errno.h:419
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ERANGE
Result too large.
Definition errno.h:640
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
Network interface management.
#define INADDR_BROADCAST
Definition in.h:22
#define IN6_IS_ADDR_MULTICAST(addr)
Definition in.h:68
#define IN_IS_MULTICAST(addr)
Definition in.h:34
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
#define __attribute__(x)
Definition compiler.h:10
EFI API.
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition efi.h:173
#define EFI_HANDLE
Definition efi.h:53
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:181
EFI_SYSTEM_TABLE * efi_systab
uint16_t handle
Handle.
Definition smbios.h:5
Transport-network layer interface.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
int iob_ensure_headroom(struct io_buffer *iobuf, size_t len)
Ensure I/O buffer has sufficient headroom.
Definition iobuf.c:235
#define iob_push(iobuf, len)
Definition iobuf.h:89
#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_pull(iobuf, len)
Definition iobuf.h:107
uint32_t base
Base.
Definition librm.h:3
unsigned long tmp
Definition linux_pci.h:65
Linked lists.
#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_empty(list)
Test whether a list is empty.
Definition list.h:137
#define LIST_HEAD(list)
Declare a static list head.
Definition list.h:38
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
int netdev_configure_all(struct net_device *netdev)
Start network device configuration via all supported configurators.
Definition netdevice.c:1340
int netdev_configuration_ok(struct net_device *netdev)
Check if network device has at least one successful configuration.
Definition netdevice.c:1396
int netdev_configuration_in_progress(struct net_device *netdev)
Check if network device configuration is in progress.
Definition netdevice.c:1384
Network device management.
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:568
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:579
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:590
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
int xfer_open_uri(struct interface *intf, struct uri *uri)
Open URI.
Definition open.c:68
Data transfer interface opening.
uint32_t blksize
Cipher block size.
Definition pccrr.h:1
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void step(void)
Single-step a single process.
Definition process.c:99
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static int process_running(struct process *process)
Check if process is running.
Definition process.h:176
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
IP4_t dest_ip
Destination IP address.
Definition pxe_api.h:2
IP4_t src_ip
IP address of this station.
Definition pxe_api.h:1
UINT8_t filter
Receive packet filter.
Definition pxe_api.h:11
IP4_t ip
Destination IP address.
Definition pxe_api.h:1
UDP_PORT_t src_port
Source UDP port.
Definition pxe_api.h:3
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
Reference counting.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition settings.c:913
Socket addresses.
uint16_t sa_family_t
A socket address family.
Definition socket.h:86
static const char * socket_family_name(int family)
Name address family.
Definition socket.h:76
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
EFI Boot Services Table.
Definition UefiSpec.h:1931
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces
Definition UefiSpec.h:2011
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces
Definition UefiSpec.h:2010
32-byte buffer containing a network Media Access Control address.
Discover() information override structure.
IP Receive Filter structure.
Definition PxeBaseCode.h:78
EFI_PXE_BASE_CODE_MODE.
EFI_PXE_BASE_CODE_PACKET DhcpAck
EFI_PXE_BASE_CODE_PACKET PxeReply
EFI_PXE_BASE_CODE_MODE * Mode
The pointer to the EFI_PXE_BASE_CODE_MODE data for this device.
A DHCP packet.
Definition dhcppkt.h:21
A DHCP header.
Definition dhcp.h:616
EFI UDP pseudo-header.
Definition efi_pxe.c:430
struct net_protocol * net
Network-layer protocol.
Definition efi_pxe.c:432
uint16_t src_port
Source port.
Definition efi_pxe.c:436
uint16_t dest_port
Destination port.
Definition efi_pxe.c:434
A PXE base code.
Definition efi_pxe.c:70
struct tcpip_net_protocol * tcpip
TCP/IP network-layer protocol.
Definition efi_pxe.c:90
size_t blksize
Block size (for TFTP)
Definition efi_pxe.c:102
unsigned int opcode
Opcode.
Definition efi_pxe.c:100
struct interface udp
UDP interface.
Definition efi_pxe.c:107
struct xfer_buffer buf
Data transfer buffer.
Definition efi_pxe.c:95
struct net_protocol * net
Network-layer protocol.
Definition efi_pxe.c:92
struct net_device * netdev
Underlying network device.
Definition efi_pxe.c:74
struct list_head list
List of PXE base codes.
Definition efi_pxe.c:78
EFI_PXE_BASE_CODE_PROTOCOL base
PXE base code protocol.
Definition efi_pxe.c:83
struct list_head queue
List of received UDP packets.
Definition efi_pxe.c:109
struct interface tftp
(M)TFTP download interface
Definition efi_pxe.c:98
int rc
Overall return status.
Definition efi_pxe.c:104
EFI_PXE_BASE_CODE_MODE mode
PXE base code mode.
Definition efi_pxe.c:85
EFI_APPLE_NET_BOOT_PROTOCOL apple
Apple NetBoot protocol.
Definition efi_pxe.c:87
struct refcnt refcnt
Reference count.
Definition efi_pxe.c:72
const char * name
Name.
Definition efi_pxe.c:76
EFI_HANDLE handle
Installed handle.
Definition efi_pxe.c:81
struct process process
UDP interface closer process.
Definition efi_pxe.c:111
IP6 address structure.
Definition in.h:51
IP address structure.
Definition in.h:42
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
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 doubly-linked list entry (or list head)
Definition list.h:19
A network device.
Definition netdevice.h:353
unsigned int scope_id
Scope ID.
Definition netdevice.h:361
A network-layer protocol.
Definition netdevice.h:65
const char * name
Protocol name.
Definition netdevice.h:67
uint8_t net_addr_len
Network-layer address length.
Definition netdevice.h:102
const char *(* ntoa)(const void *net_addr)
Transcribe network-layer address.
Definition netdevice.h:95
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A reference counter.
Definition refcnt.h:27
An EFI socket address.
Definition efi_pxe.c:158
sa_family_t se_family
Socket address family (part of struct sockaddr)
Definition efi_pxe.c:160
uint16_t se_flags
Flags (part of struct sockaddr_tcpip)
Definition efi_pxe.c:162
uint16_t se_scope_id
Scope ID (part of struct sockaddr_tcpip)
Definition efi_pxe.c:170
char pad[sizeof(struct sockaddr) -(sizeof(sa_family_t)+sizeof(uint16_t)+sizeof(uint16_t)+sizeof(uint16_t)+sizeof(EFI_IP_ADDRESS))]
Padding.
Definition efi_pxe.c:184
uint16_t se_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition efi_pxe.c:164
EFI_IP_ADDRESS se_addr
IP address.
Definition efi_pxe.c:172
TCP/IP socket address.
Definition tcpip.h:76
Generalized socket address structure.
Definition socket.h:97
sa_family_t sa_family
Socket address family.
Definition socket.h:102
A network-layer protocol of the TCP/IP stack (eg.
Definition tcpip.h:141
sa_family_t sa_family
Network address family.
Definition tcpip.h:145
struct net_protocol * net_protocol
Network-layer protocol.
Definition tcpip.h:149
A Uniform Resource Identifier.
Definition uri.h:65
A data transfer buffer.
Definition xferbuf.h:19
size_t max
Maximum required size of data.
Definition xferbuf.h:25
Data transfer metadata.
Definition xfer.h:23
struct sockaddr_tcpip st
Definition syslog.c:58
struct sockaddr sa
Definition syslog.c:57
struct tcpip_net_protocol * tcpip_net_protocol(sa_family_t sa_family)
Find TCP/IP network-layer protocol.
Definition tcpip.c:69
#define TRUE
Definition tlan.h:46
#define FALSE
Definition tlan.h:45
int udp_open_promisc(struct interface *xfer)
Open a promiscuous UDP connection.
Definition udp.c:145
UDP protocol.
16-byte buffer aligned on a 4-byte boundary.
Packet structure.
EFI_PXE_BASE_CODE_DHCPV4_PACKET Dhcpv4
struct uri * pxe_uri(struct sockaddr *sa_server, const char *filename)
Construct URI from server address and filename.
Definition uri.c:810
Uniform Resource Identifiers.
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition uri.h:206
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48
int xferbuf_deliver(struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Add received data to data transfer buffer.
Definition xferbuf.c:177
Data transfer buffer.
static void xferbuf_fixed_init(struct xfer_buffer *xferbuf, void *data, size_t len)
Initialise fixed-size data transfer buffer.
Definition xferbuf.h:83
static void xferbuf_void_init(struct xfer_buffer *xferbuf)
Initialise void data transfer buffer.
Definition xferbuf.h:98