From a6e1dbebd1973944eea15b4122346170eece5767 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Sun, 21 Aug 2016 21:54:06 +0200 Subject: scripts: imx-usb-loader: do DCD only once, cleanup Only the first encountered DCD block should be processed, optional DCD processing may be switched off by command option. Clean up the corresponding logic. Signed-off-by: Alexander Kurz Signed-off-by: Sascha Hauer --- scripts/imx/imx-usb-loader.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index 17324972bf..f8306f829a 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -45,7 +45,6 @@ #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; @@ -67,7 +66,7 @@ struct mach_id { struct usb_work { char filename[256]; - unsigned char dcd; + unsigned char do_dcd_once; unsigned char plug; }; @@ -980,9 +979,6 @@ static int perform_dcd(unsigned char *p, const unsigned char *file_start, struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p; int ret = 0; - if (skip_image_dcd) - return 0; - switch (usb_id->mach_id->header_type) { case HDR_MX51: ret = write_dcd_table_old(ohdr, file_start, cnt); @@ -1066,13 +1062,13 @@ static int process_header(struct usb_work *curr, unsigned char *buf, int cnt, return ret; } - if (curr->dcd) { + if (curr->do_dcd_once) { ret = perform_dcd(p, buf, cnt); if (ret < 0) { printf("!!perform_dcd returned %i\n", ret); return ret; } - curr->dcd = 0; + curr->do_dcd_once = 0; } if (*p_plugin && (!curr->plug) && (!header_cnt)) { @@ -1264,6 +1260,8 @@ int main(int argc, char *argv[]) int opt; char *initfile = NULL; + w.do_dcd_once = 1; + while ((opt = getopt(argc, argv, "cvhi:s")) != -1) { switch (opt) { case 'c': @@ -1278,7 +1276,7 @@ int main(int argc, char *argv[]) initfile = optarg; break; case 's': - skip_image_dcd = 1; + w.do_dcd_once = 0; break; default: exit(1); @@ -1292,7 +1290,6 @@ int main(int argc, char *argv[]) } w.plug = 1; - w.dcd = 1; strncpy(w.filename, argv[optind], sizeof(w.filename) - 1); r = libusb_init(NULL); -- cgit v1.2.3 From 2af7f2b26b67d8030df7a4a7d957b02bb1a09507 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Sun, 21 Aug 2016 22:16:13 +0200 Subject: scripts: imx-image: DCD check command for v2 only DCD check command is currently implemented for imximg v2 only. This command may also be available for v1 as mentioned in IMX35RM as DCD-address-type "wait/read", but due to the lack of further details it will be not supported. Signed-off-by: Alexander Kurz Signed-off-by: Sascha Hauer --- scripts/imx/imx-image.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts') diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c index c0bf9c004f..d0c4152b81 100644 --- a/scripts/imx/imx-image.c +++ b/scripts/imx/imx-image.c @@ -450,6 +450,11 @@ static int write_dcd(const char *outfile) static int check(const struct config_data *data, uint32_t cmd, uint32_t addr, uint32_t mask) { + if (data->header_version != 2) { + fprintf(stderr, "DCD check command is not available or " + "not yet implemented for this SOC\n"); + return -EINVAL; + } if (curdcd > MAX_DCD - 3) { fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD); return -ENOMEM; -- cgit v1.2.3 From fdb7f089e5e4d67366327372e4a3df8c2558d635 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Sun, 21 Aug 2016 22:18:36 +0200 Subject: scripts: imx-usb-loader: enable DCD 16-bit write for hdr v1 Do some cleanup which enables DCDv1 16 bit write access as side effect. Signed-off-by: Alexander Kurz Signed-off-by: Sascha Hauer --- scripts/imx/imx-usb-loader.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index f8306f829a..0b0864aa8e 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -888,16 +888,11 @@ static int write_dcd_table_old(const struct imx_flash_header *hdr, switch (type) { case 1: - if (verbose > 1) - printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val); - err = write_memory(addr, val, 1); - if (err < 0) - return err; - break; + case 2: case 4: if (verbose > 1) printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val); - err = write_memory(addr, val, 4); + err = write_memory(addr, val, type); if (err < 0) return err; break; -- cgit v1.2.3 From 4bbfe971bbd654a974c14a01b551c53270ab3253 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Sun, 21 Aug 2016 22:18:37 +0200 Subject: scripts: imx-usb-loader: structured DCD v1 element access DCD v1 elements are encoded little endian. Signed-off-by: Alexander Kurz Signed-off-by: Sascha Hauer --- scripts/imx/imx-usb-loader.c | 19 +++++++++++-------- scripts/imx/imx.h | 6 ++++++ 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index 0b0864aa8e..413def675d 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -871,7 +872,6 @@ static int get_dcd_range_old(const struct imx_flash_header *hdr, static int write_dcd_table_old(const struct imx_flash_header *hdr, const unsigned char *file_start, unsigned cnt) { - unsigned val; unsigned char *dcd_end; unsigned char* dcd; int err = get_dcd_range_old(hdr, file_start, cnt, &dcd, &dcd_end); @@ -881,23 +881,26 @@ static int write_dcd_table_old(const struct imx_flash_header *hdr, printf("writing DCD table...\n"); while (dcd < dcd_end) { - unsigned type = (dcd[0] << 0) | (dcd[1] << 8) | (dcd[2] << 16) | (dcd[3] << 24); - unsigned addr = (dcd[4] << 0) | (dcd[5] << 8) | (dcd[6] << 16) | (dcd[7] << 24); - val = (dcd[8] << 0) | (dcd[9] << 8) | (dcd[10] << 16) | (dcd[11] << 24); - dcd += 12; + struct imx_dcd_rec_v1 *rec = (struct imx_dcd_rec_v1 *) dcd; + unsigned type = le32toh(rec->type); + dcd += sizeof *rec; switch (type) { case 1: case 2: case 4: if (verbose > 1) - printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val); - err = write_memory(addr, val, type); + printf("type=%08x *0x%08x = 0x%08x\n", type, + le32toh(rec->addr), + le32toh(rec->val)); + err = write_memory(le32toh(rec->addr), + le32toh(rec->val), type); if (err < 0) return err; break; default: - printf("!!!unknown type=%08x *0x%08x = 0x%08x\n", type, addr, val); + printf("WARNING: unknown DCD type=%08x ignored\n", + type); } } diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h index 8db7e7b46c..64ebdcec40 100644 --- a/scripts/imx/imx.h +++ b/scripts/imx/imx.h @@ -26,6 +26,12 @@ struct imx_boot_data { uint32_t plugin; } __attribute__((packed)); +struct imx_dcd_rec_v1 { + uint32_t type; + uint32_t addr; + uint32_t val; +} __attribute__((packed)); + #define TAG_IVT_HEADER 0xd1 #define IVT_VERSION 0x40 #define TAG_DCD_HEADER 0xd2 -- cgit v1.2.3 From c973b3adbf5a9575e4d186877c3a47ea602acf35 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Fri, 2 Sep 2016 22:47:56 +0200 Subject: scripts: imx-usb-loader: cleanup DCD v2 processing Re-Implement the DCD v2 processing. Processing for the DCD write command went into a separate function enabling the over-all DCD processing to handle check, nop and unlock commands as well. The trivial NOP command is supported right away. Further changes: put in some data consistancy checks and error handling, do structured member access and proper endianess handling and direct error messages to stderr. Signed-off-by: Alexander Kurz Signed-off-by: Sascha Hauer --- scripts/imx/imx-usb-loader.c | 125 +++++++++++++++++++++++++++---------------- scripts/imx/imx.h | 17 +++++- 2 files changed, 95 insertions(+), 47 deletions(-) (limited to 'scripts') diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index 413def675d..b5c1531ab2 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -743,7 +743,45 @@ static int sdp_jump_address(unsigned addr) return 0; } -static int write_dcd_table_ivt(const struct imx_flash_header_v2 *hdr, +static int do_dcd_v2_cmd_write(const unsigned char *dcd) +{ + int set_bits = 0, clear_bits = 0; + int idx, bytes; + struct imx_dcd_v2_write *recs = (struct imx_dcd_v2_write *) dcd; + int num_rec = (ntohs(recs->length) - 4) / + sizeof(struct imx_dcd_v2_write_rec); + printf("DCD write: sub dcd length: 0x%04x, flags: 0x%02x\n", + ntohs(recs->length), recs->param); + + if (recs->param & PARAMETER_FLAG_MASK) { + if (recs->param & PARAMETER_FLAG_SET) + set_bits = 1; + else + clear_bits = 1; + } + bytes = recs->param & 7; + switch (bytes) { + case 1: + case 2: + case 4: + break; + default: + fprintf(stderr, "ERROR: bad DCD write width %i\n", bytes); + return -1; + } + + for (idx = 0; idx < num_rec; idx++) { + const struct imx_dcd_v2_write_rec *record = &recs->data[idx]; + int ret = modify_memory(ntohl(record->addr), + ntohl(record->val), bytes, + set_bits, clear_bits); + if (ret < 0) + return ret; + } + return 0; +} + +static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr, const unsigned char *file_start, unsigned cnt) { unsigned char *dcd_end; @@ -751,7 +789,7 @@ static int write_dcd_table_ivt(const struct imx_flash_header_v2 *hdr, #define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self) unsigned char* dcd; const unsigned char *file_end = file_start + cnt; - int err = 0; + struct imx_ivt_header *dcd_hdr; if (!hdr->dcd_ptr) { printf("No dcd table in this ivt\n"); @@ -761,65 +799,60 @@ static int write_dcd_table_ivt(const struct imx_flash_header_v2 *hdr, dcd = hdr->dcd_ptr + cvt_dest_to_src; if ((dcd < file_start) || ((dcd + 4) > file_end)) { - printf("bad dcd_ptr %08x\n", hdr->dcd_ptr); + fprintf(stderr, "bad dcd_ptr %08x\n", hdr->dcd_ptr); return -1; } - m_length = (dcd[1] << 8) + dcd[2]; - - printf("main dcd length %x\n", m_length); - - if ((dcd[0] != 0xd2) || (dcd[3] != 0x40)) { - printf("Unknown tag\n"); + dcd_hdr = (struct imx_ivt_header *) dcd; + if ((dcd_hdr->tag != TAG_DCD_HEADER) || + (dcd_hdr->version != DCD_VERSION)) { + fprintf(stderr, "Error: Unknown DCD header tag\n"); return -1; } - + m_length = ntohs(dcd_hdr->length); dcd_end = dcd + m_length; - if (dcd_end > file_end) { - printf("bad dcd length %08x\n", m_length); + fprintf(stderr, "Error: DCD length %08x exceeds EOF\n", + m_length); return -1; } + printf("main dcd length %x\n", m_length); dcd += 4; while (dcd < dcd_end) { - unsigned s_length = (dcd[1] << 8) + dcd[2]; - unsigned char *s_end = dcd + s_length; - int set_bits = 0, clear_bits = 0; - - printf("command: 0x%02x sub dcd length: 0x%04x, flags: 0x%02x\n", dcd[0], s_length, dcd[3]); - - if ((dcd[0] != 0xcc)) { - printf("Skipping unknown sub tag 0x%02x with len %04x\n", dcd[0], s_length); - usleep(50000); - dcd += s_length; - continue; - } - - if (dcd[3] & PARAMETER_FLAG_MASK) { - if (dcd[3] & PARAMETER_FLAG_SET) - set_bits = 1; - else - clear_bits = 1; - } - - dcd += 4; - - if (s_end > dcd_end) { - printf("error s_end(%p) > dcd_end(%p)\n", s_end, dcd_end); + int ret = 0; + struct imx_ivt_header *cmd_hdr = (struct imx_ivt_header *) dcd; + unsigned s_length = ntohs(cmd_hdr->length); + if (dcd + s_length > file_end) { + fprintf(stderr, "Error: DCD length %08x exceeds EOF\n", + s_length); return -1; } - - while (dcd < s_end) { - unsigned addr = (dcd[0] << 24) | (dcd[1] << 16) | (dcd[2] << 8) | dcd[3]; - unsigned val = (dcd[4] << 24) | (dcd[5] << 16) | (dcd[6] << 8) | dcd[7]; - - dcd += 8; - - modify_memory(addr, val, 4, set_bits, clear_bits); + switch (cmd_hdr->tag) { + case TAG_WRITE: + ret = do_dcd_v2_cmd_write(dcd); + break; + case TAG_CHECK: + fprintf(stderr, "DCD check not implemented yet\n"); + usleep(50000); + break; + case TAG_UNLOCK: + fprintf(stderr, "DCD unlock not implemented yet\n"); + usleep(50000); + break; + case TAG_NOP: + break; + default: + fprintf(stderr, "Skipping unknown DCD sub tag 0x%02x " + "with len %04x\n", cmd_hdr->tag, s_length); + usleep(50000); + break; } + dcd += s_length; + if (ret < 0) + return ret; } - return err; + return 0; } static int get_dcd_range_old(const struct imx_flash_header *hdr, @@ -984,7 +1017,7 @@ static int perform_dcd(unsigned char *p, const unsigned char *file_start, break; case HDR_MX53: - ret = write_dcd_table_ivt(hdr, file_start, cnt); + ret = process_dcd_table_ivt(hdr, file_start, cnt); hdr->dcd_ptr = 0; break; diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h index 64ebdcec40..ae3702c116 100644 --- a/scripts/imx/imx.h +++ b/scripts/imx/imx.h @@ -36,10 +36,12 @@ struct imx_dcd_rec_v1 { #define IVT_VERSION 0x40 #define TAG_DCD_HEADER 0xd2 #define DCD_VERSION 0x40 +#define TAG_UNLOCK 0xb2 +#define TAG_NOP 0xc0 #define TAG_WRITE 0xcc +#define TAG_CHECK 0xcf #define PARAMETER_FLAG_MASK (1 << 3) #define PARAMETER_FLAG_SET (1 << 4) -#define TAG_CHECK 0xcf struct imx_ivt_header { uint8_t tag; @@ -79,4 +81,17 @@ struct config_data { char *csf; }; +#define MAX_RECORDS_DCD_V2 1024 +struct imx_dcd_v2_write_rec { + uint32_t addr; + uint32_t val; +} __attribute__((packed)); + +struct imx_dcd_v2_write { + uint8_t tag; + uint16_t length; + uint8_t param; + struct imx_dcd_v2_write_rec data[MAX_RECORDS_DCD_V2]; +} __attribute__((packed)); + int parse_config(struct config_data *data, const char *filename); -- cgit v1.2.3 From 2f9ff8a8f7c54bfed6aa95cf7945f42b1b710767 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Fri, 9 Sep 2016 17:43:40 +0200 Subject: scripts: imx: add support for i.MX50 Add imximg support for i.MX50 processors which use the i.MX flash header v2 format. Signed-off-by: Alexander Kurz Signed-off-by: Sascha Hauer --- scripts/imx/imx-image.c | 2 +- scripts/imx/imx-usb-loader.c | 3 +++ scripts/imx/imx.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c index d0c4152b81..f87efe98f7 100644 --- a/scripts/imx/imx-image.c +++ b/scripts/imx/imx-image.c @@ -274,7 +274,7 @@ static int write_mem_v1(uint32_t addr, uint32_t val, int width, int set_bits, in /* * ============================================================================ - * i.MX flash header v2 handling. Found on i.MX53 and i.MX6 + * i.MX flash header v2 handling. Found on i.MX50, i.MX53 and i.MX6 * ============================================================================ */ diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index b5c1531ab2..c0aaa7d629 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -90,6 +90,9 @@ struct mach_id imx_ids[] = { .vid = 0x15a2, .pid = 0x0052, .name = "i.MX50", + .header_type = HDR_MX53, + .mode = MODE_HID, + .max_transfer = 1024, }, { .vid = 0x15a2, .pid = 0x0054, diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c index 4ec8c89541..c8ee3091e0 100644 --- a/scripts/imx/imx.c +++ b/scripts/imx/imx.c @@ -219,6 +219,7 @@ struct soc_type { static struct soc_type socs[] = { { .name = "imx25", .header_version = 1, .cpu_type = IMX_CPU_IMX25 }, { .name = "imx35", .header_version = 1, .cpu_type = IMX_CPU_IMX35 }, + { .name = "imx50", .header_version = 2, .cpu_type = IMX_CPU_IMX50 }, { .name = "imx51", .header_version = 1, .cpu_type = IMX_CPU_IMX51 }, { .name = "imx53", .header_version = 2, .cpu_type = IMX_CPU_IMX53 }, { .name = "imx6", .header_version = 2, .cpu_type = IMX_CPU_IMX6 }, -- cgit v1.2.3