dm: spi: Return 0 if driver does not implement ops->cs_info
[oweals/u-boot.git] / fs / cramfs / cramfs.c
index 369d1f16740a2abbb040842f994c694f966f8234..228f599d44bbca3e7c067ab5ae86ce9981e10a5e 100644 (file)
@@ -26,9 +26,6 @@
 
 #include <common.h>
 #include <malloc.h>
-
-#if defined(CONFIG_CMD_JFFS2)
-
 #include <asm/byteorder.h>
 #include <linux/stat.h>
 #include <jffs2/jffs2.h>
@@ -44,8 +41,16 @@ 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) (x->offset + flash_info[x->dev->id->num].start[0])
+#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)
 {
@@ -92,6 +97,22 @@ static int cramfs_read_super (struct part_info *info)
        return 0;
 }
 
+/* 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)
@@ -125,7 +146,8 @@ static unsigned long cramfs_resolve (unsigned long 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'))
@@ -140,6 +162,33 @@ static unsigned long cramfs_resolve (unsigned long 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,
@@ -159,7 +208,7 @@ 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)) +
@@ -232,20 +281,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 (PART_OFFSET(info), 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");
 
@@ -343,5 +384,3 @@ int cramfs_check (struct part_info *info)
        }
        return 1;
 }
-
-#endif /* CFG_FS_CRAMFS */