
This patch adds a new command 'wol': It waits for an incoming Wake-on-LAN packet or times 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 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.
Signed-off-by: Lothar Felten lothar.felten@gmail.com --- net/wol.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/wol.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 net/wol.c create mode 100644 net/wol.h
diff --git a/net/wol.c b/net/wol.c new file mode 100644 index 0000000000..0cedbaed85 --- /dev/null +++ b/net/wol.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Lothar Felten, lothar.felten@gmail.com + */ + +#include <common.h> +#include <command.h> +#include <net.h> +#include "wol.h" + +/* + * Handle a received wake-on-lan packet. + */ +void wol_receive(struct ip_udp_hdr *ip, unsigned int len) +{ + char buf[4]; + int i; + struct wol_hdr *wol; + + wol = (struct wol_hdr *)ip; + + if (len < 102) + return; + + for (i = 0; i < 6; i++) + if (wol->wol_sync[i] != 0xff) + return; + + for (i = 0; i < 16; i++) + if (memcmp(&wol->wol_dest[i * 6], net_ethaddr, 6) != 0) + return; + + /* save the optional password using the etherwake format */ + if (len >= 106) { + sprintf(buf, "%i.%i.%i.%i", + wol->wol_passwd[0], wol->wol_passwd[1], + wol->wol_passwd[2], wol->wol_passwd[3]); + env_set("wolpassword", buf); + } + net_set_state(NETLOOP_SUCCESS); +} + +static void wol_timeout_handler(void) +{ + eth_halt(); + net_set_state(NETLOOP_FAIL); +} + +void wol_start(void) +{ + ulong timeout = env_get_ulong("woltimeout", 10, 5); + + net_set_timeout_handler(timeout * 1000, wol_timeout_handler); +} diff --git a/net/wol.h b/net/wol.h new file mode 100644 index 0000000000..e34767c733 --- /dev/null +++ b/net/wol.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2018 Lothar Felten, lothar.felten@gmail.com + */ + +#if defined(CONFIG_CMD_WOL) + +#ifndef __WOL_H__ +#define __WOL_H__ + +#include <net.h> + +/**********************************************************************/ + +/* + * Wake-on-LAN header. + */ +struct wol_hdr { + u8 wol_sync[6]; /* sync bytes */ + u8 wol_dest[16 * 6]; /* 16x destination MAC address */ + u8 wol_passwd[4]; /* optional password */ +}; + +/* + * Initialize wol (beginning of netloop) + */ +void wol_start(void); + +/* + * Deal with the receipt of a wol packet + * + * @param ip IP header in the packet + * @param len Packet length + */ +void wol_receive(struct ip_udp_hdr *ip, unsigned int len); + +/**********************************************************************/ + +#endif /* __WOL_H__ */ +#endif