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