1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Tests for read and write commands
4  */
5 
6 #include <common.h>
7 #include <dm/test.h>
8 #include <mapmem.h>
9 #include <part.h>
10 #include <test/test.h>
11 #include <test/ut.h>
12 
setup_partitions(struct unit_test_state * uts,struct blk_desc ** mmc_dev_desc)13 static int setup_partitions(struct unit_test_state *uts, struct blk_desc **mmc_dev_desc)
14 {
15 	char str_disk_guid[UUID_STR_LEN + 1];
16 	struct disk_partition parts[2] = {
17 		{
18 			.start = 48, /* GPT data takes up the first 34 blocks or so */
19 			.size = 4,
20 			.name = "data",
21 		},
22 		{
23 			.start = 52,
24 			.size = 10,
25 			.name = "log",
26 		},
27 	};
28 
29 	ut_asserteq(2, blk_get_device_by_str("mmc", "2", mmc_dev_desc));
30 	if (CONFIG_IS_ENABLED(RANDOM_UUID)) {
31 		gen_rand_uuid_str(parts[0].uuid, UUID_STR_FORMAT_STD);
32 		gen_rand_uuid_str(parts[1].uuid, UUID_STR_FORMAT_STD);
33 		gen_rand_uuid_str(str_disk_guid, UUID_STR_FORMAT_STD);
34 	}
35 	ut_assertok(gpt_restore(*mmc_dev_desc, str_disk_guid, parts,
36 				ARRAY_SIZE(parts)));
37 	return 0;
38 }
39 
40 /* Fill the write buffer with pseudo-random data, clear the read buffer. */
init_buffers(char * rb,char * wb,size_t size,unsigned seed)41 static void init_buffers(char *rb, char *wb, size_t size, unsigned seed)
42 {
43 	memset(rb, 0, size);
44 	while (size--) {
45 		*wb++ = seed;
46 		seed *= 43;
47 		seed += 17 + size/4;
48 	}
49 }
50 
dm_test_read_write(struct unit_test_state * uts)51 static int dm_test_read_write(struct unit_test_state *uts)
52 {
53 	struct blk_desc *dev_desc;
54 	char wbuf[1024], rbuf[1024];
55 	ulong wa, ra;
56 
57 #define INIT_BUFFERS() init_buffers(rbuf, wbuf, sizeof(rbuf), __LINE__)
58 
59 	ut_assertok(setup_partitions(uts, &dev_desc));
60 
61 	wa = map_to_sysmem(wbuf);
62 	ra = map_to_sysmem(rbuf);
63 
64 	/* Simple test, write to/read from same partition. */
65 	INIT_BUFFERS();
66 	ut_assertok(run_commandf("write mmc 2:1 0x%lx 0 2", wa));
67 	ut_assertok(run_commandf("read  mmc 2:1 0x%lx 0 2", ra));
68 	ut_assertok(memcmp(wbuf, rbuf, sizeof(wbuf)));
69 	ut_assertok(run_commandf("read  mmc 2:1 0x%lx 1 1", ra));
70 	ut_assertok(memcmp(&wbuf[512], rbuf, 512));
71 
72 	/* Use name for write, number for read. */
73 	INIT_BUFFERS();
74 	ut_assertok(run_commandf("write mmc 2#log 0x%lx 0 2", wa));
75 	ut_assertok(run_commandf("read  mmc 2:2   0x%lx 0 2", ra));
76 	ut_assertok(memcmp(wbuf, rbuf, sizeof(wbuf)));
77 
78 	/* Use full device for write, name for read. */
79 	INIT_BUFFERS();
80 	ut_assertok(run_commandf("write mmc 2:0    0x%lx 0x30 2", wa));
81 	ut_assertok(run_commandf("read  mmc 2#data 0x%lx    0 2", ra));
82 	ut_assertok(memcmp(wbuf, rbuf, sizeof(wbuf)));
83 
84 	/* Use name for write, full device for read */
85 	INIT_BUFFERS();
86 	ut_assertok(run_commandf("write mmc 2#log 0x%lx    1 2", wa));
87 	ut_assertok(run_commandf("read  mmc 2:0   0x%lx 0x35 2", ra));
88 	ut_assertok(memcmp(wbuf, rbuf, sizeof(wbuf)));
89 
90 	/* Read/write outside partition bounds should be rejected upfront. */
91 	console_record_reset_enable();
92 	ut_asserteq(1, run_commandf("read mmc 2#data 0x%lx 3 2", ra));
93 	ut_assert_nextlinen("read out of range");
94 	ut_assert_console_end();
95 
96 	console_record_reset_enable();
97 	ut_asserteq(1, run_commandf("write mmc 2#log 0x%lx 9 2", wa));
98 	ut_assert_nextlinen("write out of range");
99 	ut_assert_console_end();
100 
101 	return 0;
102 }
103 
104 DM_TEST(dm_test_read_write, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
105