📄 cmd_boot.c
字号:
/*
* (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 <ppcboot.h>
#include <command.h>
#include <cmd_boot.h>
#include <s_record.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)
void do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int i;
ulong ip = bd->bi_ip_addr;
char buf[32];
printf (" memstart = 0x%08lx\n", bd->bi_memstart );
printf (" memsize = 0x%08lx\n", bd->bi_memsize );
printf (" flashstart = 0x%08lx\n", bd->bi_flashstart );
printf (" flashsize = 0x%08lx\n", bd->bi_flashsize );
printf (" flashoffset = 0x%08lx\n", bd->bi_flashoffset);
printf (" sramstart = 0x%08lx\n", bd->bi_sramstart );
printf (" sramsize = 0x%08lx\n", bd->bi_sramsize );
#ifdef CONFIG_8xx
printf (" immr_base = 0x%08lx\n", bd->bi_immr_base );
#endif
printf (" bootflags = 0x%08lx\n", bd->bi_bootflags );
printf (" intfreq = %6s MHz\n", strmhz(buf, bd->bi_intfreq));
printf (" busfreq = %6s MHz\n", strmhz(buf, bd->bi_busfreq));
printf (" ethaddr =");
for (i=0; i<6; ++i) {
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
}
printf ("\n IP addr =");
for (i=0; i<4; ++i) {
printf ("%c%ld", i ? '.' : ' ', (ip >> 24) & 0xFF);
ip <<= 8;
}
printf ("\n baudrate = %6ld bps\n", bd->bi_baudrate );
printf (" getc = 0x%08lx\n",(ulong)bd->bi_mon_fnc->getc);
printf (" tstc = 0x%08lx\n",(ulong)bd->bi_mon_fnc->tstc);
printf (" putc = 0x%08lx\n",(ulong)bd->bi_mon_fnc->putc);
printf (" puts = 0x%08lx\n",(ulong)bd->bi_mon_fnc->puts);
printf (" printf = 0x%08lx\n",(ulong)bd->bi_mon_fnc->printf);
printf (" install_hdlr= 0x%08lx\n",(ulong)bd->bi_mon_fnc->install_hdlr);
printf (" free_hdlr = 0x%08lx\n",(ulong)bd->bi_mon_fnc->free_hdlr);
printf (" malloc = 0x%08lx\n",(ulong)bd->bi_mon_fnc->malloc);
printf (" free = 0x%08lx\n",(ulong)bd->bi_mon_fnc->free);
}
#endif /* CFG_CMD_BDI */
void 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;
}
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);
}
#if (CONFIG_COMMANDS & CFG_CMD_LOADS)
void 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("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
}
static ulong
load_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 int
read_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 (bd_ptr->bi_mon_fnc->getc != serial_getc)
{
if (tstc())
{
switch (getc()){
case '\0':
case 0x03: /* ^C - Control C */
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 */
void 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;
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->bi_intfreq, 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) {
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->bi_intfreq, bd->bi_baudrate);
udelay (50000);
for (;;) {
if (getc() == 0x1B) /* ESC */
break;
}
}
}
static ulong
load_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 + -