efi_loader: implement MCastIPtoMAC
[oweals/u-boot.git] / lib / efi_loader / efi_net.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Simple network protocol
4  * PXE base code protocol
5  *
6  * Copyright (c) 2016 Alexander Graf
7  *
8  * The simple network protocol has the following statuses and services
9  * to move between them:
10  *
11  * Start():      EfiSimpleNetworkStopped     -> EfiSimpleNetworkStarted
12  * Initialize(): EfiSimpleNetworkStarted     -> EfiSimpleNetworkInitialized
13  * Shutdown():   EfiSimpleNetworkInitialized -> EfiSimpleNetworkStarted
14  * Stop():       EfiSimpleNetworkStarted     -> EfiSimpleNetworkStopped
15  * Reset():      EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized
16  */
17
18 #include <common.h>
19 #include <efi_loader.h>
20 #include <malloc.h>
21
22 static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
23 static const efi_guid_t efi_pxe_base_code_protocol_guid =
24                                         EFI_PXE_BASE_CODE_PROTOCOL_GUID;
25 static struct efi_pxe_packet *dhcp_ack;
26 static bool new_rx_packet;
27 static void *new_tx_packet;
28 static void *transmit_buffer;
29
30 /*
31  * The notification function of this event is called in every timer cycle
32  * to check if a new network packet has been received.
33  */
34 static struct efi_event *network_timer_event;
35 /*
36  * This event is signaled when a packet has been received.
37  */
38 static struct efi_event *wait_for_packet;
39
40 /**
41  * struct efi_net_obj - EFI object representing a network interface
42  *
43  * @header:     EFI object header
44  * @net:        simple network protocol interface
45  * @net_mode:   status of the network interface
46  * @pxe:        PXE base code protocol interface
47  * @pxe_mode:   status of the PXE base code protocol
48  */
49 struct efi_net_obj {
50         struct efi_object header;
51         struct efi_simple_network net;
52         struct efi_simple_network_mode net_mode;
53         struct efi_pxe_base_code_protocol pxe;
54         struct efi_pxe_mode pxe_mode;
55 };
56
57 /*
58  * efi_net_start() - start the network interface
59  *
60  * This function implements the Start service of the
61  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
62  * (UEFI) specification for details.
63  *
64  * @this:       pointer to the protocol instance
65  * Return:      status code
66  */
67 static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
68 {
69         efi_status_t ret = EFI_SUCCESS;
70
71         EFI_ENTRY("%p", this);
72
73         /* Check parameters */
74         if (!this) {
75                 ret = EFI_INVALID_PARAMETER;
76                 goto out;
77         }
78
79         if (this->mode->state != EFI_NETWORK_STOPPED) {
80                 ret = EFI_ALREADY_STARTED;
81         } else {
82                 this->int_status = 0;
83                 wait_for_packet->is_signaled = false;
84                 this->mode->state = EFI_NETWORK_STARTED;
85         }
86 out:
87         return EFI_EXIT(ret);
88 }
89
90 /*
91  * efi_net_stop() - stop the network interface
92  *
93  * This function implements the Stop service of the
94  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
95  * (UEFI) specification for details.
96  *
97  * @this:       pointer to the protocol instance
98  * Return:      status code
99  */
100 static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
101 {
102         efi_status_t ret = EFI_SUCCESS;
103
104         EFI_ENTRY("%p", this);
105
106         /* Check parameters */
107         if (!this) {
108                 ret = EFI_INVALID_PARAMETER;
109                 goto out;
110         }
111
112         if (this->mode->state == EFI_NETWORK_STOPPED) {
113                 ret = EFI_NOT_STARTED;
114         } else {
115                 /* Disable hardware and put it into the reset state */
116                 eth_halt();
117                 this->mode->state = EFI_NETWORK_STOPPED;
118         }
119 out:
120         return EFI_EXIT(ret);
121 }
122
123 /*
124  * efi_net_initialize() - initialize the network interface
125  *
126  * This function implements the Initialize service of the
127  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
128  * (UEFI) specification for details.
129  *
130  * @this:       pointer to the protocol instance
131  * @extra_rx:   extra receive buffer to be allocated
132  * @extra_tx:   extra transmit buffer to be allocated
133  * Return:      status code
134  */
135 static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
136                                               ulong extra_rx, ulong extra_tx)
137 {
138         int ret;
139         efi_status_t r = EFI_SUCCESS;
140
141         EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx);
142
143         /* Check parameters */
144         if (!this) {
145                 r = EFI_INVALID_PARAMETER;
146                 goto out;
147         }
148
149         switch (this->mode->state) {
150         case EFI_NETWORK_INITIALIZED:
151         case EFI_NETWORK_STARTED:
152                 break;
153         default:
154                 r = EFI_NOT_STARTED;
155                 goto out;
156         }
157
158         /* Setup packet buffers */
159         net_init();
160         /* Disable hardware and put it into the reset state */
161         eth_halt();
162         /* Set current device according to environment variables */
163         eth_set_current();
164         /* Get hardware ready for send and receive operations */
165         ret = eth_init();
166         if (ret < 0) {
167                 eth_halt();
168                 this->mode->state = EFI_NETWORK_STOPPED;
169                 r = EFI_DEVICE_ERROR;
170                 goto out;
171         } else {
172                 this->int_status = 0;
173                 wait_for_packet->is_signaled = false;
174                 this->mode->state = EFI_NETWORK_INITIALIZED;
175         }
176 out:
177         return EFI_EXIT(r);
178 }
179
180 /*
181  * efi_net_reset() - reinitialize the network interface
182  *
183  * This function implements the Reset service of the
184  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
185  * (UEFI) specification for details.
186  *
187  * @this:                       pointer to the protocol instance
188  * @extended_verification:      execute exhaustive verification
189  * Return:                      status code
190  */
191 static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this,
192                                          int extended_verification)
193 {
194         efi_status_t ret;
195
196         EFI_ENTRY("%p, %x", this, extended_verification);
197
198         /* Check parameters */
199         if (!this) {
200                 ret = EFI_INVALID_PARAMETER;
201                 goto out;
202         }
203
204         switch (this->mode->state) {
205         case EFI_NETWORK_INITIALIZED:
206                 break;
207         case EFI_NETWORK_STOPPED:
208                 ret = EFI_NOT_STARTED;
209                 goto out;
210         default:
211                 ret = EFI_DEVICE_ERROR;
212                 goto out;
213         }
214
215         this->mode->state = EFI_NETWORK_STARTED;
216         ret = EFI_CALL(efi_net_initialize(this, 0, 0));
217 out:
218         return EFI_EXIT(ret);
219 }
220
221 /*
222  * efi_net_shutdown() - shut down the network interface
223  *
224  * This function implements the Shutdown service of the
225  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
226  * (UEFI) specification for details.
227  *
228  * @this:       pointer to the protocol instance
229  * Return:      status code
230  */
231 static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
232 {
233         efi_status_t ret = EFI_SUCCESS;
234
235         EFI_ENTRY("%p", this);
236
237         /* Check parameters */
238         if (!this) {
239                 ret = EFI_INVALID_PARAMETER;
240                 goto out;
241         }
242
243         switch (this->mode->state) {
244         case EFI_NETWORK_INITIALIZED:
245                 break;
246         case EFI_NETWORK_STOPPED:
247                 ret = EFI_NOT_STARTED;
248                 goto out;
249         default:
250                 ret = EFI_DEVICE_ERROR;
251                 goto out;
252         }
253
254         eth_halt();
255         this->int_status = 0;
256         wait_for_packet->is_signaled = false;
257         this->mode->state = EFI_NETWORK_STARTED;
258
259 out:
260         return EFI_EXIT(ret);
261 }
262
263 /*
264  * efi_net_receive_filters() - mange multicast receive filters
265  *
266  * This function implements the ReceiveFilters service of the
267  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
268  * (UEFI) specification for details.
269  *
270  * @this:               pointer to the protocol instance
271  * @enable:             bit mask of receive filters to enable
272  * @disable:            bit mask of receive filters to disable
273  * @reset_mcast_filter: true resets contents of the filters
274  * @mcast_filter_count: number of hardware MAC addresses in the new filters list
275  * @mcast_filter:       list of new filters
276  * Return:              status code
277  */
278 static efi_status_t EFIAPI efi_net_receive_filters
279                 (struct efi_simple_network *this, u32 enable, u32 disable,
280                  int reset_mcast_filter, ulong mcast_filter_count,
281                  struct efi_mac_address *mcast_filter)
282 {
283         EFI_ENTRY("%p, %x, %x, %x, %lx, %p", this, enable, disable,
284                   reset_mcast_filter, mcast_filter_count, mcast_filter);
285
286         return EFI_EXIT(EFI_UNSUPPORTED);
287 }
288
289 /*
290  * efi_net_station_address() - set the hardware MAC address
291  *
292  * This function implements the StationAddress service of the
293  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
294  * (UEFI) specification for details.
295  *
296  * @this:       pointer to the protocol instance
297  * @reset:      if true reset the address to default
298  * @new_mac:    new MAC address
299  * Return:      status code
300  */
301 static efi_status_t EFIAPI efi_net_station_address
302                 (struct efi_simple_network *this, int reset,
303                  struct efi_mac_address *new_mac)
304 {
305         EFI_ENTRY("%p, %x, %p", this, reset, new_mac);
306
307         return EFI_EXIT(EFI_UNSUPPORTED);
308 }
309
310 /*
311  * efi_net_statistics() - reset or collect statistics of the network interface
312  *
313  * This function implements the Statistics service of the
314  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
315  * (UEFI) specification for details.
316  *
317  * @this:       pointer to the protocol instance
318  * @reset:      if true, the statistics are reset
319  * @stat_size:  size of the statistics table
320  * @stat_table: table to receive the statistics
321  * Return:      status code
322  */
323 static efi_status_t EFIAPI efi_net_statistics(struct efi_simple_network *this,
324                                               int reset, ulong *stat_size,
325                                               void *stat_table)
326 {
327         EFI_ENTRY("%p, %x, %p, %p", this, reset, stat_size, stat_table);
328
329         return EFI_EXIT(EFI_UNSUPPORTED);
330 }
331
332 /*
333  * efi_net_mcastiptomac() - translate multicast IP address to MAC address
334  *
335  * This function implements the MCastIPtoMAC service of the
336  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
337  * (UEFI) specification for details.
338  *
339  * @this:       pointer to the protocol instance
340  * @ipv6:       true if the IP address is an IPv6 address
341  * @ip:         IP address
342  * @mac:        MAC address
343  * Return:      status code
344  */
345 static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this,
346                                                 int ipv6,
347                                                 struct efi_ip_address *ip,
348                                                 struct efi_mac_address *mac)
349 {
350         efi_status_t ret = EFI_SUCCESS;
351
352         EFI_ENTRY("%p, %x, %p, %p", this, ipv6, ip, mac);
353
354         if (!this || !ip || !mac) {
355                 ret = EFI_INVALID_PARAMETER;
356                 goto out;
357         }
358
359         if (ipv6) {
360                 ret = EFI_UNSUPPORTED;
361                 goto out;
362         }
363
364         /* Multi-cast addresses are in the range 224.0.0.0 - 239.255.255.255 */
365         if ((ip->ip_addr[0] & 0xf0) != 0xe0) {
366                 ret = EFI_INVALID_PARAMETER;
367                 goto out;
368         };
369
370         switch (this->mode->state) {
371         case EFI_NETWORK_INITIALIZED:
372         case EFI_NETWORK_STARTED:
373                 break;
374         default:
375                 ret = EFI_NOT_STARTED;
376                 goto out;
377         }
378
379         memset(mac, 0, sizeof(struct efi_mac_address));
380
381         /*
382          * Copy lower 23 bits of IPv4 multi-cast address
383          * RFC 1112, RFC 7042 2.1.1.
384          */
385         mac->mac_addr[0] = 0x01;
386         mac->mac_addr[1] = 0x00;
387         mac->mac_addr[2] = 0x5E;
388         mac->mac_addr[3] = ip->ip_addr[1] & 0x7F;
389         mac->mac_addr[4] = ip->ip_addr[2];
390         mac->mac_addr[5] = ip->ip_addr[3];
391 out:
392         return EFI_EXIT(ret);
393 }
394
395 /**
396  * efi_net_nvdata() - read or write NVRAM
397  *
398  * This function implements the GetStatus service of the Simple Network
399  * Protocol. See the UEFI spec for details.
400  *
401  * @this:               the instance of the Simple Network Protocol
402  * @readwrite:          true for read, false for write
403  * @offset:             offset in NVRAM
404  * @buffer_size:        size of buffer
405  * @buffer:             buffer
406  * Return:              status code
407  */
408 static efi_status_t EFIAPI efi_net_nvdata(struct efi_simple_network *this,
409                                           int read_write, ulong offset,
410                                           ulong buffer_size, char *buffer)
411 {
412         EFI_ENTRY("%p, %x, %lx, %lx, %p", this, read_write, offset, buffer_size,
413                   buffer);
414
415         return EFI_EXIT(EFI_UNSUPPORTED);
416 }
417
418 /**
419  * efi_net_get_status() - get interrupt status
420  *
421  * This function implements the GetStatus service of the Simple Network
422  * Protocol. See the UEFI spec for details.
423  *
424  * @this:               the instance of the Simple Network Protocol
425  * @int_status:         interface status
426  * @txbuf:              transmission buffer
427  */
428 static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
429                                               u32 *int_status, void **txbuf)
430 {
431         efi_status_t ret = EFI_SUCCESS;
432
433         EFI_ENTRY("%p, %p, %p", this, int_status, txbuf);
434
435         efi_timer_check();
436
437         /* Check parameters */
438         if (!this) {
439                 ret = EFI_INVALID_PARAMETER;
440                 goto out;
441         }
442
443         switch (this->mode->state) {
444         case EFI_NETWORK_STOPPED:
445                 ret = EFI_NOT_STARTED;
446                 goto out;
447         case EFI_NETWORK_STARTED:
448                 ret = EFI_DEVICE_ERROR;
449                 goto out;
450         default:
451                 break;
452         }
453
454         if (int_status) {
455                 *int_status = this->int_status;
456                 this->int_status = 0;
457         }
458         if (txbuf)
459                 *txbuf = new_tx_packet;
460
461         new_tx_packet = NULL;
462 out:
463         return EFI_EXIT(ret);
464 }
465
466 /**
467  * efi_net_transmit() - transmit a packet
468  *
469  * This function implements the Transmit service of the Simple Network Protocol.
470  * See the UEFI spec for details.
471  *
472  * @this:               the instance of the Simple Network Protocol
473  * @header_size:        size of the media header
474  * @buffer_size:        size of the buffer to receive the packet
475  * @buffer:             buffer to receive the packet
476  * @src_addr:           source hardware MAC address
477  * @dest_addr:          destination hardware MAC address
478  * @protocol:           type of header to build
479  * Return:              status code
480  */
481 static efi_status_t EFIAPI efi_net_transmit
482                 (struct efi_simple_network *this, size_t header_size,
483                  size_t buffer_size, void *buffer,
484                  struct efi_mac_address *src_addr,
485                  struct efi_mac_address *dest_addr, u16 *protocol)
486 {
487         efi_status_t ret = EFI_SUCCESS;
488
489         EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this,
490                   (unsigned long)header_size, (unsigned long)buffer_size,
491                   buffer, src_addr, dest_addr, protocol);
492
493         efi_timer_check();
494
495         /* Check parameters */
496         if (!this || !buffer) {
497                 ret = EFI_INVALID_PARAMETER;
498                 goto out;
499         }
500
501         /* We do not support jumbo packets */
502         if (buffer_size > PKTSIZE_ALIGN) {
503                 ret = EFI_INVALID_PARAMETER;
504                 goto out;
505         }
506
507         /* At least the IP header has to fit into the buffer */
508         if (buffer_size < this->mode->media_header_size) {
509                 ret = EFI_BUFFER_TOO_SMALL;
510                 goto out;
511         }
512
513         /*
514          * TODO:
515          * Support VLANs. Use net_set_ether() for copying the header. Use a
516          * U_BOOT_ENV_CALLBACK to update the media header size.
517          */
518         if (header_size) {
519                 struct ethernet_hdr *header = buffer;
520
521                 if (!dest_addr || !protocol ||
522                     header_size != this->mode->media_header_size) {
523                         ret = EFI_INVALID_PARAMETER;
524                         goto out;
525                 }
526                 if (!src_addr)
527                         src_addr = &this->mode->current_address;
528
529                 memcpy(header->et_dest, dest_addr, ARP_HLEN);
530                 memcpy(header->et_src, src_addr, ARP_HLEN);
531                 header->et_protlen = htons(*protocol);
532         }
533
534         switch (this->mode->state) {
535         case EFI_NETWORK_STOPPED:
536                 ret = EFI_NOT_STARTED;
537                 goto out;
538         case EFI_NETWORK_STARTED:
539                 ret = EFI_DEVICE_ERROR;
540                 goto out;
541         default:
542                 break;
543         }
544
545         /* Ethernet packets always fit, just bounce */
546         memcpy(transmit_buffer, buffer, buffer_size);
547         net_send_packet(transmit_buffer, buffer_size);
548
549         new_tx_packet = buffer;
550         this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
551 out:
552         return EFI_EXIT(ret);
553 }
554
555 /**
556  * efi_net_receive() - receive a packet from a network interface
557  *
558  * This function implements the Receive service of the Simple Network Protocol.
559  * See the UEFI spec for details.
560  *
561  * @this:               the instance of the Simple Network Protocol
562  * @header_size:        size of the media header
563  * @buffer_size:        size of the buffer to receive the packet
564  * @buffer:             buffer to receive the packet
565  * @src_addr:           source MAC address
566  * @dest_addr:          destination MAC address
567  * @protocol:           protocol
568  * Return:              status code
569  */
570 static efi_status_t EFIAPI efi_net_receive
571                 (struct efi_simple_network *this, size_t *header_size,
572                  size_t *buffer_size, void *buffer,
573                  struct efi_mac_address *src_addr,
574                  struct efi_mac_address *dest_addr, u16 *protocol)
575 {
576         efi_status_t ret = EFI_SUCCESS;
577         struct ethernet_hdr *eth_hdr;
578         size_t hdr_size = sizeof(struct ethernet_hdr);
579         u16 protlen;
580
581         EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size,
582                   buffer_size, buffer, src_addr, dest_addr, protocol);
583
584         /* Execute events */
585         efi_timer_check();
586
587         /* Check parameters */
588         if (!this || !buffer || !buffer_size) {
589                 ret = EFI_INVALID_PARAMETER;
590                 goto out;
591         }
592
593         switch (this->mode->state) {
594         case EFI_NETWORK_STOPPED:
595                 ret = EFI_NOT_STARTED;
596                 goto out;
597         case EFI_NETWORK_STARTED:
598                 ret = EFI_DEVICE_ERROR;
599                 goto out;
600         default:
601                 break;
602         }
603
604         if (!new_rx_packet) {
605                 ret = EFI_NOT_READY;
606                 goto out;
607         }
608         /* Fill export parameters */
609         eth_hdr = (struct ethernet_hdr *)net_rx_packet;
610         protlen = ntohs(eth_hdr->et_protlen);
611         if (protlen == 0x8100) {
612                 hdr_size += 4;
613                 protlen = ntohs(*(u16 *)&net_rx_packet[hdr_size - 2]);
614         }
615         if (header_size)
616                 *header_size = hdr_size;
617         if (dest_addr)
618                 memcpy(dest_addr, eth_hdr->et_dest, ARP_HLEN);
619         if (src_addr)
620                 memcpy(src_addr, eth_hdr->et_src, ARP_HLEN);
621         if (protocol)
622                 *protocol = protlen;
623         if (*buffer_size < net_rx_packet_len) {
624                 /* Packet doesn't fit, try again with bigger buffer */
625                 *buffer_size = net_rx_packet_len;
626                 ret = EFI_BUFFER_TOO_SMALL;
627                 goto out;
628         }
629         /* Copy packet */
630         memcpy(buffer, net_rx_packet, net_rx_packet_len);
631         *buffer_size = net_rx_packet_len;
632         new_rx_packet = 0;
633         this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
634 out:
635         return EFI_EXIT(ret);
636 }
637
638 /**
639  * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address
640  *
641  * This function is called by dhcp_handler().
642  */
643 void efi_net_set_dhcp_ack(void *pkt, int len)
644 {
645         int maxsize = sizeof(*dhcp_ack);
646
647         if (!dhcp_ack)
648                 dhcp_ack = malloc(maxsize);
649
650         memcpy(dhcp_ack, pkt, min(len, maxsize));
651 }
652
653 /**
654  * efi_net_push() - callback for received network packet
655  *
656  * This function is called when a network packet is received by eth_rx().
657  *
658  * @pkt:        network packet
659  * @len:        length
660  */
661 static void efi_net_push(void *pkt, int len)
662 {
663         new_rx_packet = true;
664 }
665
666 /**
667  * efi_network_timer_notify() - check if a new network packet has been received
668  *
669  * This notification function is called in every timer cycle.
670  *
671  * @event       the event for which this notification function is registered
672  * @context     event context - not used in this function
673  */
674 static void EFIAPI efi_network_timer_notify(struct efi_event *event,
675                                             void *context)
676 {
677         struct efi_simple_network *this = (struct efi_simple_network *)context;
678
679         EFI_ENTRY("%p, %p", event, context);
680
681         /*
682          * Some network drivers do not support calling eth_rx() before
683          * initialization.
684          */
685         if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
686                 goto out;
687
688         if (!new_rx_packet) {
689                 push_packet = efi_net_push;
690                 eth_rx();
691                 push_packet = NULL;
692                 if (new_rx_packet) {
693                         /* Check that we at least received an Ethernet header */
694                         if (net_rx_packet_len >=
695                             sizeof(struct ethernet_hdr)) {
696                                 this->int_status |=
697                                         EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
698                                 wait_for_packet->is_signaled = true;
699                         } else {
700                                 new_rx_packet = 0;
701                         }
702                 }
703         }
704 out:
705         EFI_EXIT(EFI_SUCCESS);
706 }
707
708 static efi_status_t EFIAPI efi_pxe_base_code_start(
709                                 struct efi_pxe_base_code_protocol *this,
710                                 u8 use_ipv6)
711 {
712         return EFI_UNSUPPORTED;
713 }
714
715 static efi_status_t EFIAPI efi_pxe_base_code_stop(
716                                 struct efi_pxe_base_code_protocol *this)
717 {
718         return EFI_UNSUPPORTED;
719 }
720
721 static efi_status_t EFIAPI efi_pxe_base_code_dhcp(
722                                 struct efi_pxe_base_code_protocol *this,
723                                 u8 sort_offers)
724 {
725         return EFI_UNSUPPORTED;
726 }
727
728 static efi_status_t EFIAPI efi_pxe_base_code_discover(
729                                 struct efi_pxe_base_code_protocol *this,
730                                 u16 type, u16 *layer, u8 bis,
731                                 struct efi_pxe_base_code_discover_info *info)
732 {
733         return EFI_UNSUPPORTED;
734 }
735
736 static efi_status_t EFIAPI efi_pxe_base_code_mtftp(
737                                 struct efi_pxe_base_code_protocol *this,
738                                 u32 operation, void *buffer_ptr,
739                                 u8 overwrite, efi_uintn_t *buffer_size,
740                                 struct efi_ip_address server_ip, char *filename,
741                                 struct efi_pxe_base_code_mtftp_info *info,
742                                 u8 dont_use_buffer)
743 {
744         return EFI_UNSUPPORTED;
745 }
746
747 static efi_status_t EFIAPI efi_pxe_base_code_udp_write(
748                                 struct efi_pxe_base_code_protocol *this,
749                                 u16 op_flags, struct efi_ip_address *dest_ip,
750                                 u16 *dest_port,
751                                 struct efi_ip_address *gateway_ip,
752                                 struct efi_ip_address *src_ip, u16 *src_port,
753                                 efi_uintn_t *header_size, void *header_ptr,
754                                 efi_uintn_t *buffer_size, void *buffer_ptr)
755 {
756         return EFI_UNSUPPORTED;
757 }
758
759 static efi_status_t EFIAPI efi_pxe_base_code_udp_read(
760                                 struct efi_pxe_base_code_protocol *this,
761                                 u16 op_flags, struct efi_ip_address *dest_ip,
762                                 u16 *dest_port, struct efi_ip_address *src_ip,
763                                 u16 *src_port, efi_uintn_t *header_size,
764                                 void *header_ptr, efi_uintn_t *buffer_size,
765                                 void *buffer_ptr)
766 {
767         return EFI_UNSUPPORTED;
768 }
769
770 static efi_status_t EFIAPI efi_pxe_base_code_set_ip_filter(
771                                 struct efi_pxe_base_code_protocol *this,
772                                 struct efi_pxe_base_code_filter *new_filter)
773 {
774         return EFI_UNSUPPORTED;
775 }
776
777 static efi_status_t EFIAPI efi_pxe_base_code_arp(
778                                 struct efi_pxe_base_code_protocol *this,
779                                 struct efi_ip_address *ip_addr,
780                                 struct efi_mac_address *mac_addr)
781 {
782         return EFI_UNSUPPORTED;
783 }
784
785 static efi_status_t EFIAPI efi_pxe_base_code_set_parameters(
786                                 struct efi_pxe_base_code_protocol *this,
787                                 u8 *new_auto_arp, u8 *new_send_guid,
788                                 u8 *new_ttl, u8 *new_tos,
789                                 u8 *new_make_callback)
790 {
791         return EFI_UNSUPPORTED;
792 }
793
794 static efi_status_t EFIAPI efi_pxe_base_code_set_station_ip(
795                                 struct efi_pxe_base_code_protocol *this,
796                                 struct efi_ip_address *new_station_ip,
797                                 struct efi_ip_address *new_subnet_mask)
798 {
799         return EFI_UNSUPPORTED;
800 }
801
802 static efi_status_t EFIAPI efi_pxe_base_code_set_packets(
803                                 struct efi_pxe_base_code_protocol *this,
804                                 u8 *new_dhcp_discover_valid,
805                                 u8 *new_dhcp_ack_received,
806                                 u8 *new_proxy_offer_received,
807                                 u8 *new_pxe_discover_valid,
808                                 u8 *new_pxe_reply_received,
809                                 u8 *new_pxe_bis_reply_received,
810                                 EFI_PXE_BASE_CODE_PACKET *new_dchp_discover,
811                                 EFI_PXE_BASE_CODE_PACKET *new_dhcp_acc,
812                                 EFI_PXE_BASE_CODE_PACKET *new_proxy_offer,
813                                 EFI_PXE_BASE_CODE_PACKET *new_pxe_discover,
814                                 EFI_PXE_BASE_CODE_PACKET *new_pxe_reply,
815                                 EFI_PXE_BASE_CODE_PACKET *new_pxe_bis_reply)
816 {
817         return EFI_UNSUPPORTED;
818 }
819
820 /**
821  * efi_net_register() - register the simple network protocol
822  *
823  * This gets called from do_bootefi_exec().
824  */
825 efi_status_t efi_net_register(void)
826 {
827         struct efi_net_obj *netobj = NULL;
828         efi_status_t r;
829
830         if (!eth_get_dev()) {
831                 /* No network device active, don't expose any */
832                 return EFI_SUCCESS;
833         }
834
835         /* We only expose the "active" network device, so one is enough */
836         netobj = calloc(1, sizeof(*netobj));
837         if (!netobj)
838                 goto out_of_resources;
839
840         /* Allocate an aligned transmit buffer */
841         transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
842         if (!transmit_buffer)
843                 goto out_of_resources;
844         transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
845
846         /* Hook net up to the device list */
847         efi_add_handle(&netobj->header);
848
849         /* Fill in object data */
850         r = efi_add_protocol(&netobj->header, &efi_net_guid,
851                              &netobj->net);
852         if (r != EFI_SUCCESS)
853                 goto failure_to_add_protocol;
854         r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
855                              efi_dp_from_eth());
856         if (r != EFI_SUCCESS)
857                 goto failure_to_add_protocol;
858         r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
859                              &netobj->pxe);
860         if (r != EFI_SUCCESS)
861                 goto failure_to_add_protocol;
862         netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
863         netobj->net.start = efi_net_start;
864         netobj->net.stop = efi_net_stop;
865         netobj->net.initialize = efi_net_initialize;
866         netobj->net.reset = efi_net_reset;
867         netobj->net.shutdown = efi_net_shutdown;
868         netobj->net.receive_filters = efi_net_receive_filters;
869         netobj->net.station_address = efi_net_station_address;
870         netobj->net.statistics = efi_net_statistics;
871         netobj->net.mcastiptomac = efi_net_mcastiptomac;
872         netobj->net.nvdata = efi_net_nvdata;
873         netobj->net.get_status = efi_net_get_status;
874         netobj->net.transmit = efi_net_transmit;
875         netobj->net.receive = efi_net_receive;
876         netobj->net.mode = &netobj->net_mode;
877         netobj->net_mode.state = EFI_NETWORK_STOPPED;
878         memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
879         netobj->net_mode.hwaddr_size = ARP_HLEN;
880         netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
881         netobj->net_mode.max_packet_size = PKTSIZE;
882         netobj->net_mode.if_type = ARP_ETHER;
883
884         netobj->pxe.revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;
885         netobj->pxe.start = efi_pxe_base_code_start;
886         netobj->pxe.stop = efi_pxe_base_code_stop;
887         netobj->pxe.dhcp = efi_pxe_base_code_dhcp;
888         netobj->pxe.discover = efi_pxe_base_code_discover;
889         netobj->pxe.mtftp = efi_pxe_base_code_mtftp;
890         netobj->pxe.udp_write = efi_pxe_base_code_udp_write;
891         netobj->pxe.udp_read = efi_pxe_base_code_udp_read;
892         netobj->pxe.set_ip_filter = efi_pxe_base_code_set_ip_filter;
893         netobj->pxe.arp = efi_pxe_base_code_arp;
894         netobj->pxe.set_parameters = efi_pxe_base_code_set_parameters;
895         netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip;
896         netobj->pxe.set_packets = efi_pxe_base_code_set_packets;
897         netobj->pxe.mode = &netobj->pxe_mode;
898         if (dhcp_ack)
899                 netobj->pxe_mode.dhcp_ack = *dhcp_ack;
900
901         /*
902          * Create WaitForPacket event.
903          */
904         r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
905                              efi_network_timer_notify, NULL, NULL,
906                              &wait_for_packet);
907         if (r != EFI_SUCCESS) {
908                 printf("ERROR: Failed to register network event\n");
909                 return r;
910         }
911         netobj->net.wait_for_packet = wait_for_packet;
912         /*
913          * Create a timer event.
914          *
915          * The notification function is used to check if a new network packet
916          * has been received.
917          *
918          * iPXE is running at TPL_CALLBACK most of the time. Use a higher TPL.
919          */
920         r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
921                              efi_network_timer_notify, &netobj->net, NULL,
922                              &network_timer_event);
923         if (r != EFI_SUCCESS) {
924                 printf("ERROR: Failed to register network event\n");
925                 return r;
926         }
927         /* Network is time critical, create event in every timer cycle */
928         r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0);
929         if (r != EFI_SUCCESS) {
930                 printf("ERROR: Failed to set network timer\n");
931                 return r;
932         }
933
934         return EFI_SUCCESS;
935 failure_to_add_protocol:
936         printf("ERROR: Failure to add protocol\n");
937         return r;
938 out_of_resources:
939         free(netobj);
940         /* free(transmit_buffer) not needed yet */
941         printf("ERROR: Out of memory\n");
942         return EFI_OUT_OF_RESOURCES;
943 }