linux/drivers/mtd/mtdchar.c
<<
>>
Prefs
   1/*
   2 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17 *
  18 */
  19
  20#include <linux/device.h>
  21#include <linux/fs.h>
  22#include <linux/mm.h>
  23#include <linux/err.h>
  24#include <linux/init.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/slab.h>
  28#include <linux/sched.h>
  29#include <linux/mutex.h>
  30#include <linux/backing-dev.h>
  31#include <linux/compat.h>
  32#include <linux/mount.h>
  33#include <linux/blkpg.h>
  34#include <linux/magic.h>
  35#include <linux/major.h>
  36#include <linux/mtd/mtd.h>
  37#include <linux/mtd/partitions.h>
  38#include <linux/mtd/map.h>
  39
  40#include <linux/uaccess.h>
  41
  42#include "mtdcore.h"
  43
  44static DEFINE_MUTEX(mtd_mutex);
  45
  46/*
  47 * Data structure to hold the pointer to the mtd device as well
  48 * as mode information of various use cases.
  49 */
  50struct mtd_file_info {
  51        struct mtd_info *mtd;
  52        enum mtd_file_modes mode;
  53};
  54
  55static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig)
  56{
  57        struct mtd_file_info *mfi = file->private_data;
  58        return fixed_size_llseek(file, offset, orig, mfi->mtd->size);
  59}
  60
  61static int mtdchar_open(struct inode *inode, struct file *file)
  62{
  63        int minor = iminor(inode);
  64        int devnum = minor >> 1;
  65        int ret = 0;
  66        struct mtd_info *mtd;
  67        struct mtd_file_info *mfi;
  68
  69        pr_debug("MTD_open\n");
  70
  71        /* You can't open the RO devices RW */
  72        if ((file->f_mode & FMODE_WRITE) && (minor & 1))
  73                return -EACCES;
  74
  75        mutex_lock(&mtd_mutex);
  76        mtd = get_mtd_device(NULL, devnum);
  77
  78        if (IS_ERR(mtd)) {
  79                ret = PTR_ERR(mtd);
  80                goto out;
  81        }
  82
  83        if (mtd->type == MTD_ABSENT) {
  84                ret = -ENODEV;
  85                goto out1;
  86        }
  87
  88        /* You can't open it RW if it's not a writeable device */
  89        if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
  90                ret = -EACCES;
  91                goto out1;
  92        }
  93
  94        mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
  95        if (!mfi) {
  96                ret = -ENOMEM;
  97                goto out1;
  98        }
  99        mfi->mtd = mtd;
 100        file->private_data = mfi;
 101        mutex_unlock(&mtd_mutex);
 102        return 0;
 103
 104out1:
 105        put_mtd_device(mtd);
 106out:
 107        mutex_unlock(&mtd_mutex);
 108        return ret;
 109} /* mtdchar_open */
 110
 111/*====================================================================*/
 112
 113static int mtdchar_close(struct inode *inode, struct file *file)
 114{
 115        struct mtd_file_info *mfi = file->private_data;
 116        struct mtd_info *mtd = mfi->mtd;
 117
 118        pr_debug("MTD_close\n");
 119
 120        /* Only sync if opened RW */
 121        if ((file->f_mode & FMODE_WRITE))
 122                mtd_sync(mtd);
 123
 124        put_mtd_device(mtd);
 125        file->private_data = NULL;
 126        kfree(mfi);
 127
 128        return 0;
 129} /* mtdchar_close */
 130
 131/* Back in June 2001, dwmw2 wrote:
 132 *
 133 *   FIXME: This _really_ needs to die. In 2.5, we should lock the
 134 *   userspace buffer down and use it directly with readv/writev.
 135 *
 136 * The implementation below, using mtd_kmalloc_up_to, mitigates
 137 * allocation failures when the system is under low-memory situations
 138 * or if memory is highly fragmented at the cost of reducing the
 139 * performance of the requested transfer due to a smaller buffer size.
 140 *
 141 * A more complex but more memory-efficient implementation based on
 142 * get_user_pages and iovecs to cover extents of those pages is a
 143 * longer-term goal, as intimated by dwmw2 above. However, for the
 144 * write case, this requires yet more complex head and tail transfer
 145 * handling when those head and tail offsets and sizes are such that
 146 * alignment requirements are not met in the NAND subdriver.
 147 */
 148
 149static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
 150                        loff_t *ppos)
 151{
 152        struct mtd_file_info *mfi = file->private_data;
 153        struct mtd_info *mtd = mfi->mtd;
 154        size_t retlen;
 155        size_t total_retlen=0;
 156        int ret=0;
 157        int len;
 158        size_t size = count;
 159        char *kbuf;
 160
 161        pr_debug("MTD_read\n");
 162
 163        if (*ppos + count > mtd->size)
 164                count = mtd->size - *ppos;
 165
 166        if (!count)
 167                return 0;
 168
 169        kbuf = mtd_kmalloc_up_to(mtd, &size);
 170        if (!kbuf)
 171                return -ENOMEM;
 172
 173        while (count) {
 174                len = min_t(size_t, count, size);
 175
 176                switch (mfi->mode) {
 177                case MTD_FILE_MODE_OTP_FACTORY:
 178                        ret = mtd_read_fact_prot_reg(mtd, *ppos, len,
 179                                                     &retlen, kbuf);
 180                        break;
 181                case MTD_FILE_MODE_OTP_USER:
 182                        ret = mtd_read_user_prot_reg(mtd, *ppos, len,
 183                                                     &retlen, kbuf);
 184                        break;
 185                case MTD_FILE_MODE_RAW:
 186                {
 187                        struct mtd_oob_ops ops;
 188
 189                        ops.mode = MTD_OPS_RAW;
 190                        ops.datbuf = kbuf;
 191                        ops.oobbuf = NULL;
 192                        ops.len = len;
 193
 194                        ret = mtd_read_oob(mtd, *ppos, &ops);
 195                        retlen = ops.retlen;
 196                        break;
 197                }
 198                default:
 199                        ret = mtd_read(mtd, *ppos, len, &retlen, kbuf);
 200                }
 201                /* Nand returns -EBADMSG on ECC errors, but it returns
 202                 * the data. For our userspace tools it is important
 203                 * to dump areas with ECC errors!
 204                 * For kernel internal usage it also might return -EUCLEAN
 205                 * to signal the caller that a bitflip has occurred and has
 206                 * been corrected by the ECC algorithm.
 207                 * Userspace software which accesses NAND this way
 208                 * must be aware of the fact that it deals with NAND
 209                 */
 210                if (!ret || mtd_is_bitflip_or_eccerr(ret)) {
 211                        *ppos += retlen;
 212                        if (copy_to_user(buf, kbuf, retlen)) {
 213                                kfree(kbuf);
 214                                return -EFAULT;
 215                        }
 216                        else
 217                                total_retlen += retlen;
 218
 219                        count -= retlen;
 220                        buf += retlen;
 221                        if (retlen == 0)
 222                                count = 0;
 223                }
 224                else {
 225                        kfree(kbuf);
 226                        return ret;
 227                }
 228
 229        }
 230
 231        kfree(kbuf);
 232        return total_retlen;
 233} /* mtdchar_read */
 234
 235static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t count,
 236                        loff_t *ppos)
 237{
 238        struct mtd_file_info *mfi = file->private_data;
 239        struct mtd_info *mtd = mfi->mtd;
 240        size_t size = count;
 241        char *kbuf;
 242        size_t retlen;
 243        size_t total_retlen=0;
 244        int ret=0;
 245        int len;
 246
 247        pr_debug("MTD_write\n");
 248
 249        if (*ppos == mtd->size)
 250                return -ENOSPC;
 251
 252        if (*ppos + count > mtd->size)
 253                count = mtd->size - *ppos;
 254
 255        if (!count)
 256                return 0;
 257
 258        kbuf = mtd_kmalloc_up_to(mtd, &size);
 259        if (!kbuf)
 260                return -ENOMEM;
 261
 262        while (count) {
 263                len = min_t(size_t, count, size);
 264
 265                if (copy_from_user(kbuf, buf, len)) {
 266                        kfree(kbuf);
 267                        return -EFAULT;
 268                }
 269
 270                switch (mfi->mode) {
 271                case MTD_FILE_MODE_OTP_FACTORY:
 272                        ret = -EROFS;
 273                        break;
 274                case MTD_FILE_MODE_OTP_USER:
 275                        ret = mtd_write_user_prot_reg(mtd, *ppos, len,
 276                                                      &retlen, kbuf);
 277                        break;
 278
 279                case MTD_FILE_MODE_RAW:
 280                {
 281                        struct mtd_oob_ops ops;
 282
 283                        ops.mode = MTD_OPS_RAW;
 284                        ops.datbuf = kbuf;
 285                        ops.oobbuf = NULL;
 286                        ops.ooboffs = 0;
 287                        ops.len = len;
 288
 289                        ret = mtd_write_oob(mtd, *ppos, &ops);
 290                        retlen = ops.retlen;
 291                        break;
 292                }
 293
 294                default:
 295                        ret = mtd_write(mtd, *ppos, len, &retlen, kbuf);
 296                }
 297
 298                /*
 299                 * Return -ENOSPC only if no data could be written at all.
 300                 * Otherwise just return the number of bytes that actually
 301                 * have been written.
 302                 */
 303                if ((ret == -ENOSPC) && (total_retlen))
 304                        break;
 305
 306                if (!ret) {
 307                        *ppos += retlen;
 308                        total_retlen += retlen;
 309                        count -= retlen;
 310                        buf += retlen;
 311                }
 312                else {
 313                        kfree(kbuf);
 314                        return ret;
 315                }
 316        }
 317
 318        kfree(kbuf);
 319        return total_retlen;
 320} /* mtdchar_write */
 321
 322/*======================================================================
 323
 324    IOCTL calls for getting device parameters.
 325
 326======================================================================*/
 327
 328static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
 329{
 330        struct mtd_info *mtd = mfi->mtd;
 331        size_t retlen;
 332
 333        switch (mode) {
 334        case MTD_OTP_FACTORY:
 335                if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) ==
 336                                -EOPNOTSUPP)
 337                        return -EOPNOTSUPP;
 338
 339                mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
 340                break;
 341        case MTD_OTP_USER:
 342                if (mtd_read_user_prot_reg(mtd, -1, 0, &retlen, NULL) ==
 343                                -EOPNOTSUPP)
 344                        return -EOPNOTSUPP;
 345
 346                mfi->mode = MTD_FILE_MODE_OTP_USER;
 347                break;
 348        case MTD_OTP_OFF:
 349                mfi->mode = MTD_FILE_MODE_NORMAL;
 350                break;
 351        default:
 352                return -EINVAL;
 353        }
 354
 355        return 0;
 356}
 357
 358static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
 359        uint64_t start, uint32_t length, void __user *ptr,
 360        uint32_t __user *retp)
 361{
 362        struct mtd_file_info *mfi = file->private_data;
 363        struct mtd_oob_ops ops;
 364        uint32_t retlen;
 365        int ret = 0;
 366
 367        if (!(file->f_mode & FMODE_WRITE))
 368                return -EPERM;
 369
 370        if (length > 4096)
 371                return -EINVAL;
 372
 373        if (!mtd->_write_oob)
 374                return -EOPNOTSUPP;
 375
 376        ops.ooblen = length;
 377        ops.ooboffs = start & (mtd->writesize - 1);
 378        ops.datbuf = NULL;
 379        ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
 380                MTD_OPS_PLACE_OOB;
 381
 382        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 383                return -EINVAL;
 384
 385        ops.oobbuf = memdup_user(ptr, length);
 386        if (IS_ERR(ops.oobbuf))
 387                return PTR_ERR(ops.oobbuf);
 388
 389        start &= ~((uint64_t)mtd->writesize - 1);
 390        ret = mtd_write_oob(mtd, start, &ops);
 391
 392        if (ops.oobretlen > 0xFFFFFFFFU)
 393                ret = -EOVERFLOW;
 394        retlen = ops.oobretlen;
 395        if (copy_to_user(retp, &retlen, sizeof(length)))
 396                ret = -EFAULT;
 397
 398        kfree(ops.oobbuf);
 399        return ret;
 400}
 401
 402static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
 403        uint64_t start, uint32_t length, void __user *ptr,
 404        uint32_t __user *retp)
 405{
 406        struct mtd_file_info *mfi = file->private_data;
 407        struct mtd_oob_ops ops;
 408        int ret = 0;
 409
 410        if (length > 4096)
 411                return -EINVAL;
 412
 413        ops.ooblen = length;
 414        ops.ooboffs = start & (mtd->writesize - 1);
 415        ops.datbuf = NULL;
 416        ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
 417                MTD_OPS_PLACE_OOB;
 418
 419        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 420                return -EINVAL;
 421
 422        ops.oobbuf = kmalloc(length, GFP_KERNEL);
 423        if (!ops.oobbuf)
 424                return -ENOMEM;
 425
 426        start &= ~((uint64_t)mtd->writesize - 1);
 427        ret = mtd_read_oob(mtd, start, &ops);
 428
 429        if (put_user(ops.oobretlen, retp))
 430                ret = -EFAULT;
 431        else if (ops.oobretlen && copy_to_user(ptr, ops.oobbuf,
 432                                            ops.oobretlen))
 433                ret = -EFAULT;
 434
 435        kfree(ops.oobbuf);
 436
 437        /*
 438         * NAND returns -EBADMSG on ECC errors, but it returns the OOB
 439         * data. For our userspace tools it is important to dump areas
 440         * with ECC errors!
 441         * For kernel internal usage it also might return -EUCLEAN
 442         * to signal the caller that a bitflip has occurred and has
 443         * been corrected by the ECC algorithm.
 444         *
 445         * Note: currently the standard NAND function, nand_read_oob_std,
 446         * does not calculate ECC for the OOB area, so do not rely on
 447         * this behavior unless you have replaced it with your own.
 448         */
 449        if (mtd_is_bitflip_or_eccerr(ret))
 450                return 0;
 451
 452        return ret;
 453}
 454
 455/*
 456 * Copies (and truncates, if necessary) OOB layout information to the
 457 * deprecated layout struct, nand_ecclayout_user. This is necessary only to
 458 * support the deprecated API ioctl ECCGETLAYOUT while allowing all new
 459 * functionality to use mtd_ooblayout_ops flexibly (i.e. mtd_ooblayout_ops
 460 * can describe any kind of OOB layout with almost zero overhead from a
 461 * memory usage point of view).
 462 */
 463static int shrink_ecclayout(struct mtd_info *mtd,
 464                            struct nand_ecclayout_user *to)
 465{
 466        struct mtd_oob_region oobregion;
 467        int i, section = 0, ret;
 468
 469        if (!mtd || !to)
 470                return -EINVAL;
 471
 472        memset(to, 0, sizeof(*to));
 473
 474        to->eccbytes = 0;
 475        for (i = 0; i < MTD_MAX_ECCPOS_ENTRIES;) {
 476                u32 eccpos;
 477
 478                ret = mtd_ooblayout_ecc(mtd, section++, &oobregion);
 479                if (ret < 0) {
 480                        if (ret != -ERANGE)
 481                                return ret;
 482
 483                        break;
 484                }
 485
 486                eccpos = oobregion.offset;
 487                for (; i < MTD_MAX_ECCPOS_ENTRIES &&
 488                       eccpos < oobregion.offset + oobregion.length; i++) {
 489                        to->eccpos[i] = eccpos++;
 490                        to->eccbytes++;
 491                }
 492        }
 493
 494        for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
 495                ret = mtd_ooblayout_free(mtd, i, &oobregion);
 496                if (ret < 0) {
 497                        if (ret != -ERANGE)
 498                                return ret;
 499
 500                        break;
 501                }
 502
 503                to->oobfree[i].offset = oobregion.offset;
 504                to->oobfree[i].length = oobregion.length;
 505                to->oobavail += to->oobfree[i].length;
 506        }
 507
 508        return 0;
 509}
 510
 511static int get_oobinfo(struct mtd_info *mtd, struct nand_oobinfo *to)
 512{
 513        struct mtd_oob_region oobregion;
 514        int i, section = 0, ret;
 515
 516        if (!mtd || !to)
 517                return -EINVAL;
 518
 519        memset(to, 0, sizeof(*to));
 520
 521        to->eccbytes = 0;
 522        for (i = 0; i < ARRAY_SIZE(to->eccpos);) {
 523                u32 eccpos;
 524
 525                ret = mtd_ooblayout_ecc(mtd, section++, &oobregion);
 526                if (ret < 0) {
 527                        if (ret != -ERANGE)
 528                                return ret;
 529
 530                        break;
 531                }
 532
 533                if (oobregion.length + i > ARRAY_SIZE(to->eccpos))
 534                        return -EINVAL;
 535
 536                eccpos = oobregion.offset;
 537                for (; eccpos < oobregion.offset + oobregion.length; i++) {
 538                        to->eccpos[i] = eccpos++;
 539                        to->eccbytes++;
 540                }
 541        }
 542
 543        for (i = 0; i < 8; i++) {
 544                ret = mtd_ooblayout_free(mtd, i, &oobregion);
 545                if (ret < 0) {
 546                        if (ret != -ERANGE)
 547                                return ret;
 548
 549                        break;
 550                }
 551
 552                to->oobfree[i][0] = oobregion.offset;
 553                to->oobfree[i][1] = oobregion.length;
 554        }
 555
 556        to->useecc = MTD_NANDECC_AUTOPLACE;
 557
 558        return 0;
 559}
 560
 561static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
 562                               struct blkpg_ioctl_arg *arg)
 563{
 564        struct blkpg_partition p;
 565
 566        if (!capable(CAP_SYS_ADMIN))
 567                return -EPERM;
 568
 569        if (copy_from_user(&p, arg->data, sizeof(p)))
 570                return -EFAULT;
 571
 572        switch (arg->op) {
 573        case BLKPG_ADD_PARTITION:
 574
 575                /* Only master mtd device must be used to add partitions */
 576                if (mtd_is_partition(mtd))
 577                        return -EINVAL;
 578
 579                /* Sanitize user input */
 580                p.devname[BLKPG_DEVNAMELTH - 1] = '\0';
 581
 582                return mtd_add_partition(mtd, p.devname, p.start, p.length);
 583
 584        case BLKPG_DEL_PARTITION:
 585
 586                if (p.pno < 0)
 587                        return -EINVAL;
 588
 589                return mtd_del_partition(mtd, p.pno);
 590
 591        default:
 592                return -EINVAL;
 593        }
 594}
 595
 596static int mtdchar_write_ioctl(struct mtd_info *mtd,
 597                struct mtd_write_req __user *argp)
 598{
 599        struct mtd_write_req req;
 600        struct mtd_oob_ops ops;
 601        const void __user *usr_data, *usr_oob;
 602        int ret;
 603
 604        if (copy_from_user(&req, argp, sizeof(req)))
 605                return -EFAULT;
 606
 607        usr_data = (const void __user *)(uintptr_t)req.usr_data;
 608        usr_oob = (const void __user *)(uintptr_t)req.usr_oob;
 609
 610        if (!mtd->_write_oob)
 611                return -EOPNOTSUPP;
 612
 613        ops.mode = req.mode;
 614        ops.len = (size_t)req.len;
 615        ops.ooblen = (size_t)req.ooblen;
 616        ops.ooboffs = 0;
 617
 618        if (usr_data) {
 619                ops.datbuf = memdup_user(usr_data, ops.len);
 620                if (IS_ERR(ops.datbuf))
 621                        return PTR_ERR(ops.datbuf);
 622        } else {
 623                ops.datbuf = NULL;
 624        }
 625
 626        if (usr_oob) {
 627                ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
 628                if (IS_ERR(ops.oobbuf)) {
 629                        kfree(ops.datbuf);
 630                        return PTR_ERR(ops.oobbuf);
 631                }
 632        } else {
 633                ops.oobbuf = NULL;
 634        }
 635
 636        ret = mtd_write_oob(mtd, (loff_t)req.start, &ops);
 637
 638        kfree(ops.datbuf);
 639        kfree(ops.oobbuf);
 640
 641        return ret;
 642}
 643
 644static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 645{
 646        struct mtd_file_info *mfi = file->private_data;
 647        struct mtd_info *mtd = mfi->mtd;
 648        void __user *argp = (void __user *)arg;
 649        int ret = 0;
 650        struct mtd_info_user info;
 651
 652        pr_debug("MTD_ioctl\n");
 653
 654        switch (cmd) {
 655        case MEMGETREGIONCOUNT:
 656                if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
 657                        return -EFAULT;
 658                break;
 659
 660        case MEMGETREGIONINFO:
 661        {
 662                uint32_t ur_idx;
 663                struct mtd_erase_region_info *kr;
 664                struct region_info_user __user *ur = argp;
 665
 666                if (get_user(ur_idx, &(ur->regionindex)))
 667                        return -EFAULT;
 668
 669                if (ur_idx >= mtd->numeraseregions)
 670                        return -EINVAL;
 671
 672                kr = &(mtd->eraseregions[ur_idx]);
 673
 674                if (put_user(kr->offset, &(ur->offset))
 675                    || put_user(kr->erasesize, &(ur->erasesize))
 676                    || put_user(kr->numblocks, &(ur->numblocks)))
 677                        return -EFAULT;
 678
 679                break;
 680        }
 681
 682        case MEMGETINFO:
 683                memset(&info, 0, sizeof(info));
 684                info.type       = mtd->type;
 685                info.flags      = mtd->flags;
 686                info.size       = mtd->size;
 687                info.erasesize  = mtd->erasesize;
 688                info.writesize  = mtd->writesize;
 689                info.oobsize    = mtd->oobsize;
 690                /* The below field is obsolete */
 691                info.padding    = 0;
 692                if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 693                        return -EFAULT;
 694                break;
 695
 696        case MEMERASE:
 697        case MEMERASE64:
 698        {
 699                struct erase_info *erase;
 700
 701                if(!(file->f_mode & FMODE_WRITE))
 702                        return -EPERM;
 703
 704                erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
 705                if (!erase)
 706                        ret = -ENOMEM;
 707                else {
 708                        if (cmd == MEMERASE64) {
 709                                struct erase_info_user64 einfo64;
 710
 711                                if (copy_from_user(&einfo64, argp,
 712                                            sizeof(struct erase_info_user64))) {
 713                                        kfree(erase);
 714                                        return -EFAULT;
 715                                }
 716                                erase->addr = einfo64.start;
 717                                erase->len = einfo64.length;
 718                        } else {
 719                                struct erase_info_user einfo32;
 720
 721                                if (copy_from_user(&einfo32, argp,
 722                                            sizeof(struct erase_info_user))) {
 723                                        kfree(erase);
 724                                        return -EFAULT;
 725                                }
 726                                erase->addr = einfo32.start;
 727                                erase->len = einfo32.length;
 728                        }
 729
 730                        ret = mtd_erase(mtd, erase);
 731                        kfree(erase);
 732                }
 733                break;
 734        }
 735
 736        case MEMWRITEOOB:
 737        {
 738                struct mtd_oob_buf buf;
 739                struct mtd_oob_buf __user *buf_user = argp;
 740
 741                /* NOTE: writes return length to buf_user->length */
 742                if (copy_from_user(&buf, argp, sizeof(buf)))
 743                        ret = -EFAULT;
 744                else
 745                        ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
 746                                buf.ptr, &buf_user->length);
 747                break;
 748        }
 749
 750        case MEMREADOOB:
 751        {
 752                struct mtd_oob_buf buf;
 753                struct mtd_oob_buf __user *buf_user = argp;
 754
 755                /* NOTE: writes return length to buf_user->start */
 756                if (copy_from_user(&buf, argp, sizeof(buf)))
 757                        ret = -EFAULT;
 758                else
 759                        ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
 760                                buf.ptr, &buf_user->start);
 761                break;
 762        }
 763
 764        case MEMWRITEOOB64:
 765        {
 766                struct mtd_oob_buf64 buf;
 767                struct mtd_oob_buf64 __user *buf_user = argp;
 768
 769                if (copy_from_user(&buf, argp, sizeof(buf)))
 770                        ret = -EFAULT;
 771                else
 772                        ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
 773                                (void __user *)(uintptr_t)buf.usr_ptr,
 774                                &buf_user->length);
 775                break;
 776        }
 777
 778        case MEMREADOOB64:
 779        {
 780                struct mtd_oob_buf64 buf;
 781                struct mtd_oob_buf64 __user *buf_user = argp;
 782
 783                if (copy_from_user(&buf, argp, sizeof(buf)))
 784                        ret = -EFAULT;
 785                else
 786                        ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
 787                                (void __user *)(uintptr_t)buf.usr_ptr,
 788                                &buf_user->length);
 789                break;
 790        }
 791
 792        case MEMWRITE:
 793        {
 794                ret = mtdchar_write_ioctl(mtd,
 795                      (struct mtd_write_req __user *)arg);
 796                break;
 797        }
 798
 799        case MEMLOCK:
 800        {
 801                struct erase_info_user einfo;
 802
 803                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 804                        return -EFAULT;
 805
 806                ret = mtd_lock(mtd, einfo.start, einfo.length);
 807                break;
 808        }
 809
 810        case MEMUNLOCK:
 811        {
 812                struct erase_info_user einfo;
 813
 814                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 815                        return -EFAULT;
 816
 817                ret = mtd_unlock(mtd, einfo.start, einfo.length);
 818                break;
 819        }
 820
 821        case MEMISLOCKED:
 822        {
 823                struct erase_info_user einfo;
 824
 825                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 826                        return -EFAULT;
 827
 828                ret = mtd_is_locked(mtd, einfo.start, einfo.length);
 829                break;
 830        }
 831
 832        /* Legacy interface */
 833        case MEMGETOOBSEL:
 834        {
 835                struct nand_oobinfo oi;
 836
 837                if (!mtd->ooblayout)
 838                        return -EOPNOTSUPP;
 839
 840                ret = get_oobinfo(mtd, &oi);
 841                if (ret)
 842                        return ret;
 843
 844                if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
 845                        return -EFAULT;
 846                break;
 847        }
 848
 849        case MEMGETBADBLOCK:
 850        {
 851                loff_t offs;
 852
 853                if (copy_from_user(&offs, argp, sizeof(loff_t)))
 854                        return -EFAULT;
 855                return mtd_block_isbad(mtd, offs);
 856                break;
 857        }
 858
 859        case MEMSETBADBLOCK:
 860        {
 861                loff_t offs;
 862
 863                if (copy_from_user(&offs, argp, sizeof(loff_t)))
 864                        return -EFAULT;
 865                return mtd_block_markbad(mtd, offs);
 866                break;
 867        }
 868
 869        case OTPSELECT:
 870        {
 871                int mode;
 872                if (copy_from_user(&mode, argp, sizeof(int)))
 873                        return -EFAULT;
 874
 875                mfi->mode = MTD_FILE_MODE_NORMAL;
 876
 877                ret = otp_select_filemode(mfi, mode);
 878
 879                file->f_pos = 0;
 880                break;
 881        }
 882
 883        case OTPGETREGIONCOUNT:
 884        case OTPGETREGIONINFO:
 885        {
 886                struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
 887                size_t retlen;
 888                if (!buf)
 889                        return -ENOMEM;
 890                switch (mfi->mode) {
 891                case MTD_FILE_MODE_OTP_FACTORY:
 892                        ret = mtd_get_fact_prot_info(mtd, 4096, &retlen, buf);
 893                        break;
 894                case MTD_FILE_MODE_OTP_USER:
 895                        ret = mtd_get_user_prot_info(mtd, 4096, &retlen, buf);
 896                        break;
 897                default:
 898                        ret = -EINVAL;
 899                        break;
 900                }
 901                if (!ret) {
 902                        if (cmd == OTPGETREGIONCOUNT) {
 903                                int nbr = retlen / sizeof(struct otp_info);
 904                                ret = copy_to_user(argp, &nbr, sizeof(int));
 905                        } else
 906                                ret = copy_to_user(argp, buf, retlen);
 907                        if (ret)
 908                                ret = -EFAULT;
 909                }
 910                kfree(buf);
 911                break;
 912        }
 913
 914        case OTPLOCK:
 915        {
 916                struct otp_info oinfo;
 917
 918                if (mfi->mode != MTD_FILE_MODE_OTP_USER)
 919                        return -EINVAL;
 920                if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
 921                        return -EFAULT;
 922                ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
 923                break;
 924        }
 925
 926        /* This ioctl is being deprecated - it truncates the ECC layout */
 927        case ECCGETLAYOUT:
 928        {
 929                struct nand_ecclayout_user *usrlay;
 930
 931                if (!mtd->ooblayout)
 932                        return -EOPNOTSUPP;
 933
 934                usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL);
 935                if (!usrlay)
 936                        return -ENOMEM;
 937
 938                shrink_ecclayout(mtd, usrlay);
 939
 940                if (copy_to_user(argp, usrlay, sizeof(*usrlay)))
 941                        ret = -EFAULT;
 942                kfree(usrlay);
 943                break;
 944        }
 945
 946        case ECCGETSTATS:
 947        {
 948                if (copy_to_user(argp, &mtd->ecc_stats,
 949                                 sizeof(struct mtd_ecc_stats)))
 950                        return -EFAULT;
 951                break;
 952        }
 953
 954        case MTDFILEMODE:
 955        {
 956                mfi->mode = 0;
 957
 958                switch(arg) {
 959                case MTD_FILE_MODE_OTP_FACTORY:
 960                case MTD_FILE_MODE_OTP_USER:
 961                        ret = otp_select_filemode(mfi, arg);
 962                        break;
 963
 964                case MTD_FILE_MODE_RAW:
 965                        if (!mtd_has_oob(mtd))
 966                                return -EOPNOTSUPP;
 967                        mfi->mode = arg;
 968
 969                case MTD_FILE_MODE_NORMAL:
 970                        break;
 971                default:
 972                        ret = -EINVAL;
 973                }
 974                file->f_pos = 0;
 975                break;
 976        }
 977
 978        case BLKPG:
 979        {
 980                struct blkpg_ioctl_arg __user *blk_arg = argp;
 981                struct blkpg_ioctl_arg a;
 982
 983                if (copy_from_user(&a, blk_arg, sizeof(a)))
 984                        ret = -EFAULT;
 985                else
 986                        ret = mtdchar_blkpg_ioctl(mtd, &a);
 987                break;
 988        }
 989
 990        case BLKRRPART:
 991        {
 992                /* No reread partition feature. Just return ok */
 993                ret = 0;
 994                break;
 995        }
 996
 997        default:
 998                ret = -ENOTTY;
 999        }
1000
1001        return ret;
1002} /* memory_ioctl */
1003
1004static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
1005{
1006        int ret;
1007
1008        mutex_lock(&mtd_mutex);
1009        ret = mtdchar_ioctl(file, cmd, arg);
1010        mutex_unlock(&mtd_mutex);
1011
1012        return ret;
1013}
1014
1015#ifdef CONFIG_COMPAT
1016
1017struct mtd_oob_buf32 {
1018        u_int32_t start;
1019        u_int32_t length;
1020        compat_caddr_t ptr;     /* unsigned char* */
1021};
1022
1023#define MEMWRITEOOB32           _IOWR('M', 3, struct mtd_oob_buf32)
1024#define MEMREADOOB32            _IOWR('M', 4, struct mtd_oob_buf32)
1025
1026static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
1027        unsigned long arg)
1028{
1029        struct mtd_file_info *mfi = file->private_data;
1030        struct mtd_info *mtd = mfi->mtd;
1031        void __user *argp = compat_ptr(arg);
1032        int ret = 0;
1033
1034        mutex_lock(&mtd_mutex);
1035
1036        switch (cmd) {
1037        case MEMWRITEOOB32:
1038        {
1039                struct mtd_oob_buf32 buf;
1040                struct mtd_oob_buf32 __user *buf_user = argp;
1041
1042                if (copy_from_user(&buf, argp, sizeof(buf)))
1043                        ret = -EFAULT;
1044                else
1045                        ret = mtdchar_writeoob(file, mtd, buf.start,
1046                                buf.length, compat_ptr(buf.ptr),
1047                                &buf_user->length);
1048                break;
1049        }
1050
1051        case MEMREADOOB32:
1052        {
1053                struct mtd_oob_buf32 buf;
1054                struct mtd_oob_buf32 __user *buf_user = argp;
1055
1056                /* NOTE: writes return length to buf->start */
1057                if (copy_from_user(&buf, argp, sizeof(buf)))
1058                        ret = -EFAULT;
1059                else
1060                        ret = mtdchar_readoob(file, mtd, buf.start,
1061                                buf.length, compat_ptr(buf.ptr),
1062                                &buf_user->start);
1063                break;
1064        }
1065
1066        case BLKPG:
1067        {
1068                /* Convert from blkpg_compat_ioctl_arg to blkpg_ioctl_arg */
1069                struct blkpg_compat_ioctl_arg __user *uarg = argp;
1070                struct blkpg_compat_ioctl_arg compat_arg;
1071                struct blkpg_ioctl_arg a;
1072
1073                if (copy_from_user(&compat_arg, uarg, sizeof(compat_arg))) {
1074                        ret = -EFAULT;
1075                        break;
1076                }
1077
1078                memset(&a, 0, sizeof(a));
1079                a.op = compat_arg.op;
1080                a.flags = compat_arg.flags;
1081                a.datalen = compat_arg.datalen;
1082                a.data = compat_ptr(compat_arg.data);
1083
1084                ret = mtdchar_blkpg_ioctl(mtd, &a);
1085                break;
1086        }
1087
1088        default:
1089                ret = mtdchar_ioctl(file, cmd, (unsigned long)argp);
1090        }
1091
1092        mutex_unlock(&mtd_mutex);
1093
1094        return ret;
1095}
1096
1097#endif /* CONFIG_COMPAT */
1098
1099/*
1100 * try to determine where a shared mapping can be made
1101 * - only supported for NOMMU at the moment (MMU can't doesn't copy private
1102 *   mappings)
1103 */
1104#ifndef CONFIG_MMU
1105static unsigned long mtdchar_get_unmapped_area(struct file *file,
1106                                           unsigned long addr,
1107                                           unsigned long len,
1108                                           unsigned long pgoff,
1109                                           unsigned long flags)
1110{
1111        struct mtd_file_info *mfi = file->private_data;
1112        struct mtd_info *mtd = mfi->mtd;
1113        unsigned long offset;
1114        int ret;
1115
1116        if (addr != 0)
1117                return (unsigned long) -EINVAL;
1118
1119        if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
1120                return (unsigned long) -EINVAL;
1121
1122        offset = pgoff << PAGE_SHIFT;
1123        if (offset > mtd->size - len)
1124                return (unsigned long) -EINVAL;
1125
1126        ret = mtd_get_unmapped_area(mtd, len, offset, flags);
1127        return ret == -EOPNOTSUPP ? -ENODEV : ret;
1128}
1129
1130static unsigned mtdchar_mmap_capabilities(struct file *file)
1131{
1132        struct mtd_file_info *mfi = file->private_data;
1133
1134        return mtd_mmap_capabilities(mfi->mtd);
1135}
1136#endif
1137
1138/*
1139 * set up a mapping for shared memory segments
1140 */
1141static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
1142{
1143#ifdef CONFIG_MMU
1144        struct mtd_file_info *mfi = file->private_data;
1145        struct mtd_info *mtd = mfi->mtd;
1146        struct map_info *map = mtd->priv;
1147
1148        /* This is broken because it assumes the MTD device is map-based
1149           and that mtd->priv is a valid struct map_info.  It should be
1150           replaced with something that uses the mtd_get_unmapped_area()
1151           operation properly. */
1152        if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
1153#ifdef pgprot_noncached
1154                if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
1155                        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1156#endif
1157                return vm_iomap_memory(vma, map->phys, map->size);
1158        }
1159        return -ENODEV;
1160#else
1161        return vma->vm_flags & VM_SHARED ? 0 : -EACCES;
1162#endif
1163}
1164
1165static const struct file_operations mtd_fops = {
1166        .owner          = THIS_MODULE,
1167        .llseek         = mtdchar_lseek,
1168        .read           = mtdchar_read,
1169        .write          = mtdchar_write,
1170        .unlocked_ioctl = mtdchar_unlocked_ioctl,
1171#ifdef CONFIG_COMPAT
1172        .compat_ioctl   = mtdchar_compat_ioctl,
1173#endif
1174        .open           = mtdchar_open,
1175        .release        = mtdchar_close,
1176        .mmap           = mtdchar_mmap,
1177#ifndef CONFIG_MMU
1178        .get_unmapped_area = mtdchar_get_unmapped_area,
1179        .mmap_capabilities = mtdchar_mmap_capabilities,
1180#endif
1181};
1182
1183int __init init_mtdchar(void)
1184{
1185        int ret;
1186
1187        ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,
1188                                   "mtd", &mtd_fops);
1189        if (ret < 0) {
1190                pr_err("Can't allocate major number %d for MTD\n",
1191                       MTD_CHAR_MAJOR);
1192                return ret;
1193        }
1194
1195        return ret;
1196}
1197
1198void __exit cleanup_mtdchar(void)
1199{
1200        __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1201}
1202
1203MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR);
1204