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