0101-mtd-split.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. --- a/arch/mips/lantiq/xway/Makefile
  2. +++ b/arch/mips/lantiq/xway/Makefile
  3. @@ -1,6 +1,6 @@
  4. obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
  5. -obj-y += vmmc.o tffs.o
  6. +obj-y += vmmc.o tffs.o mtd_split.o
  7. obj-y += eth_mac.o
  8. obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
  9. --- /dev/null
  10. +++ b/arch/mips/lantiq/xway/mtd_split.c
  11. @@ -0,0 +1,129 @@
  12. +#include <linux/magic.h>
  13. +#include <linux/root_dev.h>
  14. +#include <linux/mtd/mtd.h>
  15. +#include <linux/mtd/partitions.h>
  16. +
  17. +#define ROOTFS_SPLIT_NAME "rootfs_data"
  18. +
  19. +struct squashfs_super_block {
  20. + __le32 s_magic;
  21. + __le32 pad0[9];
  22. + __le64 bytes_used;
  23. +};
  24. +
  25. +static void split_brnimage_kernel(struct mtd_info *master, const char *name,
  26. + int offset, int size)
  27. +{
  28. + unsigned long buf[4];
  29. + // Assume at most 2MB of kernel image
  30. + unsigned long end = offset + (2 << 20);
  31. + unsigned long part_size = offset + 0x400 - 12;
  32. + size_t len;
  33. + int ret;
  34. +
  35. + if (strcmp(name, "firmware") != 0)
  36. + return;
  37. + while (part_size < end) {
  38. + long size_min = part_size - 0x400 - 12 - offset;
  39. + long size_max = part_size + 12 - offset;
  40. + ret = mtd_read(master, part_size, 16, &len, (void *)buf);
  41. + if (ret || len != 16)
  42. + return;
  43. +
  44. + if (le32_to_cpu(buf[0]) < size_min ||
  45. + le32_to_cpu(buf[0]) > size_max) {
  46. + part_size += 0x400;
  47. + continue;
  48. + }
  49. +
  50. + if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) {
  51. + part_size += 12 - offset;
  52. + __mtd_add_partition(master, "rootfs", offset + part_size,
  53. + size - part_size, false);
  54. + return;
  55. + }
  56. + part_size += 0x400;
  57. + }
  58. +}
  59. +
  60. +static void split_eva_kernel(struct mtd_info *master, const char *name,
  61. + int offset, int size)
  62. +{
  63. +#define EVA_MAGIC 0xfeed1281
  64. + unsigned long magic = 0;
  65. + unsigned long part_size = 0, p;
  66. + size_t len;
  67. + int ret;
  68. +
  69. + if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
  70. + return;
  71. +
  72. + ret = mtd_read(master, offset, 4, &len, (void *)&magic);
  73. + if (ret || len != sizeof(magic))
  74. + return;
  75. +
  76. + if (le32_to_cpu(magic) != EVA_MAGIC)
  77. + return;
  78. +
  79. + ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size);
  80. + if (ret || len != sizeof(part_size))
  81. + return;
  82. +
  83. + p = part_size = le32_to_cpu(part_size) + 0x18;
  84. + p &= ~0xffff;
  85. + p += 0x10000;
  86. +
  87. + ret = mtd_read(master, offset + p, 4, &len, (void *)&magic);
  88. + if (ret || len != sizeof(magic))
  89. + return;
  90. +
  91. + if (magic == SQUASHFS_MAGIC)
  92. + part_size = p + 0x100;
  93. + else
  94. + part_size = mtd_pad_erasesize(master, offset, len);
  95. +
  96. + if (part_size + master->erasesize > size)
  97. + return;
  98. +
  99. + __mtd_add_partition(master, "rootfs", offset + part_size,
  100. + size - part_size, false);
  101. +}
  102. +
  103. +static void split_tplink_kernel(struct mtd_info *master, const char *name,
  104. + int offset, int size)
  105. +{
  106. +#define TPLINK_MAGIC 0x00000002
  107. + unsigned long magic = 0;
  108. + unsigned long part_size = 0;
  109. + size_t len;
  110. + int ret;
  111. +
  112. + if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
  113. + return;
  114. +
  115. + ret = mtd_read(master, offset, 4, &len, (void *)&magic);
  116. + if (ret || len != sizeof(magic))
  117. + return;
  118. +
  119. + if (le32_to_cpu(magic) != TPLINK_MAGIC)
  120. + return;
  121. +
  122. + ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size);
  123. + if (ret || len != sizeof(part_size))
  124. + return;
  125. +
  126. + part_size = be32_to_cpu(part_size) + 0x200;
  127. + if (part_size + master->erasesize > size)
  128. + return;
  129. +
  130. + __mtd_add_partition(master, "rootfs", offset + part_size,
  131. + size - part_size, false);
  132. +}
  133. +
  134. +void arch_split_mtd_part(struct mtd_info *master, const char *name,
  135. + int offset, int size)
  136. +{
  137. + split_tplink_kernel(master, name, offset, size);
  138. + split_eva_kernel(master, name, offset, size);
  139. + split_brnimage_kernel(master, name, offset, size);
  140. +}
  141. --- a/include/linux/mtd/partitions.h
  142. +++ b/include/linux/mtd/partitions.h
  143. @@ -89,12 +89,17 @@ extern void deregister_mtd_parser(struct
  144. int mtd_is_partition(const struct mtd_info *mtd);
  145. int mtd_add_partition(struct mtd_info *master, const char *name,
  146. long long offset, long long length);
  147. +int __mtd_add_partition(struct mtd_info *master, const char *name,
  148. + long long offset, long long length, bool dup_check);
  149. +
  150. int mtd_del_partition(struct mtd_info *master, int partno);
  151. struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
  152. uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
  153. uint64_t mtd_get_device_size(const struct mtd_info *mtd);
  154. -extern void __weak arch_split_mtd_part(struct mtd_info *master,
  155. - const char *name, int offset, int size);
  156. +void __weak arch_split_mtd_part(struct mtd_info *master,
  157. + const char *name, int offset, int size);
  158. +unsigned long
  159. +mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len);
  160. int parse_mtd_partitions_by_type(struct mtd_info *master,
  161. enum mtd_parser_type type,
  162. --- a/drivers/mtd/mtdpart.c
  163. +++ b/drivers/mtd/mtdpart.c
  164. @@ -627,7 +627,7 @@ out_register:
  165. }
  166. -static int
  167. +int
  168. __mtd_add_partition(struct mtd_info *master, const char *name,
  169. long long offset, long long length, bool dup_check)
  170. {
  171. @@ -748,7 +748,7 @@ run_parsers_by_type(struct mtd_part *sla
  172. return nr_parts;
  173. }
  174. -static inline unsigned long
  175. +unsigned long
  176. mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
  177. {
  178. unsigned long mask = mtd->erasesize - 1;
  179. @@ -818,7 +818,6 @@ static void split_uimage(struct mtd_info
  180. return;
  181. len = be32_to_cpu(hdr.size) + 0x40;
  182. - len = mtd_pad_erasesize(master, part->offset, len);
  183. if (len + master->erasesize > part->mtd.size)
  184. return;