X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Fhost%2Fosmocon%2Fosmocon.c;h=6f6f5669c708f0f823a3f6d91579057ac77e583d;hb=a69d67ec732ca35b2c71c261af04456ed64b9c9b;hp=b823b5b8709bd86052ae9ab46a6e5bb00d5b56a4;hpb=9faa6dd1d58fbf1584b22529efa127b49e6cae9e;p=osmocom-bb.git diff --git a/src/host/osmocon/osmocon.c b/src/host/osmocon/osmocon.c index b823b5b..6f6f566 100644 --- a/src/host/osmocon/osmocon.c +++ b/src/host/osmocon/osmocon.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -30,19 +31,18 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include #include +#include #include @@ -51,12 +51,16 @@ #define MAX_HDR_SIZE 128 #define MAGIC_OFFSET 0x3be2 +#define DEFAULT_BEACON_INTERVAL 50000 #define ROMLOAD_INIT_BAUDRATE B19200 #define ROMLOAD_DL_BAUDRATE B115200 -#define ROMLOAD_BEACON_INTERVAL 50000 #define ROMLOAD_BLOCK_HDR_LEN 10 #define ROMLOAD_ADDRESS 0x820000 +#define MTK_INIT_BAUDRATE B19200 +#define MTK_ADDRESS 0x40001400 +#define MTK_BLOCK_SIZE 1024 + struct tool_server *tool_server_for_dlci[256]; /** @@ -96,6 +100,20 @@ enum romload_state { FINISHED, }; +enum mtk_state { + MTK_INIT_1, + MTK_INIT_2, + MTK_INIT_3, + MTK_INIT_4, + MTK_WAIT_WRITE_ACK, + MTK_WAIT_ADDR_ACK, + MTK_WAIT_SIZE_ACK, + MTK_SENDING_BLOCKS, + MTK_WAIT_BRANCH_CMD_ACK, + MTK_WAIT_BRANCH_ADDR_ACK, + MTK_FINISHED, +}; + enum dnload_mode { MODE_C123, MODE_C123xor, @@ -103,16 +121,23 @@ enum dnload_mode { MODE_C140xor, MODE_C155, MODE_ROMLOAD, + MODE_MTK, }; struct dnload { enum dnload_state state; enum romload_state romload_state; + enum mtk_state mtk_state; enum dnload_mode mode; struct bsc_fd serial_fd; char *filename; + char *chainload_filename; - int print_hdlc; + int expect_hdlc; + + int dump_rx; + int dump_tx; + int beacon_interval; /* data to be downloaded */ uint8_t *data; @@ -127,6 +152,11 @@ struct dnload { uint16_t block_payload_size; int romload_dl_checksum; uint8_t *block_ptr; + uint8_t load_address[4]; + + uint8_t mtk_send_size[4]; + int block_count; + int echo_bytecount; struct tool_server layer2_server; struct tool_server loader_server; @@ -134,6 +164,7 @@ struct dnload { static struct dnload dnload; +static struct timer_list tick_timer; /* Compal ramloader specific */ static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 }; @@ -145,7 +176,19 @@ static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x1 static const uint8_t ftmtool[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c }; static const uint8_t phone_magic[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */ -/* romloader specific */ +/* The C123 has a hard-coded check inside the ramloader that requires the + * following bytes to be always the first four bytes of the image */ +static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 }; + +/* The C155 doesn't have some strange restriction on what the first four bytes + * have to be, but it starts the ramloader in THUMB mode. We use the following + * four bytes to switch back to ARM mode: + 800100: 4778 bx pc + 800102: 46c0 nop ; (mov r8, r8) + */ +static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 }; + +/* Calypso romloader specific */ static const uint8_t romload_ident_cmd[] = { 0x3c, 0x69 }; /* B */ static const uint8_t romload_param[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/* The C123 has a hard-coded check inside the ramloader that requires the following - * bytes to be always the first four bytes of the image */ -static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 }; - -/* The C155 doesn't have some strange restriction on what the first four bytes have - * to be, but it starts the ramloader in THUMB mode. We use the following four bytes - * to switch back to ARM mode: - 800100: 4778 bx pc - 800102: 46c0 nop ; (mov r8, r8) - */ -static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 }; +/* MTK romloader specific */ +static const uint8_t mtk_init_cmd[] = { 0xa0, 0x0a, 0x50, 0x05 }; +static const uint8_t mtk_init_resp[] = { 0x5f, 0xf5, 0xaf, 0xfa }; +static const uint8_t mtk_command[] = { 0xa1, 0xa2, 0xa4, 0xa8 }; /* FIXME: this routine is more or less what openbsc/src/rs232:rs232_setup() * does, we should move it to libosmocore at some point */ @@ -230,6 +266,11 @@ static int serial_set_baudrate(speed_t baudrate) int rc; struct termios tio; + rc = tcgetattr(dnload.serial_fd.fd, &tio); + if (rc < 0) { + perror("tcgetattr()"); + return rc; + } cfsetispeed(&tio, baudrate); cfsetospeed(&tio, baudrate); @@ -237,45 +278,35 @@ static int serial_set_baudrate(speed_t baudrate) return rc; } -static void reload_beacon_timer(void) -{ - struct itimerval t_val; - int rc; - - /* load timer to our > 24) & 0xff; + dnload.mtk_send_size[1] = (tmp_size >> 16) & 0xff; + dnload.mtk_send_size[2] = (tmp_size >> 8) & 0xff; + dnload.mtk_send_size[3] = tmp_size & 0xff; + + /* initialize write pointer to start of data */ + dnload.write_ptr = dnload.data; + } + + block_data = dnload.block; + dnload.write_ptr = dnload.data + 2 + + (dnload.block_len * dnload.block_number); + + remaining_bytes = dnload.data_len - 3 - + (dnload.block_len * dnload.block_number); + + memcpy(block_data, dnload.write_ptr, MTK_BLOCK_SIZE); + + if (remaining_bytes <= MTK_BLOCK_SIZE) { + fill_bytes = (MTK_BLOCK_SIZE - remaining_bytes); + printf("Preparing the last block, filling %i bytes\n", + fill_bytes); + memset(block_data + remaining_bytes, 0x00, fill_bytes); + dnload.romload_state = SENDING_LAST_BLOCK; + } else { + dnload.romload_state = SENDING_BLOCKS; + printf("Preparing block %i\n", dnload.block_number+1); + } + + /* for the mtk romloader we need to swap MSB <-> LSB */ + for (i = 0; i < dnload.block_len; i += 2) { + tmp_byteswap = dnload.block[i]; + dnload.block[i] = dnload.block[i+1]; + dnload.block[i+1] = tmp_byteswap; + } + + /* initialize block pointer to start of block */ + dnload.block_ptr = dnload.block; + + dnload.block_number++; return rc; } @@ -603,7 +713,9 @@ static int handle_sercomm_write(void) static int handle_write(void) { - if (dnload.mode == MODE_ROMLOAD) { + /* TODO: simplify this again (global state: downloading, sercomm) */ + switch (dnload.mode) { + case MODE_ROMLOAD: switch (dnload.romload_state) { case SENDING_BLOCKS: case SENDING_LAST_BLOCK: @@ -611,7 +723,16 @@ static int handle_write(void) default: return handle_sercomm_write(); } - } else { + break; + case MODE_MTK: + switch (dnload.mtk_state) { + case MTK_SENDING_BLOCKS: + return handle_write_block(); + default: + return handle_sercomm_write(); + } + break; + default: switch (dnload.state) { case DOWNLOADING: return handle_write_dnload(); @@ -631,8 +752,10 @@ static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len) struct msgb *msg; uint8_t *dest; - printf("hdlc_send_to_phone(dlci=%u): ", dlci); - hexdump(data, len); + if(dnload.dump_tx) { + printf("hdlc_send(dlci=%u): ", dlci); + hexdump(data, len); + } if (len > 512) { fprintf(stderr, "Too much data to send. %u\n", len); @@ -667,11 +790,16 @@ static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg) { struct tool_server *srv = tool_server_for_dlci[dlci]; + if(dnload.dump_rx) { + printf("hdlc_recv(dlci=%u): ", dlci); + hexdump(msg->data, msg->len); + } + if(srv) { struct tool_connection *con; - u_int16_t *len; + uint16_t *len; - len = (u_int16_t *) msgb_push(msg, 2); + len = (uint16_t *) msgb_push(msg, 2); *len = htons(msg->len - sizeof(*len)); llist_for_each_entry(con, &srv->connections, entry) { @@ -686,18 +814,9 @@ static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg) msgb_free(msg); } -static void print_hdlc(uint8_t *buffer, int length) -{ - int i; - - for (i = 0; i < length; ++i) - if (sercomm_drv_rx_char(buffer[i]) == 0) - printf("Dropping sample '%c'\n", buffer[i]); -} - static int handle_buffer(int buf_used_len) { - int nbytes, buf_left; + int nbytes, buf_left, i; buf_left = buf_used_len - (bufptr - buffer); if (buf_left <= 0) { @@ -710,12 +829,14 @@ static int handle_buffer(int buf_used_len) if (nbytes <= 0) return nbytes; - if (!dnload.print_hdlc) { + if (!dnload.expect_hdlc) { printf("got %i bytes from modem, ", nbytes); printf("data looks like: "); hexdump(bufptr, nbytes); } else { - print_hdlc(bufptr, nbytes); + for (i = 0; i < nbytes; ++i) + if (sercomm_drv_rx_char(bufptr[i]) == 0) + printf("Dropping sample '%c'\n", bufptr[i]); } return nbytes; @@ -732,34 +853,53 @@ static int handle_read(void) if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) { printf("Received PROMPT1 from phone, responding with CMD\n"); - dnload.print_hdlc = 0; + dnload.expect_hdlc = 0; dnload.state = WAITING_PROMPT2; - rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd)); - - /* re-read file */ - rc = read_file(dnload.filename); - if (rc < 0) { - fprintf(stderr, "read_file(%s) failed with %d\n", - dnload.filename, rc); - exit(1); + if(dnload.filename) { + rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd)); + + /* re-read file */ + rc = read_file(dnload.filename); + if (rc < 0) { + fprintf(stderr, "read_file(%s) failed with %d\n", + dnload.filename, rc); + exit(1); + } } } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) { printf("Received PROMPT2 from phone, starting download\n"); dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE; dnload.state = DOWNLOADING; } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) { - printf("Received DOWNLOAD ACK from phone, your code is running now!\n"); + printf("Received DOWNLOAD ACK from phone, your code is" + " running now!\n"); dnload.serial_fd.when = BSC_FD_READ; dnload.state = WAITING_PROMPT1; dnload.write_ptr = dnload.data; - dnload.print_hdlc = 1; + dnload.expect_hdlc = 1; + + /* check for romloader chainloading mode used as a workaround + * for the magic on the C139/C140 and J100i */ + if (dnload.chainload_filename != NULL) { + printf("Enabled Compal ramloader -> Calypso romloader" + " chainloading mode\n"); + bufptr = buffer; + dnload.filename = dnload.chainload_filename; + dnload.mode = MODE_ROMLOAD; + serial_set_baudrate(ROMLOAD_INIT_BAUDRATE); + tick_timer.cb = &beacon_timer_cb; + tick_timer.data = &tick_timer; + bsc_schedule_timer(&tick_timer, 0, dnload.beacon_interval); + } } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) { - printf("Received DOWNLOAD NACK from phone, something went wrong :(\n"); + printf("Received DOWNLOAD NACK from phone, something went" + " wrong :(\n"); dnload.serial_fd.when = BSC_FD_READ; dnload.state = WAITING_PROMPT1; dnload.write_ptr = dnload.data; } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) { - printf("Received MAGIC NACK from phone, you need to have \"1003\" at 0x803ce0\n"); + printf("Received MAGIC NACK from phone, you need to" + " have \"1003\" at 0x803ce0\n"); dnload.serial_fd.when = BSC_FD_READ; dnload.state = WAITING_PROMPT1; dnload.write_ptr = dnload.data; @@ -808,7 +948,7 @@ static int handle_read_romload(void) printf("Received ident ack from phone, sending " "parameter sequence\n"); - dnload.print_hdlc = 1; + dnload.expect_hdlc = 1; dnload.romload_state = WAITING_PARAM_ACK; rc = write(dnload.serial_fd.fd, romload_param, sizeof(romload_param)); @@ -828,8 +968,6 @@ static int handle_read_romload(void) printf("Received parameter ack from phone, " "starting download\n"); serial_set_baudrate(ROMLOAD_DL_BAUDRATE); - /* let the target's UART settle after changing baud*/ - usleep(ROMLOAD_BEACON_INTERVAL*2); /* using the max blocksize the phone tells us */ dnload.block_payload_size = ((buffer[3] << 8) + buffer[2]); @@ -866,8 +1004,7 @@ static int handle_read_romload(void) "something went wrong, aborting\n"); serial_set_baudrate(ROMLOAD_INIT_BAUDRATE); dnload.romload_state = WAITING_IDENTIFICATION; - usleep(ROMLOAD_BEACON_INTERVAL*2); - reload_beacon_timer(); + bsc_schedule_timer(&tick_timer, 0, dnload.beacon_interval); } break; case WAITING_CHECKSUM_ACK: @@ -875,28 +1012,21 @@ static int handle_read_romload(void) sizeof(romload_checksum_ack))) { printf("Checksum on phone side matches, " "let's branch to your code\n"); - - uint32_t branch_address_32 = ROMLOAD_ADDRESS; - uint8_t branch_address[4]; - branch_address[0] = (branch_address_32 >> 24) & 0xff; - branch_address[1] = (branch_address_32 >> 16) & 0xff; - branch_address[2] = (branch_address_32 >> 8) & 0xff; - branch_address[3] = branch_address_32 & 0xff; - printf("Branching to 0x%08x\n", branch_address_32); + printf("Branching to 0x%08x\n", ROMLOAD_ADDRESS); rc = write(dnload.serial_fd.fd, romload_branch_cmd, sizeof(romload_branch_cmd)); - rc = write(dnload.serial_fd.fd, &branch_address, 4); + rc = write(dnload.serial_fd.fd, &dnload.load_address, + sizeof(dnload.load_address)); dnload.romload_state = WAITING_BRANCH_ACK; bufptr -= 1; } else if (!memcmp(buffer, romload_checksum_nack, sizeof(romload_checksum_nack))) { printf("Checksum on phone side (0x%02x) doesn't " - "match ours, aborting\n", buffer[2]); + "match ours, aborting\n", ~buffer[2]); serial_set_baudrate(ROMLOAD_INIT_BAUDRATE); dnload.romload_state = WAITING_IDENTIFICATION; - usleep(ROMLOAD_BEACON_INTERVAL*2); - reload_beacon_timer(); + bsc_schedule_timer(&tick_timer, 0, dnload.beacon_interval); bufptr -= 1; } break; @@ -907,16 +1037,153 @@ static int handle_read_romload(void) dnload.serial_fd.when = BSC_FD_READ; dnload.romload_state = FINISHED; dnload.write_ptr = dnload.data; - dnload.print_hdlc = 1; + dnload.expect_hdlc = 1; } else if (!memcmp(buffer, romload_branch_nack, sizeof(romload_branch_nack))) { printf("Received branch nack, aborting\n"); serial_set_baudrate(ROMLOAD_INIT_BAUDRATE); dnload.romload_state = WAITING_IDENTIFICATION; - usleep(ROMLOAD_BEACON_INTERVAL*2); - reload_beacon_timer(); + bsc_schedule_timer(&tick_timer, 0, dnload.beacon_interval); + } + break; + default: + break; + } + + bufptr += nbytes; + return nbytes; +} + +/* MTK romloader */ +static int handle_read_mtk(void) +{ + int rc, nbytes, buf_used_len; + + switch (dnload.mtk_state) { + case MTK_WAIT_ADDR_ACK: + case MTK_WAIT_SIZE_ACK: + case MTK_WAIT_BRANCH_ADDR_ACK: + buf_used_len = 4; + break; + case MTK_FINISHED: + buf_used_len = sizeof(buffer); + break; + default: + buf_used_len = 1; + } + + nbytes = handle_buffer(buf_used_len); + if (nbytes <= 0) + return nbytes; + + switch (dnload.mtk_state) { + case MTK_INIT_1: + if (!(buffer[0] == mtk_init_resp[0])) + break; + dnload.mtk_state = MTK_INIT_2; + printf("Received init magic byte 1\n"); + rc = write(dnload.serial_fd.fd, &mtk_init_cmd[1], 1); + break; + case MTK_INIT_2: + if (!(buffer[0] == mtk_init_resp[1])) + break; + dnload.mtk_state = MTK_INIT_3; + printf("Received init magic byte 2\n"); + rc = write(dnload.serial_fd.fd, &mtk_init_cmd[2], 1); + break; + case MTK_INIT_3: + if (!(buffer[0] == mtk_init_resp[2])) + break; + dnload.mtk_state = MTK_INIT_4; + printf("Received init magic byte 3\n"); + rc = write(dnload.serial_fd.fd, &mtk_init_cmd[3], 1); + break; + case MTK_INIT_4: + if (!(buffer[0] == mtk_init_resp[3])) + break; + dnload.mtk_state = MTK_WAIT_WRITE_ACK; + printf("Received init magic byte 4, requesting write\n"); + rc = write(dnload.serial_fd.fd, &mtk_command[0], 1); + break; + case MTK_WAIT_WRITE_ACK: + if (!(buffer[0] == mtk_command[0])) + break; + dnload.mtk_state = MTK_WAIT_ADDR_ACK; + printf("Received write ack, sending load address\n"); + + rc = write(dnload.serial_fd.fd, &dnload.load_address, + sizeof(dnload.load_address)); + break; + case MTK_WAIT_ADDR_ACK: + if (memcmp(buffer, dnload.load_address, + sizeof(dnload.load_address))) + break; + printf("Received address ack from phone, sending loadsize\n"); + /* re-read file */ + rc = read_file(dnload.filename); + if (rc < 0) { + fprintf(stderr, "read_file(%s) failed with %d\n", + dnload.filename, rc); + exit(1); + } + dnload.block_number = 0; + mtk_prepare_block(); + dnload.mtk_state = MTK_WAIT_SIZE_ACK; + rc = write(dnload.serial_fd.fd, &dnload.mtk_send_size, + sizeof(dnload.mtk_send_size)); + break; + case MTK_WAIT_SIZE_ACK: + if (memcmp(buffer, dnload.mtk_send_size, + sizeof(dnload.mtk_send_size))) + break; + printf("Received size ack\n"); + dnload.expect_hdlc = 1; + dnload.mtk_state = MTK_SENDING_BLOCKS; + dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE; + bufptr -= 3; + break; + case MTK_SENDING_BLOCKS: + if (!(buffer[0] == dnload.block[dnload.echo_bytecount])) + printf("Warning: Byte %i of Block %i doesn't match," + " check your serial connection!\n", + dnload.echo_bytecount, dnload.block_number); + dnload.echo_bytecount++; + + if ((dnload.echo_bytecount+1) > MTK_BLOCK_SIZE) { + if ( dnload.block_number == dnload.block_count) { + rc = write(dnload.serial_fd.fd, + &mtk_command[3], 1); + printf("Sending branch command\n"); + dnload.expect_hdlc = 0; + dnload.mtk_state = MTK_WAIT_BRANCH_CMD_ACK; + break; + } + printf("Received Block %i preparing next block\n", + dnload.block_number); + mtk_prepare_block(); + dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE; } break; + case MTK_WAIT_BRANCH_CMD_ACK: + if (!(buffer[0] == mtk_command[3])) + break; + dnload.mtk_state = MTK_WAIT_BRANCH_ADDR_ACK; + printf("Received branch command ack, sending address\n"); + + rc = write(dnload.serial_fd.fd, &dnload.load_address, + sizeof(dnload.load_address)); + break; + case MTK_WAIT_BRANCH_ADDR_ACK: + if (memcmp(buffer, dnload.load_address, + sizeof(dnload.load_address))) + break; + printf("Received branch address ack, code should run now\n"); + serial_set_baudrate(MODEM_BAUDRATE); + dnload.serial_fd.when = BSC_FD_READ; + dnload.mtk_state = MTK_FINISHED; + dnload.write_ptr = dnload.data; + dnload.expect_hdlc = 1; + break; default: break; } @@ -929,11 +1196,17 @@ static int serial_read(struct bsc_fd *fd, unsigned int flags) { int rc; if (flags & BSC_FD_READ) { - if (dnload.mode == MODE_ROMLOAD) - rc = handle_read_romload(); - else - rc = handle_read(); - + switch (dnload.mode) { + case MODE_ROMLOAD: + rc = handle_read_romload(); + break; + case MODE_MTK: + rc = handle_read_mtk(); + break; + default: + rc = handle_read(); + break; + } if (rc == 0) exit(2); } @@ -960,15 +1233,20 @@ static int parse_mode(const char *arg) return MODE_C155; else if (!strcasecmp(arg, "romload")) return MODE_ROMLOAD; + else if (!strcasecmp(arg, "mtk")) + return MODE_MTK; return -1; } #define HELP_TEXT \ - "[ -v | -h ] [ -p /dev/ttyXXXX ] [ -s /tmp/osmocom_l2 ]\n" \ - "\t\t[ -l /tmp/osmocom_loader ]\n" \ - "\t\t[ -m {c123,c123xor,c140,c140xor,c155,romload} ]\n" \ - "\t\t file.bin\n\n" \ + "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \ + "\t\t [ -s /tmp/osmocom_l2 ]\n" \ + "\t\t [ -l /tmp/osmocom_loader ]\n" \ + "\t\t [ -m {c123,c123xor,c140,c140xor,c155,romload,mtk} ]\n" \ + "\t\t [ -c /to-be-chainloaded-file.bin ]\n" \ + "\t\t [ -i beacon-interval (mS) ]\n" \ + "\t\t file.bin\n\n" \ "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \ "* Perform handshaking with the ramloader in the phone\n" \ "* Download file.bin to the attached phone (base address 0x00800100)\n" @@ -989,8 +1267,8 @@ static int version(const char *name) static int un_tool_read(struct bsc_fd *fd, unsigned int flags) { int rc, c; - u_int16_t length = 0xffff; - u_int8_t buf[4096]; + uint16_t length = 0xffff; + uint8_t buf[4096]; struct tool_connection *con = (struct tool_connection *)fd->data; c = 0; @@ -1010,7 +1288,7 @@ static int un_tool_read(struct bsc_fd *fd, unsigned int flags) c += rc; } - length = ntohs(*(u_int16_t*)buf); + length = ntohs(*(uint16_t*)buf); c = 0; while(c < length) { @@ -1082,8 +1360,8 @@ static int tool_accept(struct bsc_fd *fd, unsigned int flags) * Register and start a tool server */ static int register_tool_server(struct tool_server *ts, - const char *path, - uint8_t dlci) + const char *path, + uint8_t dlci) { struct bsc_fd *bfd = &ts->bfd; struct sockaddr_un local; @@ -1147,16 +1425,38 @@ static int register_tool_server(struct tool_server *ts, extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg); +void parse_debug(const char *str) +{ + while(*str) { + switch(*str) { + case 't': + dnload.dump_tx = 1; + break; + case 'r': + dnload.dump_rx = 1; + break; + default: + printf("Unknown debug flag %c\n", *str); + abort(); + break; + } + str++; + } +} + int main(int argc, char **argv) { int opt, flags; + uint32_t tmp_load_address = ROMLOAD_ADDRESS; const char *serial_dev = "/dev/ttyUSB1"; const char *layer2_un_path = "/tmp/osmocom_l2"; const char *loader_un_path = "/tmp/osmocom_loader"; dnload.mode = MODE_C123; + dnload.chainload_filename = NULL; + dnload.beacon_interval = DEFAULT_BEACON_INTERVAL; - while ((opt = getopt(argc, argv, "hl:p:m:s:v")) != -1) { + while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:i:v")) != -1) { switch (opt) { case 'p': serial_dev = optarg; @@ -1175,6 +1475,15 @@ int main(int argc, char **argv) case 'v': version(argv[0]); break; + case 'd': + parse_debug(optarg); + break; + case 'c': + dnload.chainload_filename = optarg; + break; + case 'i': + dnload.beacon_interval = atoi(optarg) * 1000; + break; case 'h': default: usage(argv[0]); @@ -1183,12 +1492,11 @@ int main(int argc, char **argv) } if (argc <= optind) { - fprintf(stderr, "You have to specify the filename\n"); - usage(argv[0]); + dnload.filename = NULL; + } else { + dnload.filename = argv[optind]; } - dnload.filename = argv[optind]; - dnload.serial_fd.fd = serial_init(serial_dev); if (dnload.serial_fd.fd < 0) { fprintf(stderr, "Cannot open serial device %s\n", serial_dev); @@ -1224,9 +1532,24 @@ int main(int argc, char **argv) /* if in romload mode, start our beacon timer */ if (dnload.mode == MODE_ROMLOAD) { + tmp_load_address = ROMLOAD_ADDRESS; serial_set_baudrate(ROMLOAD_INIT_BAUDRATE); - start_beacon_timer(); + tick_timer.cb = &beacon_timer_cb; + tick_timer.data = &tick_timer; + bsc_schedule_timer(&tick_timer, 0, dnload.beacon_interval); } + else if (dnload.mode == MODE_MTK) { + tmp_load_address = MTK_ADDRESS; + serial_set_baudrate(MTK_INIT_BAUDRATE); + tick_timer.cb = &mtk_timer_cb; + tick_timer.data = &tick_timer; + bsc_schedule_timer(&tick_timer, 0, dnload.beacon_interval); + } + + dnload.load_address[0] = (tmp_load_address >> 24) & 0xff; + dnload.load_address[1] = (tmp_load_address >> 16) & 0xff; + dnload.load_address[2] = (tmp_load_address >> 8) & 0xff; + dnload.load_address[3] = tmp_load_address & 0xff; while (1) bsc_select_main(0);