diff mbox series

[3/4] tools: zynqmpimage: add partition extracting

Message ID 20240104185258.39465-3-brandon.maier@collins.com
State Accepted
Commit d47935b35fc1126f59b6ddde36597948afbfa66e
Delegated to: Michal Simek
Headers show
Series [1/4] tools: zynqmpimage: show info on partition 0 | expand

Commit Message

Brandon Maier Jan. 4, 2024, 6:50 p.m. UTC
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 <brandon.maier@collins.com>
---

 tools/zynqmpimage.c | 57 +++++++++++++++++++++++++++++---------------
 tools/zynqmpimage.h | 58 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
index 2795a2b9a77..307edd63ebb 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 ca7489835a8..32be0d125fd 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_ */