]> Git Repo - J-u-boot.git/blobdiff - fs/cramfs/cramfs.c
common: Drop flash.h from common header
[J-u-boot.git] / fs / cramfs / cramfs.c
index 98ff5672692c56bfbe838c35caea4131fcab021e..7ef48bbc064c46a87fbb6156843de518e53e61ce 100644 (file)
  */
 
 #include <common.h>
+#include <flash.h>
 #include <malloc.h>
-
-#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
-
 #include <asm/byteorder.h>
 #include <linux/stat.h>
 #include <jffs2/jffs2.h>
 
 struct cramfs_super super;
 
+/* CPU address space offset calculation macro, struct part_info offset is
+ * device address space offset, so we need to shift it by a device start address. */
+#if defined(CONFIG_MTD_NOR_FLASH)
+extern flash_info_t flash_info[];
+#define PART_OFFSET(x) ((ulong)x->offset + \
+                        flash_info[x->dev->id->num].start[0])
+#else
+#define PART_OFFSET(x) ((ulong)x->offset)
+#endif
+
+static int cramfs_uncompress (unsigned long begin, unsigned long offset,
+                             unsigned long loadoffset);
+
 static int cramfs_read_super (struct part_info *info)
 {
        unsigned long root_offset;
 
        /* Read the first block and get the superblock from it */
-       memcpy (&super, (void *) info->offset, sizeof (super));
+       memcpy (&super, (void *) PART_OFFSET(info), sizeof (super));
 
        /* Do sanity checks on the superblock */
        if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) {
                /* check at 512 byte offset */
-               memcpy (&super, (void *) info->offset + 512, sizeof (super));
+               memcpy (&super, (void *) PART_OFFSET(info) + 512, sizeof (super));
                if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) {
                        printf ("cramfs: wrong magic\n");
                        return -1;
@@ -87,7 +98,23 @@ static int cramfs_read_super (struct part_info *info)
        return 0;
 }
 
-static unsigned long cramfs_resolve (char *begin, unsigned long offset,
+/* Unpack to an allocated buffer, trusting in the inode's size field. */
+static char *cramfs_uncompress_link (unsigned long begin, unsigned long offset)
+{
+       struct cramfs_inode *inode = (struct cramfs_inode *)(begin + offset);
+       unsigned long size = CRAMFS_24 (inode->size);
+       char *link = malloc (size + 1);
+
+       if (!link || cramfs_uncompress (begin, offset, (unsigned long)link) != size) {
+               free (link);
+               link = NULL;
+       } else {
+               link[size] = '\0';
+       }
+       return link;
+}
+
+static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset,
                                     unsigned long size, int raw,
                                     char *filename)
 {
@@ -120,7 +147,8 @@ static unsigned long cramfs_resolve (char *begin, unsigned long offset,
                        namelen--;
                }
 
-               if (!strncmp (filename, name, namelen)) {
+               if (!strncmp(filename, name, namelen) &&
+                   (namelen == strlen(filename))) {
                        char *p = strtok (NULL, "/");
 
                        if (raw && (p == NULL || *p == '\0'))
@@ -135,6 +163,33 @@ static unsigned long cramfs_resolve (char *begin, unsigned long offset,
                                                       p);
                        } else if (S_ISREG (CRAMFS_16 (inode->mode))) {
                                return offset + inodeoffset;
+                       } else if (S_ISLNK (CRAMFS_16 (inode->mode))) {
+                               unsigned long ret;
+                               char *link;
+                               if (p && strlen(p)) {
+                                       printf ("unsupported symlink to \
+                                                non-terminal path\n");
+                                       return 0;
+                               }
+                               link = cramfs_uncompress_link (begin,
+                                               offset + inodeoffset);
+                               if (!link) {
+                                       printf ("%*.*s: Error reading link\n",
+                                               namelen, namelen, name);
+                                       return 0;
+                               } else if (link[0] == '/') {
+                                       printf ("unsupported symlink to \
+                                                absolute path\n");
+                                       free (link);
+                                       return 0;
+                               }
+                               ret = cramfs_resolve (begin,
+                                                     offset,
+                                                     size,
+                                                     raw,
+                                                     strtok(link, "/"));
+                               free (link);
+                               return ret;
                        } else {
                                printf ("%*.*s: unsupported file type (%x)\n",
                                        namelen, namelen, name,
@@ -150,11 +205,11 @@ static unsigned long cramfs_resolve (char *begin, unsigned long offset,
        return 0;
 }
 
-static int cramfs_uncompress (char *begin, unsigned long offset,
+static int cramfs_uncompress (unsigned long begin, unsigned long offset,
                              unsigned long loadoffset)
 {
        struct cramfs_inode *inode = (struct cramfs_inode *) (begin + offset);
-       unsigned long *block_ptrs = (unsigned long *)
+       u32 *block_ptrs = (u32 *)
                (begin + (CRAMFS_GET_OFFSET (inode) << 2));
        unsigned long curr_block = (CRAMFS_GET_OFFSET (inode) +
                                    (((CRAMFS_24 (inode->size)) +
@@ -187,7 +242,7 @@ int cramfs_load (char *loadoffset, struct part_info *info, char *filename)
        if (cramfs_read_super (info))
                return -1;
 
-       offset = cramfs_resolve (info->offset,
+       offset = cramfs_resolve (PART_OFFSET(info),
                                 CRAMFS_GET_OFFSET (&(super.root)) << 2,
                                 CRAMFS_24 (super.root.size), 0,
                                 strtok (filename, "/"));
@@ -195,14 +250,14 @@ int cramfs_load (char *loadoffset, struct part_info *info, char *filename)
        if (offset <= 0)
                return offset;
 
-       return cramfs_uncompress (info->offset, offset,
+       return cramfs_uncompress (PART_OFFSET(info), offset,
                                  (unsigned long) loadoffset);
 }
 
 static int cramfs_list_inode (struct part_info *info, unsigned long offset)
 {
        struct cramfs_inode *inode = (struct cramfs_inode *)
-               (info->offset + offset);
+               (PART_OFFSET(info) + offset);
        char *name, str[20];
        int namelen, nextoff;
 
@@ -227,20 +282,12 @@ static int cramfs_list_inode (struct part_info *info, unsigned long offset)
                CRAMFS_24 (inode->size), namelen, namelen, name);
 
        if ((CRAMFS_16 (inode->mode) & S_IFMT) == S_IFLNK) {
-               /* symbolic link.
-                * Unpack the link target, trusting in the inode's size field.
-                */
-               unsigned long size = CRAMFS_24 (inode->size);
-               char *link = malloc (size);
-
-               if (link != NULL && cramfs_uncompress (info->offset, offset,
-                                                      (unsigned long) link)
-                   == size)
-                       printf (" -> %*.*s\n", (int) size, (int) size, link);
+               char *link = cramfs_uncompress_link (PART_OFFSET(info), offset);
+               if (link)
+                       printf (" -> %s\n", link);
                else
                        printf (" [Error reading link]\n");
-               if (link)
-                       free (link);
+               free (link);
        } else
                printf ("\n");
 
@@ -262,7 +309,7 @@ int cramfs_ls (struct part_info *info, char *filename)
                size = CRAMFS_24 (super.root.size);
        } else {
                /* Resolve the path */
-               offset = cramfs_resolve (info->offset,
+               offset = cramfs_resolve (PART_OFFSET(info),
                                         CRAMFS_GET_OFFSET (&(super.root)) <<
                                         2, CRAMFS_24 (super.root.size), 1,
                                         strtok (filename, "/"));
@@ -271,7 +318,7 @@ int cramfs_ls (struct part_info *info, char *filename)
                        return offset;
 
                /* Resolving was successful. Examine the inode */
-               inode = (struct cramfs_inode *) (info->offset + offset);
+               inode = (struct cramfs_inode *) (PART_OFFSET(info) + offset);
                if (!S_ISDIR (CRAMFS_16 (inode->mode))) {
                        /* It's not a directory - list it, and that's that */
                        return (cramfs_list_inode (info, offset) > 0);
@@ -284,7 +331,7 @@ int cramfs_ls (struct part_info *info, char *filename)
 
        /* List the given directory */
        while (inodeoffset < size) {
-               inode = (struct cramfs_inode *) (info->offset + offset +
+               inode = (struct cramfs_inode *) (PART_OFFSET(info) + offset +
                                                 inodeoffset);
 
                nextoffset = cramfs_list_inode (info, offset + inodeoffset);
@@ -324,16 +371,17 @@ int cramfs_info (struct part_info *info)
 
 int cramfs_check (struct part_info *info)
 {
-       struct cramfs_super *sb = (struct cramfs_super *) info->offset;
+       struct cramfs_super *sb;
 
+       if (info->dev->id->type != MTD_DEV_TYPE_NOR)
+               return 0;
+
+       sb = (struct cramfs_super *) PART_OFFSET(info);
        if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC)) {
                /* check at 512 byte offset */
-               sb = (struct cramfs_super *) (info->offset + 512);
-               if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC)) {
+               sb = (struct cramfs_super *) (PART_OFFSET(info) + 512);
+               if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC))
                        return 0;
-               }
        }
        return 1;
 }
-
-#endif /* CFG_FS_CRAMFS */
This page took 0.033777 seconds and 4 git commands to generate.