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		err = 0;
510	} else {
511		pr_err("error: can write past end of OOB\n");
512		errcnt += 1;
513	}
514
515	/* Attempt to read off end of OOB */
516	ops.mode      = MTD_OPS_AUTO_OOB;
517	ops.len       = 0;
518	ops.retlen    = 0;
519	ops.ooblen    = 1;
520	ops.oobretlen = 0;
521	ops.ooboffs   = mtd->oobavail;
522	ops.datbuf    = NULL;
523	ops.oobbuf    = readbuf;
524	pr_info("attempting to start read past end of OOB\n");
525	pr_info("an error is expected...\n");
526	err = mtd_read_oob(mtd, addr0, &ops);
527	if (mtd_is_bitflip(err))
528		err = 0;
529
530	if (err) {
531		pr_info("error occurred as expected\n");
532		err = 0;
533	} else {
534		pr_err("error: can read past end of OOB\n");
535		errcnt += 1;
536	}
537
538	if (bbt[ebcnt - 1])
539		pr_info("skipping end of device tests because last "
540		       "block is bad\n");
541	else {
542		/* Attempt to write off end of device */
543		ops.mode      = MTD_OPS_AUTO_OOB;
544		ops.len       = 0;
545		ops.retlen    = 0;
546		ops.ooblen    = mtd->oobavail + 1;
547		ops.oobretlen = 0;
548		ops.ooboffs   = 0;
549		ops.datbuf    = NULL;
550		ops.oobbuf    = writebuf;
551		pr_info("attempting to write past end of device\n");
552		pr_info("an error is expected...\n");
553		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
554		if (err) {
555			pr_info("error occurred as expected\n");
556			err = 0;
557		} else {
558			pr_err("error: wrote past end of device\n");
559			errcnt += 1;
560		}
561
562		/* Attempt to read off end of device */
563		ops.mode      = MTD_OPS_AUTO_OOB;
564		ops.len       = 0;
565		ops.retlen    = 0;
566		ops.ooblen    = mtd->oobavail + 1;
567		ops.oobretlen = 0;
568		ops.ooboffs   = 0;
569		ops.datbuf    = NULL;
570		ops.oobbuf    = readbuf;
571		pr_info("attempting to read past end of device\n");
572		pr_info("an error is expected...\n");
573		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
574		if (mtd_is_bitflip(err))
575			err = 0;
576
577		if (err) {
578			pr_info("error occurred as expected\n");
579			err = 0;
580		} else {
581			pr_err("error: read past end of device\n");
582			errcnt += 1;
583		}
584
585		err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
586		if (err)
587			goto out;
588
589		/* Attempt to write off end of device */
590		ops.mode      = MTD_OPS_AUTO_OOB;
591		ops.len       = 0;
592		ops.retlen    = 0;
593		ops.ooblen    = mtd->oobavail;
594		ops.oobretlen = 0;
595		ops.ooboffs   = 1;
596		ops.datbuf    = NULL;
597		ops.oobbuf    = writebuf;
598		pr_info("attempting to write past end of device\n");
599		pr_info("an error is expected...\n");
600		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
601		if (err) {
602			pr_info("error occurred as expected\n");
603			err = 0;
604		} else {
605			pr_err("error: wrote past end of device\n");
606			errcnt += 1;
607		}
608
609		/* Attempt to read off end of device */
610		ops.mode      = MTD_OPS_AUTO_OOB;
611		ops.len       = 0;
612		ops.retlen    = 0;
613		ops.ooblen    = mtd->oobavail;
614		ops.oobretlen = 0;
615		ops.ooboffs   = 1;
616		ops.datbuf    = NULL;
617		ops.oobbuf    = readbuf;
618		pr_info("attempting to read past end of device\n");
619		pr_info("an error is expected...\n");
620		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
621		if (mtd_is_bitflip(err))
622			err = 0;
623
624		if (err) {
625			pr_info("error occurred as expected\n");
626			err = 0;
627		} else {
628			pr_err("error: read past end of device\n");
629			errcnt += 1;
630		}
631	}
632
633	/* Fifth test: write / read across block boundaries */
634	pr_info("test 5 of 5\n");
635
636	/* Erase all eraseblocks */
637	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
638	if (err)
639		goto out;
640
641	/* Write all eraseblocks */
642	prandom_seed_state(&rnd_state, 11);
643	pr_info("writing OOBs of whole device\n");
644	for (i = 0; i < ebcnt - 1; ++i) {
645		int cnt = 2;
646		int pg;
647		size_t sz = mtd->oobavail;
648		if (bbt[i] || bbt[i + 1])
649			continue;
650		addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
651		prandom_bytes_state(&rnd_state, writebuf, sz * cnt);
652		for (pg = 0; pg < cnt; ++pg) {
653			ops.mode      = MTD_OPS_AUTO_OOB;
654			ops.len       = 0;
655			ops.retlen    = 0;
656			ops.ooblen    = sz;
657			ops.oobretlen = 0;
658			ops.ooboffs   = 0;
659			ops.datbuf    = NULL;
660			ops.oobbuf    = writebuf + pg * sz;
661			err = mtd_write_oob(mtd, addr, &ops);
662			if (err)
663				goto out;
664			if (i % 256 == 0)
665				pr_info("written up to eraseblock %u\n", i);
666
667			err = mtdtest_relax();
668			if (err)
669				goto out;
670
671			addr += mtd->writesize;
672		}
673	}
674	pr_info("written %u eraseblocks\n", i);
675
676	/* Check all eraseblocks */
677	prandom_seed_state(&rnd_state, 11);
678	pr_info("verifying all eraseblocks\n");
679	for (i = 0; i < ebcnt - 1; ++i) {
680		if (bbt[i] || bbt[i + 1])
681			continue;
682		prandom_bytes_state(&rnd_state, writebuf, mtd->oobavail * 2);
683		addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
684		ops.mode      = MTD_OPS_AUTO_OOB;
685		ops.len       = 0;
686		ops.retlen    = 0;
687		ops.ooblen    = mtd->oobavail * 2;
688		ops.oobretlen = 0;
689		ops.ooboffs   = 0;
690		ops.datbuf    = NULL;
691		ops.oobbuf    = readbuf;
692		err = mtd_read_oob(mtd, addr, &ops);
693		if (mtd_is_bitflip(err))
694			err = 0;
695
696		if (err)
697			goto out;
698		if (memcmpshow(addr, readbuf, writebuf,
699			       mtd->oobavail * 2)) {
700			pr_err("error: verify failed at %#llx\n",
701			       (long long)addr);
702			errcnt += 1;
703			if (errcnt > 1000) {
704				pr_err("error: too many errors\n");
705				goto out;
706			}
707		}
708		if (i % 256 == 0)
709			pr_info("verified up to eraseblock %u\n", i);
710
711		err = mtdtest_relax();
712		if (err)
713			goto out;
714	}
715	pr_info("verified %u eraseblocks\n", i);
716
717	pr_info("finished with %d errors\n", errcnt);
718out:
719	kfree(bbt);
720	kfree(writebuf);
721	kfree(readbuf);
722	put_mtd_device(mtd);
723	if (err)
724		pr_info("error %d occurred\n", err);
725	printk(KERN_INFO "=================================================\n");
726	return err;
727}
728module_init(mtd_oobtest_init);
729
730static void __exit mtd_oobtest_exit(void)
731{
732	return;
733}
734module_exit(mtd_oobtest_exit);
735
736MODULE_DESCRIPTION("Out-of-band test module");
737MODULE_AUTHOR("Adrian Hunter");
738MODULE_LICENSE("GPL");
739