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