diff mbox

[U-Boot,V4,08/11] imximage: enable word writes for version2 header

Message ID 1354066303-29762-9-git-send-email-troy.kisky@boundarydevices.com
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Troy Kisky Nov. 28, 2012, 1:31 a.m. UTC
Before, only 1 write_dcd_command table was built.
Now, a new table is built when the size changes.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>

---
v3: moved static variables together
---
 tools/imximage.c |  143 ++++++++++++++++++++++++++----------------------------
 tools/imximage.h |   18 +++----
 2 files changed, 76 insertions(+), 85 deletions(-)

Comments

Wolfgang Denk Nov. 28, 2012, 9:39 a.m. UTC | #1
Dear Troy Kisky,

In message <1354066303-29762-9-git-send-email-troy.kisky@boundarydevices.com> you wrote:
> Before, only 1 write_dcd_command table was built.
> Now, a new table is built when the size changes.

I cannot see how the Subject: and the actual commit message (and code)
are related.

Best regards,

Wolfgang Denk
Liu Hui-R64343 Nov. 28, 2012, 10:47 a.m. UTC | #2
>-----Original Message-----
>From: Troy Kisky [mailto:troy.kisky@boundarydevices.com]
>Sent: Wednesday, November 28, 2012 9:32 AM
>To: sbabic@denx.de
>Cc: dirk.behme@googlemail.com; u-boot@lists.denx.de; Liu Hui-R64343;
>festevam@gmail.com; Troy Kisky
>Subject: [PATCH V4 08/11] imximage: enable word writes for version2 header
>
>Before, only 1 write_dcd_command table was built.
>Now, a new table is built when the size changes.
>
>Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>

Acked-by: Jason Liu <r64343@freescale.com>

>
>---
>v3: moved static variables together
>---
> tools/imximage.c |  143 ++++++++++++++++++++++++++----------------------------
> tools/imximage.h |   18 +++----
> 2 files changed, 76 insertions(+), 85 deletions(-)
>
>diff --git a/tools/imximage.c b/tools/imximage.c index 6d5cfa7..2f5ee14
>100644
>--- a/tools/imximage.c
>+++ b/tools/imximage.c
>@@ -65,8 +65,6 @@ static table_entry_t imximage_versions[] = {
> 	{-1,            "",     " (Invalid)",                 },
> };
>
>-static set_dcd_rst_t set_dcd_rst;
>-static uint32_t max_dcd_entries;
> static uint32_t *header_size_ptr;
> static uint32_t g_flash_offset;
>
>@@ -115,7 +113,7 @@ static void err_imximage_version(int version)  }
>
> static void set_dcd_val_v1(struct data_src *ds, char *name, int lineno,
>-					int fld, uint32_t value, uint32_t off)
>+					int fld, uint32_t value)
> {
> 	dcd_v1_t *dcd_v1 = &ds->imxhdr->header.hdr_v1.dcd_table;
>
>@@ -128,13 +126,15 @@ static void set_dcd_val_v1(struct data_src *ds, char
>*name, int lineno,
> 				name, lineno, value);
> 			exit(EXIT_FAILURE);
> 		}
>-		dcd_v1->addr_data[off].type = value;
>+		*ds->p_entry++ = value;
> 		break;
> 	case CFG_REG_ADDRESS:
>-		dcd_v1->addr_data[off].addr = value;
>+		*ds->p_entry++ = value;
> 		break;
> 	case CFG_REG_VALUE:
>-		dcd_v1->addr_data[off].value = value;
>+		*ds->p_entry++ = value;
>+		dcd_v1->preamble.length = (char *)ds->p_entry
>+				- (char *)&dcd_v1->addr_data[0].type;
> 		break;
> 	default:
> 		break;
>@@ -143,16 +143,42 @@ static void set_dcd_val_v1(struct data_src *ds, char
>*name, int lineno,  }
>
> static void set_dcd_val_v2(struct data_src *ds, char *name, int lineno,
>-					int fld, uint32_t value, uint32_t off)
>+					int fld, uint32_t value)
> {
>+	uint32_t len;
> 	dcd_v2_t *dcd_v2 = &ds->imxhdr->header.hdr_v2.dcd_table;
>
> 	switch (fld) {
>+	case CFG_REG_SIZE:
>+		/* Byte, halfword, word */
>+		if ((value != 1) && (value != 2) && (value != 4)) {
>+			fprintf(stderr, "Error: %s[%d] - "
>+				"Invalid register size " "(%d)\n",
>+				name, lineno, value);
>+			exit(EXIT_FAILURE);
>+		}
>+		if (ds->p_dcd && (ds->p_dcd->param == value))
>+			break;
>+		if (!ds->p_dcd) {
>+			dcd_v2->header.tag = DCD_HEADER_TAG;
>+			dcd_v2->header.version = DCD_VERSION;
>+			ds->p_dcd = &dcd_v2->write_dcd_command;
>+		} else {
>+			ds->p_dcd = (write_dcd_command_t *)ds->p_entry;
>+		}
>+		ds->p_dcd->param = value;
>+		ds->p_dcd->tag = DCD_COMMAND_TAG;
>+		ds->p_entry = (uint32_t *)(ds->p_dcd + 1);
>+		break;
> 	case CFG_REG_ADDRESS:
>-		dcd_v2->addr_data[off].addr = cpu_to_be32(value);
>+		*ds->p_entry++ = cpu_to_be32(value);
> 		break;
> 	case CFG_REG_VALUE:
>-		dcd_v2->addr_data[off].value = cpu_to_be32(value);
>+		*ds->p_entry++ = cpu_to_be32(value);
>+		len = (char *)ds->p_entry - (char *)&dcd_v2->header;
>+		dcd_v2->header.length = cpu_to_be16(len);
>+		len = (char *)ds->p_entry - (char *)ds->p_dcd;
>+		ds->p_dcd->length = cpu_to_be16(len);
> 		break;
> 	default:
> 		break;
>@@ -160,47 +186,14 @@ static void set_dcd_val_v2(struct data_src *ds, char
>*name, int lineno,
> 	}
> }
>
>-/*
>- * Complete setting up the rest field of DCD of V1
>- * such as barker code and DCD data length.
>- */
>-static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len,
>-						char *name, int lineno)
>-{
>-	dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
>-
>-	dcd_v1->preamble.barker = DCD_BARKER;
>-	dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t);
>-}
>-
>-/*
>- * Complete setting up the reset field of DCD of V2
>- * such as DCD tag, version, length, etc.
>- */
>-static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len,
>-						char *name, int lineno)
>-{
>-	dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table;
>-
>-	dcd_v2->header.tag = DCD_HEADER_TAG;
>-	dcd_v2->header.length = cpu_to_be16(
>-			dcd_len * sizeof(dcd_addr_data_t) + 8);
>-	dcd_v2->header.version = DCD_VERSION;
>-	dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG;
>-	dcd_v2->write_dcd_command.length = cpu_to_be16(
>-			dcd_len * sizeof(dcd_addr_data_t) + 4);
>-	dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM;
>-}
>-
>-static int set_imx_hdr_v1(struct data_src *ds, uint32_t dcd_len,
>+static int set_imx_hdr_v1(struct data_src *ds,
> 		uint32_t entry_point, uint32_t flash_offset)  {
> 	imx_header_v1_t *hdr_v1 = &ds->imxhdr->header.hdr_v1;
> 	flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
>-	dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
> 	uint32_t hdr_base;
>-	uint32_t header_length = (((char *)&dcd_v1-
>>addr_data[dcd_len].addr)
>-			- ((char *)ds->imxhdr));
>+	uint32_t header_length = ((char *)ds->p_entry) + 4
>+			- ((char *)ds->imxhdr);
>
> 	/* Set magic number */
> 	fhdr_v1->app_code_barker = APP_CODE_BARKER; @@ -220,15
>+213,13 @@ static int set_imx_hdr_v1(struct data_src *ds, uint32_t dcd_len,
> 	return header_length;
> }
>
>-static int set_imx_hdr_v2(struct data_src *ds, uint32_t dcd_len,
>+static int set_imx_hdr_v2(struct data_src *ds,
> 		uint32_t entry_point, uint32_t flash_offset)  {
> 	imx_header_v2_t *hdr_v2 = &ds->imxhdr->header.hdr_v2;
> 	flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
> 	uint32_t hdr_base;
>-	uint32_t header_length = (dcd_len) ?
>-		(char *)&hdr_v2->dcd_table.addr_data[dcd_len] -
>-		((char *)ds->imxhdr) : offsetof(imx_header_v2_t, dcd_table);
>+	uint32_t header_length = ((char *)ds->p_entry) - ((char *)ds->imxhdr);
>
> 	/* Set magic number */
> 	fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ @@ -239,7
>+230,7 @@ static int set_imx_hdr_v2(struct data_src *ds, uint32_t dcd_len,
> 	fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
> 	fhdr_v2->self = hdr_base = entry_point - header_length;
>
>-	fhdr_v2->dcd_ptr = (dcd_len) ? hdr_base
>+	fhdr_v2->dcd_ptr = (ds->p_dcd) ? hdr_base
> 			+ offsetof(imx_header_v2_t, dcd_table) : 0;
> 	fhdr_v2->boot_data_ptr = hdr_base
> 			+ offsetof(imx_header_v2_t, boot_data); @@ -256,15
>+247,20 @@ static void set_hdr_func(struct data_src *ds, uint32_t
>imximage_version)
> 	switch (imximage_version) {
> 	case IMXIMAGE_V1:
> 		ds->set_dcd_val = set_dcd_val_v1;
>-		set_dcd_rst = set_dcd_rst_v1;
> 		ds->set_imx_hdr = set_imx_hdr_v1;
>-		max_dcd_entries = MAX_HW_CFG_SIZE_V1;
>+		ds->p_entry = &ds->imxhdr->header.hdr_v1.dcd_table
>+				.addr_data[0].type;
>+		ds->p_max_dcd = &ds->imxhdr->header.hdr_v1.dcd_table
>+				.addr_data[MAX_HW_CFG_SIZE_V1].type;
>+		ds->imxhdr->header.hdr_v1.dcd_table.preamble.barker =
>+				DCD_BARKER;
> 		break;
> 	case IMXIMAGE_V2:
> 		ds->set_dcd_val = set_dcd_val_v2;
>-		set_dcd_rst = set_dcd_rst_v2;
> 		ds->set_imx_hdr = set_imx_hdr_v2;
>-		max_dcd_entries = MAX_HW_CFG_SIZE_V2;
>+		ds->p_entry = (uint32_t *)&ds->imxhdr-
>>header.hdr_v2.dcd_table;
>+		ds->p_max_dcd = (uint32_t *)
>+				((char *)ds->imxhdr + MAX_HEADER_SIZE);
> 		break;
> 	default:
> 		err_imximage_version(imximage_version);
>@@ -328,7 +324,7 @@ static void print_hdr_v2(struct imx_header
>*imx_hdr)  }
>
> static void parse_cfg_cmd(struct data_src *ds, int32_t cmd, char *token,
>-				char *name, int lineno, int fld, int dcd_len)
>+				char *name, int lineno, int fld)
> {
> 	int value;
> 	static int cmd_ver_first = ~0;
>@@ -359,7 +355,7 @@ static void parse_cfg_cmd(struct data_src *ds, int32_t
>cmd, char *token,
> 		break;
> 	case CMD_DATA:
> 		value = get_cfg_value(token, name, lineno);
>-		(*ds->set_dcd_val)(ds, name, lineno, fld, value, dcd_len);
>+		(*ds->set_dcd_val)(ds, name, lineno, fld, value);
> 		if (unlikely(cmd_ver_first != 1))
> 			cmd_ver_first = 0;
> 		break;
>@@ -367,7 +363,7 @@ static void parse_cfg_cmd(struct data_src *ds, int32_t
>cmd, char *token,  }
>
> static void parse_cfg_fld(struct data_src *ds, int32_t *cmd,
>-		char *token, char *name, int lineno, int fld, int *dcd_len)
>+		char *token, char *name, int lineno, int fld)
> {
> 	int value;
>
>@@ -382,7 +378,7 @@ static void parse_cfg_fld(struct data_src *ds, int32_t
>*cmd,
> 		}
> 		break;
> 	case CFG_REG_SIZE:
>-		parse_cfg_cmd(ds, *cmd, token, name, lineno, fld, *dcd_len);
>+		parse_cfg_cmd(ds, *cmd, token, name, lineno, fld);
> 		break;
> 	case CFG_REG_ADDRESS:
> 	case CFG_REG_VALUE:
>@@ -390,16 +386,14 @@ static void parse_cfg_fld(struct data_src *ds,
>int32_t *cmd,
> 			return;
>
> 		value = get_cfg_value(token, name, lineno);
>-		(*ds->set_dcd_val)(ds, name, lineno, fld, value, *dcd_len);
>-
>-		if (fld == CFG_REG_VALUE) {
>-			(*dcd_len)++;
>-			if (*dcd_len > max_dcd_entries) {
>-				fprintf(stderr, "Error: %s[%d] -"
>-					"DCD table exceeds maximum size(%d)\n",
>-					name, lineno, max_dcd_entries);
>-				exit(EXIT_FAILURE);
>-			}
>+		(*ds->set_dcd_val)(ds, name, lineno, fld, value);
>+		if (ds->p_entry > ds->p_max_dcd) {
>+			uint32_t size = (char *)ds->p_max_dcd -
>+					(char *)ds->imxhdr;
>+			fprintf(stderr, "Error: %s[%d] -"
>+					"header exceeds maximum size(%d)\n",
>+					name, lineno, size);
>+			exit(EXIT_FAILURE);
> 		}
> 		break;
> 	default:
>@@ -417,7 +411,6 @@ static int parse_cfg_file(struct imx_header *imxhdr,
>char *name,
> 	int lineno = 0;
> 	int fld;
> 	size_t len;
>-	int dcd_len = 0;
> 	int32_t cmd;
>
> 	/* Be able to detect if the cfg file has no BOOT_FROM tag */ @@ -
>458,12 +451,10 @@ static int parse_cfg_file(struct imx_header *imxhdr, char
>*name,
> 				break;
>
> 			parse_cfg_fld(&ds, &cmd, token, name,
>-					lineno, fld, &dcd_len);
>+					lineno, fld);
> 		}
>
> 	}
>-
>-	(*set_dcd_rst)(imxhdr, dcd_len, name, lineno);
> 	fclose(fd);
>
> 	/* Exit if there is no BOOT_FROM field specifying the flash_offset */
>@@ -472,7 +463,7 @@ static int parse_cfg_file(struct imx_header *imxhdr,
>char *name,
> 		exit(EXIT_FAILURE);
> 	}
> 	/* Set the imx header */
>-	return (*ds.set_imx_hdr)(&ds, dcd_len, entry_point, g_flash_offset);
>+	return (*ds.set_imx_hdr)(&ds, entry_point, g_flash_offset);
> }
>
> static int imximage_check_image_types(uint8_t type) @@ -517,7 +508,11
>@@ int imximage_vrec_header(struct mkimage_params *params,  {
> 	struct imx_header *imxhdr;
>
>-	imxhdr = calloc(1, MAX_HEADER_SIZE);
>+	/*
>+	 * A little extra space to avoid access violation on dcd table overflow.
>+	 * Overflow is checked after entry is added.
>+	 */
>+	imxhdr = calloc(1, MAX_HEADER_SIZE + 32);
> 	if (!imxhdr) {
> 		fprintf(stderr, "Error: out of memory\n");
> 		exit(EXIT_FAILURE);
>diff --git a/tools/imximage.h b/tools/imximage.h index 444ddce..196bb51
>100644
>--- a/tools/imximage.h
>+++ b/tools/imximage.h
>@@ -47,7 +47,6 @@
> #define DCD_HEADER_TAG 0xD2
> #define DCD_COMMAND_TAG 0xCC
> #define DCD_VERSION 0x40
>-#define DCD_COMMAND_PARAM 0x4
>
> enum imximage_cmd {
> 	CMD_INVALID,
>@@ -160,21 +159,18 @@ struct imx_header {  };
>
> struct data_src;
>-typedef void (*set_dcd_val_t)(struct data_src *ds,
>-					char *name, int lineno,
>-					int fld, uint32_t value,
>-					uint32_t off);
>+typedef void (*set_dcd_val_t)(struct data_src *ds, char *name,
>+		int lineno, int fld, uint32_t value);
>
>-typedef void (*set_dcd_rst_t)(struct imx_header *imxhdr,
>-					uint32_t dcd_len,
>-					char *name, int lineno);
>-
>-typedef int (*set_imx_hdr_t)(struct data_src *ds, uint32_t dcd_len,
>-		uint32_t entry_point, uint32_t flash_offset);
>+typedef int (*set_imx_hdr_t)(struct data_src *ds, uint32_t entry_point,
>+		uint32_t flash_offset);
>
> struct data_src {
> 	struct imx_header *imxhdr;
> 	set_imx_hdr_t set_imx_hdr;
> 	set_dcd_val_t set_dcd_val;
>+	uint32_t *p_max_dcd;
>+	uint32_t *p_entry;
>+	write_dcd_command_t *p_dcd;
> };
> #endif /* _IMXIMAGE_H_ */
>--
>1.7.9.5
>
Troy Kisky Nov. 28, 2012, 8:40 p.m. UTC | #3
On 11/28/2012 2:39 AM, Wolfgang Denk wrote:
> Dear Troy Kisky,
>
> In message <1354066303-29762-9-git-send-email-troy.kisky@boundarydevices.com> you wrote:
>> Before, only 1 write_dcd_command table was built.
>> Now, a new table is built when the size changes.
> I cannot see how the Subject: and the actual commit message (and code)
> are related.
>
> Best regards,
>
> Wolfgang Denk
>
How about this for the commit message

Before, only 1 write_dcd_command table was built.
Now, a new table is built when the size changes.

i.e. before this patch, the sequence
DATA 4 0x83FD9014 0x00000000
DATA 2 0x83FC8000 0x00fe

was only valid for Version 1 headers, now it is valid
for Version 2 headers as well.

Parameters were changed for set_dcd_val_t to accomplish
this. So, set_dcd_val_v1 for version 1 was also slightly modified.
But no new functionality was added for version 1.

No current config files use this functionality, but this patch
removes more lines than it adds.
Stefano Babic Dec. 4, 2012, 8:23 a.m. UTC | #4
On 28/11/2012 21:40, Troy Kisky wrote:
> On 11/28/2012 2:39 AM, Wolfgang Denk wrote:
>> Dear Troy Kisky,
>>
>> In message
>> <1354066303-29762-9-git-send-email-troy.kisky@boundarydevices.com> you
>> wrote:
>>> Before, only 1 write_dcd_command table was built.
>>> Now, a new table is built when the size changes.
>> I cannot see how the Subject: and the actual commit message (and code)
>> are related.
>>
>> Best regards,
>>
>> Wolfgang Denk
>>
> How about this for the commit message
> 
> Before, only 1 write_dcd_command table was built.
> Now, a new table is built when the size changes.
> 
> i.e. before this patch, the sequence
> DATA 4 0x83FD9014 0x00000000
> DATA 2 0x83FC8000 0x00fe
> 
> was only valid for Version 1 headers, now it is valid
> for Version 2 headers as well.

Much better ! Maybe you can also change the title of the patch, telling
that you are fixing a bug (the fact that first parameter was not
correctly interpreted for V2 *is* a bug). And the example explains very
well the issue.

> 
> Parameters were changed for set_dcd_val_t to accomplish
> this. So, set_dcd_val_v1 for version 1 was also slightly modified.
> But no new functionality was added for version 1.
> 
> No current config files use this functionality, but this patch
> removes more lines than it adds.


Best regards,
Stefano Babic
diff mbox

Patch

diff --git a/tools/imximage.c b/tools/imximage.c
index 6d5cfa7..2f5ee14 100644
--- a/tools/imximage.c
+++ b/tools/imximage.c
@@ -65,8 +65,6 @@  static table_entry_t imximage_versions[] = {
 	{-1,            "",     " (Invalid)",                 },
 };
 
-static set_dcd_rst_t set_dcd_rst;
-static uint32_t max_dcd_entries;
 static uint32_t *header_size_ptr;
 static uint32_t g_flash_offset;
 
@@ -115,7 +113,7 @@  static void err_imximage_version(int version)
 }
 
 static void set_dcd_val_v1(struct data_src *ds, char *name, int lineno,
-					int fld, uint32_t value, uint32_t off)
+					int fld, uint32_t value)
 {
 	dcd_v1_t *dcd_v1 = &ds->imxhdr->header.hdr_v1.dcd_table;
 
@@ -128,13 +126,15 @@  static void set_dcd_val_v1(struct data_src *ds, char *name, int lineno,
 				name, lineno, value);
 			exit(EXIT_FAILURE);
 		}
-		dcd_v1->addr_data[off].type = value;
+		*ds->p_entry++ = value;
 		break;
 	case CFG_REG_ADDRESS:
-		dcd_v1->addr_data[off].addr = value;
+		*ds->p_entry++ = value;
 		break;
 	case CFG_REG_VALUE:
-		dcd_v1->addr_data[off].value = value;
+		*ds->p_entry++ = value;
+		dcd_v1->preamble.length = (char *)ds->p_entry
+				- (char *)&dcd_v1->addr_data[0].type;
 		break;
 	default:
 		break;
@@ -143,16 +143,42 @@  static void set_dcd_val_v1(struct data_src *ds, char *name, int lineno,
 }
 
 static void set_dcd_val_v2(struct data_src *ds, char *name, int lineno,
-					int fld, uint32_t value, uint32_t off)
+					int fld, uint32_t value)
 {
+	uint32_t len;
 	dcd_v2_t *dcd_v2 = &ds->imxhdr->header.hdr_v2.dcd_table;
 
 	switch (fld) {
+	case CFG_REG_SIZE:
+		/* Byte, halfword, word */
+		if ((value != 1) && (value != 2) && (value != 4)) {
+			fprintf(stderr, "Error: %s[%d] - "
+				"Invalid register size " "(%d)\n",
+				name, lineno, value);
+			exit(EXIT_FAILURE);
+		}
+		if (ds->p_dcd && (ds->p_dcd->param == value))
+			break;
+		if (!ds->p_dcd) {
+			dcd_v2->header.tag = DCD_HEADER_TAG;
+			dcd_v2->header.version = DCD_VERSION;
+			ds->p_dcd = &dcd_v2->write_dcd_command;
+		} else {
+			ds->p_dcd = (write_dcd_command_t *)ds->p_entry;
+		}
+		ds->p_dcd->param = value;
+		ds->p_dcd->tag = DCD_COMMAND_TAG;
+		ds->p_entry = (uint32_t *)(ds->p_dcd + 1);
+		break;
 	case CFG_REG_ADDRESS:
-		dcd_v2->addr_data[off].addr = cpu_to_be32(value);
+		*ds->p_entry++ = cpu_to_be32(value);
 		break;
 	case CFG_REG_VALUE:
-		dcd_v2->addr_data[off].value = cpu_to_be32(value);
+		*ds->p_entry++ = cpu_to_be32(value);
+		len = (char *)ds->p_entry - (char *)&dcd_v2->header;
+		dcd_v2->header.length = cpu_to_be16(len);
+		len = (char *)ds->p_entry - (char *)ds->p_dcd;
+		ds->p_dcd->length = cpu_to_be16(len);
 		break;
 	default:
 		break;
@@ -160,47 +186,14 @@  static void set_dcd_val_v2(struct data_src *ds, char *name, int lineno,
 	}
 }
 
-/*
- * Complete setting up the rest field of DCD of V1
- * such as barker code and DCD data length.
- */
-static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len,
-						char *name, int lineno)
-{
-	dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
-
-	dcd_v1->preamble.barker = DCD_BARKER;
-	dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t);
-}
-
-/*
- * Complete setting up the reset field of DCD of V2
- * such as DCD tag, version, length, etc.
- */
-static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len,
-						char *name, int lineno)
-{
-	dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table;
-
-	dcd_v2->header.tag = DCD_HEADER_TAG;
-	dcd_v2->header.length = cpu_to_be16(
-			dcd_len * sizeof(dcd_addr_data_t) + 8);
-	dcd_v2->header.version = DCD_VERSION;
-	dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG;
-	dcd_v2->write_dcd_command.length = cpu_to_be16(
-			dcd_len * sizeof(dcd_addr_data_t) + 4);
-	dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM;
-}
-
-static int set_imx_hdr_v1(struct data_src *ds, uint32_t dcd_len,
+static int set_imx_hdr_v1(struct data_src *ds,
 		uint32_t entry_point, uint32_t flash_offset)
 {
 	imx_header_v1_t *hdr_v1 = &ds->imxhdr->header.hdr_v1;
 	flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
-	dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
 	uint32_t hdr_base;
-	uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr)
-			- ((char *)ds->imxhdr));
+	uint32_t header_length = ((char *)ds->p_entry) + 4
+			- ((char *)ds->imxhdr);
 
 	/* Set magic number */
 	fhdr_v1->app_code_barker = APP_CODE_BARKER;
@@ -220,15 +213,13 @@  static int set_imx_hdr_v1(struct data_src *ds, uint32_t dcd_len,
 	return header_length;
 }
 
-static int set_imx_hdr_v2(struct data_src *ds, uint32_t dcd_len,
+static int set_imx_hdr_v2(struct data_src *ds,
 		uint32_t entry_point, uint32_t flash_offset)
 {
 	imx_header_v2_t *hdr_v2 = &ds->imxhdr->header.hdr_v2;
 	flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
 	uint32_t hdr_base;
-	uint32_t header_length = (dcd_len) ?
-		(char *)&hdr_v2->dcd_table.addr_data[dcd_len] -
-		((char *)ds->imxhdr) : offsetof(imx_header_v2_t, dcd_table);
+	uint32_t header_length = ((char *)ds->p_entry) - ((char *)ds->imxhdr);
 
 	/* Set magic number */
 	fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
@@ -239,7 +230,7 @@  static int set_imx_hdr_v2(struct data_src *ds, uint32_t dcd_len,
 	fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
 	fhdr_v2->self = hdr_base = entry_point - header_length;
 
-	fhdr_v2->dcd_ptr = (dcd_len) ? hdr_base
+	fhdr_v2->dcd_ptr = (ds->p_dcd) ? hdr_base
 			+ offsetof(imx_header_v2_t, dcd_table) : 0;
 	fhdr_v2->boot_data_ptr = hdr_base
 			+ offsetof(imx_header_v2_t, boot_data);
@@ -256,15 +247,20 @@  static void set_hdr_func(struct data_src *ds, uint32_t imximage_version)
 	switch (imximage_version) {
 	case IMXIMAGE_V1:
 		ds->set_dcd_val = set_dcd_val_v1;
-		set_dcd_rst = set_dcd_rst_v1;
 		ds->set_imx_hdr = set_imx_hdr_v1;
-		max_dcd_entries = MAX_HW_CFG_SIZE_V1;
+		ds->p_entry = &ds->imxhdr->header.hdr_v1.dcd_table
+				.addr_data[0].type;
+		ds->p_max_dcd = &ds->imxhdr->header.hdr_v1.dcd_table
+				.addr_data[MAX_HW_CFG_SIZE_V1].type;
+		ds->imxhdr->header.hdr_v1.dcd_table.preamble.barker =
+				DCD_BARKER;
 		break;
 	case IMXIMAGE_V2:
 		ds->set_dcd_val = set_dcd_val_v2;
-		set_dcd_rst = set_dcd_rst_v2;
 		ds->set_imx_hdr = set_imx_hdr_v2;
-		max_dcd_entries = MAX_HW_CFG_SIZE_V2;
+		ds->p_entry = (uint32_t *)&ds->imxhdr->header.hdr_v2.dcd_table;
+		ds->p_max_dcd = (uint32_t *)
+				((char *)ds->imxhdr + MAX_HEADER_SIZE);
 		break;
 	default:
 		err_imximage_version(imximage_version);
@@ -328,7 +324,7 @@  static void print_hdr_v2(struct imx_header *imx_hdr)
 }
 
 static void parse_cfg_cmd(struct data_src *ds, int32_t cmd, char *token,
-				char *name, int lineno, int fld, int dcd_len)
+				char *name, int lineno, int fld)
 {
 	int value;
 	static int cmd_ver_first = ~0;
@@ -359,7 +355,7 @@  static void parse_cfg_cmd(struct data_src *ds, int32_t cmd, char *token,
 		break;
 	case CMD_DATA:
 		value = get_cfg_value(token, name, lineno);
-		(*ds->set_dcd_val)(ds, name, lineno, fld, value, dcd_len);
+		(*ds->set_dcd_val)(ds, name, lineno, fld, value);
 		if (unlikely(cmd_ver_first != 1))
 			cmd_ver_first = 0;
 		break;
@@ -367,7 +363,7 @@  static void parse_cfg_cmd(struct data_src *ds, int32_t cmd, char *token,
 }
 
 static void parse_cfg_fld(struct data_src *ds, int32_t *cmd,
-		char *token, char *name, int lineno, int fld, int *dcd_len)
+		char *token, char *name, int lineno, int fld)
 {
 	int value;
 
@@ -382,7 +378,7 @@  static void parse_cfg_fld(struct data_src *ds, int32_t *cmd,
 		}
 		break;
 	case CFG_REG_SIZE:
-		parse_cfg_cmd(ds, *cmd, token, name, lineno, fld, *dcd_len);
+		parse_cfg_cmd(ds, *cmd, token, name, lineno, fld);
 		break;
 	case CFG_REG_ADDRESS:
 	case CFG_REG_VALUE:
@@ -390,16 +386,14 @@  static void parse_cfg_fld(struct data_src *ds, int32_t *cmd,
 			return;
 
 		value = get_cfg_value(token, name, lineno);
-		(*ds->set_dcd_val)(ds, name, lineno, fld, value, *dcd_len);
-
-		if (fld == CFG_REG_VALUE) {
-			(*dcd_len)++;
-			if (*dcd_len > max_dcd_entries) {
-				fprintf(stderr, "Error: %s[%d] -"
-					"DCD table exceeds maximum size(%d)\n",
-					name, lineno, max_dcd_entries);
-				exit(EXIT_FAILURE);
-			}
+		(*ds->set_dcd_val)(ds, name, lineno, fld, value);
+		if (ds->p_entry > ds->p_max_dcd) {
+			uint32_t size = (char *)ds->p_max_dcd -
+					(char *)ds->imxhdr;
+			fprintf(stderr, "Error: %s[%d] -"
+					"header exceeds maximum size(%d)\n",
+					name, lineno, size);
+			exit(EXIT_FAILURE);
 		}
 		break;
 	default:
@@ -417,7 +411,6 @@  static int parse_cfg_file(struct imx_header *imxhdr, char *name,
 	int lineno = 0;
 	int fld;
 	size_t len;
-	int dcd_len = 0;
 	int32_t cmd;
 
 	/* Be able to detect if the cfg file has no BOOT_FROM tag */
@@ -458,12 +451,10 @@  static int parse_cfg_file(struct imx_header *imxhdr, char *name,
 				break;
 
 			parse_cfg_fld(&ds, &cmd, token, name,
-					lineno, fld, &dcd_len);
+					lineno, fld);
 		}
 
 	}
-
-	(*set_dcd_rst)(imxhdr, dcd_len, name, lineno);
 	fclose(fd);
 
 	/* Exit if there is no BOOT_FROM field specifying the flash_offset */
@@ -472,7 +463,7 @@  static int parse_cfg_file(struct imx_header *imxhdr, char *name,
 		exit(EXIT_FAILURE);
 	}
 	/* Set the imx header */
-	return (*ds.set_imx_hdr)(&ds, dcd_len, entry_point, g_flash_offset);
+	return (*ds.set_imx_hdr)(&ds, entry_point, g_flash_offset);
 }
 
 static int imximage_check_image_types(uint8_t type)
@@ -517,7 +508,11 @@  int imximage_vrec_header(struct mkimage_params *params,
 {
 	struct imx_header *imxhdr;
 
-	imxhdr = calloc(1, MAX_HEADER_SIZE);
+	/*
+	 * A little extra space to avoid access violation on dcd table overflow.
+	 * Overflow is checked after entry is added.
+	 */
+	imxhdr = calloc(1, MAX_HEADER_SIZE + 32);
 	if (!imxhdr) {
 		fprintf(stderr, "Error: out of memory\n");
 		exit(EXIT_FAILURE);
diff --git a/tools/imximage.h b/tools/imximage.h
index 444ddce..196bb51 100644
--- a/tools/imximage.h
+++ b/tools/imximage.h
@@ -47,7 +47,6 @@ 
 #define DCD_HEADER_TAG 0xD2
 #define DCD_COMMAND_TAG 0xCC
 #define DCD_VERSION 0x40
-#define DCD_COMMAND_PARAM 0x4
 
 enum imximage_cmd {
 	CMD_INVALID,
@@ -160,21 +159,18 @@  struct imx_header {
 };
 
 struct data_src;
-typedef void (*set_dcd_val_t)(struct data_src *ds,
-					char *name, int lineno,
-					int fld, uint32_t value,
-					uint32_t off);
+typedef void (*set_dcd_val_t)(struct data_src *ds, char *name,
+		int lineno, int fld, uint32_t value);
 
-typedef void (*set_dcd_rst_t)(struct imx_header *imxhdr,
-					uint32_t dcd_len,
-					char *name, int lineno);
-
-typedef int (*set_imx_hdr_t)(struct data_src *ds, uint32_t dcd_len,
-		uint32_t entry_point, uint32_t flash_offset);
+typedef int (*set_imx_hdr_t)(struct data_src *ds, uint32_t entry_point,
+		uint32_t flash_offset);
 
 struct data_src {
 	struct imx_header *imxhdr;
 	set_imx_hdr_t set_imx_hdr;
 	set_dcd_val_t set_dcd_val;
+	uint32_t *p_max_dcd;
+	uint32_t *p_entry;
+	write_dcd_command_t *p_dcd;
 };
 #endif /* _IMXIMAGE_H_ */