3 /* (C) 2010,2018 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2010 by Steve Markgraf <steve@steve-m.de>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
42 #include <osmocom/core/linuxlist.h>
43 #include <osmocom/core/select.h>
44 #include <osmocom/core/serial.h>
45 #include <osmocom/core/talloc.h>
46 #include <osmocom/core/timer.h>
47 #include <osmocom/core/application.h>
48 #include <osmocom/core/socket.h>
50 #include <arpa/inet.h>
52 #define MODEM_BAUDRATE B115200
53 #define MAX_DNLOAD_SIZE 0xFFFF
54 #define MAX_HDR_SIZE 128
55 #define MAGIC_OFFSET 0x3be2
57 #define DEFAULT_BEACON_INTERVAL 50000
58 #define ROMLOAD_INIT_BAUDRATE B19200
59 #define ROMLOAD_DL_BAUDRATE B115200
60 #define ROMLOAD_BLOCK_HDR_LEN 10
61 #define ROMLOAD_ADDRESS 0x820000
63 #define MTK_INIT_BAUDRATE B19200
64 #define MTK_ADDRESS 0x40001400
65 #define MTK_BLOCK_SIZE 1024
67 struct tool_server
*tool_server_for_dlci
[256];
70 * a connection from some other tool
72 struct tool_connection
{
73 struct tool_server
*server
;
74 struct llist_head entry
;
84 struct llist_head connections
;
95 WAITING_IDENTIFICATION
,
101 WAITING_CHECKSUM_ACK
,
115 MTK_WAIT_BRANCH_CMD_ACK
,
116 MTK_WAIT_BRANCH_ADDR_ACK
,
132 enum dnload_state state
;
133 enum romload_state romload_state
;
134 enum mtk_state mtk_state
;
135 enum dnload_mode mode
, previous_mode
;
136 struct osmo_fd serial_fd
;
146 /* data to be downloaded */
152 /* romload: block to be downloaded */
155 uint8_t block_number
;
156 uint16_t block_payload_size
;
157 int romload_dl_checksum
;
159 uint8_t load_address
[4];
161 uint8_t mtk_send_size
[4];
165 struct tool_server layer2_server
;
166 struct tool_server loader_server
;
170 static struct dnload dnload
;
171 static struct osmo_timer_list tick_timer
;
173 /* Compal ramloader specific */
174 static const uint8_t phone_prompt1
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
175 static const uint8_t dnload_cmd
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
176 static const uint8_t phone_prompt2
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
177 static const uint8_t phone_ack
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
178 static const uint8_t phone_nack_magic
[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
179 static const uint8_t phone_nack
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
180 static const uint8_t ftmtool
[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c };
181 static const uint8_t phone_magic
[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */
183 /* The C123 has a hard-coded check inside the ramloader that requires the
184 * following bytes to be always the first four bytes of the image */
185 static const uint8_t data_hdr_c123
[] = { 0xee, 0x4c, 0x9f, 0x63 };
187 /* The C155 doesn't have some strange restriction on what the first four bytes
188 * have to be, but it starts the ramloader in THUMB mode. We use the following
189 * four bytes to switch back to ARM mode:
191 800102: 46c0 nop ; (mov r8, r8)
193 static const uint8_t data_hdr_c155
[] = { 0x78, 0x47, 0xc0, 0x46 };
195 /* small loader that enables the bootrom and executes the TI romloader:
197 * ldr r1, =0x000a0000
201 * ldr r1, =0xfffffb10
206 static const uint8_t chainloader
[] = {
207 0x0a, 0x18, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff,
208 0x1a, 0x08, 0x10, 0x9f, 0xe5, 0x01, 0x2c, 0xa0, 0xe3, 0xb0, 0x20,
209 0xc1, 0xe1, 0x00, 0xf0, 0xa0, 0xe3, 0x10, 0xfb, 0xff, 0xff,
212 /* Calypso romloader specific */
213 static const uint8_t romload_ident_cmd
[] = { 0x3c, 0x69 }; /* <i */
214 static const uint8_t __attribute__((__unused__
)) romload_abort_cmd
[] = { 0x3c, 0x61 }; /* <a */
215 static const uint8_t romload_write_cmd
[] = { 0x3c, 0x77 }; /* <w */
216 static const uint8_t romload_checksum_cmd
[] = { 0x3c, 0x63 }; /* <c */
217 static const uint8_t romload_branch_cmd
[] = { 0x3c, 0x62 }; /* <b */
218 static const uint8_t romload_ident_ack
[] = { 0x3e, 0x69 }; /* >i */
219 static const uint8_t romload_param_ack
[] = { 0x3e, 0x70 }; /* >p */
220 static const uint8_t __attribute__((__unused__
)) romload_param_nack
[] = { 0x3e, 0x50 }; /* >P */
221 static const uint8_t romload_block_ack
[] = { 0x3e, 0x77 }; /* >w */
222 static const uint8_t romload_block_nack
[] = { 0x3e, 0x57 }; /* >W */
223 static const uint8_t romload_checksum_ack
[] = { 0x3e, 0x63 }; /* >c */
224 static const uint8_t romload_checksum_nack
[] = { 0x3e, 0x43 }; /* >C */
225 static const uint8_t romload_branch_ack
[] = { 0x3e, 0x62 }; /* >b */
226 static const uint8_t romload_branch_nack
[] = { 0x3e, 0x42 }; /* >B */
228 /* romload_param: {"<p", uint8_t baudrate, uint8_t dpll, uint16_t memory_config,
229 * uint8_t strobe_af, uint32_t uart_timeout} */
231 static const uint8_t romload_param
[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04,
232 0x00, 0x00, 0x00, 0x00, 0x00 };
234 /* MTK romloader specific */
235 static const uint8_t mtk_init_cmd
[] = { 0xa0, 0x0a, 0x50, 0x05 };
236 static const uint8_t mtk_init_resp
[] = { 0x5f, 0xf5, 0xaf, 0xfa };
237 static const uint8_t mtk_command
[] = { 0xa1, 0xa2, 0xa4, 0xa8 };
239 static void beacon_timer_cb(void *p
)
243 if (dnload
.romload_state
== WAITING_IDENTIFICATION
) {
244 rc
= write(dnload
.serial_fd
.fd
, romload_ident_cmd
,
245 sizeof(romload_ident_cmd
));
247 if (!(rc
== sizeof(romload_ident_cmd
)))
248 printf("Error sending identification beacon\n");
250 osmo_timer_schedule(p
, 0, dnload
.beacon_interval
);
254 static void mtk_timer_cb(void *p
)
258 if (dnload
.mtk_state
== MTK_INIT_1
) {
259 printf("Sending MTK romloader beacon...\n");
260 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[0], 1);
263 printf("Error sending identification beacon\n");
265 osmo_timer_schedule(p
, 0, dnload
.beacon_interval
);
269 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
270 int read_file(const char *filename
, int chainload
)
274 const uint8_t *hdr
= NULL
;
280 uint8_t running_xor
= 0x02;
283 fd
= open(filename
, O_RDONLY
);
285 perror("opening file");
295 if ((st
.st_size
> MAX_DNLOAD_SIZE
) && (dnload
.mode
!= MODE_ROMLOAD
)) {
296 fprintf(stderr
, "The maximum file size is 64kBytes (%u bytes)\n",
302 st
.st_size
= sizeof(chainloader
);
308 if (dnload
.mode
== MODE_C140
|| dnload
.mode
== MODE_C140xor
) {
309 if (st
.st_size
< (MAGIC_OFFSET
+ sizeof(phone_magic
)))
310 payload_size
= MAGIC_OFFSET
+ sizeof(phone_magic
);
312 printf("\nThe filesize is larger than 15kb, code on "
313 "the magic address will be overwritten!\nUse "
314 "loader.bin and upload the application with "
315 "osmoload instead!\n\n");
316 payload_size
= st
.st_size
;
319 payload_size
= st
.st_size
;
321 dnload
.data
= malloc(MAX_HDR_SIZE
+ payload_size
);
326 fprintf(stderr
, "No memory\n");
330 /* copy in the header, if any */
331 switch (dnload
.mode
) {
334 hdr_len
= sizeof(data_hdr_c155
);
341 hdr_len
= sizeof(data_hdr_c123
);
350 memcpy(dnload
.data
, hdr
, hdr_len
);
352 /* 2 bytes for length + header */
353 file_data
= dnload
.data
+ 2 + hdr_len
;
355 /* write the length, keep running XOR */
356 tot_len
= hdr_len
+ payload_size
;
357 nibble
= tot_len
>> 8;
358 dnload
.data
[0] = nibble
;
359 running_xor
^= nibble
;
360 nibble
= tot_len
& 0xff;
361 dnload
.data
[1] = nibble
;
362 running_xor
^= nibble
;
364 if (hdr_len
&& hdr
) {
365 memcpy(dnload
.data
+2, hdr
, hdr_len
);
367 for (i
= 0; i
< hdr_len
; i
++)
368 running_xor
^= hdr
[i
];
372 rc
= read(fd
, file_data
, st
.st_size
);
374 perror("error reading file\n");
380 if (rc
< st
.st_size
) {
384 fprintf(stderr
, "Short read of file (%d < %d)\n",
385 rc
, (int)st
.st_size
);
390 memcpy(file_data
, chainloader
, st
.st_size
);
393 dnload
.data_len
= (file_data
+payload_size
) - dnload
.data
;
395 /* fill memory between data end and magic, add magic */
396 if(dnload
.mode
== MODE_C140
|| dnload
.mode
== MODE_C140xor
) {
397 if (st
.st_size
< MAGIC_OFFSET
)
398 memset(file_data
+ st
.st_size
, 0x00,
399 payload_size
- st
.st_size
);
400 memcpy(dnload
.data
+ MAGIC_OFFSET
, phone_magic
,
401 sizeof(phone_magic
));
404 /* calculate XOR sum */
405 for (i
= 0; i
< payload_size
; i
++)
406 running_xor
^= file_data
[i
];
408 dnload
.data
[dnload
.data_len
++] = running_xor
;
410 /* initialize write pointer to start of data */
411 dnload
.write_ptr
= dnload
.data
;
413 printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n",
414 chainload
? "chainloader" : filename
, (int)st
.st_size
,
415 hdr_len
, dnload
.data_len
);
420 static void osmocon_osmo_hexdump(const uint8_t *data
, unsigned int len
)
424 for (n
=0; n
< len
; n
++)
425 printf("%02x ", data
[n
]);
427 for (n
=0; n
< len
; n
++)
428 if (isprint(data
[n
]))
435 static int romload_prepare_block(void)
439 int block_checksum
= 5;
443 uint32_t block_address
;
445 dnload
.block_len
= ROMLOAD_BLOCK_HDR_LEN
+ dnload
.block_payload_size
;
447 /* if first block, allocate memory */
448 if (!dnload
.block_number
) {
449 dnload
.block
= malloc(dnload
.block_len
);
451 fprintf(stderr
, "No memory\n");
454 dnload
.romload_dl_checksum
= 0;
455 /* initialize write pointer to start of data */
456 dnload
.write_ptr
= dnload
.data
;
459 block_address
= ROMLOAD_ADDRESS
+
460 (dnload
.block_number
* dnload
.block_payload_size
);
462 /* prepare our block header (10 bytes) */
463 memcpy(dnload
.block
, romload_write_cmd
, sizeof(romload_write_cmd
));
464 dnload
.block
[2] = 0x01; /* block index */
465 /* should normally be the block number, but hangs when sending !0x01 */
466 dnload
.block
[3] = 0x01; /* dnload.block_number+1 */
467 dnload
.block
[4] = (dnload
.block_payload_size
>> 8) & 0xff;
468 dnload
.block
[5] = dnload
.block_payload_size
& 0xff;
469 dnload
.block
[6] = (block_address
>> 24) & 0xff;
470 dnload
.block
[7] = (block_address
>> 16) & 0xff;
471 dnload
.block
[8] = (block_address
>> 8) & 0xff;
472 dnload
.block
[9] = block_address
& 0xff;
474 block_data
= dnload
.block
+ ROMLOAD_BLOCK_HDR_LEN
;
475 dnload
.write_ptr
= dnload
.data
+ 2 +
476 (dnload
.block_payload_size
* dnload
.block_number
);
478 remaining_bytes
= dnload
.data_len
- 3 -
479 (dnload
.block_payload_size
* dnload
.block_number
);
481 memcpy(block_data
, dnload
.write_ptr
, OSMO_MIN(dnload
.block_payload_size
, remaining_bytes
));
483 if (remaining_bytes
<= dnload
.block_payload_size
) {
484 fill_bytes
= (dnload
.block_payload_size
- remaining_bytes
);
485 memset(block_data
+ remaining_bytes
, 0x00, fill_bytes
);
486 dnload
.romload_state
= SENDING_LAST_BLOCK
;
488 dnload
.romload_state
= SENDING_BLOCKS
;
491 /* block checksum is lsb of ~(5 + block_size_lsb + all bytes of
492 * block_address + all data bytes) */
493 for (i
= 5; i
< ROMLOAD_BLOCK_HDR_LEN
+ dnload
.block_payload_size
; i
++)
494 block_checksum
+= dnload
.block
[i
];
496 /* checksum is lsb of ~(sum of LSBs of all block checksums) */
497 dnload
.romload_dl_checksum
+= ~(block_checksum
) & 0xff;
499 /* initialize block pointer to start of block */
500 dnload
.block_ptr
= dnload
.block
;
502 dnload
.block_number
++;
503 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
| OSMO_FD_WRITE
);
507 static int mtk_prepare_block(void)
513 uint8_t tmp_byteswap
;
516 dnload
.block_len
= MTK_BLOCK_SIZE
;
517 dnload
.echo_bytecount
= 0;
519 /* if first block, allocate memory */
520 if (!dnload
.block_number
) {
521 dnload
.block
= malloc(dnload
.block_len
);
523 fprintf(stderr
, "No memory\n");
527 /* calculate the number of blocks we need to send */
528 dnload
.block_count
= (dnload
.data_len
-3) / MTK_BLOCK_SIZE
;
529 /* add one more block if no multiple of blocksize */
530 if((dnload
.data_len
-3) % MTK_BLOCK_SIZE
)
531 dnload
.block_count
++;
533 /* divide by 2, since we have to tell the mtk loader the size
534 * as count of uint16 (odd transfer sizes are not possible) */
535 tmp_size
= (dnload
.block_count
* MTK_BLOCK_SIZE
)/2;
536 dnload
.mtk_send_size
[0] = (tmp_size
>> 24) & 0xff;
537 dnload
.mtk_send_size
[1] = (tmp_size
>> 16) & 0xff;
538 dnload
.mtk_send_size
[2] = (tmp_size
>> 8) & 0xff;
539 dnload
.mtk_send_size
[3] = tmp_size
& 0xff;
541 /* initialize write pointer to start of data */
542 dnload
.write_ptr
= dnload
.data
;
545 block_data
= dnload
.block
;
546 dnload
.write_ptr
= dnload
.data
+ 2 +
547 (dnload
.block_len
* dnload
.block_number
);
549 remaining_bytes
= dnload
.data_len
- 3 -
550 (dnload
.block_len
* dnload
.block_number
);
552 memcpy(block_data
, dnload
.write_ptr
, MTK_BLOCK_SIZE
);
554 if (remaining_bytes
<= MTK_BLOCK_SIZE
) {
555 fill_bytes
= (MTK_BLOCK_SIZE
- remaining_bytes
);
556 printf("Preparing the last block, filling %i bytes\n",
558 memset(block_data
+ remaining_bytes
, 0x00, fill_bytes
);
559 dnload
.romload_state
= SENDING_LAST_BLOCK
;
561 dnload
.romload_state
= SENDING_BLOCKS
;
562 printf("Preparing block %i\n", dnload
.block_number
+1);
565 /* for the mtk romloader we need to swap MSB <-> LSB */
566 for (i
= 0; i
< dnload
.block_len
; i
+= 2) {
567 tmp_byteswap
= dnload
.block
[i
];
568 dnload
.block
[i
] = dnload
.block
[i
+1];
569 dnload
.block
[i
+1] = tmp_byteswap
;
572 /* initialize block pointer to start of block */
573 dnload
.block_ptr
= dnload
.block
;
575 dnload
.block_number
++;
579 static int handle_write_block(void)
581 int bytes_left
, write_len
, rc
;
582 int progress
= 100 * (dnload
.block_number
* dnload
.block_payload_size
)
585 if (dnload
.block_ptr
>= dnload
.block
+ dnload
.block_len
) {
586 printf("Progress: %i%%\r", progress
);
588 dnload
.write_ptr
= dnload
.data
;
589 osmo_fd_write_disable(&dnload
.serial_fd
);
590 if (dnload
.romload_state
== SENDING_LAST_BLOCK
) {
591 dnload
.romload_state
= LAST_BLOCK_SENT
;
592 printf("Finished, sent %i blocks in total\n",
593 dnload
.block_number
);
595 dnload
.romload_state
= WAITING_BLOCK_ACK
;
601 /* try to write a maximum of block_len bytes */
602 bytes_left
= (dnload
.block
+ dnload
.block_len
) - dnload
.block_ptr
;
603 write_len
= dnload
.block_len
;
604 if (bytes_left
< dnload
.block_len
)
605 write_len
= bytes_left
;
607 rc
= write(dnload
.serial_fd
.fd
, dnload
.block_ptr
, write_len
);
609 perror("Error during write");
613 dnload
.block_ptr
+= rc
;
618 #define WRITE_BLOCK 4096
620 static int handle_write_dnload(void)
622 int bytes_left
, write_len
, rc
;
623 uint8_t xor_init
= 0x02;
625 printf("handle_write(): ");
626 if (dnload
.write_ptr
== dnload
.data
) {
627 /* no bytes have been transferred yet */
628 switch (dnload
.mode
) {
632 rc
= write(dnload
.serial_fd
.fd
, &xor_init
, 1);
633 OSMO_ASSERT(rc
== 1);
638 } else if (dnload
.write_ptr
>= dnload
.data
+ dnload
.data_len
) {
639 printf("finished\n");
640 dnload
.write_ptr
= dnload
.data
;
641 osmo_fd_write_disable(&dnload
.serial_fd
);
645 /* try to write a maximum of WRITE_BLOCK bytes */
646 bytes_left
= (dnload
.data
+ dnload
.data_len
) - dnload
.write_ptr
;
647 write_len
= WRITE_BLOCK
;
648 if (bytes_left
< WRITE_BLOCK
)
649 write_len
= bytes_left
;
651 rc
= write(dnload
.serial_fd
.fd
, dnload
.write_ptr
, write_len
);
653 perror("Error during write");
656 OSMO_ASSERT(rc
== write_len
);
658 dnload
.write_ptr
+= rc
;
660 printf("%u bytes (%lu/%u)\n", rc
, dnload
.write_ptr
- dnload
.data
,
666 static int handle_sercomm_write(void)
669 int i
, count
= 0, end
= 0;
671 for (i
= 0; i
< sizeof(buffer
); i
++) {
672 if (sercomm_drv_pull(&buffer
[i
]) == 0) {
680 if (write(dnload
.serial_fd
.fd
, buffer
, count
) != count
)
681 perror("short write");
685 osmo_fd_write_disable(&dnload
.serial_fd
);
690 static int handle_write(void)
692 /* TODO: simplify this again (global state: downloading, sercomm) */
693 switch (dnload
.mode
) {
695 switch (dnload
.romload_state
) {
697 case SENDING_LAST_BLOCK
:
698 return handle_write_block();
700 return handle_sercomm_write();
704 switch (dnload
.mtk_state
) {
705 case MTK_SENDING_BLOCKS
:
706 return handle_write_block();
708 return handle_sercomm_write();
712 switch (dnload
.state
) {
714 return handle_write_dnload();
716 return handle_sercomm_write();
723 static uint8_t buffer
[sizeof(phone_prompt1
)];
724 static uint8_t *bufptr
= buffer
;
726 static void hdlc_send_to_phone(uint8_t dlci
, uint8_t *data
, int len
)
732 printf("hdlc_send(dlci=%u): ", dlci
);
733 osmocon_osmo_hexdump(data
, len
);
737 fprintf(stderr
, "Too much data to send. %u\n", len
);
741 /* push the message into the stack */
742 msg
= sercomm_alloc_msgb(512);
744 fprintf(stderr
, "Failed to create data for the frame.\n");
749 dest
= msgb_put(msg
, len
);
750 memcpy(dest
, data
, len
);
752 sercomm_sendmsg(dlci
, msg
);
754 osmo_fd_write_enable(&dnload
.serial_fd
);
757 static void hdlc_console_cb(uint8_t dlci
, struct msgb
*msg
)
759 write(1, msg
->data
, msg
->len
);
763 static void hdlc_tool_cb(uint8_t dlci
, struct msgb
*msg
)
765 struct tool_server
*srv
= tool_server_for_dlci
[dlci
];
768 printf("hdlc_recv(dlci=%u): ", dlci
);
769 osmocon_osmo_hexdump(msg
->data
, msg
->len
);
773 struct tool_connection
*con
;
776 len
= (uint16_t *) msgb_push(msg
, 2);
777 *len
= htons(msg
->len
- sizeof(*len
));
779 llist_for_each_entry(con
, &srv
->connections
, entry
) {
780 if (write(con
->fd
.fd
, msg
->data
, msg
->len
) != msg
->len
) {
782 "Failed to write msg to the socket..\n");
791 static int handle_buffer(int buf_used_len
)
793 int nbytes
, buf_left
, i
;
795 buf_left
= buf_used_len
- (bufptr
- buffer
);
797 memmove(buffer
, buffer
+1, buf_used_len
-1);
802 nbytes
= read(dnload
.serial_fd
.fd
, bufptr
, buf_left
);
806 if (!dnload
.expect_hdlc
) {
807 printf("got %i bytes from modem, ", nbytes
);
808 printf("data looks like: ");
809 osmocon_osmo_hexdump(bufptr
, nbytes
);
811 for (i
= 0; i
< nbytes
; ++i
)
812 if (sercomm_drv_rx_char(bufptr
[i
]) == 0)
813 printf("Dropping sample '%c'\n", bufptr
[i
]);
819 /* Compal ramloader */
820 static int handle_read(void)
824 nbytes
= handle_buffer(sizeof(buffer
));
828 if (!memcmp(buffer
, phone_prompt1
, sizeof(phone_prompt1
))) {
829 printf("Received PROMPT1 from phone, responding with CMD\n");
830 dnload
.expect_hdlc
= 0;
831 dnload
.state
= WAITING_PROMPT2
;
832 if(dnload
.filename
) {
833 rc
= write(dnload
.serial_fd
.fd
, dnload_cmd
, sizeof(dnload_cmd
));
836 rc
= read_file(dnload
.filename
, dnload
.do_chainload
);
838 fprintf(stderr
, "read_file(%s) failed with %d\n",
839 dnload
.filename
, rc
);
843 } else if (!memcmp(buffer
, phone_prompt2
, sizeof(phone_prompt2
))) {
844 printf("Received PROMPT2 from phone, starting download\n");
845 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
| OSMO_FD_WRITE
);
846 dnload
.state
= DOWNLOADING
;
847 } else if (!memcmp(buffer
, phone_ack
, sizeof(phone_ack
))) {
848 printf("Received DOWNLOAD ACK from phone, your code is"
850 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
);
851 dnload
.state
= WAITING_PROMPT1
;
852 dnload
.write_ptr
= dnload
.data
;
853 dnload
.expect_hdlc
= 1;
855 /* check for romloader chainloading mode used as a workaround
856 * for the magic on the C139/C140 and J100i */
857 if (dnload
.do_chainload
) {
858 printf("Enabled Compal ramloader -> Calypso romloader"
859 " chainloading mode\n");
861 dnload
.previous_mode
= dnload
.mode
;
862 dnload
.mode
= MODE_ROMLOAD
;
863 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
864 tick_timer
.cb
= &beacon_timer_cb
;
865 tick_timer
.data
= &tick_timer
;
866 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
868 } else if (!memcmp(buffer
, phone_nack
, sizeof(phone_nack
))) {
869 printf("Received DOWNLOAD NACK from phone, something went"
871 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
);
872 dnload
.state
= WAITING_PROMPT1
;
873 dnload
.write_ptr
= dnload
.data
;
874 } else if (!memcmp(buffer
, phone_nack_magic
, sizeof(phone_nack_magic
))) {
875 printf("Received MAGIC NACK from phone, you need to"
876 " have \"1003\" at 0x803ce0\n");
877 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
);
878 dnload
.state
= WAITING_PROMPT1
;
879 dnload
.write_ptr
= dnload
.data
;
880 } else if (!memcmp(buffer
, ftmtool
, sizeof(ftmtool
))) {
881 printf("Received FTMTOOL from phone, ramloader has aborted\n");
882 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
);
883 dnload
.state
= WAITING_PROMPT1
;
884 dnload
.write_ptr
= dnload
.data
;
891 /* "Calypso non-secure romloader" */
892 static int handle_read_romload(void)
894 int rc
, nbytes
, buf_used_len
;
896 /* virtually limit buffer length for romloader, since responses
897 * are shorter and vary in length */
899 switch (dnload
.romload_state
) {
900 case WAITING_PARAM_ACK
:
901 buf_used_len
= 4; /* ">p" + uint16_t len */
903 case WAITING_CHECKSUM_ACK
:
904 buf_used_len
= 3; /* ">c" + uint8_t checksum */
907 buf_used_len
= sizeof(buffer
);
910 buf_used_len
= 2; /* ">*" */
913 nbytes
= handle_buffer(buf_used_len
);
917 switch (dnload
.romload_state
) {
918 case WAITING_IDENTIFICATION
:
919 if (memcmp(buffer
, romload_ident_ack
,
920 sizeof(romload_ident_ack
)))
923 printf("Received ident ack from phone, sending "
924 "parameter sequence\n");
925 dnload
.expect_hdlc
= 1;
926 dnload
.romload_state
= WAITING_PARAM_ACK
;
927 rc
= write(dnload
.serial_fd
.fd
, romload_param
,
928 sizeof(romload_param
));
930 rc
= read_file(dnload
.filename
, 0);
932 fprintf(stderr
, "read_file(%s) failed with %d\n",
933 dnload
.filename
, rc
);
937 case WAITING_PARAM_ACK
:
938 if (memcmp(buffer
, romload_param_ack
,
939 sizeof(romload_param_ack
)))
942 printf("Received parameter ack from phone, "
943 "starting download\n");
944 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_DL_BAUDRATE
);
946 /* using the max blocksize the phone tells us */
947 dnload
.block_payload_size
= ((buffer
[3] << 8) + buffer
[2]);
948 dnload
.block_payload_size
-= ROMLOAD_BLOCK_HDR_LEN
;
949 dnload
.romload_state
= SENDING_BLOCKS
;
950 dnload
.block_number
= 0;
951 romload_prepare_block();
954 case WAITING_BLOCK_ACK
:
955 case LAST_BLOCK_SENT
:
956 if (!memcmp(buffer
, romload_block_ack
,
957 sizeof(romload_block_ack
))) {
958 if (dnload
.romload_state
== LAST_BLOCK_SENT
) {
959 /* send the checksum */
960 uint8_t final_checksum
=
961 (~(dnload
.romload_dl_checksum
) & 0xff);
962 rc
= write(dnload
.serial_fd
.fd
,
963 romload_checksum_cmd
,
964 sizeof(romload_checksum_cmd
));
965 rc
= write(dnload
.serial_fd
.fd
,
967 dnload
.romload_state
= WAITING_CHECKSUM_ACK
;
969 romload_prepare_block();
970 } else if (!memcmp(buffer
, romload_block_nack
,
971 sizeof(romload_block_nack
))) {
972 printf("Received block nack from phone, "
973 "something went wrong, aborting\n");
974 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
975 dnload
.romload_state
= WAITING_IDENTIFICATION
;
976 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
979 case WAITING_CHECKSUM_ACK
:
980 if (!memcmp(buffer
, romload_checksum_ack
,
981 sizeof(romload_checksum_ack
))) {
983 rc
= write(dnload
.serial_fd
.fd
, romload_branch_cmd
,
984 sizeof(romload_branch_cmd
));
985 rc
= write(dnload
.serial_fd
.fd
, &dnload
.load_address
,
986 sizeof(dnload
.load_address
));
987 dnload
.romload_state
= WAITING_BRANCH_ACK
;
989 } else if (!memcmp(buffer
, romload_checksum_nack
,
990 sizeof(romload_checksum_nack
))) {
991 printf("Checksum on phone side (0x%02x) doesn't "
992 "match ours, aborting\n", ~buffer
[2]);
993 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
994 dnload
.romload_state
= WAITING_IDENTIFICATION
;
995 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
999 case WAITING_BRANCH_ACK
:
1000 if (!memcmp(buffer
, romload_branch_ack
,
1001 sizeof(romload_branch_ack
))) {
1002 printf("Received branch ack, your code is running now!\n");
1003 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
);
1004 dnload
.romload_state
= FINISHED
;
1005 dnload
.write_ptr
= dnload
.data
;
1006 dnload
.expect_hdlc
= 1;
1008 if (!dnload
.do_chainload
)
1011 /* if using chainloading mode, switch back to the Compal
1012 * ramloader settings to make sure the auto-reload
1015 dnload
.mode
= dnload
.previous_mode
;
1016 dnload
.romload_state
= WAITING_IDENTIFICATION
;
1017 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, MODEM_BAUDRATE
);
1018 } else if (!memcmp(buffer
, romload_branch_nack
,
1019 sizeof(romload_branch_nack
))) {
1020 printf("Received branch nack, aborting\n");
1021 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
1022 dnload
.romload_state
= WAITING_IDENTIFICATION
;
1023 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
1035 static int handle_read_mtk(void)
1037 int rc
, nbytes
, buf_used_len
;
1039 switch (dnload
.mtk_state
) {
1040 case MTK_WAIT_ADDR_ACK
:
1041 case MTK_WAIT_SIZE_ACK
:
1042 case MTK_WAIT_BRANCH_ADDR_ACK
:
1046 buf_used_len
= sizeof(buffer
);
1052 nbytes
= handle_buffer(buf_used_len
);
1056 switch (dnload
.mtk_state
) {
1058 if (!(buffer
[0] == mtk_init_resp
[0]))
1060 dnload
.mtk_state
= MTK_INIT_2
;
1061 printf("Received init magic byte 1\n");
1062 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[1], 1);
1065 if (!(buffer
[0] == mtk_init_resp
[1]))
1067 dnload
.mtk_state
= MTK_INIT_3
;
1068 printf("Received init magic byte 2\n");
1069 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[2], 1);
1072 if (!(buffer
[0] == mtk_init_resp
[2]))
1074 dnload
.mtk_state
= MTK_INIT_4
;
1075 printf("Received init magic byte 3\n");
1076 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[3], 1);
1079 if (!(buffer
[0] == mtk_init_resp
[3]))
1081 dnload
.mtk_state
= MTK_WAIT_WRITE_ACK
;
1082 printf("Received init magic byte 4, requesting write\n");
1083 rc
= write(dnload
.serial_fd
.fd
, &mtk_command
[0], 1);
1085 case MTK_WAIT_WRITE_ACK
:
1086 if (!(buffer
[0] == mtk_command
[0]))
1088 dnload
.mtk_state
= MTK_WAIT_ADDR_ACK
;
1089 printf("Received write ack, sending load address\n");
1091 rc
= write(dnload
.serial_fd
.fd
, &dnload
.load_address
,
1092 sizeof(dnload
.load_address
));
1094 case MTK_WAIT_ADDR_ACK
:
1095 if (memcmp(buffer
, dnload
.load_address
,
1096 sizeof(dnload
.load_address
)))
1098 printf("Received address ack from phone, sending loadsize\n");
1100 rc
= read_file(dnload
.filename
, 0);
1102 fprintf(stderr
, "read_file(%s) failed with %d\n",
1103 dnload
.filename
, rc
);
1106 dnload
.block_number
= 0;
1107 mtk_prepare_block();
1108 dnload
.mtk_state
= MTK_WAIT_SIZE_ACK
;
1109 rc
= write(dnload
.serial_fd
.fd
, &dnload
.mtk_send_size
,
1110 sizeof(dnload
.mtk_send_size
));
1112 case MTK_WAIT_SIZE_ACK
:
1113 if (memcmp(buffer
, dnload
.mtk_send_size
,
1114 sizeof(dnload
.mtk_send_size
)))
1116 printf("Received size ack\n");
1117 dnload
.expect_hdlc
= 1;
1118 dnload
.mtk_state
= MTK_SENDING_BLOCKS
;
1119 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
| OSMO_FD_WRITE
);
1122 case MTK_SENDING_BLOCKS
:
1123 if (!(buffer
[0] == dnload
.block
[dnload
.echo_bytecount
]))
1124 printf("Warning: Byte %i of Block %i doesn't match,"
1125 " check your serial connection!\n",
1126 dnload
.echo_bytecount
, dnload
.block_number
);
1127 dnload
.echo_bytecount
++;
1129 if ((dnload
.echo_bytecount
+1) > MTK_BLOCK_SIZE
) {
1130 if ( dnload
.block_number
== dnload
.block_count
) {
1131 rc
= write(dnload
.serial_fd
.fd
,
1132 &mtk_command
[3], 1);
1133 printf("Sending branch command\n");
1134 dnload
.expect_hdlc
= 0;
1135 dnload
.mtk_state
= MTK_WAIT_BRANCH_CMD_ACK
;
1138 printf("Received Block %i preparing next block\n",
1139 dnload
.block_number
);
1140 mtk_prepare_block();
1141 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
| OSMO_FD_WRITE
);
1144 case MTK_WAIT_BRANCH_CMD_ACK
:
1145 if (!(buffer
[0] == mtk_command
[3]))
1147 dnload
.mtk_state
= MTK_WAIT_BRANCH_ADDR_ACK
;
1148 printf("Received branch command ack, sending address\n");
1150 rc
= write(dnload
.serial_fd
.fd
, &dnload
.load_address
,
1151 sizeof(dnload
.load_address
));
1153 case MTK_WAIT_BRANCH_ADDR_ACK
:
1154 if (memcmp(buffer
, dnload
.load_address
,
1155 sizeof(dnload
.load_address
)))
1157 printf("Received branch address ack, code should run now\n");
1158 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, MODEM_BAUDRATE
);
1159 osmo_fd_update_when(&dnload
.serial_fd
, 0, OSMO_FD_READ
);
1160 dnload
.mtk_state
= MTK_FINISHED
;
1161 dnload
.write_ptr
= dnload
.data
;
1162 dnload
.expect_hdlc
= 1;
1172 static int serial_read(struct osmo_fd
*fd
, unsigned int flags
)
1175 if (flags
& OSMO_FD_READ
) {
1176 switch (dnload
.mode
) {
1178 while ((rc
= handle_read_romload()) > 0);
1181 while ((rc
= handle_read_mtk()) > 0);
1184 while ((rc
= handle_read()) > 0);
1191 if (flags
& OSMO_FD_WRITE
) {
1192 rc
= handle_write();
1194 dnload
.state
= WAITING_PROMPT1
;
1199 static int parse_mode(const char *arg
)
1201 if (!strcasecmp(arg
, "c123"))
1203 else if (!strcasecmp(arg
, "c123xor"))
1204 return MODE_C123xor
;
1205 else if (!strcasecmp(arg
, "c140"))
1207 else if (!strcasecmp(arg
, "c140xor"))
1208 return MODE_C140xor
;
1209 else if (!strcasecmp(arg
, "c155"))
1211 else if (!strcasecmp(arg
, "romload"))
1212 return MODE_ROMLOAD
;
1213 else if (!strcasecmp(arg
, "mtk"))
1216 return MODE_INVALID
;
1220 "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \
1221 "\t\t [ -c ] (enable chainloading of highram-images)\n" \
1222 "\t\t [ -s /tmp/osmocom_l2 ]\n" \
1223 "\t\t [ -l /tmp/osmocom_loader ]\n" \
1224 "\t\t [ -m {c123,c123xor,c140,c140xor,c155,romload,mtk} ]\n" \
1225 "\t\t [ -i beacon-interval (mS) ]\n" \
1226 "\t\t file.bin\n\n" \
1227 "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \
1228 "* Perform handshaking with the ramloader in the phone\n" \
1229 "* Download file.bin to the attached phone (base address 0x00800100)\n"
1231 static int usage(const char *name
)
1233 printf("Usage: %s ", name
);
1238 static int version(const char *name
)
1240 printf("%s version %s\n", name
, PACKAGE_VERSION
);
1244 static int un_tool_read(struct osmo_fd
*fd
, unsigned int flags
)
1247 uint16_t length
= 0xffff;
1249 struct tool_connection
*con
= (struct tool_connection
*)fd
->data
;
1253 rc
= read(fd
->fd
, buf
+ c
, 2 - c
);
1259 if(errno
== EAGAIN
) {
1262 fprintf(stderr
, "Err from socket: %s\n", strerror(errno
));
1268 memcpy(&length
, buf
, sizeof length
);
1269 length
= ntohs(length
);
1273 rc
= read(fd
->fd
, buf
+ c
, length
- c
);
1279 if(errno
== EAGAIN
) {
1282 fprintf(stderr
, "Err from socket: %s\n", strerror(errno
));
1288 hdlc_send_to_phone(con
->server
->dlci
, buf
, length
);
1294 osmo_fd_unregister(fd
);
1295 llist_del(&con
->entry
);
1300 /* accept a new connection */
1301 static int tool_accept(struct osmo_fd
*fd
, unsigned int flags
)
1303 struct tool_server
*srv
= (struct tool_server
*)fd
->data
;
1304 struct tool_connection
*con
;
1305 struct sockaddr_un un_addr
;
1309 len
= sizeof(un_addr
);
1310 rc
= accept(fd
->fd
, (struct sockaddr
*) &un_addr
, &len
);
1312 fprintf(stderr
, "Failed to accept a new connection.\n");
1316 con
= talloc_zero(NULL
, struct tool_connection
);
1318 fprintf(stderr
, "Failed to create tool connection.\n");
1325 osmo_fd_setup(&con
->fd
, rc
, OSMO_FD_READ
, un_tool_read
, con
, 0);
1326 if (osmo_fd_register(&con
->fd
) != 0) {
1327 fprintf(stderr
, "Failed to register the fd.\n");
1333 llist_add(&con
->entry
, &srv
->connections
);
1338 * Register and start a tool server
1340 static int register_tool_server(struct tool_server
*ts
,
1344 struct osmo_fd
*bfd
= &ts
->bfd
;
1347 rc
= osmo_sock_unix_init_ofd(bfd
, SOCK_STREAM
, 0, path
, OSMO_SOCK_F_BIND
);
1349 fprintf(stderr
, "Failed to create Unix Domain Socket.\n");
1353 bfd
->cb
= tool_accept
;
1357 INIT_LLIST_HEAD(&ts
->connections
);
1359 tool_server_for_dlci
[dlci
] = ts
;
1361 sercomm_register_rx_cb(dlci
, hdlc_tool_cb
);
1366 extern void hdlc_tpudbg_cb(uint8_t dlci
, struct msgb
*msg
);
1368 void parse_debug(const char *str
)
1379 printf("Unknown debug flag %c\n", *str
);
1387 int main(int argc
, char **argv
)
1390 uint32_t tmp_load_address
= ROMLOAD_ADDRESS
;
1391 const char *serial_dev
= "/dev/ttyUSB1";
1392 const char *layer2_un_path
= "/tmp/osmocom_l2";
1393 const char *loader_un_path
= "/tmp/osmocom_loader";
1395 dnload
.mode
= MODE_C123
;
1396 dnload
.beacon_interval
= DEFAULT_BEACON_INTERVAL
;
1397 dnload
.do_chainload
= 0;
1399 osmo_init_ignore_signals();
1401 while ((opt
= getopt(argc
, argv
, "d:hl:p:m:cs:i:v")) != -1) {
1404 serial_dev
= optarg
;
1407 dnload
.mode
= parse_mode(optarg
);
1408 if (dnload
.mode
== MODE_INVALID
)
1412 layer2_un_path
= optarg
;
1415 loader_un_path
= optarg
;
1421 parse_debug(optarg
);
1424 dnload
.do_chainload
= 1;
1427 dnload
.beacon_interval
= atoi(optarg
) * 1000;
1436 if (argc
<= optind
) {
1437 dnload
.filename
= NULL
;
1439 dnload
.filename
= argv
[optind
];
1442 fd
= osmo_serial_init(serial_dev
, MODEM_BAUDRATE
);
1444 fprintf(stderr
, "Cannot open serial device %s\n", serial_dev
);
1448 osmo_fd_setup(&dnload
.serial_fd
, fd
, OSMO_FD_READ
, serial_read
, NULL
, 0);
1449 if (osmo_fd_register(&dnload
.serial_fd
) != 0) {
1450 fprintf(stderr
, "Failed to register the serial.\n");
1454 /* Set serial socket to non-blocking mode of operation */
1455 flags
= fcntl(dnload
.serial_fd
.fd
, F_GETFL
);
1456 flags
|= O_NONBLOCK
;
1457 fcntl(dnload
.serial_fd
.fd
, F_SETFL
, flags
);
1459 /* initialize the HDLC layer */
1461 sercomm_register_rx_cb(SC_DLCI_CONSOLE
, hdlc_console_cb
);
1462 sercomm_register_rx_cb(SC_DLCI_DEBUG
, hdlc_tpudbg_cb
);
1464 /* unix domain socket handling */
1465 if (register_tool_server(&dnload
.layer2_server
, layer2_un_path
,
1466 SC_DLCI_L1A_L23
) != 0)
1469 if (register_tool_server(&dnload
.loader_server
, loader_un_path
,
1470 SC_DLCI_LOADER
) != 0)
1473 /* if in romload mode, start our beacon timer */
1474 if (dnload
.mode
== MODE_ROMLOAD
) {
1475 tmp_load_address
= ROMLOAD_ADDRESS
;
1476 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
1477 tick_timer
.cb
= &beacon_timer_cb
;
1478 tick_timer
.data
= &tick_timer
;
1479 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
1481 else if (dnload
.mode
== MODE_MTK
) {
1482 tmp_load_address
= MTK_ADDRESS
;
1483 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, MTK_INIT_BAUDRATE
);
1484 tick_timer
.cb
= &mtk_timer_cb
;
1485 tick_timer
.data
= &tick_timer
;
1486 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
1489 dnload
.load_address
[0] = (tmp_load_address
>> 24) & 0xff;
1490 dnload
.load_address
[1] = (tmp_load_address
>> 16) & 0xff;
1491 dnload
.load_address
[2] = (tmp_load_address
>> 8) & 0xff;
1492 dnload
.load_address
[3] = tmp_load_address
& 0xff;
1495 if (osmo_select_main(0) < 0)
1499 close(dnload
.serial_fd
.fd
);