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