📄 cmd_boot.c
字号:
/* * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* * Boot support */#include <armboot.h>#include <command.h>#include <cmd_boot.h>#include <cmd_autoscript.h>#include <s_record.h>#include <net.h>#if (CONFIG_COMMANDS & CFG_CMD_LOADS)static ulong load_serial (ulong offset);static int read_record (char *buf, ulong len);static int do_echo = 1;#endif#if (CONFIG_COMMANDS & CFG_CMD_BDI)int do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]){ int i; printf ("enetaddr ="); for (i=0; i<6; ++i) { printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]); } printf("\n"); printf ("ip_addr = "); print_IPaddr (bd->bi_ip_addr); printf("\n"); printf ("baudrate = %d bps\n", bd->bi_baudrate); printf ("arch_number = %ld\n", bd->bi_arch_number); printf ("env_t = %08lX\n", (ulong)bd->bi_env); printf ("boot_params = %08lX\n", (ulong)bd->bi_boot_params); for (i=0; i<CONFIG_NR_DRAM_BANKS; ++i) { printf ("DRAM:%02d.start = %08lX\n", i, bd->bi_dram[i].start); printf ("DRAM:%02d.size = %08lX\n", i, bd->bi_dram[i].size); } return 0;}#endif /* CFG_CMD_BDI */int do_go (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]){ ulong addr, rc; if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } addr = simple_strtoul(argv[1], NULL, 16); printf ("## Starting application at 0x%08lx ...\n", addr); /* * pass address parameter as argv[0] (aka command name), * and all remaining args */ rc = ((ulong (*)(bd_t *, int, char *[]))addr) (bd, --argc, &argv[1]); printf ("## Application terminated, rc = 0x%lx\n", rc); return 0;}#if (CONFIG_COMMANDS & CFG_CMD_LOADS)int do_load_serial (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]){ ulong offset = 0; ulong addr; int i; char *env_echo;#ifdef CFG_LOADS_BAUD_CHANGE int loads_baudrate = bd->bi_baudrate;#endif if (((env_echo = getenv(bd, "loads_echo")) != NULL) && (*env_echo == '1')) { do_echo = 1; } else { do_echo = 0; }#ifdef CFG_LOADS_BAUD_CHANGE if (argc >= 2) { offset = simple_strtoul(argv[1], NULL, 16); } if (argc == 3) { loads_baudrate = (int)simple_strtoul(argv[2], NULL, 10); /* default to current baudrate */ if (loads_baudrate == 0) loads_baudrate = bd->bi_baudrate; }#else /* ! CFG_LOADS_BAUD_CHANGE */ if (argc == 2) { offset = simple_strtoul(argv[1], NULL, 16); }#endif /* CFG_LOADS_BAUD_CHANGE */#ifdef CFG_LOADS_BAUD_CHANGE if (loads_baudrate != bd->bi_baudrate) { printf ("## Switch baudrate to %d bps and press ENTER ...\n", loads_baudrate); udelay(50000); serial_setbrg (bd->bi_intfreq, loads_baudrate); udelay(50000); for (;;) { if (getc() == '\r') break; } }#endif /* CFG_LOADS_BAUD_CHANGE */ printf ("## Ready for S-Record download ...\n"); addr = load_serial (offset); /* * Gather any trailing characters (for instance, the ^D which * is sent by 'cu' after sending a file), and give the * box some time (100 * 1 ms) */ for (i=0; i<100; ++i) { if (serial_tstc()) { (void) serial_getc(); } udelay(1000); } if (addr == ~0) { printf ("## S-Record download aborted\n"); } else { printf ("## Start Addr = 0x%08lx\n", addr); load_addr = addr; }#ifdef CFG_LOADS_BAUD_CHANGE if (loads_baudrate != bd->bi_baudrate) { printf ("## Switch baudrate to %d bps and press ESC ...\n", (int)bd->bi_baudrate); udelay (50000); serial_setbrg (bd->bi_intfreq, bd->bi_baudrate); udelay (50000); for (;;) { if (getc() == 0x1B) /* ESC */ break; } }#endif return 0;}static ulongload_serial (ulong offset){ char record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record */ char binbuf[SREC_MAXBINLEN]; /* buffer for binary data */ int binlen; /* no. of data bytes in S-Rec. */ int type; /* return code for record type */ ulong addr; /* load address from S-Record */ ulong store_addr; ulong start_addr = ~0; ulong end_addr = 0; int line_count = 0; while (read_record(record, SREC_MAXRECLEN + 1) >= 0) { type = srec_decode (record, &binlen, &addr, binbuf); if (type < 0) { return (~0); /* Invalid S-Record */ } switch (type) { case SREC_DATA2: case SREC_DATA3: case SREC_DATA4: store_addr = addr + offset; if (addr2info(store_addr)) { int rc; switch (rc=flash_write((uchar *)binbuf,store_addr,binlen)) { case 0: break; case 1: printf ("\nError: Timeout writing to Flash\n"); return (~0); case 2: printf ("\nError: Flash not Erased\n"); return (~0); case 4: printf ("\nError: Can't write to protected Flash sectors\n"); return (~0); default: printf ("%s[%d] FIXME: rc=%d\n", __FILE__,__LINE__,rc); return (~0); } } else { memcpy ((char *)(store_addr), binbuf, binlen); } if ((store_addr) < start_addr) start_addr = store_addr; if ((store_addr+binlen-1) > end_addr) end_addr = store_addr+binlen-1; break; case SREC_END2: case SREC_END3: case SREC_END4: udelay (10000); printf ("\n" "## First Load Addr = 0x%08lx\n" "## Last Load Addr = 0x%08lx\n" "## Total Size = 0x%08lx = %ld Bytes\n", start_addr, end_addr, end_addr-start_addr+1, end_addr-start_addr+1 ); return (addr); case SREC_START: break; default: break; } if (!do_echo) { /* print a '.' every 100 lines */ if ((++line_count % 100) == 0) putc ('.'); } } return (~0); /* Download aborted */}static intread_record (char *buf, ulong len){ char *p; char c; --len; /* always leave room for terminating '\0' byte */ for (p=buf; p < buf+len; ++p) { c = serial_getc(); /* read character */ if (do_echo) serial_putc (c); /* ... and echo it */ switch (c) { case '\r': case '\n': *p = '\0'; return (p - buf); case '\0': case 0x03: /* ^C - Control C */ return (-1); default: *p = c; } // Check for the console hangup (if any different from serial) if (ctrlc()) { return (-1); } } /* line too long - truncate */ *p = '\0'; return (p - buf);}#endif /* CFG_CMD_LOADS */#if (CONFIG_COMMANDS & CFG_CMD_LOADB) /* loadb command (load binary) included */#define XON_CHAR 17#define XOFF_CHAR 19#define START_CHAR 0x01#define END_CHAR 0x0D#define SPACE 0x20#define K_ESCAPE 0x23#define SEND_TYPE 'S'#define DATA_TYPE 'D'#define ACK_TYPE 'Y'#define NACK_TYPE 'N'#define BREAK_TYPE 'B'#define tochar(x) ((char) (((x) + SPACE) & 0xff))#define untochar(x) ((int) (((x) - SPACE) & 0xff))extern int os_data_count;extern int os_data_header[8];void set_kerm_bin_mode(unsigned long *);int k_recv(void);int s1boot(unsigned long *, unsigned long *, int *);static ulong load_serial_bin (ulong offset);char his_eol; /* character he needs at end of packet */int his_pad_count; /* number of pad chars he needs */char his_pad_char; /* pad chars he needs */char his_quote; /* quote chars he'll use */int do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]){ ulong offset = 0; ulong addr; int i; int loadb_baudrate = bd->bi_baudrate; int rc = 0; if (argc >= 2) { offset = simple_strtoul(argv[1], NULL, 16); } if (argc == 3) { loadb_baudrate = (int)simple_strtoul(argv[2], NULL, 10); /* default to current baudrate */ if (loadb_baudrate == 0) loadb_baudrate = bd->bi_baudrate; } if (loadb_baudrate != bd->bi_baudrate) { printf ("## Switch baudrate to %d bps and press ENTER ...\n", loadb_baudrate); udelay(50000); serial_setbrg (bd, loadb_baudrate); udelay(50000); for (;;) { if (getc() == '\r') break; } } printf ("## Ready for binary (kermit) download ...\n"); addr = load_serial_bin (offset); /* * Gather any trailing characters (for instance, the ^D which * is sent by 'cu' after sending a file), and give the * box some time (100 * 1 ms) */ for (i=0; i<100; ++i) { if (serial_tstc()) { (void) serial_getc(); } udelay(1000); } if (addr == ~0) { load_addr = 0; printf ("## Binary (kermit) download aborted\n"); } else { printf ("## Start Addr = 0x%08lx\n", addr); load_addr = addr; } if (loadb_baudrate != bd->bi_baudrate) { printf ("## Switch baudrate to %d bps and press ESC ...\n", (int)bd->bi_baudrate); udelay (50000); serial_setbrg (bd, bd->bi_baudrate); udelay (50000); for (;;) { if (getc() == 0x1B) /* ESC */ break; } }#ifdef CONFIG_AUTOSCRIPT if (load_addr) { char *s; if (((s = getenv(bd, "autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { printf("Running autoscript at addr 0x%08lX ...\n", load_addr); rc = autoscript (bd, load_addr); } }#endif return rc;}static ulongload_serial_bin (ulong offset){ set_kerm_bin_mode((ulong *)offset); k_recv(); return offset;}void send_pad(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -