blob: addcad3ac14080157f6a7fdc6c32005c46571c0b [file] [log] [blame]
Tom Rini10e47792018-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 Glass1ea97892020-05-10 11:40:00 -060011#include <bootstage.h>
wdenk38635852002-08-27 05:55:31 +000012#include <command.h>
Tim Harveyc4e71e72021-06-18 15:26:21 -070013#include <dm.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060014#include <env.h>
Simon Glass85f13782019-12-28 10:45:03 -070015#include <image.h>
wdenk38635852002-08-27 05:55:31 +000016#include <net.h>
Philippe Reynes2829d992020-09-18 14:13:02 +020017#include <net/udp.h>
18#include <net/sntp.h>
Samuel Mendoza-Jonasfeebd6c2022-08-08 21:46:04 +093019#include <net/ncsi.h>
wdenk38635852002-08-27 05:55:31 +000020
Simon Glassed38aef2020-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 Hershbergerb0429462018-04-13 15:26:30 -050023#ifdef CONFIG_CMD_BOOTP
Simon Glassed38aef2020-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 Phillipsdc00a682012-10-29 13:34:31 +000027 return netboot_common(BOOTP, cmdtp, argc, argv);
wdenk38635852002-08-27 05:55:31 +000028}
29
wdenkf287a242003-07-01 21:06:45 +000030U_BOOT_CMD(
31 bootp, 3, 1, do_bootp,
Peter Tyserdfb72b82009-01-27 18:03:12 -060032 "boot image via network using BOOTP/TFTP protocol",
Wolfgang Denkc54781c2009-05-24 17:06:54 +020033 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk57b2d802003-06-27 21:31:46 +000034);
Joe Hershbergerb0429462018-04-13 15:26:30 -050035#endif
wdenk57b2d802003-06-27 21:31:46 +000036
Joe Hershbergerb0429462018-04-13 15:26:30 -050037#ifdef CONFIG_CMD_TFTPBOOT
Simon Glassed38aef2020-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 Glass768cbf02011-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
wdenkf287a242003-07-01 21:06:45 +000048U_BOOT_CMD(
49 tftpboot, 3, 1, do_tftpb,
Heinrich Schuchardt7d289f12022-09-04 09:08:11 +020050 "load file via network using TFTP protocol",
Wolfgang Denkc54781c2009-05-24 17:06:54 +020051 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk57b2d802003-06-27 21:31:46 +000052);
Joe Hershbergerb0429462018-04-13 15:26:30 -050053#endif
wdenk57b2d802003-06-27 21:31:46 +000054
Simon Glass85d96ec2011-10-24 18:00:08 +000055#ifdef CONFIG_CMD_TFTPPUT
Simon Glassed38aef2020-05-10 11:40:03 -060056static int do_tftpput(struct cmd_tbl *cmdtp, int flag, int argc,
57 char *const argv[])
Simon Glass85d96ec2011-10-24 18:00:08 +000058{
Joe Hershbergerba867832015-03-22 17:09:09 -050059 return netboot_common(TFTPPUT, cmdtp, argc, argv);
Simon Glass85d96ec2011-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 Ceresoli7aa81a42011-05-17 00:03:40 +000069#ifdef CONFIG_CMD_TFTPSRV
Simon Glassed38aef2020-05-10 11:40:03 -060070static int do_tftpsrv(struct cmd_tbl *cmdtp, int flag, int argc,
71 char *const argv[])
Luca Ceresoli7aa81a42011-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 Tyserf7a48ca2010-09-30 11:25:48 -050087#ifdef CONFIG_CMD_RARP
Simon Glassed38aef2020-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 Phillipsdc00a682012-10-29 13:34:31 +000090 return netboot_common(RARP, cmdtp, argc, argv);
wdenk38635852002-08-27 05:55:31 +000091}
92
wdenkf287a242003-07-01 21:06:45 +000093U_BOOT_CMD(
94 rarpboot, 3, 1, do_rarpb,
Peter Tyserdfb72b82009-01-27 18:03:12 -060095 "boot image via network using RARP/TFTP protocol",
Wolfgang Denkc54781c2009-05-24 17:06:54 +020096 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk57b2d802003-06-27 21:31:46 +000097);
Peter Tyserf7a48ca2010-09-30 11:25:48 -050098#endif
wdenk57b2d802003-06-27 21:31:46 +000099
Jon Loeligerd76b5c12007-07-08 18:02:23 -0500100#if defined(CONFIG_CMD_DHCP)
Simon Glassed38aef2020-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}
wdenk57b2d802003-06-27 21:31:46 +0000106
wdenkf287a242003-07-01 21:06:45 +0000107U_BOOT_CMD(
108 dhcp, 3, 1, do_dhcp,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600109 "boot image via network using DHCP/TFTP protocol",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200110 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenk57b2d802003-06-27 21:31:46 +0000111);
Jon Loeligerd704d912007-07-10 11:02:44 -0500112#endif
wdenk38635852002-08-27 05:55:31 +0000113
Jon Loeligerd76b5c12007-07-08 18:02:23 -0500114#if defined(CONFIG_CMD_NFS)
Simon Glassed38aef2020-05-10 11:40:03 -0600115static int do_nfs(struct cmd_tbl *cmdtp, int flag, int argc,
116 char *const argv[])
wdenkbe9c1cb2004-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 Tyserdfb72b82009-01-27 18:03:12 -0600123 "boot image via network using NFS protocol",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200124 "[loadAddress] [[hostIPaddr:]bootfilename]"
wdenkbe9c1cb2004-02-24 02:00:03 +0000125);
Jon Loeligerd704d912007-07-10 11:02:44 -0500126#endif
wdenkbe9c1cb2004-02-24 02:00:03 +0000127
Kim Phillipsdc00a682012-10-29 13:34:31 +0000128static void netboot_update_env(void)
wdenk38635852002-08-27 05:55:31 +0000129{
wdenk05939202004-04-18 17:39:38 +0000130 char tmp[22];
wdenk38635852002-08-27 05:55:31 +0000131
Joe Hershberger5874dec2015-04-08 01:41:01 -0500132 if (net_gateway.s_addr) {
133 ip_to_string(net_gateway, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600134 env_set("gatewayip", tmp);
wdenk05939202004-04-18 17:39:38 +0000135 }
wdenk38635852002-08-27 05:55:31 +0000136
Joe Hershberger5874dec2015-04-08 01:41:01 -0500137 if (net_netmask.s_addr) {
138 ip_to_string(net_netmask, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600139 env_set("netmask", tmp);
wdenk05939202004-04-18 17:39:38 +0000140 }
wdenk38635852002-08-27 05:55:31 +0000141
Krebs, Olafd9249382020-03-09 14:27:55 +0000142#ifdef CONFIG_CMD_BOOTP
Joe Hershberger6d236432015-04-08 01:41:03 -0500143 if (net_hostname[0])
Simon Glass6a38e412017-08-03 12:22:09 -0600144 env_set("hostname", net_hostname);
Krebs, Olafd9249382020-03-09 14:27:55 +0000145#endif
wdenk38635852002-08-27 05:55:31 +0000146
Krebs, Olafd9249382020-03-09 14:27:55 +0000147#ifdef CONFIG_CMD_BOOTP
Joe Hershberger6d236432015-04-08 01:41:03 -0500148 if (net_root_path[0])
Simon Glass6a38e412017-08-03 12:22:09 -0600149 env_set("rootpath", net_root_path);
Krebs, Olafd9249382020-03-09 14:27:55 +0000150#endif
wdenk38635852002-08-27 05:55:31 +0000151
Joe Hershberger5874dec2015-04-08 01:41:01 -0500152 if (net_ip.s_addr) {
153 ip_to_string(net_ip, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600154 env_set("ipaddr", tmp);
wdenk05939202004-04-18 17:39:38 +0000155 }
Joe Hershbergerd4762042012-05-23 07:59:17 +0000156 /*
Baruch Siachbc713252016-12-27 11:03:29 +0200157 * Only attempt to change serverip if net/bootp.c:store_net_params()
Joe Hershbergerd4762042012-05-23 07:59:17 +0000158 * could have set it
159 */
Simon Glass297fc202021-12-18 11:27:52 -0700160 if (!IS_ENABLED(CONFIG_BOOTP_SERVERIP) && net_server_ip.s_addr) {
Joe Hershberger5874dec2015-04-08 01:41:01 -0500161 ip_to_string(net_server_ip, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600162 env_set("serverip", tmp);
wdenk05939202004-04-18 17:39:38 +0000163 }
Joe Hershberger5874dec2015-04-08 01:41:01 -0500164 if (net_dns_server.s_addr) {
165 ip_to_string(net_dns_server, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600166 env_set("dnsip", tmp);
wdenk05939202004-04-18 17:39:38 +0000167 }
Jon Loeliger5336a762007-07-09 22:08:34 -0500168#if defined(CONFIG_BOOTP_DNS2)
Joe Hershberger5874dec2015-04-08 01:41:01 -0500169 if (net_dns_server2.s_addr) {
170 ip_to_string(net_dns_server2, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600171 env_set("dnsip2", tmp);
wdenk05939202004-04-18 17:39:38 +0000172 }
stroesee0aadfb2003-08-28 14:17:32 +0000173#endif
Krebs, Olafd9249382020-03-09 14:27:55 +0000174#ifdef CONFIG_CMD_BOOTP
Joe Hershberger6d236432015-04-08 01:41:03 -0500175 if (net_nis_domain[0])
Simon Glass6a38e412017-08-03 12:22:09 -0600176 env_set("domain", net_nis_domain);
Krebs, Olafd9249382020-03-09 14:27:55 +0000177#endif
wdenkb4ad9622005-04-01 00:25:43 +0000178
Joe Hershberger013d3872015-04-08 01:41:17 -0500179#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500180 if (net_ntp_time_offset) {
181 sprintf(tmp, "%d", net_ntp_time_offset);
Simon Glass6a38e412017-08-03 12:22:09 -0600182 env_set("timeoffset", tmp);
wdenkb4ad9622005-04-01 00:25:43 +0000183 }
184#endif
Joe Hershberger013d3872015-04-08 01:41:17 -0500185#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
Joe Hershberger5874dec2015-04-08 01:41:01 -0500186 if (net_ntp_server.s_addr) {
187 ip_to_string(net_ntp_server, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600188 env_set("ntpserverip", tmp);
wdenkb4ad9622005-04-01 00:25:43 +0000189 }
190#endif
wdenk38635852002-08-27 05:55:31 +0000191}
wdenk05939202004-04-18 17:39:38 +0000192
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000193/**
194 * parse_addr_size() - parse address and size arguments for tftpput
195 *
196 * @argv: command line arguments
197 * Return: 0 on success
198 */
199static int parse_addr_size(char * const argv[])
wdenk38635852002-08-27 05:55:31 +0000200{
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000201 if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 ||
202 strict_strtoul(argv[2], 16, &image_save_size) < 0) {
203 printf("Invalid address/size\n");
204 return CMD_RET_USAGE;
205 }
206 return 0;
207}
Alexander Graff43bf5d2018-06-15 10:29:27 +0200208
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000209/**
210 * parse_args() - parse command line arguments
211 *
212 * @proto: command prototype
213 * @argc: number of arguments
214 * @argv: command line arguments
215 * Return: 0 on success
216 */
217static int parse_args(enum proto_t proto, int argc, char *const argv[])
218{
219 ulong addr;
220 char *end;
wdenk38635852002-08-27 05:55:31 +0000221
222 switch (argc) {
223 case 1:
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000224 if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT)
225 return 1;
226
Joe Hershberger2e135272018-07-03 19:36:42 -0500227 /* refresh bootfile name from env */
228 copy_filename(net_boot_file_name, env_get("bootfile"),
229 sizeof(net_boot_file_name));
wdenk38635852002-08-27 05:55:31 +0000230 break;
231
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000232 case 2:
233 if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT)
234 return 1;
235 /*
Peter Tyser24c297d2008-12-02 12:59:51 -0600236 * Only one arg - accept two forms:
237 * Just load address, or just boot file name. The latter
238 * form must be written in a format which can not be
239 * mis-interpreted as a valid number.
wdenk38635852002-08-27 05:55:31 +0000240 */
Simon Glass3ff49ec2021-07-24 09:03:29 -0600241 addr = hextoul(argv[1], &end);
Alexander Graff43bf5d2018-06-15 10:29:27 +0200242 if (end == (argv[1] + strlen(argv[1]))) {
Simon Glass892265d2019-12-28 10:45:02 -0700243 image_load_addr = addr;
Joe Hershberger2e135272018-07-03 19:36:42 -0500244 /* refresh bootfile name from env */
245 copy_filename(net_boot_file_name, env_get("bootfile"),
246 sizeof(net_boot_file_name));
Alexander Graff43bf5d2018-06-15 10:29:27 +0200247 } else {
248 net_boot_file_name_explicit = true;
Joe Hershberger290c8992015-04-08 01:41:02 -0500249 copy_filename(net_boot_file_name, argv[1],
250 sizeof(net_boot_file_name));
Alexander Graff43bf5d2018-06-15 10:29:27 +0200251 }
wdenk38635852002-08-27 05:55:31 +0000252 break;
253
Joe Hershberger013d3872015-04-08 01:41:17 -0500254 case 3:
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000255 if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT) {
256 if (parse_addr_size(argv))
257 return 1;
258 } else {
259 image_load_addr = hextoul(argv[1], NULL);
260 net_boot_file_name_explicit = true;
261 copy_filename(net_boot_file_name, argv[2],
262 sizeof(net_boot_file_name));
263 }
wdenk38635852002-08-27 05:55:31 +0000264 break;
265
Simon Glass85d96ec2011-10-24 18:00:08 +0000266#ifdef CONFIG_CMD_TFTPPUT
267 case 4:
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000268 if (parse_addr_size(argv))
269 return 1;
Alexander Graff43bf5d2018-06-15 10:29:27 +0200270 net_boot_file_name_explicit = true;
Joe Hershberger290c8992015-04-08 01:41:02 -0500271 copy_filename(net_boot_file_name, argv[3],
272 sizeof(net_boot_file_name));
Simon Glass85d96ec2011-10-24 18:00:08 +0000273 break;
274#endif
Wolfgang Denk3b683112010-07-17 01:06:04 +0200275 default:
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000276 return 1;
277 }
278 return 0;
279}
280
281static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
282 char *const argv[])
283{
284 char *s;
285 int rcode = 0;
286 int size;
287
288 net_boot_file_name_explicit = false;
289 *net_boot_file_name = '\0';
290
291 /* pre-set image_load_addr */
292 s = env_get("loadaddr");
293 if (s != NULL)
294 image_load_addr = hextoul(s, NULL);
295
296 if (parse_args(proto, argc, argv)) {
Simon Glass0169e6b2012-02-13 13:51:18 +0000297 bootstage_error(BOOTSTAGE_ID_NET_START);
Simon Glassa06dfc72011-12-10 08:44:01 +0000298 return CMD_RET_USAGE;
wdenk38635852002-08-27 05:55:31 +0000299 }
Heinrich Schuchardt107b3a42022-09-03 12:21:09 +0000300
Simon Glass0169e6b2012-02-13 13:51:18 +0000301 bootstage_mark(BOOTSTAGE_ID_NET_START);
wdenk38635852002-08-27 05:55:31 +0000302
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500303 size = net_loop(proto);
Joe Hershberger013d3872015-04-08 01:41:17 -0500304 if (size < 0) {
Simon Glass0169e6b2012-02-13 13:51:18 +0000305 bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
Joe Hershbergerba867832015-03-22 17:09:09 -0500306 return CMD_RET_FAILURE;
Heiko Schocher633e03a2007-06-22 19:11:54 +0200307 }
Simon Glass0169e6b2012-02-13 13:51:18 +0000308 bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
wdenk38635852002-08-27 05:55:31 +0000309
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500310 /* net_loop ok, update environment */
wdenk38635852002-08-27 05:55:31 +0000311 netboot_update_env();
312
wdenkc217f6d2002-11-11 02:11:37 +0000313 /* done if no file was loaded (no errors though) */
Heiko Schocher633e03a2007-06-22 19:11:54 +0200314 if (size == 0) {
Simon Glass0169e6b2012-02-13 13:51:18 +0000315 bootstage_error(BOOTSTAGE_ID_NET_LOADED);
Joe Hershbergerba867832015-03-22 17:09:09 -0500316 return CMD_RET_SUCCESS;
Heiko Schocher633e03a2007-06-22 19:11:54 +0200317 }
wdenkc217f6d2002-11-11 02:11:37 +0000318
Simon Glass0169e6b2012-02-13 13:51:18 +0000319 bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
Simon Glass964d1d42012-01-14 15:24:52 +0000320
Mike Frysinger194c2e82011-06-05 13:43:02 +0000321 rcode = bootm_maybe_autostart(cmdtp, argv[0]);
wdenk38635852002-08-27 05:55:31 +0000322
Joe Hershbergerba867832015-03-22 17:09:09 -0500323 if (rcode == CMD_RET_SUCCESS)
Simon Glass0169e6b2012-02-13 13:51:18 +0000324 bootstage_mark(BOOTSTAGE_ID_NET_DONE);
Joe Hershbergerba867832015-03-22 17:09:09 -0500325 else
326 bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
wdenk38635852002-08-27 05:55:31 +0000327 return rcode;
328}
wdenke6466f62003-06-05 19:27:42 +0000329
Jon Loeligerd76b5c12007-07-08 18:02:23 -0500330#if defined(CONFIG_CMD_PING)
Simon Glassed38aef2020-05-10 11:40:03 -0600331static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc,
332 char *const argv[])
wdenke6466f62003-06-05 19:27:42 +0000333{
334 if (argc < 2)
Joe Hershbergerba867832015-03-22 17:09:09 -0500335 return CMD_RET_USAGE;
wdenke6466f62003-06-05 19:27:42 +0000336
Joe Hershberger5874dec2015-04-08 01:41:01 -0500337 net_ping_ip = string_to_ip(argv[1]);
338 if (net_ping_ip.s_addr == 0)
Simon Glassa06dfc72011-12-10 08:44:01 +0000339 return CMD_RET_USAGE;
wdenke6466f62003-06-05 19:27:42 +0000340
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500341 if (net_loop(PING) < 0) {
wdenke6466f62003-06-05 19:27:42 +0000342 printf("ping failed; host %s is not alive\n", argv[1]);
Joe Hershbergerba867832015-03-22 17:09:09 -0500343 return CMD_RET_FAILURE;
wdenke6466f62003-06-05 19:27:42 +0000344 }
345
346 printf("host %s is alive\n", argv[1]);
347
Joe Hershbergerba867832015-03-22 17:09:09 -0500348 return CMD_RET_SUCCESS;
wdenke6466f62003-06-05 19:27:42 +0000349}
wdenkca9bc762003-07-15 07:45:49 +0000350
351U_BOOT_CMD(
352 ping, 2, 1, do_ping,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600353 "send ICMP ECHO_REQUEST to network host",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200354 "pingAddress"
wdenkca9bc762003-07-15 07:45:49 +0000355);
Jon Loeligerd704d912007-07-10 11:02:44 -0500356#endif
wdenk38635852002-08-27 05:55:31 +0000357
Jon Loeligerd76b5c12007-07-08 18:02:23 -0500358#if defined(CONFIG_CMD_CDP)
wdenk145d2c12004-04-15 21:48:45 +0000359
360static void cdp_update_env(void)
361{
362 char tmp[16];
363
Joe Hershberger527336f2015-04-08 01:41:14 -0500364 if (cdp_appliance_vlan != htons(-1)) {
365 printf("CDP offered appliance VLAN %d\n",
366 ntohs(cdp_appliance_vlan));
Joe Hershberger013d3872015-04-08 01:41:17 -0500367 vlan_to_string(cdp_appliance_vlan, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600368 env_set("vlan", tmp);
Joe Hershberger013d3872015-04-08 01:41:17 -0500369 net_our_vlan = cdp_appliance_vlan;
wdenk145d2c12004-04-15 21:48:45 +0000370 }
371
Joe Hershberger527336f2015-04-08 01:41:14 -0500372 if (cdp_native_vlan != htons(-1)) {
373 printf("CDP offered native VLAN %d\n", ntohs(cdp_native_vlan));
Joe Hershberger013d3872015-04-08 01:41:17 -0500374 vlan_to_string(cdp_native_vlan, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600375 env_set("nvlan", tmp);
Joe Hershberger013d3872015-04-08 01:41:17 -0500376 net_native_vlan = cdp_native_vlan;
wdenk145d2c12004-04-15 21:48:45 +0000377 }
wdenk145d2c12004-04-15 21:48:45 +0000378}
379
Simon Glassed38aef2020-05-10 11:40:03 -0600380int do_cdp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenk145d2c12004-04-15 21:48:45 +0000381{
382 int r;
383
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500384 r = net_loop(CDP);
wdenk145d2c12004-04-15 21:48:45 +0000385 if (r < 0) {
386 printf("cdp failed; perhaps not a CISCO switch?\n");
Joe Hershbergerba867832015-03-22 17:09:09 -0500387 return CMD_RET_FAILURE;
wdenk145d2c12004-04-15 21:48:45 +0000388 }
389
390 cdp_update_env();
391
Joe Hershbergerba867832015-03-22 17:09:09 -0500392 return CMD_RET_SUCCESS;
wdenk145d2c12004-04-15 21:48:45 +0000393}
394
395U_BOOT_CMD(
396 cdp, 1, 1, do_cdp,
Wolfgang Denkd29afc32010-10-26 23:42:23 +0200397 "Perform CDP network configuration",
Wolfgang Denkf003d922010-12-23 17:02:18 +0100398 "\n"
wdenk145d2c12004-04-15 21:48:45 +0000399);
Jon Loeligerd704d912007-07-10 11:02:44 -0500400#endif
wdenk145d2c12004-04-15 21:48:45 +0000401
Jon Loeligerd76b5c12007-07-08 18:02:23 -0500402#if defined(CONFIG_CMD_SNTP)
Philippe Reynes2829d992020-09-18 14:13:02 +0200403static struct udp_ops sntp_ops = {
404 .prereq = sntp_prereq,
405 .start = sntp_start,
406 .data = NULL,
407};
408
Simon Glassed38aef2020-05-10 11:40:03 -0600409int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenkb4ad9622005-04-01 00:25:43 +0000410{
411 char *toff;
412
413 if (argc < 2) {
Simon Glassda1a1342017-08-03 12:22:15 -0600414 net_ntp_server = env_get_ip("ntpserverip");
Joe Hershberger5874dec2015-04-08 01:41:01 -0500415 if (net_ntp_server.s_addr == 0) {
Kim Phillipsdc00a682012-10-29 13:34:31 +0000416 printf("ntpserverip not set\n");
Joe Hershbergerba867832015-03-22 17:09:09 -0500417 return CMD_RET_FAILURE;
wdenkb4ad9622005-04-01 00:25:43 +0000418 }
419 } else {
Joe Hershberger5874dec2015-04-08 01:41:01 -0500420 net_ntp_server = string_to_ip(argv[1]);
421 if (net_ntp_server.s_addr == 0) {
Kim Phillipsdc00a682012-10-29 13:34:31 +0000422 printf("Bad NTP server IP address\n");
Joe Hershbergerba867832015-03-22 17:09:09 -0500423 return CMD_RET_FAILURE;
wdenkb4ad9622005-04-01 00:25:43 +0000424 }
425 }
426
Simon Glass64b723f2017-08-03 12:22:12 -0600427 toff = env_get("timeoffset");
Kim Phillipsdc00a682012-10-29 13:34:31 +0000428 if (toff == NULL)
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500429 net_ntp_time_offset = 0;
Kim Phillipsdc00a682012-10-29 13:34:31 +0000430 else
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500431 net_ntp_time_offset = simple_strtol(toff, NULL, 10);
wdenkb4ad9622005-04-01 00:25:43 +0000432
Philippe Reynes2829d992020-09-18 14:13:02 +0200433 if (udp_loop(&sntp_ops) < 0) {
Luuk Paulussen7cb3f892011-05-16 18:27:11 +0000434 printf("SNTP failed: host %pI4 not responding\n",
Joe Hershberger013d3872015-04-08 01:41:17 -0500435 &net_ntp_server);
Joe Hershbergerba867832015-03-22 17:09:09 -0500436 return CMD_RET_FAILURE;
wdenkb4ad9622005-04-01 00:25:43 +0000437 }
438
Joe Hershbergerba867832015-03-22 17:09:09 -0500439 return CMD_RET_SUCCESS;
wdenkb4ad9622005-04-01 00:25:43 +0000440}
441
442U_BOOT_CMD(
443 sntp, 2, 1, do_sntp,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600444 "synchronize RTC via network",
wdenkb4ad9622005-04-01 00:25:43 +0000445 "[NTP server IP]\n"
446);
Jon Loeligerd704d912007-07-10 11:02:44 -0500447#endif
Robin Getz82f0d232009-07-20 14:53:54 -0400448
449#if defined(CONFIG_CMD_DNS)
Simon Glassed38aef2020-05-10 11:40:03 -0600450int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Robin Getz82f0d232009-07-20 14:53:54 -0400451{
Wolfgang Denk3b683112010-07-17 01:06:04 +0200452 if (argc == 1)
Simon Glassa06dfc72011-12-10 08:44:01 +0000453 return CMD_RET_USAGE;
Robin Getz82f0d232009-07-20 14:53:54 -0400454
455 /*
456 * We should check for a valid hostname:
457 * - Each label must be between 1 and 63 characters long
458 * - the entire hostname has a maximum of 255 characters
459 * - only the ASCII letters 'a' through 'z' (case-insensitive),
460 * the digits '0' through '9', and the hyphen
461 * - cannot begin or end with a hyphen
462 * - no other symbols, punctuation characters, or blank spaces are
463 * permitted
464 * but hey - this is a minimalist implmentation, so only check length
465 * and let the name server deal with things.
466 */
467 if (strlen(argv[1]) >= 255) {
468 printf("dns error: hostname too long\n");
Joe Hershbergerba867832015-03-22 17:09:09 -0500469 return CMD_RET_FAILURE;
Robin Getz82f0d232009-07-20 14:53:54 -0400470 }
471
Joe Hershbergerf725e342015-04-08 01:41:15 -0500472 net_dns_resolve = argv[1];
Robin Getz82f0d232009-07-20 14:53:54 -0400473
474 if (argc == 3)
Joe Hershbergerf725e342015-04-08 01:41:15 -0500475 net_dns_env_var = argv[2];
Robin Getz82f0d232009-07-20 14:53:54 -0400476 else
Joe Hershbergerf725e342015-04-08 01:41:15 -0500477 net_dns_env_var = NULL;
Robin Getz82f0d232009-07-20 14:53:54 -0400478
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500479 if (net_loop(DNS) < 0) {
Robin Getz82f0d232009-07-20 14:53:54 -0400480 printf("dns lookup of %s failed, check setup\n", argv[1]);
Joe Hershbergerba867832015-03-22 17:09:09 -0500481 return CMD_RET_FAILURE;
Robin Getz82f0d232009-07-20 14:53:54 -0400482 }
483
Joe Hershbergerba867832015-03-22 17:09:09 -0500484 return CMD_RET_SUCCESS;
Robin Getz82f0d232009-07-20 14:53:54 -0400485}
486
487U_BOOT_CMD(
488 dns, 3, 1, do_dns,
489 "lookup the IP of a hostname",
490 "hostname [envvar]"
491);
492
493#endif /* CONFIG_CMD_DNS */
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000494
495#if defined(CONFIG_CMD_LINK_LOCAL)
Simon Glassed38aef2020-05-10 11:40:03 -0600496static int do_link_local(struct cmd_tbl *cmdtp, int flag, int argc,
497 char *const argv[])
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000498{
499 char tmp[22];
500
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500501 if (net_loop(LINKLOCAL) < 0)
Joe Hershbergerba867832015-03-22 17:09:09 -0500502 return CMD_RET_FAILURE;
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000503
Joe Hershberger5874dec2015-04-08 01:41:01 -0500504 net_gateway.s_addr = 0;
505 ip_to_string(net_gateway, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600506 env_set("gatewayip", tmp);
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000507
Joe Hershberger5874dec2015-04-08 01:41:01 -0500508 ip_to_string(net_netmask, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600509 env_set("netmask", tmp);
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000510
Joe Hershberger5874dec2015-04-08 01:41:01 -0500511 ip_to_string(net_ip, tmp);
Simon Glass6a38e412017-08-03 12:22:09 -0600512 env_set("ipaddr", tmp);
513 env_set("llipaddr", tmp); /* store this for next time */
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000514
Joe Hershbergerba867832015-03-22 17:09:09 -0500515 return CMD_RET_SUCCESS;
Joe Hershbergerb35a3a62012-05-23 08:00:12 +0000516}
517
518U_BOOT_CMD(
519 linklocal, 1, 1, do_link_local,
520 "acquire a network IP address using the link-local protocol",
521 ""
522);
523
524#endif /* CONFIG_CMD_LINK_LOCAL */
Tim Harveyc4e71e72021-06-18 15:26:21 -0700525
526#ifdef CONFIG_DM_ETH
527static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
528{
529 const struct udevice *current = eth_get_dev();
530 unsigned char env_enetaddr[ARP_HLEN];
531 const struct udevice *dev;
532 struct uclass *uc;
533
534 uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
535 eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
536 printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
537 current == dev ? "active" : "");
538 }
539 return CMD_RET_SUCCESS;
540}
541
542static struct cmd_tbl cmd_net[] = {
543 U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
544};
545
546static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
547{
548 struct cmd_tbl *cp;
549
550 cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
551
552 /* Drop the net command */
553 argc--;
554 argv++;
555
556 if (!cp || argc > cp->maxargs)
557 return CMD_RET_USAGE;
558 if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
559 return CMD_RET_SUCCESS;
560
561 return cp->cmd(cmdtp, flag, argc, argv);
562}
563
564U_BOOT_CMD(
565 net, 2, 1, do_net,
566 "NET sub-system",
567 "list - list available devices\n"
568);
569#endif // CONFIG_DM_ETH
Samuel Mendoza-Jonasfeebd6c2022-08-08 21:46:04 +0930570
571#if defined(CONFIG_CMD_NCSI)
572static int do_ncsi(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
573{
574 if (!phy_interface_is_ncsi() || !ncsi_active()) {
575 printf("Device not configured for NC-SI\n");
576 return CMD_RET_FAILURE;
577 }
578
579 if (net_loop(NCSI) < 0)
580 return CMD_RET_FAILURE;
581
582 return CMD_RET_SUCCESS;
583}
584
585U_BOOT_CMD(
586 ncsi, 1, 1, do_ncsi,
587 "Configure attached NIC via NC-SI",
588 ""
589);
590#endif /* CONFIG_CMD_NCSI */