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
  33int 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)
 107int 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)
 120int 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)
 277int 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) NetTimeOffset = 0;
 368        else NetTimeOffset = simple_strtol (toff, NULL, 10);
 369
 370        if (NetLoop(SNTP) < 0) {
 371                printf("SNTP failed: host %pI4 not responding\n",
 372                        &NetNtpServerIP);
 373                return 1;
 374        }
 375
 376        return 0;
 377}
 378
 379U_BOOT_CMD(
 380        sntp,   2,      1,      do_sntp,
 381        "synchronize RTC via network",
 382        "[NTP server IP]\n"
 383);
 384#endif
 385
 386#if defined(CONFIG_CMD_DNS)
 387int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 388{
 389        if (argc == 1)
 390                return CMD_RET_USAGE;
 391
 392        /*
 393         * We should check for a valid hostname:
 394         * - Each label must be between 1 and 63 characters long
 395         * - the entire hostname has a maximum of 255 characters
 396         * - only the ASCII letters 'a' through 'z' (case-insensitive),
 397         *   the digits '0' through '9', and the hyphen
 398         * - cannot begin or end with a hyphen
 399         * - no other symbols, punctuation characters, or blank spaces are
 400         *   permitted
 401         * but hey - this is a minimalist implmentation, so only check length
 402         * and let the name server deal with things.
 403         */
 404        if (strlen(argv[1]) >= 255) {
 405                printf("dns error: hostname too long\n");
 406                return 1;
 407        }
 408
 409        NetDNSResolve = argv[1];
 410
 411        if (argc == 3)
 412                NetDNSenvvar = argv[2];
 413        else
 414                NetDNSenvvar = NULL;
 415
 416        if (NetLoop(DNS) < 0) {
 417                printf("dns lookup of %s failed, check setup\n", argv[1]);
 418                return 1;
 419        }
 420
 421        return 0;
 422}
 423
 424U_BOOT_CMD(
 425        dns,    3,      1,      do_dns,
 426        "lookup the IP of a hostname",
 427        "hostname [envvar]"
 428);
 429
 430#endif  /* CONFIG_CMD_DNS */
 431
 432#if defined(CONFIG_CMD_LINK_LOCAL)
 433static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 434                        char * const argv[])
 435{
 436        char tmp[22];
 437
 438        if (NetLoop(LINKLOCAL) < 0)
 439                return 1;
 440
 441        NetOurGatewayIP = 0;
 442        ip_to_string(NetOurGatewayIP, tmp);
 443        setenv("gatewayip", tmp);
 444
 445        ip_to_string(NetOurSubnetMask, tmp);
 446        setenv("netmask", tmp);
 447
 448        ip_to_string(NetOurIP, tmp);
 449        setenv("ipaddr", tmp);
 450        setenv("llipaddr", tmp); /* store this for next time */
 451
 452        return 0;
 453}
 454
 455U_BOOT_CMD(
 456        linklocal,      1,      1,      do_link_local,
 457        "acquire a network IP address using the link-local protocol",
 458        ""
 459);
 460
 461#endif  /* CONFIG_CMD_LINK_LOCAL */
 462