romfs.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * (C) Copyright 2007 Michal Simek
  3. *
  4. * Michal SIMEK <monstr@monstr.eu>
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. */
  24. #include <common.h>
  25. #include <malloc.h>
  26. #include <command.h>
  27. #if defined(CONFIG_CMD_JFFS2)
  28. #include <asm/byteorder.h>
  29. #include <linux/stat.h>
  30. #include <jffs2/jffs2.h>
  31. #include <jffs2/load_kernel.h>
  32. #undef DEBUG_ROMFS
  33. /* ROMFS superblock */
  34. struct romfs_super {
  35. u32 word0;
  36. u32 word1;
  37. u32 size;
  38. u32 checksum;
  39. char name[0];
  40. };
  41. struct romfs_inode {
  42. u32 next;
  43. u32 spec;
  44. u32 size;
  45. u32 checksum;
  46. char name[0];
  47. };
  48. extern flash_info_t flash_info[];
  49. #define PART_OFFSET(x) (x->offset + flash_info[x->dev->id->num].start[0])
  50. #define ALIGN(x) (((x) & 0xfffffff0))
  51. #define HEADERSIZE(name) (0x20 + ALIGN(strlen(name)))
  52. static unsigned long romfs_resolve (unsigned long begin, unsigned long offset,
  53. unsigned long size, int raw, char *filename)
  54. {
  55. unsigned long inodeoffset = 0, nextoffset;
  56. struct romfs_inode *inode;
  57. #ifdef DEBUG_ROMFS
  58. printf ("ROMFS_resolve: begin 0x%x, offset 0x%x, size 0x%x, raw 0x%x, \
  59. filename %s\n", begin, offset, size, raw, filename);
  60. #endif
  61. while (inodeoffset < size) {
  62. inode = (struct romfs_inode *)(begin + offset + inodeoffset);
  63. offset = 0;
  64. nextoffset = ALIGN (inode->next);
  65. #ifdef DEBUG_ROMFS
  66. printf("inode 0x%x, name %s - len 0x%x, next inode 0x%x, \
  67. compare names 0x%x\n",
  68. inode, inode->name, strlen (inode->name), nextoffset,
  69. strncmp (filename, inode->name, strlen (filename)));
  70. #endif
  71. if (!strncmp (filename, inode->name, strlen (inode->name))) {
  72. char *p = strtok (NULL, "/");
  73. if (raw && (p == NULL || *p == '\0')) {
  74. return offset + inodeoffset;
  75. }
  76. return romfs_resolve (begin,
  77. inodeoffset + HEADERSIZE (inode->name),
  78. size, raw, p);
  79. }
  80. inodeoffset = nextoffset;
  81. }
  82. printf ("can't find corresponding entry\n");
  83. return 0;
  84. }
  85. int romfs_load (char *loadoffset, struct part_info *info, char *filename)
  86. {
  87. struct romfs_inode *inode;
  88. struct romfs_super *sb;
  89. char *data;
  90. int pocet;
  91. sb = (struct romfs_super *) PART_OFFSET (info);
  92. unsigned long offset;
  93. offset = romfs_resolve (PART_OFFSET (info), HEADERSIZE (sb->name),
  94. sb->size, 1, strtok (filename, "/"));
  95. if (offset <= 0)
  96. return offset;
  97. inode = (struct romfs_inode *)(PART_OFFSET (info) + offset);
  98. data = (char *)((int)inode + HEADERSIZE (inode->name));
  99. pocet = inode->size;
  100. while (pocet--) {
  101. *loadoffset++ = *data++;
  102. }
  103. return inode->size;
  104. }
  105. static int romfs_list_inode (struct part_info *info, unsigned long offset)
  106. {
  107. struct romfs_inode *inode =
  108. (struct romfs_inode *)(PART_OFFSET (info) + offset);
  109. struct romfs_inode *hardlink = NULL;
  110. char str[3], *data;
  111. /*
  112. * mapping spec.info means
  113. * 0 hard link link destination [file header]
  114. * 1 directory first file's header
  115. * 2 regular file unused, must be zero [MBZ]
  116. * 3 symbolic link unused, MBZ (file data is the link content)
  117. * 4 block device 16/16 bits major/minor number
  118. * 5 char device - " -
  119. * 6 socket unused, MBZ
  120. * 7 fifo unused, MBZ
  121. */
  122. char attributes[] = "hdflbcsp";
  123. str[0] = attributes[inode->next & 0x7];
  124. str[1] = (inode->next & 0x8) ? 'x' : '-';
  125. str[2] = '\0';
  126. if ((str[0] == 'b') || (str[0] == 'c')) {
  127. #ifdef DEBUG_ROMFS
  128. printf (" %s %3d,%3d %12s 0x%08x 0x%08x", str,
  129. (inode->spec & 0xffff0000) >> 16,
  130. inode->spec & 0x0000ffff, inode->name, inode,
  131. inode->spec);
  132. #else
  133. printf (" %s %3d,%3d %12s", str,
  134. (inode->spec & 0xffff0000) >> 16,
  135. inode->spec & 0x0000ffff);
  136. #endif
  137. } else {
  138. #ifdef DEBUG_ROMFS
  139. printf (" %s %7d %12s 0x%08x 0x%08x", str, inode->size,
  140. inode->name, inode, inode->spec);
  141. #else
  142. printf (" %s %7d %12s", str, inode->size, inode->name);
  143. #endif
  144. if (str[0] == 'l') {
  145. data = (char *)((int)inode + HEADERSIZE (inode->name));
  146. puts (" -> ");
  147. puts (data);
  148. }
  149. if (str[0] == 'h') {
  150. hardlink = (struct romfs_inode *)(PART_OFFSET (info) +
  151. inode->spec);
  152. puts (" -> ");
  153. puts (hardlink->name);
  154. }
  155. }
  156. puts ("\n");
  157. return ALIGN (inode->next);
  158. }
  159. int romfs_ls (struct part_info *info, char *filename)
  160. {
  161. struct romfs_inode *inode;
  162. unsigned long inodeoffset = 0, nextoffset;
  163. unsigned long offset, size;
  164. struct romfs_super *sb;
  165. sb = (struct romfs_super *)PART_OFFSET (info);
  166. if (strlen (filename) == 0 || !strcmp (filename, "/")) {
  167. offset = HEADERSIZE (sb->name);
  168. size = sb->size;
  169. } else {
  170. offset = romfs_resolve (PART_OFFSET (info),
  171. HEADERSIZE (sb->name), sb->size, 1,
  172. strtok (filename, "/"));
  173. if (offset == 0) {
  174. return offset;
  175. }
  176. inode = (struct romfs_inode *)(PART_OFFSET (info) + offset);
  177. if ((inode->next & 0x7) != 1) {
  178. return (romfs_list_inode (info, offset) > 0);
  179. }
  180. size = sb->size;
  181. offset = offset + HEADERSIZE (inode->name);
  182. }
  183. inodeoffset = offset + inodeoffset;
  184. while (inodeoffset < size) {
  185. nextoffset = romfs_list_inode (info, inodeoffset);
  186. if (nextoffset == 0)
  187. break;
  188. inodeoffset = nextoffset;
  189. }
  190. return 1;
  191. }
  192. int romfs_info (struct part_info *info)
  193. {
  194. struct romfs_super *sb;
  195. sb = (struct romfs_super *)PART_OFFSET (info);
  196. printf ("name: \t\t%s, len %d B\n", sb->name, strlen (sb->name));
  197. printf ("size of SB:\t%d B\n", HEADERSIZE (sb->name));
  198. printf ("full size:\t%d B\n", sb->size);
  199. printf ("checksum:\t0x%x\n", sb->checksum);
  200. return 0;
  201. }
  202. int romfs_check (struct part_info *info)
  203. {
  204. struct romfs_super *sb;
  205. if (info->dev->id->type != MTD_DEV_TYPE_NOR)
  206. return 0;
  207. sb = (struct romfs_super *)PART_OFFSET (info);
  208. if ((sb->word0 != 0x2D726F6D) || (sb->word1 != 0x3166732D)) {
  209. return 0;
  210. }
  211. return 1;
  212. }
  213. #endif