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