66c1898940fce92e881a15ce026e820cd834b373
[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 Statistics 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_ENTRY("%p, %x, %p, %p", this, ipv6, ip, mac);
351
352         return EFI_EXIT(EFI_INVALID_PARAMETER);
353 }
354
355 /**
356  * efi_net_nvdata() - read or write NVRAM
357  *
358  * This function implements the GetStatus service of the Simple Network
359  * Protocol. See the UEFI spec for details.
360  *
361  * @this:               the instance of the Simple Network Protocol
362  * @readwrite:          true for read, false for write
363  * @offset:             offset in NVRAM
364  * @buffer_size:        size of buffer
365  * @buffer:             buffer
366  * Return:              status code
367  */
368 static efi_status_t EFIAPI efi_net_nvdata(struct efi_simple_network *this,
369                                           int read_write, ulong offset,
370                                           ulong buffer_size, char *buffer)
371 {
372         EFI_ENTRY("%p, %x, %lx, %lx, %p", this, read_write, offset, buffer_size,
373                   buffer);
374
375         return EFI_EXIT(EFI_UNSUPPORTED);
376 }
377
378 /**
379  * efi_net_get_status() - get interrupt status
380  *
381  * This function implements the GetStatus service of the Simple Network
382  * Protocol. See the UEFI spec for details.
383  *
384  * @this:               the instance of the Simple Network Protocol
385  * @int_status:         interface status
386  * @txbuf:              transmission buffer
387  */
388 static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
389                                               u32 *int_status, void **txbuf)
390 {
391         efi_status_t ret = EFI_SUCCESS;
392
393         EFI_ENTRY("%p, %p, %p", this, int_status, txbuf);
394
395         efi_timer_check();
396
397         /* Check parameters */
398         if (!this) {
399                 ret = EFI_INVALID_PARAMETER;
400                 goto out;
401         }
402
403         switch (this->mode->state) {
404         case EFI_NETWORK_STOPPED:
405                 ret = EFI_NOT_STARTED;
406                 goto out;
407         case EFI_NETWORK_STARTED:
408                 ret = EFI_DEVICE_ERROR;
409                 goto out;
410         default:
411                 break;
412         }
413
414         if (int_status) {
415                 *int_status = this->int_status;
416                 this->int_status = 0;
417         }
418         if (txbuf)
419                 *txbuf = new_tx_packet;
420
421         new_tx_packet = NULL;
422 out:
423         return EFI_EXIT(ret);
424 }
425
426 /**
427  * efi_net_transmit() - transmit a packet
428  *
429  * This function implements the Transmit service of the Simple Network Protocol.
430  * See the UEFI spec for details.
431  *
432  * @this:               the instance of the Simple Network Protocol
433  * @header_size:        size of the media header
434  * @buffer_size:        size of the buffer to receive the packet
435  * @buffer:             buffer to receive the packet
436  * @src_addr:           source hardware MAC address
437  * @dest_addr:          destination hardware MAC address
438  * @protocol:           type of header to build
439  * Return:              status code
440  */
441 static efi_status_t EFIAPI efi_net_transmit
442                 (struct efi_simple_network *this, size_t header_size,
443                  size_t buffer_size, void *buffer,
444                  struct efi_mac_address *src_addr,
445                  struct efi_mac_address *dest_addr, u16 *protocol)
446 {
447         efi_status_t ret = EFI_SUCCESS;
448
449         EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this,
450                   (unsigned long)header_size, (unsigned long)buffer_size,
451                   buffer, src_addr, dest_addr, protocol);
452
453         efi_timer_check();
454
455         /* Check parameters */
456         if (!this || !buffer) {
457                 ret = EFI_INVALID_PARAMETER;
458                 goto out;
459         }
460
461         /* We do not support jumbo packets */
462         if (buffer_size > PKTSIZE_ALIGN) {
463                 ret = EFI_INVALID_PARAMETER;
464                 goto out;
465         }
466
467         /* At least the IP header has to fit into the buffer */
468         if (buffer_size < this->mode->media_header_size) {
469                 ret = EFI_BUFFER_TOO_SMALL;
470                 goto out;
471         }
472
473         /*
474          * TODO:
475          * Support VLANs. Use net_set_ether() for copying the header. Use a
476          * U_BOOT_ENV_CALLBACK to update the media header size.
477          */
478         if (header_size) {
479                 struct ethernet_hdr *header = buffer;
480
481                 if (!dest_addr || !protocol ||
482                     header_size != this->mode->media_header_size) {
483                         ret = EFI_INVALID_PARAMETER;
484                         goto out;
485                 }
486                 if (!src_addr)
487                         src_addr = &this->mode->current_address;
488
489                 memcpy(header->et_dest, dest_addr, ARP_HLEN);
490                 memcpy(header->et_src, src_addr, ARP_HLEN);
491                 header->et_protlen = htons(*protocol);
492         }
493
494         switch (this->mode->state) {
495         case EFI_NETWORK_STOPPED:
496                 ret = EFI_NOT_STARTED;
497                 goto out;
498         case EFI_NETWORK_STARTED:
499                 ret = EFI_DEVICE_ERROR;
500                 goto out;
501         default:
502                 break;
503         }
504
505         /* Ethernet packets always fit, just bounce */
506         memcpy(transmit_buffer, buffer, buffer_size);
507         net_send_packet(transmit_buffer, buffer_size);
508
509         new_tx_packet = buffer;
510         this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
511 out:
512         return EFI_EXIT(ret);
513 }
514
515 /**
516  * efi_net_receive() - receive a packet from a network interface
517  *
518  * This function implements the Receive service of the Simple Network Protocol.
519  * See the UEFI spec for details.
520  *
521  * @this:               the instance of the Simple Network Protocol
522  * @header_size:        size of the media header
523  * @buffer_size:        size of the buffer to receive the packet
524  * @buffer:             buffer to receive the packet
525  * @src_addr:           source MAC address
526  * @dest_addr:          destination MAC address
527  * @protocol:           protocol
528  * Return:              status code
529  */
530 static efi_status_t EFIAPI efi_net_receive
531                 (struct efi_simple_network *this, size_t *header_size,
532                  size_t *buffer_size, void *buffer,
533                  struct efi_mac_address *src_addr,
534                  struct efi_mac_address *dest_addr, u16 *protocol)
535 {
536         efi_status_t ret = EFI_SUCCESS;
537         struct ethernet_hdr *eth_hdr;
538         size_t hdr_size = sizeof(struct ethernet_hdr);
539         u16 protlen;
540
541         EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size,
542                   buffer_size, buffer, src_addr, dest_addr, protocol);
543
544         /* Execute events */
545         efi_timer_check();
546
547         /* Check parameters */
548         if (!this || !buffer || !buffer_size) {
549                 ret = EFI_INVALID_PARAMETER;
550                 goto out;
551         }
552
553         switch (this->mode->state) {
554         case EFI_NETWORK_STOPPED:
555                 ret = EFI_NOT_STARTED;
556                 goto out;
557         case EFI_NETWORK_STARTED:
558                 ret = EFI_DEVICE_ERROR;
559                 goto out;
560         default:
561                 break;
562         }
563
564         if (!new_rx_packet) {
565                 ret = EFI_NOT_READY;
566                 goto out;
567         }
568         /* Fill export parameters */
569         eth_hdr = (struct ethernet_hdr *)net_rx_packet;
570         protlen = ntohs(eth_hdr->et_protlen);
571         if (protlen == 0x8100) {
572                 hdr_size += 4;
573                 protlen = ntohs(*(u16 *)&net_rx_packet[hdr_size - 2]);
574         }
575         if (header_size)
576                 *header_size = hdr_size;
577         if (dest_addr)
578                 memcpy(dest_addr, eth_hdr->et_dest, ARP_HLEN);
579         if (src_addr)
580                 memcpy(src_addr, eth_hdr->et_src, ARP_HLEN);
581         if (protocol)
582                 *protocol = protlen;
583         if (*buffer_size < net_rx_packet_len) {
584                 /* Packet doesn't fit, try again with bigger buffer */
585                 *buffer_size = net_rx_packet_len;
586                 ret = EFI_BUFFER_TOO_SMALL;
587                 goto out;
588         }
589         /* Copy packet */
590         memcpy(buffer, net_rx_packet, net_rx_packet_len);
591         *buffer_size = net_rx_packet_len;
592         new_rx_packet = 0;
593         this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
594 out:
595         return EFI_EXIT(ret);
596 }
597
598 /**
599  * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address
600  *
601  * This function is called by dhcp_handler().
602  */
603 void efi_net_set_dhcp_ack(void *pkt, int len)
604 {
605         int maxsize = sizeof(*dhcp_ack);
606
607         if (!dhcp_ack)
608                 dhcp_ack = malloc(maxsize);
609
610         memcpy(dhcp_ack, pkt, min(len, maxsize));
611 }
612
613 /**
614  * efi_net_push() - callback for received network packet
615  *
616  * This function is called when a network packet is received by eth_rx().
617  *
618  * @pkt:        network packet
619  * @len:        length
620  */
621 static void efi_net_push(void *pkt, int len)
622 {
623         new_rx_packet = true;
624 }
625
626 /**
627  * efi_network_timer_notify() - check if a new network packet has been received
628  *
629  * This notification function is called in every timer cycle.
630  *
631  * @event       the event for which this notification function is registered
632  * @context     event context - not used in this function
633  */
634 static void EFIAPI efi_network_timer_notify(struct efi_event *event,
635                                             void *context)
636 {
637         struct efi_simple_network *this = (struct efi_simple_network *)context;
638
639         EFI_ENTRY("%p, %p", event, context);
640
641         /*
642          * Some network drivers do not support calling eth_rx() before
643          * initialization.
644          */
645         if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
646                 goto out;
647
648         if (!new_rx_packet) {
649                 push_packet = efi_net_push;
650                 eth_rx();
651                 push_packet = NULL;
652                 if (new_rx_packet) {
653                         /* Check that we at least received an Ethernet header */
654                         if (net_rx_packet_len >=
655                             sizeof(struct ethernet_hdr)) {
656                                 this->int_status |=
657                                         EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
658                                 wait_for_packet->is_signaled = true;
659                         } else {
660                                 new_rx_packet = 0;
661                         }
662                 }
663         }
664 out:
665         EFI_EXIT(EFI_SUCCESS);
666 }
667
668 static efi_status_t EFIAPI efi_pxe_base_code_start(
669                                 struct efi_pxe_base_code_protocol *this,
670                                 u8 use_ipv6)
671 {
672         return EFI_UNSUPPORTED;
673 }
674
675 static efi_status_t EFIAPI efi_pxe_base_code_stop(
676                                 struct efi_pxe_base_code_protocol *this)
677 {
678         return EFI_UNSUPPORTED;
679 }
680
681 static efi_status_t EFIAPI efi_pxe_base_code_dhcp(
682                                 struct efi_pxe_base_code_protocol *this,
683                                 u8 sort_offers)
684 {
685         return EFI_UNSUPPORTED;
686 }
687
688 static efi_status_t EFIAPI efi_pxe_base_code_discover(
689                                 struct efi_pxe_base_code_protocol *this,
690                                 u16 type, u16 *layer, u8 bis,
691                                 struct efi_pxe_base_code_discover_info *info)
692 {
693         return EFI_UNSUPPORTED;
694 }
695
696 static efi_status_t EFIAPI efi_pxe_base_code_mtftp(
697                                 struct efi_pxe_base_code_protocol *this,
698                                 u32 operation, void *buffer_ptr,
699                                 u8 overwrite, efi_uintn_t *buffer_size,
700                                 struct efi_ip_address server_ip, char *filename,
701                                 struct efi_pxe_base_code_mtftp_info *info,
702                                 u8 dont_use_buffer)
703 {
704         return EFI_UNSUPPORTED;
705 }
706
707 static efi_status_t EFIAPI efi_pxe_base_code_udp_write(
708                                 struct efi_pxe_base_code_protocol *this,
709                                 u16 op_flags, struct efi_ip_address *dest_ip,
710                                 u16 *dest_port,
711                                 struct efi_ip_address *gateway_ip,
712                                 struct efi_ip_address *src_ip, u16 *src_port,
713                                 efi_uintn_t *header_size, void *header_ptr,
714                                 efi_uintn_t *buffer_size, void *buffer_ptr)
715 {
716         return EFI_UNSUPPORTED;
717 }
718
719 static efi_status_t EFIAPI efi_pxe_base_code_udp_read(
720                                 struct efi_pxe_base_code_protocol *this,
721                                 u16 op_flags, struct efi_ip_address *dest_ip,
722                                 u16 *dest_port, struct efi_ip_address *src_ip,
723                                 u16 *src_port, efi_uintn_t *header_size,
724                                 void *header_ptr, efi_uintn_t *buffer_size,
725                                 void *buffer_ptr)
726 {
727         return EFI_UNSUPPORTED;
728 }
729
730 static efi_status_t EFIAPI efi_pxe_base_code_set_ip_filter(
731                                 struct efi_pxe_base_code_protocol *this,
732                                 struct efi_pxe_base_code_filter *new_filter)
733 {
734         return EFI_UNSUPPORTED;
735 }
736
737 static efi_status_t EFIAPI efi_pxe_base_code_arp(
738                                 struct efi_pxe_base_code_protocol *this,
739                                 struct efi_ip_address *ip_addr,
740                                 struct efi_mac_address *mac_addr)
741 {
742         return EFI_UNSUPPORTED;
743 }
744
745 static efi_status_t EFIAPI efi_pxe_base_code_set_parameters(
746                                 struct efi_pxe_base_code_protocol *this,
747                                 u8 *new_auto_arp, u8 *new_send_guid,
748                                 u8 *new_ttl, u8 *new_tos,
749                                 u8 *new_make_callback)
750 {
751         return EFI_UNSUPPORTED;
752 }
753
754 static efi_status_t EFIAPI efi_pxe_base_code_set_station_ip(
755                                 struct efi_pxe_base_code_protocol *this,
756                                 struct efi_ip_address *new_station_ip,
757                                 struct efi_ip_address *new_subnet_mask)
758 {
759         return EFI_UNSUPPORTED;
760 }
761
762 static efi_status_t EFIAPI efi_pxe_base_code_set_packets(
763                                 struct efi_pxe_base_code_protocol *this,
764                                 u8 *new_dhcp_discover_valid,
765                                 u8 *new_dhcp_ack_received,
766                                 u8 *new_proxy_offer_received,
767                                 u8 *new_pxe_discover_valid,
768                                 u8 *new_pxe_reply_received,
769                                 u8 *new_pxe_bis_reply_received,
770                                 EFI_PXE_BASE_CODE_PACKET *new_dchp_discover,
771                                 EFI_PXE_BASE_CODE_PACKET *new_dhcp_acc,
772                                 EFI_PXE_BASE_CODE_PACKET *new_proxy_offer,
773                                 EFI_PXE_BASE_CODE_PACKET *new_pxe_discover,
774                                 EFI_PXE_BASE_CODE_PACKET *new_pxe_reply,
775                                 EFI_PXE_BASE_CODE_PACKET *new_pxe_bis_reply)
776 {
777         return EFI_UNSUPPORTED;
778 }
779
780 /**
781  * efi_net_register() - register the simple network protocol
782  *
783  * This gets called from do_bootefi_exec().
784  */
785 efi_status_t efi_net_register(void)
786 {
787         struct efi_net_obj *netobj = NULL;
788         efi_status_t r;
789
790         if (!eth_get_dev()) {
791                 /* No network device active, don't expose any */
792                 return EFI_SUCCESS;
793         }
794
795         /* We only expose the "active" network device, so one is enough */
796         netobj = calloc(1, sizeof(*netobj));
797         if (!netobj)
798                 goto out_of_resources;
799
800         /* Allocate an aligned transmit buffer */
801         transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
802         if (!transmit_buffer)
803                 goto out_of_resources;
804         transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
805
806         /* Hook net up to the device list */
807         efi_add_handle(&netobj->header);
808
809         /* Fill in object data */
810         r = efi_add_protocol(&netobj->header, &efi_net_guid,
811                              &netobj->net);
812         if (r != EFI_SUCCESS)
813                 goto failure_to_add_protocol;
814         r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
815                              efi_dp_from_eth());
816         if (r != EFI_SUCCESS)
817                 goto failure_to_add_protocol;
818         r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
819                              &netobj->pxe);
820         if (r != EFI_SUCCESS)
821                 goto failure_to_add_protocol;
822         netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
823         netobj->net.start = efi_net_start;
824         netobj->net.stop = efi_net_stop;
825         netobj->net.initialize = efi_net_initialize;
826         netobj->net.reset = efi_net_reset;
827         netobj->net.shutdown = efi_net_shutdown;
828         netobj->net.receive_filters = efi_net_receive_filters;
829         netobj->net.station_address = efi_net_station_address;
830         netobj->net.statistics = efi_net_statistics;
831         netobj->net.mcastiptomac = efi_net_mcastiptomac;
832         netobj->net.nvdata = efi_net_nvdata;
833         netobj->net.get_status = efi_net_get_status;
834         netobj->net.transmit = efi_net_transmit;
835         netobj->net.receive = efi_net_receive;
836         netobj->net.mode = &netobj->net_mode;
837         netobj->net_mode.state = EFI_NETWORK_STOPPED;
838         memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
839         netobj->net_mode.hwaddr_size = ARP_HLEN;
840         netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
841         netobj->net_mode.max_packet_size = PKTSIZE;
842         netobj->net_mode.if_type = ARP_ETHER;
843
844         netobj->pxe.revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;
845         netobj->pxe.start = efi_pxe_base_code_start;
846         netobj->pxe.stop = efi_pxe_base_code_stop;
847         netobj->pxe.dhcp = efi_pxe_base_code_dhcp;
848         netobj->pxe.discover = efi_pxe_base_code_discover;
849         netobj->pxe.mtftp = efi_pxe_base_code_mtftp;
850         netobj->pxe.udp_write = efi_pxe_base_code_udp_write;
851         netobj->pxe.udp_read = efi_pxe_base_code_udp_read;
852         netobj->pxe.set_ip_filter = efi_pxe_base_code_set_ip_filter;
853         netobj->pxe.arp = efi_pxe_base_code_arp;
854         netobj->pxe.set_parameters = efi_pxe_base_code_set_parameters;
855         netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip;
856         netobj->pxe.set_packets = efi_pxe_base_code_set_packets;
857         netobj->pxe.mode = &netobj->pxe_mode;
858         if (dhcp_ack)
859                 netobj->pxe_mode.dhcp_ack = *dhcp_ack;
860
861         /*
862          * Create WaitForPacket event.
863          */
864         r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
865                              efi_network_timer_notify, NULL, NULL,
866                              &wait_for_packet);
867         if (r != EFI_SUCCESS) {
868                 printf("ERROR: Failed to register network event\n");
869                 return r;
870         }
871         netobj->net.wait_for_packet = wait_for_packet;
872         /*
873          * Create a timer event.
874          *
875          * The notification function is used to check if a new network packet
876          * has been received.
877          *
878          * iPXE is running at TPL_CALLBACK most of the time. Use a higher TPL.
879          */
880         r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
881                              efi_network_timer_notify, &netobj->net, NULL,
882                              &network_timer_event);
883         if (r != EFI_SUCCESS) {
884                 printf("ERROR: Failed to register network event\n");
885                 return r;
886         }
887         /* Network is time critical, create event in every timer cycle */
888         r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0);
889         if (r != EFI_SUCCESS) {
890                 printf("ERROR: Failed to set network timer\n");
891                 return r;
892         }
893
894         return EFI_SUCCESS;
895 failure_to_add_protocol:
896         printf("ERROR: Failure to add protocol\n");
897         return r;
898 out_of_resources:
899         free(netobj);
900         /* free(transmit_buffer) not needed yet */
901         printf("ERROR: Out of memory\n");
902         return EFI_OUT_OF_RESOURCES;
903 }