1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2006-2008 Nokia Corporation
4 *
5 * Test OOB read and write on MTD device.
6 *
7 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12#include <asm/div64.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/err.h>
17#include <linux/mtd/mtd.h>
18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/random.h>
21
22#include "mtd_test.h"
23
24static int dev = -EINVAL;
25static int bitflip_limit;
26module_param(dev, int, S_IRUGO);
27MODULE_PARM_DESC(dev, "MTD device number to use");
28module_param(bitflip_limit, int, S_IRUGO);
29MODULE_PARM_DESC(bitflip_limit, "Max. allowed bitflips per page");
30
31static struct mtd_info *mtd;
32static unsigned char *readbuf;
33static unsigned char *writebuf;
34static unsigned char *bbt;
35
36static int ebcnt;
37static int pgcnt;
38static int errcnt;
39static int use_offset;
40static int use_len;
41static int use_len_max;
42static int vary_offset;
43static struct rnd_state rnd_state;
44
45static void do_vary_offset(void)
46{
47	use_len -= 1;
48	if (use_len < 1) {
49		use_offset += 1;
50		if (use_offset >= use_len_max)
51			use_offset = 0;
52		use_len = use_len_max - use_offset;
53	}
54}
55
56static int write_eraseblock(int ebnum)
57{
58	int i;
59	struct mtd_oob_ops ops = { };
60	int err = 0;
61	loff_t addr = (loff_t)ebnum * mtd->erasesize;
62
63	prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
64	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
65		ops.mode      = MTD_OPS_AUTO_OOB;
66		ops.len       = 0;
67		ops.retlen    = 0;
68		ops.ooblen    = use_len;
69		ops.oobretlen = 0;
70		ops.ooboffs   = use_offset;
71		ops.datbuf    = NULL;
72		ops.oobbuf    = writebuf + (use_len_max * i) + use_offset;
73		err = mtd_write_oob(mtd, addr, &ops);
74		if (err || ops.oobretlen != use_len) {
75			pr_err("error: writeoob failed at %#llx\n",
76			       (long long)addr);
77			pr_err("error: use_len %d, use_offset %d\n",
78			       use_len, use_offset);
79			errcnt += 1;
80			return err ? err : -1;
81		}
82		if (vary_offset)
83			do_vary_offset();
84	}
85
86	return err;
87}
88
89static int write_whole_device(void)
90{
91	int err;
92	unsigned int i;
93
94	pr_info("writing OOBs of whole device\n");
95	for (i = 0; i < ebcnt; ++i) {
96		if (bbt[i])
97			continue;
98		err = write_eraseblock(i);
99		if (err)
100			return err;
101		if (i % 256 == 0)
102			pr_info("written up to eraseblock %u\n", i);
103
104		err = mtdtest_relax();
105		if (err)
106			return err;
107	}
108	pr_info("written %u eraseblocks\n", i);
109	return 0;
110}
111
112/*
113 * Display the address, offset and data bytes at comparison failure.
114 * Return number of bitflips encountered.
115 */
116static size_t memcmpshowoffset(loff_t addr, loff_t offset, const void *cs,
117			       const void *ct, size_t count)
118{
119	const unsigned char *su1, *su2;
120	int res;
121	size_t i = 0;
122	size_t bitflips = 0;
123
124	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--, i++) {
125		res = *su1 ^ *su2;
126		if (res) {
127			pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0x%x diff 0x%x\n",
128				(unsigned long)addr, (unsigned long)offset + i,
129				*su1, *su2, res);
130			bitflips += hweight8(res);
131		}
132	}
133
134	return bitflips;
135}
136
137#define memcmpshow(addr, cs, ct, count) memcmpshowoffset((addr), 0, (cs), (ct),\
138							 (count))
139
140/*
141 * Compare with 0xff and show the address, offset and data bytes at
142 * comparison failure. Return number of bitflips encountered.
143 */
144static size_t memffshow(loff_t addr, loff_t offset, const void *cs,
145			size_t count)
146{
147	const unsigned char *su1;
148	int res;
149	size_t i = 0;
150	size_t bitflips = 0;
151
152	for (su1 = cs; 0 < count; ++su1, count--, i++) {
153		res = *su1 ^ 0xff;
154		if (res) {
155			pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0xff diff 0x%x\n",
156				(unsigned long)addr, (unsigned long)offset + i,
157				*su1, res);
158			bitflips += hweight8(res);
159		}
160	}
161
162	return bitflips;
163}
164
165static int verify_eraseblock(int ebnum)
166{
167	int i;
168	struct mtd_oob_ops ops = { };
169	int err = 0;
170	loff_t addr = (loff_t)ebnum * mtd->erasesize;
171	size_t bitflips;
172
173	prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
174	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
175		ops.mode      = MTD_OPS_AUTO_OOB;
176		ops.len       = 0;
177		ops.retlen    = 0;
178		ops.ooblen    = use_len;
179		ops.oobretlen = 0;
180		ops.ooboffs   = use_offset;
181		ops.datbuf    = NULL;
182		ops.oobbuf    = readbuf;
183		err = mtd_read_oob(mtd, addr, &ops);
184		if (mtd_is_bitflip(err))
185			err = 0;
186
187		if (err || ops.oobretlen != use_len) {
188			pr_err("error: readoob failed at %#llx\n",
189			       (long long)addr);
190			errcnt += 1;
191			return err ? err : -1;
192		}
193
194		bitflips = memcmpshow(addr, readbuf,
195				      writebuf + (use_len_max * i) + use_offset,
196				      use_len);
197		if (bitflips > bitflip_limit) {
198			pr_err("error: verify failed at %#llx\n",
199			       (long long)addr);
200			errcnt += 1;
201			if (errcnt > 1000) {
202				pr_err("error: too many errors\n");
203				return -1;
204			}
205		} else if (bitflips) {
206			pr_info("ignoring error as within bitflip_limit\n");
207		}
208
209		if (use_offset != 0 || use_len < mtd->oobavail) {
210			int k;
211
212			ops.mode      = MTD_OPS_AUTO_OOB;
213			ops.len       = 0;
214			ops.retlen    = 0;
215			ops.ooblen    = mtd->oobavail;
216			ops.oobretlen = 0;
217			ops.ooboffs   = 0;
218			ops.datbuf    = NULL;
219			ops.oobbuf    = readbuf;
220			err = mtd_read_oob(mtd, addr, &ops);
221			if (mtd_is_bitflip(err))
222				err = 0;
223
224			if (err || ops.oobretlen != mtd->oobavail) {
225				pr_err("error: readoob failed at %#llx\n",
226						(long long)addr);
227				errcnt += 1;
228				return err ? err : -1;
229			}
230			bitflips = memcmpshowoffset(addr, use_offset,
231						    readbuf + use_offset,
232						    writebuf + (use_len_max * i) + use_offset,
233						    use_len);
234
235			/* verify pre-offset area for 0xff */
236			bitflips += memffshow(addr, 0, readbuf, use_offset);
237
238			/* verify post-(use_offset + use_len) area for 0xff */
239			k = use_offset + use_len;
240			bitflips += memffshow(addr, k, readbuf + k,
241					      mtd->oobavail - k);
242
243			if (bitflips > bitflip_limit) {
244				pr_err("error: verify failed at %#llx\n",
245						(long long)addr);
246				errcnt += 1;
247				if (errcnt > 1000) {
248					pr_err("error: too many errors\n");
249					return -1;
250				}
251			} else if (bitflips) {
252				pr_info("ignoring errors as within bitflip limit\n");
253			}
254		}
255		if (vary_offset)
256			do_vary_offset();
257	}
258	return err;
259}
260
261static int verify_eraseblock_in_one_go(int ebnum)
262{
263	struct mtd_oob_ops ops = { };
264	int err = 0;
265	loff_t addr = (loff_t)ebnum * mtd->erasesize;
266	size_t len = mtd->oobavail * pgcnt;
267	size_t oobavail = mtd->oobavail;
268	size_t bitflips;
269	int i;
270
271	prandom_bytes_state(&rnd_state, writebuf, len);
272	ops.mode      = MTD_OPS_AUTO_OOB;
273	ops.len       = 0;
274	ops.retlen    = 0;
275	ops.ooblen    = len;
276	ops.oobretlen = 0;
277	ops.ooboffs   = 0;
278	ops.datbuf    = NULL;
279	ops.oobbuf    = readbuf;
280
281	/* read entire block's OOB at one go */
282	err = mtd_read_oob(mtd, addr, &ops);
283	if (mtd_is_bitflip(err))
284		err = 0;
285
286	if (err || ops.oobretlen != len) {
287		pr_err("error: readoob failed at %#llx\n",
288		       (long long)addr);
289		errcnt += 1;
290		return err ? err : -1;
291	}
292
293	/* verify one page OOB at a time for bitflip per page limit check */
294	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
295		bitflips = memcmpshow(addr, readbuf + (i * oobavail),
296				      writebuf + (i * oobavail), oobavail);
297		if (bitflips > bitflip_limit) {
298			pr_err("error: verify failed at %#llx\n",
299			       (long long)addr);
300			errcnt += 1;
301			if (errcnt > 1000) {
302				pr_err("error: too many errors\n");
303				return -1;
304			}
305		} else if (bitflips) {
306			pr_info("ignoring error as within bitflip_limit\n");
307		}
308	}
309
310	return err;
311}
312
313static int verify_all_eraseblocks(void)
314{
315	int err;
316	unsigned int i;
317
318	pr_info("verifying all eraseblocks\n");
319	for (i = 0; i < ebcnt; ++i) {
320		if (bbt[i])
321			continue;
322		err = verify_eraseblock(i);
323		if (err)
324			return err;
325		if (i % 256 == 0)
326			pr_info("verified up to eraseblock %u\n", i);
327
328		err = mtdtest_relax();
329		if (err)
330			return err;
331	}
332	pr_info("verified %u eraseblocks\n", i);
333	return 0;
334}
335
336static int __init mtd_oobtest_init(void)
337{
338	int err = 0;
339	unsigned int i;
340	uint64_t tmp;
341	struct mtd_oob_ops ops = { };
342	loff_t addr = 0, addr0;
343
344	printk(KERN_INFO "\n");
345	printk(KERN_INFO "=================================================\n");
346
347	if (dev < 0) {
348		pr_info("Please specify a valid mtd-device via module parameter\n");
349		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
350		return -EINVAL;
351	}
352
353	pr_info("MTD device: %d\n", dev);
354
355	mtd = get_mtd_device(NULL, dev);
356	if (IS_ERR(mtd)) {
357		err = PTR_ERR(mtd);
358		pr_err("error: cannot get MTD device\n");
359		return err;
360	}
361
362	if (!mtd_type_is_nand(mtd)) {
363		pr_info("this test requires NAND flash\n");
364		goto out;
365	}
366
367	tmp = mtd->size;
368	do_div(tmp, mtd->erasesize);
369	ebcnt = tmp;
370	pgcnt = mtd->erasesize / mtd->writesize;
371
372	pr_info("MTD device size %llu, eraseblock size %u, "
373	       "page size %u, count of eraseblocks %u, pages per "
374	       "eraseblock %u, OOB size %u\n",
375	       (unsigned long long)mtd->size, mtd->erasesize,
376	       mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
377
378	err = -ENOMEM;
379	readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
380	if (!readbuf)
381		goto out;
382	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
383	if (!writebuf)
384		goto out;
385	bbt = kzalloc(ebcnt, GFP_KERNEL);
386	if (!bbt)
387		goto out;
388
389	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
390	if (err)
391		goto out;
392
393	use_offset = 0;
394	use_len = mtd->oobavail;
395	use_len_max = mtd->oobavail;
396	vary_offset = 0;
397
398	/* First test: write all OOB, read it back and verify */
399	pr_info("test 1 of 5\n");
400
401	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
402	if (err)
403		goto out;
404
405	prandom_seed_state(&rnd_state, 1);
406	err = write_whole_device();
407	if (err)
408		goto out;
409
410	prandom_seed_state(&rnd_state, 1);
411	err = verify_all_eraseblocks();
412	if (err)
413		goto out;
414
415	/*
416	 * Second test: write all OOB, a block at a time, read it back and
417	 * verify.
418	 */
419	pr_info("test 2 of 5\n");
420
421	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
422	if (err)
423		goto out;
424
425	prandom_seed_state(&rnd_state, 3);
426	err = write_whole_device();
427	if (err)
428		goto out;
429
430	/* Check all eraseblocks */
431	prandom_seed_state(&rnd_state, 3);
432	pr_info("verifying all eraseblocks\n");
433	for (i = 0; i < ebcnt; ++i) {
434		if (bbt[i])
435			continue;
436		err = verify_eraseblock_in_one_go(i);
437		if (err)
438			goto out;
439		if (i % 256 == 0)
440			pr_info("verified up to eraseblock %u\n", i);
441
442		err = mtdtest_relax();
443		if (err)
444			goto out;
445	}
446	pr_info("verified %u eraseblocks\n", i);
447
448	/*
449	 * Third test: write OOB at varying offsets and lengths, read it back
450	 * and verify.
451	 */
452	pr_info("test 3 of 5\n");
453
454	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
455	if (err)
456		goto out;
457
458	/* Write all eraseblocks */
459	use_offset = 0;
460	use_len = mtd->oobavail;
461	use_len_max = mtd->oobavail;
462	vary_offset = 1;
463	prandom_seed_state(&rnd_state, 5);
464
465	err = write_whole_device();
466	if (err)
467		goto out;
468
469	/* Check all eraseblocks */
470	use_offset = 0;
471	use_len = mtd->oobavail;
472	use_len_max = mtd->oobavail;
473	vary_offset = 1;
474	prandom_seed_state(&rnd_state, 5);
475	err = verify_all_eraseblocks();
476	if (err)
477		goto out;
478
479	use_offset = 0;
480	use_len = mtd->oobavail;
481	use_len_max = mtd->oobavail;
482	vary_offset = 0;
483
484	/* Fourth test: try to write off end of device */
485	pr_info("test 4 of 5\n");
486
487	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
488	if (err)
489		goto out;
490
491	addr0 = 0;
492	for (i = 0; i < ebcnt && bbt[i]; ++i)
493		addr0 += mtd->erasesize;
494
495	/* Attempt to write off end of OOB */
496	ops.mode      = MTD_OPS_AUTO_OOB;
497	ops.len       = 0;
498	ops.retlen    = 0;
499	ops.ooblen    = 1;
500	ops.oobretlen = 0;
501	ops.ooboffs   = mtd->oobavail;
502	ops.datbuf    = NULL;
503	ops.oobbuf    = writebuf;
504	pr_info("attempting to start write past end of OOB\n");
505	pr_info("an error is expected...\n");
506	err = mtd_write_oob(mtd, addr0, &ops);
507	if (err) {
508		pr_info("error occurred as expected\n");
509	} else {
510		pr_err("error: can write past end of OOB\n");
511		errcnt += 1;
512	}
513
514	/* Attempt to read off end of OOB */
515	ops.mode      = MTD_OPS_AUTO_OOB;
516	ops.len       = 0;
517	ops.retlen    = 0;
518	ops.ooblen    = 1;
519	ops.oobretlen = 0;
520	ops.ooboffs   = mtd->oobavail;
521	ops.datbuf    = NULL;
522	ops.oobbuf    = readbuf;
523	pr_info("attempting to start read past end of OOB\n");
524	pr_info("an error is expected...\n");
525	err = mtd_read_oob(mtd, addr0, &ops);
526	if (mtd_is_bitflip(err))
527		err = 0;
528
529	if (err) {
530		pr_info("error occurred as expected\n");
531	} else {
532		pr_err("error: can read past end of OOB\n");
533		errcnt += 1;
534	}
535
536	if (bbt[ebcnt - 1])
537		pr_info("skipping end of device tests because last "
538		       "block is bad\n");
539	else {
540		/* Attempt to write off end of device */
541		ops.mode      = MTD_OPS_AUTO_OOB;
542		ops.len       = 0;
543		ops.retlen    = 0;
544		ops.ooblen    = mtd->oobavail + 1;
545		ops.oobretlen = 0;
546		ops.ooboffs   = 0;
547		ops.datbuf    = NULL;
548		ops.oobbuf    = writebuf;
549		pr_info("attempting to write past end of device\n");
550		pr_info("an error is expected...\n");
551		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
552		if (err) {
553			pr_info("error occurred as expected\n");
554		} else {
555			pr_err("error: wrote past end of device\n");
556			errcnt += 1;
557		}
558
559		/* Attempt to read off end of device */
560		ops.mode      = MTD_OPS_AUTO_OOB;
561		ops.len       = 0;
562		ops.retlen    = 0;
563		ops.ooblen    = mtd->oobavail + 1;
564		ops.oobretlen = 0;
565		ops.ooboffs   = 0;
566		ops.datbuf    = NULL;
567		ops.oobbuf    = readbuf;
568		pr_info("attempting to read past end of device\n");
569		pr_info("an error is expected...\n");
570		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
571		if (mtd_is_bitflip(err))
572			err = 0;
573
574		if (err) {
575			pr_info("error occurred as expected\n");
576		} else {
577			pr_err("error: read past end of device\n");
578			errcnt += 1;
579		}
580
581		err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
582		if (err)
583			goto out;
584
585		/* Attempt to write off end of device */
586		ops.mode      = MTD_OPS_AUTO_OOB;
587		ops.len       = 0;
588		ops.retlen    = 0;
589		ops.ooblen    = mtd->oobavail;
590		ops.oobretlen = 0;
591		ops.ooboffs   = 1;
592		ops.datbuf    = NULL;
593		ops.oobbuf    = writebuf;
594		pr_info("attempting to write past end of device\n");
595		pr_info("an error is expected...\n");
596		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
597		if (err) {
598			pr_info("error occurred as expected\n");
599		} else {
600			pr_err("error: wrote past end of device\n");
601			errcnt += 1;
602		}
603
604		/* Attempt to read off end of device */
605		ops.mode      = MTD_OPS_AUTO_OOB;
606		ops.len       = 0;
607		ops.retlen    = 0;
608		ops.ooblen    = mtd->oobavail;
609		ops.oobretlen = 0;
610		ops.ooboffs   = 1;
611		ops.datbuf    = NULL;
612		ops.oobbuf    = readbuf;
613		pr_info("attempting to read past end of device\n");
614		pr_info("an error is expected...\n");
615		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
616		if (mtd_is_bitflip(err))
617			err = 0;
618
619		if (err) {
620			pr_info("error occurred as expected\n");
621		} else {
622			pr_err("error: read past end of device\n");
623			errcnt += 1;
624		}
625	}
626
627	/* Fifth test: write / read across block boundaries */
628	pr_info("test 5 of 5\n");
629
630	/* Erase all eraseblocks */
631	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
632	if (err)
633		goto out;
634
635	/* Write all eraseblocks */
636	prandom_seed_state(&rnd_state, 11);
637	pr_info("writing OOBs of whole device\n");
638	for (i = 0; i < ebcnt - 1; ++i) {
639		int cnt = 2;
640		int pg;
641		size_t sz = mtd->oobavail;
642		if (bbt[i] || bbt[i + 1])
643			continue;
644		addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
645		prandom_bytes_state(&rnd_state, writebuf, sz * cnt);
646		for (pg = 0; pg < cnt; ++pg) {
647			ops.mode      = MTD_OPS_AUTO_OOB;
648			ops.len       = 0;
649			ops.retlen    = 0;
650			ops.ooblen    = sz;
651			ops.oobretlen = 0;
652			ops.ooboffs   = 0;
653			ops.datbuf    = NULL;
654			ops.oobbuf    = writebuf + pg * sz;
655			err = mtd_write_oob(mtd, addr, &ops);
656			if (err)
657				goto out;
658			if (i % 256 == 0)
659				pr_info("written up to eraseblock %u\n", i);
660
661			err = mtdtest_relax();
662			if (err)
663				goto out;
664
665			addr += mtd->writesize;
666		}
667	}
668	pr_info("written %u eraseblocks\n", i);
669
670	/* Check all eraseblocks */
671	prandom_seed_state(&rnd_state, 11);
672	pr_info("verifying all eraseblocks\n");
673	for (i = 0; i < ebcnt - 1; ++i) {
674		if (bbt[i] || bbt[i + 1])
675			continue;
676		prandom_bytes_state(&rnd_state, writebuf, mtd->oobavail * 2);
677		addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
678		ops.mode      = MTD_OPS_AUTO_OOB;
679		ops.len       = 0;
680		ops.retlen    = 0;
681		ops.ooblen    = mtd->oobavail * 2;
682		ops.oobretlen = 0;
683		ops.ooboffs   = 0;
684		ops.datbuf    = NULL;
685		ops.oobbuf    = readbuf;
686		err = mtd_read_oob(mtd, addr, &ops);
687		if (mtd_is_bitflip(err))
688			err = 0;
689
690		if (err)
691			goto out;
692		if (memcmpshow(addr, readbuf, writebuf,
693			       mtd->oobavail * 2)) {
694			pr_err("error: verify failed at %#llx\n",
695			       (long long)addr);
696			errcnt += 1;
697			if (errcnt > 1000) {
698				err = -EINVAL;
699				pr_err("error: too many errors\n");
700				goto out;
701			}
702		}
703		if (i % 256 == 0)
704			pr_info("verified up to eraseblock %u\n", i);
705
706		err = mtdtest_relax();
707		if (err)
708			goto out;
709	}
710	pr_info("verified %u eraseblocks\n", i);
711
712	pr_info("finished with %d errors\n", errcnt);
713out:
714	kfree(bbt);
715	kfree(writebuf);
716	kfree(readbuf);
717	put_mtd_device(mtd);
718	if (err)
719		pr_info("error %d occurred\n", err);
720	printk(KERN_INFO "=================================================\n");
721	return err;
722}
723module_init(mtd_oobtest_init);
724
725static void __exit mtd_oobtest_exit(void)
726{
727	return;
728}
729module_exit(mtd_oobtest_exit);
730
731MODULE_DESCRIPTION("Out-of-band test module");
732MODULE_AUTHOR("Adrian Hunter");
733MODULE_LICENSE("GPL");
734