060-rootfs_split.patch 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. Index: linux/drivers/mtd/Kconfig
  2. ===================================================================
  3. --- linux.orig/drivers/mtd/Kconfig
  4. +++ linux/drivers/mtd/Kconfig
  5. @@ -49,6 +49,16 @@ config MTD_PARTITIONS
  6. devices. Partitioning on NFTL 'devices' is a different - that's the
  7. 'normal' form of partitioning used on a block device.
  8. +config MTD_ROOTFS_ROOT_DEV
  9. + bool "Automatically set 'rootfs' partition to be root filesystem"
  10. + depends on MTD_PARTITIONS
  11. + default y
  12. +
  13. +config MTD_ROOTFS_SPLIT
  14. + bool "Automatically split 'rootfs' partition for squashfs"
  15. + depends on MTD_PARTITIONS
  16. + default y
  17. +
  18. config MTD_REDBOOT_PARTS
  19. tristate "RedBoot partition table parsing"
  20. depends on MTD_PARTITIONS
  21. Index: linux/drivers/mtd/mtdpart.c
  22. ===================================================================
  23. --- linux.orig/drivers/mtd/mtdpart.c
  24. +++ linux/drivers/mtd/mtdpart.c
  25. @@ -20,6 +20,8 @@
  26. #include <linux/mtd/mtd.h>
  27. #include <linux/mtd/partitions.h>
  28. #include <linux/mtd/compatmac.h>
  29. +#include <linux/squashfs_fs.h>
  30. +#include <linux/root_dev.h>
  31. /* Our partition linked list */
  32. static LIST_HEAD(mtd_partitions);
  33. @@ -308,6 +310,266 @@ int del_mtd_partitions(struct mtd_info *
  34. return 0;
  35. }
  36. +static u_int32_t cur_offset = 0;
  37. +static int add_one_partition(struct mtd_info *master, const struct mtd_partition *part,
  38. + int i, struct mtd_part **slp)
  39. +{
  40. + struct mtd_part *slave;
  41. +
  42. + /* allocate the partition structure */
  43. + slave = kzalloc (sizeof(*slave), GFP_KERNEL);
  44. + if (!slave) {
  45. + printk ("memory allocation error while creating partitions for \"%s\"\n",
  46. + master->name);
  47. + del_mtd_partitions(master);
  48. + return -ENOMEM;
  49. + }
  50. + list_add(&slave->list, &mtd_partitions);
  51. +
  52. + /* set up the MTD object for this partition */
  53. + slave->mtd.type = master->type;
  54. + slave->mtd.flags = master->flags & ~part->mask_flags;
  55. + slave->mtd.size = part->size;
  56. + slave->mtd.writesize = master->writesize;
  57. + slave->mtd.oobsize = master->oobsize;
  58. + slave->mtd.oobavail = master->oobavail;
  59. + slave->mtd.subpage_sft = master->subpage_sft;
  60. +
  61. + slave->mtd.name = part->name;
  62. + slave->mtd.bank_size = master->bank_size;
  63. + slave->mtd.owner = master->owner;
  64. +
  65. + slave->mtd.read = part_read;
  66. + slave->mtd.write = part_write;
  67. +
  68. + if(master->point && master->unpoint){
  69. + slave->mtd.point = part_point;
  70. + slave->mtd.unpoint = part_unpoint;
  71. + }
  72. +
  73. + if (master->read_oob)
  74. + slave->mtd.read_oob = part_read_oob;
  75. + if (master->write_oob)
  76. + slave->mtd.write_oob = part_write_oob;
  77. + if(master->read_user_prot_reg)
  78. + slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
  79. + if(master->read_fact_prot_reg)
  80. + slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
  81. + if(master->write_user_prot_reg)
  82. + slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
  83. + if(master->lock_user_prot_reg)
  84. + slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
  85. + if(master->get_user_prot_info)
  86. + slave->mtd.get_user_prot_info = part_get_user_prot_info;
  87. + if(master->get_fact_prot_info)
  88. + slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
  89. + if (master->sync)
  90. + slave->mtd.sync = part_sync;
  91. + if (!i && master->suspend && master->resume) {
  92. + slave->mtd.suspend = part_suspend;
  93. + slave->mtd.resume = part_resume;
  94. + }
  95. + if (master->writev)
  96. + slave->mtd.writev = part_writev;
  97. + if (master->lock)
  98. + slave->mtd.lock = part_lock;
  99. + if (master->unlock)
  100. + slave->mtd.unlock = part_unlock;
  101. + if (master->block_isbad)
  102. + slave->mtd.block_isbad = part_block_isbad;
  103. + if (master->block_markbad)
  104. + slave->mtd.block_markbad = part_block_markbad;
  105. + slave->mtd.erase = part_erase;
  106. + slave->master = master;
  107. + slave->offset = part->offset;
  108. + slave->index = i;
  109. +
  110. + if (slave->offset == MTDPART_OFS_APPEND)
  111. + slave->offset = cur_offset;
  112. + if (slave->offset == MTDPART_OFS_NXTBLK) {
  113. + slave->offset = cur_offset;
  114. + if ((cur_offset % master->erasesize) != 0) {
  115. + /* Round up to next erasesize */
  116. + slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
  117. + printk(KERN_NOTICE "Moving partition %d: "
  118. + "0x%08x -> 0x%08x\n", i,
  119. + cur_offset, slave->offset);
  120. + }
  121. + }
  122. + if (slave->mtd.size == MTDPART_SIZ_FULL)
  123. + slave->mtd.size = master->size - slave->offset;
  124. + cur_offset = slave->offset + slave->mtd.size;
  125. +
  126. + printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
  127. + slave->offset + slave->mtd.size, slave->mtd.name);
  128. +
  129. + /* let's do some sanity checks */
  130. + if (slave->offset >= master->size) {
  131. + /* let's register it anyway to preserve ordering */
  132. + slave->offset = 0;
  133. + slave->mtd.size = 0;
  134. + printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
  135. + part->name);
  136. + }
  137. + if (slave->offset + slave->mtd.size > master->size) {
  138. + slave->mtd.size = master->size - slave->offset;
  139. + printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
  140. + part->name, master->name, slave->mtd.size);
  141. + }
  142. + if (master->numeraseregions>1) {
  143. + /* Deal with variable erase size stuff */
  144. + int i;
  145. + struct mtd_erase_region_info *regions = master->eraseregions;
  146. +
  147. + /* Find the first erase regions which is part of this partition. */
  148. + for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
  149. + ;
  150. +
  151. + for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
  152. + if (slave->mtd.erasesize < regions[i].erasesize) {
  153. + slave->mtd.erasesize = regions[i].erasesize;
  154. + }
  155. + }
  156. + } else {
  157. + /* Single erase size */
  158. + slave->mtd.erasesize = master->erasesize;
  159. + }
  160. +
  161. + if ((slave->mtd.flags & MTD_WRITEABLE) &&
  162. + (slave->offset % slave->mtd.erasesize)) {
  163. + /* Doesn't start on a boundary of major erase size */
  164. + /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
  165. + slave->mtd.flags &= ~MTD_WRITEABLE;
  166. + printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
  167. + part->name);
  168. + }
  169. + if ((slave->mtd.flags & MTD_WRITEABLE) &&
  170. + (slave->mtd.size % slave->mtd.erasesize)) {
  171. + slave->mtd.flags &= ~MTD_WRITEABLE;
  172. + printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
  173. + part->name);
  174. + }
  175. +
  176. + slave->mtd.ecclayout = master->ecclayout;
  177. + if (master->block_isbad) {
  178. + uint32_t offs = 0;
  179. +
  180. + while(offs < slave->mtd.size) {
  181. + if (master->block_isbad(master,
  182. + offs + slave->offset))
  183. + slave->mtd.ecc_stats.badblocks++;
  184. + offs += slave->mtd.erasesize;
  185. + }
  186. + }
  187. +
  188. + if(part->mtdp)
  189. + { /* store the object pointer (caller may or may not register it */
  190. + *part->mtdp = &slave->mtd;
  191. + slave->registered = 0;
  192. + }
  193. + else
  194. + {
  195. + /* register our partition */
  196. + add_mtd_device(&slave->mtd);
  197. + slave->registered = 1;
  198. + }
  199. +
  200. + if (slp)
  201. + *slp = slave;
  202. +
  203. + return 0;
  204. +}
  205. +
  206. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  207. +#define ROOTFS_SPLIT_NAME "rootfs_data"
  208. +static int split_squashfs(struct mtd_info *master, struct mtd_partition *old,
  209. + struct mtd_partition **new)
  210. +{
  211. + struct mtd_partition *part = NULL;
  212. + int len;
  213. + char buf[512];
  214. + struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
  215. + int ret;
  216. +
  217. + ret = master->read(master, old->offset, sizeof(*sb), &len, buf);
  218. + if (ret) {
  219. + printk(KERN_ALERT "split_squashfs: error occured while reading "
  220. + "from \"%s\"\n", master->name);
  221. + goto out;
  222. + }
  223. +
  224. + if (len != sizeof(*sb)) {
  225. + printk(KERN_ALERT "split_squashfs: unable to read superblock "
  226. + "from \"%s\"\n", master->name);
  227. + ret=-1;
  228. + goto out;
  229. + }
  230. +
  231. + if (*((u32 *) buf) != SQUASHFS_MAGIC) {
  232. + printk(KERN_ALERT "split_squasfs: no squashfs found in \"%s\"\n",
  233. + master->name);
  234. + ret=0;
  235. + goto out;
  236. + }
  237. +
  238. + if (sb->bytes_used <= 0) {
  239. + printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
  240. + master->name);
  241. + ret=0;
  242. + goto out;
  243. + }
  244. +
  245. + part = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
  246. + if (part == NULL) {
  247. + printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
  248. + ROOTFS_SPLIT_NAME);
  249. + ret = -ENOMEM;
  250. + goto out;
  251. + }
  252. +
  253. + memcpy(part, old, sizeof(*part));
  254. + part->name = (unsigned char *)&part[1];
  255. + strcpy(part->name, ROOTFS_SPLIT_NAME);
  256. +
  257. + len = (u32) sb->bytes_used;
  258. + len += (part->offset & 0x000fffff);
  259. + len += (master->erasesize - 1);
  260. + len &= ~(master->erasesize - 1);
  261. + len -= (part->offset & 0x000fffff);
  262. + part->offset += len;
  263. + part->size -= len;
  264. +
  265. + ret = 0;
  266. +
  267. +out:
  268. + *new = part;
  269. + return ret;
  270. +}
  271. +
  272. +static int split_rootfs_data(struct mtd_info *master, struct mtd_partition *part,
  273. + int index)
  274. +{
  275. + struct mtd_partition *dpart;
  276. + int ret;
  277. +
  278. + ret = split_squashfs(master, part, &dpart);
  279. + if (ret)
  280. + return ret;
  281. +
  282. + if (dpart == NULL)
  283. + return 1;
  284. +
  285. + printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n",
  286. + ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
  287. +
  288. + ret = add_one_partition(master, dpart, index, NULL);
  289. + if (ret)
  290. + kfree(dpart);
  291. +
  292. + return ret;
  293. +}
  294. +#endif /* CONFIG_MTD_ROOTFS_SPLIT */
  295. +
  296. /*
  297. * This function, given a master MTD object and a partition table, creates
  298. * and registers slave MTD objects which are bound to the master according to
  299. @@ -320,169 +582,31 @@ int add_mtd_partitions(struct mtd_info *
  300. int nbparts)
  301. {
  302. struct mtd_part *slave;
  303. - u_int32_t cur_offset = 0;
  304. - int i;
  305. + struct mtd_partition *part;
  306. + int i, j, ret = 0;
  307. printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
  308. - for (i = 0; i < nbparts; i++) {
  309. -
  310. - /* allocate the partition structure */
  311. - slave = kzalloc (sizeof(*slave), GFP_KERNEL);
  312. - if (!slave) {
  313. - printk ("memory allocation error while creating partitions for \"%s\"\n",
  314. - master->name);
  315. - del_mtd_partitions(master);
  316. - return -ENOMEM;
  317. - }
  318. - list_add(&slave->list, &mtd_partitions);
  319. -
  320. - /* set up the MTD object for this partition */
  321. - slave->mtd.type = master->type;
  322. - slave->mtd.flags = master->flags & ~parts[i].mask_flags;
  323. - slave->mtd.size = parts[i].size;
  324. - slave->mtd.writesize = master->writesize;
  325. - slave->mtd.oobsize = master->oobsize;
  326. - slave->mtd.oobavail = master->oobavail;
  327. - slave->mtd.subpage_sft = master->subpage_sft;
  328. -
  329. - slave->mtd.name = parts[i].name;
  330. - slave->mtd.bank_size = master->bank_size;
  331. - slave->mtd.owner = master->owner;
  332. -
  333. - slave->mtd.read = part_read;
  334. - slave->mtd.write = part_write;
  335. -
  336. - if(master->point && master->unpoint){
  337. - slave->mtd.point = part_point;
  338. - slave->mtd.unpoint = part_unpoint;
  339. - }
  340. -
  341. - if (master->read_oob)
  342. - slave->mtd.read_oob = part_read_oob;
  343. - if (master->write_oob)
  344. - slave->mtd.write_oob = part_write_oob;
  345. - if(master->read_user_prot_reg)
  346. - slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
  347. - if(master->read_fact_prot_reg)
  348. - slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
  349. - if(master->write_user_prot_reg)
  350. - slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
  351. - if(master->lock_user_prot_reg)
  352. - slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
  353. - if(master->get_user_prot_info)
  354. - slave->mtd.get_user_prot_info = part_get_user_prot_info;
  355. - if(master->get_fact_prot_info)
  356. - slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
  357. - if (master->sync)
  358. - slave->mtd.sync = part_sync;
  359. - if (!i && master->suspend && master->resume) {
  360. - slave->mtd.suspend = part_suspend;
  361. - slave->mtd.resume = part_resume;
  362. - }
  363. - if (master->writev)
  364. - slave->mtd.writev = part_writev;
  365. - if (master->lock)
  366. - slave->mtd.lock = part_lock;
  367. - if (master->unlock)
  368. - slave->mtd.unlock = part_unlock;
  369. - if (master->block_isbad)
  370. - slave->mtd.block_isbad = part_block_isbad;
  371. - if (master->block_markbad)
  372. - slave->mtd.block_markbad = part_block_markbad;
  373. - slave->mtd.erase = part_erase;
  374. - slave->master = master;
  375. - slave->offset = parts[i].offset;
  376. - slave->index = i;
  377. -
  378. - if (slave->offset == MTDPART_OFS_APPEND)
  379. - slave->offset = cur_offset;
  380. - if (slave->offset == MTDPART_OFS_NXTBLK) {
  381. - slave->offset = cur_offset;
  382. - if ((cur_offset % master->erasesize) != 0) {
  383. - /* Round up to next erasesize */
  384. - slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
  385. - printk(KERN_NOTICE "Moving partition %d: "
  386. - "0x%08x -> 0x%08x\n", i,
  387. - cur_offset, slave->offset);
  388. - }
  389. - }
  390. - if (slave->mtd.size == MTDPART_SIZ_FULL)
  391. - slave->mtd.size = master->size - slave->offset;
  392. - cur_offset = slave->offset + slave->mtd.size;
  393. -
  394. - printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
  395. - slave->offset + slave->mtd.size, slave->mtd.name);
  396. -
  397. - /* let's do some sanity checks */
  398. - if (slave->offset >= master->size) {
  399. - /* let's register it anyway to preserve ordering */
  400. - slave->offset = 0;
  401. - slave->mtd.size = 0;
  402. - printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
  403. - parts[i].name);
  404. - }
  405. - if (slave->offset + slave->mtd.size > master->size) {
  406. - slave->mtd.size = master->size - slave->offset;
  407. - printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
  408. - parts[i].name, master->name, slave->mtd.size);
  409. - }
  410. - if (master->numeraseregions>1) {
  411. - /* Deal with variable erase size stuff */
  412. - int i;
  413. - struct mtd_erase_region_info *regions = master->eraseregions;
  414. -
  415. - /* Find the first erase regions which is part of this partition. */
  416. - for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
  417. - ;
  418. -
  419. - for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
  420. - if (slave->mtd.erasesize < regions[i].erasesize) {
  421. - slave->mtd.erasesize = regions[i].erasesize;
  422. - }
  423. - }
  424. - } else {
  425. - /* Single erase size */
  426. - slave->mtd.erasesize = master->erasesize;
  427. - }
  428. -
  429. - if ((slave->mtd.flags & MTD_WRITEABLE) &&
  430. - (slave->offset % slave->mtd.erasesize)) {
  431. - /* Doesn't start on a boundary of major erase size */
  432. - /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
  433. - slave->mtd.flags &= ~MTD_WRITEABLE;
  434. - printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
  435. - parts[i].name);
  436. - }
  437. - if ((slave->mtd.flags & MTD_WRITEABLE) &&
  438. - (slave->mtd.size % slave->mtd.erasesize)) {
  439. - slave->mtd.flags &= ~MTD_WRITEABLE;
  440. - printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
  441. - parts[i].name);
  442. - }
  443. -
  444. - slave->mtd.ecclayout = master->ecclayout;
  445. - if (master->block_isbad) {
  446. - uint32_t offs = 0;
  447. -
  448. - while(offs < slave->mtd.size) {
  449. - if (master->block_isbad(master,
  450. - offs + slave->offset))
  451. - slave->mtd.ecc_stats.badblocks++;
  452. - offs += slave->mtd.erasesize;
  453. + for (i = 0, j = 0; i < nbparts; i++) {
  454. + part = (struct mtd_partition *) &parts[i];
  455. + ret = add_one_partition(master, part, j, &slave);
  456. + if (ret)
  457. + return ret;
  458. + j++;
  459. +
  460. + if (strcmp(part->name, "rootfs") == 0 && slave->registered) {
  461. +#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
  462. + if (ROOT_DEV == 0) {
  463. + printk(KERN_NOTICE "mtd: partition \"rootfs\" "
  464. + "set to be root filesystem\n");
  465. + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
  466. }
  467. - }
  468. -
  469. - if(parts[i].mtdp)
  470. - { /* store the object pointer (caller may or may not register it */
  471. - *parts[i].mtdp = &slave->mtd;
  472. - slave->registered = 0;
  473. - }
  474. - else
  475. - {
  476. - /* register our partition */
  477. - add_mtd_device(&slave->mtd);
  478. - slave->registered = 1;
  479. +#endif
  480. +#ifdef CONFIG_MTD_ROOTFS_SPLIT
  481. + ret = split_rootfs_data(master, part, j);
  482. + if (ret == 0)
  483. + j++;
  484. +#endif
  485. }
  486. }