tools: kwboot: Fix initializing tty device
[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         rc = tcgetattr(fd, &tio);
652         if (rc)
653                 goto out;
654
655         cfmakeraw(&tio);
656         tio.c_cflag |= CREAD|CLOCAL;
657         tio.c_cc[VMIN] = 1;
658         tio.c_cc[VTIME] = 10;
659
660         rc = tcsetattr(fd, TCSANOW, &tio);
661         if (rc)
662                 goto out;
663
664         rc = kwboot_tty_change_baudrate(fd, baudrate);
665         if (rc)
666                 goto out;
667
668         rc = fd;
669 out:
670         if (rc < 0) {
671                 if (fd >= 0)
672                         close(fd);
673         }
674
675         return rc;
676 }
677
678 static int
679 kwboot_bootmsg(int tty, void *msg)
680 {
681         int rc;
682         char c;
683         int count;
684
685         if (msg == NULL)
686                 kwboot_printv("Please reboot the target into UART boot mode...");
687         else
688                 kwboot_printv("Sending boot message. Please reboot the target...");
689
690         do {
691                 rc = tcflush(tty, TCIOFLUSH);
692                 if (rc)
693                         break;
694
695                 for (count = 0; count < 128; count++) {
696                         rc = kwboot_tty_send(tty, msg, 8);
697                         if (rc) {
698                                 usleep(msg_req_delay * 1000);
699                                 continue;
700                         }
701                 }
702
703                 rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo);
704
705                 kwboot_spinner();
706
707         } while (rc || c != NAK);
708
709         kwboot_printv("\n");
710
711         return rc;
712 }
713
714 static int
715 kwboot_debugmsg(int tty, void *msg)
716 {
717         int rc;
718
719         kwboot_printv("Sending debug message. Please reboot the target...");
720
721         do {
722                 char buf[16];
723
724                 rc = tcflush(tty, TCIOFLUSH);
725                 if (rc)
726                         break;
727
728                 rc = kwboot_tty_send(tty, msg, 8);
729                 if (rc) {
730                         usleep(msg_req_delay * 1000);
731                         continue;
732                 }
733
734                 rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo);
735
736                 kwboot_spinner();
737
738         } while (rc);
739
740         kwboot_printv("\n");
741
742         return rc;
743 }
744
745 static size_t
746 kwboot_xm_makeblock(struct kwboot_block *block, const void *data,
747                     size_t size, int pnum)
748 {
749         size_t i, n;
750
751         block->soh = SOH;
752         block->pnum = pnum;
753         block->_pnum = ~block->pnum;
754
755         n = size < KWBOOT_XM_BLKSZ ? size : KWBOOT_XM_BLKSZ;
756         memcpy(&block->data[0], data, n);
757         memset(&block->data[n], 0, KWBOOT_XM_BLKSZ - n);
758
759         block->csum = 0;
760         for (i = 0; i < n; i++)
761                 block->csum += block->data[i];
762
763         return n;
764 }
765
766 static uint64_t
767 _now(void)
768 {
769         struct timespec ts;
770
771         if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
772                 static int err_print;
773
774                 if (!err_print) {
775                         perror("clock_gettime() does not work");
776                         err_print = 1;
777                 }
778
779                 /* this will just make the timeout not work */
780                 return -1ULL;
781         }
782
783         return ts.tv_sec * 1000ULL + (ts.tv_nsec + 500000) / 1000000;
784 }
785
786 static int
787 _is_xm_reply(char c)
788 {
789         return c == ACK || c == NAK || c == CAN;
790 }
791
792 static int
793 _xm_reply_to_error(int c)
794 {
795         int rc = -1;
796
797         switch (c) {
798         case ACK:
799                 rc = 0;
800                 break;
801         case NAK:
802                 errno = EBADMSG;
803                 break;
804         case CAN:
805                 errno = ECANCELED;
806                 break;
807         default:
808                 errno = EPROTO;
809                 break;
810         }
811
812         return rc;
813 }
814
815 static int
816 kwboot_baud_magic_handle(int fd, char c, int baudrate)
817 {
818         static size_t rcv_len;
819
820         if (rcv_len < sizeof(kwb_baud_magic)) {
821                 /* try to recognize whole magic word */
822                 if (c == kwb_baud_magic[rcv_len]) {
823                         rcv_len++;
824                 } else {
825                         printf("%.*s%c", (int)rcv_len, kwb_baud_magic, c);
826                         fflush(stdout);
827                         rcv_len = 0;
828                 }
829         }
830
831         if (rcv_len == sizeof(kwb_baud_magic)) {
832                 /* magic word received */
833                 kwboot_printv("\nChanging baudrate to %d Bd\n", baudrate);
834
835                 return kwboot_tty_change_baudrate(fd, baudrate) ? : 1;
836         } else {
837                 return 0;
838         }
839 }
840
841 static int
842 kwboot_xm_recv_reply(int fd, char *c, int allow_non_xm, int *non_xm_print,
843                      int baudrate, int *baud_changed)
844 {
845         int timeout = allow_non_xm ? KWBOOT_HDR_RSP_TIMEO : blk_rsp_timeo;
846         uint64_t recv_until = _now() + timeout;
847         int rc;
848
849         if (non_xm_print)
850                 *non_xm_print = 0;
851         if (baud_changed)
852                 *baud_changed = 0;
853
854         while (1) {
855                 rc = kwboot_tty_recv(fd, c, 1, timeout);
856                 if (rc) {
857                         if (errno != ETIMEDOUT)
858                                 return rc;
859                         else if (allow_non_xm && *non_xm_print)
860                                 return -1;
861                         else
862                                 *c = NAK;
863                 }
864
865                 /* If received xmodem reply, end. */
866                 if (_is_xm_reply(*c))
867                         break;
868
869                 /*
870                  * If receiving/printing non-xmodem text output is allowed and
871                  * such a byte was received, we want to increase receiving time
872                  * and either:
873                  * - print the byte, if it is not part of baudrate change magic
874                  *   sequence while baudrate change was requested (-B option)
875                  * - change baudrate
876                  * Otherwise decrease timeout by time elapsed.
877                  */
878                 if (allow_non_xm) {
879                         recv_until = _now() + timeout;
880
881                         if (baudrate && !*baud_changed) {
882                                 rc = kwboot_baud_magic_handle(fd, *c, baudrate);
883                                 if (rc == 1)
884                                         *baud_changed = 1;
885                                 else if (!rc)
886                                         *non_xm_print = 1;
887                                 else
888                                         return rc;
889                         } else if (!baudrate || !*baud_changed) {
890                                 putchar(*c);
891                                 fflush(stdout);
892                                 *non_xm_print = 1;
893                         }
894                 } else {
895                         timeout = recv_until - _now();
896                         if (timeout < 0) {
897                                 errno = ETIMEDOUT;
898                                 return -1;
899                         }
900                 }
901         }
902
903         return 0;
904 }
905
906 static int
907 kwboot_xm_sendblock(int fd, struct kwboot_block *block, int allow_non_xm,
908                     int *done_print, int baudrate)
909 {
910         int non_xm_print, baud_changed;
911         int rc, err, retries;
912         char c;
913
914         *done_print = 0;
915
916         retries = 16;
917         do {
918                 rc = kwboot_tty_send(fd, block, sizeof(*block));
919                 if (rc)
920                         return rc;
921
922                 if (allow_non_xm && !*done_print) {
923                         kwboot_progress(100, '.');
924                         kwboot_printv("Done\n");
925                         *done_print = 1;
926                 }
927
928                 rc = kwboot_xm_recv_reply(fd, &c, allow_non_xm, &non_xm_print,
929                                           baudrate, &baud_changed);
930                 if (rc)
931                         goto can;
932
933                 if (!allow_non_xm && c != ACK)
934                         kwboot_progress(-1, '+');
935         } while (c == NAK && retries-- > 0);
936
937         if (non_xm_print)
938                 kwboot_printv("\n");
939
940         if (allow_non_xm && baudrate && !baud_changed) {
941                 fprintf(stderr, "Baudrate was not changed\n");
942                 rc = -1;
943                 errno = EPROTO;
944                 goto can;
945         }
946
947         return _xm_reply_to_error(c);
948 can:
949         err = errno;
950         kwboot_tty_send_char(fd, CAN);
951         kwboot_printv("\n");
952         errno = err;
953         return rc;
954 }
955
956 static int
957 kwboot_xm_finish(int fd)
958 {
959         int rc, retries;
960         char c;
961
962         kwboot_printv("Finishing transfer\n");
963
964         retries = 16;
965         do {
966                 rc = kwboot_tty_send_char(fd, EOT);
967                 if (rc)
968                         return rc;
969
970                 rc = kwboot_xm_recv_reply(fd, &c, 0, NULL, 0, NULL);
971                 if (rc)
972                         return rc;
973         } while (c == NAK && retries-- > 0);
974
975         return _xm_reply_to_error(c);
976 }
977
978 static int
979 kwboot_xmodem_one(int tty, int *pnum, int header, const uint8_t *data,
980                   size_t size, int baudrate)
981 {
982         int done_print = 0;
983         size_t sent, left;
984         int rc;
985
986         kwboot_printv("Sending boot image %s (%zu bytes)...\n",
987                       header ? "header" : "data", size);
988
989         left = size;
990         sent = 0;
991
992         while (sent < size) {
993                 struct kwboot_block block;
994                 int last_block;
995                 size_t blksz;
996
997                 blksz = kwboot_xm_makeblock(&block, data, left, (*pnum)++);
998                 data += blksz;
999
1000                 last_block = (left <= blksz);
1001
1002                 rc = kwboot_xm_sendblock(tty, &block, header && last_block,
1003                                          &done_print, baudrate);
1004                 if (rc)
1005                         goto out;
1006
1007                 sent += blksz;
1008                 left -= blksz;
1009
1010                 if (!done_print)
1011                         kwboot_progress(sent * 100 / size, '.');
1012         }
1013
1014         if (!done_print)
1015                 kwboot_printv("Done\n");
1016
1017         return 0;
1018 out:
1019         kwboot_printv("\n");
1020         return rc;
1021 }
1022
1023 static int
1024 kwboot_xmodem(int tty, const void *_img, size_t size, int baudrate)
1025 {
1026         const uint8_t *img = _img;
1027         int rc, pnum;
1028         size_t hdrsz;
1029
1030         hdrsz = kwbheader_size(img);
1031
1032         kwboot_printv("Waiting 2s and flushing tty\n");
1033         sleep(2); /* flush isn't effective without it */
1034         tcflush(tty, TCIOFLUSH);
1035
1036         pnum = 1;
1037
1038         rc = kwboot_xmodem_one(tty, &pnum, 1, img, hdrsz, baudrate);
1039         if (rc)
1040                 return rc;
1041
1042         img += hdrsz;
1043         size -= hdrsz;
1044
1045         rc = kwboot_xmodem_one(tty, &pnum, 0, img, size, 0);
1046         if (rc)
1047                 return rc;
1048
1049         rc = kwboot_xm_finish(tty);
1050         if (rc)
1051                 return rc;
1052
1053         if (baudrate) {
1054                 char buf[sizeof(kwb_baud_magic)];
1055
1056                 /* Wait 1s for baudrate change magic */
1057                 rc = kwboot_tty_recv(tty, buf, sizeof(buf), 1000);
1058                 if (rc)
1059                         return rc;
1060
1061                 if (memcmp(buf, kwb_baud_magic, sizeof(buf))) {
1062                         errno = EPROTO;
1063                         return -1;
1064                 }
1065
1066                 kwboot_printv("\nChanging baudrate back to 115200 Bd\n\n");
1067                 rc = kwboot_tty_change_baudrate(tty, 115200);
1068                 if (rc)
1069                         return rc;
1070         }
1071
1072         return 0;
1073 }
1074
1075 static int
1076 kwboot_term_pipe(int in, int out, const char *quit, int *s)
1077 {
1078         ssize_t nin;
1079         char _buf[128], *buf = _buf;
1080
1081         nin = read(in, buf, sizeof(_buf));
1082         if (nin <= 0)
1083                 return -1;
1084
1085         if (quit) {
1086                 int i;
1087
1088                 for (i = 0; i < nin; i++) {
1089                         if (*buf == quit[*s]) {
1090                                 (*s)++;
1091                                 if (!quit[*s])
1092                                         return 0;
1093                                 buf++;
1094                                 nin--;
1095                         } else {
1096                                 if (kwboot_write(out, quit, *s) < 0)
1097                                         return -1;
1098                                 *s = 0;
1099                         }
1100                 }
1101         }
1102
1103         if (kwboot_write(out, buf, nin) < 0)
1104                 return -1;
1105
1106         return 0;
1107 }
1108
1109 static int
1110 kwboot_terminal(int tty)
1111 {
1112         int rc, in, s;
1113         const char *quit = "\34c";
1114         struct termios otio, tio;
1115
1116         rc = -1;
1117
1118         in = STDIN_FILENO;
1119         if (isatty(in)) {
1120                 rc = tcgetattr(in, &otio);
1121                 if (!rc) {
1122                         tio = otio;
1123                         cfmakeraw(&tio);
1124                         rc = tcsetattr(in, TCSANOW, &tio);
1125                 }
1126                 if (rc) {
1127                         perror("tcsetattr");
1128                         goto out;
1129                 }
1130
1131                 kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n",
1132                               quit[0]|0100, quit[1]);
1133         } else
1134                 in = -1;
1135
1136         rc = 0;
1137         s = 0;
1138
1139         do {
1140                 fd_set rfds;
1141                 int nfds = 0;
1142
1143                 FD_SET(tty, &rfds);
1144                 nfds = nfds < tty ? tty : nfds;
1145
1146                 if (in >= 0) {
1147                         FD_SET(in, &rfds);
1148                         nfds = nfds < in ? in : nfds;
1149                 }
1150
1151                 nfds = select(nfds + 1, &rfds, NULL, NULL, NULL);
1152                 if (nfds < 0)
1153                         break;
1154
1155                 if (FD_ISSET(tty, &rfds)) {
1156                         rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL);
1157                         if (rc)
1158                                 break;
1159                 }
1160
1161                 if (in >= 0 && FD_ISSET(in, &rfds)) {
1162                         rc = kwboot_term_pipe(in, tty, quit, &s);
1163                         if (rc)
1164                                 break;
1165                 }
1166         } while (quit[s] != 0);
1167
1168         if (in >= 0)
1169                 tcsetattr(in, TCSANOW, &otio);
1170         printf("\n");
1171 out:
1172         return rc;
1173 }
1174
1175 static void *
1176 kwboot_read_image(const char *path, size_t *size, size_t reserve)
1177 {
1178         int rc, fd;
1179         struct stat st;
1180         void *img;
1181         off_t tot;
1182
1183         rc = -1;
1184         img = NULL;
1185
1186         fd = open(path, O_RDONLY);
1187         if (fd < 0)
1188                 goto out;
1189
1190         rc = fstat(fd, &st);
1191         if (rc)
1192                 goto out;
1193
1194         img = malloc(st.st_size + reserve);
1195         if (!img)
1196                 goto out;
1197
1198         tot = 0;
1199         while (tot < st.st_size) {
1200                 ssize_t rd = read(fd, img + tot, st.st_size - tot);
1201
1202                 if (rd < 0)
1203                         goto out;
1204
1205                 tot += rd;
1206
1207                 if (!rd && tot < st.st_size) {
1208                         errno = EIO;
1209                         goto out;
1210                 }
1211         }
1212
1213         rc = 0;
1214         *size = st.st_size;
1215 out:
1216         if (rc && img) {
1217                 free(img);
1218                 img = NULL;
1219         }
1220         if (fd >= 0)
1221                 close(fd);
1222
1223         return img;
1224 }
1225
1226 static uint8_t
1227 kwboot_hdr_csum8(const void *hdr)
1228 {
1229         const uint8_t *data = hdr;
1230         uint8_t csum;
1231         size_t size;
1232
1233         size = kwbheader_size_for_csum(hdr);
1234
1235         for (csum = 0; size-- > 0; data++)
1236                 csum += *data;
1237
1238         return csum;
1239 }
1240
1241 static int
1242 kwboot_img_is_secure(void *img)
1243 {
1244         struct opt_hdr_v1 *ohdr;
1245
1246         for_each_opt_hdr_v1 (ohdr, img)
1247                 if (ohdr->headertype == OPT_HDR_V1_SECURE_TYPE)
1248                         return 1;
1249
1250         return 0;
1251 }
1252
1253 static void *
1254 kwboot_img_grow_data_left(void *img, size_t *size, size_t grow)
1255 {
1256         uint32_t hdrsz, datasz, srcaddr;
1257         struct main_hdr_v1 *hdr = img;
1258         uint8_t *data;
1259
1260         srcaddr = le32_to_cpu(hdr->srcaddr);
1261
1262         hdrsz = kwbheader_size(hdr);
1263         data = (uint8_t *)img + srcaddr;
1264         datasz = *size - srcaddr;
1265
1266         /* only move data if there is not enough space */
1267         if (hdrsz + grow > srcaddr) {
1268                 size_t need = hdrsz + grow - srcaddr;
1269
1270                 /* move data by enough bytes */
1271                 memmove(data + need, data, datasz);
1272                 *size += need;
1273                 srcaddr += need;
1274         }
1275
1276         srcaddr -= grow;
1277         hdr->srcaddr = cpu_to_le32(srcaddr);
1278         hdr->destaddr = cpu_to_le32(le32_to_cpu(hdr->destaddr) - grow);
1279         hdr->blocksize = cpu_to_le32(le32_to_cpu(hdr->blocksize) + grow);
1280
1281         return (uint8_t *)img + srcaddr;
1282 }
1283
1284 static void
1285 kwboot_img_grow_hdr(void *img, size_t *size, size_t grow)
1286 {
1287         uint32_t hdrsz, datasz, srcaddr;
1288         struct main_hdr_v1 *hdr = img;
1289         uint8_t *data;
1290
1291         srcaddr = le32_to_cpu(hdr->srcaddr);
1292
1293         hdrsz = kwbheader_size(img);
1294         data = (uint8_t *)img + srcaddr;
1295         datasz = *size - srcaddr;
1296
1297         /* only move data if there is not enough space */
1298         if (hdrsz + grow > srcaddr) {
1299                 size_t need = hdrsz + grow - srcaddr;
1300
1301                 /* move data by enough bytes */
1302                 memmove(data + need, data, datasz);
1303
1304                 hdr->srcaddr = cpu_to_le32(srcaddr + need);
1305                 *size += need;
1306         }
1307
1308         if (kwbimage_version(img) == 1) {
1309                 hdrsz += grow;
1310                 hdr->headersz_msb = hdrsz >> 16;
1311                 hdr->headersz_lsb = cpu_to_le16(hdrsz & 0xffff);
1312         }
1313 }
1314
1315 static void *
1316 kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz)
1317 {
1318         struct main_hdr_v1 *hdr = img;
1319         struct opt_hdr_v1 *ohdr;
1320         uint32_t ohdrsz;
1321
1322         ohdrsz = binsz + 8 + sizeof(*ohdr);
1323         kwboot_img_grow_hdr(img, size, ohdrsz);
1324
1325         if (hdr->ext & 0x1) {
1326                 for_each_opt_hdr_v1 (ohdr, img)
1327                         if (opt_hdr_v1_next(ohdr) == NULL)
1328                                 break;
1329
1330                 *opt_hdr_v1_ext(ohdr) |= 1;
1331                 ohdr = opt_hdr_v1_next(ohdr);
1332         } else {
1333                 hdr->ext |= 1;
1334                 ohdr = (void *)(hdr + 1);
1335         }
1336
1337         ohdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1338         ohdr->headersz_msb = ohdrsz >> 16;
1339         ohdr->headersz_lsb = cpu_to_le16(ohdrsz & 0xffff);
1340
1341         memset(&ohdr->data[0], 0, ohdrsz - sizeof(*ohdr));
1342
1343         return &ohdr->data[4];
1344 }
1345
1346 static void
1347 _copy_baudrate_change_code(struct main_hdr_v1 *hdr, void *dst, int pre,
1348                            int old_baud, int new_baud)
1349 {
1350         size_t codesz = sizeof(kwboot_baud_code);
1351         uint8_t *code = dst;
1352
1353         if (pre) {
1354                 size_t presz = sizeof(kwboot_pre_baud_code);
1355
1356                 /*
1357                  * We need to prepend code that loads lr register with original
1358                  * value of hdr->execaddr. We do this by putting the original
1359                  * exec address before the code that loads it relatively from
1360                  * it's beginning.
1361                  * Afterwards we change the exec address to this code (which is
1362                  * at offset 4, because the first 4 bytes contain the original
1363                  * exec address).
1364                  */
1365                 memcpy(code, kwboot_pre_baud_code, presz);
1366                 *(uint32_t *)code = hdr->execaddr;
1367
1368                 hdr->execaddr = cpu_to_le32(le32_to_cpu(hdr->destaddr) + 4);
1369
1370                 code += presz;
1371         }
1372
1373         memcpy(code, kwboot_baud_code, codesz - 8);
1374         *(uint32_t *)(code + codesz - 8) = cpu_to_le32(old_baud);
1375         *(uint32_t *)(code + codesz - 4) = cpu_to_le32(new_baud);
1376 }
1377
1378 static int
1379 kwboot_img_patch(void *img, size_t *size, int baudrate)
1380 {
1381         int rc;
1382         struct main_hdr_v1 *hdr;
1383         uint32_t srcaddr;
1384         uint8_t csum;
1385         size_t hdrsz;
1386         int image_ver;
1387         int is_secure;
1388
1389         rc = -1;
1390         hdr = img;
1391
1392         if (*size < sizeof(struct main_hdr_v1)) {
1393                 errno = EINVAL;
1394                 goto out;
1395         }
1396
1397         image_ver = kwbimage_version(img);
1398         if (image_ver != 0 && image_ver != 1) {
1399                 fprintf(stderr, "Invalid image header version\n");
1400                 errno = EINVAL;
1401                 goto out;
1402         }
1403
1404         hdrsz = kwbheader_size(hdr);
1405
1406         if (*size < hdrsz) {
1407                 errno = EINVAL;
1408                 goto out;
1409         }
1410
1411         csum = kwboot_hdr_csum8(hdr) - hdr->checksum;
1412         if (csum != hdr->checksum) {
1413                 errno = EINVAL;
1414                 goto out;
1415         }
1416
1417         if (image_ver == 0) {
1418                 struct main_hdr_v0 *hdr_v0 = img;
1419
1420                 hdr_v0->nandeccmode = IBR_HDR_ECC_DISABLED;
1421                 hdr_v0->nandpagesize = 0;
1422         }
1423
1424         srcaddr = le32_to_cpu(hdr->srcaddr);
1425
1426         switch (hdr->blockid) {
1427         case IBR_HDR_SATA_ID:
1428                 if (srcaddr < 1) {
1429                         errno = EINVAL;
1430                         goto out;
1431                 }
1432                 hdr->srcaddr = cpu_to_le32((srcaddr - 1) * 512);
1433                 break;
1434
1435         case IBR_HDR_SDIO_ID:
1436                 hdr->srcaddr = cpu_to_le32(srcaddr * 512);
1437                 break;
1438
1439         case IBR_HDR_PEX_ID:
1440                 if (srcaddr == 0xFFFFFFFF)
1441                         hdr->srcaddr = cpu_to_le32(hdrsz);
1442                 break;
1443
1444         case IBR_HDR_SPI_ID:
1445                 if (hdr->destaddr == cpu_to_le32(0xFFFFFFFF)) {
1446                         kwboot_printv("Patching destination and execution addresses from SPI/NOR XIP area to DDR area 0x00800000\n");
1447                         hdr->destaddr = cpu_to_le32(0x00800000);
1448                         hdr->execaddr = cpu_to_le32(0x00800000);
1449                 }
1450                 break;
1451         }
1452
1453         if (hdrsz > le32_to_cpu(hdr->srcaddr) ||
1454             *size < le32_to_cpu(hdr->srcaddr) + le32_to_cpu(hdr->blocksize)) {
1455                 errno = EINVAL;
1456                 goto out;
1457         }
1458
1459         is_secure = kwboot_img_is_secure(img);
1460
1461         if (hdr->blockid != IBR_HDR_UART_ID) {
1462                 if (is_secure) {
1463                         fprintf(stderr,
1464                                 "Image has secure header with signature for non-UART booting\n");
1465                         errno = EINVAL;
1466                         goto out;
1467                 }
1468
1469                 kwboot_printv("Patching image boot signature to UART\n");
1470                 hdr->blockid = IBR_HDR_UART_ID;
1471         }
1472
1473         if (baudrate) {
1474                 uint32_t codesz = sizeof(kwboot_baud_code);
1475                 void *code;
1476
1477                 if (image_ver == 0) {
1478                         fprintf(stderr,
1479                                 "Cannot inject code for changing baudrate into v0 image header\n");
1480                         errno = EINVAL;
1481                         goto out;
1482                 }
1483
1484                 if (is_secure) {
1485                         fprintf(stderr,
1486                                 "Cannot inject code for changing baudrate into image with secure header\n");
1487                         errno = EINVAL;
1488                         goto out;
1489                 }
1490
1491                 /*
1492                  * First inject code that changes the baudrate from the default
1493                  * value of 115200 Bd to requested value. This code is inserted
1494                  * as a new opt hdr, so it is executed by BootROM after the
1495                  * header part is received.
1496                  */
1497                 kwboot_printv("Injecting binary header code for changing baudrate to %d Bd\n",
1498                               baudrate);
1499
1500                 code = kwboot_add_bin_ohdr_v1(img, size, codesz);
1501                 _copy_baudrate_change_code(hdr, code, 0, 115200, baudrate);
1502
1503                 /*
1504                  * Now inject code that changes the baudrate back to 115200 Bd.
1505                  * This code is prepended to the data part of the image, so it
1506                  * is executed before U-Boot proper.
1507                  */
1508                 kwboot_printv("Injecting code for changing baudrate back\n");
1509
1510                 codesz += sizeof(kwboot_pre_baud_code);
1511                 code = kwboot_img_grow_data_left(img, size, codesz);
1512                 _copy_baudrate_change_code(hdr, code, 1, baudrate, 115200);
1513
1514                 /* recompute header size */
1515                 hdrsz = kwbheader_size(hdr);
1516         }
1517
1518         if (hdrsz % KWBOOT_XM_BLKSZ) {
1519                 size_t offset = (KWBOOT_XM_BLKSZ - hdrsz % KWBOOT_XM_BLKSZ) %
1520                                 KWBOOT_XM_BLKSZ;
1521
1522                 if (is_secure) {
1523                         fprintf(stderr, "Cannot align image with secure header\n");
1524                         errno = EINVAL;
1525                         goto out;
1526                 }
1527
1528                 kwboot_printv("Aligning image header to Xmodem block size\n");
1529                 kwboot_img_grow_hdr(img, size, offset);
1530         }
1531
1532         hdr->checksum = kwboot_hdr_csum8(hdr) - csum;
1533
1534         *size = le32_to_cpu(hdr->srcaddr) + le32_to_cpu(hdr->blocksize);
1535         rc = 0;
1536 out:
1537         return rc;
1538 }
1539
1540 static void
1541 kwboot_usage(FILE *stream, char *progname)
1542 {
1543         fprintf(stream, "kwboot version %s\n", PLAIN_VERSION);
1544         fprintf(stream,
1545                 "Usage: %s [OPTIONS] [-b <image> | -D <image> ] [-B <baud> ] <TTY>\n",
1546                 progname);
1547         fprintf(stream, "\n");
1548         fprintf(stream,
1549                 "  -b <image>: boot <image> with preamble (Kirkwood, Armada 370/XP)\n");
1550         fprintf(stream,
1551                 "  -D <image>: boot <image> without preamble (Dove)\n");
1552         fprintf(stream, "  -d: enter debug mode\n");
1553         fprintf(stream, "  -a: use timings for Armada XP\n");
1554         fprintf(stream, "  -q <req-delay>:  use specific request-delay\n");
1555         fprintf(stream, "  -s <resp-timeo>: use specific response-timeout\n");
1556         fprintf(stream,
1557                 "  -o <block-timeo>: use specific xmodem block timeout\n");
1558         fprintf(stream, "\n");
1559         fprintf(stream, "  -t: mini terminal\n");
1560         fprintf(stream, "\n");
1561         fprintf(stream, "  -B <baud>: set baud rate\n");
1562         fprintf(stream, "\n");
1563 }
1564
1565 int
1566 main(int argc, char **argv)
1567 {
1568         const char *ttypath, *imgpath;
1569         int rv, rc, tty, term;
1570         void *bootmsg;
1571         void *debugmsg;
1572         void *img;
1573         size_t size;
1574         size_t after_img_rsv;
1575         int baudrate;
1576
1577         rv = 1;
1578         tty = -1;
1579         bootmsg = NULL;
1580         debugmsg = NULL;
1581         imgpath = NULL;
1582         img = NULL;
1583         term = 0;
1584         size = 0;
1585         after_img_rsv = KWBOOT_XM_BLKSZ;
1586         baudrate = 115200;
1587
1588         kwboot_verbose = isatty(STDOUT_FILENO);
1589
1590         do {
1591                 int c = getopt(argc, argv, "hb:ptaB:dD:q:s:o:");
1592                 if (c < 0)
1593                         break;
1594
1595                 switch (c) {
1596                 case 'b':
1597                         bootmsg = kwboot_msg_boot;
1598                         imgpath = optarg;
1599                         break;
1600
1601                 case 'D':
1602                         bootmsg = NULL;
1603                         imgpath = optarg;
1604                         break;
1605
1606                 case 'd':
1607                         debugmsg = kwboot_msg_debug;
1608                         break;
1609
1610                 case 'p':
1611                         /* nop, for backward compatibility */
1612                         break;
1613
1614                 case 't':
1615                         term = 1;
1616                         break;
1617
1618                 case 'a':
1619                         msg_req_delay = KWBOOT_MSG_REQ_DELAY_AXP;
1620                         msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO_AXP;
1621                         break;
1622
1623                 case 'q':
1624                         msg_req_delay = atoi(optarg);
1625                         break;
1626
1627                 case 's':
1628                         msg_rsp_timeo = atoi(optarg);
1629                         break;
1630
1631                 case 'o':
1632                         blk_rsp_timeo = atoi(optarg);
1633                         break;
1634
1635                 case 'B':
1636                         baudrate = atoi(optarg);
1637                         break;
1638
1639                 case 'h':
1640                         rv = 0;
1641                 default:
1642                         goto usage;
1643                 }
1644         } while (1);
1645
1646         if (!bootmsg && !term && !debugmsg)
1647                 goto usage;
1648
1649         if (argc - optind < 1)
1650                 goto usage;
1651
1652         ttypath = argv[optind++];
1653
1654         tty = kwboot_open_tty(ttypath, imgpath ? 115200 : baudrate);
1655         if (tty < 0) {
1656                 perror(ttypath);
1657                 goto out;
1658         }
1659
1660         if (baudrate == 115200)
1661                 /* do not change baudrate during Xmodem to the same value */
1662                 baudrate = 0;
1663         else
1664                 /* ensure we have enough space for baudrate change code */
1665                 after_img_rsv += KWBOOT_BAUDRATE_BIN_HEADER_SZ +
1666                                  sizeof(kwboot_pre_baud_code) +
1667                                  sizeof(kwboot_baud_code);
1668
1669         if (imgpath) {
1670                 img = kwboot_read_image(imgpath, &size, after_img_rsv);
1671                 if (!img) {
1672                         perror(imgpath);
1673                         goto out;
1674                 }
1675
1676                 rc = kwboot_img_patch(img, &size, baudrate);
1677                 if (rc) {
1678                         fprintf(stderr, "%s: Invalid image.\n", imgpath);
1679                         goto out;
1680                 }
1681         }
1682
1683         if (debugmsg) {
1684                 rc = kwboot_debugmsg(tty, debugmsg);
1685                 if (rc) {
1686                         perror("debugmsg");
1687                         goto out;
1688                 }
1689         } else if (bootmsg) {
1690                 rc = kwboot_bootmsg(tty, bootmsg);
1691                 if (rc) {
1692                         perror("bootmsg");
1693                         goto out;
1694                 }
1695         }
1696
1697         if (img) {
1698                 rc = kwboot_xmodem(tty, img, size, baudrate);
1699                 if (rc) {
1700                         perror("xmodem");
1701                         goto out;
1702                 }
1703         }
1704
1705         if (term) {
1706                 rc = kwboot_terminal(tty);
1707                 if (rc && !(errno == EINTR)) {
1708                         perror("terminal");
1709                         goto out;
1710                 }
1711         }
1712
1713         rv = 0;
1714 out:
1715         if (tty >= 0)
1716                 close(tty);
1717
1718         if (img)
1719                 free(img);
1720
1721         return rv;
1722
1723 usage:
1724         kwboot_usage(rv ? stderr : stdout, basename(argv[0]));
1725         goto out;
1726 }