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

📄 cmd_load.c.svn-base

📁 u-boot loader common files, like cpu, clock, environment...etc...
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* * (C) Copyright 2000-2004 * 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 *//* * Serial up- and download support */#include <common.h>#include <command.h>#include <s_record.h>#include <net.h>#include <exports.h>#if (CONFIG_COMMANDS & CFG_CMD_LOADS)static ulong load_serial (ulong offset);static int read_record (char *buf, ulong len);# if (CONFIG_COMMANDS & CFG_CMD_SAVES)static int save_serial (ulong offset, ulong size);static int write_record (char *buf);# endif /* CFG_CMD_SAVES */static int do_echo = 1;#endif /* CFG_CMD_LOADS *//* -------------------------------------------------------------------- */#if (CONFIG_COMMANDS & CFG_CMD_LOADS)int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){	ulong offset = 0;	ulong addr;	int i;	char *env_echo;	int rcode = 0;#ifdef	CFG_LOADS_BAUD_CHANGE	DECLARE_GLOBAL_DATA_PTR;	int load_baudrate, current_baudrate;	load_baudrate = current_baudrate = gd->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) {		load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);		/* default to current baudrate */		if (load_baudrate == 0)			load_baudrate = current_baudrate;	}	if (load_baudrate != current_baudrate) {		printf ("## Switch baudrate to %d bps and press ENTER ...\n",			load_baudrate);		udelay(50000);		gd->baudrate = load_baudrate;		serial_setbrg ();		udelay(50000);		for (;;) {			if (getc() == '\r')				break;		}	}#else	/* ! CFG_LOADS_BAUD_CHANGE */	if (argc == 2) {		offset = simple_strtoul(argv[1], NULL, 16);	}#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 (tstc()) {			(void) getc();		}		udelay(1000);	}	if (addr == ~0) {		printf ("## S-Record download aborted\n");		rcode = 1;	} else {		printf ("## Start Addr      = 0x%08lX\n", addr);		load_addr = addr;	}#ifdef	CFG_LOADS_BAUD_CHANGE	if (load_baudrate != current_baudrate) {		printf ("## Switch baudrate to %d bps and press ESC ...\n",			current_baudrate);		udelay (50000);		gd->baudrate = current_baudrate;		serial_setbrg ();		udelay (50000);		for (;;) {			if (getc() == 0x1B) /* ESC */				break;		}	}#endif	return rcode;}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	size;				/* number of bytes transferred	*/	char	buf[32];	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;#ifndef CFG_NO_FLASH		    if (addr2info(store_addr)) {			int rc;//			rc = flash_write((uchar *)binbuf,store_addr,binlen);			rc = flash_write(addr2info(store_addr), binbuf, store_addr, binlen);			if (rc != 0) {				flash_perror (rc);				return (~0);			}		    } else#endif		    {			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);		    size = end_addr - start_addr + 1;		    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, size, size		    );		    flush_cache (start_addr, size);		    sprintf(buf, "%lX", size);		    setenv("filesize", buf);		    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){	DECLARE_GLOBAL_DATA_PTR;	char *p;	char c;	--len;	/* always leave room for terminating '\0' byte */	for (p=buf; p < buf+len; ++p) {		c = getc();		/* read character		*/		if (do_echo)			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 (gd->jt[XF_getc] != getc) {		if (ctrlc()) {		    return (-1);		}	    }	}	/* line too long - truncate */	*p = '\0';	return (p - buf);}#if (CONFIG_COMMANDS & CFG_CMD_SAVES)int do_save_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){	ulong offset = 0;	ulong size   = 0;#ifdef	CFG_LOADS_BAUD_CHANGE	DECLARE_GLOBAL_DATA_PTR;	int save_baudrate, current_baudrate;	save_baudrate = current_baudrate = gd->baudrate;#endif	if (argc >= 2) {		offset = simple_strtoul(argv[1], NULL, 16);	}#ifdef	CFG_LOADS_BAUD_CHANGE	if (argc >= 3) {		size = simple_strtoul(argv[2], NULL, 16);	}	if (argc == 4) {		save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);		/* default to current baudrate */		if (save_baudrate == 0)			save_baudrate = current_baudrate;	}	if (save_baudrate != current_baudrate) {		printf ("## Switch baudrate to %d bps and press ENTER ...\n",			save_baudrate);		udelay(50000);		gd->baudrate = save_baudrate;		serial_setbrg ();		udelay(50000);		for (;;) {			if (getc() == '\r')				break;		}	}#else	/* ! CFG_LOADS_BAUD_CHANGE */	if (argc == 3) {		size = simple_strtoul(argv[2], NULL, 16);	}#endif	/* CFG_LOADS_BAUD_CHANGE */	printf ("## Ready for S-Record upload, press ENTER to proceed ...\n");	for (;;) {		if (getc() == '\r')			break;	}	if(save_serial (offset, size)) {		printf ("## S-Record upload aborted\n");	} else {		printf ("## S-Record upload complete\n");	}#ifdef	CFG_LOADS_BAUD_CHANGE	if (save_baudrate != current_baudrate) {		printf ("## Switch baudrate to %d bps and press ESC ...\n",			(int)current_baudrate);		udelay (50000);		gd->baudrate = current_baudrate;		serial_setbrg ();		udelay (50000);		for (;;) {			if (getc() == 0x1B) /* ESC */				break;		}	}#endif	return 0;}#define SREC3_START				"S0030000FC\n"#define SREC3_FORMAT			"S3%02X%08lX%s%02X\n"#define SREC3_END				"S70500000000FA\n"#define SREC_BYTES_PER_RECORD	16static int save_serial (ulong address, ulong count){	int i, c, reclen, checksum, length;	char *hex = "0123456789ABCDEF";	char	record[2*SREC_BYTES_PER_RECORD+16];	/* buffer for one S-Record	*/	char	data[2*SREC_BYTES_PER_RECORD+1];	/* buffer for hex data	*/	reclen = 0;	checksum  = 0;	if(write_record(SREC3_START))			/* write the header */		return (-1);	do {		if(count) {						/* collect hex data in the buffer  */			c = *(volatile uchar*)(address + reclen);	/* get one byte    */			checksum += c;							/* accumulate checksum */			data[2*reclen]   = hex[(c>>4)&0x0f];			data[2*reclen+1] = hex[c & 0x0f];			data[2*reclen+2] = '\0';			++reclen;			--count;		}		if(reclen == SREC_BYTES_PER_RECORD || count == 0) {			/* enough data collected for one record: dump it */			if(reclen) {	/* build & write a data record: */				/* address + data + checksum */				length = 4 + reclen + 1;				/* accumulate length bytes into checksum */				for(i = 0; i < 2; i++)					checksum += (length >> (8*i)) & 0xff;				/* accumulate address bytes into checksum: */				for(i = 0; i < 4; i++)					checksum += (address >> (8*i)) & 0xff;				/* make proper checksum byte: */				checksum = ~checksum & 0xff;				/* output one record: */				sprintf(record, SREC3_FORMAT, length, address, data, checksum);				if(write_record(record))					return (-1);			}			address  += reclen;  /* increment address */			checksum  = 0;			reclen    = 0;		}	}	while(count);	if(write_record(SREC3_END))	/* write the final record */		return (-1);	return(0);}static intwrite_record (char *buf){	char c;	while((c = *buf++))		putc(c);	/* Check for the console hangup (if any different from serial) */	if (ctrlc()) {	    return (-1);	}	return (0);}# endif /* CFG_CMD_SAVES */#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 ETX_CHAR	0x03#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];static void set_kerm_bin_mode(unsigned long *);static int k_recv(void);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, int flag, int argc, char *argv[]){	DECLARE_GLOBAL_DATA_PTR;	ulong offset = 0;	ulong addr;	int load_baudrate, current_baudrate;	int rcode = 0;	char *s;	/* pre-set offset from CFG_LOAD_ADDR */	offset = CFG_LOAD_ADDR;	/* pre-set offset from $loadaddr */	if ((s = getenv("loadaddr")) != NULL) {		offset = simple_strtoul(s, NULL, 16);	}	load_baudrate = current_baudrate = gd->baudrate;	if (argc >= 2) {		offset = simple_strtoul(argv[1], NULL, 16);	}	if (argc == 3) {		load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);		/* default to current baudrate */		if (load_baudrate == 0)			load_baudrate = current_baudrate;	}	if (load_baudrate != current_baudrate) {		printf ("## Switch baudrate to %d bps and press ENTER ...\n",			load_baudrate);		udelay(50000);		gd->baudrate = load_baudrate;		serial_setbrg ();		udelay(50000);		for (;;) {			if (getc() == '\r')				break;		}	}	printf ("## Ready for binary (kermit) download "		"to 0x%08lX at %d bps...\n",		offset,		load_baudrate);	addr = load_serial_bin (offset);	if (addr == ~0) {		load_addr = 0;		printf ("## Binary (kermit) download aborted\n");		rcode = 1;	} else {		printf ("## Start Addr      = 0x%08lX\n", addr);		load_addr = addr;	}	if (load_baudrate != current_baudrate) {		printf ("## Switch baudrate to %d bps and press ESC ...\n",			current_baudrate);		udelay (50000);		gd->baudrate = current_baudrate;		serial_setbrg ();		udelay (50000);		for (;;) {			if (getc() == 0x1B) /* ESC */				break;		}	}#ifdef CONFIG_AUTOSCRIPT	if (load_addr) {		char *s;		if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {			printf("Running autoscript at addr 0x%08lX ...\n", load_addr);			rcode = autoscript (load_addr);		}	}#endif	return rcode;}static ulong load_serial_bin (ulong offset){	int size, i;	char buf[32];	set_kerm_bin_mode ((ulong *) offset);	size = k_recv ();	/*	 * 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 (tstc()) {			(void) getc();		}		udelay(1000);	}	flush_cache (offset, size);	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);	sprintf(buf, "%X", size);	setenv("filesize", buf);	return offset;}void send_pad (void){	int count = his_pad_count;	while (count-- > 0)		putc (his_pad_char);}/* converts escaped kermit char to binary char */char ktrans (char in){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -