ppc64: Don't set Kp bit on SLB
[openbios/afaerber.git] / fs / grubfs / grubfs_fs.c
blobacd2a64414366f062db3ac41330d7b013b5d3ea2
1 /*
2 * /packages/grubfs-files
4 * grub vfs
6 * Copyright (C) 2004 Stefan Reinauer
7 * Copyright (C) 2004 Samuel Rydh
8 * Copyright (C) 2010 Mark Cave-Ayland
10 * inspired by HFS code from Samuel Rydh
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation
18 #include "config.h"
19 #include "libopenbios/bindings.h"
20 #include "fs/fs.h"
21 #include "filesys.h"
22 #include "glue.h"
23 #include "libc/diskio.h"
24 #include "libc/vsprintf.h"
26 extern void grubfs_init( void );
28 /************************************************************************/
29 /* grub GLOBALS (horrible... but difficult to fix) */
30 /************************************************************************/
32 /* the grub drivers want these: */
33 int filepos;
34 int filemax;
35 grub_error_t errnum;
36 char FSYS_BUF[FSYS_BUFLEN];
38 /* these are not even used by us, instead
39 * the grub fs drivers want them:
41 int fsmax;
42 void (*disk_read_hook) (int, int, int);
43 void (*disk_read_func) (int, int, int);
46 /************************************************************************/
47 /* filsystem table */
48 /************************************************************************/
50 typedef struct fsys_entry {
51 const char *name;
52 int (*mount_func) (void);
53 int (*read_func) (char *buf, int len);
54 int (*dir_func) (char *dirname);
55 void (*close_func) (void);
56 int (*embed_func) (int *start_sector, int needed_sectors);
57 } fsys_entry_t;
59 static const struct fsys_entry fsys_table[] = {
60 # ifdef CONFIG_FSYS_FAT
61 {"fat", fat_mount, fat_read, fat_dir, NULL, NULL},
62 # endif
63 # ifdef CONFIG_FSYS_EXT2FS
64 {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, NULL, NULL},
65 # endif
66 # ifdef CONFIG_FSYS_MINIX
67 {"minix", minix_mount, minix_read, minix_dir, NULL, NULL},
68 # endif
69 # ifdef CONFIG_FSYS_REISERFS
70 {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, NULL, reiserfs_embed},
71 # endif
72 # ifdef CONFIG_FSYS_JFS
73 {"jfs", jfs_mount, jfs_read, jfs_dir, NULL, jfs_embed},
74 # endif
75 # ifdef CONFIG_FSYS_XFS
76 {"xfs", xfs_mount, xfs_read, xfs_dir, NULL, NULL},
77 # endif
78 # ifdef CONFIG_FSYS_UFS
79 {"ufs", ufs_mount, ufs_read, ufs_dir, NULL, ufs_embed},
80 # endif
81 # ifdef CONFIG_FSYS_ISO9660
82 {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, NULL, NULL},
83 # endif
84 # ifdef CONFIG_FSYS_NTFS
85 {"ntfs", ntfs_mount, ntfs_read, ntfs_dir, NULL, NULL},
86 # endif
87 # ifdef CONFIG_FSYS_AFFS
88 {"affs", affs_mount, affs_read, affs_dir, NULL, NULL},
89 # endif
92 /* We don't provide a file search mechanism (yet) */
93 typedef struct {
94 unsigned long pos;
95 unsigned long len;
96 const char *path;
97 } grubfile_t;
99 typedef struct {
100 const struct fsys_entry *fsys;
101 grubfile_t *fd;
102 int dev_fd;
103 long long offset; /* Offset added onto each device read; should only ever be non-zero
104 when probing a partition for a filesystem */
105 } grubfs_t;
107 typedef struct {
108 grubfs_t *gfs;
109 } grubfs_info_t;
111 /* Static block and global pointer required for I/O glue */
112 static grubfs_t dummy_fs;
113 static grubfs_t *curfs = &dummy_fs;
115 DECLARE_NODE( grubfs, 0, sizeof(grubfs_info_t), "+/packages/grubfs-files" );
118 /************************************************************************/
119 /* I/O glue (called by grub source) */
120 /************************************************************************/
123 devread( unsigned long sector, unsigned long byte_offset,
124 unsigned long byte_len, void *buf )
126 long long offs = (long long)sector * 512 + byte_offset;
128 #ifdef CONFIG_DEBUG_FS
129 //printk("devread s=%x buf=%x, fd=%x\n",sector, buf, curfs->dev_fd);
130 #endif
132 if( !curfs ) {
133 #ifdef CONFIG_DEBUG_FS
134 printk("devread: fsys == NULL!\n");
135 #endif
136 return -1;
139 if( seek_io(curfs->dev_fd, offs + curfs->offset) ) {
140 #ifdef CONFIG_DEBUG_FS
141 printk("seek failure\n");
142 #endif
143 return -1;
145 return (read_io(curfs->dev_fd, buf, byte_len) == byte_len) ? 1:0;
149 file_read( void *buf, unsigned long len )
151 if (filepos < 0 || filepos > filemax)
152 filepos = filemax;
153 if (len > filemax-filepos)
154 len = filemax - filepos;
155 errnum = 0;
156 return curfs->fsys->read_func( buf, len );
160 /************************************************************************/
161 /* Standard package methods */
162 /************************************************************************/
164 /* ( -- success? ) */
165 static void
166 grubfs_files_open( grubfs_info_t *mi )
168 int fd, i;
169 char *path = my_args_copy();
170 char *s;
172 fd = open_ih( my_parent() );
173 if ( fd == -1 ) {
174 free( path );
175 RET( 0 );
178 mi->gfs = &dummy_fs;
180 for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) {
181 #ifdef CONFIG_DEBUG_FS
182 printk("Trying %s\n", fsys_table[i].name);
183 #endif
184 if (fsys_table[i].mount_func()) {
185 const fsys_entry_t *fsys = &fsys_table[i];
186 #ifdef CONFIG_DEBUG_FS
187 printk("Mounted %s\n", fsys->name);
188 #endif
189 mi->gfs = malloc(sizeof(grubfs_t));
190 mi->gfs->fsys = fsys;
191 mi->gfs->dev_fd = fd;
192 mi->gfs->offset = 0;
194 s = path;
195 while (*s) {
196 if(*s=='\\') *s='/';
197 s++;
199 #ifdef CONFIG_DEBUG_FS
200 printk("Path=%s\n",path);
201 #endif
202 if (!mi->gfs->fsys->dir_func((char *) path)) {
203 forth_printf("File not found\n");
204 RET( 0 );
207 mi->gfs->fd = malloc(sizeof(grubfile_t));
208 mi->gfs->fd->pos = filepos;
209 mi->gfs->fd->len = filemax;
210 mi->gfs->fd->path = strdup(path);
212 RET( -1 );
215 #ifdef CONFIG_DEBUG_FS
216 printk("Unknown filesystem type\n");
217 #endif
219 RET( 0 );
222 /* ( -- ) */
223 static void
224 grubfs_files_close( grubfs_info_t *mi )
226 grubfile_t *gf = mi->gfs->fd;
228 if (gf->path)
229 free((void *)(gf->path));
230 free(gf);
232 filepos = 0;
233 filemax = 0;
236 /* ( buf len -- actlen ) */
237 static void
238 grubfs_files_read( grubfs_info_t *mi )
240 int count = POP();
241 char *buf = (char *)cell2pointer(POP());
243 grubfile_t *file = mi->gfs->fd;
244 int ret;
246 filepos = file->pos;
247 filemax = file->len;
249 if (count > filemax - filepos)
250 count = filemax - filepos;
252 ret = mi->gfs->fsys->read_func(buf, count);
254 file->pos = filepos;
256 RET( ret );
259 /* ( pos.d -- status ) */
260 static void
261 grubfs_files_seek( grubfs_info_t *mi )
263 long long pos = DPOP();
264 int offs = (int)pos;
265 int whence = SEEK_SET;
267 grubfile_t *file = mi->gfs->fd;
268 unsigned long newpos;
270 switch( whence ) {
271 case SEEK_END:
272 if (offs < 0 && (unsigned long) -offs > file->len)
273 newpos = 0;
274 else
275 newpos = file->len + offs;
276 break;
277 default:
278 case SEEK_SET:
279 newpos = (offs < 0) ? 0 : offs;
280 break;
283 if (newpos > file->len)
284 newpos = file->len;
286 file->pos = newpos;
288 if (newpos)
289 RET( -1 );
290 else
291 RET( 0 );
294 /* ( addr -- size ) */
295 static void
296 grubfs_files_load( grubfs_info_t *mi )
298 char *buf = (char *)cell2pointer(POP());
299 int count, ret;
301 grubfile_t *file = mi->gfs->fd;
302 count = file->len;
304 ret = mi->gfs->fsys->read_func(buf, count);
305 file->pos = filepos;
307 RET( ret );
310 /* ( -- cstr ) */
311 static void
312 grubfs_files_get_path( grubfs_info_t *mi )
314 grubfile_t *file = mi->gfs->fd;
315 const char *path = file->path;
317 RET( pointer2cell(strdup(path)) );
320 /* ( -- cstr ) */
321 static void
322 grubfs_files_get_fstype( grubfs_info_t *mi )
324 grubfs_t *gfs = mi->gfs;
326 PUSH( pointer2cell(strdup(gfs->fsys->name)) );
330 /* static method, ( pos.d ih -- flag? ) */
331 static void
332 grubfs_files_probe( grubfs_info_t *dummy )
334 ihandle_t ih = POP_ih();
335 long long offs = DPOP();
336 int i;
338 curfs->dev_fd = open_ih(ih);
339 if (curfs->dev_fd == -1) {
340 RET( -1 );
342 curfs->offset = offs;
344 for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) {
345 #ifdef CONFIG_DEBUG_FS
346 printk("Probing for %s\n", fsys_table[i].name);
347 #endif
348 if (fsys_table[i].mount_func()) {
349 RET( -1 );
353 #ifdef CONFIG_DEBUG_FS
354 printk("Unknown filesystem type\n");
355 #endif
357 close_io(curfs->dev_fd);
359 RET ( 0 );
362 /* static method, ( pathstr len ihandle -- ) */
363 static void
364 grubfs_files_dir( grubfs_info_t *dummy )
366 forth_printf("dir method not implemented for grubfs filesystem\n");
367 POP();
368 POP();
369 POP();
372 static void
373 grubfs_initializer( grubfs_info_t *dummy )
375 fword("register-fs-package");
378 NODE_METHODS( grubfs ) = {
379 { "probe", grubfs_files_probe },
380 { "open", grubfs_files_open },
381 { "close", grubfs_files_close },
382 { "read", grubfs_files_read },
383 { "seek", grubfs_files_seek },
384 { "load", grubfs_files_load },
385 { "dir", grubfs_files_dir },
387 /* special */
388 { "get-path", grubfs_files_get_path },
389 { "get-fstype", grubfs_files_get_fstype },
391 { NULL, grubfs_initializer },
394 void
395 grubfs_init( void )
397 REGISTER_NODE( grubfs );