diff options
author | Greg Watson <jarrah@users.sourceforge.net> | 2004-03-13 03:09:57 +0000 |
---|---|---|
committer | Greg Watson <jarrah@users.sourceforge.net> | 2004-03-13 03:09:57 +0000 |
commit | b9f5c112ccd0e39b0652ba8496e2ebd0cb0c5fb8 (patch) | |
tree | 1c81c096a253ab9cd1b5d3e6a76ce952d100f164 /src/stream/fs/vfs.c | |
parent | fc2ae8ee9f3b90876d30d80ffedaefa3fcb243f2 (diff) |
filesystem support
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1398 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/stream/fs/vfs.c')
-rw-r--r-- | src/stream/fs/vfs.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/stream/fs/vfs.c b/src/stream/fs/vfs.c new file mode 100644 index 0000000000..401867caec --- /dev/null +++ b/src/stream/fs/vfs.c @@ -0,0 +1,190 @@ +/* Interface between GRUB's fs drivers and application code */ + +#include <console/console.h> +#include <fs/fs.h> +#include <string.h> +#include <stdlib.h> + +int filepos; +int filemax; +fs_error_t errnum; +void (*disk_read_hook) (int, int, int); +void (*disk_read_func) (int, int, int); +char FSYS_BUF[FSYS_BUFLEN]; +int fsmax; + +struct fsys_entry { + char *name; + int (*mount_func) (void); + int (*read_func) (char *buf, int len); + int (*dir_func) (char *dirname); + void (*close_func) (void); + int (*embed_func) (int *start_sector, int needed_sectors); +}; + +struct fsys_entry fsys_table[] = { +# ifdef CONFIG_FS_FAT + {"fat", fat_mount, fat_read, fat_dir, 0, 0}, +# endif +# if CONFIG_FS_EXT2 == 1 + {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0}, +# endif +# ifdef CONFIG_FS_MINIX + {"minix", minix_mount, minix_read, minix_dir, 0, 0}, +# endif +# ifdef CONFIG_FS_REISERFS + {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, + reiserfs_embed}, +# endif +# ifdef CONFIG_FS_JFS + {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed}, +# endif +# ifdef CONFIG_FS_XFS + {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0}, +# endif +# if CONFIG_FS_ISO9660 == 1 + {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0}, +# endif +}; + +/* NULLFS is used to read images from raw device */ +static int nullfs_dir(char *name) +{ + uint64_t dev_size; + + if (name) { + printk_debug("can't have a named file\n"); + return 0; + } + + dev_size = (uint64_t) part_length << 9; + /* GRUB code doesn't like 2GB or bigger files */ + if (dev_size > 0x7fffffff) + dev_size = 0x7fffffff; + filemax = dev_size; + return 1; +} + +static int nullfs_read(char *buf, int len) +{ + if (devread(filepos>>9, filepos&0x1ff, len, buf)) { + filepos += len; + return len; + } else + return 0; +} + +static struct fsys_entry nullfs = + {"nullfs", 0, nullfs_read, nullfs_dir, 0, 0}; + +static struct fsys_entry *fsys; + +int mount_fs(void) +{ + int i; + + for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) { + if (fsys_table[i].mount_func()) { + fsys = &fsys_table[i]; + printk_info("Mounted %s\n", fsys->name); + return 1; + } + } + fsys = 0; + printk_info("Unknown filesystem type\n"); + return 0; +} + +int file_open(const char *filename) +{ + char *dev = 0; + const char *path; + int len; + int retval = 0; + int reopen; + + path = strchr(filename, ':'); + if (path) { + len = path - filename; + path++; + dev = malloc(len + 1); + memcpy(dev, filename, len); + dev[len] = '\0'; + } else { + /* No colon is given. Is this device or filename? */ + if (filename[0] == '/') { + /* Anything starts with '/' must be a filename */ + dev = 0; + path = filename; + } else { + dev = strdup(filename); + path = 0; + } + } + printk_debug("dev=%s, path=%s\n", dev, path); + + if (dev && dev[0]) { + if (!devopen(dev, &reopen)) { + fsys = 0; + goto out; + } + if (!reopen) + fsys = 0; + } + + if (path) { + if (!fsys || fsys==&nullfs) { + if (!mount_fs()) + goto out; + } + using_devsize = 0; + if (!path[0]) { + printk_info("No filename is given\n"); + goto out; + } + } else + fsys = &nullfs; + + filepos = 0; + errnum = 0; + if (!fsys->dir_func((char *) path)) { + printk_info("File not found\n"); + goto out; + } + retval = 1; +out: + if (dev) + free(dev); + return retval; +} + +int file_read(void *buf, unsigned long len) +{ + if (filepos < 0 || filepos > filemax) + filepos = filemax; + if (len < 0 || len > filemax-filepos) + len = filemax - filepos; + errnum = 0; + return fsys->read_func(buf, len); +} + +int file_seek(unsigned long offset) +{ + filepos = offset; + return filepos; +} + +unsigned long file_pos(void) +{ + return filepos; +} + +unsigned long file_size(void) +{ + return filemax; +} + +void file_close(void) +{ +} + |