xref: /OK3568_Linux_fs/u-boot/cmd/load.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000-2004
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * Serial up- and download support
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <boot_rkimg.h>
13*4882a593Smuzhiyun #include <command.h>
14*4882a593Smuzhiyun #include <console.h>
15*4882a593Smuzhiyun #include <s_record.h>
16*4882a593Smuzhiyun #include <net.h>
17*4882a593Smuzhiyun #include <exports.h>
18*4882a593Smuzhiyun #include <xyzModem.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #if defined(CONFIG_CMD_LOADB)
23*4882a593Smuzhiyun static ulong load_serial_ymodem(ulong offset, int mode);
24*4882a593Smuzhiyun static ulong load_serial_zmodem(ulong offset);
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #if defined(CONFIG_CMD_LOADS)
28*4882a593Smuzhiyun static ulong load_serial(long offset);
29*4882a593Smuzhiyun static int read_record(char *buf, ulong len);
30*4882a593Smuzhiyun # if defined(CONFIG_CMD_SAVES)
31*4882a593Smuzhiyun static int save_serial(ulong offset, ulong size);
32*4882a593Smuzhiyun static int write_record(char *buf);
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static int do_echo = 1;
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /* -------------------------------------------------------------------- */
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #if defined(CONFIG_CMD_LOADS)
do_load_serial(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])41*4882a593Smuzhiyun static int do_load_serial(cmd_tbl_t *cmdtp, int flag, int argc,
42*4882a593Smuzhiyun 			  char * const argv[])
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	long offset = 0;
45*4882a593Smuzhiyun 	ulong addr;
46*4882a593Smuzhiyun 	int i;
47*4882a593Smuzhiyun 	char *env_echo;
48*4882a593Smuzhiyun 	int rcode = 0;
49*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
50*4882a593Smuzhiyun 	int load_baudrate, current_baudrate;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	load_baudrate = current_baudrate = gd->baudrate;
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	env_echo = env_get("loads_echo");
56*4882a593Smuzhiyun 	if (env_echo && *env_echo == '1')
57*4882a593Smuzhiyun 		do_echo = 1;
58*4882a593Smuzhiyun 	else
59*4882a593Smuzhiyun 		do_echo = 0;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
62*4882a593Smuzhiyun 	if (argc >= 2) {
63*4882a593Smuzhiyun 		offset = simple_strtol(argv[1], NULL, 16);
64*4882a593Smuzhiyun 	}
65*4882a593Smuzhiyun 	if (argc == 3) {
66*4882a593Smuzhiyun 		load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 		/* default to current baudrate */
69*4882a593Smuzhiyun 		if (load_baudrate == 0)
70*4882a593Smuzhiyun 			load_baudrate = current_baudrate;
71*4882a593Smuzhiyun 	}
72*4882a593Smuzhiyun 	if (load_baudrate != current_baudrate) {
73*4882a593Smuzhiyun 		printf("## Switch baudrate to %d bps and press ENTER ...\n",
74*4882a593Smuzhiyun 			load_baudrate);
75*4882a593Smuzhiyun 		udelay(50000);
76*4882a593Smuzhiyun 		gd->baudrate = load_baudrate;
77*4882a593Smuzhiyun 		serial_setbrg();
78*4882a593Smuzhiyun 		udelay(50000);
79*4882a593Smuzhiyun 		for (;;) {
80*4882a593Smuzhiyun 			if (getc() == '\r')
81*4882a593Smuzhiyun 				break;
82*4882a593Smuzhiyun 		}
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
85*4882a593Smuzhiyun 	if (argc == 2) {
86*4882a593Smuzhiyun 		offset = simple_strtol(argv[1], NULL, 16);
87*4882a593Smuzhiyun 	}
88*4882a593Smuzhiyun #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	printf("## Ready for S-Record download ...\n");
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	addr = load_serial(offset);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	/*
95*4882a593Smuzhiyun 	 * Gather any trailing characters (for instance, the ^D which
96*4882a593Smuzhiyun 	 * is sent by 'cu' after sending a file), and give the
97*4882a593Smuzhiyun 	 * box some time (100 * 1 ms)
98*4882a593Smuzhiyun 	 */
99*4882a593Smuzhiyun 	for (i=0; i<100; ++i) {
100*4882a593Smuzhiyun 		if (tstc()) {
101*4882a593Smuzhiyun 			(void) getc();
102*4882a593Smuzhiyun 		}
103*4882a593Smuzhiyun 		udelay(1000);
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	if (addr == ~0) {
107*4882a593Smuzhiyun 		printf("## S-Record download aborted\n");
108*4882a593Smuzhiyun 		rcode = 1;
109*4882a593Smuzhiyun 	} else {
110*4882a593Smuzhiyun 		printf("## Start Addr      = 0x%08lX\n", addr);
111*4882a593Smuzhiyun 		load_addr = addr;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
115*4882a593Smuzhiyun 	if (load_baudrate != current_baudrate) {
116*4882a593Smuzhiyun 		printf("## Switch baudrate to %d bps and press ESC ...\n",
117*4882a593Smuzhiyun 			current_baudrate);
118*4882a593Smuzhiyun 		udelay(50000);
119*4882a593Smuzhiyun 		gd->baudrate = current_baudrate;
120*4882a593Smuzhiyun 		serial_setbrg();
121*4882a593Smuzhiyun 		udelay(50000);
122*4882a593Smuzhiyun 		for (;;) {
123*4882a593Smuzhiyun 			if (getc() == 0x1B) /* ESC */
124*4882a593Smuzhiyun 				break;
125*4882a593Smuzhiyun 		}
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun #endif
128*4882a593Smuzhiyun 	return rcode;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
load_serial(long offset)131*4882a593Smuzhiyun static ulong load_serial(long offset)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	char	record[SREC_MAXRECLEN + 1];	/* buffer for one S-Record	*/
134*4882a593Smuzhiyun 	char	binbuf[SREC_MAXBINLEN];		/* buffer for binary data	*/
135*4882a593Smuzhiyun 	int	binlen;				/* no. of data bytes in S-Rec.	*/
136*4882a593Smuzhiyun 	int	type;				/* return code for record type	*/
137*4882a593Smuzhiyun 	ulong	addr;				/* load address from S-Record	*/
138*4882a593Smuzhiyun 	ulong	size;				/* number of bytes transferred	*/
139*4882a593Smuzhiyun 	ulong	store_addr;
140*4882a593Smuzhiyun 	ulong	start_addr = ~0;
141*4882a593Smuzhiyun 	ulong	end_addr   =  0;
142*4882a593Smuzhiyun 	int	line_count =  0;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
145*4882a593Smuzhiyun 		type = srec_decode(record, &binlen, &addr, binbuf);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 		if (type < 0) {
148*4882a593Smuzhiyun 			return (~0);		/* Invalid S-Record		*/
149*4882a593Smuzhiyun 		}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 		switch (type) {
152*4882a593Smuzhiyun 		case SREC_DATA2:
153*4882a593Smuzhiyun 		case SREC_DATA3:
154*4882a593Smuzhiyun 		case SREC_DATA4:
155*4882a593Smuzhiyun 		    store_addr = addr + offset;
156*4882a593Smuzhiyun #ifdef CONFIG_MTD_NOR_FLASH
157*4882a593Smuzhiyun 		    if (addr2info(store_addr)) {
158*4882a593Smuzhiyun 			int rc;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 			rc = flash_write((char *)binbuf,store_addr,binlen);
161*4882a593Smuzhiyun 			if (rc != 0) {
162*4882a593Smuzhiyun 				flash_perror(rc);
163*4882a593Smuzhiyun 				return (~0);
164*4882a593Smuzhiyun 			}
165*4882a593Smuzhiyun 		    } else
166*4882a593Smuzhiyun #endif
167*4882a593Smuzhiyun 		    {
168*4882a593Smuzhiyun 			memcpy((char *)(store_addr), binbuf, binlen);
169*4882a593Smuzhiyun 		    }
170*4882a593Smuzhiyun 		    if ((store_addr) < start_addr)
171*4882a593Smuzhiyun 			start_addr = store_addr;
172*4882a593Smuzhiyun 		    if ((store_addr + binlen - 1) > end_addr)
173*4882a593Smuzhiyun 			end_addr = store_addr + binlen - 1;
174*4882a593Smuzhiyun 		    break;
175*4882a593Smuzhiyun 		case SREC_END2:
176*4882a593Smuzhiyun 		case SREC_END3:
177*4882a593Smuzhiyun 		case SREC_END4:
178*4882a593Smuzhiyun 		    udelay(10000);
179*4882a593Smuzhiyun 		    size = end_addr - start_addr + 1;
180*4882a593Smuzhiyun 		    printf("\n"
181*4882a593Smuzhiyun 			    "## First Load Addr = 0x%08lX\n"
182*4882a593Smuzhiyun 			    "## Last  Load Addr = 0x%08lX\n"
183*4882a593Smuzhiyun 			    "## Total Size      = 0x%08lX = %ld Bytes\n",
184*4882a593Smuzhiyun 			    start_addr, end_addr, size, size
185*4882a593Smuzhiyun 		    );
186*4882a593Smuzhiyun 		    flush_cache(start_addr, size);
187*4882a593Smuzhiyun 		    env_set_hex("filesize", size);
188*4882a593Smuzhiyun 		    return (addr);
189*4882a593Smuzhiyun 		case SREC_START:
190*4882a593Smuzhiyun 		    break;
191*4882a593Smuzhiyun 		default:
192*4882a593Smuzhiyun 		    break;
193*4882a593Smuzhiyun 		}
194*4882a593Smuzhiyun 		if (!do_echo) {	/* print a '.' every 100 lines */
195*4882a593Smuzhiyun 			if ((++line_count % 100) == 0)
196*4882a593Smuzhiyun 				putc('.');
197*4882a593Smuzhiyun 		}
198*4882a593Smuzhiyun 	}
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	return (~0);			/* Download aborted		*/
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
read_record(char * buf,ulong len)203*4882a593Smuzhiyun static int read_record(char *buf, ulong len)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	char *p;
206*4882a593Smuzhiyun 	char c;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	--len;	/* always leave room for terminating '\0' byte */
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	for (p=buf; p < buf+len; ++p) {
211*4882a593Smuzhiyun 		c = getc();		/* read character		*/
212*4882a593Smuzhiyun 		if (do_echo)
213*4882a593Smuzhiyun 			putc(c);	/* ... and echo it		*/
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 		switch (c) {
216*4882a593Smuzhiyun 		case '\r':
217*4882a593Smuzhiyun 		case '\n':
218*4882a593Smuzhiyun 			*p = '\0';
219*4882a593Smuzhiyun 			return (p - buf);
220*4882a593Smuzhiyun 		case '\0':
221*4882a593Smuzhiyun 		case 0x03:			/* ^C - Control C		*/
222*4882a593Smuzhiyun 			return (-1);
223*4882a593Smuzhiyun 		default:
224*4882a593Smuzhiyun 			*p = c;
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	    /* Check for the console hangup (if any different from serial) */
228*4882a593Smuzhiyun 	    if (gd->jt->getc != getc) {
229*4882a593Smuzhiyun 		if (ctrlc()) {
230*4882a593Smuzhiyun 		    return (-1);
231*4882a593Smuzhiyun 		}
232*4882a593Smuzhiyun 	    }
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	/* line too long - truncate */
236*4882a593Smuzhiyun 	*p = '\0';
237*4882a593Smuzhiyun 	return (p - buf);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun #if defined(CONFIG_CMD_SAVES)
241*4882a593Smuzhiyun 
do_save_serial(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])242*4882a593Smuzhiyun int do_save_serial (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	ulong offset = 0;
245*4882a593Smuzhiyun 	ulong size   = 0;
246*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
247*4882a593Smuzhiyun 	int save_baudrate, current_baudrate;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	save_baudrate = current_baudrate = gd->baudrate;
250*4882a593Smuzhiyun #endif
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	if (argc >= 2) {
253*4882a593Smuzhiyun 		offset = simple_strtoul(argv[1], NULL, 16);
254*4882a593Smuzhiyun 	}
255*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
256*4882a593Smuzhiyun 	if (argc >= 3) {
257*4882a593Smuzhiyun 		size = simple_strtoul(argv[2], NULL, 16);
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 	if (argc == 4) {
260*4882a593Smuzhiyun 		save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		/* default to current baudrate */
263*4882a593Smuzhiyun 		if (save_baudrate == 0)
264*4882a593Smuzhiyun 			save_baudrate = current_baudrate;
265*4882a593Smuzhiyun 	}
266*4882a593Smuzhiyun 	if (save_baudrate != current_baudrate) {
267*4882a593Smuzhiyun 		printf("## Switch baudrate to %d bps and press ENTER ...\n",
268*4882a593Smuzhiyun 			save_baudrate);
269*4882a593Smuzhiyun 		udelay(50000);
270*4882a593Smuzhiyun 		gd->baudrate = save_baudrate;
271*4882a593Smuzhiyun 		serial_setbrg();
272*4882a593Smuzhiyun 		udelay(50000);
273*4882a593Smuzhiyun 		for (;;) {
274*4882a593Smuzhiyun 			if (getc() == '\r')
275*4882a593Smuzhiyun 				break;
276*4882a593Smuzhiyun 		}
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
279*4882a593Smuzhiyun 	if (argc == 3) {
280*4882a593Smuzhiyun 		size = simple_strtoul(argv[2], NULL, 16);
281*4882a593Smuzhiyun 	}
282*4882a593Smuzhiyun #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	printf("## Ready for S-Record upload, press ENTER to proceed ...\n");
285*4882a593Smuzhiyun 	for (;;) {
286*4882a593Smuzhiyun 		if (getc() == '\r')
287*4882a593Smuzhiyun 			break;
288*4882a593Smuzhiyun 	}
289*4882a593Smuzhiyun 	if (save_serial(offset, size)) {
290*4882a593Smuzhiyun 		printf("## S-Record upload aborted\n");
291*4882a593Smuzhiyun 	} else {
292*4882a593Smuzhiyun 		printf("## S-Record upload complete\n");
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
295*4882a593Smuzhiyun 	if (save_baudrate != current_baudrate) {
296*4882a593Smuzhiyun 		printf("## Switch baudrate to %d bps and press ESC ...\n",
297*4882a593Smuzhiyun 			(int)current_baudrate);
298*4882a593Smuzhiyun 		udelay(50000);
299*4882a593Smuzhiyun 		gd->baudrate = current_baudrate;
300*4882a593Smuzhiyun 		serial_setbrg();
301*4882a593Smuzhiyun 		udelay(50000);
302*4882a593Smuzhiyun 		for (;;) {
303*4882a593Smuzhiyun 			if (getc() == 0x1B) /* ESC */
304*4882a593Smuzhiyun 				break;
305*4882a593Smuzhiyun 		}
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun #endif
308*4882a593Smuzhiyun 	return 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun #define SREC3_START				"S0030000FC\n"
312*4882a593Smuzhiyun #define SREC3_FORMAT			"S3%02X%08lX%s%02X\n"
313*4882a593Smuzhiyun #define SREC3_END				"S70500000000FA\n"
314*4882a593Smuzhiyun #define SREC_BYTES_PER_RECORD	16
315*4882a593Smuzhiyun 
save_serial(ulong address,ulong count)316*4882a593Smuzhiyun static int save_serial(ulong address, ulong count)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun 	int i, c, reclen, checksum, length;
319*4882a593Smuzhiyun 	char *hex = "0123456789ABCDEF";
320*4882a593Smuzhiyun 	char	record[2*SREC_BYTES_PER_RECORD+16];	/* buffer for one S-Record	*/
321*4882a593Smuzhiyun 	char	data[2*SREC_BYTES_PER_RECORD+1];	/* buffer for hex data	*/
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	reclen = 0;
324*4882a593Smuzhiyun 	checksum  = 0;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	if(write_record(SREC3_START))			/* write the header */
327*4882a593Smuzhiyun 		return (-1);
328*4882a593Smuzhiyun 	do {
329*4882a593Smuzhiyun 		if(count) {						/* collect hex data in the buffer  */
330*4882a593Smuzhiyun 			c = *(volatile uchar*)(address + reclen);	/* get one byte    */
331*4882a593Smuzhiyun 			checksum += c;							/* accumulate checksum */
332*4882a593Smuzhiyun 			data[2*reclen]   = hex[(c>>4)&0x0f];
333*4882a593Smuzhiyun 			data[2*reclen+1] = hex[c & 0x0f];
334*4882a593Smuzhiyun 			data[2*reclen+2] = '\0';
335*4882a593Smuzhiyun 			++reclen;
336*4882a593Smuzhiyun 			--count;
337*4882a593Smuzhiyun 		}
338*4882a593Smuzhiyun 		if(reclen == SREC_BYTES_PER_RECORD || count == 0) {
339*4882a593Smuzhiyun 			/* enough data collected for one record: dump it */
340*4882a593Smuzhiyun 			if(reclen) {	/* build & write a data record: */
341*4882a593Smuzhiyun 				/* address + data + checksum */
342*4882a593Smuzhiyun 				length = 4 + reclen + 1;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 				/* accumulate length bytes into checksum */
345*4882a593Smuzhiyun 				for(i = 0; i < 2; i++)
346*4882a593Smuzhiyun 					checksum += (length >> (8*i)) & 0xff;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 				/* accumulate address bytes into checksum: */
349*4882a593Smuzhiyun 				for(i = 0; i < 4; i++)
350*4882a593Smuzhiyun 					checksum += (address >> (8*i)) & 0xff;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 				/* make proper checksum byte: */
353*4882a593Smuzhiyun 				checksum = ~checksum & 0xff;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 				/* output one record: */
356*4882a593Smuzhiyun 				sprintf(record, SREC3_FORMAT, length, address, data, checksum);
357*4882a593Smuzhiyun 				if(write_record(record))
358*4882a593Smuzhiyun 					return (-1);
359*4882a593Smuzhiyun 			}
360*4882a593Smuzhiyun 			address  += reclen;  /* increment address */
361*4882a593Smuzhiyun 			checksum  = 0;
362*4882a593Smuzhiyun 			reclen    = 0;
363*4882a593Smuzhiyun 		}
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun 	while(count);
366*4882a593Smuzhiyun 	if(write_record(SREC3_END))	/* write the final record */
367*4882a593Smuzhiyun 		return (-1);
368*4882a593Smuzhiyun 	return(0);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun 
write_record(char * buf)371*4882a593Smuzhiyun static int write_record(char *buf)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun 	char c;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	while((c = *buf++))
376*4882a593Smuzhiyun 		putc(c);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	/* Check for the console hangup (if any different from serial) */
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (ctrlc()) {
381*4882a593Smuzhiyun 	    return (-1);
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun 	return (0);
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun # endif
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun #endif
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun #if defined(CONFIG_CMD_LOADB)
391*4882a593Smuzhiyun /*
392*4882a593Smuzhiyun  * loadb command (load binary) included
393*4882a593Smuzhiyun  */
394*4882a593Smuzhiyun #define XON_CHAR        17
395*4882a593Smuzhiyun #define XOFF_CHAR       19
396*4882a593Smuzhiyun #define START_CHAR      0x01
397*4882a593Smuzhiyun #define ETX_CHAR	0x03
398*4882a593Smuzhiyun #define END_CHAR        0x0D
399*4882a593Smuzhiyun #define SPACE           0x20
400*4882a593Smuzhiyun #define K_ESCAPE        0x23
401*4882a593Smuzhiyun #define SEND_TYPE       'S'
402*4882a593Smuzhiyun #define DATA_TYPE       'D'
403*4882a593Smuzhiyun #define ACK_TYPE        'Y'
404*4882a593Smuzhiyun #define NACK_TYPE       'N'
405*4882a593Smuzhiyun #define BREAK_TYPE      'B'
406*4882a593Smuzhiyun #define tochar(x) ((char) (((x) + SPACE) & 0xff))
407*4882a593Smuzhiyun #define untochar(x) ((int) (((x) - SPACE) & 0xff))
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun static void set_kerm_bin_mode(unsigned long *);
410*4882a593Smuzhiyun static int k_recv(void);
411*4882a593Smuzhiyun static ulong load_serial_bin(ulong offset);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun static char his_eol;        /* character he needs at end of packet */
415*4882a593Smuzhiyun static int  his_pad_count;  /* number of pad chars he needs */
416*4882a593Smuzhiyun static char his_pad_char;   /* pad chars he needs */
417*4882a593Smuzhiyun static char his_quote;      /* quote chars he'll use */
418*4882a593Smuzhiyun 
do_load_serial_bin(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])419*4882a593Smuzhiyun static int do_load_serial_bin(cmd_tbl_t *cmdtp, int flag, int argc,
420*4882a593Smuzhiyun 			      char * const argv[])
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun 	ulong offset = 0;
423*4882a593Smuzhiyun 	ulong addr;
424*4882a593Smuzhiyun 	int load_baudrate, current_baudrate;
425*4882a593Smuzhiyun 	int rcode = 0;
426*4882a593Smuzhiyun 	char *s;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	/* pre-set offset from CONFIG_SYS_LOAD_ADDR */
429*4882a593Smuzhiyun 	offset = CONFIG_SYS_LOAD_ADDR;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	/* pre-set offset from $loadaddr */
432*4882a593Smuzhiyun 	s = env_get("loadaddr");
433*4882a593Smuzhiyun 	if (s)
434*4882a593Smuzhiyun 		offset = simple_strtoul(s, NULL, 16);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	load_baudrate = current_baudrate = gd->baudrate;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (argc >= 2) {
439*4882a593Smuzhiyun 		offset = simple_strtoul(argv[1], NULL, 16);
440*4882a593Smuzhiyun 	}
441*4882a593Smuzhiyun 	if (argc == 3) {
442*4882a593Smuzhiyun 		load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 		/* default to current baudrate */
445*4882a593Smuzhiyun 		if (load_baudrate == 0)
446*4882a593Smuzhiyun 			load_baudrate = current_baudrate;
447*4882a593Smuzhiyun 	}
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	if (load_baudrate != current_baudrate) {
450*4882a593Smuzhiyun 		printf("## Switch baudrate to %d bps and press ENTER ...\n",
451*4882a593Smuzhiyun 			load_baudrate);
452*4882a593Smuzhiyun 		udelay(50000);
453*4882a593Smuzhiyun 		gd->baudrate = load_baudrate;
454*4882a593Smuzhiyun 		serial_setbrg();
455*4882a593Smuzhiyun 		udelay(50000);
456*4882a593Smuzhiyun 		for (;;) {
457*4882a593Smuzhiyun 			if (getc() == '\r')
458*4882a593Smuzhiyun 				break;
459*4882a593Smuzhiyun 		}
460*4882a593Smuzhiyun 	}
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	if (strcmp(argv[0],"loady")==0) {
463*4882a593Smuzhiyun 		printf("## Ready for binary (ymodem) download "
464*4882a593Smuzhiyun 			"to 0x%08lX at %d bps...\n",
465*4882a593Smuzhiyun 			offset,
466*4882a593Smuzhiyun 			load_baudrate);
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 		addr = load_serial_ymodem(offset, xyzModem_ymodem);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	} else if (strcmp(argv[0],"loadz")==0) {
471*4882a593Smuzhiyun 		printf("## Ready for binary (zmodem) download"
472*4882a593Smuzhiyun 			"to 0x%08lX at %d bps...\n",
473*4882a593Smuzhiyun 			offset, load_baudrate);
474*4882a593Smuzhiyun 		addr = load_serial_zmodem(offset);
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	} else if (strcmp(argv[0],"loadx")==0) {
477*4882a593Smuzhiyun 		printf("## Ready for binary (xmodem) download "
478*4882a593Smuzhiyun 			"to 0x%08lX at %d bps...\n",
479*4882a593Smuzhiyun 			offset,
480*4882a593Smuzhiyun 			load_baudrate);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 		addr = load_serial_ymodem(offset, xyzModem_xmodem);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	} else {
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 		printf("## Ready for binary (kermit) download "
487*4882a593Smuzhiyun 			"to 0x%08lX at %d bps...\n",
488*4882a593Smuzhiyun 			offset,
489*4882a593Smuzhiyun 			load_baudrate);
490*4882a593Smuzhiyun 		addr = load_serial_bin(offset);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 		if (addr == ~0) {
493*4882a593Smuzhiyun 			load_addr = 0;
494*4882a593Smuzhiyun 			printf("## Binary (kermit) download aborted\n");
495*4882a593Smuzhiyun 			rcode = 1;
496*4882a593Smuzhiyun 		} else {
497*4882a593Smuzhiyun 			printf("## Start Addr      = 0x%08lX\n", addr);
498*4882a593Smuzhiyun 			load_addr = addr;
499*4882a593Smuzhiyun 		}
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 	if (load_baudrate != current_baudrate) {
502*4882a593Smuzhiyun 		printf("## Switch baudrate to %d bps and press ESC ...\n",
503*4882a593Smuzhiyun 			current_baudrate);
504*4882a593Smuzhiyun 		udelay(50000);
505*4882a593Smuzhiyun 		gd->baudrate = current_baudrate;
506*4882a593Smuzhiyun 		serial_setbrg();
507*4882a593Smuzhiyun 		udelay(50000);
508*4882a593Smuzhiyun 		for (;;) {
509*4882a593Smuzhiyun 			if (getc() == 0x1B) /* ESC */
510*4882a593Smuzhiyun 				break;
511*4882a593Smuzhiyun 		}
512*4882a593Smuzhiyun 	}
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	return rcode;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 
load_serial_bin(ulong offset)518*4882a593Smuzhiyun static ulong load_serial_bin(ulong offset)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun 	int size, i;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	set_kerm_bin_mode((ulong *) offset);
523*4882a593Smuzhiyun 	size = k_recv();
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	/*
526*4882a593Smuzhiyun 	 * Gather any trailing characters (for instance, the ^D which
527*4882a593Smuzhiyun 	 * is sent by 'cu' after sending a file), and give the
528*4882a593Smuzhiyun 	 * box some time (100 * 1 ms)
529*4882a593Smuzhiyun 	 */
530*4882a593Smuzhiyun 	for (i=0; i<100; ++i) {
531*4882a593Smuzhiyun 		if (tstc()) {
532*4882a593Smuzhiyun 			(void) getc();
533*4882a593Smuzhiyun 		}
534*4882a593Smuzhiyun 		udelay(1000);
535*4882a593Smuzhiyun 	}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	flush_cache(offset, size);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
540*4882a593Smuzhiyun 	env_set_hex("filesize", size);
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	return offset;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun 
send_pad(void)545*4882a593Smuzhiyun static void send_pad(void)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun 	int count = his_pad_count;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	while (count-- > 0)
550*4882a593Smuzhiyun 		putc(his_pad_char);
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun /* converts escaped kermit char to binary char */
ktrans(char in)554*4882a593Smuzhiyun static char ktrans(char in)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	if ((in & 0x60) == 0x40) {
557*4882a593Smuzhiyun 		return (char) (in & ~0x40);
558*4882a593Smuzhiyun 	} else if ((in & 0x7f) == 0x3f) {
559*4882a593Smuzhiyun 		return (char) (in | 0x40);
560*4882a593Smuzhiyun 	} else
561*4882a593Smuzhiyun 		return in;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
chk1(char * buffer)564*4882a593Smuzhiyun static int chk1(char *buffer)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun 	int total = 0;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	while (*buffer) {
569*4882a593Smuzhiyun 		total += *buffer++;
570*4882a593Smuzhiyun 	}
571*4882a593Smuzhiyun 	return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun 
s1_sendpacket(char * packet)574*4882a593Smuzhiyun static void s1_sendpacket(char *packet)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun 	send_pad();
577*4882a593Smuzhiyun 	while (*packet) {
578*4882a593Smuzhiyun 		putc(*packet++);
579*4882a593Smuzhiyun 	}
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun static char a_b[24];
send_ack(int n)583*4882a593Smuzhiyun static void send_ack(int n)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	a_b[0] = START_CHAR;
586*4882a593Smuzhiyun 	a_b[1] = tochar(3);
587*4882a593Smuzhiyun 	a_b[2] = tochar(n);
588*4882a593Smuzhiyun 	a_b[3] = ACK_TYPE;
589*4882a593Smuzhiyun 	a_b[4] = '\0';
590*4882a593Smuzhiyun 	a_b[4] = tochar(chk1(&a_b[1]));
591*4882a593Smuzhiyun 	a_b[5] = his_eol;
592*4882a593Smuzhiyun 	a_b[6] = '\0';
593*4882a593Smuzhiyun 	s1_sendpacket(a_b);
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun 
send_nack(int n)596*4882a593Smuzhiyun static void send_nack(int n)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun 	a_b[0] = START_CHAR;
599*4882a593Smuzhiyun 	a_b[1] = tochar(3);
600*4882a593Smuzhiyun 	a_b[2] = tochar(n);
601*4882a593Smuzhiyun 	a_b[3] = NACK_TYPE;
602*4882a593Smuzhiyun 	a_b[4] = '\0';
603*4882a593Smuzhiyun 	a_b[4] = tochar(chk1(&a_b[1]));
604*4882a593Smuzhiyun 	a_b[5] = his_eol;
605*4882a593Smuzhiyun 	a_b[6] = '\0';
606*4882a593Smuzhiyun 	s1_sendpacket(a_b);
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun static void (*os_data_init)(void);
611*4882a593Smuzhiyun static void (*os_data_char)(char new_char);
612*4882a593Smuzhiyun static int os_data_state, os_data_state_saved;
613*4882a593Smuzhiyun static char *os_data_addr, *os_data_addr_saved;
614*4882a593Smuzhiyun static char *bin_start_address;
615*4882a593Smuzhiyun 
bin_data_init(void)616*4882a593Smuzhiyun static void bin_data_init(void)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun 	os_data_state = 0;
619*4882a593Smuzhiyun 	os_data_addr = bin_start_address;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun 
os_data_save(void)622*4882a593Smuzhiyun static void os_data_save(void)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun 	os_data_state_saved = os_data_state;
625*4882a593Smuzhiyun 	os_data_addr_saved = os_data_addr;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun 
os_data_restore(void)628*4882a593Smuzhiyun static void os_data_restore(void)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun 	os_data_state = os_data_state_saved;
631*4882a593Smuzhiyun 	os_data_addr = os_data_addr_saved;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun 
bin_data_char(char new_char)634*4882a593Smuzhiyun static void bin_data_char(char new_char)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun 	switch (os_data_state) {
637*4882a593Smuzhiyun 	case 0:					/* data */
638*4882a593Smuzhiyun 		*os_data_addr++ = new_char;
639*4882a593Smuzhiyun 		break;
640*4882a593Smuzhiyun 	}
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun 
set_kerm_bin_mode(unsigned long * addr)643*4882a593Smuzhiyun static void set_kerm_bin_mode(unsigned long *addr)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun 	bin_start_address = (char *) addr;
646*4882a593Smuzhiyun 	os_data_init = bin_data_init;
647*4882a593Smuzhiyun 	os_data_char = bin_data_char;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun /* k_data_* simply handles the kermit escape translations */
652*4882a593Smuzhiyun static int k_data_escape, k_data_escape_saved;
k_data_init(void)653*4882a593Smuzhiyun static void k_data_init(void)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun 	k_data_escape = 0;
656*4882a593Smuzhiyun 	os_data_init();
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun 
k_data_save(void)659*4882a593Smuzhiyun static void k_data_save(void)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun 	k_data_escape_saved = k_data_escape;
662*4882a593Smuzhiyun 	os_data_save();
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun 
k_data_restore(void)665*4882a593Smuzhiyun static void k_data_restore(void)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	k_data_escape = k_data_escape_saved;
668*4882a593Smuzhiyun 	os_data_restore();
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun 
k_data_char(char new_char)671*4882a593Smuzhiyun static void k_data_char(char new_char)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun 	if (k_data_escape) {
674*4882a593Smuzhiyun 		/* last char was escape - translate this character */
675*4882a593Smuzhiyun 		os_data_char(ktrans(new_char));
676*4882a593Smuzhiyun 		k_data_escape = 0;
677*4882a593Smuzhiyun 	} else {
678*4882a593Smuzhiyun 		if (new_char == his_quote) {
679*4882a593Smuzhiyun 			/* this char is escape - remember */
680*4882a593Smuzhiyun 			k_data_escape = 1;
681*4882a593Smuzhiyun 		} else {
682*4882a593Smuzhiyun 			/* otherwise send this char as-is */
683*4882a593Smuzhiyun 			os_data_char(new_char);
684*4882a593Smuzhiyun 		}
685*4882a593Smuzhiyun 	}
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun #define SEND_DATA_SIZE  20
689*4882a593Smuzhiyun static char send_parms[SEND_DATA_SIZE];
690*4882a593Smuzhiyun static char *send_ptr;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun /* handle_send_packet interprits the protocol info and builds and
693*4882a593Smuzhiyun    sends an appropriate ack for what we can do */
handle_send_packet(int n)694*4882a593Smuzhiyun static void handle_send_packet(int n)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun 	int length = 3;
697*4882a593Smuzhiyun 	int bytes;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	/* initialize some protocol parameters */
700*4882a593Smuzhiyun 	his_eol = END_CHAR;		/* default end of line character */
701*4882a593Smuzhiyun 	his_pad_count = 0;
702*4882a593Smuzhiyun 	his_pad_char = '\0';
703*4882a593Smuzhiyun 	his_quote = K_ESCAPE;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	/* ignore last character if it filled the buffer */
706*4882a593Smuzhiyun 	if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
707*4882a593Smuzhiyun 		--send_ptr;
708*4882a593Smuzhiyun 	bytes = send_ptr - send_parms;	/* how many bytes we'll process */
709*4882a593Smuzhiyun 	do {
710*4882a593Smuzhiyun 		if (bytes-- <= 0)
711*4882a593Smuzhiyun 			break;
712*4882a593Smuzhiyun 		/* handle MAXL - max length */
713*4882a593Smuzhiyun 		/* ignore what he says - most I'll take (here) is 94 */
714*4882a593Smuzhiyun 		a_b[++length] = tochar(94);
715*4882a593Smuzhiyun 		if (bytes-- <= 0)
716*4882a593Smuzhiyun 			break;
717*4882a593Smuzhiyun 		/* handle TIME - time you should wait for my packets */
718*4882a593Smuzhiyun 		/* ignore what he says - don't wait for my ack longer than 1 second */
719*4882a593Smuzhiyun 		a_b[++length] = tochar(1);
720*4882a593Smuzhiyun 		if (bytes-- <= 0)
721*4882a593Smuzhiyun 			break;
722*4882a593Smuzhiyun 		/* handle NPAD - number of pad chars I need */
723*4882a593Smuzhiyun 		/* remember what he says - I need none */
724*4882a593Smuzhiyun 		his_pad_count = untochar(send_parms[2]);
725*4882a593Smuzhiyun 		a_b[++length] = tochar(0);
726*4882a593Smuzhiyun 		if (bytes-- <= 0)
727*4882a593Smuzhiyun 			break;
728*4882a593Smuzhiyun 		/* handle PADC - pad chars I need */
729*4882a593Smuzhiyun 		/* remember what he says - I need none */
730*4882a593Smuzhiyun 		his_pad_char = ktrans(send_parms[3]);
731*4882a593Smuzhiyun 		a_b[++length] = 0x40;	/* He should ignore this */
732*4882a593Smuzhiyun 		if (bytes-- <= 0)
733*4882a593Smuzhiyun 			break;
734*4882a593Smuzhiyun 		/* handle EOL - end of line he needs */
735*4882a593Smuzhiyun 		/* remember what he says - I need CR */
736*4882a593Smuzhiyun 		his_eol = untochar(send_parms[4]);
737*4882a593Smuzhiyun 		a_b[++length] = tochar(END_CHAR);
738*4882a593Smuzhiyun 		if (bytes-- <= 0)
739*4882a593Smuzhiyun 			break;
740*4882a593Smuzhiyun 		/* handle QCTL - quote control char he'll use */
741*4882a593Smuzhiyun 		/* remember what he says - I'll use '#' */
742*4882a593Smuzhiyun 		his_quote = send_parms[5];
743*4882a593Smuzhiyun 		a_b[++length] = '#';
744*4882a593Smuzhiyun 		if (bytes-- <= 0)
745*4882a593Smuzhiyun 			break;
746*4882a593Smuzhiyun 		/* handle QBIN - 8-th bit prefixing */
747*4882a593Smuzhiyun 		/* ignore what he says - I refuse */
748*4882a593Smuzhiyun 		a_b[++length] = 'N';
749*4882a593Smuzhiyun 		if (bytes-- <= 0)
750*4882a593Smuzhiyun 			break;
751*4882a593Smuzhiyun 		/* handle CHKT - the clock check type */
752*4882a593Smuzhiyun 		/* ignore what he says - I do type 1 (for now) */
753*4882a593Smuzhiyun 		a_b[++length] = '1';
754*4882a593Smuzhiyun 		if (bytes-- <= 0)
755*4882a593Smuzhiyun 			break;
756*4882a593Smuzhiyun 		/* handle REPT - the repeat prefix */
757*4882a593Smuzhiyun 		/* ignore what he says - I refuse (for now) */
758*4882a593Smuzhiyun 		a_b[++length] = 'N';
759*4882a593Smuzhiyun 		if (bytes-- <= 0)
760*4882a593Smuzhiyun 			break;
761*4882a593Smuzhiyun 		/* handle CAPAS - the capabilities mask */
762*4882a593Smuzhiyun 		/* ignore what he says - I only do long packets - I don't do windows */
763*4882a593Smuzhiyun 		a_b[++length] = tochar(2);	/* only long packets */
764*4882a593Smuzhiyun 		a_b[++length] = tochar(0);	/* no windows */
765*4882a593Smuzhiyun 		a_b[++length] = tochar(94);	/* large packet msb */
766*4882a593Smuzhiyun 		a_b[++length] = tochar(94);	/* large packet lsb */
767*4882a593Smuzhiyun 	} while (0);
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	a_b[0] = START_CHAR;
770*4882a593Smuzhiyun 	a_b[1] = tochar(length);
771*4882a593Smuzhiyun 	a_b[2] = tochar(n);
772*4882a593Smuzhiyun 	a_b[3] = ACK_TYPE;
773*4882a593Smuzhiyun 	a_b[++length] = '\0';
774*4882a593Smuzhiyun 	a_b[length] = tochar(chk1(&a_b[1]));
775*4882a593Smuzhiyun 	a_b[++length] = his_eol;
776*4882a593Smuzhiyun 	a_b[++length] = '\0';
777*4882a593Smuzhiyun 	s1_sendpacket(a_b);
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun /* k_recv receives a OS Open image file over kermit line */
k_recv(void)781*4882a593Smuzhiyun static int k_recv(void)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun 	char new_char;
784*4882a593Smuzhiyun 	char k_state, k_state_saved;
785*4882a593Smuzhiyun 	int sum;
786*4882a593Smuzhiyun 	int done;
787*4882a593Smuzhiyun 	int length;
788*4882a593Smuzhiyun 	int n, last_n;
789*4882a593Smuzhiyun 	int len_lo, len_hi;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	/* initialize some protocol parameters */
792*4882a593Smuzhiyun 	his_eol = END_CHAR;		/* default end of line character */
793*4882a593Smuzhiyun 	his_pad_count = 0;
794*4882a593Smuzhiyun 	his_pad_char = '\0';
795*4882a593Smuzhiyun 	his_quote = K_ESCAPE;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	/* initialize the k_recv and k_data state machine */
798*4882a593Smuzhiyun 	done = 0;
799*4882a593Smuzhiyun 	k_state = 0;
800*4882a593Smuzhiyun 	k_data_init();
801*4882a593Smuzhiyun 	k_state_saved = k_state;
802*4882a593Smuzhiyun 	k_data_save();
803*4882a593Smuzhiyun 	n = 0;				/* just to get rid of a warning */
804*4882a593Smuzhiyun 	last_n = -1;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	/* expect this "type" sequence (but don't check):
807*4882a593Smuzhiyun 	   S: send initiate
808*4882a593Smuzhiyun 	   F: file header
809*4882a593Smuzhiyun 	   D: data (multiple)
810*4882a593Smuzhiyun 	   Z: end of file
811*4882a593Smuzhiyun 	   B: break transmission
812*4882a593Smuzhiyun 	 */
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	/* enter main loop */
815*4882a593Smuzhiyun 	while (!done) {
816*4882a593Smuzhiyun 		/* set the send packet pointer to begining of send packet parms */
817*4882a593Smuzhiyun 		send_ptr = send_parms;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 		/* With each packet, start summing the bytes starting with the length.
820*4882a593Smuzhiyun 		   Save the current sequence number.
821*4882a593Smuzhiyun 		   Note the type of the packet.
822*4882a593Smuzhiyun 		   If a character less than SPACE (0x20) is received - error.
823*4882a593Smuzhiyun 		 */
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun #if 0
826*4882a593Smuzhiyun 		/* OLD CODE, Prior to checking sequence numbers */
827*4882a593Smuzhiyun 		/* first have all state machines save current states */
828*4882a593Smuzhiyun 		k_state_saved = k_state;
829*4882a593Smuzhiyun 		k_data_save ();
830*4882a593Smuzhiyun #endif
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 		/* get a packet */
833*4882a593Smuzhiyun 		/* wait for the starting character or ^C */
834*4882a593Smuzhiyun 		for (;;) {
835*4882a593Smuzhiyun 			switch (getc ()) {
836*4882a593Smuzhiyun 			case START_CHAR:	/* start packet */
837*4882a593Smuzhiyun 				goto START;
838*4882a593Smuzhiyun 			case ETX_CHAR:		/* ^C waiting for packet */
839*4882a593Smuzhiyun 				return (0);
840*4882a593Smuzhiyun 			default:
841*4882a593Smuzhiyun 				;
842*4882a593Smuzhiyun 			}
843*4882a593Smuzhiyun 		}
844*4882a593Smuzhiyun START:
845*4882a593Smuzhiyun 		/* get length of packet */
846*4882a593Smuzhiyun 		sum = 0;
847*4882a593Smuzhiyun 		new_char = getc();
848*4882a593Smuzhiyun 		if ((new_char & 0xE0) == 0)
849*4882a593Smuzhiyun 			goto packet_error;
850*4882a593Smuzhiyun 		sum += new_char & 0xff;
851*4882a593Smuzhiyun 		length = untochar(new_char);
852*4882a593Smuzhiyun 		/* get sequence number */
853*4882a593Smuzhiyun 		new_char = getc();
854*4882a593Smuzhiyun 		if ((new_char & 0xE0) == 0)
855*4882a593Smuzhiyun 			goto packet_error;
856*4882a593Smuzhiyun 		sum += new_char & 0xff;
857*4882a593Smuzhiyun 		n = untochar(new_char);
858*4882a593Smuzhiyun 		--length;
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 		/* NEW CODE - check sequence numbers for retried packets */
861*4882a593Smuzhiyun 		/* Note - this new code assumes that the sequence number is correctly
862*4882a593Smuzhiyun 		 * received.  Handling an invalid sequence number adds another layer
863*4882a593Smuzhiyun 		 * of complexity that may not be needed - yet!  At this time, I'm hoping
864*4882a593Smuzhiyun 		 * that I don't need to buffer the incoming data packets and can write
865*4882a593Smuzhiyun 		 * the data into memory in real time.
866*4882a593Smuzhiyun 		 */
867*4882a593Smuzhiyun 		if (n == last_n) {
868*4882a593Smuzhiyun 			/* same sequence number, restore the previous state */
869*4882a593Smuzhiyun 			k_state = k_state_saved;
870*4882a593Smuzhiyun 			k_data_restore();
871*4882a593Smuzhiyun 		} else {
872*4882a593Smuzhiyun 			/* new sequence number, checkpoint the download */
873*4882a593Smuzhiyun 			last_n = n;
874*4882a593Smuzhiyun 			k_state_saved = k_state;
875*4882a593Smuzhiyun 			k_data_save();
876*4882a593Smuzhiyun 		}
877*4882a593Smuzhiyun 		/* END NEW CODE */
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 		/* get packet type */
880*4882a593Smuzhiyun 		new_char = getc();
881*4882a593Smuzhiyun 		if ((new_char & 0xE0) == 0)
882*4882a593Smuzhiyun 			goto packet_error;
883*4882a593Smuzhiyun 		sum += new_char & 0xff;
884*4882a593Smuzhiyun 		k_state = new_char;
885*4882a593Smuzhiyun 		--length;
886*4882a593Smuzhiyun 		/* check for extended length */
887*4882a593Smuzhiyun 		if (length == -2) {
888*4882a593Smuzhiyun 			/* (length byte was 0, decremented twice) */
889*4882a593Smuzhiyun 			/* get the two length bytes */
890*4882a593Smuzhiyun 			new_char = getc();
891*4882a593Smuzhiyun 			if ((new_char & 0xE0) == 0)
892*4882a593Smuzhiyun 				goto packet_error;
893*4882a593Smuzhiyun 			sum += new_char & 0xff;
894*4882a593Smuzhiyun 			len_hi = untochar(new_char);
895*4882a593Smuzhiyun 			new_char = getc();
896*4882a593Smuzhiyun 			if ((new_char & 0xE0) == 0)
897*4882a593Smuzhiyun 				goto packet_error;
898*4882a593Smuzhiyun 			sum += new_char & 0xff;
899*4882a593Smuzhiyun 			len_lo = untochar(new_char);
900*4882a593Smuzhiyun 			length = len_hi * 95 + len_lo;
901*4882a593Smuzhiyun 			/* check header checksum */
902*4882a593Smuzhiyun 			new_char = getc();
903*4882a593Smuzhiyun 			if ((new_char & 0xE0) == 0)
904*4882a593Smuzhiyun 				goto packet_error;
905*4882a593Smuzhiyun 			if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
906*4882a593Smuzhiyun 				goto packet_error;
907*4882a593Smuzhiyun 			sum += new_char & 0xff;
908*4882a593Smuzhiyun /* --length; */ /* new length includes only data and block check to come */
909*4882a593Smuzhiyun 		}
910*4882a593Smuzhiyun 		/* bring in rest of packet */
911*4882a593Smuzhiyun 		while (length > 1) {
912*4882a593Smuzhiyun 			new_char = getc();
913*4882a593Smuzhiyun 			if ((new_char & 0xE0) == 0)
914*4882a593Smuzhiyun 				goto packet_error;
915*4882a593Smuzhiyun 			sum += new_char & 0xff;
916*4882a593Smuzhiyun 			--length;
917*4882a593Smuzhiyun 			if (k_state == DATA_TYPE) {
918*4882a593Smuzhiyun 				/* pass on the data if this is a data packet */
919*4882a593Smuzhiyun 				k_data_char (new_char);
920*4882a593Smuzhiyun 			} else if (k_state == SEND_TYPE) {
921*4882a593Smuzhiyun 				/* save send pack in buffer as is */
922*4882a593Smuzhiyun 				*send_ptr++ = new_char;
923*4882a593Smuzhiyun 				/* if too much data, back off the pointer */
924*4882a593Smuzhiyun 				if (send_ptr >= &send_parms[SEND_DATA_SIZE])
925*4882a593Smuzhiyun 					--send_ptr;
926*4882a593Smuzhiyun 			}
927*4882a593Smuzhiyun 		}
928*4882a593Smuzhiyun 		/* get and validate checksum character */
929*4882a593Smuzhiyun 		new_char = getc();
930*4882a593Smuzhiyun 		if ((new_char & 0xE0) == 0)
931*4882a593Smuzhiyun 			goto packet_error;
932*4882a593Smuzhiyun 		if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
933*4882a593Smuzhiyun 			goto packet_error;
934*4882a593Smuzhiyun 		/* get END_CHAR */
935*4882a593Smuzhiyun 		new_char = getc();
936*4882a593Smuzhiyun 		if (new_char != END_CHAR) {
937*4882a593Smuzhiyun 		  packet_error:
938*4882a593Smuzhiyun 			/* restore state machines */
939*4882a593Smuzhiyun 			k_state = k_state_saved;
940*4882a593Smuzhiyun 			k_data_restore();
941*4882a593Smuzhiyun 			/* send a negative acknowledge packet in */
942*4882a593Smuzhiyun 			send_nack(n);
943*4882a593Smuzhiyun 		} else if (k_state == SEND_TYPE) {
944*4882a593Smuzhiyun 			/* crack the protocol parms, build an appropriate ack packet */
945*4882a593Smuzhiyun 			handle_send_packet(n);
946*4882a593Smuzhiyun 		} else {
947*4882a593Smuzhiyun 			/* send simple acknowledge packet in */
948*4882a593Smuzhiyun 			send_ack(n);
949*4882a593Smuzhiyun 			/* quit if end of transmission */
950*4882a593Smuzhiyun 			if (k_state == BREAK_TYPE)
951*4882a593Smuzhiyun 				done = 1;
952*4882a593Smuzhiyun 		}
953*4882a593Smuzhiyun 	}
954*4882a593Smuzhiyun 	return ((ulong) os_data_addr - (ulong) bin_start_address);
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun 
getcxmodem(void)957*4882a593Smuzhiyun static int getcxmodem(void) {
958*4882a593Smuzhiyun 	if (tstc())
959*4882a593Smuzhiyun 		return (getc());
960*4882a593Smuzhiyun 	return -1;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun extern int zmodem_rx(unsigned int addr, int *rxsize);
load_serial_zmodem(ulong offset)964*4882a593Smuzhiyun static ulong load_serial_zmodem(ulong offset)
965*4882a593Smuzhiyun {
966*4882a593Smuzhiyun 	int size = 0;
967*4882a593Smuzhiyun 	int res;
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	printf("Start to run ZModem\n");
970*4882a593Smuzhiyun 	res = zmodem_rx(offset, &size);
971*4882a593Smuzhiyun 	if (res) {
972*4882a593Smuzhiyun 	       printf("ZModem download error, ret=%d\n", res);
973*4882a593Smuzhiyun 	       return offset;
974*4882a593Smuzhiyun 	}
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN));
977*4882a593Smuzhiyun 	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
978*4882a593Smuzhiyun 	env_set_hex("filesize", size);
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	return offset;
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun 
load_serial_ymodem(ulong offset,int mode)983*4882a593Smuzhiyun static ulong load_serial_ymodem(ulong offset, int mode)
984*4882a593Smuzhiyun {
985*4882a593Smuzhiyun 	int size;
986*4882a593Smuzhiyun 	int err;
987*4882a593Smuzhiyun 	int res;
988*4882a593Smuzhiyun 	connection_info_t info;
989*4882a593Smuzhiyun 	char ymodemBuf[1024];
990*4882a593Smuzhiyun 	ulong store_addr = ~0;
991*4882a593Smuzhiyun 	ulong addr = 0;
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	size = 0;
994*4882a593Smuzhiyun 	info.mode = mode;
995*4882a593Smuzhiyun 	res = xyzModem_stream_open(&info, &err);
996*4882a593Smuzhiyun 	if (!res) {
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 		while ((res =
999*4882a593Smuzhiyun 			xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) {
1000*4882a593Smuzhiyun 			store_addr = addr + offset;
1001*4882a593Smuzhiyun 			size += res;
1002*4882a593Smuzhiyun 			addr += res;
1003*4882a593Smuzhiyun #ifdef CONFIG_MTD_NOR_FLASH
1004*4882a593Smuzhiyun 			if (addr2info(store_addr)) {
1005*4882a593Smuzhiyun 				int rc;
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun 				rc = flash_write((char *) ymodemBuf,
1008*4882a593Smuzhiyun 						  store_addr, res);
1009*4882a593Smuzhiyun 				if (rc != 0) {
1010*4882a593Smuzhiyun 					flash_perror (rc);
1011*4882a593Smuzhiyun 					return (~0);
1012*4882a593Smuzhiyun 				}
1013*4882a593Smuzhiyun 			} else
1014*4882a593Smuzhiyun #endif
1015*4882a593Smuzhiyun 			{
1016*4882a593Smuzhiyun 				memcpy((char *)(store_addr), ymodemBuf,
1017*4882a593Smuzhiyun 					res);
1018*4882a593Smuzhiyun 			}
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 		}
1021*4882a593Smuzhiyun 	} else {
1022*4882a593Smuzhiyun 		printf("%s\n", xyzModem_error(err));
1023*4882a593Smuzhiyun 	}
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun 	xyzModem_stream_close(&err);
1026*4882a593Smuzhiyun 	xyzModem_stream_terminate(false, &getcxmodem);
1027*4882a593Smuzhiyun 
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN));
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
1032*4882a593Smuzhiyun 	env_set_hex("filesize", size);
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	return offset;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun 
do_loadz_flash(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])1037*4882a593Smuzhiyun static int do_loadz_flash(cmd_tbl_t *cmdtp, int flag, int argc,
1038*4882a593Smuzhiyun 			  char * const argv[])
1039*4882a593Smuzhiyun {
1040*4882a593Smuzhiyun 	struct blk_desc *dev_desc;
1041*4882a593Smuzhiyun 	disk_partition_t part;
1042*4882a593Smuzhiyun 	const char *part_name;
1043*4882a593Smuzhiyun 	char cmd[64];
1044*4882a593Smuzhiyun 	ulong addr, size;
1045*4882a593Smuzhiyun 	int ret, blknum;
1046*4882a593Smuzhiyun 	int baudrate;
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 	if (argc != 4)
1049*4882a593Smuzhiyun 		return CMD_RET_USAGE;
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	addr = simple_strtol(argv[1], NULL, 16);
1052*4882a593Smuzhiyun 	baudrate = (int)simple_strtoul(argv[2], NULL, 10);
1053*4882a593Smuzhiyun 	part_name = argv[3];
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun 	/* search partition */
1056*4882a593Smuzhiyun 	dev_desc = rockchip_get_bootdev();
1057*4882a593Smuzhiyun 	if (!dev_desc) {
1058*4882a593Smuzhiyun 		printf("No boot device\n");
1059*4882a593Smuzhiyun 		return -ENODEV;
1060*4882a593Smuzhiyun 	}
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	ret = part_get_info_by_name(dev_desc, part_name, &part);
1063*4882a593Smuzhiyun 	if (ret < 0) {
1064*4882a593Smuzhiyun 		printf("No partition '%s'\n", part_name);
1065*4882a593Smuzhiyun 		return -EINVAL;
1066*4882a593Smuzhiyun 	}
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	snprintf(cmd, 64, "loadz 0x%08lx %d\n", addr, baudrate);
1069*4882a593Smuzhiyun 	ret = run_command(cmd, 0);
1070*4882a593Smuzhiyun 	if (ret) {
1071*4882a593Smuzhiyun 		printf("loadz failed, ret=%d\n", ret);
1072*4882a593Smuzhiyun 		return CMD_RET_FAILURE;
1073*4882a593Smuzhiyun 	}
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	size = env_get_ulong("filesize", 16, 0);
1076*4882a593Smuzhiyun 	if (!size) {
1077*4882a593Smuzhiyun 		printf("loadz empty file\n");
1078*4882a593Smuzhiyun 		return CMD_RET_FAILURE;
1079*4882a593Smuzhiyun 	}
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 	/* flash */
1082*4882a593Smuzhiyun 	blknum = DIV_ROUND_UP(size, dev_desc->blksz);
1083*4882a593Smuzhiyun 	if (blknum > part.size) {
1084*4882a593Smuzhiyun 		printf("File size 0x%lx is too large to flash\n", size);
1085*4882a593Smuzhiyun 		return CMD_RET_FAILURE;
1086*4882a593Smuzhiyun 	}
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun #ifdef CONFIG_CMD_CRYPTO_SUM
1089*4882a593Smuzhiyun 	snprintf(cmd, 64, "crypto_sum sha256 0x%lx 0x%lx", addr, size);
1090*4882a593Smuzhiyun 	run_command(cmd, 0);
1091*4882a593Smuzhiyun #elif defined(CONFIG_CMD_HASH)
1092*4882a593Smuzhiyun 	snprintf(cmd, 64, "hash sha256 0x%lx 0x%lx", addr, size);
1093*4882a593Smuzhiyun 	run_command(cmd, 0);
1094*4882a593Smuzhiyun #endif
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 	printf("## Flash data to partition %s@0x%lx sector with size 0x%lx ... ",
1097*4882a593Smuzhiyun 		part_name, (ulong)part.start, (ulong)size);
1098*4882a593Smuzhiyun 	if (dev_desc->if_type == IF_TYPE_MTD)
1099*4882a593Smuzhiyun 		dev_desc->op_flag |= BLK_MTD_CONT_WRITE;
1100*4882a593Smuzhiyun 	ret = blk_dwrite(dev_desc, part.start, blknum, (void *)addr);
1101*4882a593Smuzhiyun 	if (dev_desc->if_type == IF_TYPE_MTD)
1102*4882a593Smuzhiyun 		dev_desc->op_flag &= ~(BLK_MTD_CONT_WRITE);
1103*4882a593Smuzhiyun 	if (ret != blknum) {
1104*4882a593Smuzhiyun 		printf("Failed(%d)\n\n", ret);
1105*4882a593Smuzhiyun 		return CMD_RET_FAILURE;
1106*4882a593Smuzhiyun 	}
1107*4882a593Smuzhiyun 	printf("OK\n\n");
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	return CMD_RET_SUCCESS;
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun #endif
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun /* -------------------------------------------------------------------- */
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun #if defined(CONFIG_CMD_LOADS)
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
1118*4882a593Smuzhiyun U_BOOT_CMD(
1119*4882a593Smuzhiyun 	loads, 3, 0,	do_load_serial,
1120*4882a593Smuzhiyun 	"load S-Record file over serial line",
1121*4882a593Smuzhiyun 	"[ off ] [ baud ]\n"
1122*4882a593Smuzhiyun 	"    - load S-Record file over serial line"
1123*4882a593Smuzhiyun 	" with offset 'off' and baudrate 'baud'"
1124*4882a593Smuzhiyun );
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
1127*4882a593Smuzhiyun U_BOOT_CMD(
1128*4882a593Smuzhiyun 	loads, 2, 0,	do_load_serial,
1129*4882a593Smuzhiyun 	"load S-Record file over serial line",
1130*4882a593Smuzhiyun 	"[ off ]\n"
1131*4882a593Smuzhiyun 	"    - load S-Record file over serial line with offset 'off'"
1132*4882a593Smuzhiyun );
1133*4882a593Smuzhiyun #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun /*
1136*4882a593Smuzhiyun  * SAVES always requires LOADS support, but not vice versa
1137*4882a593Smuzhiyun  */
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun #if defined(CONFIG_CMD_SAVES)
1141*4882a593Smuzhiyun #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
1142*4882a593Smuzhiyun U_BOOT_CMD(
1143*4882a593Smuzhiyun 	saves, 4, 0,	do_save_serial,
1144*4882a593Smuzhiyun 	"save S-Record file over serial line",
1145*4882a593Smuzhiyun 	"[ off ] [size] [ baud ]\n"
1146*4882a593Smuzhiyun 	"    - save S-Record file over serial line"
1147*4882a593Smuzhiyun 	" with offset 'off', size 'size' and baudrate 'baud'"
1148*4882a593Smuzhiyun );
1149*4882a593Smuzhiyun #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
1150*4882a593Smuzhiyun U_BOOT_CMD(
1151*4882a593Smuzhiyun 	saves, 3, 0,	do_save_serial,
1152*4882a593Smuzhiyun 	"save S-Record file over serial line",
1153*4882a593Smuzhiyun 	"[ off ] [size]\n"
1154*4882a593Smuzhiyun 	"    - save S-Record file over serial line with offset 'off' and size 'size'"
1155*4882a593Smuzhiyun );
1156*4882a593Smuzhiyun #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
1157*4882a593Smuzhiyun #endif	/* CONFIG_CMD_SAVES */
1158*4882a593Smuzhiyun #endif	/* CONFIG_CMD_LOADS */
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun #if defined(CONFIG_CMD_LOADB)
1162*4882a593Smuzhiyun U_BOOT_CMD(
1163*4882a593Smuzhiyun 	loadb, 3, 0,	do_load_serial_bin,
1164*4882a593Smuzhiyun 	"load binary file over serial line (kermit mode)",
1165*4882a593Smuzhiyun 	"[ off ] [ baud ]\n"
1166*4882a593Smuzhiyun 	"    - load binary file over serial line"
1167*4882a593Smuzhiyun 	" with offset 'off' and baudrate 'baud'"
1168*4882a593Smuzhiyun );
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun U_BOOT_CMD(
1171*4882a593Smuzhiyun 	loadx, 3, 0,	do_load_serial_bin,
1172*4882a593Smuzhiyun 	"load binary file over serial line (xmodem mode)",
1173*4882a593Smuzhiyun 	"[ off ] [ baud ]\n"
1174*4882a593Smuzhiyun 	"    - load binary file over serial line"
1175*4882a593Smuzhiyun 	" with offset 'off' and baudrate 'baud'"
1176*4882a593Smuzhiyun );
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun U_BOOT_CMD(
1179*4882a593Smuzhiyun 	loady, 3, 0,	do_load_serial_bin,
1180*4882a593Smuzhiyun 	"load binary file over serial line (ymodem mode)",
1181*4882a593Smuzhiyun 	"[ off ] [ baud ]\n"
1182*4882a593Smuzhiyun 	"    - load binary file over serial line"
1183*4882a593Smuzhiyun 	" with offset 'off' and baudrate 'baud'"
1184*4882a593Smuzhiyun );
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun U_BOOT_CMD(
1187*4882a593Smuzhiyun 	loadz, 3, 0,	do_load_serial_bin,
1188*4882a593Smuzhiyun 	"load binary file over serial line (zmodem mode)",
1189*4882a593Smuzhiyun 	"[ off ] [ baud ]\n"
1190*4882a593Smuzhiyun 	"    - load binary file over serial line"
1191*4882a593Smuzhiyun 	" with offset 'off' and baudrate 'baud'"
1192*4882a593Smuzhiyun );
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun U_BOOT_CMD(
1195*4882a593Smuzhiyun 	loadzflash, 4, 0, do_loadz_flash,
1196*4882a593Smuzhiyun 	"load binary file over serial line (zmodem mode) and flash to partition",
1197*4882a593Smuzhiyun 	"[ off ] [ baud ] [partition]\n"
1198*4882a593Smuzhiyun 	"    - load binary file over serial line"
1199*4882a593Smuzhiyun 	" with offset 'off' and baudrate 'baud' and flash to 'partition'"
1200*4882a593Smuzhiyun );
1201*4882a593Smuzhiyun #endif	/* CONFIG_CMD_LOADB */
1202