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