From patchwork Fri Aug 11 20:56:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pawe=C5=82_Jarosz?= X-Patchwork-Id: 800748 X-Patchwork-Delegate: philipp.tomsich@theobroma-systems.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="faykV3tv"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xTcqd1qxRz9sRq for ; Sat, 12 Aug 2017 07:01:17 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id F1ABAC21DDC; Fri, 11 Aug 2017 21:00:02 +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=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID 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 2D190C21E11; Fri, 11 Aug 2017 20:57:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 89666C21E0A; Fri, 11 Aug 2017 20:56:51 +0000 (UTC) Received: from mail-lf0-f66.google.com (mail-lf0-f66.google.com [209.85.215.66]) by lists.denx.de (Postfix) with ESMTPS id EF76CC21E1B for ; Fri, 11 Aug 2017 20:56:39 +0000 (UTC) Received: by mail-lf0-f66.google.com with SMTP id t128so2995308lff.3 for ; Fri, 11 Aug 2017 13:56:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=FqmHKo52wzfqXyfNW9iT91Fg76AsdyxWAxMA25BOWzw=; b=faykV3tv+Flei5C3Cq9YG0s8lRIk8AsJf+G9ZoUFpXwI7xdMnlz/bJtOUA55jyPkWk Ff1bXH0gYQc7TaxrXn88Vt45Zr9/KEnDqtntl7NJjQCl2TVPxMh+3XNjvS2NX84HZwxC KVqhLBtpyf6f68lOwO/Wbneqri0G0g+ri7ZwJqP54QPS1r2ZC7zRF2QsGaWBf5Huxx5D KEs+v5WzPcdjTOqXc0f9itRB7nK09FPjRvpWzccKTJHCgHTDaqpaPADtKa/MJmmSG5fD E5mOlrSMHLSFNKVGZ9HDic7z0bSbUgmfAdKVP4uGohGa2DQnGaHzQET9XXeTNq7E8qlr TclQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=FqmHKo52wzfqXyfNW9iT91Fg76AsdyxWAxMA25BOWzw=; b=rw49P8+E4lDiZm44cViRVAxEH51W+i+U/7zzXzVWF422TQiriIFEpHBIXC0NWjJ23N 2wwLM/lvlsHHNI1Uz4OffWUVMW5iiNPqOBDzRnNYO6aUQWzAO1e/hIVdJqIQoINS6nqU 5N1r+Q7/cLSG1hiJd6lVvB/+YOHbvBzDPNWsNVyN1Ye0FbSYeE9yRQV5Q1VebQH5SX2u O4MYCrmaj6fw+8qICPYBHnNEQXQisR0utLghPddzr+gyJNt5yikT4FmBOiDXjQ6K7HQW tiztMH3xy6cXVsXeorNpZ3cYLTiVbBWiNpZb9eZShiWkzvqHEYX90N4ZJlnY8GPkzVCa jmbQ== X-Gm-Message-State: AHYfb5hegPjZg7W0bCUodC2vj6o+CSnM+9LTKr45G3OibTYWaruBFlGd rb/JIdD0ZPEpOg== X-Received: by 10.46.19.10 with SMTP id 10mr5679141ljt.173.1502484999324; Fri, 11 Aug 2017 13:56:39 -0700 (PDT) Received: from vaio-ubuntu (admf2.neoplus.adsl.tpnet.pl. [79.185.35.2]) by smtp.gmail.com with ESMTPSA id s186sm255640lja.17.2017.08.11.13.56.38 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Aug 2017 13:56:38 -0700 (PDT) Date: Fri, 11 Aug 2017 22:56:53 +0200 From: =?utf-8?B?UGF3ZcWC?= Jarosz To: u-boot@lists.denx.de Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) Subject: [U-Boot] [PATCH v2 11/19] rockchip: mkimage: add support for rockchip nand boot image 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The Rockchip boot ROM requires a particular file format for booting from NAND: * It starts with 512-byte, rc4 encoded header and is aligned to nand page size * Then first 2KB of first stage loader (tpl) aligned to nand page size * n empty pages * second 2KB of first stage loader (tpl) aligned to nand page size * n empty pages * ... * first 2KB of second stage loader (spl) aligned to nand page size * n empty pages * second 2KB of first stage loader (spl) aligned to nand page size * n empty pages * ... Size of spl and tpl must be aligned to 2KB. example usage for nand with page size 16384 and one empty page in iteration: # mkimage -n rk3066 -T rknand -d ./u-boot/tpl/u-boot-tpl.bin:./u-boot/spl/u-boot-spl.bin -X 16384,1 out Signed-off-by: Paweł Jarosz --- Changes since v1: - none common/image.c | 1 + include/image.h | 1 + tools/Makefile | 2 +- tools/imagetool.h | 1 + tools/mkimage.c | 8 ++- tools/rkcommon.c | 10 ++-- tools/rkcommon.h | 10 +++- tools/rknand.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/rksd.c | 2 +- tools/rkspi.c | 2 +- 10 files changed, 183 insertions(+), 10 deletions(-) create mode 100644 tools/rknand.c diff --git a/common/image.c b/common/image.c index 0f88984..1d677bc 100644 --- a/common/image.c +++ b/common/image.c @@ -167,6 +167,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_FPGA, "fpga", "FPGA Image" }, { IH_TYPE_TEE, "tee", "Trusted Execution Environment Image",}, { IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" }, + { IH_TYPE_RKNAND, "rknand", "Rockchip NAND Boot Image" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index c6f1513..7d90f36 100644 --- a/include/image.h +++ b/include/image.h @@ -269,6 +269,7 @@ enum { IH_TYPE_VYBRIDIMAGE, /* VYBRID .vyb Image */ IH_TYPE_TEE, /* Trusted Execution Environment OS Image */ IH_TYPE_FIRMWARE_IVT, /* Firmware Image with HABv4 IVT */ + IH_TYPE_RKNAND, /* Rockchip NAND Boot Image */ IH_TYPE_COUNT, /* Number of image types */ }; diff --git a/tools/Makefile b/tools/Makefile index 0743677..52858bc 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -79,7 +79,7 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ rsa-sign.o rsa-verify.o rsa-checksum.o \ rsa-mod-exp.o) -ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o +ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rknand.o rksd.o rkspi.o # common objs for dumpimage and mkimage dumpimage-mkimage-objs := aisimage.o \ diff --git a/tools/imagetool.h b/tools/imagetool.h index a8d5054..0b2a707 100644 --- a/tools/imagetool.h +++ b/tools/imagetool.h @@ -77,6 +77,7 @@ struct image_tool_params { bool quiet; /* Don't output text in normal operation */ unsigned int external_offset; /* Add padding to external data */ const char *engine_id; /* Engine to use for signing */ + char *extraparams; /* Extra parameters for img creation (-X) */ }; /* diff --git a/tools/mkimage.c b/tools/mkimage.c index 28ff35e..ffc91d2 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -144,7 +144,7 @@ static void process_args(int argc, char **argv) int opt; while ((opt = getopt(argc, argv, - "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) { + "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVxX:")) != -1) { switch (opt) { case 'a': params.addr = strtoull(optarg, &ptr, 16); @@ -279,6 +279,9 @@ static void process_args(int argc, char **argv) case 'x': params.xflag++; break; + case 'X': + params.extraparams = optarg; + break; default: usage("Invalid option"); } @@ -416,7 +419,8 @@ int main(int argc, char **argv) exit (retval); } - if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT)) { + if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT) && + (params.type != IH_TYPE_RKNAND)) { dfd = open(params.datafile, O_RDONLY | O_BINARY); if (dfd < 0) { fprintf(stderr, "%s: Can't open %s: %s\n", diff --git a/tools/rkcommon.c b/tools/rkcommon.c index 04e8272..a2f2160 100644 --- a/tools/rkcommon.c +++ b/tools/rkcommon.c @@ -73,6 +73,7 @@ struct spl_info { static struct spl_info spl_infos[] = { { "rk3036", "RK30", 0x1000, false, false }, + { "rk3066", "RK30", 0x8000, true, false }, { "rk3188", "RK31", 0x8000 - 0x800, true, false }, { "rk322x", "RK32", 0x8000 - 0x1000, false, false }, { "rk3288", "RK32", 0x8000, false, false }, @@ -167,7 +168,7 @@ bool rkcommon_spl_is_boot0(struct image_tool_params *params) return info->spl_boot0; } -static void rkcommon_set_header0(void *buf, uint file_size, +static void rkcommon_set_header0(void *buf, uint file_size, uint max_size, struct image_tool_params *params) { struct header0_info *hdr = buf; @@ -194,12 +195,13 @@ static void rkcommon_set_header0(void *buf, uint file_size, * see https://lists.denx.de/pipermail/u-boot/2017-May/293267.html * for a more detailed explanation by Andy Yan */ - hdr->init_boot_size = hdr->init_size + RK_MAX_BOOT_SIZE / RK_BLK_SIZE; + hdr->init_boot_size = hdr->init_size + DIV_ROUND_UP(max_size, RK_BLK_SIZE); + hdr->init_boot_size = ROUND(hdr->init_boot_size, 4); rc4_encode(buf, RK_BLK_SIZE, rc4_key); } -int rkcommon_set_header(void *buf, uint file_size, +int rkcommon_set_header(void *buf, uint file_size, uint max_size, struct image_tool_params *params) { struct header1_info *hdr = buf + RK_SPL_HDR_START; @@ -207,7 +209,7 @@ int rkcommon_set_header(void *buf, uint file_size, if (file_size > rkcommon_get_spl_size(params)) return -ENOSPC; - rkcommon_set_header0(buf, file_size, params); + rkcommon_set_header0(buf, file_size, max_size, params); /* Set up the SPL name (i.e. copy spl_hdr over) */ memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE); diff --git a/tools/rkcommon.h b/tools/rkcommon.h index 8790f1c..cd357c7 100644 --- a/tools/rkcommon.h +++ b/tools/rkcommon.h @@ -45,6 +45,14 @@ const char *rkcommon_get_spl_hdr(struct image_tool_params *params); int rkcommon_get_spl_size(struct image_tool_params *params); /** + * rkcommon_spl_is_boot0() - is magic included in spl + * + * Returns true if magic (for example RK30) is included in spl + */ + +bool rkcommon_spl_is_boot0(struct image_tool_params *params); + +/** * rkcommon_set_header() - set up the header for a Rockchip boot image * * This sets up a 2KB header which can be interpreted by the Rockchip boot ROM. @@ -53,7 +61,7 @@ int rkcommon_get_spl_size(struct image_tool_params *params); * @file_size: Size of the file we want the boot ROM to load, in bytes * @return 0 if OK, -ENOSPC if too large */ -int rkcommon_set_header(void *buf, uint file_size, +int rkcommon_set_header(void *buf, uint file_size, uint max_size, struct image_tool_params *params); /** diff --git a/tools/rknand.c b/tools/rknand.c new file mode 100644 index 0000000..690af2d --- /dev/null +++ b/tools/rknand.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017 Paweł Jarosz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "imagetool.h" +#include +#include +#include "mkimage.h" +#include "rkcommon.h" + +enum { + RKNAND_SECT_LEN = RK_BLK_SIZE * 4, +}; + +struct rknand_info { + uint32_t pagesize; + uint32_t skippages; + uint32_t tplsize; + uint32_t splsize; + uint32_t tplpaddedsize; + uint32_t splpaddedsize; + uint32_t itersize; + uint32_t tplsplsize; + char *tplfile; + char *splfile; +}; + +struct rknand_info ninfo; + +static uint32_t rknand_get_file_size(char *filename) +{ + int dfd; + struct stat sbuf; + + dfd = open(filename, O_RDONLY | O_BINARY); + if (dfd < 0) { + fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (fstat(dfd, &sbuf) < 0) { + fprintf(stderr, "Can't stat %s: %s\n", filename, strerror(errno)); + exit(EXIT_FAILURE); + } + + close(dfd); + + return sbuf.st_size; +} + +static void rknand_fill_ninfo(struct image_tool_params *params) +{ + sscanf(params->extraparams, "%u,%u", &ninfo.pagesize, &ninfo.skippages); + + ninfo.tplfile = params->datafile; + if ((ninfo.splfile = strchr(params->datafile, ':')) != NULL) { + *ninfo.splfile = '\0'; + ninfo.splfile += 1; + } + + ninfo.tplsize = rknand_get_file_size(ninfo.tplfile); + ninfo.splsize = rknand_get_file_size(ninfo.splfile); + + ninfo.tplpaddedsize = ROUND(ninfo.tplsize + + (rkcommon_spl_is_boot0(params) ? 0 : 4), RKNAND_SECT_LEN); + + ninfo.splpaddedsize = ROUND(ninfo.splsize, RKNAND_SECT_LEN); + + ninfo.itersize = ninfo.pagesize * (ninfo.skippages + 1); + ninfo.tplsplsize = ((ninfo.tplpaddedsize + ninfo.splpaddedsize) / + RKNAND_SECT_LEN) * ninfo.itersize; +} + +static void rknand_set_header(void *buf, struct stat *sbuf, int ifd, + struct image_tool_params *params) +{ + int sector, sploffset, splfd, ret; + + ret = rkcommon_set_header(buf, ninfo.tplsize, ninfo.splsize, params); + if (ret) { + printf("Warning: TPL image is too large (size %#x) and will " + "not boot\n", ninfo.tplsize); + } + + if ((splfd = open(ninfo.splfile, O_RDONLY | O_BINARY)) < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + params->cmdname, ninfo.splfile, strerror(errno)); + exit (EXIT_FAILURE); + } + + sploffset = RKNAND_SECT_LEN + ninfo.tplpaddedsize; + if (read(splfd, buf + sploffset, ninfo.splsize) != ninfo.splsize) { + fprintf (stderr, "%s: Read error on %s: %s\n", + params->cmdname, ninfo.splfile, strerror(errno)); + exit (EXIT_FAILURE); + } + close(splfd); + + if (rkcommon_need_rc4_spl(params)) + rkcommon_rc4_encode_spl(buf, sploffset, ninfo.splpaddedsize); + + /* + * Spread the image out so we only use the first 2KB of each pagesize + * region. This is a feature of the NAND format required by the Rockchip + * boot ROM. + */ + for (sector = ninfo.tplsplsize / ninfo.itersize - 1; sector >= 0; sector--) { + memmove(buf + sector * ninfo.itersize + ninfo.pagesize, + buf + (sector + 1) * RKNAND_SECT_LEN, RKNAND_SECT_LEN); + + if (sector < (ninfo.tplsplsize / ninfo.itersize - 1)) + memset(buf + sector * ninfo.itersize + ninfo.pagesize + + RKNAND_SECT_LEN, 0xFF, ninfo.itersize - + RKNAND_SECT_LEN); + } + memset(buf + RKNAND_SECT_LEN, 0xFF, ninfo.pagesize - RKNAND_SECT_LEN); + memset(buf + ninfo.tplsplsize - ninfo.pagesize + RKNAND_SECT_LEN, 0xFF, + ninfo.pagesize - RKNAND_SECT_LEN); +} + +static int rknand_check_image_type(uint8_t type) +{ + if (type == IH_TYPE_RKNAND) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +static int rknand_vrec_header(struct image_tool_params *params, + struct image_type_params *tparams) +{ + rknand_fill_ninfo(params); + rkcommon_vrec_header(params, tparams, RKNAND_SECT_LEN); + + return ninfo.tplsplsize - tparams->header_size - ninfo.tplsize; +} + +/* + * rknand parameters + */ +U_BOOT_IMAGE_TYPE( + rknand, + "Rockchip NAND Boot Image support", + 0, + NULL, + rkcommon_check_params, + rkcommon_verify_header, + rkcommon_print_header, + rknand_set_header, + NULL, + rknand_check_image_type, + NULL, + rknand_vrec_header +); diff --git a/tools/rksd.c b/tools/rksd.c index c56153d..164c1fb 100644 --- a/tools/rksd.c +++ b/tools/rksd.c @@ -26,7 +26,7 @@ static void rksd_set_header(void *buf, struct stat *sbuf, int ifd, * header). */ size = params->file_size - RK_SPL_HDR_START; - ret = rkcommon_set_header(buf, size, params); + ret = rkcommon_set_header(buf, size, RK_MAX_BOOT_SIZE, params); if (ret) { /* TODO(sjg@chromium.org): This method should return an error */ printf("Warning: SPL image is too large (size %#x) and will " diff --git a/tools/rkspi.c b/tools/rkspi.c index 4332ce1..5005051 100644 --- a/tools/rkspi.c +++ b/tools/rkspi.c @@ -25,7 +25,7 @@ static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd, int ret; size = params->orig_file_size; - ret = rkcommon_set_header(buf, size, params); + ret = rkcommon_set_header(buf, size, RK_MAX_BOOT_SIZE, params); debug("size %x\n", size); if (ret) { /* TODO(sjg@chromium.org): This method should return an error */