Blame view

cmd/load.c 26.1 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
8bde7f776   wdenk   * Code cleanup:
2
  /*
232c150a2   wdenk   Add support for S...
3
   * (C) Copyright 2000-2004
8bde7f776   wdenk   * Code cleanup:
4
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8bde7f776   wdenk   * Code cleanup:
5
6
7
8
9
10
11
   */
  
  /*
   * Serial up- and download support
   */
  #include <common.h>
  #include <command.h>
24b852a7a   Simon Glass   Move console defi...
12
  #include <console.h>
1eb69ae49   Simon Glass   common: Move ARM ...
13
  #include <cpu_func.h>
76b0a1902   Heinrich Schuchardt   cmd/load: support...
14
  #include <efi_loader.h>
c7694dd48   Simon Glass   env: Move env_set...
15
  #include <env.h>
76b0a1902   Heinrich Schuchardt   cmd/load: support...
16
  #include <exports.h>
0ee48252b   Simon Glass   common: Move flas...
17
  #include <flash.h>
8e8ccfe1a   Simon Glass   common: Move the ...
18
  #include <image.h>
c6855195e   Marek Vasut   loads: Block writ...
19
  #include <lmb.h>
76b0a1902   Heinrich Schuchardt   cmd/load: support...
20
  #include <mapmem.h>
8bde7f776   wdenk   * Code cleanup:
21
  #include <net.h>
76b0a1902   Heinrich Schuchardt   cmd/load: support...
22
  #include <s_record.h>
b03e0510d   Simon Glass   common: Move seri...
23
  #include <serial.h>
f2841d377   Markus Klotzbuecher   Add support for y...
24
  #include <xyzModem.h>
90526e9fb   Simon Glass   common: Drop net....
25
  #include <asm/cache.h>
401d1c4f5   Simon Glass   common: Drop asm/...
26
  #include <asm/global_data.h>
c05ed00af   Simon Glass   common: Drop linu...
27
  #include <linux/delay.h>
8bde7f776   wdenk   * Code cleanup:
28

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

c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
31
  #if defined(CONFIG_CMD_LOADB)
6e66bd559   Angus Ainslie   Enable xmodem sup...
32
  static ulong load_serial_ymodem(ulong offset, int mode);
8546e2390   Wolfgang Denk   Declare load_seri...
33
  #endif
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
34
  #if defined(CONFIG_CMD_LOADS)
088f1b199   Kim Phillips   common/cmd_*.c: s...
35
36
  static ulong load_serial(long offset);
  static int read_record(char *buf, ulong len);
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
37
  # if defined(CONFIG_CMD_SAVES)
088f1b199   Kim Phillips   common/cmd_*.c: s...
38
39
  static int save_serial(ulong offset, ulong size);
  static int write_record(char *buf);
902531788   Jon Loeliger   common/: Remove l...
40
  #endif
8bde7f776   wdenk   * Code cleanup:
41
42
  
  static int do_echo = 1;
902531788   Jon Loeliger   common/: Remove l...
43
  #endif
8bde7f776   wdenk   * Code cleanup:
44
45
  
  /* -------------------------------------------------------------------- */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
46
  #if defined(CONFIG_CMD_LOADS)
091401131   Simon Glass   command: Remove t...
47
48
  static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
  			  char *const argv[])
8bde7f776   wdenk   * Code cleanup:
49
  {
2b22d608f   Ricardo Ribalda Delgado   loads: allow nega...
50
  	long offset = 0;
8bde7f776   wdenk   * Code cleanup:
51
52
53
54
  	ulong addr;
  	int i;
  	char *env_echo;
  	int rcode = 0;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
55
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
56
57
58
59
  	int load_baudrate, current_baudrate;
  
  	load_baudrate = current_baudrate = gd->baudrate;
  #endif
00caae6d4   Simon Glass   env: Rename geten...
60
61
  	env_echo = env_get("loads_echo");
  	if (env_echo && *env_echo == '1')
8bde7f776   wdenk   * Code cleanup:
62
  		do_echo = 1;
00caae6d4   Simon Glass   env: Rename geten...
63
  	else
8bde7f776   wdenk   * Code cleanup:
64
  		do_echo = 0;
8bde7f776   wdenk   * Code cleanup:
65

6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
66
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
67
  	if (argc >= 2) {
2b22d608f   Ricardo Ribalda Delgado   loads: allow nega...
68
  		offset = simple_strtol(argv[1], NULL, 16);
8bde7f776   wdenk   * Code cleanup:
69
70
  	}
  	if (argc == 3) {
0b1284eb5   Simon Glass   global: Convert s...
71
  		load_baudrate = (int)dectoul(argv[2], NULL);
8bde7f776   wdenk   * Code cleanup:
72
73
74
75
76
77
  
  		/* default to current baudrate */
  		if (load_baudrate == 0)
  			load_baudrate = current_baudrate;
  	}
  	if (load_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
78
79
  		printf("## Switch baudrate to %d bps and press ENTER ...
  ",
8bde7f776   wdenk   * Code cleanup:
80
81
82
  			load_baudrate);
  		udelay(50000);
  		gd->baudrate = load_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
83
  		serial_setbrg();
8bde7f776   wdenk   * Code cleanup:
84
85
  		udelay(50000);
  		for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
86
  			if (getchar() == '\r')
8bde7f776   wdenk   * Code cleanup:
87
88
89
  				break;
  		}
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
90
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
91
  	if (argc == 2) {
2b22d608f   Ricardo Ribalda Delgado   loads: allow nega...
92
  		offset = simple_strtol(argv[1], NULL, 16);
8bde7f776   wdenk   * Code cleanup:
93
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
94
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
95

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

088f1b199   Kim Phillips   common/cmd_*.c: s...
99
  	addr = load_serial(offset);
8bde7f776   wdenk   * Code cleanup:
100
101
102
103
104
105
106
  
  	/*
  	 * 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...
107
  		if (tstc()) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
108
  			getchar();
8bde7f776   wdenk   * Code cleanup:
109
110
111
112
113
  		}
  		udelay(1000);
  	}
  
  	if (addr == ~0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
114
115
  		printf("## S-Record download aborted
  ");
8bde7f776   wdenk   * Code cleanup:
116
117
  		rcode = 1;
  	} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
118
119
  		printf("## Start Addr      = 0x%08lX
  ", addr);
bb872dd93   Simon Glass   image: Rename loa...
120
  		image_load_addr = addr;
8bde7f776   wdenk   * Code cleanup:
121
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
122
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
123
  	if (load_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
124
125
  		printf("## Switch baudrate to %d bps and press ESC ...
  ",
8bde7f776   wdenk   * Code cleanup:
126
  			current_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
127
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
128
  		gd->baudrate = current_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
129
130
  		serial_setbrg();
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
131
  		for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
132
  			if (getchar() == 0x1B) /* ESC */
8bde7f776   wdenk   * Code cleanup:
133
134
135
136
137
138
  				break;
  		}
  	}
  #endif
  	return rcode;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
139
  static ulong load_serial(long offset)
8bde7f776   wdenk   * Code cleanup:
140
  {
c6855195e   Marek Vasut   loads: Block writ...
141
  	struct lmb lmb;
8bde7f776   wdenk   * Code cleanup:
142
143
144
145
146
147
  	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:
148
149
150
151
  	ulong	store_addr;
  	ulong	start_addr = ~0;
  	ulong	end_addr   =  0;
  	int	line_count =  0;
c6855195e   Marek Vasut   loads: Block writ...
152
153
154
  	long ret;
  
  	lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
8bde7f776   wdenk   * Code cleanup:
155
156
  
  	while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
157
  		type = srec_decode(record, &binlen, &addr, binbuf);
8bde7f776   wdenk   * Code cleanup:
158
159
160
161
162
163
164
165
166
167
  
  		if (type < 0) {
  			return (~0);		/* Invalid S-Record		*/
  		}
  
  		switch (type) {
  		case SREC_DATA2:
  		case SREC_DATA3:
  		case SREC_DATA4:
  		    store_addr = addr + offset;
e856bdcfb   Masahiro Yamada   flash: complete C...
168
  #ifdef CONFIG_MTD_NOR_FLASH
8bde7f776   wdenk   * Code cleanup:
169
170
  		    if (addr2info(store_addr)) {
  			int rc;
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
171
  			rc = flash_write((char *)binbuf,store_addr,binlen);
8bde7f776   wdenk   * Code cleanup:
172
  			if (rc != 0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
173
  				flash_perror(rc);
8bde7f776   wdenk   * Code cleanup:
174
175
176
177
178
  				return (~0);
  			}
  		    } else
  #endif
  		    {
c6855195e   Marek Vasut   loads: Block writ...
179
180
181
182
183
184
185
186
  			ret = lmb_reserve(&lmb, store_addr, binlen);
  			if (ret) {
  				printf("
  Cannot overwrite reserved area (%08lx..%08lx)
  ",
  					store_addr, store_addr + binlen);
  				return ret;
  			}
088f1b199   Kim Phillips   common/cmd_*.c: s...
187
  			memcpy((char *)(store_addr), binbuf, binlen);
c6855195e   Marek Vasut   loads: Block writ...
188
  			lmb_free(&lmb, store_addr, binlen);
8bde7f776   wdenk   * Code cleanup:
189
190
191
192
193
194
195
196
197
  		    }
  		    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...
198
  		    udelay(10000);
8bde7f776   wdenk   * Code cleanup:
199
  		    size = end_addr - start_addr + 1;
088f1b199   Kim Phillips   common/cmd_*.c: s...
200
201
  		    printf("
  "
8bde7f776   wdenk   * Code cleanup:
202
203
204
205
206
207
208
209
  			    "## 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...
210
  		    flush_cache(start_addr, size);
018f53032   Simon Glass   env: Rename commo...
211
  		    env_set_hex("filesize", size);
8bde7f776   wdenk   * Code cleanup:
212
213
214
215
216
217
218
219
  		    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...
220
  				putc('.');
8bde7f776   wdenk   * Code cleanup:
221
222
223
224
225
  		}
  	}
  
  	return (~0);			/* Download aborted		*/
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
226
  static int read_record(char *buf, ulong len)
8bde7f776   wdenk   * Code cleanup:
227
228
229
230
231
232
233
  {
  	char *p;
  	char c;
  
  	--len;	/* always leave room for terminating '\0' byte */
  
  	for (p=buf; p < buf+len; ++p) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
234
  		c = getchar();		/* read character		*/
8bde7f776   wdenk   * Code cleanup:
235
  		if (do_echo)
088f1b199   Kim Phillips   common/cmd_*.c: s...
236
  			putc(c);	/* ... and echo it		*/
8bde7f776   wdenk   * Code cleanup:
237
238
239
240
241
242
243
244
245
246
247
248
249
  
  		switch (c) {
  		case '\r':
  		case '
  ':
  			*p = '\0';
  			return (p - buf);
  		case '\0':
  		case 0x03:			/* ^C - Control C		*/
  			return (-1);
  		default:
  			*p = c;
  		}
e7fcfef43   Michal Simek   cmd: load: Fix co...
250
251
252
253
  		/* Check for the console hangup (if any different from serial) */
  		if (gd->jt->getc != getchar) {
  			if (ctrlc())
  				return (-1);
8bde7f776   wdenk   * Code cleanup:
254
  		}
8bde7f776   wdenk   * Code cleanup:
255
256
257
258
259
260
  	}
  
  	/* line too long - truncate */
  	*p = '\0';
  	return (p - buf);
  }
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
261
  #if defined(CONFIG_CMD_SAVES)
8bde7f776   wdenk   * Code cleanup:
262

091401131   Simon Glass   command: Remove t...
263
264
  int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc,
  		   char *const argv[])
8bde7f776   wdenk   * Code cleanup:
265
266
267
  {
  	ulong offset = 0;
  	ulong size   = 0;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
268
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
269
270
271
272
273
274
  	int save_baudrate, current_baudrate;
  
  	save_baudrate = current_baudrate = gd->baudrate;
  #endif
  
  	if (argc >= 2) {
7e5f460ec   Simon Glass   global: Convert s...
275
  		offset = hextoul(argv[1], NULL);
8bde7f776   wdenk   * Code cleanup:
276
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
277
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
278
  	if (argc >= 3) {
7e5f460ec   Simon Glass   global: Convert s...
279
  		size = hextoul(argv[2], NULL);
8bde7f776   wdenk   * Code cleanup:
280
281
  	}
  	if (argc == 4) {
0b1284eb5   Simon Glass   global: Convert s...
282
  		save_baudrate = (int)dectoul(argv[3], NULL);
8bde7f776   wdenk   * Code cleanup:
283
284
285
286
287
288
  
  		/* default to current baudrate */
  		if (save_baudrate == 0)
  			save_baudrate = current_baudrate;
  	}
  	if (save_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
289
290
  		printf("## Switch baudrate to %d bps and press ENTER ...
  ",
8bde7f776   wdenk   * Code cleanup:
291
292
293
  			save_baudrate);
  		udelay(50000);
  		gd->baudrate = save_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
294
  		serial_setbrg();
8bde7f776   wdenk   * Code cleanup:
295
296
  		udelay(50000);
  		for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
297
  			if (getchar() == '\r')
8bde7f776   wdenk   * Code cleanup:
298
299
300
  				break;
  		}
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
301
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
302
  	if (argc == 3) {
7e5f460ec   Simon Glass   global: Convert s...
303
  		size = hextoul(argv[2], NULL);
8bde7f776   wdenk   * Code cleanup:
304
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
305
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
306

088f1b199   Kim Phillips   common/cmd_*.c: s...
307
308
  	printf("## Ready for S-Record upload, press ENTER to proceed ...
  ");
8bde7f776   wdenk   * Code cleanup:
309
  	for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
310
  		if (getchar() == '\r')
8bde7f776   wdenk   * Code cleanup:
311
312
  			break;
  	}
088f1b199   Kim Phillips   common/cmd_*.c: s...
313
314
315
  	if (save_serial(offset, size)) {
  		printf("## S-Record upload aborted
  ");
8bde7f776   wdenk   * Code cleanup:
316
  	} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
317
318
  		printf("## S-Record upload complete
  ");
8bde7f776   wdenk   * Code cleanup:
319
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
320
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
8bde7f776   wdenk   * Code cleanup:
321
  	if (save_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
322
323
  		printf("## Switch baudrate to %d bps and press ESC ...
  ",
8bde7f776   wdenk   * Code cleanup:
324
  			(int)current_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
325
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
326
  		gd->baudrate = current_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
327
328
  		serial_setbrg();
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
329
  		for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
330
  			if (getchar() == 0x1B) /* ESC */
8bde7f776   wdenk   * Code cleanup:
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  				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...
345
  static int save_serial(ulong address, ulong count)
8bde7f776   wdenk   * Code cleanup:
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
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
  {
  	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...
399
  static int write_record(char *buf)
8bde7f776   wdenk   * Code cleanup:
400
401
402
403
  {
  	char c;
  
  	while((c = *buf++))
232c150a2   wdenk   Add support for S...
404
  		putc(c);
8bde7f776   wdenk   * Code cleanup:
405
406
407
408
409
410
411
412
  
  	/* Check for the console hangup (if any different from serial) */
  
  	if (ctrlc()) {
  	    return (-1);
  	}
  	return (0);
  }
902531788   Jon Loeliger   common/: Remove l...
413
  # endif
8bde7f776   wdenk   * Code cleanup:
414

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

c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
417
  #if defined(CONFIG_CMD_LOADB)
65c450b47   Jon Loeliger   common/cmd_[i-z]*...
418
419
420
  /*
   * loadb command (load binary) included
   */
8bde7f776   wdenk   * Code cleanup:
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  #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:
435
436
  static void set_kerm_bin_mode(unsigned long *);
  static int k_recv(void);
088f1b199   Kim Phillips   common/cmd_*.c: s...
437
  static ulong load_serial_bin(ulong offset);
8bde7f776   wdenk   * Code cleanup:
438

088f1b199   Kim Phillips   common/cmd_*.c: s...
439
440
441
442
  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:
443

091401131   Simon Glass   command: Remove t...
444
445
  static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
  			      char *const argv[])
8bde7f776   wdenk   * Code cleanup:
446
  {
8bde7f776   wdenk   * Code cleanup:
447
448
449
450
451
  	ulong offset = 0;
  	ulong addr;
  	int load_baudrate, current_baudrate;
  	int rcode = 0;
  	char *s;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
452
453
  	/* pre-set offset from CONFIG_SYS_LOAD_ADDR */
  	offset = CONFIG_SYS_LOAD_ADDR;
8bde7f776   wdenk   * Code cleanup:
454
455
  
  	/* pre-set offset from $loadaddr */
00caae6d4   Simon Glass   env: Rename geten...
456
457
  	s = env_get("loadaddr");
  	if (s)
7e5f460ec   Simon Glass   global: Convert s...
458
  		offset = hextoul(s, NULL);
8bde7f776   wdenk   * Code cleanup:
459
460
461
462
  
  	load_baudrate = current_baudrate = gd->baudrate;
  
  	if (argc >= 2) {
7e5f460ec   Simon Glass   global: Convert s...
463
  		offset = hextoul(argv[1], NULL);
8bde7f776   wdenk   * Code cleanup:
464
465
  	}
  	if (argc == 3) {
0b1284eb5   Simon Glass   global: Convert s...
466
  		load_baudrate = (int)dectoul(argv[2], NULL);
8bde7f776   wdenk   * Code cleanup:
467
468
469
470
471
472
473
  
  		/* default to current baudrate */
  		if (load_baudrate == 0)
  			load_baudrate = current_baudrate;
  	}
  
  	if (load_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
474
475
  		printf("## Switch baudrate to %d bps and press ENTER ...
  ",
8bde7f776   wdenk   * Code cleanup:
476
477
478
  			load_baudrate);
  		udelay(50000);
  		gd->baudrate = load_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
479
  		serial_setbrg();
8bde7f776   wdenk   * Code cleanup:
480
481
  		udelay(50000);
  		for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
482
  			if (getchar() == '\r')
8bde7f776   wdenk   * Code cleanup:
483
484
485
  				break;
  		}
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
486
  	if (strcmp(argv[0],"loady")==0) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
487
  		printf("## Ready for binary (ymodem) download "
f2841d377   Markus Klotzbuecher   Add support for y...
488
489
490
491
  			"to 0x%08lX at %d bps...
  ",
  			offset,
  			load_baudrate);
6e66bd559   Angus Ainslie   Enable xmodem sup...
492
  		addr = load_serial_ymodem(offset, xyzModem_ymodem);
c97b2557b   Pali Rohár   xyz-modem: Show i...
493
494
495
496
497
498
499
500
501
502
  		if (addr == ~0) {
  			image_load_addr = 0;
  			printf("## Binary (ymodem) download aborted
  ");
  			rcode = 1;
  		} else {
  			printf("## Start Addr      = 0x%08lX
  ", addr);
  			image_load_addr = addr;
  		}
6e66bd559   Angus Ainslie   Enable xmodem sup...
503
504
505
506
507
508
509
510
  	} 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:
511

c97b2557b   Pali Rohár   xyz-modem: Show i...
512
513
514
515
516
517
518
519
520
521
  		if (addr == ~0) {
  			image_load_addr = 0;
  			printf("## Binary (xmodem) download aborted
  ");
  			rcode = 1;
  		} else {
  			printf("## Start Addr      = 0x%08lX
  ", addr);
  			image_load_addr = addr;
  		}
8bde7f776   wdenk   * Code cleanup:
522
  	} else {
8bde7f776   wdenk   * Code cleanup:
523

088f1b199   Kim Phillips   common/cmd_*.c: s...
524
  		printf("## Ready for binary (kermit) download "
f2841d377   Markus Klotzbuecher   Add support for y...
525
526
527
528
  			"to 0x%08lX at %d bps...
  ",
  			offset,
  			load_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
529
  		addr = load_serial_bin(offset);
f2841d377   Markus Klotzbuecher   Add support for y...
530
531
  
  		if (addr == ~0) {
bb872dd93   Simon Glass   image: Rename loa...
532
  			image_load_addr = 0;
088f1b199   Kim Phillips   common/cmd_*.c: s...
533
534
  			printf("## Binary (kermit) download aborted
  ");
f2841d377   Markus Klotzbuecher   Add support for y...
535
536
  			rcode = 1;
  		} else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
537
538
  			printf("## Start Addr      = 0x%08lX
  ", addr);
bb872dd93   Simon Glass   image: Rename loa...
539
  			image_load_addr = addr;
f2841d377   Markus Klotzbuecher   Add support for y...
540
541
  		}
  	}
8bde7f776   wdenk   * Code cleanup:
542
  	if (load_baudrate != current_baudrate) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
543
544
  		printf("## Switch baudrate to %d bps and press ESC ...
  ",
8bde7f776   wdenk   * Code cleanup:
545
  			current_baudrate);
088f1b199   Kim Phillips   common/cmd_*.c: s...
546
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
547
  		gd->baudrate = current_baudrate;
088f1b199   Kim Phillips   common/cmd_*.c: s...
548
549
  		serial_setbrg();
  		udelay(50000);
8bde7f776   wdenk   * Code cleanup:
550
  		for (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
551
  			if (getchar() == 0x1B) /* ESC */
8bde7f776   wdenk   * Code cleanup:
552
553
554
  				break;
  		}
  	}
8bde7f776   wdenk   * Code cleanup:
555
556
  	return rcode;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
557
  static ulong load_serial_bin(ulong offset)
8bde7f776   wdenk   * Code cleanup:
558
559
  {
  	int size, i;
8bde7f776   wdenk   * Code cleanup:
560

088f1b199   Kim Phillips   common/cmd_*.c: s...
561
562
  	set_kerm_bin_mode((ulong *) offset);
  	size = k_recv();
8bde7f776   wdenk   * Code cleanup:
563
564
565
566
567
568
569
  
  	/*
  	 * 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...
570
  		if (tstc()) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
571
  			getchar();
8bde7f776   wdenk   * Code cleanup:
572
573
574
  		}
  		udelay(1000);
  	}
515381414   Pali Rohár   loadb: Properly i...
575
576
  	if (size == 0)
  		return ~0; /* Download aborted */
088f1b199   Kim Phillips   common/cmd_*.c: s...
577
  	flush_cache(offset, size);
8bde7f776   wdenk   * Code cleanup:
578
579
580
  
  	printf("## Total Size      = 0x%08x = %d Bytes
  ", size, size);
018f53032   Simon Glass   env: Rename commo...
581
  	env_set_hex("filesize", size);
8bde7f776   wdenk   * Code cleanup:
582
583
584
  
  	return offset;
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
585
  static void send_pad(void)
8bde7f776   wdenk   * Code cleanup:
586
587
588
589
  {
  	int count = his_pad_count;
  
  	while (count-- > 0)
088f1b199   Kim Phillips   common/cmd_*.c: s...
590
  		putc(his_pad_char);
8bde7f776   wdenk   * Code cleanup:
591
592
593
  }
  
  /* converts escaped kermit char to binary char */
088f1b199   Kim Phillips   common/cmd_*.c: s...
594
  static char ktrans(char in)
8bde7f776   wdenk   * Code cleanup:
595
596
597
598
599
600
601
602
  {
  	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...
603
  static int chk1(char *buffer)
8bde7f776   wdenk   * Code cleanup:
604
605
606
607
608
609
610
611
  {
  	int total = 0;
  
  	while (*buffer) {
  		total += *buffer++;
  	}
  	return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
612
  static void s1_sendpacket(char *packet)
8bde7f776   wdenk   * Code cleanup:
613
  {
088f1b199   Kim Phillips   common/cmd_*.c: s...
614
  	send_pad();
8bde7f776   wdenk   * Code cleanup:
615
  	while (*packet) {
088f1b199   Kim Phillips   common/cmd_*.c: s...
616
  		putc(*packet++);
8bde7f776   wdenk   * Code cleanup:
617
618
619
620
  	}
  }
  
  static char a_b[24];
088f1b199   Kim Phillips   common/cmd_*.c: s...
621
  static void send_ack(int n)
8bde7f776   wdenk   * Code cleanup:
622
623
  {
  	a_b[0] = START_CHAR;
088f1b199   Kim Phillips   common/cmd_*.c: s...
624
625
  	a_b[1] = tochar(3);
  	a_b[2] = tochar(n);
8bde7f776   wdenk   * Code cleanup:
626
627
  	a_b[3] = ACK_TYPE;
  	a_b[4] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
628
  	a_b[4] = tochar(chk1(&a_b[1]));
8bde7f776   wdenk   * Code cleanup:
629
630
  	a_b[5] = his_eol;
  	a_b[6] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
631
  	s1_sendpacket(a_b);
8bde7f776   wdenk   * Code cleanup:
632
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
633
  static void send_nack(int n)
8bde7f776   wdenk   * Code cleanup:
634
635
  {
  	a_b[0] = START_CHAR;
088f1b199   Kim Phillips   common/cmd_*.c: s...
636
637
  	a_b[1] = tochar(3);
  	a_b[2] = tochar(n);
8bde7f776   wdenk   * Code cleanup:
638
639
  	a_b[3] = NACK_TYPE;
  	a_b[4] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
640
  	a_b[4] = tochar(chk1(&a_b[1]));
8bde7f776   wdenk   * Code cleanup:
641
642
  	a_b[5] = his_eol;
  	a_b[6] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
643
  	s1_sendpacket(a_b);
8bde7f776   wdenk   * Code cleanup:
644
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
645
646
  static void (*os_data_init)(void);
  static void (*os_data_char)(char new_char);
8bde7f776   wdenk   * Code cleanup:
647
  static int os_data_state, os_data_state_saved;
8bde7f776   wdenk   * Code cleanup:
648
649
  static char *os_data_addr, *os_data_addr_saved;
  static char *bin_start_address;
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
650

088f1b199   Kim Phillips   common/cmd_*.c: s...
651
  static void bin_data_init(void)
8bde7f776   wdenk   * Code cleanup:
652
653
  {
  	os_data_state = 0;
8bde7f776   wdenk   * Code cleanup:
654
655
  	os_data_addr = bin_start_address;
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
656

088f1b199   Kim Phillips   common/cmd_*.c: s...
657
  static void os_data_save(void)
8bde7f776   wdenk   * Code cleanup:
658
659
  {
  	os_data_state_saved = os_data_state;
8bde7f776   wdenk   * Code cleanup:
660
661
  	os_data_addr_saved = os_data_addr;
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
662

088f1b199   Kim Phillips   common/cmd_*.c: s...
663
  static void os_data_restore(void)
8bde7f776   wdenk   * Code cleanup:
664
665
  {
  	os_data_state = os_data_state_saved;
8bde7f776   wdenk   * Code cleanup:
666
667
  	os_data_addr = os_data_addr_saved;
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
668

088f1b199   Kim Phillips   common/cmd_*.c: s...
669
  static void bin_data_char(char new_char)
8bde7f776   wdenk   * Code cleanup:
670
671
672
673
  {
  	switch (os_data_state) {
  	case 0:					/* data */
  		*os_data_addr++ = new_char;
8bde7f776   wdenk   * Code cleanup:
674
675
676
  		break;
  	}
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
677

088f1b199   Kim Phillips   common/cmd_*.c: s...
678
  static void set_kerm_bin_mode(unsigned long *addr)
8bde7f776   wdenk   * Code cleanup:
679
680
681
682
683
684
685
686
687
  {
  	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...
688
  static void k_data_init(void)
8bde7f776   wdenk   * Code cleanup:
689
690
  {
  	k_data_escape = 0;
088f1b199   Kim Phillips   common/cmd_*.c: s...
691
  	os_data_init();
8bde7f776   wdenk   * Code cleanup:
692
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
693

088f1b199   Kim Phillips   common/cmd_*.c: s...
694
  static void k_data_save(void)
8bde7f776   wdenk   * Code cleanup:
695
696
  {
  	k_data_escape_saved = k_data_escape;
088f1b199   Kim Phillips   common/cmd_*.c: s...
697
  	os_data_save();
8bde7f776   wdenk   * Code cleanup:
698
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
699

088f1b199   Kim Phillips   common/cmd_*.c: s...
700
  static void k_data_restore(void)
8bde7f776   wdenk   * Code cleanup:
701
702
  {
  	k_data_escape = k_data_escape_saved;
088f1b199   Kim Phillips   common/cmd_*.c: s...
703
  	os_data_restore();
8bde7f776   wdenk   * Code cleanup:
704
  }
a9fe0c3e7   Gururaja Hebbar K R   common/cmd_load.c...
705

088f1b199   Kim Phillips   common/cmd_*.c: s...
706
  static void k_data_char(char new_char)
8bde7f776   wdenk   * Code cleanup:
707
708
709
  {
  	if (k_data_escape) {
  		/* last char was escape - translate this character */
088f1b199   Kim Phillips   common/cmd_*.c: s...
710
  		os_data_char(ktrans(new_char));
8bde7f776   wdenk   * Code cleanup:
711
712
713
714
715
716
717
  		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...
718
  			os_data_char(new_char);
8bde7f776   wdenk   * Code cleanup:
719
720
721
722
723
  		}
  	}
  }
  
  #define SEND_DATA_SIZE  20
088f1b199   Kim Phillips   common/cmd_*.c: s...
724
725
  static char send_parms[SEND_DATA_SIZE];
  static char *send_ptr;
8bde7f776   wdenk   * Code cleanup:
726
727
728
  
  /* 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...
729
  static void handle_send_packet(int n)
8bde7f776   wdenk   * Code cleanup:
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
  {
  	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...
749
  		a_b[++length] = tochar(94);
8bde7f776   wdenk   * Code cleanup:
750
751
752
753
  		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...
754
  		a_b[++length] = tochar(1);
8bde7f776   wdenk   * Code cleanup:
755
756
757
758
  		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...
759
760
  		his_pad_count = untochar(send_parms[2]);
  		a_b[++length] = tochar(0);
8bde7f776   wdenk   * Code cleanup:
761
762
763
764
  		if (bytes-- <= 0)
  			break;
  		/* handle PADC - pad chars I need */
  		/* remember what he says - I need none */
088f1b199   Kim Phillips   common/cmd_*.c: s...
765
  		his_pad_char = ktrans(send_parms[3]);
8bde7f776   wdenk   * Code cleanup:
766
767
768
769
770
  		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...
771
772
  		his_eol = untochar(send_parms[4]);
  		a_b[++length] = tochar(END_CHAR);
8bde7f776   wdenk   * Code cleanup:
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
  		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...
798
799
800
801
  		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:
802
803
804
  	} while (0);
  
  	a_b[0] = START_CHAR;
088f1b199   Kim Phillips   common/cmd_*.c: s...
805
806
  	a_b[1] = tochar(length);
  	a_b[2] = tochar(n);
8bde7f776   wdenk   * Code cleanup:
807
808
  	a_b[3] = ACK_TYPE;
  	a_b[++length] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
809
  	a_b[length] = tochar(chk1(&a_b[1]));
8bde7f776   wdenk   * Code cleanup:
810
811
  	a_b[++length] = his_eol;
  	a_b[++length] = '\0';
088f1b199   Kim Phillips   common/cmd_*.c: s...
812
  	s1_sendpacket(a_b);
8bde7f776   wdenk   * Code cleanup:
813
814
815
  }
  
  /* k_recv receives a OS Open image file over kermit line */
088f1b199   Kim Phillips   common/cmd_*.c: s...
816
  static int k_recv(void)
8bde7f776   wdenk   * Code cleanup:
817
818
819
820
821
822
823
  {
  	char new_char;
  	char k_state, k_state_saved;
  	int sum;
  	int done;
  	int length;
  	int n, last_n;
8bde7f776   wdenk   * Code cleanup:
824
825
826
827
828
829
830
831
832
833
834
  	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...
835
  	k_data_init();
8bde7f776   wdenk   * Code cleanup:
836
  	k_state_saved = k_state;
088f1b199   Kim Phillips   common/cmd_*.c: s...
837
  	k_data_save();
8bde7f776   wdenk   * Code cleanup:
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
  	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 (;;) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
870
  			switch (getchar()) {
8bde7f776   wdenk   * Code cleanup:
871
872
873
874
875
876
877
878
879
880
881
  			case START_CHAR:	/* start packet */
  				goto START;
  			case ETX_CHAR:		/* ^C waiting for packet */
  				return (0);
  			default:
  				;
  			}
  		}
  START:
  		/* get length of packet */
  		sum = 0;
c670aeee3   Heinrich Schuchardt   common: rename ge...
882
  		new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
883
884
885
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
  		sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
886
  		length = untochar(new_char);
8bde7f776   wdenk   * Code cleanup:
887
  		/* get sequence number */
c670aeee3   Heinrich Schuchardt   common: rename ge...
888
  		new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
889
890
891
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
  		sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
892
  		n = untochar(new_char);
8bde7f776   wdenk   * Code cleanup:
893
894
895
896
897
898
899
900
901
902
903
904
  		--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...
905
  			k_data_restore();
8bde7f776   wdenk   * Code cleanup:
906
907
908
909
  		} else {
  			/* new sequence number, checkpoint the download */
  			last_n = n;
  			k_state_saved = k_state;
088f1b199   Kim Phillips   common/cmd_*.c: s...
910
  			k_data_save();
8bde7f776   wdenk   * Code cleanup:
911
912
913
914
  		}
  		/* END NEW CODE */
  
  		/* get packet type */
c670aeee3   Heinrich Schuchardt   common: rename ge...
915
  		new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
916
917
918
919
920
921
922
923
924
  		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 */
c670aeee3   Heinrich Schuchardt   common: rename ge...
925
  			new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
926
927
928
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
  			sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
929
  			len_hi = untochar(new_char);
c670aeee3   Heinrich Schuchardt   common: rename ge...
930
  			new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
931
932
933
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
  			sum += new_char & 0xff;
088f1b199   Kim Phillips   common/cmd_*.c: s...
934
  			len_lo = untochar(new_char);
8bde7f776   wdenk   * Code cleanup:
935
936
  			length = len_hi * 95 + len_lo;
  			/* check header checksum */
c670aeee3   Heinrich Schuchardt   common: rename ge...
937
  			new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
938
939
  			if ((new_char & 0xE0) == 0)
  				goto packet_error;
088f1b199   Kim Phillips   common/cmd_*.c: s...
940
  			if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
8bde7f776   wdenk   * Code cleanup:
941
942
943
944
945
946
  				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) {
c670aeee3   Heinrich Schuchardt   common: rename ge...
947
  			new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
  			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 */
c670aeee3   Heinrich Schuchardt   common: rename ge...
964
  		new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
965
966
  		if ((new_char & 0xE0) == 0)
  			goto packet_error;
088f1b199   Kim Phillips   common/cmd_*.c: s...
967
  		if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
8bde7f776   wdenk   * Code cleanup:
968
969
  			goto packet_error;
  		/* get END_CHAR */
c670aeee3   Heinrich Schuchardt   common: rename ge...
970
  		new_char = getchar();
8bde7f776   wdenk   * Code cleanup:
971
972
973
974
  		if (new_char != END_CHAR) {
  		  packet_error:
  			/* restore state machines */
  			k_state = k_state_saved;
088f1b199   Kim Phillips   common/cmd_*.c: s...
975
  			k_data_restore();
8bde7f776   wdenk   * Code cleanup:
976
  			/* send a negative acknowledge packet in */
088f1b199   Kim Phillips   common/cmd_*.c: s...
977
  			send_nack(n);
8bde7f776   wdenk   * Code cleanup:
978
979
  		} else if (k_state == SEND_TYPE) {
  			/* crack the protocol parms, build an appropriate ack packet */
088f1b199   Kim Phillips   common/cmd_*.c: s...
980
  			handle_send_packet(n);
8bde7f776   wdenk   * Code cleanup:
981
982
  		} else {
  			/* send simple acknowledge packet in */
088f1b199   Kim Phillips   common/cmd_*.c: s...
983
  			send_ack(n);
8bde7f776   wdenk   * Code cleanup:
984
985
986
987
  			/* quit if end of transmission */
  			if (k_state == BREAK_TYPE)
  				done = 1;
  		}
8bde7f776   wdenk   * Code cleanup:
988
989
990
  	}
  	return ((ulong) os_data_addr - (ulong) bin_start_address);
  }
f2841d377   Markus Klotzbuecher   Add support for y...
991
992
  
  static int getcxmodem(void) {
cf48eb9ab   Wolfgang Denk   Some code cleanup
993
  	if (tstc())
c670aeee3   Heinrich Schuchardt   common: rename ge...
994
  		return (getchar());
f2841d377   Markus Klotzbuecher   Add support for y...
995
996
  	return -1;
  }
6e66bd559   Angus Ainslie   Enable xmodem sup...
997
  static ulong load_serial_ymodem(ulong offset, int mode)
f2841d377   Markus Klotzbuecher   Add support for y...
998
999
  {
  	int size;
f2841d377   Markus Klotzbuecher   Add support for y...
1000
1001
1002
  	int err;
  	int res;
  	connection_info_t info;
cf48eb9ab   Wolfgang Denk   Some code cleanup
1003
1004
1005
  	char ymodemBuf[1024];
  	ulong store_addr = ~0;
  	ulong addr = 0;
f2841d377   Markus Klotzbuecher   Add support for y...
1006

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

081bd249d   Pali Rohár   xyz-modem: Proper...
1012
  		err = 0;
cf48eb9ab   Wolfgang Denk   Some code cleanup
1013
  		while ((res =
088f1b199   Kim Phillips   common/cmd_*.c: s...
1014
  			xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) {
cf48eb9ab   Wolfgang Denk   Some code cleanup
1015
1016
1017
  			store_addr = addr + offset;
  			size += res;
  			addr += res;
e856bdcfb   Masahiro Yamada   flash: complete C...
1018
  #ifdef CONFIG_MTD_NOR_FLASH
088f1b199   Kim Phillips   common/cmd_*.c: s...
1019
  			if (addr2info(store_addr)) {
cf48eb9ab   Wolfgang Denk   Some code cleanup
1020
  				int rc;
088f1b199   Kim Phillips   common/cmd_*.c: s...
1021
  				rc = flash_write((char *) ymodemBuf,
cf48eb9ab   Wolfgang Denk   Some code cleanup
1022
1023
  						  store_addr, res);
  				if (rc != 0) {
081bd249d   Pali Rohár   xyz-modem: Proper...
1024
1025
1026
1027
  					xyzModem_stream_terminate(true, &getcxmodem);
  					xyzModem_stream_close(&err);
  					printf("
  ");
0ee48252b   Simon Glass   common: Move flas...
1028
  					flash_perror(rc);
cf48eb9ab   Wolfgang Denk   Some code cleanup
1029
1030
1031
  					return (~0);
  				}
  			} else
f2841d377   Markus Klotzbuecher   Add support for y...
1032
  #endif
cf48eb9ab   Wolfgang Denk   Some code cleanup
1033
  			{
088f1b199   Kim Phillips   common/cmd_*.c: s...
1034
  				memcpy((char *)(store_addr), ymodemBuf,
cf48eb9ab   Wolfgang Denk   Some code cleanup
1035
1036
1037
1038
  					res);
  			}
  
  		}
081bd249d   Pali Rohár   xyz-modem: Proper...
1039
1040
1041
1042
1043
1044
1045
1046
  		if (err) {
  			xyzModem_stream_terminate((err == xyzModem_cancel) ? false : true, &getcxmodem);
  			xyzModem_stream_close(&err);
  			printf("
  %s
  ", xyzModem_error(err));
  			return (~0); /* Download aborted */
  		}
76b0a1902   Heinrich Schuchardt   cmd/load: support...
1047
1048
1049
  		if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
  			efi_set_bootdev("Uart", "", "",
  					map_sysmem(offset, 0), size);
cf48eb9ab   Wolfgang Denk   Some code cleanup
1050
  	} else {
081bd249d   Pali Rohár   xyz-modem: Proper...
1051
1052
1053
1054
  		printf("
  %s
  ", xyzModem_error(err));
  		return (~0); /* Download aborted */
f2841d377   Markus Klotzbuecher   Add support for y...
1055
  	}
cf48eb9ab   Wolfgang Denk   Some code cleanup
1056

088f1b199   Kim Phillips   common/cmd_*.c: s...
1057
  	xyzModem_stream_terminate(false, &getcxmodem);
1f26c49ea   Pali Rohár   xyz-modem: Close ...
1058
  	xyzModem_stream_close(&err);
f2841d377   Markus Klotzbuecher   Add support for y...
1059

0a6036da6   Chris Packham   cmd: load: align ...
1060
  	flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN));
f2841d377   Markus Klotzbuecher   Add support for y...
1061

088f1b199   Kim Phillips   common/cmd_*.c: s...
1062
1063
  	printf("## Total Size      = 0x%08x = %d Bytes
  ", size, size);
018f53032   Simon Glass   env: Rename commo...
1064
  	env_set_hex("filesize", size);
f2841d377   Markus Klotzbuecher   Add support for y...
1065
1066
1067
  
  	return offset;
  }
902531788   Jon Loeliger   common/: Remove l...
1068
  #endif
8bde7f776   wdenk   * Code cleanup:
1069
1070
  
  /* -------------------------------------------------------------------- */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1071
  #if defined(CONFIG_CMD_LOADS)
8bde7f776   wdenk   * Code cleanup:
1072

6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1073
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
0d4983930   wdenk   Patch by Kenneth ...
1074
1075
  U_BOOT_CMD(
  	loads, 3, 0,	do_load_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1076
  	"load S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1077
1078
1079
  	"[ off ] [ baud ]
  "
  	"    - load S-Record file over serial line"
a89c33db9   Wolfgang Denk   General help mess...
1080
  	" with offset 'off' and baudrate 'baud'"
8bde7f776   wdenk   * Code cleanup:
1081
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1082
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
0d4983930   wdenk   Patch by Kenneth ...
1083
1084
  U_BOOT_CMD(
  	loads, 2, 0,	do_load_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1085
  	"load S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1086
1087
  	"[ off ]
  "
a89c33db9   Wolfgang Denk   General help mess...
1088
  	"    - load S-Record file over serial line with offset 'off'"
8bde7f776   wdenk   * Code cleanup:
1089
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1090
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
8bde7f776   wdenk   * Code cleanup:
1091
1092
1093
1094
  
  /*
   * SAVES always requires LOADS support, but not vice versa
   */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1095
  #if defined(CONFIG_CMD_SAVES)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1096
  #ifdef	CONFIG_SYS_LOADS_BAUD_CHANGE
0d4983930   wdenk   Patch by Kenneth ...
1097
1098
  U_BOOT_CMD(
  	saves, 4, 0,	do_save_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1099
  	"save S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1100
1101
1102
  	"[ off ] [size] [ baud ]
  "
  	"    - save S-Record file over serial line"
a89c33db9   Wolfgang Denk   General help mess...
1103
  	" with offset 'off', size 'size' and baudrate 'baud'"
8bde7f776   wdenk   * Code cleanup:
1104
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1105
  #else	/* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
0d4983930   wdenk   Patch by Kenneth ...
1106
1107
  U_BOOT_CMD(
  	saves, 3, 0,	do_save_serial,
2fb2604d5   Peter Tyser   Command usage cle...
1108
  	"save S-Record file over serial line",
8bde7f776   wdenk   * Code cleanup:
1109
1110
  	"[ off ] [size]
  "
a89c33db9   Wolfgang Denk   General help mess...
1111
  	"    - save S-Record file over serial line with offset 'off' and size 'size'"
8bde7f776   wdenk   * Code cleanup:
1112
  );
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1113
  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */
70d7cb925   Robert P. J. Day   cmd_load.c: Add #...
1114
1115
  #endif	/* CONFIG_CMD_SAVES */
  #endif	/* CONFIG_CMD_LOADS */
8bde7f776   wdenk   * Code cleanup:
1116

c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1117
  #if defined(CONFIG_CMD_LOADB)
0d4983930   wdenk   Patch by Kenneth ...
1118
1119
  U_BOOT_CMD(
  	loadb, 3, 0,	do_load_serial_bin,
2fb2604d5   Peter Tyser   Command usage cle...
1120
  	"load binary file over serial line (kermit mode)",
b911208f4   Heinrich Schuchardt   cmd: correct long...
1121
1122
  	"[ addr [ baud ] ]
  "
8bde7f776   wdenk   * Code cleanup:
1123
  	"    - load binary file over serial line"
b911208f4   Heinrich Schuchardt   cmd: correct long...
1124
  	" at address 'addr' with baudrate 'baud'"
6e66bd559   Angus Ainslie   Enable xmodem sup...
1125
1126
1127
1128
1129
  );
  
  U_BOOT_CMD(
  	loadx, 3, 0,	do_load_serial_bin,
  	"load binary file over serial line (xmodem mode)",
b911208f4   Heinrich Schuchardt   cmd: correct long...
1130
1131
  	"[ addr [ baud ] ]
  "
6e66bd559   Angus Ainslie   Enable xmodem sup...
1132
  	"    - load binary file over serial line"
b911208f4   Heinrich Schuchardt   cmd: correct long...
1133
  	" at address 'addr' with baudrate 'baud'"
8bde7f776   wdenk   * Code cleanup:
1134
  );
f2841d377   Markus Klotzbuecher   Add support for y...
1135
1136
  U_BOOT_CMD(
  	loady, 3, 0,	do_load_serial_bin,
2fb2604d5   Peter Tyser   Command usage cle...
1137
  	"load binary file over serial line (ymodem mode)",
b911208f4   Heinrich Schuchardt   cmd: correct long...
1138
1139
  	"[ addr [ baud ] ]
  "
f2841d377   Markus Klotzbuecher   Add support for y...
1140
  	"    - load binary file over serial line"
b911208f4   Heinrich Schuchardt   cmd: correct long...
1141
  	" at address 'addr' with baudrate 'baud'"
f2841d377   Markus Klotzbuecher   Add support for y...
1142
  );
70d7cb925   Robert P. J. Day   cmd_load.c: Add #...
1143
  #endif	/* CONFIG_CMD_LOADB */