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