load.c 25 KB

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