3 /* (C) 2010 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>
48 #include <arpa/inet.h>
50 #define MODEM_BAUDRATE B115200
51 #define MAX_DNLOAD_SIZE 0xFFFF
52 #define MAX_HDR_SIZE 128
53 #define MAGIC_OFFSET 0x3be2
55 #define DEFAULT_BEACON_INTERVAL 50000
56 #define ROMLOAD_INIT_BAUDRATE B19200
57 #define ROMLOAD_DL_BAUDRATE B115200
58 #define ROMLOAD_BLOCK_HDR_LEN 10
59 #define ROMLOAD_ADDRESS 0x820000
61 #define MTK_INIT_BAUDRATE B19200
62 #define MTK_ADDRESS 0x40001400
63 #define MTK_BLOCK_SIZE 1024
65 struct tool_server
*tool_server_for_dlci
[256];
68 * a connection from some other tool
70 struct tool_connection
{
71 struct tool_server
*server
;
72 struct llist_head entry
;
82 struct llist_head connections
;
93 WAITING_IDENTIFICATION
,
113 MTK_WAIT_BRANCH_CMD_ACK
,
114 MTK_WAIT_BRANCH_ADDR_ACK
,
130 enum dnload_state state
;
131 enum romload_state romload_state
;
132 enum mtk_state mtk_state
;
133 enum dnload_mode mode
, previous_mode
;
134 struct osmo_fd serial_fd
;
144 /* data to be downloaded */
150 /* romload: block to be downloaded */
153 uint8_t block_number
;
154 uint16_t block_payload_size
;
155 int romload_dl_checksum
;
157 uint8_t load_address
[4];
159 uint8_t mtk_send_size
[4];
163 struct tool_server layer2_server
;
164 struct tool_server loader_server
;
168 static struct dnload dnload
;
169 static struct osmo_timer_list tick_timer
;
171 /* Compal ramloader specific */
172 static const uint8_t phone_prompt1
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
173 static const uint8_t dnload_cmd
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
174 static const uint8_t phone_prompt2
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
175 static const uint8_t phone_ack
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
176 static const uint8_t phone_nack_magic
[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
177 static const uint8_t phone_nack
[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
178 static const uint8_t ftmtool
[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c };
179 static const uint8_t phone_magic
[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */
181 /* The C123 has a hard-coded check inside the ramloader that requires the
182 * following bytes to be always the first four bytes of the image */
183 static const uint8_t data_hdr_c123
[] = { 0xee, 0x4c, 0x9f, 0x63 };
185 /* The C155 doesn't have some strange restriction on what the first four bytes
186 * have to be, but it starts the ramloader in THUMB mode. We use the following
187 * four bytes to switch back to ARM mode:
189 800102: 46c0 nop ; (mov r8, r8)
191 static const uint8_t data_hdr_c155
[] = { 0x78, 0x47, 0xc0, 0x46 };
193 /* small loader that enables the bootrom and executes the TI romloader:
195 * ldr r1, =0x000a0000
199 * ldr r1, =0xfffffb10
204 static const uint8_t chainloader
[] = {
205 0x0a, 0x18, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff,
206 0x1a, 0x08, 0x10, 0x9f, 0xe5, 0x01, 0x2c, 0xa0, 0xe3, 0xb0, 0x20,
207 0xc1, 0xe1, 0x00, 0xf0, 0xa0, 0xe3, 0x10, 0xfb, 0xff, 0xff,
210 /* Calypso romloader specific */
211 static const uint8_t romload_ident_cmd
[] = { 0x3c, 0x69 }; /* <i */
212 static const uint8_t romload_abort_cmd
[] = { 0x3c, 0x61 }; /* <a */
213 static const uint8_t romload_write_cmd
[] = { 0x3c, 0x77 }; /* <w */
214 static const uint8_t romload_checksum_cmd
[] = { 0x3c, 0x63 }; /* <c */
215 static const uint8_t romload_branch_cmd
[] = { 0x3c, 0x62 }; /* <b */
216 static const uint8_t romload_ident_ack
[] = { 0x3e, 0x69 }; /* >i */
217 static const uint8_t romload_param_ack
[] = { 0x3e, 0x70 }; /* >p */
218 static const uint8_t romload_param_nack
[] = { 0x3e, 0x50 }; /* >P */
219 static const uint8_t romload_block_ack
[] = { 0x3e, 0x77 }; /* >w */
220 static const uint8_t romload_block_nack
[] = { 0x3e, 0x57 }; /* >W */
221 static const uint8_t romload_checksum_ack
[] = { 0x3e, 0x63 }; /* >c */
222 static const uint8_t romload_checksum_nack
[] = { 0x3e, 0x43 }; /* >C */
223 static const uint8_t romload_branch_ack
[] = { 0x3e, 0x62 }; /* >b */
224 static const uint8_t romload_branch_nack
[] = { 0x3e, 0x42 }; /* >B */
226 /* romload_param: {"<p", uint8_t baudrate, uint8_t dpll, uint16_t memory_config,
227 * uint8_t strobe_af, uint32_t uart_timeout} */
229 static const uint8_t romload_param
[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04,
230 0x00, 0x00, 0x00, 0x00, 0x00 };
232 /* MTK romloader specific */
233 static const uint8_t mtk_init_cmd
[] = { 0xa0, 0x0a, 0x50, 0x05 };
234 static const uint8_t mtk_init_resp
[] = { 0x5f, 0xf5, 0xaf, 0xfa };
235 static const uint8_t mtk_command
[] = { 0xa1, 0xa2, 0xa4, 0xa8 };
237 static void beacon_timer_cb(void *p
)
241 if (dnload
.romload_state
== WAITING_IDENTIFICATION
) {
242 rc
= write(dnload
.serial_fd
.fd
, romload_ident_cmd
,
243 sizeof(romload_ident_cmd
));
245 if (!(rc
== sizeof(romload_ident_cmd
)))
246 printf("Error sending identification beacon\n");
248 osmo_timer_schedule(p
, 0, dnload
.beacon_interval
);
252 static void mtk_timer_cb(void *p
)
256 if (dnload
.mtk_state
== MTK_INIT_1
) {
257 printf("Sending MTK romloader beacon...\n");
258 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[0], 1);
261 printf("Error sending identification beacon\n");
263 osmo_timer_schedule(p
, 0, dnload
.beacon_interval
);
267 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
268 int read_file(const char *filename
, int chainload
)
272 const uint8_t *hdr
= NULL
;
278 uint8_t running_xor
= 0x02;
281 fd
= open(filename
, O_RDONLY
);
283 perror("opening file");
288 if ((st
.st_size
> MAX_DNLOAD_SIZE
) && (dnload
.mode
!= MODE_ROMLOAD
)) {
289 fprintf(stderr
, "The maximum file size is 64kBytes (%u bytes)\n",
294 st
.st_size
= sizeof(chainloader
);
300 if (dnload
.mode
== MODE_C140
|| dnload
.mode
== MODE_C140xor
) {
301 if (st
.st_size
< (MAGIC_OFFSET
+ sizeof(phone_magic
)))
302 payload_size
= MAGIC_OFFSET
+ sizeof(phone_magic
);
304 printf("\nThe filesize is larger than 15kb, code on "
305 "the magic address will be overwritten!\nUse "
306 "loader.bin and upload the application with "
307 "osmoload instead!\n\n");
308 payload_size
= st
.st_size
;
311 payload_size
= st
.st_size
;
313 dnload
.data
= malloc(MAX_HDR_SIZE
+ payload_size
);
317 fprintf(stderr
, "No memory\n");
321 /* copy in the header, if any */
322 switch (dnload
.mode
) {
325 hdr_len
= sizeof(data_hdr_c155
);
332 hdr_len
= sizeof(data_hdr_c123
);
341 memcpy(dnload
.data
, hdr
, hdr_len
);
343 /* 2 bytes for length + header */
344 file_data
= dnload
.data
+ 2 + hdr_len
;
346 /* write the length, keep running XOR */
347 tot_len
= hdr_len
+ payload_size
;
348 nibble
= tot_len
>> 8;
349 dnload
.data
[0] = nibble
;
350 running_xor
^= nibble
;
351 nibble
= tot_len
& 0xff;
352 dnload
.data
[1] = nibble
;
353 running_xor
^= nibble
;
355 if (hdr_len
&& hdr
) {
356 memcpy(dnload
.data
+2, hdr
, hdr_len
);
358 for (i
= 0; i
< hdr_len
; i
++)
359 running_xor
^= hdr
[i
];
363 rc
= read(fd
, file_data
, st
.st_size
);
365 perror("error reading file\n");
371 if (rc
< st
.st_size
) {
375 fprintf(stderr
, "Short read of file (%d < %d)\n",
376 rc
, (int)st
.st_size
);
381 memcpy(file_data
, chainloader
, st
.st_size
);
384 dnload
.data_len
= (file_data
+payload_size
) - dnload
.data
;
386 /* fill memory between data end and magic, add magic */
387 if(dnload
.mode
== MODE_C140
|| dnload
.mode
== MODE_C140xor
) {
388 if (st
.st_size
< MAGIC_OFFSET
)
389 memset(file_data
+ st
.st_size
, 0x00,
390 payload_size
- st
.st_size
);
391 memcpy(dnload
.data
+ MAGIC_OFFSET
, phone_magic
,
392 sizeof(phone_magic
));
395 /* calculate XOR sum */
396 for (i
= 0; i
< payload_size
; i
++)
397 running_xor
^= file_data
[i
];
399 dnload
.data
[dnload
.data_len
++] = running_xor
;
401 /* initialize write pointer to start of data */
402 dnload
.write_ptr
= dnload
.data
;
404 printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n",
405 chainload
? "chainloader" : filename
, (int)st
.st_size
,
406 hdr_len
, dnload
.data_len
);
411 static void osmocon_osmo_hexdump(const uint8_t *data
, unsigned int len
)
415 for (n
=0; n
< len
; n
++)
416 printf("%02x ", data
[n
]);
418 for (n
=0; n
< len
; n
++)
419 if (isprint(data
[n
]))
426 static int romload_prepare_block(void)
430 int block_checksum
= 5;
434 uint32_t block_address
;
436 dnload
.block_len
= ROMLOAD_BLOCK_HDR_LEN
+ dnload
.block_payload_size
;
438 /* if first block, allocate memory */
439 if (!dnload
.block_number
) {
440 dnload
.block
= malloc(dnload
.block_len
);
442 fprintf(stderr
, "No memory\n");
445 dnload
.romload_dl_checksum
= 0;
446 /* initialize write pointer to start of data */
447 dnload
.write_ptr
= dnload
.data
;
450 block_address
= ROMLOAD_ADDRESS
+
451 (dnload
.block_number
* dnload
.block_payload_size
);
453 /* prepare our block header (10 bytes) */
454 memcpy(dnload
.block
, romload_write_cmd
, sizeof(romload_write_cmd
));
455 dnload
.block
[2] = 0x01; /* block index */
456 /* should normally be the block number, but hangs when sending !0x01 */
457 dnload
.block
[3] = 0x01; /* dnload.block_number+1 */
458 dnload
.block
[4] = (dnload
.block_payload_size
>> 8) & 0xff;
459 dnload
.block
[5] = dnload
.block_payload_size
& 0xff;
460 dnload
.block
[6] = (block_address
>> 24) & 0xff;
461 dnload
.block
[7] = (block_address
>> 16) & 0xff;
462 dnload
.block
[8] = (block_address
>> 8) & 0xff;
463 dnload
.block
[9] = block_address
& 0xff;
465 block_data
= dnload
.block
+ ROMLOAD_BLOCK_HDR_LEN
;
466 dnload
.write_ptr
= dnload
.data
+ 2 +
467 (dnload
.block_payload_size
* dnload
.block_number
);
469 remaining_bytes
= dnload
.data_len
- 3 -
470 (dnload
.block_payload_size
* dnload
.block_number
);
472 memcpy(block_data
, dnload
.write_ptr
, dnload
.block_payload_size
);
474 if (remaining_bytes
<= dnload
.block_payload_size
) {
475 fill_bytes
= (dnload
.block_payload_size
- remaining_bytes
);
476 memset(block_data
+ remaining_bytes
, 0x00, fill_bytes
);
477 dnload
.romload_state
= SENDING_LAST_BLOCK
;
479 dnload
.romload_state
= SENDING_BLOCKS
;
482 /* block checksum is lsb of ~(5 + block_size_lsb + all bytes of
483 * block_address + all data bytes) */
484 for (i
= 5; i
< ROMLOAD_BLOCK_HDR_LEN
+ dnload
.block_payload_size
; i
++)
485 block_checksum
+= dnload
.block
[i
];
487 /* checksum is lsb of ~(sum of LSBs of all block checksums) */
488 dnload
.romload_dl_checksum
+= ~(block_checksum
) & 0xff;
490 /* initialize block pointer to start of block */
491 dnload
.block_ptr
= dnload
.block
;
493 dnload
.block_number
++;
494 dnload
.serial_fd
.when
= BSC_FD_READ
| BSC_FD_WRITE
;
498 static int mtk_prepare_block(void)
505 uint8_t tmp_byteswap
;
508 dnload
.block_len
= MTK_BLOCK_SIZE
;
509 dnload
.echo_bytecount
= 0;
511 /* if first block, allocate memory */
512 if (!dnload
.block_number
) {
513 dnload
.block
= malloc(dnload
.block_len
);
515 fprintf(stderr
, "No memory\n");
519 /* calculate the number of blocks we need to send */
520 dnload
.block_count
= (dnload
.data_len
-3) / MTK_BLOCK_SIZE
;
521 /* add one more block if no multiple of blocksize */
522 if((dnload
.data_len
-3) % MTK_BLOCK_SIZE
)
523 dnload
.block_count
++;
525 /* divide by 2, since we have to tell the mtk loader the size
526 * as count of uint16 (odd transfer sizes are not possible) */
527 tmp_size
= (dnload
.block_count
* MTK_BLOCK_SIZE
)/2;
528 dnload
.mtk_send_size
[0] = (tmp_size
>> 24) & 0xff;
529 dnload
.mtk_send_size
[1] = (tmp_size
>> 16) & 0xff;
530 dnload
.mtk_send_size
[2] = (tmp_size
>> 8) & 0xff;
531 dnload
.mtk_send_size
[3] = tmp_size
& 0xff;
533 /* initialize write pointer to start of data */
534 dnload
.write_ptr
= dnload
.data
;
537 block_data
= dnload
.block
;
538 dnload
.write_ptr
= dnload
.data
+ 2 +
539 (dnload
.block_len
* dnload
.block_number
);
541 remaining_bytes
= dnload
.data_len
- 3 -
542 (dnload
.block_len
* dnload
.block_number
);
544 memcpy(block_data
, dnload
.write_ptr
, MTK_BLOCK_SIZE
);
546 if (remaining_bytes
<= MTK_BLOCK_SIZE
) {
547 fill_bytes
= (MTK_BLOCK_SIZE
- remaining_bytes
);
548 printf("Preparing the last block, filling %i bytes\n",
550 memset(block_data
+ remaining_bytes
, 0x00, fill_bytes
);
551 dnload
.romload_state
= SENDING_LAST_BLOCK
;
553 dnload
.romload_state
= SENDING_BLOCKS
;
554 printf("Preparing block %i\n", dnload
.block_number
+1);
557 /* for the mtk romloader we need to swap MSB <-> LSB */
558 for (i
= 0; i
< dnload
.block_len
; i
+= 2) {
559 tmp_byteswap
= dnload
.block
[i
];
560 dnload
.block
[i
] = dnload
.block
[i
+1];
561 dnload
.block
[i
+1] = tmp_byteswap
;
564 /* initialize block pointer to start of block */
565 dnload
.block_ptr
= dnload
.block
;
567 dnload
.block_number
++;
571 static int handle_write_block(void)
573 int bytes_left
, write_len
, rc
;
574 int progress
= 100 * (dnload
.block_number
* dnload
.block_payload_size
)
577 if (dnload
.block_ptr
>= dnload
.block
+ dnload
.block_len
) {
578 printf("Progress: %i%%\r", progress
);
580 dnload
.write_ptr
= dnload
.data
;
581 dnload
.serial_fd
.when
&= ~BSC_FD_WRITE
;
582 if (dnload
.romload_state
== SENDING_LAST_BLOCK
) {
583 dnload
.romload_state
= LAST_BLOCK_SENT
;
584 printf("Finished, sent %i blocks in total\n",
585 dnload
.block_number
);
587 dnload
.romload_state
= WAITING_BLOCK_ACK
;
593 /* try to write a maximum of block_len bytes */
594 bytes_left
= (dnload
.block
+ dnload
.block_len
) - dnload
.block_ptr
;
595 write_len
= dnload
.block_len
;
596 if (bytes_left
< dnload
.block_len
)
597 write_len
= bytes_left
;
599 rc
= write(dnload
.serial_fd
.fd
, dnload
.block_ptr
, write_len
);
601 perror("Error during write");
605 dnload
.block_ptr
+= rc
;
610 #define WRITE_BLOCK 4096
612 static int handle_write_dnload(void)
614 int bytes_left
, write_len
, rc
;
615 uint8_t xor_init
= 0x02;
617 printf("handle_write(): ");
618 if (dnload
.write_ptr
== dnload
.data
) {
619 /* no bytes have been transferred yet */
620 switch (dnload
.mode
) {
624 rc
= write(dnload
.serial_fd
.fd
, &xor_init
, 1);
629 } else if (dnload
.write_ptr
>= dnload
.data
+ dnload
.data_len
) {
630 printf("finished\n");
631 dnload
.write_ptr
= dnload
.data
;
632 dnload
.serial_fd
.when
&= ~BSC_FD_WRITE
;
636 /* try to write a maximum of WRITE_BLOCK bytes */
637 bytes_left
= (dnload
.data
+ dnload
.data_len
) - dnload
.write_ptr
;
638 write_len
= WRITE_BLOCK
;
639 if (bytes_left
< WRITE_BLOCK
)
640 write_len
= bytes_left
;
642 rc
= write(dnload
.serial_fd
.fd
, dnload
.write_ptr
, write_len
);
644 perror("Error during write");
648 dnload
.write_ptr
+= rc
;
650 printf("%u bytes (%u/%u)\n", rc
, dnload
.write_ptr
- dnload
.data
,
656 static int handle_sercomm_write(void)
659 int i
, count
= 0, end
= 0;
661 for (i
= 0; i
< sizeof(buffer
); i
++) {
662 if (sercomm_drv_pull(&buffer
[i
]) == 0) {
670 if (write(dnload
.serial_fd
.fd
, buffer
, count
) != count
)
671 perror("short write");
675 dnload
.serial_fd
.when
&= ~BSC_FD_WRITE
;
680 static int handle_write(void)
682 /* TODO: simplify this again (global state: downloading, sercomm) */
683 switch (dnload
.mode
) {
685 switch (dnload
.romload_state
) {
687 case SENDING_LAST_BLOCK
:
688 return handle_write_block();
690 return handle_sercomm_write();
694 switch (dnload
.mtk_state
) {
695 case MTK_SENDING_BLOCKS
:
696 return handle_write_block();
698 return handle_sercomm_write();
702 switch (dnload
.state
) {
704 return handle_write_dnload();
706 return handle_sercomm_write();
713 static uint8_t buffer
[sizeof(phone_prompt1
)];
714 static uint8_t *bufptr
= buffer
;
716 static void hdlc_send_to_phone(uint8_t dlci
, uint8_t *data
, int len
)
722 printf("hdlc_send(dlci=%u): ", dlci
);
723 osmocon_osmo_hexdump(data
, len
);
727 fprintf(stderr
, "Too much data to send. %u\n", len
);
731 /* push the message into the stack */
732 msg
= sercomm_alloc_msgb(512);
734 fprintf(stderr
, "Failed to create data for the frame.\n");
739 dest
= msgb_put(msg
, len
);
740 memcpy(dest
, data
, len
);
742 sercomm_sendmsg(dlci
, msg
);
744 dnload
.serial_fd
.when
|= BSC_FD_WRITE
;
747 static void hdlc_console_cb(uint8_t dlci
, struct msgb
*msg
)
749 write(1, msg
->data
, msg
->len
);
753 static void hdlc_tool_cb(uint8_t dlci
, struct msgb
*msg
)
755 struct tool_server
*srv
= tool_server_for_dlci
[dlci
];
758 printf("hdlc_recv(dlci=%u): ", dlci
);
759 osmocon_osmo_hexdump(msg
->data
, msg
->len
);
763 struct tool_connection
*con
;
766 len
= (uint16_t *) msgb_push(msg
, 2);
767 *len
= htons(msg
->len
- sizeof(*len
));
769 llist_for_each_entry(con
, &srv
->connections
, entry
) {
770 if (write(con
->fd
.fd
, msg
->data
, msg
->len
) != msg
->len
) {
772 "Failed to write msg to the socket..\n");
781 static int handle_buffer(int buf_used_len
)
783 int nbytes
, buf_left
, i
;
785 buf_left
= buf_used_len
- (bufptr
- buffer
);
787 memmove(buffer
, buffer
+1, buf_used_len
-1);
792 nbytes
= read(dnload
.serial_fd
.fd
, bufptr
, buf_left
);
796 if (!dnload
.expect_hdlc
) {
797 printf("got %i bytes from modem, ", nbytes
);
798 printf("data looks like: ");
799 osmocon_osmo_hexdump(bufptr
, nbytes
);
801 for (i
= 0; i
< nbytes
; ++i
)
802 if (sercomm_drv_rx_char(bufptr
[i
]) == 0)
803 printf("Dropping sample '%c'\n", bufptr
[i
]);
809 /* Compal ramloader */
810 static int handle_read(void)
814 nbytes
= handle_buffer(sizeof(buffer
));
818 if (!memcmp(buffer
, phone_prompt1
, sizeof(phone_prompt1
))) {
819 printf("Received PROMPT1 from phone, responding with CMD\n");
820 dnload
.expect_hdlc
= 0;
821 dnload
.state
= WAITING_PROMPT2
;
822 if(dnload
.filename
) {
823 rc
= write(dnload
.serial_fd
.fd
, dnload_cmd
, sizeof(dnload_cmd
));
826 rc
= read_file(dnload
.filename
, dnload
.do_chainload
);
828 fprintf(stderr
, "read_file(%s) failed with %d\n",
829 dnload
.filename
, rc
);
833 } else if (!memcmp(buffer
, phone_prompt2
, sizeof(phone_prompt2
))) {
834 printf("Received PROMPT2 from phone, starting download\n");
835 dnload
.serial_fd
.when
= BSC_FD_READ
| BSC_FD_WRITE
;
836 dnload
.state
= DOWNLOADING
;
837 } else if (!memcmp(buffer
, phone_ack
, sizeof(phone_ack
))) {
838 printf("Received DOWNLOAD ACK from phone, your code is"
840 dnload
.serial_fd
.when
= BSC_FD_READ
;
841 dnload
.state
= WAITING_PROMPT1
;
842 dnload
.write_ptr
= dnload
.data
;
843 dnload
.expect_hdlc
= 1;
845 /* check for romloader chainloading mode used as a workaround
846 * for the magic on the C139/C140 and J100i */
847 if (dnload
.do_chainload
) {
848 printf("Enabled Compal ramloader -> Calypso romloader"
849 " chainloading mode\n");
851 dnload
.previous_mode
= dnload
.mode
;
852 dnload
.mode
= MODE_ROMLOAD
;
853 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
854 tick_timer
.cb
= &beacon_timer_cb
;
855 tick_timer
.data
= &tick_timer
;
856 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
858 } else if (!memcmp(buffer
, phone_nack
, sizeof(phone_nack
))) {
859 printf("Received DOWNLOAD NACK from phone, something went"
861 dnload
.serial_fd
.when
= BSC_FD_READ
;
862 dnload
.state
= WAITING_PROMPT1
;
863 dnload
.write_ptr
= dnload
.data
;
864 } else if (!memcmp(buffer
, phone_nack_magic
, sizeof(phone_nack_magic
))) {
865 printf("Received MAGIC NACK from phone, you need to"
866 " have \"1003\" at 0x803ce0\n");
867 dnload
.serial_fd
.when
= BSC_FD_READ
;
868 dnload
.state
= WAITING_PROMPT1
;
869 dnload
.write_ptr
= dnload
.data
;
870 } else if (!memcmp(buffer
, ftmtool
, sizeof(ftmtool
))) {
871 printf("Received FTMTOOL from phone, ramloader has aborted\n");
872 dnload
.serial_fd
.when
= BSC_FD_READ
;
873 dnload
.state
= WAITING_PROMPT1
;
874 dnload
.write_ptr
= dnload
.data
;
881 /* "Calypso non-secure romloader" */
882 static int handle_read_romload(void)
884 int rc
, nbytes
, buf_used_len
;
886 /* virtually limit buffer length for romloader, since responses
887 * are shorter and vary in length */
889 switch (dnload
.romload_state
) {
890 case WAITING_PARAM_ACK
:
891 buf_used_len
= 4; /* ">p" + uint16_t len */
893 case WAITING_CHECKSUM_ACK
:
894 buf_used_len
= 3; /* ">c" + uint8_t checksum */
897 buf_used_len
= sizeof(buffer
);
900 buf_used_len
= 2; /* ">*" */
903 nbytes
= handle_buffer(buf_used_len
);
907 switch (dnload
.romload_state
) {
908 case WAITING_IDENTIFICATION
:
909 if (memcmp(buffer
, romload_ident_ack
,
910 sizeof(romload_ident_ack
)))
913 printf("Received ident ack from phone, sending "
914 "parameter sequence\n");
915 dnload
.expect_hdlc
= 1;
916 dnload
.romload_state
= WAITING_PARAM_ACK
;
917 rc
= write(dnload
.serial_fd
.fd
, romload_param
,
918 sizeof(romload_param
));
920 rc
= read_file(dnload
.filename
, 0);
922 fprintf(stderr
, "read_file(%s) failed with %d\n",
923 dnload
.filename
, rc
);
927 case WAITING_PARAM_ACK
:
928 if (memcmp(buffer
, romload_param_ack
,
929 sizeof(romload_param_ack
)))
932 printf("Received parameter ack from phone, "
933 "starting download\n");
934 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_DL_BAUDRATE
);
936 /* using the max blocksize the phone tells us */
937 dnload
.block_payload_size
= ((buffer
[3] << 8) + buffer
[2]);
938 dnload
.block_payload_size
-= ROMLOAD_BLOCK_HDR_LEN
;
939 dnload
.romload_state
= SENDING_BLOCKS
;
940 dnload
.block_number
= 0;
941 romload_prepare_block();
944 case WAITING_BLOCK_ACK
:
945 case LAST_BLOCK_SENT
:
946 if (!memcmp(buffer
, romload_block_ack
,
947 sizeof(romload_block_ack
))) {
948 if (dnload
.romload_state
== LAST_BLOCK_SENT
) {
949 /* send the checksum */
950 uint8_t final_checksum
=
951 (~(dnload
.romload_dl_checksum
) & 0xff);
952 rc
= write(dnload
.serial_fd
.fd
,
953 romload_checksum_cmd
,
954 sizeof(romload_checksum_cmd
));
955 rc
= write(dnload
.serial_fd
.fd
,
957 dnload
.romload_state
= WAITING_CHECKSUM_ACK
;
959 romload_prepare_block();
960 } else if (!memcmp(buffer
, romload_block_nack
,
961 sizeof(romload_block_nack
))) {
962 printf("Received block nack from phone, "
963 "something went wrong, aborting\n");
964 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
965 dnload
.romload_state
= WAITING_IDENTIFICATION
;
966 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
969 case WAITING_CHECKSUM_ACK
:
970 if (!memcmp(buffer
, romload_checksum_ack
,
971 sizeof(romload_checksum_ack
))) {
973 rc
= write(dnload
.serial_fd
.fd
, romload_branch_cmd
,
974 sizeof(romload_branch_cmd
));
975 rc
= write(dnload
.serial_fd
.fd
, &dnload
.load_address
,
976 sizeof(dnload
.load_address
));
977 dnload
.romload_state
= WAITING_BRANCH_ACK
;
979 } else if (!memcmp(buffer
, romload_checksum_nack
,
980 sizeof(romload_checksum_nack
))) {
981 printf("Checksum on phone side (0x%02x) doesn't "
982 "match ours, aborting\n", ~buffer
[2]);
983 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
984 dnload
.romload_state
= WAITING_IDENTIFICATION
;
985 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
989 case WAITING_BRANCH_ACK
:
990 if (!memcmp(buffer
, romload_branch_ack
,
991 sizeof(romload_branch_ack
))) {
992 printf("Received branch ack, your code is running now!\n");
993 dnload
.serial_fd
.when
= BSC_FD_READ
;
994 dnload
.romload_state
= FINISHED
;
995 dnload
.write_ptr
= dnload
.data
;
996 dnload
.expect_hdlc
= 1;
998 if (!dnload
.do_chainload
)
1001 /* if using chainloading mode, switch back to the Compal
1002 * ramloader settings to make sure the auto-reload
1005 dnload
.mode
= dnload
.previous_mode
;
1006 dnload
.romload_state
= WAITING_IDENTIFICATION
;
1007 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, MODEM_BAUDRATE
);
1008 } else if (!memcmp(buffer
, romload_branch_nack
,
1009 sizeof(romload_branch_nack
))) {
1010 printf("Received branch nack, aborting\n");
1011 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
1012 dnload
.romload_state
= WAITING_IDENTIFICATION
;
1013 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
1025 static int handle_read_mtk(void)
1027 int rc
, nbytes
, buf_used_len
;
1029 switch (dnload
.mtk_state
) {
1030 case MTK_WAIT_ADDR_ACK
:
1031 case MTK_WAIT_SIZE_ACK
:
1032 case MTK_WAIT_BRANCH_ADDR_ACK
:
1036 buf_used_len
= sizeof(buffer
);
1042 nbytes
= handle_buffer(buf_used_len
);
1046 switch (dnload
.mtk_state
) {
1048 if (!(buffer
[0] == mtk_init_resp
[0]))
1050 dnload
.mtk_state
= MTK_INIT_2
;
1051 printf("Received init magic byte 1\n");
1052 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[1], 1);
1055 if (!(buffer
[0] == mtk_init_resp
[1]))
1057 dnload
.mtk_state
= MTK_INIT_3
;
1058 printf("Received init magic byte 2\n");
1059 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[2], 1);
1062 if (!(buffer
[0] == mtk_init_resp
[2]))
1064 dnload
.mtk_state
= MTK_INIT_4
;
1065 printf("Received init magic byte 3\n");
1066 rc
= write(dnload
.serial_fd
.fd
, &mtk_init_cmd
[3], 1);
1069 if (!(buffer
[0] == mtk_init_resp
[3]))
1071 dnload
.mtk_state
= MTK_WAIT_WRITE_ACK
;
1072 printf("Received init magic byte 4, requesting write\n");
1073 rc
= write(dnload
.serial_fd
.fd
, &mtk_command
[0], 1);
1075 case MTK_WAIT_WRITE_ACK
:
1076 if (!(buffer
[0] == mtk_command
[0]))
1078 dnload
.mtk_state
= MTK_WAIT_ADDR_ACK
;
1079 printf("Received write ack, sending load address\n");
1081 rc
= write(dnload
.serial_fd
.fd
, &dnload
.load_address
,
1082 sizeof(dnload
.load_address
));
1084 case MTK_WAIT_ADDR_ACK
:
1085 if (memcmp(buffer
, dnload
.load_address
,
1086 sizeof(dnload
.load_address
)))
1088 printf("Received address ack from phone, sending loadsize\n");
1090 rc
= read_file(dnload
.filename
, 0);
1092 fprintf(stderr
, "read_file(%s) failed with %d\n",
1093 dnload
.filename
, rc
);
1096 dnload
.block_number
= 0;
1097 mtk_prepare_block();
1098 dnload
.mtk_state
= MTK_WAIT_SIZE_ACK
;
1099 rc
= write(dnload
.serial_fd
.fd
, &dnload
.mtk_send_size
,
1100 sizeof(dnload
.mtk_send_size
));
1102 case MTK_WAIT_SIZE_ACK
:
1103 if (memcmp(buffer
, dnload
.mtk_send_size
,
1104 sizeof(dnload
.mtk_send_size
)))
1106 printf("Received size ack\n");
1107 dnload
.expect_hdlc
= 1;
1108 dnload
.mtk_state
= MTK_SENDING_BLOCKS
;
1109 dnload
.serial_fd
.when
= BSC_FD_READ
| BSC_FD_WRITE
;
1112 case MTK_SENDING_BLOCKS
:
1113 if (!(buffer
[0] == dnload
.block
[dnload
.echo_bytecount
]))
1114 printf("Warning: Byte %i of Block %i doesn't match,"
1115 " check your serial connection!\n",
1116 dnload
.echo_bytecount
, dnload
.block_number
);
1117 dnload
.echo_bytecount
++;
1119 if ((dnload
.echo_bytecount
+1) > MTK_BLOCK_SIZE
) {
1120 if ( dnload
.block_number
== dnload
.block_count
) {
1121 rc
= write(dnload
.serial_fd
.fd
,
1122 &mtk_command
[3], 1);
1123 printf("Sending branch command\n");
1124 dnload
.expect_hdlc
= 0;
1125 dnload
.mtk_state
= MTK_WAIT_BRANCH_CMD_ACK
;
1128 printf("Received Block %i preparing next block\n",
1129 dnload
.block_number
);
1130 mtk_prepare_block();
1131 dnload
.serial_fd
.when
= BSC_FD_READ
| BSC_FD_WRITE
;
1134 case MTK_WAIT_BRANCH_CMD_ACK
:
1135 if (!(buffer
[0] == mtk_command
[3]))
1137 dnload
.mtk_state
= MTK_WAIT_BRANCH_ADDR_ACK
;
1138 printf("Received branch command ack, sending address\n");
1140 rc
= write(dnload
.serial_fd
.fd
, &dnload
.load_address
,
1141 sizeof(dnload
.load_address
));
1143 case MTK_WAIT_BRANCH_ADDR_ACK
:
1144 if (memcmp(buffer
, dnload
.load_address
,
1145 sizeof(dnload
.load_address
)))
1147 printf("Received branch address ack, code should run now\n");
1148 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, MODEM_BAUDRATE
);
1149 dnload
.serial_fd
.when
= BSC_FD_READ
;
1150 dnload
.mtk_state
= MTK_FINISHED
;
1151 dnload
.write_ptr
= dnload
.data
;
1152 dnload
.expect_hdlc
= 1;
1162 static int serial_read(struct osmo_fd
*fd
, unsigned int flags
)
1165 if (flags
& BSC_FD_READ
) {
1166 switch (dnload
.mode
) {
1168 while ((rc
= handle_read_romload()) > 0);
1171 while ((rc
= handle_read_mtk()) > 0);
1174 while ((rc
= handle_read()) > 0);
1181 if (flags
& BSC_FD_WRITE
) {
1182 rc
= handle_write();
1184 dnload
.state
= WAITING_PROMPT1
;
1189 static int parse_mode(const char *arg
)
1191 if (!strcasecmp(arg
, "c123"))
1193 else if (!strcasecmp(arg
, "c123xor"))
1194 return MODE_C123xor
;
1195 else if (!strcasecmp(arg
, "c140"))
1197 else if (!strcasecmp(arg
, "c140xor"))
1198 return MODE_C140xor
;
1199 else if (!strcasecmp(arg
, "c155"))
1201 else if (!strcasecmp(arg
, "romload"))
1202 return MODE_ROMLOAD
;
1203 else if (!strcasecmp(arg
, "mtk"))
1206 return MODE_INVALID
;
1210 "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \
1211 "\t\t [ -c ] (enable chainloading of highram-images)\n" \
1212 "\t\t [ -s /tmp/osmocom_l2 ]\n" \
1213 "\t\t [ -l /tmp/osmocom_loader ]\n" \
1214 "\t\t [ -m {c123,c123xor,c140,c140xor,c155,romload,mtk} ]\n" \
1215 "\t\t [ -i beacon-interval (mS) ]\n" \
1216 "\t\t file.bin\n\n" \
1217 "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \
1218 "* Perform handshaking with the ramloader in the phone\n" \
1219 "* Download file.bin to the attached phone (base address 0x00800100)\n"
1221 static int usage(const char *name
)
1223 printf("Usage: %s ", name
);
1228 static int version(const char *name
)
1230 printf("%s version %s\n", name
, PACKAGE_VERSION
);
1234 static int un_tool_read(struct osmo_fd
*fd
, unsigned int flags
)
1237 uint16_t length
= 0xffff;
1239 struct tool_connection
*con
= (struct tool_connection
*)fd
->data
;
1243 rc
= read(fd
->fd
, &buf
+ c
, 2 - c
);
1249 if(errno
== EAGAIN
) {
1252 fprintf(stderr
, "Err from socket: %s\n", strerror(errno
));
1258 memcpy(&length
, buf
, sizeof length
);
1259 length
= ntohs(length
);
1263 rc
= read(fd
->fd
, &buf
+ c
, length
- c
);
1269 if(errno
== EAGAIN
) {
1272 fprintf(stderr
, "Err from socket: %s\n", strerror(errno
));
1278 hdlc_send_to_phone(con
->server
->dlci
, buf
, length
);
1284 osmo_fd_unregister(fd
);
1285 llist_del(&con
->entry
);
1290 /* accept a new connection */
1291 static int tool_accept(struct osmo_fd
*fd
, unsigned int flags
)
1293 struct tool_server
*srv
= (struct tool_server
*)fd
->data
;
1294 struct tool_connection
*con
;
1295 struct sockaddr_un un_addr
;
1299 len
= sizeof(un_addr
);
1300 rc
= accept(fd
->fd
, (struct sockaddr
*) &un_addr
, &len
);
1302 fprintf(stderr
, "Failed to accept a new connection.\n");
1306 con
= talloc_zero(NULL
, struct tool_connection
);
1308 fprintf(stderr
, "Failed to create tool connection.\n");
1315 con
->fd
.when
= BSC_FD_READ
;
1316 con
->fd
.cb
= un_tool_read
;
1318 if (osmo_fd_register(&con
->fd
) != 0) {
1319 fprintf(stderr
, "Failed to register the fd.\n");
1323 llist_add(&con
->entry
, &srv
->connections
);
1328 * Register and start a tool server
1330 static int register_tool_server(struct tool_server
*ts
,
1334 struct osmo_fd
*bfd
= &ts
->bfd
;
1335 struct sockaddr_un local
;
1336 unsigned int namelen
;
1339 bfd
->fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1342 fprintf(stderr
, "Failed to create Unix Domain Socket.\n");
1346 local
.sun_family
= AF_UNIX
;
1347 strncpy(local
.sun_path
, path
, sizeof(local
.sun_path
));
1348 local
.sun_path
[sizeof(local
.sun_path
) - 1] = '\0';
1349 unlink(local
.sun_path
);
1351 /* we use the same magic that X11 uses in Xtranssock.c for
1352 * calculating the proper length of the sockaddr */
1353 #if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
1354 local
.sun_len
= strlen(local
.sun_path
);
1356 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1357 namelen
= SUN_LEN(&local
);
1359 namelen
= strlen(local
.sun_path
) +
1360 offsetof(struct sockaddr_un
, sun_path
);
1363 rc
= bind(bfd
->fd
, (struct sockaddr
*) &local
, namelen
);
1365 fprintf(stderr
, "Failed to bind the unix domain socket. '%s'\n",
1370 if (listen(bfd
->fd
, 0) != 0) {
1371 fprintf(stderr
, "Failed to listen.\n");
1375 bfd
->when
= BSC_FD_READ
;
1376 bfd
->cb
= tool_accept
;
1380 INIT_LLIST_HEAD(&ts
->connections
);
1382 tool_server_for_dlci
[dlci
] = ts
;
1384 sercomm_register_rx_cb(dlci
, hdlc_tool_cb
);
1386 if (osmo_fd_register(bfd
) != 0) {
1387 fprintf(stderr
, "Failed to register the bfd.\n");
1394 extern void hdlc_tpudbg_cb(uint8_t dlci
, struct msgb
*msg
);
1396 void parse_debug(const char *str
)
1407 printf("Unknown debug flag %c\n", *str
);
1415 int main(int argc
, char **argv
)
1418 uint32_t tmp_load_address
= ROMLOAD_ADDRESS
;
1419 const char *serial_dev
= "/dev/ttyUSB1";
1420 const char *layer2_un_path
= "/tmp/osmocom_l2";
1421 const char *loader_un_path
= "/tmp/osmocom_loader";
1423 dnload
.mode
= MODE_C123
;
1424 dnload
.beacon_interval
= DEFAULT_BEACON_INTERVAL
;
1425 dnload
.do_chainload
= 0;
1427 while ((opt
= getopt(argc
, argv
, "d:hl:p:m:cs:i:v")) != -1) {
1430 serial_dev
= optarg
;
1433 dnload
.mode
= parse_mode(optarg
);
1434 if (dnload
.mode
== MODE_INVALID
)
1438 layer2_un_path
= optarg
;
1441 loader_un_path
= optarg
;
1447 parse_debug(optarg
);
1450 dnload
.do_chainload
= 1;
1453 dnload
.beacon_interval
= atoi(optarg
) * 1000;
1462 if (argc
<= optind
) {
1463 dnload
.filename
= NULL
;
1465 dnload
.filename
= argv
[optind
];
1468 dnload
.serial_fd
.fd
= osmo_serial_init(serial_dev
, MODEM_BAUDRATE
);
1469 if (dnload
.serial_fd
.fd
< 0) {
1470 fprintf(stderr
, "Cannot open serial device %s\n", serial_dev
);
1474 if (osmo_fd_register(&dnload
.serial_fd
) != 0) {
1475 fprintf(stderr
, "Failed to register the serial.\n");
1479 /* Set serial socket to non-blocking mode of operation */
1480 flags
= fcntl(dnload
.serial_fd
.fd
, F_GETFL
);
1481 flags
|= O_NONBLOCK
;
1482 fcntl(dnload
.serial_fd
.fd
, F_SETFL
, flags
);
1484 dnload
.serial_fd
.when
= BSC_FD_READ
;
1485 dnload
.serial_fd
.cb
= serial_read
;
1487 /* initialize the HDLC layer */
1489 sercomm_register_rx_cb(SC_DLCI_CONSOLE
, hdlc_console_cb
);
1490 sercomm_register_rx_cb(SC_DLCI_DEBUG
, hdlc_tpudbg_cb
);
1492 /* unix domain socket handling */
1493 if (register_tool_server(&dnload
.layer2_server
, layer2_un_path
,
1494 SC_DLCI_L1A_L23
) != 0)
1497 if (register_tool_server(&dnload
.loader_server
, loader_un_path
,
1498 SC_DLCI_LOADER
) != 0)
1501 /* if in romload mode, start our beacon timer */
1502 if (dnload
.mode
== MODE_ROMLOAD
) {
1503 tmp_load_address
= ROMLOAD_ADDRESS
;
1504 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, ROMLOAD_INIT_BAUDRATE
);
1505 tick_timer
.cb
= &beacon_timer_cb
;
1506 tick_timer
.data
= &tick_timer
;
1507 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
1509 else if (dnload
.mode
== MODE_MTK
) {
1510 tmp_load_address
= MTK_ADDRESS
;
1511 osmo_serial_set_baudrate(dnload
.serial_fd
.fd
, MTK_INIT_BAUDRATE
);
1512 tick_timer
.cb
= &mtk_timer_cb
;
1513 tick_timer
.data
= &tick_timer
;
1514 osmo_timer_schedule(&tick_timer
, 0, dnload
.beacon_interval
);
1517 dnload
.load_address
[0] = (tmp_load_address
>> 24) & 0xff;
1518 dnload
.load_address
[1] = (tmp_load_address
>> 16) & 0xff;
1519 dnload
.load_address
[2] = (tmp_load_address
>> 8) & 0xff;
1520 dnload
.load_address
[3] = tmp_load_address
& 0xff;
1523 if (osmo_select_main(0) < 0)
1527 close(dnload
.serial_fd
.fd
);