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