From patchwork Wed Nov 18 17:32:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 1402433 X-Patchwork-Delegate: andre.przywara@arm.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=arm.com Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CbqfC4kL3z9sPB for ; Thu, 19 Nov 2020 04:33:23 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id BB309825DD; Wed, 18 Nov 2020 18:32:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 053CE825D0; Wed, 18 Nov 2020 18:32:35 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 6CB45825B9 for ; Wed, 18 Nov 2020 18:32:30 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=andre.przywara@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DB25D1534; Wed, 18 Nov 2020 09:32:28 -0800 (PST) Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B9BF53F718; Wed, 18 Nov 2020 09:32:27 -0800 (PST) From: Andre Przywara To: Jagan Teki , Simon Glass Cc: Tom Rini , Samuel Holland , u-boot@lists.denx.de, linux-sunxi@googlegroups.com Subject: [PATCH v3 2/3] tools: mkimage: Add Allwinner eGON support Date: Wed, 18 Nov 2020 17:32:03 +0000 Message-Id: <20201118173204.5811-3-andre.przywara@arm.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20201118173204.5811-1-andre.przywara@arm.com> References: <20201118173204.5811-1-andre.przywara@arm.com> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean So far we used the separate mksunxiboot tool for generating a bootable image for Allwinner SPLs, probably just for historical reasons. Use the mkimage framework to generate a so called eGON image the Allwinner BROM expects. The new image type is called "sunxi_egon", to differentiate it from the (still to be implemented) secure boot TOC0 image. Signed-off-by: Andre Przywara --- common/image.c | 1 + include/image.h | 1 + include/sunxi_image.h | 1 + tools/Makefile | 1 + tools/sunxi_egon.c | 136 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 tools/sunxi_egon.c diff --git a/common/image.c b/common/image.c index 451fc689a89..6923dac7c07 100644 --- a/common/image.c +++ b/common/image.c @@ -189,6 +189,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_STM32IMAGE, "stm32image", "STMicroelectronics STM32 Image" }, { IH_TYPE_MTKIMAGE, "mtk_image", "MediaTek BootROM loadable Image" }, { IH_TYPE_COPRO, "copro", "Coprocessor Image"}, + { IH_TYPE_SUNXI_EGON, "sunxi_egon", "Allwinner eGON Boot Image" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index 00bc03bebec..89bfca2155a 100644 --- a/include/image.h +++ b/include/image.h @@ -308,6 +308,7 @@ enum { IH_TYPE_IMX8MIMAGE, /* Freescale IMX8MBoot Image */ IH_TYPE_IMX8IMAGE, /* Freescale IMX8Boot Image */ IH_TYPE_COPRO, /* Coprocessor Image for remoteproc*/ + IH_TYPE_SUNXI_EGON, /* Allwinner eGON Boot Image */ IH_TYPE_COUNT, /* Number of image types */ }; diff --git a/include/sunxi_image.h b/include/sunxi_image.h index d0d1290eb72..5b2055c0af3 100644 --- a/include/sunxi_image.h +++ b/include/sunxi_image.h @@ -13,6 +13,7 @@ #define SUNXI_IMAGE_H #define BOOT0_MAGIC "eGON.BT0" +#define BROM_STAMP_VALUE 0x5f0a6c39 #define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */ #define SPL_MAJOR_BITS 3 #define SPL_MINOR_BITS 5 diff --git a/tools/Makefile b/tools/Makefile index 51123fd9298..2c9a0c4c4e7 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -104,6 +104,7 @@ dumpimage-mkimage-objs := aisimage.o \ stm32image.o \ $(ROCKCHIP_OBS) \ socfpgaimage.o \ + sunxi_egon.o \ lib/crc16.o \ lib/sha1.o \ lib/sha256.o \ diff --git a/tools/sunxi_egon.c b/tools/sunxi_egon.c new file mode 100644 index 00000000000..8987794518a --- /dev/null +++ b/tools/sunxi_egon.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 Arm Ltd. + */ + +#include "imagetool.h" +#include + +#include + +/* + * NAND requires 8K padding. SD/eMMC gets away with 512 bytes, + * but let's use the larger padding to cover both. + */ +#define PAD_SIZE 8192 + +static int egon_check_params(struct image_tool_params *params) +{ + /* We just need a binary image file. */ + return !params->dflag; +} + +static int egon_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params) +{ + const struct boot_file_head *header = (void *)ptr; + uint32_t length; + + /* First 4 bytes must be an ARM branch instruction. */ + if ((le32_to_cpu(header->b_instruction) & 0xff000000) != 0xea000000) + return EXIT_FAILURE; + + if (memcmp(header->magic, BOOT0_MAGIC, sizeof(header->magic))) + return EXIT_FAILURE; + + length = le32_to_cpu(header->length); + /* Must be at least 512 byte aligned. */ + if (length & 511) + return EXIT_FAILURE; + + /* + * Image could also contain U-Boot proper, so could be bigger. + * But it must not be shorter. + */ + if (image_size < length) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void egon_print_header(const void *buf) +{ + const struct boot_file_head *header = buf; + + printf("Allwinner eGON image, size: %d bytes\n", + le32_to_cpu(header->length)); + + if (memcmp(header->spl_signature, SPL_SIGNATURE, 3)) + return; + + printf("\tSPL header version %d.%d\n", + header->spl_signature[3] >> SPL_MINOR_BITS, + header->spl_signature[3] & ((1U << SPL_MINOR_BITS) - 1)); + if (header->spl_signature[3] >= SPL_DT_HEADER_VERSION) { + uint32_t dt_name_offs = le32_to_cpu(header->dt_name_offset); + + if (dt_name_offs > 0) + printf("\tDT name: %s\n", (char *)buf + dt_name_offs); + } +} + +static void egon_set_header(void *buf, struct stat *sbuf, int infd, + struct image_tool_params *params) +{ + struct boot_file_head *header = buf; + uint32_t *buf32 = buf; + uint32_t checksum = 0, value; + int i; + + /* Generate an ARM branch instruction to jump over the header. */ + value = 0xea000000 | (sizeof(struct boot_file_head) / 4 - 2); + header->b_instruction = cpu_to_le32(value); + + memcpy(header->magic, BOOT0_MAGIC, sizeof(header->magic)); + header->check_sum = cpu_to_le32(BROM_STAMP_VALUE); + header->length = cpu_to_le32(params->file_size); + + memcpy(header->spl_signature, SPL_SIGNATURE, 3); + + /* If an image name has been provided, use it as the DT name. */ + if (params->imagename && params->imagename[0]) { + header->spl_signature[3] = SPL_DT_HEADER_VERSION; + + value = offsetof(struct boot_file_head, string_pool); + header->dt_name_offset = cpu_to_le32(value); + + strncpy((char *)header->string_pool, params->imagename, 52); + /* Make sure we have a terminating zero byte. */ + ((char *)header->string_pool)[51] = 0; + } else + header->spl_signature[3] = SPL_ENV_HEADER_VERSION; + + /* Calculate the checksum. Yes, it's that simple. */ + for (i = 0; i < sbuf->st_size / 4; i++) + checksum += le32_to_cpu(buf32[i]); + header->check_sum = cpu_to_le32(checksum); +} + +static int egon_check_image_type(uint8_t type) +{ + return type == IH_TYPE_SUNXI_EGON ? 0 : 1; +} + +static int egon_vrec_header(struct image_tool_params *params, + struct image_type_params *tparams) +{ + tparams->hdr = calloc(sizeof(struct boot_file_head), 1); + + /* Return padding to 8K blocks. */ + return ALIGN(params->file_size, PAD_SIZE) - params->file_size; +} + +U_BOOT_IMAGE_TYPE( + sunxi_egon, + "Allwinner eGON Boot Image support", + sizeof(struct boot_file_head), + NULL, + egon_check_params, + egon_verify_header, + egon_print_header, + egon_set_header, + NULL, + egon_check_image_type, + NULL, + egon_vrec_header +);