Merge branch 'for-2023.07' of https://source.denx.de/u-boot/custodians/u-boot-mpc8xx
[platform/kernel/u-boot.git] / test / dm / blkmap.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2023 Addiva Elektronik
4  * Author: Tobias Waldekranz <tobias@waldekranz.com>
5  */
6
7 #include <common.h>
8 #include <blk.h>
9 #include <blkmap.h>
10 #include <dm.h>
11 #include <asm/test.h>
12 #include <dm/test.h>
13 #include <test/test.h>
14 #include <test/ut.h>
15
16 #define BLKSZ 0x200
17
18 struct mapping {
19         int src;
20         int cnt;
21         int dst;
22 };
23
24 const struct mapping unordered_mapping[] = {
25         { 0, 1, 3 },
26         { 1, 3, 0 },
27         { 4, 2, 6 },
28         { 6, 2, 4 },
29
30         { 0, 0, 0 }
31 };
32
33 const struct mapping identity_mapping[] = {
34         { 0, 8, 0 },
35
36         { 0, 0, 0 }
37 };
38
39 static char identity[8 * BLKSZ];
40 static char unordered[8 * BLKSZ];
41 static char buffer[8 * BLKSZ];
42
43 static void mkblob(void *base, const struct mapping *m)
44 {
45         int nr;
46
47         for (; m->cnt; m++) {
48                 for (nr = 0; nr < m->cnt; nr++) {
49                         memset(base + (m->dst + nr) * BLKSZ,
50                                m->src + nr, BLKSZ);
51                 }
52         }
53 }
54
55 static int dm_test_blkmap_read(struct unit_test_state *uts)
56 {
57         struct udevice *dev, *blk;
58         const struct mapping *m;
59
60         ut_assertok(blkmap_create("rdtest", &dev));
61         ut_assertok(blk_get_from_parent(dev, &blk));
62
63         /* Generate an ordered and an unordered pattern in memory */
64         mkblob(unordered, unordered_mapping);
65         mkblob(identity, identity_mapping);
66
67         /* Create a blkmap that cancels out the disorder */
68         for (m = unordered_mapping; m->cnt; m++) {
69                 ut_assertok(blkmap_map_mem(dev, m->src, m->cnt,
70                                            unordered + m->dst * BLKSZ));
71         }
72
73         /* Read out the data via the blkmap device to another area,
74          * and verify that it matches the ordered pattern.
75          */
76         ut_asserteq(8, blk_read(blk, 0, 8, buffer));
77         ut_assertok(memcmp(buffer, identity, sizeof(buffer)));
78
79         ut_assertok(blkmap_destroy(dev));
80         return 0;
81 }
82 DM_TEST(dm_test_blkmap_read, 0);
83
84 static int dm_test_blkmap_write(struct unit_test_state *uts)
85 {
86         struct udevice *dev, *blk;
87         const struct mapping *m;
88
89         ut_assertok(blkmap_create("wrtest", &dev));
90         ut_assertok(blk_get_from_parent(dev, &blk));
91
92         /* Generate an ordered and an unordered pattern in memory */
93         mkblob(unordered, unordered_mapping);
94         mkblob(identity, identity_mapping);
95
96         /* Create a blkmap that mimics the disorder */
97         for (m = unordered_mapping; m->cnt; m++) {
98                 ut_assertok(blkmap_map_mem(dev, m->src, m->cnt,
99                                            buffer + m->dst * BLKSZ));
100         }
101
102         /* Write the ordered data via the blkmap device to another
103          * area, and verify that the result matches the unordered
104          * pattern.
105          */
106         ut_asserteq(8, blk_write(blk, 0, 8, identity));
107         ut_assertok(memcmp(buffer, unordered, sizeof(buffer)));
108
109         ut_assertok(blkmap_destroy(dev));
110         return 0;
111 }
112 DM_TEST(dm_test_blkmap_write, 0);
113
114 static int dm_test_blkmap_slicing(struct unit_test_state *uts)
115 {
116         struct udevice *dev;
117
118         ut_assertok(blkmap_create("slicetest", &dev));
119
120         ut_assertok(blkmap_map_mem(dev, 8, 8, NULL));
121
122         /* Can't overlap on the low end */
123         ut_asserteq(-EBUSY, blkmap_map_mem(dev,  4, 5, NULL));
124         /* Can't be inside */
125         ut_asserteq(-EBUSY, blkmap_map_mem(dev, 10, 2, NULL));
126         /* Can't overlap on the high end */
127         ut_asserteq(-EBUSY, blkmap_map_mem(dev, 15, 4, NULL));
128
129         /* But we should be able to add slices right before and
130          * after
131          */
132         ut_assertok(blkmap_map_mem(dev,  4, 4, NULL));
133         ut_assertok(blkmap_map_mem(dev, 16, 4, NULL));
134
135         ut_assertok(blkmap_destroy(dev));
136         return 0;
137 }
138 DM_TEST(dm_test_blkmap_slicing, 0);
139
140 static int dm_test_blkmap_creation(struct unit_test_state *uts)
141 {
142         struct udevice *first, *second;
143
144         ut_assertok(blkmap_create("first", &first));
145
146         /* Can't have two "first"s */
147         ut_asserteq(-EBUSY, blkmap_create("first", &second));
148
149         /* But "second" should be fine */
150         ut_assertok(blkmap_create("second", &second));
151
152         /* Once "first" is destroyed, we should be able to create it
153          * again
154          */
155         ut_assertok(blkmap_destroy(first));
156         ut_assertok(blkmap_create("first", &first));
157
158         ut_assertok(blkmap_destroy(first));
159         ut_assertok(blkmap_destroy(second));
160         return 0;
161 }
162 DM_TEST(dm_test_blkmap_creation, 0);
163
164 static int dm_test_cmd_blkmap(struct unit_test_state *uts)
165 {
166         ulong loadaddr = env_get_hex("loadaddr", 0);
167         struct udevice *dev;
168
169         console_record_reset();
170
171         ut_assertok(run_command("blkmap info", 0));
172         ut_assert_console_end();
173
174         ut_assertok(run_command("blkmap create ramdisk", 0));
175         ut_assert_nextline("Created \"ramdisk\"");
176         ut_assert_console_end();
177
178         ut_assertnonnull((dev = blkmap_from_label("ramdisk")));
179
180         ut_assertok(run_commandf("blkmap map ramdisk 0 800 mem 0x%lx", loadaddr));
181         ut_assert_nextline("Block 0x0+0x800 mapped to 0x%lx", loadaddr);
182         ut_assert_console_end();
183
184         ut_assertok(run_command("blkmap info", 0));
185         ut_assert_nextline("Device 0: Vendor: U-Boot Rev: 1.0 Prod: blkmap");
186         ut_assert_nextline("            Type: Hard Disk");
187         ut_assert_nextline("            Capacity: 1.0 MB = 0.0 GB (2048 x 512)");
188         ut_assert_console_end();
189
190         ut_assertok(run_command("blkmap get ramdisk dev devnum", 0));
191         ut_asserteq(dev_seq(dev), env_get_hex("devnum", 0xdeadbeef));
192
193         ut_assertok(run_command("blkmap destroy ramdisk", 0));
194         ut_assert_nextline("Destroyed \"ramdisk\"");
195         ut_assert_console_end();
196
197         ut_assertok(run_command("blkmap info", 0));
198         ut_assert_console_end();
199         return 0;
200 }
201 DM_TEST(dm_test_cmd_blkmap, 0);