summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-09-13 14:56:04 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-09-13 14:56:04 +0200
commitb2c398f44031efc3c6ab2bec19f56df0c05ad3de (patch)
treef64b1bb976f832daa0160e1a67cfcd669822ae58 /scripts
parent0a12c7156890eae6c74732f69a6b731135b0bb27 (diff)
parentb12f38097bce1f12e4b7e420c2c11bea281b4daa (diff)
downloadbarebox-b2c398f44031efc3c6ab2bec19f56df0c05ad3de.tar.gz
barebox-b2c398f44031efc3c6ab2bec19f56df0c05ad3de.tar.xz
Merge branch 'for-next/imx'
Diffstat (limited to 'scripts')
-rw-r--r--scripts/imx/imx-image.c7
-rw-r--r--scripts/imx/imx-usb-loader.c169
-rw-r--r--scripts/imx/imx.c1
-rw-r--r--scripts/imx/imx.h23
4 files changed, 129 insertions, 71 deletions
diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c
index 9bdba7ef12..650a67f604 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
* ============================================================================
*/
@@ -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;
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 17324972bf..c0aaa7d629 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -32,6 +32,7 @@
#include <stdlib.h>
#include <libusb.h>
#include <getopt.h>
+#include <endian.h>
#include <arpa/inet.h>
#include <linux/kernel.h>
@@ -45,7 +46,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 +67,7 @@ struct mach_id {
struct usb_work {
char filename[256];
- unsigned char dcd;
+ unsigned char do_dcd_once;
unsigned char plug;
};
@@ -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,
@@ -743,7 +746,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 +792,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 +802,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,
@@ -872,7 +908,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);
@@ -882,28 +917,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:
- 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);
+ 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);
}
}
@@ -980,9 +1013,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);
@@ -990,7 +1020,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;
@@ -1066,13 +1096,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 +1294,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 +1310,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 +1324,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);
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 },
diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h
index 8db7e7b46c..ae3702c116 100644
--- a/scripts/imx/imx.h
+++ b/scripts/imx/imx.h
@@ -26,14 +26,22 @@ 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
#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;
@@ -73,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);