Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2017-2018 IBM Corp. */
3 : :
4 : : #include <stdio.h>
5 : : #include <stdlib.h>
6 : : #include <stdint.h>
7 : : #include <string.h>
8 : : #include <stdarg.h>
9 : :
10 : : #include <libflash/libflash.h>
11 : : #include <libflash/libflash-priv.h>
12 : :
13 : : #include "stubs.h"
14 : : #include "mbox-server.h"
15 : :
16 : : #define zalloc(n) calloc(1, n)
17 : : #define __unused __attribute__((unused))
18 : :
19 : : #undef pr_fmt
20 : :
21 : 1 : void mbox_init(void)
22 : : {
23 : 1 : }
24 : :
25 : : #include "../libflash.c"
26 : : #include "../mbox-flash.c"
27 : : #include "../ecc.c"
28 : : #include "../blocklevel.c"
29 : :
30 : : #undef pr_fmt
31 : : #define pr_fmt(fmt) "MBOX-PROXY: " fmt
32 : :
33 : : /* client interface */
34 : :
35 : : #include "../../include/lpc-mbox.h"
36 : :
37 : : #define ERR(...) FL_DBG(__VA_ARGS__)
38 : :
39 : 4 : static int run_flash_test(struct blocklevel_device *bl)
40 : : {
41 : : struct mbox_flash_data *mbox_flash;
42 : 4 : char hello[] = "Hello World";
43 : : uint32_t erase_granule;
44 : : uint64_t total_size;
45 : : const char *name;
46 : : uint16_t *test;
47 : : char *tmp;
48 : : int i, rc;
49 : :
50 : 4 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
51 : :
52 : : /*
53 : : * Do something first so that if it has been reset it does that
54 : : * before we check versions
55 : : */
56 : 4 : rc = blocklevel_get_info(bl, &name, &total_size, &erase_granule);
57 : 4 : if (rc) {
58 : 0 : ERR("blocklevel_get_info() failed with err %d\n", rc);
59 : 0 : return 1;
60 : : }
61 : 4 : if (total_size != mbox_server_total_size()) {
62 : 0 : ERR("Total flash size is incorrect: 0x%08lx vs 0x%08x\n",
63 : : total_size, mbox_server_total_size());
64 : 0 : return 1;
65 : : }
66 : 4 : if (erase_granule != mbox_server_erase_granule()) {
67 : 0 : ERR("Erase granule is incorrect 0x%08x vs 0x%08x\n",
68 : : erase_granule, mbox_server_erase_granule());
69 : 0 : return 1;
70 : : }
71 : :
72 : :
73 : : /* Sanity check that mbox_flash has inited correctly */
74 : 4 : if (mbox_flash->version != mbox_server_version()) {
75 : 0 : ERR("MBOX Flash didn't agree with the server version\n");
76 : 0 : return 1;
77 : : }
78 : 4 : if (mbox_flash->version == 1 && mbox_flash->shift != 12) {
79 : 0 : ERR("MBOX Flash version 1 isn't using a 4K shift\n");
80 : 0 : return 1;
81 : : }
82 : :
83 : 4 : mbox_server_memset(0xff);
84 : :
85 : 4 : test = calloc(erase_granule * 20, 1);
86 : :
87 : : /* Make up a test pattern */
88 : 11878404 : for (i = 0; i < erase_granule * 10; i++)
89 : 11878400 : test[i] = i;
90 : :
91 : : /* Write 64k of stuff at 0 and at 128k */
92 : 4 : printf("Writing test patterns...\n");
93 : 4 : rc = blocklevel_write(bl, 0, test, erase_granule * 10);
94 : 4 : if (rc) {
95 : 0 : ERR("blocklevel_write(0, erase_granule * 10) failed with err %d\n", rc);
96 : 0 : return 1;
97 : : }
98 : 4 : rc = blocklevel_write(bl, erase_granule * 20, test, erase_granule * 10);
99 : 4 : if (rc) {
100 : 0 : ERR("blocklevel_write(0x20000, 0x10000) failed with err %d\n", rc);
101 : 0 : return 1;
102 : : }
103 : :
104 : 4 : if (mbox_server_memcmp(0, test, erase_granule * 10)) {
105 : 0 : ERR("Test pattern mismatch !\n");
106 : 0 : return 1;
107 : : }
108 : :
109 : : /* Write "Hello world" straddling the 64k boundary */
110 : 4 : printf("Writing test string...\n");
111 : 4 : rc = blocklevel_write(bl, (erase_granule * 10) - 8, hello, sizeof(hello));
112 : 4 : if (rc) {
113 : 0 : ERR("blocklevel_write(0xfffc, %s, %lu) failed with err %d\n",
114 : : hello, sizeof(hello), rc);
115 : 0 : return 1;
116 : : }
117 : :
118 : : /* Check result */
119 : 4 : if (mbox_server_memcmp((erase_granule * 10) - 8, hello, sizeof(hello))) {
120 : 0 : ERR("Test string mismatch!\n");
121 : 0 : return 1;
122 : : }
123 : :
124 : : /* Erase granule is something but never 0x50, this shouldn't succeed */
125 : 4 : rc = blocklevel_erase(bl, 0, 0x50);
126 : 4 : if (!rc) {
127 : 0 : ERR("blocklevel_erase(0, 0x50) didn't fail!\n");
128 : 0 : return 1;
129 : : }
130 : :
131 : : /* Check it didn't silently erase */
132 : 4 : if (mbox_server_memcmp(0, test, (erase_granule * 10) - 8)) {
133 : 0 : ERR("Test pattern mismatch !\n");
134 : 0 : return 1;
135 : : }
136 : :
137 : : /*
138 : : * For v1 protocol this should NOT call MARK_WRITE_ERASED!
139 : : * The server MARK_WRITE_ERASED will call exit(1) if it gets a
140 : : * MARK_WRITE_ERASED and version == 1
141 : : */
142 : 4 : rc = blocklevel_erase(bl, 0, erase_granule);
143 : 4 : if (rc) {
144 : 0 : ERR("blocklevel_erase(0, erase_granule) failed with err %d\n", rc);
145 : 0 : return 1;
146 : : }
147 : :
148 : : /*
149 : : * Version 1 doesn't specify that the buffer actually becomes 0xff
150 : : * It is up to the daemon to do what it wants really - there are
151 : : * implementations that do nothing but writes to the same region
152 : : * work fine
153 : : */
154 : :
155 : : /* This check is important for v2 */
156 : : /* Check stuff got erased */
157 : 4 : tmp = malloc(erase_granule * 2);
158 : 4 : if (!tmp) {
159 : 0 : ERR("malloc failed\n");
160 : 0 : return 1;
161 : : }
162 : 4 : if (mbox_server_version() > 1) {
163 : 3 : memset(tmp, 0xff, erase_granule);
164 : 3 : if (mbox_server_memcmp(0, tmp, erase_granule)) {
165 : 0 : ERR("Buffer not erased\n");
166 : 0 : rc = 1;
167 : 0 : goto out;
168 : : }
169 : : }
170 : :
171 : : /* Read beyond the end of flash */
172 : 4 : rc = blocklevel_read(bl, total_size, tmp, 0x1000);
173 : 4 : if (!rc) {
174 : 0 : ERR("blocklevel_read(total_size, 0x1000) (read beyond the end) succeeded\n");
175 : 0 : goto out;
176 : : }
177 : :
178 : : /* Test some simple write/read cases, avoid first page */
179 : 4 : rc = blocklevel_write(bl, erase_granule * 2, test, erase_granule / 2);
180 : 4 : if (rc) {
181 : 0 : ERR("blocklevel_write(erase_granule, erase_granule / 2) failed with err %d\n", rc);
182 : 0 : goto out;
183 : : }
184 : 4 : rc = blocklevel_write(bl, erase_granule * 2 + erase_granule / 2, test, erase_granule / 2);
185 : 4 : if (rc) {
186 : 0 : ERR("blocklevel_write(erase_granule * 2 + erase_granule / 2, erase_granule) failed with err %d\n", rc);
187 : 0 : goto out;
188 : : }
189 : :
190 : 4 : rc = mbox_server_memcmp(erase_granule * 2, test, erase_granule / 2);
191 : 4 : if (rc) {
192 : 0 : ERR("%s:%d mbox_server_memcmp miscompare\n", __FILE__, __LINE__);
193 : 0 : goto out;
194 : : }
195 : 4 : rc = mbox_server_memcmp(erase_granule * 2 + erase_granule / 2, test, erase_granule / 2);
196 : 4 : if (rc) {
197 : 0 : ERR("%s:%d mbox_server_memcmp miscompare\n", __FILE__, __LINE__);
198 : 0 : goto out;
199 : : }
200 : :
201 : : /* Great so the writes made it, can we read them back? Do it in
202 : : * four small reads */
203 : 20 : for (i = 0; i < 4; i++) {
204 : 16 : rc = blocklevel_read(bl, erase_granule * 2 + (i * erase_granule / 4), tmp + (i * erase_granule / 4), erase_granule / 4);
205 : 16 : if (rc) {
206 : 0 : ERR("blocklevel_read(0x%08x, erase_granule / 4) failed with err %d\n",
207 : : 2 * erase_granule + (i * erase_granule / 4), rc);
208 : 0 : goto out;
209 : : }
210 : : }
211 : 4 : rc = memcmp(test, tmp, erase_granule / 2);
212 : 4 : if (rc) {
213 : 0 : ERR("%s:%d read back miscompare\n", __FILE__, __LINE__);
214 : 0 : goto out;
215 : : }
216 : 4 : rc = memcmp(test, tmp + erase_granule / 2, erase_granule / 2);
217 : 4 : if (rc) {
218 : 0 : ERR("%s:%d read back miscompare\n", __FILE__, __LINE__);
219 : 0 : goto out;
220 : : }
221 : :
222 : : /*
223 : : * Make sure we didn't corrupt other stuff, also make sure one
224 : : * blocklevel call will understand how to read from two windows
225 : : */
226 : 16 : for (i = 3; i < 9; i = i + 2) {
227 : 12 : printf("i:%d erase: 0x%08x\n", i, erase_granule);
228 : 12 : rc = blocklevel_read(bl, i * erase_granule, tmp, 2 * erase_granule);
229 : 12 : if (rc) {
230 : 0 : ERR("blocklevel_read(0x%08x, 2 * erase_granule) failed with err: %d\n", i * erase_granule, rc);
231 : 0 : goto out;
232 : : }
233 : 12 : rc = memcmp(((char *)test) + (i * erase_granule), tmp, 2 * erase_granule);
234 : 12 : if (rc) {
235 : 0 : ERR("%s:%d read back miscompare (pos: 0x%08x)\n", __FILE__, __LINE__, i * erase_granule);
236 : 0 : goto out;
237 : : }
238 : : }
239 : :
240 : 4 : srand(1);
241 : : /*
242 : : * Try to jump around the place doing a tonne of small reads.
243 : : * Worth doing the same with writes TODO
244 : : */
245 : : #ifdef __STRICT_TEST__
246 : : #define TEST_LOOPS 1000
247 : : #else
248 : : #define TEST_LOOPS 100
249 : : #endif
250 : 404 : for (i = 0; i < TEST_LOOPS; i++) {
251 : 400 : int r = rand();
252 : :
253 : 400 : printf("Loop %d of %d\n", i, TEST_LOOPS);
254 : : /* Avoid reading too far, just skip it */
255 : 400 : if ((r % erase_granule * 10) + (r % erase_granule * 2) > erase_granule * 10)
256 : 65 : continue;
257 : :
258 : 335 : rc = blocklevel_read(bl, erase_granule * 20 + (r % erase_granule * 10), tmp, r % erase_granule * 2);
259 : 335 : if (rc) {
260 : 0 : ERR("blocklevel_read(0x%08x, 0x%08x) failed with err %d\n", 0x20000 + (r % 0x100000), r % 0x2000, rc);
261 : 0 : goto out;
262 : : }
263 : 335 : rc = memcmp(((char *)test) + (r % erase_granule * 10), tmp, r % erase_granule * 2);
264 : 335 : if (rc) {
265 : 0 : ERR("%s:%d read back miscompare (pos: 0x%08x)\n", __FILE__, __LINE__, 0x20000 + (r % 0x10000));
266 : 0 : goto out;
267 : : }
268 : : }
269 : 4 : out:
270 : 4 : free(tmp);
271 : 4 : return rc;
272 : : }
273 : :
274 : 1 : int main(void)
275 : : {
276 : : struct blocklevel_device *bl;
277 : : int rc;
278 : :
279 : 1 : libflash_debug = true;
280 : :
281 : 1 : mbox_server_init();
282 : :
283 : : #ifdef __STRICT_TEST__
284 : : printf("Found __STRICT_TEST__, this may take time time.\n");
285 : : #else
286 : 1 : printf("__STRICT_TEST__ not found, use make strict-check for a more\n");
287 : 1 : printf("thorough test, it will take significantly longer.\n");
288 : : #endif
289 : :
290 : 1 : printf("Doing mbox-flash V1 tests\n");
291 : :
292 : : /* run test */
293 : 1 : mbox_flash_init(&bl);
294 : 1 : rc = run_flash_test(bl);
295 : 1 : if (rc)
296 : 0 : goto out;
297 : : /*
298 : : * Trick mbox-flash into thinking there was a reboot so we can
299 : : * switch to v2
300 : : */
301 : :
302 : 1 : printf("Doing mbox-flash V2 tests\n");
303 : :
304 : 1 : mbox_server_reset(2, 12);
305 : :
306 : : /* Do all the tests again */
307 : 1 : rc = run_flash_test(bl);
308 : 1 : if (rc)
309 : 0 : goto out;
310 : :
311 : 1 : mbox_server_reset(2, 17);
312 : :
313 : : /* Do all the tests again */
314 : 1 : rc = run_flash_test(bl);
315 : 1 : if (rc)
316 : 0 : goto out;
317 : :
318 : :
319 : 1 : printf("Doing mbox-flash V3 tests\n");
320 : :
321 : 1 : mbox_server_reset(3, 20);
322 : :
323 : : /* Do all the tests again */
324 : 1 : rc = run_flash_test(bl);
325 : :
326 : :
327 : 1 : out:
328 : 1 : mbox_flash_exit(bl);
329 : :
330 : 1 : mbox_server_destroy();
331 : :
332 : 1 : return rc;
333 : : }
|