linux/drivers/mtd/mtdchar.c
<<
>>
Prefs
   1/*
   2 * Copyright \xC2\xA9 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 <asm/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======================================================================*/
 327static void mtdchar_erase_callback (struct erase_info *instr)
 328{
 329        wake_up((wait_queue_head_t *)instr->priv);
 330}
 331
 332static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
 333{
 334        struct mtd_info *mtd = mfi->mtd;
 335        size_t retlen;
 336
 337        switch (mode) {
 338        case MTD_OTP_FACTORY:
 339                if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) ==
 340                                -EOPNOTSUPP)
 341                        return -EOPNOTSUPP;
 342
 343                mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
 344                break;
 345        case MTD_OTP_USER:
 346                if (mtd_read_user_prot_reg(mtd, -1, 0, &retlen, NULL) ==
 347                                -EOPNOTSUPP)
 348                        return -EOPNOTSUPP;
 349
 350                mfi->mode = MTD_FILE_MODE_OTP_USER;
 351                break;
 352        case MTD_OTP_OFF:
 353                mfi->mode = MTD_FILE_MODE_NORMAL;
 354                break;
 355        default:
 356                return -EINVAL;
 357        }
 358
 359        return 0;
 360}
 361
 362static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
 363        uint64_t start, uint32_t length, void __user *ptr,
 364        uint32_t __user *retp)
 365{
 366        struct mtd_file_info *mfi = file->private_data;
 367        struct mtd_oob_ops ops;
 368        uint32_t retlen;
 369        int ret = 0;
 370
 371        if (!(file->f_mode & FMODE_WRITE))
 372                return -EPERM;
 373
 374        if (length > 4096)
 375                return -EINVAL;
 376
 377        if (!mtd->_write_oob)
 378                ret = -EOPNOTSUPP;
 379        else
 380                ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT;
 381
 382        if (ret)
 383                return ret;
 384
 385        ops.ooblen = length;
 386        ops.ooboffs = start & (mtd->writesize - 1);
 387        ops.datbuf = NULL;
 388        ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
 389                MTD_OPS_PLACE_OOB;
 390
 391        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 392                return -EINVAL;
 393
 394        ops.oobbuf = memdup_user(ptr, length);
 395        if (IS_ERR(ops.oobbuf))
 396                return PTR_ERR(ops.oobbuf);
 397
 398        start &= ~((uint64_t)mtd->writesize - 1);
 399        ret = mtd_write_oob(mtd, start, &ops);
 400
 401        if (ops.oobretlen > 0xFFFFFFFFU)
 402                ret = -EOVERFLOW;
 403        retlen = ops.oobretlen;
 404        if (copy_to_user(retp, &retlen, sizeof(length)))
 405                ret = -EFAULT;
 406
 407        kfree(ops.oobbuf);
 408        return ret;
 409}
 410
 411static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
 412        uint64_t start, uint32_t length, void __user *ptr,
 413        uint32_t __user *retp)
 414{
 415        struct mtd_file_info *mfi = file->private_data;
 416        struct mtd_oob_ops ops;
 417        int ret = 0;
 418
 419        if (length > 4096)
 420                return -EINVAL;
 421
 422        if (!access_ok(VERIFY_WRITE, ptr, length))
 423                return -EFAULT;
 424
 425        ops.ooblen = length;
 426        ops.ooboffs = start & (mtd->writesize - 1);
 427        ops.datbuf = NULL;
 428        ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
 429                MTD_OPS_PLACE_OOB;
 430
 431        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 432                return -EINVAL;
 433
 434        ops.oobbuf = kmalloc(length, GFP_KERNEL);
 435        if (!ops.oobbuf)
 436                return -ENOMEM;
 437
 438        start &= ~((uint64_t)mtd->writesize - 1);
 439        ret = mtd_read_oob(mtd, start, &ops);
 440
 441        if (put_user(ops.oobretlen, retp))
 442                ret = -EFAULT;
 443        else if (ops.oobretlen && copy_to_user(ptr, ops.oobbuf,
 444                                            ops.oobretlen))
 445                ret = -EFAULT;
 446
 447        kfree(ops.oobbuf);
 448
 449        /*
 450         * NAND returns -EBADMSG on ECC errors, but it returns the OOB
 451         * data. For our userspace tools it is important to dump areas
 452         * with ECC errors!
 453         * For kernel internal usage it also might return -EUCLEAN
 454         * to signal the caller that a bitflip has occured and has
 455         * been corrected by the ECC algorithm.
 456         *
 457         * Note: currently the standard NAND function, nand_read_oob_std,
 458         * does not calculate ECC for the OOB area, so do not rely on
 459         * this behavior unless you have replaced it with your own.
 460         */
 461        if (mtd_is_bitflip_or_eccerr(ret))
 462                return 0;
 463
 464        return ret;
 465}
 466
 467/*
 468 * Copies (and truncates, if necessary) OOB layout information to the
 469 * deprecated layout struct, nand_ecclayout_user. This is necessary only to
 470 * support the deprecated API ioctl ECCGETLAYOUT while allowing all new
 471 * functionality to use mtd_ooblayout_ops flexibly (i.e. mtd_ooblayout_ops
 472 * can describe any kind of OOB layout with almost zero overhead from a
 473 * memory usage point of view).
 474 */
 475static int shrink_ecclayout(struct mtd_info *mtd,
 476                            struct nand_ecclayout_user *to)
 477{
 478        struct mtd_oob_region oobregion;
 479        int i, section = 0, ret;
 480
 481        if (!mtd || !to)
 482                return -EINVAL;
 483
 484        memset(to, 0, sizeof(*to));
 485
 486        to->eccbytes = 0;
 487        for (i = 0; i < MTD_MAX_ECCPOS_ENTRIES;) {
 488                u32 eccpos;
 489
 490                ret = mtd_ooblayout_ecc(mtd, section, &oobregion);
 491                if (ret < 0) {
 492                        if (ret != -ERANGE)
 493                                return ret;
 494
 495                        break;
 496                }
 497
 498                eccpos = oobregion.offset;
 499                for (; i < MTD_MAX_ECCPOS_ENTRIES &&
 500                       eccpos < oobregion.offset + oobregion.length; i++) {
 501                        to->eccpos[i] = eccpos++;
 502                        to->eccbytes++;
 503                }
 504        }
 505
 506        for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
 507                ret = mtd_ooblayout_free(mtd, i, &oobregion);
 508                if (ret < 0) {
 509                        if (ret != -ERANGE)
 510                                return ret;
 511
 512                        break;
 513                }
 514
 515                to->oobfree[i].offset = oobregion.offset;
 516                to->oobfree[i].length = oobregion.length;
 517                to->oobavail += to->oobfree[i].length;
 518        }
 519
 520        return 0;
 521}
 522
 523static int get_oobinfo(struct mtd_info *mtd, struct nand_oobinfo *to)
 524{
 525        struct mtd_oob_region oobregion;
 526        int i, section = 0, ret;
 527
 528        if (!mtd || !to)
 529                return -EINVAL;
 530
 531        memset(to, 0, sizeof(*to));
 532
 533        to->eccbytes = 0;
 534        for (i = 0; i < ARRAY_SIZE(to->eccpos);) {
 535                u32 eccpos;
 536
 537                ret = mtd_ooblayout_ecc(mtd, section, &oobregion);
 538                if (ret < 0) {
 539                        if (ret != -ERANGE)
 540                                return ret;
 541
 542                        break;
 543                }
 544
 545                if (oobregion.length + i > ARRAY_SIZE(to->eccpos))
 546                        return -EINVAL;
 547
 548                eccpos = oobregion.offset;
 549                for (; eccpos < oobregion.offset + oobregion.length; i++) {
 550                        to->eccpos[i] = eccpos++;
 551                        to->eccbytes++;
 552                }
 553        }
 554
 555        for (i = 0; i < 8; i++) {
 556                ret = mtd_ooblayout_free(mtd, i, &oobregion);
 557                if (ret < 0) {
 558                        if (ret != -ERANGE)
 559                                return ret;
 560
 561                        break;
 562                }
 563
 564                to->oobfree[i][0] = oobregion.offset;
 565                to->oobfree[i][1] = oobregion.length;
 566        }
 567
 568        to->useecc = MTD_NANDECC_AUTOPLACE;
 569
 570        return 0;
 571}
 572
 573static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
 574                               struct blkpg_ioctl_arg *arg)
 575{
 576        struct blkpg_partition p;
 577
 578        if (!capable(CAP_SYS_ADMIN))
 579                return -EPERM;
 580
 581        if (copy_from_user(&p, arg->data, sizeof(p)))
 582                return -EFAULT;
 583
 584        switch (arg->op) {
 585        case BLKPG_ADD_PARTITION:
 586
 587                /* Only master mtd device must be used to add partitions */
 588                if (mtd_is_partition(mtd))
 589                        return -EINVAL;
 590
 591                /* Sanitize user input */
 592                p.devname[BLKPG_DEVNAMELTH - 1] = '\0';
 593
 594                return mtd_add_partition(mtd, p.devname, p.start, p.length);
 595
 596        case BLKPG_DEL_PARTITION:
 597
 598                if (p.pno < 0)
 599                        return -EINVAL;
 600
 601                return mtd_del_partition(mtd, p.pno);
 602
 603        default:
 604                return -EINVAL;
 605        }
 606}
 607
 608static int mtdchar_write_ioctl(struct mtd_info *mtd,
 609                struct mtd_write_req __user *argp)
 610{
 611        struct mtd_write_req req;
 612        struct mtd_oob_ops ops;
 613        const void __user *usr_data, *usr_oob;
 614        int ret;
 615
 616        if (copy_from_user(&req, argp, sizeof(req)))
 617                return -EFAULT;
 618
 619        usr_data = (const void __user *)(uintptr_t)req.usr_data;
 620        usr_oob = (const void __user *)(uintptr_t)req.usr_oob;
 621        if (!access_ok(VERIFY_READ, usr_data, req.len) ||
 622            !access_ok(VERIFY_READ, usr_oob, req.ooblen))
 623                return -EFAULT;
 624
 625        if (!mtd->_write_oob)
 626                return -EOPNOTSUPP;
 627
 628        ops.mode = req.mode;
 629        ops.len = (size_t)req.len;
 630        ops.ooblen = (size_t)req.ooblen;
 631        ops.ooboffs = 0;
 632
 633        if (usr_data) {
 634                ops.datbuf = memdup_user(usr_data, ops.len);
 635                if (IS_ERR(ops.datbuf))
 636                        return PTR_ERR(ops.datbuf);
 637        } else {
 638                ops.datbuf = NULL;
 639        }
 640
 641        if (usr_oob) {
 642                ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
 643                if (IS_ERR(ops.oobbuf)) {
 644                        kfree(ops.datbuf);
 645                        return PTR_ERR(ops.oobbuf);
 646                }
 647        } else {
 648                ops.oobbuf = NULL;
 649        }
 650
 651        ret = mtd_write_oob(mtd, (loff_t)req.start, &ops);
 652
 653        kfree(ops.datbuf);
 654        kfree(ops.oobbuf);
 655
 656        return ret;
 657}
 658
 659static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 660{
 661        struct mtd_file_info *mfi = file->private_data;
 662        struct mtd_info *mtd = mfi->mtd;
 663        void __user *argp = (void __user *)arg;
 664        int ret = 0;
 665        u_long size;
 666        struct mtd_info_user info;
 667
 668        pr_debug("MTD_ioctl\n");
 669
 670        size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 671        if (cmd & IOC_IN) {
 672                if (!access_ok(VERIFY_READ, argp, size))
 673                        return -EFAULT;
 674        }
 675        if (cmd & IOC_OUT) {
 676                if (!access_ok(VERIFY_WRITE, argp, size))
 677                        return -EFAULT;
 678        }
 679
 680        switch (cmd) {
 681        case MEMGETREGIONCOUNT:
 682                if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
 683                        return -EFAULT;
 684                break;
 685
 686        case MEMGETREGIONINFO:
 687        {
 688                uint32_t ur_idx;
 689                struct mtd_erase_region_info *kr;
 690                struct region_info_user __user *ur = argp;
 691
 692                if (get_user(ur_idx, &(ur->regionindex)))
 693                        return -EFAULT;
 694
 695                if (ur_idx >= mtd->numeraseregions)
 696                        return -EINVAL;
 697
 698                kr = &(mtd->eraseregions[ur_idx]);
 699
 700                if (put_user(kr->offset, &(ur->offset))
 701                    || put_user(kr->erasesize, &(ur->erasesize))
 702                    || put_user(kr->numblocks, &(ur->numblocks)))
 703                        return -EFAULT;
 704
 705                break;
 706        }
 707
 708        case MEMGETINFO:
 709                memset(&info, 0, sizeof(info));
 710                info.type       = mtd->type;
 711                info.flags      = mtd->flags;
 712                info.size       = mtd->size;
 713                info.erasesize  = mtd->erasesize;
 714                info.writesize  = mtd->writesize;
 715                info.oobsize    = mtd->oobsize;
 716                /* The below field is obsolete */
 717                info.padding    = 0;
 718                if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 719                        return -EFAULT;
 720                break;
 721
 722        case MEMERASE:
 723        case MEMERASE64:
 724        {
 725                struct erase_info *erase;
 726
 727                if(!(file->f_mode & FMODE_WRITE))
 728                        return -EPERM;
 729
 730                erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
 731                if (!erase)
 732                        ret = -ENOMEM;
 733                else {
 734                        wait_queue_head_t waitq;
 735                        DECLARE_WAITQUEUE(wait, current);
 736
 737                        init_waitqueue_head(&waitq);
 738
 739                        if (cmd == MEMERASE64) {
 740                                struct erase_info_user64 einfo64;
 741
 742                                if (copy_from_user(&einfo64, argp,
 743                                            sizeof(struct erase_info_user64))) {
 744                                        kfree(erase);
 745                                        return -EFAULT;
 746                                }
 747                                erase->addr = einfo64.start;
 748                                erase->len = einfo64.length;
 749                        } else {
 750                                struct erase_info_user einfo32;
 751
 752                                if (copy_from_user(&einfo32, argp,
 753                                            sizeof(struct erase_info_user))) {
 754                                        kfree(erase);
 755                                        return -EFAULT;
 756                                }
 757                                erase->addr = einfo32.start;
 758                                erase->len = einfo32.length;
 759                        }
 760                        erase->mtd = mtd;
 761                        erase->callback = mtdchar_erase_callback;
 762                        erase->priv = (unsigned long)&waitq;
 763
 764                        /*
 765                          FIXME: Allow INTERRUPTIBLE. Which means
 766                          not having the wait_queue head on the stack.
 767
 768                          If the wq_head is on the stack, and we
 769                          leave because we got interrupted, then the
 770                          wq_head is no longer there when the
 771                          callback routine tries to wake us up.
 772                        */
 773                        ret = mtd_erase(mtd, erase);
 774                        if (!ret) {
 775                                set_current_state(TASK_UNINTERRUPTIBLE);
 776                                add_wait_queue(&waitq, &wait);
 777                                if (erase->state != MTD_ERASE_DONE &&
 778                                    erase->state != MTD_ERASE_FAILED)
 779                                        schedule();
 780                                remove_wait_queue(&waitq, &wait);
 781                                set_current_state(TASK_RUNNING);
 782
 783                                ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0;
 784                        }
 785                        kfree(erase);
 786                }
 787                break;
 788        }
 789
 790        case MEMWRITEOOB:
 791        {
 792                struct mtd_oob_buf buf;
 793                struct mtd_oob_buf __user *buf_user = argp;
 794
 795                /* NOTE: writes return length to buf_user->length */
 796                if (copy_from_user(&buf, argp, sizeof(buf)))
 797                        ret = -EFAULT;
 798                else
 799                        ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
 800                                buf.ptr, &buf_user->length);
 801                break;
 802        }
 803
 804        case MEMREADOOB:
 805        {
 806                struct mtd_oob_buf buf;
 807                struct mtd_oob_buf __user *buf_user = argp;
 808
 809                /* NOTE: writes return length to buf_user->start */
 810                if (copy_from_user(&buf, argp, sizeof(buf)))
 811                        ret = -EFAULT;
 812                else
 813                        ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
 814                                buf.ptr, &buf_user->start);
 815                break;
 816        }
 817
 818        case MEMWRITEOOB64:
 819        {
 820                struct mtd_oob_buf64 buf;
 821                struct mtd_oob_buf64 __user *buf_user = argp;
 822
 823                if (copy_from_user(&buf, argp, sizeof(buf)))
 824                        ret = -EFAULT;
 825                else
 826                        ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
 827                                (void __user *)(uintptr_t)buf.usr_ptr,
 828                                &buf_user->length);
 829                break;
 830        }
 831
 832        case MEMREADOOB64:
 833        {
 834                struct mtd_oob_buf64 buf;
 835                struct mtd_oob_buf64 __user *buf_user = argp;
 836
 837                if (copy_from_user(&buf, argp, sizeof(buf)))
 838                        ret = -EFAULT;
 839                else
 840                        ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
 841                                (void __user *)(uintptr_t)buf.usr_ptr,
 842                                &buf_user->length);
 843                break;
 844        }
 845
 846        case MEMWRITE:
 847        {
 848                ret = mtdchar_write_ioctl(mtd,
 849                      (struct mtd_write_req __user *)arg);
 850                break;
 851        }
 852
 853        case MEMLOCK:
 854        {
 855                struct erase_info_user einfo;
 856
 857                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 858                        return -EFAULT;
 859
 860                ret = mtd_lock(mtd, einfo.start, einfo.length);
 861                break;
 862        }
 863
 864        case MEMUNLOCK:
 865        {
 866                struct erase_info_user einfo;
 867
 868                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 869                        return -EFAULT;
 870
 871                ret = mtd_unlock(mtd, einfo.start, einfo.length);
 872                break;
 873        }
 874
 875        case MEMISLOCKED:
 876        {
 877                struct erase_info_user einfo;
 878
 879                if (copy_from_user(&einfo, argp, sizeof(einfo)))
 880                        return -EFAULT;
 881
 882                ret = mtd_is_locked(mtd, einfo.start, einfo.length);
 883                break;
 884        }
 885
 886        /* Legacy interface */
 887        case MEMGETOOBSEL:
 888        {
 889                struct nand_oobinfo oi;
 890
 891                if (!mtd->ooblayout)
 892                        return -EOPNOTSUPP;
 893
 894                ret = get_oobinfo(mtd, &oi);
 895                if (ret)
 896                        return ret;
 897
 898                if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
 899                        return -EFAULT;
 900                break;
 901        }
 902
 903        case MEMGETBADBLOCK:
 904        {
 905                loff_t offs;
 906
 907                if (copy_from_user(&offs, argp, sizeof(loff_t)))
 908                        return -EFAULT;
 909                return mtd_block_isbad(mtd, offs);
 910                break;
 911        }
 912
 913        case MEMSETBADBLOCK:
 914        {
 915                loff_t offs;
 916
 917                if (copy_from_user(&offs, argp, sizeof(loff_t)))
 918                        return -EFAULT;
 919                return mtd_block_markbad(mtd, offs);
 920                break;
 921        }
 922
 923        case OTPSELECT:
 924        {
 925                int mode;
 926                if (copy_from_user(&mode, argp, sizeof(int)))
 927                        return -EFAULT;
 928
 929                mfi->mode = MTD_FILE_MODE_NORMAL;
 930
 931                ret = otp_select_filemode(mfi, mode);
 932
 933                file->f_pos = 0;
 934                break;
 935        }
 936
 937        case OTPGETREGIONCOUNT:
 938        case OTPGETREGIONINFO:
 939        {
 940                struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
 941                size_t retlen;
 942                if (!buf)
 943                        return -ENOMEM;
 944                switch (mfi->mode) {
 945                case MTD_FILE_MODE_OTP_FACTORY:
 946                        ret = mtd_get_fact_prot_info(mtd, 4096, &retlen, buf);
 947                        break;
 948                case MTD_FILE_MODE_OTP_USER:
 949                        ret = mtd_get_user_prot_info(mtd, 4096, &retlen, buf);
 950                        break;
 951                default:
 952                        ret = -EINVAL;
 953                        break;
 954                }
 955                if (!ret) {
 956                        if (cmd == OTPGETREGIONCOUNT) {
 957                                int nbr = retlen / sizeof(struct otp_info);
 958                                ret = copy_to_user(argp, &nbr, sizeof(int));
 959                        } else
 960                                ret = copy_to_user(argp, buf, retlen);
 961                        if (ret)
 962                                ret = -EFAULT;
 963                }
 964                kfree(buf);
 965                break;
 966        }
 967
 968        case OTPLOCK:
 969        {
 970                struct otp_info oinfo;
 971
 972                if (mfi->mode != MTD_FILE_MODE_OTP_USER)
 973                        return -EINVAL;
 974                if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
 975                        return -EFAULT;
 976                ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
 977                break;
 978        }
 979
 980        /* This ioctl is being deprecated - it truncates the ECC layout */
 981        case ECCGETLAYOUT:
 982        {
 983                struct nand_ecclayout_user *usrlay;
 984
 985                if (!mtd->ooblayout)
 986                        return -EOPNOTSUPP;
 987
 988                usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL);
 989                if (!usrlay)
 990                        return -ENOMEM;
 991
 992                shrink_ecclayout(mtd, usrlay);
 993
 994                if (copy_to_user(argp, usrlay, sizeof(*usrlay)))
 995                        ret = -EFAULT;
 996                kfree(usrlay);
 997                break;
 998        }
 999
1000        case ECCGETSTATS:
1001        {
1002                if (copy_to_user(argp, &mtd->ecc_stats,
1003                                 sizeof(struct mtd_ecc_stats)))
1004                        return -EFAULT;
1005                break;
1006        }
1007
1008        case MTDFILEMODE:
1009        {
1010                mfi->mode = 0;
1011
1012                switch(arg) {
1013                case MTD_FILE_MODE_OTP_FACTORY:
1014                case MTD_FILE_MODE_OTP_USER:
1015                        ret = otp_select_filemode(mfi, arg);
1016                        break;
1017
1018                case MTD_FILE_MODE_RAW:
1019                        if (!mtd_has_oob(mtd))
1020                                return -EOPNOTSUPP;
1021                        mfi->mode = arg;
1022
1023                case MTD_FILE_MODE_NORMAL:
1024                        break;
1025                default:
1026                        ret = -EINVAL;
1027                }
1028                file->f_pos = 0;
1029                break;
1030        }
1031
1032        case BLKPG:
1033        {
1034                struct blkpg_ioctl_arg __user *blk_arg = argp;
1035                struct blkpg_ioctl_arg a;
1036
1037                if (copy_from_user(&a, blk_arg, sizeof(a)))
1038                        ret = -EFAULT;
1039                else
1040                        ret = mtdchar_blkpg_ioctl(mtd, &a);
1041                break;
1042        }
1043
1044        case BLKRRPART:
1045        {
1046                /* No reread partition feature. Just return ok */
1047                ret = 0;
1048                break;
1049        }
1050
1051        default:
1052                ret = -ENOTTY;
1053        }
1054
1055        return ret;
1056} /* memory_ioctl */
1057
1058static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
1059{
1060        int ret;
1061
1062        mutex_lock(&mtd_mutex);
1063        ret = mtdchar_ioctl(file, cmd, arg);
1064        mutex_unlock(&mtd_mutex);
1065
1066        return ret;
1067}
1068
1069#ifdef CONFIG_COMPAT
1070
1071struct mtd_oob_buf32 {
1072        u_int32_t start;
1073        u_int32_t length;
1074        compat_caddr_t ptr;     /* unsigned char* */
1075};
1076
1077#define MEMWRITEOOB32           _IOWR('M', 3, struct mtd_oob_buf32)
1078#define MEMREADOOB32            _IOWR('M', 4, struct mtd_oob_buf32)
1079
1080static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
1081        unsigned long arg)
1082{
1083        struct mtd_file_info *mfi = file->private_data;
1084        struct mtd_info *mtd = mfi->mtd;
1085        void __user *argp = compat_ptr(arg);
1086        int ret = 0;
1087
1088        mutex_lock(&mtd_mutex);
1089
1090        switch (cmd) {
1091        case MEMWRITEOOB32:
1092        {
1093                struct mtd_oob_buf32 buf;
1094                struct mtd_oob_buf32 __user *buf_user = argp;
1095
1096                if (copy_from_user(&buf, argp, sizeof(buf)))
1097                        ret = -EFAULT;
1098                else
1099                        ret = mtdchar_writeoob(file, mtd, buf.start,
1100                                buf.length, compat_ptr(buf.ptr),
1101                                &buf_user->length);
1102                break;
1103        }
1104
1105        case MEMREADOOB32:
1106        {
1107                struct mtd_oob_buf32 buf;
1108                struct mtd_oob_buf32 __user *buf_user = argp;
1109
1110                /* NOTE: writes return length to buf->start */
1111                if (copy_from_user(&buf, argp, sizeof(buf)))
1112                        ret = -EFAULT;
1113                else
1114                        ret = mtdchar_readoob(file, mtd, buf.start,
1115                                buf.length, compat_ptr(buf.ptr),
1116                                &buf_user->start);
1117                break;
1118        }
1119
1120        case BLKPG:
1121        {
1122                /* Convert from blkpg_compat_ioctl_arg to blkpg_ioctl_arg */
1123                struct blkpg_compat_ioctl_arg __user *uarg = argp;
1124                struct blkpg_compat_ioctl_arg compat_arg;
1125                struct blkpg_ioctl_arg a;
1126
1127                if (copy_from_user(&compat_arg, uarg, sizeof(compat_arg))) {
1128                        ret = -EFAULT;
1129                        break;
1130                }
1131
1132                memset(&a, 0, sizeof(a));
1133                a.op = compat_arg.op;
1134                a.flags = compat_arg.flags;
1135                a.datalen = compat_arg.datalen;
1136                a.data = compat_ptr(compat_arg.data);
1137
1138                ret = mtdchar_blkpg_ioctl(mtd, &a);
1139                break;
1140        }
1141
1142        default:
1143                ret = mtdchar_ioctl(file, cmd, (unsigned long)argp);
1144        }
1145
1146        mutex_unlock(&mtd_mutex);
1147
1148        return ret;
1149}
1150
1151#endif /* CONFIG_COMPAT */
1152
1153/*
1154 * try to determine where a shared mapping can be made
1155 * - only supported for NOMMU at the moment (MMU can't doesn't copy private
1156 *   mappings)
1157 */
1158#ifndef CONFIG_MMU
1159static unsigned long mtdchar_get_unmapped_area(struct file *file,
1160                                           unsigned long addr,
1161                                           unsigned long len,
1162                                           unsigned long pgoff,
1163                                           unsigned long flags)
1164{
1165        struct mtd_file_info *mfi = file->private_data;
1166        struct mtd_info *mtd = mfi->mtd;
1167        unsigned long offset;
1168        int ret;
1169
1170        if (addr != 0)
1171                return (unsigned long) -EINVAL;
1172
1173        if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
1174                return (unsigned long) -EINVAL;
1175
1176        offset = pgoff << PAGE_SHIFT;
1177        if (offset > mtd->size - len)
1178                return (unsigned long) -EINVAL;
1179
1180        ret = mtd_get_unmapped_area(mtd, len, offset, flags);
1181        return ret == -EOPNOTSUPP ? -ENODEV : ret;
1182}
1183
1184static unsigned mtdchar_mmap_capabilities(struct file *file)
1185{
1186        struct mtd_file_info *mfi = file->private_data;
1187
1188        return mtd_mmap_capabilities(mfi->mtd);
1189}
1190#endif
1191
1192/*
1193 * set up a mapping for shared memory segments
1194 */
1195static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
1196{
1197#ifdef CONFIG_MMU
1198        struct mtd_file_info *mfi = file->private_data;
1199        struct mtd_info *mtd = mfi->mtd;
1200        struct map_info *map = mtd->priv;
1201
1202        /* This is broken because it assumes the MTD device is map-based
1203           and that mtd->priv is a valid struct map_info.  It should be
1204           replaced with something that uses the mtd_get_unmapped_area()
1205           operation properly. */
1206        if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
1207#ifdef pgprot_noncached
1208                if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
1209                        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1210#endif
1211                return vm_iomap_memory(vma, map->phys, map->size);
1212        }
1213        return -ENODEV;
1214#else
1215        return vma->vm_flags & VM_SHARED ? 0 : -EACCES;
1216#endif
1217}
1218
1219static const struct file_operations mtd_fops = {
1220        .owner          = THIS_MODULE,
1221        .llseek         = mtdchar_lseek,
1222        .read           = mtdchar_read,
1223        .write          = mtdchar_write,
1224        .unlocked_ioctl = mtdchar_unlocked_ioctl,
1225#ifdef CONFIG_COMPAT
1226        .compat_ioctl   = mtdchar_compat_ioctl,
1227#endif
1228        .open           = mtdchar_open,
1229        .release        = mtdchar_close,
1230        .mmap           = mtdchar_mmap,
1231#ifndef CONFIG_MMU
1232        .get_unmapped_area = mtdchar_get_unmapped_area,
1233        .mmap_capabilities = mtdchar_mmap_capabilities,
1234#endif
1235};
1236
1237int __init init_mtdchar(void)
1238{
1239        int ret;
1240
1241        ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,
1242                                   "mtd", &mtd_fops);
1243        if (ret < 0) {
1244                pr_err("Can't allocate major number %d for MTD\n",
1245                       MTD_CHAR_MAJOR);
1246                return ret;
1247        }
1248
1249        return ret;
1250}
1251
1252void __exit cleanup_mtdchar(void)
1253{
1254        __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1255}
1256
1257MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR);
1258
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.