tools: kwbimage: Add support for dumping extended and binary v0 headers
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@kernel.org> Tested-by: Tony Dinh <mibodhi@gmail.com> Reviewed-by: Stefan Roese <sr@denx.de>
This commit is contained in:
parent
9a9a2c1acf
commit
f76ae2571f
140
tools/kwbimage.c
140
tools/kwbimage.c
@ -43,6 +43,21 @@ void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 struct image_cfg_element *image_cfg;
|
||||||
static int cfgn;
|
static int cfgn;
|
||||||
static int verbose_mode;
|
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)
|
static void kwbimage_print_header(const void *ptr)
|
||||||
{
|
{
|
||||||
struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
|
struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
|
||||||
|
struct bin_hdr_v0 *bhdr;
|
||||||
struct opt_hdr_v1 *ohdr;
|
struct opt_hdr_v1 *ohdr;
|
||||||
|
|
||||||
printf("Image Type: MVEBU Boot from %s Image\n",
|
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: ");
|
printf("Data Size: ");
|
||||||
genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
|
genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
|
||||||
printf("Load Address: %08x\n", mhdr->destaddr);
|
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 */
|
/* Only version 0 extended header has checksum */
|
||||||
if (kwbimage_version(ptr) == 0) {
|
if (kwbimage_version(ptr) == 0) {
|
||||||
struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
|
struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
|
||||||
|
struct ext_hdr_v0 *ext_hdr;
|
||||||
|
struct bin_hdr_v0 *bhdr;
|
||||||
|
|
||||||
if (mhdr->ext) {
|
for_each_ext_hdr_v0(ext_hdr, ptr) {
|
||||||
struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1);
|
|
||||||
|
|
||||||
csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1);
|
csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1);
|
||||||
if (csum != ext_hdr->checksum)
|
if (csum != ext_hdr->checksum)
|
||||||
return -FDT_ERR_BADSTRUCTURE;
|
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;
|
blockid = mhdr->blockid;
|
||||||
offset = le32_to_cpu(mhdr->srcaddr);
|
offset = le32_to_cpu(mhdr->srcaddr);
|
||||||
size = le32_to_cpu(mhdr->blocksize);
|
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 register_set_hdr_v1 *regset_hdr;
|
||||||
struct ext_hdr_v0_reg *regdata;
|
struct ext_hdr_v0_reg *regdata;
|
||||||
struct ext_hdr_v0 *ehdr0;
|
struct ext_hdr_v0 *ehdr0;
|
||||||
|
struct bin_hdr_v0 *bhdr0;
|
||||||
struct opt_hdr_v1 *ohdr;
|
struct opt_hdr_v1 *ohdr;
|
||||||
|
int params_count;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
|
int is_v0_ext;
|
||||||
int cur_idx;
|
int cur_idx;
|
||||||
int version;
|
int version;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
@ -2145,6 +2187,14 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
|
|||||||
|
|
||||||
version = kwbimage_version(ptr);
|
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)
|
if (version != 0)
|
||||||
fprintf(f, "VERSION %d\n", version);
|
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)
|
if (mhdr->blockid == IBR_HDR_NAND_ID)
|
||||||
fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
|
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);
|
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);
|
fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation);
|
||||||
}
|
|
||||||
|
|
||||||
if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID)
|
if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID)
|
||||||
fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode);
|
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) {
|
if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay))
|
||||||
ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1);
|
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) {
|
if (ehdr0->offset) {
|
||||||
for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset);
|
for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset);
|
||||||
(uint8_t *)regdata < (uint8_t *)ptr + header_size &&
|
(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)
|
if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset)
|
||||||
fprintf(f, "DATA 0x0 0x0\n");
|
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))
|
cur_idx = 1;
|
||||||
fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
|
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 */
|
/* 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],
|
fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0],
|
||||||
(unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
|
(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))
|
if (version == 0 && le16_to_cpu(mhdr0->rsvd2))
|
||||||
fprintf(f, "#RSVD2 0x%x\n", (unsigned)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;
|
struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
|
||||||
size_t header_size = kwbheader_size(ptr);
|
size_t header_size = kwbheader_size(ptr);
|
||||||
|
struct bin_hdr_v0 *bhdr;
|
||||||
struct opt_hdr_v1 *ohdr;
|
struct opt_hdr_v1 *ohdr;
|
||||||
int idx = params->pflag;
|
int idx = params->pflag;
|
||||||
int cur_idx;
|
int cur_idx;
|
||||||
@ -2312,6 +2420,14 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params
|
|||||||
|
|
||||||
++cur_idx;
|
++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) {
|
if (!image) {
|
||||||
fprintf(stderr, "Argument -p %d is invalid\n", idx);
|
fprintf(stderr, "Argument -p %d is invalid\n", idx);
|
||||||
|
@ -270,6 +270,57 @@ static inline size_t kwbheader_size_for_csum(const void *header)
|
|||||||
return kwbheader_size(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)
|
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);
|
return (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb);
|
||||||
|
Loading…
Reference in New Issue
Block a user