tools: kwboot: Check whether baudrate was set to requested value
[platform/kernel/u-boot.git] / tools / kwboot.c
1 /*
2  * Boot a Marvell SoC, with Xmodem over UART0.
3  *  supports Kirkwood, Dove, Armada 370, Armada XP
4  *
5  * (c) 2012 Daniel Stodden <daniel.stodden@gmail.com>
6  *
7  * References: marvell.com, "88F6180, 88F6190, 88F6192, and 88F6281
8  *   Integrated Controller: Functional Specifications" December 2,
9  *   2008. Chapter 24.2 "BootROM Firmware".
10  */
11
12 #include "kwbimage.h"
13 #include "mkimage.h"
14 #include "version.h"
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdarg.h>
20 #include <image.h>
21 #include <libgen.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <stdint.h>
26 #include <time.h>
27 #include <sys/stat.h>
28
29 #ifdef __linux__
30 #include "termios_linux.h"
31 #else
32 #include <termios.h>
33 #endif
34
35 /*
36  * Marvell BootROM UART Sensing
37  */
38
39 static unsigned char kwboot_msg_boot[] = {
40         0xBB, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
41 };
42
43 static unsigned char kwboot_msg_debug[] = {
44         0xDD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
45 };
46
47 /* Defines known to work on Kirkwood */
48 #define KWBOOT_MSG_REQ_DELAY    10 /* ms */
49 #define KWBOOT_MSG_RSP_TIMEO    50 /* ms */
50
51 /* Defines known to work on Armada XP */
52 #define KWBOOT_MSG_REQ_DELAY_AXP        1000 /* ms */
53 #define KWBOOT_MSG_RSP_TIMEO_AXP        1000 /* ms */
54
55 /*
56  * Xmodem Transfers
57  */
58
59 #define SOH     1       /* sender start of block header */
60 #define EOT     4       /* sender end of block transfer */
61 #define ACK     6       /* target block ack */
62 #define NAK     21      /* target block negative ack */
63 #define CAN     24      /* target/sender transfer cancellation */
64
65 #define KWBOOT_XM_BLKSZ 128 /* xmodem block size */
66
67 struct kwboot_block {
68         uint8_t soh;
69         uint8_t pnum;
70         uint8_t _pnum;
71         uint8_t data[KWBOOT_XM_BLKSZ];
72         uint8_t csum;
73 } __packed;
74
75 #define KWBOOT_BLK_RSP_TIMEO 1000 /* ms */
76 #define KWBOOT_HDR_RSP_TIMEO 10000 /* ms */
77
78 /* ARM code making baudrate changing function return to original exec address */
79 static unsigned char kwboot_pre_baud_code[] = {
80                                 /* exec_addr:                                 */
81         0x00, 0x00, 0x00, 0x00, /* .word 0                                    */
82         0x0c, 0xe0, 0x1f, 0xe5, /* ldr lr, exec_addr                          */
83 };
84
85 /* ARM code for binary header injection to change baudrate */
86 static unsigned char kwboot_baud_code[] = {
87                                 /* ; #define UART_BASE 0xd0012000             */
88                                 /* ; #define THR       0x00                   */
89                                 /* ; #define DLL       0x00                   */
90                                 /* ; #define DLH       0x04                   */
91                                 /* ; #define LCR       0x0c                   */
92                                 /* ; #define   DLAB    0x80                   */
93                                 /* ; #define LSR       0x14                   */
94                                 /* ; #define   THRE    0x20                   */
95                                 /* ; #define   TEMT    0x40                   */
96                                 /* ; #define DIV_ROUND(a, b) ((a + b/2) / b)  */
97                                 /* ;                                          */
98                                 /* ; u32 set_baudrate(u32 old_b, u32 new_b) { */
99                                 /* ;   const u8 *str = "$baudratechange";     */
100                                 /* ;   u8 c;                                  */
101                                 /* ;   do {                                   */
102                                 /* ;       c = *str++;                        */
103                                 /* ;       writel(UART_BASE + THR, c);        */
104                                 /* ;   } while (c);                           */
105                                 /* ;   while                                  */
106                                 /* ;      (!(readl(UART_BASE + LSR) & TEMT)); */
107                                 /* ;   u32 lcr = readl(UART_BASE + LCR);      */
108                                 /* ;   writel(UART_BASE + LCR, lcr | DLAB);   */
109                                 /* ;   u8 old_dll = readl(UART_BASE + DLL);   */
110                                 /* ;   u8 old_dlh = readl(UART_BASE + DLH);   */
111                                 /* ;   u16 old_dl = old_dll | (old_dlh << 8); */
112                                 /* ;   u32 clk = old_b * old_dl;              */
113                                 /* ;   u16 new_dl = DIV_ROUND(clk, new_b);    */
114                                 /* ;   u8 new_dll = new_dl & 0xff;            */
115                                 /* ;   u8 new_dlh = (new_dl >> 8) & 0xff;     */
116                                 /* ;   writel(UART_BASE + DLL, new_dll);      */
117                                 /* ;   writel(UART_BASE + DLH, new_dlh);      */
118                                 /* ;   writel(UART_BASE + LCR, lcr & ~DLAB);  */
119                                 /* ;   msleep(1);                             */
120                                 /* ;   return 0;                              */
121                                 /* ; }                                        */
122
123         0xfe, 0x5f, 0x2d, 0xe9, /* push  { r1 - r12, lr }                     */
124
125                                 /*  ; r0 = UART_BASE                          */
126         0x02, 0x0a, 0xa0, 0xe3, /* mov   r0, #0x2000                          */
127         0x01, 0x00, 0x4d, 0xe3, /* movt  r0, #0xd001                          */
128
129                                 /*  ; r2 = address of preamble string         */
130         0xd0, 0x20, 0x8f, 0xe2, /* adr   r2, preamble                         */
131
132                                 /*  ; Send preamble string over UART          */
133                                 /* .Lloop_preamble:                           */
134                                 /*                                            */
135                                 /*  ; Wait until Transmitter Holding is Empty */
136                                 /* .Lloop_thre:                               */
137                                 /*  ; r1 = UART_BASE[LSR] & THRE              */
138         0x14, 0x10, 0x90, 0xe5, /* ldr   r1, [r0, #0x14]                      */
139         0x20, 0x00, 0x11, 0xe3, /* tst   r1, #0x20                            */
140         0xfc, 0xff, 0xff, 0x0a, /* beq   .Lloop_thre                          */
141
142                                 /*  ; Put character into Transmitter FIFO     */
143                                 /*  ; r1 = *r2++                              */
144         0x01, 0x10, 0xd2, 0xe4, /* ldrb  r1, [r2], #1                         */
145                                 /*  ; UART_BASE[THR] = r1                     */
146         0x00, 0x10, 0x80, 0xe5, /* str   r1, [r0, #0x0]                       */
147
148                                 /*  ; Loop until end of preamble string       */
149         0x00, 0x00, 0x51, 0xe3, /* cmp   r1, #0                               */
150         0xf8, 0xff, 0xff, 0x1a, /* bne   .Lloop_preamble                      */
151
152                                 /*  ; Wait until Transmitter FIFO is Empty    */
153                                 /* .Lloop_txempty:                            */
154                                 /*  ; r1 = UART_BASE[LSR] & TEMT              */
155         0x14, 0x10, 0x90, 0xe5, /* ldr   r1, [r0, #0x14]                      */
156         0x40, 0x00, 0x11, 0xe3, /* tst   r1, #0x40                            */
157         0xfc, 0xff, 0xff, 0x0a, /* beq   .Lloop_txempty                       */
158
159                                 /*  ; Set Divisor Latch Access Bit            */
160                                 /*  ; UART_BASE[LCR] |= DLAB                  */
161         0x0c, 0x10, 0x90, 0xe5, /* ldr   r1, [r0, #0x0c]                      */
162         0x80, 0x10, 0x81, 0xe3, /* orr   r1, r1, #0x80                        */
163         0x0c, 0x10, 0x80, 0xe5, /* str   r1, [r0, #0x0c]                      */
164
165                                 /*  ; Read current Divisor Latch              */
166                                 /*  ; r1 = UART_BASE[DLH]<<8 | UART_BASE[DLL] */
167         0x00, 0x10, 0x90, 0xe5, /* ldr   r1, [r0, #0x00]                      */
168         0xff, 0x10, 0x01, 0xe2, /* and   r1, r1, #0xff                        */
169         0x01, 0x20, 0xa0, 0xe1, /* mov   r2, r1                               */
170         0x04, 0x10, 0x90, 0xe5, /* ldr   r1, [r0, #0x04]                      */
171         0xff, 0x10, 0x01, 0xe2, /* and   r1, r1, #0xff                        */
172         0x41, 0x14, 0xa0, 0xe1, /* asr   r1, r1, #8                           */
173         0x02, 0x10, 0x81, 0xe1, /* orr   r1, r1, r2                           */
174
175                                 /*  ; Read old baudrate value                 */
176                                 /*  ; r2 = old_baudrate                       */
177         0x8c, 0x20, 0x9f, 0xe5, /* ldr   r2, old_baudrate                     */
178
179                                 /*  ; Calculate base clock                    */
180                                 /*  ; r1 = r2 * r1                            */
181         0x92, 0x01, 0x01, 0xe0, /* mul   r1, r2, r1                           */
182
183                                 /*  ; Read new baudrate value                 */
184                                 /*  ; r2 = baudrate                           */
185         0x88, 0x20, 0x9f, 0xe5, /* ldr   r2, baudrate                         */
186
187                                 /*  ; Calculate new Divisor Latch             */
188                                 /*  ; r1 = DIV_ROUND(r1, r2) =                */
189                                 /*  ;    = (r1 + r2/2) / r2                   */
190         0xa2, 0x10, 0x81, 0xe0, /* add   r1, r1, r2, lsr #1                   */
191         0x02, 0x40, 0xa0, 0xe1, /* mov   r4, r2                               */
192         0xa1, 0x00, 0x54, 0xe1, /* cmp   r4, r1, lsr #1                       */
193                                 /* .Lloop_div1:                               */
194         0x84, 0x40, 0xa0, 0x91, /* movls r4, r4, lsl #1                       */
195         0xa1, 0x00, 0x54, 0xe1, /* cmp   r4, r1, lsr #1                       */
196         0xfc, 0xff, 0xff, 0x9a, /* bls   .Lloop_div1                          */
197         0x00, 0x30, 0xa0, 0xe3, /* mov   r3, #0                               */
198                                 /* .Lloop_div2:                               */
199         0x04, 0x00, 0x51, 0xe1, /* cmp   r1, r4                               */
200         0x04, 0x10, 0x41, 0x20, /* subhs r1, r1, r4                           */
201         0x03, 0x30, 0xa3, 0xe0, /* adc   r3, r3, r3                           */
202         0xa4, 0x40, 0xa0, 0xe1, /* mov   r4, r4, lsr #1                       */
203         0x02, 0x00, 0x54, 0xe1, /* cmp   r4, r2                               */
204         0xf9, 0xff, 0xff, 0x2a, /* bhs   .Lloop_div2                          */
205         0x03, 0x10, 0xa0, 0xe1, /* mov   r1, r3                               */
206
207                                 /*  ; Set new Divisor Latch Low               */
208                                 /*  ; UART_BASE[DLL] = r1 & 0xff              */
209         0x01, 0x20, 0xa0, 0xe1, /* mov   r2, r1                               */
210         0xff, 0x20, 0x02, 0xe2, /* and   r2, r2, #0xff                        */
211         0x00, 0x20, 0x80, 0xe5, /* str   r2, [r0, #0x00]                      */
212
213                                 /*  ; Set new Divisor Latch High              */
214                                 /*  ; UART_BASE[DLH] = r1>>8 & 0xff           */
215         0x41, 0x24, 0xa0, 0xe1, /* asr   r2, r1, #8                           */
216         0xff, 0x20, 0x02, 0xe2, /* and   r2, r2, #0xff                        */
217         0x04, 0x20, 0x80, 0xe5, /* str   r2, [r0, #0x04]                      */
218
219                                 /*  ; Clear Divisor Latch Access Bit          */
220                                 /*  ; UART_BASE[LCR] &= ~DLAB                 */
221         0x0c, 0x10, 0x90, 0xe5, /* ldr   r1, [r0, #0x0c]                      */
222         0x80, 0x10, 0xc1, 0xe3, /* bic   r1, r1, #0x80                        */
223         0x0c, 0x10, 0x80, 0xe5, /* str   r1, [r0, #0x0c]                      */
224
225                                 /*  ; Sleep 1ms ~~ 600000 cycles at 1200 MHz  */
226                                 /*  ; r1 = 600000                             */
227         0x9f, 0x1d, 0xa0, 0xe3, /* mov   r1, #0x27c0                          */
228         0x09, 0x10, 0x40, 0xe3, /* movt  r1, #0x0009                          */
229                                 /* .Lloop_sleep:                              */
230         0x01, 0x10, 0x41, 0xe2, /* sub   r1, r1, #1                           */
231         0x00, 0x00, 0x51, 0xe3, /* cmp   r1, #0                               */
232         0xfc, 0xff, 0xff, 0x1a, /* bne   .Lloop_sleep                         */
233
234                                 /*  ; Return 0 - no error                     */
235         0x00, 0x00, 0xa0, 0xe3, /* mov   r0, #0                               */
236         0xfe, 0x9f, 0xbd, 0xe8, /* pop   { r1 - r12, pc }                     */
237
238                                 /*  ; Preamble string                         */
239                                 /* preamble:                                  */
240         0x24, 0x62, 0x61, 0x75, /* .asciz "$baudratechange"                   */
241         0x64, 0x72, 0x61, 0x74,
242         0x65, 0x63, 0x68, 0x61,
243         0x6e, 0x67, 0x65, 0x00,
244
245                                 /*  ; Placeholder for old baudrate value      */
246                                 /* old_baudrate:                              */
247         0x00, 0x00, 0x00, 0x00, /* .word 0                                    */
248
249                                 /*  ; Placeholder for new baudrate value      */
250                                 /* new_baudrate:                              */
251         0x00, 0x00, 0x00, 0x00, /* .word 0                                    */
252 };
253
254 #define KWBOOT_BAUDRATE_BIN_HEADER_SZ (sizeof(kwboot_baud_code) + \
255                                        sizeof(struct opt_hdr_v1) + 8)
256
257 static const char kwb_baud_magic[16] = "$baudratechange";
258
259 static int kwboot_verbose;
260
261 static int msg_req_delay = KWBOOT_MSG_REQ_DELAY;
262 static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO;
263 static int blk_rsp_timeo = KWBOOT_BLK_RSP_TIMEO;
264
265 static ssize_t
266 kwboot_write(int fd, const char *buf, size_t len)
267 {
268         size_t tot = 0;
269
270         while (tot < len) {
271                 ssize_t wr = write(fd, buf + tot, len - tot);
272
273                 if (wr < 0)
274                         return -1;
275
276                 tot += wr;
277         }
278
279         return tot;
280 }
281
282 static void
283 kwboot_printv(const char *fmt, ...)
284 {
285         va_list ap;
286
287         if (kwboot_verbose) {
288                 va_start(ap, fmt);
289                 vprintf(fmt, ap);
290                 va_end(ap);
291                 fflush(stdout);
292         }
293 }
294
295 static void
296 __spinner(void)
297 {
298         const char seq[] = { '-', '\\', '|', '/' };
299         const int div = 8;
300         static int state, bs;
301
302         if (state % div == 0) {
303                 fputc(bs, stdout);
304                 fputc(seq[state / div % sizeof(seq)], stdout);
305                 fflush(stdout);
306         }
307
308         bs = '\b';
309         state++;
310 }
311
312 static void
313 kwboot_spinner(void)
314 {
315         if (kwboot_verbose)
316                 __spinner();
317 }
318
319 static void
320 __progress(int pct, char c)
321 {
322         const int width = 70;
323         static const char *nl = "";
324         static int pos;
325
326         if (pos % width == 0)
327                 printf("%s%3d %% [", nl, pct);
328
329         fputc(c, stdout);
330
331         nl = "]\n";
332         pos = (pos + 1) % width;
333
334         if (pct == 100) {
335                 while (pos && pos++ < width)
336                         fputc(' ', stdout);
337                 fputs(nl, stdout);
338                 nl = "";
339                 pos = 0;
340         }
341
342         fflush(stdout);
343
344 }
345
346 static void
347 kwboot_progress(int _pct, char c)
348 {
349         static int pct;
350
351         if (_pct != -1)
352                 pct = _pct;
353
354         if (kwboot_verbose)
355                 __progress(pct, c);
356
357         if (pct == 100)
358                 pct = 0;
359 }
360
361 static int
362 kwboot_tty_recv(int fd, void *buf, size_t len, int timeo)
363 {
364         int rc, nfds;
365         fd_set rfds;
366         struct timeval tv;
367         ssize_t n;
368
369         rc = -1;
370
371         FD_ZERO(&rfds);
372         FD_SET(fd, &rfds);
373
374         tv.tv_sec = 0;
375         tv.tv_usec = timeo * 1000;
376         if (tv.tv_usec > 1000000) {
377                 tv.tv_sec += tv.tv_usec / 1000000;
378                 tv.tv_usec %= 1000000;
379         }
380
381         do {
382                 nfds = select(fd + 1, &rfds, NULL, NULL, &tv);
383                 if (nfds < 0)
384                         goto out;
385                 if (!nfds) {
386                         errno = ETIMEDOUT;
387                         goto out;
388                 }
389
390                 n = read(fd, buf, len);
391                 if (n <= 0)
392                         goto out;
393
394                 buf = (char *)buf + n;
395                 len -= n;
396         } while (len > 0);
397
398         rc = 0;
399 out:
400         return rc;
401 }
402
403 static int
404 kwboot_tty_send(int fd, const void *buf, size_t len)
405 {
406         if (!buf)
407                 return 0;
408
409         if (kwboot_write(fd, buf, len) < 0)
410                 return -1;
411
412         return tcdrain(fd);
413 }
414
415 static int
416 kwboot_tty_send_char(int fd, unsigned char c)
417 {
418         return kwboot_tty_send(fd, &c, 1);
419 }
420
421 static speed_t
422 kwboot_tty_baudrate_to_speed(int baudrate)
423 {
424         switch (baudrate) {
425 #ifdef B4000000
426         case 4000000:
427                 return B4000000;
428 #endif
429 #ifdef B3500000
430         case 3500000:
431                 return B3500000;
432 #endif
433 #ifdef B3000000
434         case 3000000:
435                 return B3000000;
436 #endif
437 #ifdef B2500000
438         case 2500000:
439                 return B2500000;
440 #endif
441 #ifdef B2000000
442         case 2000000:
443                 return B2000000;
444 #endif
445 #ifdef B1500000
446         case 1500000:
447                 return B1500000;
448 #endif
449 #ifdef B1152000
450         case 1152000:
451                 return B1152000;
452 #endif
453 #ifdef B1000000
454         case 1000000:
455                 return B1000000;
456 #endif
457 #ifdef B921600
458         case 921600:
459                 return B921600;
460 #endif
461 #ifdef B614400
462         case 614400:
463                 return B614400;
464 #endif
465 #ifdef B576000
466         case 576000:
467                 return B576000;
468 #endif
469 #ifdef B500000
470         case 500000:
471                 return B500000;
472 #endif
473 #ifdef B460800
474         case 460800:
475                 return B460800;
476 #endif
477 #ifdef B307200
478         case 307200:
479                 return B307200;
480 #endif
481 #ifdef B230400
482         case 230400:
483                 return B230400;
484 #endif
485 #ifdef B153600
486         case 153600:
487                 return B153600;
488 #endif
489 #ifdef B115200
490         case 115200:
491                 return B115200;
492 #endif
493 #ifdef B76800
494         case 76800:
495                 return B76800;
496 #endif
497 #ifdef B57600
498         case 57600:
499                 return B57600;
500 #endif
501 #ifdef B38400
502         case 38400:
503                 return B38400;
504 #endif
505 #ifdef B19200
506         case 19200:
507                 return B19200;
508 #endif
509 #ifdef B9600
510         case 9600:
511                 return B9600;
512 #endif
513 #ifdef B4800
514         case 4800:
515                 return B4800;
516 #endif
517 #ifdef B2400
518         case 2400:
519                 return B2400;
520 #endif
521 #ifdef B1800
522         case 1800:
523                 return B1800;
524 #endif
525 #ifdef B1200
526         case 1200:
527                 return B1200;
528 #endif
529 #ifdef B600
530         case 600:
531                 return B600;
532 #endif
533 #ifdef B300
534         case 300:
535                 return B300;
536 #endif
537 #ifdef B200
538         case 200:
539                 return B200;
540 #endif
541 #ifdef B150
542         case 150:
543                 return B150;
544 #endif
545 #ifdef B134
546         case 134:
547                 return B134;
548 #endif
549 #ifdef B110
550         case 110:
551                 return B110;
552 #endif
553 #ifdef B75
554         case 75:
555                 return B75;
556 #endif
557 #ifdef B50
558         case 50:
559                 return B50;
560 #endif
561         default:
562 #ifdef BOTHER
563                 return BOTHER;
564 #else
565                 return B0;
566 #endif
567         }
568 }
569
570 static int
571 _is_within_tolerance(int value, int reference, int tolerance)
572 {
573         return 100 * value >= reference * (100 - tolerance) &&
574                100 * value <= reference * (100 + tolerance);
575 }
576
577 static int
578 kwboot_tty_change_baudrate(int fd, int baudrate)
579 {
580         struct termios tio;
581         speed_t speed;
582         int rc;
583
584         rc = tcgetattr(fd, &tio);
585         if (rc)
586                 return rc;
587
588         speed = kwboot_tty_baudrate_to_speed(baudrate);
589         if (speed == B0) {
590                 errno = EINVAL;
591                 return -1;
592         }
593
594 #ifdef BOTHER
595         if (speed == BOTHER)
596                 tio.c_ospeed = tio.c_ispeed = baudrate;
597 #endif
598
599         rc = cfsetospeed(&tio, speed);
600         if (rc)
601                 return rc;
602
603         rc = cfsetispeed(&tio, speed);
604         if (rc)
605                 return rc;
606
607         rc = tcsetattr(fd, TCSANOW, &tio);
608         if (rc)
609                 return rc;
610
611         rc = tcgetattr(fd, &tio);
612         if (rc)
613                 return rc;
614
615         if (cfgetospeed(&tio) != speed || cfgetispeed(&tio) != speed)
616                 goto baud_fail;
617
618 #ifdef BOTHER
619         /*
620          * Check whether set baudrate is within 3% tolerance.
621          * If BOTHER is defined, Linux always fills out c_ospeed / c_ispeed
622          * with real values.
623          */
624         if (!_is_within_tolerance(tio.c_ospeed, baudrate, 3))
625                 goto baud_fail;
626
627         if (!_is_within_tolerance(tio.c_ispeed, baudrate, 3))
628                 goto baud_fail;
629 #endif
630
631         return 0;
632
633 baud_fail:
634         fprintf(stderr, "Could not set baudrate to requested value\n");
635         errno = EINVAL;
636         return -1;
637 }
638
639 static int
640 kwboot_open_tty(const char *path, int baudrate)
641 {
642         int rc, fd;
643         struct termios tio;
644
645         rc = -1;
646
647         fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY);
648         if (fd < 0)
649                 goto out;
650
651         memset(&tio, 0, sizeof(tio));
652
653         tio.c_iflag = 0;
654         tio.c_cflag = CREAD|CLOCAL|CS8;
655
656         tio.c_cc[VMIN] = 1;
657         tio.c_cc[VTIME] = 10;
658
659         rc = tcsetattr(fd, TCSANOW, &tio);
660         if (rc)
661                 goto out;
662
663         rc = kwboot_tty_change_baudrate(fd, baudrate);
664         if (rc)
665                 goto out;
666
667         rc = fd;
668 out:
669         if (rc < 0) {
670                 if (fd >= 0)
671                         close(fd);
672         }
673
674         return rc;
675 }
676
677 static int
678 kwboot_bootmsg(int tty, void *msg)
679 {
680         int rc;
681         char c;
682         int count;
683
684         if (msg == NULL)
685                 kwboot_printv("Please reboot the target into UART boot mode...");
686         else
687                 kwboot_printv("Sending boot message. Please reboot the target...");
688
689         do {
690                 rc = tcflush(tty, TCIOFLUSH);
691                 if (rc)
692                         break;
693
694                 for (count = 0; count < 128; count++) {
695                         rc = kwboot_tty_send(tty, msg, 8);
696                         if (rc) {
697                                 usleep(msg_req_delay * 1000);
698                                 continue;
699                         }
700                 }
701
702                 rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo);
703
704                 kwboot_spinner();
705
706         } while (rc || c != NAK);
707
708         kwboot_printv("\n");
709
710         return rc;
711 }
712
713 static int
714 kwboot_debugmsg(int tty, void *msg)
715 {
716         int rc;
717
718         kwboot_printv("Sending debug message. Please reboot the target...");
719
720         do {
721                 char buf[16];
722
723                 rc = tcflush(tty, TCIOFLUSH);
724                 if (rc)
725                         break;
726
727                 rc = kwboot_tty_send(tty, msg, 8);
728                 if (rc) {
729                         usleep(msg_req_delay * 1000);
730                         continue;
731                 }
732
733                 rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo);
734
735                 kwboot_spinner();
736
737         } while (rc);
738
739         kwboot_printv("\n");
740
741         return rc;
742 }
743
744 static size_t
745 kwboot_xm_makeblock(struct kwboot_block *block, const void *data,
746                     size_t size, int pnum)
747 {
748         size_t i, n;
749
750         block->soh = SOH;
751         block->pnum = pnum;
752         block->_pnum = ~block->pnum;
753
754         n = size < KWBOOT_XM_BLKSZ ? size : KWBOOT_XM_BLKSZ;
755         memcpy(&block->data[0], data, n);
756         memset(&block->data[n], 0, KWBOOT_XM_BLKSZ - n);
757
758         block->csum = 0;
759         for (i = 0; i < n; i++)
760                 block->csum += block->data[i];
761
762         return n;
763 }
764
765 static uint64_t
766 _now(void)
767 {
768         struct timespec ts;
769
770         if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
771                 static int err_print;
772
773                 if (!err_print) {
774                         perror("clock_gettime() does not work");
775                         err_print = 1;
776                 }
777
778                 /* this will just make the timeout not work */
779                 return -1ULL;
780         }
781
782         return ts.tv_sec * 1000ULL + (ts.tv_nsec + 500000) / 1000000;
783 }
784
785 static int
786 _is_xm_reply(char c)
787 {
788         return c == ACK || c == NAK || c == CAN;
789 }
790
791 static int
792 _xm_reply_to_error(int c)
793 {
794         int rc = -1;
795
796         switch (c) {
797         case ACK:
798                 rc = 0;
799                 break;
800         case NAK:
801                 errno = EBADMSG;
802                 break;
803         case CAN:
804                 errno = ECANCELED;
805                 break;
806         default:
807                 errno = EPROTO;
808                 break;
809         }
810
811         return rc;
812 }
813
814 static int
815 kwboot_baud_magic_handle(int fd, char c, int baudrate)
816 {
817         static size_t rcv_len;
818
819         if (rcv_len < sizeof(kwb_baud_magic)) {
820                 /* try to recognize whole magic word */
821                 if (c == kwb_baud_magic[rcv_len]) {
822                         rcv_len++;
823                 } else {
824                         printf("%.*s%c", (int)rcv_len, kwb_baud_magic, c);
825                         fflush(stdout);
826                         rcv_len = 0;
827                 }
828         }
829
830         if (rcv_len == sizeof(kwb_baud_magic)) {
831                 /* magic word received */
832                 kwboot_printv("\nChanging baudrate to %d Bd\n", baudrate);
833
834                 return kwboot_tty_change_baudrate(fd, baudrate) ? : 1;
835         } else {
836                 return 0;
837         }
838 }
839
840 static int
841 kwboot_xm_recv_reply(int fd, char *c, int allow_non_xm, int *non_xm_print,
842                      int baudrate, int *baud_changed)
843 {
844         int timeout = allow_non_xm ? KWBOOT_HDR_RSP_TIMEO : blk_rsp_timeo;
845         uint64_t recv_until = _now() + timeout;
846         int rc;
847
848         if (non_xm_print)
849                 *non_xm_print = 0;
850         if (baud_changed)
851                 *baud_changed = 0;
852
853         while (1) {
854                 rc = kwboot_tty_recv(fd, c, 1, timeout);
855                 if (rc) {
856                         if (errno != ETIMEDOUT)
857                                 return rc;
858                         else if (allow_non_xm && *non_xm_print)
859                                 return -1;
860                         else
861                                 *c = NAK;
862                 }
863
864                 /* If received xmodem reply, end. */
865                 if (_is_xm_reply(*c))
866                         break;
867
868                 /*
869                  * If receiving/printing non-xmodem text output is allowed and
870                  * such a byte was received, we want to increase receiving time
871                  * and either:
872                  * - print the byte, if it is not part of baudrate change magic
873                  *   sequence while baudrate change was requested (-B option)
874                  * - change baudrate
875                  * Otherwise decrease timeout by time elapsed.
876                  */
877                 if (allow_non_xm) {
878                         recv_until = _now() + timeout;
879
880                         if (baudrate && !*baud_changed) {
881                                 rc = kwboot_baud_magic_handle(fd, *c, baudrate);
882                                 if (rc == 1)
883                                         *baud_changed = 1;
884                                 else if (!rc)
885                                         *non_xm_print = 1;
886                                 else
887                                         return rc;
888                         } else if (!baudrate || !*baud_changed) {
889                                 putchar(*c);
890                                 fflush(stdout);
891                                 *non_xm_print = 1;
892                         }
893                 } else {
894                         timeout = recv_until - _now();
895                         if (timeout < 0) {
896                                 errno = ETIMEDOUT;
897                                 return -1;
898                         }
899                 }
900         }
901
902         return 0;
903 }
904
905 static int
906 kwboot_xm_sendblock(int fd, struct kwboot_block *block, int allow_non_xm,
907                     int *done_print, int baudrate)
908 {
909         int non_xm_print, baud_changed;
910         int rc, err, retries;
911         char c;
912
913         *done_print = 0;
914
915         retries = 16;
916         do {
917                 rc = kwboot_tty_send(fd, block, sizeof(*block));
918                 if (rc)
919                         return rc;
920
921                 if (allow_non_xm && !*done_print) {
922                         kwboot_progress(100, '.');
923                         kwboot_printv("Done\n");
924                         *done_print = 1;
925                 }
926
927                 rc = kwboot_xm_recv_reply(fd, &c, allow_non_xm, &non_xm_print,
928                                           baudrate, &baud_changed);
929                 if (rc)
930                         goto can;
931
932                 if (!allow_non_xm && c != ACK)
933                         kwboot_progress(-1, '+');
934         } while (c == NAK && retries-- > 0);
935
936         if (non_xm_print)
937                 kwboot_printv("\n");
938
939         if (allow_non_xm && baudrate && !baud_changed) {
940                 fprintf(stderr, "Baudrate was not changed\n");
941                 rc = -1;
942                 errno = EPROTO;
943                 goto can;
944         }
945
946         return _xm_reply_to_error(c);
947 can:
948         err = errno;
949         kwboot_tty_send_char(fd, CAN);
950         kwboot_printv("\n");
951         errno = err;
952         return rc;
953 }
954
955 static int
956 kwboot_xm_finish(int fd)
957 {
958         int rc, retries;
959         char c;
960
961         kwboot_printv("Finishing transfer\n");
962
963         retries = 16;
964         do {
965                 rc = kwboot_tty_send_char(fd, EOT);
966                 if (rc)
967                         return rc;
968
969                 rc = kwboot_xm_recv_reply(fd, &c, 0, NULL, 0, NULL);
970                 if (rc)
971                         return rc;
972         } while (c == NAK && retries-- > 0);
973
974         return _xm_reply_to_error(c);
975 }
976
977 static int
978 kwboot_xmodem_one(int tty, int *pnum, int header, const uint8_t *data,
979                   size_t size, int baudrate)
980 {
981         int done_print = 0;
982         size_t sent, left;
983         int rc;
984
985         kwboot_printv("Sending boot image %s (%zu bytes)...\n",
986                       header ? "header" : "data", size);
987
988         left = size;
989         sent = 0;
990
991         while (sent < size) {
992                 struct kwboot_block block;
993                 int last_block;
994                 size_t blksz;
995
996                 blksz = kwboot_xm_makeblock(&block, data, left, (*pnum)++);
997                 data += blksz;
998
999                 last_block = (left <= blksz);
1000
1001                 rc = kwboot_xm_sendblock(tty, &block, header && last_block,
1002                                          &done_print, baudrate);
1003                 if (rc)
1004                         goto out;
1005
1006                 sent += blksz;
1007                 left -= blksz;
1008
1009                 if (!done_print)
1010                         kwboot_progress(sent * 100 / size, '.');
1011         }
1012
1013         if (!done_print)
1014                 kwboot_printv("Done\n");
1015
1016         return 0;
1017 out:
1018         kwboot_printv("\n");
1019         return rc;
1020 }
1021
1022 static int
1023 kwboot_xmodem(int tty, const void *_img, size_t size, int baudrate)
1024 {
1025         const uint8_t *img = _img;
1026         int rc, pnum;
1027         size_t hdrsz;
1028
1029         hdrsz = kwbheader_size(img);
1030
1031         kwboot_printv("Waiting 2s and flushing tty\n");
1032         sleep(2); /* flush isn't effective without it */
1033         tcflush(tty, TCIOFLUSH);
1034
1035         pnum = 1;
1036
1037         rc = kwboot_xmodem_one(tty, &pnum, 1, img, hdrsz, baudrate);
1038         if (rc)
1039                 return rc;
1040
1041         img += hdrsz;
1042         size -= hdrsz;
1043
1044         rc = kwboot_xmodem_one(tty, &pnum, 0, img, size, 0);
1045         if (rc)
1046                 return rc;
1047
1048         rc = kwboot_xm_finish(tty);
1049         if (rc)
1050                 return rc;
1051
1052         if (baudrate) {
1053                 char buf[sizeof(kwb_baud_magic)];
1054
1055                 /* Wait 1s for baudrate change magic */
1056                 rc = kwboot_tty_recv(tty, buf, sizeof(buf), 1000);
1057                 if (rc)
1058                         return rc;
1059
1060                 if (memcmp(buf, kwb_baud_magic, sizeof(buf))) {
1061                         errno = EPROTO;
1062                         return -1;
1063                 }
1064
1065                 kwboot_printv("\nChanging baudrate back to 115200 Bd\n\n");
1066                 rc = kwboot_tty_change_baudrate(tty, 115200);
1067                 if (rc)
1068                         return rc;
1069         }
1070
1071         return 0;
1072 }
1073
1074 static int
1075 kwboot_term_pipe(int in, int out, const char *quit, int *s)
1076 {
1077         ssize_t nin;
1078         char _buf[128], *buf = _buf;
1079
1080         nin = read(in, buf, sizeof(_buf));
1081         if (nin <= 0)
1082                 return -1;
1083
1084         if (quit) {
1085                 int i;
1086
1087                 for (i = 0; i < nin; i++) {
1088                         if (*buf == quit[*s]) {
1089                                 (*s)++;
1090                                 if (!quit[*s])
1091                                         return 0;
1092                                 buf++;
1093                                 nin--;
1094                         } else {
1095                                 if (kwboot_write(out, quit, *s) < 0)
1096                                         return -1;
1097                                 *s = 0;
1098                         }
1099                 }
1100         }
1101
1102         if (kwboot_write(out, buf, nin) < 0)
1103                 return -1;
1104
1105         return 0;
1106 }
1107
1108 static int
1109 kwboot_terminal(int tty)
1110 {
1111         int rc, in, s;
1112         const char *quit = "\34c";
1113         struct termios otio, tio;
1114
1115         rc = -1;
1116
1117         in = STDIN_FILENO;
1118         if (isatty(in)) {
1119                 rc = tcgetattr(in, &otio);
1120                 if (!rc) {
1121                         tio = otio;
1122                         cfmakeraw(&tio);
1123                         rc = tcsetattr(in, TCSANOW, &tio);
1124                 }
1125                 if (rc) {
1126                         perror("tcsetattr");
1127                         goto out;
1128                 }
1129
1130                 kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n",
1131                               quit[0]|0100, quit[1]);
1132         } else
1133                 in = -1;
1134
1135         rc = 0;
1136         s = 0;
1137
1138         do {
1139                 fd_set rfds;
1140                 int nfds = 0;
1141
1142                 FD_SET(tty, &rfds);
1143                 nfds = nfds < tty ? tty : nfds;
1144
1145                 if (in >= 0) {
1146                         FD_SET(in, &rfds);
1147                         nfds = nfds < in ? in : nfds;
1148                 }
1149
1150                 nfds = select(nfds + 1, &rfds, NULL, NULL, NULL);
1151                 if (nfds < 0)
1152                         break;
1153
1154                 if (FD_ISSET(tty, &rfds)) {
1155                         rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL);
1156                         if (rc)
1157                                 break;
1158                 }
1159
1160                 if (in >= 0 && FD_ISSET(in, &rfds)) {
1161                         rc = kwboot_term_pipe(in, tty, quit, &s);
1162                         if (rc)
1163                                 break;
1164                 }
1165         } while (quit[s] != 0);
1166
1167         if (in >= 0)
1168                 tcsetattr(in, TCSANOW, &otio);
1169         printf("\n");
1170 out:
1171         return rc;
1172 }
1173
1174 static void *
1175 kwboot_read_image(const char *path, size_t *size, size_t reserve)
1176 {
1177         int rc, fd;
1178         struct stat st;
1179         void *img;
1180         off_t tot;
1181
1182         rc = -1;
1183         img = NULL;
1184
1185         fd = open(path, O_RDONLY);
1186         if (fd < 0)
1187                 goto out;
1188
1189         rc = fstat(fd, &st);
1190         if (rc)
1191                 goto out;
1192
1193         img = malloc(st.st_size + reserve);
1194         if (!img)
1195                 goto out;
1196
1197         tot = 0;
1198         while (tot < st.st_size) {
1199                 ssize_t rd = read(fd, img + tot, st.st_size - tot);
1200
1201                 if (rd < 0)
1202                         goto out;
1203
1204                 tot += rd;
1205
1206                 if (!rd && tot < st.st_size) {
1207                         errno = EIO;
1208                         goto out;
1209                 }
1210         }
1211
1212         rc = 0;
1213         *size = st.st_size;
1214 out:
1215         if (rc && img) {
1216                 free(img);
1217                 img = NULL;
1218         }
1219         if (fd >= 0)
1220                 close(fd);
1221
1222         return img;
1223 }
1224
1225 static uint8_t
1226 kwboot_hdr_csum8(const void *hdr)
1227 {
1228         const uint8_t *data = hdr;
1229         uint8_t csum;
1230         size_t size;
1231
1232         size = kwbheader_size_for_csum(hdr);
1233
1234         for (csum = 0; size-- > 0; data++)
1235                 csum += *data;
1236
1237         return csum;
1238 }
1239
1240 static int
1241 kwboot_img_is_secure(void *img)
1242 {
1243         struct opt_hdr_v1 *ohdr;
1244
1245         for_each_opt_hdr_v1 (ohdr, img)
1246                 if (ohdr->headertype == OPT_HDR_V1_SECURE_TYPE)
1247                         return 1;
1248
1249         return 0;
1250 }
1251
1252 static void *
1253 kwboot_img_grow_data_left(void *img, size_t *size, size_t grow)
1254 {
1255         uint32_t hdrsz, datasz, srcaddr;
1256         struct main_hdr_v1 *hdr = img;
1257         uint8_t *data;
1258
1259         srcaddr = le32_to_cpu(hdr->srcaddr);
1260
1261         hdrsz = kwbheader_size(hdr);
1262         data = (uint8_t *)img + srcaddr;
1263         datasz = *size - srcaddr;
1264
1265         /* only move data if there is not enough space */
1266         if (hdrsz + grow > srcaddr) {
1267                 size_t need = hdrsz + grow - srcaddr;
1268
1269                 /* move data by enough bytes */
1270                 memmove(data + need, data, datasz);
1271                 *size += need;
1272                 srcaddr += need;
1273         }
1274
1275         srcaddr -= grow;
1276         hdr->srcaddr = cpu_to_le32(srcaddr);
1277         hdr->destaddr = cpu_to_le32(le32_to_cpu(hdr->destaddr) - grow);
1278         hdr->blocksize = cpu_to_le32(le32_to_cpu(hdr->blocksize) + grow);
1279
1280         return (uint8_t *)img + srcaddr;
1281 }
1282
1283 static void
1284 kwboot_img_grow_hdr(void *img, size_t *size, size_t grow)
1285 {
1286         uint32_t hdrsz, datasz, srcaddr;
1287         struct main_hdr_v1 *hdr = img;
1288         uint8_t *data;
1289
1290         srcaddr = le32_to_cpu(hdr->srcaddr);
1291
1292         hdrsz = kwbheader_size(img);
1293         data = (uint8_t *)img + srcaddr;
1294         datasz = *size - srcaddr;
1295
1296         /* only move data if there is not enough space */
1297         if (hdrsz + grow > srcaddr) {
1298                 size_t need = hdrsz + grow - srcaddr;
1299
1300                 /* move data by enough bytes */
1301                 memmove(data + need, data, datasz);
1302
1303                 hdr->srcaddr = cpu_to_le32(srcaddr + need);
1304                 *size += need;
1305         }
1306
1307         if (kwbimage_version(img) == 1) {
1308                 hdrsz += grow;
1309                 hdr->headersz_msb = hdrsz >> 16;
1310                 hdr->headersz_lsb = cpu_to_le16(hdrsz & 0xffff);
1311         }
1312 }
1313
1314 static void *
1315 kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz)
1316 {
1317         struct main_hdr_v1 *hdr = img;
1318         struct opt_hdr_v1 *ohdr;
1319         uint32_t ohdrsz;
1320
1321         ohdrsz = binsz + 8 + sizeof(*ohdr);
1322         kwboot_img_grow_hdr(img, size, ohdrsz);
1323
1324         if (hdr->ext & 0x1) {
1325                 for_each_opt_hdr_v1 (ohdr, img)
1326                         if (opt_hdr_v1_next(ohdr) == NULL)
1327                                 break;
1328
1329                 *opt_hdr_v1_ext(ohdr) |= 1;
1330                 ohdr = opt_hdr_v1_next(ohdr);
1331         } else {
1332                 hdr->ext |= 1;
1333                 ohdr = (void *)(hdr + 1);
1334         }
1335
1336         ohdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1337         ohdr->headersz_msb = ohdrsz >> 16;
1338         ohdr->headersz_lsb = cpu_to_le16(ohdrsz & 0xffff);
1339
1340         memset(&ohdr->data[0], 0, ohdrsz - sizeof(*ohdr));
1341
1342         return &ohdr->data[4];
1343 }
1344
1345 static void
1346 _copy_baudrate_change_code(struct main_hdr_v1 *hdr, void *dst, int pre,
1347                            int old_baud, int new_baud)
1348 {
1349         size_t codesz = sizeof(kwboot_baud_code);
1350         uint8_t *code = dst;
1351
1352         if (pre) {
1353                 size_t presz = sizeof(kwboot_pre_baud_code);
1354
1355                 /*
1356                  * We need to prepend code that loads lr register with original
1357                  * value of hdr->execaddr. We do this by putting the original
1358                  * exec address before the code that loads it relatively from
1359                  * it's beginning.
1360                  * Afterwards we change the exec address to this code (which is
1361                  * at offset 4, because the first 4 bytes contain the original
1362                  * exec address).
1363                  */
1364                 memcpy(code, kwboot_pre_baud_code, presz);
1365                 *(uint32_t *)code = hdr->execaddr;
1366
1367                 hdr->execaddr = cpu_to_le32(le32_to_cpu(hdr->destaddr) + 4);
1368
1369                 code += presz;
1370         }
1371
1372         memcpy(code, kwboot_baud_code, codesz - 8);
1373         *(uint32_t *)(code + codesz - 8) = cpu_to_le32(old_baud);
1374         *(uint32_t *)(code + codesz - 4) = cpu_to_le32(new_baud);
1375 }
1376
1377 static int
1378 kwboot_img_patch(void *img, size_t *size, int baudrate)
1379 {
1380         int rc;
1381         struct main_hdr_v1 *hdr;
1382         uint32_t srcaddr;
1383         uint8_t csum;
1384         size_t hdrsz;
1385         int image_ver;
1386         int is_secure;
1387
1388         rc = -1;
1389         hdr = img;
1390
1391         if (*size < sizeof(struct main_hdr_v1)) {
1392                 errno = EINVAL;
1393                 goto out;
1394         }
1395
1396         image_ver = kwbimage_version(img);
1397         if (image_ver != 0 && image_ver != 1) {
1398                 fprintf(stderr, "Invalid image header version\n");
1399                 errno = EINVAL;
1400                 goto out;
1401         }
1402
1403         hdrsz = kwbheader_size(hdr);
1404
1405         if (*size < hdrsz) {
1406                 errno = EINVAL;
1407                 goto out;
1408         }
1409
1410         csum = kwboot_hdr_csum8(hdr) - hdr->checksum;
1411         if (csum != hdr->checksum) {
1412                 errno = EINVAL;
1413                 goto out;
1414         }
1415
1416         if (image_ver == 0) {
1417                 struct main_hdr_v0 *hdr_v0 = img;
1418
1419                 hdr_v0->nandeccmode = IBR_HDR_ECC_DISABLED;
1420                 hdr_v0->nandpagesize = 0;
1421         }
1422
1423         srcaddr = le32_to_cpu(hdr->srcaddr);
1424
1425         switch (hdr->blockid) {
1426         case IBR_HDR_SATA_ID:
1427                 if (srcaddr < 1) {
1428                         errno = EINVAL;
1429                         goto out;
1430                 }
1431                 hdr->srcaddr = cpu_to_le32((srcaddr - 1) * 512);
1432                 break;
1433
1434         case IBR_HDR_SDIO_ID:
1435                 hdr->srcaddr = cpu_to_le32(srcaddr * 512);
1436                 break;
1437
1438         case IBR_HDR_PEX_ID:
1439                 if (srcaddr == 0xFFFFFFFF)
1440                         hdr->srcaddr = cpu_to_le32(hdrsz);
1441                 break;
1442
1443         case IBR_HDR_SPI_ID:
1444                 if (hdr->destaddr == cpu_to_le32(0xFFFFFFFF)) {
1445                         kwboot_printv("Patching destination and execution addresses from SPI/NOR XIP area to DDR area 0x00800000\n");
1446                         hdr->destaddr = cpu_to_le32(0x00800000);
1447                         hdr->execaddr = cpu_to_le32(0x00800000);
1448                 }
1449                 break;
1450         }
1451
1452         if (hdrsz > le32_to_cpu(hdr->srcaddr) ||
1453             *size < le32_to_cpu(hdr->srcaddr) + le32_to_cpu(hdr->blocksize)) {
1454                 errno = EINVAL;
1455                 goto out;
1456         }
1457
1458         is_secure = kwboot_img_is_secure(img);
1459
1460         if (hdr->blockid != IBR_HDR_UART_ID) {
1461                 if (is_secure) {
1462                         fprintf(stderr,
1463                                 "Image has secure header with signature for non-UART booting\n");
1464                         errno = EINVAL;
1465                         goto out;
1466                 }
1467
1468                 kwboot_printv("Patching image boot signature to UART\n");
1469                 hdr->blockid = IBR_HDR_UART_ID;
1470         }
1471
1472         if (baudrate) {
1473                 uint32_t codesz = sizeof(kwboot_baud_code);
1474                 void *code;
1475
1476                 if (image_ver == 0) {
1477                         fprintf(stderr,
1478                                 "Cannot inject code for changing baudrate into v0 image header\n");
1479                         errno = EINVAL;
1480                         goto out;
1481                 }
1482
1483                 if (is_secure) {
1484                         fprintf(stderr,
1485                                 "Cannot inject code for changing baudrate into image with secure header\n");
1486                         errno = EINVAL;
1487                         goto out;
1488                 }
1489
1490                 /*
1491                  * First inject code that changes the baudrate from the default
1492                  * value of 115200 Bd to requested value. This code is inserted
1493                  * as a new opt hdr, so it is executed by BootROM after the
1494                  * header part is received.
1495                  */
1496                 kwboot_printv("Injecting binary header code for changing baudrate to %d Bd\n",
1497                               baudrate);
1498
1499                 code = kwboot_add_bin_ohdr_v1(img, size, codesz);
1500                 _copy_baudrate_change_code(hdr, code, 0, 115200, baudrate);
1501
1502                 /*
1503                  * Now inject code that changes the baudrate back to 115200 Bd.
1504                  * This code is prepended to the data part of the image, so it
1505                  * is executed before U-Boot proper.
1506                  */
1507                 kwboot_printv("Injecting code for changing baudrate back\n");
1508
1509                 codesz += sizeof(kwboot_pre_baud_code);
1510                 code = kwboot_img_grow_data_left(img, size, codesz);
1511                 _copy_baudrate_change_code(hdr, code, 1, baudrate, 115200);
1512
1513                 /* recompute header size */
1514                 hdrsz = kwbheader_size(hdr);
1515         }
1516
1517         if (hdrsz % KWBOOT_XM_BLKSZ) {
1518                 size_t offset = (KWBOOT_XM_BLKSZ - hdrsz % KWBOOT_XM_BLKSZ) %
1519                                 KWBOOT_XM_BLKSZ;
1520
1521                 if (is_secure) {
1522                         fprintf(stderr, "Cannot align image with secure header\n");
1523                         errno = EINVAL;
1524                         goto out;
1525                 }
1526
1527                 kwboot_printv("Aligning image header to Xmodem block size\n");
1528                 kwboot_img_grow_hdr(img, size, offset);
1529         }
1530
1531         hdr->checksum = kwboot_hdr_csum8(hdr) - csum;
1532
1533         *size = le32_to_cpu(hdr->srcaddr) + le32_to_cpu(hdr->blocksize);
1534         rc = 0;
1535 out:
1536         return rc;
1537 }
1538
1539 static void
1540 kwboot_usage(FILE *stream, char *progname)
1541 {
1542         fprintf(stream, "kwboot version %s\n", PLAIN_VERSION);
1543         fprintf(stream,
1544                 "Usage: %s [OPTIONS] [-b <image> | -D <image> ] [-B <baud> ] <TTY>\n",
1545                 progname);
1546         fprintf(stream, "\n");
1547         fprintf(stream,
1548                 "  -b <image>: boot <image> with preamble (Kirkwood, Armada 370/XP)\n");
1549         fprintf(stream,
1550                 "  -D <image>: boot <image> without preamble (Dove)\n");
1551         fprintf(stream, "  -d: enter debug mode\n");
1552         fprintf(stream, "  -a: use timings for Armada XP\n");
1553         fprintf(stream, "  -q <req-delay>:  use specific request-delay\n");
1554         fprintf(stream, "  -s <resp-timeo>: use specific response-timeout\n");
1555         fprintf(stream,
1556                 "  -o <block-timeo>: use specific xmodem block timeout\n");
1557         fprintf(stream, "\n");
1558         fprintf(stream, "  -t: mini terminal\n");
1559         fprintf(stream, "\n");
1560         fprintf(stream, "  -B <baud>: set baud rate\n");
1561         fprintf(stream, "\n");
1562 }
1563
1564 int
1565 main(int argc, char **argv)
1566 {
1567         const char *ttypath, *imgpath;
1568         int rv, rc, tty, term;
1569         void *bootmsg;
1570         void *debugmsg;
1571         void *img;
1572         size_t size;
1573         size_t after_img_rsv;
1574         int baudrate;
1575
1576         rv = 1;
1577         tty = -1;
1578         bootmsg = NULL;
1579         debugmsg = NULL;
1580         imgpath = NULL;
1581         img = NULL;
1582         term = 0;
1583         size = 0;
1584         after_img_rsv = KWBOOT_XM_BLKSZ;
1585         baudrate = 115200;
1586
1587         kwboot_verbose = isatty(STDOUT_FILENO);
1588
1589         do {
1590                 int c = getopt(argc, argv, "hb:ptaB:dD:q:s:o:");
1591                 if (c < 0)
1592                         break;
1593
1594                 switch (c) {
1595                 case 'b':
1596                         bootmsg = kwboot_msg_boot;
1597                         imgpath = optarg;
1598                         break;
1599
1600                 case 'D':
1601                         bootmsg = NULL;
1602                         imgpath = optarg;
1603                         break;
1604
1605                 case 'd':
1606                         debugmsg = kwboot_msg_debug;
1607                         break;
1608
1609                 case 'p':
1610                         /* nop, for backward compatibility */
1611                         break;
1612
1613                 case 't':
1614                         term = 1;
1615                         break;
1616
1617                 case 'a':
1618                         msg_req_delay = KWBOOT_MSG_REQ_DELAY_AXP;
1619                         msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO_AXP;
1620                         break;
1621
1622                 case 'q':
1623                         msg_req_delay = atoi(optarg);
1624                         break;
1625
1626                 case 's':
1627                         msg_rsp_timeo = atoi(optarg);
1628                         break;
1629
1630                 case 'o':
1631                         blk_rsp_timeo = atoi(optarg);
1632                         break;
1633
1634                 case 'B':
1635                         baudrate = atoi(optarg);
1636                         break;
1637
1638                 case 'h':
1639                         rv = 0;
1640                 default:
1641                         goto usage;
1642                 }
1643         } while (1);
1644
1645         if (!bootmsg && !term && !debugmsg)
1646                 goto usage;
1647
1648         if (argc - optind < 1)
1649                 goto usage;
1650
1651         ttypath = argv[optind++];
1652
1653         tty = kwboot_open_tty(ttypath, imgpath ? 115200 : baudrate);
1654         if (tty < 0) {
1655                 perror(ttypath);
1656                 goto out;
1657         }
1658
1659         if (baudrate == 115200)
1660                 /* do not change baudrate during Xmodem to the same value */
1661                 baudrate = 0;
1662         else
1663                 /* ensure we have enough space for baudrate change code */
1664                 after_img_rsv += KWBOOT_BAUDRATE_BIN_HEADER_SZ +
1665                                  sizeof(kwboot_pre_baud_code) +
1666                                  sizeof(kwboot_baud_code);
1667
1668         if (imgpath) {
1669                 img = kwboot_read_image(imgpath, &size, after_img_rsv);
1670                 if (!img) {
1671                         perror(imgpath);
1672                         goto out;
1673                 }
1674
1675                 rc = kwboot_img_patch(img, &size, baudrate);
1676                 if (rc) {
1677                         fprintf(stderr, "%s: Invalid image.\n", imgpath);
1678                         goto out;
1679                 }
1680         }
1681
1682         if (debugmsg) {
1683                 rc = kwboot_debugmsg(tty, debugmsg);
1684                 if (rc) {
1685                         perror("debugmsg");
1686                         goto out;
1687                 }
1688         } else if (bootmsg) {
1689                 rc = kwboot_bootmsg(tty, bootmsg);
1690                 if (rc) {
1691                         perror("bootmsg");
1692                         goto out;
1693                 }
1694         }
1695
1696         if (img) {
1697                 rc = kwboot_xmodem(tty, img, size, baudrate);
1698                 if (rc) {
1699                         perror("xmodem");
1700                         goto out;
1701                 }
1702         }
1703
1704         if (term) {
1705                 rc = kwboot_terminal(tty);
1706                 if (rc && !(errno == EINTR)) {
1707                         perror("terminal");
1708                         goto out;
1709                 }
1710         }
1711
1712         rv = 0;
1713 out:
1714         if (tty >= 0)
1715                 close(tty);
1716
1717         if (img)
1718                 free(img);
1719
1720         return rv;
1721
1722 usage:
1723         kwboot_usage(rv ? stderr : stdout, basename(argv[0]));
1724         goto out;
1725 }