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.c470
1 files changed, 227 insertions, 243 deletions
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 8447ca2a8f..91a15345a2 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -31,21 +31,25 @@
#include <stdlib.h>
#include <libusb.h>
#include <getopt.h>
-#include <arpa/inet.h>
#include <linux/kernel.h>
+#include "../common.h"
#include "../compiler.h"
#include "imx.h"
-#define get_min(a, b) (((a) < (b)) ? (a) : (b))
+#include "../common.c"
-#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#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
+#ifndef UTS_RELEASE
+#define UTS_RELEASE "unknown"
+#endif
+
/*
* comment from libusb:
* As per the USB 3.0 specs, the current maximum limit for the depth is 7.
@@ -54,7 +58,7 @@
int verbose;
static struct libusb_device_handle *usb_dev_handle;
-static struct usb_id *usb_id;
+static const struct mach_id *mach_id;
struct mach_id {
struct mach_id * next;
@@ -72,7 +76,9 @@ struct mach_id {
unsigned short max_transfer;
#define DEV_IMX 0
#define DEV_MXS 1
+#define DEV_IMX9 2
unsigned char dev_type;
+ unsigned char hid_endpoint;
};
struct usb_work {
@@ -81,11 +87,6 @@ struct usb_work {
unsigned char plug;
};
-struct usb_id {
- const struct mach_id *mach_id;
- struct usb_work *work;
-};
-
static const struct mach_id imx_ids[] = {
{
.vid = 0x066f,
@@ -186,6 +187,22 @@ static const struct mach_id imx_ids[] = {
.max_transfer = 1024,
}, {
.vid = 0x1fc9,
+ .pid = 0x0146,
+ .name = "i.MX8MP",
+ .header_type = HDR_MX53,
+ .max_transfer = 1020,
+ .mode = MODE_HID,
+ .hid_endpoint = 1,
+ }, {
+ .vid = 0x1fc9,
+ .pid = 0x013e,
+ .name = "i.MX8MN",
+ .header_type = HDR_MX53,
+ .max_transfer = 1020,
+ .dev_type = MODE_HID,
+ .hid_endpoint = 1,
+ }, {
+ .vid = 0x1fc9,
.pid = 0x012b,
.name = "i.MX8MQ",
.header_type = HDR_MX53,
@@ -198,6 +215,14 @@ static const struct mach_id imx_ids[] = {
.header_type = HDR_MX53,
.mode = MODE_HID,
.max_transfer = 1024,
+ }, {
+ .vid = 0x1fc9,
+ .pid = 0x014e,
+ .name = "i.MX9",
+ .mode = MODE_HID,
+ .max_transfer = 1020,
+ .hid_endpoint = 1,
+ .dev_type = DEV_IMX9,
},
};
@@ -269,7 +294,8 @@ static void list_imx_device_types(void)
}
}
-static int device_location_equal(libusb_device *device, const char *location)
+static int device_location_equal(libusb_device *device, const char *location,
+ struct libusb_device_descriptor desc)
{
uint8_t port_path[MAX_USB_PORTS];
uint8_t dev_bus;
@@ -316,8 +342,9 @@ static int device_location_equal(libusb_device *device, const char *location)
/* walked the full path, all elements match */
if (path_step == path_len)
result = 1;
- else
- fprintf(stderr, " excluded by device path option\n");
+ else if (verbose)
+ fprintf(stderr, "USB device [%04x:%04x] excluded by device path option\n",
+ desc.idVendor, desc.idProduct);
done:
free(loc);
@@ -345,7 +372,7 @@ static libusb_device *find_imx_dev(libusb_device **devs, const struct mach_id **
return NULL;
}
- if (location && !device_location_equal(dev, location)) {
+ if (location && !device_location_equal(dev, location, desc)) {
libusb_close(usb_dev_handle);
usb_dev_handle = NULL;
continue;
@@ -409,61 +436,6 @@ static void dump_bytes(const void *src, unsigned cnt, unsigned addr)
}
}
-static long get_file_size(FILE *xfile)
-{
- long size;
- fseek(xfile, 0, SEEK_END);
- size = ftell(xfile);
- rewind(xfile);
-
- return size;
-}
-
-static int read_file(const char *name, unsigned char **buffer, unsigned *size)
-{
- FILE *xfile;
- unsigned fsize;
- int cnt;
- unsigned char *buf;
- xfile = fopen(name, "rb");
- if (!xfile) {
- printf("error, can not open input file: %s\n", name);
- return -5;
- }
-
- fsize = get_file_size(xfile);
- if (fsize < 0x20) {
- printf("error, file: %s is too small\n", name);
- fclose(xfile);
- return -2;
- }
-
- buf = malloc(ALIGN(fsize, 4));
- if (!buf) {
- printf("error, out of memory\n");
- fclose(xfile);
- return -2;
- }
-
- cnt = fread(buf, 1 , fsize, xfile);
- if (cnt < fsize) {
- printf("error, cannot read %s\n", name);
- fclose(xfile);
- free(buf);
- return -1;
- }
-
- if (size)
- *size = fsize;
-
- if (buffer)
- *buffer = buf;
- else
- free(buf);
-
- return 0;
-}
-
/*
* HID Class-Specific Requests values. See section 7.2 of the HID specifications
*/
@@ -504,11 +476,11 @@ static int read_file(const char *name, unsigned char **buffer, unsigned *size)
* EP2IN - bulk in
* (max packet size of 512 bytes)
*/
-static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
+static int transfer(int report, void *p, unsigned cnt, int *last_trans)
{
int err;
- if (cnt > usb_id->mach_id->max_transfer)
- cnt = usb_id->mach_id->max_transfer;
+ if (cnt > mach_id->max_transfer)
+ cnt = mach_id->max_transfer;
if (verbose > 4) {
printf("report=%i\n", report);
@@ -516,26 +488,37 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
dump_bytes(p, cnt, 0);
}
- if (usb_id->mach_id->mode == MODE_BULK) {
+ if (mach_id->mode == MODE_BULK) {
*last_trans = 0;
err = libusb_bulk_transfer(usb_dev_handle,
(report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
} else {
- unsigned char tmp[1028];
+ unsigned char tmp[1028] = { 0 };
tmp[0] = (unsigned char)report;
if (report < 3) {
memcpy(&tmp[1], p, cnt);
- err = libusb_control_transfer(usb_dev_handle,
- CTRL_OUT,
- HID_SET_REPORT,
- (HID_REPORT_TYPE_OUTPUT << 8) | report,
- 0,
- tmp, cnt + 1, 1000);
- *last_trans = (err > 0) ? err - 1 : 0;
- if (err > 0)
- err = 0;
+
+ if (report == 2)
+ cnt = mach_id->max_transfer;
+
+ if (mach_id->hid_endpoint) {
+ int trans;
+ err = libusb_interrupt_transfer(usb_dev_handle,
+ mach_id->hid_endpoint, tmp, cnt + 1, &trans, 1000);
+ *last_trans = trans - 1;
+ } else {
+ err = libusb_control_transfer(usb_dev_handle,
+ CTRL_OUT,
+ HID_SET_REPORT,
+ (HID_REPORT_TYPE_OUTPUT << 8) | report,
+ 0,
+ tmp, cnt + 1, 1000);
+ *last_trans = (err > 0) ? err - 1 : 0;
+ if (err > 0)
+ err = 0;
+ }
} else {
*last_trans = 0;
memset(&tmp[1], 0, cnt);
@@ -562,13 +545,13 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
return err;
}
-int do_status(void)
+static int do_status(void)
{
int last_trans;
unsigned char tmp[64];
int retry = 0;
int err;
- static const struct sdp_command status_command = {
+ static struct sdp_command status_command = {
.cmd = SDP_ERROR_STATUS,
.addr = 0,
.format = 0,
@@ -578,8 +561,7 @@ int do_status(void)
};
for (;;) {
- err = transfer(1, (unsigned char *) &status_command, 16,
- &last_trans);
+ err = transfer(1, &status_command, 16, &last_trans);
if (verbose > 2)
printf("report 1, wrote %i bytes, err=%i\n", last_trans, err);
@@ -602,7 +584,7 @@ int do_status(void)
break;
}
- if (usb_id->mach_id->mode == MODE_HID) {
+ if (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",
@@ -628,12 +610,11 @@ static int read_memory(unsigned addr, void *dest, unsigned cnt)
int err;
int rem;
unsigned char tmp[64];
- read_reg_command.addr = htonl(addr);
- read_reg_command.cnt = htonl(cnt);
+ read_reg_command.addr = htobe32(addr);
+ read_reg_command.cnt = htobe32(cnt);
for (;;) {
- err = transfer(1, (unsigned char *) &read_reg_command, 16,
- &last_trans);
+ 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);
@@ -660,17 +641,10 @@ static int read_memory(unsigned addr, void *dest, unsigned cnt)
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem);
break;
}
- if ((last_trans > rem) || (last_trans > 64)) {
- if ((last_trans == 64) && (rem < 64)) {
- /* Last transfer is expected to be too large for HID */
- } else {
- printf("err: %02x %02x %02x %02x cnt=%u rem=%d last_trans=%i\n",
- tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem, last_trans);
- }
+
+ if (last_trans > rem)
last_trans = rem;
- if (last_trans > 64)
- last_trans = 64;
- }
+
memcpy(dest, tmp, last_trans);
dest += last_trans;
rem -= last_trans;
@@ -693,8 +667,8 @@ static int write_memory(unsigned addr, unsigned val, int width)
.rsvd = 0,
};
- write_reg_command.addr = htonl(addr);
- write_reg_command.cnt = htonl(4);
+ write_reg_command.addr = htobe32(addr);
+ write_reg_command.cnt = htobe32(4);
if (verbose > 1)
printf("write memory reg: 0x%08x val: 0x%08x width: %d\n", addr, val, width);
@@ -713,11 +687,10 @@ static int write_memory(unsigned addr, unsigned val, int width)
return -1;
}
- write_reg_command.data = htonl(val);
+ write_reg_command.data = htobe32(val);
for (;;) {
- err = transfer(1, (unsigned char *) &write_reg_command, 16,
- &last_trans);
+ 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);
@@ -770,6 +743,31 @@ static int modify_memory(unsigned addr, unsigned val, int width, int set_bits, i
return write_memory(addr, val, 4);
}
+static int send_buf(void *buf, unsigned len)
+{
+ void *p = buf;
+ int cnt = len;
+ int err;
+
+ while (1) {
+ int now = get_min(cnt, mach_id->max_transfer);
+
+ if (now <= 0)
+ break;
+
+ err = transfer(2, p, now, &now);
+ if (err) {
+ printf("dl_command err=%i, last_trans=%i\n", err, now);
+ return err;
+ }
+
+ p += now;
+ cnt -= now;
+ }
+
+ return 0;
+}
+
static int load_file(void *buf, unsigned len, unsigned dladdr,
unsigned char type, bool mode_barebox)
{
@@ -786,18 +784,15 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
int retry = 0;
unsigned transfer_size = 0;
unsigned char tmp[64];
- void *p;
- int cnt;
len = ALIGN(len, 4);
- dl_command.addr = htonl(dladdr);
- dl_command.cnt = htonl(len);
+ dl_command.addr = htobe32(dladdr);
+ dl_command.cnt = htobe32(len);
dl_command.rsvd = type;
for (;;) {
- err = transfer(1, (unsigned char *) &dl_command, 16,
- &last_trans);
+ err = transfer(1, &dl_command, 16, &last_trans);
if (!err)
break;
@@ -810,36 +805,21 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
retry = 0;
- if (usb_id->mach_id->mode == MODE_BULK) {
+ if (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;
- }
+ err = send_buf(buf, len);
+ if (err)
+ return err;
if (mode_barebox)
return transfer_size;
- if (usb_id->mach_id->mode == MODE_HID) {
+ if (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",
@@ -869,11 +849,10 @@ static int sdp_jump_address(unsigned addr)
int last_trans, err;
int retry = 0;
- jump_command.addr = htonl(addr);
+ jump_command.addr = htobe32(addr);
for (;;) {
- err = transfer(1, (unsigned char *) &jump_command, 16,
- &last_trans);
+ err = transfer(1, &jump_command, 16, &last_trans);
if (!err)
break;
@@ -899,10 +878,10 @@ 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) /
+ int num_rec = (be16toh(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);
+ be16toh(recs->length), recs->param);
if (recs->param & PARAMETER_FLAG_MASK) {
if (recs->param & PARAMETER_FLAG_SET)
@@ -923,8 +902,8 @@ static int do_dcd_v2_cmd_write(const unsigned char *dcd)
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,
+ int ret = modify_memory(be32toh(record->addr),
+ be32toh(record->val), bytes,
set_bits, clear_bits);
if (ret < 0)
return ret;
@@ -939,13 +918,13 @@ static int do_dcd_v2_cmd_check(const unsigned char *dcd)
int bytes;
enum imx_dcd_v2_check_cond cond;
struct imx_dcd_v2_check *check = (struct imx_dcd_v2_check *) dcd;
- switch (ntohs(check->length)) {
+ switch (be16toh(check->length)) {
case 12:
/* poll indefinitely */
poll_count = 0xffffffff;
break;
case 16:
- poll_count = ntohl(check->count);
+ poll_count = be32toh(check->count);
if (poll_count == 0)
/* this command behaves as for NOP */
return 0;
@@ -978,10 +957,10 @@ static int do_dcd_v2_cmd_check(const unsigned char *dcd)
return -1;
}
- mask = ntohl(check->mask);
+ mask = be32toh(check->mask);
fprintf(stderr, "DCD check condition %i on address 0x%x\n",
- cond, ntohl(check->addr));
+ cond, be32toh(check->addr));
/* Reduce the poll count to some arbitrary practical limit.
Polling via SRP commands will be much slower compared to
polling when DCD is interpreted by the SOC microcode.
@@ -991,7 +970,7 @@ static int do_dcd_v2_cmd_check(const unsigned char *dcd)
while (poll_count > 0) {
uint32_t data = 0;
- int ret = read_memory(ntohl(check->addr), &data, bytes);
+ int ret = read_memory(be32toh(check->addr), &data, bytes);
if (ret < 0)
return ret;
@@ -1020,7 +999,7 @@ static int do_dcd_v2_cmd_check(const unsigned char *dcd)
fprintf(stderr, "Error: timeout waiting for DCD check condition %i "
"on address 0x%08x to match 0x%08x\n", cond,
- ntohl(check->addr), ntohl(check->mask));
+ be32toh(check->addr), be32toh(check->mask));
return -1;
}
@@ -1052,7 +1031,7 @@ static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr,
fprintf(stderr, "Error: Unknown DCD header tag\n");
return -1;
}
- m_length = ntohs(dcd_hdr->length);
+ m_length = be16toh(dcd_hdr->length);
dcd_end = dcd + m_length;
if (dcd_end > file_end) {
fprintf(stderr, "Error: DCD length %08x exceeds EOF\n",
@@ -1065,7 +1044,7 @@ static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr,
while (dcd < dcd_end) {
int ret = 0;
struct imx_ivt_header *cmd_hdr = (struct imx_ivt_header *) dcd;
- unsigned s_length = ntohs(cmd_hdr->length);
+ unsigned s_length = be16toh(cmd_hdr->length);
if (dcd + s_length > file_end) {
fprintf(stderr, "Error: DCD length %08x exceeds EOF\n",
s_length);
@@ -1233,7 +1212,7 @@ static int is_header(const unsigned char *p)
const struct imx_flash_header_v2 *hdr =
(const struct imx_flash_header_v2 *)p;
- switch (usb_id->mach_id->header_type) {
+ switch (mach_id->header_type) {
case HDR_MX51:
if (ohdr->app_code_barker == 0xb1)
return 1;
@@ -1253,7 +1232,7 @@ 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;
- switch (usb_id->mach_id->header_type) {
+ switch (mach_id->header_type) {
case HDR_MX51:
ret = write_dcd_table_old(ohdr, file_start, cnt);
ohdr->dcd_block_len = 0;
@@ -1270,11 +1249,11 @@ static int perform_dcd(unsigned char *p, const unsigned char *file_start,
}
static int get_dl_start(const unsigned char *p, const unsigned char *file_start,
- unsigned cnt, unsigned *max_length, unsigned *plugin,
+ unsigned cnt, size_t *firststage_len, unsigned *plugin,
unsigned *header_addr)
{
const unsigned char *file_end = file_start + cnt;
- switch (usb_id->mach_id->header_type) {
+ switch (mach_id->header_type) {
case HDR_MX51:
{
struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
@@ -1285,25 +1264,28 @@ static int get_dl_start(const unsigned char *p, const unsigned char *file_start,
*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);
+ *firststage_len = dcd_end[0] | (dcd_end[1] << 8) | (dcd_end[2] << 16) | (dcd_end[3] << 24);
break;
}
case HDR_MX53:
{
- unsigned char *bd;
+ unsigned char *_bd;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
+ struct imx_boot_data *bd;
*header_addr = hdr->self;
- bd = hdr->boot_data_ptr + cvt_dest_to_src;
- if ((bd < file_start) || ((bd + 4) > file_end)) {
+ _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;
}
- *max_length = ((struct imx_boot_data *)bd)->size;
- *plugin = ((struct imx_boot_data *)bd)->plugin;
- ((struct imx_boot_data *)bd)->plugin = 0;
+ bd = (void *)_bd;
+
+ *firststage_len = bd->size - (hdr->self - bd->start);
+ *plugin = bd->plugin;
+ bd->plugin = 0;
break;
}
@@ -1315,7 +1297,7 @@ static int get_payload_start(const unsigned char *p, uint32_t *ofs)
{
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- switch (usb_id->mach_id->header_type) {
+ switch (mach_id->header_type) {
case HDR_MX51:
return -EINVAL;
@@ -1328,7 +1310,7 @@ static int get_payload_start(const unsigned char *p, uint32_t *ofs)
}
static int process_header(struct usb_work *curr, unsigned char *buf, int cnt,
- unsigned *p_max_length, unsigned *p_plugin,
+ size_t *p_firststage_len, unsigned *p_plugin,
unsigned *p_header_addr)
{
int ret;
@@ -1343,7 +1325,7 @@ static int process_header(struct usb_work *curr, unsigned char *buf, int cnt,
if (!is_header(p))
continue;
- ret = get_dl_start(p, buf, cnt, p_max_length, p_plugin, p_header_addr);
+ ret = get_dl_start(p, buf, cnt, p_firststage_len, p_plugin, p_header_addr);
if (ret < 0) {
printf("!!get_dl_start returned %i\n", ret);
return ret;
@@ -1360,7 +1342,7 @@ static int process_header(struct usb_work *curr, unsigned char *buf, int cnt,
if (*p_plugin && (!curr->plug) && (!header_cnt)) {
header_cnt++;
- header_max = header_offset + *p_max_length + 0x400;
+ header_max = header_offset + *p_firststage_len + 0x400;
if (header_max > cnt - 32)
header_max = cnt - 32;
printf("header_max=%x\n", header_max);
@@ -1377,46 +1359,61 @@ static int process_header(struct usb_work *curr, unsigned char *buf, int cnt,
return -ENODEV;
}
+static int imx9_load_file(struct usb_work *curr)
+{
+ void *buf;
+ size_t fsize = 0;
+ int ret;
+
+ buf = read_file(curr->filename, &fsize);
+ if (!buf)
+ return -errno;
+
+ ret = send_buf(buf, fsize);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
static int do_irom_download(struct usb_work *curr, int verify)
{
int ret;
unsigned char type;
- unsigned fsize = 0;
+ size_t fsize = 0;
unsigned header_offset;
unsigned char *buf = NULL;
unsigned char *image;
unsigned char *verify_buffer = NULL;
- unsigned max_length;
+ size_t firststage_len;
unsigned plugin = 0;
unsigned header_addr = 0;
- unsigned total_size = 0;
- ret = read_file(curr->filename, &buf, &fsize);
- if (ret < 0)
- return ret;
+ buf = read_file(curr->filename, &fsize);
+ if (!buf)
+ return -errno;
- max_length = fsize;
+ firststage_len = fsize;
- ret = process_header(curr, buf, fsize, &max_length, &plugin, &header_addr);
+ ret = process_header(curr, buf, fsize, &firststage_len, &plugin, &header_addr);
if (ret < 0)
goto cleanup;
header_offset = ret;
+ if (mach_id->hid_endpoint)
+ return send_buf(buf + header_offset, fsize - header_offset);
+
if (plugin && (!curr->plug)) {
printf("Only plugin header found\n");
ret = -1;
goto cleanup;
}
+ /* skip over the imx-image-part */
image = buf + header_offset;
fsize -= header_offset;
- if (fsize > max_length) {
- total_size = fsize;
- fsize = max_length;
- }
-
type = FT_APP;
if (verify) {
@@ -1430,16 +1427,16 @@ static int do_irom_download(struct usb_work *curr, int verify)
memcpy(verify_buffer, image, 64);
- if ((type == FT_APP) && (usb_id->mach_id->mode != MODE_HID)) {
+ if ((type == FT_APP) && (mach_id->mode != MODE_HID)) {
type = FT_LOAD_ONLY;
verify = 2;
}
}
- printf("loading binary file(%s) to 0x%08x, fsize=%u type=%d...\n",
- curr->filename, header_addr, fsize, type);
+ printf("loading binary file(%s) to 0x%08x, firststage_len=%zu type=%d, hdroffset=%u...\n",
+ curr->filename, header_addr, firststage_len, type, header_offset);
- ret = load_file(image, fsize, header_addr, type, false);
+ ret = load_file(image, min(fsize, firststage_len), header_addr, type, false);
if (ret < 0)
goto cleanup;
@@ -1448,7 +1445,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
if (verify) {
printf("verifying file...\n");
- ret = verify_memory(image, fsize, header_addr);
+ ret = verify_memory(image, min(fsize, firststage_len), header_addr);
if (ret < 0) {
printf("verifying failed\n");
goto cleanup;
@@ -1469,7 +1466,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
}
}
- if (usb_id->mach_id->mode == MODE_HID && type == FT_APP) {
+ if (mach_id->mode == MODE_HID && type == FT_APP) {
printf("jumping to 0x%08x\n", header_addr);
ret = sdp_jump_address(header_addr);
@@ -1477,7 +1474,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
return ret;
}
- if (total_size) {
+ if (firststage_len < fsize) {
uint32_t ofs;
ret = get_payload_start(image, &ofs);
@@ -1485,9 +1482,9 @@ static int do_irom_download(struct usb_work *curr, int verify)
printf("Cannot get offset of payload\n");
goto cleanup;
}
- printf("Loading full image\n");
+ printf("Loading full image from offset %u\n", ofs);
printf("Note: This needs board support on the other end\n");
- load_file(image + ofs, total_size - ofs, 0, 0, true);
+ load_file(image + ofs, fsize - ofs, 0, 0, true);
}
ret = 0;
@@ -1504,65 +1501,43 @@ static int write_mem(const struct config_data *data, uint32_t addr,
return modify_memory(addr, val, width, set_bits, clear_bits);
}
-/* MXS section */
-static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size)
+static int mxs_load_buf(uint8_t *data, int size)
{
static struct mxs_command dl_command;
int last_trans, err;
- void *p;
- int cnt;
- dl_command.sign = htonl(0x424c5443); /* Signature: BLTC */
- dl_command.tag = htonl(0x1);
- dl_command.size = htonl(size);
+ dl_command.sign = htobe32(0x424c5443); /* Signature: BLTC */
+ dl_command.tag = htobe32(0x1);
+ dl_command.size = htobe32(size);
dl_command.flags = 0;
dl_command.rsvd[0] = 0;
dl_command.rsvd[1] = 0;
dl_command.cmd = MXS_CMD_FW_DOWNLOAD;
- dl_command.dw_size = htonl(size);
+ dl_command.dw_size = htobe32(size);
- err = transfer(1, (unsigned char *) &dl_command, 20, &last_trans);
+ err = transfer(1, &dl_command, 20, &last_trans);
if (err) {
printf("transfer error at init step: err=%i, last_trans=%i\n",
err, last_trans);
return err;
}
- p = data;
- cnt = size;
-
- 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, now);
- return err;
- }
-
- p += now;
- cnt -= now;
- }
+ err = send_buf(data, size);
return err;
}
-static int mxs_work(struct usb_work *curr)
+static int mxs_load_file(struct usb_work *curr)
{
- unsigned fsize = 0;
+ size_t fsize = 0;
unsigned char *buf = NULL;
- int ret;
- ret = read_file(curr->filename, &buf, &fsize);
- if (ret < 0)
- return ret;
+ buf = read_file(curr->filename, &fsize);
+ if (!buf)
+ return -errno;
- return mxs_load_file(usb_dev_handle, buf, fsize);
+ return mxs_load_buf(buf, fsize);
}
-/* end of mxs section */
static int parse_initfile(const char *filename)
{
@@ -1585,13 +1560,17 @@ static void usage(const char *prgname)
"-p <devpath> Specify device path: <bus>-<port>[.<port>]...\n"
"-s skip DCD included in image\n"
"-v verbose (give multiple times to increase)\n"
+ "--version display version number\n"
"-h this help\n", prgname);
- exit(1);
+}
+
+static void version(const char *prgname)
+{
+ fprintf(stderr, "%s %s\n", prgname, UTS_RELEASE);
}
int main(int argc, char *argv[])
{
- const struct mach_id *mach;
libusb_device **devs;
libusb_device *dev;
int r;
@@ -1605,10 +1584,20 @@ int main(int argc, char *argv[])
char *initfile = NULL;
char *devpath = NULL;
char *devtype = NULL;
+ int opt_version = 0;
+ struct option long_options[] = {
+ {"version", no_argument, &opt_version, 1},
+ { }
+ };
w.do_dcd_once = 1;
- while ((opt = getopt(argc, argv, "cvhd:i:p:s")) != -1) {
+ while ((opt = getopt_long(argc, argv, "cvhd:i:p:s", long_options, NULL)) != -1) {
+ if (opt_version) {
+ version(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+
switch (opt) {
case 'c':
verify = 1;
@@ -1618,6 +1607,7 @@ int main(int argc, char *argv[])
break;
case 'h':
usage(argv[0]);
+ exit(EXIT_SUCCESS);
case 'd':
devtype = optarg;
break;
@@ -1631,13 +1621,13 @@ int main(int argc, char *argv[])
w.do_dcd_once = 0;
break;
default:
- exit(1);
+ exit(EXIT_FAILURE);
}
}
if (devtype && strcmp(devtype, "list") == 0) {
list_imx_device_types();
- exit(0);
+ exit(EXIT_SUCCESS);
}
if (devtype && !devpath) {
@@ -1647,7 +1637,7 @@ int main(int argc, char *argv[])
if (optind == argc) {
fprintf(stderr, "no filename given\n");
usage(argv[0]);
- exit(1);
+ exit(EXIT_FAILURE);
}
w.plug = 1;
@@ -1663,7 +1653,7 @@ int main(int argc, char *argv[])
goto out;
}
- dev = find_imx_dev(devs, &mach, devpath, devtype);
+ dev = find_imx_dev(devs, &mach_id, devpath, devtype);
if (!dev) {
fprintf(stderr, "no supported device found\n");
goto out;
@@ -1682,23 +1672,20 @@ int main(int argc, char *argv[])
goto out;
}
- usb_id = malloc(sizeof(*usb_id));
- if (!usb_id) {
- perror("malloc");
- exit(1);
- }
-
- usb_id->mach_id = mach;
-
- if (mach->dev_type == DEV_MXS) {
- ret = mxs_work(&w);
+ if (mach_id->dev_type == DEV_MXS) {
+ ret = mxs_load_file(&w);
+ goto out;
+ } else if (mach_id->dev_type == DEV_IMX9) {
+ ret = imx9_load_file(&w);
goto out;
}
- err = do_status();
- if (err) {
- printf("status failed\n");
- goto out;
+ if (!mach_id->hid_endpoint) {
+ err = do_status();
+ if (err) {
+ printf("status failed\n");
+ goto out;
+ }
}
if (initfile) {
@@ -1715,9 +1702,6 @@ int main(int argc, char *argv[])
ret = 0;
out:
- if (usb_id)
- free(usb_id);
-
if (usb_dev_handle)
libusb_close(usb_dev_handle);