FAT big endian changes
[coreboot.git] / src / stream / fs / vfs.c
1 /* Interface between GRUB's fs drivers and application code */
2
3 #include <console/console.h>
4 #include <fs/fs.h>
5 #include <string.h>
6 #include <stdlib.h>
7
8 int filepos;
9 int filemax;
10 fs_error_t errnum;
11 void (*disk_read_hook) (int, int, int);
12 void (*disk_read_func) (int, int, int);
13 char FSYS_BUF[FSYS_BUFLEN];
14 int fsmax;
15
16 struct fsys_entry {
17     char *name;
18     int (*mount_func) (void);
19     int (*read_func) (char *buf, int len);
20     int (*dir_func) (char *dirname);
21     void (*close_func) (void);
22     int (*embed_func) (int *start_sector, int needed_sectors);
23 };
24
25 struct fsys_entry fsys_table[] = {
26 # if CONFIG_FS_FAT == 1
27     {"fat", fat_mount, fat_read, fat_dir, 0, 0},
28 # endif
29 # if CONFIG_FS_EXT2 == 1
30     {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0},
31 # endif
32 # if CONFIG_FS_ISO9660 == 1
33     {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0},
34 # endif
35 };
36
37 /* NULLFS is used to read images from raw device */
38 static int nullfs_dir(char *name)
39 {
40     uint64_t dev_size;
41
42     if (name) {
43         printk_debug("can't have a named file\n");
44         return 0;
45     }
46
47     dev_size = (uint64_t) part_length << 9;
48     /* GRUB code doesn't like 2GB or bigger files */
49     if (dev_size > 0x7fffffff)
50         dev_size = 0x7fffffff;
51     filemax = dev_size;
52     return 1;
53 }
54
55 static int nullfs_read(char *buf, int len)
56 {
57     if (devread(filepos>>9, filepos&0x1ff, len, buf)) {
58         filepos += len;
59         return len;
60     } else
61         return 0;
62 }
63
64 static struct fsys_entry nullfs =
65     {"nullfs", 0, nullfs_read, nullfs_dir, 0, 0};
66
67 static struct fsys_entry *fsys;
68
69 int mount_fs(void)
70 {
71     int i;
72
73     for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) {
74         if (fsys_table[i].mount_func()) {
75             fsys = &fsys_table[i];
76             printk_info("Mounted %s\n", fsys->name);
77             return 1;
78         }
79     }
80     fsys = 0;
81     printk_info("Unknown filesystem type\n");
82     return 0;
83 }
84
85 int file_open(const char *filename)
86 {
87     char *dev = 0;
88     const char *path;
89     int len;
90     int retval = 0;
91     int reopen;
92
93     path = strchr(filename, ':');
94     if (path) {
95         len = path - filename;
96         path++;
97         dev = malloc(len + 1);
98         memcpy(dev, filename, len);
99         dev[len] = '\0';
100     } else {
101         /* No colon is given. Is this device or filename? */
102         if (filename[0] == '/') {
103             /* Anything starts with '/' must be a filename */
104             dev = 0;
105             path = filename;
106         } else {
107             dev = strdup(filename);
108             path = 0;
109         }
110     }
111     printk_debug("dev=%s, path=%s\n", dev, path);
112
113     if (dev && dev[0]) {
114         if (!devopen(dev, &reopen)) {
115             fsys = 0;
116             goto out;
117         }
118         if (!reopen)
119             fsys = 0;
120     }
121
122     if (path) {
123         if (!fsys || fsys==&nullfs) {
124             if (!mount_fs())
125                 goto out;
126         }
127         using_devsize = 0;
128         if (!path[0]) {
129             printk_info("No filename is given\n");
130             goto out;
131         }
132     } else
133         fsys = &nullfs;
134
135     filepos = 0;
136     errnum = 0;
137     if (!fsys->dir_func((char *) path)) {
138         printk_info("File not found\n");
139         goto out;
140     }
141     retval = 1;
142 out:
143     if (dev)
144         free(dev);
145     return retval;
146 }
147
148 int file_read(void *buf, unsigned long len)
149 {
150     if (filepos < 0 || filepos > filemax)
151         filepos = filemax;
152     if (len < 0 || len > filemax-filepos)
153         len = filemax - filepos;
154     errnum = 0;
155     return fsys->read_func(buf, len);
156 }
157
158 int file_seek(unsigned long offset)
159 {
160     filepos = offset;
161     return filepos;
162 }
163
164 unsigned long file_pos(void)
165 {
166     return filepos;
167 }
168
169 unsigned long file_size(void)
170 {
171     return filemax;
172 }
173
174 void file_close(void)
175 {
176 }
177