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