cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

readtest.c (4505B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2006-2008 Nokia Corporation
      4 *
      5 * Check MTD device read.
      6 *
      7 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
      8 */
      9
     10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     11
     12#include <linux/init.h>
     13#include <linux/module.h>
     14#include <linux/moduleparam.h>
     15#include <linux/err.h>
     16#include <linux/mtd/mtd.h>
     17#include <linux/slab.h>
     18#include <linux/sched.h>
     19
     20#include "mtd_test.h"
     21
     22static int dev = -EINVAL;
     23module_param(dev, int, S_IRUGO);
     24MODULE_PARM_DESC(dev, "MTD device number to use");
     25
     26static struct mtd_info *mtd;
     27static unsigned char *iobuf;
     28static unsigned char *iobuf1;
     29static unsigned char *bbt;
     30
     31static int pgsize;
     32static int ebcnt;
     33static int pgcnt;
     34
     35static int read_eraseblock_by_page(int ebnum)
     36{
     37	int i, ret, err = 0;
     38	loff_t addr = (loff_t)ebnum * mtd->erasesize;
     39	void *buf = iobuf;
     40	void *oobbuf = iobuf1;
     41
     42	for (i = 0; i < pgcnt; i++) {
     43		memset(buf, 0 , pgsize);
     44		ret = mtdtest_read(mtd, addr, pgsize, buf);
     45		if (ret) {
     46			if (!err)
     47				err = ret;
     48		}
     49		if (mtd->oobsize) {
     50			struct mtd_oob_ops ops;
     51
     52			ops.mode      = MTD_OPS_PLACE_OOB;
     53			ops.len       = 0;
     54			ops.retlen    = 0;
     55			ops.ooblen    = mtd->oobsize;
     56			ops.oobretlen = 0;
     57			ops.ooboffs   = 0;
     58			ops.datbuf    = NULL;
     59			ops.oobbuf    = oobbuf;
     60			ret = mtd_read_oob(mtd, addr, &ops);
     61			if ((ret && !mtd_is_bitflip(ret)) ||
     62					ops.oobretlen != mtd->oobsize) {
     63				pr_err("error: read oob failed at "
     64						  "%#llx\n", (long long)addr);
     65				if (!err)
     66					err = ret;
     67				if (!err)
     68					err = -EINVAL;
     69			}
     70			oobbuf += mtd->oobsize;
     71		}
     72		addr += pgsize;
     73		buf += pgsize;
     74	}
     75
     76	return err;
     77}
     78
     79static void dump_eraseblock(int ebnum)
     80{
     81	int i, j, n;
     82	char line[128];
     83	int pg, oob;
     84
     85	pr_info("dumping eraseblock %d\n", ebnum);
     86	n = mtd->erasesize;
     87	for (i = 0; i < n;) {
     88		char *p = line;
     89
     90		p += sprintf(p, "%05x: ", i);
     91		for (j = 0; j < 32 && i < n; j++, i++)
     92			p += sprintf(p, "%02x", (unsigned int)iobuf[i]);
     93		printk(KERN_CRIT "%s\n", line);
     94		cond_resched();
     95	}
     96	if (!mtd->oobsize)
     97		return;
     98	pr_info("dumping oob from eraseblock %d\n", ebnum);
     99	n = mtd->oobsize;
    100	for (pg = 0, i = 0; pg < pgcnt; pg++)
    101		for (oob = 0; oob < n;) {
    102			char *p = line;
    103
    104			p += sprintf(p, "%05x: ", i);
    105			for (j = 0; j < 32 && oob < n; j++, oob++, i++)
    106				p += sprintf(p, "%02x",
    107					     (unsigned int)iobuf1[i]);
    108			printk(KERN_CRIT "%s\n", line);
    109			cond_resched();
    110		}
    111}
    112
    113static int __init mtd_readtest_init(void)
    114{
    115	uint64_t tmp;
    116	int err, i;
    117
    118	printk(KERN_INFO "\n");
    119	printk(KERN_INFO "=================================================\n");
    120
    121	if (dev < 0) {
    122		pr_info("Please specify a valid mtd-device via module parameter\n");
    123		return -EINVAL;
    124	}
    125
    126	pr_info("MTD device: %d\n", dev);
    127
    128	mtd = get_mtd_device(NULL, dev);
    129	if (IS_ERR(mtd)) {
    130		err = PTR_ERR(mtd);
    131		pr_err("error: Cannot get MTD device\n");
    132		return err;
    133	}
    134
    135	if (mtd->writesize == 1) {
    136		pr_info("not NAND flash, assume page size is 512 "
    137		       "bytes.\n");
    138		pgsize = 512;
    139	} else
    140		pgsize = mtd->writesize;
    141
    142	tmp = mtd->size;
    143	do_div(tmp, mtd->erasesize);
    144	ebcnt = tmp;
    145	pgcnt = mtd->erasesize / pgsize;
    146
    147	pr_info("MTD device size %llu, eraseblock size %u, "
    148	       "page size %u, count of eraseblocks %u, pages per "
    149	       "eraseblock %u, OOB size %u\n",
    150	       (unsigned long long)mtd->size, mtd->erasesize,
    151	       pgsize, ebcnt, pgcnt, mtd->oobsize);
    152
    153	err = -ENOMEM;
    154	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
    155	if (!iobuf)
    156		goto out;
    157	iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
    158	if (!iobuf1)
    159		goto out;
    160
    161	bbt = kzalloc(ebcnt, GFP_KERNEL);
    162	if (!bbt)
    163		goto out;
    164	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
    165	if (err)
    166		goto out;
    167
    168	/* Read all eraseblocks 1 page at a time */
    169	pr_info("testing page read\n");
    170	for (i = 0; i < ebcnt; ++i) {
    171		int ret;
    172
    173		if (bbt[i])
    174			continue;
    175		ret = read_eraseblock_by_page(i);
    176		if (ret) {
    177			dump_eraseblock(i);
    178			if (!err)
    179				err = ret;
    180		}
    181
    182		ret = mtdtest_relax();
    183		if (ret) {
    184			err = ret;
    185			goto out;
    186		}
    187	}
    188
    189	if (err)
    190		pr_info("finished with errors\n");
    191	else
    192		pr_info("finished\n");
    193
    194out:
    195
    196	kfree(iobuf);
    197	kfree(iobuf1);
    198	kfree(bbt);
    199	put_mtd_device(mtd);
    200	if (err)
    201		pr_info("error %d occurred\n", err);
    202	printk(KERN_INFO "=================================================\n");
    203	return err;
    204}
    205module_init(mtd_readtest_init);
    206
    207static void __exit mtd_readtest_exit(void)
    208{
    209	return;
    210}
    211module_exit(mtd_readtest_exit);
    212
    213MODULE_DESCRIPTION("Read test module");
    214MODULE_AUTHOR("Adrian Hunter");
    215MODULE_LICENSE("GPL");