summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS7
-rw-r--r--README1
-rw-r--r--cmd/Kconfig6
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/seama.c158
-rw-r--r--doc/usage/cmd/seama.rst60
-rw-r--r--doc/usage/index.rst1
-rw-r--r--include/test/suites.h1
-rw-r--r--test/cmd/Makefile1
-rw-r--r--test/cmd/seama.c71
-rw-r--r--test/cmd_ut.c6
11 files changed, 313 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 06c4ea2ecd..b9c505d5fa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1331,6 +1331,13 @@ F: arch/sandbox/
F: doc/arch/sandbox.rst
F: include/dt-bindings/*/sandbox*.h
+SEAMA
+M: Linus Walleij <linus.walleij@linaro.org>
+S: Maintained
+F: cmd/seama.c
+F: doc/usage/cmd/seama.rst
+F: test/cmd/seama.c
+
SEMIHOSTING
R: Sean Anderson <sean.anderson@seco.com>
S: Orphaned
diff --git a/README b/README
index edce7890c0..9cc0c981c4 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 dc0446e02e..b50e14f70a 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 7b6ff73186..b03d68d5f9 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 0000000000..3aafb43c48
--- /dev/null
+++ b/cmd/seama.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 Linus Walleij <linus.walleij@linaro.org>
+ * Support for the "SEAttle iMAge" SEAMA NAND image format
+ */
+
+#include <common.h>
+#include <command.h>
+#include <nand.h>
+
+/*
+ * 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 <addr> <imageindex>\n"
+);
diff --git a/doc/usage/cmd/seama.rst b/doc/usage/cmd/seama.rst
new file mode 100644
index 0000000000..356c00a723
--- /dev/null
+++ b/doc/usage/cmd/seama.rst
@@ -0,0 +1,60 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+seama command
+=============
+
+Synopsis
+--------
+
+::
+
+ seama <dst_addr> <index>
+
+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 3804046835..13e6939b38 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 9ce49cbb03..7c4960c004 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 09e410ec30..2ffde8703a 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 0000000000..b1b56930c6
--- /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 <linus.walleij@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#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 1713d0d1c8..409c22bfd2 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