
Add a bootmethod for Ethernet. It uses the distro boot mechanism to locate a file.
Signed-off-by: Simon Glass sjg@chromium.org ---
MAINTAINERS | 1 + configs/sandbox_defconfig | 1 + net/Kconfig | 9 +++++ net/Makefile | 1 + net/eth-uclass.c | 8 +++++ net/eth_bootmethod.c | 76 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 net/eth_bootmethod.c
diff --git a/MAINTAINERS b/MAINTAINERS index 246c5e60270..74e8eaafb10 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -643,6 +643,7 @@ F: doc/usage/bootmethod.rst F: drivers/mmc/mmc_bootmethod.c F: include/bootmethod.h F: include/distro.h +F: net/eth_bootmethod.c F: test/boot/bootmethod.c
BTRFS diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 31a8d6a1d90..321d32be73e 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -116,6 +116,7 @@ CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0" CONFIG_ENV_IMPORT_FDT=y +# CONFIG_BOOTMETHOD_ETH is not set CONFIG_BOOTP_SEND_HOSTNAME=y CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y diff --git a/net/Kconfig b/net/Kconfig index ba0ca813ce5..6f92fe44a8c 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -14,6 +14,15 @@ config PROT_UDP Enable a generic udp framework that allows defining a custom handler for udp protocol.
+config BOOTMETHOD_ETH + bool "Enable bootmethod for ethernet" + depends on BOOTMETHOD + default y + help + Provide a bootmethod for ethernet so that is it possible to boot + an operationg system over the network, using the PXE (Preboot + Execution Environment) protocol. + config BOOTP_SEND_HOSTNAME bool "Send hostname to DNS server" help diff --git a/net/Makefile b/net/Makefile index fb3eba840ff..c86bbd90349 100644 --- a/net/Makefile +++ b/net/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CMD_DNS) += dns.o obj-$(CONFIG_DM_DSA) += dsa-uclass.o ifdef CONFIG_DM_ETH obj-$(CONFIG_NET) += eth-uclass.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD_ETH) += eth_bootmethod.o else obj-$(CONFIG_NET) += eth_legacy.o endif diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 0da0e85be03..0284215b113 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY UCLASS_ETH
#include <common.h> +#include <bootmethod.h> #include <bootstage.h> #include <dm.h> #include <env.h> @@ -473,6 +474,8 @@ int eth_initialize(void)
static int eth_post_bind(struct udevice *dev) { + int ret; + if (strchr(dev->name, ' ')) { printf("\nError: eth device name "%s" has a space!\n", dev->name); @@ -482,6 +485,11 @@ static int eth_post_bind(struct udevice *dev) #ifdef CONFIG_DM_ETH_PHY eth_phy_binds_nodes(dev); #endif + if (CONFIG_IS_ENABLED(BOOTMETHOD_ETH)) { + ret = bootmethod_setup_for_dev(dev, "eth_bootmethod"); + if (ret) + return log_msg_ret("bootmethod", ret); + }
return 0; } diff --git a/net/eth_bootmethod.c b/net/eth_bootmethod.c new file mode 100644 index 00000000000..bc8843add80 --- /dev/null +++ b/net/eth_bootmethod.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for ethernet + * + * Copyright 2021 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <bootmethod.h> +#include <command.h> +#include <distro.h> +#include <dm.h> +#include <net.h> + +static int eth_get_bootflow(struct udevice *dev, int seq, + struct bootflow *bflow) +{ + char name[60]; + int ret; + + /* + * Like distro boot, this assumes there is only one Ethernet device. + * In this case, that means that @eth is ignored + */ + if (seq) + return log_msg_ret("dhcp", -ESHUTDOWN); + + bflow->seq = seq; + snprintf(name, sizeof(name), "%s.%d", dev->name, seq); + bflow->name = strdup(name); + if (!bflow->name) + return log_msg_ret("name", -ENOMEM); + if (!bflow->name) + return log_msg_ret("name", -ENOMEM); + bflow->state = BOOTFLOWST_BASE; + + /* + * There is not a direct interface to the network stack so run + * everything through the command-line interpreter for now. + * + * Don't bother checking the result of dhcp. It can fail with: + * + * DHCP client bound to address 192.168.4.50 (4 ms) + * *** Warning: no boot file name; using 'C0A80432.img' + * Using smsc95xx_eth device + * TFTP from server 192.168.4.1; our IP address is 192.168.4.50 + * Filename 'C0A80432.img'. + * Load address: 0x200000 + * Loading: * + * TFTP error: 'File not found' (1) + * + * This is not a real failure, since we don't actually care if the + * boot file exists. + */ + run_command("dhcp", 0); + bflow->state = BOOTFLOWST_MEDIA; + + if (CONFIG_IS_ENABLED(BOOTMETHOD_DISTRO)) { + ret = distro_net_setup(bflow); + if (ret) + return log_msg_ret("distro", ret); + } + + return 0; +} + +struct bootmethod_ops eth_bootmethod_ops = { + .get_bootflow = eth_get_bootflow, +}; + +U_BOOT_DRIVER(eth_bootmethod) = { + .name = "eth_bootmethod", + .id = UCLASS_BOOTMETHOD, + .ops = ð_bootmethod_ops, +};