1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2022, Linaro Limited
4  * Copyright (c) 2022, Heinrich Schuchardt <xypron.glpk@gmx.de>
5  */
6 
7 #include <blk.h>
8 #include <common.h>
9 #include <dm.h>
10 #include <fwu.h>
11 #include <fwu_mdata.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <memalign.h>
15 #include <part.h>
16 
17 #include <dm/test.h>
18 #include <test/ut.h>
19 
20 #include "fwu_mdata_disk_image.h"
21 
22 /* Block size of compressed disk image */
23 #define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
24 
25 static struct udevice *mmc_dev;
26 static struct blk_desc *dev_desc;
27 
28 /* One 8 byte block of the compressed disk image */
29 struct line {
30 	size_t addr;
31 	char *line;
32 };
33 
34 /* Compressed disk image */
35 struct compressed_disk_image {
36 	size_t length;
37 	struct line lines[];
38 };
39 
40 static const struct compressed_disk_image img = FWU_MDATA_DISK_IMG;
41 
42 /* Decompressed disk image */
43 static u8 *image;
44 
setup_blk_device(struct unit_test_state * uts)45 static int setup_blk_device(struct unit_test_state *uts)
46 {
47 	ut_assertok(uclass_get_device(UCLASS_MMC, 0, &mmc_dev));
48 	ut_assertok(blk_get_device_by_str("mmc", "0", &dev_desc));
49 
50 	return 0;
51 }
52 
populate_mmc_disk_image(struct unit_test_state * uts)53 static int populate_mmc_disk_image(struct unit_test_state *uts)
54 {
55 	u8 *buf;
56 	size_t i;
57 	size_t addr;
58 	size_t len;
59 
60 	buf = malloc(img.length);
61 	if (!buf)
62 		return -ENOMEM;
63 
64 	memset(buf, 0, img.length);
65 
66 	for (i = 0; ; i++) {
67 		if (!img.lines[i].line)
68 			break;
69 		addr = img.lines[i].addr;
70 		len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
71 		if (addr + len > img.length)
72 			len = img.length - addr;
73 		memcpy(buf + addr, img.lines[i].line, len);
74 	}
75 	image = buf;
76 
77 	return 0;
78 }
79 
write_mmc_blk_device(struct unit_test_state * uts)80 static int write_mmc_blk_device(struct unit_test_state *uts)
81 {
82 	lbaint_t blkcnt;
83 
84 	blkcnt = BLOCK_CNT(img.length, dev_desc);
85 
86 	ut_asserteq(blkcnt, blk_dwrite(dev_desc, 0, blkcnt, image));
87 
88 	return 0;
89 }
90 
dm_test_fwu_mdata_read(struct unit_test_state * uts)91 static int dm_test_fwu_mdata_read(struct unit_test_state *uts)
92 {
93 	struct udevice *dev;
94 	struct fwu_mdata mdata = { 0 };
95 
96 	ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev));
97 	ut_assertok(setup_blk_device(uts));
98 	ut_assertok(populate_mmc_disk_image(uts));
99 	ut_assertok(write_mmc_blk_device(uts));
100 
101 	ut_assertok(fwu_get_mdata(dev, &mdata));
102 
103 	ut_asserteq(mdata.version, 0x1);
104 
105 	return 0;
106 }
107 DM_TEST(dm_test_fwu_mdata_read, UT_TESTF_SCAN_FDT);
108 
dm_test_fwu_mdata_write(struct unit_test_state * uts)109 static int dm_test_fwu_mdata_write(struct unit_test_state *uts)
110 {
111 	u32 active_idx;
112 	struct udevice *dev;
113 	struct fwu_mdata mdata = { 0 };
114 
115 	ut_assertok(setup_blk_device(uts));
116 	ut_assertok(populate_mmc_disk_image(uts));
117 	ut_assertok(write_mmc_blk_device(uts));
118 
119 	ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev));
120 
121 	ut_assertok(fwu_get_mdata(dev, &mdata));
122 
123 	active_idx = (mdata.active_index + 1) % CONFIG_FWU_NUM_BANKS;
124 	ut_assertok(fwu_set_active_index(active_idx));
125 
126 	ut_assertok(fwu_get_mdata(dev, &mdata));
127 	ut_asserteq(mdata.active_index, active_idx);
128 
129 	return 0;
130 }
131 DM_TEST(dm_test_fwu_mdata_write, UT_TESTF_SCAN_FDT);
132 
dm_test_fwu_mdata_check(struct unit_test_state * uts)133 static int dm_test_fwu_mdata_check(struct unit_test_state *uts)
134 {
135 	struct udevice *dev;
136 
137 	ut_assertok(setup_blk_device(uts));
138 	ut_assertok(populate_mmc_disk_image(uts));
139 	ut_assertok(write_mmc_blk_device(uts));
140 
141 	ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev));
142 
143 	ut_assertok(fwu_check_mdata_validity());
144 
145 	return 0;
146 }
147 DM_TEST(dm_test_fwu_mdata_check, UT_TESTF_SCAN_FDT);
148