425-bcm63xxpart_parse_paritions_from_dt.patch 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. --- a/drivers/mtd/bcm63xxpart.c
  2. +++ b/drivers/mtd/bcm63xxpart.c
  3. @@ -32,6 +32,7 @@
  4. #include <linux/vmalloc.h>
  5. #include <linux/mtd/mtd.h>
  6. #include <linux/mtd/partitions.h>
  7. +#include <linux/of.h>
  8. #include <asm/mach-bcm63xx/bcm63xx_nvram.h>
  9. #include <asm/mach-bcm63xx/bcm963xx_tag.h>
  10. @@ -43,66 +44,35 @@
  11. #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
  12. -static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
  13. - struct mtd_partition **pparts,
  14. - struct mtd_part_parser_data *data)
  15. +static bool node_has_compatible(struct device_node *pp)
  16. +{
  17. + return of_get_property(pp, "compatible", NULL);
  18. +}
  19. +
  20. +static int parse_bcmtag(struct mtd_info *master, struct mtd_partition *pparts,
  21. + int next_part, size_t offset, size_t size)
  22. {
  23. - /* CFE, NVRAM and global Linux are always present */
  24. - int nrparts = 3, curpart = 0;
  25. struct bcm_tag *buf;
  26. - struct mtd_partition *parts;
  27. + u32 computed_crc;
  28. int ret;
  29. size_t retlen;
  30. - unsigned int rootfsaddr, kerneladdr, spareaddr, nvramaddr;
  31. - unsigned int rootfslen, kernellen, sparelen, totallen;
  32. - unsigned int cfelen, nvramlen;
  33. - unsigned int cfe_erasesize;
  34. - unsigned int caldatalen1 = 0, caldataaddr1 = 0;
  35. - unsigned int caldatalen2 = 0, caldataaddr2 = 0;
  36. - int i;
  37. - u32 computed_crc;
  38. + unsigned int rootfsaddr, kerneladdr;
  39. + unsigned int rootfslen, kernellen, totallen;
  40. bool rootfs_first = false;
  41. -
  42. - if (!bcm63xx_is_cfe_present())
  43. - return -EINVAL;
  44. -
  45. - cfe_erasesize = max_t(uint32_t, master->erasesize,
  46. - BCM63XX_CFE_BLOCK_SIZE);
  47. -
  48. - cfelen = cfe_erasesize;
  49. - nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
  50. - nvramlen = roundup(nvramlen, cfe_erasesize);
  51. - nvramaddr = master->size - nvramlen;
  52. -
  53. - if (data) {
  54. - if (data->caldata[0]) {
  55. - caldatalen1 = cfe_erasesize;
  56. - caldataaddr1 = rounddown(data->caldata[0],
  57. - cfe_erasesize);
  58. - }
  59. - if (data->caldata[1]) {
  60. - caldatalen2 = cfe_erasesize;
  61. - caldataaddr2 = rounddown(data->caldata[1],
  62. - cfe_erasesize);
  63. - }
  64. - if (caldataaddr1 == caldataaddr2) {
  65. - caldataaddr2 = 0;
  66. - caldatalen2 = 0;
  67. - }
  68. - }
  69. + int curr_part = next_part;
  70. /* Allocate memory for buffer */
  71. - buf = vmalloc(sizeof(struct bcm_tag));
  72. + buf = vmalloc(sizeof(*buf));
  73. if (!buf)
  74. return -ENOMEM;
  75. /* Get the tag */
  76. - ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen,
  77. + ret = mtd_read(master, offset, sizeof(*buf), &retlen,
  78. (void *)buf);
  79. - if (retlen != sizeof(struct bcm_tag)) {
  80. + if (retlen != sizeof(*buf)) {
  81. vfree(buf);
  82. - return -EIO;
  83. + return 0;
  84. }
  85. computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
  86. @@ -121,7 +91,6 @@ static int bcm63xx_parse_cfe_partitions(
  87. kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
  88. rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
  89. - spareaddr = roundup(totallen, master->erasesize) + cfelen;
  90. if (rootfsaddr < kerneladdr) {
  91. /* default Broadcom layout */
  92. @@ -130,8 +99,8 @@ static int bcm63xx_parse_cfe_partitions(
  93. } else {
  94. /* OpenWrt layout */
  95. rootfsaddr = kerneladdr + kernellen;
  96. - rootfslen = buf->real_rootfs_length;
  97. - spareaddr = rootfsaddr + rootfslen;
  98. + rootfslen = size - kernellen -
  99. + sizeof(*buf);
  100. }
  101. } else {
  102. pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
  103. @@ -139,16 +108,153 @@ static int bcm63xx_parse_cfe_partitions(
  104. kernellen = 0;
  105. rootfslen = 0;
  106. rootfsaddr = 0;
  107. - spareaddr = cfelen;
  108. }
  109. - sparelen = min_not_zero(nvramaddr, caldataaddr1) - spareaddr;
  110. - /* Determine number of partitions */
  111. - if (rootfslen > 0)
  112. - nrparts++;
  113. + if (kernellen > 0) {
  114. + int kernelpart = curr_part;
  115. - if (kernellen > 0)
  116. - nrparts++;
  117. + if (rootfslen > 0 && rootfs_first)
  118. + kernelpart++;
  119. + pparts[kernelpart].name = "kernel";
  120. + pparts[kernelpart].offset = kerneladdr;
  121. + pparts[kernelpart].size = kernellen;
  122. + curr_part++;
  123. + }
  124. +
  125. + if (rootfslen > 0) {
  126. + int rootfspart = curr_part;
  127. +
  128. + if (kernellen > 0 && rootfs_first)
  129. + rootfspart--;
  130. + pparts[rootfspart].name = "rootfs";
  131. + pparts[rootfspart].offset = rootfsaddr;
  132. + pparts[rootfspart].size = rootfslen;
  133. +
  134. + curr_part++;
  135. + }
  136. +
  137. + vfree(buf);
  138. +
  139. + return curr_part - next_part;
  140. +}
  141. +
  142. +
  143. +static int bcm63xx_parse_cfe_partitions_of(struct mtd_info *master,
  144. + struct mtd_partition **pparts,
  145. + struct mtd_part_parser_data *data)
  146. +{
  147. + struct device_node *dp = mtd_get_of_node(master);
  148. + struct device_node *pp;
  149. + int i, nr_parts = 0;
  150. + const char *partname;
  151. + int len;
  152. +
  153. + for_each_child_of_node(dp, pp) {
  154. + if (node_has_compatible(pp))
  155. + continue;
  156. +
  157. + if (!of_get_property(pp, "reg", &len))
  158. + continue;
  159. +
  160. + partname = of_get_property(pp, "label", &len);
  161. + if (!partname)
  162. + partname = of_get_property(pp, "name", &len);
  163. +
  164. + if (!strcmp(partname, "linux"))
  165. + nr_parts += 2;
  166. +
  167. + nr_parts++;
  168. + }
  169. +
  170. + *pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
  171. + if (!*pparts)
  172. + return -ENOMEM;
  173. +
  174. + i = 0;
  175. + for_each_child_of_node(dp, pp) {
  176. + const __be32 *reg;
  177. + int a_cells, s_cells;
  178. + size_t size, offset;
  179. +
  180. + if (node_has_compatible(pp))
  181. + continue;
  182. +
  183. + reg = of_get_property(pp, "reg", &len);
  184. + if (!reg)
  185. + continue;
  186. +
  187. + a_cells = of_n_addr_cells(pp);
  188. + s_cells = of_n_size_cells(pp);
  189. + offset = of_read_number(reg, a_cells);
  190. + size = of_read_number(reg + a_cells, s_cells);
  191. + partname = of_get_property(pp, "label", &len);
  192. + if (!partname)
  193. + partname = of_get_property(pp, "name", &len);
  194. +
  195. + if (!strcmp(partname, "linux"))
  196. + i += parse_bcmtag(master, *pparts, i, offset, size);
  197. +
  198. + if (of_get_property(pp, "read-only", &len))
  199. + (*pparts)[i].mask_flags |= MTD_WRITEABLE;
  200. +
  201. + if (of_get_property(pp, "lock", &len))
  202. + (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK;
  203. +
  204. + (*pparts)[i].offset = offset;
  205. + (*pparts)[i].size = size;
  206. + (*pparts)[i].name = partname;
  207. +
  208. + i++;
  209. + }
  210. +
  211. + return i;
  212. +}
  213. +
  214. +static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
  215. + struct mtd_partition **pparts,
  216. + struct mtd_part_parser_data *data)
  217. +{
  218. + /* CFE, NVRAM and global Linux are always present */
  219. + int nrparts = 5, curpart = 0;
  220. + struct mtd_partition *parts;
  221. + unsigned int nvramaddr;
  222. + unsigned int cfelen, nvramlen;
  223. + unsigned int cfe_erasesize;
  224. + unsigned int caldatalen1 = 0, caldataaddr1 = 0;
  225. + unsigned int caldatalen2 = 0, caldataaddr2 = 0;
  226. + unsigned int imageaddr, imagelen;
  227. + int i;
  228. +
  229. + if (!bcm63xx_is_cfe_present())
  230. + return -EINVAL;
  231. +
  232. + cfe_erasesize = max_t(uint32_t, master->erasesize,
  233. + BCM63XX_CFE_BLOCK_SIZE);
  234. +
  235. + cfelen = cfe_erasesize;
  236. + nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
  237. + nvramlen = roundup(nvramlen, cfe_erasesize);
  238. + nvramaddr = master->size - nvramlen;
  239. +
  240. + if (data) {
  241. + if (data->caldata[0]) {
  242. + caldatalen1 = cfe_erasesize;
  243. + caldataaddr1 = rounddown(data->caldata[0],
  244. + cfe_erasesize);
  245. + }
  246. + if (data->caldata[1]) {
  247. + caldatalen2 = cfe_erasesize;
  248. + caldataaddr2 = rounddown(data->caldata[1],
  249. + cfe_erasesize);
  250. + }
  251. + if (caldataaddr1 == caldataaddr2) {
  252. + caldataaddr2 = 0;
  253. + caldatalen2 = 0;
  254. + }
  255. + }
  256. +
  257. + imageaddr = cfelen;
  258. + imagelen = min_not_zero(nvramaddr, caldataaddr1) - imageaddr;
  259. if (caldatalen1 > 0)
  260. nrparts++;
  261. @@ -158,10 +264,8 @@ static int bcm63xx_parse_cfe_partitions(
  262. /* Ask kernel for more memory */
  263. parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
  264. - if (!parts) {
  265. - vfree(buf);
  266. + if (!parts)
  267. return -ENOMEM;
  268. - }
  269. /* Start building partition list */
  270. parts[curpart].name = "CFE";
  271. @@ -169,29 +273,7 @@ static int bcm63xx_parse_cfe_partitions(
  272. parts[curpart].size = cfelen;
  273. curpart++;
  274. - if (kernellen > 0) {
  275. - int kernelpart = curpart;
  276. -
  277. - if (rootfslen > 0 && rootfs_first)
  278. - kernelpart++;
  279. - parts[kernelpart].name = "kernel";
  280. - parts[kernelpart].offset = kerneladdr;
  281. - parts[kernelpart].size = kernellen;
  282. - curpart++;
  283. - }
  284. -
  285. - if (rootfslen > 0) {
  286. - int rootfspart = curpart;
  287. -
  288. - if (kernellen > 0 && rootfs_first)
  289. - rootfspart--;
  290. - parts[rootfspart].name = "rootfs";
  291. - parts[rootfspart].offset = rootfsaddr;
  292. - parts[rootfspart].size = rootfslen;
  293. - if (sparelen > 0 && !rootfs_first)
  294. - parts[rootfspart].size += sparelen;
  295. - curpart++;
  296. - }
  297. + curpart += parse_bcmtag(master, parts, curpart, imageaddr, imagelen);
  298. if (caldatalen1 > 0) {
  299. if (caldatalen2 > 0)
  300. @@ -217,25 +299,33 @@ static int bcm63xx_parse_cfe_partitions(
  301. /* Global partition "linux" to make easy firmware upgrade */
  302. parts[curpart].name = "linux";
  303. - parts[curpart].offset = cfelen;
  304. - parts[curpart].size = min_not_zero(nvramaddr, caldataaddr1) - cfelen;
  305. + parts[curpart].offset = imageaddr;
  306. + parts[curpart].size = imagelen;
  307. + curpart++;
  308. - for (i = 0; i < nrparts; i++)
  309. + for (i = 0; i < curpart; i++)
  310. pr_info("Partition %d is %s offset %llx and length %llx\n", i,
  311. parts[i].name, parts[i].offset, parts[i].size);
  312. - pr_info("Spare partition is offset %x and length %x\n", spareaddr,
  313. - sparelen);
  314. -
  315. *pparts = parts;
  316. - vfree(buf);
  317. return nrparts;
  318. };
  319. +
  320. +static int bcm63xx_parse_partitions(struct mtd_info *master,
  321. + struct mtd_partition **pparts,
  322. + struct mtd_part_parser_data *data)
  323. +{
  324. + if (mtd_get_of_node(master))
  325. + return bcm63xx_parse_cfe_partitions_of(master, pparts, data);
  326. + else
  327. + return bcm63xx_parse_cfe_partitions(master, pparts, data);
  328. +}
  329. +
  330. static struct mtd_part_parser bcm63xx_cfe_parser = {
  331. .owner = THIS_MODULE,
  332. - .parse_fn = bcm63xx_parse_cfe_partitions,
  333. + .parse_fn = bcm63xx_parse_partitions,
  334. .name = "bcm63xxpart",
  335. };