summaryrefslogtreecommitdiffstats
path: root/scripts/imx/imx-usb-loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/imx/imx-usb-loader.c')
-rw-r--r--scripts/imx/imx-usb-loader.c671
1 files changed, 282 insertions, 389 deletions
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 195b27b8ee..ed27831386 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -32,10 +32,21 @@
#include <stdlib.h>
#include <libusb.h>
#include <getopt.h>
+#include <linux/kernel.h>
+
+#include "imx.h"
#define get_min(a, b) (((a) < (b)) ? (a) : (b))
+#define FT_APP 0xaa
+#define FT_CSF 0xcc
+#define FT_DCD 0xee
+#define FT_LOAD_ONLY 0x00
+
int verbose;
+static int skip_image_dcd;
+static struct libusb_device_handle *usb_dev_handle;
+static struct usb_id *usb_id;
struct mach_id {
struct mach_id * next;
@@ -53,11 +64,6 @@ struct mach_id {
unsigned short max_transfer;
};
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
-#endif
-
struct usb_work {
char filename[256];
unsigned char dcd;
@@ -194,9 +200,10 @@ static libusb_device *find_imx_dev(libusb_device **devs, struct mach_id **pp_id)
return NULL;
}
-static void dump_long(unsigned char *src, unsigned cnt, unsigned addr)
+static void dump_long(const void *src, unsigned cnt, unsigned addr)
{
- unsigned *p = (unsigned *)src;
+ const unsigned *p = (unsigned *)src;
+
while (cnt >= 32) {
printf("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
addr, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
@@ -215,9 +222,9 @@ static void dump_long(unsigned char *src, unsigned cnt, unsigned addr)
}
}
-static void dump_bytes(unsigned char *src, unsigned cnt, unsigned addr)
+static void dump_bytes(const void *src, unsigned cnt, unsigned addr)
{
- unsigned char *p = src;
+ const unsigned char *p = src;
int i;
while (cnt >= 16) {
@@ -297,12 +304,11 @@ static long get_file_size(FILE *xfile)
* EP2IN - bulk in
* (max packet size of 512 bytes)
*/
-static int transfer(struct libusb_device_handle *h, int report, unsigned char *p, unsigned cnt,
- int* last_trans, struct usb_id *p_id)
+static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
{
int err;
- if (cnt > p_id->mach_id->max_transfer)
- cnt = p_id->mach_id->max_transfer;
+ if (cnt > usb_id->mach_id->max_transfer)
+ cnt = usb_id->mach_id->max_transfer;
if (verbose > 4) {
printf("report=%i\n", report);
@@ -310,9 +316,10 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
dump_bytes(p, cnt, 0);
}
- if (p_id->mach_id->mode == MODE_BULK) {
+ if (usb_id->mach_id->mode == MODE_BULK) {
*last_trans = 0;
- err = libusb_bulk_transfer(h, (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
+ err = libusb_bulk_transfer(usb_dev_handle,
+ (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
} else {
unsigned char tmp[1028];
@@ -320,7 +327,7 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
if (report < 3) {
memcpy(&tmp[1], p, cnt);
- err = libusb_control_transfer(h,
+ err = libusb_control_transfer(usb_dev_handle,
CTRL_OUT,
HID_SET_REPORT,
(HID_REPORT_TYPE_OUTPUT << 8) | report,
@@ -332,7 +339,8 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
} else {
*last_trans = 0;
memset(&tmp[1], 0, cnt);
- err = libusb_interrupt_transfer(h, 1 + EP_IN, tmp, cnt + 1, last_trans, 1000);
+ err = libusb_interrupt_transfer(usb_dev_handle,
+ 1 + EP_IN, tmp, cnt + 1, last_trans, 1000);
if (err >= 0) {
if (tmp[0] == (unsigned char)report) {
if (*last_trans > 1) {
@@ -354,7 +362,7 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
return err;
}
-int do_status(libusb_device_handle *h, struct usb_id *p_id)
+int do_status(void)
{
int last_trans;
unsigned char tmp[64];
@@ -369,14 +377,14 @@ int do_status(libusb_device_handle *h, struct usb_id *p_id)
};
for (;;) {
- err = transfer(h, 1, (unsigned char*)status_command, 16, &last_trans, p_id);
+ err = transfer(1, (unsigned char*)status_command, 16, &last_trans);
if (verbose > 2)
printf("report 1, wrote %i bytes, err=%i\n", last_trans, err);
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 3, tmp, 64, &last_trans, p_id);
+ err = transfer(3, tmp, 64, &last_trans);
if (verbose > 2) {
printf("report 3, read %i bytes, err=%i\n", last_trans, err);
@@ -392,8 +400,8 @@ int do_status(libusb_device_handle *h, struct usb_id *p_id)
break;
}
- if (p_id->mach_id->mode == MODE_HID) {
- err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id);
+ if (usb_id->mach_id->mode == MODE_HID) {
+ err = transfer(4, tmp, sizeof(tmp), &last_trans);
if (err)
printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
@@ -402,43 +410,9 @@ int do_status(libusb_device_handle *h, struct usb_id *p_id)
return err;
}
-struct boot_data {
- uint32_t dest;
- uint32_t image_len;
- uint32_t plugin;
-};
-
-struct imx_flash_header_v2 {
-#define IVT_BARKER 0x402000d1
- uint32_t barker;
- uint32_t start_addr;
- uint32_t reserv1;
- uint32_t dcd_ptr;
- uint32_t boot_data_ptr; /* struct boot_data * */
- uint32_t self_ptr; /* struct imx_flash_header_v2 *, this - boot_data.start = offset linked at */
- uint32_t app_code_csf;
- uint32_t reserv2;
-};
-
-/*
- * MX51 header type
- */
-struct imx_flash_header_v1 {
- uint32_t app_start_addr;
-#define APP_BARKER 0xb1
-#define DCD_BARKER 0xb17219e9
- uint32_t app_barker;
- uint32_t csf_ptr;
- uint32_t dcd_ptr_ptr;
- uint32_t srk_ptr;
- uint32_t dcd_ptr;
- uint32_t app_dest_ptr;
-};
-
#define V(a) (((a) >> 24) & 0xff), (((a) >> 16) & 0xff), (((a) >> 8) & 0xff), ((a) & 0xff)
-static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned addr, unsigned char *dest, unsigned cnt)
+static int read_memory(unsigned addr, unsigned char *dest, unsigned cnt)
{
static unsigned char read_reg_command[] = {
1,
@@ -466,7 +440,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
read_reg_command[10] = (unsigned char)(cnt);
for (;;) {
- err = transfer(h, 1, read_reg_command, 16, &last_trans, p_id);
+ err = transfer(1, read_reg_command, 16, &last_trans);
if (!err)
break;
printf("read_reg_command err=%i, last_trans=%i\n", err, last_trans);
@@ -476,7 +450,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
retry++;
}
- err = transfer(h, 3, tmp, 4, &last_trans, p_id);
+ err = transfer(3, tmp, 4, &last_trans);
if (err) {
printf("r3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
@@ -487,7 +461,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
while (rem) {
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
- err = transfer(h, 4, tmp, 64, &last_trans, p_id);
+ err = transfer(4, tmp, 64, &last_trans);
if (err) {
printf("r4 in err=%i, last_trans=%i %02x %02x %02x %02x cnt=%u rem=%d\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem);
@@ -511,8 +485,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
return err;
}
-static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned addr, unsigned val, int width)
+static int write_memory(unsigned addr, unsigned val, int width)
{
int retry = 0;
int last_trans;
@@ -555,7 +528,7 @@ static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
write_reg_command[14] = (unsigned char)(val);
for (;;) {
- err = transfer(h, 1, write_reg_command, 16, &last_trans, p_id);
+ err = transfer(1, write_reg_command, 16, &last_trans);
if (!err)
break;
printf("write_reg_command err=%i, last_trans=%i\n", err, last_trans);
@@ -567,7 +540,7 @@ static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
if (err) {
printf("w3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
@@ -576,25 +549,109 @@ static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id);
+ err = transfer(4, tmp, sizeof(tmp), &last_trans);
if (err)
printf("w4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
return err;
}
-static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_id,
- struct imx_flash_header_v2 *hdr, unsigned char *file_start, unsigned cnt)
+static int load_file(void *buf, unsigned len, unsigned dladdr, unsigned char type)
+{
+ static unsigned char dl_command[] = {
+ 0x04,
+ 0x04,
+ V(0), /* address */
+ 0x00, /* format */
+ V(0x00000020), /* data count */
+ V(0), /* data */
+ 0xaa, /* type */
+ };
+ int last_trans, err;
+ int retry = 0;
+ unsigned transfer_size = 0;
+ unsigned char tmp[64];
+ void *p;
+ int cnt;
+
+ dl_command[2] = (unsigned char)(dladdr >> 24);
+ dl_command[3] = (unsigned char)(dladdr >> 16);
+ dl_command[4] = (unsigned char)(dladdr >> 8);
+ dl_command[5] = (unsigned char)(dladdr);
+
+ dl_command[7] = (unsigned char)(len >> 24);
+ dl_command[8] = (unsigned char)(len >> 16);
+ dl_command[9] = (unsigned char)(len >> 8);
+ dl_command[10] = (unsigned char)(len);
+ dl_command[15] = type;
+
+ for (;;) {
+ err = transfer(1, dl_command, 16, &last_trans);
+ if (!err)
+ break;
+
+ printf("dl_command err=%i, last_trans=%i\n", err, last_trans);
+
+ if (retry > 5)
+ return -4;
+ retry++;
+ }
+
+ retry = 0;
+
+ if (usb_id->mach_id->mode == MODE_BULK) {
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
+ if (err)
+ printf("in err=%i, last_trans=%i %02x %02x %02x %02x\n",
+ err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
+ }
+
+ p = buf;
+ cnt = len;
+
+ while (1) {
+ int now = get_min(cnt, usb_id->mach_id->max_transfer);
+
+ if (!now)
+ break;
+
+ err = transfer(2, p, now, &now);
+ if (err) {
+ printf("dl_command err=%i, last_trans=%i\n", err, last_trans);
+ return err;
+ }
+
+ p += now;
+ cnt -= now;
+ }
+
+ if (usb_id->mach_id->mode == MODE_HID) {
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
+ if (err)
+ printf("3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
+ err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
+ err = transfer(4, tmp, sizeof(tmp), &last_trans);
+ if (err)
+ printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
+ err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
+ } else {
+ do_status();
+ }
+
+ return transfer_size;
+}
+
+static int write_dcd_table_ivt(struct imx_flash_header_v2 *hdr, unsigned char *file_start, unsigned cnt)
{
unsigned char *dcd_end;
unsigned m_length;
-#define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self_ptr)
+#define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self)
unsigned char* dcd;
unsigned char* file_end = file_start + cnt;
int err = 0;
if (!hdr->dcd_ptr) {
- printf("No dcd table, barker=%x\n", hdr->barker);
+ printf("No dcd table in this ivt\n");
return 0; /* nothing to do */
}
@@ -646,7 +703,7 @@ static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_
unsigned val = (dcd[4] << 24) | (dcd[5] << 16) | (dcd[6] << 8) | dcd[7];
dcd += 8;
- err = write_memory(h, p_id, addr, val, 4);
+ err = write_memory(addr, val, 4);
if (err < 0)
return err;
}
@@ -654,27 +711,27 @@ static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_
return err;
}
-static int get_dcd_range_old(struct imx_flash_header_v1 *hdr,
+static int get_dcd_range_old(struct imx_flash_header *hdr,
unsigned char *file_start, unsigned cnt,
unsigned char **pstart, unsigned char **pend)
{
unsigned char *dcd_end;
unsigned m_length;
-#define cvt_dest_to_src_old (((unsigned char *)&hdr->dcd_ptr) - hdr->dcd_ptr_ptr)
+#define cvt_dest_to_src_old (((unsigned char *)&hdr->dcd) - hdr->dcd_ptr_ptr)
unsigned char* dcd;
unsigned val;
unsigned char* file_end = file_start + cnt;
- if (!hdr->dcd_ptr) {
- printf("No dcd table, barker=%x\n", hdr->app_barker);
- *pstart = *pend = ((unsigned char *)hdr) + sizeof(struct imx_flash_header_v1);
+ if (!hdr->dcd) {
+ printf("No dcd table, barker=%x\n", hdr->app_code_barker);
+ *pstart = *pend = ((unsigned char *)hdr) + sizeof(struct imx_flash_header);
return 0; /* nothing to do */
}
- dcd = hdr->dcd_ptr + cvt_dest_to_src_old;
+ dcd = hdr->dcd + cvt_dest_to_src_old;
if ((dcd < file_start) || ((dcd + 8) > file_end)) {
- printf("bad dcd_ptr %08x\n", hdr->dcd_ptr);
+ printf("bad dcd_ptr %08x\n", hdr->dcd);
return -1;
}
@@ -701,8 +758,7 @@ static int get_dcd_range_old(struct imx_flash_header_v1 *hdr,
return 0;
}
-static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_id,
- struct imx_flash_header_v1 *hdr, unsigned char *file_start, unsigned cnt)
+static int write_dcd_table_old(struct imx_flash_header *hdr, unsigned char *file_start, unsigned cnt)
{
unsigned val;
unsigned char *dcd_end;
@@ -723,14 +779,14 @@ static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_
case 1:
if (verbose > 1)
printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val);
- err = write_memory(h, p_id, addr, val, 1);
+ err = write_memory(addr, val, 1);
if (err < 0)
return err;
break;
case 4:
if (verbose > 1)
printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val);
- err = write_memory(h, p_id, addr, val, 4);
+ err = write_memory(addr, val, 4);
if (err < 0)
return err;
break;
@@ -747,117 +803,79 @@ static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_
return err;
}
-static int verify_memory(struct libusb_device_handle *h, struct usb_id *p_id,
- FILE *xfile, unsigned offset, unsigned addr, unsigned size,
- unsigned char *verify_buffer, unsigned verify_cnt)
+static int verify_memory(const void *buf, unsigned len, unsigned addr)
{
- int mismatch = 0;
- unsigned char file_buf[1024];
- fseek(xfile, offset + verify_cnt, SEEK_SET);
-
- while (size) {
- unsigned char mem_buf[64];
- unsigned char *p = file_buf;
- int cnt = addr & 0x3f;
- int request = get_min(size, sizeof(file_buf));
-
- if (cnt) {
- cnt = 64 - cnt;
- if (request > cnt)
- request = cnt;
- }
+ int ret, mismatch = 0;
+ void *readbuf;
+ unsigned offset = 0, now;
- if (verify_cnt) {
- p = verify_buffer;
- cnt = get_min(request, verify_cnt);
- verify_buffer += cnt;
- verify_cnt -= cnt;
- } else {
- cnt = fread(p, 1, request, xfile);
- if (cnt <= 0) {
- printf("Unexpected end of file, request=0x%0x, size=0x%x, cnt=%i\n",
- request, size, cnt);
- return -1;
- }
- }
-
- size -= cnt;
-
- while (cnt) {
- int ret;
+ readbuf = malloc(len);
+ if (!readbuf)
+ return -ENOMEM;
- request = get_min(cnt, sizeof(mem_buf));
-
- ret = read_memory(h, p_id, addr, mem_buf, request);
- if (ret < 0)
- return ret;
-
- if (memcmp(p, mem_buf, request)) {
- unsigned char * m = mem_buf;
- if (!mismatch)
- printf("!!!!mismatch\n");
- mismatch++;
-
- while (request) {
- unsigned req = get_min(request, 32);
- if (memcmp(p, m, req)) {
- dump_long(p, req, offset);
- dump_long(m, req, addr);
- printf("\n");
- }
- p += req;
- m+= req;
- offset += req;
- addr += req;
- cnt -= req;
- request -= req;
- }
- if (mismatch >= 5)
- return -1;
- }
- p += request;
- offset += request;
- addr += request;
- cnt -= request;
+ ret = read_memory(addr, readbuf, len);
+ if (ret < 0)
+ goto err;
+
+ while (len) {
+ now = get_min(len, 32);
+
+ if (memcmp(buf + offset, readbuf + offset, now)) {
+ printf("mismatch at offset 0x%08x. expected:\n", offset);
+ dump_long(buf + offset, now, addr + offset);
+ printf("read:\n");
+ dump_long(readbuf + offset, now, addr + offset);
+ ret = -EINVAL;
+ mismatch++;
+ if (mismatch > 4)
+ goto err;
}
+
+ len -= now;
+ offset += now;
}
- return mismatch ? -1 : 0;
+err:
+ free(readbuf);
+
+ return ret;
}
-static int is_header(struct usb_id *p_id, unsigned char *p)
+static int is_header(unsigned char *p)
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- switch (p_id->mach_id->header_type) {
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
- if (ohdr->app_barker == 0xb1)
+ if (ohdr->app_code_barker == 0xb1)
return 1;
break;
case HDR_MX53:
- if (hdr->barker == IVT_BARKER)
+ if (hdr->header.tag == TAG_IVT_HEADER && hdr->header.version == IVT_VERSION)
return 1;
}
return 0;
}
-static int perform_dcd(struct libusb_device_handle *h, struct usb_id *p_id, unsigned char *p,
- unsigned char *file_start, unsigned cnt)
+static int perform_dcd(unsigned char *p, unsigned char *file_start, unsigned cnt)
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
int ret = 0;
- switch (p_id->mach_id->header_type) {
+ if (skip_image_dcd)
+ return 0;
+
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
- ret = write_dcd_table_old(h, p_id, ohdr, file_start, cnt);
- ohdr->dcd_ptr = 0;
+ ret = write_dcd_table_old(ohdr, file_start, cnt);
+ ohdr->dcd_block_len = 0;
break;
case HDR_MX53:
- ret = write_dcd_table_ivt(h, p_id, hdr, file_start, cnt);
+ ret = write_dcd_table_ivt(hdr, file_start, cnt);
hdr->dcd_ptr = 0;
break;
@@ -866,16 +884,15 @@ static int perform_dcd(struct libusb_device_handle *h, struct usb_id *p_id, unsi
return ret;
}
-static int clear_dcd_ptr(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned char *p, unsigned char *file_start, unsigned cnt)
+static int clear_dcd_ptr(unsigned char *p, unsigned char *file_start, unsigned cnt)
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- switch (p_id->mach_id->header_type) {
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
- printf("clear dcd_ptr=0x%08x\n", ohdr->dcd_ptr);
- ohdr->dcd_ptr = 0;
+ printf("clear dcd_ptr=0x%08x\n", ohdr->dcd);
+ ohdr->dcd = 0;
break;
case HDR_MX53:
printf("clear dcd_ptr=0x%08x\n", hdr->dcd_ptr);
@@ -885,21 +902,21 @@ static int clear_dcd_ptr(struct libusb_device_handle *h, struct usb_id *p_id,
return 0;
}
-static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *file_start,
+static int get_dl_start(unsigned char *p, unsigned char *file_start,
unsigned cnt, unsigned *dladdr, unsigned *max_length, unsigned *plugin,
unsigned *header_addr)
{
unsigned char* file_end = file_start + cnt;
- switch (p_id->mach_id->header_type) {
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
unsigned char *dcd_end;
unsigned char* dcd;
int err = get_dcd_range_old(ohdr, file_start, cnt, &dcd, &dcd_end);
- *dladdr = ohdr->app_dest_ptr;
- *header_addr = ohdr->dcd_ptr_ptr - offsetof(struct imx_flash_header_v1, dcd_ptr);
+ *dladdr = ohdr->app_dest;
+ *header_addr = ohdr->dcd_ptr_ptr - offsetof(struct imx_flash_header, dcd);
*plugin = 0;
if (err >= 0)
*max_length = dcd_end[0] | (dcd_end[1] << 8) | (dcd_end[2] << 16) | (dcd_end[3] << 24);
@@ -911,20 +928,18 @@ static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *fi
unsigned char *bd;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- *dladdr = hdr->self_ptr;
- *header_addr = hdr->self_ptr;
+ *dladdr = hdr->self;
+ *header_addr = hdr->self;
bd = hdr->boot_data_ptr + cvt_dest_to_src;
if ((bd < file_start) || ((bd + 4) > file_end)) {
printf("bad boot_data_ptr %08x\n", hdr->boot_data_ptr);
return -1;
}
- *dladdr = ((struct boot_data *)bd)->dest;
- *max_length = ((struct boot_data *)bd)->image_len;
- *plugin = ((struct boot_data *)bd)->plugin;
- ((struct boot_data *)bd)->plugin = 0;
-
- hdr->boot_data_ptr = 0;
+ *dladdr = ((struct imx_boot_data *)bd)->start;
+ *max_length = ((struct imx_boot_data *)bd)->size;
+ *plugin = ((struct imx_boot_data *)bd)->plugin;
+ ((struct imx_boot_data *)bd)->plugin = 0;
break;
}
@@ -932,8 +947,7 @@ static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *fi
return 0;
}
-static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
- struct usb_work *curr, unsigned char *buf, int cnt,
+static int process_header(struct usb_work *curr, unsigned char *buf, int cnt,
unsigned *p_dladdr, unsigned *p_max_length, unsigned *p_plugin,
unsigned *p_header_addr)
{
@@ -946,17 +960,17 @@ static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
for (header_offset = 0; header_offset < header_max; header_offset += header_inc, p += header_inc) {
- if (!is_header(p_id, p))
+ if (!is_header(p))
continue;
- ret = get_dl_start(p_id, p, buf, cnt, p_dladdr, p_max_length, p_plugin, p_header_addr);
+ ret = get_dl_start(p, buf, cnt, p_dladdr, p_max_length, p_plugin, p_header_addr);
if (ret < 0) {
printf("!!get_dl_start returned %i\n", ret);
return ret;
}
if (curr->dcd) {
- ret = perform_dcd(h, p_id, p, buf, cnt);
+ ret = perform_dcd(p, buf, cnt);
if (ret < 0) {
printf("!!perform_dcd returned %i\n", ret);
return ret;
@@ -969,7 +983,7 @@ static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
}
if (curr->clear_dcd) {
- ret = clear_dcd_ptr(h, p_id, p, buf, cnt);
+ ret = clear_dcd_ptr(p, buf, cnt);
if (ret < 0) {
printf("!!clear_dcd returned %i\n", ret);
return ret;
@@ -995,137 +1009,7 @@ static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
return -ENODEV;
}
-static int load_file(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned char *p, int cnt, unsigned char *buf, unsigned buf_cnt,
- unsigned dladdr, unsigned fsize, unsigned char type, FILE* xfile)
-{
- static unsigned char dl_command[] = {
- 0x04,
- 0x04,
- V(0), /* address */
- 0x00, /* format */
- V(0x00000020), /* data count */
- V(0), /* data */
- 0xaa, /* type */
- };
- int last_trans, err;
- int retry = 0;
- unsigned transfer_size = 0;
- int max = p_id->mach_id->max_transfer;
- unsigned char tmp[64];
-
- dl_command[2] = (unsigned char)(dladdr >> 24);
- dl_command[3] = (unsigned char)(dladdr >> 16);
- dl_command[4] = (unsigned char)(dladdr >> 8);
- dl_command[5] = (unsigned char)(dladdr);
-
- dl_command[7] = (unsigned char)(fsize >> 24);
- dl_command[8] = (unsigned char)(fsize >> 16);
- dl_command[9] = (unsigned char)(fsize >> 8);
- dl_command[10] = (unsigned char)(fsize);
- dl_command[15] = type;
-
- for (;;) {
- err = transfer(h, 1, dl_command, 16, &last_trans, p_id);
- if (!err)
- break;
-
- printf("dl_command err=%i, last_trans=%i\n", err, last_trans);
-
- if (retry > 5)
- return -4;
- retry++;
- }
-
- retry = 0;
-
- if (p_id->mach_id->mode == MODE_BULK) {
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
- if (err)
- printf("in err=%i, last_trans=%i %02x %02x %02x %02x\n",
- err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
- }
-
- while (1) {
- int retry;
-
- if (cnt > (int)(fsize - transfer_size))
- cnt = (fsize - transfer_size);
-
- if (cnt <= 0)
- break;
-
- retry = 0;
-
- while (cnt) {
- err = transfer(h, 2, p, get_min(cnt, max), &last_trans, p_id);
- if (err) {
- printf("out err=%i, last_trans=%i cnt=0x%x max=0x%x transfer_size=0x%X retry=%i\n",
- err, last_trans, cnt, max, transfer_size, retry);
- if (retry >= 10) {
- printf("Giving up\n");
- return err;
- }
- if (max >= 16)
- max >>= 1;
- else
- max <<= 1;
- usleep(10000);
- retry++;
- continue;
- }
- max = p_id->mach_id->max_transfer;
- retry = 0;
- if (cnt < last_trans) {
- printf("error: last_trans=0x%x, attempted only=0%x\n", last_trans, cnt);
- cnt = last_trans;
- }
- if (!last_trans) {
- printf("Nothing last_trans, err=%i\n", err);
- break;
- }
- p += last_trans;
- cnt -= last_trans;
- transfer_size += last_trans;
- }
-
- if (!last_trans)
- break;
-
- if (feof(xfile))
- break;
-
- cnt = fsize - transfer_size;
- if (cnt <= 0)
- break;
-
- cnt = fread(buf, 1 , get_min(cnt, buf_cnt), xfile);
- p = buf;
- }
-
- if (p_id->mach_id->mode == MODE_HID) {
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
- if (err)
- printf("3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
- err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
- err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id);
- if (err)
- printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
- err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
- } else {
- do_status(h, p_id);
- }
-
- return transfer_size;
-}
-
-#define FT_APP 0xaa
-#define FT_CSF 0xcc
-#define FT_DCD 0xee
-#define FT_LOAD_ONLY 0x00
-
-static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
- struct usb_work *curr, int verify)
+static int do_irom_download(struct usb_work *curr, int verify)
{
static unsigned char jump_command[] = {0x0b,0x0b, V(0), 0x00, V(0x00000000), V(0), 0x00};
@@ -1137,10 +1021,9 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
int cnt;
unsigned file_base;
int last_trans, err;
-#define BUF_SIZE (1024*16)
unsigned char *buf = NULL;
+ unsigned char *image;
unsigned char *verify_buffer = NULL;
- unsigned verify_cnt;
unsigned char *p;
unsigned char tmp[64];
unsigned dladdr = 0;
@@ -1149,7 +1032,6 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
unsigned header_addr = 0;
unsigned skip = 0;
- unsigned transfer_size=0;
int retry = 0;
xfile = fopen(curr->filename, "rb" );
@@ -1158,26 +1040,29 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
return -5;
}
- buf = malloc(BUF_SIZE);
- if (!buf) {
- printf("error, out of memory\n");
+ fsize = get_file_size(xfile);
+ if (fsize < 0x20) {
+ printf("error, file: %s is too small\n", curr->filename);
ret = -2;
goto cleanup;
}
- fsize = get_file_size(xfile);
-
- cnt = fread(buf, 1 , BUF_SIZE, xfile);
-
- if (cnt < 0x20) {
- printf("error, file: %s is too small\n", curr->filename);
+ buf = malloc(fsize);
+ if (!buf) {
+ printf("error, out of memory\n");
ret = -2;
goto cleanup;
}
+ cnt = fread(buf, 1 , fsize, xfile);
+ if (cnt < fsize) {
+ printf("error, cannot read %s\n", curr->filename);
+ return -1;
+ }
+
max_length = fsize;
- ret = process_header(h, p_id, curr, buf, cnt,
+ ret = process_header(curr, buf, cnt,
&dladdr, &max_length, &plugin, &header_addr);
if (ret < 0)
goto cleanup;
@@ -1206,7 +1091,7 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
type = (curr->plug || curr->jump_mode) ? FT_APP : FT_LOAD_ONLY;
- if (p_id->mach_id->mode == MODE_BULK && type == FT_APP) {
+ if (usb_id->mach_id->mode == MODE_BULK && type == FT_APP) {
/* No jump command, dladdr should point to header */
dladdr = header_addr;
}
@@ -1218,22 +1103,9 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
skip = dladdr - file_base;
- if (skip > cnt) {
- if (skip > fsize) {
- printf("skip(0x%08x) > fsize(0x%08x) file_base=0x%08x, header_offset=0x%x\n",
- skip, fsize, file_base, header_offset);
- ret = -4;
- goto cleanup;
- }
-
- fseek(xfile, skip, SEEK_SET);
- cnt -= skip;
- fsize -= skip;
- skip = 0;
- cnt = fread(buf, 1 , BUF_SIZE, xfile);
- }
+ image = buf + skip;
- p = &buf[skip];
+ p = image;
cnt -= skip;
fsize -= skip;
@@ -1241,13 +1113,7 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
fsize = max_length;
if (verify) {
- /*
- * we need to save header for verification
- * because some of the file is changed
- * before download
- */
- verify_buffer = malloc(cnt);
- verify_cnt = cnt;
+ verify_buffer = malloc(64);
if (!verify_buffer) {
printf("error, out of memory\n");
@@ -1255,9 +1121,9 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
goto cleanup;
}
- memcpy(verify_buffer, p, cnt);
+ memcpy(verify_buffer, p, 64);
- if ((type == FT_APP) && (p_id->mach_id->mode != MODE_HID)) {
+ if ((type == FT_APP) && (usb_id->mach_id->mode != MODE_HID)) {
type = FT_LOAD_ONLY;
verify = 2;
}
@@ -1266,19 +1132,16 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
printf("loading binary file(%s) to %08x, skip=0x%x, fsize=%u type=%d...\n",
curr->filename, dladdr, skip, fsize, type);
- ret = load_file(h, p_id, p, cnt, buf, BUF_SIZE,
- dladdr, fsize, type, xfile);
+ ret = load_file(image, fsize, dladdr, type);
if (ret < 0)
goto cleanup;
printf("binary file successfully loaded\n");
- transfer_size = ret;
-
if (verify) {
printf("verifying file...\n");
- ret = verify_memory(h, p_id, xfile, skip, dladdr, fsize, verify_buffer, verify_cnt);
+ ret = verify_memory(image, fsize, dladdr);
if (ret < 0) {
printf("verifying failed\n");
goto cleanup;
@@ -1287,18 +1150,19 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
printf("file successfully verified\n");
if (verify == 2) {
- if (verify_cnt > 64)
- verify_cnt = 64;
- ret = load_file(h, p_id, verify_buffer, verify_cnt,
- buf, BUF_SIZE, dladdr, verify_cnt,
- FT_APP, xfile);
+ /*
+ * In bulk mode we do not have an explicit jump command,
+ * so we load part of the image again with type FT_APP
+ * this time.
+ */
+ ret = load_file(verify_buffer, 64, dladdr, FT_APP);
if (ret < 0)
goto cleanup;
}
}
- if (p_id->mach_id->mode == MODE_HID && type == FT_APP) {
+ if (usb_id->mach_id->mode == MODE_HID && type == FT_APP) {
printf("jumping to 0x%08x\n", header_addr);
jump_command[2] = (unsigned char)(header_addr >> 24);
@@ -1310,7 +1174,7 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
retry = 0;
for (;;) {
- err = transfer(h, 1, jump_command, 16, &last_trans, p_id);
+ err = transfer(1, jump_command, 16, &last_trans);
if (!err)
break;
@@ -1323,14 +1187,14 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
}
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
if (err)
printf("j3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
}
- ret = (fsize == transfer_size) ? 0 : -16;
+ ret = 0;
cleanup:
fclose(xfile);
free(verify_buffer);
@@ -1339,10 +1203,28 @@ cleanup:
return ret;
}
+static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width)
+{
+ printf("wr 0x%08x 0x%08x\n", addr, val);
+
+ return write_memory(addr, val, width);
+}
+
+static int parse_initfile(const char *filename)
+{
+ struct config_data data = {
+ .write_mem = write_mem,
+ };
+
+ return parse_config(&data, filename);
+}
+
static void usage(const char *prgname)
{
fprintf(stderr, "usage: %s [OPTIONS] [FILENAME]\n\n"
"-c check correctness of flashed image\n"
+ "-i <cfgfile> Specify custom SoC initialization file\n"
+ "-s skip DCD included in image\n"
"-v verbose (give multiple times to increase)\n"
"-h this help\n", prgname);
exit(1);
@@ -1350,7 +1232,6 @@ static void usage(const char *prgname)
int main(int argc, char *argv[])
{
- struct usb_id *p_id = NULL;
struct mach_id *mach;
libusb_device **devs;
libusb_device *dev;
@@ -1358,13 +1239,13 @@ int main(int argc, char *argv[])
int err;
int ret = 1;
ssize_t cnt;
- libusb_device_handle *h = NULL;
int config = 0;
int verify = 0;
struct usb_work w = {};
int opt;
+ char *initfile = NULL;
- while ((opt = getopt(argc, argv, "cvh")) != -1) {
+ while ((opt = getopt(argc, argv, "cvhi:s")) != -1) {
switch (opt) {
case 'c':
verify = 1;
@@ -1374,6 +1255,12 @@ int main(int argc, char *argv[])
break;
case 'h':
usage(argv[0]);
+ case 'i':
+ initfile = optarg;
+ break;
+ case 's':
+ skip_image_dcd = 1;
+ break;
default:
exit(1);
}
@@ -1406,7 +1293,7 @@ int main(int argc, char *argv[])
goto out;
}
- err = libusb_open(dev, &h);
+ err = libusb_open(dev, &usb_dev_handle);
if (err) {
fprintf(stderr, "Could not open device vid=0x%x pid=0x%x err=%d\n",
mach->vid, mach->pid, err);
@@ -1415,44 +1302,50 @@ int main(int argc, char *argv[])
libusb_free_device_list(devs, 1);
- libusb_get_configuration(h, &config);
+ libusb_get_configuration(usb_dev_handle, &config);
- if (libusb_kernel_driver_active(h, 0))
- libusb_detach_kernel_driver(h, 0);
+ if (libusb_kernel_driver_active(usb_dev_handle, 0))
+ libusb_detach_kernel_driver(usb_dev_handle, 0);
- err = libusb_claim_interface(h, 0);
+ err = libusb_claim_interface(usb_dev_handle, 0);
if (err) {
printf("Claim failed\n");
goto out;
}
- p_id = malloc(sizeof(*p_id));
- if (!p_id) {
+ usb_id = malloc(sizeof(*usb_id));
+ if (!usb_id) {
perror("malloc");
exit(1);
}
- p_id->mach_id = mach;
+ usb_id->mach_id = mach;
- err = do_status(h, p_id);
+ err = do_status();
if (err) {
printf("status failed\n");
goto out;
}
- err = do_irom_download(h, p_id, &w, verify);
+ if (initfile) {
+ err = parse_initfile(initfile);
+ if (err)
+ goto out;
+ }
+
+ err = do_irom_download(&w, verify);
if (err) {
- err = do_status(h, p_id);
+ err = do_status();
goto out;
}
ret = 0;
out:
- if (p_id)
- free(p_id);
+ if (usb_id)
+ free(usb_id);
- if (h)
- libusb_close(h);
+ if (usb_dev_handle)
+ libusb_close(usb_dev_handle);
libusb_exit(NULL);