[PATCH u-boot-marvell v2 3/7] tools: kwbimage: Add support for dumping extended and binary v0 headers

Stefan Roese sr at denx.de
Thu Feb 17 11:57:50 CET 2022


On 2/17/22 10:43, Pali Rohár wrote:
> dumpimage is now able to successfully parse and dump content of the Dove
> bootloader image.
> 
> Note that support for generating these extended parts of v0 images is not
> included yet.
> 
> Signed-off-by: Pali Rohár <pali at kernel.org>
> Tested-by: Tony Dinh <mibodhi at gmail.com>
> 
> --
> Changes in v2:
> * Implement custom function fls4() as it is not possible to use U-Boot's
>    fls() from asm-generic/bitsops/fls.h file when compling for Mac or Win.

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan

> ---
>   tools/kwbimage.c | 140 +++++++++++++++++++++++++++++++++++++++++++----
>   tools/kwbimage.h |  51 +++++++++++++++++
>   2 files changed, 179 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/kwbimage.c b/tools/kwbimage.c
> index 99d38cd1cfb2..5a717e5354bf 100644
> --- a/tools/kwbimage.c
> +++ b/tools/kwbimage.c
> @@ -43,6 +43,21 @@ void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
>   }
>   #endif
>   
> +/* fls - find last (most-significant) bit set in 4-bit integer */
> +static inline int fls4(int num)
> +{
> +	if (num & 0x8)
> +		return 4;
> +	else if (num & 0x4)
> +		return 3;
> +	else if (num & 0x2)
> +		return 2;
> +	else if (num & 0x1)
> +		return 1;
> +	else
> +		return 0;
> +}
> +
>   static struct image_cfg_element *image_cfg;
>   static int cfgn;
>   static int verbose_mode;
> @@ -1898,6 +1913,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
>   static void kwbimage_print_header(const void *ptr)
>   {
>   	struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
> +	struct bin_hdr_v0 *bhdr;
>   	struct opt_hdr_v1 *ohdr;
>   
>   	printf("Image Type:   MVEBU Boot from %s Image\n",
> @@ -1915,6 +1931,13 @@ static void kwbimage_print_header(const void *ptr)
>   		}
>   	}
>   
> +	for_each_bin_hdr_v0(bhdr, mhdr) {
> +		printf("BIN Img Size: ");
> +		genimg_print_size(le32_to_cpu(bhdr->size));
> +		printf("BIN Img Addr: %08x\n", le32_to_cpu(bhdr->destaddr));
> +		printf("BIN Img Entr: %08x\n", le32_to_cpu(bhdr->execaddr));
> +	}
> +
>   	printf("Data Size:    ");
>   	genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
>   	printf("Load Address: %08x\n", mhdr->destaddr);
> @@ -1947,15 +1970,31 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
>   	/* Only version 0 extended header has checksum */
>   	if (kwbimage_version(ptr) == 0) {
>   		struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
> +		struct ext_hdr_v0 *ext_hdr;
> +		struct bin_hdr_v0 *bhdr;
>   
> -		if (mhdr->ext) {
> -			struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1);
> -
> +		for_each_ext_hdr_v0(ext_hdr, ptr) {
>   			csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1);
>   			if (csum != ext_hdr->checksum)
>   				return -FDT_ERR_BADSTRUCTURE;
>   		}
>   
> +		for_each_bin_hdr_v0(bhdr, ptr) {
> +			csum = image_checksum8(bhdr, (uint8_t *)&bhdr->checksum - (uint8_t *)bhdr - 1);
> +			if (csum != bhdr->checksum)
> +				return -FDT_ERR_BADSTRUCTURE;
> +
> +			if (bhdr->offset > sizeof(*bhdr) || bhdr->offset % 4 != 0)
> +				return -FDT_ERR_BADSTRUCTURE;
> +
> +			if (bhdr->offset + bhdr->size + 4 > sizeof(*bhdr) || bhdr->size % 4 != 0)
> +				return -FDT_ERR_BADSTRUCTURE;
> +
> +			if (image_checksum32((uint8_t *)bhdr + bhdr->offset, bhdr->size) !=
> +			    *(uint32_t *)((uint8_t *)bhdr + bhdr->offset + bhdr->size))
> +				return -FDT_ERR_BADSTRUCTURE;
> +		}
> +
>   		blockid = mhdr->blockid;
>   		offset = le32_to_cpu(mhdr->srcaddr);
>   		size = le32_to_cpu(mhdr->blocksize);
> @@ -2130,8 +2169,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
>   	struct register_set_hdr_v1 *regset_hdr;
>   	struct ext_hdr_v0_reg *regdata;
>   	struct ext_hdr_v0 *ehdr0;
> +	struct bin_hdr_v0 *bhdr0;
>   	struct opt_hdr_v1 *ohdr;
> +	int params_count;
>   	unsigned offset;
> +	int is_v0_ext;
>   	int cur_idx;
>   	int version;
>   	FILE *f;
> @@ -2145,6 +2187,14 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
>   
>   	version = kwbimage_version(ptr);
>   
> +	is_v0_ext = 0;
> +	if (version == 0) {
> +		if (mhdr0->ext > 1 || mhdr0->bin ||
> +		    ((ehdr0 = ext_hdr_v0_first(ptr)) &&
> +		     (ehdr0->match_addr || ehdr0->match_mask || ehdr0->match_value)))
> +			is_v0_ext = 1;
> +	}
> +
>   	if (version != 0)
>   		fprintf(f, "VERSION %d\n", version);
>   
> @@ -2156,10 +2206,11 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
>   	if (mhdr->blockid == IBR_HDR_NAND_ID)
>   		fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
>   
> -	if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) {
> +	if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID)
>   		fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize);
> +
> +	if (mhdr->blockid == IBR_HDR_NAND_ID && (mhdr->nandbadblklocation != 0 || is_v0_ext))
>   		fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation);
> -	}
>   
>   	if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID)
>   		fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode);
> @@ -2222,8 +2273,39 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
>   		}
>   	}
>   
> -	if (version == 0 && mhdr0->ext) {
> -		ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1);
> +	if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay))
> +		fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
> +
> +	for_each_ext_hdr_v0(ehdr0, ptr) {
> +		if (is_v0_ext) {
> +			fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
> +				le32_to_cpu(ehdr0->match_addr),
> +				le32_to_cpu(ehdr0->match_mask),
> +				le32_to_cpu(ehdr0->match_value));
> +			if (ehdr0->rsvd1[0] || ehdr0->rsvd1[1] || ehdr0->rsvd1[2] ||
> +			    ehdr0->rsvd1[3] || ehdr0->rsvd1[4] || ehdr0->rsvd1[5] ||
> +			    ehdr0->rsvd1[6] || ehdr0->rsvd1[7])
> +				fprintf(f, "#DDR_RSVD1 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
> +					ehdr0->rsvd1[0], ehdr0->rsvd1[1], ehdr0->rsvd1[2],
> +					ehdr0->rsvd1[3], ehdr0->rsvd1[4], ehdr0->rsvd1[5],
> +					ehdr0->rsvd1[6], ehdr0->rsvd1[7]);
> +			if (ehdr0->rsvd2[0] || ehdr0->rsvd2[1] || ehdr0->rsvd2[2] ||
> +			    ehdr0->rsvd2[3] || ehdr0->rsvd2[4] || ehdr0->rsvd2[5] ||
> +			    ehdr0->rsvd2[6])
> +				fprintf(f, "#DDR_RSVD2 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
> +					ehdr0->rsvd2[0], ehdr0->rsvd2[1], ehdr0->rsvd2[2],
> +					ehdr0->rsvd2[3], ehdr0->rsvd2[4], ehdr0->rsvd2[5],
> +					ehdr0->rsvd2[6]);
> +			if (ehdr0->ddrwritetype)
> +				fprintf(f, "DDR_WRITE_TYPE %u\n", (unsigned)ehdr0->ddrwritetype);
> +			if (ehdr0->ddrresetmpp)
> +				fprintf(f, "DDR_RESET_MPP 0x%x\n", (unsigned)ehdr0->ddrresetmpp);
> +			if (ehdr0->ddrclkenmpp)
> +				fprintf(f, "DDR_CLKEN_MPP 0x%x\n", (unsigned)ehdr0->ddrclkenmpp);
> +			if (ehdr0->ddrinitdelay)
> +				fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)ehdr0->ddrinitdelay);
> +		}
> +
>   		if (ehdr0->offset) {
>   			for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset);
>   			     (uint8_t *)regdata < (uint8_t *)ptr + header_size &&
> @@ -2234,10 +2316,38 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
>   			if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset)
>   				fprintf(f, "DATA 0x0 0x0\n");
>   		}
> +
> +		if (le32_to_cpu(ehdr0->enddelay))
> +			fprintf(f, "DATA_DELAY %u\n", le32_to_cpu(ehdr0->enddelay));
> +		else if (is_v0_ext)
> +			fprintf(f, "DATA_DELAY SDRAM_SETUP\n");
>   	}
>   
> -	if (version == 0 && le16_to_cpu(mhdr0->ddrinitdelay))
> -		fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
> +	cur_idx = 1;
> +	for_each_bin_hdr_v0(bhdr0, ptr) {
> +		fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
> +			le32_to_cpu(bhdr0->match_addr),
> +			le32_to_cpu(bhdr0->match_mask),
> +			le32_to_cpu(bhdr0->match_value));
> +
> +		fprintf(f, "BINARY binary%d.bin", cur_idx);
> +		params_count = fls4(bhdr0->params_flags & 0xF);
> +		for (i = 0; i < params_count; i++)
> +			fprintf(f, " 0x%x", (bhdr0->params[i] & (1 << i)) ? bhdr0->params[i] : 0);
> +		fprintf(f, " LOAD_ADDRESS 0x%08x", le32_to_cpu(bhdr0->destaddr));
> +		fprintf(f, " EXEC_ADDRESS 0x%08x", le32_to_cpu(bhdr0->execaddr));
> +		fprintf(f, "\n");
> +
> +		fprintf(f, "#BINARY_OFFSET 0x%x\n", le32_to_cpu(bhdr0->offset));
> +		fprintf(f, "#BINARY_SIZE 0x%x\n", le32_to_cpu(bhdr0->size));
> +
> +		if (bhdr0->rsvd1)
> +			fprintf(f, "#BINARY_RSVD1 0x%x\n", (unsigned)bhdr0->rsvd1);
> +		if (bhdr0->rsvd2)
> +			fprintf(f, "#BINARY_RSVD2 0x%x\n", (unsigned)bhdr0->rsvd2);
> +
> +		cur_idx++;
> +	}
>   
>   	/* Undocumented reserved fields */
>   
> @@ -2245,9 +2355,6 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
>   		fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0],
>   			(unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
>   
> -	if (version == 0 && mhdr0->rsvd3)
> -		fprintf(f, "#RSVD3 0x%x\n", (unsigned)mhdr0->rsvd3);
> -
>   	if (version == 0 && le16_to_cpu(mhdr0->rsvd2))
>   		fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
>   
> @@ -2266,6 +2373,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
>   {
>   	struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
>   	size_t header_size = kwbheader_size(ptr);
> +	struct bin_hdr_v0 *bhdr;
>   	struct opt_hdr_v1 *ohdr;
>   	int idx = params->pflag;
>   	int cur_idx;
> @@ -2312,6 +2420,14 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
>   
>   			++cur_idx;
>   		}
> +		for_each_bin_hdr_v0(bhdr, ptr) {
> +			if (idx == cur_idx) {
> +				image = (ulong)bhdr + bhdr->offset;
> +				size = bhdr->size;
> +				break;
> +			}
> +			++cur_idx;
> +		}
>   
>   		if (!image) {
>   			fprintf(stderr, "Argument -p %d is invalid\n", idx);
> diff --git a/tools/kwbimage.h b/tools/kwbimage.h
> index 502b6d503305..505522332bd4 100644
> --- a/tools/kwbimage.h
> +++ b/tools/kwbimage.h
> @@ -270,6 +270,57 @@ static inline size_t kwbheader_size_for_csum(const void *header)
>   		return kwbheader_size(header);
>   }
>   
> +static inline struct ext_hdr_v0 *ext_hdr_v0_first(void *img)
> +{
> +	struct main_hdr_v0 *mhdr;
> +
> +	if (kwbimage_version(img) != 0)
> +		return NULL;
> +
> +	mhdr = img;
> +	if (mhdr->ext)
> +		return (struct ext_hdr_v0 *)(mhdr + 1);
> +	else
> +		return NULL;
> +}
> +
> +static inline void *_ext_hdr_v0_end(struct main_hdr_v0 *mhdr)
> +{
> +	return (uint8_t *)mhdr + kwbheader_size(mhdr) - mhdr->bin * sizeof(struct bin_hdr_v0);
> +}
> +
> +static inline struct ext_hdr_v0 *ext_hdr_v0_next(void *img, struct ext_hdr_v0 *cur)
> +{
> +	if ((void *)(cur + 1) < _ext_hdr_v0_end(img))
> +		return (struct ext_hdr_v0 *)((uint8_t *)(cur + 1) + 0x20);
> +	else
> +		return NULL;
> +}
> +
> +#define for_each_ext_hdr_v0(ehdr, img)			\
> +	for ((ehdr) = ext_hdr_v0_first((img));		\
> +	     (ehdr) != NULL;				\
> +	     (ehdr) = ext_hdr_v0_next((img), (ehdr)))
> +
> +static inline struct bin_hdr_v0 *bin_hdr_v0_first(void *img)
> +{
> +	struct main_hdr_v0 *mhdr;
> +
> +	if (kwbimage_version(img) != 0)
> +		return NULL;
> +
> +	mhdr = img;
> +	if (mhdr->bin)
> +		return _ext_hdr_v0_end(mhdr);
> +	else
> +		return NULL;
> +}
> +
> +#define for_each_bin_hdr_v0(bhdr, img)							\
> +	for ((bhdr) = bin_hdr_v0_first((img));						\
> +	     (bhdr) && (void *)(bhdr) < (void *)((uint8_t *)img + kwbheader_size(img));	\
> +	     (bhdr) = (struct bin_hdr_v0 *)((bhdr))+1)
> +
>   static inline uint32_t opt_hdr_v1_size(const struct opt_hdr_v1 *ohdr)
>   {
>   	return (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb);

Viele Grüße,
Stefan Roese

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list