xref: /rk3399_rockchip-uboot/cmd/net.c (revision 909b97280011ddb537aab987a6b65d83dd6e42fc)
12e192b24SSimon Glass /*
22e192b24SSimon Glass  * (C) Copyright 2000
32e192b24SSimon Glass  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
42e192b24SSimon Glass  *
52e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
62e192b24SSimon Glass  */
72e192b24SSimon Glass 
82e192b24SSimon Glass /*
92e192b24SSimon Glass  * Boot support
102e192b24SSimon Glass  */
112e192b24SSimon Glass #include <common.h>
122e192b24SSimon Glass #include <command.h>
132e192b24SSimon Glass #include <net.h>
14*909b9728SJoseph Chen #include <boot_rkimg.h>
152e192b24SSimon Glass 
162e192b24SSimon Glass static int netboot_common(enum proto_t, cmd_tbl_t *, int, char * const []);
172e192b24SSimon Glass 
182e192b24SSimon Glass static int do_bootp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
192e192b24SSimon Glass {
202e192b24SSimon Glass 	return netboot_common(BOOTP, cmdtp, argc, argv);
212e192b24SSimon Glass }
222e192b24SSimon Glass 
232e192b24SSimon Glass U_BOOT_CMD(
242e192b24SSimon Glass 	bootp,	3,	1,	do_bootp,
252e192b24SSimon Glass 	"boot image via network using BOOTP/TFTP protocol",
262e192b24SSimon Glass 	"[loadAddress] [[hostIPaddr:]bootfilename]"
272e192b24SSimon Glass );
282e192b24SSimon Glass 
292e192b24SSimon Glass int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
302e192b24SSimon Glass {
312e192b24SSimon Glass 	int ret;
322e192b24SSimon Glass 
332e192b24SSimon Glass 	bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
342e192b24SSimon Glass 	ret = netboot_common(TFTPGET, cmdtp, argc, argv);
352e192b24SSimon Glass 	bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
362e192b24SSimon Glass 	return ret;
372e192b24SSimon Glass }
382e192b24SSimon Glass 
392e192b24SSimon Glass U_BOOT_CMD(
40*909b9728SJoseph Chen 	tftp,		3,	1,	do_tftpb,
41*909b9728SJoseph Chen 	"download image via network using TFTP protocol",
422e192b24SSimon Glass 	"[loadAddress] [[hostIPaddr:]bootfilename]"
432e192b24SSimon Glass );
442e192b24SSimon Glass 
45*909b9728SJoseph Chen #ifdef CONFIG_CMD_TFTP_BOOTM
46*909b9728SJoseph Chen int do_tftpbootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
47*909b9728SJoseph Chen {
48*909b9728SJoseph Chen 	char *tftp_argv[] = { "tftp", NULL, NULL };
49*909b9728SJoseph Chen 	char *bootm_argv[] = { "bootm", NULL };
50*909b9728SJoseph Chen 	char *fileaddr;
51*909b9728SJoseph Chen 	ulong filesize;
52*909b9728SJoseph Chen 
53*909b9728SJoseph Chen 	if (argc != 3)
54*909b9728SJoseph Chen 		return CMD_RET_USAGE;
55*909b9728SJoseph Chen 
56*909b9728SJoseph Chen 	/* tftp download */
57*909b9728SJoseph Chen 	tftp_argv[1] = argv[1];
58*909b9728SJoseph Chen 	tftp_argv[2] = argv[2];
59*909b9728SJoseph Chen 	if (do_tftpb(cmdtp, 0, 3, tftp_argv))
60*909b9728SJoseph Chen 		return -ENOENT;
61*909b9728SJoseph Chen 
62*909b9728SJoseph Chen 	fileaddr = env_get("fileaddr");
63*909b9728SJoseph Chen 	filesize = env_get_ulong("filesize", 16, 0);
64*909b9728SJoseph Chen 	if (!fileaddr || !filesize)
65*909b9728SJoseph Chen 		return -ENOENT;
66*909b9728SJoseph Chen 
67*909b9728SJoseph Chen 	/* bootm */
68*909b9728SJoseph Chen 	bootm_argv[1] = fileaddr;
69*909b9728SJoseph Chen 	printf("## TFTP bootm %s at %s size 0x%lx\n",
70*909b9728SJoseph Chen 	       argv[2], fileaddr, filesize);
71*909b9728SJoseph Chen 
72*909b9728SJoseph Chen 	return do_bootm(NULL, 0, ARRAY_SIZE(bootm_argv), bootm_argv);
73*909b9728SJoseph Chen }
74*909b9728SJoseph Chen 
75*909b9728SJoseph Chen U_BOOT_CMD(
76*909b9728SJoseph Chen 	tftpbootm,	3,	1,	do_tftpbootm,
77*909b9728SJoseph Chen 	"tftpbootm aosp/uImage/FIT image via network using TFTP protocol",
78*909b9728SJoseph Chen 	"[loadAddress] [[hostIPaddr:]bootfilename]"
79*909b9728SJoseph Chen );
80*909b9728SJoseph Chen #endif
81*909b9728SJoseph Chen 
82*909b9728SJoseph Chen #ifdef CONFIG_CMD_TFTP_FLASH
83*909b9728SJoseph Chen int do_tftpflash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
84*909b9728SJoseph Chen {
85*909b9728SJoseph Chen 	char *tftp_argv[] = { "tftp", NULL, NULL };
86*909b9728SJoseph Chen 	struct blk_desc *dev_desc;
87*909b9728SJoseph Chen 	disk_partition_t part;
88*909b9728SJoseph Chen 	ulong fileaddr;
89*909b9728SJoseph Chen 	ulong filesize;
90*909b9728SJoseph Chen 	char *part_name;
91*909b9728SJoseph Chen 	int ret, blknum;
92*909b9728SJoseph Chen 
93*909b9728SJoseph Chen 	if (argc != 4)
94*909b9728SJoseph Chen 		return CMD_RET_USAGE;
95*909b9728SJoseph Chen 
96*909b9728SJoseph Chen 	/* search partition */
97*909b9728SJoseph Chen 	dev_desc = rockchip_get_bootdev();
98*909b9728SJoseph Chen 	if (!dev_desc) {
99*909b9728SJoseph Chen 		printf("No boot device\n");
100*909b9728SJoseph Chen 		return -ENODEV;
101*909b9728SJoseph Chen 	}
102*909b9728SJoseph Chen 
103*909b9728SJoseph Chen 	part_name = argv[3];
104*909b9728SJoseph Chen 	ret = part_get_info_by_name(dev_desc, part_name, &part);
105*909b9728SJoseph Chen 	if (ret < 0) {
106*909b9728SJoseph Chen 		printf("No partition '%s'\n", part_name);
107*909b9728SJoseph Chen 		return -EINVAL;
108*909b9728SJoseph Chen 	}
109*909b9728SJoseph Chen 
110*909b9728SJoseph Chen 	/* tftp download */
111*909b9728SJoseph Chen 	tftp_argv[1] = argv[1];
112*909b9728SJoseph Chen 	tftp_argv[2] = argv[2];
113*909b9728SJoseph Chen 	if (do_tftpb(cmdtp, 0, ARRAY_SIZE(tftp_argv), tftp_argv))
114*909b9728SJoseph Chen 		return -ENOENT;
115*909b9728SJoseph Chen 
116*909b9728SJoseph Chen 	fileaddr = env_get_ulong("fileaddr", 16, 0);
117*909b9728SJoseph Chen 	filesize = env_get_ulong("filesize", 16, 0);
118*909b9728SJoseph Chen 	if (!fileaddr || !filesize)
119*909b9728SJoseph Chen 		return -ENOENT;
120*909b9728SJoseph Chen 
121*909b9728SJoseph Chen 	/* flash */
122*909b9728SJoseph Chen 	blknum = DIV_ROUND_UP(filesize, dev_desc->blksz);
123*909b9728SJoseph Chen 	if (blknum > part.size) {
124*909b9728SJoseph Chen 		printf("File size 0x%lx is too large to flash\n", filesize);
125*909b9728SJoseph Chen 		return -EINVAL;
126*909b9728SJoseph Chen 	}
127*909b9728SJoseph Chen 
128*909b9728SJoseph Chen 	printf("## TFTP flash %s to partititon '%s' size 0x%lx ... ",
129*909b9728SJoseph Chen 	       argv[2], part_name, filesize);
130*909b9728SJoseph Chen 
131*909b9728SJoseph Chen 	ret = blk_dwrite(dev_desc, part.start, blknum, (void *)fileaddr);
132*909b9728SJoseph Chen 	if (ret != blknum)
133*909b9728SJoseph Chen 		printf("Failed(%d)\n", ret);
134*909b9728SJoseph Chen 	else
135*909b9728SJoseph Chen 		printf("OK\n");
136*909b9728SJoseph Chen 
137*909b9728SJoseph Chen 	return 0;
138*909b9728SJoseph Chen }
139*909b9728SJoseph Chen 
140*909b9728SJoseph Chen U_BOOT_CMD(
141*909b9728SJoseph Chen 	tftpflash,	4,	0,	do_tftpflash,
142*909b9728SJoseph Chen 	"flash image via network using TFTP protocol",
143*909b9728SJoseph Chen 	"[loadAddress] [[hostIPaddr:]bootfilename] [partition]"
144*909b9728SJoseph Chen );
145*909b9728SJoseph Chen #endif
146*909b9728SJoseph Chen 
1472e192b24SSimon Glass #ifdef CONFIG_CMD_TFTPPUT
1480c1b869bSMasahiro Yamada static int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1492e192b24SSimon Glass {
1502e192b24SSimon Glass 	return netboot_common(TFTPPUT, cmdtp, argc, argv);
1512e192b24SSimon Glass }
1522e192b24SSimon Glass 
1532e192b24SSimon Glass U_BOOT_CMD(
1542e192b24SSimon Glass 	tftpput,	4,	1,	do_tftpput,
1552e192b24SSimon Glass 	"TFTP put command, for uploading files to a server",
1562e192b24SSimon Glass 	"Address Size [[hostIPaddr:]filename]"
1572e192b24SSimon Glass );
1582e192b24SSimon Glass #endif
1592e192b24SSimon Glass 
1602e192b24SSimon Glass #ifdef CONFIG_CMD_TFTPSRV
1612e192b24SSimon Glass static int do_tftpsrv(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1622e192b24SSimon Glass {
1632e192b24SSimon Glass 	return netboot_common(TFTPSRV, cmdtp, argc, argv);
1642e192b24SSimon Glass }
1652e192b24SSimon Glass 
1662e192b24SSimon Glass U_BOOT_CMD(
1672e192b24SSimon Glass 	tftpsrv,	2,	1,	do_tftpsrv,
1682e192b24SSimon Glass 	"act as a TFTP server and boot the first received file",
1692e192b24SSimon Glass 	"[loadAddress]\n"
1702e192b24SSimon Glass 	"Listen for an incoming TFTP transfer, receive a file and boot it.\n"
1712e192b24SSimon Glass 	"The transfer is aborted if a transfer has not been started after\n"
1722e192b24SSimon Glass 	"about 50 seconds or if Ctrl-C is pressed."
1732e192b24SSimon Glass );
1742e192b24SSimon Glass #endif
1752e192b24SSimon Glass 
176965eda41SJocelyn Bohr #ifdef CONFIG_UDP_FUNCTION_FASTBOOT
177965eda41SJocelyn Bohr int do_fastboot_udp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
178965eda41SJocelyn Bohr {
179965eda41SJocelyn Bohr 	return netboot_common(FASTBOOT, cmdtp, argc, argv);
180965eda41SJocelyn Bohr }
181965eda41SJocelyn Bohr #endif
1822e192b24SSimon Glass 
1832e192b24SSimon Glass #ifdef CONFIG_CMD_RARP
1842e192b24SSimon Glass int do_rarpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1852e192b24SSimon Glass {
1862e192b24SSimon Glass 	return netboot_common(RARP, cmdtp, argc, argv);
1872e192b24SSimon Glass }
1882e192b24SSimon Glass 
1892e192b24SSimon Glass U_BOOT_CMD(
1902e192b24SSimon Glass 	rarpboot,	3,	1,	do_rarpb,
1912e192b24SSimon Glass 	"boot image via network using RARP/TFTP protocol",
1922e192b24SSimon Glass 	"[loadAddress] [[hostIPaddr:]bootfilename]"
1932e192b24SSimon Glass );
1942e192b24SSimon Glass #endif
1952e192b24SSimon Glass 
1962e192b24SSimon Glass #if defined(CONFIG_CMD_DHCP)
1972e192b24SSimon Glass static int do_dhcp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1982e192b24SSimon Glass {
1992e192b24SSimon Glass 	return netboot_common(DHCP, cmdtp, argc, argv);
2002e192b24SSimon Glass }
2012e192b24SSimon Glass 
2022e192b24SSimon Glass U_BOOT_CMD(
2032e192b24SSimon Glass 	dhcp,	3,	1,	do_dhcp,
2042e192b24SSimon Glass 	"boot image via network using DHCP/TFTP protocol",
2052e192b24SSimon Glass 	"[loadAddress] [[hostIPaddr:]bootfilename]"
2062e192b24SSimon Glass );
2072e192b24SSimon Glass #endif
2082e192b24SSimon Glass 
2092e192b24SSimon Glass #if defined(CONFIG_CMD_NFS)
2102e192b24SSimon Glass static int do_nfs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2112e192b24SSimon Glass {
2122e192b24SSimon Glass 	return netboot_common(NFS, cmdtp, argc, argv);
2132e192b24SSimon Glass }
2142e192b24SSimon Glass 
2152e192b24SSimon Glass U_BOOT_CMD(
2162e192b24SSimon Glass 	nfs,	3,	1,	do_nfs,
2172e192b24SSimon Glass 	"boot image via network using NFS protocol",
2182e192b24SSimon Glass 	"[loadAddress] [[hostIPaddr:]bootfilename]"
2192e192b24SSimon Glass );
2202e192b24SSimon Glass #endif
2212e192b24SSimon Glass 
2222e192b24SSimon Glass static void netboot_update_env(void)
2232e192b24SSimon Glass {
2242e192b24SSimon Glass 	char tmp[22];
2252e192b24SSimon Glass 
2262e192b24SSimon Glass 	if (net_gateway.s_addr) {
2272e192b24SSimon Glass 		ip_to_string(net_gateway, tmp);
228382bee57SSimon Glass 		env_set("gatewayip", tmp);
2292e192b24SSimon Glass 	}
2302e192b24SSimon Glass 
2312e192b24SSimon Glass 	if (net_netmask.s_addr) {
2322e192b24SSimon Glass 		ip_to_string(net_netmask, tmp);
233382bee57SSimon Glass 		env_set("netmask", tmp);
2342e192b24SSimon Glass 	}
2352e192b24SSimon Glass 
2362e192b24SSimon Glass 	if (net_hostname[0])
237382bee57SSimon Glass 		env_set("hostname", net_hostname);
2382e192b24SSimon Glass 
2392e192b24SSimon Glass 	if (net_root_path[0])
240382bee57SSimon Glass 		env_set("rootpath", net_root_path);
2412e192b24SSimon Glass 
2422e192b24SSimon Glass 	if (net_ip.s_addr) {
2432e192b24SSimon Glass 		ip_to_string(net_ip, tmp);
244382bee57SSimon Glass 		env_set("ipaddr", tmp);
2452e192b24SSimon Glass 	}
2462e192b24SSimon Glass #if !defined(CONFIG_BOOTP_SERVERIP)
2472e192b24SSimon Glass 	/*
248ff78ad28SBaruch Siach 	 * Only attempt to change serverip if net/bootp.c:store_net_params()
2492e192b24SSimon Glass 	 * could have set it
2502e192b24SSimon Glass 	 */
2512e192b24SSimon Glass 	if (net_server_ip.s_addr) {
2522e192b24SSimon Glass 		ip_to_string(net_server_ip, tmp);
253382bee57SSimon Glass 		env_set("serverip", tmp);
2542e192b24SSimon Glass 	}
2552e192b24SSimon Glass #endif
2562e192b24SSimon Glass 	if (net_dns_server.s_addr) {
2572e192b24SSimon Glass 		ip_to_string(net_dns_server, tmp);
258382bee57SSimon Glass 		env_set("dnsip", tmp);
2592e192b24SSimon Glass 	}
2602e192b24SSimon Glass #if defined(CONFIG_BOOTP_DNS2)
2612e192b24SSimon Glass 	if (net_dns_server2.s_addr) {
2622e192b24SSimon Glass 		ip_to_string(net_dns_server2, tmp);
263382bee57SSimon Glass 		env_set("dnsip2", tmp);
2642e192b24SSimon Glass 	}
2652e192b24SSimon Glass #endif
2662e192b24SSimon Glass 	if (net_nis_domain[0])
267382bee57SSimon Glass 		env_set("domain", net_nis_domain);
2682e192b24SSimon Glass 
2692e192b24SSimon Glass #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
2702e192b24SSimon Glass 	if (net_ntp_time_offset) {
2712e192b24SSimon Glass 		sprintf(tmp, "%d", net_ntp_time_offset);
272382bee57SSimon Glass 		env_set("timeoffset", tmp);
2732e192b24SSimon Glass 	}
2742e192b24SSimon Glass #endif
2752e192b24SSimon Glass #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
2762e192b24SSimon Glass 	if (net_ntp_server.s_addr) {
2772e192b24SSimon Glass 		ip_to_string(net_ntp_server, tmp);
278382bee57SSimon Glass 		env_set("ntpserverip", tmp);
2792e192b24SSimon Glass 	}
2802e192b24SSimon Glass #endif
2812e192b24SSimon Glass }
2822e192b24SSimon Glass 
2832e192b24SSimon Glass static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
2842e192b24SSimon Glass 		char * const argv[])
2852e192b24SSimon Glass {
2862e192b24SSimon Glass 	char *s;
2872e192b24SSimon Glass 	char *end;
2882e192b24SSimon Glass 	int   rcode = 0;
2892e192b24SSimon Glass 	int   size;
2902e192b24SSimon Glass 	ulong addr;
2912e192b24SSimon Glass 
2922e192b24SSimon Glass 	/* pre-set load_addr */
29300caae6dSSimon Glass 	s = env_get("loadaddr");
2942e192b24SSimon Glass 	if (s != NULL)
2952e192b24SSimon Glass 		load_addr = simple_strtoul(s, NULL, 16);
2962e192b24SSimon Glass 
2972e192b24SSimon Glass 	switch (argc) {
2982e192b24SSimon Glass 	case 1:
2992e192b24SSimon Glass 		break;
3002e192b24SSimon Glass 
3012e192b24SSimon Glass 	case 2:	/*
3022e192b24SSimon Glass 		 * Only one arg - accept two forms:
3032e192b24SSimon Glass 		 * Just load address, or just boot file name. The latter
3042e192b24SSimon Glass 		 * form must be written in a format which can not be
3052e192b24SSimon Glass 		 * mis-interpreted as a valid number.
3062e192b24SSimon Glass 		 */
3072e192b24SSimon Glass 		addr = simple_strtoul(argv[1], &end, 16);
3082e192b24SSimon Glass 		if (end == (argv[1] + strlen(argv[1])))
3092e192b24SSimon Glass 			load_addr = addr;
3102e192b24SSimon Glass 		else
3112e192b24SSimon Glass 			copy_filename(net_boot_file_name, argv[1],
3122e192b24SSimon Glass 				      sizeof(net_boot_file_name));
3132e192b24SSimon Glass 		break;
3142e192b24SSimon Glass 
3152e192b24SSimon Glass 	case 3:
3162e192b24SSimon Glass 		load_addr = simple_strtoul(argv[1], NULL, 16);
3172e192b24SSimon Glass 		copy_filename(net_boot_file_name, argv[2],
3182e192b24SSimon Glass 			      sizeof(net_boot_file_name));
3192e192b24SSimon Glass 
3202e192b24SSimon Glass 		break;
3212e192b24SSimon Glass 
3222e192b24SSimon Glass #ifdef CONFIG_CMD_TFTPPUT
3232e192b24SSimon Glass 	case 4:
3242e192b24SSimon Glass 		if (strict_strtoul(argv[1], 16, &save_addr) < 0 ||
3252e192b24SSimon Glass 		    strict_strtoul(argv[2], 16, &save_size) < 0) {
3262e192b24SSimon Glass 			printf("Invalid address/size\n");
3272e192b24SSimon Glass 			return CMD_RET_USAGE;
3282e192b24SSimon Glass 		}
3292e192b24SSimon Glass 		copy_filename(net_boot_file_name, argv[3],
3302e192b24SSimon Glass 			      sizeof(net_boot_file_name));
3312e192b24SSimon Glass 		break;
3322e192b24SSimon Glass #endif
3332e192b24SSimon Glass 	default:
3342e192b24SSimon Glass 		bootstage_error(BOOTSTAGE_ID_NET_START);
3352e192b24SSimon Glass 		return CMD_RET_USAGE;
3362e192b24SSimon Glass 	}
3372e192b24SSimon Glass 	bootstage_mark(BOOTSTAGE_ID_NET_START);
3382e192b24SSimon Glass 
3392e192b24SSimon Glass 	size = net_loop(proto);
3402e192b24SSimon Glass 	if (size < 0) {
3412e192b24SSimon Glass 		bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
3422e192b24SSimon Glass 		return CMD_RET_FAILURE;
3432e192b24SSimon Glass 	}
3442e192b24SSimon Glass 	bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
3452e192b24SSimon Glass 
3462e192b24SSimon Glass 	/* net_loop ok, update environment */
3472e192b24SSimon Glass 	netboot_update_env();
3482e192b24SSimon Glass 
3492e192b24SSimon Glass 	/* done if no file was loaded (no errors though) */
3502e192b24SSimon Glass 	if (size == 0) {
3512e192b24SSimon Glass 		bootstage_error(BOOTSTAGE_ID_NET_LOADED);
3522e192b24SSimon Glass 		return CMD_RET_SUCCESS;
3532e192b24SSimon Glass 	}
3542e192b24SSimon Glass 
3552e192b24SSimon Glass 	bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
3562e192b24SSimon Glass 
3572e192b24SSimon Glass 	rcode = bootm_maybe_autostart(cmdtp, argv[0]);
3582e192b24SSimon Glass 
3592e192b24SSimon Glass 	if (rcode == CMD_RET_SUCCESS)
3602e192b24SSimon Glass 		bootstage_mark(BOOTSTAGE_ID_NET_DONE);
3612e192b24SSimon Glass 	else
3622e192b24SSimon Glass 		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
3632e192b24SSimon Glass 	return rcode;
3642e192b24SSimon Glass }
3652e192b24SSimon Glass 
3662e192b24SSimon Glass #if defined(CONFIG_CMD_PING)
3672e192b24SSimon Glass static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3682e192b24SSimon Glass {
3692e192b24SSimon Glass 	if (argc < 2)
3702e192b24SSimon Glass 		return CMD_RET_USAGE;
3712e192b24SSimon Glass 
3722e192b24SSimon Glass 	net_ping_ip = string_to_ip(argv[1]);
3732e192b24SSimon Glass 	if (net_ping_ip.s_addr == 0)
3742e192b24SSimon Glass 		return CMD_RET_USAGE;
3752e192b24SSimon Glass 
3762e192b24SSimon Glass 	if (net_loop(PING) < 0) {
3772e192b24SSimon Glass 		printf("ping failed; host %s is not alive\n", argv[1]);
3782e192b24SSimon Glass 		return CMD_RET_FAILURE;
3792e192b24SSimon Glass 	}
3802e192b24SSimon Glass 
3812e192b24SSimon Glass 	printf("host %s is alive\n", argv[1]);
3822e192b24SSimon Glass 
3832e192b24SSimon Glass 	return CMD_RET_SUCCESS;
3842e192b24SSimon Glass }
3852e192b24SSimon Glass 
3862e192b24SSimon Glass U_BOOT_CMD(
3872e192b24SSimon Glass 	ping,	2,	1,	do_ping,
3882e192b24SSimon Glass 	"send ICMP ECHO_REQUEST to network host",
3892e192b24SSimon Glass 	"pingAddress"
3902e192b24SSimon Glass );
3912e192b24SSimon Glass #endif
3922e192b24SSimon Glass 
3932e192b24SSimon Glass #if defined(CONFIG_CMD_CDP)
3942e192b24SSimon Glass 
3952e192b24SSimon Glass static void cdp_update_env(void)
3962e192b24SSimon Glass {
3972e192b24SSimon Glass 	char tmp[16];
3982e192b24SSimon Glass 
3992e192b24SSimon Glass 	if (cdp_appliance_vlan != htons(-1)) {
4002e192b24SSimon Glass 		printf("CDP offered appliance VLAN %d\n",
4012e192b24SSimon Glass 		       ntohs(cdp_appliance_vlan));
4022e192b24SSimon Glass 		vlan_to_string(cdp_appliance_vlan, tmp);
403382bee57SSimon Glass 		env_set("vlan", tmp);
4042e192b24SSimon Glass 		net_our_vlan = cdp_appliance_vlan;
4052e192b24SSimon Glass 	}
4062e192b24SSimon Glass 
4072e192b24SSimon Glass 	if (cdp_native_vlan != htons(-1)) {
4082e192b24SSimon Glass 		printf("CDP offered native VLAN %d\n", ntohs(cdp_native_vlan));
4092e192b24SSimon Glass 		vlan_to_string(cdp_native_vlan, tmp);
410382bee57SSimon Glass 		env_set("nvlan", tmp);
4112e192b24SSimon Glass 		net_native_vlan = cdp_native_vlan;
4122e192b24SSimon Glass 	}
4132e192b24SSimon Glass }
4142e192b24SSimon Glass 
4152e192b24SSimon Glass int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
4162e192b24SSimon Glass {
4172e192b24SSimon Glass 	int r;
4182e192b24SSimon Glass 
4192e192b24SSimon Glass 	r = net_loop(CDP);
4202e192b24SSimon Glass 	if (r < 0) {
4212e192b24SSimon Glass 		printf("cdp failed; perhaps not a CISCO switch?\n");
4222e192b24SSimon Glass 		return CMD_RET_FAILURE;
4232e192b24SSimon Glass 	}
4242e192b24SSimon Glass 
4252e192b24SSimon Glass 	cdp_update_env();
4262e192b24SSimon Glass 
4272e192b24SSimon Glass 	return CMD_RET_SUCCESS;
4282e192b24SSimon Glass }
4292e192b24SSimon Glass 
4302e192b24SSimon Glass U_BOOT_CMD(
4312e192b24SSimon Glass 	cdp,	1,	1,	do_cdp,
4322e192b24SSimon Glass 	"Perform CDP network configuration",
4332e192b24SSimon Glass 	"\n"
4342e192b24SSimon Glass );
4352e192b24SSimon Glass #endif
4362e192b24SSimon Glass 
4372e192b24SSimon Glass #if defined(CONFIG_CMD_SNTP)
4382e192b24SSimon Glass int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
4392e192b24SSimon Glass {
4402e192b24SSimon Glass 	char *toff;
4412e192b24SSimon Glass 
4422e192b24SSimon Glass 	if (argc < 2) {
443723806ccSSimon Glass 		net_ntp_server = env_get_ip("ntpserverip");
4442e192b24SSimon Glass 		if (net_ntp_server.s_addr == 0) {
4452e192b24SSimon Glass 			printf("ntpserverip not set\n");
4462e192b24SSimon Glass 			return CMD_RET_FAILURE;
4472e192b24SSimon Glass 		}
4482e192b24SSimon Glass 	} else {
4492e192b24SSimon Glass 		net_ntp_server = string_to_ip(argv[1]);
4502e192b24SSimon Glass 		if (net_ntp_server.s_addr == 0) {
4512e192b24SSimon Glass 			printf("Bad NTP server IP address\n");
4522e192b24SSimon Glass 			return CMD_RET_FAILURE;
4532e192b24SSimon Glass 		}
4542e192b24SSimon Glass 	}
4552e192b24SSimon Glass 
45600caae6dSSimon Glass 	toff = env_get("timeoffset");
4572e192b24SSimon Glass 	if (toff == NULL)
4582e192b24SSimon Glass 		net_ntp_time_offset = 0;
4592e192b24SSimon Glass 	else
4602e192b24SSimon Glass 		net_ntp_time_offset = simple_strtol(toff, NULL, 10);
4612e192b24SSimon Glass 
4622e192b24SSimon Glass 	if (net_loop(SNTP) < 0) {
4632e192b24SSimon Glass 		printf("SNTP failed: host %pI4 not responding\n",
4642e192b24SSimon Glass 		       &net_ntp_server);
4652e192b24SSimon Glass 		return CMD_RET_FAILURE;
4662e192b24SSimon Glass 	}
4672e192b24SSimon Glass 
4682e192b24SSimon Glass 	return CMD_RET_SUCCESS;
4692e192b24SSimon Glass }
4702e192b24SSimon Glass 
4712e192b24SSimon Glass U_BOOT_CMD(
4722e192b24SSimon Glass 	sntp,	2,	1,	do_sntp,
4732e192b24SSimon Glass 	"synchronize RTC via network",
4742e192b24SSimon Glass 	"[NTP server IP]\n"
4752e192b24SSimon Glass );
4762e192b24SSimon Glass #endif
4772e192b24SSimon Glass 
4782e192b24SSimon Glass #if defined(CONFIG_CMD_DNS)
4792e192b24SSimon Glass int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
4802e192b24SSimon Glass {
4812e192b24SSimon Glass 	if (argc == 1)
4822e192b24SSimon Glass 		return CMD_RET_USAGE;
4832e192b24SSimon Glass 
4842e192b24SSimon Glass 	/*
4852e192b24SSimon Glass 	 * We should check for a valid hostname:
4862e192b24SSimon Glass 	 * - Each label must be between 1 and 63 characters long
4872e192b24SSimon Glass 	 * - the entire hostname has a maximum of 255 characters
4882e192b24SSimon Glass 	 * - only the ASCII letters 'a' through 'z' (case-insensitive),
4892e192b24SSimon Glass 	 *   the digits '0' through '9', and the hyphen
4902e192b24SSimon Glass 	 * - cannot begin or end with a hyphen
4912e192b24SSimon Glass 	 * - no other symbols, punctuation characters, or blank spaces are
4922e192b24SSimon Glass 	 *   permitted
4932e192b24SSimon Glass 	 * but hey - this is a minimalist implmentation, so only check length
4942e192b24SSimon Glass 	 * and let the name server deal with things.
4952e192b24SSimon Glass 	 */
4962e192b24SSimon Glass 	if (strlen(argv[1]) >= 255) {
4972e192b24SSimon Glass 		printf("dns error: hostname too long\n");
4982e192b24SSimon Glass 		return CMD_RET_FAILURE;
4992e192b24SSimon Glass 	}
5002e192b24SSimon Glass 
5012e192b24SSimon Glass 	net_dns_resolve = argv[1];
5022e192b24SSimon Glass 
5032e192b24SSimon Glass 	if (argc == 3)
5042e192b24SSimon Glass 		net_dns_env_var = argv[2];
5052e192b24SSimon Glass 	else
5062e192b24SSimon Glass 		net_dns_env_var = NULL;
5072e192b24SSimon Glass 
5082e192b24SSimon Glass 	if (net_loop(DNS) < 0) {
5092e192b24SSimon Glass 		printf("dns lookup of %s failed, check setup\n", argv[1]);
5102e192b24SSimon Glass 		return CMD_RET_FAILURE;
5112e192b24SSimon Glass 	}
5122e192b24SSimon Glass 
5132e192b24SSimon Glass 	return CMD_RET_SUCCESS;
5142e192b24SSimon Glass }
5152e192b24SSimon Glass 
5162e192b24SSimon Glass U_BOOT_CMD(
5172e192b24SSimon Glass 	dns,	3,	1,	do_dns,
5182e192b24SSimon Glass 	"lookup the IP of a hostname",
5192e192b24SSimon Glass 	"hostname [envvar]"
5202e192b24SSimon Glass );
5212e192b24SSimon Glass 
5222e192b24SSimon Glass #endif	/* CONFIG_CMD_DNS */
5232e192b24SSimon Glass 
5242e192b24SSimon Glass #if defined(CONFIG_CMD_LINK_LOCAL)
5252e192b24SSimon Glass static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
5262e192b24SSimon Glass 			char * const argv[])
5272e192b24SSimon Glass {
5282e192b24SSimon Glass 	char tmp[22];
5292e192b24SSimon Glass 
5302e192b24SSimon Glass 	if (net_loop(LINKLOCAL) < 0)
5312e192b24SSimon Glass 		return CMD_RET_FAILURE;
5322e192b24SSimon Glass 
5332e192b24SSimon Glass 	net_gateway.s_addr = 0;
5342e192b24SSimon Glass 	ip_to_string(net_gateway, tmp);
535382bee57SSimon Glass 	env_set("gatewayip", tmp);
5362e192b24SSimon Glass 
5372e192b24SSimon Glass 	ip_to_string(net_netmask, tmp);
538382bee57SSimon Glass 	env_set("netmask", tmp);
5392e192b24SSimon Glass 
5402e192b24SSimon Glass 	ip_to_string(net_ip, tmp);
541382bee57SSimon Glass 	env_set("ipaddr", tmp);
542382bee57SSimon Glass 	env_set("llipaddr", tmp); /* store this for next time */
5432e192b24SSimon Glass 
5442e192b24SSimon Glass 	return CMD_RET_SUCCESS;
5452e192b24SSimon Glass }
5462e192b24SSimon Glass 
5472e192b24SSimon Glass U_BOOT_CMD(
5482e192b24SSimon Glass 	linklocal,	1,	1,	do_link_local,
5492e192b24SSimon Glass 	"acquire a network IP address using the link-local protocol",
5502e192b24SSimon Glass 	""
5512e192b24SSimon Glass );
5522e192b24SSimon Glass 
5532e192b24SSimon Glass #endif  /* CONFIG_CMD_LINK_LOCAL */
554