From: seanedmond@linux.microsoft.com
To: u-boot@lists.denx.de
Cc: joe.hershberger@ni.com, rfried.dev@gmail.com, sjg@chromium.org,
v.v.mitrofanov@yadro.com, seanedmond@microsoft.com
Subject: [PATCH v2 2/3] net: dhcp6: pxe: Add DHCP/PXE commands for IPv6
Date: Thu, 6 Apr 2023 23:56:18 -0700 [thread overview]
Message-ID: <20230407065619.15908-3-seanedmond@linux.microsoft.com> (raw)
In-Reply-To: <20230407065619.15908-1-seanedmond@linux.microsoft.com>
From: Sean Edmond <seanedmond@microsoft.com>
Adds commands to support DHCP and PXE with IPv6.
New configs added:
- CMD_DHCP6
- DHCP6_PXE_CLIENTARCH
- DHCP6_PXE_DHCP_OPTION
- DHCP6_ENTERPRISE_ID
New commands added (when IPv6 is enabled):
- dhcp6
- pxe get -ipv6
- pxe boot -ipv6
Signed-off-by: Sean Edmond <seanedmond@microsoft.com>
---
boot/bootmeth_distro.c | 2 +-
boot/bootmeth_pxe.c | 4 +-
boot/pxe_utils.c | 3 +-
cmd/Kconfig | 26 +++++++++++++
cmd/net.c | 23 +++++++++++
cmd/pxe.c | 86 +++++++++++++++++++++++++++++++++++++-----
cmd/sysboot.c | 2 +-
include/pxe_utils.h | 10 ++++-
8 files changed, 140 insertions(+), 16 deletions(-)
diff --git a/boot/bootmeth_distro.c b/boot/bootmeth_distro.c
index 356929828b..b4b73ecbf5 100644
--- a/boot/bootmeth_distro.c
+++ b/boot/bootmeth_distro.c
@@ -150,7 +150,7 @@ static int distro_boot(struct udevice *dev, struct bootflow *bflow)
info.dev = dev;
info.bflow = bflow;
ret = pxe_setup_ctx(&ctx, &cmdtp, distro_getfile, &info, true,
- bflow->subdir);
+ bflow->subdir, false);
if (ret)
return log_msg_ret("ctx", -EINVAL);
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
index ecf8557af8..5a8af2bbd0 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -70,7 +70,7 @@ static int distro_pxe_read_bootflow(struct udevice *dev, struct bootflow *bflow)
addr = simple_strtoul(addr_str, NULL, 16);
log_debug("calling pxe_get()\n");
- ret = pxe_get(addr, &bootdir, &size);
+ ret = pxe_get(addr, &bootdir, &size, false);
log_debug("pxe_get() returned %d\n", ret);
if (ret)
return log_msg_ret("pxeb", ret);
@@ -146,7 +146,7 @@ static int distro_pxe_boot(struct udevice *dev, struct bootflow *bflow)
info.bflow = bflow;
info.cmdtp = &cmdtp;
ret = pxe_setup_ctx(ctx, &cmdtp, distro_pxe_getfile, &info, false,
- bflow->subdir);
+ bflow->subdir, false);
if (ret)
return log_msg_ret("ctx", -EINVAL);
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 3a1e50f2b1..d13c47dd94 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -1578,7 +1578,7 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
pxe_getfile_func getfile, void *userdata,
- bool allow_abs_path, const char *bootfile)
+ bool allow_abs_path, const char *bootfile, bool use_ipv6)
{
const char *last_slash;
size_t path_len = 0;
@@ -1588,6 +1588,7 @@ int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
ctx->getfile = getfile;
ctx->userdata = userdata;
ctx->allow_abs_path = allow_abs_path;
+ ctx->use_ipv6 = use_ipv6;
/* figure out the boot directory, if there is one */
if (bootfile && strlen(bootfile) >= MAX_TFTP_PATH_LEN)
diff --git a/cmd/Kconfig b/cmd/Kconfig
index bab35fc667..8448cf3400 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1672,6 +1672,15 @@ config CMD_DHCP
help
Boot image via network using DHCP/TFTP protocol
+config CMD_DHCP6
+ bool "dhcp6"
+ depends on IPV6
+ help
+ Boot image via network using DHCPv6/TFTP protocol using IPv6.
+
+ Will perform 4-message exchange with DHCPv6 server, requesting
+ the minimum required options to TFTP boot. Complies with RFC 8415.
+
config BOOTP_MAY_FAIL
bool "Allow for the BOOTP/DHCP server to not be found"
depends on CMD_BOOTP
@@ -1785,6 +1794,23 @@ config BOOTP_VCI_STRING
default "U-Boot.arm" if ARM
default "U-Boot"
+if CMD_DHCP6
+
+config DHCP6_PXE_CLIENTARCH
+ hex
+ default 0x16 if ARM64
+ default 0x15 if ARM
+ default 0xFF
+
+config DHCP6_PXE_DHCP_OPTION
+ bool "Request & store 'pxe_configfile' from DHCP6 server"
+
+config DHCP6_ENTERPRISE_ID
+ int "Enterprise ID to send in DHCPv6 Vendor Class Option"
+ default 0
+
+endif
+
config CMD_TFTPBOOT
bool "tftpboot"
default y
diff --git a/cmd/net.c b/cmd/net.c
index d5e20843dd..95529a9d12 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -111,6 +111,29 @@ U_BOOT_CMD(
);
#endif
+#if defined(CONFIG_CMD_DHCP6)
+static int do_dhcp6(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+ int dhcp_argc;
+ char *dhcp_argv[] = {NULL, NULL, NULL, NULL};
+
+ /* Add -ipv6 flag for autoload */
+ for (i = 0; i < argc; i++)
+ dhcp_argv[i] = argv[i];
+ dhcp_argc = argc + 1;
+ dhcp_argv[dhcp_argc - 1] = USE_IP6_CMD_PARAM;
+
+ return netboot_common(DHCP6, cmdtp, dhcp_argc, dhcp_argv);
+}
+
+U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6,
+ "boot image via network using DHCPv6/TFTP protocol. \n"
+ "Use IPv6 hostIPaddr framed with [] brackets",
+ "[loadAddress] [[hostIPaddr:]bootfilename]");
+#endif
+
#if defined(CONFIG_CMD_DHCP)
static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
diff --git a/cmd/pxe.c b/cmd/pxe.c
index db8e4697f2..71e6fd9633 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -8,6 +8,7 @@
#include <command.h>
#include <fs.h>
#include <net.h>
+#include <net6.h>
#include "pxe_utils.h"
@@ -29,12 +30,20 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
{
char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
int ret;
+ int num_args;
tftp_argv[1] = file_addr;
tftp_argv[2] = (void *)file_path;
+ if (ctx->use_ipv6) {
+ tftp_argv[3] = USE_IP6_CMD_PARAM;
+ num_args = 4;
+ } else {
+ num_args = 3;
+ }
- if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
+ if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv))
return -ENOENT;
+
ret = pxe_get_file_size(sizep);
if (ret)
return log_msg_ret("tftp", ret);
@@ -43,6 +52,23 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
return 1;
}
+#if defined(CONFIG_DHCP6_PXE_DHCP_OPTION)
+/*
+ * Looks for a pxe file with specified config file name,
+ * which is received from DHCPv4 option 209 or
+ * DHCPv6 option 60.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+static inline int pxe_dhcp_option_path(struct pxe_context *ctx, unsigned long pxefile_addr_r)
+{
+ int ret = get_pxe_file(ctx, pxelinux_configfile, pxefile_addr_r);
+
+ free(pxelinux_configfile);
+
+ return ret;
+}
+#endif
/*
* Looks for a pxe file with a name based on the pxeuuid environment variable.
*
@@ -105,15 +131,25 @@ static int pxe_ipaddr_paths(struct pxe_context *ctx, unsigned long pxefile_addr_
return -ENOENT;
}
-int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep)
+int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool use_ipv6)
{
struct cmd_tbl cmdtp[] = {}; /* dummy */
struct pxe_context ctx;
int i;
if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
- env_get("bootfile")))
+ env_get("bootfile"), use_ipv6))
return -ENOMEM;
+
+#if defined(CONFIG_DHCP6_PXE_DHCP_OPTION)
+ if (pxelinux_configfile && use_ipv6) {
+ if (pxe_dhcp_option_path(&ctx, pxefile_addr_r) > 0)
+ goto done;
+
+ goto error_exit;
+ }
+#endif
+
/*
* Keep trying paths until we successfully get a file we're looking
* for.
@@ -131,9 +167,12 @@ int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep)
i++;
}
+#if defined(CONFIG_DHCP6_PXE_DHCP_OPTION)
+error_exit:
pxe_destroy_ctx(&ctx);
return -ENOENT;
+#endif
done:
*bootdirp = env_get("bootfile");
@@ -169,9 +208,17 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
char *fname;
ulong size;
int ret;
+ bool use_ipv6 = false;
- if (argc != 1)
- return CMD_RET_USAGE;
+ if (IS_ENABLED(CONFIG_IPV6)) {
+ if (argc != 1 && argc != 2)
+ return CMD_RET_USAGE;
+ if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM))
+ use_ipv6 = true;
+ } else {
+ if (argc != 1)
+ return CMD_RET_USAGE;
+ }
pxefile_addr_str = from_env("pxefile_addr_r");
@@ -183,7 +230,7 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (ret < 0)
return 1;
- ret = pxe_get(pxefile_addr_r, &fname, &size);
+ ret = pxe_get(pxefile_addr_r, &fname, &size, use_ipv6);
switch (ret) {
case 0:
printf("Config file '%s' found\n", fname);
@@ -211,13 +258,19 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
char *pxefile_addr_str;
struct pxe_context ctx;
int ret;
+ bool use_ipv6 = false;
+
+ if (IS_ENABLED(CONFIG_IPV6)) {
+ if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM))
+ use_ipv6 = true;
+ }
- if (argc == 1) {
+ if (argc == 1 || (argc == 2 && use_ipv6)) {
pxefile_addr_str = from_env("pxefile_addr_r");
if (!pxefile_addr_str)
return 1;
- } else if (argc == 2) {
+ } else if (argc == 2 || (argc == 3 && use_ipv6)) {
pxefile_addr_str = argv[1];
} else {
return CMD_RET_USAGE;
@@ -229,7 +282,7 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
}
if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
- env_get("bootfile"))) {
+ env_get("bootfile"), use_ipv6)) {
printf("Out of memory\n");
return CMD_RET_FAILURE;
}
@@ -244,8 +297,13 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
}
static struct cmd_tbl cmd_pxe_sub[] = {
+#if IS_ENABLED(CONFIG_IPV6)
+ U_BOOT_CMD_MKENT(get, 2, 1, do_pxe_get, "", ""),
+ U_BOOT_CMD_MKENT(boot, 3, 1, do_pxe_boot, "", "")
+#else
U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""),
U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "")
+#endif
};
static void __maybe_unused pxe_reloc(void)
@@ -281,9 +339,19 @@ static int do_pxe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
return CMD_RET_USAGE;
}
+#if IS_ENABLED(CONFIG_IPV6)
+U_BOOT_CMD(pxe, 4, 1, do_pxe,
+ "commands to get and boot from pxe files\n"
+ "To use IPv6 add -ipv6 parameter",
+ "get [" USE_IP6_CMD_PARAM "] - try to retrieve a pxe file using tftp\n"
+ "pxe boot [pxefile_addr_r] [-ipv6] - boot from the pxe file at pxefile_addr_r\n"
+);
+#else
U_BOOT_CMD(pxe, 3, 1, do_pxe,
"commands to get and boot from pxe files",
"get - try to retrieve a pxe file using tftp\n"
"pxe boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n"
);
#endif
+
+#endif /* CONFIG_CMD_NET */
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 04c0702026..63a7806deb 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -101,7 +101,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
}
if (pxe_setup_ctx(&ctx, cmdtp, sysboot_read_file, &info, true,
- filename)) {
+ filename, false)) {
printf("Out of memory\n");
return CMD_RET_FAILURE;
}
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 1e5e8424f5..9f19593048 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -93,6 +93,7 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
* @bootdir: Directory that files are loaded from ("" if no directory). This is
* allocated
* @pxe_file_size: Size of the PXE file
+ * @use_ipv6: TRUE : use IPv6 addressing, FALSE : use IPv4 addressing
*/
struct pxe_context {
struct cmd_tbl *cmdtp;
@@ -112,6 +113,7 @@ struct pxe_context {
bool allow_abs_path;
char *bootdir;
ulong pxe_file_size;
+ bool use_ipv6;
};
/**
@@ -209,12 +211,14 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
* @allow_abs_path: true to allow absolute paths
* @bootfile: Bootfile whose directory loaded files are relative to, NULL if
* none
+ * @use_ipv6: TRUE : use IPv6 addressing
+ * FALSE : use IPv4 addressing
* Return: 0 if OK, -ENOMEM if out of memory, -E2BIG if bootfile is larger than
* MAX_TFTP_PATH_LEN bytes
*/
int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
pxe_getfile_func getfile, void *userdata,
- bool allow_abs_path, const char *bootfile);
+ bool allow_abs_path, const char *bootfile, bool use_ipv6);
/**
* pxe_destroy_ctx() - Destroy a PXE context
@@ -251,7 +255,9 @@ int pxe_get_file_size(ulong *sizep);
* "rpi/info", which indicates that all files should be fetched from the
* "rpi/" subdirectory
* @sizep: Size of the PXE file (not bootfile)
+ * @use_ipv6: TRUE : use IPv6 addressing
+ * FALSE : use IPv4 addressing
*/
-int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep);
+int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool use_ipv6);
#endif /* __PXE_UTILS_H */
--
2.40.0
next prev parent reply other threads:[~2023-04-07 6:57 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-07 6:56 [PATCH v2 0/3] *** net: DHCPv6 protocol and commands *** seanedmond
2023-04-07 6:56 ` [PATCH v2 1/3] net: dhcp6: Add DHCPv6 (DHCP for IPv6) seanedmond
2023-04-07 18:55 ` Simon Glass
2023-04-25 19:03 ` Ramon Fried
2023-05-02 22:11 ` Sean Edmond
2023-04-07 6:56 ` seanedmond [this message]
2023-04-07 18:55 ` [PATCH v2 2/3] net: dhcp6: pxe: Add DHCP/PXE commands for IPv6 Simon Glass
2023-04-11 0:03 ` Sean Edmond
2023-04-19 1:46 ` Simon Glass
2023-04-07 6:56 ` [PATCH v2 3/3] net: dhcp6: Add a sandbox test for dhcp6 seanedmond
2023-04-07 18:55 ` Simon Glass
2023-04-25 19:04 ` Ramon Fried
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230407065619.15908-3-seanedmond@linux.microsoft.com \
--to=seanedmond@linux.microsoft.com \
--cc=joe.hershberger@ni.com \
--cc=rfried.dev@gmail.com \
--cc=seanedmond@microsoft.com \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
--cc=v.v.mitrofanov@yadro.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.