1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2000
3*4882a593Smuzhiyun * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun * Boot support
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <command.h>
13*4882a593Smuzhiyun #include <net.h>
14*4882a593Smuzhiyun #include <boot_rkimg.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun static int netboot_common(enum proto_t, cmd_tbl_t *, int, char * const []);
17*4882a593Smuzhiyun
do_bootp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])18*4882a593Smuzhiyun static int do_bootp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun return netboot_common(BOOTP, cmdtp, argc, argv);
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun U_BOOT_CMD(
24*4882a593Smuzhiyun bootp, 3, 1, do_bootp,
25*4882a593Smuzhiyun "boot image via network using BOOTP/TFTP protocol",
26*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename]"
27*4882a593Smuzhiyun );
28*4882a593Smuzhiyun
do_tftpb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])29*4882a593Smuzhiyun int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun int ret;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
34*4882a593Smuzhiyun ret = netboot_common(TFTPGET, cmdtp, argc, argv);
35*4882a593Smuzhiyun bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
36*4882a593Smuzhiyun return ret;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun U_BOOT_CMD(
40*4882a593Smuzhiyun tftp, 3, 1, do_tftpb,
41*4882a593Smuzhiyun "download image via network using TFTP protocol",
42*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename]"
43*4882a593Smuzhiyun );
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #ifdef CONFIG_CMD_TFTP_BOOTM
do_tftpbootm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])46*4882a593Smuzhiyun int do_tftpbootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun char *tftp_argv[] = { "tftp", NULL, NULL };
49*4882a593Smuzhiyun char *bootm_argv[] = { "bootm", NULL };
50*4882a593Smuzhiyun char *fileaddr;
51*4882a593Smuzhiyun ulong filesize;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun if (argc != 3)
54*4882a593Smuzhiyun return CMD_RET_USAGE;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* tftp download */
57*4882a593Smuzhiyun tftp_argv[1] = argv[1];
58*4882a593Smuzhiyun tftp_argv[2] = argv[2];
59*4882a593Smuzhiyun if (do_tftpb(cmdtp, 0, 3, tftp_argv))
60*4882a593Smuzhiyun return -ENOENT;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun fileaddr = env_get("fileaddr");
63*4882a593Smuzhiyun filesize = env_get_ulong("filesize", 16, 0);
64*4882a593Smuzhiyun if (!fileaddr || !filesize)
65*4882a593Smuzhiyun return -ENOENT;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* bootm */
68*4882a593Smuzhiyun bootm_argv[1] = fileaddr;
69*4882a593Smuzhiyun printf("## TFTP bootm %s at %s size 0x%lx\n",
70*4882a593Smuzhiyun argv[2], fileaddr, filesize);
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun return do_bootm(NULL, 0, ARRAY_SIZE(bootm_argv), bootm_argv);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun U_BOOT_CMD(
76*4882a593Smuzhiyun tftpbootm, 3, 1, do_tftpbootm,
77*4882a593Smuzhiyun "tftpbootm aosp/uImage/FIT image via network using TFTP protocol",
78*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename]"
79*4882a593Smuzhiyun );
80*4882a593Smuzhiyun #endif
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun #ifdef CONFIG_CMD_TFTP_FLASH
do_tftpflash(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])83*4882a593Smuzhiyun int do_tftpflash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun char *tftp_argv[] = { "tftp", NULL, NULL };
86*4882a593Smuzhiyun struct blk_desc *dev_desc;
87*4882a593Smuzhiyun disk_partition_t part;
88*4882a593Smuzhiyun ulong fileaddr;
89*4882a593Smuzhiyun ulong filesize;
90*4882a593Smuzhiyun char *part_name;
91*4882a593Smuzhiyun int ret, blknum;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (argc != 4)
94*4882a593Smuzhiyun return CMD_RET_USAGE;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /* search partition */
97*4882a593Smuzhiyun dev_desc = rockchip_get_bootdev();
98*4882a593Smuzhiyun if (!dev_desc) {
99*4882a593Smuzhiyun printf("No boot device\n");
100*4882a593Smuzhiyun return -ENODEV;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun part_name = argv[3];
104*4882a593Smuzhiyun ret = part_get_info_by_name(dev_desc, part_name, &part);
105*4882a593Smuzhiyun if (ret < 0) {
106*4882a593Smuzhiyun printf("No partition '%s'\n", part_name);
107*4882a593Smuzhiyun return -EINVAL;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* tftp download */
111*4882a593Smuzhiyun tftp_argv[1] = argv[1];
112*4882a593Smuzhiyun tftp_argv[2] = argv[2];
113*4882a593Smuzhiyun if (do_tftpb(cmdtp, 0, ARRAY_SIZE(tftp_argv), tftp_argv))
114*4882a593Smuzhiyun return -ENOENT;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun fileaddr = env_get_ulong("fileaddr", 16, 0);
117*4882a593Smuzhiyun filesize = env_get_ulong("filesize", 16, 0);
118*4882a593Smuzhiyun if (!fileaddr || !filesize)
119*4882a593Smuzhiyun return -ENOENT;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* flash */
122*4882a593Smuzhiyun blknum = DIV_ROUND_UP(filesize, dev_desc->blksz);
123*4882a593Smuzhiyun if (blknum > part.size) {
124*4882a593Smuzhiyun printf("File size 0x%lx is too large to flash\n", filesize);
125*4882a593Smuzhiyun return -EINVAL;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun printf("## TFTP flash %s to partititon '%s' size 0x%lx ... ",
129*4882a593Smuzhiyun argv[2], part_name, filesize);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (dev_desc->if_type == IF_TYPE_MTD)
132*4882a593Smuzhiyun dev_desc->op_flag |= BLK_MTD_CONT_WRITE;
133*4882a593Smuzhiyun ret = blk_dwrite(dev_desc, part.start, blknum, (void *)fileaddr);
134*4882a593Smuzhiyun if (dev_desc->if_type == IF_TYPE_MTD)
135*4882a593Smuzhiyun dev_desc->op_flag &= ~(BLK_MTD_CONT_WRITE);
136*4882a593Smuzhiyun if (ret != blknum)
137*4882a593Smuzhiyun printf("Failed(%d)\n", ret);
138*4882a593Smuzhiyun else
139*4882a593Smuzhiyun printf("OK\n");
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun U_BOOT_CMD(
145*4882a593Smuzhiyun tftpflash, 4, 0, do_tftpflash,
146*4882a593Smuzhiyun "flash image via network using TFTP protocol",
147*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename] [partition]"
148*4882a593Smuzhiyun );
149*4882a593Smuzhiyun #endif
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #ifdef CONFIG_CMD_TFTPPUT
do_tftpput(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])152*4882a593Smuzhiyun static int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun return netboot_common(TFTPPUT, cmdtp, argc, argv);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun U_BOOT_CMD(
158*4882a593Smuzhiyun tftpput, 4, 1, do_tftpput,
159*4882a593Smuzhiyun "TFTP put command, for uploading files to a server",
160*4882a593Smuzhiyun "Address Size [[hostIPaddr:]filename]"
161*4882a593Smuzhiyun );
162*4882a593Smuzhiyun #endif
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun #ifdef CONFIG_CMD_TFTPSRV
do_tftpsrv(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])165*4882a593Smuzhiyun static int do_tftpsrv(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun return netboot_common(TFTPSRV, cmdtp, argc, argv);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun U_BOOT_CMD(
171*4882a593Smuzhiyun tftpsrv, 2, 1, do_tftpsrv,
172*4882a593Smuzhiyun "act as a TFTP server and boot the first received file",
173*4882a593Smuzhiyun "[loadAddress]\n"
174*4882a593Smuzhiyun "Listen for an incoming TFTP transfer, receive a file and boot it.\n"
175*4882a593Smuzhiyun "The transfer is aborted if a transfer has not been started after\n"
176*4882a593Smuzhiyun "about 50 seconds or if Ctrl-C is pressed."
177*4882a593Smuzhiyun );
178*4882a593Smuzhiyun #endif
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun #ifdef CONFIG_UDP_FUNCTION_FASTBOOT
do_fastboot_udp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])181*4882a593Smuzhiyun int do_fastboot_udp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun return netboot_common(FASTBOOT, cmdtp, argc, argv);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun #endif
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun #ifdef CONFIG_CMD_RARP
do_rarpb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])188*4882a593Smuzhiyun int do_rarpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun return netboot_common(RARP, cmdtp, argc, argv);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun U_BOOT_CMD(
194*4882a593Smuzhiyun rarpboot, 3, 1, do_rarpb,
195*4882a593Smuzhiyun "boot image via network using RARP/TFTP protocol",
196*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename]"
197*4882a593Smuzhiyun );
198*4882a593Smuzhiyun #endif
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun #if defined(CONFIG_CMD_DHCP)
do_dhcp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])201*4882a593Smuzhiyun static int do_dhcp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun return netboot_common(DHCP, cmdtp, argc, argv);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun U_BOOT_CMD(
207*4882a593Smuzhiyun dhcp, 3, 1, do_dhcp,
208*4882a593Smuzhiyun "boot image via network using DHCP/TFTP protocol",
209*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename]"
210*4882a593Smuzhiyun );
211*4882a593Smuzhiyun #endif
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun #if defined(CONFIG_CMD_NFS)
do_nfs(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])214*4882a593Smuzhiyun static int do_nfs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun return netboot_common(NFS, cmdtp, argc, argv);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun U_BOOT_CMD(
220*4882a593Smuzhiyun nfs, 3, 1, do_nfs,
221*4882a593Smuzhiyun "boot image via network using NFS protocol",
222*4882a593Smuzhiyun "[loadAddress] [[hostIPaddr:]bootfilename]"
223*4882a593Smuzhiyun );
224*4882a593Smuzhiyun #endif
225*4882a593Smuzhiyun
netboot_update_env(void)226*4882a593Smuzhiyun static void netboot_update_env(void)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun char tmp[22];
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (net_gateway.s_addr) {
231*4882a593Smuzhiyun ip_to_string(net_gateway, tmp);
232*4882a593Smuzhiyun env_set("gatewayip", tmp);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (net_netmask.s_addr) {
236*4882a593Smuzhiyun ip_to_string(net_netmask, tmp);
237*4882a593Smuzhiyun env_set("netmask", tmp);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun if (net_hostname[0])
241*4882a593Smuzhiyun env_set("hostname", net_hostname);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (net_root_path[0])
244*4882a593Smuzhiyun env_set("rootpath", net_root_path);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (net_ip.s_addr) {
247*4882a593Smuzhiyun ip_to_string(net_ip, tmp);
248*4882a593Smuzhiyun env_set("ipaddr", tmp);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun #if !defined(CONFIG_BOOTP_SERVERIP)
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * Only attempt to change serverip if net/bootp.c:store_net_params()
253*4882a593Smuzhiyun * could have set it
254*4882a593Smuzhiyun */
255*4882a593Smuzhiyun if (net_server_ip.s_addr) {
256*4882a593Smuzhiyun ip_to_string(net_server_ip, tmp);
257*4882a593Smuzhiyun env_set("serverip", tmp);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun #endif
260*4882a593Smuzhiyun if (net_dns_server.s_addr) {
261*4882a593Smuzhiyun ip_to_string(net_dns_server, tmp);
262*4882a593Smuzhiyun env_set("dnsip", tmp);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun #if defined(CONFIG_BOOTP_DNS2)
265*4882a593Smuzhiyun if (net_dns_server2.s_addr) {
266*4882a593Smuzhiyun ip_to_string(net_dns_server2, tmp);
267*4882a593Smuzhiyun env_set("dnsip2", tmp);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun #endif
270*4882a593Smuzhiyun if (net_nis_domain[0])
271*4882a593Smuzhiyun env_set("domain", net_nis_domain);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
274*4882a593Smuzhiyun if (net_ntp_time_offset) {
275*4882a593Smuzhiyun sprintf(tmp, "%d", net_ntp_time_offset);
276*4882a593Smuzhiyun env_set("timeoffset", tmp);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun #endif
279*4882a593Smuzhiyun #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
280*4882a593Smuzhiyun if (net_ntp_server.s_addr) {
281*4882a593Smuzhiyun ip_to_string(net_ntp_server, tmp);
282*4882a593Smuzhiyun env_set("ntpserverip", tmp);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun #endif
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
netboot_common(enum proto_t proto,cmd_tbl_t * cmdtp,int argc,char * const argv[])287*4882a593Smuzhiyun static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
288*4882a593Smuzhiyun char * const argv[])
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun char *s;
291*4882a593Smuzhiyun char *end;
292*4882a593Smuzhiyun int rcode = 0;
293*4882a593Smuzhiyun int size;
294*4882a593Smuzhiyun ulong addr;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun /* pre-set load_addr */
297*4882a593Smuzhiyun s = env_get("loadaddr");
298*4882a593Smuzhiyun if (s != NULL)
299*4882a593Smuzhiyun load_addr = simple_strtoul(s, NULL, 16);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun switch (argc) {
302*4882a593Smuzhiyun case 1:
303*4882a593Smuzhiyun break;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun case 2: /*
306*4882a593Smuzhiyun * Only one arg - accept two forms:
307*4882a593Smuzhiyun * Just load address, or just boot file name. The latter
308*4882a593Smuzhiyun * form must be written in a format which can not be
309*4882a593Smuzhiyun * mis-interpreted as a valid number.
310*4882a593Smuzhiyun */
311*4882a593Smuzhiyun addr = simple_strtoul(argv[1], &end, 16);
312*4882a593Smuzhiyun if (end == (argv[1] + strlen(argv[1])))
313*4882a593Smuzhiyun load_addr = addr;
314*4882a593Smuzhiyun else
315*4882a593Smuzhiyun copy_filename(net_boot_file_name, argv[1],
316*4882a593Smuzhiyun sizeof(net_boot_file_name));
317*4882a593Smuzhiyun break;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun case 3:
320*4882a593Smuzhiyun load_addr = simple_strtoul(argv[1], NULL, 16);
321*4882a593Smuzhiyun copy_filename(net_boot_file_name, argv[2],
322*4882a593Smuzhiyun sizeof(net_boot_file_name));
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun break;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun #ifdef CONFIG_CMD_TFTPPUT
327*4882a593Smuzhiyun case 4:
328*4882a593Smuzhiyun if (strict_strtoul(argv[1], 16, &save_addr) < 0 ||
329*4882a593Smuzhiyun strict_strtoul(argv[2], 16, &save_size) < 0) {
330*4882a593Smuzhiyun printf("Invalid address/size\n");
331*4882a593Smuzhiyun return CMD_RET_USAGE;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun copy_filename(net_boot_file_name, argv[3],
334*4882a593Smuzhiyun sizeof(net_boot_file_name));
335*4882a593Smuzhiyun break;
336*4882a593Smuzhiyun #endif
337*4882a593Smuzhiyun default:
338*4882a593Smuzhiyun bootstage_error(BOOTSTAGE_ID_NET_START);
339*4882a593Smuzhiyun return CMD_RET_USAGE;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun bootstage_mark(BOOTSTAGE_ID_NET_START);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun size = net_loop(proto);
344*4882a593Smuzhiyun if (size < 0) {
345*4882a593Smuzhiyun bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
346*4882a593Smuzhiyun return CMD_RET_FAILURE;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /* net_loop ok, update environment */
351*4882a593Smuzhiyun netboot_update_env();
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /* done if no file was loaded (no errors though) */
354*4882a593Smuzhiyun if (size == 0) {
355*4882a593Smuzhiyun bootstage_error(BOOTSTAGE_ID_NET_LOADED);
356*4882a593Smuzhiyun return CMD_RET_SUCCESS;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun rcode = bootm_maybe_autostart(cmdtp, argv[0]);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun if (rcode == CMD_RET_SUCCESS)
364*4882a593Smuzhiyun bootstage_mark(BOOTSTAGE_ID_NET_DONE);
365*4882a593Smuzhiyun else
366*4882a593Smuzhiyun bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
367*4882a593Smuzhiyun return rcode;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun #if defined(CONFIG_CMD_PING)
do_ping(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])371*4882a593Smuzhiyun static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun if (argc < 2)
374*4882a593Smuzhiyun return CMD_RET_USAGE;
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun net_ping_ip = string_to_ip(argv[1]);
377*4882a593Smuzhiyun if (net_ping_ip.s_addr == 0)
378*4882a593Smuzhiyun return CMD_RET_USAGE;
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (net_loop(PING) < 0) {
381*4882a593Smuzhiyun printf("ping failed; host %s is not alive\n", argv[1]);
382*4882a593Smuzhiyun return CMD_RET_FAILURE;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun printf("host %s is alive\n", argv[1]);
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun return CMD_RET_SUCCESS;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun U_BOOT_CMD(
391*4882a593Smuzhiyun ping, 2, 1, do_ping,
392*4882a593Smuzhiyun "send ICMP ECHO_REQUEST to network host",
393*4882a593Smuzhiyun "pingAddress"
394*4882a593Smuzhiyun );
395*4882a593Smuzhiyun #endif
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun #if defined(CONFIG_CMD_CDP)
398*4882a593Smuzhiyun
cdp_update_env(void)399*4882a593Smuzhiyun static void cdp_update_env(void)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun char tmp[16];
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun if (cdp_appliance_vlan != htons(-1)) {
404*4882a593Smuzhiyun printf("CDP offered appliance VLAN %d\n",
405*4882a593Smuzhiyun ntohs(cdp_appliance_vlan));
406*4882a593Smuzhiyun vlan_to_string(cdp_appliance_vlan, tmp);
407*4882a593Smuzhiyun env_set("vlan", tmp);
408*4882a593Smuzhiyun net_our_vlan = cdp_appliance_vlan;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun if (cdp_native_vlan != htons(-1)) {
412*4882a593Smuzhiyun printf("CDP offered native VLAN %d\n", ntohs(cdp_native_vlan));
413*4882a593Smuzhiyun vlan_to_string(cdp_native_vlan, tmp);
414*4882a593Smuzhiyun env_set("nvlan", tmp);
415*4882a593Smuzhiyun net_native_vlan = cdp_native_vlan;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
do_cdp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])419*4882a593Smuzhiyun int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun int r;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun r = net_loop(CDP);
424*4882a593Smuzhiyun if (r < 0) {
425*4882a593Smuzhiyun printf("cdp failed; perhaps not a CISCO switch?\n");
426*4882a593Smuzhiyun return CMD_RET_FAILURE;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun cdp_update_env();
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun return CMD_RET_SUCCESS;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun U_BOOT_CMD(
435*4882a593Smuzhiyun cdp, 1, 1, do_cdp,
436*4882a593Smuzhiyun "Perform CDP network configuration",
437*4882a593Smuzhiyun "\n"
438*4882a593Smuzhiyun );
439*4882a593Smuzhiyun #endif
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun #if defined(CONFIG_CMD_SNTP)
do_sntp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])442*4882a593Smuzhiyun int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun char *toff;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (argc < 2) {
447*4882a593Smuzhiyun net_ntp_server = env_get_ip("ntpserverip");
448*4882a593Smuzhiyun if (net_ntp_server.s_addr == 0) {
449*4882a593Smuzhiyun printf("ntpserverip not set\n");
450*4882a593Smuzhiyun return CMD_RET_FAILURE;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun } else {
453*4882a593Smuzhiyun net_ntp_server = string_to_ip(argv[1]);
454*4882a593Smuzhiyun if (net_ntp_server.s_addr == 0) {
455*4882a593Smuzhiyun printf("Bad NTP server IP address\n");
456*4882a593Smuzhiyun return CMD_RET_FAILURE;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun toff = env_get("timeoffset");
461*4882a593Smuzhiyun if (toff == NULL)
462*4882a593Smuzhiyun net_ntp_time_offset = 0;
463*4882a593Smuzhiyun else
464*4882a593Smuzhiyun net_ntp_time_offset = simple_strtol(toff, NULL, 10);
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun if (net_loop(SNTP) < 0) {
467*4882a593Smuzhiyun printf("SNTP failed: host %pI4 not responding\n",
468*4882a593Smuzhiyun &net_ntp_server);
469*4882a593Smuzhiyun return CMD_RET_FAILURE;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun return CMD_RET_SUCCESS;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun U_BOOT_CMD(
476*4882a593Smuzhiyun sntp, 2, 1, do_sntp,
477*4882a593Smuzhiyun "synchronize RTC via network",
478*4882a593Smuzhiyun "[NTP server IP]\n"
479*4882a593Smuzhiyun );
480*4882a593Smuzhiyun #endif
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun #if defined(CONFIG_CMD_DNS)
do_dns(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])483*4882a593Smuzhiyun int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun if (argc == 1)
486*4882a593Smuzhiyun return CMD_RET_USAGE;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun /*
489*4882a593Smuzhiyun * We should check for a valid hostname:
490*4882a593Smuzhiyun * - Each label must be between 1 and 63 characters long
491*4882a593Smuzhiyun * - the entire hostname has a maximum of 255 characters
492*4882a593Smuzhiyun * - only the ASCII letters 'a' through 'z' (case-insensitive),
493*4882a593Smuzhiyun * the digits '0' through '9', and the hyphen
494*4882a593Smuzhiyun * - cannot begin or end with a hyphen
495*4882a593Smuzhiyun * - no other symbols, punctuation characters, or blank spaces are
496*4882a593Smuzhiyun * permitted
497*4882a593Smuzhiyun * but hey - this is a minimalist implmentation, so only check length
498*4882a593Smuzhiyun * and let the name server deal with things.
499*4882a593Smuzhiyun */
500*4882a593Smuzhiyun if (strlen(argv[1]) >= 255) {
501*4882a593Smuzhiyun printf("dns error: hostname too long\n");
502*4882a593Smuzhiyun return CMD_RET_FAILURE;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun net_dns_resolve = argv[1];
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun if (argc == 3)
508*4882a593Smuzhiyun net_dns_env_var = argv[2];
509*4882a593Smuzhiyun else
510*4882a593Smuzhiyun net_dns_env_var = NULL;
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun if (net_loop(DNS) < 0) {
513*4882a593Smuzhiyun printf("dns lookup of %s failed, check setup\n", argv[1]);
514*4882a593Smuzhiyun return CMD_RET_FAILURE;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun return CMD_RET_SUCCESS;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun U_BOOT_CMD(
521*4882a593Smuzhiyun dns, 3, 1, do_dns,
522*4882a593Smuzhiyun "lookup the IP of a hostname",
523*4882a593Smuzhiyun "hostname [envvar]"
524*4882a593Smuzhiyun );
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun #endif /* CONFIG_CMD_DNS */
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun #if defined(CONFIG_CMD_LINK_LOCAL)
do_link_local(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])529*4882a593Smuzhiyun static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
530*4882a593Smuzhiyun char * const argv[])
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun char tmp[22];
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun if (net_loop(LINKLOCAL) < 0)
535*4882a593Smuzhiyun return CMD_RET_FAILURE;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun net_gateway.s_addr = 0;
538*4882a593Smuzhiyun ip_to_string(net_gateway, tmp);
539*4882a593Smuzhiyun env_set("gatewayip", tmp);
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun ip_to_string(net_netmask, tmp);
542*4882a593Smuzhiyun env_set("netmask", tmp);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun ip_to_string(net_ip, tmp);
545*4882a593Smuzhiyun env_set("ipaddr", tmp);
546*4882a593Smuzhiyun env_set("llipaddr", tmp); /* store this for next time */
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun return CMD_RET_SUCCESS;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun U_BOOT_CMD(
552*4882a593Smuzhiyun linklocal, 1, 1, do_link_local,
553*4882a593Smuzhiyun "acquire a network IP address using the link-local protocol",
554*4882a593Smuzhiyun ""
555*4882a593Smuzhiyun );
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun #endif /* CONFIG_CMD_LINK_LOCAL */
558