Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2013-2018 IBM Corp. */
3 : :
4 : : #include <stdio.h>
5 : : #include <stdlib.h>
6 : : #include <stdint.h>
7 : : #include <string.h>
8 : :
9 : : #include <libflash/blocklevel.h>
10 : :
11 : : #include "../ecc.c"
12 : : #include "../blocklevel.c"
13 : :
14 : : #define __unused __attribute__((unused))
15 : :
16 : : #define ERR(fmt...) fprintf(stderr, fmt)
17 : :
18 : : bool libflash_debug;
19 : :
20 : 0 : static int bl_test_bad_read(struct blocklevel_device *bl __unused, uint64_t pos __unused,
21 : : void *buf __unused, uint64_t len __unused)
22 : : {
23 : 0 : return FLASH_ERR_PARM_ERROR;
24 : : }
25 : :
26 : 25 : static int bl_test_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
27 : : {
28 : 25 : if (pos + len > 0x1000)
29 : 0 : return FLASH_ERR_PARM_ERROR;
30 : :
31 : 25 : memcpy(buf, bl->priv + pos, len);
32 : :
33 : 25 : return 0;
34 : : }
35 : :
36 : 0 : static int bl_test_bad_write(struct blocklevel_device *bl __unused, uint64_t pos __unused,
37 : : const void *buf __unused, uint64_t len __unused)
38 : : {
39 : 0 : return FLASH_ERR_PARM_ERROR;
40 : : }
41 : :
42 : 14 : static int bl_test_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)
43 : : {
44 : 14 : if (pos + len > 0x1000)
45 : 0 : return FLASH_ERR_PARM_ERROR;
46 : :
47 : 14 : memcpy(bl->priv + pos, buf, len);
48 : :
49 : 14 : return 0;
50 : : }
51 : :
52 : 12 : static int bl_test_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
53 : : {
54 : 12 : if (pos + len > 0x1000)
55 : 0 : return FLASH_ERR_PARM_ERROR;
56 : :
57 : 12 : memset(bl->priv + pos, 0xff, len);
58 : :
59 : 12 : return 0;
60 : : }
61 : :
62 : 0 : static void dump_buf(uint8_t *buf, int start, int end, int miss)
63 : : {
64 : : int i;
65 : :
66 : 0 : printf("pos: value\n");
67 : 0 : for (i = start; i < end; i++)
68 : 0 : printf("%04x: %c%s\n", i, buf[i] == 0xff ? '-' : buf[i], i == miss ? " <- First missmatch" : "");
69 : 0 : }
70 : :
71 : : /*
72 : : * Returns zero if the buffer is ok. Otherwise returns the position of
73 : : * the mismatch. If the mismatch is at zero -1 is returned
74 : : */
75 : 8 : static int check_buf(uint8_t *buf, int zero_start, int zero_end)
76 : : {
77 : : int i;
78 : :
79 : 32776 : for (i = 0; i < 0x1000; i++) {
80 : 32768 : if (i >= zero_start && i < zero_end && buf[i] != 0xff)
81 : 0 : return i == 0 ? -1 : i;
82 : 32768 : if ((i < zero_start || i >= zero_end) && buf[i] != (i % 26) + 'a')
83 : 0 : return i == 0 ? -1 : i;
84 : : }
85 : :
86 : 8 : return 0;
87 : : }
88 : :
89 : 9 : static void reset_buf(uint8_t *buf)
90 : : {
91 : : int i;
92 : :
93 : 36873 : for (i = 0; i < 0x1000; i++) {
94 : : /* This gives repeating a - z which will be nice to visualise */
95 : 36864 : buf[i] = (i % 26) + 'a';
96 : : }
97 : 9 : }
98 : :
99 : 0 : static void print_ptr(void *ptr, int len)
100 : : {
101 : : int i;
102 : 0 : char *p = ptr;
103 : :
104 : 0 : printf("0x");
105 : 0 : for (i = 0; i < len; i++) {
106 : 0 : putchar(*p);
107 : 0 : if (i && i % 8 == 0) {
108 : 0 : putchar('\n');
109 : 0 : if (len - i)
110 : 0 : printf("0x");
111 : : }
112 : : }
113 : 0 : putchar('\n');
114 : 0 : }
115 : :
116 : 1 : int main(void)
117 : : {
118 : 1 : struct blocklevel_device bl_mem = { 0 };
119 : 1 : struct blocklevel_device *bl = &bl_mem;
120 : : uint64_t with_ecc[10], without_ecc[10];
121 : 1 : char *buf = NULL, *data = NULL;
122 : : int i, rc, miss;
123 : :
124 : 1 : if (blocklevel_ecc_protect(bl, 0, 0x1000)) {
125 : 0 : ERR("Failed to blocklevel_ecc_protect!\n");
126 : 0 : return 1;
127 : : }
128 : :
129 : : /* 0x1000 -> 0x3000 should remain unprotected */
130 : :
131 : 1 : if (blocklevel_ecc_protect(bl, 0x3000, 0x1000)) {
132 : 0 : ERR("Failed to blocklevel_ecc_protect(0x3000, 0x1000)\n");
133 : 0 : return 1;
134 : : }
135 : 1 : if (blocklevel_ecc_protect(bl, 0x2f00, 0x1100)) {
136 : 0 : ERR("Failed to blocklevel_ecc_protect(0x2f00, 0x1100)\n");
137 : 0 : return 1;
138 : : }
139 : :
140 : : /* Zero length protection */
141 : 1 : if (!blocklevel_ecc_protect(bl, 0x4000, 0)) {
142 : 0 : ERR("Shouldn't have succeeded blocklevel_ecc_protect(0x4000, 0)\n");
143 : 0 : return 1;
144 : : }
145 : :
146 : : /* Minimum creatable size */
147 : 1 : if (blocklevel_ecc_protect(bl, 0x4000, BYTES_PER_ECC)) {
148 : 0 : ERR("Failed to blocklevel_ecc_protect(0x4000, BYTES_PER_ECC)\n");
149 : 0 : return 1;
150 : : }
151 : :
152 : : /* Deal with overlapping protections */
153 : 1 : if (blocklevel_ecc_protect(bl, 0x100, 0x1000)) {
154 : 0 : ERR("Failed to protect overlaping region blocklevel_ecc_protect(0x100, 0x1000)\n");
155 : 0 : return 1;
156 : : }
157 : :
158 : : /* Deal with overflow */
159 : 1 : if (!blocklevel_ecc_protect(bl, 1, 0xFFFFFFFF)) {
160 : 0 : ERR("Added an 'overflow' protection blocklevel_ecc_protect(1, 0xFFFFFFFF)\n");
161 : 0 : return 1;
162 : : }
163 : :
164 : : /* Protect everything */
165 : 1 : if (blocklevel_ecc_protect(bl, 0, 0xFFFFFFFF)) {
166 : 0 : ERR("Couldn't protect everything blocklevel_ecc_protect(0, 0xFFFFFFFF)\n");
167 : 0 : return 1;
168 : : }
169 : :
170 : 1 : if (ecc_protected(bl, 0, 1, NULL) != 1) {
171 : 0 : ERR("Invaid result for ecc_protected(0, 1)\n");
172 : 0 : return 1;
173 : : }
174 : :
175 : 1 : if (ecc_protected(bl, 0, 0x1000, NULL) != 1) {
176 : 0 : ERR("Invalid result for ecc_protected(0, 0x1000)\n");
177 : 0 : return 1;
178 : : }
179 : :
180 : 1 : if (ecc_protected(bl, 0x100, 0x100, NULL) != 1) {
181 : 0 : ERR("Invalid result for ecc_protected(0x0100, 0x100)\n");
182 : 0 : return 1;
183 : : }
184 : :
185 : : /* Clear the protections */
186 : 1 : bl->ecc_prot.n_prot = 0;
187 : : /* Reprotect */
188 : 1 : if (blocklevel_ecc_protect(bl, 0x3000, 0x1000)) {
189 : 0 : ERR("Failed to blocklevel_ecc_protect(0x3000, 0x1000)\n");
190 : 0 : return 1;
191 : : }
192 : : /* Deal with overlapping protections */
193 : 1 : if (blocklevel_ecc_protect(bl, 0x100, 0x1000)) {
194 : 0 : ERR("Failed to protect overlaping region blocklevel_ecc_protect(0x100, 0x1000)\n");
195 : 0 : return 1;
196 : : }
197 : :
198 : 1 : if (ecc_protected(bl, 0x1000, 0, NULL) != 1) {
199 : 0 : ERR("Invalid result for ecc_protected(0x1000, 0)\n");
200 : 0 : return 1;
201 : : }
202 : :
203 : 1 : if (ecc_protected(bl, 0x1000, 0x1000, NULL) != -1) {
204 : 0 : ERR("Invalid result for ecc_protected(0x1000, 0x1000)\n");
205 : 0 : return 1;
206 : : }
207 : :
208 : 1 : if (ecc_protected(bl, 0x1000, 0x100, NULL) != 1) {
209 : 0 : ERR("Invalid result for ecc_protected(0x1000, 0x100)\n");
210 : 0 : return 1;
211 : : }
212 : :
213 : 1 : if (ecc_protected(bl, 0x2000, 0, NULL) != 0) {
214 : 0 : ERR("Invalid result for ecc_protected(0x2000, 0)\n");
215 : 0 : return 1;
216 : : }
217 : :
218 : 1 : if (ecc_protected(bl, 0x4000, 1, NULL) != 0) {
219 : 0 : ERR("Invalid result for ecc_protected(0x4000, 1)\n");
220 : 0 : return 1;
221 : : }
222 : :
223 : : /* Check for asking for a region with mixed protection */
224 : 1 : if (ecc_protected(bl, 0x100, 0x2000, NULL) != -1) {
225 : 0 : ERR("Invalid result for ecc_protected(0x100, 0x2000)\n");
226 : 0 : return 1;
227 : : }
228 : :
229 : : /* Test the auto extending of regions */
230 : 1 : if (blocklevel_ecc_protect(bl, 0x5000, 0x100)) {
231 : 0 : ERR("Failed to blocklevel_ecc_protect(0x5000, 0x100)\n");
232 : 0 : return 1;
233 : : }
234 : :
235 : 1 : if (blocklevel_ecc_protect(bl, 0x5100, 0x100)) {
236 : 0 : ERR("Failed to blocklevel_ecc_protect(0x5100, 0x100)\n");
237 : 0 : return 1;
238 : : }
239 : :
240 : 1 : if (blocklevel_ecc_protect(bl, 0x5200, 0x100)) {
241 : 0 : ERR("Failed to blocklevel_ecc_protect(0x5200, 0x100)\n");
242 : 0 : return 1;
243 : : }
244 : :
245 : 1 : if (ecc_protected(bl, 0x5120, 0x10, NULL) != 1) {
246 : 0 : ERR("Invalid result for ecc_protected(0x5120, 0x10)\n");
247 : 0 : return 1;
248 : : }
249 : :
250 : 1 : if (blocklevel_ecc_protect(bl, 0x4f00, 0x100)) {
251 : 0 : ERR("Failed to blocklevel_ecc_protected(0x4900, 0x100)\n");
252 : 0 : return 1;
253 : : }
254 : :
255 : 1 : if (blocklevel_ecc_protect(bl, 0x4900, 0x100)) {
256 : 0 : ERR("Failed to blocklevel_ecc_protected(0x4900, 0x100)\n");
257 : 0 : return 1;
258 : : }
259 : :
260 : 1 : if (ecc_protected(bl, 0x4920, 0x10, NULL) != 1) {
261 : 0 : ERR("Invalid result for ecc_protected(0x4920, 0x10)\n");
262 : 0 : return 1;
263 : : }
264 : :
265 : 1 : if (blocklevel_ecc_protect(bl, 0x5290, 0x10)) {
266 : 0 : ERR("Failed to blocklevel_ecc_protect(0x5290, 0x10)\n");
267 : 0 : return 1;
268 : : }
269 : :
270 : : /* Test the auto extending of regions */
271 : 1 : if (blocklevel_ecc_protect(bl, 0x6000, 0x100)) {
272 : 0 : ERR("Failed to blocklevel_ecc_protect(0x6000, 0x100)\n");
273 : 0 : return 1;
274 : : }
275 : :
276 : 1 : if (blocklevel_ecc_protect(bl, 0x6200, 0x100)) {
277 : 0 : ERR("Failed to blocklevel_ecc_protect(0x6200, 0x100)\n");
278 : 0 : return 1;
279 : : }
280 : :
281 : : /* Test ECC reading and writing being 100% transparent to the
282 : : * caller */
283 : 1 : buf = malloc(0x1000);
284 : 1 : data = malloc(0x100);
285 : 1 : if (!buf || !data) {
286 : 0 : ERR("Malloc failed\n");
287 : 0 : rc = 1;
288 : 0 : goto out;
289 : : }
290 : 1 : memset(bl, 0, sizeof(*bl));
291 : 1 : bl_mem.read = &bl_test_read;
292 : 1 : bl_mem.write = &bl_test_write;
293 : 1 : bl_mem.erase = &bl_test_erase;
294 : 1 : bl_mem.erase_mask = 0xff;
295 : 1 : bl_mem.priv = buf;
296 : 1 : reset_buf(buf);
297 : :
298 : :
299 : : /*
300 : : * Test 1: One full and exact erase block, this shouldn't call
301 : : * read or write, ensure this fails if it does.
302 : : */
303 : 1 : bl_mem.write = &bl_test_bad_write;
304 : 1 : bl_mem.read = &bl_test_bad_read;
305 : 1 : if (blocklevel_smart_erase(bl, 0x100, 0x100)) {
306 : 0 : ERR("Failed to blocklevel_smart_erase(0x100, 0x100)\n");
307 : 0 : goto out;
308 : : }
309 : 1 : miss = check_buf(buf, 0x100, 0x200);
310 : 1 : if (miss) {
311 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x100) at 0x%0x\n",
312 : : miss == -1 ? 0 : miss);
313 : 0 : dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
314 : 0 : dump_buf(buf, 0x1fc, 0x205, miss == -1 ? 0 : miss);
315 : 0 : goto out;
316 : : }
317 : 1 : bl_mem.read = &bl_test_read;
318 : 1 : bl_mem.write = &bl_test_write;
319 : :
320 : 1 : reset_buf(buf);
321 : : /* Test 2: Only touch one erase block */
322 : 1 : if (blocklevel_smart_erase(bl, 0x20, 0x40)) {
323 : 0 : ERR("Failed to blocklevel_smart_erase(0x20, 0x40)\n");
324 : 0 : goto out;
325 : : }
326 : 1 : miss = check_buf(buf, 0x20, 0x60);
327 : 1 : if (miss) {
328 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x20, 0x40) at 0x%x\n",
329 : : miss == -1 ? 0 : miss);
330 : 0 : dump_buf(buf, 0x1c, 0x65, miss == -1 ? 0 : miss);
331 : 0 : goto out;
332 : : }
333 : :
334 : 1 : reset_buf(buf);
335 : : /* Test 3: Start aligned but finish somewhere in it */
336 : 1 : if (blocklevel_smart_erase(bl, 0x100, 0x50)) {
337 : 0 : ERR("Failed to blocklevel_smart_erase(0x100, 0x50)\n");
338 : 0 : goto out;
339 : : }
340 : 1 : miss = check_buf(buf, 0x100, 0x150);
341 : 1 : if (miss) {
342 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x50) at 0x%0x\n",
343 : : miss == -1 ? 0 : miss);
344 : 0 : dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
345 : 0 : dump_buf(buf, 0x14c, 0x155, miss == -1 ? 0 : miss);
346 : 0 : goto out;
347 : : }
348 : :
349 : 1 : reset_buf(buf);
350 : : /* Test 4: Start somewhere in it, finish aligned */
351 : 1 : if (blocklevel_smart_erase(bl, 0x50, 0xb0)) {
352 : 0 : ERR("Failed to blocklevel_smart_erase(0x50, 0xb0)\n");
353 : 0 : goto out;
354 : : }
355 : 1 : miss = check_buf(buf, 0x50, 0x100);
356 : 1 : if (miss) {
357 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x50, 0xb0) at 0x%x\n",
358 : : miss == -1 ? 0 : miss);
359 : 0 : dump_buf(buf, 0x4c, 0x55, miss == -1 ? 0 : miss);
360 : 0 : dump_buf(buf, 0x100, 0x105, miss == -1 ? 0 : miss);
361 : 0 : goto out;
362 : : }
363 : :
364 : 1 : reset_buf(buf);
365 : : /* Test 5: Cover two erase blocks exactly */
366 : 1 : if (blocklevel_smart_erase(bl, 0x100, 0x200)) {
367 : 0 : ERR("Failed to blocklevel_smart_erase(0x100, 0x200)\n");
368 : 0 : goto out;
369 : : }
370 : 1 : miss = check_buf(buf, 0x100, 0x300);
371 : 1 : if (miss) {
372 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x200) at 0x%x\n",
373 : : miss == -1 ? 0 : miss);
374 : 0 : dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
375 : 0 : dump_buf(buf, 0x2fc, 0x305, miss == -1 ? 0 : miss);
376 : 0 : goto out;
377 : : }
378 : :
379 : 1 : reset_buf(buf);
380 : : /* Test 6: Erase 1.5 blocks (start aligned) */
381 : 1 : if (blocklevel_smart_erase(bl, 0x100, 0x180)) {
382 : 0 : ERR("Failed to blocklevel_smart_erase(0x100, 0x180)\n");
383 : 0 : goto out;
384 : : }
385 : 1 : miss = check_buf(buf, 0x100, 0x280);
386 : 1 : if (miss) {
387 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x180) at 0x%x\n",
388 : : miss == -1 ? 0 : miss);
389 : 0 : dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
390 : 0 : dump_buf(buf, 0x27c, 0x285, miss == -1 ? 0 : miss);
391 : 0 : goto out;
392 : : }
393 : :
394 : 1 : reset_buf(buf);
395 : : /* Test 7: Erase 1.5 blocks (end aligned) */
396 : 1 : if (blocklevel_smart_erase(bl, 0x80, 0x180)) {
397 : 0 : ERR("Failed to blocklevel_smart_erase(0x80, 0x180)\n");
398 : 0 : goto out;
399 : : }
400 : 1 : miss = check_buf(buf, 0x80, 0x200);
401 : 1 : if (miss) {
402 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x80, 0x180) at 0x%x\n",
403 : : miss == -1 ? 0 : miss);
404 : 0 : dump_buf(buf, 0x7c, 0x85, miss == -1 ? 0 : miss);
405 : 0 : dump_buf(buf, 0x1fc, 0x205, miss == -1 ? 0 : miss);
406 : 0 : goto out;
407 : : }
408 : :
409 : 1 : reset_buf(buf);
410 : : /* Test 8: Erase a big section, not aligned */
411 : 1 : if (blocklevel_smart_erase(bl, 0x120, 0x544)) {
412 : 0 : ERR("Failed to blocklevel_smart_erase(0x120, 0x544)\n");
413 : 0 : goto out;
414 : : }
415 : 1 : miss = check_buf(buf, 0x120, 0x664);
416 : 1 : if (miss) {
417 : 0 : ERR("Buffer mismatch after blocklevel_smart_erase(0x120, 0x544) at 0x%x\n",
418 : : miss == -1 ? 0 : miss);
419 : 0 : dump_buf(buf, 0x11c, 0x125, miss == -1 ? 0 : miss);
420 : 0 : dump_buf(buf, 0x65f, 0x669, miss == -1 ? 0 : miss);
421 : 0 : goto out;
422 : : }
423 : :
424 : 1 : bl_mem.priv = buf;
425 : 1 : reset_buf(buf);
426 : :
427 : 257 : for (i = 0; i < 0x100; i++)
428 : 256 : data[i] = i;
429 : :
430 : : /* This really shouldn't fail */
431 : 1 : rc = blocklevel_ecc_protect(bl, 0, 0x100);
432 : 1 : if (rc) {
433 : 0 : ERR("Couldn't blocklevel_ecc_protect(0, 0x100)\n");
434 : 0 : goto out;
435 : : }
436 : :
437 : 1 : rc = blocklevel_write(bl, 0, data, 0x100);
438 : 1 : if (rc) {
439 : 0 : ERR("Couldn't blocklevel_write(0, 0x100)\n");
440 : 0 : goto out;
441 : : }
442 : :
443 : 1 : rc = blocklevel_write(bl, 0x200, data, 0x100);
444 : 1 : if (rc) {
445 : 0 : ERR("Couldn't blocklevel_write(0x200, 0x100)\n");
446 : 0 : goto out;
447 : : }
448 : :
449 : : /*
450 : : * 0x50 once adjusted for the presence of ECC becomes 0x5a which
451 : : * is ECC aligned.
452 : : */
453 : 1 : rc = blocklevel_read(bl, 0x50, with_ecc, 8);
454 : 1 : if (rc) {
455 : 0 : ERR("Couldn't blocklevel_read(0x50, 8) with ecc rc=%d\n", rc);
456 : 0 : goto out;
457 : : }
458 : 1 : rc = blocklevel_read(bl, 0x250, without_ecc, 8);
459 : 1 : if (rc) {
460 : 0 : ERR("Couldn't blocklevel_read(0x250, 8) without ecc rc=%d\n", rc);
461 : 0 : goto out;
462 : : }
463 : 1 : if (memcmp(with_ecc, without_ecc, 8) || memcmp(with_ecc, &data[0x50], 8)) {
464 : 0 : ERR("ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
465 : 0 : print_ptr(with_ecc, 8);
466 : 0 : print_ptr(without_ecc, 8);
467 : 0 : print_ptr(&data[50], 8);
468 : 0 : rc = 1;
469 : 0 : goto out;
470 : : }
471 : :
472 : : /*
473 : : * 0x50 once adjusted for the presence of ECC becomes 0x5a which
474 : : * is ECC aligned.
475 : : * So 0x4f won't be aligned!
476 : : */
477 : 1 : rc = blocklevel_read(bl, 0x4f, with_ecc, 8);
478 : 1 : if (rc) {
479 : 0 : ERR("Couldn't blocklevel_read(0x4f, 8) with ecc %d\n", rc);
480 : 0 : goto out;
481 : : }
482 : 1 : rc = blocklevel_read(bl, 0x24f, without_ecc, 8);
483 : 1 : if (rc) {
484 : 0 : ERR("Couldn't blocklevel_read(0x24f, 8) without ecc %d\n", rc);
485 : 0 : goto out;
486 : : }
487 : 1 : if (memcmp(with_ecc, without_ecc, 8) || memcmp(with_ecc, &data[0x4f], 8)) {
488 : 0 : ERR("ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
489 : 0 : print_ptr(with_ecc, 8);
490 : 0 : print_ptr(without_ecc, 8);
491 : 0 : print_ptr(&data[0x4f], 8);
492 : 0 : rc = 1;
493 : 0 : goto out;
494 : : }
495 : :
496 : : /*
497 : : * 0x50 once adjusted for the presence of ECC becomes 0x5a which
498 : : * is ECC aligned.
499 : : */
500 : 1 : rc = blocklevel_read(bl, 0x50, with_ecc, 16);
501 : 1 : if (rc) {
502 : 0 : ERR("Couldn't blocklevel_read(0x50, 16) with ecc %d\n", rc);
503 : 0 : goto out;
504 : : }
505 : 1 : rc = blocklevel_read(bl, 0x250, without_ecc, 16);
506 : 1 : if (rc) {
507 : 0 : ERR("Couldn't blocklevel_read(0x250, 16) without ecc %d\n", rc);
508 : 0 : goto out;
509 : : }
510 : 1 : if (memcmp(with_ecc, without_ecc, 16)|| memcmp(with_ecc, &data[0x50], 16)) {
511 : 0 : ERR("(long read )ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
512 : 0 : print_ptr(with_ecc, 16);
513 : 0 : print_ptr(without_ecc, 16);
514 : 0 : print_ptr(&data[0x50], 16);
515 : 0 : rc = 1;
516 : 0 : goto out;
517 : : }
518 : :
519 : : /*
520 : : * 0x50 once adjusted for the presence of ECC becomes 0x5a which
521 : : * is ECC aligned. So 4f won't be.
522 : : */
523 : 1 : rc = blocklevel_read(bl, 0x4f, with_ecc, 24);
524 : 1 : if (rc) {
525 : 0 : ERR("Couldn't blocklevel_read(0x4f, 24) with ecc %d\n", rc);
526 : 0 : goto out;
527 : : }
528 : 1 : rc = blocklevel_read(bl, 0x24f, without_ecc, 24);
529 : 1 : if (rc) {
530 : 0 : ERR("Couldn't blocklevel_read(0x24f, 24) without ecc %d\n", rc);
531 : 0 : goto out;
532 : : }
533 : 1 : if (memcmp(with_ecc, without_ecc, 24)|| memcmp(with_ecc, &data[0x4f], 24)) {
534 : 0 : ERR("(long read )ECC read and non-ECC read don't match or are wrong: %d\n", __LINE__);
535 : 0 : print_ptr(with_ecc, 24);
536 : 0 : print_ptr(without_ecc, 24);
537 : 0 : print_ptr(&data[0x4f], 24);
538 : 0 : rc = 1;
539 : 0 : goto out;
540 : : }
541 : :
542 : : /*
543 : : * Now lets try to write at non ECC aligned positions
544 : : * Go easy first, 0x50 becomes 0x5a which is ECC byte aligned but
545 : : * not aligned to the start of the partition
546 : : */
547 : :
548 : 1 : rc = blocklevel_write(bl, 0x50, data, 0xb0);
549 : 1 : if (rc) {
550 : 0 : ERR("Couldn't blocklevel_write()\n");
551 : 0 : goto out;
552 : : }
553 : : /* Read 8 bytes before to make sure we didn't ruin that */
554 : 1 : rc = blocklevel_read(bl, 0x48, with_ecc, 24);
555 : 1 : if (rc) {
556 : 0 : ERR("Couldn't blocklevel_read() with ecc %d\n", rc);
557 : 0 : goto out;
558 : : }
559 : 1 : if (memcmp(with_ecc, data + 0x48, 8) || memcmp(with_ecc + 1, data, 16)) {
560 : 0 : rc = 1;
561 : 0 : ERR("Couldn't read back what we thought we wrote line: %d\n", __LINE__);
562 : 0 : print_ptr(with_ecc, 24);
563 : 0 : print_ptr(&data[0x48], 8);
564 : 0 : print_ptr(data, 16);
565 : 0 : goto out;
566 : : }
567 : :
568 : : /* Ok lets get tricky */
569 : 1 : rc = blocklevel_write(bl, 0x31, data, 0xcf);
570 : 1 : if (rc) {
571 : 0 : ERR("Couldn't blocklevel_write(0x31, 0xcf)\n");
572 : 0 : goto out;
573 : : }
574 : : /* Read 8 bytes before to make sure we didn't ruin that */
575 : 1 : rc = blocklevel_read(bl, 0x29, with_ecc, 24);
576 : 1 : if (rc) {
577 : 0 : ERR("Couldn't blocklevel_read(0x29, 24) with ecc rc=%d\n", rc);
578 : 0 : goto out;
579 : : }
580 : 1 : if (memcmp(with_ecc, &data[0x29], 8) || memcmp(with_ecc + 1, data, 16)) {
581 : 0 : ERR("Couldn't read back what we thought we wrote line: %d\n", __LINE__);
582 : 0 : print_ptr(with_ecc, 24);
583 : 0 : print_ptr(&data[0x29], 8);
584 : 0 : print_ptr(data, 16);
585 : 0 : rc = 1;
586 : 0 : goto out;
587 : : }
588 : :
589 : : /*
590 : : * Rewrite the pattern that we've messed up
591 : : */
592 : 1 : rc = blocklevel_write(bl, 0, data, 0x100);
593 : 1 : if (rc) {
594 : 0 : ERR("Couldn't blocklevel_write(0, 0x100) to reset\n");
595 : 0 : goto out;
596 : : }
597 : :
598 : : /* Be unalignmed as possible from now on, starting somewhat easy */
599 : 1 : rc = blocklevel_read(bl, 0, with_ecc, 5);
600 : 1 : if (rc) {
601 : 0 : ERR("Couldn't blocklevel_write(0, 5)\n");
602 : 0 : goto out;
603 : : }
604 : 1 : if (memcmp(with_ecc, data, 5)) {
605 : 0 : ERR("blocklevel_read 5, 0) didn't match line: %d\n", __LINE__);
606 : 0 : print_ptr(with_ecc, 5);
607 : 0 : print_ptr(data, 5);
608 : 0 : rc = 1;
609 : 0 : goto out;
610 : : }
611 : :
612 : : /* 39 is neither divisible by 8 or by 9 */
613 : 1 : rc = blocklevel_read(bl, 39, with_ecc, 5);
614 : 1 : if (rc) {
615 : 0 : ERR("Couldn't blocklevel_write(39, 5)\n");
616 : 0 : goto out;
617 : : }
618 : 1 : if (memcmp(with_ecc, &data[39], 5)) {
619 : 0 : ERR("blocklevel_read(5, 39() didn't match line: %d\n", __LINE__);
620 : 0 : print_ptr(with_ecc, 5);
621 : 0 : print_ptr(&data[39], 5);
622 : 0 : rc = 1;
623 : 0 : goto out;
624 : : }
625 : :
626 : 1 : rc = blocklevel_read(bl, 0xb, &with_ecc, 39);
627 : 1 : if (rc) {
628 : 0 : ERR("Couldn't blocklevel_read(0xb, 39)\n");
629 : 0 : goto out;
630 : : }
631 : 1 : if (memcmp(with_ecc, &data[0xb], 39)) {
632 : 0 : ERR("Strange sized and positioned read failed, blocklevel_read(0xb, 39) line: %d\n", __LINE__);
633 : 0 : print_ptr(with_ecc, 39);
634 : 0 : print_ptr(&data[0xb], 39);
635 : 0 : rc = 1;
636 : 0 : goto out;
637 : : }
638 : :
639 : 1 : rc = blocklevel_write(bl, 39, data, 50);
640 : 1 : if (rc) {
641 : 0 : ERR("Couldn't blocklevel_write(39, 50)\n");
642 : 0 : goto out;
643 : : }
644 : :
645 : 1 : rc = blocklevel_read(bl, 32, with_ecc, 39);
646 : 1 : if (rc) {
647 : 0 : ERR("Couldn't blocklevel_read(32, 39)\n");
648 : 0 : goto out;
649 : : }
650 : :
651 : 1 : if (memcmp(with_ecc, &data[32], 7) || memcmp(((char *)with_ecc) + 7, data, 32)) {
652 : 0 : ERR("Read back of odd placed/odd sized write failed, blocklevel_read(32, 39) line: %d\n", __LINE__);
653 : 0 : print_ptr(with_ecc, 39);
654 : 0 : print_ptr(&data[32], 7);
655 : 0 : print_ptr(data, 32);
656 : 0 : rc = 1;
657 : 0 : goto out;
658 : : }
659 : :
660 : 1 : out:
661 : 1 : free(buf);
662 : 1 : free(data);
663 : 1 : return rc;
664 : : }
|