From 85acf83a09583e472538c23c6a2d23176135485f Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Thu, 4 Jan 2024 18:50:06 +0000 Subject: tools: zynqmpimage: show info on partition 0 The zynqmpimage_print_header() skips printing the first partition. This is because the image header can contain duplicate fields as the first partition. However some fields, like the partition attributes, are only present in the partition table. It is also possible for the first partition to not be declared in the image header, if the image is not a bootloader image. Signed-off-by: Brandon Maier Link: https://lore.kernel.org/r/20240104185258.39465-1-brandon.maier@collins.com Signed-off-by: Michal Simek --- tools/zynqmpimage.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index bb54f41..05af1e8 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -262,9 +262,7 @@ void zynqmpimage_print_header(const void *ptr, struct image_tool_params *params) for (i = 0; i < le32_to_cpu(iht->nr_parts); i++) { next = le32_to_cpu(ph->next_partition_offset) * 4; - /* Partition 0 is the base image itself */ - if (i) - print_partition(ptr, ph); + print_partition(ptr, ph); ph = (void *)ptr + next; } -- cgit v1.1 From 2ddd0248e9cc8bf1da7c3d42c0bab1f65e859913 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Thu, 4 Jan 2024 18:50:07 +0000 Subject: tools: zynqmpimage: print all partition sizes Two of the partition size fields are not printed. Currently only the "total" size is displayed, which is the size of the image data (encrypted), padding, expansion, and authentication data. Add the "unencrypted data" size, which is the original size of the data before being encrypted. And "encrypted data" size, which is just the encrypted data. To avoid printing useless information, only print the encrypted and unencrypted sizes if they are different from the total. Signed-off-by: Brandon Maier Link: https://lore.kernel.org/r/20240104185258.39465-2-brandon.maier@collins.com Signed-off-by: Michal Simek --- tools/zynqmpimage.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools') diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index 05af1e8..2795a2b 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -139,6 +139,8 @@ static void print_partition(const void *ptr, const struct partition_header *ph) { uint32_t attr = le32_to_cpu(ph->attributes); unsigned long len = le32_to_cpu(ph->len) * 4; + unsigned long len_enc = le32_to_cpu(ph->len_enc) * 4; + unsigned long len_unenc = le32_to_cpu(ph->len_unenc) * 4; const char *part_owner; const char *dest_devs[0x8] = { "none", "PS", "PL", "PMU", "unknown", "unknown", "unknown", @@ -163,6 +165,10 @@ static void print_partition(const void *ptr, const struct partition_header *ph) printf(" Offset : 0x%08x\n", le32_to_cpu(ph->offset) * 4); printf(" Size : %lu (0x%lx) bytes\n", len, len); + if (len != len_unenc) + printf(" Size Data : %lu (0x%lx) bytes\n", len_unenc, len_unenc); + if (len_unenc != len_enc) + printf(" Size Enc : %lu (0x%lx) bytes\n", len_unenc, len_unenc); printf(" Load : 0x%08llx", (unsigned long long)le64_to_cpu(ph->load_address)); if (ph->load_address != ph->entry_point) -- cgit v1.1 From d47935b35fc1126f59b6ddde36597948afbfa66e Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Thu, 4 Jan 2024 18:50:08 +0000 Subject: tools: zynqmpimage: add partition extracting Extract partitions from a Xilinx Boot Image using dumpimage. Add helper for_each_zynqmp_part() to reuse the partition walking code between the printing and extracting functions. Signed-off-by: Brandon Maier Link: https://lore.kernel.org/r/20240104185258.39465-3-brandon.maier@collins.com Signed-off-by: Michal Simek --- tools/zynqmpimage.c | 57 ++++++++++++++++++++++++++++++++++------------------ tools/zynqmpimage.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 19 deletions(-) (limited to 'tools') diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index 2795a2b..307edd6 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -218,6 +218,7 @@ static void print_partition(const void *ptr, const struct partition_header *ph) void zynqmpimage_print_header(const void *ptr, struct image_tool_params *params) { struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr; + struct partition_header *ph; int i; printf("Image Type : Xilinx ZynqMP Boot Image support\n"); @@ -255,23 +256,8 @@ void zynqmpimage_print_header(const void *ptr, struct image_tool_params *params) le32_to_cpu(zynqhdr->register_init[i].data)); } - if (zynqhdr->image_header_table_offset) { - struct image_header_table *iht = (void *)ptr + - zynqhdr->image_header_table_offset; - struct partition_header *ph; - uint32_t ph_offset; - uint32_t next; - int i; - - ph_offset = le32_to_cpu(iht->partition_header_offset) * 4; - ph = (void *)ptr + ph_offset; - for (i = 0; i < le32_to_cpu(iht->nr_parts); i++) { - next = le32_to_cpu(ph->next_partition_offset) * 4; - - print_partition(ptr, ph); - - ph = (void *)ptr + next; - } + for_each_zynqmp_part(zynqhdr, i, ph) { + print_partition(ptr, ph); } free(dynamic_header); @@ -296,7 +282,7 @@ static int zynqmpimage_check_params(struct image_tool_params *params) return -1; } - return !(params->lflag || params->dflag); + return !(params->lflag || params->dflag || params->outfile); } static int zynqmpimage_check_image_types(uint8_t type) @@ -431,6 +417,39 @@ static void zynqmpimage_set_header(void *ptr, struct stat *sbuf, int ifd, zynqhdr->checksum = zynqmpimage_checksum(zynqhdr); } +static int zynqmpimage_partition_extract(struct zynqmp_header *zynqhdr, + const struct partition_header *ph, + const char *filename) +{ + ulong data = (ulong)zynqmp_get_offset(zynqhdr, ph->offset); + unsigned long len = le32_to_cpu(ph->len_enc) * 4; + + return imagetool_save_subimage(filename, data, len); +} + +/** + * zynqmpimage_extract_contents - retrieve a sub-image component from the image + * @ptr: pointer to the image header + * @params: command line parameters + * + * returns: + * zero in case of success or a negative value if fail. + */ +static int zynqmpimage_extract_contents(void *ptr, struct image_tool_params *params) +{ + struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr; + struct partition_header *ph; + int i; + + for_each_zynqmp_part(zynqhdr, i, ph) { + if (i == params->pflag) + return zynqmpimage_partition_extract(ptr, ph, params->outfile); + } + + printf("No partition found\n"); + return -1; +} + static int zynqmpimage_vrec_header(struct image_tool_params *params, struct image_type_params *tparams) { @@ -484,7 +503,7 @@ U_BOOT_IMAGE_TYPE( zynqmpimage_verify_header, zynqmpimage_print_header, zynqmpimage_set_header, - NULL, + zynqmpimage_extract_contents, zynqmpimage_check_image_types, NULL, zynqmpimage_vrec_header diff --git a/tools/zynqmpimage.h b/tools/zynqmpimage.h index ca74898..32be0d1 100644 --- a/tools/zynqmpimage.h +++ b/tools/zynqmpimage.h @@ -135,4 +135,62 @@ struct zynqmp_header { void zynqmpimage_default_header(struct zynqmp_header *ptr); void zynqmpimage_print_header(const void *ptr, struct image_tool_params *params); +static inline struct image_header_table * +zynqmp_get_iht(const struct zynqmp_header *zynqhdr) +{ + if (!zynqhdr->image_header_table_offset) + return NULL; + return (struct image_header_table *)((void *)zynqhdr + zynqhdr->image_header_table_offset); +} + +static inline void *zynqmp_get_offset(const struct zynqmp_header *zynqhdr, + uint32_t offset) +{ + uint32_t offset_cpu = le32_to_cpu(offset); + + if (!offset_cpu) + return NULL; + return (void *)zynqhdr + offset_cpu * 4; +} + +static inline struct partition_header * +zynqmp_part_first(const struct zynqmp_header *zynqhdr) +{ + struct image_header_table *iht; + + iht = zynqmp_get_iht(zynqhdr); + if (!iht) + return NULL; + + return zynqmp_get_offset(zynqhdr, iht->partition_header_offset); +} + +static inline struct partition_header * +zynqmp_part_next(const struct zynqmp_header *zynqhdr, + const struct partition_header *ph) +{ + return zynqmp_get_offset(zynqhdr, ph->next_partition_offset); +} + +static inline size_t zynqmp_part_count(const struct zynqmp_header *zynqhdr) +{ + struct image_header_table *iht; + + iht = zynqmp_get_iht(zynqhdr); + if (!iht) + return 0; + + return le32_to_cpu(iht->nr_parts); +} + +#define _for_each_zynqmp_part(_zynqhdr, _iter, _ph, _start, _count) \ + for (_iter = 0, _ph = _start; \ + _iter < (_count) && _ph; \ + _iter++, _ph = zynqmp_part_next(_zynqhdr, _ph)) + +#define for_each_zynqmp_part(_zynqhdr, _iter, _ph) \ + _for_each_zynqmp_part(_zynqhdr, _iter, _ph, \ + zynqmp_part_first(_zynqhdr), \ + zynqmp_part_count(_zynqhdr)) + #endif /* _ZYNQMPIMAGE_H_ */ -- cgit v1.1 From c9190693b052036cf9fac5f48d80f24d06a268fc Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Thu, 4 Jan 2024 18:50:09 +0000 Subject: tools: zynqmpimage: print partition names Each partition may belong to an image, which has a name. That name can be useful for debugging as it helps identify where the partition came from. Signed-off-by: Brandon Maier Link: https://lore.kernel.org/r/20240104185258.39465-4-brandon.maier@collins.com Signed-off-by: Michal Simek --- tools/zynqmpimage.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/zynqmpimage.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) (limited to 'tools') diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index 307edd6..4db9877 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -135,6 +135,53 @@ static int zynqmpimage_verify_header(unsigned char *ptr, int image_size, return 0; } +static struct image_header * +find_partition_image(const struct zynqmp_header *zynqhdr, + const struct partition_header *ph) +{ + struct partition_header *ph_walk; + struct image_header *ih; + int i; + + for_each_zynqmp_image(zynqhdr, ih) { + for_each_zynqmp_part_in_image(zynqhdr, i, ph_walk, ih) { + if (ph == ph_walk) + return ih; + } + } + + return NULL; +} + +static void print_partition_name(const struct zynqmp_header *zynqhdr, + const struct partition_header *ph) +{ + const struct image_header *ih; + size_t word_len; + char *name; + int i; + + ih = find_partition_image(zynqhdr, ph); + if (!ih) + return; + + /* Name is stored in big-endian words, find the terminating word and + * byte-swap into a new buffer + */ + word_len = strlen((char *)ih->image_name); + word_len = ALIGN(word_len + 1, 4); + + name = calloc(1, word_len); + if (!name) + return; + + for (i = 0; i < word_len / 4; i++) + ((uint32_t *)name)[i] = uswap_32(ih->image_name[i]); + + printf(" Image name : %s\n", name); + free(name); +} + static void print_partition(const void *ptr, const struct partition_header *ph) { uint32_t attr = le32_to_cpu(ph->attributes); @@ -163,6 +210,7 @@ static void print_partition(const void *ptr, const struct partition_header *ph) dest_cpus[(attr & PART_ATTR_DEST_CPU_MASK) >> 8], dest_devs[(attr & PART_ATTR_DEST_DEVICE_MASK) >> 4]); + print_partition_name(ptr, ph); printf(" Offset : 0x%08x\n", le32_to_cpu(ph->offset) * 4); printf(" Size : %lu (0x%lx) bytes\n", len, len); if (len != len_unenc) diff --git a/tools/zynqmpimage.h b/tools/zynqmpimage.h index 32be0d1..7c47dc0 100644 --- a/tools/zynqmpimage.h +++ b/tools/zynqmpimage.h @@ -51,6 +51,14 @@ struct image_header_table { uint32_t checksum; /* 0x3c */ }; +struct image_header { + uint32_t next_image_header_offset; /* 0x00 */ + uint32_t corresponding_partition_header; /* 0x04 */ + uint32_t __reserved1; /* 0x08 */ + uint32_t partition_count; /* 0x0c */ + uint32_t image_name[]; /* 0x10 */ +}; + #define PART_ATTR_VEC_LOCATION 0x800000 #define PART_ATTR_BS_BLOCK_SIZE_MASK 0x700000 #define PART_ATTR_BS_BLOCK_SIZE_DEFAULT 0x000000 @@ -193,4 +201,45 @@ static inline size_t zynqmp_part_count(const struct zynqmp_header *zynqhdr) zynqmp_part_first(_zynqhdr), \ zynqmp_part_count(_zynqhdr)) +static inline struct partition_header * +zynqmp_part_in_image_first(const struct zynqmp_header *zynqhdr, + const struct image_header *ih) +{ + return zynqmp_get_offset(zynqhdr, ih->corresponding_partition_header); +} + +static inline size_t zynqmp_part_in_image_count(const struct image_header *ih) +{ + return le32_to_cpu(ih->partition_count); +} + +#define for_each_zynqmp_part_in_image(_zynqhdr, _iter, _ph, _ih) \ + _for_each_zynqmp_part(_zynqhdr, _iter, _ph, \ + zynqmp_part_in_image_first(_zynqhdr, _ih), \ + zynqmp_part_in_image_count(_ih)) + +static inline struct image_header * +zynqmp_image_first(const struct zynqmp_header *zynqhdr) +{ + struct image_header_table *iht; + + iht = zynqmp_get_iht(zynqhdr); + if (!iht) + return NULL; + + return zynqmp_get_offset(zynqhdr, iht->image_header_offset); +} + +static inline struct image_header * +zynqmp_image_next(const struct zynqmp_header *zynqhdr, + const struct image_header *ih) +{ + return zynqmp_get_offset(zynqhdr, ih->next_image_header_offset); +} + +#define for_each_zynqmp_image(_zynqhdr, _ih) \ + for (_ih = zynqmp_image_first(_zynqhdr); \ + _ih; \ + _ih = zynqmp_image_next(_zynqhdr, _ih)) + #endif /* _ZYNQMPIMAGE_H_ */ -- cgit v1.1