From patchwork Thu Mar 15 21:49:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 131886 Delivered-To: patch@linaro.org Received: by 10.46.84.17 with SMTP id i17csp1648112ljb; Thu, 15 Mar 2018 14:49:31 -0700 (PDT) X-Google-Smtp-Source: AG47ELvsp9V6QNfHXkyWk60y6QS6jwdo2BiqjUfOj18SU9NEImf2QrUnqQIWLCj/DIHdUHGBXHBZ X-Received: by 10.80.201.76 with SMTP id p12mr10646755edh.199.1521150571107; Thu, 15 Mar 2018 14:49:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521150571; cv=none; d=google.com; s=arc-20160816; b=se1MLC9EV5VMe+OiYFBVmxeJwoRyYnYiP0X1rZ8sZ4v5h69a9EBL68BB4h+K7e+fIF gaPDTGjwzAEHOfzQY1xGh1CmtcG46VTDdlcwG+P+96tY2u7TtCFaAcHwAQbF4E4J4DiT QU17E7dfR/rYkYK4RYax9BSShwrZIYaCQQbOJMWnIwEMXsr0Le1Xwxy4hbuI41U3TBuy notmHhYYeoPR6DRuJO4yZrW+DI7ANFyz5GfLOWGlZd9foCWhLzRGYYS+HVXvZe5/jPsR zv0eIWFxhwKgF4hSVT+RRdLHSdp044lR6xWPPtGMsI5ardFsd3Up2dG6fxvbcQzG1DDE moCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:message-id:date:to:from :arc-authentication-results; bh=lpcFfUAbMoKbEA6+7gp4w54Fv96900Hg4AReSvDlVkI=; b=JYFkNU4S3TuqOiGSPXME0cWDx10V+1GWIhw/B/RSjzzw09XfUPfXEGnTmPD6DGjHR7 xHr+3Uu/lrMX/WMzzbK7JYCutWrCZ29iVaA07hOaw7+Wrv4W3ilBWevVhPfoFFCdedoA thOOGfli22hBKlHanVbehkwRj1xeg5T5ANw09A9frUWdYfpvZ0t85RIxUi7RLoh6lEMr dMP57RfM334IE8nIYT3CkJqFTcHVQOisiUJ2/UEdXImKe/zWUvJvttVwr/7qxBbWgJcN EEGWXMZ8KQE/NwaTNZDBd+JcovZpBrkBsrDhWHEVeg30QhJ1rlSfOQgtN4VNfM6gPStb 7w9g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id r1si902210edm.553.2018.03.15.14.49.29; Thu, 15 Mar 2018 14:49:31 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by lists.denx.de (Postfix, from userid 105) id AFE7BC21E07; Thu, 15 Mar 2018 21:49:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 690DDC21DAF; Thu, 15 Mar 2018 21:49:24 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 708B7C21DAF; Thu, 15 Mar 2018 21:49:23 +0000 (UTC) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by lists.denx.de (Postfix) with ESMTPS id 085DEC21BE5 for ; Thu, 15 Mar 2018 21:49:23 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 8DDD5B002; Thu, 15 Mar 2018 21:49:22 +0000 (UTC) From: Alexander Graf To: u-boot@lists.denx.de Date: Thu, 15 Mar 2018 22:49:22 +0100 Message-Id: <20180315214922.58745-1-agraf@suse.de> X-Mailer: git-send-email 2.12.3 Cc: Michal Simek Subject: [U-Boot] [PATCH] tools: zynqimage: Add partition read support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "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 --- tools/zynqmpimage.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 1 deletion(-) diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index f48ac6dbe5..5183ea9bc8 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -80,6 +80,71 @@ struct zynqmp_reginit { #define HEADER_INTERRUPT_VECTORS 8 #define HEADER_REGINITS 256 +struct image_header_table { + uint32_t version; + uint32_t nr_parts; + uint32_t partition_header_offset; /* divided by 4 */ + uint32_t __reserved1; + uint32_t auth_certificate_offset; + uint32_t partition_present_device; + uint32_t __reserved2[9]; + uint32_t checksum; +}; + +#define PART_ATTR_VEC_LOCATION 0x800000 +#define PART_ATTR_BLOCK_SIZE_MASK 0x700000 +#define PART_ATTR_BIG_ENDIAN 0x040000 +#define PART_ATTR_PART_OWNER_MASK 0x030000 +#define PART_ATTR_PART_OWNER_FSBL 0x000000 +#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_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_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_A53_EXEC_AARCH32 0x000008 +#define PART_ATTR_TARGET_EL_MASK 0x000006 +#define PART_ATTR_TR_SECURE_MASK 0x000001 + +static const char *dest_cpus[0x10] = { + "none", "A53-0", "A53-1", "A53-2", "A53-3", "R5-0", "R5-1", + "R5-L", "PMU", "unknown", "unknown", "unknown", "unknown", + "unknown", "unknown", "unknown" +}; + +struct partition_header { + uint32_t len_enc; /* divided by 4 */ + uint32_t len_unenc; /* divided by 4 */ + uint32_t len; /* divided by 4 */ + uint32_t next_partition_offset; + uint64_t entry_point; + uint64_t load_address; + uint32_t offset; /* divided by 4 */ + uint32_t attributes; + uint32_t section_count; + uint32_t checksum_offset; /* divided by 4 */ + uint32_t image_header_offset; + uint32_t auth_certificate_offset; + uint32_t __reserved1[1]; + uint32_t checksum; +}; + struct zynqmp_header { uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */ uint32_t width_detection; /* 0x20 */ @@ -93,7 +158,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 */ }; @@ -173,6 +240,74 @@ 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); + const char *part_owner; + const char *dest_devs[0x8] = { + "none", "PS", "PL", "PMU", "unknown", "unknown", "unknown", + "unknown" + }; + + if ((attr & PART_ATTR_PART_OWNER_MASK) == PART_ATTR_PART_OWNER_FSBL) + part_owner = "FSBL"; + else + part_owner = "Unknown"; + + 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)); + printf(" Size : %lu bytes\n", + (unsigned long)le32_to_cpu(ph->len) * 4); + 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_TR_SECURE_MASK) + 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 +348,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); }