summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:35 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:35 +0200
commit0ed157cd19b5b9efe815219c9853300a314f3eed (patch)
treee7efb5c010da88600de6d19d9ed3feec983bf790 /fs
parent79bd10153a001529971d474b79701f324f5c21c4 (diff)
downloadbarebox-0ed157cd19b5b9efe815219c9853300a314f3eed.tar.gz
barebox-0ed157cd19b5b9efe815219c9853300a314f3eed.tar.xz
svn_rev_234
beginning filesystem support
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig12
-rw-r--r--fs/Makefile31
-rw-r--r--fs/cramfs/Makefile51
-rw-r--r--fs/cramfs/cramfs.c106
-rw-r--r--fs/cramfs/uncompress.c4
-rw-r--r--fs/fs.c163
6 files changed, 241 insertions, 126 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
new file mode 100644
index 0000000000..f12b08162e
--- /dev/null
+++ b/fs/Kconfig
@@ -0,0 +1,12 @@
+
+menuconfig FS
+ bool "Filesystem support"
+
+if FS
+
+config FS_CRAMFS
+ bool
+ select ZLIB
+ prompt "cramfs support"
+
+endif
diff --git a/fs/Makefile b/fs/Makefile
index 273d90e011..ceb38fc3de 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -1,29 +1,2 @@
-#
-# (C) Copyright 2000-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-# MA 02111-1307 USA
-#
-#
-
-SUBDIRS := jffs2 cramfs fdos fat reiserfs ext2
-
-$(obj).depend all:
- @for dir in $(SUBDIRS) ; do \
- $(MAKE) -C $$dir $@ ; done
+obj-$(CONFIG_FS_CRAMFS) += cramfs/
+obj-$(CONFIG_FS) += fs.o
diff --git a/fs/cramfs/Makefile b/fs/cramfs/Makefile
index 13c043fcde..4e84a98fe1 100644
--- a/fs/cramfs/Makefile
+++ b/fs/cramfs/Makefile
@@ -1,49 +1,2 @@
-#
-# (C) Copyright 2000-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-# MA 02111-1307 USA
-#
-
-include $(TOPDIR)/config.mk
-
-LIB = $(obj)libcramfs.a
-
-AOBJS =
-COBJS = cramfs.o uncompress.o
-
-SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
-
-#CPPFLAGS +=
-
-all: $(LIB) $(AOBJS)
-
-$(LIB): $(obj).depend $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+obj-y += cramfs.o
+obj-y += uncompress.o
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index 48e7f63aa4..a5f5a5842e 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -26,8 +26,10 @@
#include <common.h>
#include <malloc.h>
-
-#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
+#include <driver.h>
+#include <init.h>
+#include <asm-generic/errno.h>
+#include <fs.h>
#include <asm/byteorder.h>
#include <linux/stat.h>
@@ -42,22 +44,22 @@
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. */
-extern flash_info_t flash_info[];
-#define PART_OFFSET(x) (x->offset + flash_info[x->dev->id->num].start[0])
-
-static int cramfs_read_super (struct part_info *info)
+static int cramfs_read_super (struct device_d *dev)
{
unsigned long root_offset;
- /* Read the first block and get the superblock from it */
- memcpy (&super, (void *) PART_OFFSET(info), sizeof (super));
+ if (read(dev, &super, sizeof (super), 0, 0) < sizeof (super)) {
+ printf("read superblock failed\n");
+ return -EINVAL;
+ }
/* Do sanity checks on the superblock */
if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) {
/* check at 512 byte offset */
- memcpy (&super, (void *) PART_OFFSET(info) + 512, sizeof (super));
+ if (read(dev, &super, sizeof (super), 512, 0) < sizeof (super)) {
+ printf("read superblock failed\n");
+ return -EINVAL;
+ }
if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) {
printf ("cramfs: wrong magic\n");
return -1;
@@ -185,29 +187,32 @@ static int cramfs_uncompress (unsigned long begin, unsigned long offset,
return total_size;
}
-int cramfs_load (char *loadoffset, struct part_info *info, char *filename)
+int cramfs_load (char *loadoffset, struct device_d *dev, const char *filename)
{
unsigned long offset;
-
- if (cramfs_read_super (info))
+ char *f;
+ if (cramfs_read_super (dev))
return -1;
- offset = cramfs_resolve (PART_OFFSET(info),
+ f = strdup(filename);
+ offset = cramfs_resolve (dev->map_base,
CRAMFS_GET_OFFSET (&(super.root)) << 2,
CRAMFS_24 (super.root.size), 0,
- strtok (filename, "/"));
+ strtok (f, "/"));
+
+ free(f);
if (offset <= 0)
return offset;
- return cramfs_uncompress (PART_OFFSET(info), offset,
+ return cramfs_uncompress (dev->map_base, offset,
(unsigned long) loadoffset);
}
-static int cramfs_list_inode (struct part_info *info, unsigned long offset)
+static int cramfs_list_inode (struct device_d *dev, unsigned long offset)
{
struct cramfs_inode *inode = (struct cramfs_inode *)
- (PART_OFFSET(info) + offset);
+ (dev->map_base + offset);
char *name, str[20];
int namelen, nextoff;
@@ -238,7 +243,7 @@ static int cramfs_list_inode (struct part_info *info, unsigned long offset)
unsigned long size = CRAMFS_24 (inode->size);
char *link = malloc (size);
- if (link != NULL && cramfs_uncompress (PART_OFFSET(info), offset,
+ if (link != NULL && cramfs_uncompress (dev->map_base, offset,
(unsigned long) link)
== size)
printf (" -> %*.*s\n", (int) size, (int) size, link);
@@ -252,13 +257,16 @@ static int cramfs_list_inode (struct part_info *info, unsigned long offset)
return nextoff;
}
-int cramfs_ls (struct part_info *info, char *filename)
+int cramfs_ls (struct device_d *dev, const char *filename)
{
struct cramfs_inode *inode;
unsigned long inodeoffset = 0, nextoffset;
unsigned long offset, size;
+ char *f;
+
+ printf("cramfs_ls: %s\n", filename);
- if (cramfs_read_super (info))
+ if (cramfs_read_super (dev))
return -1;
if (strlen (filename) == 0 || !strcmp (filename, "/")) {
@@ -266,20 +274,21 @@ int cramfs_ls (struct part_info *info, char *filename)
offset = CRAMFS_GET_OFFSET (&(super.root)) << 2;
size = CRAMFS_24 (super.root.size);
} else {
+ f = strdup(filename);
/* Resolve the path */
- offset = cramfs_resolve (PART_OFFSET(info),
+ offset = cramfs_resolve (dev->map_base,
CRAMFS_GET_OFFSET (&(super.root)) <<
2, CRAMFS_24 (super.root.size), 1,
- strtok (filename, "/"));
-
+ strtok (f, "/"));
+ free(f);
if (offset <= 0)
return offset;
/* Resolving was successful. Examine the inode */
- inode = (struct cramfs_inode *) (PART_OFFSET(info) + offset);
+ inode = (struct cramfs_inode *) (dev->map_base + 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);
+ return (cramfs_list_inode (dev, offset) > 0);
}
/* It's a directory. List files within */
@@ -289,21 +298,21 @@ int cramfs_ls (struct part_info *info, char *filename)
/* List the given directory */
while (inodeoffset < size) {
- inode = (struct cramfs_inode *) (PART_OFFSET(info) + offset +
+ inode = (struct cramfs_inode *) (dev->map_base + offset +
inodeoffset);
- nextoffset = cramfs_list_inode (info, offset + inodeoffset);
+ nextoffset = cramfs_list_inode (dev, offset + inodeoffset);
if (nextoffset == 0)
break;
inodeoffset += sizeof (struct cramfs_inode) + nextoffset;
}
- return 1;
+ return 0;
}
-int cramfs_info (struct part_info *info)
+int cramfs_info (struct device_d *dev)
{
- if (cramfs_read_super (info))
+ if (cramfs_read_super (dev))
return 0;
printf ("size: 0x%x (%u)\n", super.size, super.size);
@@ -327,21 +336,30 @@ int cramfs_info (struct part_info *info)
return 1;
}
-int cramfs_check (struct part_info *info)
+int cramfs_probe(struct device_d *dev)
{
- struct cramfs_super *sb;
+ if (cramfs_read_super (dev)) {
+ printf("no valid cramfs found on %s\n",dev->id);
+ return -EINVAL;
+ }
- if (info->dev->id->type != MTD_DEV_TYPE_NOR)
- return 0;
+ 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 *) (PART_OFFSET(info) + 512);
- if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC))
- return 0;
+static struct fs_driver_d cramfs_driver = {
+ .type = FS_TYPE_CRAMFS,
+ .probe = cramfs_probe,
+ .ls = cramfs_ls,
+ .drv = {
+ .type = DEVICE_TYPE_FS,
+ .name = "cramfs",
+ .driver_data = &cramfs_driver,
}
- return 1;
+};
+
+int cramfs_init(void)
+{
+ return register_fs_driver(&cramfs_driver);
}
-#endif /* CFG_FS_CRAMFS */
+device_initcall(cramfs_init);
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
index 170832a9c5..659869bfe4 100644
--- a/fs/cramfs/uncompress.c
+++ b/fs/cramfs/uncompress.c
@@ -25,8 +25,6 @@
#include <watchdog.h>
#include <zlib.h>
-#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
-
static z_stream stream;
#define ZALLOC_ALIGNMENT 16
@@ -102,5 +100,3 @@ int cramfs_uncompress_exit (void)
inflateEnd (&stream);
return 0;
}
-
-#endif /* CFG_FS_CRAMFS */
diff --git a/fs/fs.c b/fs/fs.c
new file mode 100644
index 0000000000..824645bca3
--- /dev/null
+++ b/fs/fs.c
@@ -0,0 +1,163 @@
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <driver.h>
+#include <errno.h>
+#include <asm-generic/errno.h>
+#include <malloc.h>
+#include <linux/stat.h>
+
+char *mkmodestr(unsigned long mode, char *str)
+{
+ static const char *l = "xwr";
+ int mask = 1, i;
+ char c;
+
+ switch (mode & S_IFMT) {
+ case S_IFDIR: str[0] = 'd'; break;
+ case S_IFBLK: str[0] = 'b'; break;
+ case S_IFCHR: str[0] = 'c'; break;
+ case S_IFIFO: str[0] = 'f'; break;
+ case S_IFLNK: str[0] = 'l'; break;
+ case S_IFSOCK: str[0] = 's'; break;
+ case S_IFREG: str[0] = '-'; break;
+ default: str[0] = '?';
+ }
+
+ for(i = 0; i < 9; i++) {
+ c = l[i%3];
+ str[9-i] = (mode & mask)?c:'-';
+ mask = mask<<1;
+ }
+
+ if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S';
+ if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S';
+ if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T';
+ str[10] = '\0';
+ return str;
+}
+
+static int fs_probe(struct device_d *dev)
+{
+ struct fs_device_d *fs_dev = dev->platform_data;
+
+ return fs_dev->driver->probe(fs_dev->parent);
+}
+
+int register_fs_driver(struct fs_driver_d *new_fs_drv)
+{
+ new_fs_drv->drv.probe = fs_probe;
+ new_fs_drv->drv.driver_data = new_fs_drv;
+
+ return register_driver(&new_fs_drv->drv);
+}
+
+int register_filesystem(struct device_d *dev, char *fsname)
+{
+ struct fs_device_d *new_fs_dev;
+ struct driver_d *drv;
+ struct fs_driver_d *fs_drv;
+
+ drv = get_driver_by_name(fsname);
+ if (!drv) {
+ printf("no driver for fstype %s\n", fsname);
+ return -EINVAL;
+ }
+
+ if (drv->type != DEVICE_TYPE_FS) {
+ printf("driver %s is no filesystem driver\n");
+ return -EINVAL;
+ }
+
+ new_fs_dev = malloc(sizeof(struct fs_device_d));
+
+ fs_drv = drv->driver_data;
+
+ new_fs_dev->driver = fs_drv;
+ new_fs_dev->parent = dev;
+ new_fs_dev->dev.platform_data = new_fs_dev;
+ new_fs_dev->dev.type = DEVICE_TYPE_FS;
+ sprintf(new_fs_dev->dev.name, "%s", fsname);
+ sprintf(new_fs_dev->dev.id, "%s", "fs0");
+
+ register_device(&new_fs_dev->dev);
+
+ if (!new_fs_dev->dev.driver) {
+ unregister_device(&new_fs_dev->dev);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int ls(struct device_d *dev, const char *filename)
+{
+ struct fs_device_d *fs_dev;
+
+ if (!dev || dev->type != DEVICE_TYPE_FS || !dev->driver)
+ return -ENODEV;
+
+ fs_dev = dev->platform_data;
+
+ return fs_dev->driver->ls(fs_dev->parent, filename);
+}
+
+/* addfs <device> <fstype> */
+int do_addfs ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ struct device_d *dev;
+ int ret = 0;
+
+ if (argc != 3) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ dev = get_device_by_id(argv[1]);
+ if (!dev) {
+ printf("no such device: %s\n", argv[1]);
+ return -ENODEV;
+ }
+
+ if ((ret = register_filesystem(dev, argv[2]))) {
+ perror("register_device", ret);
+ return 1;
+ }
+ return 0;
+}
+
+int do_ls ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ struct device_d *dev;
+ char *endp;
+ int ret;
+
+ dev = device_from_spec_str(argv[1], &endp);
+
+ ret = ls(dev, endp);
+ if (ret) {
+ perror("ls", ret);
+ return 1;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ ls, 2, 0, do_ls,
+ "ls - list a file or directory\n",
+ "<dev:path> list files on device"
+);
+
+U_BOOT_CMD(
+ addfs, 3, 0, do_addfs,
+ "addfs - add a filesystem to a device\n",
+ " <device> <type> add a filesystem of type 'type' on the given device"
+);
+#if 0
+U_BOOT_CMD(
+ delfs, 2, 0, do_delfs,
+ "delfs - delete a filesystem from a device\n",
+ ""
+);
+#endif