[U-Boot] [PATCH v2] imx: mx6: Add support for MX6 plugin images

Stefano Babic sbabic at denx.de
Wed Nov 5 09:41:46 CET 2014


Hi Ye,

On 05/11/2014 09:13, Ye.Li wrote:
> Plugin image is a firmware which can be executed during booting.
> Unlike device configuration data (DCD) which is static and interpretative
> configuration, plugin can be used to implement rich logics more than
> the peripherals configuration.
> 
> Customers may consider to use the plugin, for the cases including but
> not limited to:
> 1) Need runtime condition judging.
> 2) Add delay to booting.
> 3) Apply custom settings to boot device and memory system.
> 4) Need more perpherals other than the boot device to work during booting.
> 
> The boot ROM detects the image type using the plugin flag of the boot
> data structure. If the plugin flag is 1, then the ROM uses the image
> as a plugin function. The function must initialize the boot device and
> copy the program image to the final location. At the end the plugin
> function must return with the program image parameters.
> 
> This patch supports generating plugin images and implement a framework
> for plugin code entry and exit. For any board to generate the plugin
> image, the macros below must be implemented:
>   imx6_ddr_setting
>   imx6_clock_gating
>   imx6_qos_setting
> 

Before reviewing deeply these patches, I want to discuss here which are
the pros and cons for a plugin approach. We had already in the past a
large discussion about this topic, and maybe we have to extend it.

Let's see the advantages you are listing here. Of course, if we are
comparing to the way was mostly used for i.MXes, it takes advantages.
Using only the DCD, most configurations must be decided at compile time.
This does not allow to have a single image for multiple boards, for
example if a different i.MX6 variant is mounted on the board. And there
are a lot of other things that are known only at runtime.

But generally in the U-Boot project was already found solution, that is
not only valid for Freescale's i.MXes: SPL. Using SPL, this adds much
more flexibility as with plugins. You can program whatever you want, and
of course you can add any runtime detection is possible, without
intervention of the BOOT ROM. And this is not limited to ddr settzing,
clock gating or pinmux setup.

This is not a new approach, and support for SPL was already added to
mainline - see the Gateway's ventana board. The different layout of the
pinmux is correctly handled. The processor is detected at runtime,
making possible to have a single image for several variations of the
same board.

I see that plugins are the way found to circumvent the static
limitations of the DCD, but it is not a general solution. On the other
side, the SPL concept works well on i.MXes as on other SOCs (TIs,
Nvidia,...).

I have not changed my mind and I still think that i.MXes in U-Boot
should not be an island in the project. Some general concepts must work
for all supported SOCs, including i.MXes. In principle, I tend to reject
this patchset, because the same new features you list here are already
available with SPL. And I encourage to use SPL for other and new i.MX
boards.

Best regards,
Stefano Babic




> Signed-off-by: Ye.Li <B37916 at freescale.com>
> ---
> Changes since v1:
> - Improve the patch message to explicate more about the usage of plugin image.
> 
>  arch/arm/include/asm/arch-mx6/mx6_plugin.S |  145 +++++++++++++++
>  tools/imximage.c                           |  263 ++++++++++++++++++++++------
>  tools/imximage.h                           |   10 +-
>  3 files changed, 366 insertions(+), 52 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-mx6/mx6_plugin.S
> 
> diff --git a/arch/arm/include/asm/arch-mx6/mx6_plugin.S b/arch/arm/include/asm/arch-mx6/mx6_plugin.S
> new file mode 100644
> index 0000000..1f5ae83
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx6/mx6_plugin.S
> @@ -0,0 +1,145 @@
> +/*
> + * Copyright (C) 2012-2014 Freescale Semiconductor, Inc.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <config.h>
> +
> +#ifdef CONFIG_ROM_UNIFIED_SECTIONS
> +#define ROM_API_TABLE_BASE_ADDR_LEGACY		0x180
> +#define ROM_VERSION_OFFSET               	0x80
> +#else
> +#define ROM_API_TABLE_BASE_ADDR_LEGACY		0xC0
> +#define ROM_VERSION_OFFSET               	0x48
> +#endif
> +#define ROM_API_TABLE_BASE_ADDR_MX6DQ_TO15	0xC4
> +#define ROM_API_TABLE_BASE_ADDR_MX6DL_TO12	0xC4
> +#define ROM_API_HWCNFG_SETUP_OFFSET		0x08
> +#define ROM_VERSION_TO10			0x10
> +#define ROM_VERSION_TO12			0x12
> +#define ROM_VERSION_TO15			0x15
> +
> +plugin_start:
> +
> +	push    {r0-r4, lr}
> +
> +	imx6_ddr_setting
> +	imx6_clock_gating
> +	imx6_qos_setting
> +
> +/*
> + * The following is to fill in those arguments for this ROM function
> + * pu_irom_hwcnfg_setup(void **start, size_t *bytes, const void *boot_data)
> + * This function is used to copy data from the storage media into DDR.
> + * start - Initial (possibly partial) image load address on entry.
> + *         Final image load address on exit.
> + * bytes - Initial (possibly partial) image size on entry.
> + *         Final image size on exit.
> + * boot_data - Initial @ref ivt Boot Data load address.
> + */
> +	adr r0, boot_data2
> +	adr r1, image_len2
> +	adr r2, boot_data2
> +
> +#ifdef CONFIG_SYS_BOOT_EIMNOR
> +#ifdef CONFIG_MX6SX
> +	ldr r3, =ROM_VERSION_OFFSET
> +	ldr r4, [r3]
> +	cmp r4, #ROM_VERSION_TO10
> +	bgt before_calling_rom___pu_irom_hwcnfg_setup
> +	ldr r3, =0x00900b00
> +	ldr r4, =0x50000000
> +	str r4, [r3, #0x5c]
> +#else
> +	ldr r3, =0x00900800
> +	ldr r4, =0x08000000
> +	str r4, [r3, #0xc0]
> +#endif
> +#endif
> +
> +/*
> + * check the _pu_irom_api_table for the address
> + */
> +before_calling_rom___pu_irom_hwcnfg_setup:
> +	ldr r3, =ROM_VERSION_OFFSET
> +	ldr r4, [r3]
> +#if defined(CONFIG_MX6SOLO) || defined(CONFIG_MX6DL)
> +	ldr r3, =ROM_VERSION_TO12
> +	cmp r4, r3
> +	ldrge r3, =ROM_API_TABLE_BASE_ADDR_MX6DL_TO12
> +	ldrlt r3, =ROM_API_TABLE_BASE_ADDR_LEGACY
> +#elif defined(CONFIG_MX6Q)
> +	ldr r3, =ROM_VERSION_TO15
> +	cmp r4, r3
> +	ldrge r3, =ROM_API_TABLE_BASE_ADDR_MX6DQ_TO15
> +	ldrlt r3, =ROM_API_TABLE_BASE_ADDR_LEGACY
> +#else
> +	ldr r3, =ROM_API_TABLE_BASE_ADDR_LEGACY
> +#endif
> +	ldr r4, [r3, #ROM_API_HWCNFG_SETUP_OFFSET]
> +	blx r4
> +after_calling_rom___pu_irom_hwcnfg_setup:
> +
> +
> +/* To return to ROM from plugin, we need to fill in these argument.
> + * Here is what need to do:
> + * Need to construct the paramters for this function before return to ROM:
> + * plugin_download(void **start, size_t *bytes, UINT32 *ivt_offset)
> + */
> +	pop {r0-r4, lr}
> +	push {r5}
> +	ldr r5, boot_data2
> +	str r5, [r0]
> +	ldr r5, image_len2
> +	str r5, [r1]
> +	ldr r5, second_ivt_offset
> +	str r5, [r2]
> +	mov r0, #1
> +	pop {r5}
> +
> +	/* return back to ROM code */
> +	bx lr
> +
> +/* make the following data right in the end of the output*/
> +.ltorg
> +
> +#if (defined(CONFIG_SYS_BOOT_EIMNOR) || defined(CONFIG_SYS_BOOT_QSPI))
> +#define FLASH_OFFSET 0x1000
> +#else
> +#define FLASH_OFFSET 0x400
> +#endif
> +
> +/*
> + * second_ivt_offset is the offset from the "second_ivt_header" to
> + * "image_copy_start", which involves FLASH_OFFSET, plus the first
> + * ivt_header, the plugin code size itself recorded by "ivt2_header"
> + */
> +
> +second_ivt_offset:      .long (ivt2_header + 0x2C + FLASH_OFFSET)
> +
> +/*
> + * The following is the second IVT header plus the second boot data
> + */
> +ivt2_header:            .long 0x0
> +app2_code_jump_v:       .long 0x0
> +reserv3:                .long 0x0
> +dcd2_ptr:               .long 0x0
> +boot_data2_ptr:         .long 0x0
> +self_ptr2:              .long 0x0
> +app_code_csf2:          .long 0x0
> +reserv4:                .long 0x0
> +boot_data2:             .long 0x0
> +image_len2:             .long 0x0
> +plugin2:                .long 0x0
> diff --git a/tools/imximage.c b/tools/imximage.c
> index 526b7d4..70a988e 100644
> --- a/tools/imximage.c
> +++ b/tools/imximage.c
> @@ -24,6 +24,9 @@ static table_entry_t imximage_cmds[] = {
>  	{CMD_DATA,              "DATA",                 "Reg Write Data", },
>  	{CMD_CSF,               "CSF",           "Command Sequence File", },
>  	{CMD_IMAGE_VERSION,     "IMAGE_VERSION",        "image version",  },
> +#ifdef CONFIG_USE_PLUGIN
> +	{CMD_PLUGIN,			"PLUGIN",				"file plugin_addr",  },
> +#endif
>  	{-1,                    "",                     "",	          },
>  };
>  
> @@ -75,6 +78,8 @@ static uint32_t imximage_ivt_offset = UNDEFINED;
>  static uint32_t imximage_csf_size = UNDEFINED;
>  /* Initial Load Region Size */
>  static uint32_t imximage_init_loadsize;
> +static uint32_t imximage_iram_free_start;
> +static uint32_t imximage_plugin_size;
>  
>  static set_dcd_val_t set_dcd_val;
>  static set_dcd_rst_t set_dcd_rst;
> @@ -112,7 +117,11 @@ static uint32_t detect_imximage_version(struct imx_header *imx_hdr)
>  
>  	/* Try to detect V2 */
>  	if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
> -		(hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG))
> +		(hdr_v2->data.dcd_table.header.tag == DCD_HEADER_TAG))
> +		return IMXIMAGE_V2;
> +
> +	if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
> +		hdr_v2->boot_data.plugin)
>  		return IMXIMAGE_V2;
>  
>  	return IMXIMAGE_VER_INVALID;
> @@ -157,7 +166,7 @@ static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno,
>  static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno,
>  					int fld, uint32_t value, uint32_t off)
>  {
> -	dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table;
> +	dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table;
>  
>  	switch (fld) {
>  	case CFG_REG_ADDRESS:
> @@ -192,16 +201,18 @@ static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len,
>  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;
> +	if (!imxhdr->header.hdr_v2.boot_data.plugin) {
> +		dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.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 void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len,
> @@ -243,20 +254,87 @@ static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len,
>  	fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t));
>  	fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
>  
> -	fhdr_v2->entry = entry_point;
> -	fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
> -	hdr_base = entry_point - imximage_init_loadsize +
> -		flash_offset;
> -	fhdr_v2->self = hdr_base;
> -	fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table);
> -	fhdr_v2->boot_data_ptr = hdr_base
> -			+ offsetof(imx_header_v2_t, boot_data);
> -	hdr_v2->boot_data.start = entry_point - imximage_init_loadsize;
> +	if (!hdr_v2->boot_data.plugin) {
> +		fhdr_v2->entry = entry_point;
> +		fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
> +		hdr_base = entry_point - imximage_init_loadsize +
> +			flash_offset;
> +		fhdr_v2->self = hdr_base;
> +		fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, data);
> +		fhdr_v2->boot_data_ptr = hdr_base
> +				+ offsetof(imx_header_v2_t, boot_data);
> +		hdr_v2->boot_data.start = entry_point - imximage_init_loadsize;
> +
> +		fhdr_v2->csf = 0;
> +
> +		header_size_ptr = &hdr_v2->boot_data.size;
> +		csf_ptr = &fhdr_v2->csf;
> +	} else {
> +		imx_header_v2_t *next_hdr_v2;
> +		flash_header_v2_t *next_fhdr_v2;
> +
> +		if(imximage_csf_size != 0) {
> +			fprintf(stderr, "Error: Header v2: SECURE_BOOT"
> +					"is only supported in DCD mode!");
> +			exit(EXIT_FAILURE);
> +		}
> +
> +		fhdr_v2->entry = imximage_iram_free_start +
> +			flash_offset + sizeof(flash_header_v2_t) +
> +			sizeof(boot_data_t);
> +
> +		fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
> +		fhdr_v2->self = imximage_iram_free_start + flash_offset;
> +
> +		fhdr_v2->dcd_ptr = 0;
> +
> +		fhdr_v2->boot_data_ptr = fhdr_v2->self +
> +				offsetof(imx_header_v2_t, boot_data);
>  
> -	fhdr_v2->csf = 0;
> +		hdr_v2->boot_data.start = imximage_iram_free_start;
> +		/*
> +		 * The actural size of plugin image is "imximage_plugin_size +
> +		 * sizeof(flash_header_v2_t) + sizeof(boot_data_t)", plus the
> +		 * flash_offset space.The ROM code only need to copy this size
> +		 * to run the plugin code. However, later when copy the whole
> +		 * U-Boot image to DDR, the ROM code use memcpy to copy the
> +		 * first part of the image, and use the storage read function
> +		 * to get the remaining part. This requires the dividing point
> +		 * must be multiple of storage sector size. Here we set the
> +		 * first section to be 16KB for this purpose.
> +		 */
> +		hdr_v2->boot_data.size = MAX_PLUGIN_CODE_SIZE;
> +
> +		/* Security feature are not supported */
> +		fhdr_v2->csf = 0;
> +
> +		next_hdr_v2 = (imx_header_v2_t *)((char*)hdr_v2 +
> +				imximage_plugin_size);
> +
> +		next_fhdr_v2 = &next_hdr_v2->fhdr;
> +
> +		next_fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
> +		next_fhdr_v2->header.length =
> +			cpu_to_be16(sizeof(flash_header_v2_t));
> +		next_fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
>  
> -	header_size_ptr = &hdr_v2->boot_data.size;
> -	csf_ptr = &fhdr_v2->csf;
> +		next_fhdr_v2->entry = entry_point;
> +		hdr_base = entry_point - sizeof(struct imx_header);
> +		next_fhdr_v2->reserved1 = next_fhdr_v2->reserved2 = 0;
> +		next_fhdr_v2->self = hdr_base + imximage_plugin_size;
> +
> +		next_fhdr_v2->dcd_ptr = 0;
> +		next_fhdr_v2->boot_data_ptr = next_fhdr_v2->self +
> +				offsetof(imx_header_v2_t, boot_data);
> +
> +		next_hdr_v2->boot_data.start = hdr_base - flash_offset;
> +
> +		header_size_ptr = &next_hdr_v2->boot_data.size;
> +
> +		next_hdr_v2->boot_data.plugin = 0;
> +
> +		next_fhdr_v2->csf = 0;
> +	}
>  }
>  
>  static void set_hdr_func(void)
> @@ -312,16 +390,19 @@ static void print_hdr_v2(struct imx_header *imx_hdr)
>  {
>  	imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
>  	flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
> -	dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table;
> -	uint32_t size, version;
> +	dcd_v2_t *dcd_v2 = &hdr_v2->data.dcd_table;
> +	uint32_t size, version, plugin;
>  
> -	size = be16_to_cpu(dcd_v2->header.length) - 8;
> -	if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) {
> +	plugin = hdr_v2->boot_data.plugin;
> +	if (!plugin) {
> +		size = be16_to_cpu(dcd_v2->header.length) - 8;
> +		if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) {
>  		fprintf(stderr,
>  			"Error: Image corrupt DCD size %d exceed maximum %d\n",
>  			(uint32_t)(size / sizeof(dcd_addr_data_t)),
>  			MAX_HW_CFG_SIZE_V2);
>  		exit(EXIT_FAILURE);
> +		}
>  	}
>  
>  	version = detect_imximage_version(imx_hdr);
> @@ -329,18 +410,82 @@ static void print_hdr_v2(struct imx_header *imx_hdr)
>  	printf("Image Type:   Freescale IMX Boot Image\n");
>  	printf("Image Ver:    %x", version);
>  	printf("%s\n", get_table_entry_name(imximage_versions, NULL, version));
> -	printf("Data Size:    ");
> -	genimg_print_size(hdr_v2->boot_data.size);
> -	printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr);
> -	printf("Entry Point:  %08x\n", (uint32_t)fhdr_v2->entry);
> -	if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) &&
> -	    (imximage_csf_size != UNDEFINED)) {
> -		printf("HAB Blocks:   %08x %08x %08x\n",
> -		       (uint32_t)fhdr_v2->self, 0,
> -		       hdr_v2->boot_data.size - imximage_ivt_offset -
> -		       imximage_csf_size);
> +	printf("Mode:         %s\n", plugin ? "PLUGIN" : "DCD");
> +	if (!plugin) {
> +		printf("Data Size:    ");
> +		genimg_print_size(hdr_v2->boot_data.size);
> +		printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr);
> +		printf("Entry Point:  %08x\n", (uint32_t)fhdr_v2->entry);
> +		if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) &&
> +		    (imximage_csf_size != UNDEFINED)) {
> +			printf("HAB Blocks:   %08x %08x %08x\n",
> +			       (uint32_t)fhdr_v2->self, 0,
> +			       hdr_v2->boot_data.size - imximage_ivt_offset -
> +			       imximage_csf_size);
> +		}
> +	} else {
> +		imx_header_v2_t *next_hdr_v2;
> +		flash_header_v2_t *next_fhdr_v2;
> +
> +		/*First Header*/
> +		printf("Plugin Data Size:     ");
> +		genimg_print_size(hdr_v2->boot_data.size);
> +		printf("Plugin Code Size:     ");
> +		genimg_print_size(imximage_plugin_size);
> +		printf("Plugin Load Address:  %08x\n", hdr_v2->boot_data.start);
> +		printf("Plugin Entry Point:   %08x\n",
> +				(uint32_t)fhdr_v2->entry);
> +
> +		/*Second Header*/
> +		next_hdr_v2 = (imx_header_v2_t *)((char*)hdr_v2 +
> +				imximage_plugin_size);
> +		next_fhdr_v2 = &next_hdr_v2->fhdr;
> +		printf("U-Boot Data Size:     ");
> +		genimg_print_size(next_hdr_v2->boot_data.size);
> +		printf("U-Boot Load Address:  %08x\n", next_hdr_v2->boot_data.start);
> +		printf("U-Boot Entry Point:   %08x\n",
> +				(uint32_t)next_fhdr_v2->entry);
> +	}
> +}
> +
> +#ifdef CONFIG_USE_PLUGIN
> +static void copy_plugin_code(struct imx_header *imxhdr, char *plugin_file)
> +{
> +	int ifd = -1;
> +	struct stat sbuf;
> +	char *plugin_buf = imxhdr->header.hdr_v2.data.plugin_code;
> +	char *ptr;
> +
> +	ifd = open(plugin_file, O_RDONLY|O_BINARY);
> +	if (fstat(ifd, &sbuf) < 0) {
> +		fprintf(stderr, "Can't stat %s: %s\n",
> +			plugin_file,
> +			strerror(errno));
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
> +	if (ptr == MAP_FAILED) {
> +		fprintf(stderr, "Can't read %s: %s\n",
> +			plugin_file,
> +			strerror(errno));
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	if (sbuf.st_size > MAX_PLUGIN_CODE_SIZE) {
> +		printf("plugin binary size too large\n");
> +		exit(EXIT_FAILURE);
>  	}
> +
> +	memcpy(plugin_buf, ptr, sbuf.st_size);
> +	imximage_plugin_size = sbuf.st_size;
> +
> +	(void) munmap((void *)ptr, sbuf.st_size);
> +	(void) close(ifd);
> +
> +	imxhdr->header.hdr_v2.boot_data.plugin = 1;
>  }
> +#endif
>  
>  static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token,
>  				char *name, int lineno, int fld, int dcd_len)
> @@ -411,6 +556,11 @@ static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token,
>  		if (unlikely(cmd_ver_first != 1))
>  			cmd_ver_first = 0;
>  		break;
> +#ifdef CONFIG_USE_PLUGIN
> +	case CMD_PLUGIN:
> +		copy_plugin_code(imxhdr, token);
> +		break;
> +#endif
>  	}
>  }
>  
> @@ -434,20 +584,31 @@ static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd,
>  		break;
>  	case CFG_REG_ADDRESS:
>  	case CFG_REG_VALUE:
> -		if (*cmd != CMD_DATA)
> -			return;
> -
> -		value = get_cfg_value(token, name, lineno);
> -		(*set_dcd_val)(imxhdr, 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);
> +		switch (*cmd) {
> +		case CMD_DATA:
> +			value = get_cfg_value(token, name, lineno);
> +			(*set_dcd_val)(imxhdr, 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);
> +				}
>  			}
> +			break;
> +#ifdef CONFIG_USE_PLUGIN
> +		case CMD_PLUGIN:
> +			value = get_cfg_value(token, name, lineno);
> +			imximage_iram_free_start = value;
> +			break;
> +#endif
> +		default:
> +			return;
>  		}
>  		break;
>  	default:
> diff --git a/tools/imximage.h b/tools/imximage.h
> index 5b5ad0e..ef41d52 100644
> --- a/tools/imximage.h
> +++ b/tools/imximage.h
> @@ -8,7 +8,9 @@
>  #ifndef _IMXIMAGE_H_
>  #define _IMXIMAGE_H_
>  
> +#include <config.h>
>  #define MAX_HW_CFG_SIZE_V2 220 /* Max number of registers imx can set for v2 */
> +#define MAX_PLUGIN_CODE_SIZE (16*1024)
>  #define MAX_HW_CFG_SIZE_V1 60  /* Max number of registers imx can set for v1 */
>  #define APP_CODE_BARKER	0xB1
>  #define DCD_BARKER	0xB17219E9
> @@ -54,6 +56,7 @@ enum imximage_cmd {
>  	CMD_BOOT_OFFSET,
>  	CMD_DATA,
>  	CMD_CSF,
> +	CMD_PLUGIN,
>  };
>  
>  enum imximage_fld_types {
> @@ -149,7 +152,12 @@ typedef struct {
>  typedef struct {
>  	flash_header_v2_t fhdr;
>  	boot_data_t boot_data;
> -	dcd_v2_t dcd_table;
> +	union {
> +		dcd_v2_t dcd_table;
> +#ifdef CONFIG_USE_PLUGIN
> +		char plugin_code[MAX_PLUGIN_CODE_SIZE];
> +#endif
> +	} data;
>  } imx_header_v2_t;
>  
>  /* The header must be aligned to 4k on MX53 for NAND boot */
> 


-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================


More information about the U-Boot mailing list