cybertan_part.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (C) 2009 Christian Daniel <cd@maintech.de>
  3. * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18. *
  19. * TRX flash partition table.
  20. * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
  21. *
  22. */
  23. #include <linux/kernel.h>
  24. #include <linux/module.h>
  25. #include <linux/slab.h>
  26. #include <linux/vmalloc.h>
  27. #include <linux/mtd/mtd.h>
  28. #include <linux/mtd/partitions.h>
  29. struct cybertan_header {
  30. char magic[4];
  31. u8 res1[4];
  32. char fw_date[3];
  33. char fw_ver[3];
  34. char id[4];
  35. char hw_ver;
  36. char unused;
  37. u8 flags[2];
  38. u8 res2[10];
  39. };
  40. #define TRX_PARTS 6
  41. #define TRX_MAGIC 0x30524448
  42. #define TRX_MAX_OFFSET 3
  43. struct trx_header {
  44. uint32_t magic; /* "HDR0" */
  45. uint32_t len; /* Length of file including header */
  46. uint32_t crc32; /* 32-bit CRC from flag_version to end of file */
  47. uint32_t flag_version; /* 0:15 flags, 16:31 version */
  48. uint32_t offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
  49. };
  50. #define IH_MAGIC 0x27051956 /* Image Magic Number */
  51. #define IH_NMLEN 32 /* Image Name Length */
  52. struct uimage_header {
  53. uint32_t ih_magic; /* Image Header Magic Number */
  54. uint32_t ih_hcrc; /* Image Header CRC Checksum */
  55. uint32_t ih_time; /* Image Creation Timestamp */
  56. uint32_t ih_size; /* Image Data Size */
  57. uint32_t ih_load; /* Data» Load Address */
  58. uint32_t ih_ep; /* Entry Point Address */
  59. uint32_t ih_dcrc; /* Image Data CRC Checksum */
  60. uint8_t ih_os; /* Operating System */
  61. uint8_t ih_arch; /* CPU architecture */
  62. uint8_t ih_type; /* Image Type */
  63. uint8_t ih_comp; /* Compression Type */
  64. uint8_t ih_name[IH_NMLEN]; /* Image Name */
  65. };
  66. struct firmware_header {
  67. struct cybertan_header cybertan;
  68. struct trx_header trx;
  69. struct uimage_header uimage;
  70. } __packed;
  71. #define UBOOT_LEN 0x40000
  72. #define ART_LEN 0x10000
  73. #define NVRAM_LEN 0x10000
  74. static int cybertan_parse_partitions(struct mtd_info *master,
  75. struct mtd_partition **pparts,
  76. struct mtd_part_parser_data *data)
  77. {
  78. struct firmware_header *header;
  79. struct trx_header *theader;
  80. struct uimage_header *uheader;
  81. struct mtd_partition *trx_parts;
  82. size_t retlen;
  83. unsigned int kernel_len;
  84. unsigned int uboot_len;
  85. unsigned int nvram_len;
  86. unsigned int art_len;
  87. int ret;
  88. uboot_len = max_t(unsigned int, master->erasesize, UBOOT_LEN);
  89. nvram_len = max_t(unsigned int, master->erasesize, NVRAM_LEN);
  90. art_len = max_t(unsigned int, master->erasesize, ART_LEN);
  91. trx_parts = kzalloc(TRX_PARTS * sizeof(struct mtd_partition),
  92. GFP_KERNEL);
  93. if (!trx_parts) {
  94. ret = -ENOMEM;
  95. goto out;
  96. }
  97. header = vmalloc(sizeof(*header));
  98. if (!header) {
  99. return -ENOMEM;
  100. goto free_parts;
  101. }
  102. ret = mtd_read(master, uboot_len, sizeof(*header),
  103. &retlen, (void *) header);
  104. if (ret)
  105. goto free_hdr;
  106. if (retlen != sizeof(*header)) {
  107. ret = -EIO;
  108. goto free_hdr;
  109. }
  110. theader = &header->trx;
  111. if (le32_to_cpu(theader->magic) != TRX_MAGIC) {
  112. printk(KERN_NOTICE "%s: no TRX header found\n", master->name);
  113. goto free_hdr;
  114. }
  115. uheader = &header->uimage;
  116. if (uheader->ih_magic != IH_MAGIC) {
  117. printk(KERN_NOTICE "%s: no uImage found\n", master->name);
  118. goto free_hdr;
  119. }
  120. kernel_len = le32_to_cpu(theader->offsets[1]) +
  121. sizeof(struct cybertan_header);
  122. trx_parts[0].name = "u-boot";
  123. trx_parts[0].offset = 0;
  124. trx_parts[0].size = uboot_len;
  125. trx_parts[0].mask_flags = MTD_WRITEABLE;
  126. trx_parts[1].name = "kernel";
  127. trx_parts[1].offset = trx_parts[0].offset + trx_parts[0].size;
  128. trx_parts[1].size = kernel_len;
  129. trx_parts[1].mask_flags = 0;
  130. trx_parts[2].name = "rootfs";
  131. trx_parts[2].offset = trx_parts[1].offset + trx_parts[1].size;
  132. trx_parts[2].size = master->size - uboot_len - nvram_len - art_len -
  133. trx_parts[1].size;
  134. trx_parts[2].mask_flags = 0;
  135. trx_parts[3].name = "nvram";
  136. trx_parts[3].offset = master->size - nvram_len - art_len;
  137. trx_parts[3].size = nvram_len;
  138. trx_parts[3].mask_flags = MTD_WRITEABLE;
  139. trx_parts[4].name = "art";
  140. trx_parts[4].offset = master->size - art_len;
  141. trx_parts[4].size = art_len;
  142. trx_parts[4].mask_flags = MTD_WRITEABLE;
  143. trx_parts[5].name = "firmware";
  144. trx_parts[5].offset = uboot_len;
  145. trx_parts[5].size = master->size - uboot_len - nvram_len - art_len;
  146. trx_parts[5].mask_flags = 0;
  147. vfree(header);
  148. *pparts = trx_parts;
  149. return TRX_PARTS;
  150. free_hdr:
  151. vfree(header);
  152. free_parts:
  153. kfree(trx_parts);
  154. out:
  155. return ret;
  156. }
  157. static struct mtd_part_parser cybertan_parser = {
  158. .owner = THIS_MODULE,
  159. .parse_fn = cybertan_parse_partitions,
  160. .name = "cybertan",
  161. };
  162. static int __init cybertan_parser_init(void)
  163. {
  164. register_mtd_parser(&cybertan_parser);
  165. return 0;
  166. }
  167. module_init(cybertan_parser_init);
  168. MODULE_LICENSE("GPL");
  169. MODULE_AUTHOR("Christian Daniel <cd@maintech.de>");