From 1479b6812baa180fd97331c04bea6b58a1e54450 Mon Sep 17 00:00:00 2001 From: Steve Markgraf Date: Wed, 23 Jan 2013 18:01:21 +0100 Subject: osmocon: embed chainloader This allows to directly load highram-images on compal phones with the commandline-switch -c. Signed-off-by: Steve Markgraf --- src/host/osmocon/osmocon.c | 109 +++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/src/host/osmocon/osmocon.c b/src/host/osmocon/osmocon.c index 349e366a..01eafcdf 100644 --- a/src/host/osmocon/osmocon.c +++ b/src/host/osmocon/osmocon.c @@ -132,10 +132,10 @@ struct dnload { enum mtk_state mtk_state; enum dnload_mode mode, previous_mode; struct osmo_fd serial_fd; - char *filename, *previous_filename; - char *chainload_filename; + char *filename; int expect_hdlc; + int do_chainload; int dump_rx; int dump_tx; @@ -190,6 +190,23 @@ static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 }; */ static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 }; +/* small loader that enables the bootrom and executes the TI romloader: + * _start: + * ldr r1, =0x000a0000 + * wait: + * subs r1, r1, #1 + * bne wait + * ldr r1, =0xfffffb10 + * ldr r2, =0x100 + * strh r2, [r1] + * ldr pc, =0x0 + */ +static const uint8_t chainloader[] = { + 0x0a, 0x18, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff, + 0x1a, 0x08, 0x10, 0x9f, 0xe5, 0x01, 0x2c, 0xa0, 0xe3, 0xb0, 0x20, + 0xc1, 0xe1, 0x00, 0xf0, 0xa0, 0xe3, 0x10, 0xfb, 0xff, 0xff, +}; + /* Calypso romloader specific */ static const uint8_t romload_ident_cmd[] = { 0x3c, 0x69 }; /* MAX_DNLOAD_SIZE) && (dnload.mode != MODE_ROMLOAD)) { - fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n", - MAX_DNLOAD_SIZE); - return -EFBIG; + rc = fstat(fd, &st); + if ((st.st_size > MAX_DNLOAD_SIZE) && (dnload.mode != MODE_ROMLOAD)) { + fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n", + MAX_DNLOAD_SIZE); + return -EFBIG; + } + } else { + st.st_size = sizeof(chainloader); } free(dnload.data); @@ -338,25 +359,28 @@ int read_file(const char *filename) running_xor ^= hdr[i]; } - rc = read(fd, file_data, st.st_size); - if (rc < 0) { - perror("error reading file\n"); - free(dnload.data); - dnload.data = NULL; - close(fd); - return -EIO; - } - if (rc < st.st_size) { - free(dnload.data); - dnload.data = NULL; + if (!chainload) { + rc = read(fd, file_data, st.st_size); + if (rc < 0) { + perror("error reading file\n"); + free(dnload.data); + dnload.data = NULL; + close(fd); + return -EIO; + } + if (rc < st.st_size) { + free(dnload.data); + dnload.data = NULL; + close(fd); + fprintf(stderr, "Short read of file (%d < %d)\n", + rc, (int)st.st_size); + return -EIO; + } close(fd); - fprintf(stderr, "Short read of file (%d < %d)\n", - rc, (int)st.st_size); - return -EIO; + } else { + memcpy(file_data, chainloader, st.st_size); } - close(fd); - dnload.data_len = (file_data+payload_size) - dnload.data; /* fill memory between data end and magic, add magic */ @@ -378,7 +402,8 @@ int read_file(const char *filename) dnload.write_ptr = dnload.data; printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n", - filename, (int)st.st_size, hdr_len, dnload.data_len); + chainload ? "chainloader" : filename, (int)st.st_size, + hdr_len, dnload.data_len); return 0; } @@ -787,7 +812,7 @@ static int handle_read(void) rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd)); /* re-read file */ - rc = read_file(dnload.filename); + rc = read_file(dnload.filename, dnload.do_chainload); if (rc < 0) { fprintf(stderr, "read_file(%s) failed with %d\n", dnload.filename, rc); @@ -808,12 +833,10 @@ static int handle_read(void) /* check for romloader chainloading mode used as a workaround * for the magic on the C139/C140 and J100i */ - if (dnload.chainload_filename != NULL) { + if (dnload.do_chainload) { printf("Enabled Compal ramloader -> Calypso romloader" " chainloading mode\n"); bufptr = buffer; - dnload.previous_filename = dnload.filename; - dnload.filename = dnload.chainload_filename; dnload.previous_mode = dnload.mode; dnload.mode = MODE_ROMLOAD; osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE); @@ -883,7 +906,7 @@ static int handle_read_romload(void) rc = write(dnload.serial_fd.fd, romload_param, sizeof(romload_param)); /* re-read file */ - rc = read_file(dnload.filename); + rc = read_file(dnload.filename, 0); if (rc < 0) { fprintf(stderr, "read_file(%s) failed with %d\n", dnload.filename, rc); @@ -961,16 +984,15 @@ static int handle_read_romload(void) dnload.write_ptr = dnload.data; dnload.expect_hdlc = 1; - if (dnload.chainload_filename == NULL) + if (!dnload.do_chainload) break; /* if using chainloading mode, switch back to the Compal * ramloader settings to make sure the auto-reload * feature works */ bufptr = buffer; - dnload.romload_state = WAITING_IDENTIFICATION; - dnload.filename = dnload.previous_filename; dnload.mode = dnload.previous_mode; + dnload.romload_state = WAITING_IDENTIFICATION; osmo_serial_set_baudrate(dnload.serial_fd.fd, MODEM_BAUDRATE); } else if (!memcmp(buffer, romload_branch_nack, sizeof(romload_branch_nack))) { @@ -1054,7 +1076,7 @@ static int handle_read_mtk(void) break; printf("Received address ack from phone, sending loadsize\n"); /* re-read file */ - rc = read_file(dnload.filename); + rc = read_file(dnload.filename, 0); if (rc < 0) { fprintf(stderr, "read_file(%s) failed with %d\n", dnload.filename, rc); @@ -1175,10 +1197,10 @@ static int parse_mode(const char *arg) #define HELP_TEXT \ "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \ + "\t\t [ -c ] (enable chainloading of highram-images)\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" \ @@ -1388,11 +1410,10 @@ int main(int argc, char **argv) const char *loader_un_path = "/tmp/osmocom_loader"; dnload.mode = MODE_C123; - dnload.chainload_filename = NULL; - dnload.previous_filename = NULL; dnload.beacon_interval = DEFAULT_BEACON_INTERVAL; + dnload.do_chainload = 0; - while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:i:v")) != -1) { + while ((opt = getopt(argc, argv, "d:hl:p:m:cs:i:v")) != -1) { switch (opt) { case 'p': serial_dev = optarg; @@ -1415,7 +1436,7 @@ int main(int argc, char **argv) parse_debug(optarg); break; case 'c': - dnload.chainload_filename = optarg; + dnload.do_chainload = 1; break; case 'i': dnload.beacon_interval = atoi(optarg) * 1000; -- cgit v1.2.3