brintos

brintos / linux-shallow public Read only

0
0
Text · 31.1 KiB · 8dc4f5c Raw
1440 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>4 */5 6#include <linux/device.h>7#include <linux/fs.h>8#include <linux/mm.h>9#include <linux/err.h>10#include <linux/init.h>11#include <linux/kernel.h>12#include <linux/module.h>13#include <linux/slab.h>14#include <linux/sched.h>15#include <linux/mutex.h>16#include <linux/backing-dev.h>17#include <linux/compat.h>18#include <linux/mount.h>19#include <linux/blkpg.h>20#include <linux/magic.h>21#include <linux/major.h>22#include <linux/mtd/mtd.h>23#include <linux/mtd/partitions.h>24#include <linux/mtd/map.h>25 26#include <linux/uaccess.h>27 28#include "mtdcore.h"29 30/*31 * Data structure to hold the pointer to the mtd device as well32 * as mode information of various use cases.33 */34struct mtd_file_info {35	struct mtd_info *mtd;36	enum mtd_file_modes mode;37};38 39static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig)40{41	struct mtd_file_info *mfi = file->private_data;42	return fixed_size_llseek(file, offset, orig, mfi->mtd->size);43}44 45static int mtdchar_open(struct inode *inode, struct file *file)46{47	int minor = iminor(inode);48	int devnum = minor >> 1;49	int ret = 0;50	struct mtd_info *mtd;51	struct mtd_file_info *mfi;52 53	pr_debug("MTD_open\n");54 55	/* You can't open the RO devices RW */56	if ((file->f_mode & FMODE_WRITE) && (minor & 1))57		return -EACCES;58 59	mtd = get_mtd_device(NULL, devnum);60 61	if (IS_ERR(mtd))62		return PTR_ERR(mtd);63 64	if (mtd->type == MTD_ABSENT) {65		ret = -ENODEV;66		goto out1;67	}68 69	/* You can't open it RW if it's not a writeable device */70	if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {71		ret = -EACCES;72		goto out1;73	}74 75	mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);76	if (!mfi) {77		ret = -ENOMEM;78		goto out1;79	}80	mfi->mtd = mtd;81	file->private_data = mfi;82	return 0;83 84out1:85	put_mtd_device(mtd);86	return ret;87} /* mtdchar_open */88 89/*====================================================================*/90 91static int mtdchar_close(struct inode *inode, struct file *file)92{93	struct mtd_file_info *mfi = file->private_data;94	struct mtd_info *mtd = mfi->mtd;95 96	pr_debug("MTD_close\n");97 98	/* Only sync if opened RW */99	if ((file->f_mode & FMODE_WRITE))100		mtd_sync(mtd);101 102	put_mtd_device(mtd);103	file->private_data = NULL;104	kfree(mfi);105 106	return 0;107} /* mtdchar_close */108 109/* Back in June 2001, dwmw2 wrote:110 *111 *   FIXME: This _really_ needs to die. In 2.5, we should lock the112 *   userspace buffer down and use it directly with readv/writev.113 *114 * The implementation below, using mtd_kmalloc_up_to, mitigates115 * allocation failures when the system is under low-memory situations116 * or if memory is highly fragmented at the cost of reducing the117 * performance of the requested transfer due to a smaller buffer size.118 *119 * A more complex but more memory-efficient implementation based on120 * get_user_pages and iovecs to cover extents of those pages is a121 * longer-term goal, as intimated by dwmw2 above. However, for the122 * write case, this requires yet more complex head and tail transfer123 * handling when those head and tail offsets and sizes are such that124 * alignment requirements are not met in the NAND subdriver.125 */126 127static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,128			loff_t *ppos)129{130	struct mtd_file_info *mfi = file->private_data;131	struct mtd_info *mtd = mfi->mtd;132	size_t retlen;133	size_t total_retlen=0;134	int ret=0;135	int len;136	size_t size = count;137	char *kbuf;138 139	pr_debug("MTD_read\n");140 141	if (*ppos + count > mtd->size) {142		if (*ppos < mtd->size)143			count = mtd->size - *ppos;144		else145			count = 0;146	}147 148	if (!count)149		return 0;150 151	kbuf = mtd_kmalloc_up_to(mtd, &size);152	if (!kbuf)153		return -ENOMEM;154 155	while (count) {156		len = min_t(size_t, count, size);157 158		switch (mfi->mode) {159		case MTD_FILE_MODE_OTP_FACTORY:160			ret = mtd_read_fact_prot_reg(mtd, *ppos, len,161						     &retlen, kbuf);162			break;163		case MTD_FILE_MODE_OTP_USER:164			ret = mtd_read_user_prot_reg(mtd, *ppos, len,165						     &retlen, kbuf);166			break;167		case MTD_FILE_MODE_RAW:168		{169			struct mtd_oob_ops ops = {};170 171			ops.mode = MTD_OPS_RAW;172			ops.datbuf = kbuf;173			ops.oobbuf = NULL;174			ops.len = len;175 176			ret = mtd_read_oob(mtd, *ppos, &ops);177			retlen = ops.retlen;178			break;179		}180		default:181			ret = mtd_read(mtd, *ppos, len, &retlen, kbuf);182		}183		/* Nand returns -EBADMSG on ECC errors, but it returns184		 * the data. For our userspace tools it is important185		 * to dump areas with ECC errors!186		 * For kernel internal usage it also might return -EUCLEAN187		 * to signal the caller that a bitflip has occurred and has188		 * been corrected by the ECC algorithm.189		 * Userspace software which accesses NAND this way190		 * must be aware of the fact that it deals with NAND191		 */192		if (!ret || mtd_is_bitflip_or_eccerr(ret)) {193			*ppos += retlen;194			if (copy_to_user(buf, kbuf, retlen)) {195				kfree(kbuf);196				return -EFAULT;197			}198			else199				total_retlen += retlen;200 201			count -= retlen;202			buf += retlen;203			if (retlen == 0)204				count = 0;205		}206		else {207			kfree(kbuf);208			return ret;209		}210 211	}212 213	kfree(kbuf);214	return total_retlen;215} /* mtdchar_read */216 217static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t count,218			loff_t *ppos)219{220	struct mtd_file_info *mfi = file->private_data;221	struct mtd_info *mtd = mfi->mtd;222	size_t size = count;223	char *kbuf;224	size_t retlen;225	size_t total_retlen=0;226	int ret=0;227	int len;228 229	pr_debug("MTD_write\n");230 231	if (*ppos >= mtd->size)232		return -ENOSPC;233 234	if (*ppos + count > mtd->size)235		count = mtd->size - *ppos;236 237	if (!count)238		return 0;239 240	kbuf = mtd_kmalloc_up_to(mtd, &size);241	if (!kbuf)242		return -ENOMEM;243 244	while (count) {245		len = min_t(size_t, count, size);246 247		if (copy_from_user(kbuf, buf, len)) {248			kfree(kbuf);249			return -EFAULT;250		}251 252		switch (mfi->mode) {253		case MTD_FILE_MODE_OTP_FACTORY:254			ret = -EROFS;255			break;256		case MTD_FILE_MODE_OTP_USER:257			ret = mtd_write_user_prot_reg(mtd, *ppos, len,258						      &retlen, kbuf);259			break;260 261		case MTD_FILE_MODE_RAW:262		{263			struct mtd_oob_ops ops = {};264 265			ops.mode = MTD_OPS_RAW;266			ops.datbuf = kbuf;267			ops.oobbuf = NULL;268			ops.ooboffs = 0;269			ops.len = len;270 271			ret = mtd_write_oob(mtd, *ppos, &ops);272			retlen = ops.retlen;273			break;274		}275 276		default:277			ret = mtd_write(mtd, *ppos, len, &retlen, kbuf);278		}279 280		/*281		 * Return -ENOSPC only if no data could be written at all.282		 * Otherwise just return the number of bytes that actually283		 * have been written.284		 */285		if ((ret == -ENOSPC) && (total_retlen))286			break;287 288		if (!ret) {289			*ppos += retlen;290			total_retlen += retlen;291			count -= retlen;292			buf += retlen;293		}294		else {295			kfree(kbuf);296			return ret;297		}298	}299 300	kfree(kbuf);301	return total_retlen;302} /* mtdchar_write */303 304/*======================================================================305 306    IOCTL calls for getting device parameters.307 308======================================================================*/309 310static int otp_select_filemode(struct mtd_file_info *mfi, int mode)311{312	struct mtd_info *mtd = mfi->mtd;313	size_t retlen;314 315	switch (mode) {316	case MTD_OTP_FACTORY:317		if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) ==318				-EOPNOTSUPP)319			return -EOPNOTSUPP;320 321		mfi->mode = MTD_FILE_MODE_OTP_FACTORY;322		break;323	case MTD_OTP_USER:324		if (mtd_read_user_prot_reg(mtd, -1, 0, &retlen, NULL) ==325				-EOPNOTSUPP)326			return -EOPNOTSUPP;327 328		mfi->mode = MTD_FILE_MODE_OTP_USER;329		break;330	case MTD_OTP_OFF:331		mfi->mode = MTD_FILE_MODE_NORMAL;332		break;333	default:334		return -EINVAL;335	}336 337	return 0;338}339 340static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,341	uint64_t start, uint32_t length, void __user *ptr,342	uint32_t __user *retp)343{344	struct mtd_info *master  = mtd_get_master(mtd);345	struct mtd_file_info *mfi = file->private_data;346	struct mtd_oob_ops ops = {};347	uint32_t retlen;348	int ret = 0;349 350	if (length > 4096)351		return -EINVAL;352 353	if (!master->_write_oob)354		return -EOPNOTSUPP;355 356	ops.ooblen = length;357	ops.ooboffs = start & (mtd->writesize - 1);358	ops.datbuf = NULL;359	ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :360		MTD_OPS_PLACE_OOB;361 362	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))363		return -EINVAL;364 365	ops.oobbuf = memdup_user(ptr, length);366	if (IS_ERR(ops.oobbuf))367		return PTR_ERR(ops.oobbuf);368 369	start &= ~((uint64_t)mtd->writesize - 1);370	ret = mtd_write_oob(mtd, start, &ops);371 372	if (ops.oobretlen > 0xFFFFFFFFU)373		ret = -EOVERFLOW;374	retlen = ops.oobretlen;375	if (copy_to_user(retp, &retlen, sizeof(length)))376		ret = -EFAULT;377 378	kfree(ops.oobbuf);379	return ret;380}381 382static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,383	uint64_t start, uint32_t length, void __user *ptr,384	uint32_t __user *retp)385{386	struct mtd_file_info *mfi = file->private_data;387	struct mtd_oob_ops ops = {};388	int ret = 0;389 390	if (length > 4096)391		return -EINVAL;392 393	ops.ooblen = length;394	ops.ooboffs = start & (mtd->writesize - 1);395	ops.datbuf = NULL;396	ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :397		MTD_OPS_PLACE_OOB;398 399	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))400		return -EINVAL;401 402	ops.oobbuf = kmalloc(length, GFP_KERNEL);403	if (!ops.oobbuf)404		return -ENOMEM;405 406	start &= ~((uint64_t)mtd->writesize - 1);407	ret = mtd_read_oob(mtd, start, &ops);408 409	if (put_user(ops.oobretlen, retp))410		ret = -EFAULT;411	else if (ops.oobretlen && copy_to_user(ptr, ops.oobbuf,412					    ops.oobretlen))413		ret = -EFAULT;414 415	kfree(ops.oobbuf);416 417	/*418	 * NAND returns -EBADMSG on ECC errors, but it returns the OOB419	 * data. For our userspace tools it is important to dump areas420	 * with ECC errors!421	 * For kernel internal usage it also might return -EUCLEAN422	 * to signal the caller that a bitflip has occurred and has423	 * been corrected by the ECC algorithm.424	 *425	 * Note: currently the standard NAND function, nand_read_oob_std,426	 * does not calculate ECC for the OOB area, so do not rely on427	 * this behavior unless you have replaced it with your own.428	 */429	if (mtd_is_bitflip_or_eccerr(ret))430		return 0;431 432	return ret;433}434 435/*436 * Copies (and truncates, if necessary) OOB layout information to the437 * deprecated layout struct, nand_ecclayout_user. This is necessary only to438 * support the deprecated API ioctl ECCGETLAYOUT while allowing all new439 * functionality to use mtd_ooblayout_ops flexibly (i.e. mtd_ooblayout_ops440 * can describe any kind of OOB layout with almost zero overhead from a441 * memory usage point of view).442 */443static int shrink_ecclayout(struct mtd_info *mtd,444			    struct nand_ecclayout_user *to)445{446	struct mtd_oob_region oobregion;447	int i, section = 0, ret;448 449	if (!mtd || !to)450		return -EINVAL;451 452	memset(to, 0, sizeof(*to));453 454	to->eccbytes = 0;455	for (i = 0; i < MTD_MAX_ECCPOS_ENTRIES;) {456		u32 eccpos;457 458		ret = mtd_ooblayout_ecc(mtd, section++, &oobregion);459		if (ret < 0) {460			if (ret != -ERANGE)461				return ret;462 463			break;464		}465 466		eccpos = oobregion.offset;467		for (; i < MTD_MAX_ECCPOS_ENTRIES &&468		       eccpos < oobregion.offset + oobregion.length; i++) {469			to->eccpos[i] = eccpos++;470			to->eccbytes++;471		}472	}473 474	for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {475		ret = mtd_ooblayout_free(mtd, i, &oobregion);476		if (ret < 0) {477			if (ret != -ERANGE)478				return ret;479 480			break;481		}482 483		to->oobfree[i].offset = oobregion.offset;484		to->oobfree[i].length = oobregion.length;485		to->oobavail += to->oobfree[i].length;486	}487 488	return 0;489}490 491static int get_oobinfo(struct mtd_info *mtd, struct nand_oobinfo *to)492{493	struct mtd_oob_region oobregion;494	int i, section = 0, ret;495 496	if (!mtd || !to)497		return -EINVAL;498 499	memset(to, 0, sizeof(*to));500 501	to->eccbytes = 0;502	for (i = 0; i < ARRAY_SIZE(to->eccpos);) {503		u32 eccpos;504 505		ret = mtd_ooblayout_ecc(mtd, section++, &oobregion);506		if (ret < 0) {507			if (ret != -ERANGE)508				return ret;509 510			break;511		}512 513		if (oobregion.length + i > ARRAY_SIZE(to->eccpos))514			return -EINVAL;515 516		eccpos = oobregion.offset;517		for (; eccpos < oobregion.offset + oobregion.length; i++) {518			to->eccpos[i] = eccpos++;519			to->eccbytes++;520		}521	}522 523	for (i = 0; i < 8; i++) {524		ret = mtd_ooblayout_free(mtd, i, &oobregion);525		if (ret < 0) {526			if (ret != -ERANGE)527				return ret;528 529			break;530		}531 532		to->oobfree[i][0] = oobregion.offset;533		to->oobfree[i][1] = oobregion.length;534	}535 536	to->useecc = MTD_NANDECC_AUTOPLACE;537 538	return 0;539}540 541static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,542			       struct blkpg_ioctl_arg *arg)543{544	struct blkpg_partition p;545 546	if (!capable(CAP_SYS_ADMIN))547		return -EPERM;548 549	if (copy_from_user(&p, arg->data, sizeof(p)))550		return -EFAULT;551 552	switch (arg->op) {553	case BLKPG_ADD_PARTITION:554 555		/* Only master mtd device must be used to add partitions */556		if (mtd_is_partition(mtd))557			return -EINVAL;558 559		/* Sanitize user input */560		p.devname[BLKPG_DEVNAMELTH - 1] = '\0';561 562		return mtd_add_partition(mtd, p.devname, p.start, p.length);563 564	case BLKPG_DEL_PARTITION:565 566		if (p.pno < 0)567			return -EINVAL;568 569		return mtd_del_partition(mtd, p.pno);570 571	default:572		return -EINVAL;573	}574}575 576static void adjust_oob_length(struct mtd_info *mtd, uint64_t start,577			      struct mtd_oob_ops *ops)578{579	uint32_t start_page, end_page;580	u32 oob_per_page;581 582	if (ops->len == 0 || ops->ooblen == 0)583		return;584 585	start_page = mtd_div_by_ws(start, mtd);586	end_page = mtd_div_by_ws(start + ops->len - 1, mtd);587	oob_per_page = mtd_oobavail(mtd, ops);588 589	ops->ooblen = min_t(size_t, ops->ooblen,590			    (end_page - start_page + 1) * oob_per_page);591}592 593static noinline_for_stack int594mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)595{596	struct mtd_info *master = mtd_get_master(mtd);597	struct mtd_write_req req;598	const void __user *usr_data, *usr_oob;599	uint8_t *datbuf = NULL, *oobbuf = NULL;600	size_t datbuf_len, oobbuf_len;601	int ret = 0;602 603	if (copy_from_user(&req, argp, sizeof(req)))604		return -EFAULT;605 606	usr_data = (const void __user *)(uintptr_t)req.usr_data;607	usr_oob = (const void __user *)(uintptr_t)req.usr_oob;608 609	if (!master->_write_oob)610		return -EOPNOTSUPP;611 612	if (!usr_data)613		req.len = 0;614 615	if (!usr_oob)616		req.ooblen = 0;617 618	req.len &= 0xffffffff;619	req.ooblen &= 0xffffffff;620 621	if (req.start + req.len > mtd->size)622		return -EINVAL;623 624	datbuf_len = min_t(size_t, req.len, mtd->erasesize);625	if (datbuf_len > 0) {626		datbuf = kvmalloc(datbuf_len, GFP_KERNEL);627		if (!datbuf)628			return -ENOMEM;629	}630 631	oobbuf_len = min_t(size_t, req.ooblen, mtd->erasesize);632	if (oobbuf_len > 0) {633		oobbuf = kvmalloc(oobbuf_len, GFP_KERNEL);634		if (!oobbuf) {635			kvfree(datbuf);636			return -ENOMEM;637		}638	}639 640	while (req.len > 0 || (!usr_data && req.ooblen > 0)) {641		struct mtd_oob_ops ops = {642			.mode = req.mode,643			.len = min_t(size_t, req.len, datbuf_len),644			.ooblen = min_t(size_t, req.ooblen, oobbuf_len),645			.datbuf = datbuf,646			.oobbuf = oobbuf,647		};648 649		/*650		 * Shorten non-page-aligned, eraseblock-sized writes so that651		 * the write ends on an eraseblock boundary.  This is necessary652		 * for adjust_oob_length() to properly handle non-page-aligned653		 * writes.654		 */655		if (ops.len == mtd->erasesize)656			ops.len -= mtd_mod_by_ws(req.start + ops.len, mtd);657 658		/*659		 * For writes which are not OOB-only, adjust the amount of OOB660		 * data written according to the number of data pages written.661		 * This is necessary to prevent OOB data from being skipped662		 * over in data+OOB writes requiring multiple mtd_write_oob()663		 * calls to be completed.664		 */665		adjust_oob_length(mtd, req.start, &ops);666 667		if (copy_from_user(datbuf, usr_data, ops.len) ||668		    copy_from_user(oobbuf, usr_oob, ops.ooblen)) {669			ret = -EFAULT;670			break;671		}672 673		ret = mtd_write_oob(mtd, req.start, &ops);674		if (ret)675			break;676 677		req.start += ops.retlen;678		req.len -= ops.retlen;679		usr_data += ops.retlen;680 681		req.ooblen -= ops.oobretlen;682		usr_oob += ops.oobretlen;683	}684 685	kvfree(datbuf);686	kvfree(oobbuf);687 688	return ret;689}690 691static noinline_for_stack int692mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)693{694	struct mtd_info *master = mtd_get_master(mtd);695	struct mtd_read_req req;696	void __user *usr_data, *usr_oob;697	uint8_t *datbuf = NULL, *oobbuf = NULL;698	size_t datbuf_len, oobbuf_len;699	size_t orig_len, orig_ooblen;700	int ret = 0;701 702	if (copy_from_user(&req, argp, sizeof(req)))703		return -EFAULT;704 705	orig_len = req.len;706	orig_ooblen = req.ooblen;707 708	usr_data = (void __user *)(uintptr_t)req.usr_data;709	usr_oob = (void __user *)(uintptr_t)req.usr_oob;710 711	if (!master->_read_oob)712		return -EOPNOTSUPP;713 714	if (!usr_data)715		req.len = 0;716 717	if (!usr_oob)718		req.ooblen = 0;719 720	req.ecc_stats.uncorrectable_errors = 0;721	req.ecc_stats.corrected_bitflips = 0;722	req.ecc_stats.max_bitflips = 0;723 724	req.len &= 0xffffffff;725	req.ooblen &= 0xffffffff;726 727	if (req.start + req.len > mtd->size) {728		ret = -EINVAL;729		goto out;730	}731 732	datbuf_len = min_t(size_t, req.len, mtd->erasesize);733	if (datbuf_len > 0) {734		datbuf = kvmalloc(datbuf_len, GFP_KERNEL);735		if (!datbuf) {736			ret = -ENOMEM;737			goto out;738		}739	}740 741	oobbuf_len = min_t(size_t, req.ooblen, mtd->erasesize);742	if (oobbuf_len > 0) {743		oobbuf = kvmalloc(oobbuf_len, GFP_KERNEL);744		if (!oobbuf) {745			ret = -ENOMEM;746			goto out;747		}748	}749 750	while (req.len > 0 || (!usr_data && req.ooblen > 0)) {751		struct mtd_req_stats stats;752		struct mtd_oob_ops ops = {753			.mode = req.mode,754			.len = min_t(size_t, req.len, datbuf_len),755			.ooblen = min_t(size_t, req.ooblen, oobbuf_len),756			.datbuf = datbuf,757			.oobbuf = oobbuf,758			.stats = &stats,759		};760 761		/*762		 * Shorten non-page-aligned, eraseblock-sized reads so that the763		 * read ends on an eraseblock boundary.  This is necessary in764		 * order to prevent OOB data for some pages from being765		 * duplicated in the output of non-page-aligned reads requiring766		 * multiple mtd_read_oob() calls to be completed.767		 */768		if (ops.len == mtd->erasesize)769			ops.len -= mtd_mod_by_ws(req.start + ops.len, mtd);770 771		ret = mtd_read_oob(mtd, (loff_t)req.start, &ops);772 773		req.ecc_stats.uncorrectable_errors +=774			stats.uncorrectable_errors;775		req.ecc_stats.corrected_bitflips += stats.corrected_bitflips;776		req.ecc_stats.max_bitflips =777			max(req.ecc_stats.max_bitflips, stats.max_bitflips);778 779		if (ret && !mtd_is_bitflip_or_eccerr(ret))780			break;781 782		if (copy_to_user(usr_data, ops.datbuf, ops.retlen) ||783		    copy_to_user(usr_oob, ops.oobbuf, ops.oobretlen)) {784			ret = -EFAULT;785			break;786		}787 788		req.start += ops.retlen;789		req.len -= ops.retlen;790		usr_data += ops.retlen;791 792		req.ooblen -= ops.oobretlen;793		usr_oob += ops.oobretlen;794	}795 796	/*797	 * As multiple iterations of the above loop (and therefore multiple798	 * mtd_read_oob() calls) may be necessary to complete the read request,799	 * adjust the final return code to ensure it accounts for all detected800	 * ECC errors.801	 */802	if (!ret || mtd_is_bitflip(ret)) {803		if (req.ecc_stats.uncorrectable_errors > 0)804			ret = -EBADMSG;805		else if (req.ecc_stats.corrected_bitflips > 0)806			ret = -EUCLEAN;807	}808 809out:810	req.len = orig_len - req.len;811	req.ooblen = orig_ooblen - req.ooblen;812 813	if (copy_to_user(argp, &req, sizeof(req)))814		ret = -EFAULT;815 816	kvfree(datbuf);817	kvfree(oobbuf);818 819	return ret;820}821 822static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)823{824	struct mtd_file_info *mfi = file->private_data;825	struct mtd_info *mtd = mfi->mtd;826	struct mtd_info *master = mtd_get_master(mtd);827	void __user *argp = (void __user *)arg;828	int ret = 0;829	struct mtd_info_user info;830 831	pr_debug("MTD_ioctl\n");832 833	/*834	 * Check the file mode to require "dangerous" commands to have write835	 * permissions.836	 */837	switch (cmd) {838	/* "safe" commands */839	case MEMGETREGIONCOUNT:840	case MEMGETREGIONINFO:841	case MEMGETINFO:842	case MEMREADOOB:843	case MEMREADOOB64:844	case MEMREAD:845	case MEMISLOCKED:846	case MEMGETOOBSEL:847	case MEMGETBADBLOCK:848	case OTPSELECT:849	case OTPGETREGIONCOUNT:850	case OTPGETREGIONINFO:851	case ECCGETLAYOUT:852	case ECCGETSTATS:853	case MTDFILEMODE:854	case BLKPG:855	case BLKRRPART:856		break;857 858	/* "dangerous" commands */859	case MEMERASE:860	case MEMERASE64:861	case MEMLOCK:862	case MEMUNLOCK:863	case MEMSETBADBLOCK:864	case MEMWRITEOOB:865	case MEMWRITEOOB64:866	case MEMWRITE:867	case OTPLOCK:868	case OTPERASE:869		if (!(file->f_mode & FMODE_WRITE))870			return -EPERM;871		break;872 873	default:874		return -ENOTTY;875	}876 877	switch (cmd) {878	case MEMGETREGIONCOUNT:879		if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))880			return -EFAULT;881		break;882 883	case MEMGETREGIONINFO:884	{885		uint32_t ur_idx;886		struct mtd_erase_region_info *kr;887		struct region_info_user __user *ur = argp;888 889		if (get_user(ur_idx, &(ur->regionindex)))890			return -EFAULT;891 892		if (ur_idx >= mtd->numeraseregions)893			return -EINVAL;894 895		kr = &(mtd->eraseregions[ur_idx]);896 897		if (put_user(kr->offset, &(ur->offset))898		    || put_user(kr->erasesize, &(ur->erasesize))899		    || put_user(kr->numblocks, &(ur->numblocks)))900			return -EFAULT;901 902		break;903	}904 905	case MEMGETINFO:906		memset(&info, 0, sizeof(info));907		info.type	= mtd->type;908		info.flags	= mtd->flags;909		info.size	= mtd->size;910		info.erasesize	= mtd->erasesize;911		info.writesize	= mtd->writesize;912		info.oobsize	= mtd->oobsize;913		/* The below field is obsolete */914		info.padding	= 0;915		if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))916			return -EFAULT;917		break;918 919	case MEMERASE:920	case MEMERASE64:921	{922		struct erase_info *erase;923 924		erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);925		if (!erase)926			ret = -ENOMEM;927		else {928			if (cmd == MEMERASE64) {929				struct erase_info_user64 einfo64;930 931				if (copy_from_user(&einfo64, argp,932					    sizeof(struct erase_info_user64))) {933					kfree(erase);934					return -EFAULT;935				}936				erase->addr = einfo64.start;937				erase->len = einfo64.length;938			} else {939				struct erase_info_user einfo32;940 941				if (copy_from_user(&einfo32, argp,942					    sizeof(struct erase_info_user))) {943					kfree(erase);944					return -EFAULT;945				}946				erase->addr = einfo32.start;947				erase->len = einfo32.length;948			}949 950			ret = mtd_erase(mtd, erase);951			kfree(erase);952		}953		break;954	}955 956	case MEMWRITEOOB:957	{958		struct mtd_oob_buf buf;959		struct mtd_oob_buf __user *buf_user = argp;960 961		/* NOTE: writes return length to buf_user->length */962		if (copy_from_user(&buf, argp, sizeof(buf)))963			ret = -EFAULT;964		else965			ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,966				buf.ptr, &buf_user->length);967		break;968	}969 970	case MEMREADOOB:971	{972		struct mtd_oob_buf buf;973		struct mtd_oob_buf __user *buf_user = argp;974 975		/* NOTE: writes return length to buf_user->start */976		if (copy_from_user(&buf, argp, sizeof(buf)))977			ret = -EFAULT;978		else979			ret = mtdchar_readoob(file, mtd, buf.start, buf.length,980				buf.ptr, &buf_user->start);981		break;982	}983 984	case MEMWRITEOOB64:985	{986		struct mtd_oob_buf64 buf;987		struct mtd_oob_buf64 __user *buf_user = argp;988 989		if (copy_from_user(&buf, argp, sizeof(buf)))990			ret = -EFAULT;991		else992			ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,993				(void __user *)(uintptr_t)buf.usr_ptr,994				&buf_user->length);995		break;996	}997 998	case MEMREADOOB64:999	{1000		struct mtd_oob_buf64 buf;1001		struct mtd_oob_buf64 __user *buf_user = argp;1002 1003		if (copy_from_user(&buf, argp, sizeof(buf)))1004			ret = -EFAULT;1005		else1006			ret = mtdchar_readoob(file, mtd, buf.start, buf.length,1007				(void __user *)(uintptr_t)buf.usr_ptr,1008				&buf_user->length);1009		break;1010	}1011 1012	case MEMWRITE:1013	{1014		ret = mtdchar_write_ioctl(mtd,1015		      (struct mtd_write_req __user *)arg);1016		break;1017	}1018 1019	case MEMREAD:1020	{1021		ret = mtdchar_read_ioctl(mtd,1022		      (struct mtd_read_req __user *)arg);1023		break;1024	}1025 1026	case MEMLOCK:1027	{1028		struct erase_info_user einfo;1029 1030		if (copy_from_user(&einfo, argp, sizeof(einfo)))1031			return -EFAULT;1032 1033		ret = mtd_lock(mtd, einfo.start, einfo.length);1034		break;1035	}1036 1037	case MEMUNLOCK:1038	{1039		struct erase_info_user einfo;1040 1041		if (copy_from_user(&einfo, argp, sizeof(einfo)))1042			return -EFAULT;1043 1044		ret = mtd_unlock(mtd, einfo.start, einfo.length);1045		break;1046	}1047 1048	case MEMISLOCKED:1049	{1050		struct erase_info_user einfo;1051 1052		if (copy_from_user(&einfo, argp, sizeof(einfo)))1053			return -EFAULT;1054 1055		ret = mtd_is_locked(mtd, einfo.start, einfo.length);1056		break;1057	}1058 1059	/* Legacy interface */1060	case MEMGETOOBSEL:1061	{1062		struct nand_oobinfo oi;1063 1064		if (!master->ooblayout)1065			return -EOPNOTSUPP;1066 1067		ret = get_oobinfo(mtd, &oi);1068		if (ret)1069			return ret;1070 1071		if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))1072			return -EFAULT;1073		break;1074	}1075 1076	case MEMGETBADBLOCK:1077	{1078		loff_t offs;1079 1080		if (copy_from_user(&offs, argp, sizeof(loff_t)))1081			return -EFAULT;1082		return mtd_block_isbad(mtd, offs);1083	}1084 1085	case MEMSETBADBLOCK:1086	{1087		loff_t offs;1088 1089		if (copy_from_user(&offs, argp, sizeof(loff_t)))1090			return -EFAULT;1091		return mtd_block_markbad(mtd, offs);1092	}1093 1094	case OTPSELECT:1095	{1096		int mode;1097		if (copy_from_user(&mode, argp, sizeof(int)))1098			return -EFAULT;1099 1100		mfi->mode = MTD_FILE_MODE_NORMAL;1101 1102		ret = otp_select_filemode(mfi, mode);1103 1104		file->f_pos = 0;1105		break;1106	}1107 1108	case OTPGETREGIONCOUNT:1109	case OTPGETREGIONINFO:1110	{1111		struct otp_info *buf = kmalloc(4096, GFP_KERNEL);1112		size_t retlen;1113		if (!buf)1114			return -ENOMEM;1115		switch (mfi->mode) {1116		case MTD_FILE_MODE_OTP_FACTORY:1117			ret = mtd_get_fact_prot_info(mtd, 4096, &retlen, buf);1118			break;1119		case MTD_FILE_MODE_OTP_USER:1120			ret = mtd_get_user_prot_info(mtd, 4096, &retlen, buf);1121			break;1122		default:1123			ret = -EINVAL;1124			break;1125		}1126		if (!ret) {1127			if (cmd == OTPGETREGIONCOUNT) {1128				int nbr = retlen / sizeof(struct otp_info);1129				ret = copy_to_user(argp, &nbr, sizeof(int));1130			} else1131				ret = copy_to_user(argp, buf, retlen);1132			if (ret)1133				ret = -EFAULT;1134		}1135		kfree(buf);1136		break;1137	}1138 1139	case OTPLOCK:1140	case OTPERASE:1141	{1142		struct otp_info oinfo;1143 1144		if (mfi->mode != MTD_FILE_MODE_OTP_USER)1145			return -EINVAL;1146		if (copy_from_user(&oinfo, argp, sizeof(oinfo)))1147			return -EFAULT;1148		if (cmd == OTPLOCK)1149			ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length);1150		else1151			ret = mtd_erase_user_prot_reg(mtd, oinfo.start, oinfo.length);1152		break;1153	}1154 1155	/* This ioctl is being deprecated - it truncates the ECC layout */1156	case ECCGETLAYOUT:1157	{1158		struct nand_ecclayout_user *usrlay;1159 1160		if (!master->ooblayout)1161			return -EOPNOTSUPP;1162 1163		usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL);1164		if (!usrlay)1165			return -ENOMEM;1166 1167		shrink_ecclayout(mtd, usrlay);1168 1169		if (copy_to_user(argp, usrlay, sizeof(*usrlay)))1170			ret = -EFAULT;1171		kfree(usrlay);1172		break;1173	}1174 1175	case ECCGETSTATS:1176	{1177		if (copy_to_user(argp, &mtd->ecc_stats,1178				 sizeof(struct mtd_ecc_stats)))1179			return -EFAULT;1180		break;1181	}1182 1183	case MTDFILEMODE:1184	{1185		mfi->mode = 0;1186 1187		switch(arg) {1188		case MTD_FILE_MODE_OTP_FACTORY:1189		case MTD_FILE_MODE_OTP_USER:1190			ret = otp_select_filemode(mfi, arg);1191			break;1192 1193		case MTD_FILE_MODE_RAW:1194			if (!mtd_has_oob(mtd))1195				return -EOPNOTSUPP;1196			mfi->mode = arg;1197			break;1198 1199		case MTD_FILE_MODE_NORMAL:1200			break;1201		default:1202			ret = -EINVAL;1203		}1204		file->f_pos = 0;1205		break;1206	}1207 1208	case BLKPG:1209	{1210		struct blkpg_ioctl_arg __user *blk_arg = argp;1211		struct blkpg_ioctl_arg a;1212 1213		if (copy_from_user(&a, blk_arg, sizeof(a)))1214			ret = -EFAULT;1215		else1216			ret = mtdchar_blkpg_ioctl(mtd, &a);1217		break;1218	}1219 1220	case BLKRRPART:1221	{1222		/* No reread partition feature. Just return ok */1223		ret = 0;1224		break;1225	}1226	}1227 1228	return ret;1229} /* memory_ioctl */1230 1231static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)1232{1233	struct mtd_file_info *mfi = file->private_data;1234	struct mtd_info *mtd = mfi->mtd;1235	struct mtd_info *master = mtd_get_master(mtd);1236	int ret;1237 1238	mutex_lock(&master->master.chrdev_lock);1239	ret = mtdchar_ioctl(file, cmd, arg);1240	mutex_unlock(&master->master.chrdev_lock);1241 1242	return ret;1243}1244 1245#ifdef CONFIG_COMPAT1246 1247struct mtd_oob_buf32 {1248	u_int32_t start;1249	u_int32_t length;1250	compat_caddr_t ptr;	/* unsigned char* */1251};1252 1253#define MEMWRITEOOB32		_IOWR('M', 3, struct mtd_oob_buf32)1254#define MEMREADOOB32		_IOWR('M', 4, struct mtd_oob_buf32)1255 1256static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,1257	unsigned long arg)1258{1259	struct mtd_file_info *mfi = file->private_data;1260	struct mtd_info *mtd = mfi->mtd;1261	struct mtd_info *master = mtd_get_master(mtd);1262	void __user *argp = compat_ptr(arg);1263	int ret = 0;1264 1265	mutex_lock(&master->master.chrdev_lock);1266 1267	switch (cmd) {1268	case MEMWRITEOOB32:1269	{1270		struct mtd_oob_buf32 buf;1271		struct mtd_oob_buf32 __user *buf_user = argp;1272 1273		if (!(file->f_mode & FMODE_WRITE)) {1274			ret = -EPERM;1275			break;1276		}1277 1278		if (copy_from_user(&buf, argp, sizeof(buf)))1279			ret = -EFAULT;1280		else1281			ret = mtdchar_writeoob(file, mtd, buf.start,1282				buf.length, compat_ptr(buf.ptr),1283				&buf_user->length);1284		break;1285	}1286 1287	case MEMREADOOB32:1288	{1289		struct mtd_oob_buf32 buf;1290		struct mtd_oob_buf32 __user *buf_user = argp;1291 1292		/* NOTE: writes return length to buf->start */1293		if (copy_from_user(&buf, argp, sizeof(buf)))1294			ret = -EFAULT;1295		else1296			ret = mtdchar_readoob(file, mtd, buf.start,1297				buf.length, compat_ptr(buf.ptr),1298				&buf_user->start);1299		break;1300	}1301 1302	case BLKPG:1303	{1304		/* Convert from blkpg_compat_ioctl_arg to blkpg_ioctl_arg */1305		struct blkpg_compat_ioctl_arg __user *uarg = argp;1306		struct blkpg_compat_ioctl_arg compat_arg;1307		struct blkpg_ioctl_arg a;1308 1309		if (copy_from_user(&compat_arg, uarg, sizeof(compat_arg))) {1310			ret = -EFAULT;1311			break;1312		}1313 1314		memset(&a, 0, sizeof(a));1315		a.op = compat_arg.op;1316		a.flags = compat_arg.flags;1317		a.datalen = compat_arg.datalen;1318		a.data = compat_ptr(compat_arg.data);1319 1320		ret = mtdchar_blkpg_ioctl(mtd, &a);1321		break;1322	}1323 1324	default:1325		ret = mtdchar_ioctl(file, cmd, (unsigned long)argp);1326	}1327 1328	mutex_unlock(&master->master.chrdev_lock);1329 1330	return ret;1331}1332 1333#endif /* CONFIG_COMPAT */1334 1335/*1336 * try to determine where a shared mapping can be made1337 * - only supported for NOMMU at the moment (MMU can't doesn't copy private1338 *   mappings)1339 */1340#ifndef CONFIG_MMU1341static unsigned long mtdchar_get_unmapped_area(struct file *file,1342					   unsigned long addr,1343					   unsigned long len,1344					   unsigned long pgoff,1345					   unsigned long flags)1346{1347	struct mtd_file_info *mfi = file->private_data;1348	struct mtd_info *mtd = mfi->mtd;1349	unsigned long offset;1350	int ret;1351 1352	if (addr != 0)1353		return (unsigned long) -EINVAL;1354 1355	if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))1356		return (unsigned long) -EINVAL;1357 1358	offset = pgoff << PAGE_SHIFT;1359	if (offset > mtd->size - len)1360		return (unsigned long) -EINVAL;1361 1362	ret = mtd_get_unmapped_area(mtd, len, offset, flags);1363	return ret == -EOPNOTSUPP ? -ENODEV : ret;1364}1365 1366static unsigned mtdchar_mmap_capabilities(struct file *file)1367{1368	struct mtd_file_info *mfi = file->private_data;1369 1370	return mtd_mmap_capabilities(mfi->mtd);1371}1372#endif1373 1374/*1375 * set up a mapping for shared memory segments1376 */1377static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)1378{1379#ifdef CONFIG_MMU1380	struct mtd_file_info *mfi = file->private_data;1381	struct mtd_info *mtd = mfi->mtd;1382	struct map_info *map = mtd->priv;1383 1384        /* This is broken because it assumes the MTD device is map-based1385	   and that mtd->priv is a valid struct map_info.  It should be1386	   replaced with something that uses the mtd_get_unmapped_area()1387	   operation properly. */1388	if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {1389#ifdef pgprot_noncached1390		if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))1391			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);1392#endif1393		return vm_iomap_memory(vma, map->phys, map->size);1394	}1395	return -ENODEV;1396#else1397	return vma->vm_flags & VM_SHARED ? 0 : -EACCES;1398#endif1399}1400 1401static const struct file_operations mtd_fops = {1402	.owner		= THIS_MODULE,1403	.llseek		= mtdchar_lseek,1404	.read		= mtdchar_read,1405	.write		= mtdchar_write,1406	.unlocked_ioctl	= mtdchar_unlocked_ioctl,1407#ifdef CONFIG_COMPAT1408	.compat_ioctl	= mtdchar_compat_ioctl,1409#endif1410	.open		= mtdchar_open,1411	.release	= mtdchar_close,1412	.mmap		= mtdchar_mmap,1413#ifndef CONFIG_MMU1414	.get_unmapped_area = mtdchar_get_unmapped_area,1415	.mmap_capabilities = mtdchar_mmap_capabilities,1416#endif1417};1418 1419int __init init_mtdchar(void)1420{1421	int ret;1422 1423	ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,1424				   "mtd", &mtd_fops);1425	if (ret < 0) {1426		pr_err("Can't allocate major number %d for MTD\n",1427		       MTD_CHAR_MAJOR);1428		return ret;1429	}1430 1431	return ret;1432}1433 1434void __exit cleanup_mtdchar(void)1435{1436	__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");1437}1438 1439MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR);1440