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.c130
1 files changed, 92 insertions, 38 deletions
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 1242f2dedd..91a15345a2 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -31,7 +31,6 @@
#include <stdlib.h>
#include <libusb.h>
#include <getopt.h>
-#include <arpa/inet.h>
#include <linux/kernel.h>
#include "../common.h"
@@ -47,6 +46,10 @@
#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.
@@ -73,6 +76,7 @@ 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;
};
@@ -211,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,
},
};
@@ -481,12 +493,16 @@ static int transfer(int report, void *p, unsigned cnt, int *last_trans)
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);
+
+ if (report == 2)
+ cnt = mach_id->max_transfer;
+
if (mach_id->hid_endpoint) {
int trans;
err = libusb_interrupt_transfer(usb_dev_handle,
@@ -594,8 +610,8 @@ 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, &read_reg_command, 16, &last_trans);
@@ -651,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);
@@ -671,7 +687,7 @@ 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, &write_reg_command, 16, &last_trans);
@@ -736,7 +752,7 @@ static int send_buf(void *buf, unsigned len)
while (1) {
int now = get_min(cnt, mach_id->max_transfer);
- if (!now)
+ if (now <= 0)
break;
err = transfer(2, p, now, &now);
@@ -771,8 +787,8 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
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 (;;) {
@@ -833,7 +849,7 @@ 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, &jump_command, 16, &last_trans);
@@ -862,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)
@@ -886,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;
@@ -902,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;
@@ -941,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.
@@ -954,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;
@@ -983,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;
}
@@ -1015,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",
@@ -1028,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);
@@ -1343,6 +1359,23 @@ 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;
@@ -1403,7 +1436,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
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, firststage_len, header_addr, type, false);
+ ret = load_file(image, min(fsize, firststage_len), header_addr, type, false);
if (ret < 0)
goto cleanup;
@@ -1412,7 +1445,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
if (verify) {
printf("verifying file...\n");
- ret = verify_memory(image, firststage_len, header_addr);
+ ret = verify_memory(image, min(fsize, firststage_len), header_addr);
if (ret < 0) {
printf("verifying failed\n");
goto cleanup;
@@ -1473,14 +1506,14 @@ static int mxs_load_buf(uint8_t *data, int size)
static struct mxs_command dl_command;
int last_trans, err;
- 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, &dl_command, 20, &last_trans);
if (err) {
@@ -1527,8 +1560,13 @@ 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[])
@@ -1546,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;
@@ -1559,6 +1607,7 @@ int main(int argc, char *argv[])
break;
case 'h':
usage(argv[0]);
+ exit(EXIT_SUCCESS);
case 'd':
devtype = optarg;
break;
@@ -1572,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) {
@@ -1588,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;
@@ -1626,12 +1675,17 @@ int main(int argc, char *argv[])
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) {