| /* 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[] = { |
| # if CONFIG_FS_FAT == 1 |
| {"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 |
| # 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; |
| } |
| } |
| |
| 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) |
| { |
| } |
| |