iPXE
efi_pxe.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <string.h>
00027 #include <errno.h>
00028 #include <ipxe/refcnt.h>
00029 #include <ipxe/list.h>
00030 #include <ipxe/netdevice.h>
00031 #include <ipxe/fakedhcp.h>
00032 #include <ipxe/process.h>
00033 #include <ipxe/uri.h>
00034 #include <ipxe/in.h>
00035 #include <ipxe/socket.h>
00036 #include <ipxe/tcpip.h>
00037 #include <ipxe/xferbuf.h>
00038 #include <ipxe/open.h>
00039 #include <ipxe/dhcppkt.h>
00040 #include <ipxe/udp.h>
00041 #include <ipxe/efi/efi.h>
00042 #include <ipxe/efi/efi_snp.h>
00043 #include <ipxe/efi/efi_pxe.h>
00044 #include <ipxe/efi/Protocol/PxeBaseCode.h>
00045 #include <ipxe/efi/Protocol/AppleNetBoot.h>
00046 #include <usr/ifmgmt.h>
00047 #include <config/general.h>
00048 
00049 /** @file
00050  *
00051  * EFI PXE base code protocol
00052  *
00053  */
00054 
00055 /* Downgrade user experience if configured to do so
00056  *
00057  * See comments in efi_snp.c
00058  */
00059 #ifdef EFI_DOWNGRADE_UX
00060 static EFI_GUID dummy_pxe_base_code_protocol_guid = {
00061         0x70647523, 0x2320, 0x7477,
00062         { 0x66, 0x20, 0x23, 0x6d, 0x6f, 0x72, 0x6f, 0x6e }
00063 };
00064 #define efi_pxe_base_code_protocol_guid dummy_pxe_base_code_protocol_guid
00065 #endif
00066 
00067 /** A PXE base code */
00068 struct efi_pxe {
00069         /** Reference count */
00070         struct refcnt refcnt;
00071         /** Underlying network device */
00072         struct net_device *netdev;
00073         /** Name */
00074         const char *name;
00075         /** List of PXE base codes */
00076         struct list_head list;
00077 
00078         /** Installed handle */
00079         EFI_HANDLE handle;
00080         /** PXE base code protocol */
00081         EFI_PXE_BASE_CODE_PROTOCOL base;
00082         /** PXE base code mode */
00083         EFI_PXE_BASE_CODE_MODE mode;
00084         /** Apple NetBoot protocol */
00085         EFI_APPLE_NET_BOOT_PROTOCOL apple;
00086 
00087         /** TCP/IP network-layer protocol */
00088         struct tcpip_net_protocol *tcpip;
00089         /** Network-layer protocol */
00090         struct net_protocol *net;
00091 
00092         /** Data transfer buffer */
00093         struct xfer_buffer buf;
00094 
00095         /** (M)TFTP download interface */
00096         struct interface tftp;
00097         /** Block size (for TFTP) */
00098         size_t blksize;
00099         /** Overall return status */
00100         int rc;
00101 
00102         /** UDP interface */
00103         struct interface udp;
00104         /** List of received UDP packets */
00105         struct list_head queue;
00106         /** UDP interface closer process */
00107         struct process process;
00108 };
00109 
00110 /**
00111  * Free PXE base code
00112  *
00113  * @v refcnt            Reference count
00114  */
00115 static void efi_pxe_free ( struct refcnt *refcnt ) {
00116         struct efi_pxe *pxe = container_of ( refcnt, struct efi_pxe, refcnt );
00117 
00118         netdev_put ( pxe->netdev );
00119         free ( pxe );
00120 }
00121 
00122 /** List of PXE base codes */
00123 static LIST_HEAD ( efi_pxes );
00124 
00125 /**
00126  * Locate PXE base code
00127  *
00128  * @v handle            EFI handle
00129  * @ret pxe             PXE base code, or NULL
00130  */
00131 static struct efi_pxe * efi_pxe_find ( EFI_HANDLE handle ) {
00132         struct efi_pxe *pxe;
00133 
00134         /* Locate base code */
00135         list_for_each_entry ( pxe, &efi_pxes, list ) {
00136                 if ( pxe->handle == handle )
00137                         return pxe;
00138         }
00139 
00140         return NULL;
00141 }
00142 
00143 /******************************************************************************
00144  *
00145  * IP addresses
00146  *
00147  ******************************************************************************
00148  */
00149 
00150 /**
00151  * An EFI socket address
00152  *
00153  */
00154 struct sockaddr_efi {
00155         /** Socket address family (part of struct @c sockaddr) */
00156         sa_family_t se_family;
00157         /** Flags (part of struct @c sockaddr_tcpip) */
00158         uint16_t se_flags;
00159         /** TCP/IP port (part of struct @c sockaddr_tcpip) */
00160         uint16_t se_port;
00161         /** Scope ID (part of struct @c sockaddr_tcpip)
00162          *
00163          * For link-local or multicast addresses, this is the network
00164          * device index.
00165          */
00166         uint16_t se_scope_id;
00167         /** IP address */
00168         EFI_IP_ADDRESS se_addr;
00169         /** Padding
00170          *
00171          * This ensures that a struct @c sockaddr_tcpip is large
00172          * enough to hold a socket address for any TCP/IP address
00173          * family.
00174          */
00175         char pad[ sizeof ( struct sockaddr ) -
00176                   ( sizeof ( sa_family_t ) /* se_family */ +
00177                     sizeof ( uint16_t ) /* se_flags */ +
00178                     sizeof ( uint16_t ) /* se_port */ +
00179                     sizeof ( uint16_t ) /* se_scope_id */ +
00180                     sizeof ( EFI_IP_ADDRESS ) /* se_addr */ ) ];
00181 } __attribute__ (( packed, may_alias ));
00182 
00183 /**
00184  * Populate socket address from EFI IP address
00185  *
00186  * @v pxe               PXE base code
00187  * @v ip                EFI IP address
00188  * @v sa                Socket address to fill in
00189  */
00190 static void efi_pxe_ip_sockaddr ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
00191                                   struct sockaddr *sa ) {
00192         union {
00193                 struct sockaddr sa;
00194                 struct sockaddr_efi se;
00195         } *sockaddr = container_of ( sa, typeof ( *sockaddr ), sa );
00196 
00197         /* Initialise socket address */
00198         memset ( sockaddr, 0, sizeof ( *sockaddr ) );
00199         sockaddr->sa.sa_family = pxe->tcpip->sa_family;
00200         memcpy ( &sockaddr->se.se_addr, ip, pxe->net->net_addr_len );
00201         sockaddr->se.se_scope_id = pxe->netdev->index;
00202 }
00203 
00204 /**
00205  * Transcribe EFI IP address (for debugging)
00206  *
00207  * @v pxe               PXE base code
00208  * @v ip                EFI IP address
00209  * @ret text            Transcribed IP address
00210  */
00211 static const char * efi_pxe_ip_ntoa ( struct efi_pxe *pxe,
00212                                       EFI_IP_ADDRESS *ip ) {
00213 
00214         return pxe->net->ntoa ( ip );
00215 }
00216 
00217 /**
00218  * Populate local IP address
00219  *
00220  * @v pxe               PXE base code
00221  * @ret rc              Return status code
00222  */
00223 static int efi_pxe_ip ( struct efi_pxe *pxe ) {
00224         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00225         struct in_addr address;
00226         struct in_addr netmask;
00227 
00228         /* It's unclear which of the potentially many IPv6 addresses
00229          * is supposed to be used.
00230          */
00231         if ( mode->UsingIpv6 )
00232                 return -ENOTSUP;
00233 
00234         /* Fetch IP address and subnet mask */
00235         fetch_ipv4_setting ( netdev_settings ( pxe->netdev ), &ip_setting,
00236                              &address );
00237         fetch_ipv4_setting ( netdev_settings ( pxe->netdev ), &netmask_setting,
00238                              &netmask );
00239 
00240         /* Populate IP address and subnet mask */
00241         memset ( &mode->StationIp, 0, sizeof ( mode->StationIp ) );
00242         memcpy ( &mode->StationIp, &address, sizeof ( address ) );
00243         memset ( &mode->SubnetMask, 0, sizeof ( mode->SubnetMask ) );
00244         memcpy ( &mode->SubnetMask, &netmask, sizeof ( netmask ) );
00245 
00246         return 0;
00247 }
00248 
00249 /**
00250  * Check if IP address matches filter
00251  *
00252  * @v pxe               PXE base code
00253  * @v ip                EFI IP address
00254  * @ret is_match        IP address matches filter
00255  */
00256 static int efi_pxe_ip_filter ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip ) {
00257         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00258         EFI_PXE_BASE_CODE_IP_FILTER *filter = &mode->IpFilter;
00259         uint8_t filters = filter->Filters;
00260         union {
00261                 EFI_IP_ADDRESS ip;
00262                 struct in_addr in;
00263                 struct in6_addr in6;
00264         } *u = container_of ( ip, typeof ( *u ), ip );
00265         size_t addr_len = pxe->net->net_addr_len;
00266         unsigned int i;
00267 
00268         /* Match everything, if applicable */
00269         if ( filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS )
00270                 return 1;
00271 
00272         /* Match all multicasts, if applicable */
00273         if ( filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST ) {
00274                 if ( mode->UsingIpv6 ) {
00275                         if ( IN6_IS_ADDR_MULTICAST ( &u->in6 ) )
00276                                 return 1;
00277                 } else {
00278                         if ( IN_IS_MULTICAST ( u->in.s_addr ) )
00279                                 return 1;
00280                 }
00281         }
00282 
00283         /* Match IPv4 broadcasts, if applicable */
00284         if ( filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST ) {
00285                 if ( ( ! mode->UsingIpv6 ) &&
00286                      ( u->in.s_addr == INADDR_BROADCAST ) )
00287                         return 1;
00288         }
00289 
00290         /* Match station address, if applicable */
00291         if ( filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP ) {
00292                 if ( memcmp ( ip, &mode->StationIp, addr_len ) == 0 )
00293                         return 1;
00294         }
00295 
00296         /* Match explicit addresses, if applicable */
00297         for ( i = 0 ; i < filter->IpCnt ; i++ ) {
00298                 if ( memcmp ( ip, &filter->IpList[i], addr_len ) == 0 )
00299                         return 1;
00300         }
00301 
00302         return 0;
00303 }
00304 
00305 /******************************************************************************
00306  *
00307  * Data transfer buffer
00308  *
00309  ******************************************************************************
00310  */
00311 
00312 /**
00313  * Reallocate PXE data transfer buffer
00314  *
00315  * @v xferbuf           Data transfer buffer
00316  * @v len               New length (or zero to free buffer)
00317  * @ret rc              Return status code
00318  */
00319 static int efi_pxe_buf_realloc ( struct xfer_buffer *xferbuf __unused,
00320                                  size_t len __unused ) {
00321 
00322         /* Can never reallocate: return EFI_BUFFER_TOO_SMALL */
00323         return -ERANGE;
00324 }
00325 
00326 /**
00327  * Write data to PXE data transfer buffer
00328  *
00329  * @v xferbuf           Data transfer buffer
00330  * @v offset            Starting offset
00331  * @v data              Data to copy
00332  * @v len               Length of data
00333  */
00334 static void efi_pxe_buf_write ( struct xfer_buffer *xferbuf, size_t offset,
00335                                 const void *data, size_t len ) {
00336 
00337         /* Copy data to buffer */
00338         memcpy ( ( xferbuf->data + offset ), data, len );
00339 }
00340 
00341 /** PXE data transfer buffer operations */
00342 static struct xfer_buffer_operations efi_pxe_buf_operations = {
00343         .realloc = efi_pxe_buf_realloc,
00344         .write = efi_pxe_buf_write,
00345 };
00346 
00347 /******************************************************************************
00348  *
00349  * (M)TFTP download interface
00350  *
00351  ******************************************************************************
00352  */
00353 
00354 /**
00355  * Close PXE (M)TFTP download interface
00356  *
00357  * @v pxe               PXE base code
00358  * @v rc                Reason for close
00359  */
00360 static void efi_pxe_tftp_close ( struct efi_pxe *pxe, int rc ) {
00361 
00362         /* Restart interface */
00363         intf_restart ( &pxe->tftp, rc );
00364 
00365         /* Record overall status */
00366         pxe->rc = rc;
00367 }
00368 
00369 /**
00370  * Check PXE (M)TFTP download flow control window
00371  *
00372  * @v pxe               PXE base code
00373  * @ret len             Length of window
00374  */
00375 static size_t efi_pxe_tftp_window ( struct efi_pxe *pxe ) {
00376 
00377         /* Return requested blocksize */
00378         return pxe->blksize;
00379 }
00380 
00381 /**
00382  * Receive new PXE (M)TFTP download data
00383  *
00384  * @v pxe               PXE base code
00385  * @v iobuf             I/O buffer
00386  * @v meta              Transfer metadata
00387  * @ret rc              Return status code
00388  */
00389 static int efi_pxe_tftp_deliver ( struct efi_pxe *pxe,
00390                                   struct io_buffer *iobuf,
00391                                   struct xfer_metadata *meta ) {
00392         int rc;
00393 
00394         /* Deliver to data transfer buffer */
00395         if ( ( rc = xferbuf_deliver ( &pxe->buf, iob_disown ( iobuf ),
00396                                       meta ) ) != 0 )
00397                 goto err_deliver;
00398 
00399         return 0;
00400 
00401  err_deliver:
00402         efi_pxe_tftp_close ( pxe, rc );
00403         return rc;
00404 }
00405 
00406 /** PXE file data transfer interface operations */
00407 static struct interface_operation efi_pxe_tftp_operations[] = {
00408         INTF_OP ( xfer_deliver, struct efi_pxe *, efi_pxe_tftp_deliver ),
00409         INTF_OP ( xfer_window, struct efi_pxe *, efi_pxe_tftp_window ),
00410         INTF_OP ( intf_close, struct efi_pxe *, efi_pxe_tftp_close ),
00411 };
00412 
00413 /** PXE file data transfer interface descriptor */
00414 static struct interface_descriptor efi_pxe_tftp_desc =
00415         INTF_DESC ( struct efi_pxe, tftp, efi_pxe_tftp_operations );
00416 
00417 /**
00418  * Open (M)TFTP download interface
00419  *
00420  * @v pxe               PXE base code
00421  * @v ip                EFI IP address
00422  * @v filename          Filename
00423  * @ret rc              Return status code
00424  */
00425 static int efi_pxe_tftp_open ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip,
00426                                const char *filename ) {
00427         struct sockaddr server;
00428         struct uri *uri;
00429         int rc;
00430 
00431         /* Parse server address and filename */
00432         efi_pxe_ip_sockaddr ( pxe, ip, &server );
00433         uri = pxe_uri ( &server, filename );
00434         if ( ! uri ) {
00435                 DBGC ( pxe, "PXE %s could not parse %s:%s\n", pxe->name,
00436                        efi_pxe_ip_ntoa ( pxe, ip ), filename );
00437                 rc = -ENOTSUP;
00438                 goto err_parse;
00439         }
00440 
00441         /* Open URI */
00442         if ( ( rc = xfer_open_uri ( &pxe->tftp, uri ) ) != 0 ) {
00443                 DBGC ( pxe, "PXE %s could not open: %s\n",
00444                        pxe->name, strerror ( rc ) );
00445                 goto err_open;
00446         }
00447 
00448  err_open:
00449         uri_put ( uri );
00450  err_parse:
00451         return rc;
00452 }
00453 
00454 /******************************************************************************
00455  *
00456  * UDP interface
00457  *
00458  ******************************************************************************
00459  */
00460 
00461 /** EFI UDP pseudo-header */
00462 struct efi_pxe_udp_pseudo_header {
00463         /** Network-layer protocol */
00464         struct net_protocol *net;
00465         /** Destination port */
00466         uint16_t dest_port;
00467         /** Source port */
00468         uint16_t src_port;
00469 } __attribute__ (( packed ));
00470 
00471 /**
00472  * Close UDP interface
00473  *
00474  * @v pxe               PXE base code
00475  * @v rc                Reason for close
00476  */
00477 static void efi_pxe_udp_close ( struct efi_pxe *pxe, int rc ) {
00478         struct io_buffer *iobuf;
00479         struct io_buffer *tmp;
00480 
00481         /* Release our claim on SNP devices, if applicable */
00482         if ( process_running ( &pxe->process ) )
00483                 efi_snp_release();
00484 
00485         /* Stop process */
00486         process_del ( &pxe->process );
00487 
00488         /* Restart UDP interface */
00489         intf_restart ( &pxe->udp, rc );
00490 
00491         /* Flush any received UDP packets */
00492         list_for_each_entry_safe ( iobuf, tmp, &pxe->queue, list ) {
00493                 list_del ( &iobuf->list );
00494                 free_iob ( iobuf );
00495         }
00496 }
00497 
00498 /**
00499  * Receive UDP packet
00500  *
00501  * @v pxe               PXE base code
00502  * @v iobuf             I/O buffer
00503  * @v meta              Data transfer metadata
00504  * @ret rc              Return status code
00505  */
00506 static int efi_pxe_udp_deliver ( struct efi_pxe *pxe, struct io_buffer *iobuf,
00507                                  struct xfer_metadata *meta ) {
00508         struct sockaddr_efi *se_src;
00509         struct sockaddr_efi *se_dest;
00510         struct tcpip_net_protocol *tcpip;
00511         struct net_protocol *net;
00512         struct efi_pxe_udp_pseudo_header *pshdr;
00513         size_t addr_len;
00514         size_t pshdr_len;
00515         int rc;
00516 
00517         /* Sanity checks */
00518         assert ( meta != NULL );
00519         se_src = ( ( struct sockaddr_efi * ) meta->src );
00520         assert ( se_src != NULL );
00521         se_dest = ( ( struct sockaddr_efi * ) meta->dest );
00522         assert ( se_dest != NULL );
00523         assert ( se_src->se_family == se_dest->se_family );
00524 
00525         /* Determine protocol */
00526         tcpip = tcpip_net_protocol ( se_src->se_family );
00527         if ( ! tcpip ) {
00528                 rc = -ENOTSUP;
00529                 goto err_unsupported;
00530         }
00531         net = tcpip->net_protocol;
00532         addr_len = net->net_addr_len;
00533 
00534         /* Construct pseudo-header */
00535         pshdr_len = ( sizeof ( *pshdr ) + ( 2 * addr_len ) );
00536         if ( ( rc = iob_ensure_headroom ( iobuf, pshdr_len ) ) != 0 )
00537                 goto err_headroom;
00538         memcpy ( iob_push ( iobuf, addr_len ), &se_src->se_addr, addr_len );
00539         memcpy ( iob_push ( iobuf, addr_len ), &se_dest->se_addr, addr_len );
00540         pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
00541         pshdr->net = net;
00542         pshdr->dest_port = ntohs ( se_dest->se_port );
00543         pshdr->src_port = ntohs ( se_src->se_port );
00544 
00545         /* Add to queue */
00546         list_add_tail ( &iobuf->list, &pxe->queue );
00547 
00548         return 0;
00549 
00550  err_unsupported:
00551  err_headroom:
00552         free_iob ( iobuf );
00553         return rc;
00554 }
00555 
00556 /** PXE UDP interface operations */
00557 static struct interface_operation efi_pxe_udp_operations[] = {
00558         INTF_OP ( xfer_deliver, struct efi_pxe *, efi_pxe_udp_deliver ),
00559         INTF_OP ( intf_close, struct efi_pxe *, efi_pxe_udp_close ),
00560 };
00561 
00562 /** PXE UDP interface descriptor */
00563 static struct interface_descriptor efi_pxe_udp_desc =
00564         INTF_DESC ( struct efi_pxe, udp, efi_pxe_udp_operations );
00565 
00566 /**
00567  * Open UDP interface
00568  *
00569  * @v pxe               PXE base code
00570  * @ret rc              Return status code
00571  */
00572 static int efi_pxe_udp_open ( struct efi_pxe *pxe ) {
00573         int rc;
00574 
00575         /* If interface is already open, then cancel the scheduled close */
00576         if ( process_running ( &pxe->process ) ) {
00577                 process_del ( &pxe->process );
00578                 return 0;
00579         }
00580 
00581         /* Open promiscuous UDP interface */
00582         if ( ( rc = udp_open_promisc ( &pxe->udp ) ) != 0 ) {
00583                 DBGC ( pxe, "PXE %s could not open UDP connection: %s\n",
00584                        pxe->name, strerror ( rc ) );
00585                 return rc;
00586         }
00587 
00588         /* Claim network devices */
00589         efi_snp_claim();
00590 
00591         return 0;
00592 }
00593 
00594 /**
00595  * Schedule close of UDP interface
00596  *
00597  * @v pxe               PXE base code
00598  */
00599 static void efi_pxe_udp_schedule_close ( struct efi_pxe *pxe ) {
00600 
00601         /* The EFI PXE base code protocol does not provide any
00602          * explicit UDP open/close methods.  To avoid the overhead of
00603          * reopening a socket for each read/write operation, we start
00604          * a process which will close the socket immediately if the
00605          * next call into iPXE is anything other than a UDP
00606          * read/write.
00607          */
00608         process_add ( &pxe->process );
00609 }
00610 
00611 /**
00612  * Scheduled close of UDP interface
00613  *
00614  * @v pxe               PXE base code
00615  */
00616 static void efi_pxe_udp_scheduled_close ( struct efi_pxe *pxe ) {
00617 
00618         /* Close UDP interface */
00619         efi_pxe_udp_close ( pxe, 0 );
00620 }
00621 
00622 /** UDP close process descriptor */
00623 static struct process_descriptor efi_pxe_process_desc =
00624         PROC_DESC_ONCE ( struct efi_pxe, process, efi_pxe_udp_scheduled_close );
00625 
00626 /******************************************************************************
00627  *
00628  * Fake DHCP packets
00629  *
00630  ******************************************************************************
00631  */
00632 
00633 /**
00634  * Name fake DHCP packet
00635  *
00636  * @v pxe               PXE base code
00637  * @v packet            Packet
00638  * @ret name            Name of packet
00639  */
00640 static const char * efi_pxe_fake_name ( struct efi_pxe *pxe,
00641                                         EFI_PXE_BASE_CODE_PACKET *packet ) {
00642         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00643 
00644         if ( packet == &mode->DhcpDiscover ) {
00645                 return "DhcpDiscover";
00646         } else if ( packet == &mode->DhcpAck ) {
00647                 return "DhcpAck";
00648         } else if ( packet == &mode->ProxyOffer ) {
00649                 return "ProxyOffer";
00650         } else if ( packet == &mode->PxeDiscover ) {
00651                 return "PxeDiscover";
00652         } else if ( packet == &mode->PxeReply ) {
00653                 return "PxeReply";
00654         } else if ( packet == &mode->PxeBisReply ) {
00655                 return "PxeBisReply";
00656         } else {
00657                 return "<UNKNOWN>";
00658         }
00659 }
00660 
00661 /**
00662  * Construct fake DHCP packet and flag
00663  *
00664  * @v pxe               PXE base code
00665  * @v fake              Fake packet constructor
00666  * @v packet            Packet to fill in
00667  * @ret exists          Packet existence flag
00668  */
00669 static BOOLEAN efi_pxe_fake ( struct efi_pxe *pxe,
00670                               int ( * fake ) ( struct net_device *netdev,
00671                                                void *data, size_t len ),
00672                               EFI_PXE_BASE_CODE_PACKET *packet ) {
00673         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00674         struct dhcp_packet dhcppkt;
00675         struct dhcphdr *dhcphdr;
00676         unsigned int len;
00677         int rc;
00678 
00679         /* The fake packet constructors do not support IPv6 */
00680         if ( mode->UsingIpv6 )
00681                 return FALSE;
00682 
00683         /* Attempt to construct packet */
00684         if ( ( rc = fake ( pxe->netdev, packet, sizeof ( *packet ) ) != 0 ) ) {
00685                 DBGC ( pxe, "PXE %s could not fake %s: %s\n", pxe->name,
00686                        efi_pxe_fake_name ( pxe, packet ), strerror ( rc ) );
00687                 return FALSE;
00688         }
00689 
00690         /* The WDS bootstrap wdsmgfw.efi has a buggy DHCPv4 packet
00691          * parser which does not correctly handle DHCP padding bytes.
00692          * Specifically, if a padding byte (i.e. a zero) is
00693          * encountered, the parse will first increment the pointer by
00694          * one to skip over the padding byte but will then drop into
00695          * the code path for handling normal options, which increments
00696          * the pointer by two to skip over the (already-skipped) type
00697          * field and the (non-existent) length field.
00698          *
00699          * The upshot of this bug in WDS is that the parser will fail
00700          * with an error 0xc0000023 if the number of spare bytes after
00701          * the end of the options is not an exact multiple of three.
00702          *
00703          * Work around this buggy parser by adding an explicit
00704          * DHCP_END tag.
00705          */
00706         dhcphdr = container_of ( &packet->Dhcpv4.BootpOpcode,
00707                                  struct dhcphdr, op );
00708         dhcppkt_init ( &dhcppkt, dhcphdr, sizeof ( *packet ) );
00709         len = dhcppkt_len ( &dhcppkt );
00710         if ( len < sizeof ( *packet ) )
00711                 packet->Raw[len] = DHCP_END;
00712 
00713         return TRUE;
00714 }
00715 
00716 /**
00717  * Construct fake DHCP packets
00718  *
00719  * @v pxe               PXE base code
00720  */
00721 static void efi_pxe_fake_all ( struct efi_pxe *pxe ) {
00722         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00723 
00724         /* Construct fake packets */
00725         mode->DhcpDiscoverValid =
00726                 efi_pxe_fake ( pxe, create_fakedhcpdiscover,
00727                                &mode->DhcpDiscover );
00728         mode->DhcpAckReceived =
00729                 efi_pxe_fake ( pxe, create_fakedhcpack,
00730                                &mode->DhcpAck );
00731         mode->PxeReplyReceived =
00732                 efi_pxe_fake ( pxe, create_fakepxebsack,
00733                                &mode->PxeReply );
00734 }
00735 
00736 /******************************************************************************
00737  *
00738  * Base code protocol
00739  *
00740  ******************************************************************************
00741  */
00742 
00743 /**
00744  * Start PXE base code
00745  *
00746  * @v base              PXE base code protocol
00747  * @v use_ipv6          Use IPv6
00748  * @ret efirc           EFI status code
00749  */
00750 static EFI_STATUS EFIAPI efi_pxe_start ( EFI_PXE_BASE_CODE_PROTOCOL *base,
00751                                          BOOLEAN use_ipv6 ) {
00752         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
00753         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00754         struct tcpip_net_protocol *ipv6 = tcpip_net_protocol ( AF_INET6 );
00755         sa_family_t family = ( use_ipv6 ? AF_INET6 : AF_INET );
00756         int rc;
00757 
00758         DBGC ( pxe, "PXE %s START %s\n", pxe->name, ( ipv6 ? "IPv6" : "IPv4" ));
00759 
00760         /* Initialise mode structure */
00761         memset ( mode, 0, sizeof ( *mode ) );
00762         mode->AutoArp = TRUE;
00763         mode->TTL = DEFAULT_TTL;
00764         mode->ToS = DEFAULT_ToS;
00765         mode->IpFilter.Filters =
00766                 ( EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP |
00767                   EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST |
00768                   EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS |
00769                   EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST );
00770 
00771         /* Check for IPv4/IPv6 support */
00772         mode->Ipv6Supported = ( ipv6 != NULL );
00773         mode->Ipv6Available = ( ipv6 != NULL );
00774         pxe->tcpip = tcpip_net_protocol ( family );
00775         if ( ! pxe->tcpip ) {
00776                 DBGC ( pxe, "PXE %s has no support for %s\n",
00777                        pxe->name, socket_family_name ( family ) );
00778                 return EFI_UNSUPPORTED;
00779         }
00780         pxe->net = pxe->tcpip->net_protocol;
00781         mode->UsingIpv6 = use_ipv6;
00782 
00783         /* Populate station IP address */
00784         if ( ( rc = efi_pxe_ip ( pxe ) ) != 0 )
00785                 return rc;
00786 
00787         /* Construct fake DHCP packets */
00788         efi_pxe_fake_all ( pxe );
00789 
00790         /* Record that base code is started */
00791         mode->Started = TRUE;
00792         DBGC ( pxe, "PXE %s using %s\n",
00793                pxe->name, pxe->net->ntoa ( &mode->StationIp ) );
00794 
00795         return 0;
00796 }
00797 
00798 /**
00799  * Stop PXE base code
00800  *
00801  * @v base              PXE base code protocol
00802  * @ret efirc           EFI status code
00803  */
00804 static EFI_STATUS EFIAPI efi_pxe_stop ( EFI_PXE_BASE_CODE_PROTOCOL *base ) {
00805         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
00806         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
00807 
00808         DBGC ( pxe, "PXE %s STOP\n", pxe->name );
00809 
00810         /* Record that base code is stopped */
00811         mode->Started = FALSE;
00812 
00813         /* Close TFTP */
00814         efi_pxe_tftp_close ( pxe, 0 );
00815 
00816         /* Close UDP */
00817         efi_pxe_udp_close ( pxe, 0 );
00818 
00819         return 0;
00820 }
00821 
00822 /**
00823  * Perform DHCP
00824  *
00825  * @v base              PXE base code protocol
00826  * @v sort              Offers should be sorted
00827  * @ret efirc           EFI status code
00828  */
00829 static EFI_STATUS EFIAPI efi_pxe_dhcp ( EFI_PXE_BASE_CODE_PROTOCOL *base,
00830                                         BOOLEAN sort ) {
00831         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
00832         struct net_device *netdev = pxe->netdev;
00833         int rc;
00834 
00835         DBGC ( pxe, "PXE %s DHCP %s\n",
00836                pxe->name, ( sort ? "sorted" : "unsorted" ) );
00837 
00838         /* Claim network devices */
00839         efi_snp_claim();
00840 
00841         /* Initiate configuration */
00842         if ( ( rc = netdev_configure_all ( netdev ) ) != 0 ) {
00843                 DBGC ( pxe, "PXE %s could not initiate configuration: %s\n",
00844                        pxe->name, strerror ( rc ) );
00845                 goto err_configure;
00846         }
00847 
00848         /* Wait for configuration to complete (or time out) */
00849         while ( netdev_configuration_in_progress ( netdev ) )
00850                 step();
00851 
00852         /* Report timeout if configuration failed */
00853         if ( ! netdev_configuration_ok ( netdev ) ) {
00854                 rc = -ETIMEDOUT;
00855                 goto err_timeout;
00856         }
00857 
00858         /* Update station IP address */
00859         if ( ( rc = efi_pxe_ip ( pxe ) ) != 0 )
00860                 goto err_ip;
00861 
00862         /* Update faked DHCP packets */
00863         efi_pxe_fake_all ( pxe );
00864 
00865  err_ip:
00866  err_timeout:
00867  err_configure:
00868         efi_snp_release();
00869         return EFIRC ( rc );
00870 }
00871 
00872 /**
00873  * Perform boot server discovery
00874  *
00875  * @v base              PXE base code protocol
00876  * @v type              Boot server type
00877  * @v layer             Boot server layer
00878  * @v bis               Use boot integrity services
00879  * @v info              Additional information
00880  * @ret efirc           EFI status code
00881  */
00882 static EFI_STATUS EFIAPI
00883 efi_pxe_discover ( EFI_PXE_BASE_CODE_PROTOCOL *base, UINT16 type, UINT16 *layer,
00884                    BOOLEAN bis, EFI_PXE_BASE_CODE_DISCOVER_INFO *info ) {
00885         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
00886         EFI_IP_ADDRESS *ip;
00887         unsigned int i;
00888 
00889         DBGC ( pxe, "PXE %s DISCOVER type %d layer %d%s\n",
00890                pxe->name, type, *layer, ( bis ? " bis" : "" ) );
00891         if ( info ) {
00892                 DBGC ( pxe, "%s%s%s%s %s",
00893                        ( info->UseMCast ? " mcast" : "" ),
00894                        ( info->UseBCast ? " bcast" : "" ),
00895                        ( info->UseUCast ? " ucast" : "" ),
00896                        ( info->MustUseList ? " list" : "" ),
00897                        efi_pxe_ip_ntoa ( pxe, &info->ServerMCastIp ) );
00898                 for ( i = 0 ; i < info->IpCnt ; i++ ) {
00899                         ip = &info->SrvList[i].IpAddr;
00900                         DBGC ( pxe, " %d%s:%s", info->SrvList[i].Type,
00901                                ( info->SrvList[i].AcceptAnyResponse ?
00902                                  ":any" : "" ), efi_pxe_ip_ntoa ( pxe, ip ) );
00903                 }
00904         }
00905         DBGC ( pxe, "\n" );
00906 
00907         /* Not used by any bootstrap I can find to test with */
00908         return EFI_UNSUPPORTED;
00909 }
00910 
00911 /**
00912  * Perform (M)TFTP
00913  *
00914  * @v base              PXE base code protocol
00915  * @v opcode            TFTP opcode
00916  * @v data              Data buffer
00917  * @v overwrite         Overwrite file
00918  * @v len               Length of data buffer
00919  * @v blksize           Block size
00920  * @v ip                Server address
00921  * @v filename          Filename
00922  * @v info              Additional information
00923  * @v callback          Pass packets to callback instead of data buffer
00924  * @ret efirc           EFI status code
00925  */
00926 static EFI_STATUS EFIAPI
00927 efi_pxe_mtftp ( EFI_PXE_BASE_CODE_PROTOCOL *base,
00928                 EFI_PXE_BASE_CODE_TFTP_OPCODE opcode, VOID *data,
00929                 BOOLEAN overwrite, UINT64 *len, UINTN *blksize,
00930                 EFI_IP_ADDRESS *ip, UINT8 *filename,
00931                 EFI_PXE_BASE_CODE_MTFTP_INFO *info, BOOLEAN callback ) {
00932         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
00933         int rc;
00934 
00935         DBGC ( pxe, "PXE %s MTFTP %d%s %p+%llx", pxe->name, opcode,
00936                ( overwrite ? " overwrite" : "" ), data, *len );
00937         if ( blksize )
00938                 DBGC ( pxe, " blksize %zd", ( ( size_t ) *blksize ) );
00939         DBGC ( pxe, " %s:%s", efi_pxe_ip_ntoa ( pxe, ip ), filename );
00940         if ( info ) {
00941                 DBGC ( pxe, " %s:%d:%d:%d:%d",
00942                        efi_pxe_ip_ntoa ( pxe, &info->MCastIp ),
00943                        info->CPort, info->SPort, info->ListenTimeout,
00944                        info->TransmitTimeout );
00945         }
00946         DBGC ( pxe, "%s\n", ( callback ? " callback" : "" ) );
00947 
00948         /* Fail unless operation is supported */
00949         if ( ! ( ( opcode == EFI_PXE_BASE_CODE_TFTP_READ_FILE ) ||
00950                  ( opcode == EFI_PXE_BASE_CODE_MTFTP_READ_FILE ) ) ) {
00951                 DBGC ( pxe, "PXE %s unsupported MTFTP opcode %d\n",
00952                        pxe->name, opcode );
00953                 rc = -ENOTSUP;
00954                 goto err_opcode;
00955         }
00956 
00957         /* Claim network devices */
00958         efi_snp_claim();
00959 
00960         /* Determine block size.  Ignore the requested block size
00961          * unless we are using callbacks, since limiting HTTP to a
00962          * 512-byte TCP window is not sensible.
00963          */
00964         pxe->blksize = ( ( callback && blksize ) ? *blksize : -1UL );
00965 
00966         /* Initialise data transfer buffer */
00967         pxe->buf.data = data;
00968         pxe->buf.len = *len;
00969 
00970         /* Open download */
00971         if ( ( rc = efi_pxe_tftp_open ( pxe, ip,
00972                                         ( ( const char * ) filename ) ) ) != 0 )
00973                 goto err_open;
00974 
00975         /* Wait for download to complete */
00976         pxe->rc = -EINPROGRESS;
00977         while ( pxe->rc == -EINPROGRESS )
00978                 step();
00979         if ( ( rc = pxe->rc ) != 0 ) {
00980                 DBGC ( pxe, "PXE %s download failed: %s\n",
00981                        pxe->name, strerror ( rc ) );
00982                 goto err_download;
00983         }
00984 
00985  err_download:
00986         efi_pxe_tftp_close ( pxe, rc );
00987  err_open:
00988         efi_snp_release();
00989  err_opcode:
00990         return EFIRC ( rc );
00991 }
00992 
00993 /**
00994  * Transmit UDP packet
00995  *
00996  * @v base              PXE base code protocol
00997  * @v flags             Operation flags
00998  * @v dest_ip           Destination address
00999  * @v dest_port         Destination port
01000  * @v gateway           Gateway address
01001  * @v src_ip            Source address
01002  * @v src_port          Source port
01003  * @v hdr_len           Header length
01004  * @v hdr               Header data
01005  * @v len               Length
01006  * @v data              Data
01007  * @ret efirc           EFI status code
01008  */
01009 static EFI_STATUS EFIAPI
01010 efi_pxe_udp_write ( EFI_PXE_BASE_CODE_PROTOCOL *base, UINT16 flags,
01011                     EFI_IP_ADDRESS *dest_ip,
01012                     EFI_PXE_BASE_CODE_UDP_PORT *dest_port,
01013                     EFI_IP_ADDRESS *gateway, EFI_IP_ADDRESS *src_ip,
01014                     EFI_PXE_BASE_CODE_UDP_PORT *src_port,
01015                     UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data ) {
01016         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01017         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
01018         struct io_buffer *iobuf;
01019         struct xfer_metadata meta;
01020         union {
01021                 struct sockaddr_tcpip st;
01022                 struct sockaddr sa;
01023         } dest;
01024         union {
01025                 struct sockaddr_tcpip st;
01026                 struct sockaddr sa;
01027         } src;
01028         int rc;
01029 
01030         DBGC2 ( pxe, "PXE %s UDP WRITE ", pxe->name );
01031         if ( src_ip )
01032                 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, src_ip ) );
01033         DBGC2 ( pxe, ":" );
01034         if ( src_port &&
01035              ( ! ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT ) ) ) {
01036                 DBGC2 ( pxe, "%d", *src_port );
01037         } else {
01038                 DBGC2 ( pxe, "*" );
01039         }
01040         DBGC2 ( pxe, "->%s:%d", efi_pxe_ip_ntoa ( pxe, dest_ip ), *dest_port );
01041         if ( gateway )
01042                 DBGC2 ( pxe, " via %s", efi_pxe_ip_ntoa ( pxe, gateway ) );
01043         if ( hdr_len )
01044                 DBGC2 ( pxe, " %p+%zx", hdr, ( ( size_t ) *hdr_len ) );
01045         DBGC2 ( pxe, " %p+%zx", data, ( ( size_t ) *len ) );
01046         if ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT )
01047                 DBGC2 ( pxe, " frag" );
01048         DBGC2 ( pxe, "\n" );
01049 
01050         /* Open UDP connection (if applicable) */
01051         if ( ( rc = efi_pxe_udp_open ( pxe ) ) != 0 )
01052                 goto err_open;
01053 
01054         /* Construct destination address */
01055         efi_pxe_ip_sockaddr ( pxe, dest_ip, &dest.sa );
01056         dest.st.st_port = htons ( *dest_port );
01057 
01058         /* Construct source address */
01059         efi_pxe_ip_sockaddr ( pxe, ( src_ip ? src_ip : &mode->StationIp ),
01060                               &src.sa );
01061         if ( src_port &&
01062              ( ! ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT ) ) ) {
01063                 src.st.st_port = htons ( *src_port );
01064         } else {
01065                 /* The API does not allow for a sensible concept of
01066                  * binding to a local port, so just use a random value.
01067                  */
01068                 src.st.st_port = ( random() | htons ( 1024 ) );
01069                 if ( src_port )
01070                         *src_port = ntohs ( src.st.st_port );
01071         }
01072 
01073         /* Allocate I/O buffer */
01074         iobuf = xfer_alloc_iob ( &pxe->udp,
01075                                  ( *len + ( hdr_len ? *hdr_len : 0 ) ) );
01076         if ( ! iobuf ) {
01077                 rc = -ENOMEM;
01078                 goto err_alloc;
01079         }
01080 
01081         /* Populate I/O buffer */
01082         if ( hdr_len )
01083                 memcpy ( iob_put ( iobuf, *hdr_len ), hdr, *hdr_len );
01084         memcpy ( iob_put ( iobuf, *len ), data, *len );
01085 
01086         /* Construct metadata */
01087         memset ( &meta, 0, sizeof ( meta ) );
01088         meta.src = &src.sa;
01089         meta.dest = &dest.sa;
01090         meta.netdev = pxe->netdev;
01091 
01092         /* Deliver I/O buffer */
01093         if ( ( rc = xfer_deliver ( &pxe->udp, iob_disown ( iobuf ),
01094                                    &meta ) ) != 0 ) {
01095                 DBGC ( pxe, "PXE %s could not transmit: %s\n",
01096                        pxe->name, strerror ( rc ) );
01097                 goto err_deliver;
01098         }
01099 
01100  err_deliver:
01101         free_iob ( iobuf );
01102  err_alloc:
01103         efi_pxe_udp_schedule_close ( pxe );
01104  err_open:
01105         return EFIRC ( rc );
01106 }
01107 
01108 /**
01109  * Receive UDP packet
01110  *
01111  * @v base              PXE base code protocol
01112  * @v flags             Operation flags
01113  * @v dest_ip           Destination address
01114  * @v dest_port         Destination port
01115  * @v src_ip            Source address
01116  * @v src_port          Source port
01117  * @v hdr_len           Header length
01118  * @v hdr               Header data
01119  * @v len               Length
01120  * @v data              Data
01121  * @ret efirc           EFI status code
01122  */
01123 static EFI_STATUS EFIAPI
01124 efi_pxe_udp_read ( EFI_PXE_BASE_CODE_PROTOCOL *base, UINT16 flags,
01125                    EFI_IP_ADDRESS *dest_ip,
01126                    EFI_PXE_BASE_CODE_UDP_PORT *dest_port,
01127                    EFI_IP_ADDRESS *src_ip,
01128                    EFI_PXE_BASE_CODE_UDP_PORT *src_port,
01129                    UINTN *hdr_len, VOID *hdr, UINTN *len, VOID *data ) {
01130         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01131         struct io_buffer *iobuf;
01132         struct efi_pxe_udp_pseudo_header *pshdr;
01133         EFI_IP_ADDRESS *actual_dest_ip;
01134         EFI_IP_ADDRESS *actual_src_ip;
01135         size_t addr_len;
01136         size_t frag_len;
01137         int rc;
01138 
01139         DBGC2 ( pxe, "PXE %s UDP READ ", pxe->name );
01140         if ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER ) {
01141                 DBGC2 ( pxe, "(filter)" );
01142         } else if ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP ) {
01143                 DBGC2 ( pxe, "*" );
01144         } else if ( dest_ip ) {
01145                 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, dest_ip ) );
01146         }
01147         DBGC2 ( pxe, ":" );
01148         if ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT ) {
01149                 DBGC2 ( pxe, "*" );
01150         } else if ( dest_port ) {
01151                 DBGC2 ( pxe, "%d", *dest_port );
01152         } else {
01153                 DBGC2 ( pxe, "<NULL>" );
01154         }
01155         DBGC2 ( pxe, "<-" );
01156         if ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP ) {
01157                 DBGC2 ( pxe, "*" );
01158         } else if ( src_ip ) {
01159                 DBGC2 ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, src_ip ) );
01160         } else {
01161                 DBGC2 ( pxe, "<NULL>" );
01162         }
01163         DBGC2 ( pxe, ":" );
01164         if ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT ) {
01165                 DBGC2 ( pxe, "*" );
01166         } else if ( src_port ) {
01167                 DBGC2 ( pxe, "%d", *src_port );
01168         } else {
01169                 DBGC2 ( pxe, "<NULL>" );
01170         }
01171         if ( hdr_len )
01172                 DBGC2 ( pxe, " %p+%zx", hdr, ( ( size_t ) *hdr_len ) );
01173         DBGC2 ( pxe, " %p+%zx\n", data, ( ( size_t ) *len ) );
01174 
01175         /* Open UDP connection (if applicable) */
01176         if ( ( rc = efi_pxe_udp_open ( pxe ) ) != 0 )
01177                 goto err_open;
01178 
01179         /* Try receiving a packet, if the queue is empty */
01180         if ( list_empty ( &pxe->queue ) )
01181                 step();
01182 
01183         /* Remove first packet from the queue */
01184         iobuf = list_first_entry ( &pxe->queue, struct io_buffer, list );
01185         if ( ! iobuf ) {
01186                 rc = -ETIMEDOUT; /* "no packet" */
01187                 goto err_empty;
01188         }
01189         list_del ( &iobuf->list );
01190 
01191         /* Strip pseudo-header */
01192         pshdr = iobuf->data;
01193         addr_len = ( pshdr->net->net_addr_len );
01194         iob_pull ( iobuf, sizeof ( *pshdr ) );
01195         actual_dest_ip = iobuf->data;
01196         iob_pull ( iobuf, addr_len );
01197         actual_src_ip = iobuf->data;
01198         iob_pull ( iobuf, addr_len );
01199         DBGC2 ( pxe, "PXE %s UDP RX %s:%d", pxe->name,
01200                 pshdr->net->ntoa ( actual_dest_ip ), pshdr->dest_port );
01201         DBGC2 ( pxe, "<-%s:%d len %#zx\n", pshdr->net->ntoa ( actual_src_ip ),
01202                 pshdr->src_port, iob_len ( iobuf ) );
01203 
01204         /* Filter based on network-layer protocol */
01205         if ( pshdr->net != pxe->net ) {
01206                 DBGC2 ( pxe, "PXE %s filtered out %s packet\n",
01207                         pxe->name, pshdr->net->name );
01208                 rc = -ETIMEDOUT; /* "no packet" */
01209                 goto err_filter;
01210         }
01211 
01212         /* Filter based on port numbers */
01213         if ( ! ( ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT ) ||
01214                  ( dest_port && ( *dest_port == pshdr->dest_port ) ) ) ) {
01215                 DBGC2 ( pxe, "PXE %s filtered out destination port %d\n",
01216                         pxe->name, pshdr->dest_port );
01217                 rc = -ETIMEDOUT; /* "no packet" */
01218                 goto err_filter;
01219         }
01220         if ( ! ( ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT ) ||
01221                  ( src_port && ( *src_port == pshdr->src_port ) ) ) ) {
01222                 DBGC2 ( pxe, "PXE %s filtered out source port %d\n",
01223                         pxe->name, pshdr->src_port );
01224                 rc = -ETIMEDOUT; /* "no packet" */
01225                 goto err_filter;
01226         }
01227 
01228         /* Filter based on source IP address */
01229         if ( ! ( ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP ) ||
01230                  ( src_ip &&
01231                    ( memcmp ( src_ip, actual_src_ip, addr_len ) == 0 ) ) ) ) {
01232                 DBGC2 ( pxe, "PXE %s filtered out source IP %s\n",
01233                         pxe->name, pshdr->net->ntoa ( actual_src_ip ) );
01234                 rc = -ETIMEDOUT; /* "no packet" */
01235                 goto err_filter;
01236         }
01237 
01238         /* Filter based on destination IP address */
01239         if ( ! ( ( ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER ) &&
01240                    efi_pxe_ip_filter ( pxe, actual_dest_ip ) ) ||
01241                  ( ( ! ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER ) ) &&
01242                    ( ( flags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP ) ||
01243                         ( dest_ip && ( memcmp ( dest_ip, actual_dest_ip,
01244                                                 addr_len ) == 0 ) ) ) ) ) ) {
01245                 DBGC2 ( pxe, "PXE %s filtered out destination IP %s\n",
01246                         pxe->name, pshdr->net->ntoa ( actual_dest_ip ) );
01247                 rc = -ETIMEDOUT; /* "no packet" */
01248                 goto err_filter;
01249         }
01250 
01251         /* Fill in addresses and port numbers */
01252         if ( dest_ip )
01253                 memcpy ( dest_ip, actual_dest_ip, addr_len );
01254         if ( dest_port )
01255                 *dest_port = pshdr->dest_port;
01256         if ( src_ip )
01257                 memcpy ( src_ip, actual_src_ip, addr_len );
01258         if ( src_port )
01259                 *src_port = pshdr->src_port;
01260 
01261         /* Fill in header, if applicable */
01262         if ( hdr_len ) {
01263                 frag_len = iob_len ( iobuf );
01264                 if ( frag_len > *hdr_len )
01265                         frag_len = *hdr_len;
01266                 memcpy ( hdr, iobuf->data, frag_len );
01267                 iob_pull ( iobuf, frag_len );
01268                 *hdr_len = frag_len;
01269         }
01270 
01271         /* Fill in data buffer */
01272         frag_len = iob_len ( iobuf );
01273         if ( frag_len > *len )
01274                 frag_len = *len;
01275         memcpy ( data, iobuf->data, frag_len );
01276         iob_pull ( iobuf, frag_len );
01277         *len = frag_len;
01278 
01279         /* Check for overflow */
01280         if ( iob_len ( iobuf ) ) {
01281                 rc = -ERANGE;
01282                 goto err_too_short;
01283         }
01284 
01285         /* Success */
01286         rc = 0;
01287 
01288  err_too_short:
01289  err_filter:
01290         free_iob ( iobuf );
01291  err_empty:
01292         efi_pxe_udp_schedule_close ( pxe );
01293  err_open:
01294         return EFIRC ( rc );
01295 }
01296 
01297 /**
01298  * Set receive filter
01299  *
01300  * @v base              PXE base code protocol
01301  * @v filter            Receive filter
01302  * @ret efirc           EFI status code
01303  */
01304 static EFI_STATUS EFIAPI
01305 efi_pxe_set_ip_filter ( EFI_PXE_BASE_CODE_PROTOCOL *base,
01306                         EFI_PXE_BASE_CODE_IP_FILTER *filter ) {
01307         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01308         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
01309         unsigned int i;
01310 
01311         DBGC ( pxe, "PXE %s SET IP FILTER %02x",
01312                pxe->name, filter->Filters );
01313         for ( i = 0 ; i < filter->IpCnt ; i++ ) {
01314                 DBGC ( pxe, " %s",
01315                        efi_pxe_ip_ntoa ( pxe, &filter->IpList[i] ) );
01316         }
01317         DBGC ( pxe, "\n" );
01318 
01319         /* Update filter */
01320         memcpy ( &mode->IpFilter, filter, sizeof ( mode->IpFilter ) );
01321 
01322         return 0;
01323 }
01324 
01325 /**
01326  * Resolve MAC address
01327  *
01328  * @v base              PXE base code protocol
01329  * @v ip                IP address
01330  * @v mac               MAC address to fill in
01331  * @ret efirc           EFI status code
01332  */
01333 static EFI_STATUS EFIAPI efi_pxe_arp ( EFI_PXE_BASE_CODE_PROTOCOL *base,
01334                                        EFI_IP_ADDRESS *ip,
01335                                        EFI_MAC_ADDRESS *mac ) {
01336         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01337 
01338         DBGC ( pxe, "PXE %s ARP %s %p\n",
01339                pxe->name, efi_pxe_ip_ntoa ( pxe, ip ), mac );
01340 
01341         /* Not used by any bootstrap I can find to test with */
01342         return EFI_UNSUPPORTED;
01343 }
01344 
01345 /**
01346  * Set parameters
01347  *
01348  * @v base              PXE base code protocol
01349  * @v autoarp           Automatic ARP packet generation
01350  * @v sendguid          Send GUID as client hardware address
01351  * @v ttl               IP time to live
01352  * @v tos               IP type of service
01353  * @v callback          Make callbacks
01354  * @ret efirc           EFI status code
01355  */
01356 static EFI_STATUS EFIAPI
01357 efi_pxe_set_parameters ( EFI_PXE_BASE_CODE_PROTOCOL *base,
01358                          BOOLEAN *autoarp, BOOLEAN *sendguid, UINT8 *ttl,
01359                          UINT8 *tos, BOOLEAN *callback ) {
01360         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01361         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
01362 
01363         DBGC ( pxe, "PXE %s SET PARAMETERS", pxe->name );
01364         if ( autoarp )
01365                 DBGC ( pxe, " %s", ( *autoarp ? "autoarp" : "noautoarp" ) );
01366         if ( sendguid )
01367                 DBGC ( pxe, " %s", ( *sendguid ? "sendguid" : "sendmac" ) );
01368         if ( ttl )
01369                 DBGC ( pxe, " ttl %d", *ttl );
01370         if ( tos )
01371                 DBGC ( pxe, " tos %d", *tos );
01372         if ( callback ) {
01373                 DBGC ( pxe, " %s",
01374                        ( *callback ? "callback" : "nocallback" ) );
01375         }
01376         DBGC ( pxe, "\n" );
01377 
01378         /* Update parameters */
01379         if ( autoarp )
01380                 mode->AutoArp = *autoarp;
01381         if ( sendguid )
01382                 mode->SendGUID = *sendguid;
01383         if ( ttl )
01384                 mode->TTL = *ttl;
01385         if ( tos )
01386                 mode->ToS = *tos;
01387         if ( callback )
01388                 mode->MakeCallbacks = *callback;
01389 
01390         return 0;
01391 }
01392 
01393 /**
01394  * Set IP address
01395  *
01396  * @v base              PXE base code protocol
01397  * @v ip                IP address
01398  * @v netmask           Subnet mask
01399  * @ret efirc           EFI status code
01400  */
01401 static EFI_STATUS EFIAPI
01402 efi_pxe_set_station_ip ( EFI_PXE_BASE_CODE_PROTOCOL *base,
01403                          EFI_IP_ADDRESS *ip, EFI_IP_ADDRESS *netmask ) {
01404         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01405         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
01406 
01407         DBGC ( pxe, "PXE %s SET STATION IP ", pxe->name );
01408         if ( ip )
01409                 DBGC ( pxe, "%s", efi_pxe_ip_ntoa ( pxe, ip ) );
01410         if ( netmask )
01411                 DBGC ( pxe, "/%s", efi_pxe_ip_ntoa ( pxe, netmask ) );
01412         DBGC ( pxe, "\n" );
01413 
01414         /* Update IP address and netmask */
01415         if ( ip )
01416                 memcpy ( &mode->StationIp, ip, sizeof ( mode->StationIp ) );
01417         if ( netmask )
01418                 memcpy ( &mode->SubnetMask, netmask, sizeof (mode->SubnetMask));
01419 
01420         return 0;
01421 }
01422 
01423 /**
01424  * Update cached DHCP packets
01425  *
01426  * @v base              PXE base code protocol
01427  * @v dhcpdisc_ok       DHCPDISCOVER is valid
01428  * @v dhcpack_ok        DHCPACK received
01429  * @v proxyoffer_ok     ProxyDHCPOFFER received
01430  * @v pxebsdisc_ok      PxeBsDISCOVER valid
01431  * @v pxebsack_ok       PxeBsACK received
01432  * @v pxebsbis_ok       PxeBsBIS received
01433  * @v dhcpdisc          DHCPDISCOVER packet
01434  * @v dhcpack           DHCPACK packet
01435  * @v proxyoffer        ProxyDHCPOFFER packet
01436  * @v pxebsdisc         PxeBsDISCOVER packet
01437  * @v pxebsack          PxeBsACK packet
01438  * @v pxebsbis          PxeBsBIS packet
01439  * @ret efirc           EFI status code
01440  */
01441 static EFI_STATUS EFIAPI
01442 efi_pxe_set_packets ( EFI_PXE_BASE_CODE_PROTOCOL *base, BOOLEAN *dhcpdisc_ok,
01443                       BOOLEAN *dhcpack_ok, BOOLEAN *proxyoffer_ok,
01444                       BOOLEAN *pxebsdisc_ok, BOOLEAN *pxebsack_ok,
01445                       BOOLEAN *pxebsbis_ok, EFI_PXE_BASE_CODE_PACKET *dhcpdisc,
01446                       EFI_PXE_BASE_CODE_PACKET *dhcpack,
01447                       EFI_PXE_BASE_CODE_PACKET *proxyoffer,
01448                       EFI_PXE_BASE_CODE_PACKET *pxebsdisc,
01449                       EFI_PXE_BASE_CODE_PACKET *pxebsack,
01450                       EFI_PXE_BASE_CODE_PACKET *pxebsbis ) {
01451         struct efi_pxe *pxe = container_of ( base, struct efi_pxe, base );
01452         EFI_PXE_BASE_CODE_MODE *mode = &pxe->mode;
01453 
01454         DBGC ( pxe, "PXE %s SET PACKETS\n", pxe->name );
01455 
01456         /* Update fake packet flags */
01457         if ( dhcpdisc_ok )
01458                 mode->DhcpDiscoverValid = *dhcpdisc_ok;
01459         if ( dhcpack_ok )
01460                 mode->DhcpAckReceived = *dhcpack_ok;
01461         if ( proxyoffer_ok )
01462                 mode->ProxyOfferReceived = *proxyoffer_ok;
01463         if ( pxebsdisc_ok )
01464                 mode->PxeDiscoverValid = *pxebsdisc_ok;
01465         if ( pxebsack_ok )
01466                 mode->PxeReplyReceived = *pxebsack_ok;
01467         if ( pxebsbis_ok )
01468                 mode->PxeBisReplyReceived = *pxebsbis_ok;
01469 
01470         /* Update fake packet contents */
01471         if ( dhcpdisc )
01472                 memcpy ( &mode->DhcpDiscover, dhcpdisc, sizeof ( *dhcpdisc ) );
01473         if ( dhcpack )
01474                 memcpy ( &mode->DhcpAck, dhcpack, sizeof ( *dhcpack ) );
01475         if ( proxyoffer )
01476                 memcpy ( &mode->ProxyOffer, proxyoffer, sizeof ( *proxyoffer ));
01477         if ( pxebsdisc )
01478                 memcpy ( &mode->PxeDiscover, pxebsdisc, sizeof ( *pxebsdisc ) );
01479         if ( pxebsack )
01480                 memcpy ( &mode->PxeReply, pxebsack, sizeof ( *pxebsack ) );
01481         if ( pxebsbis )
01482                 memcpy ( &mode->PxeBisReply, pxebsbis, sizeof ( *pxebsbis ) );
01483 
01484         return 0;
01485 }
01486 
01487 /** PXE base code protocol */
01488 static EFI_PXE_BASE_CODE_PROTOCOL efi_pxe_base_code_protocol = {
01489         .Revision       = EFI_PXE_BASE_CODE_PROTOCOL_REVISION,
01490         .Start          = efi_pxe_start,
01491         .Stop           = efi_pxe_stop,
01492         .Dhcp           = efi_pxe_dhcp,
01493         .Discover       = efi_pxe_discover,
01494         .Mtftp          = efi_pxe_mtftp,
01495         .UdpWrite       = efi_pxe_udp_write,
01496         .UdpRead        = efi_pxe_udp_read,
01497         .SetIpFilter    = efi_pxe_set_ip_filter,
01498         .Arp            = efi_pxe_arp,
01499         .SetParameters  = efi_pxe_set_parameters,
01500         .SetStationIp   = efi_pxe_set_station_ip,
01501         .SetPackets     = efi_pxe_set_packets,
01502 };
01503 
01504 /******************************************************************************
01505  *
01506  * Apple NetBoot protocol
01507  *
01508  ******************************************************************************
01509  */
01510 
01511 /**
01512  * Get DHCP/BSDP response
01513  *
01514  * @v packet            Packet
01515  * @v len               Length of data buffer
01516  * @v data              Data buffer
01517  * @ret efirc           EFI status code
01518  */
01519 static EFI_STATUS EFIAPI
01520 efi_apple_get_response ( EFI_PXE_BASE_CODE_PACKET *packet, UINTN *len,
01521                          VOID *data ) {
01522 
01523         /* Check length */
01524         if ( *len < sizeof ( *packet ) ) {
01525                 *len = sizeof ( *packet );
01526                 return EFI_BUFFER_TOO_SMALL;
01527         }
01528 
01529         /* Copy packet */
01530         memcpy ( data, packet, sizeof ( *packet ) );
01531         *len = sizeof ( *packet );
01532 
01533         return EFI_SUCCESS;
01534 }
01535 
01536 /**
01537  * Get DHCP response
01538  *
01539  * @v apple             Apple NetBoot protocol
01540  * @v len               Length of data buffer
01541  * @v data              Data buffer
01542  * @ret efirc           EFI status code
01543  */
01544 static EFI_STATUS EFIAPI
01545 efi_apple_get_dhcp_response ( EFI_APPLE_NET_BOOT_PROTOCOL *apple,
01546                               UINTN *len, VOID *data ) {
01547         struct efi_pxe *pxe = container_of ( apple, struct efi_pxe, apple );
01548 
01549         return efi_apple_get_response ( &pxe->mode.DhcpAck, len, data );
01550 }
01551 
01552 /**
01553  * Get BSDP response
01554  *
01555  * @v apple             Apple NetBoot protocol
01556  * @v len               Length of data buffer
01557  * @v data              Data buffer
01558  * @ret efirc           EFI status code
01559  */
01560 static EFI_STATUS EFIAPI
01561 efi_apple_get_bsdp_response ( EFI_APPLE_NET_BOOT_PROTOCOL *apple,
01562                               UINTN *len, VOID *data ) {
01563         struct efi_pxe *pxe = container_of ( apple, struct efi_pxe, apple );
01564 
01565         return efi_apple_get_response ( &pxe->mode.PxeReply, len, data );
01566 }
01567 
01568 /** Apple NetBoot protocol */
01569 static EFI_APPLE_NET_BOOT_PROTOCOL efi_apple_net_boot_protocol = {
01570         .GetDhcpResponse = efi_apple_get_dhcp_response,
01571         .GetBsdpResponse = efi_apple_get_bsdp_response,
01572 };
01573 
01574 /******************************************************************************
01575  *
01576  * Installer
01577  *
01578  ******************************************************************************
01579  */
01580 
01581 /**
01582  * Install PXE base code protocol
01583  *
01584  * @v handle            EFI handle
01585  * @v netdev            Underlying network device
01586  * @ret rc              Return status code
01587  */
01588 int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) {
01589         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
01590         struct tcpip_net_protocol *ipv6 = tcpip_net_protocol ( AF_INET6 );
01591         struct efi_pxe *pxe;
01592         struct in_addr ip;
01593         BOOLEAN use_ipv6;
01594         EFI_STATUS efirc;
01595         int rc;
01596 
01597         /* Allocate and initialise structure */
01598         pxe = zalloc ( sizeof ( *pxe ) );
01599         if ( ! pxe ) {
01600                 rc = -ENOMEM;
01601                 goto err_alloc;
01602         }
01603         ref_init ( &pxe->refcnt, efi_pxe_free );
01604         pxe->netdev = netdev_get ( netdev );
01605         pxe->name = netdev->name;
01606         pxe->handle = handle;
01607         memcpy ( &pxe->base, &efi_pxe_base_code_protocol, sizeof ( pxe->base ));
01608         pxe->base.Mode = &pxe->mode;
01609         memcpy ( &pxe->apple, &efi_apple_net_boot_protocol,
01610                  sizeof ( pxe->apple ) );
01611         pxe->buf.op = &efi_pxe_buf_operations;
01612         intf_init ( &pxe->tftp, &efi_pxe_tftp_desc, &pxe->refcnt );
01613         intf_init ( &pxe->udp, &efi_pxe_udp_desc, &pxe->refcnt );
01614         INIT_LIST_HEAD ( &pxe->queue );
01615         process_init_stopped ( &pxe->process, &efi_pxe_process_desc,
01616                                &pxe->refcnt );
01617 
01618         /* Crude heuristic: assume that we prefer to use IPv4 if we
01619          * have an IPv4 address for the network device, otherwise
01620          * prefer IPv6 (if available).
01621          */
01622         fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting, &ip );
01623         use_ipv6 = ( ip.s_addr ? FALSE : ( ipv6 != NULL ) );
01624 
01625         /* Start base code */
01626         efi_pxe_start ( &pxe->base, use_ipv6 );
01627 
01628         /* Install PXE base code protocol */
01629         if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
01630                         &handle,
01631                         &efi_pxe_base_code_protocol_guid, &pxe->base,
01632                         &efi_apple_net_boot_protocol_guid, &pxe->apple,
01633                         NULL ) ) != 0 ) {
01634                 rc = -EEFI ( efirc );
01635                 DBGC ( pxe, "PXE %s could not install base code protocol: %s\n",
01636                        pxe->name, strerror ( rc ) );
01637                 goto err_install_protocol;
01638         }
01639 
01640         /* Transfer reference to list and return */
01641         list_add_tail ( &pxe->list, &efi_pxes );
01642         DBGC ( pxe, "PXE %s installed for %s\n",
01643                pxe->name, efi_handle_name ( handle ) );
01644         return 0;
01645 
01646         bs->UninstallMultipleProtocolInterfaces (
01647                         handle,
01648                         &efi_pxe_base_code_protocol_guid, &pxe->base,
01649                         &efi_apple_net_boot_protocol_guid, &pxe->apple,
01650                         NULL );
01651  err_install_protocol:
01652         ref_put ( &pxe->refcnt );
01653  err_alloc:
01654         return rc;
01655 }
01656 
01657 /**
01658  * Uninstall PXE base code protocol
01659  *
01660  * @v handle            EFI handle
01661  */
01662 void efi_pxe_uninstall ( EFI_HANDLE handle ) {
01663         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
01664         struct efi_pxe *pxe;
01665 
01666         /* Locate PXE base code */
01667         pxe = efi_pxe_find ( handle );
01668         if ( ! handle ) {
01669                 DBG ( "PXE could not find base code for %s\n",
01670                       efi_handle_name ( handle ) );
01671                 return;
01672         }
01673 
01674         /* Stop base code */
01675         efi_pxe_stop ( &pxe->base );
01676 
01677         /* Uninstall PXE base code protocol */
01678         bs->UninstallMultipleProtocolInterfaces (
01679                         handle,
01680                         &efi_pxe_base_code_protocol_guid, &pxe->base,
01681                         &efi_apple_net_boot_protocol_guid, &pxe->apple,
01682                         NULL );
01683 
01684         /* Remove from list and drop list's reference */
01685         list_del ( &pxe->list );
01686         ref_put ( &pxe->refcnt );
01687 }