9
0
Fork 0

svn_rev_234

beginning filesystem support
This commit is contained in:
Sascha Hauer 2007-07-05 18:01:35 +02:00 committed by Sascha Hauer
parent 79bd10153a
commit 0ed157cd19
7 changed files with 244 additions and 139 deletions

View File

@ -5,17 +5,7 @@
#include <driver.h>
#include <malloc.h>
#include <asm-generic/errno.h>
struct partition {
int num;
unsigned long offset;
struct device_d *parent;
struct device_d device;
char name[16];
};
#include <partition.h>
static void dev_del_partitions(struct device_d *dev)
{

12
fs/Kconfig Normal file
View File

@ -0,0 +1,12 @@
menuconfig FS
bool "Filesystem support"
if FS
config FS_CRAMFS
bool
select ZLIB
prompt "cramfs support"
endif

View File

@ -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

View File

@ -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

View File

@ -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;
if (cramfs_read_super (info))
printf("cramfs_ls: %s\n", filename);
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 (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 *) (PART_OFFSET(info) + 512);
if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC))
return 0;
if (cramfs_read_super (dev)) {
printf("no valid cramfs found on %s\n",dev->id);
return -EINVAL;
}
return 1;
return 0;
}
#endif /* CFG_FS_CRAMFS */
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,
}
};
int cramfs_init(void)
{
return register_fs_driver(&cramfs_driver);
}
device_initcall(cramfs_init);

View File

@ -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 */

163
fs/fs.c Normal file
View File

@ -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