summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Markgraf <steve@steve-m.de>2013-01-23 18:01:21 +0100
committerSylvain Munaut <tnt@246tNt.com>2013-04-07 11:34:48 +0200
commit1479b6812baa180fd97331c04bea6b58a1e54450 (patch)
tree254cf2dd8e81916558d117d97f7d17c2d15d781b
parent1a80966cbde423eb7e92bd341721ef981339a0f0 (diff)
osmocon: embed chainloader
This allows to directly load highram-images on compal phones with the commandline-switch -c. Signed-off-by: Steve Markgraf <steve@steve-m.de>
-rw-r--r--src/host/osmocon/osmocon.c109
1 files 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 }; /* <i */
static const uint8_t romload_abort_cmd[] = { 0x3c, 0x61 }; /* <a */
@@ -248,7 +265,7 @@ static void mtk_timer_cb(void *p)
}
/* Read the to-be-downloaded file, prepend header and length, append XOR sum */
-int read_file(const char *filename)
+int read_file(const char *filename, int chainload)
{
int fd, rc, i;
struct stat st;
@@ -260,17 +277,21 @@ int read_file(const char *filename)
uint8_t nibble;
uint8_t running_xor = 0x02;
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- perror("opening file");
- exit(1);
- }
+ if (!chainload) {
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror("opening file");
+ exit(1);
+ }
- 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;
+ 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;