root/drivers/mtd/mtdpart.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mtd_to_part
  2. part_absolute_offset
  3. part_read
  4. part_point
  5. part_unpoint
  6. part_read_oob
  7. part_read_user_prot_reg
  8. part_get_user_prot_info
  9. part_read_fact_prot_reg
  10. part_get_fact_prot_info
  11. part_write
  12. part_panic_write
  13. part_write_oob
  14. part_write_user_prot_reg
  15. part_lock_user_prot_reg
  16. part_writev
  17. part_erase
  18. part_lock
  19. part_unlock
  20. part_is_locked
  21. part_sync
  22. part_suspend
  23. part_resume
  24. part_block_isreserved
  25. part_block_isbad
  26. part_block_markbad
  27. part_get_device
  28. part_put_device
  29. part_ooblayout_ecc
  30. part_ooblayout_free
  31. part_max_bad_blocks
  32. free_partition
  33. allocate_partition
  34. mtd_partition_offset_show
  35. mtd_add_partition_attrs
  36. mtd_add_partition
  37. __mtd_del_partition
  38. del_mtd_partitions
  39. mtd_del_partition
  40. add_mtd_partitions
  41. mtd_part_parser_get
  42. mtd_part_parser_put
  43. mtd_part_parser_cleanup_default
  44. __register_mtd_parser
  45. deregister_mtd_parser
  46. mtd_part_do_parse
  47. mtd_part_get_compatible_parser
  48. mtd_part_of_parse
  49. parse_mtd_partitions
  50. mtd_part_parser_cleanup
  51. mtd_is_partition
  52. mtd_get_device_size

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Simple MTD partitioning layer
   4  *
   5  * Copyright © 2000 Nicolas Pitre <nico@fluxnic.net>
   6  * Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de>
   7  * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/types.h>
  12 #include <linux/kernel.h>
  13 #include <linux/slab.h>
  14 #include <linux/list.h>
  15 #include <linux/kmod.h>
  16 #include <linux/mtd/mtd.h>
  17 #include <linux/mtd/partitions.h>
  18 #include <linux/err.h>
  19 #include <linux/of.h>
  20 
  21 #include "mtdcore.h"
  22 
  23 /* Our partition linked list */
  24 static LIST_HEAD(mtd_partitions);
  25 static DEFINE_MUTEX(mtd_partitions_mutex);
  26 
  27 /**
  28  * struct mtd_part - our partition node structure
  29  *
  30  * @mtd: struct holding partition details
  31  * @parent: parent mtd - flash device or another partition
  32  * @offset: partition offset relative to the *flash device*
  33  */
  34 struct mtd_part {
  35         struct mtd_info mtd;
  36         struct mtd_info *parent;
  37         uint64_t offset;
  38         struct list_head list;
  39 };
  40 
  41 /*
  42  * Given a pointer to the MTD object in the mtd_part structure, we can retrieve
  43  * the pointer to that structure.
  44  */
  45 static inline struct mtd_part *mtd_to_part(const struct mtd_info *mtd)
  46 {
  47         return container_of(mtd, struct mtd_part, mtd);
  48 }
  49 
  50 static u64 part_absolute_offset(struct mtd_info *mtd)
  51 {
  52         struct mtd_part *part = mtd_to_part(mtd);
  53 
  54         if (!mtd_is_partition(mtd))
  55                 return 0;
  56 
  57         return part_absolute_offset(part->parent) + part->offset;
  58 }
  59 
  60 /*
  61  * MTD methods which simply translate the effective address and pass through
  62  * to the _real_ device.
  63  */
  64 
  65 static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
  66                 size_t *retlen, u_char *buf)
  67 {
  68         struct mtd_part *part = mtd_to_part(mtd);
  69         struct mtd_ecc_stats stats;
  70         int res;
  71 
  72         stats = part->parent->ecc_stats;
  73         res = part->parent->_read(part->parent, from + part->offset, len,
  74                                   retlen, buf);
  75         if (unlikely(mtd_is_eccerr(res)))
  76                 mtd->ecc_stats.failed +=
  77                         part->parent->ecc_stats.failed - stats.failed;
  78         else
  79                 mtd->ecc_stats.corrected +=
  80                         part->parent->ecc_stats.corrected - stats.corrected;
  81         return res;
  82 }
  83 
  84 static int part_point(struct mtd_info *mtd, loff_t from, size_t len,
  85                 size_t *retlen, void **virt, resource_size_t *phys)
  86 {
  87         struct mtd_part *part = mtd_to_part(mtd);
  88 
  89         return part->parent->_point(part->parent, from + part->offset, len,
  90                                     retlen, virt, phys);
  91 }
  92 
  93 static int part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
  94 {
  95         struct mtd_part *part = mtd_to_part(mtd);
  96 
  97         return part->parent->_unpoint(part->parent, from + part->offset, len);
  98 }
  99 
 100 static int part_read_oob(struct mtd_info *mtd, loff_t from,
 101                 struct mtd_oob_ops *ops)
 102 {
 103         struct mtd_part *part = mtd_to_part(mtd);
 104         struct mtd_ecc_stats stats;
 105         int res;
 106 
 107         stats = part->parent->ecc_stats;
 108         res = part->parent->_read_oob(part->parent, from + part->offset, ops);
 109         if (unlikely(mtd_is_eccerr(res)))
 110                 mtd->ecc_stats.failed +=
 111                         part->parent->ecc_stats.failed - stats.failed;
 112         else
 113                 mtd->ecc_stats.corrected +=
 114                         part->parent->ecc_stats.corrected - stats.corrected;
 115         return res;
 116 }
 117 
 118 static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
 119                 size_t len, size_t *retlen, u_char *buf)
 120 {
 121         struct mtd_part *part = mtd_to_part(mtd);
 122         return part->parent->_read_user_prot_reg(part->parent, from, len,
 123                                                  retlen, buf);
 124 }
 125 
 126 static int part_get_user_prot_info(struct mtd_info *mtd, size_t len,
 127                                    size_t *retlen, struct otp_info *buf)
 128 {
 129         struct mtd_part *part = mtd_to_part(mtd);
 130         return part->parent->_get_user_prot_info(part->parent, len, retlen,
 131                                                  buf);
 132 }
 133 
 134 static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
 135                 size_t len, size_t *retlen, u_char *buf)
 136 {
 137         struct mtd_part *part = mtd_to_part(mtd);
 138         return part->parent->_read_fact_prot_reg(part->parent, from, len,
 139                                                  retlen, buf);
 140 }
 141 
 142 static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len,
 143                                    size_t *retlen, struct otp_info *buf)
 144 {
 145         struct mtd_part *part = mtd_to_part(mtd);
 146         return part->parent->_get_fact_prot_info(part->parent, len, retlen,
 147                                                  buf);
 148 }
 149 
 150 static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
 151                 size_t *retlen, const u_char *buf)
 152 {
 153         struct mtd_part *part = mtd_to_part(mtd);
 154         return part->parent->_write(part->parent, to + part->offset, len,
 155                                     retlen, buf);
 156 }
 157 
 158 static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
 159                 size_t *retlen, const u_char *buf)
 160 {
 161         struct mtd_part *part = mtd_to_part(mtd);
 162         return part->parent->_panic_write(part->parent, to + part->offset, len,
 163                                           retlen, buf);
 164 }
 165 
 166 static int part_write_oob(struct mtd_info *mtd, loff_t to,
 167                 struct mtd_oob_ops *ops)
 168 {
 169         struct mtd_part *part = mtd_to_part(mtd);
 170 
 171         return part->parent->_write_oob(part->parent, to + part->offset, ops);
 172 }
 173 
 174 static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
 175                 size_t len, size_t *retlen, u_char *buf)
 176 {
 177         struct mtd_part *part = mtd_to_part(mtd);
 178         return part->parent->_write_user_prot_reg(part->parent, from, len,
 179                                                   retlen, buf);
 180 }
 181 
 182 static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
 183                 size_t len)
 184 {
 185         struct mtd_part *part = mtd_to_part(mtd);
 186         return part->parent->_lock_user_prot_reg(part->parent, from, len);
 187 }
 188 
 189 static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
 190                 unsigned long count, loff_t to, size_t *retlen)
 191 {
 192         struct mtd_part *part = mtd_to_part(mtd);
 193         return part->parent->_writev(part->parent, vecs, count,
 194                                      to + part->offset, retlen);
 195 }
 196 
 197 static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
 198 {
 199         struct mtd_part *part = mtd_to_part(mtd);
 200         int ret;
 201 
 202         instr->addr += part->offset;
 203         ret = part->parent->_erase(part->parent, instr);
 204         if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
 205                 instr->fail_addr -= part->offset;
 206         instr->addr -= part->offset;
 207 
 208         return ret;
 209 }
 210 
 211 static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 212 {
 213         struct mtd_part *part = mtd_to_part(mtd);
 214         return part->parent->_lock(part->parent, ofs + part->offset, len);
 215 }
 216 
 217 static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 218 {
 219         struct mtd_part *part = mtd_to_part(mtd);
 220         return part->parent->_unlock(part->parent, ofs + part->offset, len);
 221 }
 222 
 223 static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 224 {
 225         struct mtd_part *part = mtd_to_part(mtd);
 226         return part->parent->_is_locked(part->parent, ofs + part->offset, len);
 227 }
 228 
 229 static void part_sync(struct mtd_info *mtd)
 230 {
 231         struct mtd_part *part = mtd_to_part(mtd);
 232         part->parent->_sync(part->parent);
 233 }
 234 
 235 static int part_suspend(struct mtd_info *mtd)
 236 {
 237         struct mtd_part *part = mtd_to_part(mtd);
 238         return part->parent->_suspend(part->parent);
 239 }
 240 
 241 static void part_resume(struct mtd_info *mtd)
 242 {
 243         struct mtd_part *part = mtd_to_part(mtd);
 244         part->parent->_resume(part->parent);
 245 }
 246 
 247 static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 248 {
 249         struct mtd_part *part = mtd_to_part(mtd);
 250         ofs += part->offset;
 251         return part->parent->_block_isreserved(part->parent, ofs);
 252 }
 253 
 254 static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
 255 {
 256         struct mtd_part *part = mtd_to_part(mtd);
 257         ofs += part->offset;
 258         return part->parent->_block_isbad(part->parent, ofs);
 259 }
 260 
 261 static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
 262 {
 263         struct mtd_part *part = mtd_to_part(mtd);
 264         int res;
 265 
 266         ofs += part->offset;
 267         res = part->parent->_block_markbad(part->parent, ofs);
 268         if (!res)
 269                 mtd->ecc_stats.badblocks++;
 270         return res;
 271 }
 272 
 273 static int part_get_device(struct mtd_info *mtd)
 274 {
 275         struct mtd_part *part = mtd_to_part(mtd);
 276         return part->parent->_get_device(part->parent);
 277 }
 278 
 279 static void part_put_device(struct mtd_info *mtd)
 280 {
 281         struct mtd_part *part = mtd_to_part(mtd);
 282         part->parent->_put_device(part->parent);
 283 }
 284 
 285 static int part_ooblayout_ecc(struct mtd_info *mtd, int section,
 286                               struct mtd_oob_region *oobregion)
 287 {
 288         struct mtd_part *part = mtd_to_part(mtd);
 289 
 290         return mtd_ooblayout_ecc(part->parent, section, oobregion);
 291 }
 292 
 293 static int part_ooblayout_free(struct mtd_info *mtd, int section,
 294                                struct mtd_oob_region *oobregion)
 295 {
 296         struct mtd_part *part = mtd_to_part(mtd);
 297 
 298         return mtd_ooblayout_free(part->parent, section, oobregion);
 299 }
 300 
 301 static const struct mtd_ooblayout_ops part_ooblayout_ops = {
 302         .ecc = part_ooblayout_ecc,
 303         .free = part_ooblayout_free,
 304 };
 305 
 306 static int part_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
 307 {
 308         struct mtd_part *part = mtd_to_part(mtd);
 309 
 310         return part->parent->_max_bad_blocks(part->parent,
 311                                              ofs + part->offset, len);
 312 }
 313 
 314 static inline void free_partition(struct mtd_part *p)
 315 {
 316         kfree(p->mtd.name);
 317         kfree(p);
 318 }
 319 
 320 static struct mtd_part *allocate_partition(struct mtd_info *parent,
 321                         const struct mtd_partition *part, int partno,
 322                         uint64_t cur_offset)
 323 {
 324         int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize :
 325                                                             parent->erasesize;
 326         struct mtd_part *slave;
 327         u32 remainder;
 328         char *name;
 329         u64 tmp;
 330 
 331         /* allocate the partition structure */
 332         slave = kzalloc(sizeof(*slave), GFP_KERNEL);
 333         name = kstrdup(part->name, GFP_KERNEL);
 334         if (!name || !slave) {
 335                 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
 336                        parent->name);
 337                 kfree(name);
 338                 kfree(slave);
 339                 return ERR_PTR(-ENOMEM);
 340         }
 341 
 342         /* set up the MTD object for this partition */
 343         slave->mtd.type = parent->type;
 344         slave->mtd.flags = parent->orig_flags & ~part->mask_flags;
 345         slave->mtd.orig_flags = slave->mtd.flags;
 346         slave->mtd.size = part->size;
 347         slave->mtd.writesize = parent->writesize;
 348         slave->mtd.writebufsize = parent->writebufsize;
 349         slave->mtd.oobsize = parent->oobsize;
 350         slave->mtd.oobavail = parent->oobavail;
 351         slave->mtd.subpage_sft = parent->subpage_sft;
 352         slave->mtd.pairing = parent->pairing;
 353 
 354         slave->mtd.name = name;
 355         slave->mtd.owner = parent->owner;
 356 
 357         /* NOTE: Historically, we didn't arrange MTDs as a tree out of
 358          * concern for showing the same data in multiple partitions.
 359          * However, it is very useful to have the master node present,
 360          * so the MTD_PARTITIONED_MASTER option allows that. The master
 361          * will have device nodes etc only if this is set, so make the
 362          * parent conditional on that option. Note, this is a way to
 363          * distinguish between the master and the partition in sysfs.
 364          */
 365         slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ?
 366                                 &parent->dev :
 367                                 parent->dev.parent;
 368         slave->mtd.dev.of_node = part->of_node;
 369 
 370         if (parent->_read)
 371                 slave->mtd._read = part_read;
 372         if (parent->_write)
 373                 slave->mtd._write = part_write;
 374 
 375         if (parent->_panic_write)
 376                 slave->mtd._panic_write = part_panic_write;
 377 
 378         if (parent->_point && parent->_unpoint) {
 379                 slave->mtd._point = part_point;
 380                 slave->mtd._unpoint = part_unpoint;
 381         }
 382 
 383         if (parent->_read_oob)
 384                 slave->mtd._read_oob = part_read_oob;
 385         if (parent->_write_oob)
 386                 slave->mtd._write_oob = part_write_oob;
 387         if (parent->_read_user_prot_reg)
 388                 slave->mtd._read_user_prot_reg = part_read_user_prot_reg;
 389         if (parent->_read_fact_prot_reg)
 390                 slave->mtd._read_fact_prot_reg = part_read_fact_prot_reg;
 391         if (parent->_write_user_prot_reg)
 392                 slave->mtd._write_user_prot_reg = part_write_user_prot_reg;
 393         if (parent->_lock_user_prot_reg)
 394                 slave->mtd._lock_user_prot_reg = part_lock_user_prot_reg;
 395         if (parent->_get_user_prot_info)
 396                 slave->mtd._get_user_prot_info = part_get_user_prot_info;
 397         if (parent->_get_fact_prot_info)
 398                 slave->mtd._get_fact_prot_info = part_get_fact_prot_info;
 399         if (parent->_sync)
 400                 slave->mtd._sync = part_sync;
 401         if (!partno && !parent->dev.class && parent->_suspend &&
 402             parent->_resume) {
 403                 slave->mtd._suspend = part_suspend;
 404                 slave->mtd._resume = part_resume;
 405         }
 406         if (parent->_writev)
 407                 slave->mtd._writev = part_writev;
 408         if (parent->_lock)
 409                 slave->mtd._lock = part_lock;
 410         if (parent->_unlock)
 411                 slave->mtd._unlock = part_unlock;
 412         if (parent->_is_locked)
 413                 slave->mtd._is_locked = part_is_locked;
 414         if (parent->_block_isreserved)
 415                 slave->mtd._block_isreserved = part_block_isreserved;
 416         if (parent->_block_isbad)
 417                 slave->mtd._block_isbad = part_block_isbad;
 418         if (parent->_block_markbad)
 419                 slave->mtd._block_markbad = part_block_markbad;
 420         if (parent->_max_bad_blocks)
 421                 slave->mtd._max_bad_blocks = part_max_bad_blocks;
 422 
 423         if (parent->_get_device)
 424                 slave->mtd._get_device = part_get_device;
 425         if (parent->_put_device)
 426                 slave->mtd._put_device = part_put_device;
 427 
 428         slave->mtd._erase = part_erase;
 429         slave->parent = parent;
 430         slave->offset = part->offset;
 431 
 432         if (slave->offset == MTDPART_OFS_APPEND)
 433                 slave->offset = cur_offset;
 434         if (slave->offset == MTDPART_OFS_NXTBLK) {
 435                 tmp = cur_offset;
 436                 slave->offset = cur_offset;
 437                 remainder = do_div(tmp, wr_alignment);
 438                 if (remainder) {
 439                         slave->offset += wr_alignment - remainder;
 440                         printk(KERN_NOTICE "Moving partition %d: "
 441                                "0x%012llx -> 0x%012llx\n", partno,
 442                                (unsigned long long)cur_offset, (unsigned long long)slave->offset);
 443                 }
 444         }
 445         if (slave->offset == MTDPART_OFS_RETAIN) {
 446                 slave->offset = cur_offset;
 447                 if (parent->size - slave->offset >= slave->mtd.size) {
 448                         slave->mtd.size = parent->size - slave->offset
 449                                                         - slave->mtd.size;
 450                 } else {
 451                         printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
 452                                 part->name, parent->size - slave->offset,
 453                                 slave->mtd.size);
 454                         /* register to preserve ordering */
 455                         goto out_register;
 456                 }
 457         }
 458         if (slave->mtd.size == MTDPART_SIZ_FULL)
 459                 slave->mtd.size = parent->size - slave->offset;
 460 
 461         printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
 462                 (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
 463 
 464         /* let's do some sanity checks */
 465         if (slave->offset >= parent->size) {
 466                 /* let's register it anyway to preserve ordering */
 467                 slave->offset = 0;
 468                 slave->mtd.size = 0;
 469 
 470                 /* Initialize ->erasesize to make add_mtd_device() happy. */
 471                 slave->mtd.erasesize = parent->erasesize;
 472 
 473                 printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
 474                         part->name);
 475                 goto out_register;
 476         }
 477         if (slave->offset + slave->mtd.size > parent->size) {
 478                 slave->mtd.size = parent->size - slave->offset;
 479                 printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",
 480                         part->name, parent->name, (unsigned long long)slave->mtd.size);
 481         }
 482         if (parent->numeraseregions > 1) {
 483                 /* Deal with variable erase size stuff */
 484                 int i, max = parent->numeraseregions;
 485                 u64 end = slave->offset + slave->mtd.size;
 486                 struct mtd_erase_region_info *regions = parent->eraseregions;
 487 
 488                 /* Find the first erase regions which is part of this
 489                  * partition. */
 490                 for (i = 0; i < max && regions[i].offset <= slave->offset; i++)
 491                         ;
 492                 /* The loop searched for the region _behind_ the first one */
 493                 if (i > 0)
 494                         i--;
 495 
 496                 /* Pick biggest erasesize */
 497                 for (; i < max && regions[i].offset < end; i++) {
 498                         if (slave->mtd.erasesize < regions[i].erasesize) {
 499                                 slave->mtd.erasesize = regions[i].erasesize;
 500                         }
 501                 }
 502                 BUG_ON(slave->mtd.erasesize == 0);
 503         } else {
 504                 /* Single erase size */
 505                 slave->mtd.erasesize = parent->erasesize;
 506         }
 507 
 508         /*
 509          * Slave erasesize might differ from the master one if the master
 510          * exposes several regions with different erasesize. Adjust
 511          * wr_alignment accordingly.
 512          */
 513         if (!(slave->mtd.flags & MTD_NO_ERASE))
 514                 wr_alignment = slave->mtd.erasesize;
 515 
 516         tmp = part_absolute_offset(parent) + slave->offset;
 517         remainder = do_div(tmp, wr_alignment);
 518         if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
 519                 /* Doesn't start on a boundary of major erase size */
 520                 /* FIXME: Let it be writable if it is on a boundary of
 521                  * _minor_ erase size though */
 522                 slave->mtd.flags &= ~MTD_WRITEABLE;
 523                 printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
 524                         part->name);
 525         }
 526 
 527         tmp = part_absolute_offset(parent) + slave->mtd.size;
 528         remainder = do_div(tmp, wr_alignment);
 529         if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
 530                 slave->mtd.flags &= ~MTD_WRITEABLE;
 531                 printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
 532                         part->name);
 533         }
 534 
 535         mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops);
 536         slave->mtd.ecc_step_size = parent->ecc_step_size;
 537         slave->mtd.ecc_strength = parent->ecc_strength;
 538         slave->mtd.bitflip_threshold = parent->bitflip_threshold;
 539 
 540         if (parent->_block_isbad) {
 541                 uint64_t offs = 0;
 542 
 543                 while (offs < slave->mtd.size) {
 544                         if (mtd_block_isreserved(parent, offs + slave->offset))
 545                                 slave->mtd.ecc_stats.bbtblocks++;
 546                         else if (mtd_block_isbad(parent, offs + slave->offset))
 547                                 slave->mtd.ecc_stats.badblocks++;
 548                         offs += slave->mtd.erasesize;
 549                 }
 550         }
 551 
 552 out_register:
 553         return slave;
 554 }
 555 
 556 static ssize_t mtd_partition_offset_show(struct device *dev,
 557                 struct device_attribute *attr, char *buf)
 558 {
 559         struct mtd_info *mtd = dev_get_drvdata(dev);
 560         struct mtd_part *part = mtd_to_part(mtd);
 561         return snprintf(buf, PAGE_SIZE, "%llu\n", part->offset);
 562 }
 563 
 564 static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL);
 565 
 566 static const struct attribute *mtd_partition_attrs[] = {
 567         &dev_attr_offset.attr,
 568         NULL
 569 };
 570 
 571 static int mtd_add_partition_attrs(struct mtd_part *new)
 572 {
 573         int ret = sysfs_create_files(&new->mtd.dev.kobj, mtd_partition_attrs);
 574         if (ret)
 575                 printk(KERN_WARNING
 576                        "mtd: failed to create partition attrs, err=%d\n", ret);
 577         return ret;
 578 }
 579 
 580 int mtd_add_partition(struct mtd_info *parent, const char *name,
 581                       long long offset, long long length)
 582 {
 583         struct mtd_partition part;
 584         struct mtd_part *new;
 585         int ret = 0;
 586 
 587         /* the direct offset is expected */
 588         if (offset == MTDPART_OFS_APPEND ||
 589             offset == MTDPART_OFS_NXTBLK)
 590                 return -EINVAL;
 591 
 592         if (length == MTDPART_SIZ_FULL)
 593                 length = parent->size - offset;
 594 
 595         if (length <= 0)
 596                 return -EINVAL;
 597 
 598         memset(&part, 0, sizeof(part));
 599         part.name = name;
 600         part.size = length;
 601         part.offset = offset;
 602 
 603         new = allocate_partition(parent, &part, -1, offset);
 604         if (IS_ERR(new))
 605                 return PTR_ERR(new);
 606 
 607         mutex_lock(&mtd_partitions_mutex);
 608         list_add(&new->list, &mtd_partitions);
 609         mutex_unlock(&mtd_partitions_mutex);
 610 
 611         ret = add_mtd_device(&new->mtd);
 612         if (ret)
 613                 goto err_remove_part;
 614 
 615         mtd_add_partition_attrs(new);
 616 
 617         return 0;
 618 
 619 err_remove_part:
 620         mutex_lock(&mtd_partitions_mutex);
 621         list_del(&new->list);
 622         mutex_unlock(&mtd_partitions_mutex);
 623 
 624         free_partition(new);
 625 
 626         return ret;
 627 }
 628 EXPORT_SYMBOL_GPL(mtd_add_partition);
 629 
 630 /**
 631  * __mtd_del_partition - delete MTD partition
 632  *
 633  * @priv: internal MTD struct for partition to be deleted
 634  *
 635  * This function must be called with the partitions mutex locked.
 636  */
 637 static int __mtd_del_partition(struct mtd_part *priv)
 638 {
 639         struct mtd_part *child, *next;
 640         int err;
 641 
 642         list_for_each_entry_safe(child, next, &mtd_partitions, list) {
 643                 if (child->parent == &priv->mtd) {
 644                         err = __mtd_del_partition(child);
 645                         if (err)
 646                                 return err;
 647                 }
 648         }
 649 
 650         sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs);
 651 
 652         err = del_mtd_device(&priv->mtd);
 653         if (err)
 654                 return err;
 655 
 656         list_del(&priv->list);
 657         free_partition(priv);
 658 
 659         return 0;
 660 }
 661 
 662 /*
 663  * This function unregisters and destroy all slave MTD objects which are
 664  * attached to the given MTD object.
 665  */
 666 int del_mtd_partitions(struct mtd_info *mtd)
 667 {
 668         struct mtd_part *slave, *next;
 669         int ret, err = 0;
 670 
 671         mutex_lock(&mtd_partitions_mutex);
 672         list_for_each_entry_safe(slave, next, &mtd_partitions, list)
 673                 if (slave->parent == mtd) {
 674                         ret = __mtd_del_partition(slave);
 675                         if (ret < 0)
 676                                 err = ret;
 677                 }
 678         mutex_unlock(&mtd_partitions_mutex);
 679 
 680         return err;
 681 }
 682 
 683 int mtd_del_partition(struct mtd_info *mtd, int partno)
 684 {
 685         struct mtd_part *slave, *next;
 686         int ret = -EINVAL;
 687 
 688         mutex_lock(&mtd_partitions_mutex);
 689         list_for_each_entry_safe(slave, next, &mtd_partitions, list)
 690                 if ((slave->parent == mtd) &&
 691                     (slave->mtd.index == partno)) {
 692                         ret = __mtd_del_partition(slave);
 693                         break;
 694                 }
 695         mutex_unlock(&mtd_partitions_mutex);
 696 
 697         return ret;
 698 }
 699 EXPORT_SYMBOL_GPL(mtd_del_partition);
 700 
 701 /*
 702  * This function, given a master MTD object and a partition table, creates
 703  * and registers slave MTD objects which are bound to the master according to
 704  * the partition definitions.
 705  *
 706  * For historical reasons, this function's caller only registers the master
 707  * if the MTD_PARTITIONED_MASTER config option is set.
 708  */
 709 
 710 int add_mtd_partitions(struct mtd_info *master,
 711                        const struct mtd_partition *parts,
 712                        int nbparts)
 713 {
 714         struct mtd_part *slave;
 715         uint64_t cur_offset = 0;
 716         int i, ret;
 717 
 718         printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 719 
 720         for (i = 0; i < nbparts; i++) {
 721                 slave = allocate_partition(master, parts + i, i, cur_offset);
 722                 if (IS_ERR(slave)) {
 723                         ret = PTR_ERR(slave);
 724                         goto err_del_partitions;
 725                 }
 726 
 727                 mutex_lock(&mtd_partitions_mutex);
 728                 list_add(&slave->list, &mtd_partitions);
 729                 mutex_unlock(&mtd_partitions_mutex);
 730 
 731                 ret = add_mtd_device(&slave->mtd);
 732                 if (ret) {
 733                         mutex_lock(&mtd_partitions_mutex);
 734                         list_del(&slave->list);
 735                         mutex_unlock(&mtd_partitions_mutex);
 736 
 737                         free_partition(slave);
 738                         goto err_del_partitions;
 739                 }
 740 
 741                 mtd_add_partition_attrs(slave);
 742                 /* Look for subpartitions */
 743                 parse_mtd_partitions(&slave->mtd, parts[i].types, NULL);
 744 
 745                 cur_offset = slave->offset + slave->mtd.size;
 746         }
 747 
 748         return 0;
 749 
 750 err_del_partitions:
 751         del_mtd_partitions(master);
 752 
 753         return ret;
 754 }
 755 
 756 static DEFINE_SPINLOCK(part_parser_lock);
 757 static LIST_HEAD(part_parsers);
 758 
 759 static struct mtd_part_parser *mtd_part_parser_get(const char *name)
 760 {
 761         struct mtd_part_parser *p, *ret = NULL;
 762 
 763         spin_lock(&part_parser_lock);
 764 
 765         list_for_each_entry(p, &part_parsers, list)
 766                 if (!strcmp(p->name, name) && try_module_get(p->owner)) {
 767                         ret = p;
 768                         break;
 769                 }
 770 
 771         spin_unlock(&part_parser_lock);
 772 
 773         return ret;
 774 }
 775 
 776 static inline void mtd_part_parser_put(const struct mtd_part_parser *p)
 777 {
 778         module_put(p->owner);
 779 }
 780 
 781 /*
 782  * Many partition parsers just expected the core to kfree() all their data in
 783  * one chunk. Do that by default.
 784  */
 785 static void mtd_part_parser_cleanup_default(const struct mtd_partition *pparts,
 786                                             int nr_parts)
 787 {
 788         kfree(pparts);
 789 }
 790 
 791 int __register_mtd_parser(struct mtd_part_parser *p, struct module *owner)
 792 {
 793         p->owner = owner;
 794 
 795         if (!p->cleanup)
 796                 p->cleanup = &mtd_part_parser_cleanup_default;
 797 
 798         spin_lock(&part_parser_lock);
 799         list_add(&p->list, &part_parsers);
 800         spin_unlock(&part_parser_lock);
 801 
 802         return 0;
 803 }
 804 EXPORT_SYMBOL_GPL(__register_mtd_parser);
 805 
 806 void deregister_mtd_parser(struct mtd_part_parser *p)
 807 {
 808         spin_lock(&part_parser_lock);
 809         list_del(&p->list);
 810         spin_unlock(&part_parser_lock);
 811 }
 812 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 813 
 814 /*
 815  * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
 816  * are changing this array!
 817  */
 818 static const char * const default_mtd_part_types[] = {
 819         "cmdlinepart",
 820         "ofpart",
 821         NULL
 822 };
 823 
 824 /* Check DT only when looking for subpartitions. */
 825 static const char * const default_subpartition_types[] = {
 826         "ofpart",
 827         NULL
 828 };
 829 
 830 static int mtd_part_do_parse(struct mtd_part_parser *parser,
 831                              struct mtd_info *master,
 832                              struct mtd_partitions *pparts,
 833                              struct mtd_part_parser_data *data)
 834 {
 835         int ret;
 836 
 837         ret = (*parser->parse_fn)(master, &pparts->parts, data);
 838         pr_debug("%s: parser %s: %i\n", master->name, parser->name, ret);
 839         if (ret <= 0)
 840                 return ret;
 841 
 842         pr_notice("%d %s partitions found on MTD device %s\n", ret,
 843                   parser->name, master->name);
 844 
 845         pparts->nr_parts = ret;
 846         pparts->parser = parser;
 847 
 848         return ret;
 849 }
 850 
 851 /**
 852  * mtd_part_get_compatible_parser - find MTD parser by a compatible string
 853  *
 854  * @compat: compatible string describing partitions in a device tree
 855  *
 856  * MTD parsers can specify supported partitions by providing a table of
 857  * compatibility strings. This function finds a parser that advertises support
 858  * for a passed value of "compatible".
 859  */
 860 static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat)
 861 {
 862         struct mtd_part_parser *p, *ret = NULL;
 863 
 864         spin_lock(&part_parser_lock);
 865 
 866         list_for_each_entry(p, &part_parsers, list) {
 867                 const struct of_device_id *matches;
 868 
 869                 matches = p->of_match_table;
 870                 if (!matches)
 871                         continue;
 872 
 873                 for (; matches->compatible[0]; matches++) {
 874                         if (!strcmp(matches->compatible, compat) &&
 875                             try_module_get(p->owner)) {
 876                                 ret = p;
 877                                 break;
 878                         }
 879                 }
 880 
 881                 if (ret)
 882                         break;
 883         }
 884 
 885         spin_unlock(&part_parser_lock);
 886 
 887         return ret;
 888 }
 889 
 890 static int mtd_part_of_parse(struct mtd_info *master,
 891                              struct mtd_partitions *pparts)
 892 {
 893         struct mtd_part_parser *parser;
 894         struct device_node *np;
 895         struct property *prop;
 896         const char *compat;
 897         const char *fixed = "fixed-partitions";
 898         int ret, err = 0;
 899 
 900         np = mtd_get_of_node(master);
 901         if (mtd_is_partition(master))
 902                 of_node_get(np);
 903         else
 904                 np = of_get_child_by_name(np, "partitions");
 905 
 906         of_property_for_each_string(np, "compatible", prop, compat) {
 907                 parser = mtd_part_get_compatible_parser(compat);
 908                 if (!parser)
 909                         continue;
 910                 ret = mtd_part_do_parse(parser, master, pparts, NULL);
 911                 if (ret > 0) {
 912                         of_node_put(np);
 913                         return ret;
 914                 }
 915                 mtd_part_parser_put(parser);
 916                 if (ret < 0 && !err)
 917                         err = ret;
 918         }
 919         of_node_put(np);
 920 
 921         /*
 922          * For backward compatibility we have to try the "fixed-partitions"
 923          * parser. It supports old DT format with partitions specified as a
 924          * direct subnodes of a flash device DT node without any compatibility
 925          * specified we could match.
 926          */
 927         parser = mtd_part_parser_get(fixed);
 928         if (!parser && !request_module("%s", fixed))
 929                 parser = mtd_part_parser_get(fixed);
 930         if (parser) {
 931                 ret = mtd_part_do_parse(parser, master, pparts, NULL);
 932                 if (ret > 0)
 933                         return ret;
 934                 mtd_part_parser_put(parser);
 935                 if (ret < 0 && !err)
 936                         err = ret;
 937         }
 938 
 939         return err;
 940 }
 941 
 942 /**
 943  * parse_mtd_partitions - parse and register MTD partitions
 944  *
 945  * @master: the master partition (describes whole MTD device)
 946  * @types: names of partition parsers to try or %NULL
 947  * @data: MTD partition parser-specific data
 948  *
 949  * This function tries to find & register partitions on MTD device @master. It
 950  * uses MTD partition parsers, specified in @types. However, if @types is %NULL,
 951  * then the default list of parsers is used. The default list contains only the
 952  * "cmdlinepart" and "ofpart" parsers ATM.
 953  * Note: If there are more then one parser in @types, the kernel only takes the
 954  * partitions parsed out by the first parser.
 955  *
 956  * This function may return:
 957  * o a negative error code in case of failure
 958  * o number of found partitions otherwise
 959  */
 960 int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
 961                          struct mtd_part_parser_data *data)
 962 {
 963         struct mtd_partitions pparts = { };
 964         struct mtd_part_parser *parser;
 965         int ret, err = 0;
 966 
 967         if (!types)
 968                 types = mtd_is_partition(master) ? default_subpartition_types :
 969                         default_mtd_part_types;
 970 
 971         for ( ; *types; types++) {
 972                 /*
 973                  * ofpart is a special type that means OF partitioning info
 974                  * should be used. It requires a bit different logic so it is
 975                  * handled in a separated function.
 976                  */
 977                 if (!strcmp(*types, "ofpart")) {
 978                         ret = mtd_part_of_parse(master, &pparts);
 979                 } else {
 980                         pr_debug("%s: parsing partitions %s\n", master->name,
 981                                  *types);
 982                         parser = mtd_part_parser_get(*types);
 983                         if (!parser && !request_module("%s", *types))
 984                                 parser = mtd_part_parser_get(*types);
 985                         pr_debug("%s: got parser %s\n", master->name,
 986                                 parser ? parser->name : NULL);
 987                         if (!parser)
 988                                 continue;
 989                         ret = mtd_part_do_parse(parser, master, &pparts, data);
 990                         if (ret <= 0)
 991                                 mtd_part_parser_put(parser);
 992                 }
 993                 /* Found partitions! */
 994                 if (ret > 0) {
 995                         err = add_mtd_partitions(master, pparts.parts,
 996                                                  pparts.nr_parts);
 997                         mtd_part_parser_cleanup(&pparts);
 998                         return err ? err : pparts.nr_parts;
 999                 }
1000                 /*
1001                  * Stash the first error we see; only report it if no parser
1002                  * succeeds
1003                  */
1004                 if (ret < 0 && !err)
1005                         err = ret;
1006         }
1007         return err;
1008 }
1009 
1010 void mtd_part_parser_cleanup(struct mtd_partitions *parts)
1011 {
1012         const struct mtd_part_parser *parser;
1013 
1014         if (!parts)
1015                 return;
1016 
1017         parser = parts->parser;
1018         if (parser) {
1019                 if (parser->cleanup)
1020                         parser->cleanup(parts->parts, parts->nr_parts);
1021 
1022                 mtd_part_parser_put(parser);
1023         }
1024 }
1025 
1026 int mtd_is_partition(const struct mtd_info *mtd)
1027 {
1028         struct mtd_part *part;
1029         int ispart = 0;
1030 
1031         mutex_lock(&mtd_partitions_mutex);
1032         list_for_each_entry(part, &mtd_partitions, list)
1033                 if (&part->mtd == mtd) {
1034                         ispart = 1;
1035                         break;
1036                 }
1037         mutex_unlock(&mtd_partitions_mutex);
1038 
1039         return ispart;
1040 }
1041 EXPORT_SYMBOL_GPL(mtd_is_partition);
1042 
1043 /* Returns the size of the entire flash chip */
1044 uint64_t mtd_get_device_size(const struct mtd_info *mtd)
1045 {
1046         if (!mtd_is_partition(mtd))
1047                 return mtd->size;
1048 
1049         return mtd_get_device_size(mtd_to_part(mtd)->parent);
1050 }
1051 EXPORT_SYMBOL_GPL(mtd_get_device_size);

/* [<][>][^][v][top][bottom][index][help] */