Blame view
cmd/net.c
10.2 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
3863585bb
|
2 3 4 |
/* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
3863585bb
|
5 6 7 8 9 10 11 |
*/ /* * Boot support */ #include <common.h> #include <command.h> |
9fb625ce0
|
12 |
#include <env.h> |
8e8ccfe1a
|
13 |
#include <image.h> |
3863585bb
|
14 |
#include <net.h> |
e4bf0c5cf
|
15 |
static int netboot_common(enum proto_t, cmd_tbl_t *, int, char * const []); |
3863585bb
|
16 |
|
d7a45eafd
|
17 |
#ifdef CONFIG_CMD_BOOTP |
088f1b199
|
18 |
static int do_bootp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
3863585bb
|
19 |
{ |
088f1b199
|
20 |
return netboot_common(BOOTP, cmdtp, argc, argv); |
3863585bb
|
21 |
} |
0d4983930
|
22 23 |
U_BOOT_CMD( bootp, 3, 1, do_bootp, |
2fb2604d5
|
24 |
"boot image via network using BOOTP/TFTP protocol", |
a89c33db9
|
25 |
"[loadAddress] [[hostIPaddr:]bootfilename]" |
8bde7f776
|
26 |
); |
d7a45eafd
|
27 |
#endif |
8bde7f776
|
28 |
|
d7a45eafd
|
29 |
#ifdef CONFIG_CMD_TFTPBOOT |
088f1b199
|
30 |
int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
3863585bb
|
31 |
{ |
573f14fe4
|
32 33 34 35 36 37 |
int ret; bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); ret = netboot_common(TFTPGET, cmdtp, argc, argv); bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); return ret; |
3863585bb
|
38 |
} |
0d4983930
|
39 40 |
U_BOOT_CMD( tftpboot, 3, 1, do_tftpb, |
2fb2604d5
|
41 |
"boot image via network using TFTP protocol", |
a89c33db9
|
42 |
"[loadAddress] [[hostIPaddr:]bootfilename]" |
8bde7f776
|
43 |
); |
d7a45eafd
|
44 |
#endif |
8bde7f776
|
45 |
|
2d46cf291
|
46 |
#ifdef CONFIG_CMD_TFTPPUT |
0c1b869b2
|
47 |
static int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
2d46cf291
|
48 |
{ |
85848f037
|
49 |
return netboot_common(TFTPPUT, cmdtp, argc, argv); |
2d46cf291
|
50 51 52 53 54 55 56 57 |
} U_BOOT_CMD( tftpput, 4, 1, do_tftpput, "TFTP put command, for uploading files to a server", "Address Size [[hostIPaddr:]filename]" ); #endif |
7a83af07a
|
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#ifdef CONFIG_CMD_TFTPSRV static int do_tftpsrv(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { return netboot_common(TFTPSRV, cmdtp, argc, argv); } U_BOOT_CMD( tftpsrv, 2, 1, do_tftpsrv, "act as a TFTP server and boot the first received file", "[loadAddress] " "Listen for an incoming TFTP transfer, receive a file and boot it. " "The transfer is aborted if a transfer has not been started after " "about 50 seconds or if Ctrl-C is pressed." ); #endif |
bf6cb247a
|
76 |
#ifdef CONFIG_CMD_RARP |
088f1b199
|
77 |
int do_rarpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
3863585bb
|
78 |
{ |
088f1b199
|
79 |
return netboot_common(RARP, cmdtp, argc, argv); |
3863585bb
|
80 |
} |
0d4983930
|
81 82 |
U_BOOT_CMD( rarpboot, 3, 1, do_rarpb, |
2fb2604d5
|
83 |
"boot image via network using RARP/TFTP protocol", |
a89c33db9
|
84 |
"[loadAddress] [[hostIPaddr:]bootfilename]" |
8bde7f776
|
85 |
); |
bf6cb247a
|
86 |
#endif |
8bde7f776
|
87 |
|
c76fe4742
|
88 |
#if defined(CONFIG_CMD_DHCP) |
088f1b199
|
89 |
static int do_dhcp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
3863585bb
|
90 91 92 |
{ return netboot_common(DHCP, cmdtp, argc, argv); } |
8bde7f776
|
93 |
|
0d4983930
|
94 95 |
U_BOOT_CMD( dhcp, 3, 1, do_dhcp, |
2fb2604d5
|
96 |
"boot image via network using DHCP/TFTP protocol", |
a89c33db9
|
97 |
"[loadAddress] [[hostIPaddr:]bootfilename]" |
8bde7f776
|
98 |
); |
902531788
|
99 |
#endif |
3863585bb
|
100 |
|
c76fe4742
|
101 |
#if defined(CONFIG_CMD_NFS) |
088f1b199
|
102 |
static int do_nfs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
cbd8a35c6
|
103 104 105 106 107 108 |
{ return netboot_common(NFS, cmdtp, argc, argv); } U_BOOT_CMD( nfs, 3, 1, do_nfs, |
2fb2604d5
|
109 |
"boot image via network using NFS protocol", |
a89c33db9
|
110 |
"[loadAddress] [[hostIPaddr:]bootfilename]" |
cbd8a35c6
|
111 |
); |
902531788
|
112 |
#endif |
cbd8a35c6
|
113 |
|
088f1b199
|
114 |
static void netboot_update_env(void) |
3863585bb
|
115 |
{ |
6e5923851
|
116 |
char tmp[22]; |
3863585bb
|
117 |
|
049a95a77
|
118 119 |
if (net_gateway.s_addr) { ip_to_string(net_gateway, tmp); |
382bee57f
|
120 |
env_set("gatewayip", tmp); |
6e5923851
|
121 |
} |
3863585bb
|
122 |
|
049a95a77
|
123 124 |
if (net_netmask.s_addr) { ip_to_string(net_netmask, tmp); |
382bee57f
|
125 |
env_set("netmask", tmp); |
6e5923851
|
126 |
} |
3863585bb
|
127 |
|
586cbe51a
|
128 |
if (net_hostname[0]) |
382bee57f
|
129 |
env_set("hostname", net_hostname); |
3863585bb
|
130 |
|
586cbe51a
|
131 |
if (net_root_path[0]) |
382bee57f
|
132 |
env_set("rootpath", net_root_path); |
3863585bb
|
133 |
|
049a95a77
|
134 135 |
if (net_ip.s_addr) { ip_to_string(net_ip, tmp); |
382bee57f
|
136 |
env_set("ipaddr", tmp); |
6e5923851
|
137 |
} |
a3e1a727f
|
138 139 |
#if !defined(CONFIG_BOOTP_SERVERIP) /* |
ff78ad284
|
140 |
* Only attempt to change serverip if net/bootp.c:store_net_params() |
a3e1a727f
|
141 142 |
* could have set it */ |
049a95a77
|
143 144 |
if (net_server_ip.s_addr) { ip_to_string(net_server_ip, tmp); |
382bee57f
|
145 |
env_set("serverip", tmp); |
6e5923851
|
146 |
} |
a3e1a727f
|
147 |
#endif |
049a95a77
|
148 149 |
if (net_dns_server.s_addr) { ip_to_string(net_dns_server, tmp); |
382bee57f
|
150 |
env_set("dnsip", tmp); |
6e5923851
|
151 |
} |
1fe80d79c
|
152 |
#if defined(CONFIG_BOOTP_DNS2) |
049a95a77
|
153 154 |
if (net_dns_server2.s_addr) { ip_to_string(net_dns_server2, tmp); |
382bee57f
|
155 |
env_set("dnsip2", tmp); |
6e5923851
|
156 |
} |
fe389a82c
|
157 |
#endif |
586cbe51a
|
158 |
if (net_nis_domain[0]) |
382bee57f
|
159 |
env_set("domain", net_nis_domain); |
ea287debe
|
160 |
|
4fd5055f5
|
161 |
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) |
bc0571fc1
|
162 163 |
if (net_ntp_time_offset) { sprintf(tmp, "%d", net_ntp_time_offset); |
382bee57f
|
164 |
env_set("timeoffset", tmp); |
ea287debe
|
165 166 |
} #endif |
4fd5055f5
|
167 |
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER) |
049a95a77
|
168 169 |
if (net_ntp_server.s_addr) { ip_to_string(net_ntp_server, tmp); |
382bee57f
|
170 |
env_set("ntpserverip", tmp); |
ea287debe
|
171 172 |
} #endif |
3863585bb
|
173 |
} |
6e5923851
|
174 |
|
e4bf0c5cf
|
175 176 |
static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, char * const argv[]) |
3863585bb
|
177 178 |
{ char *s; |
2e4970d81
|
179 |
char *end; |
3863585bb
|
180 181 |
int rcode = 0; int size; |
2e4970d81
|
182 |
ulong addr; |
3863585bb
|
183 |
|
449312c1c
|
184 |
net_boot_file_name_explicit = false; |
bb872dd93
|
185 |
/* pre-set image_load_addr */ |
00caae6d4
|
186 |
s = env_get("loadaddr"); |
4fd5055f5
|
187 |
if (s != NULL) |
bb872dd93
|
188 |
image_load_addr = simple_strtoul(s, NULL, 16); |
3863585bb
|
189 190 191 |
switch (argc) { case 1: |
f43308fa0
|
192 193 194 |
/* refresh bootfile name from env */ copy_filename(net_boot_file_name, env_get("bootfile"), sizeof(net_boot_file_name)); |
3863585bb
|
195 |
break; |
2e4970d81
|
196 197 198 199 200 |
case 2: /* * Only one arg - accept two forms: * Just load address, or just boot file name. The latter * form must be written in a format which can not be * mis-interpreted as a valid number. |
3863585bb
|
201 |
*/ |
2e4970d81
|
202 |
addr = simple_strtoul(argv[1], &end, 16); |
449312c1c
|
203 |
if (end == (argv[1] + strlen(argv[1]))) { |
bb872dd93
|
204 |
image_load_addr = addr; |
f43308fa0
|
205 206 207 |
/* refresh bootfile name from env */ copy_filename(net_boot_file_name, env_get("bootfile"), sizeof(net_boot_file_name)); |
449312c1c
|
208 209 |
} else { net_boot_file_name_explicit = true; |
1411157d8
|
210 211 |
copy_filename(net_boot_file_name, argv[1], sizeof(net_boot_file_name)); |
449312c1c
|
212 |
} |
3863585bb
|
213 |
break; |
4fd5055f5
|
214 |
case 3: |
bb872dd93
|
215 |
image_load_addr = simple_strtoul(argv[1], NULL, 16); |
449312c1c
|
216 |
net_boot_file_name_explicit = true; |
1411157d8
|
217 218 |
copy_filename(net_boot_file_name, argv[2], sizeof(net_boot_file_name)); |
3863585bb
|
219 220 |
break; |
2d46cf291
|
221 222 |
#ifdef CONFIG_CMD_TFTPPUT case 4: |
bb872dd93
|
223 224 |
if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 || strict_strtoul(argv[2], 16, &image_save_size) < 0) { |
38bd80b48
|
225 226 |
printf("Invalid address/size "); |
85848f037
|
227 |
return CMD_RET_USAGE; |
38bd80b48
|
228 |
} |
449312c1c
|
229 |
net_boot_file_name_explicit = true; |
1411157d8
|
230 231 |
copy_filename(net_boot_file_name, argv[3], sizeof(net_boot_file_name)); |
2d46cf291
|
232 233 |
break; #endif |
47e26b1bf
|
234 |
default: |
770605e4f
|
235 |
bootstage_error(BOOTSTAGE_ID_NET_START); |
4c12eeb8b
|
236 |
return CMD_RET_USAGE; |
3863585bb
|
237 |
} |
770605e4f
|
238 |
bootstage_mark(BOOTSTAGE_ID_NET_START); |
3863585bb
|
239 |
|
bc0571fc1
|
240 |
size = net_loop(proto); |
4fd5055f5
|
241 |
if (size < 0) { |
770605e4f
|
242 |
bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK); |
85848f037
|
243 |
return CMD_RET_FAILURE; |
566a494f5
|
244 |
} |
770605e4f
|
245 |
bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK); |
3863585bb
|
246 |
|
bc0571fc1
|
247 |
/* net_loop ok, update environment */ |
3863585bb
|
248 |
netboot_update_env(); |
eb9401e3e
|
249 |
/* done if no file was loaded (no errors though) */ |
566a494f5
|
250 |
if (size == 0) { |
770605e4f
|
251 |
bootstage_error(BOOTSTAGE_ID_NET_LOADED); |
85848f037
|
252 |
return CMD_RET_SUCCESS; |
566a494f5
|
253 |
} |
eb9401e3e
|
254 |
|
770605e4f
|
255 |
bootstage_mark(BOOTSTAGE_ID_NET_LOADED); |
c8e66db78
|
256 |
|
67d668bf9
|
257 |
rcode = bootm_maybe_autostart(cmdtp, argv[0]); |
3863585bb
|
258 |
|
85848f037
|
259 |
if (rcode == CMD_RET_SUCCESS) |
770605e4f
|
260 |
bootstage_mark(BOOTSTAGE_ID_NET_DONE); |
85848f037
|
261 262 |
else bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR); |
3863585bb
|
263 264 |
return rcode; } |
c76fe4742
|
265 |
#if defined(CONFIG_CMD_PING) |
088f1b199
|
266 |
static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
73a8b27c5
|
267 268 |
{ if (argc < 2) |
85848f037
|
269 |
return CMD_RET_USAGE; |
73a8b27c5
|
270 |
|
049a95a77
|
271 272 |
net_ping_ip = string_to_ip(argv[1]); if (net_ping_ip.s_addr == 0) |
4c12eeb8b
|
273 |
return CMD_RET_USAGE; |
73a8b27c5
|
274 |
|
bc0571fc1
|
275 |
if (net_loop(PING) < 0) { |
73a8b27c5
|
276 277 |
printf("ping failed; host %s is not alive ", argv[1]); |
85848f037
|
278 |
return CMD_RET_FAILURE; |
73a8b27c5
|
279 280 281 282 |
} printf("host %s is alive ", argv[1]); |
85848f037
|
283 |
return CMD_RET_SUCCESS; |
73a8b27c5
|
284 |
} |
6dff55297
|
285 286 287 |
U_BOOT_CMD( ping, 2, 1, do_ping, |
2fb2604d5
|
288 |
"send ICMP ECHO_REQUEST to network host", |
a89c33db9
|
289 |
"pingAddress" |
6dff55297
|
290 |
); |
902531788
|
291 |
#endif |
73a8b27c5
|
292 |
|
c76fe4742
|
293 |
#if defined(CONFIG_CMD_CDP) |
a3d991bd0
|
294 295 296 297 |
static void cdp_update_env(void) { char tmp[16]; |
6aede5b75
|
298 299 300 301 |
if (cdp_appliance_vlan != htons(-1)) { printf("CDP offered appliance VLAN %d ", ntohs(cdp_appliance_vlan)); |
4fd5055f5
|
302 |
vlan_to_string(cdp_appliance_vlan, tmp); |
382bee57f
|
303 |
env_set("vlan", tmp); |
4fd5055f5
|
304 |
net_our_vlan = cdp_appliance_vlan; |
a3d991bd0
|
305 |
} |
6aede5b75
|
306 307 308 |
if (cdp_native_vlan != htons(-1)) { printf("CDP offered native VLAN %d ", ntohs(cdp_native_vlan)); |
4fd5055f5
|
309 |
vlan_to_string(cdp_native_vlan, tmp); |
382bee57f
|
310 |
env_set("nvlan", tmp); |
4fd5055f5
|
311 |
net_native_vlan = cdp_native_vlan; |
a3d991bd0
|
312 |
} |
a3d991bd0
|
313 |
} |
088f1b199
|
314 |
int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
a3d991bd0
|
315 316 |
{ int r; |
bc0571fc1
|
317 |
r = net_loop(CDP); |
a3d991bd0
|
318 319 320 |
if (r < 0) { printf("cdp failed; perhaps not a CISCO switch? "); |
85848f037
|
321 |
return CMD_RET_FAILURE; |
a3d991bd0
|
322 323 324 |
} cdp_update_env(); |
85848f037
|
325 |
return CMD_RET_SUCCESS; |
a3d991bd0
|
326 327 328 329 |
} U_BOOT_CMD( cdp, 1, 1, do_cdp, |
ec5c04cdb
|
330 |
"Perform CDP network configuration", |
4b58266e9
|
331 332 |
" " |
a3d991bd0
|
333 |
); |
902531788
|
334 |
#endif |
a3d991bd0
|
335 |
|
c76fe4742
|
336 |
#if defined(CONFIG_CMD_SNTP) |
088f1b199
|
337 |
int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
ea287debe
|
338 339 340 341 |
{ char *toff; if (argc < 2) { |
723806cc5
|
342 |
net_ntp_server = env_get_ip("ntpserverip"); |
049a95a77
|
343 |
if (net_ntp_server.s_addr == 0) { |
088f1b199
|
344 345 |
printf("ntpserverip not set "); |
85848f037
|
346 |
return CMD_RET_FAILURE; |
ea287debe
|
347 348 |
} } else { |
049a95a77
|
349 350 |
net_ntp_server = string_to_ip(argv[1]); if (net_ntp_server.s_addr == 0) { |
088f1b199
|
351 352 |
printf("Bad NTP server IP address "); |
85848f037
|
353 |
return CMD_RET_FAILURE; |
ea287debe
|
354 355 |
} } |
00caae6d4
|
356 |
toff = env_get("timeoffset"); |
088f1b199
|
357 |
if (toff == NULL) |
bc0571fc1
|
358 |
net_ntp_time_offset = 0; |
088f1b199
|
359 |
else |
bc0571fc1
|
360 |
net_ntp_time_offset = simple_strtol(toff, NULL, 10); |
ea287debe
|
361 |
|
bc0571fc1
|
362 |
if (net_loop(SNTP) < 0) { |
d6840e3d7
|
363 364 |
printf("SNTP failed: host %pI4 not responding ", |
4fd5055f5
|
365 |
&net_ntp_server); |
85848f037
|
366 |
return CMD_RET_FAILURE; |
ea287debe
|
367 |
} |
85848f037
|
368 |
return CMD_RET_SUCCESS; |
ea287debe
|
369 370 371 372 |
} U_BOOT_CMD( sntp, 2, 1, do_sntp, |
2fb2604d5
|
373 |
"synchronize RTC via network", |
ea287debe
|
374 375 376 |
"[NTP server IP] " ); |
902531788
|
377 |
#endif |
1a32bf418
|
378 379 |
#if defined(CONFIG_CMD_DNS) |
54841ab50
|
380 |
int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
1a32bf418
|
381 |
{ |
47e26b1bf
|
382 |
if (argc == 1) |
4c12eeb8b
|
383 |
return CMD_RET_USAGE; |
1a32bf418
|
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
/* * We should check for a valid hostname: * - Each label must be between 1 and 63 characters long * - the entire hostname has a maximum of 255 characters * - only the ASCII letters 'a' through 'z' (case-insensitive), * the digits '0' through '9', and the hyphen * - cannot begin or end with a hyphen * - no other symbols, punctuation characters, or blank spaces are * permitted * but hey - this is a minimalist implmentation, so only check length * and let the name server deal with things. */ if (strlen(argv[1]) >= 255) { printf("dns error: hostname too long "); |
85848f037
|
400 |
return CMD_RET_FAILURE; |
1a32bf418
|
401 |
} |
786eac5f9
|
402 |
net_dns_resolve = argv[1]; |
1a32bf418
|
403 404 |
if (argc == 3) |
786eac5f9
|
405 |
net_dns_env_var = argv[2]; |
1a32bf418
|
406 |
else |
786eac5f9
|
407 |
net_dns_env_var = NULL; |
1a32bf418
|
408 |
|
bc0571fc1
|
409 |
if (net_loop(DNS) < 0) { |
1a32bf418
|
410 411 |
printf("dns lookup of %s failed, check setup ", argv[1]); |
85848f037
|
412 |
return CMD_RET_FAILURE; |
1a32bf418
|
413 |
} |
85848f037
|
414 |
return CMD_RET_SUCCESS; |
1a32bf418
|
415 416 417 418 419 420 421 422 423 |
} U_BOOT_CMD( dns, 3, 1, do_dns, "lookup the IP of a hostname", "hostname [envvar]" ); #endif /* CONFIG_CMD_DNS */ |
d22c338e0
|
424 425 426 427 428 429 |
#if defined(CONFIG_CMD_LINK_LOCAL) static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char tmp[22]; |
bc0571fc1
|
430 |
if (net_loop(LINKLOCAL) < 0) |
85848f037
|
431 |
return CMD_RET_FAILURE; |
d22c338e0
|
432 |
|
049a95a77
|
433 434 |
net_gateway.s_addr = 0; ip_to_string(net_gateway, tmp); |
382bee57f
|
435 |
env_set("gatewayip", tmp); |
d22c338e0
|
436 |
|
049a95a77
|
437 |
ip_to_string(net_netmask, tmp); |
382bee57f
|
438 |
env_set("netmask", tmp); |
d22c338e0
|
439 |
|
049a95a77
|
440 |
ip_to_string(net_ip, tmp); |
382bee57f
|
441 442 |
env_set("ipaddr", tmp); env_set("llipaddr", tmp); /* store this for next time */ |
d22c338e0
|
443 |
|
85848f037
|
444 |
return CMD_RET_SUCCESS; |
d22c338e0
|
445 446 447 448 449 450 451 452 453 |
} U_BOOT_CMD( linklocal, 1, 1, do_link_local, "acquire a network IP address using the link-local protocol", "" ); #endif /* CONFIG_CMD_LINK_LOCAL */ |