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