1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Tests for mbr command
4 *
5 * Copyright 2023 Matrox Video
6 * Written by Alex Gendin <agendin@matrox.com>
7 */
8
9#include <dm.h>
10#include <console.h>
11#include <dm/test.h>
12#include <mapmem.h>
13#include <part.h>
14#include <asm/global_data.h>
15#include <dm/device-internal.h>
16#include <dm/lists.h>
17#include <test/suites.h>
18#include <test/ut.h>
19
20DECLARE_GLOBAL_DATA_PTR;
21/*
22 * Requirements for running test manually:
23 * mmc6.img - File size needs to be at least 12 MiB
24 *
25 * Command to create mmc6.img:
26 * $ dd if=/dev/zero of=mmc6.img bs=12M count=1
27 *
28 * To run this test manually, place mmc6.img into the same directory as u-boot,
29 * then run:
30 * $ ./u-boot -Tc 'ut mbr'
31 *
32 * To run this test as part of U-Boot test:
33 * $ ./test/py/test.py --bd sandbox --build -k ut_dm -v
34 * Note: mmc6.img will be created by the test suit.
35 */
36
37static char * mbr_parts_header = "setenv mbr_parts '";
38static char * mbr_parts_p1 = "uuid_disk=0x12345678;name=p1,start=8M,bootable,size=1M,id=0x0e";
39static char * mbr_parts_p2 = ";name=p2,size=1M,id=0x0e";
40static char * mbr_parts_p3 = ";name=p3,size=1M,id=0x0e";
41static char * mbr_parts_p4 = ";name=p4,size=1M,id=0x0e";
42static char * mbr_parts_p5 = ";name=[ext],size=2M,id=0x05;name=p5,size=1M,id=0x0e";
43static char * mbr_parts_tail = "'";
44
45/*
46 * One MBR partition
47000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
48000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 00  |...%$..@........|
49000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
50000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
51000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
52*/
53static unsigned mbr_cmp_start = 0x1B8;
54static unsigned mbr_cmp_size = 0x48;
55static unsigned char mbr_parts_ref_p1[] = {
56                                                0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
570x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
580x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
61};
62
63/*
64 * Two MBR partitions
65000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
66000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
67000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 00  |%..F...H........|
68000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
69000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
70*/
71static unsigned char mbr_parts_ref_p2[] = {
72                                                0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
730x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
740x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
750x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
77};
78
79/*
80 * Three MBR partitions
81000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
82000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
83000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 46  |%..F...H.......F|
84000001e0  06 01 0e 66 25 01 00 50  00 00 00 08 00 00 00 00  |...f%..P........|
85000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
86*/
87static unsigned char mbr_parts_ref_p3[] = {
88                                                0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
890x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
900x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46,
910x06, 0x01, 0x0e, 0x66, 0x25, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
93};
94
95/*
96 * Four MBR partitions
97000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
98000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
99000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 46  |%..F...H.......F|
100000001e0  06 01 0e 66 25 01 00 50  00 00 00 08 00 00 00 66  |...f%..P.......f|
101000001f0  26 01 0e 87 06 01 00 58  00 00 00 08 00 00 55 aa  |&......X......U.|
102*/
103static unsigned char mbr_parts_ref_p4[] = {
104                                                0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
1050x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
1060x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46,
1070x06, 0x01, 0x0e, 0x66, 0x25, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x66,
1080x26, 0x01, 0x0e, 0x87, 0x06, 0x01, 0x00, 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x55, 0xaa
109};
110
111/*
112 * Five MBR partitions
113000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
114000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
115000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 46  |%..F...H.......F|
116000001e0  06 01 0e 66 25 01 00 50  00 00 00 08 00 00 00 66  |...f%..P.......f|
117000001f0  26 01 05 a7 26 01 00 58  00 00 00 10 00 00 55 aa  |&...&..X......U.|
118*/
119static unsigned char mbr_parts_ref_p5[] = {
120                                                0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
1210x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
1220x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46,
1230x06, 0x01, 0x0e, 0x66, 0x25, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x66,
1240x26, 0x01, 0x05, 0xa7, 0x26, 0x01, 0x00, 0x58, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x55, 0xaa
125};
126static unsigned ebr_cmp_start = 0x1B8;
127static unsigned ebr_cmp_size = 0x48;
128/*
129 * EBR
13000b001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 87  |................|
13100b001c0  07 01 0e a7 26 01 00 08  00 00 00 08 00 00 00 00  |....&...........|
13200b001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
13300b001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
13400b001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
135*/
136static unsigned char ebr_parts_ref_p5[] = {
137                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
1380x07, 0x01, 0x0e, 0xa7, 0x26, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
1390x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1400x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1410x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
142};
143
144/* Fill write buffers with pseudo-random data */
145static void init_write_buffers(char *mbr_wb, size_t mbr_wb_size,
146			char *ebr_wb, size_t ebr_wb_size, unsigned seed)
147{
148	while (mbr_wb_size--) {
149		*mbr_wb++ = seed;
150		seed *= 43;
151		seed += 17 + mbr_wb_size/4;
152	}
153	while (ebr_wb_size--) {
154		*ebr_wb++ = seed;
155		seed *= 43;
156		seed += 17 + ebr_wb_size/4;
157	}
158}
159
160/* Build string with MBR partition(s) layout */
161static unsigned build_mbr_parts(char *buf, size_t buf_size, unsigned num_parts)
162{
163	size_t bytes_remaining, cur_str_size;
164	char * cur_buf;
165
166	if (!num_parts || num_parts > 5 || !buf)
167		return 1;
168
169	cur_buf = buf;
170	*cur_buf = '\0';
171	bytes_remaining = buf_size;
172
173	cur_str_size = sizeof(mbr_parts_header);
174	if (cur_str_size + 1 > bytes_remaining)
175		return 1;
176	strcat(cur_buf, mbr_parts_header);
177	bytes_remaining -= cur_str_size;
178
179	if (num_parts >= 1) {
180		cur_str_size = sizeof(mbr_parts_p1);
181		if (cur_str_size + 1 > bytes_remaining)
182			return 1;
183		strcat(cur_buf, mbr_parts_p1);
184		bytes_remaining -= cur_str_size;
185
186		if (num_parts >= 2) {
187			cur_str_size = sizeof(mbr_parts_p2);
188			if (cur_str_size + 1 > bytes_remaining)
189				return 1;
190			strcat(cur_buf, mbr_parts_p2);
191			bytes_remaining -= cur_str_size;
192
193			if (num_parts >= 3) {
194				cur_str_size = sizeof(mbr_parts_p3);
195				if (cur_str_size + 1 > bytes_remaining)
196					return 1;
197				strcat(cur_buf, mbr_parts_p3);
198				bytes_remaining -= cur_str_size;
199
200				if (num_parts == 4) {
201					cur_str_size = sizeof(mbr_parts_p4);
202					if (cur_str_size + 1 > bytes_remaining)
203						return 1;
204					strcat(cur_buf, mbr_parts_p4);
205					bytes_remaining -= cur_str_size;
206
207				}
208				else if (num_parts == 5) {
209					cur_str_size = sizeof(mbr_parts_p5);
210					if (cur_str_size + 1 > bytes_remaining)
211						return 1;
212					strcat(cur_buf, mbr_parts_p5);
213					bytes_remaining -= cur_str_size;
214
215				}
216			}
217		}
218	}
219
220	cur_str_size = sizeof(mbr_parts_tail);
221	if (cur_str_size + 1 > bytes_remaining)
222		return 1;
223	strcat(cur_buf, mbr_parts_tail);
224
225	return 0;
226}
227
228static int mbr_test_run(struct unit_test_state *uts)
229{
230	struct blk_desc *mmc_dev_desc;
231	unsigned char mbr_wbuf[512], ebr_wbuf[512], rbuf[512];
232	char mbr_parts_buf[256];
233	ulong mbr_wa, ebr_wa, ra, ebr_blk, mbr_parts_max;
234	struct udevice *dev;
235	ofnode root, node;
236
237	/* Enable the mmc6 node for this test */
238	root = oftree_root(oftree_default());
239	node = ofnode_find_subnode(root, "mmc6");
240	ut_assert(ofnode_valid(node));
241	ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
242
243	/*
244	 * 1 byte for null character
245	 * 2 reserved bytes
246	 */
247	mbr_parts_max = 1 + 2 +
248		strlen(mbr_parts_header) +
249		strlen(mbr_parts_p1) +
250		strlen(mbr_parts_p2) +
251		strlen(mbr_parts_p3) +
252		max(strlen(mbr_parts_p4), strlen(mbr_parts_p5)) +
253		strlen(mbr_parts_tail);
254	ut_assertf(sizeof(mbr_parts_buf) >= mbr_parts_max, "Buffer avail: %ld; buffer req: %ld\n",
255		sizeof(mbr_parts_buf), mbr_parts_max);
256
257	mbr_wa = map_to_sysmem(mbr_wbuf);
258	ebr_wa = map_to_sysmem(ebr_wbuf);
259	ra = map_to_sysmem(rbuf);
260	ebr_blk = (ulong)0xB00000 / 0x200;
261
262	/* Make sure mmc6 exists */
263	ut_asserteq(6, blk_get_device_by_str("mmc", "6", &mmc_dev_desc));
264	ut_assertok(console_record_reset_enable());
265	ut_assertok(run_commandf("mmc dev 6"));
266	ut_assert_nextline("switch to partitions #0, OK");
267	ut_assert_nextline("mmc6 is current device");
268	ut_assertok(ut_check_console_end(uts));
269
270	/* Make sure mmc6 is 12+ MiB in size */
271	ut_assertok(run_commandf("mmc read 0x%lx 0x%lx 1", ra, (ulong)0xBFFE00 / 0x200));
272
273	/* Test one MBR partition */
274	init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
275	ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 1));
276	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
277	memset(rbuf, 0, sizeof(rbuf));
278	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
279	ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
280	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
281	memset(rbuf, 0, sizeof(rbuf));
282	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
283	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
284	ut_assertok(console_record_reset_enable());
285	ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
286	ut_assertok(run_commandf("mbr write mmc 6"));
287	ut_assert_nextline("MBR: write success!");
288	ut_assertok(run_commandf("mbr verify mmc 6"));
289	ut_assert_nextline("MBR: verify success!");
290	memset(rbuf, 0, sizeof(rbuf));
291	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
292	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
293	ut_assertok(ut_check_console_end(uts));
294	/*
295	000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
296	000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 00  |...%$..@........|
297	000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
298	000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
299	000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
300	*/
301	memset(rbuf, 0, sizeof(rbuf));
302	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
303	for (unsigned i = 0; i < mbr_cmp_size; i++) {
304		ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p1[i],
305			"1P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
306			mbr_cmp_start + i, mbr_parts_ref_p1[i], rbuf[mbr_cmp_start + i]);
307	}
308
309	/* Test two MBR partitions */
310	init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
311	ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 2));
312	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
313	memset(rbuf, 0, sizeof(rbuf));
314	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
315	ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
316	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
317	memset(rbuf, 0, sizeof(rbuf));
318	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
319	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
320	ut_assertok(console_record_reset_enable());
321	ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
322	ut_assertok(run_commandf("mbr write mmc 6"));
323	ut_assert_nextline("MBR: write success!");
324	ut_assertok(run_commandf("mbr verify mmc 6"));
325	ut_assert_nextline("MBR: verify success!");
326	memset(rbuf, 0, sizeof(rbuf));
327	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
328	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
329	ut_assertok(ut_check_console_end(uts));
330	/*
331	000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
332	000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
333	000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 00  |%..F...H........|
334	000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
335	000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
336	*/
337	memset(rbuf, 0, sizeof(rbuf));
338	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
339	for (unsigned i = 0; i < mbr_cmp_size; i++) {
340		ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p2[i],
341			"2P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
342			mbr_cmp_start + i, mbr_parts_ref_p2[i], rbuf[mbr_cmp_start + i]);
343	}
344
345	/* Test three MBR partitions */
346	init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
347	ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 3));
348	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
349	memset(rbuf, 0, sizeof(rbuf));
350	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
351	ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
352	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
353	memset(rbuf, 0, sizeof(rbuf));
354	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
355	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
356	ut_assertok(console_record_reset_enable());
357	ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
358	ut_assertok(run_commandf("mbr write mmc 6"));
359	ut_assert_nextline("MBR: write success!");
360	ut_assertok(run_commandf("mbr verify mmc 6"));
361	ut_assert_nextline("MBR: verify success!");
362	memset(rbuf, 0, sizeof(rbuf));
363	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
364	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
365	ut_assertok(ut_check_console_end(uts));
366	/*
367	000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
368	000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
369	000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 46  |%..F...H.......F|
370	000001e0  06 01 0e 66 25 01 00 50  00 00 00 08 00 00 00 00  |...f%..P........|
371	000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
372	*/
373	memset(rbuf, 0, sizeof(rbuf));
374	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
375	for (unsigned i = 0; i < mbr_cmp_size; i++) {
376		ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p3[i],
377			"3P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
378			mbr_cmp_start + i, mbr_parts_ref_p3[i], rbuf[mbr_cmp_start + i]);
379	}
380
381	/* Test four MBR partitions */
382	init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
383	ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 4));
384	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
385	memset(rbuf, 0, sizeof(rbuf));
386	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
387	ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
388	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
389	memset(rbuf, 0, sizeof(rbuf));
390	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
391	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
392	ut_assertok(console_record_reset_enable());
393	ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
394	ut_assertok(run_commandf("mbr write mmc 6"));
395	ut_assert_nextline("MBR: write success!");
396	ut_assertok(run_commandf("mbr verify mmc 6"));
397	ut_assert_nextline("MBR: verify success!");
398	memset(rbuf, 0, sizeof(rbuf));
399	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
400	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
401	ut_assertok(ut_check_console_end(uts));
402	/*
403	000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
404	000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
405	000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 46  |%..F...H.......F|
406	000001e0  06 01 0e 66 25 01 00 50  00 00 00 08 00 00 00 66  |...f%..P.......f|
407	000001f0  26 01 0e 87 06 01 00 58  00 00 00 08 00 00 55 aa  |&......X......U.|
408	*/
409	memset(rbuf, 0, sizeof(rbuf));
410	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
411	for (unsigned i = 0; i < mbr_cmp_size; i++) {
412		ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p4[i],
413			"4P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
414			mbr_cmp_start + i, mbr_parts_ref_p4[i], rbuf[mbr_cmp_start + i]);
415	}
416
417	/* Test five MBR partitions */
418	init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
419	ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 5));
420	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
421	memset(rbuf, 0, sizeof(rbuf));
422	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
423	ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
424	ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
425	memset(rbuf, 0, sizeof(rbuf));
426	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
427	ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
428	ut_assertok(console_record_reset_enable());
429	ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
430	ut_assertf(0 == run_commandf("mbr write mmc 6"), "Invalid partitions string: %s\n", mbr_parts_buf);
431	ut_assert_nextline("MBR: write success!");
432	ut_assertok(run_commandf("mbr verify mmc 6"));
433	ut_assert_nextline("MBR: verify success!");
434	ut_assertok(ut_check_console_end(uts));
435	/*
436	000001b0  00 00 00 00 00 00 00 00  78 56 34 12 00 00 80 05  |........xV4.....|
437	000001c0  05 01 0e 25 24 01 00 40  00 00 00 08 00 00 00 25  |...%$..@.......%|
438	000001d0  25 01 0e 46 05 01 00 48  00 00 00 08 00 00 00 46  |%..F...H.......F|
439	000001e0  06 01 0e 66 25 01 00 50  00 00 00 08 00 00 00 66  |...f%..P.......f|
440	000001f0  26 01 05 a7 26 01 00 58  00 00 00 10 00 00 55 aa  |&...&..X......U.|
441	*/
442	memset(rbuf, 0, sizeof(rbuf));
443	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
444	for (unsigned i = 0; i < mbr_cmp_size; i++) {
445		ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p5[i],
446			"5P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
447			mbr_cmp_start + i, mbr_parts_ref_p5[i], rbuf[mbr_cmp_start + i]);
448	}
449	/*
450	00b001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 87  |................|
451	00b001c0  07 01 0e a7 26 01 00 08  00 00 00 08 00 00 00 00  |....&...........|
452	00b001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
453	00b001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
454	00b001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
455	*/
456	memset(rbuf, 0, sizeof(rbuf));
457	ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
458	for (unsigned i = 0; i < ebr_cmp_size; i++) {
459		ut_assertf(rbuf[ebr_cmp_start + i] == ebr_parts_ref_p5[i],
460			"5P EBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
461			ebr_cmp_start + i, ebr_parts_ref_p5[i], rbuf[ebr_cmp_start + i]);
462	}
463
464	return 0;
465}
466
467/* Declare mbr test */
468UNIT_TEST(mbr_test_run, UT_TESTF_CONSOLE_REC, mbr_test);
469
470int do_ut_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
471{
472	struct unit_test *tests = UNIT_TEST_SUITE_START(mbr_test);
473	const int n_ents = UNIT_TEST_SUITE_COUNT(mbr_test);
474
475	return cmd_ut_category("mbr", "mbr_test_", tests, n_ents, argc, argv);
476}
477
478static int dm_test_cmd_mbr(struct unit_test_state *uts)
479{
480	return mbr_test_run(uts);
481}
482
483DM_TEST(dm_test_cmd_mbr, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
484