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