Blame view

common/cmd_load.c 25.3 KB
8bde7f776   wdenk   * Code cleanup:
1
  /*
232c150a2   wdenk   Add support for S...
2
   * (C) Copyright 2000-2004
8bde7f776   wdenk   * Code cleanup:
3
4
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
5
   * SPDX-License-Identifier:	GPL-2.0+
8bde7f776   wdenk   * Code cleanup:
6
7
8
9
10
11
12
   */
  
  /*
   * Serial up- and download support
   */
  #include <common.h>
  #include <command.h>
8bde7f776   wdenk   * Code cleanup:
13
14
  #include <s_record.h>
  #include <net.h>
27b207fd0   wdenk   * Implement new m...
15
  #include <exports.h>
f2841d377   Markus Klotzbuecher   Add support for y...
16
  #include <xyzModem.h>
8bde7f776   wdenk   * Code cleanup:
17

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
18
  DECLARE_GLOBAL_DATA_PTR;
8bde7f776   wdenk   * Code cleanup:
19

c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
20
  #if defined(CONFIG_CMD_LOADB)
6e66bd559   Angus Ainslie   Enable xmodem sup...
21
  static ulong load_serial_ymodem(ulong offset, int mode);
8546e2390   Wolfgang Denk   Declare load_seri...
22
  #endif
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
23
  #if defined(CONFIG_CMD_LOADS)
088f1b199   Kim Phillips   common/cmd_*.c: s...
24
25
  static ulong load_serial(long offset);
  static int read_record(char *buf, ulong len);
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
26
  # if defined(CONFIG_CMD_SAVES)
088f1b199   Kim Phillips   common/cmd_*.c: s...
27
28
  static int save_serial(ulong offset, ulong size);
  static int write_record(char *buf);
902531788   Jon Loeliger   common/: Remove l...
29
  #endif
8bde7f776   wdenk   * Code cleanup:
30
31
  
  static int do_echo = 1;
902531788   Jon Loeliger   common/: Remove l...
32
  #endif
8bde7f776   wdenk   * Code cleanup:
33
34
  
  /* -------------------------------------------------------------------- */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
35
  #if defined(CONFIG_CMD_LOADS)
088f1b199   Kim Phillips   common/cmd_*.c: s...
36
37
  static int do_load_serial(cmd_tbl_t *cmdtp, int flag, int argc,
  			  char * const argv[])
8bde7f776   wdenk   * Code cleanup:
38
  {
2b22d608f   Ricardo Ribalda Delgado   loads: allow nega...
39
  	long offset = 0;
8bde7f776   wdenk   * Code cleanup:
40
41
42
43
  	ulong addr;
  	int i;
  	char *env_echo;
  	int rcode = 0;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
44
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
45
46
47
48
49
50
51
52
53
54
  	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;
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
55
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
56
  	if (argc >= 2) {
2b22d608f   Ricardo Ribalda Delgado   loads: allow nega...
57
  		offset = simple_strtol(argv[1], NULL, 16);
8bde7f776   wdenk   * Code cleanup:
58
59
60
61
62
63
64
65
66
  	}
  	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) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
67
68
  		printf("## Switch baudrate to %d bps and press ENTER ...
  ",
8bde7f776   wdenk   * Code cleanup:
69
70
71
  			load_baudrate);
  		udelay(50000);
  		gd->baudrate = load_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
72
  		serial_setbrg();
8bde7f776   wdenk   * Code cleanup:
73
74
75
76
77
78
  		udelay(50000);
  		for (;;) {
  			if (getc() == '\r')
  				break;
  		}
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
79
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
80
  	if (argc == 2) {
2b22d608f   Ricardo Ribalda Delgado   loads: allow nega...
81
  		offset = simple_strtol(argv[1], NULL, 16);
8bde7f776   wdenk   * Code cleanup:
82
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
83
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
84

088f1b199   Kim Phillips   common/cmd_*.c: s...
85
86
  	printf("## Ready for S-Record download ...
  ");
8bde7f776   wdenk   * Code cleanup:
87

088f1b199   Kim Phillips   common/cmd_*.c: s...
88
  	addr = load_serial(offset);
8bde7f776   wdenk   * Code cleanup:
89
90
91
92
93
94
95
  
  	/*
  	 * 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) {
232c150a2   wdenk   Add support for S...
96
97
  		if (tstc()) {
  			(void) getc();
8bde7f776   wdenk   * Code cleanup:
98
99
100
101
102
  		}
  		udelay(1000);
  	}
  
  	if (addr == ~0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
103
104
  		printf("## S-Record download aborted
  ");
8bde7f776   wdenk   * Code cleanup:
105
106
  		rcode = 1;
  	} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
107
108
  		printf("## Start Addr      = 0x%08lX
  ", addr);
8bde7f776   wdenk   * Code cleanup:
109
110
  		load_addr = addr;
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
111
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
112
  	if (load_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
113
114
  		printf("## Switch baudrate to %d bps and press ESC ...
  ",
8bde7f776   wdenk   * Code cleanup:
115
  			current_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
116
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
117
  		gd->baudrate = current_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
118
119
  		serial_setbrg();
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
120
121
122
123
124
125
126
127
  		for (;;) {
  			if (getc() == 0x1B) /* ESC */
  				break;
  		}
  	}
  #endif
  	return rcode;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
128
  static ulong load_serial(long offset)
8bde7f776   wdenk   * Code cleanup:
129
130
131
132
133
134
135
  {
  	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	*/
8bde7f776   wdenk   * Code cleanup:
136
137
138
139
140
141
  	ulong	store_addr;
  	ulong	start_addr = ~0;
  	ulong	end_addr   =  0;
  	int	line_count =  0;
  
  	while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
142
  		type = srec_decode(record, &binlen, &addr, binbuf);
8bde7f776   wdenk   * Code cleanup:
143
144
145
146
147
148
149
150
151
152
  
  		if (type < 0) {
  			return (~0);		/* Invalid S-Record		*/
  		}
  
  		switch (type) {
  		case SREC_DATA2:
  		case SREC_DATA3:
  		case SREC_DATA4:
  		    store_addr = addr + offset;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
153
  #ifndef CONFIG_SYS_NO_FLASH
8bde7f776   wdenk   * Code cleanup:
154
155
  		    if (addr2info(store_addr)) {
  			int rc;
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
156
  			rc = flash_write((char *)binbuf,store_addr,binlen);
8bde7f776   wdenk   * Code cleanup:
157
  			if (rc != 0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
158
  				flash_perror(rc);
8bde7f776   wdenk   * Code cleanup:
159
160
161
162
163
  				return (~0);
  			}
  		    } else
  #endif
  		    {
088f1b199   Kim Phillips   common/cmd_*.c: s...
164
  			memcpy((char *)(store_addr), binbuf, binlen);
8bde7f776   wdenk   * Code cleanup:
165
166
167
168
169
170
171
172
173
  		    }
  		    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:
088f1b199   Kim Phillips   common/cmd_*.c: s...
174
  		    udelay(10000);
8bde7f776   wdenk   * Code cleanup:
175
  		    size = end_addr - start_addr + 1;
088f1b199   Kim Phillips   common/cmd_*.c: s...
176
177
  		    printf("
  "
8bde7f776   wdenk   * Code cleanup:
178
179
180
181
182
183
184
185
  			    "## First Load Addr = 0x%08lX
  "
  			    "## Last  Load Addr = 0x%08lX
  "
  			    "## Total Size      = 0x%08lX = %ld Bytes
  ",
  			    start_addr, end_addr, size, size
  		    );
088f1b199   Kim Phillips   common/cmd_*.c: s...
186
  		    flush_cache(start_addr, size);
41ef372c1   Simon Glass   common: Use new n...
187
  		    setenv_hex("filesize", size);
8bde7f776   wdenk   * Code cleanup:
188
189
190
191
192
193
194
195
  		    return (addr);
  		case SREC_START:
  		    break;
  		default:
  		    break;
  		}
  		if (!do_echo) {	/* print a '.' every 100 lines */
  			if ((++line_count % 100) == 0)
088f1b199   Kim Phillips   common/cmd_*.c: s...
196
  				putc('.');
8bde7f776   wdenk   * Code cleanup:
197
198
199
200
201
  		}
  	}
  
  	return (~0);			/* Download aborted		*/
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
202
  static int read_record(char *buf, ulong len)
8bde7f776   wdenk   * Code cleanup:
203
204
205
206
207
208
209
  {
  	char *p;
  	char c;
  
  	--len;	/* always leave room for terminating '\0' byte */
  
  	for (p=buf; p < buf+len; ++p) {
232c150a2   wdenk   Add support for S...
210
  		c = getc();		/* read character		*/
8bde7f776   wdenk   * Code cleanup:
211
  		if (do_echo)
088f1b199   Kim Phillips   common/cmd_*.c: s...
212
  			putc(c);	/* ... and echo it		*/
8bde7f776   wdenk   * Code cleanup:
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  
  		switch (c) {
  		case '\r':
  		case '
  ':
  			*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) */
232c150a2   wdenk   Add support for S...
228
  	    if (gd->jt[XF_getc] != getc) {
8bde7f776   wdenk   * Code cleanup:
229
230
231
232
  		if (ctrlc()) {
  		    return (-1);
  		}
  	    }
8bde7f776   wdenk   * Code cleanup:
233
234
235
236
237
238
  	}
  
  	/* line too long - truncate */
  	*p = '\0';
  	return (p - buf);
  }
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
239
  #if defined(CONFIG_CMD_SAVES)
8bde7f776   wdenk   * Code cleanup:
240

54841ab50   Wolfgang Denk   Make sure that ar...
241
  int do_save_serial (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
8bde7f776   wdenk   * Code cleanup:
242
243
244
  {
  	ulong offset = 0;
  	ulong size   = 0;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
245
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
246
247
248
249
250
251
252
253
  	int save_baudrate, current_baudrate;
  
  	save_baudrate = current_baudrate = gd->baudrate;
  #endif
  
  	if (argc >= 2) {
  		offset = simple_strtoul(argv[1], NULL, 16);
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
254
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
255
256
257
258
259
260
261
262
263
264
265
  	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) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
266
267
  		printf("## Switch baudrate to %d bps and press ENTER ...
  ",
8bde7f776   wdenk   * Code cleanup:
268
269
270
  			save_baudrate);
  		udelay(50000);
  		gd->baudrate = save_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
271
  		serial_setbrg();
8bde7f776   wdenk   * Code cleanup:
272
273
274
275
276
277
  		udelay(50000);
  		for (;;) {
  			if (getc() == '\r')
  				break;
  		}
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
278
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
279
280
281
  	if (argc == 3) {
  		size = simple_strtoul(argv[2], NULL, 16);
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
282
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
283

088f1b199   Kim Phillips   common/cmd_*.c: s...
284
285
  	printf("## Ready for S-Record upload, press ENTER to proceed ...
  ");
8bde7f776   wdenk   * Code cleanup:
286
287
288
289
  	for (;;) {
  		if (getc() == '\r')
  			break;
  	}
088f1b199   Kim Phillips   common/cmd_*.c: s...
290
291
292
  	if (save_serial(offset, size)) {
  		printf("## S-Record upload aborted
  ");
8bde7f776   wdenk   * Code cleanup:
293
  	} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
294
295
  		printf("## S-Record upload complete
  ");
8bde7f776   wdenk   * Code cleanup:
296
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
297
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
298
  	if (save_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
299
300
  		printf("## Switch baudrate to %d bps and press ESC ...
  ",
8bde7f776   wdenk   * Code cleanup:
301
  			(int)current_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
302
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
303
  		gd->baudrate = current_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
304
305
  		serial_setbrg();
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  		for (;;) {
  			if (getc() == 0x1B) /* ESC */
  				break;
  		}
  	}
  #endif
  	return 0;
  }
  
  #define SREC3_START				"S0030000FC
  "
  #define SREC3_FORMAT			"S3%02X%08lX%s%02X
  "
  #define SREC3_END				"S70500000000FA
  "
  #define SREC_BYTES_PER_RECORD	16
088f1b199   Kim Phillips   common/cmd_*.c: s...
322
  static int save_serial(ulong address, ulong count)
8bde7f776   wdenk   * Code cleanup:
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  {
  	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);
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
376
  static int write_record(char *buf)
8bde7f776   wdenk   * Code cleanup:
377
378
379
380
  {
  	char c;
  
  	while((c = *buf++))
232c150a2   wdenk   Add support for S...
381
  		putc(c);
8bde7f776   wdenk   * Code cleanup:
382
383
384
385
386
387
388
389
  
  	/* Check for the console hangup (if any different from serial) */
  
  	if (ctrlc()) {
  	    return (-1);
  	}
  	return (0);
  }
902531788   Jon Loeliger   common/: Remove l...
390
  # endif
8bde7f776   wdenk   * Code cleanup:
391

902531788   Jon Loeliger   common/: Remove l...
392
  #endif
8bde7f776   wdenk   * Code cleanup:
393

c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
394
  #if defined(CONFIG_CMD_LOADB)
65c450b47   Jon Loeliger   common/cmd_[i-z]*...
395
396
397
  /*
   * loadb command (load binary) included
   */
8bde7f776   wdenk   * Code cleanup:
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  #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))
8bde7f776   wdenk   * Code cleanup:
412
413
  static void set_kerm_bin_mode(unsigned long *);
  static int k_recv(void);
088f1b199   Kim Phillips   common/cmd_*.c: s...
414
  static ulong load_serial_bin(ulong offset);
8bde7f776   wdenk   * Code cleanup:
415

088f1b199   Kim Phillips   common/cmd_*.c: s...
416
417
418
419
  static char his_eol;        /* character he needs at end of packet */
  static int  his_pad_count;  /* number of pad chars he needs */
  static char his_pad_char;   /* pad chars he needs */
  static char his_quote;      /* quote chars he'll use */
8bde7f776   wdenk   * Code cleanup:
420

088f1b199   Kim Phillips   common/cmd_*.c: s...
421
422
  static int do_load_serial_bin(cmd_tbl_t *cmdtp, int flag, int argc,
  			      char * const argv[])
8bde7f776   wdenk   * Code cleanup:
423
  {
8bde7f776   wdenk   * Code cleanup:
424
425
426
427
428
  	ulong offset = 0;
  	ulong addr;
  	int load_baudrate, current_baudrate;
  	int rcode = 0;
  	char *s;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
429
430
  	/* pre-set offset from CONFIG_SYS_LOAD_ADDR */
  	offset = CONFIG_SYS_LOAD_ADDR;
8bde7f776   wdenk   * Code cleanup:
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  
  	/* 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) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
451
452
  		printf("## Switch baudrate to %d bps and press ENTER ...
  ",
8bde7f776   wdenk   * Code cleanup:
453
454
455
  			load_baudrate);
  		udelay(50000);
  		gd->baudrate = load_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
456
  		serial_setbrg();
8bde7f776   wdenk   * Code cleanup:
457
458
459
460
461
462
  		udelay(50000);
  		for (;;) {
  			if (getc() == '\r')
  				break;
  		}
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
463
  	if (strcmp(argv[0],"loady")==0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
464
  		printf("## Ready for binary (ymodem) download "
f2841d377   Markus Klotzbuecher   Add support for y...
465
466
467
468
  			"to 0x%08lX at %d bps...
  ",
  			offset,
  			load_baudrate);
6e66bd559   Angus Ainslie   Enable xmodem sup...
469
470
471
472
473
474
475
476
477
478
  		addr = load_serial_ymodem(offset, xyzModem_ymodem);
  
  	} else if (strcmp(argv[0],"loadx")==0) {
  		printf("## Ready for binary (xmodem) download "
  			"to 0x%08lX at %d bps...
  ",
  			offset,
  			load_baudrate);
  
  		addr = load_serial_ymodem(offset, xyzModem_xmodem);
8bde7f776   wdenk   * Code cleanup:
479

8bde7f776   wdenk   * Code cleanup:
480
  	} else {
8bde7f776   wdenk   * Code cleanup:
481

088f1b199   Kim Phillips   common/cmd_*.c: s...
482
  		printf("## Ready for binary (kermit) download "
f2841d377   Markus Klotzbuecher   Add support for y...
483
484
485
486
  			"to 0x%08lX at %d bps...
  ",
  			offset,
  			load_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
487
  		addr = load_serial_bin(offset);
f2841d377   Markus Klotzbuecher   Add support for y...
488
489
490
  
  		if (addr == ~0) {
  			load_addr = 0;
088f1b199   Kim Phillips   common/cmd_*.c: s...
491
492
  			printf("## Binary (kermit) download aborted
  ");
f2841d377   Markus Klotzbuecher   Add support for y...
493
494
  			rcode = 1;
  		} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
495
496
  			printf("## Start Addr      = 0x%08lX
  ", addr);
f2841d377   Markus Klotzbuecher   Add support for y...
497
498
499
  			load_addr = addr;
  		}
  	}
8bde7f776   wdenk   * Code cleanup:
500
  	if (load_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
501
502
  		printf("## Switch baudrate to %d bps and press ESC ...
  ",
8bde7f776   wdenk   * Code cleanup:
503
  			current_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
504
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
505
  		gd->baudrate = current_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
506
507
  		serial_setbrg();
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
508
509
510
511
512
  		for (;;) {
  			if (getc() == 0x1B) /* ESC */
  				break;
  		}
  	}
8bde7f776   wdenk   * Code cleanup:
513
514
  	return rcode;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
515
  static ulong load_serial_bin(ulong offset)
8bde7f776   wdenk   * Code cleanup:
516
517
  {
  	int size, i;
8bde7f776   wdenk   * Code cleanup:
518

088f1b199   Kim Phillips   common/cmd_*.c: s...
519
520
  	set_kerm_bin_mode((ulong *) offset);
  	size = k_recv();
8bde7f776   wdenk   * Code cleanup:
521
522
523
524
525
526
527
  
  	/*
  	 * 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) {
232c150a2   wdenk   Add support for S...
528
529
  		if (tstc()) {
  			(void) getc();
8bde7f776   wdenk   * Code cleanup:
530
531
532
  		}
  		udelay(1000);
  	}
088f1b199   Kim Phillips   common/cmd_*.c: s...
533
  	flush_cache(offset, size);
8bde7f776   wdenk   * Code cleanup:
534
535
536
  
  	printf("## Total Size      = 0x%08x = %d Bytes
  ", size, size);
41ef372c1   Simon Glass   common: Use new n...
537
  	setenv_hex("filesize", size);
8bde7f776   wdenk   * Code cleanup:
538
539
540
  
  	return offset;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
541
  static void send_pad(void)
8bde7f776   wdenk   * Code cleanup:
542
543
544
545
  {
  	int count = his_pad_count;
  
  	while (count-- > 0)
088f1b199   Kim Phillips   common/cmd_*.c: s...
546
  		putc(his_pad_char);
8bde7f776   wdenk   * Code cleanup:
547
548
549
  }
  
  /* converts escaped kermit char to binary char */
088f1b199   Kim Phillips   common/cmd_*.c: s...
550
  static char ktrans(char in)
8bde7f776   wdenk   * Code cleanup:
551
552
553
554
555
556
557
558
  {
  	if ((in & 0x60) == 0x40) {
  		return (char) (in & ~0x40);
  	} else if ((in & 0x7f) == 0x3f) {
  		return (char) (in | 0x40);
  	} else
  		return in;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
559
  static int chk1(char *buffer)
8bde7f776   wdenk   * Code cleanup:
560
561
562
563
564
565
566
567
  {
  	int total = 0;
  
  	while (*buffer) {
  		total += *buffer++;
  	}
  	return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
568
  static void s1_sendpacket(char *packet)
8bde7f776   wdenk   * Code cleanup:
569
  {
088f1b199   Kim Phillips   common/cmd_*.c: s...
570
  	send_pad();
8bde7f776   wdenk   * Code cleanup:
571
  	while (*packet) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
572
  		putc(*packet++);
8bde7f776   wdenk   * Code cleanup:
573
574
575
576
  	}
  }
  
  static char a_b[24];
088f1b199   Kim Phillips   common/cmd_*.c: s...
577
  static void send_ack(int n)
8bde7f776   wdenk   * Code cleanup:
578
579
  {
  	a_b[0] = START_CHAR;
088f1b199   Kim Phillips   common/cmd_*.c: s...
580
581
  	a_b[1] = tochar(3);
  	a_b[2] = tochar(n);
8bde7f776   wdenk   * Code cleanup:
582
583
  	a_b[3] = ACK_TYPE;
  	a_b[4] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
584
  	a_b[4] = tochar(chk1(&a_b[1]));
8bde7f776   wdenk   * Code cleanup:
585
586
  	a_b[5] = his_eol;
  	a_b[6] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
587
  	s1_sendpacket(a_b);
8bde7f776   wdenk   * Code cleanup:
588
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
589
  static void send_nack(int n)
8bde7f776   wdenk   * Code cleanup:
590
591
  {
  	a_b[0] = START_CHAR;
088f1b199   Kim Phillips   common/cmd_*.c: s...
592
593
  	a_b[1] = tochar(3);
  	a_b[2] = tochar(n);
8bde7f776   wdenk   * Code cleanup:
594
595
  	a_b[3] = NACK_TYPE;
  	a_b[4] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
596
  	a_b[4] = tochar(chk1(&a_b[1]));
8bde7f776   wdenk   * Code cleanup:
597
598
  	a_b[5] = his_eol;
  	a_b[6] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
599
  	s1_sendpacket(a_b);
8bde7f776   wdenk   * Code cleanup:
600
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
601
602
  static void (*os_data_init)(void);
  static void (*os_data_char)(char new_char);
8bde7f776   wdenk   * Code cleanup:
603
  static int os_data_state, os_data_state_saved;
8bde7f776   wdenk   * Code cleanup:
604
605
  static char *os_data_addr, *os_data_addr_saved;
  static char *bin_start_address;
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
606

088f1b199   Kim Phillips   common/cmd_*.c: s...
607
  static void bin_data_init(void)
8bde7f776   wdenk   * Code cleanup:
608
609
  {
  	os_data_state = 0;
8bde7f776   wdenk   * Code cleanup:
610
611
  	os_data_addr = bin_start_address;
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
612

088f1b199   Kim Phillips   common/cmd_*.c: s...
613
  static void os_data_save(void)
8bde7f776   wdenk   * Code cleanup:
614
615
  {
  	os_data_state_saved = os_data_state;
8bde7f776   wdenk   * Code cleanup:
616
617
  	os_data_addr_saved = os_data_addr;
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
618

088f1b199   Kim Phillips   common/cmd_*.c: s...
619
  static void os_data_restore(void)
8bde7f776   wdenk   * Code cleanup:
620
621
  {
  	os_data_state = os_data_state_saved;
8bde7f776   wdenk   * Code cleanup:
622
623
  	os_data_addr = os_data_addr_saved;
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
624

088f1b199   Kim Phillips   common/cmd_*.c: s...
625
  static void bin_data_char(char new_char)
8bde7f776   wdenk   * Code cleanup:
626
627
628
629
  {
  	switch (os_data_state) {
  	case 0:					/* data */
  		*os_data_addr++ = new_char;
8bde7f776   wdenk   * Code cleanup:
630
631
632
  		break;
  	}
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
633

088f1b199   Kim Phillips   common/cmd_*.c: s...
634
  static void set_kerm_bin_mode(unsigned long *addr)
8bde7f776   wdenk   * Code cleanup:
635
636
637
638
639
640
641
642
643
  {
  	bin_start_address = (char *) addr;
  	os_data_init = bin_data_init;
  	os_data_char = bin_data_char;
  }
  
  
  /* k_data_* simply handles the kermit escape translations */
  static int k_data_escape, k_data_escape_saved;
088f1b199   Kim Phillips   common/cmd_*.c: s...
644
  static void k_data_init(void)
8bde7f776   wdenk   * Code cleanup:
645
646
  {
  	k_data_escape = 0;
088f1b199   Kim Phillips   common/cmd_*.c: s...
647
  	os_data_init();
8bde7f776   wdenk   * Code cleanup:
648
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
649

088f1b199   Kim Phillips   common/cmd_*.c: s...
650
  static void k_data_save(void)
8bde7f776   wdenk   * Code cleanup:
651
652
  {
  	k_data_escape_saved = k_data_escape;
088f1b199   Kim Phillips   common/cmd_*.c: s...
653
  	os_data_save();
8bde7f776   wdenk   * Code cleanup:
654
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
655

088f1b199   Kim Phillips   common/cmd_*.c: s...
656
  static void k_data_restore(void)
8bde7f776   wdenk   * Code cleanup:
657
658
  {
  	k_data_escape = k_data_escape_saved;
088f1b199   Kim Phillips   common/cmd_*.c: s...
659
  	os_data_restore();
8bde7f776   wdenk   * Code cleanup:
660
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
661

088f1b199   Kim Phillips   common/cmd_*.c: s...
662
  static void k_data_char(char new_char)
8bde7f776   wdenk   * Code cleanup:
663
664
665
  {
  	if (k_data_escape) {
  		/* last char was escape - translate this character */
088f1b199   Kim Phillips   common/cmd_*.c: s...
666
  		os_data_char(ktrans(new_char));
8bde7f776   wdenk   * Code cleanup:
667
668
669
670
671
672
673
  		k_data_escape = 0;
  	} else {
  		if (new_char == his_quote) {
  			/* this char is escape - remember */
  			k_data_escape = 1;
  		} else {
  			/* otherwise send this char as-is */
088f1b199   Kim Phillips   common/cmd_*.c: s...
674
  			os_data_char(new_char);
8bde7f776   wdenk   * Code cleanup:
675
676
677
678
679
  		}
  	}
  }
  
  #define SEND_DATA_SIZE  20
088f1b199   Kim Phillips   common/cmd_*.c: s...
680
681
  static char send_parms[SEND_DATA_SIZE];
  static char *send_ptr;
8bde7f776   wdenk   * Code cleanup:
682
683
684
  
  /* handle_send_packet interprits the protocol info and builds and
     sends an appropriate ack for what we can do */
088f1b199   Kim Phillips   common/cmd_*.c: s...
685
  static void handle_send_packet(int n)
8bde7f776   wdenk   * Code cleanup:
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
  {
  	int length = 3;
  	int bytes;
  
  	/* initialize some protocol parameters */
  	his_eol = END_CHAR;		/* default end of line character */
  	his_pad_count = 0;
  	his_pad_char = '\0';
  	his_quote = K_ESCAPE;
  
  	/* ignore last character if it filled the buffer */
  	if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
  		--send_ptr;
  	bytes = send_ptr - send_parms;	/* how many bytes we'll process */
  	do {
  		if (bytes-- <= 0)
  			break;
  		/* handle MAXL - max length */
  		/* ignore what he says - most I'll take (here) is 94 */
088f1b199   Kim Phillips   common/cmd_*.c: s...
705
  		a_b[++length] = tochar(94);
8bde7f776   wdenk   * Code cleanup:
706
707
708
709
  		if (bytes-- <= 0)
  			break;
  		/* handle TIME - time you should wait for my packets */
  		/* ignore what he says - don't wait for my ack longer than 1 second */
088f1b199   Kim Phillips   common/cmd_*.c: s...
710
  		a_b[++length] = tochar(1);
8bde7f776   wdenk   * Code cleanup:
711
712
713
714
  		if (bytes-- <= 0)
  			break;
  		/* handle NPAD - number of pad chars I need */
  		/* remember what he says - I need none */
088f1b199   Kim Phillips   common/cmd_*.c: s...
715
716
  		his_pad_count = untochar(send_parms[2]);
  		a_b[++length] = tochar(0);
8bde7f776   wdenk   * Code cleanup:
717
718
719
720
  		if (bytes-- <= 0)
  			break;
  		/* handle PADC - pad chars I need */
  		/* remember what he says - I need none */
088f1b199   Kim Phillips   common/cmd_*.c: s...
721
  		his_pad_char = ktrans(send_parms[3]);
8bde7f776   wdenk   * Code cleanup:
722
723
724
725
726
  		a_b[++length] = 0x40;	/* He should ignore this */
  		if (bytes-- <= 0)
  			break;
  		/* handle EOL - end of line he needs */
  		/* remember what he says - I need CR */
088f1b199   Kim Phillips   common/cmd_*.c: s...
727
728
  		his_eol = untochar(send_parms[4]);
  		a_b[++length] = tochar(END_CHAR);
8bde7f776   wdenk   * Code cleanup:
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
  		if (bytes-- <= 0)
  			break;
  		/* handle QCTL - quote control char he'll use */
  		/* remember what he says - I'll use '#' */
  		his_quote = send_parms[5];
  		a_b[++length] = '#';
  		if (bytes-- <= 0)
  			break;
  		/* handle QBIN - 8-th bit prefixing */
  		/* ignore what he says - I refuse */
  		a_b[++length] = 'N';
  		if (bytes-- <= 0)
  			break;
  		/* handle CHKT - the clock check type */
  		/* ignore what he says - I do type 1 (for now) */
  		a_b[++length] = '1';
  		if (bytes-- <= 0)
  			break;
  		/* handle REPT - the repeat prefix */
  		/* ignore what he says - I refuse (for now) */
  		a_b[++length] = 'N';
  		if (bytes-- <= 0)
  			break;
  		/* handle CAPAS - the capabilities mask */
  		/* ignore what he says - I only do long packets - I don't do windows */
088f1b199   Kim Phillips   common/cmd_*.c: s...
754
755
756
757
  		a_b[++length] = tochar(2);	/* only long packets */
  		a_b[++length] = tochar(0);	/* no windows */
  		a_b[++length] = tochar(94);	/* large packet msb */
  		a_b[++length] = tochar(94);	/* large packet lsb */
8bde7f776   wdenk   * Code cleanup:
758
759
760
  	} while (0);
  
  	a_b[0] = START_CHAR;
088f1b199   Kim Phillips   common/cmd_*.c: s...
761
762
  	a_b[1] = tochar(length);
  	a_b[2] = tochar(n);
8bde7f776   wdenk   * Code cleanup:
763
764
  	a_b[3] = ACK_TYPE;
  	a_b[++length] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
765
  	a_b[length] = tochar(chk1(&a_b[1]));
8bde7f776   wdenk   * Code cleanup:
766
767
  	a_b[++length] = his_eol;
  	a_b[++length] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
768
  	s1_sendpacket(a_b);
8bde7f776   wdenk   * Code cleanup:
769
770
771
  }
  
  /* k_recv receives a OS Open image file over kermit line */
088f1b199   Kim Phillips   common/cmd_*.c: s...
772
  static int k_recv(void)
8bde7f776   wdenk   * Code cleanup:
773
774
775
776
777
778
779
  {
  	char new_char;
  	char k_state, k_state_saved;
  	int sum;
  	int done;
  	int length;
  	int n, last_n;
8bde7f776   wdenk   * Code cleanup:
780
781
782
783
784
785
786
787
788
789
790
  	int len_lo, len_hi;
  
  	/* initialize some protocol parameters */
  	his_eol = END_CHAR;		/* default end of line character */
  	his_pad_count = 0;
  	his_pad_char = '\0';
  	his_quote = K_ESCAPE;
  
  	/* initialize the k_recv and k_data state machine */
  	done = 0;
  	k_state = 0;
088f1b199   Kim Phillips   common/cmd_*.c: s...
791
  	k_data_init();
8bde7f776   wdenk   * Code cleanup:
792
  	k_state_saved = k_state;
088f1b199   Kim Phillips   common/cmd_*.c: s...
793
  	k_data_save();
8bde7f776   wdenk   * Code cleanup:
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  	n = 0;				/* just to get rid of a warning */
  	last_n = -1;
  
  	/* expect this "type" sequence (but don't check):
  	   S: send initiate
  	   F: file header
  	   D: data (multiple)
  	   Z: end of file
  	   B: break transmission
  	 */
  
  	/* enter main loop */
  	while (!done) {
  		/* set the send packet pointer to begining of send packet parms */
  		send_ptr = send_parms;
  
  		/* With each packet, start summing the bytes starting with the length.
  		   Save the current sequence number.
  		   Note the type of the packet.
  		   If a character less than SPACE (0x20) is received - error.
  		 */
  
  #if 0
  		/* OLD CODE, Prior to checking sequence numbers */
  		/* first have all state machines save current states */
  		k_state_saved = k_state;
  		k_data_save ();
  #endif
  
  		/* get a packet */
  		/* wait for the starting character or ^C */
  		for (;;) {
232c150a2   wdenk   Add support for S...
826
  			switch (getc ()) {
8bde7f776   wdenk   * Code cleanup:
827
828
829
830
831
832
833
834
835
836
837
  			case START_CHAR:	/* start packet */
  				goto START;
  			case ETX_CHAR:		/* ^C waiting for packet */
  				return (0);
  			default:
  				;
  			}
  		}
  START:
  		/* get length of packet */
  		sum = 0;
088f1b199   Kim Phillips   common/cmd_*.c: s...
838
  		new_char = getc();
8bde7f776   wdenk   * Code cleanup:
839
840
841
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
  		sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
842
  		length = untochar(new_char);
8bde7f776   wdenk   * Code cleanup:
843
  		/* get sequence number */
088f1b199   Kim Phillips   common/cmd_*.c: s...
844
  		new_char = getc();
8bde7f776   wdenk   * Code cleanup:
845
846
847
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
  		sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
848
  		n = untochar(new_char);
8bde7f776   wdenk   * Code cleanup:
849
850
851
852
853
854
855
856
857
858
859
860
  		--length;
  
  		/* NEW CODE - check sequence numbers for retried packets */
  		/* Note - this new code assumes that the sequence number is correctly
  		 * received.  Handling an invalid sequence number adds another layer
  		 * of complexity that may not be needed - yet!  At this time, I'm hoping
  		 * that I don't need to buffer the incoming data packets and can write
  		 * the data into memory in real time.
  		 */
  		if (n == last_n) {
  			/* same sequence number, restore the previous state */
  			k_state = k_state_saved;
088f1b199   Kim Phillips   common/cmd_*.c: s...
861
  			k_data_restore();
8bde7f776   wdenk   * Code cleanup:
862
863
864
865
  		} else {
  			/* new sequence number, checkpoint the download */
  			last_n = n;
  			k_state_saved = k_state;
088f1b199   Kim Phillips   common/cmd_*.c: s...
866
  			k_data_save();
8bde7f776   wdenk   * Code cleanup:
867
868
869
870
  		}
  		/* END NEW CODE */
  
  		/* get packet type */
088f1b199   Kim Phillips   common/cmd_*.c: s...
871
  		new_char = getc();
8bde7f776   wdenk   * Code cleanup:
872
873
874
875
876
877
878
879
880
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
  		sum += new_char & 0xff;
  		k_state = new_char;
  		--length;
  		/* check for extended length */
  		if (length == -2) {
  			/* (length byte was 0, decremented twice) */
  			/* get the two length bytes */
088f1b199   Kim Phillips   common/cmd_*.c: s...
881
  			new_char = getc();
8bde7f776   wdenk   * Code cleanup:
882
883
884
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
  			sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
885
886
  			len_hi = untochar(new_char);
  			new_char = getc();
8bde7f776   wdenk   * Code cleanup:
887
888
889
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
  			sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
890
  			len_lo = untochar(new_char);
8bde7f776   wdenk   * Code cleanup:
891
892
  			length = len_hi * 95 + len_lo;
  			/* check header checksum */
088f1b199   Kim Phillips   common/cmd_*.c: s...
893
  			new_char = getc();
8bde7f776   wdenk   * Code cleanup:
894
895
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
088f1b199   Kim Phillips   common/cmd_*.c: s...
896
  			if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
8bde7f776   wdenk   * Code cleanup:
897
898
899
900
901
902
  				goto packet_error;
  			sum += new_char & 0xff;
  /* --length; */ /* new length includes only data and block check to come */
  		}
  		/* bring in rest of packet */
  		while (length > 1) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
903
  			new_char = getc();
8bde7f776   wdenk   * Code cleanup:
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
  			sum += new_char & 0xff;
  			--length;
  			if (k_state == DATA_TYPE) {
  				/* pass on the data if this is a data packet */
  				k_data_char (new_char);
  			} else if (k_state == SEND_TYPE) {
  				/* save send pack in buffer as is */
  				*send_ptr++ = new_char;
  				/* if too much data, back off the pointer */
  				if (send_ptr >= &send_parms[SEND_DATA_SIZE])
  					--send_ptr;
  			}
  		}
  		/* get and validate checksum character */
088f1b199   Kim Phillips   common/cmd_*.c: s...
920
  		new_char = getc();
8bde7f776   wdenk   * Code cleanup:
921
922
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
088f1b199   Kim Phillips   common/cmd_*.c: s...
923
  		if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
8bde7f776   wdenk   * Code cleanup:
924
925
  			goto packet_error;
  		/* get END_CHAR */
088f1b199   Kim Phillips   common/cmd_*.c: s...
926
  		new_char = getc();
8bde7f776   wdenk   * Code cleanup:
927
928
929
930
  		if (new_char != END_CHAR) {
  		  packet_error:
  			/* restore state machines */
  			k_state = k_state_saved;
088f1b199   Kim Phillips   common/cmd_*.c: s...
931
  			k_data_restore();
8bde7f776   wdenk   * Code cleanup:
932
  			/* send a negative acknowledge packet in */
088f1b199   Kim Phillips   common/cmd_*.c: s...
933
  			send_nack(n);
8bde7f776   wdenk   * Code cleanup:
934
935
  		} else if (k_state == SEND_TYPE) {
  			/* crack the protocol parms, build an appropriate ack packet */
088f1b199   Kim Phillips   common/cmd_*.c: s...
936
  			handle_send_packet(n);
8bde7f776   wdenk   * Code cleanup:
937
938
  		} else {
  			/* send simple acknowledge packet in */
088f1b199   Kim Phillips   common/cmd_*.c: s...
939
  			send_ack(n);
8bde7f776   wdenk   * Code cleanup:
940
941
942
943
  			/* quit if end of transmission */
  			if (k_state == BREAK_TYPE)
  				done = 1;
  		}
8bde7f776   wdenk   * Code cleanup:
944
945
946
  	}
  	return ((ulong) os_data_addr - (ulong) bin_start_address);
  }
f2841d377   Markus Klotzbuecher   Add support for y...
947
948
  
  static int getcxmodem(void) {
cf48eb9ab   Wolfgang Denk   Some code cleanup
949
  	if (tstc())
f2841d377   Markus Klotzbuecher   Add support for y...
950
951
952
  		return (getc());
  	return -1;
  }
6e66bd559   Angus Ainslie   Enable xmodem sup...
953
  static ulong load_serial_ymodem(ulong offset, int mode)
f2841d377   Markus Klotzbuecher   Add support for y...
954
955
  {
  	int size;
f2841d377   Markus Klotzbuecher   Add support for y...
956
957
958
  	int err;
  	int res;
  	connection_info_t info;
cf48eb9ab   Wolfgang Denk   Some code cleanup
959
960
961
  	char ymodemBuf[1024];
  	ulong store_addr = ~0;
  	ulong addr = 0;
f2841d377   Markus Klotzbuecher   Add support for y...
962

cf48eb9ab   Wolfgang Denk   Some code cleanup
963
  	size = 0;
6e66bd559   Angus Ainslie   Enable xmodem sup...
964
  	info.mode = mode;
088f1b199   Kim Phillips   common/cmd_*.c: s...
965
  	res = xyzModem_stream_open(&info, &err);
f2841d377   Markus Klotzbuecher   Add support for y...
966
  	if (!res) {
f2841d377   Markus Klotzbuecher   Add support for y...
967

cf48eb9ab   Wolfgang Denk   Some code cleanup
968
  		while ((res =
088f1b199   Kim Phillips   common/cmd_*.c: s...
969
  			xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) {
cf48eb9ab   Wolfgang Denk   Some code cleanup
970
971
972
  			store_addr = addr + offset;
  			size += res;
  			addr += res;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
973
  #ifndef CONFIG_SYS_NO_FLASH
088f1b199   Kim Phillips   common/cmd_*.c: s...
974
  			if (addr2info(store_addr)) {
cf48eb9ab   Wolfgang Denk   Some code cleanup
975
  				int rc;
088f1b199   Kim Phillips   common/cmd_*.c: s...
976
  				rc = flash_write((char *) ymodemBuf,
cf48eb9ab   Wolfgang Denk   Some code cleanup
977
978
979
980
981
982
  						  store_addr, res);
  				if (rc != 0) {
  					flash_perror (rc);
  					return (~0);
  				}
  			} else
f2841d377   Markus Klotzbuecher   Add support for y...
983
  #endif
cf48eb9ab   Wolfgang Denk   Some code cleanup
984
  			{
088f1b199   Kim Phillips   common/cmd_*.c: s...
985
  				memcpy((char *)(store_addr), ymodemBuf,
cf48eb9ab   Wolfgang Denk   Some code cleanup
986
987
988
989
990
  					res);
  			}
  
  		}
  	} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
991
992
  		printf("%s
  ", xyzModem_error(err));
f2841d377   Markus Klotzbuecher   Add support for y...
993
  	}
cf48eb9ab   Wolfgang Denk   Some code cleanup
994

088f1b199   Kim Phillips   common/cmd_*.c: s...
995
996
  	xyzModem_stream_close(&err);
  	xyzModem_stream_terminate(false, &getcxmodem);
f2841d377   Markus Klotzbuecher   Add support for y...
997

088f1b199   Kim Phillips   common/cmd_*.c: s...
998
  	flush_cache(offset, size);
f2841d377   Markus Klotzbuecher   Add support for y...
999

088f1b199   Kim Phillips   common/cmd_*.c: s...
1000
1001
  	printf("## Total Size      = 0x%08x = %d Bytes
  ", size, size);
41ef372c1   Simon Glass   common: Use new n...
1002
  	setenv_hex("filesize", size);
f2841d377   Markus Klotzbuecher   Add support for y...
1003
1004
1005
  
  	return offset;
  }
902531788   Jon Loeliger   common/: Remove l...
1006
  #endif
8bde7f776   wdenk   * Code cleanup:
1007
1008
  
  /* -------------------------------------------------------------------- */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1009
  #if defined(CONFIG_CMD_LOADS)
8bde7f776   wdenk   * Code cleanup:
1010

6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1011
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
0d4983930   wdenk   Patch by Kenneth ...
1012
1013
  U_BOOT_CMD(
  	loads, 3, 0,	do_load_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1014
  	"load S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1015
1016
1017
  	"[ off ] [ baud ]
  "
  	"    - load S-Record file over serial line"
a89c33db9   Wolfgang Denk   General help mess...
1018
  	" with offset 'off' and baudrate 'baud'"
8bde7f776   wdenk   * Code cleanup:
1019
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1020
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
0d4983930   wdenk   Patch by Kenneth ...
1021
1022
  U_BOOT_CMD(
  	loads, 2, 0,	do_load_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1023
  	"load S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1024
1025
  	"[ off ]
  "
a89c33db9   Wolfgang Denk   General help mess...
1026
  	"    - load S-Record file over serial line with offset 'off'"
8bde7f776   wdenk   * Code cleanup:
1027
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1028
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
1029
1030
1031
1032
  
  /*
   * SAVES always requires LOADS support, but not vice versa
   */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1033
  #if defined(CONFIG_CMD_SAVES)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1034
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
0d4983930   wdenk   Patch by Kenneth ...
1035
1036
  U_BOOT_CMD(
  	saves, 4, 0,	do_save_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1037
  	"save S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1038
1039
1040
  	"[ off ] [size] [ baud ]
  "
  	"    - save S-Record file over serial line"
a89c33db9   Wolfgang Denk   General help mess...
1041
  	" with offset 'off', size 'size' and baudrate 'baud'"
8bde7f776   wdenk   * Code cleanup:
1042
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1043
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
0d4983930   wdenk   Patch by Kenneth ...
1044
1045
  U_BOOT_CMD(
  	saves, 3, 0,	do_save_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1046
  	"save S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1047
1048
  	"[ off ] [size]
  "
a89c33db9   Wolfgang Denk   General help mess...
1049
  	"    - save S-Record file over serial line with offset 'off' and size 'size'"
8bde7f776   wdenk   * Code cleanup:
1050
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1051
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
70d7cb925   Robert P. J. Day   cmd_load.c: Add #...
1052
1053
  #endif	/* CONFIG_CMD_SAVES */
  #endif	/* CONFIG_CMD_LOADS */
8bde7f776   wdenk   * Code cleanup:
1054

c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1055
  #if defined(CONFIG_CMD_LOADB)
0d4983930   wdenk   Patch by Kenneth ...
1056
1057
  U_BOOT_CMD(
  	loadb, 3, 0,	do_load_serial_bin,
2fb2604d5   Peter Tyser   Command usage cle...
1058
  	"load binary file over serial line (kermit mode)",
8bde7f776   wdenk   * Code cleanup:
1059
1060
1061
  	"[ off ] [ baud ]
  "
  	"    - load binary file over serial line"
6e66bd559   Angus Ainslie   Enable xmodem sup...
1062
1063
1064
1065
1066
1067
1068
1069
1070
  	" with offset 'off' and baudrate 'baud'"
  );
  
  U_BOOT_CMD(
  	loadx, 3, 0,	do_load_serial_bin,
  	"load binary file over serial line (xmodem mode)",
  	"[ off ] [ baud ]
  "
  	"    - load binary file over serial line"
a89c33db9   Wolfgang Denk   General help mess...
1071
  	" with offset 'off' and baudrate 'baud'"
8bde7f776   wdenk   * Code cleanup:
1072
  );
f2841d377   Markus Klotzbuecher   Add support for y...
1073
1074
  U_BOOT_CMD(
  	loady, 3, 0,	do_load_serial_bin,
2fb2604d5   Peter Tyser   Command usage cle...
1075
  	"load binary file over serial line (ymodem mode)",
f2841d377   Markus Klotzbuecher   Add support for y...
1076
1077
1078
  	"[ off ] [ baud ]
  "
  	"    - load binary file over serial line"
a89c33db9   Wolfgang Denk   General help mess...
1079
  	" with offset 'off' and baudrate 'baud'"
f2841d377   Markus Klotzbuecher   Add support for y...
1080
  );
70d7cb925   Robert P. J. Day   cmd_load.c: Add #...
1081
  #endif	/* CONFIG_CMD_LOADB */
8bde7f776   wdenk   * Code cleanup:
1082
1083
  
  /* -------------------------------------------------------------------- */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1084
  #if defined(CONFIG_CMD_HWFLOW)
088f1b199   Kim Phillips   common/cmd_*.c: s...
1085
  int do_hwflow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
8bde7f776   wdenk   * Code cleanup:
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
  {
  	extern int hwflow_onoff(int);
  
  	if (argc == 2) {
  		if (strcmp(argv[1], "off") == 0)
  			hwflow_onoff(-1);
  		else
  			if (strcmp(argv[1], "on") == 0)
  				hwflow_onoff(1);
  			else
4c12eeb8b   Simon Glass   Convert cmd_usage...
1096
  				return CMD_RET_USAGE;
8bde7f776   wdenk   * Code cleanup:
1097
1098
1099
1100
1101
1102
1103
  	}
  	printf("RTS/CTS hardware flow control: %s
  ", hwflow_onoff(0) ? "on" : "off");
  	return 0;
  }
  
  /* -------------------------------------------------------------------- */
0d4983930   wdenk   Patch by Kenneth ...
1104
  U_BOOT_CMD(
f12e568ca   wdenk   * Add support for...
1105
  	hwflow, 2, 0,	do_hwflow,
a89c33db9   Wolfgang Denk   General help mess...
1106
1107
  	"turn RTS/CTS hardware flow control in serial line on/off",
  	"[on|off]"
8bde7f776   wdenk   * Code cleanup:
1108
  );
70d7cb925   Robert P. J. Day   cmd_load.c: Add #...
1109
  #endif	/* CONFIG_CMD_HWFLOW */