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 /** Block size (for TFTP) */
100 size_t blksize;
101 /** Overall return status */
102 int rc;
103
104 /** UDP interface */
106 /** List of received UDP packets */
108 /** UDP interface closer process */
110};
111
112/**
113 * Free PXE base code
114 *
115 * @v refcnt Reference count
116 */
117static void efi_pxe_free ( struct refcnt *refcnt ) {
118 struct efi_pxe *pxe = container_of ( refcnt, struct efi_pxe, refcnt );
119
120 netdev_put ( pxe->netdev );
121 free ( pxe );
122}
123
124/** List of PXE base codes */
125static LIST_HEAD ( efi_pxes );
126
127/**
128 * Locate PXE base code
129 *
130 * @v handle EFI handle
131 * @ret pxe PXE base code, or NULL
132 */
134 struct efi_pxe *pxe;
135
136 /* Locate base code */
137 list_for_each_entry ( pxe, &efi_pxes, list ) {
138 if ( pxe->handle == handle )
139 return pxe;
140 }
141
142 return NULL;
143}
144
145/******************************************************************************
146 *
147 * IP addresses
148 *
149 ******************************************************************************
150 */
151
152/**
153 * An EFI socket address
154 *
155 */
157 /** Socket address family (part of struct @c sockaddr) */
159 /** Flags (part of struct @c sockaddr_tcpip) */
161 /** TCP/IP port (part of struct @c sockaddr_tcpip) */
163 /** Scope ID (part of struct @c sockaddr_tcpip)
164 *
165 * For link-local or multicast addresses, this is the network
166 * device index.
167 */
169 /** IP address */
171 /** Padding
172 *
173 * This ensures that a struct @c sockaddr_tcpip is large
174 * enough to hold a socket address for any TCP/IP address
175 * family.
176 */
177 char pad[ sizeof ( struct sockaddr ) -
178 ( sizeof ( sa_family_t ) /* se_family */ +
179 sizeof ( uint16_t ) /* se_flags */ +
180 sizeof ( uint16_t ) /* se_port */ +
181 sizeof ( uint16_t ) /* se_scope_id */ +
182 sizeof ( EFI_IP_ADDRESS ) /* se_addr */ ) ];
183} __attribute__ (( packed, may_alias ));
184
185/**
186 * Populate socket address from EFI IP address
187 *
188 * @v pxe PXE base code
189 * @v ip EFI IP address
190 * @v sa Socket address to fill in
191 */
192static void efi_pxe_ip_sockaddr ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
193 struct sockaddr *sa ) {
194 union {
195 struct sockaddr sa;
196 struct sockaddr_efi se;
197 } *sockaddr = container_of ( sa, typeof ( *sockaddr ), sa );
198
199 /* Initialise socket address */
200 memset ( sockaddr, 0, sizeof ( *sockaddr ) );
201 sockaddr->sa.sa_family = pxe->tcpip->sa_family;
202 memcpy ( &sockaddr->se.se_addr, ip, pxe->net->net_addr_len );
203 sockaddr->se.se_scope_id = pxe->netdev->scope_id;
204}
205
206/**
207 * Transcribe EFI IP address (for debugging)
208 *
209 * @v pxe PXE base code
210 * @v ip EFI IP address
211 * @ret text Transcribed IP address
212 */
213static const char * efi_pxe_ip_ntoa ( struct efi_pxe *pxe,
214 EFI_IP_ADDRESS *ip ) {
215
216 return pxe->net->ntoa ( ip );
217}
218
219/**
220 * Populate local IP address
221 *
222 * @v pxe PXE base code
223 * @ret rc Return status code
224 */
225static int efi_pxe_ip ( struct efi_pxe *pxe ) {
227 struct in_addr address;
228 struct in_addr netmask;
229
230 /* It's unclear which of the potentially many IPv6 addresses
231 * is supposed to be used.
232 */
233 if ( mode->UsingIpv6 )
234 return -ENOTSUP;
235
236 /* Fetch IP address and subnet mask */
238 &address );
240 &netmask );
241
242 /* Populate IP address and subnet mask */
243 memset ( &mode->StationIp, 0, sizeof ( mode->StationIp ) );
244 memcpy ( &mode->StationIp, &address, sizeof ( address ) );
245 memset ( &mode->SubnetMask, 0, sizeof ( mode->SubnetMask ) );
246 memcpy ( &mode->SubnetMask, &netmask, sizeof ( netmask ) );
247
248 return 0;
249}
250
251/**
252 * Check if IP address matches filter
253 *
254 * @v pxe PXE base code
255 * @v ip EFI IP address
256 * @ret is_match IP address matches filter
257 */
258static int efi_pxe_ip_filter ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip ) {
261 uint8_t filters = filter->Filters;
262 union {
264 struct in_addr in;
265 struct in6_addr in6;
266 } *u = container_of ( ip, typeof ( *u ), ip );
267 size_t addr_len = pxe->net->net_addr_len;
268 unsigned int i;
269
270 /* Match everything, if applicable */
272 return 1;
273
274 /* Match all multicasts, if applicable */
276 if ( mode->UsingIpv6 ) {
277 if ( IN6_IS_ADDR_MULTICAST ( &u->in6 ) )
278 return 1;
279 } else {
280 if ( IN_IS_MULTICAST ( u->in.s_addr ) )
281 return 1;
282 }
283 }
284
285 /* Match IPv4 broadcasts, if applicable */
287 if ( ( ! mode->UsingIpv6 ) &&
288 ( u->in.s_addr == INADDR_BROADCAST ) )
289 return 1;
290 }
291
292 /* Match station address, if applicable */
294 if ( memcmp ( ip, &mode->StationIp, addr_len ) == 0 )
295 return 1;
296 }
297
298 /* Match explicit addresses, if applicable */
299 for ( i = 0 ; i < filter->IpCnt ; i++ ) {
300 if ( memcmp ( ip, &filter->IpList[i], addr_len ) == 0 )
301 return 1;
302 }
303
304 return 0;
305}
306
307/******************************************************************************
308 *
309 * (M)TFTP download interface
310 *
311 ******************************************************************************
312 */
313
314/**
315 * Close PXE (M)TFTP download interface
316 *
317 * @v pxe PXE base code
318 * @v rc Reason for close
319 */
320static void efi_pxe_tftp_close ( struct efi_pxe *pxe, int rc ) {
321
322 /* Restart interface */
323 intf_restart ( &pxe->tftp, rc );
324
325 /* Record overall status */
326 pxe->rc = rc;
327}
328
329/**
330 * Check PXE (M)TFTP download flow control window
331 *
332 * @v pxe PXE base code
333 * @ret len Length of window
334 */
335static size_t efi_pxe_tftp_window ( struct efi_pxe *pxe ) {
336
337 /* Return requested blocksize */
338 return pxe->blksize;
339}
340
341/**
342 * Receive new PXE (M)TFTP download data
343 *
344 * @v pxe PXE base code
345 * @v iobuf I/O buffer
346 * @v meta Transfer metadata
347 * @ret rc Return status code
348 */
349static int efi_pxe_tftp_deliver ( struct efi_pxe *pxe,
350 struct io_buffer *iobuf,
351 struct xfer_metadata *meta ) {
352 int rc;
353
354 /* Deliver to data transfer buffer */
355 if ( ( rc = xferbuf_deliver ( &pxe->buf, iob_disown ( iobuf ),
356 meta ) ) != 0 )
357 goto err_deliver;
358
359 return 0;
360
361 err_deliver:
362 efi_pxe_tftp_close ( pxe, rc );
363 return rc;
364}
365
366/** PXE file data transfer interface operations */
372
373/** PXE file data transfer interface descriptor */
375 INTF_DESC ( struct efi_pxe, tftp, efi_pxe_tftp_operations );
376
377/**
378 * Open (M)TFTP download interface
379 *
380 * @v pxe PXE base code
381 * @v ip EFI IP address
382 * @v filename Filename
383 * @ret rc Return status code
384 */
385static int efi_pxe_tftp_open ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
386 const char *filename ) {
387 struct sockaddr server;
388 struct uri *uri;
389 int rc;
390
391 /* Parse server address and filename */
392 efi_pxe_ip_sockaddr ( pxe, ip, &server );
393 uri = pxe_uri ( &server, filename );
394 if ( ! uri ) {
395 DBGC ( pxe, "PXE %s could not parse %s:%s\n", pxe->name,
396 efi_pxe_ip_ntoa ( pxe, ip ), filename );
397 rc = -ENOTSUP;
398 goto err_parse;
399 }
400
401 /* Open URI */
402 if ( ( rc = xfer_open_uri ( &pxe->tftp, uri ) ) != 0 ) {
403 DBGC ( pxe, "PXE %s could not open: %s\n",
404 pxe->name, strerror ( rc ) );
405 goto err_open;
406 }
407
408 err_open:
409 uri_put ( uri );
410 err_parse:
411 return rc;
412}
413
414/******************************************************************************
415 *
416 * UDP interface
417 *
418 ******************************************************************************
419 */
420
421/** EFI UDP pseudo-header */
423 /** Network-layer protocol */
425 /** Destination port */
427 /** Source port */
429} __attribute__ (( packed ));
430
431/**
432 * Close UDP interface
433 *
434 * @v pxe PXE base code
435 * @v rc Reason for close
436 */
437static void efi_pxe_udp_close ( struct efi_pxe *pxe, int rc ) {
438 struct io_buffer *iobuf;
439 struct io_buffer *tmp;
440
441 /* Release our claim on SNP devices, if applicable */
442 if ( process_running ( &pxe->process ) )
444
445 /* Stop process */
446 process_del ( &pxe->process );
447
448 /* Restart UDP interface */
449 intf_restart ( &pxe->udp, rc );
450
451 /* Flush any received UDP packets */
452 list_for_each_entry_safe ( iobuf, tmp, &pxe->queue, list ) {
453 list_del ( &iobuf->list );
454 free_iob ( iobuf );
455 }
456}
457
458/**
459 * Receive UDP packet
460 *
461 * @v pxe PXE base code
462 * @v iobuf I/O buffer
463 * @v meta Data transfer metadata
464 * @ret rc Return status code
465 */
466static int efi_pxe_udp_deliver ( struct efi_pxe *pxe, struct io_buffer *iobuf,
467 struct xfer_metadata *meta ) {
468 struct sockaddr_efi *se_src;
469 struct sockaddr_efi *se_dest;
470 struct tcpip_net_protocol *tcpip;
471 struct net_protocol *net;
472 struct efi_pxe_udp_pseudo_header *pshdr;
473 size_t addr_len;
474 size_t pshdr_len;
475 int rc;
476
477 /* Sanity checks */
478 assert ( meta != NULL );
479 se_src = ( ( struct sockaddr_efi * ) meta->src );
480 assert ( se_src != NULL );
481 se_dest = ( ( struct sockaddr_efi * ) meta->dest );
482 assert ( se_dest != NULL );
483 assert ( se_src->se_family == se_dest->se_family );
484
485 /* Determine protocol */
486 tcpip = tcpip_net_protocol ( se_src->se_family );
487 if ( ! tcpip ) {
488 rc = -ENOTSUP;
489 goto err_unsupported;
490 }
491 net = tcpip->net_protocol;
492 addr_len = net->net_addr_len;
493
494 /* Construct pseudo-header */
495 pshdr_len = ( sizeof ( *pshdr ) + ( 2 * addr_len ) );
496 if ( ( rc = iob_ensure_headroom ( iobuf, pshdr_len ) ) != 0 )
497 goto err_headroom;
498 memcpy ( iob_push ( iobuf, addr_len ), &se_src->se_addr, addr_len );
499 memcpy ( iob_push ( iobuf, addr_len ), &se_dest->se_addr, addr_len );
500 pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
501 pshdr->net = net;
502 pshdr->dest_port = ntohs ( se_dest->se_port );
503 pshdr->src_port = ntohs ( se_src->se_port );
504
505 /* Add to queue */
506 list_add_tail ( &iobuf->list, &pxe->queue );
507
508 return 0;
509
510 err_unsupported:
511 err_headroom:
512 free_iob ( iobuf );
513 return rc;
514}
515
516/** PXE UDP interface operations */
521
522/** PXE UDP interface descriptor */
525
526/**
527 * Open UDP interface
528 *
529 * @v pxe PXE base code
530 * @ret rc Return status code
531 */
532static int efi_pxe_udp_open ( struct efi_pxe *pxe ) {
533 int rc;
534
535 /* If interface is already open, then cancel the scheduled close */
536 if ( process_running ( &pxe->process ) ) {
537 process_del ( &pxe->process );
538 return 0;
539 }
540
541 /* Open promiscuous UDP interface */
542 if ( ( rc = udp_open_promisc ( &pxe->udp ) ) != 0 ) {
543 DBGC ( pxe, "PXE %s could not open UDP connection: %s\n",
544 pxe->name, strerror ( rc ) );
545 return rc;
546 }
547
548 /* Claim network devices */
550
551 return 0;
552}
553
554/**
555 * Schedule close of UDP interface
556 *
557 * @v pxe PXE base code
558 */
559static void efi_pxe_udp_schedule_close ( struct efi_pxe *pxe ) {
560
561 /* The EFI PXE base code protocol does not provide any
562 * explicit UDP open/close methods. To avoid the overhead of
563 * reopening a socket for each read/write operation, we start
564 * a process which will close the socket immediately if the
565 * next call into iPXE is anything other than a UDP
566 * read/write.
567 */
568 process_add ( &pxe->process );
569}
570
571/**
572 * Scheduled close of UDP interface
573 *
574 * @v pxe PXE base code
575 */
576static void efi_pxe_udp_scheduled_close ( struct efi_pxe *pxe ) {
577
578 /* Close UDP interface */
579 efi_pxe_udp_close ( pxe, 0 );
580}
581
582/** UDP close process descriptor */
585
586/******************************************************************************
587 *
588 * Fake DHCP packets
589 *
590 ******************************************************************************
591 */
592
593/**
594 * Name fake DHCP packet
595 *
596 * @v pxe PXE base code
597 * @v packet Packet
598 * @ret name Name of packet
599 */
600static const char * efi_pxe_fake_name ( struct efi_pxe *pxe,
601 EFI_PXE_BASE_CODE_PACKET *packet ) {
603
604 if ( packet == &mode->DhcpDiscover ) {
605 return "DhcpDiscover";
606 } else if ( packet == &mode->DhcpAck ) {
607 return "DhcpAck";
608 } else if ( packet == &mode->ProxyOffer ) {
609 return "ProxyOffer";
610 } else if ( packet == &mode->PxeDiscover ) {
611 return "PxeDiscover";
612 } else if ( packet == &mode->PxeReply ) {
613 return "PxeReply";
614 } else if ( packet == &mode->PxeBisReply ) {
615 return "PxeBisReply";
616 } else {
617 return "<UNKNOWN>";
618 }
619}
620
621/**
622 * Construct fake DHCP packet and flag
623 *
624 * @v pxe PXE base code
625 * @v fake Fake packet constructor
626 * @v packet Packet to fill in
627 * @ret exists Packet existence flag
628 */
629static BOOLEAN efi_pxe_fake ( struct efi_pxe *pxe,
630 int ( * fake ) ( struct net_device *netdev,
631 void *data, size_t len ),
632 EFI_PXE_BASE_CODE_PACKET *packet ) {
634 struct dhcp_packet dhcppkt;
635 struct dhcphdr *dhcphdr;
636 unsigned int len;
637 int rc;
638
639 /* The fake packet constructors do not support IPv6 */
640 if ( mode->UsingIpv6 )
641 return FALSE;
642
643 /* Attempt to construct packet */
644 if ( ( rc = fake ( pxe->netdev, packet, sizeof ( *packet ) ) != 0 ) ) {
645 DBGC ( pxe, "PXE %s could not fake %s: %s\n", pxe->name,
646 efi_pxe_fake_name ( pxe, packet ), strerror ( rc ) );
647 return FALSE;
648 }
649
650 /* The WDS bootstrap wdsmgfw.efi has a buggy DHCPv4 packet
651 * parser which does not correctly handle DHCP padding bytes.
652 * Specifically, if a padding byte (i.e. a zero) is
653 * encountered, the parse will first increment the pointer by
654 * one to skip over the padding byte but will then drop into
655 * the code path for handling normal options, which increments
656 * the pointer by two to skip over the (already-skipped) type
657 * field and the (non-existent) length field.
658 *
659 * The upshot of this bug in WDS is that the parser will fail
660 * with an error 0xc0000023 if the number of spare bytes after
661 * the end of the options is not an exact multiple of three.
662 *
663 * Work around this buggy parser by adding an explicit
664 * DHCP_END tag.
665 */
667 struct dhcphdr, op );
668 dhcppkt_init ( &dhcppkt, dhcphdr, sizeof ( *packet ) );
669 len = dhcppkt_len ( &dhcppkt );
670 if ( len < sizeof ( *packet ) )
671 packet->Raw[len] = DHCP_END;
672
673 return TRUE;
674}
675
676/**
677 * Construct fake DHCP packets
678 *
679 * @v pxe PXE base code
680 */
681static void efi_pxe_fake_all ( struct efi_pxe *pxe ) {
683
684 /* Construct fake packets */
685 mode->DhcpDiscoverValid =
687 &mode->DhcpDiscover );
688 mode->DhcpAckReceived =
690 &mode->DhcpAck );
691 mode->PxeReplyReceived =
693 &mode->PxeReply );
694}
695
696/******************************************************************************
697 *
698 * Base code protocol
699 *
700 ******************************************************************************
701 */
702
703/**
704 * Start PXE base code
705 *
706 * @v base PXE base code protocol
707 * @v use_ipv6 Use IPv6
708 * @ret efirc EFI status code
709 */
711 BOOLEAN use_ipv6 ) {
712 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
715 sa_family_t family = ( use_ipv6 ? AF_INET6 : AF_INET );
716 int rc;
717
718 DBGC ( pxe, "PXE %s START %s\n",
719 pxe->name, ( use_ipv6 ? "IPv6" : "IPv4" ) );
720
721 /* Initialise mode structure */
722 memset ( mode, 0, sizeof ( *mode ) );
723 mode->AutoArp = TRUE;
724 mode->TTL = DEFAULT_TTL;
725 mode->ToS = DEFAULT_ToS;
726 mode->IpFilter.Filters =
731
732 /* Check for IPv4/IPv6 support */
733 mode->Ipv6Supported = ( ipv6 != NULL );
734 mode->Ipv6Available = ( ipv6 != NULL );
735 pxe->tcpip = tcpip_net_protocol ( family );
736 if ( ! pxe->tcpip ) {
737 DBGC ( pxe, "PXE %s has no support for %s\n",
738 pxe->name, socket_family_name ( family ) );
739 return EFI_UNSUPPORTED;
740 }
741 pxe->net = pxe->tcpip->net_protocol;
742 mode->UsingIpv6 = use_ipv6;
743
744 /* Populate station IP address */
745 if ( ( rc = efi_pxe_ip ( pxe ) ) != 0 )
746 return rc;
747
748 /* Construct fake DHCP packets */
749 efi_pxe_fake_all ( pxe );
750
751 /* Record that base code is started */
752 mode->Started = TRUE;
753 DBGC ( pxe, "PXE %s using %s\n",
754 pxe->name, pxe->net->ntoa ( &mode->StationIp ) );
755
756 return 0;
757}
758
759/**
760 * Stop PXE base code
761 *
762 * @v base PXE base code protocol
763 * @ret efirc EFI status code
764 */
766 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
768
769 DBGC ( pxe, "PXE %s STOP\n", pxe->name );
770
771 /* Record that base code is stopped */
772 mode->Started = FALSE;
773
774 /* Close TFTP */
775 efi_pxe_tftp_close ( pxe, 0 );
776
777 /* Close UDP */
778 efi_pxe_udp_close ( pxe, 0 );
779
780 return 0;
781}
782
783/**
784 * Perform DHCP
785 *
786 * @v base PXE base code protocol
787 * @v sort Offers should be sorted
788 * @ret efirc EFI status code
789 */
791 BOOLEAN sort ) {
792 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
793 struct net_device *netdev = pxe->netdev;
794 int rc;
795
796 DBGC ( pxe, "PXE %s DHCP %s\n",
797 pxe->name, ( sort ? "sorted" : "unsorted" ) );
798
799 /* Claim network devices */
801
802 /* Initiate configuration */
803 if ( ( rc = netdev_configure_all ( netdev ) ) != 0 ) {
804 DBGC ( pxe, "PXE %s could not initiate configuration: %s\n",
805 pxe->name, strerror ( rc ) );
806 goto err_configure;
807 }
808
809 /* Wait for configuration to complete (or time out) */
811 step();
812
813 /* Report timeout if configuration failed */
814 if ( ! netdev_configuration_ok ( netdev ) ) {
815 rc = -ETIMEDOUT;
816 goto err_timeout;
817 }
818
819 /* Update station IP address */
820 if ( ( rc = efi_pxe_ip ( pxe ) ) != 0 )
821 goto err_ip;
822
823 /* Update faked DHCP packets */
824 efi_pxe_fake_all ( pxe );
825
826 err_ip:
827 err_timeout:
828 err_configure:
830 return EFIRC ( rc );
831}
832
833/**
834 * Perform boot server discovery
835 *
836 * @v base PXE base code protocol
837 * @v type Boot server type
838 * @v layer Boot server layer
839 * @v bis Use boot integrity services
840 * @v info Additional information
841 * @ret efirc EFI status code
842 */
843static EFI_STATUS EFIAPI
846 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
848 unsigned int i;
849
850 DBGC ( pxe, "PXE %s DISCOVER type %d layer %d%s\n",
851 pxe->name, type, *layer, ( bis ? " bis" : "" ) );
852 if ( info ) {
853 DBGC ( pxe, "%s%s%s%s %s",
854 ( info->UseMCast ? " mcast" : "" ),
855 ( info->UseBCast ? " bcast" : "" ),
856 ( info->UseUCast ? " ucast" : "" ),
857 ( info->MustUseList ? " list" : "" ),
858 efi_pxe_ip_ntoa ( pxe, &info->ServerMCastIp ) );
859 for ( i = 0 ; i < info->IpCnt ; i++ ) {
860 ip = &info->SrvList[i].IpAddr;
861 DBGC ( pxe, " %d%s:%s", info->SrvList[i].Type,
862 ( info->SrvList[i].AcceptAnyResponse ?
863 ":any" : "" ), efi_pxe_ip_ntoa ( pxe, ip ) );
864 }
865 }
866 DBGC ( pxe, "\n" );
867
868 /* Not used by any bootstrap I can find to test with */
869 return EFI_UNSUPPORTED;
870}
871
872/**
873 * Perform (M)TFTP
874 *
875 * @v base PXE base code protocol
876 * @v opcode TFTP opcode
877 * @v data Data buffer
878 * @v overwrite Overwrite file
879 * @v len Length of data buffer
880 * @v blksize Block size
881 * @v ip Server address
882 * @v filename Filename
883 * @v info Additional information
884 * @v callback Pass packets to callback instead of data buffer
885 * @ret efirc EFI status code
886 */
887static EFI_STATUS EFIAPI
891 EFI_IP_ADDRESS *ip, UINT8 *filename,
893 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
894 int rc;
895
896 DBGC ( pxe, "PXE %s MTFTP %d%s %p+%llx", pxe->name, opcode,
897 ( overwrite ? " overwrite" : "" ), data, *len );
898 if ( blksize )
899 DBGC ( pxe, " blksize %zd", ( ( size_t ) *blksize ) );
900 DBGC ( pxe, " %s:%s", efi_pxe_ip_ntoa ( pxe, ip ), filename );
901 if ( info ) {
902 DBGC ( pxe, " %s:%d:%d:%d:%d",
903 efi_pxe_ip_ntoa ( pxe, &info->MCastIp ),
904 info->CPort, info->SPort, info->ListenTimeout,
905 info->TransmitTimeout );
906 }
907 DBGC ( pxe, "%s\n", ( callback ? " callback" : "" ) );
908
909 /* Fail unless operation is supported */
912 DBGC ( pxe, "PXE %s unsupported MTFTP opcode %d\n",
913 pxe->name, opcode );
914 rc = -ENOTSUP;
915 goto err_opcode;
916 }
917
918 /* Claim network devices */
920
921 /* Determine block size. Ignore the requested block size
922 * unless we are using callbacks, since limiting HTTP to a
923 * 512-byte TCP window is not sensible.
924 */
925 pxe->blksize = ( ( callback && blksize ) ? *blksize : -1UL );
926
927 /* Initialise data transfer buffer */
928 xferbuf_fixed_init ( &pxe->buf, data, *len );
929
930 /* Open download */
931 if ( ( rc = efi_pxe_tftp_open ( pxe, ip,
932 ( ( const char * ) filename ) ) ) != 0 )
933 goto err_open;
934
935 /* Wait for download to complete */
936 pxe->rc = -EINPROGRESS;
937 while ( pxe->rc == -EINPROGRESS )
938 step();
939 if ( ( rc = pxe->rc ) != 0 ) {
940 DBGC ( pxe, "PXE %s download failed: %s\n",
941 pxe->name, strerror ( rc ) );
942 goto err_download;
943 }
944
945 err_download:
946 efi_pxe_tftp_close ( pxe, rc );
947 err_open:
948 xferbuf_fixed_init ( &pxe->buf, NULL, 0 );
950 err_opcode:
951 return EFIRC ( rc );
952}
953
954/**
955 * Transmit UDP packet
956 *
957 * @v base PXE base code protocol
958 * @v flags Operation flags
959 * @v dest_ip Destination address
960 * @v dest_port Destination port
961 * @v gateway Gateway address
962 * @v src_ip Source address
963 * @v src_port Source port
964 * @v hdr_len Header length
965 * @v hdr Header data
966 * @v len Length
967 * @v data Data
968 * @ret efirc EFI status code
969 */
970static EFI_STATUS EFIAPI
976 UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data ) {
977 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
979 struct io_buffer *iobuf;
980 struct xfer_metadata meta;
981 union {
982 struct sockaddr_tcpip st;
983 struct sockaddr sa;
984 } dest;
985 union {
986 struct sockaddr_tcpip st;
987 struct sockaddr sa;
988 } src;
989 int rc;
990
991 DBGC2 ( pxe, "PXE %s UDP WRITE ", pxe->name );
992 if ( src_ip )
993 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, src_ip ) );
994 DBGC2 ( pxe, ":" );
995 if ( src_port &&
997 DBGC2 ( pxe, "%d", *src_port );
998 } else {
999 DBGC2 ( pxe, "*" );
1000 }
1001 DBGC2 ( pxe, "->%s:%d", efi_pxe_ip_ntoa ( pxe, dest_ip ), *dest_port );
1002 if ( gateway )
1003 DBGC2 ( pxe, " via %s", efi_pxe_ip_ntoa ( pxe, gateway ) );
1004 if ( hdr_len )
1005 DBGC2 ( pxe, " %p+%zx", hdr, ( ( size_t ) *hdr_len ) );
1006 DBGC2 ( pxe, " %p+%zx", data, ( ( size_t ) *len ) );
1008 DBGC2 ( pxe, " frag" );
1009 DBGC2 ( pxe, "\n" );
1010
1011 /* Open UDP connection (if applicable) */
1012 if ( ( rc = efi_pxe_udp_open ( pxe ) ) != 0 )
1013 goto err_open;
1014
1015 /* Construct destination address */
1016 efi_pxe_ip_sockaddr ( pxe, dest_ip, &dest.sa );
1017 dest.st.st_port = htons ( *dest_port );
1018
1019 /* Construct source address */
1020 efi_pxe_ip_sockaddr ( pxe, ( src_ip ? src_ip : &mode->StationIp ),
1021 &src.sa );
1022 if ( src_port &&
1024 src.st.st_port = htons ( *src_port );
1025 } else {
1026 /* The API does not allow for a sensible concept of
1027 * binding to a local port, so just use a random value.
1028 */
1029 src.st.st_port = ( random() | htons ( 1024 ) );
1030 if ( src_port )
1031 *src_port = ntohs ( src.st.st_port );
1032 }
1033
1034 /* Allocate I/O buffer */
1035 iobuf = xfer_alloc_iob ( &pxe->udp,
1036 ( *len + ( hdr_len ? *hdr_len : 0 ) ) );
1037 if ( ! iobuf ) {
1038 rc = -ENOMEM;
1039 goto err_alloc;
1040 }
1041
1042 /* Populate I/O buffer */
1043 if ( hdr_len )
1044 memcpy ( iob_put ( iobuf, *hdr_len ), hdr, *hdr_len );
1045 memcpy ( iob_put ( iobuf, *len ), data, *len );
1046
1047 /* Construct metadata */
1048 memset ( &meta, 0, sizeof ( meta ) );
1049 meta.src = &src.sa;
1050 meta.dest = &dest.sa;
1051 meta.netdev = pxe->netdev;
1052
1053 /* Deliver I/O buffer */
1054 if ( ( rc = xfer_deliver ( &pxe->udp, iob_disown ( iobuf ),
1055 &meta ) ) != 0 ) {
1056 DBGC ( pxe, "PXE %s could not transmit: %s\n",
1057 pxe->name, strerror ( rc ) );
1058 goto err_deliver;
1059 }
1060
1061 err_deliver:
1062 free_iob ( iobuf );
1063 err_alloc:
1065 err_open:
1066 return EFIRC ( rc );
1067}
1068
1069/**
1070 * Receive UDP packet
1071 *
1072 * @v base PXE base code protocol
1073 * @v flags Operation flags
1074 * @v dest_ip Destination address
1075 * @v dest_port Destination port
1076 * @v src_ip Source address
1077 * @v src_port Source port
1078 * @v hdr_len Header length
1079 * @v hdr Header data
1080 * @v len Length
1081 * @v data Data
1082 * @ret efirc EFI status code
1083 */
1084static EFI_STATUS EFIAPI
1087 EFI_PXE_BASE_CODE_UDP_PORT *dest_port,
1090 UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data ) {
1091 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1092 struct io_buffer *iobuf;
1093 struct efi_pxe_udp_pseudo_header *pshdr;
1094 EFI_IP_ADDRESS *actual_dest_ip;
1095 EFI_IP_ADDRESS *actual_src_ip;
1096 size_t addr_len;
1097 size_t frag_len;
1098 int rc;
1099
1100 DBGC2 ( pxe, "PXE %s UDP READ ", pxe->name );
1102 DBGC2 ( pxe, "(filter)" );
1104 DBGC2 ( pxe, "*" );
1105 } else if ( dest_ip ) {
1106 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, dest_ip ) );
1107 }
1108 DBGC2 ( pxe, ":" );
1110 DBGC2 ( pxe, "*" );
1111 } else if ( dest_port ) {
1112 DBGC2 ( pxe, "%d", *dest_port );
1113 } else {
1114 DBGC2 ( pxe, "<NULL>" );
1115 }
1116 DBGC2 ( pxe, "<-" );
1118 DBGC2 ( pxe, "*" );
1119 } else if ( src_ip ) {
1120 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, src_ip ) );
1121 } else {
1122 DBGC2 ( pxe, "<NULL>" );
1123 }
1124 DBGC2 ( pxe, ":" );
1126 DBGC2 ( pxe, "*" );
1127 } else if ( src_port ) {
1128 DBGC2 ( pxe, "%d", *src_port );
1129 } else {
1130 DBGC2 ( pxe, "<NULL>" );
1131 }
1132 if ( hdr_len )
1133 DBGC2 ( pxe, " %p+%zx", hdr, ( ( size_t ) *hdr_len ) );
1134 DBGC2 ( pxe, " %p+%zx\n", data, ( ( size_t ) *len ) );
1135
1136 /* Open UDP connection (if applicable) */
1137 if ( ( rc = efi_pxe_udp_open ( pxe ) ) != 0 )
1138 goto err_open;
1139
1140 /* Try receiving a packet, if the queue is empty */
1141 if ( list_empty ( &pxe->queue ) )
1142 step();
1143
1144 /* Remove first packet from the queue */
1145 iobuf = list_first_entry ( &pxe->queue, struct io_buffer, list );
1146 if ( ! iobuf ) {
1147 rc = -ETIMEDOUT; /* "no packet" */
1148 goto err_empty;
1149 }
1150 list_del ( &iobuf->list );
1151
1152 /* Strip pseudo-header */
1153 pshdr = iobuf->data;
1154 addr_len = ( pshdr->net->net_addr_len );
1155 iob_pull ( iobuf, sizeof ( *pshdr ) );
1156 actual_dest_ip = iobuf->data;
1157 iob_pull ( iobuf, addr_len );
1158 actual_src_ip = iobuf->data;
1159 iob_pull ( iobuf, addr_len );
1160 DBGC2 ( pxe, "PXE %s UDP RX %s:%d", pxe->name,
1161 pshdr->net->ntoa ( actual_dest_ip ), pshdr->dest_port );
1162 DBGC2 ( pxe, "<-%s:%d len %#zx\n", pshdr->net->ntoa ( actual_src_ip ),
1163 pshdr->src_port, iob_len ( iobuf ) );
1164
1165 /* Filter based on network-layer protocol */
1166 if ( pshdr->net != pxe->net ) {
1167 DBGC2 ( pxe, "PXE %s filtered out %s packet\n",
1168 pxe->name, pshdr->net->name );
1169 rc = -ETIMEDOUT; /* "no packet" */
1170 goto err_filter;
1171 }
1172
1173 /* Filter based on port numbers */
1175 ( dest_port && ( *dest_port == pshdr->dest_port ) ) ) ) {
1176 DBGC2 ( pxe, "PXE %s filtered out destination port %d\n",
1177 pxe->name, pshdr->dest_port );
1178 rc = -ETIMEDOUT; /* "no packet" */
1179 goto err_filter;
1180 }
1182 ( src_port && ( *src_port == pshdr->src_port ) ) ) ) {
1183 DBGC2 ( pxe, "PXE %s filtered out source port %d\n",
1184 pxe->name, pshdr->src_port );
1185 rc = -ETIMEDOUT; /* "no packet" */
1186 goto err_filter;
1187 }
1188
1189 /* Filter based on source IP address */
1191 ( src_ip &&
1192 ( memcmp ( src_ip, actual_src_ip, addr_len ) == 0 ) ) ) ) {
1193 DBGC2 ( pxe, "PXE %s filtered out source IP %s\n",
1194 pxe->name, pshdr->net->ntoa ( actual_src_ip ) );
1195 rc = -ETIMEDOUT; /* "no packet" */
1196 goto err_filter;
1197 }
1198
1199 /* Filter based on destination IP address */
1201 efi_pxe_ip_filter ( pxe, actual_dest_ip ) ) ||
1204 ( dest_ip && ( memcmp ( dest_ip, actual_dest_ip,
1205 addr_len ) == 0 ) ) ) ) ) ) {
1206 DBGC2 ( pxe, "PXE %s filtered out destination IP %s\n",
1207 pxe->name, pshdr->net->ntoa ( actual_dest_ip ) );
1208 rc = -ETIMEDOUT; /* "no packet" */
1209 goto err_filter;
1210 }
1211
1212 /* Fill in addresses and port numbers */
1213 if ( dest_ip )
1214 memcpy ( dest_ip, actual_dest_ip, addr_len );
1215 if ( dest_port )
1216 *dest_port = pshdr->dest_port;
1217 if ( src_ip )
1218 memcpy ( src_ip, actual_src_ip, addr_len );
1219 if ( src_port )
1220 *src_port = pshdr->src_port;
1221
1222 /* Fill in header, if applicable */
1223 if ( hdr_len ) {
1224 frag_len = iob_len ( iobuf );
1225 if ( frag_len > *hdr_len )
1226 frag_len = *hdr_len;
1227 memcpy ( hdr, iobuf->data, frag_len );
1228 iob_pull ( iobuf, frag_len );
1229 *hdr_len = frag_len;
1230 }
1231
1232 /* Fill in data buffer */
1233 frag_len = iob_len ( iobuf );
1234 if ( frag_len > *len )
1235 frag_len = *len;
1236 memcpy ( data, iobuf->data, frag_len );
1237 iob_pull ( iobuf, frag_len );
1238 *len = frag_len;
1239
1240 /* Check for overflow */
1241 if ( iob_len ( iobuf ) ) {
1242 rc = -ERANGE;
1243 goto err_too_short;
1244 }
1245
1246 /* Success */
1247 rc = 0;
1248
1249 err_too_short:
1250 err_filter:
1251 free_iob ( iobuf );
1252 err_empty:
1254 err_open:
1255 return EFIRC ( rc );
1256}
1257
1258/**
1259 * Set receive filter
1260 *
1261 * @v base PXE base code protocol
1262 * @v filter Receive filter
1263 * @ret efirc EFI status code
1264 */
1265static EFI_STATUS EFIAPI
1268 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1270 unsigned int i;
1271
1272 DBGC ( pxe, "PXE %s SET IP FILTER %02x",
1273 pxe->name, filter->Filters );
1274 for ( i = 0 ; i < filter->IpCnt ; i++ ) {
1275 DBGC ( pxe, " %s",
1276 efi_pxe_ip_ntoa ( pxe, &filter->IpList[i] ) );
1277 }
1278 DBGC ( pxe, "\n" );
1279
1280 /* Update filter */
1281 memcpy ( &mode->IpFilter, filter, sizeof ( mode->IpFilter ) );
1282
1283 return 0;
1284}
1285
1286/**
1287 * Resolve MAC address
1288 *
1289 * @v base PXE base code protocol
1290 * @v ip IP address
1291 * @v mac MAC address to fill in
1292 * @ret efirc EFI status code
1293 */
1296 EFI_MAC_ADDRESS *mac ) {
1297 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1298
1299 DBGC ( pxe, "PXE %s ARP %s %p\n",
1300 pxe->name, efi_pxe_ip_ntoa ( pxe, ip ), mac );
1301
1302 /* Not used by any bootstrap I can find to test with */
1303 return EFI_UNSUPPORTED;
1304}
1305
1306/**
1307 * Set parameters
1308 *
1309 * @v base PXE base code protocol
1310 * @v autoarp Automatic ARP packet generation
1311 * @v sendguid Send GUID as client hardware address
1312 * @v ttl IP time to live
1313 * @v tos IP type of service
1314 * @v callback Make callbacks
1315 * @ret efirc EFI status code
1316 */
1317static EFI_STATUS EFIAPI
1319 BOOLEAN *autoarp, BOOLEAN *sendguid, UINT8 *ttl,
1320 UINT8 *tos, BOOLEAN *callback ) {
1321 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1323
1324 DBGC ( pxe, "PXE %s SET PARAMETERS", pxe->name );
1325 if ( autoarp )
1326 DBGC ( pxe, " %s", ( *autoarp ? "autoarp" : "noautoarp" ) );
1327 if ( sendguid )
1328 DBGC ( pxe, " %s", ( *sendguid ? "sendguid" : "sendmac" ) );
1329 if ( ttl )
1330 DBGC ( pxe, " ttl %d", *ttl );
1331 if ( tos )
1332 DBGC ( pxe, " tos %d", *tos );
1333 if ( callback ) {
1334 DBGC ( pxe, " %s",
1335 ( *callback ? "callback" : "nocallback" ) );
1336 }
1337 DBGC ( pxe, "\n" );
1338
1339 /* Update parameters */
1340 if ( autoarp )
1341 mode->AutoArp = *autoarp;
1342 if ( sendguid )
1343 mode->SendGUID = *sendguid;
1344 if ( ttl )
1345 mode->TTL = *ttl;
1346 if ( tos )
1347 mode->ToS = *tos;
1348 if ( callback )
1349 mode->MakeCallbacks = *callback;
1350
1351 return 0;
1352}
1353
1354/**
1355 * Set IP address
1356 *
1357 * @v base PXE base code protocol
1358 * @v ip IP address
1359 * @v netmask Subnet mask
1360 * @ret efirc EFI status code
1361 */
1362static EFI_STATUS EFIAPI
1364 EFI_IP_ADDRESS *ip, EFI_IP_ADDRESS *netmask ) {
1365 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1367
1368 DBGC ( pxe, "PXE %s SET STATION IP ", pxe->name );
1369 if ( ip )
1370 DBGC ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, ip ) );
1371 if ( netmask )
1372 DBGC ( pxe, "/%s", efi_pxe_ip_ntoa ( pxe, netmask ) );
1373 DBGC ( pxe, "\n" );
1374
1375 /* Update IP address and netmask */
1376 if ( ip )
1377 memcpy ( &mode->StationIp, ip, sizeof ( mode->StationIp ) );
1378 if ( netmask )
1379 memcpy ( &mode->SubnetMask, netmask, sizeof (mode->SubnetMask));
1380
1381 return 0;
1382}
1383
1384/**
1385 * Update cached DHCP packets
1386 *
1387 * @v base PXE base code protocol
1388 * @v dhcpdisc_ok DHCPDISCOVER is valid
1389 * @v dhcpack_ok DHCPACK received
1390 * @v proxyoffer_ok ProxyDHCPOFFER received
1391 * @v pxebsdisc_ok PxeBsDISCOVER valid
1392 * @v pxebsack_ok PxeBsACK received
1393 * @v pxebsbis_ok PxeBsBIS received
1394 * @v dhcpdisc DHCPDISCOVER packet
1395 * @v dhcpack DHCPACK packet
1396 * @v proxyoffer ProxyDHCPOFFER packet
1397 * @v pxebsdisc PxeBsDISCOVER packet
1398 * @v pxebsack PxeBsACK packet
1399 * @v pxebsbis PxeBsBIS packet
1400 * @ret efirc EFI status code
1401 */
1402static EFI_STATUS EFIAPI
1404 BOOLEAN *dhcpack_ok, BOOLEAN *proxyoffer_ok,
1405 BOOLEAN *pxebsdisc_ok, BOOLEAN *pxebsack_ok,
1406 BOOLEAN *pxebsbis_ok, EFI_PXE_BASE_CODE_PACKET *dhcpdisc,
1407 EFI_PXE_BASE_CODE_PACKET *dhcpack,
1408 EFI_PXE_BASE_CODE_PACKET *proxyoffer,
1409 EFI_PXE_BASE_CODE_PACKET *pxebsdisc,
1410 EFI_PXE_BASE_CODE_PACKET *pxebsack,
1411 EFI_PXE_BASE_CODE_PACKET *pxebsbis ) {
1412 struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
1414
1415 DBGC ( pxe, "PXE %s SET PACKETS\n", pxe->name );
1416
1417 /* Update fake packet flags */
1418 if ( dhcpdisc_ok )
1419 mode->DhcpDiscoverValid = *dhcpdisc_ok;
1420 if ( dhcpack_ok )
1421 mode->DhcpAckReceived = *dhcpack_ok;
1422 if ( proxyoffer_ok )
1423 mode->ProxyOfferReceived = *proxyoffer_ok;
1424 if ( pxebsdisc_ok )
1425 mode->PxeDiscoverValid = *pxebsdisc_ok;
1426 if ( pxebsack_ok )
1427 mode->PxeReplyReceived = *pxebsack_ok;
1428 if ( pxebsbis_ok )
1429 mode->PxeBisReplyReceived = *pxebsbis_ok;
1430
1431 /* Update fake packet contents */
1432 if ( dhcpdisc )
1433 memcpy ( &mode->DhcpDiscover, dhcpdisc, sizeof ( *dhcpdisc ) );
1434 if ( dhcpack )
1435 memcpy ( &mode->DhcpAck, dhcpack, sizeof ( *dhcpack ) );
1436 if ( proxyoffer )
1437 memcpy ( &mode->ProxyOffer, proxyoffer, sizeof ( *proxyoffer ));
1438 if ( pxebsdisc )
1439 memcpy ( &mode->PxeDiscover, pxebsdisc, sizeof ( *pxebsdisc ) );
1440 if ( pxebsack )
1441 memcpy ( &mode->PxeReply, pxebsack, sizeof ( *pxebsack ) );
1442 if ( pxebsbis )
1443 memcpy ( &mode->PxeBisReply, pxebsbis, sizeof ( *pxebsbis ) );
1444
1445 return 0;
1446}
1447
1448/** PXE base code protocol */
1451 .Start = efi_pxe_start,
1452 .Stop = efi_pxe_stop,
1453 .Dhcp = efi_pxe_dhcp,
1454 .Discover = efi_pxe_discover,
1455 .Mtftp = efi_pxe_mtftp,
1456 .UdpWrite = efi_pxe_udp_write,
1457 .UdpRead = efi_pxe_udp_read,
1458 .SetIpFilter = efi_pxe_set_ip_filter,
1459 .Arp = efi_pxe_arp,
1460 .SetParameters = efi_pxe_set_parameters,
1461 .SetStationIp = efi_pxe_set_station_ip,
1462 .SetPackets = efi_pxe_set_packets,
1463};
1464
1465/******************************************************************************
1466 *
1467 * Apple NetBoot protocol
1468 *
1469 ******************************************************************************
1470 */
1471
1472/**
1473 * Get DHCP/BSDP response
1474 *
1475 * @v packet Packet
1476 * @v len Length of data buffer
1477 * @v data Data buffer
1478 * @ret efirc EFI status code
1479 */
1480static EFI_STATUS EFIAPI
1482 VOID *data ) {
1483
1484 /* Check length */
1485 if ( *len < sizeof ( *packet ) ) {
1486 *len = sizeof ( *packet );
1487 return EFI_BUFFER_TOO_SMALL;
1488 }
1489
1490 /* Copy packet */
1491 memcpy ( data, packet, sizeof ( *packet ) );
1492 *len = sizeof ( *packet );
1493
1494 return EFI_SUCCESS;
1495}
1496
1497/**
1498 * Get DHCP response
1499 *
1500 * @v apple Apple NetBoot protocol
1501 * @v len Length of data buffer
1502 * @v data Data buffer
1503 * @ret efirc EFI status code
1504 */
1505static EFI_STATUS EFIAPI
1512
1513/**
1514 * Get BSDP response
1515 *
1516 * @v apple Apple NetBoot protocol
1517 * @v len Length of data buffer
1518 * @v data Data buffer
1519 * @ret efirc EFI status code
1520 */
1521static EFI_STATUS EFIAPI
1528
1529/** Apple NetBoot protocol */
1534
1535/******************************************************************************
1536 *
1537 * Installer
1538 *
1539 ******************************************************************************
1540 */
1541
1542/**
1543 * Install PXE base code protocol
1544 *
1545 * @v handle EFI handle
1546 * @v netdev Underlying network device
1547 * @ret rc Return status code
1548 */
1550 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1552 struct efi_pxe *pxe;
1553 struct in_addr ip;
1554 BOOLEAN use_ipv6;
1555 int leak = 0;
1556 EFI_STATUS efirc;
1557 int rc;
1558
1559 /* Allocate and initialise structure */
1560 pxe = zalloc ( sizeof ( *pxe ) );
1561 if ( ! pxe ) {
1562 rc = -ENOMEM;
1563 goto err_alloc;
1564 }
1565 ref_init ( &pxe->refcnt, efi_pxe_free );
1566 pxe->netdev = netdev_get ( netdev );
1567 pxe->name = netdev->name;
1568 pxe->handle = handle;
1569 memcpy ( &pxe->base, &efi_pxe_base_code_protocol, sizeof ( pxe->base ));
1570 pxe->base.Mode = &pxe->mode;
1572 sizeof ( pxe->apple ) );
1573 intf_init ( &pxe->tftp, &efi_pxe_tftp_desc, &pxe->refcnt );
1574 intf_init ( &pxe->udp, &efi_pxe_udp_desc, &pxe->refcnt );
1575 INIT_LIST_HEAD ( &pxe->queue );
1577 &pxe->refcnt );
1578
1579 /* Crude heuristic: assume that we prefer to use IPv4 if we
1580 * have an IPv4 address for the network device, otherwise
1581 * prefer IPv6 (if available).
1582 */
1584 use_ipv6 = ( ip.s_addr ? FALSE : ( ipv6 != NULL ) );
1585
1586 /* Start base code */
1587 efi_pxe_start ( &pxe->base, use_ipv6 );
1588
1589 /* Install PXE base code protocol */
1590 if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1591 &handle,
1594 NULL ) ) != 0 ) {
1595 rc = -EEFI ( efirc );
1596 DBGC ( pxe, "PXE %s could not install base code protocol: %s\n",
1597 pxe->name, strerror ( rc ) );
1598 goto err_install_protocol;
1599 }
1600
1601 /* Transfer reference to list and return */
1602 list_add_tail ( &pxe->list, &efi_pxes );
1603 DBGC ( pxe, "PXE %s installed for %s\n",
1604 pxe->name, efi_handle_name ( handle ) );
1605 return 0;
1606
1607 if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1608 handle,
1611 NULL ) ) != 0 ) {
1612 DBGC ( pxe, "PXE %s could not uninstall: %s\n",
1613 pxe->name, strerror ( -EEFI ( efirc ) ) );
1614 leak = 1;
1615 }
1616 efi_nullify_pxe ( &pxe->base );
1617 efi_nullify_apple ( &pxe->apple );
1618 err_install_protocol:
1619 if ( ! leak )
1620 ref_put ( &pxe->refcnt );
1621 err_alloc:
1622 if ( leak )
1623 DBGC ( pxe, "PXE %s nullified and leaked\n", pxe->name );
1624 return rc;
1625}
1626
1627/**
1628 * Uninstall PXE base code protocol
1629 *
1630 * @v handle EFI handle
1631 */
1633 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1634 struct efi_pxe *pxe;
1635 int leak = efi_shutdown_in_progress;
1636 EFI_STATUS efirc;
1637
1638 /* Locate PXE base code */
1639 pxe = efi_pxe_find ( handle );
1640 if ( ! pxe ) {
1641 DBG ( "PXE could not find base code for %s\n",
1642 efi_handle_name ( handle ) );
1643 return;
1644 }
1645
1646 /* Stop base code */
1647 efi_pxe_stop ( &pxe->base );
1648
1649 /* Uninstall PXE base code protocol */
1650 if ( ( ! efi_shutdown_in_progress ) &&
1651 ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
1652 handle,
1655 NULL ) ) != 0 ) ) {
1656 DBGC ( pxe, "PXE %s could not uninstall: %s\n",
1657 pxe->name, strerror ( -EEFI ( efirc ) ) );
1658 leak = 1;
1659 }
1660 efi_nullify_pxe ( &pxe->base );
1661 efi_nullify_apple ( &pxe->apple );
1662
1663 /* Remove from list and drop list's reference */
1664 list_del ( &pxe->list );
1665 if ( ! leak )
1666 ref_put ( &pxe->refcnt );
1667
1668 /* Report leakage, if applicable */
1669 if ( leak && ( ! efi_shutdown_in_progress ) )
1670 DBGC ( pxe, "PXE %s nullified and leaked\n", pxe->name );
1671}
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_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
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:225
void efi_pxe_uninstall(EFI_HANDLE handle)
Uninstall PXE base code protocol.
Definition efi_pxe.c:1632
static struct interface_descriptor efi_pxe_udp_desc
PXE UDP interface descriptor.
Definition efi_pxe.c:523
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:888
static struct interface_operation efi_pxe_udp_operations[]
PXE UDP interface operations.
Definition efi_pxe.c:517
static EFI_STATUS EFIAPI efi_pxe_dhcp(EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN sort)
Perform DHCP.
Definition efi_pxe.c:790
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:1481
static struct interface_descriptor efi_pxe_tftp_desc
PXE file data transfer interface descriptor.
Definition efi_pxe.c:374
static int efi_pxe_udp_open(struct efi_pxe *pxe)
Open UDP interface.
Definition efi_pxe.c:532
static EFI_STATUS EFIAPI efi_pxe_stop(EFI_PXE_BASE_CODE_PROTOCOL *base)
Stop PXE base code.
Definition efi_pxe.c:765
static void efi_pxe_free(struct refcnt *refcnt)
Free PXE base code.
Definition efi_pxe.c:117
static EFI_PXE_BASE_CODE_PROTOCOL efi_pxe_base_code_protocol
PXE base code protocol.
Definition efi_pxe.c:1449
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:1266
static void efi_pxe_fake_all(struct efi_pxe *pxe)
Construct fake DHCP packets.
Definition efi_pxe.c:681
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:971
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:1522
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:466
static struct efi_pxe * efi_pxe_find(EFI_HANDLE handle)
Locate PXE base code.
Definition efi_pxe.c:133
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:600
static void efi_pxe_udp_close(struct efi_pxe *pxe, int rc)
Close UDP interface.
Definition efi_pxe.c:437
static void efi_pxe_tftp_close(struct efi_pxe *pxe, int rc)
Close PXE (M)TFTP download interface.
Definition efi_pxe.c:320
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:1403
static EFI_STATUS EFIAPI efi_pxe_start(EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN use_ipv6)
Start PXE base code.
Definition efi_pxe.c:710
static int efi_pxe_ip_filter(struct efi_pxe *pxe, EFI_IP_ADDRESS *ip)
Check if IP address matches filter.
Definition efi_pxe.c:258
static struct interface_operation efi_pxe_tftp_operations[]
PXE file data transfer interface operations.
Definition efi_pxe.c:367
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:192
static struct process_descriptor efi_pxe_process_desc
UDP close process descriptor.
Definition efi_pxe.c:583
static size_t efi_pxe_tftp_window(struct efi_pxe *pxe)
Check PXE (M)TFTP download flow control window.
Definition efi_pxe.c:335
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:1363
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:349
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:844
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:1506
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:213
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:1294
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:629
static void efi_pxe_udp_schedule_close(struct efi_pxe *pxe)
Schedule close of UDP interface.
Definition efi_pxe.c:559
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:1318
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:385
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:1085
static void efi_pxe_udp_scheduled_close(struct efi_pxe *pxe)
Scheduled close of UDP interface.
Definition efi_pxe.c:576
static EFI_APPLE_NET_BOOT_PROTOCOL efi_apple_net_boot_protocol
Apple NetBoot protocol.
Definition efi_pxe.c:1530
int efi_pxe_install(EFI_HANDLE handle, struct net_device *netdev)
Install PXE base code protocol.
Definition efi_pxe.c:1549
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:167
#define EFI_HANDLE
Definition efi.h:53
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:175
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:1336
int netdev_configuration_ok(struct net_device *netdev)
Check if network device has at least one successful configuration.
Definition netdevice.c:1392
int netdev_configuration_in_progress(struct net_device *netdev)
Check if network device configuration is in progress.
Definition netdevice.c:1380
Network device management.
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:565
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:587
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:422
struct net_protocol * net
Network-layer protocol.
Definition efi_pxe.c:424
uint16_t src_port
Source port.
Definition efi_pxe.c:428
uint16_t dest_port
Destination port.
Definition efi_pxe.c:426
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:100
struct interface udp
UDP interface.
Definition efi_pxe.c:105
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:107
struct interface tftp
(M)TFTP download interface
Definition efi_pxe.c:98
int rc
Overall return status.
Definition efi_pxe.c:102
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:109
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:156
sa_family_t se_family
Socket address family (part of struct sockaddr)
Definition efi_pxe.c:158
uint16_t se_flags
Flags (part of struct sockaddr_tcpip)
Definition efi_pxe.c:160
uint16_t se_scope_id
Scope ID (part of struct sockaddr_tcpip)
Definition efi_pxe.c:168
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:182
uint16_t se_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition efi_pxe.c:162
EFI_IP_ADDRESS se_addr
IP address.
Definition efi_pxe.c:170
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
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
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:175
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:81