]>
git.ipfire.org Git - people/ms/u-boot.git/blob - common/cmd_boot.c
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 #include <cmd_autoscript.h>
36 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)
37 static ulong
load_serial (ulong offset
);
38 static int read_record (char *buf
, ulong len
);
39 # if (CONFIG_COMMANDS & CFG_CMD_SAVES)
40 static int save_serial (ulong offset
, ulong size
);
41 static int write_record (char *buf
);
42 # endif /* CFG_CMD_SAVES */
44 static int do_echo
= 1;
45 #endif /* CFG_CMD_LOADS */
48 #if (CONFIG_COMMANDS & CFG_CMD_BDI)
49 static void print_num(const char *, ulong
);
51 #ifndef CONFIG_ARM /* PowerPC and other */
54 static void print_str(const char *, const char *);
56 int do_bdinfo ( cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
58 DECLARE_GLOBAL_DATA_PTR
;
65 print_num ("bd address", (ulong
)bd
);
67 print_num ("memstart", bd
->bi_memstart
);
68 print_num ("memsize", bd
->bi_memsize
);
69 print_num ("flashstart", bd
->bi_flashstart
);
70 print_num ("flashsize", bd
->bi_flashsize
);
71 print_num ("flashoffset", bd
->bi_flashoffset
);
72 print_num ("sramstart", bd
->bi_sramstart
);
73 print_num ("sramsize", bd
->bi_sramsize
);
74 #if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260)
75 print_num ("immr_base", bd
->bi_immr_base
);
77 print_num ("bootflags", bd
->bi_bootflags
);
78 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP)
79 print_str ("procfreq", strmhz(buf
, bd
->bi_procfreq
));
80 print_str ("plb_busfreq", strmhz(buf
, bd
->bi_plb_busfreq
));
81 #if defined(CONFIG_405GP) || defined(CONFIG_405EP)
82 print_str ("pci_busfreq", strmhz(buf
, bd
->bi_pci_busfreq
));
85 #if defined(CONFIG_8260)
86 print_str ("vco", strmhz(buf
, bd
->bi_vco
));
87 print_str ("sccfreq", strmhz(buf
, bd
->bi_sccfreq
));
88 print_str ("brgfreq", strmhz(buf
, bd
->bi_brgfreq
));
90 print_str ("intfreq", strmhz(buf
, bd
->bi_intfreq
));
91 #if defined(CONFIG_8260)
92 print_str ("cpmfreq", strmhz(buf
, bd
->bi_cpmfreq
));
94 print_str ("busfreq", strmhz(buf
, bd
->bi_busfreq
));
95 #endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
98 printf ("%c%02X", i
? ':' : ' ', bd
->bi_enetaddr
[i
]);
101 printf ("\neth1addr =");
102 for (i
=0; i
<6; ++i
) {
103 printf ("%c%02X", i
? ':' : ' ', bd
->bi_enet1addr
[i
]);
105 #endif /* CONFIG_PN62 */
107 print_str ("ethspeed", strmhz(buf
, bd
->bi_ethspeed
));
109 printf ("\nIP addr = "); print_IPaddr (bd
->bi_ip_addr
);
110 printf ("\nbaudrate = %6ld bps\n", bd
->bi_baudrate
);
116 int do_bdinfo ( cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
118 DECLARE_GLOBAL_DATA_PTR
;
123 print_num ("boot_params", (ulong
)bd
->bi_boot_params
);
124 print_num ("memstart", (ulong
)bd
->bi_memstart
);
125 print_num ("memsize", (ulong
)bd
->bi_memsize
);
126 print_num ("flashstart", (ulong
)bd
->bi_flashstart
);
127 print_num ("flashsize", (ulong
)bd
->bi_flashsize
);
128 print_num ("flashoffset", (ulong
)bd
->bi_flashoffset
);
130 printf ("ethaddr =");
131 for (i
=0; i
<6; ++i
) {
132 printf ("%c%02X", i
? ':' : ' ', bd
->bi_enetaddr
[i
]);
134 printf ("\nip_addr = ");
135 print_IPaddr (bd
->bi_ip_addr
);
136 printf ("\nbaudrate = %d bps\n", bd
->bi_baudrate
);
144 int do_bdinfo ( cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
146 DECLARE_GLOBAL_DATA_PTR
;
151 print_num ("arch_number", bd
->bi_arch_number
);
152 print_num ("env_t", (ulong
)bd
->bi_env
);
153 print_num ("boot_params", (ulong
)bd
->bi_boot_params
);
155 for (i
=0; i
<CONFIG_NR_DRAM_BANKS
; ++i
) {
156 print_num("DRAM bank", i
);
157 print_num("-> start", bd
->bi_dram
[i
].start
);
158 print_num("-> size", bd
->bi_dram
[i
].size
);
161 printf ("ethaddr =");
162 for (i
=0; i
<6; ++i
) {
163 printf ("%c%02X", i
? ':' : ' ', bd
->bi_enetaddr
[i
]);
167 print_IPaddr (bd
->bi_ip_addr
);
169 "baudrate = %d bps\n", bd
->bi_baudrate
);
174 #endif /* CONFIG_ARM XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
176 static void print_num(const char *name
, ulong value
)
178 printf ("%-12s= 0x%08lX\n", name
, value
);
182 static void print_str(const char *name
, const char *str
)
184 printf ("%-12s= %6s MHz\n", name
, str
);
186 #endif /* CONFIG_PPC */
188 #endif /* CFG_CMD_BDI */
190 int do_go (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
196 printf ("Usage:\n%s\n", cmdtp
->usage
);
200 addr
= simple_strtoul(argv
[1], NULL
, 16);
202 printf ("## Starting application at 0x%08lX ...\n", addr
);
205 * pass address parameter as argv[0] (aka command name),
206 * and all remaining args
208 rc
= ((ulong (*)(int, char *[]))addr
) (--argc
, &argv
[1]);
209 if (rc
!= 0) rcode
= 1;
211 printf ("## Application terminated, rc = 0x%lX\n", rc
);
215 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)
216 int do_load_serial (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
223 #ifdef CFG_LOADS_BAUD_CHANGE
224 DECLARE_GLOBAL_DATA_PTR
;
225 int load_baudrate
, current_baudrate
;
227 load_baudrate
= current_baudrate
= gd
->baudrate
;
230 if (((env_echo
= getenv("loads_echo")) != NULL
) && (*env_echo
== '1')) {
236 #ifdef CFG_LOADS_BAUD_CHANGE
238 offset
= simple_strtoul(argv
[1], NULL
, 16);
241 load_baudrate
= (int)simple_strtoul(argv
[2], NULL
, 10);
243 /* default to current baudrate */
244 if (load_baudrate
== 0)
245 load_baudrate
= current_baudrate
;
247 #else /* ! CFG_LOADS_BAUD_CHANGE */
249 offset
= simple_strtoul(argv
[1], NULL
, 16);
251 #endif /* CFG_LOADS_BAUD_CHANGE */
253 #ifdef CFG_LOADS_BAUD_CHANGE
254 if (load_baudrate
!= current_baudrate
) {
255 printf ("## Switch baudrate to %d bps and press ENTER ...\n",
258 gd
->baudrate
= load_baudrate
;
266 #endif /* CFG_LOADS_BAUD_CHANGE */
267 printf ("## Ready for S-Record download ...\n");
269 addr
= load_serial (offset
);
272 * Gather any trailing characters (for instance, the ^D which
273 * is sent by 'cu' after sending a file), and give the
274 * box some time (100 * 1 ms)
276 for (i
=0; i
<100; ++i
) {
278 (void) serial_getc();
284 printf ("## S-Record download aborted\n");
287 printf ("## Start Addr = 0x%08lX\n", addr
);
291 #ifdef CFG_LOADS_BAUD_CHANGE
292 if (load_baudrate
!= current_baudrate
) {
293 printf ("## Switch baudrate to %d bps and press ESC ...\n",
296 gd
->baudrate
= current_baudrate
;
300 if (getc() == 0x1B) /* ESC */
309 load_serial (ulong offset
)
311 char record
[SREC_MAXRECLEN
+ 1]; /* buffer for one S-Record */
312 char binbuf
[SREC_MAXBINLEN
]; /* buffer for binary data */
313 int binlen
; /* no. of data bytes in S-Rec. */
314 int type
; /* return code for record type */
315 ulong addr
; /* load address from S-Record */
316 ulong size
; /* number of bytes transferred */
319 ulong start_addr
= ~0;
323 while (read_record(record
, SREC_MAXRECLEN
+ 1) >= 0) {
324 type
= srec_decode (record
, &binlen
, &addr
, binbuf
);
327 return (~0); /* Invalid S-Record */
334 store_addr
= addr
+ offset
;
336 if (addr2info(store_addr
)) {
339 rc
= flash_write((uchar
*)binbuf
,store_addr
,binlen
);
347 memcpy ((char *)(store_addr
), binbuf
, binlen
);
349 if ((store_addr
) < start_addr
)
350 start_addr
= store_addr
;
351 if ((store_addr
+ binlen
- 1) > end_addr
)
352 end_addr
= store_addr
+ binlen
- 1;
358 size
= end_addr
- start_addr
+ 1;
360 "## First Load Addr = 0x%08lX\n"
361 "## Last Load Addr = 0x%08lX\n"
362 "## Total Size = 0x%08lX = %ld Bytes\n",
363 start_addr
, end_addr
, size
, size
365 flush_cache (addr
, size
);
366 sprintf(buf
, "%lX", size
);
367 setenv("filesize", buf
);
374 if (!do_echo
) { /* print a '.' every 100 lines */
375 if ((++line_count
% 100) == 0)
380 return (~0); /* Download aborted */
384 read_record (char *buf
, ulong len
)
389 --len
; /* always leave room for terminating '\0' byte */
391 for (p
=buf
; p
< buf
+len
; ++p
) {
392 c
= serial_getc(); /* read character */
394 serial_putc (c
); /* ... and echo it */
402 case 0x03: /* ^C - Control C */
408 /* Check for the console hangup (if any different from serial) */
409 #ifdef CONFIG_PPC /* we don't have syscall_tbl anywhere else */
410 if (syscall_tbl
[SYSCALL_GETC
] != serial_getc
) {
418 /* line too long - truncate */
423 #if (CONFIG_COMMANDS & CFG_CMD_SAVES)
425 int do_save_serial (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
429 #ifdef CFG_LOADS_BAUD_CHANGE
430 DECLARE_GLOBAL_DATA_PTR
;
431 int save_baudrate
, current_baudrate
;
433 save_baudrate
= current_baudrate
= gd
->baudrate
;
437 offset
= simple_strtoul(argv
[1], NULL
, 16);
439 #ifdef CFG_LOADS_BAUD_CHANGE
441 size
= simple_strtoul(argv
[2], NULL
, 16);
444 save_baudrate
= (int)simple_strtoul(argv
[3], NULL
, 10);
446 /* default to current baudrate */
447 if (save_baudrate
== 0)
448 save_baudrate
= current_baudrate
;
450 #else /* ! CFG_LOADS_BAUD_CHANGE */
452 size
= simple_strtoul(argv
[2], NULL
, 16);
454 #endif /* CFG_LOADS_BAUD_CHANGE */
456 #ifdef CFG_LOADS_BAUD_CHANGE
457 if (save_baudrate
!= current_baudrate
) {
458 printf ("## Switch baudrate to %d bps and press ENTER ...\n",
461 gd
->baudrate
= save_baudrate
;
469 #endif /* CFG_LOADS_BAUD_CHANGE */
470 printf ("## Ready for S-Record upload, press ENTER to proceed ...\n");
475 if(save_serial (offset
, size
)) {
476 printf ("## S-Record upload aborted\n");
478 printf ("## S-Record upload complete\n");
480 #ifdef CFG_LOADS_BAUD_CHANGE
481 if (save_baudrate
!= current_baudrate
) {
482 printf ("## Switch baudrate to %d bps and press ESC ...\n",
483 (int)current_baudrate
);
485 gd
->baudrate
= current_baudrate
;
489 if (getc() == 0x1B) /* ESC */
497 #define SREC3_START "S0030000FC\n"
498 #define SREC3_FORMAT "S3%02X%08lX%s%02X\n"
499 #define SREC3_END "S70500000000FA\n"
500 #define SREC_BYTES_PER_RECORD 16
502 static int save_serial (ulong address
, ulong count
)
504 int i
, c
, reclen
, checksum
, length
;
505 char *hex
= "0123456789ABCDEF";
506 char record
[2*SREC_BYTES_PER_RECORD
+16]; /* buffer for one S-Record */
507 char data
[2*SREC_BYTES_PER_RECORD
+1]; /* buffer for hex data */
512 if(write_record(SREC3_START
)) /* write the header */
515 if(count
) { /* collect hex data in the buffer */
516 c
= *(volatile uchar
*)(address
+ reclen
); /* get one byte */
517 checksum
+= c
; /* accumulate checksum */
518 data
[2*reclen
] = hex
[(c
>>4)&0x0f];
519 data
[2*reclen
+1] = hex
[c
& 0x0f];
520 data
[2*reclen
+2] = '\0';
524 if(reclen
== SREC_BYTES_PER_RECORD
|| count
== 0) {
525 /* enough data collected for one record: dump it */
526 if(reclen
) { /* build & write a data record: */
527 /* address + data + checksum */
528 length
= 4 + reclen
+ 1;
530 /* accumulate length bytes into checksum */
531 for(i
= 0; i
< 2; i
++)
532 checksum
+= (length
>> (8*i
)) & 0xff;
534 /* accumulate address bytes into checksum: */
535 for(i
= 0; i
< 4; i
++)
536 checksum
+= (address
>> (8*i
)) & 0xff;
538 /* make proper checksum byte: */
539 checksum
= ~checksum
& 0xff;
541 /* output one record: */
542 sprintf(record
, SREC3_FORMAT
, length
, address
, data
, checksum
);
543 if(write_record(record
))
546 address
+= reclen
; /* increment address */
552 if(write_record(SREC3_END
)) /* write the final record */
558 write_record (char *buf
)
565 /* Check for the console hangup (if any different from serial) */
572 # endif /* CFG_CMD_SAVES */
574 #endif /* CFG_CMD_LOADS */
577 #if (CONFIG_COMMANDS & CFG_CMD_LOADB) /* loadb command (load binary) included */
581 #define START_CHAR 0x01
582 #define ETX_CHAR 0x03
583 #define END_CHAR 0x0D
585 #define K_ESCAPE 0x23
586 #define SEND_TYPE 'S'
587 #define DATA_TYPE 'D'
589 #define NACK_TYPE 'N'
590 #define BREAK_TYPE 'B'
591 #define tochar(x) ((char) (((x) + SPACE) & 0xff))
592 #define untochar(x) ((int) (((x) - SPACE) & 0xff))
594 extern int os_data_count
;
595 extern int os_data_header
[8];
597 static void set_kerm_bin_mode(unsigned long *);
598 static int k_recv(void);
599 static ulong
load_serial_bin (ulong offset
);
602 char his_eol
; /* character he needs at end of packet */
603 int his_pad_count
; /* number of pad chars he needs */
604 char his_pad_char
; /* pad chars he needs */
605 char his_quote
; /* quote chars he'll use */
607 int do_load_serial_bin (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
609 DECLARE_GLOBAL_DATA_PTR
;
613 int load_baudrate
, current_baudrate
;
617 /* pre-set offset from CFG_LOAD_ADDR */
618 offset
= CFG_LOAD_ADDR
;
620 /* pre-set offset from $loadaddr */
621 if ((s
= getenv("loadaddr")) != NULL
) {
622 offset
= simple_strtoul(s
, NULL
, 16);
625 load_baudrate
= current_baudrate
= gd
->baudrate
;
628 offset
= simple_strtoul(argv
[1], NULL
, 16);
631 load_baudrate
= (int)simple_strtoul(argv
[2], NULL
, 10);
633 /* default to current baudrate */
634 if (load_baudrate
== 0)
635 load_baudrate
= current_baudrate
;
638 if (load_baudrate
!= current_baudrate
) {
639 printf ("## Switch baudrate to %d bps and press ENTER ...\n",
642 gd
->baudrate
= load_baudrate
;
651 printf ("## Ready for binary (kermit) download "
652 "to 0x%08lX at %d bps...\n",
655 addr
= load_serial_bin (offset
);
659 printf ("## Binary (kermit) download aborted\n");
662 printf ("## Start Addr = 0x%08lX\n", addr
);
666 if (load_baudrate
!= current_baudrate
) {
667 printf ("## Switch baudrate to %d bps and press ESC ...\n",
670 gd
->baudrate
= current_baudrate
;
674 if (getc() == 0x1B) /* ESC */
679 #ifdef CONFIG_AUTOSCRIPT
683 if (((s
= getenv("autoscript")) != NULL
) && (strcmp(s
,"yes") == 0)) {
684 printf("Running autoscript at addr 0x%08lX ...\n", load_addr
);
685 rcode
= autoscript (load_addr
);
693 static ulong
load_serial_bin (ulong offset
)
698 set_kerm_bin_mode ((ulong
*) offset
);
702 * Gather any trailing characters (for instance, the ^D which
703 * is sent by 'cu' after sending a file), and give the
704 * box some time (100 * 1 ms)
706 for (i
=0; i
<100; ++i
) {
708 (void) serial_getc();
713 flush_cache (offset
, size
);
715 printf("## Total Size = 0x%08x = %d Bytes\n", size
, size
);
716 sprintf(buf
, "%X", size
);
717 setenv("filesize", buf
);
724 int count
= his_pad_count
;
727 serial_putc (his_pad_char
);
730 /* converts escaped kermit char to binary char */
731 char ktrans (char in
)
733 if ((in
& 0x60) == 0x40) {
734 return (char) (in
& ~0x40);
735 } else if ((in
& 0x7f) == 0x3f) {
736 return (char) (in
| 0x40);
741 int chk1 (char *buffer
)
748 return (int) ((total
+ ((total
>> 6) & 0x03)) & 0x3f);
751 void s1_sendpacket (char *packet
)
755 serial_putc (*packet
++);
760 void send_ack (int n
)
767 a_b
[4] = tochar (chk1 (&a_b
[1]));
773 void send_nack (int n
)
780 a_b
[4] = tochar (chk1 (&a_b
[1]));
788 /* os_data_* takes an OS Open image and puts it into memory, and
789 puts the boot header in an array named os_data_header
791 if image is binary, no header is stored in os_data_header.
793 void (*os_data_init
) (void);
794 void (*os_data_char
) (char new_char
);
795 static int os_data_state
, os_data_state_saved
;
797 static int os_data_count_saved
;
798 static char *os_data_addr
, *os_data_addr_saved
;
799 static char *bin_start_address
;
800 int os_data_header
[8];
801 static void bin_data_init (void)
805 os_data_addr
= bin_start_address
;
807 static void os_data_save (void)
809 os_data_state_saved
= os_data_state
;
810 os_data_count_saved
= os_data_count
;
811 os_data_addr_saved
= os_data_addr
;
813 static void os_data_restore (void)
815 os_data_state
= os_data_state_saved
;
816 os_data_count
= os_data_count_saved
;
817 os_data_addr
= os_data_addr_saved
;
819 static void bin_data_char (char new_char
)
821 switch (os_data_state
) {
823 *os_data_addr
++ = new_char
;
828 static void set_kerm_bin_mode (unsigned long *addr
)
830 bin_start_address
= (char *) addr
;
831 os_data_init
= bin_data_init
;
832 os_data_char
= bin_data_char
;
836 /* k_data_* simply handles the kermit escape translations */
837 static int k_data_escape
, k_data_escape_saved
;
838 void k_data_init (void)
843 void k_data_save (void)
845 k_data_escape_saved
= k_data_escape
;
848 void k_data_restore (void)
850 k_data_escape
= k_data_escape_saved
;
853 void k_data_char (char new_char
)
856 /* last char was escape - translate this character */
857 os_data_char (ktrans (new_char
));
860 if (new_char
== his_quote
) {
861 /* this char is escape - remember */
864 /* otherwise send this char as-is */
865 os_data_char (new_char
);
870 #define SEND_DATA_SIZE 20
871 char send_parms
[SEND_DATA_SIZE
];
874 /* handle_send_packet interprits the protocol info and builds and
875 sends an appropriate ack for what we can do */
876 void handle_send_packet (int n
)
881 /* initialize some protocol parameters */
882 his_eol
= END_CHAR
; /* default end of line character */
885 his_quote
= K_ESCAPE
;
887 /* ignore last character if it filled the buffer */
888 if (send_ptr
== &send_parms
[SEND_DATA_SIZE
- 1])
890 bytes
= send_ptr
- send_parms
; /* how many bytes we'll process */
894 /* handle MAXL - max length */
895 /* ignore what he says - most I'll take (here) is 94 */
896 a_b
[++length
] = tochar (94);
899 /* handle TIME - time you should wait for my packets */
900 /* ignore what he says - don't wait for my ack longer than 1 second */
901 a_b
[++length
] = tochar (1);
904 /* handle NPAD - number of pad chars I need */
905 /* remember what he says - I need none */
906 his_pad_count
= untochar (send_parms
[2]);
907 a_b
[++length
] = tochar (0);
910 /* handle PADC - pad chars I need */
911 /* remember what he says - I need none */
912 his_pad_char
= ktrans (send_parms
[3]);
913 a_b
[++length
] = 0x40; /* He should ignore this */
916 /* handle EOL - end of line he needs */
917 /* remember what he says - I need CR */
918 his_eol
= untochar (send_parms
[4]);
919 a_b
[++length
] = tochar (END_CHAR
);
922 /* handle QCTL - quote control char he'll use */
923 /* remember what he says - I'll use '#' */
924 his_quote
= send_parms
[5];
928 /* handle QBIN - 8-th bit prefixing */
929 /* ignore what he says - I refuse */
933 /* handle CHKT - the clock check type */
934 /* ignore what he says - I do type 1 (for now) */
938 /* handle REPT - the repeat prefix */
939 /* ignore what he says - I refuse (for now) */
943 /* handle CAPAS - the capabilities mask */
944 /* ignore what he says - I only do long packets - I don't do windows */
945 a_b
[++length
] = tochar (2); /* only long packets */
946 a_b
[++length
] = tochar (0); /* no windows */
947 a_b
[++length
] = tochar (94); /* large packet msb */
948 a_b
[++length
] = tochar (94); /* large packet lsb */
952 a_b
[1] = tochar (length
);
955 a_b
[++length
] = '\0';
956 a_b
[length
] = tochar (chk1 (&a_b
[1]));
957 a_b
[++length
] = his_eol
;
958 a_b
[++length
] = '\0';
962 /* k_recv receives a OS Open image file over kermit line */
963 static int k_recv (void)
966 char k_state
, k_state_saved
;
974 /* initialize some protocol parameters */
975 his_eol
= END_CHAR
; /* default end of line character */
978 his_quote
= K_ESCAPE
;
980 /* initialize the k_recv and k_data state machine */
984 k_state_saved
= k_state
;
986 n
= 0; /* just to get rid of a warning */
989 /* expect this "type" sequence (but don't check):
994 B: break transmission
997 /* enter main loop */
999 /* set the send packet pointer to begining of send packet parms */
1000 send_ptr
= send_parms
;
1002 /* With each packet, start summing the bytes starting with the length.
1003 Save the current sequence number.
1004 Note the type of the packet.
1005 If a character less than SPACE (0x20) is received - error.
1009 /* OLD CODE, Prior to checking sequence numbers */
1010 /* first have all state machines save current states */
1011 k_state_saved
= k_state
;
1016 /* wait for the starting character or ^C */
1018 switch (serial_getc ()) {
1019 case START_CHAR
: /* start packet */
1021 case ETX_CHAR
: /* ^C waiting for packet */
1028 /* get length of packet */
1030 new_char
= serial_getc ();
1031 if ((new_char
& 0xE0) == 0)
1033 sum
+= new_char
& 0xff;
1034 length
= untochar (new_char
);
1035 /* get sequence number */
1036 new_char
= serial_getc ();
1037 if ((new_char
& 0xE0) == 0)
1039 sum
+= new_char
& 0xff;
1040 n
= untochar (new_char
);
1043 /* NEW CODE - check sequence numbers for retried packets */
1044 /* Note - this new code assumes that the sequence number is correctly
1045 * received. Handling an invalid sequence number adds another layer
1046 * of complexity that may not be needed - yet! At this time, I'm hoping
1047 * that I don't need to buffer the incoming data packets and can write
1048 * the data into memory in real time.
1051 /* same sequence number, restore the previous state */
1052 k_state
= k_state_saved
;
1055 /* new sequence number, checkpoint the download */
1057 k_state_saved
= k_state
;
1062 /* get packet type */
1063 new_char
= serial_getc ();
1064 if ((new_char
& 0xE0) == 0)
1066 sum
+= new_char
& 0xff;
1069 /* check for extended length */
1071 /* (length byte was 0, decremented twice) */
1072 /* get the two length bytes */
1073 new_char
= serial_getc ();
1074 if ((new_char
& 0xE0) == 0)
1076 sum
+= new_char
& 0xff;
1077 len_hi
= untochar (new_char
);
1078 new_char
= serial_getc ();
1079 if ((new_char
& 0xE0) == 0)
1081 sum
+= new_char
& 0xff;
1082 len_lo
= untochar (new_char
);
1083 length
= len_hi
* 95 + len_lo
;
1084 /* check header checksum */
1085 new_char
= serial_getc ();
1086 if ((new_char
& 0xE0) == 0)
1088 if (new_char
!= tochar ((sum
+ ((sum
>> 6) & 0x03)) & 0x3f))
1090 sum
+= new_char
& 0xff;
1091 /* --length; */ /* new length includes only data and block check to come */
1093 /* bring in rest of packet */
1094 while (length
> 1) {
1095 new_char
= serial_getc ();
1096 if ((new_char
& 0xE0) == 0)
1098 sum
+= new_char
& 0xff;
1100 if (k_state
== DATA_TYPE
) {
1101 /* pass on the data if this is a data packet */
1102 k_data_char (new_char
);
1103 } else if (k_state
== SEND_TYPE
) {
1104 /* save send pack in buffer as is */
1105 *send_ptr
++ = new_char
;
1106 /* if too much data, back off the pointer */
1107 if (send_ptr
>= &send_parms
[SEND_DATA_SIZE
])
1111 /* get and validate checksum character */
1112 new_char
= serial_getc ();
1113 if ((new_char
& 0xE0) == 0)
1115 if (new_char
!= tochar ((sum
+ ((sum
>> 6) & 0x03)) & 0x3f))
1118 new_char
= serial_getc ();
1119 if (new_char
!= END_CHAR
) {
1121 /* restore state machines */
1122 k_state
= k_state_saved
;
1124 /* send a negative acknowledge packet in */
1126 } else if (k_state
== SEND_TYPE
) {
1127 /* crack the protocol parms, build an appropriate ack packet */
1128 handle_send_packet (n
);
1130 /* send simple acknowledge packet in */
1132 /* quit if end of transmission */
1133 if (k_state
== BREAK_TYPE
)
1138 return ((ulong
) os_data_addr
- (ulong
) bin_start_address
);
1140 #endif /* CFG_CMD_LOADB */
1141 #if (CONFIG_COMMANDS & CFG_CMD_HWFLOW)
1142 int do_hwflow (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[])
1144 extern int hwflow_onoff(int);
1147 if (strcmp(argv
[1], "off") == 0)
1150 if (strcmp(argv
[1], "on") == 0)
1153 printf("Usage: %s\n", cmdtp
->usage
);
1155 printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off");
1158 #endif /* CFG_CMD_HWFLOW */