From patchwork Tue Jan 31 23:16:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 1735149 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=oFnpbImu; dkim-atps=neutral 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 ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4P61C570zJz23hd for ; Wed, 1 Feb 2023 10:16:33 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D487585B13; Wed, 1 Feb 2023 00:16:29 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="oFnpbImu"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C756485B35; Wed, 1 Feb 2023 00:16:28 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4691585B0F for ; Wed, 1 Feb 2023 00:16:25 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=linus.walleij@linaro.org Received: by mail-ed1-x52f.google.com with SMTP id n6so13360511edo.9 for ; Tue, 31 Jan 2023 15:16:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=gwX6ZVgKoA//BT0jgT+wRt+prEdMCXufUe+xvApyr98=; b=oFnpbImuKnNcSRyW+iE2YwnMNTcNgRzy9MA1m/GN2a1lAy8PUY4GZKvsZsv8hCDWJI Zmqz0/RY6KYL3ZI/zEn1HJyDCJFsvGLs8M/+WKYGGaKKGSXdFhdSrWD5lEgE2hjZsJeY 4WsLsw3JWuuCsDTLRCNYxAIBYpy1i/KqpV149hmFoTJgQF486WthSXLL/uhXMDGeTkPS tBFJ2X8nPD5xeum/lnbBS5MV08dSE08ZXECZFe3pLYpdeZ4k6liEqJNXvnUeOxzOk3Sd Coww0/7WNIIDJav6sLzAwlYUHIpQRS1KIMkKRlWGh7uAnKFigc/5416cDRVfL6vi++zu 3Pfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=gwX6ZVgKoA//BT0jgT+wRt+prEdMCXufUe+xvApyr98=; b=tpB1pZgc2gpJbdXzgOfkFDfi03b/v/WzAqsyBSXQ2Z6S0tQ6JAYcLiFNrUOxH2GFEP biFtpVBdJj7CmNc+F3bZUJ3bD8a50nxLf8S83gDiM1r7k118DNBvKnSpzQmmOVh1tNS6 W1smll/CuUhe0mmZQR2+yGCbeeKx2NIdP5bCsJxfkgWC7Ba3mUkmoRDB0XleN/K4BYyZ PAqPy1yvkb+hCoT4gX2BsCkREBkKQi6IWw+yflt9KtTXBBethmIeylX9sJiR8HtxLYBV q84Bl2do66QP4JqrhH9w8IG0INkdbCswupytczbdNk1kasonBCghEpr5awkYkdJIcsGs wAKQ== X-Gm-Message-State: AO0yUKVZ+Xo7RixUM6v6kMfvEVS8nbCacvZrx7ra81rpLNE8U+m8iiPG DcnT9+90Klrx4kjIOgJVQZ9uPcidKnb0r1xP X-Google-Smtp-Source: AK7set/Hv4kBOyZKqeJERTTRlS021fo5neubWjo7FBK/okMrqOxuOTmIv/e30KMx/AHgTdaBKCld2A== X-Received: by 2002:a05:6402:43cc:b0:49e:a0f7:9a75 with SMTP id p12-20020a05640243cc00b0049ea0f79a75mr5415315edc.12.1675206984486; Tue, 31 Jan 2023 15:16:24 -0800 (PST) Received: from localhost.localdomain (c-05d8225c.014-348-6c756e10.bbcust.telenor.se. [92.34.216.5]) by smtp.gmail.com with ESMTPSA id i8-20020a50fc08000000b004a087d1d313sm8894105edr.64.2023.01.31.15.16.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Jan 2023 15:16:23 -0800 (PST) From: Linus Walleij To: u-boot@lists.denx.de, Tom Rini Cc: Linus Walleij , =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= Subject: [PATCH] cmd: Add a SEAMA image load command Date: Wed, 1 Feb 2023 00:16:13 +0100 Message-Id: <20230131231613.365724-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean Add a command to load SEAMA (Seattle Image), a NAND flash on-flash storage format. This type of flash image is found in some D-Link routers such as DIR-645, DIR-842, DIR-859, DIR-860L, DIR-885L, DIR890L and DCH-M225, as well as in WD and NEC routers on the ath79 (MIPS), Broadcom BCM53xx, and RAMIPS platforms. This U-Boot command will read and decode a SEAMA image from raw NAND flash on any platform. As it is always using big endian format for the data decoding is always necessary on platforms such as ARM. The command is needed to read a SEAMA-encoded boot image on the D-Link DIR-890L router for boot from NAND flash in an upcoming port of U-Boot to the Broadcom Northstar (BCM4709, BCM53xx) architecture. A basic test and documentation is added as well. The test must be run on a target with NAND flash support and at least one resident SEAMA image in flash. Cc: Rafał Miłecki Signed-off-by: Linus Walleij --- MAINTAINERS | 7 ++ README | 1 + cmd/Kconfig | 6 ++ cmd/Makefile | 1 + cmd/seama.c | 158 ++++++++++++++++++++++++++++++++++++++++ doc/usage/cmd/seama.rst | 60 +++++++++++++++ doc/usage/index.rst | 1 + include/test/suites.h | 1 + test/cmd/Makefile | 1 + test/cmd/seama.c | 71 ++++++++++++++++++ test/cmd_ut.c | 6 ++ 11 files changed, 313 insertions(+) create mode 100644 cmd/seama.c create mode 100644 doc/usage/cmd/seama.rst create mode 100644 test/cmd/seama.c diff --git a/MAINTAINERS b/MAINTAINERS index 2dd2b46fcda6..359fde15936c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1329,6 +1329,13 @@ F: arch/sandbox/ F: doc/arch/sandbox.rst F: include/dt-bindings/*/sandbox*.h +SEAMA +M: Linus Walleij +S: Maintained +F: cmd/seama.c +F: doc/usage/cmd/seama.rst +F: test/cmd/seama.c + SEMIHOSTING R: Sean Anderson S: Orphaned diff --git a/README b/README index edce7890c0f9..9cc0c981c43c 100644 --- a/README +++ b/README @@ -1810,6 +1810,7 @@ sspi - SPI utility commands base - print or set address offset printenv- print environment variables pwm - control pwm channels +seama - load SEAMA NAND image setenv - set environment variables saveenv - save environment variables to persistent storage protect - enable or disable FLASH write protection diff --git a/cmd/Kconfig b/cmd/Kconfig index 4fe2c75de256..ead98c39cdee 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -337,6 +337,12 @@ config BOOTM_RTEMS help Support booting RTEMS images via the bootm command. +config CMD_SEAMA + bool "Support read SEAMA NAND images" + depends on MTD_RAW_NAND + help + Support reading NAND Seattle Image (SEAMA) images. + config CMD_VBE bool "vbe - Verified Boot for Embedded" depends on BOOTMETH_VBE diff --git a/cmd/Makefile b/cmd/Makefile index 0b6a96c1d914..4fea084b44fa 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -156,6 +156,7 @@ obj-$(CONFIG_SANDBOX) += sb.o obj-$(CONFIG_CMD_SF) += sf.o obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o +obj-$(CONFIG_CMD_SEAMA) += seama.o obj-$(CONFIG_CMD_SETEXPR) += setexpr.o obj-$(CONFIG_CMD_SETEXPR_FMT) += printf.o obj-$(CONFIG_CMD_SPI) += spi.o diff --git a/cmd/seama.c b/cmd/seama.c new file mode 100644 index 000000000000..3aafb43c48a0 --- /dev/null +++ b/cmd/seama.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2023 Linus Walleij + * Support for the "SEAttle iMAge" SEAMA NAND image format + */ + +#include +#include +#include + +/* + * All SEAMA data is stored in the flash in "network endianness" + * i.e. big endian, which means that it needs to be byte-swapped + * on all little endian platforms. + * + * structure for a SEAMA entity in NAND flash: + * + * 32 bit SEAMA magic 0x5EA3A417 + * 16 bit reserved + * 16 bit metadata size (following the header) + * 32 bit image size + * 16 bytes MD5 digest of the image + * meta data + * ... image data ... + * + * Then if a new SEAMA magic follows, that is the next image. + */ + +#define SEAMA_MAGIC 0x5EA3A417 +#define SEAMA_HDR_NO_META_SZ 28 +#define SEAMA_MAX_META_SZ (1024 - SEAMA_HDR_NO_META_SZ) + +struct seama_header { + u32 magic; + u32 meta_size; + u32 image_size; + u8 md5[16]; + u8 metadata[SEAMA_MAX_META_SZ]; +}; + +static struct seama_header shdr; + +static int env_set_val(const char *varname, ulong val) +{ + int ret; + + ret = env_set_hex(varname, val); + if (ret) + printf("Failed to %s env var\n", varname); + + return ret; +} + +static int do_seama_load_image(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct mtd_info *mtd; + uintptr_t load_addr; + unsigned long image_index; + u32 len; + size_t readsz; + int ret; + u32 *start; + u32 *offset; + u32 *end; + u32 tmp; + + if (argc < 2 || argc > 3) + return CMD_RET_USAGE; + + load_addr = hextoul(argv[1], NULL); + if (!load_addr) { + printf("Invalid load address\n"); + return CMD_RET_USAGE; + } + + /* Can be 0 for first image */ + image_index = hextoul(argv[2], NULL); + + /* We only support one NAND, the first one */ + nand_curr_device = 0; + mtd = get_nand_dev_by_index(0); + if (!mtd) { + printf("NAND Device 0 not available\n"); + return CMD_RET_FAILURE; + } + +#ifdef CONFIG_SYS_NAND_SELECT_DEVICE + board_nand_select_device(mtd_to_nand(mtd), 0); +#endif + + printf("Loading SEAMA image %lu from %s\n", image_index, mtd->name); + + readsz = sizeof(shdr); + offset = 0; + ret = nand_read_skip_bad(mtd, 0, &readsz, NULL, mtd->size, + (u_char *)&shdr); + if (ret) { + printf("Read error reading SEAMA header\n"); + return CMD_RET_FAILURE; + } + + if (shdr.magic != SEAMA_MAGIC) { + printf("Invalid SEAMA image magic: 0x%08x\n", shdr.magic); + return CMD_RET_FAILURE; + } + + /* Only the lower 16 bits are valid */ + shdr.meta_size &= 0xFFFF; + + if (env_set_val("seama_image_size", 0)) + return CMD_RET_FAILURE; + + printf("SEMA IMAGE:\n"); + printf(" metadata size %d\n", shdr.meta_size); + printf(" image size %d\n", shdr.image_size); + printf(" checksum %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + shdr.md5[0], shdr.md5[1], shdr.md5[2], shdr.md5[3], + shdr.md5[4], shdr.md5[5], shdr.md5[6], shdr.md5[7], + shdr.md5[8], shdr.md5[9], shdr.md5[10], shdr.md5[11], + shdr.md5[12], shdr.md5[13], shdr.md5[14], shdr.md5[15]); + + /* TODO: handle metadata if needed */ + + len = shdr.image_size; + if (env_set_val("seama_image_size", len)) + return CMD_RET_FAILURE; + + /* We need to include the header (read full pages) */ + readsz = shdr.image_size + SEAMA_HDR_NO_META_SZ + shdr.meta_size; + ret = nand_read_skip_bad(mtd, 0, &readsz, NULL, mtd->size, + (u_char *)load_addr); + if (ret) { + printf("Read error reading SEAMA main image\n"); + return CMD_RET_FAILURE; + } + + /* We use a temporary variable tmp to avoid to hairy casts */ + start = (u32 *)load_addr; + tmp = (u32)start; + tmp += SEAMA_HDR_NO_META_SZ + shdr.meta_size; + offset = (u32 *)tmp; + tmp += shdr.image_size; + end = (u32 *)tmp; + + printf("Decoding SEAMA image 0x%08x..0x%08x to 0x%08x\n", + (u32)offset, (u32)end, (u32)start); + for (; start < end; start++, offset++) + *start = be32_to_cpu(*offset); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD + (seama, 3, 1, do_seama_load_image, + "Load the SEAMA image and sets envs", + "seama \n" +); diff --git a/doc/usage/cmd/seama.rst b/doc/usage/cmd/seama.rst new file mode 100644 index 000000000000..356c00a72331 --- /dev/null +++ b/doc/usage/cmd/seama.rst @@ -0,0 +1,60 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +seama command +============= + +Synopsis +-------- + +:: + + seama + +Description +----------- + +The seama command is used to load and decode SEAttle iMAges from NAND +flash to memory. + +This type of flash image is found in some D-Link routers such as +DIR-645, DIR-842, DIR-859, DIR-860L, DIR-885L, DIR890L and DCH-M225, +as well as in WD and NEC routers on the ath79 (MIPS), Broadcom +BCM53xx, and RAMIPS platforms. + +This U-Boot command will read and decode a SEAMA image from raw NAND +flash on any platform. As it is always using big endian format for +the data decoding is always necessary on platforms such as ARM. + +dst_addr + destination address of the byte stream to be loaded + +index + the image index (0, 1, 2..) can be omitted + +Example +------- + +:: + + => seama 0x01000000 + Loading SEAMA image 0 from nand0 + SEMA IMAGE: + metadata size 36 + image size 8781764 + checksum 054859cfb1487b59befda98824e09dd6 + Decoding SEAMA image 0x01000040..0x01860004 to 0x01000000 + + +Configuration +------------- + +The command is available if CONFIG_CMD_SEAMA=y. + +Return value +------------ + +The return value $? is set 0 (true) if the loading is succefull, and +is set to 1 (false) in case of error. + +The environment variable $seama_image_size is set to the size of the +loaded SEAMA image. diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 2c95471f45c9..ca99b01952d4 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -75,6 +75,7 @@ Shell commands cmd/sbi cmd/sf cmd/scp03 + cmd/seama cmd/setexpr cmd/size cmd/sleep diff --git a/include/test/suites.h b/include/test/suites.h index 9ce49cbb031a..7c4960c004d7 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -49,6 +49,7 @@ int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_seama(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 09e410ec30e5..2ffde8703abf 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o obj-$(CONFIG_CMD_PINMUX) += pinmux.o obj-$(CONFIG_CMD_PWM) += pwm.o +obj-$(CONFIG_CMD_SEAMA) += seama.o ifdef CONFIG_SANDBOX obj-$(CONFIG_CMD_SETEXPR) += setexpr.o endif diff --git a/test/cmd/seama.c b/test/cmd/seama.c new file mode 100644 index 000000000000..b1b56930c646 --- /dev/null +++ b/test/cmd/seama.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Executes tests for SEAMA (SEAttle iMAge) command + * + * Copyright (C) 2021 Linus Walleij + */ + +#include +#include +#include +#include +#include +#include + +#define SEAMA_TEST(_name, _flags) UNIT_TEST(_name, _flags, seama_test) + +static int seama_test_noargs(struct unit_test_state *uts) +{ + /* Test that 'seama' with no arguments fails gracefully */ + console_record_reset(); + run_command("seama", 0); + ut_assert_nextlinen("seama - Load the SEAMA image and sets envs"); + ut_assert_skipline(); + ut_assert_skipline(); + ut_assert_skipline(); + ut_assert_skipline(); + ut_assert_console_end(); + return 0; +} +SEAMA_TEST(seama_test_noargs, UT_TESTF_CONSOLE_REC); + +static int seama_test_addr(struct unit_test_state *uts) +{ + /* Test that loads SEAMA image 0 to address 0x01000000 */ + console_record_reset(); + run_command("seama 0x01000000", 0); + ut_assert_nextlinen("Loading SEAMA image 0 from nand0"); + ut_assert_nextlinen("SEMA IMAGE:"); + ut_assert_nextlinen(" metadata size "); + ut_assert_nextlinen(" image size "); + ut_assert_nextlinen(" checksum "); + ut_assert_nextlinen("Decoding SEAMA image 0x01000040.."); + ut_assert_console_end(); + return 0; +} +SEAMA_TEST(seama_test_addr, UT_TESTF_CONSOLE_REC); + +static int seama_test_index(struct unit_test_state *uts) +{ + /* Test that loads SEAMA image 0 exlicitly specified */ + console_record_reset(); + run_command("seama 0x01000000 0", 0); + ut_assert_nextlinen("Loading SEAMA image 0 from nand0"); + ut_assert_nextlinen("SEMA IMAGE:"); + ut_assert_nextlinen(" metadata size "); + ut_assert_nextlinen(" image size "); + ut_assert_nextlinen(" checksum "); + ut_assert_nextlinen("Decoding SEAMA image 0x01000040.."); + ut_assert_console_end(); + return 0; +} +SEAMA_TEST(seama_test_index, UT_TESTF_CONSOLE_REC); + +int do_ut_seama(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(seama_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(seama_test); + + return cmd_ut_category("seama", "seama_test_", tests, n_ents, argc, + argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 1713d0d1c85e..409c22bfd243 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -110,6 +110,9 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_CMD_LOADM U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""), #endif +#ifdef CONFIG_CMD_SEAMA + U_BOOT_CMD_MKENT(seama, CONFIG_SYS_MAXARGS, 1, do_ut_seama, "", ""), +#endif }; static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc, @@ -212,6 +215,9 @@ static char ut_help_text[] = #ifdef CONFIG_SANDBOX "\nstr - basic test of string functions" #endif +#ifdef CONFIG_CMD_SEAMA + "\nseama - seama command parameters loading and decoding" +#endif #ifdef CONFIG_UT_TIME "\ntime - very basic test of time functions" #endif