diff --git a/cmd/Kconfig b/cmd/Kconfig
index 45c83359add828a60dd8e6f69f9b4abb39a2e44d..bbf9fc9113053bc74bc59fffef09292035a8df76 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1239,6 +1239,11 @@ config CMD_PXE
 	help
 	  Boot image via network using PXE protocol
 
+config CMD_WOL
+	bool "wol"
+	help
+	  Wait for wake-on-lan Magic Packet
+
 endif
 
 menu "Misc commands"
diff --git a/cmd/Makefile b/cmd/Makefile
index 13cf7bf6c205d43a42214f4d44bde4205c661386..323f1fd2c77f210770f93eabd1411cb674cfcc03 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_CMD_PCI) += pci.o
 endif
 obj-y += pcmcia.o
 obj-$(CONFIG_CMD_PXE) += pxe.o
+obj-$(CONFIG_CMD_WOL) += wol.o
 obj-$(CONFIG_CMD_QFW) += qfw.o
 obj-$(CONFIG_CMD_READ) += read.o
 obj-$(CONFIG_CMD_REGINFO) += reginfo.o
diff --git a/cmd/wol.c b/cmd/wol.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a756f373c8edd7dafca4bee1a999d36e816d1e9
--- /dev/null
+++ b/cmd/wol.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Lothar Felte, lothar.felten@gmail.com
+ */
+
+/*
+ * Wake-on-LAN support
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+
+#if defined(CONFIG_CMD_WOL)
+void wol_set_timeout(ulong);
+
+int do_wol(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	/* Validate arguments */
+	if (argc < 2)
+		return CMD_RET_USAGE;
+	wol_set_timeout(simple_strtol(argv[1], NULL, 10) * 1000);
+	if (net_loop(WOL) < 0)
+		return CMD_RET_FAILURE;
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+	wol,	2,	1,	do_wol,
+	"wait for an incoming wake-on-lan packet",
+	"Timeout"
+);
+#endif
diff --git a/configs/pengwyn_defconfig b/configs/pengwyn_defconfig
index 0ee8e6e1b982de49a5a0f560f56a01ccf59c19fe..76b5715a9904bfd992899d7027f822156c863952 100644
--- a/configs/pengwyn_defconfig
+++ b/configs/pengwyn_defconfig
@@ -37,6 +37,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_WOL=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
diff --git a/include/net.h b/include/net.h
index 57606855564f002f5b0d4e38c1df926a998e0a43..9c7199aca92c05e41b3c2a14882910d9ea35eced 100644
--- a/include/net.h
+++ b/include/net.h
@@ -344,6 +344,7 @@ struct vlan_ethernet_hdr {
 
 #define PROT_IP		0x0800		/* IP protocol			*/
 #define PROT_ARP	0x0806		/* IP ARP protocol		*/
+#define PROT_WOL	0x0842		/* ether-wake WoL protocol	*/
 #define PROT_RARP	0x8035		/* IP ARP protocol		*/
 #define PROT_VLAN	0x8100		/* IEEE 802.1q protocol		*/
 #define PROT_IPV6	0x86dd		/* IPv6 over bluebook		*/
@@ -535,7 +536,7 @@ extern int		net_restart_wrap;	/* Tried all network devices */
 
 enum proto_t {
 	BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP,
-	TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT
+	TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL
 };
 
 extern char	net_boot_file_name[1024];/* Boot File name */
diff --git a/net/Makefile b/net/Makefile
index 07466879f501f77aea77853b9f2ba609f7ad64a7..ce36362168509cf423155d7a972d44acaf1903c7 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_RARP) += rarp.o
 obj-$(CONFIG_CMD_SNTP) += sntp.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 obj-$(CONFIG_UDP_FUNCTION_FASTBOOT)  += fastboot.o
+obj-$(CONFIG_CMD_WOL)  += wol.o
 
 # Disable this warning as it is triggered by:
 # sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/net.c b/net/net.c
index b4563a4cab1fbfbccf595ee40a5e865514d79884..084269e31ecf65bad2aa190c075d755be928cef8 100644
--- a/net/net.c
+++ b/net/net.c
@@ -78,6 +78,12 @@
  *			- own IP address
  *	We want:	- network time
  *	Next step:	none
+ *
+ * WOL:
+ *
+ *	Prerequisites:	- own ethernet address
+ *	We want:	- magic packet or timeout
+ *	Next step:	none
  */
 
 
@@ -108,6 +114,9 @@
 #if defined(CONFIG_CMD_SNTP)
 #include "sntp.h"
 #endif
+#if defined(CONFIG_CMD_WOL)
+#include "wol.h"
+#endif
 
 /** BOOTP EXTENTIONS **/
 
@@ -514,6 +523,11 @@ restart:
 		case LINKLOCAL:
 			link_local_start();
 			break;
+#endif
+#if defined(CONFIG_CMD_WOL)
+		case WOL:
+			wol_start();
+			break;
 #endif
 		default:
 			break;
@@ -1281,6 +1295,11 @@ void net_process_received_packet(uchar *in_packet, int len)
 				      ntohs(ip->udp_src),
 				      ntohs(ip->udp_len) - UDP_HDR_SIZE);
 		break;
+#ifdef CONFIG_CMD_WOL
+	case PROT_WOL:
+		wol_receive(ip, len);
+		break;
+#endif
 	}
 }
 
diff --git a/net/wol.c b/net/wol.c
new file mode 100644
index 0000000000000000000000000000000000000000..946bd91b473d3f45e05c4576209ba192199a93c5
--- /dev/null
+++ b/net/wol.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Lothar Felten, lothar.felten@gmail.com
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <environment.h>
+#include "wol.h"
+
+static ulong wol_timeout = WOL_DEFAULT_TIMEOUT;
+
+/*
+ * Check incoming Wake-on-LAN packet for:
+ * - sync bytes
+ * - sixteen copies of the target MAC address
+ *
+ * @param wol Wake-on-LAN packet
+ * @param len Packet length
+ */
+static int wol_check_magic(struct wol_hdr *wol, unsigned int len)
+{
+	int i;
+
+	if (len < sizeof(struct wol_hdr))
+		return 0;
+
+	for (i = 0; i < WOL_SYNC_COUNT; i++)
+		if (wol->wol_sync[i] != WOL_SYNC_BYTE)
+			return 0;
+
+	for (i = 0; i < WOL_MAC_REPETITIONS; i++)
+		if (memcmp(&wol->wol_dest[i * ARP_HLEN],
+			   net_ethaddr, ARP_HLEN) != 0)
+			return 0;
+
+	return 1;
+}
+
+void wol_receive(struct ip_udp_hdr *ip, unsigned int len)
+{
+	struct wol_hdr *wol;
+
+	wol = (struct wol_hdr *)ip;
+
+	if (!wol_check_magic(wol, len))
+		return;
+
+	/* save the optional password using the ether-wake formats */
+	/* don't check for exact length, the packet might have padding */
+	if (len >= (sizeof(struct wol_hdr) + WOL_PASSWORD_6B)) {
+		eth_env_set_enetaddr("wolpassword", wol->wol_passwd);
+	} else if (len >= (sizeof(struct wol_hdr) + WOL_PASSWORD_4B)) {
+		char buffer[16];
+		struct in_addr *ip = (struct in_addr *)(wol->wol_passwd);
+
+		ip_to_string(*ip, buffer);
+		env_set("wolpassword", buffer);
+	}
+	net_set_state(NETLOOP_SUCCESS);
+}
+
+static void wol_udp_handler(uchar *pkt, unsigned int dest, struct in_addr sip,
+			    unsigned int src, unsigned int len)
+{
+	struct wol_hdr *wol;
+
+	wol = (struct wol_hdr *)pkt;
+
+	/* UDP destination port must be 0, 7 or 9 */
+	if (dest != 0 && dest != 7 && dest != 9)
+		return;
+
+	if (!wol_check_magic(wol, len))
+		return;
+
+	net_set_state(NETLOOP_SUCCESS);
+}
+
+void wol_set_timeout(ulong timeout)
+{
+	wol_timeout = timeout;
+}
+
+static void wol_timeout_handler(void)
+{
+	eth_halt();
+	net_set_state(NETLOOP_FAIL);
+}
+
+void wol_start(void)
+{
+	net_set_timeout_handler(wol_timeout, wol_timeout_handler);
+	net_set_udp_handler(wol_udp_handler);
+}
diff --git a/net/wol.h b/net/wol.h
new file mode 100644
index 0000000000000000000000000000000000000000..ebc81f24b6e53658333c8e5f507e165f5f07b5b1
--- /dev/null
+++ b/net/wol.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * wol - Wake-on-LAN
+ *
+ * Supports both Wake-on-LAN packet types:
+ * - EtherType 0x0842 packets
+ * - UDP packets on ports 0, 7 and 9.
+ *
+ * Copyright 2018 Lothar Felten, lothar.felten@gmail.com
+ */
+
+#if defined(CONFIG_CMD_WOL)
+
+#ifndef __WOL_H__
+#define __WOL_H__
+
+#include <net.h>
+
+/**********************************************************************/
+
+#define WOL_SYNC_BYTE			0xFF
+#define WOL_SYNC_COUNT			6
+#define WOL_MAC_REPETITIONS		16
+#define WOL_DEFAULT_TIMEOUT		5000
+#define WOL_PASSWORD_4B			4
+#define WOL_PASSWORD_6B			6
+
+/*
+ * Wake-on-LAN header
+ */
+struct wol_hdr {
+	u8	wol_sync[WOL_SYNC_COUNT];			/* sync bytes */
+	u8	wol_dest[WOL_MAC_REPETITIONS * ARP_HLEN];	/* 16x MAC */
+	u8	wol_passwd[0];					/* optional */
+};
+
+/*
+ * Initialize wol (beginning of netloop)
+ */
+void wol_start(void);
+
+/*
+ * Check incoming Wake-on-LAN packet for:
+ * - sync bytes
+ * - sixteen copies of the target MAC address
+ *
+ * Optionally store the four or six byte password in the environment
+ * variable "wolpassword"
+ *
+ * @param ip IP header in the packet
+ * @param len Packet length
+ */
+void wol_receive(struct ip_udp_hdr *ip, unsigned int len);
+
+/*
+ * Set the timeout for the reception of a Wake-on-LAN packet
+ *
+ * @param timeout in milliseconds
+ */
+void wol_set_timeout(ulong timeout);
+
+/**********************************************************************/
+
+#endif /* __WOL_H__ */
+#endif