[PATCH 8/9] test: boot: add imagemap unit tests
Daniel Golle
daniel at makrotopia.org
Sun Aug 23 12:16:10 PDT 2026
Add a test suite exercising imagemap:
- the translation-table core (map, lookup, map_to, cleanup, region
growth, the block-aligned read path, and edge cases) using a mock
RAM-backed reader, so most tests need no real storage;
- a NOR read through mtd_blk: write a known pattern into a
device-tree partition of the sandbox SPI-NOR and read it back
through imagemap, exercising imagemap -> spl_load_region ->
blk_dread -> mtd_blk_read -> mtd_read for real;
- a UBI-volume read through ubiblock: attach UBI on the sandbox NAND,
create a volume, write a pattern and read it back through imagemap
on the ubi_blk device.
Registered under ut_boot_imagemap in cmd_ut.c.
Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
MAINTAINERS | 1 +
test/boot/Makefile | 2 +
test/boot/imagemap.c | 645 +++++++++++++++++++++++++++++++++++++++++++
test/cmd_ut.c | 2 +
4 files changed, 650 insertions(+)
create mode 100644 test/boot/imagemap.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 48ee01e033d..e8f0e94597f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1192,6 +1192,7 @@ L: openwrt-devel at lists.openwrt.org
S: Maintained
F: boot/imagemap.c
F: include/imagemap.h
+F: test/boot/imagemap.c
INTERCONNECT
M: Neil Armstrong <neil.armstrong at linaro.org>
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 59a87028704..8dbecabde79 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -27,3 +27,5 @@ endif
obj-$(CONFIG_BOOTMETH_VBE) += vbe_fixup.o
obj-$(CONFIG_UPL) += upl.o
+
+obj-$(CONFIG_IMAGEMAP) += imagemap.o
diff --git a/test/boot/imagemap.c b/test/boot/imagemap.c
new file mode 100644
index 00000000000..540a55676a8
--- /dev/null
+++ b/test/boot/imagemap.c
@@ -0,0 +1,645 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for imagemap framework (UCLASS_IMAGEMAP)
+ *
+ * Copyright (C) 2026 Daniel Golle <daniel at makrotopia.org>
+ */
+
+#include <dm.h>
+#include <blk.h>
+#include <imagemap.h>
+#include <mtd.h>
+#include <part.h>
+#include <ubi_uboot.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <lmb.h>
+#include <mapmem.h>
+#include <malloc.h>
+#include <asm/cache.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <dm/uclass-internal.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define IMAGEMAP_TEST(_name, _flags) \
+ UNIT_TEST(_name, _flags, imagemap)
+
+/* Synthetic image size used throughout the tests */
+#define IMAGE_SIZE 4096
+
+/**
+ * struct mock_priv - private data for the mock storage backend
+ *
+ * @image: pointer to synthetic image data in RAM
+ * @image_size: size of the synthetic image
+ * @read_count: number of times .read() was called
+ * @last_off: offset from the most recent .read() call
+ * @last_size: size from the most recent .read() call
+ */
+struct mock_priv {
+ const void *image;
+ size_t image_size;
+ int read_count;
+ loff_t last_off;
+ ulong last_size;
+};
+
+static ulong mock_reader(struct spl_load_info *info, ulong sector,
+ ulong count, void *buf)
+{
+ struct mock_priv *p = info->priv;
+
+ if (sector + count > p->image_size)
+ return 0;
+
+ memcpy(buf, (const char *)p->image + sector, count);
+ p->read_count++;
+ p->last_off = sector;
+ p->last_size = count;
+
+ return count;
+}
+
+U_BOOT_DRIVER(imagemap_mock) = {
+ .name = "imagemap_mock",
+ .id = UCLASS_IMAGEMAP,
+ .priv_auto = sizeof(struct mock_priv),
+};
+
+/**
+ * create_mock_loader() - create a mock imagemap device for testing
+ *
+ * @image: synthetic image buffer
+ * @image_size: size of @image
+ * @devp: on success, the new imagemap device
+ * Return: 0 on success, negative errno on failure
+ */
+static int create_mock_loader_bl(const void *image, size_t image_size,
+ uint bl_len, struct udevice **devp)
+{
+ struct udevice *dev;
+ struct imagemap_priv *im;
+ struct mock_priv *priv;
+ int ret;
+
+ ret = device_bind_driver(dm_root(), "imagemap_mock",
+ "imagemap-test", &dev);
+ if (ret)
+ return ret;
+
+ ret = device_probe(dev);
+ if (ret) {
+ device_unbind(dev);
+ return ret;
+ }
+
+ priv = dev_get_priv(dev);
+ priv->image = image;
+ priv->image_size = image_size;
+ priv->read_count = 0;
+
+ /* Point the imagemap's shared load-to-mem reader at the mock image */
+ im = dev_get_uclass_priv(dev);
+ spl_load_init(&im->info, mock_reader, priv, bl_len);
+
+ *devp = dev;
+
+ return 0;
+}
+
+static int create_mock_loader(const void *image, size_t image_size,
+ struct udevice **devp)
+{
+ return create_mock_loader_bl(image, image_size, 1, devp);
+}
+
+/**
+ * get_mock_priv() - get mock private data from an imagemap device
+ */
+static struct mock_priv *get_mock_priv(struct udevice *dev)
+{
+ return dev_get_priv(dev);
+}
+
+/* Test: map() allocates, reads and records a region */
+static int imagemap_test_map_basic(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct imagemap_priv *priv;
+ struct mock_priv *mock;
+ u8 image[IMAGE_SIZE];
+ void *p;
+
+ /* Fill image with a recognisable pattern */
+ for (int i = 0; i < IMAGE_SIZE; i++)
+ image[i] = (u8)(i & 0xff);
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+ mock = get_mock_priv(dev);
+ priv = dev_get_uclass_priv(dev);
+
+ /* Map a 64-byte region at offset 0 */
+ p = imagemap_map(dev, 0, 64);
+ ut_assert(!IS_ERR(p));
+ ut_asserteq_mem(image, p, 64);
+ ut_asserteq(1, mock->read_count);
+ ut_asserteq(1, priv->regions.count);
+ ut_asserteq(0, (int)alist_get(&priv->regions, 0, struct imagemap_region)->img_offset);
+ ut_asserteq(64, (int)alist_get(&priv->regions, 0, struct imagemap_region)->size);
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_map_basic, 0);
+
+/* Test: map() returns cached pointer for already-mapped range */
+static int imagemap_test_map_cached(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct mock_priv *mock;
+ u8 image[IMAGE_SIZE];
+ void *p1, *p2;
+
+ memset(image, 0xaa, IMAGE_SIZE);
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+ mock = get_mock_priv(dev);
+
+ p1 = imagemap_map(dev, 0, 128);
+ ut_assert(!IS_ERR(p1));
+ ut_asserteq(1, mock->read_count);
+
+ /* Same range — should return same pointer, no new read */
+ p2 = imagemap_map(dev, 0, 128);
+ ut_asserteq_ptr(p1, p2);
+ ut_asserteq(1, mock->read_count);
+
+ /* Subset of the already-mapped range — still cached */
+ p2 = imagemap_map(dev, 0, 64);
+ ut_asserteq_ptr(p1, p2);
+ ut_asserteq(1, mock->read_count);
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_map_cached, 0);
+
+/* Test: map() returns correct offset within a larger region */
+static int imagemap_test_map_offset(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct mock_priv *mock;
+ u8 image[IMAGE_SIZE];
+ void *p1, *p2;
+
+ for (int i = 0; i < IMAGE_SIZE; i++)
+ image[i] = (u8)(i & 0xff);
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+ mock = get_mock_priv(dev);
+
+ /* Map a 256-byte region starting at offset 0 */
+ p1 = imagemap_map(dev, 0, 256);
+ ut_assert(!IS_ERR(p1));
+
+ /* Request a sub-range within the previously mapped region */
+ p2 = imagemap_map(dev, 64, 64);
+ ut_assert(!IS_ERR(p2));
+ /* p2 should point 64 bytes into p1 */
+ ut_asserteq_ptr((char *)p1 + 64, p2);
+ ut_asserteq_mem(image + 64, p2, 64);
+ /* Only one read should have occurred */
+ ut_asserteq(1, mock->read_count);
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_map_offset, 0);
+
+/* Test: map() re-reads when extending a region to a larger size */
+static int imagemap_test_map_extend(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct imagemap_priv *priv;
+ struct mock_priv *mock;
+ u8 image[IMAGE_SIZE];
+ void *p1, *p2;
+
+ for (int i = 0; i < IMAGE_SIZE; i++)
+ image[i] = (u8)(i & 0xff);
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+ mock = get_mock_priv(dev);
+ priv = dev_get_uclass_priv(dev);
+
+ /* Initial small mapping */
+ p1 = imagemap_map(dev, 0, 64);
+ ut_assert(!IS_ERR(p1));
+ ut_asserteq(1, mock->read_count);
+
+ /* Request larger range at same base — should re-read (extend) */
+ p2 = imagemap_map(dev, 0, 256);
+ ut_assert(!IS_ERR(p2));
+ ut_asserteq(2, mock->read_count);
+ ut_asserteq_mem(image, p2, 256);
+
+ /* Region count should still be 1 (updated, not added) */
+ ut_asserteq(1, priv->regions.count);
+ ut_asserteq(256, (int)alist_get(&priv->regions, 0, struct imagemap_region)->size);
+
+ /*
+ * Map a new region after the extend — it must not overlap the
+ * extended first region. This is the exact pattern that bit us
+ * on real hardware: FIT header at offset 0 extended from 64 to
+ * 4096, then kernel payload at offset 4096 was allocated at
+ * an address that overlapped the header, clobbering it.
+ * With LMB allocation this cannot happen because each allocation
+ * reserves distinct memory.
+ */
+ {
+ void *p3 = imagemap_map(dev, 256, 128);
+ ulong p2_end = map_to_sysmem(p2) + 256;
+
+ ut_assert(!IS_ERR(p3));
+ ut_asserteq(2, priv->regions.count);
+ /* New region must not overlap the extended first region */
+ ut_assert(map_to_sysmem(p3) >= p2_end ||
+ map_to_sysmem(p3) + 128 <= map_to_sysmem(p2));
+ ut_asserteq_mem(image + 256, p3, 128);
+ }
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_map_extend, 0);
+
+/* Test: map_to() reads to a specified address and records it */
+static int imagemap_test_map_to(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct imagemap_priv *priv;
+ struct mock_priv *mock;
+ u8 image[IMAGE_SIZE];
+ u8 dst[256];
+ void *p;
+
+ for (int i = 0; i < IMAGE_SIZE; i++)
+ image[i] = (u8)(i & 0xff);
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+ mock = get_mock_priv(dev);
+ priv = dev_get_uclass_priv(dev);
+
+ p = imagemap_map_to(dev, 128, 256, dst);
+ ut_assert(!IS_ERR(p));
+ ut_asserteq_ptr(dst, p);
+ ut_asserteq_mem(image + 128, dst, 256);
+ ut_asserteq(1, mock->read_count);
+ ut_asserteq(1, priv->regions.count);
+ ut_asserteq(128, (int)alist_get(&priv->regions, 0, struct imagemap_region)->img_offset);
+ ut_asserteq(256, (int)alist_get(&priv->regions, 0, struct imagemap_region)->size);
+ ut_asserteq_ptr(dst, alist_get(&priv->regions, 0, struct imagemap_region)->ram);
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_map_to, 0);
+
+/* Test: lookup() returns NULL for unmapped ranges */
+static int imagemap_test_lookup_miss(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u8 image[IMAGE_SIZE];
+ void *p;
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+
+ /* Nothing mapped yet — should return NULL */
+ p = imagemap_lookup(dev, 0, 64);
+ ut_assertnull(p);
+
+ /* Map a region at offset 0 */
+ ut_assert(!IS_ERR(imagemap_map(dev, 0, 64)));
+
+ /* Lookup within the mapped region — should succeed */
+ p = imagemap_lookup(dev, 0, 32);
+ ut_assertnonnull(p);
+
+ /* Lookup at a different offset — should miss */
+ p = imagemap_lookup(dev, 128, 32);
+ ut_assertnull(p);
+
+ /* Lookup extending beyond the mapped region — should miss */
+ p = imagemap_lookup(dev, 0, 128);
+ ut_assertnull(p);
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_lookup_miss, 0);
+
+/* Test: LMB reservations are made for map() allocations */
+static int imagemap_test_lmb_reserve(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u8 image[IMAGE_SIZE];
+ void *p1, *p2;
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+
+ /* Map 100 bytes — should be LMB reserved */
+ p1 = imagemap_map(dev, 0, 100);
+ ut_assert(!IS_ERR(p1));
+ ut_assert(lmb_is_reserved_flags(map_to_sysmem(p1), LMB_NONE));
+
+ /* Map another 200 bytes at a different offset */
+ p2 = imagemap_map(dev, 200, 200);
+ ut_assert(!IS_ERR(p2));
+ ut_assert(lmb_is_reserved_flags(map_to_sysmem(p2), LMB_NONE));
+
+ /* Regions must not overlap */
+ ut_assert(map_to_sysmem(p2) >= map_to_sysmem(p1) + 100 ||
+ map_to_sysmem(p1) >= map_to_sysmem(p2) + 200);
+
+ /* Cleanup frees the LMB reservations */
+ imagemap_cleanup(dev);
+ ut_assert(!lmb_is_reserved_flags(map_to_sysmem(p1), LMB_NONE));
+ ut_assert(!lmb_is_reserved_flags(map_to_sysmem(p2), LMB_NONE));
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_lmb_reserve, 0);
+
+/* Test: cleanup() removes the device */
+static int imagemap_test_cleanup(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u8 image[IMAGE_SIZE];
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+
+ /* Map something so regions are not empty */
+ ut_assert(!IS_ERR(imagemap_map(dev, 0, 64)));
+
+ /* Cleanup should remove and unbind the device */
+ imagemap_cleanup(dev);
+
+ /* NULL cleanup should be safe */
+ imagemap_cleanup(NULL);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_cleanup, 0);
+
+/* Test: map() with multiple disjoint regions */
+static int imagemap_test_multi_region(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct imagemap_priv *priv;
+ struct mock_priv *mock;
+ u8 image[IMAGE_SIZE];
+ void *p1, *p2, *p3;
+
+ for (int i = 0; i < IMAGE_SIZE; i++)
+ image[i] = (u8)(i & 0xff);
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+ mock = get_mock_priv(dev);
+ priv = dev_get_uclass_priv(dev);
+
+ p1 = imagemap_map(dev, 0, 64);
+ ut_assert(!IS_ERR(p1));
+ p2 = imagemap_map(dev, 512, 128);
+ ut_assert(!IS_ERR(p2));
+ p3 = imagemap_map(dev, 1024, 256);
+ ut_assert(!IS_ERR(p3));
+
+ ut_asserteq(3, priv->regions.count);
+ ut_asserteq(3, mock->read_count);
+
+ /* Verify data in each region */
+ ut_asserteq_mem(image, p1, 64);
+ ut_asserteq_mem(image + 512, p2, 128);
+ ut_asserteq_mem(image + 1024, p3, 256);
+
+ /* Lookup each region */
+ ut_asserteq_ptr(p1, imagemap_lookup(dev, 0, 64));
+ ut_asserteq_ptr(p2, imagemap_lookup(dev, 512, 128));
+ ut_asserteq_ptr(p3, imagemap_lookup(dev, 1024, 256));
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_multi_region, 0);
+
+/* Test: read beyond image size returns error */
+static int imagemap_test_read_oob(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u8 image[IMAGE_SIZE];
+ void *p;
+
+ ut_assertok(create_mock_loader(image, IMAGE_SIZE, &dev));
+
+ /* Attempt to map beyond the end of the image */
+ p = imagemap_map(dev, IMAGE_SIZE - 32, 64);
+ ut_assert(IS_ERR(p));
+
+ /* map_to should also fail */
+ u8 dst[64];
+
+ p = imagemap_map_to(dev, IMAGE_SIZE - 32, 64, dst);
+ ut_assert(IS_ERR(p));
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_read_oob, 0);
+
+/*
+ * Test: block-addressed backend (bl_len > 1) still returns/places the
+ * wanted bytes byte-exact for unaligned offsets and multi-block ranges.
+ */
+static int imagemap_test_blocklen(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u8 image[IMAGE_SIZE];
+ u8 dst[1024];
+ void *p;
+
+ for (int i = 0; i < IMAGE_SIZE; i++)
+ image[i] = (u8)(i & 0xff);
+
+ ut_assertok(create_mock_loader_bl(image, IMAGE_SIZE, 512, &dev));
+
+ /* map() at an unaligned offset returns byte-exact data */
+ p = imagemap_map(dev, 100, 200);
+ ut_assert(!IS_ERR(p));
+ ut_asserteq_mem(image + 100, p, 200);
+
+ /* map_to() places the payload byte-exact at dst (partial head only) */
+ p = imagemap_map_to(dev, 100, 200, dst);
+ ut_assert(!IS_ERR(p));
+ ut_asserteq_ptr(dst, p);
+ ut_asserteq_mem(image + 100, dst, 200);
+
+ /* map_to() spanning partial head + aligned middle + partial tail */
+ p = imagemap_map_to(dev, 500, 600, dst);
+ ut_assert(!IS_ERR(p));
+ ut_asserteq_ptr(dst, p);
+ ut_asserteq_mem(image + 500, dst, 600);
+
+ imagemap_cleanup(dev);
+
+ return 0;
+}
+
+IMAGEMAP_TEST(imagemap_test_blocklen, 0);
+
+#if CONFIG_IS_ENABLED(MTD_BLOCK)
+/*
+ * End-to-end: read a known pattern back from a bare (non-NAND) MTD
+ * partition through imagemap on the mtd_blk block device. Exercises the
+ * real path imagemap -> spl_load_region -> blk_dread -> mtd_blk_read ->
+ * mtd_read on the sandbox SPI-NOR (no mock).
+ */
+static int imagemap_test_mtd_blk(struct unit_test_state *uts)
+{
+ const ulong blks = 4, len = blks * 512;
+ struct udevice *blk = NULL, *dev, *imdev;
+ struct blk_desc *desc = NULL;
+ struct disk_partition info;
+ void *mapped;
+ u8 *wbuf;
+ int i;
+
+ /*
+ * Probe the SPI-NOR (add_mtd_device() then binds its mtd_blk) and
+ * parse its device-tree partitions.
+ */
+ mtd_probe_devices();
+
+ /* Find the bound mtd_blk (a PART_TYPE_MTD block device) */
+ for (uclass_find_first_device(UCLASS_BLK, &dev); dev;
+ uclass_find_next_device(&dev)) {
+ desc = dev_get_uclass_plat(dev);
+ if (desc->part_type == PART_TYPE_MTD) {
+ blk = dev;
+ break;
+ }
+ }
+ ut_assertnonnull(blk);
+ ut_assertok(device_probe(blk));
+ desc = dev_get_uclass_plat(blk);
+
+ /* Write a known pattern into the "nor-fit" partition */
+ ut_assert(part_get_info_by_name(desc, "nor-fit", &info) >= 1);
+ wbuf = malloc(len);
+ ut_assertnonnull(wbuf);
+ for (i = 0; i < len; i++)
+ wbuf[i] = (u8)(i * 5 + 1);
+ ut_asserteq(blks, blk_dwrite(desc, info.start, blks, wbuf));
+
+ /* Read it back through imagemap on the mtd_blk device */
+ ut_assertok(imagemap_create(blk, "nor-fit", 0, &imdev));
+ mapped = imagemap_map(imdev, 0, len);
+ ut_assert(!IS_ERR(mapped));
+ ut_asserteq_mem(wbuf, mapped, len);
+
+ imagemap_cleanup(imdev);
+ free(wbuf);
+
+ return 0;
+}
+IMAGEMAP_TEST(imagemap_test_mtd_blk, 0);
+#endif /* MTD_BLOCK */
+
+#if CONFIG_IS_ENABLED(MTD_UBI) && CONFIG_IS_ENABLED(UBI_BLOCK)
+/*
+ * End-to-end: attach UBI on the sandbox NAND, create a volume, write a
+ * known pattern and read it back through imagemap on the ubi_blk block
+ * device. Exercises imagemap -> spl_load_region -> blk_dread ->
+ * ubi_bread -> ubi_volume_read for real (no mock).
+ */
+static int imagemap_test_ubiblock(struct unit_test_state *uts)
+{
+ const ulong len = 4096;
+ struct udevice *blk = NULL, *dev, *imdev;
+ struct erase_info ei;
+ struct mtd_info *mtd;
+ void *mapped;
+ u8 *wbuf;
+ u64 off;
+ int i;
+
+ mtd_probe_devices();
+ mtd = get_mtd_device_nm("nand2");
+ ut_assert(!IS_ERR_OR_NULL(mtd));
+
+ /* Erase so UBI can format the (empty) clean chip */
+ for (off = 0; off < mtd->size; off += mtd->erasesize) {
+ if (mtd_block_isbad(mtd, off))
+ continue;
+ memset(&ei, 0, sizeof(ei));
+ ei.mtd = mtd;
+ ei.addr = off;
+ ei.len = mtd->erasesize;
+ ut_assertok(mtd_erase(mtd, &ei));
+ }
+ put_mtd_device(mtd);
+
+ /* Attach UBI by name; this binds the ubi_blk block device */
+ ut_assertok(ubi_part("nand2", NULL));
+ ut_assertok(ubi_create_vol("vol0", 0x10000, true, UBI_VOL_NUM_AUTO,
+ false));
+
+ wbuf = malloc(len);
+ ut_assertnonnull(wbuf);
+ for (i = 0; i < len; i++)
+ wbuf[i] = (u8)(i * 7 + 3);
+ ut_assertok(ubi_volume_write("vol0", wbuf, 0, len));
+
+ /* Find the ubi_blk block device */
+ for (uclass_find_first_device(UCLASS_BLK, &dev); dev;
+ uclass_find_next_device(&dev)) {
+ if (dev->driver == DM_DRIVER_GET(ubi_blk)) {
+ blk = dev;
+ break;
+ }
+ }
+ ut_assertnonnull(blk);
+ ut_assertok(device_probe(blk));
+
+ /* Read the volume back through imagemap and compare */
+ ut_assertok(imagemap_create(blk, "vol0", 0, &imdev));
+ mapped = imagemap_map(imdev, 0, len);
+ ut_assert(!IS_ERR(mapped));
+ ut_asserteq_mem(wbuf, mapped, len);
+
+ imagemap_cleanup(imdev);
+ free(wbuf);
+
+ return 0;
+}
+IMAGEMAP_TEST(imagemap_test_ubiblock, 0);
+#endif /* MTD_UBI && UBI_BLOCK */
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 4328670d0d6..17610cdc2af 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -73,6 +73,7 @@ SUITE_DECL(optee);
SUITE_DECL(pci_mps);
SUITE_DECL(seama);
SUITE_DECL(setexpr);
+SUITE_DECL(imagemap);
SUITE_DECL(upl);
static struct suite suites[] = {
@@ -102,6 +103,7 @@ static struct suite suites[] = {
SUITE(pci_mps, "PCI Express Maximum Payload Size"),
SUITE(seama, "seama command parameters loading and decoding"),
SUITE(setexpr, "setexpr command"),
+ SUITE(imagemap, "imagemap on-demand storage loading"),
SUITE(upl, "Universal payload support"),
};
--
2.55.0
More information about the openwrt-devel
mailing list