1 /* 2 * Character-device access to raw MTD devices. 3 * 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/smp_lock.h> 16 #include <linux/backing-dev.h> 17 #include <linux/compat.h> 18 19 #include <linux/mtd/mtd.h> 20 #include <linux/mtd/compatmac.h> 21 22 #include <asm/uaccess.h> 23 24 25 /* 26 * Data structure to hold the pointer to the mtd device as well 27 * as mode information ofr various use cases. 28 */ 29 struct mtd_file_info { 30 struct mtd_info *mtd; 31 enum mtd_file_modes mode; 32 }; 33 34 static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) 35 { 36 struct mtd_file_info *mfi = file->private_data; 37 struct mtd_info *mtd = mfi->mtd; 38 39 switch (orig) { 40 case SEEK_SET: 41 break; 42 case SEEK_CUR: 43 offset += file->f_pos; 44 break; 45 case SEEK_END: 46 offset += mtd->size; 47 break; 48 default: 49 return -EINVAL; 50 } 51 52 if (offset >= 0 && offset <= mtd->size) 53 return file->f_pos = offset; 54 55 return -EINVAL; 56 } 57 58 59 60 static int mtd_open(struct inode *inode, struct file *file) 61 { 62 int minor = iminor(inode); 63 int devnum = minor >> 1; 64 int ret = 0; 65 struct mtd_info *mtd; 66 struct mtd_file_info *mfi; 67 68 DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n"); 69 70 if (devnum >= MAX_MTD_DEVICES) 71 return -ENODEV; 72 73 /* You can't open the RO devices RW */ 74 if ((file->f_mode & FMODE_WRITE) && (minor & 1)) 75 return -EACCES; 76 77 lock_kernel(); 78 mtd = get_mtd_device(NULL, devnum); 79 80 if (IS_ERR(mtd)) { 81 ret = PTR_ERR(mtd); 82 goto out; 83 } 84 85 if (mtd->type == MTD_ABSENT) { 86 put_mtd_device(mtd); 87 ret = -ENODEV; 88 goto out; 89 } 90 91 if (mtd->backing_dev_info) 92 file->f_mapping->backing_dev_info = mtd->backing_dev_info; 93 94 /* You can't open it RW if it's not a writeable device */ 95 if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { 96 put_mtd_device(mtd); 97 ret = -EACCES; 98 goto out; 99 } 100 101 mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); 102 if (!mfi) { 103 put_mtd_device(mtd); 104 ret = -ENOMEM; 105 goto out; 106 } 107 mfi->mtd = mtd; 108 file->private_data = mfi; 109 110 out: 111 unlock_kernel(); 112 return ret; 113 } /* mtd_open */ 114 115 /*====================================================================*/ 116 117 static int mtd_close(struct inode *inode, struct file *file) 118 { 119 struct mtd_file_info *mfi = file->private_data; 120 struct mtd_info *mtd = mfi->mtd; 121 122 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); 123 124 /* Only sync if opened RW */ 125 if ((file->f_mode & FMODE_WRITE) && mtd->sync) 126 mtd->sync(mtd); 127 128 put_mtd_device(mtd); 129 file->private_data = NULL; 130 kfree(mfi); 131 132 return 0; 133 } /* mtd_close */ 134 135 /* FIXME: This _really_ needs to die. In 2.5, we should lock the 136 userspace buffer down and use it directly with readv/writev. 137 */ 138 #define MAX_KMALLOC_SIZE 0x20000 139 140 static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) 141 { 142 struct mtd_file_info *mfi = file->private_data; 143 struct mtd_info *mtd = mfi->mtd; 144 size_t retlen=0; 145 size_t total_retlen=0; 146 int ret=0; 147 int len; 148 char *kbuf; 149 150 DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); 151 152 if (*ppos + count > mtd->size) 153 count = mtd->size - *ppos; 154 155 if (!count) 156 return 0; 157 158 /* FIXME: Use kiovec in 2.5 to lock down the user's buffers 159 and pass them directly to the MTD functions */ 160 161 if (count > MAX_KMALLOC_SIZE) 162 kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); 163 else 164 kbuf=kmalloc(count, GFP_KERNEL); 165 166 if (!kbuf) 167 return -ENOMEM; 168 169 while (count) { 170 171 if (count > MAX_KMALLOC_SIZE) 172 len = MAX_KMALLOC_SIZE; 173 else 174 len = count; 175 176 switch (mfi->mode) { 177 case MTD_MODE_OTP_FACTORY: 178 ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); 179 break; 180 case MTD_MODE_OTP_USER: 181 ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); 182 break; 183 case MTD_MODE_RAW: 184 { 185 struct mtd_oob_ops ops; 186 187 ops.mode = MTD_OOB_RAW; 188 ops.datbuf = kbuf; 189 ops.oobbuf = NULL; 190 ops.len = len; 191 192 ret = mtd->read_oob(mtd, *ppos, &ops); 193 retlen = ops.retlen; 194 break; 195 } 196 default: 197 ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); 198 } 199 /* Nand returns -EBADMSG on ecc errors, but it returns 200 * the data. For our userspace tools it is important 201 * to dump areas with ecc errors ! 202 * For kernel internal usage it also might return -EUCLEAN 203 * to signal the caller that a bitflip has occured and has 204 * been corrected by the ECC algorithm. 205 * Userspace software which accesses NAND this way 206 * must be aware of the fact that it deals with NAND 207 */ 208 if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) { 209 *ppos += retlen; 210 if (copy_to_user(buf, kbuf, retlen)) { 211 kfree(kbuf); 212 return -EFAULT; 213 } 214 else 215 total_retlen += retlen; 216 217 count -= retlen; 218 buf += retlen; 219 if (retlen == 0) 220 count = 0; 221 } 222 else { 223 kfree(kbuf); 224 return ret; 225 } 226 227 } 228 229 kfree(kbuf); 230 return total_retlen; 231 } /* mtd_read */ 232 233 static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) 234 { 235 struct mtd_file_info *mfi = file->private_data; 236 struct mtd_info *mtd = mfi->mtd; 237 char *kbuf; 238 size_t retlen; 239 size_t total_retlen=0; 240 int ret=0; 241 int len; 242 243 DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); 244 245 if (*ppos == mtd->size) 246 return -ENOSPC; 247 248 if (*ppos + count > mtd->size) 249 count = mtd->size - *ppos; 250 251 if (!count) 252 return 0; 253 254 if (count > MAX_KMALLOC_SIZE) 255 kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); 256 else 257 kbuf=kmalloc(count, GFP_KERNEL); 258 259 if (!kbuf) 260 return -ENOMEM; 261 262 while (count) { 263 264 if (count > MAX_KMALLOC_SIZE) 265 len = MAX_KMALLOC_SIZE; 266 else 267 len = count; 268 269 if (copy_from_user(kbuf, buf, len)) { 270 kfree(kbuf); 271 return -EFAULT; 272 } 273 274 switch (mfi->mode) { 275 case MTD_MODE_OTP_FACTORY: 276 ret = -EROFS; 277 break; 278 case MTD_MODE_OTP_USER: 279 if (!mtd->write_user_prot_reg) { 280 ret = -EOPNOTSUPP; 281 break; 282 } 283 ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); 284 break; 285 286 case MTD_MODE_RAW: 287 { 288 struct mtd_oob_ops ops; 289 290 ops.mode = MTD_OOB_RAW; 291 ops.datbuf = kbuf; 292 ops.oobbuf = NULL; 293 ops.len = len; 294 295 ret = mtd->write_oob(mtd, *ppos, &ops); 296 retlen = ops.retlen; 297 break; 298 } 299 300 default: 301 ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf); 302 } 303 if (!ret) { 304 *ppos += retlen; 305 total_retlen += retlen; 306 count -= retlen; 307 buf += retlen; 308 } 309 else { 310 kfree(kbuf); 311 return ret; 312 } 313 } 314 315 kfree(kbuf); 316 return total_retlen; 317 } /* mtd_write */ 318 319 /*====================================================================== 320 321 IOCTL calls for getting device parameters. 322 323 ======================================================================*/ 324 static void mtdchar_erase_callback (struct erase_info *instr) 325 { 326 wake_up((wait_queue_head_t *)instr->priv); 327 } 328 329 #ifdef CONFIG_HAVE_MTD_OTP 330 static int otp_select_filemode(struct mtd_file_info *mfi, int mode) 331 { 332 struct mtd_info *mtd = mfi->mtd; 333 int ret = 0; 334 335 switch (mode) { 336 case MTD_OTP_FACTORY: 337 if (!mtd->read_fact_prot_reg) 338 ret = -EOPNOTSUPP; 339 else 340 mfi->mode = MTD_MODE_OTP_FACTORY; 341 break; 342 case MTD_OTP_USER: 343 if (!mtd->read_fact_prot_reg) 344 ret = -EOPNOTSUPP; 345 else 346 mfi->mode = MTD_MODE_OTP_USER; 347 break; 348 default: 349 ret = -EINVAL; 350 case MTD_OTP_OFF: 351 break; 352 } 353 return ret; 354 } 355 #else 356 # define otp_select_filemode(f,m) -EOPNOTSUPP 357 #endif 358 359 static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, 360 uint64_t start, uint32_t length, void __user *ptr, 361 uint32_t __user *retp) 362 { 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 ret = -EOPNOTSUPP; 375 else 376 ret = access_ok(VERIFY_READ, ptr, length) ? 0 : EFAULT; 377 378 if (ret) 379 return ret; 380 381 ops.ooblen = length; 382 ops.ooboffs = start & (mtd->oobsize - 1); 383 ops.datbuf = NULL; 384 ops.mode = MTD_OOB_PLACE; 385 386 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) 387 return -EINVAL; 388 389 ops.oobbuf = kmalloc(length, GFP_KERNEL); 390 if (!ops.oobbuf) 391 return -ENOMEM; 392 393 if (copy_from_user(ops.oobbuf, ptr, length)) { 394 kfree(ops.oobbuf); 395 return -EFAULT; 396 } 397 398 start &= ~((uint64_t)mtd->oobsize - 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 411 static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, 412 uint32_t length, void __user *ptr, uint32_t __user *retp) 413 { 414 struct mtd_oob_ops ops; 415 int ret = 0; 416 417 if (length > 4096) 418 return -EINVAL; 419 420 if (!mtd->read_oob) 421 ret = -EOPNOTSUPP; 422 else 423 ret = access_ok(VERIFY_WRITE, ptr, 424 length) ? 0 : -EFAULT; 425 if (ret) 426 return ret; 427 428 ops.ooblen = length; 429 ops.ooboffs = start & (mtd->oobsize - 1); 430 ops.datbuf = NULL; 431 ops.mode = MTD_OOB_PLACE; 432 433 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) 434 return -EINVAL; 435 436 ops.oobbuf = kmalloc(length, GFP_KERNEL); 437 if (!ops.oobbuf) 438 return -ENOMEM; 439 440 start &= ~((uint64_t)mtd->oobsize - 1); 441 ret = mtd->read_oob(mtd, start, &ops); 442 443 if (put_user(ops.oobretlen, retp)) 444 ret = -EFAULT; 445 else if (ops.oobretlen && copy_to_user(ptr, ops.oobbuf, 446 ops.oobretlen)) 447 ret = -EFAULT; 448 449 kfree(ops.oobbuf); 450 return ret; 451 } 452 453 static int mtd_ioctl(struct inode *inode, struct file *file, 454 u_int cmd, u_long arg) 455 { 456 struct mtd_file_info *mfi = file->private_data; 457 struct mtd_info *mtd = mfi->mtd; 458 void __user *argp = (void __user *)arg; 459 int ret = 0; 460 u_long size; 461 struct mtd_info_user info; 462 463 DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n"); 464 465 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; 466 if (cmd & IOC_IN) { 467 if (!access_ok(VERIFY_READ, argp, size)) 468 return -EFAULT; 469 } 470 if (cmd & IOC_OUT) { 471 if (!access_ok(VERIFY_WRITE, argp, size)) 472 return -EFAULT; 473 } 474 475 switch (cmd) { 476 case MEMGETREGIONCOUNT: 477 if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) 478 return -EFAULT; 479 break; 480 481 case MEMGETREGIONINFO: 482 { 483 uint32_t ur_idx; 484 struct mtd_erase_region_info *kr; 485 struct region_info_user *ur = (struct region_info_user *) argp; 486 487 if (get_user(ur_idx, &(ur->regionindex))) 488 return -EFAULT; 489 490 kr = &(mtd->eraseregions[ur_idx]); 491 492 if (put_user(kr->offset, &(ur->offset)) 493 || put_user(kr->erasesize, &(ur->erasesize)) 494 || put_user(kr->numblocks, &(ur->numblocks))) 495 return -EFAULT; 496 497 break; 498 } 499 500 case MEMGETINFO: 501 info.type = mtd->type; 502 info.flags = mtd->flags; 503 info.size = mtd->size; 504 info.erasesize = mtd->erasesize; 505 info.writesize = mtd->writesize; 506 info.oobsize = mtd->oobsize; 507 /* The below fields are obsolete */ 508 info.ecctype = -1; 509 info.eccsize = 0; 510 if (copy_to_user(argp, &info, sizeof(struct mtd_info_user))) 511 return -EFAULT; 512 break; 513 514 case MEMERASE: 515 case MEMERASE64: 516 { 517 struct erase_info *erase; 518 519 if(!(file->f_mode & FMODE_WRITE)) 520 return -EPERM; 521 522 erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL); 523 if (!erase) 524 ret = -ENOMEM; 525 else { 526 wait_queue_head_t waitq; 527 DECLARE_WAITQUEUE(wait, current); 528 529 init_waitqueue_head(&waitq); 530 531 if (cmd == MEMERASE64) { 532 struct erase_info_user64 einfo64; 533 534 if (copy_from_user(&einfo64, argp, 535 sizeof(struct erase_info_user64))) { 536 kfree(erase); 537 return -EFAULT; 538 } 539 erase->addr = einfo64.start; 540 erase->len = einfo64.length; 541 } else { 542 struct erase_info_user einfo32; 543 544 if (copy_from_user(&einfo32, argp, 545 sizeof(struct erase_info_user))) { 546 kfree(erase); 547 return -EFAULT; 548 } 549 erase->addr = einfo32.start; 550 erase->len = einfo32.length; 551 } 552 erase->mtd = mtd; 553 erase->callback = mtdchar_erase_callback; 554 erase->priv = (unsigned long)&waitq; 555 556 /* 557 FIXME: Allow INTERRUPTIBLE. Which means 558 not having the wait_queue head on the stack. 559 560 If the wq_head is on the stack, and we 561 leave because we got interrupted, then the 562 wq_head is no longer there when the 563 callback routine tries to wake us up. 564 */ 565 ret = mtd->erase(mtd, erase); 566 if (!ret) { 567 set_current_state(TASK_UNINTERRUPTIBLE); 568 add_wait_queue(&waitq, &wait); 569 if (erase->state != MTD_ERASE_DONE && 570 erase->state != MTD_ERASE_FAILED) 571 schedule(); 572 remove_wait_queue(&waitq, &wait); 573 set_current_state(TASK_RUNNING); 574 575 ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0; 576 } 577 kfree(erase); 578 } 579 break; 580 } 581 582 case MEMWRITEOOB: 583 { 584 struct mtd_oob_buf buf; 585 struct mtd_oob_buf __user *buf_user = argp; 586 587 /* NOTE: writes return length to buf_user->length */ 588 if (copy_from_user(&buf, argp, sizeof(buf))) 589 ret = -EFAULT; 590 else 591 ret = mtd_do_writeoob(file, mtd, buf.start, buf.length, 592 buf.ptr, &buf_user->length); 593 break; 594 } 595 596 case MEMREADOOB: 597 { 598 struct mtd_oob_buf buf; 599 struct mtd_oob_buf __user *buf_user = argp; 600 601 /* NOTE: writes return length to buf_user->start */ 602 if (copy_from_user(&buf, argp, sizeof(buf))) 603 ret = -EFAULT; 604 else 605 ret = mtd_do_readoob(mtd, buf.start, buf.length, 606 buf.ptr, &buf_user->start); 607 break; 608 } 609 610 case MEMWRITEOOB64: 611 { 612 struct mtd_oob_buf64 buf; 613 struct mtd_oob_buf64 __user *buf_user = argp; 614 615 if (copy_from_user(&buf, argp, sizeof(buf))) 616 ret = -EFAULT; 617 else 618 ret = mtd_do_writeoob(file, mtd, buf.start, buf.length, 619 (void __user *)(uintptr_t)buf.usr_ptr, 620 &buf_user->length); 621 break; 622 } 623 624 case MEMREADOOB64: 625 { 626 struct mtd_oob_buf64 buf; 627 struct mtd_oob_buf64 __user *buf_user = argp; 628 629 if (copy_from_user(&buf, argp, sizeof(buf))) 630 ret = -EFAULT; 631 else 632 ret = mtd_do_readoob(mtd, buf.start, buf.length, 633 (void __user *)(uintptr_t)buf.usr_ptr, 634 &buf_user->length); 635 break; 636 } 637 638 case MEMLOCK: 639 { 640 struct erase_info_user einfo; 641 642 if (copy_from_user(&einfo, argp, sizeof(einfo))) 643 return -EFAULT; 644 645 if (!mtd->lock) 646 ret = -EOPNOTSUPP; 647 else 648 ret = mtd->lock(mtd, einfo.start, einfo.length); 649 break; 650 } 651 652 case MEMUNLOCK: 653 { 654 struct erase_info_user einfo; 655 656 if (copy_from_user(&einfo, argp, sizeof(einfo))) 657 return -EFAULT; 658 659 if (!mtd->unlock) 660 ret = -EOPNOTSUPP; 661 else 662 ret = mtd->unlock(mtd, einfo.start, einfo.length); 663 break; 664 } 665 666 /* Legacy interface */ 667 case MEMGETOOBSEL: 668 { 669 struct nand_oobinfo oi; 670 671 if (!mtd->ecclayout) 672 return -EOPNOTSUPP; 673 if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos)) 674 return -EINVAL; 675 676 oi.useecc = MTD_NANDECC_AUTOPLACE; 677 memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); 678 memcpy(&oi.oobfree, mtd->ecclayout->oobfree, 679 sizeof(oi.oobfree)); 680 oi.eccbytes = mtd->ecclayout->eccbytes; 681 682 if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) 683 return -EFAULT; 684 break; 685 } 686 687 case MEMGETBADBLOCK: 688 { 689 loff_t offs; 690 691 if (copy_from_user(&offs, argp, sizeof(loff_t))) 692 return -EFAULT; 693 if (!mtd->block_isbad) 694 ret = -EOPNOTSUPP; 695 else 696 return mtd->block_isbad(mtd, offs); 697 break; 698 } 699 700 case MEMSETBADBLOCK: 701 { 702 loff_t offs; 703 704 if (copy_from_user(&offs, argp, sizeof(loff_t))) 705 return -EFAULT; 706 if (!mtd->block_markbad) 707 ret = -EOPNOTSUPP; 708 else 709 return mtd->block_markbad(mtd, offs); 710 break; 711 } 712 713 #ifdef CONFIG_HAVE_MTD_OTP 714 case OTPSELECT: 715 { 716 int mode; 717 if (copy_from_user(&mode, argp, sizeof(int))) 718 return -EFAULT; 719 720 mfi->mode = MTD_MODE_NORMAL; 721 722 ret = otp_select_filemode(mfi, mode); 723 724 file->f_pos = 0; 725 break; 726 } 727 728 case OTPGETREGIONCOUNT: 729 case OTPGETREGIONINFO: 730 { 731 struct otp_info *buf = kmalloc(4096, GFP_KERNEL); 732 if (!buf) 733 return -ENOMEM; 734 ret = -EOPNOTSUPP; 735 switch (mfi->mode) { 736 case MTD_MODE_OTP_FACTORY: 737 if (mtd->get_fact_prot_info) 738 ret = mtd->get_fact_prot_info(mtd, buf, 4096); 739 break; 740 case MTD_MODE_OTP_USER: 741 if (mtd->get_user_prot_info) 742 ret = mtd->get_user_prot_info(mtd, buf, 4096); 743 break; 744 default: 745 break; 746 } 747 if (ret >= 0) { 748 if (cmd == OTPGETREGIONCOUNT) { 749 int nbr = ret / sizeof(struct otp_info); 750 ret = copy_to_user(argp, &nbr, sizeof(int)); 751 } else 752 ret = copy_to_user(argp, buf, ret); 753 if (ret) 754 ret = -EFAULT; 755 } 756 kfree(buf); 757 break; 758 } 759 760 case OTPLOCK: 761 { 762 struct otp_info oinfo; 763 764 if (mfi->mode != MTD_MODE_OTP_USER) 765 return -EINVAL; 766 if (copy_from_user(&oinfo, argp, sizeof(oinfo))) 767 return -EFAULT; 768 if (!mtd->lock_user_prot_reg) 769 return -EOPNOTSUPP; 770 ret = mtd->lock_user_prot_reg(mtd, oinfo.start, oinfo.length); 771 break; 772 } 773 #endif 774 775 case ECCGETLAYOUT: 776 { 777 if (!mtd->ecclayout) 778 return -EOPNOTSUPP; 779 780 if (copy_to_user(argp, mtd->ecclayout, 781 sizeof(struct nand_ecclayout))) 782 return -EFAULT; 783 break; 784 } 785 786 case ECCGETSTATS: 787 { 788 if (copy_to_user(argp, &mtd->ecc_stats, 789 sizeof(struct mtd_ecc_stats))) 790 return -EFAULT; 791 break; 792 } 793 794 case MTDFILEMODE: 795 { 796 mfi->mode = 0; 797 798 switch(arg) { 799 case MTD_MODE_OTP_FACTORY: 800 case MTD_MODE_OTP_USER: 801 ret = otp_select_filemode(mfi, arg); 802 break; 803 804 case MTD_MODE_RAW: 805 if (!mtd->read_oob || !mtd->write_oob) 806 return -EOPNOTSUPP; 807 mfi->mode = arg; 808 809 case MTD_MODE_NORMAL: 810 break; 811 default: 812 ret = -EINVAL; 813 } 814 file->f_pos = 0; 815 break; 816 } 817 818 default: 819 ret = -ENOTTY; 820 } 821 822 return ret; 823 } /* memory_ioctl */ 824 825 #ifdef CONFIG_COMPAT 826 827 struct mtd_oob_buf32 { 828 u_int32_t start; 829 u_int32_t length; 830 compat_caddr_t ptr; /* unsigned char* */ 831 }; 832 833 #define MEMWRITEOOB32 _IOWR('M', 3, struct mtd_oob_buf32) 834 #define MEMREADOOB32 _IOWR('M', 4, struct mtd_oob_buf32) 835 836 static long mtd_compat_ioctl(struct file *file, unsigned int cmd, 837 unsigned long arg) 838 { 839 struct inode *inode = file->f_path.dentry->d_inode; 840 struct mtd_file_info *mfi = file->private_data; 841 struct mtd_info *mtd = mfi->mtd; 842 void __user *argp = compat_ptr(arg); 843 int ret = 0; 844 845 lock_kernel(); 846 847 switch (cmd) { 848 case MEMWRITEOOB32: 849 { 850 struct mtd_oob_buf32 buf; 851 struct mtd_oob_buf32 __user *buf_user = argp; 852 853 if (copy_from_user(&buf, argp, sizeof(buf))) 854 ret = -EFAULT; 855 else 856 ret = mtd_do_writeoob(file, mtd, buf.start, 857 buf.length, compat_ptr(buf.ptr), 858 &buf_user->length); 859 break; 860 } 861 862 case MEMREADOOB32: 863 { 864 struct mtd_oob_buf32 buf; 865 struct mtd_oob_buf32 __user *buf_user = argp; 866 867 /* NOTE: writes return length to buf->start */ 868 if (copy_from_user(&buf, argp, sizeof(buf))) 869 ret = -EFAULT; 870 else 871 ret = mtd_do_readoob(mtd, buf.start, 872 buf.length, compat_ptr(buf.ptr), 873 &buf_user->start); 874 break; 875 } 876 default: 877 ret = mtd_ioctl(inode, file, cmd, (unsigned long)argp); 878 } 879 880 unlock_kernel(); 881 882 return ret; 883 } 884 885 #endif /* CONFIG_COMPAT */ 886 887 /* 888 * try to determine where a shared mapping can be made 889 * - only supported for NOMMU at the moment (MMU can't doesn't copy private 890 * mappings) 891 */ 892 #ifndef CONFIG_MMU 893 static unsigned long mtd_get_unmapped_area(struct file *file, 894 unsigned long addr, 895 unsigned long len, 896 unsigned long pgoff, 897 unsigned long flags) 898 { 899 struct mtd_file_info *mfi = file->private_data; 900 struct mtd_info *mtd = mfi->mtd; 901 902 if (mtd->get_unmapped_area) { 903 unsigned long offset; 904 905 if (addr != 0) 906 return (unsigned long) -EINVAL; 907 908 if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT)) 909 return (unsigned long) -EINVAL; 910 911 offset = pgoff << PAGE_SHIFT; 912 if (offset > mtd->size - len) 913 return (unsigned long) -EINVAL; 914 915 return mtd->get_unmapped_area(mtd, len, offset, flags); 916 } 917 918 /* can't map directly */ 919 return (unsigned long) -ENOSYS; 920 } 921 #endif 922 923 /* 924 * set up a mapping for shared memory segments 925 */ 926 static int mtd_mmap(struct file *file, struct vm_area_struct *vma) 927 { 928 #ifdef CONFIG_MMU 929 struct mtd_file_info *mfi = file->private_data; 930 struct mtd_info *mtd = mfi->mtd; 931 932 if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) 933 return 0; 934 return -ENOSYS; 935 #else 936 return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; 937 #endif 938 } 939 940 static const struct file_operations mtd_fops = { 941 .owner = THIS_MODULE, 942 .llseek = mtd_lseek, 943 .read = mtd_read, 944 .write = mtd_write, 945 .ioctl = mtd_ioctl, 946 #ifdef CONFIG_COMPAT 947 .compat_ioctl = mtd_compat_ioctl, 948 #endif 949 .open = mtd_open, 950 .release = mtd_close, 951 .mmap = mtd_mmap, 952 #ifndef CONFIG_MMU 953 .get_unmapped_area = mtd_get_unmapped_area, 954 #endif 955 }; 956 957 static int __init init_mtdchar(void) 958 { 959 int status; 960 961 status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); 962 if (status < 0) { 963 printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", 964 MTD_CHAR_MAJOR); 965 } 966 967 return status; 968 } 969 970 static void __exit cleanup_mtdchar(void) 971 { 972 unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); 973 } 974 975 module_init(init_mtdchar); 976 module_exit(cleanup_mtdchar); 977 978 MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR); 979 980 MODULE_LICENSE("GPL"); 981 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 982 MODULE_DESCRIPTION("Direct character-device access to MTD devices"); 983 MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR); 984