2 * /packages/grubfs-files
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
19 #include "libopenbios/bindings.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: */
36 char FSYS_BUF
[FSYS_BUFLEN
];
38 /* these are not even used by us, instead
39 * the grub fs drivers want them:
42 void (*disk_read_hook
) (int, int, int);
43 void (*disk_read_func
) (int, int, int);
46 /************************************************************************/
48 /************************************************************************/
50 typedef struct fsys_entry
{
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
);
59 static const struct fsys_entry fsys_table
[] = {
60 # ifdef CONFIG_FSYS_FAT
61 {"fat", fat_mount
, fat_read
, fat_dir
, NULL
, NULL
},
63 # ifdef CONFIG_FSYS_EXT2FS
64 {"ext2fs", ext2fs_mount
, ext2fs_read
, ext2fs_dir
, NULL
, NULL
},
66 # ifdef CONFIG_FSYS_MINIX
67 {"minix", minix_mount
, minix_read
, minix_dir
, NULL
, NULL
},
69 # ifdef CONFIG_FSYS_REISERFS
70 {"reiserfs", reiserfs_mount
, reiserfs_read
, reiserfs_dir
, NULL
, reiserfs_embed
},
72 # ifdef CONFIG_FSYS_JFS
73 {"jfs", jfs_mount
, jfs_read
, jfs_dir
, NULL
, jfs_embed
},
75 # ifdef CONFIG_FSYS_XFS
76 {"xfs", xfs_mount
, xfs_read
, xfs_dir
, NULL
, NULL
},
78 # ifdef CONFIG_FSYS_UFS
79 {"ufs", ufs_mount
, ufs_read
, ufs_dir
, NULL
, ufs_embed
},
81 # ifdef CONFIG_FSYS_ISO9660
82 {"iso9660", iso9660_mount
, iso9660_read
, iso9660_dir
, NULL
, NULL
},
84 # ifdef CONFIG_FSYS_NTFS
85 {"ntfs", ntfs_mount
, ntfs_read
, ntfs_dir
, NULL
, NULL
},
87 # ifdef CONFIG_FSYS_AFFS
88 {"affs", affs_mount
, affs_read
, affs_dir
, NULL
, NULL
},
92 /* We don't provide a file search mechanism (yet) */
100 const struct fsys_entry
*fsys
;
103 long long offset
; /* Offset added onto each device read; should only ever be non-zero
104 when probing a partition for a filesystem */
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);
133 #ifdef CONFIG_DEBUG_FS
134 printk("devread: fsys == NULL!\n");
139 if( seek_io(curfs
->dev_fd
, offs
+ curfs
->offset
) ) {
140 #ifdef CONFIG_DEBUG_FS
141 printk("seek failure\n");
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
)
153 if (len
> filemax
-filepos
)
154 len
= filemax
- filepos
;
156 return curfs
->fsys
->read_func( buf
, len
);
160 /************************************************************************/
161 /* Standard package methods */
162 /************************************************************************/
164 /* ( -- success? ) */
166 grubfs_files_open( grubfs_info_t
*mi
)
169 char *path
= my_args_copy();
172 fd
= open_ih( my_parent() );
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
);
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
);
189 mi
->gfs
= malloc(sizeof(grubfs_t
));
190 mi
->gfs
->fsys
= fsys
;
191 mi
->gfs
->dev_fd
= fd
;
199 #ifdef CONFIG_DEBUG_FS
200 printk("Path=%s\n",path
);
202 if (!mi
->gfs
->fsys
->dir_func((char *) path
)) {
203 forth_printf("File not found\n");
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
);
215 #ifdef CONFIG_DEBUG_FS
216 printk("Unknown filesystem type\n");
224 grubfs_files_close( grubfs_info_t
*mi
)
226 grubfile_t
*gf
= mi
->gfs
->fd
;
229 free((void *)(gf
->path
));
236 /* ( buf len -- actlen ) */
238 grubfs_files_read( grubfs_info_t
*mi
)
241 char *buf
= (char *)cell2pointer(POP());
243 grubfile_t
*file
= mi
->gfs
->fd
;
249 if (count
> filemax
- filepos
)
250 count
= filemax
- filepos
;
252 ret
= mi
->gfs
->fsys
->read_func(buf
, count
);
259 /* ( pos.d -- status ) */
261 grubfs_files_seek( grubfs_info_t
*mi
)
263 long long pos
= DPOP();
265 int whence
= SEEK_SET
;
267 grubfile_t
*file
= mi
->gfs
->fd
;
268 unsigned long newpos
;
272 if (offs
< 0 && (unsigned long) -offs
> file
->len
)
275 newpos
= file
->len
+ offs
;
279 newpos
= (offs
< 0) ? 0 : offs
;
283 if (newpos
> file
->len
)
294 /* ( addr -- size ) */
296 grubfs_files_load( grubfs_info_t
*mi
)
298 char *buf
= (char *)cell2pointer(POP());
301 grubfile_t
*file
= mi
->gfs
->fd
;
304 ret
= mi
->gfs
->fsys
->read_func(buf
, count
);
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
)) );
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? ) */
332 grubfs_files_probe( grubfs_info_t
*dummy
)
334 ihandle_t ih
= POP_ih();
335 long long offs
= DPOP();
338 curfs
->dev_fd
= open_ih(ih
);
339 if (curfs
->dev_fd
== -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
);
348 if (fsys_table
[i
].mount_func()) {
353 #ifdef CONFIG_DEBUG_FS
354 printk("Unknown filesystem type\n");
357 close_io(curfs
->dev_fd
);
362 /* static method, ( pathstr len ihandle -- ) */
364 grubfs_files_dir( grubfs_info_t
*dummy
)
366 forth_printf("dir method not implemented for grubfs filesystem\n");
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
},
388 { "get-path", grubfs_files_get_path
},
389 { "get-fstype", grubfs_files_get_fstype
},
391 { NULL
, grubfs_initializer
},
397 REGISTER_NODE( grubfs
);