Skip to content

Commit 7d01889

Browse files
seanedmond-msfttrini
authored andcommitted
net: dhcp6: pxe: Add DHCP/PXE commands for IPv6
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 <[email protected]> Reviewed-by: Ramon Fried <[email protected]>
1 parent a024581 commit 7d01889

File tree

8 files changed

+132
-23
lines changed

8 files changed

+132
-23
lines changed

boot/bootmeth_distro.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ static int distro_boot(struct udevice *dev, struct bootflow *bflow)
150150
info.dev = dev;
151151
info.bflow = bflow;
152152
ret = pxe_setup_ctx(&ctx, &cmdtp, distro_getfile, &info, true,
153-
bflow->subdir);
153+
bflow->subdir, false);
154154
if (ret)
155155
return log_msg_ret("ctx", -EINVAL);
156156

boot/bootmeth_pxe.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static int distro_pxe_read_bootflow(struct udevice *dev, struct bootflow *bflow)
7070
addr = simple_strtoul(addr_str, NULL, 16);
7171

7272
log_debug("calling pxe_get()\n");
73-
ret = pxe_get(addr, &bootdir, &size);
73+
ret = pxe_get(addr, &bootdir, &size, false);
7474
log_debug("pxe_get() returned %d\n", ret);
7575
if (ret)
7676
return log_msg_ret("pxeb", ret);
@@ -146,7 +146,7 @@ static int distro_pxe_boot(struct udevice *dev, struct bootflow *bflow)
146146
info.bflow = bflow;
147147
info.cmdtp = &cmdtp;
148148
ret = pxe_setup_ctx(ctx, &cmdtp, distro_pxe_getfile, &info, false,
149-
bflow->subdir);
149+
bflow->subdir, false);
150150
if (ret)
151151
return log_msg_ret("ctx", -EINVAL);
152152

boot/pxe_utils.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1578,7 +1578,7 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
15781578

15791579
int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
15801580
pxe_getfile_func getfile, void *userdata,
1581-
bool allow_abs_path, const char *bootfile)
1581+
bool allow_abs_path, const char *bootfile, bool use_ipv6)
15821582
{
15831583
const char *last_slash;
15841584
size_t path_len = 0;
@@ -1588,6 +1588,7 @@ int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
15881588
ctx->getfile = getfile;
15891589
ctx->userdata = userdata;
15901590
ctx->allow_abs_path = allow_abs_path;
1591+
ctx->use_ipv6 = use_ipv6;
15911592

15921593
/* figure out the boot directory, if there is one */
15931594
if (bootfile && strlen(bootfile) >= MAX_TFTP_PATH_LEN)

cmd/Kconfig

+26
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,15 @@ config CMD_DHCP
16731673
help
16741674
Boot image via network using DHCP/TFTP protocol
16751675

1676+
config CMD_DHCP6
1677+
bool "dhcp6"
1678+
depends on IPV6
1679+
help
1680+
Boot image via network using DHCPv6/TFTP protocol using IPv6.
1681+
1682+
Will perform 4-message exchange with DHCPv6 server, requesting
1683+
the minimum required options to TFTP boot. Complies with RFC 8415.
1684+
16761685
config BOOTP_MAY_FAIL
16771686
bool "Allow for the BOOTP/DHCP server to not be found"
16781687
depends on CMD_BOOTP
@@ -1786,6 +1795,23 @@ config BOOTP_VCI_STRING
17861795
default "U-Boot.arm" if ARM
17871796
default "U-Boot"
17881797

1798+
if CMD_DHCP6
1799+
1800+
config DHCP6_PXE_CLIENTARCH
1801+
hex
1802+
default 0x16 if ARM64
1803+
default 0x15 if ARM
1804+
default 0xFF
1805+
1806+
config DHCP6_PXE_DHCP_OPTION
1807+
bool "Request & store 'pxe_configfile' from DHCP6 server"
1808+
1809+
config DHCP6_ENTERPRISE_ID
1810+
int "Enterprise ID to send in DHCPv6 Vendor Class Option"
1811+
default 0
1812+
1813+
endif
1814+
17891815
config CMD_TFTPBOOT
17901816
bool "tftpboot"
17911817
default y

cmd/net.c

+23
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,29 @@ U_BOOT_CMD(
111111
);
112112
#endif
113113

114+
#if defined(CONFIG_CMD_DHCP6)
115+
static int do_dhcp6(struct cmd_tbl *cmdtp, int flag, int argc,
116+
char *const argv[])
117+
{
118+
int i;
119+
int dhcp_argc;
120+
char *dhcp_argv[] = {NULL, NULL, NULL, NULL};
121+
122+
/* Add -ipv6 flag for autoload */
123+
for (i = 0; i < argc; i++)
124+
dhcp_argv[i] = argv[i];
125+
dhcp_argc = argc + 1;
126+
dhcp_argv[dhcp_argc - 1] = USE_IP6_CMD_PARAM;
127+
128+
return netboot_common(DHCP6, cmdtp, dhcp_argc, dhcp_argv);
129+
}
130+
131+
U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6,
132+
"boot image via network using DHCPv6/TFTP protocol.\n"
133+
"Use IPv6 hostIPaddr framed with [] brackets",
134+
"[loadAddress] [[hostIPaddr:]bootfilename]");
135+
#endif
136+
114137
#if defined(CONFIG_CMD_DHCP)
115138
static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
116139
char *const argv[])

cmd/pxe.c

+69-16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <command.h>
99
#include <fs.h>
1010
#include <net.h>
11+
#include <net6.h>
12+
#include <malloc.h>
1113

1214
#include "pxe_utils.h"
1315

@@ -29,12 +31,20 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
2931
{
3032
char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
3133
int ret;
34+
int num_args;
3235

3336
tftp_argv[1] = file_addr;
3437
tftp_argv[2] = (void *)file_path;
38+
if (ctx->use_ipv6) {
39+
tftp_argv[3] = USE_IP6_CMD_PARAM;
40+
num_args = 4;
41+
} else {
42+
num_args = 3;
43+
}
3544

36-
if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
45+
if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv))
3746
return -ENOENT;
47+
3848
ret = pxe_get_file_size(sizep);
3949
if (ret)
4050
return log_msg_ret("tftp", ret);
@@ -43,6 +53,22 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
4353
return 1;
4454
}
4555

56+
/*
57+
* Looks for a pxe file with specified config file name,
58+
* which is received from DHCPv4 option 209 or
59+
* DHCPv6 option 60.
60+
*
61+
* Returns 1 on success or < 0 on error.
62+
*/
63+
static int pxe_dhcp_option_path(struct pxe_context *ctx, unsigned long pxefile_addr_r)
64+
{
65+
int ret = get_pxe_file(ctx, pxelinux_configfile, pxefile_addr_r);
66+
67+
free(pxelinux_configfile);
68+
69+
return ret;
70+
}
71+
4672
/*
4773
* Looks for a pxe file with a name based on the pxeuuid environment variable.
4874
*
@@ -105,15 +131,24 @@ static int pxe_ipaddr_paths(struct pxe_context *ctx, unsigned long pxefile_addr_
105131
return -ENOENT;
106132
}
107133

108-
int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep)
134+
int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool use_ipv6)
109135
{
110136
struct cmd_tbl cmdtp[] = {}; /* dummy */
111137
struct pxe_context ctx;
112138
int i;
113139

114140
if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
115-
env_get("bootfile")))
141+
env_get("bootfile"), use_ipv6))
116142
return -ENOMEM;
143+
144+
if (IS_ENABLED(CONFIG_DHCP6_PXE_DHCP_OPTION) &&
145+
pxelinux_configfile && use_ipv6) {
146+
if (pxe_dhcp_option_path(&ctx, pxefile_addr_r) > 0)
147+
goto done;
148+
149+
goto error_exit;
150+
}
151+
117152
/*
118153
* Keep trying paths until we successfully get a file we're looking
119154
* for.
@@ -131,6 +166,7 @@ int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep)
131166
i++;
132167
}
133168

169+
error_exit:
134170
pxe_destroy_ctx(&ctx);
135171

136172
return -ENOENT;
@@ -169,9 +205,18 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
169205
char *fname;
170206
ulong size;
171207
int ret;
208+
bool use_ipv6 = false;
172209

173-
if (argc != 1)
174-
return CMD_RET_USAGE;
210+
if (IS_ENABLED(CONFIG_IPV6)) {
211+
if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM))
212+
use_ipv6 = true;
213+
214+
if (!(argc == 1 || (argc == 2 && use_ipv6)))
215+
return CMD_RET_USAGE;
216+
} else {
217+
if (argc != 1)
218+
return CMD_RET_USAGE;
219+
}
175220

176221
pxefile_addr_str = from_env("pxefile_addr_r");
177222

@@ -183,7 +228,7 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
183228
if (ret < 0)
184229
return 1;
185230

186-
ret = pxe_get(pxefile_addr_r, &fname, &size);
231+
ret = pxe_get(pxefile_addr_r, &fname, &size, use_ipv6);
187232
switch (ret) {
188233
case 0:
189234
printf("Config file '%s' found\n", fname);
@@ -211,13 +256,19 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
211256
char *pxefile_addr_str;
212257
struct pxe_context ctx;
213258
int ret;
259+
bool use_ipv6 = false;
260+
261+
if (IS_ENABLED(CONFIG_IPV6)) {
262+
if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM))
263+
use_ipv6 = true;
264+
}
214265

215-
if (argc == 1) {
266+
if (argc == 1 || (argc == 2 && use_ipv6)) {
216267
pxefile_addr_str = from_env("pxefile_addr_r");
217268
if (!pxefile_addr_str)
218269
return 1;
219270

220-
} else if (argc == 2) {
271+
} else if (argc == 2 || (argc == 3 && use_ipv6)) {
221272
pxefile_addr_str = argv[1];
222273
} else {
223274
return CMD_RET_USAGE;
@@ -229,7 +280,7 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
229280
}
230281

231282
if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
232-
env_get("bootfile"))) {
283+
env_get("bootfile"), use_ipv6)) {
233284
printf("Out of memory\n");
234285
return CMD_RET_FAILURE;
235286
}
@@ -244,8 +295,8 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
244295
}
245296

246297
static struct cmd_tbl cmd_pxe_sub[] = {
247-
U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""),
248-
U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "")
298+
U_BOOT_CMD_MKENT(get, 2, 1, do_pxe_get, "", ""),
299+
U_BOOT_CMD_MKENT(boot, 3, 1, do_pxe_boot, "", "")
249300
};
250301

251302
static void __maybe_unused pxe_reloc(void)
@@ -281,9 +332,11 @@ static int do_pxe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
281332
return CMD_RET_USAGE;
282333
}
283334

284-
U_BOOT_CMD(pxe, 3, 1, do_pxe,
285-
"commands to get and boot from pxe files",
286-
"get - try to retrieve a pxe file using tftp\n"
287-
"pxe boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n"
335+
U_BOOT_CMD(pxe, 4, 1, do_pxe,
336+
"commands to get and boot from pxe files\n"
337+
"To use IPv6 add -ipv6 parameter",
338+
"get [" USE_IP6_CMD_PARAM "] - try to retrieve a pxe file using tftp\n"
339+
"pxe boot [pxefile_addr_r] [-ipv6] - boot from the pxe file at pxefile_addr_r\n"
288340
);
289-
#endif
341+
342+
#endif /* CONFIG_CMD_NET */

cmd/sysboot.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
101101
}
102102

103103
if (pxe_setup_ctx(&ctx, cmdtp, sysboot_read_file, &info, true,
104-
filename)) {
104+
filename, false)) {
105105
printf("Out of memory\n");
106106
return CMD_RET_FAILURE;
107107
}

include/pxe_utils.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
9393
* @bootdir: Directory that files are loaded from ("" if no directory). This is
9494
* allocated
9595
* @pxe_file_size: Size of the PXE file
96+
* @use_ipv6: TRUE : use IPv6 addressing, FALSE : use IPv4 addressing
9697
*/
9798
struct pxe_context {
9899
struct cmd_tbl *cmdtp;
@@ -112,6 +113,7 @@ struct pxe_context {
112113
bool allow_abs_path;
113114
char *bootdir;
114115
ulong pxe_file_size;
116+
bool use_ipv6;
115117
};
116118

117119
/**
@@ -209,12 +211,14 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
209211
* @allow_abs_path: true to allow absolute paths
210212
* @bootfile: Bootfile whose directory loaded files are relative to, NULL if
211213
* none
214+
* @use_ipv6: TRUE : use IPv6 addressing
215+
* FALSE : use IPv4 addressing
212216
* Return: 0 if OK, -ENOMEM if out of memory, -E2BIG if bootfile is larger than
213217
* MAX_TFTP_PATH_LEN bytes
214218
*/
215219
int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
216220
pxe_getfile_func getfile, void *userdata,
217-
bool allow_abs_path, const char *bootfile);
221+
bool allow_abs_path, const char *bootfile, bool use_ipv6);
218222

219223
/**
220224
* pxe_destroy_ctx() - Destroy a PXE context
@@ -251,7 +255,9 @@ int pxe_get_file_size(ulong *sizep);
251255
* "rpi/info", which indicates that all files should be fetched from the
252256
* "rpi/" subdirectory
253257
* @sizep: Size of the PXE file (not bootfile)
258+
* @use_ipv6: TRUE : use IPv6 addressing
259+
* FALSE : use IPv4 addressing
254260
*/
255-
int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep);
261+
int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool use_ipv6);
256262

257263
#endif /* __PXE_UTILS_H */

0 commit comments

Comments
 (0)