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