linux/drivers/mtd/mtdchar.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright \xC2\xA9 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 well
  32 * 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 the
 112 *   userspace buffer down and use it directly with readv/writev.
 113 *
 114 * The implementation below, using mtd_kmalloc_up_to, mitigates
 115 * allocation failures when the system is under low-memory situations
 116 * or if memory is highly fragmented at the cost of reducing the
 117 * performance of the requested transfer due to a smaller buffer size.
 118 *
 119 * A more complex but more memory-efficient implementation based on
 120 * get_user_pages and iovecs to cover extents of those pages is a
 121 * longer-term goal, as intimated by dwmw2 above. However, for the
 122 * write case, this requires yet more complex head and tail transfer
 123 * handling when those head and tail offsets and sizes are such that
 124 * 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                else
 145                        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 returns
 184                 * the data. For our userspace tools it is important
 185                 * to dump areas with ECC errors!
 186                 * For kernel internal usage it also might return -EUCLEAN
 187                 * to signal the caller that a bitflip has occurred and has
 188                 * been corrected by the ECC algorithm.
 189                 * Userspace software which accesses NAND this way
 190                 * must be aware of the fact that it deals with NAND
 191                 */
 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                        else
 199                                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 actually
 283                 * 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 OOB
 419         * data. For our userspace tools it is important to dump areas
 420         * with ECC errors!
 421         * For kernel internal usage it also might return -EUCLEAN
 422         * to signal the caller that a bitflip has occurred and has
 423         * 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 on
 427         * 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 the
 437 * deprecated layout struct, nand_ecclayout_user. This is necessary only to
 438 * support the deprecated API ioctl ECCGETLAYOUT while allowing all new
 439 * functionality to use mtd_ooblayout_ops flexibly (i.e. mtd_ooblayout_ops
 440 * can describe any kind of OOB layout with almost zero overhead from a
 441 * 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 int mtdchar_write_ioctl(struct mtd_info *mtd,
 577                struct mtd_write_req __user *argp)
 578{
 579        struct mtd_info *master = mtd_get_master(mtd);
 580        struct mtd_write_req req;
 581        struct mtd_oob_ops ops = {};
 582        const void __user *usr_data, *usr_oob;
 583        int ret;
 584
 585        if (copy_from_user(&req, argp, sizeof(req)))
 586                return -EFAULT;
 587
 588        usr_data = (const void __user *)(uintptr_t)req.usr_data;
 589        usr_oob = (const void __user *)(uintptr_t)req.usr_oob;
 590
 591        if (!master->_write_oob)
 592                return -EOPNOTSUPP;
 593        ops.mode = req.mode;
 594        ops.len = (size_t)req.len;
 595        ops.ooblen = (size_t)req.ooblen;
 596        ops.ooboffs = 0;
 597
 598        if (usr_data) {
 599                ops.datbuf = memdup_user(usr_data, ops.len);
 600                if (IS_ERR(ops.datbuf))
 601                        return PTR_ERR(ops.datbuf);
 602        } else {
 603                ops.datbuf = NULL;
 604        }
 605
 606        if (usr_oob) {
 607                ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
 608                if (IS_ERR(ops.oobbuf)) {
 609                        kfree(ops.datbuf);
 610                        return PTR_ERR(ops.oobbuf);
 611                }
 612        } else {
 613                ops.oobbuf = NULL;
 614        }
 615
 616        ret = mtd_write_oob(mtd, (loff_t)req.start, &ops);
 617
 618        kfree(ops.datbuf);
 619        kfree(ops.oobbuf);
 620
 621        return ret;
 622}
 623
 624static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 625{
 626        struct mtd_file_info *mfi = file->private_data;
 627        struct mtd_info *mtd = mfi->mtd;
 628        struct mtd_info *master = mtd_get_master(mtd);
 629        void __user *argp = (void __user *)arg;
 630        int ret = 0;
 631        struct mtd_info_user info;
 632
 633        pr_debug("MTD_ioctl\n");
 634
 635        /*
 636         * Check the file mode to require "dangerous" commands to have write
 637         * permissions.
 638         */
 639        switch (cmd) {
 640        /* "safe" commands */
 641        case MEMGETREGIONCOUNT:
 642        case MEMGETREGIONINFO:
 643        case MEMGETINFO:
 644        case MEMREADOOB:
 645        case MEMREADOOB64:
 646        case MEMISLOCKED:
 647        case MEMGETOOBSEL:
 648        case MEMGETBADBLOCK:
 649        case OTPSELECT:
 650        case OTPGETREGIONCOUNT:
 651        case OTPGETREGIONINFO:
 652        case ECCGETLAYOUT:
 653        case ECCGETSTATS:
 654        case MTDFILEMODE:
 655        case BLKPG:
 656        case BLKRRPART:
 657                break;
 658
 659        /* "dangerous" commands */
 660        case MEMERASE:
 661        case MEMERASE64:
 662        case MEMLOCK:
 663        case MEMUNLOCK:
 664        case MEMSETBADBLOCK:
 665        case MEMWRITEOOB:
 666        case MEMWRITEOOB64:
 667        case MEMWRITE:
 668        case OTPLOCK:
 669        case OTPERASE:
 670                if (!(file->f_mode & FMODE_WRITE))
 671                        return -EPERM;
 672                break;
 673
 674        default:
 675                return -ENOTTY;
 676        }
 677
 678        switch (cmd) {
 679        case MEMGETREGIONCOUNT:
 680                if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
 681                        return -EFAULT;
 682                break;
 683
 684        case MEMGETREGIONINFO:
 685        {
 686                uint32_t ur_idx;
 687                struct mtd_erase_region_info *kr;
 688                struct region_info_user __user *ur = argp;
 689
 690                if (get_user(ur_idx, &(ur->regionindex)))
 691                        return -EFAULT;
 692
 693                if (ur_idx >= mtd->numeraseregions)
 694                        return -EINVAL;
 695
 696                kr = &(mtd->eraseregions[ur_idx]);
 697
 698                if (put_user(kr->offset, &(ur->offset))
 699                    || put_user(kr->erasesize, &(ur->erasesize))
 700                    || put_user(kr->numblocks, &(ur->numblocks)))
 701                        return -EFAULT;
 702
 703                break;
 704        }
 705
 706        case MEMGETINFO:
 707                memset(&info, 0, sizeof(info));
 708                info.type       = mtd->type;
 709                info.flags      = mtd->flags;
 710                info.size       = mtd->size;
 711                info.erasesize  = mtd->erasesize;
 712                info.writesize  = mtd->writesize;
 713                info.oobsize    = mtd->oobsize;
 714                /* The below field is obsolete */
 715                info.padding    = 0;
 716                if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 717                        return -EFAULT;
 718                break;
 719
 720        case MEMERASE:
 721        case MEMERASE64:
 722        {
 723                struct erase_info *erase;
 724
 725                erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
 726                if (!erase)
 727                        ret = -ENOMEM;
 728                else {
 729                        if (cmd == MEMERASE64) {
 730                                struct erase_info_user64 einfo64;
 731
 732                                if (copy_from_user(&einfo64, argp,
 733                                            sizeof(struct erase_info_user64))) {
 734                                        kfree(erase);
 735                                        return -EFAULT;
 736                                }
 737                                erase->addr = einfo64.start;
 738                                erase->len = einfo64.length;
 739                        } else {
 740                                struct erase_info_user einfo32;
 741
 742                                if (copy_from_user(&einfo32, argp,
 743                                            sizeof(struct erase_info_user))) {
 744                                        kfree(erase);
 745                                        return -EFAULT;
 746                                }
 747                                erase->addr = einfo32.start;
 748                                erase->len = einfo32.length;
 749                        }
 750
 751                        ret = mtd_erase(mtd, erase);
 752                        kfree(erase);
 753                }
 754                break;
 755        }
 756
 757        case MEMWRITEOOB:
 758        {
 759                struct mtd_oob_buf buf;
 760                struct mtd_oob_buf __user *buf_user = argp;
 761
 762                /* NOTE: writes return length to buf_user->length */
 763                if (copy_from_user(&buf, argp, sizeof(buf)))
 764                        ret = -EFAULT;
 765                else
 766                        ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
 767                                buf.ptr, &buf_user->length);
 768                break;
 769        }
 770
 771        case MEMREADOOB:
 772        {
 773                struct mtd_oob_buf buf;
 774                struct mtd_oob_buf __user *buf_user = argp;
 775
 776                /* NOTE: writes return length to buf_user->start */
 777                if (copy_from_user(&buf, argp, sizeof(buf)))
 778                        ret = -EFAULT;
 779                else
 780                        ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
 781                                buf.ptr, &buf_user->start);
 782                break;
 783        }
 784
 785        case MEMWRITEOOB64:
 786        {
 787                struct mtd_oob_buf64 buf;
 788                struct mtd_oob_buf64 __user *buf_user = argp;
 789
 790                if (copy_from_user(&buf, argp, sizeof(buf)))
 791                        ret = -EFAULT;
 792                else
 793                        ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
 794                                (void __user *)(uintptr_t)buf.usr_ptr,
 795                                &buf_user->length);
 796                break;
 797        }
 798
 799        case MEMREADOOB64:
 800        {
 801                struct mtd_oob_buf64 buf;
 802                struct mtd_oob_buf64 __user *buf_user = argp;
 803
 804                if (copy_from_user(&buf, argp, sizeof(buf)))
 805                        ret = -EFAULT;
 806                else
 807                        ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
 808                                (void __user *)(uintptr_t)buf.usr_ptr,
 809                                &buf_user->length);
 810                break;
 811        }
 812
 813        case MEMWRITE:
 814        {
 815                ret = mtdchar_write_ioctl(mtd,
 816                      (struct mtd_write_req __user *)arg);
 817                break;
 818        }
 819
 820        case MEMLOCK:
 821        {
 822                struct erase_info_user einfo;
 823
 824                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 825                        return -EFAULT;
 826
 827                ret = mtd_lock(mtd, einfo.start, einfo.length);
 828                break;
 829        }
 830
 831        case MEMUNLOCK:
 832        {
 833                struct erase_info_user einfo;
 834
 835                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 836                        return -EFAULT;
 837
 838                ret = mtd_unlock(mtd, einfo.start, einfo.length);
 839                break;
 840        }
 841
 842        case MEMISLOCKED:
 843        {
 844                struct erase_info_user einfo;
 845
 846                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 847                        return -EFAULT;
 848
 849                ret = mtd_is_locked(mtd, einfo.start, einfo.length);
 850                break;
 851        }
 852
 853        /* Legacy interface */
 854        case MEMGETOOBSEL:
 855        {
 856                struct nand_oobinfo oi;
 857
 858                if (!master->ooblayout)
 859                        return -EOPNOTSUPP;
 860
 861                ret = get_oobinfo(mtd, &oi);
 862                if (ret)
 863                        return ret;
 864
 865                if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
 866                        return -EFAULT;
 867                break;
 868        }
 869
 870        case MEMGETBADBLOCK:
 871        {
 872                loff_t offs;
 873
 874                if (copy_from_user(&offs, argp, sizeof(loff_t)))
 875                        return -EFAULT;
 876                return mtd_block_isbad(mtd, offs);
 877        }
 878
 879        case MEMSETBADBLOCK:
 880        {
 881                loff_t offs;
 882
 883                if (copy_from_user(&offs, argp, sizeof(loff_t)))
 884                        return -EFAULT;
 885                return mtd_block_markbad(mtd, offs);
 886        }
 887
 888        case OTPSELECT:
 889        {
 890                int mode;
 891                if (copy_from_user(&mode, argp, sizeof(int)))
 892                        return -EFAULT;
 893
 894                mfi->mode = MTD_FILE_MODE_NORMAL;
 895
 896                ret = otp_select_filemode(mfi, mode);
 897
 898                file->f_pos = 0;
 899                break;
 900        }
 901
 902        case OTPGETREGIONCOUNT:
 903        case OTPGETREGIONINFO:
 904        {
 905                struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
 906                size_t retlen;
 907                if (!buf)
 908                        return -ENOMEM;
 909                switch (mfi->mode) {
 910                case MTD_FILE_MODE_OTP_FACTORY:
 911                        ret = mtd_get_fact_prot_info(mtd, 4096, &retlen, buf);
 912                        break;
 913                case MTD_FILE_MODE_OTP_USER:
 914                        ret = mtd_get_user_prot_info(mtd, 4096, &retlen, buf);
 915                        break;
 916                default:
 917                        ret = -EINVAL;
 918                        break;
 919                }
 920                if (!ret) {
 921                        if (cmd == OTPGETREGIONCOUNT) {
 922                                int nbr = retlen / sizeof(struct otp_info);
 923                                ret = copy_to_user(argp, &nbr, sizeof(int));
 924                        } else
 925                                ret = copy_to_user(argp, buf, retlen);
 926                        if (ret)
 927                                ret = -EFAULT;
 928                }
 929                kfree(buf);
 930                break;
 931        }
 932
 933        case OTPLOCK:
 934        case OTPERASE:
 935        {
 936                struct otp_info oinfo;
 937
 938                if (mfi->mode != MTD_FILE_MODE_OTP_USER)
 939                        return -EINVAL;
 940                if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
 941                        return -EFAULT;
 942                if (cmd == OTPLOCK)
 943                        ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
 944                else
 945                        ret = mtd_erase_user_prot_reg(mtd, oinfo.start, oinfo.length);
 946                break;
 947        }
 948
 949        /* This ioctl is being deprecated - it truncates the ECC layout */
 950        case ECCGETLAYOUT:
 951        {
 952                struct nand_ecclayout_user *usrlay;
 953
 954                if (!master->ooblayout)
 955                        return -EOPNOTSUPP;
 956
 957                usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL);
 958                if (!usrlay)
 959                        return -ENOMEM;
 960
 961                shrink_ecclayout(mtd, usrlay);
 962
 963                if (copy_to_user(argp, usrlay, sizeof(*usrlay)))
 964                        ret = -EFAULT;
 965                kfree(usrlay);
 966                break;
 967        }
 968
 969        case ECCGETSTATS:
 970        {
 971                if (copy_to_user(argp, &mtd->ecc_stats,
 972                                 sizeof(struct mtd_ecc_stats)))
 973                        return -EFAULT;
 974                break;
 975        }
 976
 977        case MTDFILEMODE:
 978        {
 979                mfi->mode = 0;
 980
 981                switch(arg) {
 982                case MTD_FILE_MODE_OTP_FACTORY:
 983                case MTD_FILE_MODE_OTP_USER:
 984                        ret = otp_select_filemode(mfi, arg);
 985                        break;
 986
 987                case MTD_FILE_MODE_RAW:
 988                        if (!mtd_has_oob(mtd))
 989                                return -EOPNOTSUPP;
 990                        mfi->mode = arg;
 991                        break;
 992
 993                case MTD_FILE_MODE_NORMAL:
 994                        break;
 995                default:
 996                        ret = -EINVAL;
 997                }
 998                file->f_pos = 0;
 999                break;
1000        }
1001
1002        case BLKPG:
1003        {
1004                struct blkpg_ioctl_arg __user *blk_arg = argp;
1005                struct blkpg_ioctl_arg a;
1006
1007                if (copy_from_user(&a, blk_arg, sizeof(a)))
1008                        ret = -EFAULT;
1009                else
1010                        ret = mtdchar_blkpg_ioctl(mtd, &a);
1011                break;
1012        }
1013
1014        case BLKRRPART:
1015        {
1016                /* No reread partition feature. Just return ok */
1017                ret = 0;
1018                break;
1019        }
1020        }
1021
1022        return ret;
1023} /* memory_ioctl */
1024
1025static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
1026{
1027        struct mtd_file_info *mfi = file->private_data;
1028        struct mtd_info *mtd = mfi->mtd;
1029        struct mtd_info *master = mtd_get_master(mtd);
1030        int ret;
1031
1032        mutex_lock(&master->master.chrdev_lock);
1033        ret = mtdchar_ioctl(file, cmd, arg);
1034        mutex_unlock(&master->master.chrdev_lock);
1035
1036        return ret;
1037}
1038
1039#ifdef CONFIG_COMPAT
1040
1041struct mtd_oob_buf32 {
1042        u_int32_t start;
1043        u_int32_t length;
1044        compat_caddr_t ptr;     /* unsigned char* */
1045};
1046
1047#define MEMWRITEOOB32           _IOWR('M', 3, struct mtd_oob_buf32)
1048#define MEMREADOOB32            _IOWR('M', 4, struct mtd_oob_buf32)
1049
1050static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
1051        unsigned long arg)
1052{
1053        struct mtd_file_info *mfi = file->private_data;
1054        struct mtd_info *mtd = mfi->mtd;
1055        struct mtd_info *master = mtd_get_master(mtd);
1056        void __user *argp = compat_ptr(arg);
1057        int ret = 0;
1058
1059        mutex_lock(&master->master.chrdev_lock);
1060
1061        switch (cmd) {
1062        case MEMWRITEOOB32:
1063        {
1064                struct mtd_oob_buf32 buf;
1065                struct mtd_oob_buf32 __user *buf_user = argp;
1066
1067                if (!(file->f_mode & FMODE_WRITE)) {
1068                        ret = -EPERM;
1069                        break;
1070                }
1071
1072                if (copy_from_user(&buf, argp, sizeof(buf)))
1073                        ret = -EFAULT;
1074                else
1075                        ret = mtdchar_writeoob(file, mtd, buf.start,
1076                                buf.length, compat_ptr(buf.ptr),
1077                                &buf_user->length);
1078                break;
1079        }
1080
1081        case MEMREADOOB32:
1082        {
1083                struct mtd_oob_buf32 buf;
1084                struct mtd_oob_buf32 __user *buf_user = argp;
1085
1086                /* NOTE: writes return length to buf->start */
1087                if (copy_from_user(&buf, argp, sizeof(buf)))
1088                        ret = -EFAULT;
1089                else
1090                        ret = mtdchar_readoob(file, mtd, buf.start,
1091                                buf.length, compat_ptr(buf.ptr),
1092                                &buf_user->start);
1093                break;
1094        }
1095
1096        case BLKPG:
1097        {
1098                /* Convert from blkpg_compat_ioctl_arg to blkpg_ioctl_arg */
1099                struct blkpg_compat_ioctl_arg __user *uarg = argp;
1100                struct blkpg_compat_ioctl_arg compat_arg;
1101                struct blkpg_ioctl_arg a;
1102
1103                if (copy_from_user(&compat_arg, uarg, sizeof(compat_arg))) {
1104                        ret = -EFAULT;
1105                        break;
1106                }
1107
1108                memset(&a, 0, sizeof(a));
1109                a.op = compat_arg.op;
1110                a.flags = compat_arg.flags;
1111                a.datalen = compat_arg.datalen;
1112                a.data = compat_ptr(compat_arg.data);
1113
1114                ret = mtdchar_blkpg_ioctl(mtd, &a);
1115                break;
1116        }
1117
1118        default:
1119                ret = mtdchar_ioctl(file, cmd, (unsigned long)argp);
1120        }
1121
1122        mutex_unlock(&master->master.chrdev_lock);
1123
1124        return ret;
1125}
1126
1127#endif /* CONFIG_COMPAT */
1128
1129/*
1130 * try to determine where a shared mapping can be made
1131 * - only supported for NOMMU at the moment (MMU can't doesn't copy private
1132 *   mappings)
1133 */
1134#ifndef CONFIG_MMU
1135static unsigned long mtdchar_get_unmapped_area(struct file *file,
1136                                           unsigned long addr,
1137                                           unsigned long len,
1138                                           unsigned long pgoff,
1139                                           unsigned long flags)
1140{
1141        struct mtd_file_info *mfi = file->private_data;
1142        struct mtd_info *mtd = mfi->mtd;
1143        unsigned long offset;
1144        int ret;
1145
1146        if (addr != 0)
1147                return (unsigned long) -EINVAL;
1148
1149        if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
1150                return (unsigned long) -EINVAL;
1151
1152        offset = pgoff << PAGE_SHIFT;
1153        if (offset > mtd->size - len)
1154                return (unsigned long) -EINVAL;
1155
1156        ret = mtd_get_unmapped_area(mtd, len, offset, flags);
1157        return ret == -EOPNOTSUPP ? -ENODEV : ret;
1158}
1159
1160static unsigned mtdchar_mmap_capabilities(struct file *file)
1161{
1162        struct mtd_file_info *mfi = file->private_data;
1163
1164        return mtd_mmap_capabilities(mfi->mtd);
1165}
1166#endif
1167
1168/*
1169 * set up a mapping for shared memory segments
1170 */
1171static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
1172{
1173#ifdef CONFIG_MMU
1174        struct mtd_file_info *mfi = file->private_data;
1175        struct mtd_info *mtd = mfi->mtd;
1176        struct map_info *map = mtd->priv;
1177
1178        /* This is broken because it assumes the MTD device is map-based
1179           and that mtd->priv is a valid struct map_info.  It should be
1180           replaced with something that uses the mtd_get_unmapped_area()
1181           operation properly. */
1182        if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
1183#ifdef pgprot_noncached
1184                if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
1185                        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1186#endif
1187                return vm_iomap_memory(vma, map->phys, map->size);
1188        }
1189        return -ENODEV;
1190#else
1191        return vma->vm_flags & VM_SHARED ? 0 : -EACCES;
1192#endif
1193}
1194
1195static const struct file_operations mtd_fops = {
1196        .owner          = THIS_MODULE,
1197        .llseek         = mtdchar_lseek,
1198        .read           = mtdchar_read,
1199        .write          = mtdchar_write,
1200        .unlocked_ioctl = mtdchar_unlocked_ioctl,
1201#ifdef CONFIG_COMPAT
1202        .compat_ioctl   = mtdchar_compat_ioctl,
1203#endif
1204        .open           = mtdchar_open,
1205        .release        = mtdchar_close,
1206        .mmap           = mtdchar_mmap,
1207#ifndef CONFIG_MMU
1208        .get_unmapped_area = mtdchar_get_unmapped_area,
1209        .mmap_capabilities = mtdchar_mmap_capabilities,
1210#endif
1211};
1212
1213int __init init_mtdchar(void)
1214{
1215        int ret;
1216
1217        ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,
1218                                   "mtd", &mtd_fops);
1219        if (ret < 0) {
1220                pr_err("Can't allocate major number %d for MTD\n",
1221                       MTD_CHAR_MAJOR);
1222                return ret;
1223        }
1224
1225        return ret;
1226}
1227
1228void __exit cleanup_mtdchar(void)
1229{
1230        __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1231}
1232
1233MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR);
1234