| // SPDX-License-Identifier: GPL-2.0+ | |
| /* | |
| * Copyright (c) 2023 Addiva Elektronik | |
| * Author: Tobias Waldekranz <tobias@waldekranz.com> | |
| */ | |
| #include <blk.h> | |
| #include <blkmap.h> | |
| #include <dm.h> | |
| #include <env.h> | |
| #include <asm/test.h> | |
| #include <dm/test.h> | |
| #include <test/test.h> | |
| #include <test/ut.h> | |
| #define BLKSZ 0x200 | |
| struct mapping { | |
| int src; | |
| int cnt; | |
| int dst; | |
| }; | |
| const struct mapping unordered_mapping[] = { | |
| { 0, 1, 3 }, | |
| { 1, 3, 0 }, | |
| { 4, 2, 6 }, | |
| { 6, 2, 4 }, | |
| { 0, 0, 0 } | |
| }; | |
| const struct mapping identity_mapping[] = { | |
| { 0, 8, 0 }, | |
| { 0, 0, 0 } | |
| }; | |
| static char identity[8 * BLKSZ]; | |
| static char unordered[8 * BLKSZ]; | |
| static char buffer[8 * BLKSZ]; | |
| static void mkblob(void *base, const struct mapping *m) | |
| { | |
| int nr; | |
| for (; m->cnt; m++) { | |
| for (nr = 0; nr < m->cnt; nr++) { | |
| memset(base + (m->dst + nr) * BLKSZ, | |
| m->src + nr, BLKSZ); | |
| } | |
| } | |
| } | |
| static int dm_test_blkmap_read(struct unit_test_state *uts) | |
| { | |
| struct udevice *dev, *blk; | |
| const struct mapping *m; | |
| ut_assertok(blkmap_create("rdtest", &dev)); | |
| ut_assertok(blk_get_from_parent(dev, &blk)); | |
| /* Generate an ordered and an unordered pattern in memory */ | |
| mkblob(unordered, unordered_mapping); | |
| mkblob(identity, identity_mapping); | |
| /* Create a blkmap that cancels out the disorder */ | |
| for (m = unordered_mapping; m->cnt; m++) { | |
| ut_assertok(blkmap_map_mem(dev, m->src, m->cnt, | |
| unordered + m->dst * BLKSZ)); | |
| } | |
| /* Read out the data via the blkmap device to another area, | |
| * and verify that it matches the ordered pattern. | |
| */ | |
| ut_asserteq(8, blk_read(blk, 0, 8, buffer)); | |
| ut_assertok(memcmp(buffer, identity, sizeof(buffer))); | |
| ut_assertok(blkmap_destroy(dev)); | |
| return 0; | |
| } | |
| DM_TEST(dm_test_blkmap_read, 0); | |
| static int dm_test_blkmap_write(struct unit_test_state *uts) | |
| { | |
| struct udevice *dev, *blk; | |
| const struct mapping *m; | |
| ut_assertok(blkmap_create("wrtest", &dev)); | |
| ut_assertok(blk_get_from_parent(dev, &blk)); | |
| /* Generate an ordered and an unordered pattern in memory */ | |
| mkblob(unordered, unordered_mapping); | |
| mkblob(identity, identity_mapping); | |
| /* Create a blkmap that mimics the disorder */ | |
| for (m = unordered_mapping; m->cnt; m++) { | |
| ut_assertok(blkmap_map_mem(dev, m->src, m->cnt, | |
| buffer + m->dst * BLKSZ)); | |
| } | |
| /* Write the ordered data via the blkmap device to another | |
| * area, and verify that the result matches the unordered | |
| * pattern. | |
| */ | |
| ut_asserteq(8, blk_write(blk, 0, 8, identity)); | |
| ut_assertok(memcmp(buffer, unordered, sizeof(buffer))); | |
| ut_assertok(blkmap_destroy(dev)); | |
| return 0; | |
| } | |
| DM_TEST(dm_test_blkmap_write, 0); | |
| static int dm_test_blkmap_slicing(struct unit_test_state *uts) | |
| { | |
| struct udevice *dev; | |
| ut_assertok(blkmap_create("slicetest", &dev)); | |
| ut_assertok(blkmap_map_mem(dev, 8, 8, NULL)); | |
| /* Can't overlap on the low end */ | |
| ut_asserteq(-EBUSY, blkmap_map_mem(dev, 4, 5, NULL)); | |
| /* Can't be inside */ | |
| ut_asserteq(-EBUSY, blkmap_map_mem(dev, 10, 2, NULL)); | |
| /* Can't overlap on the high end */ | |
| ut_asserteq(-EBUSY, blkmap_map_mem(dev, 15, 4, NULL)); | |
| /* But we should be able to add slices right before and | |
| * after | |
| */ | |
| ut_assertok(blkmap_map_mem(dev, 4, 4, NULL)); | |
| ut_assertok(blkmap_map_mem(dev, 16, 4, NULL)); | |
| ut_assertok(blkmap_destroy(dev)); | |
| return 0; | |
| } | |
| DM_TEST(dm_test_blkmap_slicing, 0); | |
| static int dm_test_blkmap_creation(struct unit_test_state *uts) | |
| { | |
| struct udevice *first, *second; | |
| ut_assertok(blkmap_create("first", &first)); | |
| /* Can't have two "first"s */ | |
| ut_asserteq(-EBUSY, blkmap_create("first", &second)); | |
| /* But "second" should be fine */ | |
| ut_assertok(blkmap_create("second", &second)); | |
| /* Once "first" is destroyed, we should be able to create it | |
| * again | |
| */ | |
| ut_assertok(blkmap_destroy(first)); | |
| ut_assertok(blkmap_create("first", &first)); | |
| ut_assertok(blkmap_destroy(first)); | |
| ut_assertok(blkmap_destroy(second)); | |
| return 0; | |
| } | |
| DM_TEST(dm_test_blkmap_creation, 0); | |
| static int dm_test_cmd_blkmap(struct unit_test_state *uts) | |
| { | |
| ulong loadaddr = env_get_hex("loadaddr", 0); | |
| struct udevice *dev; | |
| ut_assertok(run_command("blkmap info", 0)); | |
| ut_assert_console_end(); | |
| ut_assertok(run_command("blkmap create ramdisk", 0)); | |
| ut_assert_nextline("Created \"ramdisk\""); | |
| ut_assert_console_end(); | |
| ut_assertnonnull((dev = blkmap_from_label("ramdisk"))); | |
| ut_assertok(run_commandf("blkmap map ramdisk 0 800 mem 0x%lx", loadaddr)); | |
| ut_assert_nextline("Block 0x0+0x800 mapped to 0x%lx", loadaddr); | |
| ut_assert_console_end(); | |
| ut_assertok(run_command("blkmap info", 0)); | |
| ut_assert_nextline("Device 0: Vendor: U-Boot Rev: 1.0 Prod: blkmap"); | |
| ut_assert_nextline(" Type: Hard Disk"); | |
| ut_assert_nextline(" Capacity: 1.0 MB = 0.0 GB (2048 x 512)"); | |
| ut_assert_console_end(); | |
| ut_assertok(run_command("blkmap get ramdisk dev devnum", 0)); | |
| ut_asserteq(dev_seq(dev), env_get_hex("devnum", 0xdeadbeef)); | |
| ut_assertok(run_command("blkmap destroy ramdisk", 0)); | |
| ut_assert_nextline("Destroyed \"ramdisk\""); | |
| ut_assert_console_end(); | |
| ut_assertok(run_command("blkmap info", 0)); | |
| ut_assert_console_end(); | |
| return 0; | |
| } | |
| DM_TEST(dm_test_cmd_blkmap, UTF_CONSOLE); |