blob: f6d9f5ea3ab25e41ab089135285a8363408a9b5f [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk38635852002-08-27 05:55:31 +00002/*
3 * (C) Copyright 2000
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
wdenk38635852002-08-27 05:55:31 +00005 */
6
7/*
8 * Boot support
9 */
10#include <common.h>
Simon Glass52f24232020-05-10 11:40:00 -060011#include <bootstage.h>
wdenk38635852002-08-27 05:55:31 +000012#include <command.h>
Tim Harvey8a3987f2021-06-18 15:26:21 -070013#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060014#include <env.h>
Simon Glass8e8ccfe2019-12-28 10:45:03 -070015#include <image.h>
wdenk38635852002-08-27 05:55:31 +000016#include <net.h>
Philippe Reynes912ece42020-09-18 14:13:02 +020017#include <net/udp.h>
18#include <net/sntp.h>
Samuel Mendoza-Jonas4b290d42022-08-08 21:46:04 +093019#include <net/ncsi.h>
wdenk38635852002-08-27 05:55:31 +000020
Simon Glass09140112020-05-10 11:40:03 -060021static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
wdenk38635852002-08-27 05:55:31 +000022
Joe Hershbergerd7a45ea2018-04-13 15:26:30 -050023#ifdef CONFIG_CMD_BOOTP
Simon Glass09140112020-05-10 11:40:03 -060024static int do_bootp(struct cmd_tbl *cmdtp, int flag, int argc,
25 char *const argv[])
wdenk38635852002-08-27 05:55:31 +000026{
Kim Phillips088f1b12012-10-29 13:34:31 +000027 return netboot_common(BOOTP, cmdtp, argc, argv);
wdenk38635852002-08-27 05:55:31 +000028}
29
wdenk0d498392003-07-01 21:06:45 +000030U_BOOT_CMD(
31 bootp, 3, 1, do_bootp,
Peter Tyser2fb26042009-01-27 18:03:12 -060032 "boot image via network using BOOTP/TFTP protocol",
Wolfgang Denka89c33d2009-05-24 17:06:54 +020033 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk8bde7f72003-06-27 21:31:46 +000034);
Joe Hershbergerd7a45ea2018-04-13 15:26:30 -050035#endif
wdenk8bde7f72003-06-27 21:31:46 +000036
Joe Hershbergerd7a45ea2018-04-13 15:26:30 -050037#ifdef CONFIG_CMD_TFTPBOOT
Simon Glass09140112020-05-10 11:40:03 -060038int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenk38635852002-08-27 05:55:31 +000039{
Simon Glass573f14f2011-12-10 11:08:06 +000040 int ret;
41
42 bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
43 ret = netboot_common(TFTPGET, cmdtp, argc, argv);
44 bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
45 return ret;
wdenk38635852002-08-27 05:55:31 +000046}
47
wdenk0d498392003-07-01 21:06:45 +000048U_BOOT_CMD(
49 tftpboot, 3, 1, do_tftpb,
Heinrich Schuchardt651031e2022-09-04 09:08:11 +020050 "load file via network using TFTP protocol",
Wolfgang Denka89c33d2009-05-24 17:06:54 +020051 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk8bde7f72003-06-27 21:31:46 +000052);
Joe Hershbergerd7a45ea2018-04-13 15:26:30 -050053#endif
wdenk8bde7f72003-06-27 21:31:46 +000054
Simon Glass2d46cf22011-10-24 18:00:08 +000055#ifdef CONFIG_CMD_TFTPPUT
Simon Glass09140112020-05-10 11:40:03 -060056static int do_tftpput(struct cmd_tbl *cmdtp, int flag, int argc,
57 char *const argv[])
Simon Glass2d46cf22011-10-24 18:00:08 +000058{
Joe Hershberger85848f02015-03-22 17:09:09 -050059 return netboot_common(TFTPPUT, cmdtp, argc, argv);
Simon Glass2d46cf22011-10-24 18:00:08 +000060}
61
62U_BOOT_CMD(
63 tftpput, 4, 1, do_tftpput,
64 "TFTP put command, for uploading files to a server",
65 "Address Size [[hostIPaddr:]filename]"
66);
67#endif
68
Luca Ceresoli7a83af02011-05-17 00:03:40 +000069#ifdef CONFIG_CMD_TFTPSRV
Simon Glass09140112020-05-10 11:40:03 -060070static int do_tftpsrv(struct cmd_tbl *cmdtp, int flag, int argc,
71 char *const argv[])
Luca Ceresoli7a83af02011-05-17 00:03:40 +000072{
73 return netboot_common(TFTPSRV, cmdtp, argc, argv);
74}
75
76U_BOOT_CMD(
77 tftpsrv, 2, 1, do_tftpsrv,
78 "act as a TFTP server and boot the first received file",
79 "[loadAddress]\n"
80 "Listen for an incoming TFTP transfer, receive a file and boot it.\n"
81 "The transfer is aborted if a transfer has not been started after\n"
82 "about 50 seconds or if Ctrl-C is pressed."
83);
84#endif
85
86
Peter Tyserbf6cb242010-09-30 11:25:48 -050087#ifdef CONFIG_CMD_RARP
Simon Glass09140112020-05-10 11:40:03 -060088int do_rarpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenk38635852002-08-27 05:55:31 +000089{
Kim Phillips088f1b12012-10-29 13:34:31 +000090 return netboot_common(RARP, cmdtp, argc, argv);
wdenk38635852002-08-27 05:55:31 +000091}
92
wdenk0d498392003-07-01 21:06:45 +000093U_BOOT_CMD(
94 rarpboot, 3, 1, do_rarpb,
Peter Tyser2fb26042009-01-27 18:03:12 -060095 "boot image via network using RARP/TFTP protocol",
Wolfgang Denka89c33d2009-05-24 17:06:54 +020096 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk8bde7f72003-06-27 21:31:46 +000097);
Peter Tyserbf6cb242010-09-30 11:25:48 -050098#endif
wdenk8bde7f72003-06-27 21:31:46 +000099
Jon Loeligerc76fe472007-07-08 18:02:23 -0500100#if defined(CONFIG_CMD_DHCP)
Simon Glass09140112020-05-10 11:40:03 -0600101static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
102 char *const argv[])
wdenk38635852002-08-27 05:55:31 +0000103{
104 return netboot_common(DHCP, cmdtp, argc, argv);
105}
wdenk8bde7f72003-06-27 21:31:46 +0000106
wdenk0d498392003-07-01 21:06:45 +0000107U_BOOT_CMD(
108 dhcp, 3, 1, do_dhcp,
Peter Tyser2fb26042009-01-27 18:03:12 -0600109 "boot image via network using DHCP/TFTP protocol",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200110 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk8bde7f72003-06-27 21:31:46 +0000111);
Jon Loeliger90253172007-07-10 11:02:44 -0500112#endif
wdenk38635852002-08-27 05:55:31 +0000113
Jon Loeligerc76fe472007-07-08 18:02:23 -0500114#if defined(CONFIG_CMD_NFS)
Simon Glass09140112020-05-10 11:40:03 -0600115static int do_nfs(struct cmd_tbl *cmdtp, int flag, int argc,
116 char *const argv[])
wdenkcbd8a352004-02-24 02:00:03 +0000117{
118 return netboot_common(NFS, cmdtp, argc, argv);
119}
120
121U_BOOT_CMD(
122 nfs, 3, 1, do_nfs,
Peter Tyser2fb26042009-01-27 18:03:12 -0600123 "boot image via network using NFS protocol",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200124 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenkcbd8a352004-02-24 02:00:03 +0000125);
Jon Loeliger90253172007-07-10 11:02:44 -0500126#endif
wdenkcbd8a352004-02-24 02:00:03 +0000127
Ying-Chun Liu (PaulLiu)cfbae482022-11-08 14:17:29 +0800128#if defined(CONFIG_CMD_WGET)
129static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
130{
131 return netboot_common(WGET, cmdtp, argc, argv);
132}
133
134U_BOOT_CMD(
135 wget, 3, 1, do_wget,
136 "boot image via network using HTTP protocol",
137 "[loadAddress] [[hostIPaddr:]path and image name]"
138);
139#endif
140
Kim Phillips088f1b12012-10-29 13:34:31 +0000141static void netboot_update_env(void)
wdenk38635852002-08-27 05:55:31 +0000142{
wdenk6e592382004-04-18 17:39:38 +0000143 char tmp[22];
wdenk38635852002-08-27 05:55:31 +0000144
Joe Hershberger049a95a2015-04-08 01:41:01 -0500145 if (net_gateway.s_addr) {
146 ip_to_string(net_gateway, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600147 env_set("gatewayip", tmp);
wdenk6e592382004-04-18 17:39:38 +0000148 }
wdenk38635852002-08-27 05:55:31 +0000149
Joe Hershberger049a95a2015-04-08 01:41:01 -0500150 if (net_netmask.s_addr) {
151 ip_to_string(net_netmask, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600152 env_set("netmask", tmp);
wdenk6e592382004-04-18 17:39:38 +0000153 }
wdenk38635852002-08-27 05:55:31 +0000154
Krebs, Olaf808f13d2020-03-09 14:27:55 +0000155#ifdef CONFIG_CMD_BOOTP
Joe Hershberger586cbe52015-04-08 01:41:03 -0500156 if (net_hostname[0])
Simon Glass382bee52017-08-03 12:22:09 -0600157 env_set("hostname", net_hostname);
Krebs, Olaf808f13d2020-03-09 14:27:55 +0000158#endif
wdenk38635852002-08-27 05:55:31 +0000159
Krebs, Olaf808f13d2020-03-09 14:27:55 +0000160#ifdef CONFIG_CMD_BOOTP
Joe Hershberger586cbe52015-04-08 01:41:03 -0500161 if (net_root_path[0])
Simon Glass382bee52017-08-03 12:22:09 -0600162 env_set("rootpath", net_root_path);
Krebs, Olaf808f13d2020-03-09 14:27:55 +0000163#endif
wdenk38635852002-08-27 05:55:31 +0000164
Joe Hershberger049a95a2015-04-08 01:41:01 -0500165 if (net_ip.s_addr) {
166 ip_to_string(net_ip, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600167 env_set("ipaddr", tmp);
wdenk6e592382004-04-18 17:39:38 +0000168 }
Joe Hershbergera3e1a722012-05-23 07:59:17 +0000169 /*
Baruch Siachff78ad22016-12-27 11:03:29 +0200170 * Only attempt to change serverip if net/bootp.c:store_net_params()
Joe Hershbergera3e1a722012-05-23 07:59:17 +0000171 * could have set it
172 */
Simon Glass43407532021-12-18 11:27:52 -0700173 if (!IS_ENABLED(CONFIG_BOOTP_SERVERIP) && net_server_ip.s_addr) {
Joe Hershberger049a95a2015-04-08 01:41:01 -0500174 ip_to_string(net_server_ip, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600175 env_set("serverip", tmp);
wdenk6e592382004-04-18 17:39:38 +0000176 }
Joe Hershberger049a95a2015-04-08 01:41:01 -0500177 if (net_dns_server.s_addr) {
178 ip_to_string(net_dns_server, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600179 env_set("dnsip", tmp);
wdenk6e592382004-04-18 17:39:38 +0000180 }
Jon Loeliger1fe80d72007-07-09 22:08:34 -0500181#if defined(CONFIG_BOOTP_DNS2)
Joe Hershberger049a95a2015-04-08 01:41:01 -0500182 if (net_dns_server2.s_addr) {
183 ip_to_string(net_dns_server2, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600184 env_set("dnsip2", tmp);
wdenk6e592382004-04-18 17:39:38 +0000185 }
stroesefe389a82003-08-28 14:17:32 +0000186#endif
Krebs, Olaf808f13d2020-03-09 14:27:55 +0000187#ifdef CONFIG_CMD_BOOTP
Joe Hershberger586cbe52015-04-08 01:41:03 -0500188 if (net_nis_domain[0])
Simon Glass382bee52017-08-03 12:22:09 -0600189 env_set("domain", net_nis_domain);
Krebs, Olaf808f13d2020-03-09 14:27:55 +0000190#endif
wdenkea287de2005-04-01 00:25:43 +0000191
Joe Hershberger4fd50552015-04-08 01:41:17 -0500192#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500193 if (net_ntp_time_offset) {
194 sprintf(tmp, "%d", net_ntp_time_offset);
Simon Glass382bee52017-08-03 12:22:09 -0600195 env_set("timeoffset", tmp);
wdenkea287de2005-04-01 00:25:43 +0000196 }
197#endif
Joe Hershberger4fd50552015-04-08 01:41:17 -0500198#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
Joe Hershberger049a95a2015-04-08 01:41:01 -0500199 if (net_ntp_server.s_addr) {
200 ip_to_string(net_ntp_server, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600201 env_set("ntpserverip", tmp);
wdenkea287de2005-04-01 00:25:43 +0000202 }
203#endif
wdenk38635852002-08-27 05:55:31 +0000204}
wdenk6e592382004-04-18 17:39:38 +0000205
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000206/**
207 * parse_addr_size() - parse address and size arguments for tftpput
208 *
209 * @argv: command line arguments
210 * Return: 0 on success
211 */
212static int parse_addr_size(char * const argv[])
wdenk38635852002-08-27 05:55:31 +0000213{
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000214 if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 ||
215 strict_strtoul(argv[2], 16, &image_save_size) < 0) {
216 printf("Invalid address/size\n");
217 return CMD_RET_USAGE;
218 }
219 return 0;
220}
221
222/**
223 * parse_args() - parse command line arguments
224 *
225 * @proto: command prototype
226 * @argc: number of arguments
227 * @argv: command line arguments
228 * Return: 0 on success
229 */
230static int parse_args(enum proto_t proto, int argc, char *const argv[])
231{
Peter Tyser2e4970d2008-12-02 12:59:51 -0600232 ulong addr;
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000233 char *end;
wdenk38635852002-08-27 05:55:31 +0000234
235 switch (argc) {
236 case 1:
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000237 if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT)
238 return 1;
239
Joe Hershbergerf43308f2018-07-03 19:36:42 -0500240 /* refresh bootfile name from env */
241 copy_filename(net_boot_file_name, env_get("bootfile"),
242 sizeof(net_boot_file_name));
wdenk38635852002-08-27 05:55:31 +0000243 break;
244
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000245 case 2:
246 if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT)
247 return 1;
248 /*
Peter Tyser2e4970d2008-12-02 12:59:51 -0600249 * Only one arg - accept two forms:
250 * Just load address, or just boot file name. The latter
251 * form must be written in a format which can not be
252 * mis-interpreted as a valid number.
wdenk38635852002-08-27 05:55:31 +0000253 */
Simon Glass7e5f4602021-07-24 09:03:29 -0600254 addr = hextoul(argv[1], &end);
Alexander Graf449312c2018-06-15 10:29:27 +0200255 if (end == (argv[1] + strlen(argv[1]))) {
Simon Glassbb872dd2019-12-28 10:45:02 -0700256 image_load_addr = addr;
Joe Hershbergerf43308f2018-07-03 19:36:42 -0500257 /* refresh bootfile name from env */
258 copy_filename(net_boot_file_name, env_get("bootfile"),
259 sizeof(net_boot_file_name));
Alexander Graf449312c2018-06-15 10:29:27 +0200260 } else {
261 net_boot_file_name_explicit = true;
Joe Hershberger14111572015-04-08 01:41:02 -0500262 copy_filename(net_boot_file_name, argv[1],
263 sizeof(net_boot_file_name));
Alexander Graf449312c2018-06-15 10:29:27 +0200264 }
wdenk38635852002-08-27 05:55:31 +0000265 break;
266
Joe Hershberger4fd50552015-04-08 01:41:17 -0500267 case 3:
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000268 if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT) {
269 if (parse_addr_size(argv))
270 return 1;
271 } else {
272 image_load_addr = hextoul(argv[1], NULL);
273 net_boot_file_name_explicit = true;
274 copy_filename(net_boot_file_name, argv[2],
275 sizeof(net_boot_file_name));
276 }
wdenk38635852002-08-27 05:55:31 +0000277 break;
278
Simon Glass2d46cf22011-10-24 18:00:08 +0000279#ifdef CONFIG_CMD_TFTPPUT
280 case 4:
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000281 if (parse_addr_size(argv))
282 return 1;
Alexander Graf449312c2018-06-15 10:29:27 +0200283 net_boot_file_name_explicit = true;
Joe Hershberger14111572015-04-08 01:41:02 -0500284 copy_filename(net_boot_file_name, argv[3],
285 sizeof(net_boot_file_name));
Simon Glass2d46cf22011-10-24 18:00:08 +0000286 break;
287#endif
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200288 default:
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000289 return 1;
290 }
291 return 0;
292}
293
294static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
295 char *const argv[])
296{
297 char *s;
298 int rcode = 0;
299 int size;
300
301 net_boot_file_name_explicit = false;
302 *net_boot_file_name = '\0';
303
304 /* pre-set image_load_addr */
305 s = env_get("loadaddr");
306 if (s != NULL)
307 image_load_addr = hextoul(s, NULL);
308
309 if (parse_args(proto, argc, argv)) {
Simon Glass770605e2012-02-13 13:51:18 +0000310 bootstage_error(BOOTSTAGE_ID_NET_START);
Simon Glass4c12eeb2011-12-10 08:44:01 +0000311 return CMD_RET_USAGE;
wdenk38635852002-08-27 05:55:31 +0000312 }
Heinrich Schuchardt5f46c6e2022-09-03 12:21:09 +0000313
Simon Glass770605e2012-02-13 13:51:18 +0000314 bootstage_mark(BOOTSTAGE_ID_NET_START);
wdenk38635852002-08-27 05:55:31 +0000315
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500316 size = net_loop(proto);
Joe Hershberger4fd50552015-04-08 01:41:17 -0500317 if (size < 0) {
Simon Glass770605e2012-02-13 13:51:18 +0000318 bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
Joe Hershberger85848f02015-03-22 17:09:09 -0500319 return CMD_RET_FAILURE;
Heiko Schocher566a4942007-06-22 19:11:54 +0200320 }
Simon Glass770605e2012-02-13 13:51:18 +0000321 bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
wdenk38635852002-08-27 05:55:31 +0000322
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500323 /* net_loop ok, update environment */
wdenk38635852002-08-27 05:55:31 +0000324 netboot_update_env();
325
wdenkeb9401e2002-11-11 02:11:37 +0000326 /* done if no file was loaded (no errors though) */
Heiko Schocher566a4942007-06-22 19:11:54 +0200327 if (size == 0) {
Simon Glass770605e2012-02-13 13:51:18 +0000328 bootstage_error(BOOTSTAGE_ID_NET_LOADED);
Joe Hershberger85848f02015-03-22 17:09:09 -0500329 return CMD_RET_SUCCESS;
Heiko Schocher566a4942007-06-22 19:11:54 +0200330 }
wdenkeb9401e2002-11-11 02:11:37 +0000331
Simon Glass770605e2012-02-13 13:51:18 +0000332 bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
Simon Glassc8e66db2012-01-14 15:24:52 +0000333
Mike Frysinger67d668b2011-06-05 13:43:02 +0000334 rcode = bootm_maybe_autostart(cmdtp, argv[0]);
wdenk38635852002-08-27 05:55:31 +0000335
Joe Hershberger85848f02015-03-22 17:09:09 -0500336 if (rcode == CMD_RET_SUCCESS)
Simon Glass770605e2012-02-13 13:51:18 +0000337 bootstage_mark(BOOTSTAGE_ID_NET_DONE);
Joe Hershberger85848f02015-03-22 17:09:09 -0500338 else
339 bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
wdenk38635852002-08-27 05:55:31 +0000340 return rcode;
341}
342
Jon Loeligerc76fe472007-07-08 18:02:23 -0500343#if defined(CONFIG_CMD_PING)
Simon Glass09140112020-05-10 11:40:03 -0600344static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc,
345 char *const argv[])
wdenk73a8b272003-06-05 19:27:42 +0000346{
347 if (argc < 2)
Joe Hershberger85848f02015-03-22 17:09:09 -0500348 return CMD_RET_USAGE;
wdenk73a8b272003-06-05 19:27:42 +0000349
Joe Hershberger049a95a2015-04-08 01:41:01 -0500350 net_ping_ip = string_to_ip(argv[1]);
351 if (net_ping_ip.s_addr == 0)
Simon Glass4c12eeb2011-12-10 08:44:01 +0000352 return CMD_RET_USAGE;
wdenk73a8b272003-06-05 19:27:42 +0000353
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500354 if (net_loop(PING) < 0) {
wdenk73a8b272003-06-05 19:27:42 +0000355 printf("ping failed; host %s is not alive\n", argv[1]);
Joe Hershberger85848f02015-03-22 17:09:09 -0500356 return CMD_RET_FAILURE;
wdenk73a8b272003-06-05 19:27:42 +0000357 }
358
359 printf("host %s is alive\n", argv[1]);
360
Joe Hershberger85848f02015-03-22 17:09:09 -0500361 return CMD_RET_SUCCESS;
wdenk73a8b272003-06-05 19:27:42 +0000362}
wdenk6dff5522003-07-15 07:45:49 +0000363
364U_BOOT_CMD(
365 ping, 2, 1, do_ping,
Peter Tyser2fb26042009-01-27 18:03:12 -0600366 "send ICMP ECHO_REQUEST to network host",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200367 "pingAddress"
wdenk6dff5522003-07-15 07:45:49 +0000368);
Jon Loeliger90253172007-07-10 11:02:44 -0500369#endif
wdenk73a8b272003-06-05 19:27:42 +0000370
Jon Loeligerc76fe472007-07-08 18:02:23 -0500371#if defined(CONFIG_CMD_CDP)
wdenka3d991b2004-04-15 21:48:45 +0000372
373static void cdp_update_env(void)
374{
375 char tmp[16];
376
Joe Hershberger6aede5b2015-04-08 01:41:14 -0500377 if (cdp_appliance_vlan != htons(-1)) {
378 printf("CDP offered appliance VLAN %d\n",
379 ntohs(cdp_appliance_vlan));
Joe Hershberger4fd50552015-04-08 01:41:17 -0500380 vlan_to_string(cdp_appliance_vlan, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600381 env_set("vlan", tmp);
Joe Hershberger4fd50552015-04-08 01:41:17 -0500382 net_our_vlan = cdp_appliance_vlan;
wdenka3d991b2004-04-15 21:48:45 +0000383 }
384
Joe Hershberger6aede5b2015-04-08 01:41:14 -0500385 if (cdp_native_vlan != htons(-1)) {
386 printf("CDP offered native VLAN %d\n", ntohs(cdp_native_vlan));
Joe Hershberger4fd50552015-04-08 01:41:17 -0500387 vlan_to_string(cdp_native_vlan, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600388 env_set("nvlan", tmp);
Joe Hershberger4fd50552015-04-08 01:41:17 -0500389 net_native_vlan = cdp_native_vlan;
wdenka3d991b2004-04-15 21:48:45 +0000390 }
wdenka3d991b2004-04-15 21:48:45 +0000391}
392
Simon Glass09140112020-05-10 11:40:03 -0600393int do_cdp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenka3d991b2004-04-15 21:48:45 +0000394{
395 int r;
396
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500397 r = net_loop(CDP);
wdenka3d991b2004-04-15 21:48:45 +0000398 if (r < 0) {
399 printf("cdp failed; perhaps not a CISCO switch?\n");
Joe Hershberger85848f02015-03-22 17:09:09 -0500400 return CMD_RET_FAILURE;
wdenka3d991b2004-04-15 21:48:45 +0000401 }
402
403 cdp_update_env();
404
Joe Hershberger85848f02015-03-22 17:09:09 -0500405 return CMD_RET_SUCCESS;
wdenka3d991b2004-04-15 21:48:45 +0000406}
407
408U_BOOT_CMD(
409 cdp, 1, 1, do_cdp,
Wolfgang Denkec5c04c2010-10-26 23:42:23 +0200410 "Perform CDP network configuration",
Wolfgang Denk4b582662010-12-23 17:02:18 +0100411 "\n"
wdenka3d991b2004-04-15 21:48:45 +0000412);
Jon Loeliger90253172007-07-10 11:02:44 -0500413#endif
wdenka3d991b2004-04-15 21:48:45 +0000414
Jon Loeligerc76fe472007-07-08 18:02:23 -0500415#if defined(CONFIG_CMD_SNTP)
Philippe Reynes912ece42020-09-18 14:13:02 +0200416static struct udp_ops sntp_ops = {
417 .prereq = sntp_prereq,
418 .start = sntp_start,
419 .data = NULL,
420};
421
Simon Glass09140112020-05-10 11:40:03 -0600422int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenkea287de2005-04-01 00:25:43 +0000423{
424 char *toff;
425
426 if (argc < 2) {
Simon Glass723806c2017-08-03 12:22:15 -0600427 net_ntp_server = env_get_ip("ntpserverip");
Joe Hershberger049a95a2015-04-08 01:41:01 -0500428 if (net_ntp_server.s_addr == 0) {
Kim Phillips088f1b12012-10-29 13:34:31 +0000429 printf("ntpserverip not set\n");
Joe Hershberger85848f02015-03-22 17:09:09 -0500430 return CMD_RET_FAILURE;
wdenkea287de2005-04-01 00:25:43 +0000431 }
432 } else {
Joe Hershberger049a95a2015-04-08 01:41:01 -0500433 net_ntp_server = string_to_ip(argv[1]);
434 if (net_ntp_server.s_addr == 0) {
Kim Phillips088f1b12012-10-29 13:34:31 +0000435 printf("Bad NTP server IP address\n");
Joe Hershberger85848f02015-03-22 17:09:09 -0500436 return CMD_RET_FAILURE;
wdenkea287de2005-04-01 00:25:43 +0000437 }
438 }
439
Simon Glass00caae62017-08-03 12:22:12 -0600440 toff = env_get("timeoffset");
Kim Phillips088f1b12012-10-29 13:34:31 +0000441 if (toff == NULL)
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500442 net_ntp_time_offset = 0;
Kim Phillips088f1b12012-10-29 13:34:31 +0000443 else
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500444 net_ntp_time_offset = simple_strtol(toff, NULL, 10);
wdenkea287de2005-04-01 00:25:43 +0000445
Philippe Reynes912ece42020-09-18 14:13:02 +0200446 if (udp_loop(&sntp_ops) < 0) {
Luuk Paulussend6840e32011-05-16 18:27:11 +0000447 printf("SNTP failed: host %pI4 not responding\n",
Joe Hershberger4fd50552015-04-08 01:41:17 -0500448 &net_ntp_server);
Joe Hershberger85848f02015-03-22 17:09:09 -0500449 return CMD_RET_FAILURE;
wdenkea287de2005-04-01 00:25:43 +0000450 }
451
Joe Hershberger85848f02015-03-22 17:09:09 -0500452 return CMD_RET_SUCCESS;
wdenkea287de2005-04-01 00:25:43 +0000453}
454
455U_BOOT_CMD(
456 sntp, 2, 1, do_sntp,
Peter Tyser2fb26042009-01-27 18:03:12 -0600457 "synchronize RTC via network",
wdenkea287de2005-04-01 00:25:43 +0000458 "[NTP server IP]\n"
459);
Jon Loeliger90253172007-07-10 11:02:44 -0500460#endif
Robin Getz1a32bf42009-07-20 14:53:54 -0400461
462#if defined(CONFIG_CMD_DNS)
Simon Glass09140112020-05-10 11:40:03 -0600463int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Robin Getz1a32bf42009-07-20 14:53:54 -0400464{
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200465 if (argc == 1)
Simon Glass4c12eeb2011-12-10 08:44:01 +0000466 return CMD_RET_USAGE;
Robin Getz1a32bf42009-07-20 14:53:54 -0400467
468 /*
469 * We should check for a valid hostname:
470 * - Each label must be between 1 and 63 characters long
471 * - the entire hostname has a maximum of 255 characters
472 * - only the ASCII letters 'a' through 'z' (case-insensitive),
473 * the digits '0' through '9', and the hyphen
474 * - cannot begin or end with a hyphen
475 * - no other symbols, punctuation characters, or blank spaces are
476 * permitted
477 * but hey - this is a minimalist implmentation, so only check length
478 * and let the name server deal with things.
479 */
480 if (strlen(argv[1]) >= 255) {
481 printf("dns error: hostname too long\n");
Joe Hershberger85848f02015-03-22 17:09:09 -0500482 return CMD_RET_FAILURE;
Robin Getz1a32bf42009-07-20 14:53:54 -0400483 }
484
Joe Hershberger786eac52015-04-08 01:41:15 -0500485 net_dns_resolve = argv[1];
Robin Getz1a32bf42009-07-20 14:53:54 -0400486
487 if (argc == 3)
Joe Hershberger786eac52015-04-08 01:41:15 -0500488 net_dns_env_var = argv[2];
Robin Getz1a32bf42009-07-20 14:53:54 -0400489 else
Joe Hershberger786eac52015-04-08 01:41:15 -0500490 net_dns_env_var = NULL;
Robin Getz1a32bf42009-07-20 14:53:54 -0400491
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500492 if (net_loop(DNS) < 0) {
Robin Getz1a32bf42009-07-20 14:53:54 -0400493 printf("dns lookup of %s failed, check setup\n", argv[1]);
Joe Hershberger85848f02015-03-22 17:09:09 -0500494 return CMD_RET_FAILURE;
Robin Getz1a32bf42009-07-20 14:53:54 -0400495 }
496
Joe Hershberger85848f02015-03-22 17:09:09 -0500497 return CMD_RET_SUCCESS;
Robin Getz1a32bf42009-07-20 14:53:54 -0400498}
499
500U_BOOT_CMD(
501 dns, 3, 1, do_dns,
502 "lookup the IP of a hostname",
503 "hostname [envvar]"
504);
505
506#endif /* CONFIG_CMD_DNS */
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000507
508#if defined(CONFIG_CMD_LINK_LOCAL)
Simon Glass09140112020-05-10 11:40:03 -0600509static int do_link_local(struct cmd_tbl *cmdtp, int flag, int argc,
510 char *const argv[])
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000511{
512 char tmp[22];
513
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500514 if (net_loop(LINKLOCAL) < 0)
Joe Hershberger85848f02015-03-22 17:09:09 -0500515 return CMD_RET_FAILURE;
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000516
Joe Hershberger049a95a2015-04-08 01:41:01 -0500517 net_gateway.s_addr = 0;
518 ip_to_string(net_gateway, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600519 env_set("gatewayip", tmp);
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000520
Joe Hershberger049a95a2015-04-08 01:41:01 -0500521 ip_to_string(net_netmask, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600522 env_set("netmask", tmp);
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000523
Joe Hershberger049a95a2015-04-08 01:41:01 -0500524 ip_to_string(net_ip, tmp);
Simon Glass382bee52017-08-03 12:22:09 -0600525 env_set("ipaddr", tmp);
526 env_set("llipaddr", tmp); /* store this for next time */
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000527
Joe Hershberger85848f02015-03-22 17:09:09 -0500528 return CMD_RET_SUCCESS;
Joe Hershbergerd22c3382012-05-23 08:00:12 +0000529}
530
531U_BOOT_CMD(
532 linklocal, 1, 1, do_link_local,
533 "acquire a network IP address using the link-local protocol",
534 ""
535);
536
537#endif /* CONFIG_CMD_LINK_LOCAL */
Tim Harvey8a3987f2021-06-18 15:26:21 -0700538
539#ifdef CONFIG_DM_ETH
540static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
541{
542 const struct udevice *current = eth_get_dev();
543 unsigned char env_enetaddr[ARP_HLEN];
544 const struct udevice *dev;
545 struct uclass *uc;
546
547 uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
548 eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
549 printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
550 current == dev ? "active" : "");
551 }
552 return CMD_RET_SUCCESS;
553}
554
555static struct cmd_tbl cmd_net[] = {
556 U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
557};
558
559static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
560{
561 struct cmd_tbl *cp;
562
563 cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
564
565 /* Drop the net command */
566 argc--;
567 argv++;
568
569 if (!cp || argc > cp->maxargs)
570 return CMD_RET_USAGE;
571 if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
572 return CMD_RET_SUCCESS;
573
574 return cp->cmd(cmdtp, flag, argc, argv);
575}
576
577U_BOOT_CMD(
578 net, 2, 1, do_net,
579 "NET sub-system",
580 "list - list available devices\n"
581);
582#endif // CONFIG_DM_ETH
Samuel Mendoza-Jonas4b290d42022-08-08 21:46:04 +0930583
584#if defined(CONFIG_CMD_NCSI)
585static int do_ncsi(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
586{
587 if (!phy_interface_is_ncsi() || !ncsi_active()) {
588 printf("Device not configured for NC-SI\n");
589 return CMD_RET_FAILURE;
590 }
591
592 if (net_loop(NCSI) < 0)
593 return CMD_RET_FAILURE;
594
595 return CMD_RET_SUCCESS;
596}
597
598U_BOOT_CMD(
599 ncsi, 1, 1, do_ncsi,
600 "Configure attached NIC via NC-SI",
601 ""
602);
603#endif /* CONFIG_CMD_NCSI */