All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 0/3] tools: zynqmpimage: Support partitions
@ 2018-04-12 13:48 Alexander Graf
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support Alexander Graf
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Alexander Graf @ 2018-04-12 13:48 UTC (permalink / raw)
  To: u-boot

A good chunk of the booting chain of ZynqMP based systems is open source
(depending on your definition of it), except for the image generation flow.

This patch set aims to change that, with read and write support for boot.bin
partitions which allows us to create boot.bin files using only open source
tools.

v1 -> v2:

  - Add bif based generation
  - Add documentation pointer
  - Split definitions into separate header

v2 -> v3:

  - zero initialize header
  - reduce default debug verbosity

Alexander Graf (3):
  tools: zynqmpimage: Add partition read support
  tools: zynqmpimage: Move defines to header
  tools: zynqmpimage: Add bif support

 common/image.c      |   1 +
 include/image.h     |   1 +
 tools/Makefile      |   1 +
 tools/imagetool.h   |   1 +
 tools/mkimage.c     |   3 +
 tools/zynqmpbif.c   | 839 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/zynqmpimage.c | 141 ++++++---
 tools/zynqmpimage.h | 135 +++++++++
 8 files changed, 1080 insertions(+), 42 deletions(-)
 create mode 100644 tools/zynqmpbif.c
 create mode 100644 tools/zynqmpimage.h

-- 
2.12.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support
  2018-04-12 13:48 [U-Boot] [PATCH v3 0/3] tools: zynqmpimage: Support partitions Alexander Graf
@ 2018-04-12 13:48 ` Alexander Graf
  2018-04-13  9:40   ` Michal Simek
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 2/3] tools: zynqmpimage: Move defines to header Alexander Graf
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 3/3] tools: zynqmpimage: Add bif support Alexander Graf
  2 siblings, 1 reply; 6+ messages in thread
From: Alexander Graf @ 2018-04-12 13:48 UTC (permalink / raw)
  To: u-boot

The zynqmp image format has support for inline partitions which are
used by FSBL to describe payloads that are loaded by FSBL itself.

While we can't create images that contain partitions (yet), we should
still at least be able to examine them and show the user what's inside
when we analyze an image created by bootgen.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - prettify defines
  - fix offset and size outputs
  - add u-boot as payload target
  - align CPU names with bif
  - add shift constants
  - add U-Boot as potential partition owner
  - mention documentation source
  - add HEADER_CPU_SELECT_A53_64BIT define
---
 tools/zynqmpimage.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 172 insertions(+), 2 deletions(-)

diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
index a61fb17c40..8117913da3 100644
--- a/tools/zynqmpimage.c
+++ b/tools/zynqmpimage.c
@@ -7,6 +7,7 @@
  * The following Boot Header format/structures and values are defined in the
  * following documents:
  *   * ug1085 ZynqMP TRM doc v1.4 (Chapter 11, Table 11-4)
+ *   * ug1137 ZynqMP Software Developer Guide v6.0 (Chapter 16)
  *
  * Expected Header Size = 0x9C0
  * Forced as 'little' endian, 32-bit words
@@ -63,6 +64,7 @@
 #define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff))
 #define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566))
 #define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58))
+#define HEADER_CPU_SELECT_A53_64BIT	(0x2 << 10)
 
 enum {
 	ENCRYPTION_EFUSE = 0xa5c3c5a3,
@@ -80,6 +82,78 @@ struct zynqmp_reginit {
 #define HEADER_INTERRUPT_VECTORS	8
 #define HEADER_REGINITS			256
 
+struct image_header_table {
+	uint32_t version;		  /* 0x00 */
+	uint32_t nr_parts;		  /* 0x04 */
+	uint32_t partition_header_offset; /* 0x08, divided by 4 */
+	uint32_t image_header_offset;	  /* 0x0c, divided by 4 */
+	uint32_t auth_certificate_offset; /* 0x10 */
+	uint32_t boot_device;		  /* 0x14 */
+	uint32_t __reserved1[9];	  /* 0x18 - 0x38 */
+	uint32_t checksum;		  /* 0x3c */
+};
+
+#define PART_ATTR_VEC_LOCATION		0x800000
+#define PART_ATTR_BS_BLOCK_SIZE_MASK	0x700000
+#define     PART_ATTR_BS_BLOCK_SIZE_DEFAULT	0x000000
+#define     PART_ATTR_BS_BLOCK_SIZE_8MB		0x400000
+#define PART_ATTR_BIG_ENDIAN		0x040000
+#define PART_ATTR_PART_OWNER_MASK	0x030000
+#define     PART_ATTR_PART_OWNER_FSBL		0x000000
+#define     PART_ATTR_PART_OWNER_UBOOT		0x010000
+#define PART_ATTR_RSA_SIG		0x008000
+#define PART_ATTR_CHECKSUM_MASK		0x007000
+#define    PART_ATTR_CHECKSUM_NONE		0x000000
+#define    PART_ATTR_CHECKSUM_MD5		0x001000
+#define    PART_ATTR_CHECKSUM_SHA2		0x002000
+#define    PART_ATTR_CHECKSUM_SHA3		0x003000
+#define PART_ATTR_DEST_CPU_SHIFT	8
+#define PART_ATTR_DEST_CPU_MASK		0x000f00
+#define    PART_ATTR_DEST_CPU_NONE		0x000000
+#define    PART_ATTR_DEST_CPU_A53_0		0x000100
+#define    PART_ATTR_DEST_CPU_A53_1		0x000200
+#define    PART_ATTR_DEST_CPU_A53_2		0x000300
+#define    PART_ATTR_DEST_CPU_A53_3		0x000400
+#define    PART_ATTR_DEST_CPU_R5_0		0x000500
+#define    PART_ATTR_DEST_CPU_R5_1		0x000600
+#define    PART_ATTR_DEST_CPU_R5_L		0x000700
+#define    PART_ATTR_DEST_CPU_PMU		0x000800
+#define PART_ATTR_ENCRYPTED		0x000080
+#define PART_ATTR_DEST_DEVICE_SHIFT	4
+#define PART_ATTR_DEST_DEVICE_MASK	0x000070
+#define    PART_ATTR_DEST_DEVICE_NONE		0x000000
+#define    PART_ATTR_DEST_DEVICE_PS		0x000010
+#define    PART_ATTR_DEST_DEVICE_PL		0x000020
+#define    PART_ATTR_DEST_DEVICE_PMU		0x000030
+#define    PART_ATTR_DEST_DEVICE_XIP		0x000040
+#define PART_ATTR_A53_EXEC_AARCH32	0x000008
+#define PART_ATTR_TARGET_EL_SHIFT	1
+#define PART_ATTR_TARGET_EL_MASK	0x000006
+#define PART_ATTR_TZ_SECURE		0x000001
+
+static const char *dest_cpus[0x10] = {
+	"none", "a5x-0", "a5x-1", "a5x-2", "a5x-3", "r5-0", "r5-1",
+	"r5-lockstep", "pmu", "unknown", "unknown", "unknown", "unknown",
+	"unknown", "unknown", "unknown"
+};
+
+struct partition_header {
+	uint32_t len_enc;		  /* 0x00, divided by 4 */
+	uint32_t len_unenc;		  /* 0x04, divided by 4 */
+	uint32_t len;			  /* 0x08, divided by 4 */
+	uint32_t next_partition_offset;   /* 0x0c */
+	uint64_t entry_point;		  /* 0x10 */
+	uint64_t load_address;		  /* 0x18 */
+	uint32_t offset;		  /* 0x20, divided by 4 */
+	uint32_t attributes;		  /* 0x24 */
+	uint32_t __reserved1;		  /* 0x28 */
+	uint32_t checksum_offset;	  /* 0x2c, divided by 4 */
+	uint32_t __reserved2;		  /* 0x30 */
+	uint32_t auth_certificate_offset; /* 0x34 */
+	uint32_t __reserved3;		  /* 0x38 */
+	uint32_t checksum;		  /* 0x3c */
+};
+
 struct zynqmp_header {
 	uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */
 	uint32_t width_detection; /* 0x20 */
@@ -93,7 +167,9 @@ struct zynqmp_header {
 	uint32_t image_stored_size; /* 0x40 */
 	uint32_t image_attributes; /* 0x44 */
 	uint32_t checksum; /* 0x48 */
-	uint32_t __reserved1[27]; /* 0x4c */
+	uint32_t __reserved1[19]; /* 0x4c */
+	uint32_t image_header_table_offset; /* 0x98 */
+	uint32_t __reserved2[7]; /* 0x9c */
 	struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */
 	uint32_t __reserved4[66]; /* 0x9c0 */
 };
@@ -132,7 +208,7 @@ static void zynqmpimage_default_header(struct zynqmp_header *ptr)
 		return;
 
 	ptr->width_detection = HEADER_WIDTHDETECTION;
-	ptr->image_attributes = 0x800;
+	ptr->image_attributes = HEADER_CPU_SELECT_A53_64BIT;
 	ptr->image_identifier = HEADER_IMAGEIDENTIFIER;
 	ptr->encryption = cpu_to_le32(ENCRYPTION_NONE);
 
@@ -173,6 +249,81 @@ static int zynqmpimage_verify_header(unsigned char *ptr, int image_size,
 	return 0;
 }
 
+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;
+	const char *part_owner;
+	const char *dest_devs[0x8] = {
+		"none", "PS", "PL", "PMU", "unknown", "unknown", "unknown",
+		"unknown"
+	};
+
+	switch (attr & PART_ATTR_PART_OWNER_MASK) {
+	case PART_ATTR_PART_OWNER_FSBL:
+		part_owner = "FSBL";
+		break;
+	case PART_ATTR_PART_OWNER_UBOOT:
+		part_owner = "U-Boot";
+		break;
+	default:
+		part_owner = "Unknown";
+		break;
+	}
+
+	printf("%s payload on CPU %s (%s):\n",
+		part_owner,
+		dest_cpus[(attr & PART_ATTR_DEST_CPU_MASK) >> 8],
+		dest_devs[(attr & PART_ATTR_DEST_DEVICE_MASK) >> 4]);
+
+	printf("    Offset     : 0x%08x\n", le32_to_cpu(ph->offset) * 4);
+	printf("    Size       : %lu (0x%lx) bytes\n", len, len);
+	printf("    Load       : 0x%08llx",
+		(unsigned long long)le64_to_cpu(ph->load_address));
+	if (ph->load_address != ph->entry_point)
+		printf(" (entry=0x%08llx)\n",
+		(unsigned long long)le64_to_cpu(ph->entry_point));
+	else
+		printf("\n");
+	printf("    Attributes : ");
+
+	if (attr & PART_ATTR_VEC_LOCATION)
+		printf("vec ");
+
+	if (attr & PART_ATTR_ENCRYPTED)
+		printf("encrypted ");
+
+	switch (attr & PART_ATTR_CHECKSUM_MASK) {
+	case PART_ATTR_CHECKSUM_MD5:
+		printf("md5 ");
+		break;
+	case PART_ATTR_CHECKSUM_SHA2:
+		printf("sha2 ");
+		break;
+	case PART_ATTR_CHECKSUM_SHA3:
+		printf("sha3 ");
+		break;
+	}
+
+	if (attr & PART_ATTR_BIG_ENDIAN)
+		printf("BigEndian ");
+
+	if (attr & PART_ATTR_RSA_SIG)
+		printf("RSA ");
+
+	if (attr & PART_ATTR_A53_EXEC_AARCH32)
+		printf("AArch32 ");
+
+	if (attr & PART_ATTR_TARGET_EL_MASK)
+		printf("EL%d ", (attr & PART_ATTR_TARGET_EL_MASK) >> 1);
+
+	if (attr & PART_ATTR_TZ_SECURE)
+		printf("secure ");
+	printf("\n");
+
+	printf("    Checksum   : 0x%08x\n", le32_to_cpu(ph->checksum));
+}
+
 static void zynqmpimage_print_header(const void *ptr)
 {
 	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
@@ -213,6 +364,25 @@ static void zynqmpimage_print_header(const void *ptr)
 		       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;
+		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++) {
+			uint32_t next = le32_to_cpu(ph->next_partition_offset) * 4;
+
+			/* Partition 0 is the base image itself */
+			if (i)
+				print_partition(ptr, ph);
+			ph = (void*)ptr + next;
+		}
+	}
+
 	free(dynamic_header);
 }
 
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 2/3] tools: zynqmpimage: Move defines to header
  2018-04-12 13:48 [U-Boot] [PATCH v3 0/3] tools: zynqmpimage: Support partitions Alexander Graf
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support Alexander Graf
@ 2018-04-12 13:48 ` Alexander Graf
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 3/3] tools: zynqmpimage: Add bif support Alexander Graf
  2 siblings, 0 replies; 6+ messages in thread
From: Alexander Graf @ 2018-04-12 13:48 UTC (permalink / raw)
  To: u-boot

We will add support for ZynqMP bif input files later, so let's move
all structure definitions into a header file that can be used by that
one as well.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 tools/zynqmpimage.c | 115 +--------------------------------------------
 tools/zynqmpimage.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 114 deletions(-)
 create mode 100644 tools/zynqmpimage.h

diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
index 8117913da3..8f4766f077 100644
--- a/tools/zynqmpimage.c
+++ b/tools/zynqmpimage.c
@@ -58,122 +58,9 @@
 
 #include "imagetool.h"
 #include "mkimage.h"
+#include "zynqmpimage.h"
 #include <image.h>
 
-#define HEADER_INTERRUPT_DEFAULT (cpu_to_le32(0xeafffffe))
-#define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff))
-#define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566))
-#define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58))
-#define HEADER_CPU_SELECT_A53_64BIT	(0x2 << 10)
-
-enum {
-	ENCRYPTION_EFUSE = 0xa5c3c5a3,
-	ENCRYPTION_OEFUSE = 0xa5c3c5a7,
-	ENCRYPTION_BBRAM = 0x3a5c3c5a,
-	ENCRYPTION_OBBRAM = 0xa35c7ca5,
-	ENCRYPTION_NONE = 0x0,
-};
-
-struct zynqmp_reginit {
-	uint32_t address;
-	uint32_t data;
-};
-
-#define HEADER_INTERRUPT_VECTORS	8
-#define HEADER_REGINITS			256
-
-struct image_header_table {
-	uint32_t version;		  /* 0x00 */
-	uint32_t nr_parts;		  /* 0x04 */
-	uint32_t partition_header_offset; /* 0x08, divided by 4 */
-	uint32_t image_header_offset;	  /* 0x0c, divided by 4 */
-	uint32_t auth_certificate_offset; /* 0x10 */
-	uint32_t boot_device;		  /* 0x14 */
-	uint32_t __reserved1[9];	  /* 0x18 - 0x38 */
-	uint32_t checksum;		  /* 0x3c */
-};
-
-#define PART_ATTR_VEC_LOCATION		0x800000
-#define PART_ATTR_BS_BLOCK_SIZE_MASK	0x700000
-#define     PART_ATTR_BS_BLOCK_SIZE_DEFAULT	0x000000
-#define     PART_ATTR_BS_BLOCK_SIZE_8MB		0x400000
-#define PART_ATTR_BIG_ENDIAN		0x040000
-#define PART_ATTR_PART_OWNER_MASK	0x030000
-#define     PART_ATTR_PART_OWNER_FSBL		0x000000
-#define     PART_ATTR_PART_OWNER_UBOOT		0x010000
-#define PART_ATTR_RSA_SIG		0x008000
-#define PART_ATTR_CHECKSUM_MASK		0x007000
-#define    PART_ATTR_CHECKSUM_NONE		0x000000
-#define    PART_ATTR_CHECKSUM_MD5		0x001000
-#define    PART_ATTR_CHECKSUM_SHA2		0x002000
-#define    PART_ATTR_CHECKSUM_SHA3		0x003000
-#define PART_ATTR_DEST_CPU_SHIFT	8
-#define PART_ATTR_DEST_CPU_MASK		0x000f00
-#define    PART_ATTR_DEST_CPU_NONE		0x000000
-#define    PART_ATTR_DEST_CPU_A53_0		0x000100
-#define    PART_ATTR_DEST_CPU_A53_1		0x000200
-#define    PART_ATTR_DEST_CPU_A53_2		0x000300
-#define    PART_ATTR_DEST_CPU_A53_3		0x000400
-#define    PART_ATTR_DEST_CPU_R5_0		0x000500
-#define    PART_ATTR_DEST_CPU_R5_1		0x000600
-#define    PART_ATTR_DEST_CPU_R5_L		0x000700
-#define    PART_ATTR_DEST_CPU_PMU		0x000800
-#define PART_ATTR_ENCRYPTED		0x000080
-#define PART_ATTR_DEST_DEVICE_SHIFT	4
-#define PART_ATTR_DEST_DEVICE_MASK	0x000070
-#define    PART_ATTR_DEST_DEVICE_NONE		0x000000
-#define    PART_ATTR_DEST_DEVICE_PS		0x000010
-#define    PART_ATTR_DEST_DEVICE_PL		0x000020
-#define    PART_ATTR_DEST_DEVICE_PMU		0x000030
-#define    PART_ATTR_DEST_DEVICE_XIP		0x000040
-#define PART_ATTR_A53_EXEC_AARCH32	0x000008
-#define PART_ATTR_TARGET_EL_SHIFT	1
-#define PART_ATTR_TARGET_EL_MASK	0x000006
-#define PART_ATTR_TZ_SECURE		0x000001
-
-static const char *dest_cpus[0x10] = {
-	"none", "a5x-0", "a5x-1", "a5x-2", "a5x-3", "r5-0", "r5-1",
-	"r5-lockstep", "pmu", "unknown", "unknown", "unknown", "unknown",
-	"unknown", "unknown", "unknown"
-};
-
-struct partition_header {
-	uint32_t len_enc;		  /* 0x00, divided by 4 */
-	uint32_t len_unenc;		  /* 0x04, divided by 4 */
-	uint32_t len;			  /* 0x08, divided by 4 */
-	uint32_t next_partition_offset;   /* 0x0c */
-	uint64_t entry_point;		  /* 0x10 */
-	uint64_t load_address;		  /* 0x18 */
-	uint32_t offset;		  /* 0x20, divided by 4 */
-	uint32_t attributes;		  /* 0x24 */
-	uint32_t __reserved1;		  /* 0x28 */
-	uint32_t checksum_offset;	  /* 0x2c, divided by 4 */
-	uint32_t __reserved2;		  /* 0x30 */
-	uint32_t auth_certificate_offset; /* 0x34 */
-	uint32_t __reserved3;		  /* 0x38 */
-	uint32_t checksum;		  /* 0x3c */
-};
-
-struct zynqmp_header {
-	uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */
-	uint32_t width_detection; /* 0x20 */
-	uint32_t image_identifier; /* 0x24 */
-	uint32_t encryption; /* 0x28 */
-	uint32_t image_load; /* 0x2c */
-	uint32_t image_offset; /* 0x30 */
-	uint32_t pfw_image_length; /* 0x34 */
-	uint32_t total_pfw_image_length; /* 0x38 */
-	uint32_t image_size; /* 0x3c */
-	uint32_t image_stored_size; /* 0x40 */
-	uint32_t image_attributes; /* 0x44 */
-	uint32_t checksum; /* 0x48 */
-	uint32_t __reserved1[19]; /* 0x4c */
-	uint32_t image_header_table_offset; /* 0x98 */
-	uint32_t __reserved2[7]; /* 0x9c */
-	struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */
-	uint32_t __reserved4[66]; /* 0x9c0 */
-};
-
 static struct zynqmp_header zynqmpimage_header;
 static void *dynamic_header;
 static FILE *fpmu;
diff --git a/tools/zynqmpimage.h b/tools/zynqmpimage.h
new file mode 100644
index 0000000000..f3b5c195ad
--- /dev/null
+++ b/tools/zynqmpimage.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 Michal Simek <michals@xilinx.com>
+ * Copyright (C) 2015 Nathan Rossi <nathan@nathanrossi.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * The following Boot Header format/structures and values are defined in the
+ * following documents:
+ *   * ug1085 ZynqMP TRM doc v1.4 (Chapter 11, Table 11-4)
+ *   * ug1137 ZynqMP Software Developer Guide v6.0 (Chapter 16)
+ */
+
+#ifndef _ZYNQMPIMAGE_H_
+#define _ZYNQMPIMAGE_H_
+
+#include <stdint.h>
+
+#define HEADER_INTERRUPT_DEFAULT (cpu_to_le32(0xeafffffe))
+#define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff))
+#define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566))
+#define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58))
+#define HEADER_CPU_SELECT_A53_64BIT	(0x2 << 10)
+
+enum {
+	ENCRYPTION_EFUSE = 0xa5c3c5a3,
+	ENCRYPTION_OEFUSE = 0xa5c3c5a7,
+	ENCRYPTION_BBRAM = 0x3a5c3c5a,
+	ENCRYPTION_OBBRAM = 0xa35c7ca5,
+	ENCRYPTION_NONE = 0x0,
+};
+
+struct zynqmp_reginit {
+	uint32_t address;
+	uint32_t data;
+};
+
+#define HEADER_INTERRUPT_VECTORS	8
+#define HEADER_REGINITS			256
+
+struct image_header_table {
+	uint32_t version;		  /* 0x00 */
+	uint32_t nr_parts;		  /* 0x04 */
+	uint32_t partition_header_offset; /* 0x08, divided by 4 */
+	uint32_t image_header_offset;	  /* 0x0c, divided by 4 */
+	uint32_t auth_certificate_offset; /* 0x10 */
+	uint32_t boot_device;		  /* 0x14 */
+	uint32_t __reserved1[9];	  /* 0x18 - 0x38 */
+	uint32_t checksum;		  /* 0x3c */
+};
+
+#define PART_ATTR_VEC_LOCATION		0x800000
+#define PART_ATTR_BS_BLOCK_SIZE_MASK	0x700000
+#define     PART_ATTR_BS_BLOCK_SIZE_DEFAULT	0x000000
+#define     PART_ATTR_BS_BLOCK_SIZE_8MB		0x400000
+#define PART_ATTR_BIG_ENDIAN		0x040000
+#define PART_ATTR_PART_OWNER_MASK	0x030000
+#define     PART_ATTR_PART_OWNER_FSBL		0x000000
+#define     PART_ATTR_PART_OWNER_UBOOT		0x010000
+#define PART_ATTR_RSA_SIG		0x008000
+#define PART_ATTR_CHECKSUM_MASK		0x007000
+#define    PART_ATTR_CHECKSUM_NONE		0x000000
+#define    PART_ATTR_CHECKSUM_MD5		0x001000
+#define    PART_ATTR_CHECKSUM_SHA2		0x002000
+#define    PART_ATTR_CHECKSUM_SHA3		0x003000
+#define PART_ATTR_DEST_CPU_SHIFT	8
+#define PART_ATTR_DEST_CPU_MASK		0x000f00
+#define    PART_ATTR_DEST_CPU_NONE		0x000000
+#define    PART_ATTR_DEST_CPU_A53_0		0x000100
+#define    PART_ATTR_DEST_CPU_A53_1		0x000200
+#define    PART_ATTR_DEST_CPU_A53_2		0x000300
+#define    PART_ATTR_DEST_CPU_A53_3		0x000400
+#define    PART_ATTR_DEST_CPU_R5_0		0x000500
+#define    PART_ATTR_DEST_CPU_R5_1		0x000600
+#define    PART_ATTR_DEST_CPU_R5_L		0x000700
+#define    PART_ATTR_DEST_CPU_PMU		0x000800
+#define PART_ATTR_ENCRYPTED		0x000080
+#define PART_ATTR_DEST_DEVICE_SHIFT	4
+#define PART_ATTR_DEST_DEVICE_MASK	0x000070
+#define    PART_ATTR_DEST_DEVICE_NONE		0x000000
+#define    PART_ATTR_DEST_DEVICE_PS		0x000010
+#define    PART_ATTR_DEST_DEVICE_PL		0x000020
+#define    PART_ATTR_DEST_DEVICE_PMU		0x000030
+#define    PART_ATTR_DEST_DEVICE_XIP		0x000040
+#define PART_ATTR_A53_EXEC_AARCH32	0x000008
+#define PART_ATTR_TARGET_EL_SHIFT	1
+#define PART_ATTR_TARGET_EL_MASK	0x000006
+#define PART_ATTR_TZ_SECURE		0x000001
+
+static const char *dest_cpus[0x10] = {
+	"none", "a5x-0", "a5x-1", "a5x-2", "a5x-3", "r5-0", "r5-1",
+	"r5-lockstep", "pmu", "unknown", "unknown", "unknown", "unknown",
+	"unknown", "unknown", "unknown"
+};
+
+struct partition_header {
+	uint32_t len_enc;		  /* 0x00, divided by 4 */
+	uint32_t len_unenc;		  /* 0x04, divided by 4 */
+	uint32_t len;			  /* 0x08, divided by 4 */
+	uint32_t next_partition_offset;   /* 0x0c */
+	uint64_t entry_point;		  /* 0x10 */
+	uint64_t load_address;		  /* 0x18 */
+	uint32_t offset;		  /* 0x20, divided by 4 */
+	uint32_t attributes;		  /* 0x24 */
+	uint32_t __reserved1;		  /* 0x28 */
+	uint32_t checksum_offset;	  /* 0x2c, divided by 4 */
+	uint32_t __reserved2;		  /* 0x30 */
+	uint32_t auth_certificate_offset; /* 0x34 */
+	uint32_t __reserved3;		  /* 0x38 */
+	uint32_t checksum;		  /* 0x3c */
+};
+
+struct zynqmp_header {
+	uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */
+	uint32_t width_detection; /* 0x20 */
+	uint32_t image_identifier; /* 0x24 */
+	uint32_t encryption; /* 0x28 */
+	uint32_t image_load; /* 0x2c */
+	uint32_t image_offset; /* 0x30 */
+	uint32_t pfw_image_length; /* 0x34 */
+	uint32_t total_pfw_image_length; /* 0x38 */
+	uint32_t image_size; /* 0x3c */
+	uint32_t image_stored_size; /* 0x40 */
+	uint32_t image_attributes; /* 0x44 */
+	uint32_t checksum; /* 0x48 */
+	uint32_t __reserved1[19]; /* 0x4c */
+	uint32_t image_header_table_offset; /* 0x98 */
+	uint32_t __reserved2[7]; /* 0x9c */
+	struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */
+	uint32_t __reserved4[66]; /* 0x9c0 */
+};
+
+#endif /* _ZYNQMPIMAGE_H_ */
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 3/3] tools: zynqmpimage: Add bif support
  2018-04-12 13:48 [U-Boot] [PATCH v3 0/3] tools: zynqmpimage: Support partitions Alexander Graf
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support Alexander Graf
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 2/3] tools: zynqmpimage: Move defines to header Alexander Graf
@ 2018-04-12 13:48 ` Alexander Graf
  2018-04-13  9:40   ` Michal Simek
  2 siblings, 1 reply; 6+ messages in thread
From: Alexander Graf @ 2018-04-12 13:48 UTC (permalink / raw)
  To: u-boot

The officially described way to generate boot.bin files for ZynqMP is to
describe the contents of the target binary using a file of the "bif" format.
This file then links to other files that all get packed into a bootable image.

This patch adds support to read such a .bif file and generate a respective
ZynqMP boot.bin file that can include the normal image and pmu files, but also
supports image partitions now. This makes it a handy replacement for the
proprietary "bootgen" utility that is currently used to generate boot.bin
files with FSBL.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v2 -> v3:

  - zero initialize header
  - reduce default debug verbosity
---
 common/image.c      |   1 +
 include/image.h     |   1 +
 tools/Makefile      |   1 +
 tools/imagetool.h   |   1 +
 tools/mkimage.c     |   3 +
 tools/zynqmpbif.c   | 839 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/zynqmpimage.c |   4 +-
 tools/zynqmpimage.h |   3 +
 8 files changed, 851 insertions(+), 2 deletions(-)
 create mode 100644 tools/zynqmpbif.c

diff --git a/common/image.c b/common/image.c
index e1c50eb25d..f30dfa229b 100644
--- a/common/image.c
+++ b/common/image.c
@@ -159,6 +159,7 @@ static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_VYBRIDIMAGE, "vybridimage",  "Vybrid Boot Image", },
 	{	IH_TYPE_ZYNQIMAGE,  "zynqimage",  "Xilinx Zynq Boot Image" },
 	{	IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" },
+	{	IH_TYPE_ZYNQMPBIF,  "zynqmpbif",  "Xilinx ZynqMP Boot Image (bif)" },
 	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
 	{       IH_TYPE_TEE,        "tee",        "Trusted Execution Environment Image",},
 	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },
diff --git a/include/image.h b/include/image.h
index a579c5f509..c5af912aeb 100644
--- a/include/image.h
+++ b/include/image.h
@@ -269,6 +269,7 @@ enum {
 	IH_TYPE_RKSPI,			/* Rockchip SPI image		*/
 	IH_TYPE_ZYNQIMAGE,		/* Xilinx Zynq Boot Image */
 	IH_TYPE_ZYNQMPIMAGE,		/* Xilinx ZynqMP Boot Image */
+	IH_TYPE_ZYNQMPBIF,		/* Xilinx ZynqMP Boot Image (bif) */
 	IH_TYPE_FPGA,			/* FPGA Image */
 	IH_TYPE_VYBRIDIMAGE,	/* VYBRID .vyb Image */
 	IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */
diff --git a/tools/Makefile b/tools/Makefile
index 8143c25666..204685ec9e 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -113,6 +113,7 @@ dumpimage-mkimage-objs := aisimage.o \
 			ublimage.o \
 			zynqimage.o \
 			zynqmpimage.o \
+			zynqmpbif.o \
 			$(LIBFDT_OBJS) \
 			gpimage.o \
 			gpimage-common.o \
diff --git a/tools/imagetool.h b/tools/imagetool.h
index e67de9b5ad..d78a9458f4 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -232,6 +232,7 @@ time_t imagetool_get_source_date(
 
 
 void pbl_load_uboot(int fd, struct image_tool_params *mparams);
+void zynqmpbif_copy_image(int fd, struct image_tool_params *mparams);
 
 #define ___cat(a, b) a ## b
 #define __cat(a, b) ___cat(a, b)
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 4e561820e7..72183f5f2b 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -514,6 +514,9 @@ int main(int argc, char **argv)
 		} else if (params.type == IH_TYPE_PBLIMAGE) {
 			/* PBL has special Image format, implements its' own */
 			pbl_load_uboot(ifd, &params);
+		} else if (params.type == IH_TYPE_ZYNQMPBIF) {
+			/* Image file is meta, walk through actual targets */
+			zynqmpbif_copy_image(ifd, &params);
 		} else {
 			copy_file(ifd, params.datafile, pad_len);
 		}
diff --git a/tools/zynqmpbif.c b/tools/zynqmpbif.c
new file mode 100644
index 0000000000..d60eff1d8b
--- /dev/null
+++ b/tools/zynqmpbif.c
@@ -0,0 +1,839 @@
+/*
+ * Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "imagetool.h"
+#include "mkimage.h"
+#include "zynqmpimage.h"
+#include <elf.h>
+#include <image.h>
+
+struct bif_entry {
+	const char *filename;
+	uint64_t flags;
+	uint64_t dest_cpu;
+	uint64_t exp_lvl;
+	uint64_t dest_dev;
+	uint64_t load;
+	uint64_t entry;
+};
+
+enum bif_flag {
+	BIF_FLAG_AESKEYFILE,
+	BIF_FLAG_INIT,
+	BIF_FLAG_UDF_BH,
+	BIF_FLAG_HEADERSIGNATURE,
+	BIF_FLAG_PPKFILE,
+	BIF_FLAG_PSKFILE,
+	BIF_FLAG_SPKFILE,
+	BIF_FLAG_SSKFILE,
+	BIF_FLAG_SPKSIGNATURE,
+	BIF_FLAG_FSBL_CONFIG,
+	BIF_FLAG_AUTH_PARAMS,
+	BIF_FLAG_KEYSRC_ENCRYPTION,
+	BIF_FLAG_PMUFW_IMAGE,
+	BIF_FLAG_BOOTLOADER,
+	BIF_FLAG_TZ,
+	BIF_FLAG_BH_KEY_IV,
+	BIF_FLAG_BH_KEYFILE,
+	BIF_FLAG_PUF_FILE,
+
+	/* Internal flags */
+	BIF_FLAG_BIT_FILE,
+	BIF_FLAG_ELF_FILE,
+	BIF_FLAG_BIN_FILE,
+};
+
+struct bif_flags {
+	const char name[32];
+	uint64_t flag;
+	char *(*parse)(char *line, struct bif_entry *bf);
+};
+
+struct bif_file_type {
+	const char name[32];
+	uint32_t header;
+	int (*add)(struct bif_entry *bf);
+};
+
+struct bif_output {
+	size_t data_len;
+	char *data;
+	struct image_header_table *imgheader;
+	struct zynqmp_header *header;
+	struct partition_header *last_part;
+};
+
+struct bif_output bif_output;
+
+static uint32_t zynqmp_csum(void *start, void *end)
+{
+	uint32_t checksum = 0;
+	uint32_t *ptr32 = start;
+
+	while (ptr32 != end) {
+		checksum += le32_to_cpu(*ptr32);
+		ptr32++;
+	}
+
+	return ~checksum;
+}
+
+static int zynqmpbif_check_params(struct image_tool_params *params)
+{
+	if (!params)
+		return 0;
+
+	if (params->addr != 0x0) {
+		fprintf(stderr, "Error: Load Address can not be specified.\n");
+		return -1;
+	}
+
+	if (params->eflag) {
+		fprintf(stderr, "Error: Entry Point can not be specified.\n");
+		return -1;
+	}
+
+	return !(params->lflag || params->dflag);
+}
+
+static int zynqmpbif_check_image_types(uint8_t type)
+{
+	return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static char *parse_dest_cpu(char *line, struct bif_entry *bf)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dest_cpus); i++) {
+		if (!strncmp(line, dest_cpus[i], strlen(dest_cpus[i]))) {
+			bf->dest_cpu = i;
+			return line + strlen(dest_cpus[i]);
+		}
+	}
+
+	return line;
+}
+
+static char *parse_el(char *line, struct bif_entry *bf)
+{
+	const char *dest_els[] = { "none", "el-0", "el-1", "el-2", "el-3" };
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dest_els); i++) {
+		if (!strncmp(line, dest_els[i], strlen(dest_els[i]))) {
+			bf->exp_lvl = i;
+			return line + strlen(dest_els[i]);
+		}
+	}
+
+	return line;
+}
+
+static char *parse_load(char *line, struct bif_entry *bf)
+{
+	char *endptr;
+
+	bf->load = strtoll(line, &endptr, 0);
+
+	return endptr;
+}
+
+static char *parse_entry(char *line, struct bif_entry *bf)
+{
+	char *endptr;
+
+	bf->entry = strtoll(line, &endptr, 0);
+
+	return endptr;
+}
+
+static const struct bif_flags bif_flags[] = {
+	{ "fsbl_config", BIF_FLAG_FSBL_CONFIG },
+	{ "trustzone", BIF_FLAG_TZ },
+	{ "pmufw_image", BIF_FLAG_PMUFW_IMAGE },
+	{ "bootloader", BIF_FLAG_BOOTLOADER },
+	{ "destination_cpu=", 0, parse_dest_cpu },
+	{ "exception_level=", 0, parse_el },
+	{ "load=", 0, parse_load },
+	{ "startup=", 0, parse_entry },
+};
+
+static char *read_full_file(const char *filename, size_t *size)
+{
+	char *buf, *bufp;
+	struct stat sbuf;
+	int len = 0, r, fd;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		return NULL;
+
+	if (fstat(fd, &sbuf) < 0)
+		return NULL;
+
+	if (size)
+		*size = sbuf.st_size;
+
+	bufp = buf = malloc(sbuf.st_size);
+	if (!buf)
+		return NULL;
+
+	while (len < sbuf.st_size) {
+		r = read(fd, bufp, sbuf.st_size - len);
+		if (r < 0)
+			return NULL;
+		len += r;
+		bufp += r;
+	}
+
+	close(fd);
+
+	return buf;
+}
+
+static int bif_add_blob(const void *data, size_t len, size_t *offset)
+{
+	size_t new_size = ROUND(bif_output.data_len + len, 64);
+	uintptr_t header_off;
+	uintptr_t last_part_off;
+	uintptr_t imgheader_off;
+	uintptr_t old_data = (uintptr_t)bif_output.data;
+
+	header_off = (uintptr_t)bif_output.header - old_data;
+	last_part_off = (uintptr_t)bif_output.last_part - old_data;
+	imgheader_off = (uintptr_t)bif_output.imgheader - old_data;
+
+	bif_output.data = realloc(bif_output.data, new_size);
+	memcpy(bif_output.data + bif_output.data_len, data, len);
+	if (offset)
+		*offset = bif_output.data_len;
+	bif_output.data_len = new_size;
+
+	/* Readjust internal pointers */
+	if (bif_output.header)
+		bif_output.header = (void*)(bif_output.data + header_off);
+	if (bif_output.last_part)
+		bif_output.last_part = (void*)(bif_output.data + last_part_off);
+	if (bif_output.imgheader)
+		bif_output.imgheader = (void*)(bif_output.data + imgheader_off);
+
+	return 0;
+}
+
+static int bif_init(void)
+{
+	struct zynqmp_header header = { { 0 } };
+	int r;
+
+	zynqmpimage_default_header(&header);
+
+	r = bif_add_blob(&header, sizeof(header), NULL);
+	if (r)
+		return r;
+
+	bif_output.header = (void*)bif_output.data;
+
+	return 0;
+}
+
+static int bif_add_pmufw(struct bif_entry *bf, const char *data, size_t len)
+{
+	size_t offset;
+
+	if (bif_output.header->image_offset) {
+		printf("PMUFW expected before bootloader in your .bif file!\n");
+		return -1;
+	}
+
+	bif_add_blob(data, len, &offset);
+	len = ROUND(len, 64);
+	bif_output.header->pfw_image_length = cpu_to_le32(len);
+	bif_output.header->total_pfw_image_length = cpu_to_le32(len);
+	bif_output.header->image_offset = cpu_to_le32(offset);
+
+	return 0;
+}
+
+static int bif_add_part(struct bif_entry *bf, const char *data, size_t len)
+{
+	size_t parthdr_offset, part_offset;
+	struct partition_header parthdr = {
+		.len_enc = cpu_to_le32(len / 4),
+		.len_unenc = cpu_to_le32(len / 4),
+		.len = cpu_to_le32(len / 4),
+		.entry_point = cpu_to_le64(bf->entry),
+		.load_address = cpu_to_le64(bf->load),
+	};
+	int r;
+	uint32_t csum;
+
+	if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE))
+		return bif_add_pmufw(bf, data, len);
+
+	bif_add_blob(data, len, &part_offset);
+	parthdr.offset = cpu_to_le32(part_offset / 4);
+
+	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
+		if (bif_output.last_part) {
+			printf("ERROR: Bootloader needs to come as first non-PMU partition");
+			return -1;
+		}
+
+		parthdr.offset = cpu_to_le32(bif_output.header->image_offset);
+		parthdr.len = cpu_to_le32((part_offset + len -
+			bif_output.header->image_offset) / 4);
+		parthdr.len_enc = parthdr.len;
+		parthdr.len_unenc = parthdr.len;
+	}
+
+	/* Normalize EL */
+	bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3;
+	parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT;
+	parthdr.attributes |= bf->dest_dev;
+	parthdr.attributes |= bf->dest_cpu << PART_ATTR_DEST_CPU_SHIFT;
+	if (bf->flags & (1ULL << BIF_FLAG_TZ))
+		parthdr.attributes |= PART_ATTR_TZ_SECURE;
+
+	csum = zynqmp_csum(&parthdr, &parthdr.checksum);
+	parthdr.checksum = cpu_to_le32(csum);
+
+	r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset);
+	if (r)
+		return r;
+
+	/* Add image header table if not there yet */
+	if (!bif_output.imgheader) {
+		size_t imghdr_off;
+		struct image_header_table imghdr = {
+			.version = cpu_to_le32(0x01020000),
+			.nr_parts = 0,
+		};
+
+		r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off);
+		if (r)
+			return r;
+
+		bif_output.header->image_header_table_offset = imghdr_off;
+		bif_output.imgheader = (void*)(bif_output.data + imghdr_off);
+	}
+
+	bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu(
+		bif_output.imgheader->nr_parts) + 1);
+
+	/* Link to this partition header */
+	if (bif_output.last_part) {
+		bif_output.last_part->next_partition_offset =
+			cpu_to_le32(parthdr_offset / 4);
+
+		/* Recalc checksum of last_part */
+		csum = zynqmp_csum(bif_output.last_part,
+				   &bif_output.last_part->checksum);
+		bif_output.last_part->checksum = cpu_to_le32(csum);
+	} else {
+		bif_output.imgheader->partition_header_offset =
+			cpu_to_le32(parthdr_offset / 4);
+	}
+	bif_output.last_part = (void*)(bif_output.data + parthdr_offset);
+
+	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
+		bif_output.header->image_load = cpu_to_le32(bf->load);
+		if (!bif_output.header->image_offset)
+			bif_output.header->image_offset =
+				cpu_to_le32(part_offset);
+		bif_output.header->image_size = cpu_to_le32(len);
+		bif_output.header->image_stored_size = cpu_to_le32(len);
+	}
+
+	return 0;
+}
+
+/* Add .bit bitstream */
+static int bif_add_bit(struct bif_entry *bf)
+{
+	char *bit = read_full_file(bf->filename, NULL);
+	char *bitbin;
+	uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
+				     0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
+	uint16_t len;
+	uint32_t bitlen;
+	int i;
+
+	if (!bit)
+		return -1;
+
+	/* Skip initial header */
+	if (memcmp(bit, initial_header, sizeof(initial_header)))
+		return -1;
+
+	bit += sizeof(initial_header);
+
+	/* Design name */
+	len = be16_to_cpu(*(uint16_t*)bit);
+	bit += sizeof(uint16_t);
+	debug("Design: %s\n", bit);
+	bit += len;
+
+	/* Device identifier */
+	if (*bit != 'b')
+		return -1;
+	bit++;
+	len = be16_to_cpu(*(uint16_t*)bit);
+	bit += sizeof(uint16_t);
+	debug("Device: %s\n", bit);
+	bit += len;
+
+	/* Date */
+	if (*bit != 'c')
+		return -1;
+	bit++;
+	len = be16_to_cpu(*(uint16_t*)bit);
+	bit += sizeof(uint16_t);
+	debug("Date: %s\n", bit);
+	bit += len;
+
+	/* Time */
+	if (*bit != 'd')
+		return -1;
+	bit++;
+	len = be16_to_cpu(*(uint16_t*)bit);
+	bit += sizeof(uint16_t);
+	debug("Time: %s\n", bit);
+	bit += len;
+
+	/* Bitstream length */
+	if (*bit != 'e')
+		return -1;
+	bit++;
+	bitlen = be32_to_cpu(*(uint32_t*)bit);
+	bit += sizeof(uint32_t);
+	bitbin = bit;
+
+	debug("Bitstream Length: 0x%x\n", bitlen);
+	for (i = 0; i < bitlen; i += sizeof(uint32_t)) {
+		uint32_t *bitbin32 = (uint32_t*)&bitbin[i];
+		*bitbin32 = __swab32(*bitbin32);
+	}
+
+	if (!bf->dest_dev)
+		bf->dest_dev = PART_ATTR_DEST_DEVICE_PL;
+
+	bf->load = 0xffffffff;
+	bf->entry = 0;
+
+	bf->flags |= 1ULL << BIF_FLAG_BIT_FILE;
+	return bif_add_part(bf, bit, bitlen);
+}
+
+/* Add .bin bitstream */
+static int bif_add_bin(struct bif_entry *bf)
+{
+	size_t size;
+	char *bin = read_full_file(bf->filename, &size);
+
+	if (!bf->dest_dev)
+		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
+
+	bf->flags |= 1ULL << BIF_FLAG_BIN_FILE;
+	return bif_add_part(bf, bin, size);
+}
+
+/* Add elf file */
+static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr)
+{
+	Elf64_Ehdr *ehdr;
+	Elf64_Shdr *shdr;
+	size_t min_addr = -1, max_addr = 0;
+	char *flat;
+	int i;
+
+	ehdr = (void*)elf;
+	shdr = (void*)(elf + le64_to_cpu(ehdr->e_shoff));
+
+	/* Look for smallest / biggest address */
+	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++) {
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC) ||
+		    (shdr->sh_type == SHT_NOBITS)) {
+			shdr++;
+			continue;
+		}
+
+		if (le64_to_cpu(shdr->sh_addr) < min_addr)
+			min_addr = le64_to_cpu(shdr->sh_addr);
+		if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) >
+			max_addr)
+			max_addr = le64_to_cpu(shdr->sh_addr) +
+				   le64_to_cpu(shdr->sh_size);
+
+		shdr++;
+	}
+
+	*load_addr = min_addr;
+	*flat_size = max_addr - min_addr;
+	flat = calloc(1, *flat_size);
+	if (!flat)
+		return NULL;
+
+	shdr = (void*)(elf + le64_to_cpu(ehdr->e_shoff));
+	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++) {
+		char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr;
+		char *src = elf + le64_to_cpu(shdr->sh_offset);
+
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC)) {
+			shdr++;
+			continue;
+		}
+
+		if (shdr->sh_type != SHT_NOBITS) {
+
+			memcpy(dst, src, le64_to_cpu(shdr->sh_size));
+		}
+		shdr++;
+	}
+
+	return flat;
+}
+
+static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr)
+{
+	Elf32_Ehdr *ehdr;
+	Elf32_Shdr *shdr;
+	size_t min_addr = -1, max_addr = 0;
+	char *flat;
+	int i;
+
+	ehdr = (void*)elf;
+	shdr = (void*)(elf + le32_to_cpu(ehdr->e_shoff));
+
+	/* Look for smallest / biggest address */
+	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++) {
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC) ||
+		    (shdr->sh_type == SHT_NOBITS)) {
+			shdr++;
+			continue;
+		}
+
+		if (le32_to_cpu(shdr->sh_addr) < min_addr)
+			min_addr = le32_to_cpu(shdr->sh_addr);
+		if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) >
+			max_addr)
+			max_addr = le32_to_cpu(shdr->sh_addr) +
+				   le32_to_cpu(shdr->sh_size);
+
+		shdr++;
+	}
+
+	*load_addr = min_addr;
+	*flat_size = max_addr - min_addr;
+	flat = calloc(1, *flat_size);
+	if (!flat)
+		return NULL;
+
+	shdr = (void*)(elf + le32_to_cpu(ehdr->e_shoff));
+	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++) {
+		char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr;
+		char *src = elf + le32_to_cpu(shdr->sh_offset);
+
+		if (!shdr->sh_size || !shdr->sh_addr ||
+		    !(shdr->sh_flags & SHF_ALLOC)) {
+			shdr++;
+			continue;
+		}
+
+		if (shdr->sh_type != SHT_NOBITS) {
+
+			memcpy(dst, src, le32_to_cpu(shdr->sh_size));
+		}
+		shdr++;
+	}
+
+	return flat;
+}
+
+static int bif_add_elf(struct bif_entry *bf)
+{
+	size_t size;
+	size_t elf_size;
+	char *elf;
+	char *flat;
+	size_t load_addr;
+	Elf32_Ehdr *ehdr32;
+	Elf64_Ehdr *ehdr64;
+
+	elf = read_full_file(bf->filename, &elf_size);
+	if (!elf)
+		return -1;
+
+	ehdr32 = (void*)elf;
+	ehdr64 = (void*)elf;
+
+	switch (ehdr32->e_ident[EI_CLASS]) {
+	case ELFCLASS32:
+		flat = elf2flat32(elf, &size, &load_addr);
+		bf->entry = le32_to_cpu(ehdr32->e_entry);
+		break;
+	case ELFCLASS64:
+		flat = elf2flat64(elf, &size, &load_addr);
+		bf->entry = le64_to_cpu(ehdr64->e_entry);
+		break;
+	default:
+		printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]);
+		return -1;
+	}
+
+	if (!flat)
+		return -1;
+
+	bf->load = load_addr;
+	if (!bf->dest_dev)
+		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
+
+	bf->flags |= 1ULL << BIF_FLAG_ELF_FILE;
+	return bif_add_part(bf, flat, size);
+}
+
+static const struct bif_file_type bif_file_types[] = {
+	{
+		.name = "bitstream (.bit)",
+		.header = 0x00090ff0,
+		.add = bif_add_bit,
+	},
+
+	{
+		.name = "ELF",
+		.header = 0x7f454c46,
+		.add = bif_add_elf,
+	},
+
+	/* Anything else is a .bin file */
+	{
+		.name = ".bin",
+		.add = bif_add_bin,
+	},
+};
+
+static const struct bif_flags *find_flag(char *str)
+{
+	const struct bif_flags *bf;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bif_flags); i++) {
+		bf = &bif_flags[i];
+		if (!strncmp(bf->name, str, strlen(bf->name)))
+			return bf;
+	}
+
+	printf("ERROR: Flag '%s' not found\n", str);
+
+	return NULL;
+}
+
+static int bif_open_file(struct bif_entry *entry)
+{
+	int fd = open(entry->filename, O_RDONLY);
+
+	if (fd < 0)
+		printf("Error opening file %s\n", entry->filename);
+
+	return fd;
+}
+
+static const struct bif_file_type *get_file_type(struct bif_entry *entry)
+{
+	int fd = bif_open_file(entry);
+	uint32_t header;
+	int i;
+
+	if (fd < 0)
+		return NULL;
+
+	if (read(fd, &header, sizeof(header)) != sizeof(header)) {
+		printf("Error reading file %s", entry->filename);
+		return NULL;
+	}
+
+	close(fd);
+
+	for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) {
+		const struct bif_file_type *type = &bif_file_types[i];
+
+		if (!type->header)
+			return type;
+		if (type->header == be32_to_cpu(header))
+			return type;
+	}
+
+	return NULL;
+}
+
+#define NEXT_CHAR(str, chr) ({		\
+	char *_n = strchr(str, chr);	\
+	if (!_n)			\
+		goto err;		\
+	_n;				\
+})
+
+static char *skip_whitespace(char *str)
+{
+	while (*str == ' ' || *str == '\t')
+		str++;
+
+	return str;
+}
+
+void zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams)
+{
+	char *bif, *bifp, *bifpn;
+	char *line;
+	struct bif_entry entries[32] = { { 0 } };
+	int nr_entries = 0;
+	struct bif_entry *entry = entries;
+	size_t len;
+	int i;
+	uint32_t csum;
+
+	bif_init();
+
+	/* Read .bif input file */
+	bifp = bif = read_full_file(mparams->datafile, NULL);
+	if (!bif)
+		goto err;
+
+	/* Interpret .bif file */
+	bifp = bif;
+
+	/* A bif description starts with a { section */
+	bifp = NEXT_CHAR(bifp, '{') + 1;
+
+	/* Read every line */
+	while (1) {
+		bifpn = NEXT_CHAR(bifp, '\n');
+
+		*bifpn = '\0';
+		bifpn++;
+		line = bifp;
+
+		line = skip_whitespace(line);
+
+		/* Attributes? */
+		if (*line == '[') {
+			line++;
+			while (1) {
+				const struct bif_flags *bf;
+
+				line = skip_whitespace(line);
+				bf = find_flag(line);
+				if (!bf)
+					goto err;
+
+				line += strlen(bf->name);
+				if (bf->parse)
+					line = bf->parse(line, entry);
+				else
+					entry->flags |= 1ULL << bf->flag;
+
+				/* Go to next attribute or quit */
+				if (*line == ']') {
+					line++;
+					break;
+				}
+				if (*line == ',')
+					line++;
+			}
+		}
+
+		/* End of image description */
+		if (*line == '}')
+			break;
+
+		if (*line) {
+			line = skip_whitespace(line);
+			entry->filename = line;
+			nr_entries++;
+			entry++;
+		}
+
+		/* Use next line */
+		bifp = bifpn;
+	}
+
+	for (i = 0; i < nr_entries; i++) {
+		debug("Entry flags=%#lx name=%s\n", entries[i].flags,
+		      entries[i].filename);
+	}
+
+	for (i = 0; i < nr_entries; i++) {
+		struct bif_entry *entry = &entries[i];
+		const struct bif_file_type *type;
+		int r;
+
+		type = get_file_type(entry);
+		if (!type)
+			goto err;
+
+		debug("type=%s file=%s\n", type->name, entry->filename);
+		r = type->add(entry);
+		if (r)
+			goto err;
+	}
+
+	/* Calculate checksums */
+	csum = zynqmp_csum(&bif_output.header->width_detection,
+			   &bif_output.header->checksum);
+	bif_output.header->checksum = cpu_to_le32(csum);
+
+	if (bif_output.imgheader) {
+		csum = zynqmp_csum(bif_output.imgheader,
+				   &bif_output.imgheader->checksum);
+		bif_output.imgheader->checksum = cpu_to_le32(csum);
+	}
+
+	/* Write headers and components */
+	if (lseek(outfd, 0, SEEK_SET) != 0)
+		goto err;
+
+	len = bif_output.data_len;
+	bifp = bif_output.data;
+	while (len) {
+		int r;
+		r = write(outfd, bifp, len);
+		if (r < 0)
+			goto err;
+		len -= r;
+		bifp += r;
+	}
+
+	return;
+
+err:
+	fprintf(stderr, "Error: Failed to create image.\n");
+}
+
+/* Needs to be stubbed out so we can print after creation */
+static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd,
+		struct image_tool_params *params)
+{
+}
+
+static struct zynqmp_header zynqmpimage_header;
+
+U_BOOT_IMAGE_TYPE(
+	zynqmpbif,
+	"Xilinx ZynqMP Boot Image support (bif)",
+	sizeof(struct zynqmp_header),
+	(void *)&zynqmpimage_header,
+	zynqmpbif_check_params,
+	NULL,
+	zynqmpimage_print_header,
+	zynqmpbif_set_header,
+	NULL,
+	zynqmpbif_check_image_types,
+	NULL,
+	NULL
+);
diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
index 8f4766f077..145391de3e 100644
--- a/tools/zynqmpimage.c
+++ b/tools/zynqmpimage.c
@@ -87,7 +87,7 @@ static uint32_t zynqmpimage_checksum(struct zynqmp_header *ptr)
 	return cpu_to_le32(checksum);
 }
 
-static void zynqmpimage_default_header(struct zynqmp_header *ptr)
+void zynqmpimage_default_header(struct zynqmp_header *ptr)
 {
 	int i;
 
@@ -211,7 +211,7 @@ static void print_partition(const void *ptr, const struct partition_header *ph)
 	printf("    Checksum   : 0x%08x\n", le32_to_cpu(ph->checksum));
 }
 
-static void zynqmpimage_print_header(const void *ptr)
+void zynqmpimage_print_header(const void *ptr)
 {
 	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
 	int i;
diff --git a/tools/zynqmpimage.h b/tools/zynqmpimage.h
index f3b5c195ad..b421e4f94c 100644
--- a/tools/zynqmpimage.h
+++ b/tools/zynqmpimage.h
@@ -129,4 +129,7 @@ struct zynqmp_header {
 	uint32_t __reserved4[66]; /* 0x9c0 */
 };
 
+void zynqmpimage_default_header(struct zynqmp_header *ptr);
+void zynqmpimage_print_header(const void *ptr);
+
 #endif /* _ZYNQMPIMAGE_H_ */
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 3/3] tools: zynqmpimage: Add bif support
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 3/3] tools: zynqmpimage: Add bif support Alexander Graf
@ 2018-04-13  9:40   ` Michal Simek
  0 siblings, 0 replies; 6+ messages in thread
From: Michal Simek @ 2018-04-13  9:40 UTC (permalink / raw)
  To: u-boot

On 12.4.2018 15:48, Alexander Graf wrote:
> The officially described way to generate boot.bin files for ZynqMP is to
> describe the contents of the target binary using a file of the "bif" format.
> This file then links to other files that all get packed into a bootable image.
> 
> This patch adds support to read such a .bif file and generate a respective
> ZynqMP boot.bin file that can include the normal image and pmu files, but also
> supports image partitions now. This makes it a handy replacement for the
> proprietary "bootgen" utility that is currently used to generate boot.bin
> files with FSBL.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> 
> ---
> 
> v2 -> v3:
> 
>   - zero initialize header
>   - reduce default debug verbosity
> ---
>  common/image.c      |   1 +
>  include/image.h     |   1 +
>  tools/Makefile      |   1 +
>  tools/imagetool.h   |   1 +
>  tools/mkimage.c     |   3 +
>  tools/zynqmpbif.c   | 839 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/zynqmpimage.c |   4 +-
>  tools/zynqmpimage.h |   3 +
>  8 files changed, 851 insertions(+), 2 deletions(-)
>  create mode 100644 tools/zynqmpbif.c
> 
> diff --git a/common/image.c b/common/image.c
> index e1c50eb25d..f30dfa229b 100644
> --- a/common/image.c
> +++ b/common/image.c
> @@ -159,6 +159,7 @@ static const table_entry_t uimage_type[] = {
>  	{	IH_TYPE_VYBRIDIMAGE, "vybridimage",  "Vybrid Boot Image", },
>  	{	IH_TYPE_ZYNQIMAGE,  "zynqimage",  "Xilinx Zynq Boot Image" },
>  	{	IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" },
> +	{	IH_TYPE_ZYNQMPBIF,  "zynqmpbif",  "Xilinx ZynqMP Boot Image (bif)" },
>  	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
>  	{       IH_TYPE_TEE,        "tee",        "Trusted Execution Environment Image",},
>  	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },
> diff --git a/include/image.h b/include/image.h
> index a579c5f509..c5af912aeb 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -269,6 +269,7 @@ enum {
>  	IH_TYPE_RKSPI,			/* Rockchip SPI image		*/
>  	IH_TYPE_ZYNQIMAGE,		/* Xilinx Zynq Boot Image */
>  	IH_TYPE_ZYNQMPIMAGE,		/* Xilinx ZynqMP Boot Image */
> +	IH_TYPE_ZYNQMPBIF,		/* Xilinx ZynqMP Boot Image (bif) */
>  	IH_TYPE_FPGA,			/* FPGA Image */
>  	IH_TYPE_VYBRIDIMAGE,	/* VYBRID .vyb Image */
>  	IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */
> diff --git a/tools/Makefile b/tools/Makefile
> index 8143c25666..204685ec9e 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -113,6 +113,7 @@ dumpimage-mkimage-objs := aisimage.o \
>  			ublimage.o \
>  			zynqimage.o \
>  			zynqmpimage.o \
> +			zynqmpbif.o \
>  			$(LIBFDT_OBJS) \
>  			gpimage.o \
>  			gpimage-common.o \
> diff --git a/tools/imagetool.h b/tools/imagetool.h
> index e67de9b5ad..d78a9458f4 100644
> --- a/tools/imagetool.h
> +++ b/tools/imagetool.h
> @@ -232,6 +232,7 @@ time_t imagetool_get_source_date(
>  
>  
>  void pbl_load_uboot(int fd, struct image_tool_params *mparams);
> +void zynqmpbif_copy_image(int fd, struct image_tool_params *mparams);

This should return value which you will check

>  
>  #define ___cat(a, b) a ## b
>  #define __cat(a, b) ___cat(a, b)
> diff --git a/tools/mkimage.c b/tools/mkimage.c
> index 4e561820e7..72183f5f2b 100644
> --- a/tools/mkimage.c
> +++ b/tools/mkimage.c
> @@ -514,6 +514,9 @@ int main(int argc, char **argv)
>  		} else if (params.type == IH_TYPE_PBLIMAGE) {
>  			/* PBL has special Image format, implements its' own */
>  			pbl_load_uboot(ifd, &params);
> +		} else if (params.type == IH_TYPE_ZYNQMPBIF) {
> +			/* Image file is meta, walk through actual targets */
> +			zynqmpbif_copy_image(ifd, &params);

The same here because if there is for example comment in bif format
which is permitted than you need to error out.

>  		} else {
>  			copy_file(ifd, params.datafile, pad_len);
>  		}
> diff --git a/tools/zynqmpbif.c b/tools/zynqmpbif.c
> new file mode 100644
> index 0000000000..d60eff1d8b
> --- /dev/null
> +++ b/tools/zynqmpbif.c
> @@ -0,0 +1,839 @@
> +/*
> + * Copyright (C) 2018 Alexander Graf <agraf@suse.de>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include "imagetool.h"
> +#include "mkimage.h"
> +#include "zynqmpimage.h"
> +#include <elf.h>
> +#include <image.h>
> +
> +struct bif_entry {
> +	const char *filename;
> +	uint64_t flags;
> +	uint64_t dest_cpu;
> +	uint64_t exp_lvl;
> +	uint64_t dest_dev;
> +	uint64_t load;
> +	uint64_t entry;
> +};
> +
> +enum bif_flag {
> +	BIF_FLAG_AESKEYFILE,
> +	BIF_FLAG_INIT,
> +	BIF_FLAG_UDF_BH,
> +	BIF_FLAG_HEADERSIGNATURE,
> +	BIF_FLAG_PPKFILE,
> +	BIF_FLAG_PSKFILE,
> +	BIF_FLAG_SPKFILE,
> +	BIF_FLAG_SSKFILE,
> +	BIF_FLAG_SPKSIGNATURE,
> +	BIF_FLAG_FSBL_CONFIG,
> +	BIF_FLAG_AUTH_PARAMS,
> +	BIF_FLAG_KEYSRC_ENCRYPTION,
> +	BIF_FLAG_PMUFW_IMAGE,
> +	BIF_FLAG_BOOTLOADER,
> +	BIF_FLAG_TZ,
> +	BIF_FLAG_BH_KEY_IV,
> +	BIF_FLAG_BH_KEYFILE,
> +	BIF_FLAG_PUF_FILE,
> +
> +	/* Internal flags */
> +	BIF_FLAG_BIT_FILE,
> +	BIF_FLAG_ELF_FILE,
> +	BIF_FLAG_BIN_FILE,
> +};
> +
> +struct bif_flags {
> +	const char name[32];
> +	uint64_t flag;
> +	char *(*parse)(char *line, struct bif_entry *bf);
> +};
> +
> +struct bif_file_type {
> +	const char name[32];
> +	uint32_t header;
> +	int (*add)(struct bif_entry *bf);
> +};
> +
> +struct bif_output {
> +	size_t data_len;
> +	char *data;
> +	struct image_header_table *imgheader;
> +	struct zynqmp_header *header;
> +	struct partition_header *last_part;
> +};
> +
> +struct bif_output bif_output;
> +
> +static uint32_t zynqmp_csum(void *start, void *end)
> +{
> +	uint32_t checksum = 0;
> +	uint32_t *ptr32 = start;
> +
> +	while (ptr32 != end) {
> +		checksum += le32_to_cpu(*ptr32);
> +		ptr32++;
> +	}
> +
> +	return ~checksum;
> +}
> +
> +static int zynqmpbif_check_params(struct image_tool_params *params)
> +{
> +	if (!params)
> +		return 0;
> +
> +	if (params->addr != 0x0) {
> +		fprintf(stderr, "Error: Load Address can not be specified.\n");
> +		return -1;
> +	}
> +
> +	if (params->eflag) {
> +		fprintf(stderr, "Error: Entry Point can not be specified.\n");
> +		return -1;
> +	}
> +
> +	return !(params->lflag || params->dflag);
> +}
> +
> +static int zynqmpbif_check_image_types(uint8_t type)
> +{
> +	return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
> +}
> +
> +static char *parse_dest_cpu(char *line, struct bif_entry *bf)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dest_cpus); i++) {
> +		if (!strncmp(line, dest_cpus[i], strlen(dest_cpus[i]))) {
> +			bf->dest_cpu = i;
> +			return line + strlen(dest_cpus[i]);
> +		}
> +	}
> +
> +	return line;
> +}
> +
> +static char *parse_el(char *line, struct bif_entry *bf)
> +{
> +	const char *dest_els[] = { "none", "el-0", "el-1", "el-2", "el-3" };
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dest_els); i++) {
> +		if (!strncmp(line, dest_els[i], strlen(dest_els[i]))) {
> +			bf->exp_lvl = i;
> +			return line + strlen(dest_els[i]);
> +		}
> +	}
> +
> +	return line;
> +}
> +
> +static char *parse_load(char *line, struct bif_entry *bf)
> +{
> +	char *endptr;
> +
> +	bf->load = strtoll(line, &endptr, 0);
> +
> +	return endptr;
> +}
> +
> +static char *parse_entry(char *line, struct bif_entry *bf)
> +{
> +	char *endptr;
> +
> +	bf->entry = strtoll(line, &endptr, 0);
> +
> +	return endptr;
> +}
> +
> +static const struct bif_flags bif_flags[] = {
> +	{ "fsbl_config", BIF_FLAG_FSBL_CONFIG },
> +	{ "trustzone", BIF_FLAG_TZ },
> +	{ "pmufw_image", BIF_FLAG_PMUFW_IMAGE },
> +	{ "bootloader", BIF_FLAG_BOOTLOADER },
> +	{ "destination_cpu=", 0, parse_dest_cpu },
> +	{ "exception_level=", 0, parse_el },
> +	{ "load=", 0, parse_load },
> +	{ "startup=", 0, parse_entry },
> +};
> +
> +static char *read_full_file(const char *filename, size_t *size)
> +{
> +	char *buf, *bufp;
> +	struct stat sbuf;
> +	int len = 0, r, fd;
> +
> +	fd = open(filename, O_RDONLY);
> +	if (fd < 0)
> +		return NULL;
> +
> +	if (fstat(fd, &sbuf) < 0)
> +		return NULL;
> +
> +	if (size)
> +		*size = sbuf.st_size;
> +
> +	bufp = buf = malloc(sbuf.st_size);
> +	if (!buf)
> +		return NULL;
> +
> +	while (len < sbuf.st_size) {
> +		r = read(fd, bufp, sbuf.st_size - len);
> +		if (r < 0)
> +			return NULL;
> +		len += r;
> +		bufp += r;
> +	}
> +
> +	close(fd);
> +
> +	return buf;
> +}
> +
> +static int bif_add_blob(const void *data, size_t len, size_t *offset)
> +{
> +	size_t new_size = ROUND(bif_output.data_len + len, 64);
> +	uintptr_t header_off;
> +	uintptr_t last_part_off;
> +	uintptr_t imgheader_off;
> +	uintptr_t old_data = (uintptr_t)bif_output.data;
> +
> +	header_off = (uintptr_t)bif_output.header - old_data;
> +	last_part_off = (uintptr_t)bif_output.last_part - old_data;
> +	imgheader_off = (uintptr_t)bif_output.imgheader - old_data;
> +
> +	bif_output.data = realloc(bif_output.data, new_size);
> +	memcpy(bif_output.data + bif_output.data_len, data, len);
> +	if (offset)
> +		*offset = bif_output.data_len;
> +	bif_output.data_len = new_size;
> +
> +	/* Readjust internal pointers */
> +	if (bif_output.header)
> +		bif_output.header = (void*)(bif_output.data + header_off);
> +	if (bif_output.last_part)
> +		bif_output.last_part = (void*)(bif_output.data + last_part_off);
> +	if (bif_output.imgheader)
> +		bif_output.imgheader = (void*)(bif_output.data + imgheader_off);
> +
> +	return 0;
> +}
> +
> +static int bif_init(void)
> +{
> +	struct zynqmp_header header = { { 0 } };
> +	int r;
> +
> +	zynqmpimage_default_header(&header);
> +
> +	r = bif_add_blob(&header, sizeof(header), NULL);
> +	if (r)
> +		return r;
> +
> +	bif_output.header = (void*)bif_output.data;
> +
> +	return 0;
> +}
> +
> +static int bif_add_pmufw(struct bif_entry *bf, const char *data, size_t len)
> +{
> +	size_t offset;
> +
> +	if (bif_output.header->image_offset) {
> +		printf("PMUFW expected before bootloader in your .bif file!\n");
> +		return -1;
> +	}
> +
> +	bif_add_blob(data, len, &offset);
> +	len = ROUND(len, 64);
> +	bif_output.header->pfw_image_length = cpu_to_le32(len);
> +	bif_output.header->total_pfw_image_length = cpu_to_le32(len);
> +	bif_output.header->image_offset = cpu_to_le32(offset);
> +
> +	return 0;
> +}
> +
> +static int bif_add_part(struct bif_entry *bf, const char *data, size_t len)
> +{
> +	size_t parthdr_offset, part_offset;
> +	struct partition_header parthdr = {
> +		.len_enc = cpu_to_le32(len / 4),
> +		.len_unenc = cpu_to_le32(len / 4),
> +		.len = cpu_to_le32(len / 4),
> +		.entry_point = cpu_to_le64(bf->entry),
> +		.load_address = cpu_to_le64(bf->load),
> +	};
> +	int r;
> +	uint32_t csum;
> +
> +	if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE))
> +		return bif_add_pmufw(bf, data, len);
> +
> +	bif_add_blob(data, len, &part_offset);
> +	parthdr.offset = cpu_to_le32(part_offset / 4);
> +
> +	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
> +		if (bif_output.last_part) {
> +			printf("ERROR: Bootloader needs to come as first non-PMU partition");
> +			return -1;
> +		}
> +
> +		parthdr.offset = cpu_to_le32(bif_output.header->image_offset);
> +		parthdr.len = cpu_to_le32((part_offset + len -
> +			bif_output.header->image_offset) / 4);
> +		parthdr.len_enc = parthdr.len;
> +		parthdr.len_unenc = parthdr.len;
> +	}
> +
> +	/* Normalize EL */
> +	bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3;
> +	parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT;
> +	parthdr.attributes |= bf->dest_dev;
> +	parthdr.attributes |= bf->dest_cpu << PART_ATTR_DEST_CPU_SHIFT;
> +	if (bf->flags & (1ULL << BIF_FLAG_TZ))
> +		parthdr.attributes |= PART_ATTR_TZ_SECURE;
> +
> +	csum = zynqmp_csum(&parthdr, &parthdr.checksum);
> +	parthdr.checksum = cpu_to_le32(csum);
> +
> +	r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset);
> +	if (r)
> +		return r;
> +
> +	/* Add image header table if not there yet */
> +	if (!bif_output.imgheader) {
> +		size_t imghdr_off;
> +		struct image_header_table imghdr = {
> +			.version = cpu_to_le32(0x01020000),
> +			.nr_parts = 0,
> +		};
> +
> +		r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off);
> +		if (r)
> +			return r;
> +
> +		bif_output.header->image_header_table_offset = imghdr_off;
> +		bif_output.imgheader = (void*)(bif_output.data + imghdr_off);
> +	}
> +
> +	bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu(
> +		bif_output.imgheader->nr_parts) + 1);
> +
> +	/* Link to this partition header */
> +	if (bif_output.last_part) {
> +		bif_output.last_part->next_partition_offset =
> +			cpu_to_le32(parthdr_offset / 4);
> +
> +		/* Recalc checksum of last_part */
> +		csum = zynqmp_csum(bif_output.last_part,
> +				   &bif_output.last_part->checksum);
> +		bif_output.last_part->checksum = cpu_to_le32(csum);
> +	} else {
> +		bif_output.imgheader->partition_header_offset =
> +			cpu_to_le32(parthdr_offset / 4);
> +	}
> +	bif_output.last_part = (void*)(bif_output.data + parthdr_offset);
> +
> +	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
> +		bif_output.header->image_load = cpu_to_le32(bf->load);
> +		if (!bif_output.header->image_offset)
> +			bif_output.header->image_offset =
> +				cpu_to_le32(part_offset);
> +		bif_output.header->image_size = cpu_to_le32(len);
> +		bif_output.header->image_stored_size = cpu_to_le32(len);
> +	}
> +
> +	return 0;
> +}
> +
> +/* Add .bit bitstream */
> +static int bif_add_bit(struct bif_entry *bf)
> +{
> +	char *bit = read_full_file(bf->filename, NULL);
> +	char *bitbin;
> +	uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
> +				     0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
> +	uint16_t len;
> +	uint32_t bitlen;
> +	int i;
> +
> +	if (!bit)
> +		return -1;
> +
> +	/* Skip initial header */
> +	if (memcmp(bit, initial_header, sizeof(initial_header)))
> +		return -1;
> +
> +	bit += sizeof(initial_header);
> +
> +	/* Design name */
> +	len = be16_to_cpu(*(uint16_t*)bit);
> +	bit += sizeof(uint16_t);
> +	debug("Design: %s\n", bit);
> +	bit += len;
> +
> +	/* Device identifier */
> +	if (*bit != 'b')
> +		return -1;
> +	bit++;
> +	len = be16_to_cpu(*(uint16_t*)bit);
> +	bit += sizeof(uint16_t);
> +	debug("Device: %s\n", bit);
> +	bit += len;
> +
> +	/* Date */
> +	if (*bit != 'c')
> +		return -1;
> +	bit++;
> +	len = be16_to_cpu(*(uint16_t*)bit);
> +	bit += sizeof(uint16_t);
> +	debug("Date: %s\n", bit);
> +	bit += len;
> +
> +	/* Time */
> +	if (*bit != 'd')
> +		return -1;
> +	bit++;
> +	len = be16_to_cpu(*(uint16_t*)bit);
> +	bit += sizeof(uint16_t);
> +	debug("Time: %s\n", bit);
> +	bit += len;
> +
> +	/* Bitstream length */
> +	if (*bit != 'e')
> +		return -1;
> +	bit++;
> +	bitlen = be32_to_cpu(*(uint32_t*)bit);
> +	bit += sizeof(uint32_t);
> +	bitbin = bit;
> +
> +	debug("Bitstream Length: 0x%x\n", bitlen);
> +	for (i = 0; i < bitlen; i += sizeof(uint32_t)) {
> +		uint32_t *bitbin32 = (uint32_t*)&bitbin[i];
> +		*bitbin32 = __swab32(*bitbin32);
> +	}
> +
> +	if (!bf->dest_dev)
> +		bf->dest_dev = PART_ATTR_DEST_DEVICE_PL;
> +
> +	bf->load = 0xffffffff;
> +	bf->entry = 0;
> +
> +	bf->flags |= 1ULL << BIF_FLAG_BIT_FILE;
> +	return bif_add_part(bf, bit, bitlen);
> +}
> +
> +/* Add .bin bitstream */
> +static int bif_add_bin(struct bif_entry *bf)
> +{
> +	size_t size;
> +	char *bin = read_full_file(bf->filename, &size);
> +
> +	if (!bf->dest_dev)
> +		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
> +
> +	bf->flags |= 1ULL << BIF_FLAG_BIN_FILE;
> +	return bif_add_part(bf, bin, size);
> +}
> +
> +/* Add elf file */
> +static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr)
> +{
> +	Elf64_Ehdr *ehdr;
> +	Elf64_Shdr *shdr;
> +	size_t min_addr = -1, max_addr = 0;
> +	char *flat;
> +	int i;
> +
> +	ehdr = (void*)elf;
> +	shdr = (void*)(elf + le64_to_cpu(ehdr->e_shoff));
> +
> +	/* Look for smallest / biggest address */
> +	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++) {
> +		if (!shdr->sh_size || !shdr->sh_addr ||
> +		    !(shdr->sh_flags & SHF_ALLOC) ||
> +		    (shdr->sh_type == SHT_NOBITS)) {
> +			shdr++;
> +			continue;
> +		}
> +
> +		if (le64_to_cpu(shdr->sh_addr) < min_addr)
> +			min_addr = le64_to_cpu(shdr->sh_addr);
> +		if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) >
> +			max_addr)
> +			max_addr = le64_to_cpu(shdr->sh_addr) +
> +				   le64_to_cpu(shdr->sh_size);
> +
> +		shdr++;
> +	}
> +
> +	*load_addr = min_addr;
> +	*flat_size = max_addr - min_addr;
> +	flat = calloc(1, *flat_size);
> +	if (!flat)
> +		return NULL;
> +
> +	shdr = (void*)(elf + le64_to_cpu(ehdr->e_shoff));
> +	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++) {
> +		char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr;
> +		char *src = elf + le64_to_cpu(shdr->sh_offset);
> +
> +		if (!shdr->sh_size || !shdr->sh_addr ||
> +		    !(shdr->sh_flags & SHF_ALLOC)) {
> +			shdr++;
> +			continue;
> +		}
> +
> +		if (shdr->sh_type != SHT_NOBITS) {
> +
> +			memcpy(dst, src, le64_to_cpu(shdr->sh_size));
> +		}
> +		shdr++;
> +	}
> +
> +	return flat;
> +}
> +
> +static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr)
> +{
> +	Elf32_Ehdr *ehdr;
> +	Elf32_Shdr *shdr;
> +	size_t min_addr = -1, max_addr = 0;
> +	char *flat;
> +	int i;
> +
> +	ehdr = (void*)elf;
> +	shdr = (void*)(elf + le32_to_cpu(ehdr->e_shoff));
> +
> +	/* Look for smallest / biggest address */
> +	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++) {
> +		if (!shdr->sh_size || !shdr->sh_addr ||
> +		    !(shdr->sh_flags & SHF_ALLOC) ||
> +		    (shdr->sh_type == SHT_NOBITS)) {
> +			shdr++;
> +			continue;
> +		}
> +
> +		if (le32_to_cpu(shdr->sh_addr) < min_addr)
> +			min_addr = le32_to_cpu(shdr->sh_addr);
> +		if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) >
> +			max_addr)
> +			max_addr = le32_to_cpu(shdr->sh_addr) +
> +				   le32_to_cpu(shdr->sh_size);
> +
> +		shdr++;
> +	}
> +
> +	*load_addr = min_addr;
> +	*flat_size = max_addr - min_addr;
> +	flat = calloc(1, *flat_size);
> +	if (!flat)
> +		return NULL;
> +
> +	shdr = (void*)(elf + le32_to_cpu(ehdr->e_shoff));
> +	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++) {
> +		char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr;
> +		char *src = elf + le32_to_cpu(shdr->sh_offset);
> +
> +		if (!shdr->sh_size || !shdr->sh_addr ||
> +		    !(shdr->sh_flags & SHF_ALLOC)) {
> +			shdr++;
> +			continue;
> +		}
> +
> +		if (shdr->sh_type != SHT_NOBITS) {
> +
> +			memcpy(dst, src, le32_to_cpu(shdr->sh_size));
> +		}
> +		shdr++;
> +	}
> +
> +	return flat;
> +}
> +
> +static int bif_add_elf(struct bif_entry *bf)
> +{
> +	size_t size;
> +	size_t elf_size;
> +	char *elf;
> +	char *flat;
> +	size_t load_addr;
> +	Elf32_Ehdr *ehdr32;
> +	Elf64_Ehdr *ehdr64;
> +
> +	elf = read_full_file(bf->filename, &elf_size);
> +	if (!elf)
> +		return -1;
> +
> +	ehdr32 = (void*)elf;
> +	ehdr64 = (void*)elf;
> +
> +	switch (ehdr32->e_ident[EI_CLASS]) {
> +	case ELFCLASS32:
> +		flat = elf2flat32(elf, &size, &load_addr);
> +		bf->entry = le32_to_cpu(ehdr32->e_entry);
> +		break;
> +	case ELFCLASS64:
> +		flat = elf2flat64(elf, &size, &load_addr);
> +		bf->entry = le64_to_cpu(ehdr64->e_entry);
> +		break;
> +	default:
> +		printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]);
> +		return -1;
> +	}
> +
> +	if (!flat)
> +		return -1;
> +
> +	bf->load = load_addr;
> +	if (!bf->dest_dev)
> +		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
> +
> +	bf->flags |= 1ULL << BIF_FLAG_ELF_FILE;
> +	return bif_add_part(bf, flat, size);
> +}
> +
> +static const struct bif_file_type bif_file_types[] = {
> +	{
> +		.name = "bitstream (.bit)",
> +		.header = 0x00090ff0,
> +		.add = bif_add_bit,
> +	},
> +
> +	{
> +		.name = "ELF",
> +		.header = 0x7f454c46,
> +		.add = bif_add_elf,
> +	},
> +
> +	/* Anything else is a .bin file */
> +	{
> +		.name = ".bin",
> +		.add = bif_add_bin,
> +	},
> +};
> +
> +static const struct bif_flags *find_flag(char *str)
> +{
> +	const struct bif_flags *bf;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(bif_flags); i++) {
> +		bf = &bif_flags[i];
> +		if (!strncmp(bf->name, str, strlen(bf->name)))
> +			return bf;
> +	}
> +
> +	printf("ERROR: Flag '%s' not found\n", str);
> +
> +	return NULL;
> +}
> +
> +static int bif_open_file(struct bif_entry *entry)
> +{
> +	int fd = open(entry->filename, O_RDONLY);
> +
> +	if (fd < 0)
> +		printf("Error opening file %s\n", entry->filename);
> +
> +	return fd;
> +}
> +
> +static const struct bif_file_type *get_file_type(struct bif_entry *entry)
> +{
> +	int fd = bif_open_file(entry);
> +	uint32_t header;
> +	int i;
> +
> +	if (fd < 0)
> +		return NULL;
> +
> +	if (read(fd, &header, sizeof(header)) != sizeof(header)) {
> +		printf("Error reading file %s", entry->filename);
> +		return NULL;
> +	}
> +
> +	close(fd);
> +
> +	for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) {
> +		const struct bif_file_type *type = &bif_file_types[i];
> +
> +		if (!type->header)
> +			return type;
> +		if (type->header == be32_to_cpu(header))
> +			return type;
> +	}
> +
> +	return NULL;
> +}
> +
> +#define NEXT_CHAR(str, chr) ({		\
> +	char *_n = strchr(str, chr);	\
> +	if (!_n)			\
> +		goto err;		\
> +	_n;				\
> +})
> +
> +static char *skip_whitespace(char *str)
> +{
> +	while (*str == ' ' || *str == '\t')
> +		str++;
> +
> +	return str;
> +}
> +
> +void zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams)
> +{
> +	char *bif, *bifp, *bifpn;
> +	char *line;
> +	struct bif_entry entries[32] = { { 0 } };
> +	int nr_entries = 0;
> +	struct bif_entry *entry = entries;
> +	size_t len;
> +	int i;
> +	uint32_t csum;
> +
> +	bif_init();
> +
> +	/* Read .bif input file */
> +	bifp = bif = read_full_file(mparams->datafile, NULL);
> +	if (!bif)
> +		goto err;
> +
> +	/* Interpret .bif file */
> +	bifp = bif;
> +
> +	/* A bif description starts with a { section */
> +	bifp = NEXT_CHAR(bifp, '{') + 1;
> +
> +	/* Read every line */
> +	while (1) {
> +		bifpn = NEXT_CHAR(bifp, '\n');
> +
> +		*bifpn = '\0';
> +		bifpn++;
> +		line = bifp;
> +
> +		line = skip_whitespace(line);
> +
> +		/* Attributes? */
> +		if (*line == '[') {
> +			line++;
> +			while (1) {
> +				const struct bif_flags *bf;
> +
> +				line = skip_whitespace(line);
> +				bf = find_flag(line);
> +				if (!bf)
> +					goto err;
> +
> +				line += strlen(bf->name);
> +				if (bf->parse)
> +					line = bf->parse(line, entry);
> +				else
> +					entry->flags |= 1ULL << bf->flag;
> +
> +				/* Go to next attribute or quit */
> +				if (*line == ']') {
> +					line++;
> +					break;
> +				}
> +				if (*line == ',')
> +					line++;
> +			}
> +		}
> +
> +		/* End of image description */
> +		if (*line == '}')
> +			break;
> +
> +		if (*line) {
> +			line = skip_whitespace(line);
> +			entry->filename = line;
> +			nr_entries++;
> +			entry++;
> +		}
> +
> +		/* Use next line */
> +		bifp = bifpn;
> +	}
> +
> +	for (i = 0; i < nr_entries; i++) {
> +		debug("Entry flags=%#lx name=%s\n", entries[i].flags,
> +		      entries[i].filename);
> +	}
> +
> +	for (i = 0; i < nr_entries; i++) {
> +		struct bif_entry *entry = &entries[i];
> +		const struct bif_file_type *type;
> +		int r;
> +
> +		type = get_file_type(entry);
> +		if (!type)
> +			goto err;
> +
> +		debug("type=%s file=%s\n", type->name, entry->filename);
> +		r = type->add(entry);
> +		if (r)
> +			goto err;
> +	}
> +
> +	/* Calculate checksums */
> +	csum = zynqmp_csum(&bif_output.header->width_detection,
> +			   &bif_output.header->checksum);
> +	bif_output.header->checksum = cpu_to_le32(csum);
> +
> +	if (bif_output.imgheader) {
> +		csum = zynqmp_csum(bif_output.imgheader,
> +				   &bif_output.imgheader->checksum);
> +		bif_output.imgheader->checksum = cpu_to_le32(csum);
> +	}
> +
> +	/* Write headers and components */
> +	if (lseek(outfd, 0, SEEK_SET) != 0)
> +		goto err;
> +
> +	len = bif_output.data_len;
> +	bifp = bif_output.data;
> +	while (len) {
> +		int r;
> +		r = write(outfd, bifp, len);
> +		if (r < 0)
> +			goto err;
> +		len -= r;
> +		bifp += r;
> +	}
> +
> +	return;
> +
> +err:
> +	fprintf(stderr, "Error: Failed to create image.\n");
> +}
> +
> +/* Needs to be stubbed out so we can print after creation */
> +static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd,
> +		struct image_tool_params *params)
> +{
> +}
> +
> +static struct zynqmp_header zynqmpimage_header;
> +
> +U_BOOT_IMAGE_TYPE(
> +	zynqmpbif,
> +	"Xilinx ZynqMP Boot Image support (bif)",
> +	sizeof(struct zynqmp_header),
> +	(void *)&zynqmpimage_header,
> +	zynqmpbif_check_params,
> +	NULL,
> +	zynqmpimage_print_header,
> +	zynqmpbif_set_header,
> +	NULL,
> +	zynqmpbif_check_image_types,
> +	NULL,
> +	NULL
> +);
> diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
> index 8f4766f077..145391de3e 100644
> --- a/tools/zynqmpimage.c
> +++ b/tools/zynqmpimage.c
> @@ -87,7 +87,7 @@ static uint32_t zynqmpimage_checksum(struct zynqmp_header *ptr)
>  	return cpu_to_le32(checksum);
>  }
>  
> -static void zynqmpimage_default_header(struct zynqmp_header *ptr)
> +void zynqmpimage_default_header(struct zynqmp_header *ptr)
>  {
>  	int i;
>  
> @@ -211,7 +211,7 @@ static void print_partition(const void *ptr, const struct partition_header *ph)
>  	printf("    Checksum   : 0x%08x\n", le32_to_cpu(ph->checksum));
>  }
>  
> -static void zynqmpimage_print_header(const void *ptr)
> +void zynqmpimage_print_header(const void *ptr)
>  {
>  	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
>  	int i;
> diff --git a/tools/zynqmpimage.h b/tools/zynqmpimage.h
> index f3b5c195ad..b421e4f94c 100644
> --- a/tools/zynqmpimage.h
> +++ b/tools/zynqmpimage.h
> @@ -129,4 +129,7 @@ struct zynqmp_header {
>  	uint32_t __reserved4[66]; /* 0x9c0 */
>  };
>  
> +void zynqmpimage_default_header(struct zynqmp_header *ptr);
> +void zynqmpimage_print_header(const void *ptr);
> +
>  #endif /* _ZYNQMPIMAGE_H_ */
> 

Also please run checkpatch over it.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support
  2018-04-12 13:48 ` [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support Alexander Graf
@ 2018-04-13  9:40   ` Michal Simek
  0 siblings, 0 replies; 6+ messages in thread
From: Michal Simek @ 2018-04-13  9:40 UTC (permalink / raw)
  To: u-boot

Hi,

On 12.4.2018 15:48, Alexander Graf wrote:
> The zynqmp image format has support for inline partitions which are
> used by FSBL to describe payloads that are loaded by FSBL itself.
> 
> While we can't create images that contain partitions (yet), we should
> still at least be able to examine them and show the user what's inside
> when we analyze an image created by bootgen.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> 
> ---
> 
> v1 -> v2:
> 
>   - prettify defines
>   - fix offset and size outputs
>   - add u-boot as payload target
>   - align CPU names with bif
>   - add shift constants
>   - add U-Boot as potential partition owner
>   - mention documentation source
>   - add HEADER_CPU_SELECT_A53_64BIT define


first of all please run checkpatch on this patch. I see several issues
there.

The rest looks good.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-04-13  9:40 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-12 13:48 [U-Boot] [PATCH v3 0/3] tools: zynqmpimage: Support partitions Alexander Graf
2018-04-12 13:48 ` [U-Boot] [PATCH v3 1/3] tools: zynqmpimage: Add partition read support Alexander Graf
2018-04-13  9:40   ` Michal Simek
2018-04-12 13:48 ` [U-Boot] [PATCH v3 2/3] tools: zynqmpimage: Move defines to header Alexander Graf
2018-04-12 13:48 ` [U-Boot] [PATCH v3 3/3] tools: zynqmpimage: Add bif support Alexander Graf
2018-04-13  9:40   ` Michal Simek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.