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