cmd_load.c 26 KB

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