aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLothar Felten2018-06-22 15:29:54 -0500
committerJoe Hershberger2018-07-02 14:14:20 -0500
commitd8970dae276377a0beff1c3e9d8b6f805ecf5cd5 (patch)
treeeb3fdb9ef7d734fbca0d0a92ddd30915c52ba44a /net
parent318b5d76b6661dcaf6934b0a925bbcfdf0469069 (diff)
downloadu-boot-d8970dae276377a0beff1c3e9d8b6f805ecf5cd5.tar.gz
u-boot-d8970dae276377a0beff1c3e9d8b6f805ecf5cd5.tar.xz
u-boot-d8970dae276377a0beff1c3e9d8b6f805ecf5cd5.zip
net: Add new wol command - Wake on LAN
Add a new command 'wol': Wait for an incoming Wake-on-LAN packet or time out if no WoL packed is received. If the WoL packet contains a password, it is saved in the environment variable 'wolpassword' using the etherwake format (dot or colon separated decimals). Intended use case: a networked device should boot an alternate image. It's attached to a network on a client site, modifying the DHCP server configuration or setup of a tftp server is not allowed. After power on the device waits a few seconds for a WoL packet. If a packet is received, the device boots the alternate image. Otherwise it boots the default image. This method is a simple way to interact with a system via network even if only the MAC address is known. Tools to send WoL packets are available on all common platforms. Some Ethernet drivers seem to pad the incoming packet. The additional padding bytes might be recognized as Wake-on-LAN password bytes. By default enabled in pengwyn_defconfig. Signed-off-by: Lothar Felten <lothar.felten@gmail.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'net')
-rw-r--r--net/Makefile1
-rw-r--r--net/net.c19
-rw-r--r--net/wol.c96
-rw-r--r--net/wol.h65
4 files changed, 181 insertions, 0 deletions
diff --git a/net/Makefile b/net/Makefile
index 07466879f5..ce36362168 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_RARP) += rarp.o
24obj-$(CONFIG_CMD_SNTP) += sntp.o 24obj-$(CONFIG_CMD_SNTP) += sntp.o
25obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o 25obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
26obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot.o 26obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot.o
27obj-$(CONFIG_CMD_WOL) += wol.o
27 28
28# Disable this warning as it is triggered by: 29# Disable this warning as it is triggered by:
29# sprintf(buf, index ? "foo%d" : "foo", index) 30# sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/net.c b/net/net.c
index b4563a4cab..084269e31e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -78,6 +78,12 @@
78 * - own IP address 78 * - own IP address
79 * We want: - network time 79 * We want: - network time
80 * Next step: none 80 * Next step: none
81 *
82 * WOL:
83 *
84 * Prerequisites: - own ethernet address
85 * We want: - magic packet or timeout
86 * Next step: none
81 */ 87 */
82 88
83 89
@@ -108,6 +114,9 @@
108#if defined(CONFIG_CMD_SNTP) 114#if defined(CONFIG_CMD_SNTP)
109#include "sntp.h" 115#include "sntp.h"
110#endif 116#endif
117#if defined(CONFIG_CMD_WOL)
118#include "wol.h"
119#endif
111 120
112/** BOOTP EXTENTIONS **/ 121/** BOOTP EXTENTIONS **/
113 122
@@ -515,6 +524,11 @@ restart:
515 link_local_start(); 524 link_local_start();
516 break; 525 break;
517#endif 526#endif
527#if defined(CONFIG_CMD_WOL)
528 case WOL:
529 wol_start();
530 break;
531#endif
518 default: 532 default:
519 break; 533 break;
520 } 534 }
@@ -1281,6 +1295,11 @@ void net_process_received_packet(uchar *in_packet, int len)
1281 ntohs(ip->udp_src), 1295 ntohs(ip->udp_src),
1282 ntohs(ip->udp_len) - UDP_HDR_SIZE); 1296 ntohs(ip->udp_len) - UDP_HDR_SIZE);
1283 break; 1297 break;
1298#ifdef CONFIG_CMD_WOL
1299 case PROT_WOL:
1300 wol_receive(ip, len);
1301 break;
1302#endif
1284 } 1303 }
1285} 1304}
1286 1305
diff --git a/net/wol.c b/net/wol.c
new file mode 100644
index 0000000000..946bd91b47
--- /dev/null
+++ b/net/wol.c
@@ -0,0 +1,96 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 Lothar Felten, lothar.felten@gmail.com
4 */
5
6#include <common.h>
7#include <command.h>
8#include <net.h>
9#include <environment.h>
10#include "wol.h"
11
12static ulong wol_timeout = WOL_DEFAULT_TIMEOUT;
13
14/*
15 * Check incoming Wake-on-LAN packet for:
16 * - sync bytes
17 * - sixteen copies of the target MAC address
18 *
19 * @param wol Wake-on-LAN packet
20 * @param len Packet length
21 */
22static int wol_check_magic(struct wol_hdr *wol, unsigned int len)
23{
24 int i;
25
26 if (len < sizeof(struct wol_hdr))
27 return 0;
28
29 for (i = 0; i < WOL_SYNC_COUNT; i++)
30 if (wol->wol_sync[i] != WOL_SYNC_BYTE)
31 return 0;
32
33 for (i = 0; i < WOL_MAC_REPETITIONS; i++)
34 if (memcmp(&wol->wol_dest[i * ARP_HLEN],
35 net_ethaddr, ARP_HLEN) != 0)
36 return 0;
37
38 return 1;
39}
40
41void wol_receive(struct ip_udp_hdr *ip, unsigned int len)
42{
43 struct wol_hdr *wol;
44
45 wol = (struct wol_hdr *)ip;
46
47 if (!wol_check_magic(wol, len))
48 return;
49
50 /* save the optional password using the ether-wake formats */
51 /* don't check for exact length, the packet might have padding */
52 if (len >= (sizeof(struct wol_hdr) + WOL_PASSWORD_6B)) {
53 eth_env_set_enetaddr("wolpassword", wol->wol_passwd);
54 } else if (len >= (sizeof(struct wol_hdr) + WOL_PASSWORD_4B)) {
55 char buffer[16];
56 struct in_addr *ip = (struct in_addr *)(wol->wol_passwd);
57
58 ip_to_string(*ip, buffer);
59 env_set("wolpassword", buffer);
60 }
61 net_set_state(NETLOOP_SUCCESS);
62}
63
64static void wol_udp_handler(uchar *pkt, unsigned int dest, struct in_addr sip,
65 unsigned int src, unsigned int len)
66{
67 struct wol_hdr *wol;
68
69 wol = (struct wol_hdr *)pkt;
70
71 /* UDP destination port must be 0, 7 or 9 */
72 if (dest != 0 && dest != 7 && dest != 9)
73 return;
74
75 if (!wol_check_magic(wol, len))
76 return;
77
78 net_set_state(NETLOOP_SUCCESS);
79}
80
81void wol_set_timeout(ulong timeout)
82{
83 wol_timeout = timeout;
84}
85
86static void wol_timeout_handler(void)
87{
88 eth_halt();
89 net_set_state(NETLOOP_FAIL);
90}
91
92void wol_start(void)
93{
94 net_set_timeout_handler(wol_timeout, wol_timeout_handler);
95 net_set_udp_handler(wol_udp_handler);
96}
diff --git a/net/wol.h b/net/wol.h
new file mode 100644
index 0000000000..ebc81f24b6
--- /dev/null
+++ b/net/wol.h
@@ -0,0 +1,65 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * wol - Wake-on-LAN
4 *
5 * Supports both Wake-on-LAN packet types:
6 * - EtherType 0x0842 packets
7 * - UDP packets on ports 0, 7 and 9.
8 *
9 * Copyright 2018 Lothar Felten, lothar.felten@gmail.com
10 */
11
12#if defined(CONFIG_CMD_WOL)
13
14#ifndef __WOL_H__
15#define __WOL_H__
16
17#include <net.h>
18
19/**********************************************************************/
20
21#define WOL_SYNC_BYTE 0xFF
22#define WOL_SYNC_COUNT 6
23#define WOL_MAC_REPETITIONS 16
24#define WOL_DEFAULT_TIMEOUT 5000
25#define WOL_PASSWORD_4B 4
26#define WOL_PASSWORD_6B 6
27
28/*
29 * Wake-on-LAN header
30 */
31struct wol_hdr {
32 u8 wol_sync[WOL_SYNC_COUNT]; /* sync bytes */
33 u8 wol_dest[WOL_MAC_REPETITIONS * ARP_HLEN]; /* 16x MAC */
34 u8 wol_passwd[0]; /* optional */
35};
36
37/*
38 * Initialize wol (beginning of netloop)
39 */
40void wol_start(void);
41
42/*
43 * Check incoming Wake-on-LAN packet for:
44 * - sync bytes
45 * - sixteen copies of the target MAC address
46 *
47 * Optionally store the four or six byte password in the environment
48 * variable "wolpassword"
49 *
50 * @param ip IP header in the packet
51 * @param len Packet length
52 */
53void wol_receive(struct ip_udp_hdr *ip, unsigned int len);
54
55/*
56 * Set the timeout for the reception of a Wake-on-LAN packet
57 *
58 * @param timeout in milliseconds
59 */
60void wol_set_timeout(ulong timeout);
61
62/**********************************************************************/
63
64#endif /* __WOL_H__ */
65#endif