⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd_boot.c

📁 嵌入式ARM的一些源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * (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 + -