|
|
1.1 ! root 1: /* ! 2: * /packages/grubfs-files ! 3: * ! 4: * grub vfs ! 5: * ! 6: * Copyright (C) 2004 Stefan Reinauer ! 7: * Copyright (C) 2004 Samuel Rydh ! 8: * Copyright (C) 2010 Mark Cave-Ayland ! 9: * ! 10: * inspired by HFS code from Samuel Rydh ! 11: * ! 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 ! 15: * ! 16: */ ! 17: ! 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" ! 25: ! 26: extern void grubfs_init( void ); ! 27: ! 28: /************************************************************************/ ! 29: /* grub GLOBALS (horrible... but difficult to fix) */ ! 30: /************************************************************************/ ! 31: ! 32: /* the grub drivers want these: */ ! 33: int filepos; ! 34: int filemax; ! 35: grub_error_t errnum; ! 36: char FSYS_BUF[FSYS_BUFLEN]; ! 37: ! 38: /* these are not even used by us, instead ! 39: * the grub fs drivers want them: ! 40: */ ! 41: int fsmax; ! 42: void (*disk_read_hook) (int, int, int); ! 43: void (*disk_read_func) (int, int, int); ! 44: ! 45: ! 46: /************************************************************************/ ! 47: /* filsystem table */ ! 48: /************************************************************************/ ! 49: ! 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; ! 58: ! 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 ! 90: }; ! 91: ! 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; ! 98: ! 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; ! 106: ! 107: typedef struct { ! 108: grubfs_t *gfs; ! 109: } grubfs_info_t; ! 110: ! 111: /* Static block and global pointer required for I/O glue */ ! 112: static grubfs_t dummy_fs; ! 113: static grubfs_t *curfs = &dummy_fs; ! 114: ! 115: DECLARE_NODE( grubfs, 0, sizeof(grubfs_info_t), "+/packages/grubfs-files" ); ! 116: ! 117: ! 118: /************************************************************************/ ! 119: /* I/O glue (called by grub source) */ ! 120: /************************************************************************/ ! 121: ! 122: int ! 123: devread( unsigned long sector, unsigned long byte_offset, ! 124: unsigned long byte_len, void *buf ) ! 125: { ! 126: long long offs = (long long)sector * 512 + byte_offset; ! 127: ! 128: #ifdef CONFIG_DEBUG_FS ! 129: //printk("devread s=%x buf=%x, fd=%x\n",sector, buf, curfs->dev_fd); ! 130: #endif ! 131: ! 132: if( !curfs ) { ! 133: #ifdef CONFIG_DEBUG_FS ! 134: printk("devread: fsys == NULL!\n"); ! 135: #endif ! 136: return -1; ! 137: } ! 138: ! 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; ! 144: } ! 145: return (read_io(curfs->dev_fd, buf, byte_len) == byte_len) ? 1:0; ! 146: } ! 147: ! 148: int ! 149: file_read( void *buf, unsigned long len ) ! 150: { ! 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 ); ! 157: } ! 158: ! 159: ! 160: /************************************************************************/ ! 161: /* Standard package methods */ ! 162: /************************************************************************/ ! 163: ! 164: /* ( -- success? ) */ ! 165: static void ! 166: grubfs_files_open( grubfs_info_t *mi ) ! 167: { ! 168: int fd, i; ! 169: char *path = my_args_copy(); ! 170: char *s; ! 171: ! 172: fd = open_ih( my_parent() ); ! 173: if ( fd == -1 ) { ! 174: free( path ); ! 175: RET( 0 ); ! 176: } ! 177: ! 178: mi->gfs = &dummy_fs; ! 179: ! 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; ! 193: ! 194: s = path; ! 195: while (*s) { ! 196: if(*s=='\\') *s='/'; ! 197: s++; ! 198: } ! 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 ); ! 205: } ! 206: ! 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); ! 211: ! 212: RET( -1 ); ! 213: } ! 214: } ! 215: #ifdef CONFIG_DEBUG_FS ! 216: printk("Unknown filesystem type\n"); ! 217: #endif ! 218: ! 219: RET( 0 ); ! 220: } ! 221: ! 222: /* ( -- ) */ ! 223: static void ! 224: grubfs_files_close( grubfs_info_t *mi ) ! 225: { ! 226: grubfile_t *gf = mi->gfs->fd; ! 227: ! 228: if (gf->path) ! 229: free((void *)(gf->path)); ! 230: free(gf); ! 231: ! 232: filepos = 0; ! 233: filemax = 0; ! 234: } ! 235: ! 236: /* ( buf len -- actlen ) */ ! 237: static void ! 238: grubfs_files_read( grubfs_info_t *mi ) ! 239: { ! 240: int count = POP(); ! 241: char *buf = (char *)cell2pointer(POP()); ! 242: ! 243: grubfile_t *file = mi->gfs->fd; ! 244: int ret; ! 245: ! 246: filepos = file->pos; ! 247: filemax = file->len; ! 248: ! 249: if (count > filemax - filepos) ! 250: count = filemax - filepos; ! 251: ! 252: ret = mi->gfs->fsys->read_func(buf, count); ! 253: ! 254: file->pos = filepos; ! 255: ! 256: RET( ret ); ! 257: } ! 258: ! 259: /* ( pos.d -- status ) */ ! 260: static void ! 261: grubfs_files_seek( grubfs_info_t *mi ) ! 262: { ! 263: long long pos = DPOP(); ! 264: int offs = (int)pos; ! 265: int whence = SEEK_SET; ! 266: ! 267: grubfile_t *file = mi->gfs->fd; ! 268: unsigned long newpos; ! 269: ! 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; ! 281: } ! 282: ! 283: if (newpos > file->len) ! 284: newpos = file->len; ! 285: ! 286: file->pos = newpos; ! 287: ! 288: if (newpos) ! 289: RET( -1 ); ! 290: else ! 291: RET( 0 ); ! 292: } ! 293: ! 294: /* ( addr -- size ) */ ! 295: static void ! 296: grubfs_files_load( grubfs_info_t *mi ) ! 297: { ! 298: char *buf = (char *)cell2pointer(POP()); ! 299: int count, ret; ! 300: ! 301: grubfile_t *file = mi->gfs->fd; ! 302: count = file->len; ! 303: ! 304: ret = mi->gfs->fsys->read_func(buf, count); ! 305: file->pos = filepos; ! 306: ! 307: RET( ret ); ! 308: } ! 309: ! 310: /* ( -- cstr ) */ ! 311: static void ! 312: grubfs_files_get_path( grubfs_info_t *mi ) ! 313: { ! 314: grubfile_t *file = mi->gfs->fd; ! 315: const char *path = file->path; ! 316: ! 317: RET( pointer2cell(strdup(path)) ); ! 318: } ! 319: ! 320: /* ( -- cstr ) */ ! 321: static void ! 322: grubfs_files_get_fstype( grubfs_info_t *mi ) ! 323: { ! 324: grubfs_t *gfs = mi->gfs; ! 325: ! 326: PUSH( pointer2cell(strdup(gfs->fsys->name)) ); ! 327: } ! 328: ! 329: ! 330: /* static method, ( pos.d ih -- flag? ) */ ! 331: static void ! 332: grubfs_files_probe( grubfs_info_t *dummy ) ! 333: { ! 334: ihandle_t ih = POP_ih(); ! 335: long long offs = DPOP(); ! 336: int i; ! 337: ! 338: curfs->dev_fd = open_ih(ih); ! 339: if (curfs->dev_fd == -1) { ! 340: RET( -1 ); ! 341: } ! 342: curfs->offset = offs; ! 343: ! 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 ); ! 350: } ! 351: } ! 352: ! 353: #ifdef CONFIG_DEBUG_FS ! 354: printk("Unknown filesystem type\n"); ! 355: #endif ! 356: ! 357: close_io(curfs->dev_fd); ! 358: ! 359: RET ( 0 ); ! 360: } ! 361: ! 362: /* static method, ( pathstr len ihandle -- ) */ ! 363: static void ! 364: grubfs_files_dir( grubfs_info_t *dummy ) ! 365: { ! 366: forth_printf("dir method not implemented for grubfs filesystem\n"); ! 367: POP(); ! 368: POP(); ! 369: POP(); ! 370: } ! 371: ! 372: static void ! 373: grubfs_initializer( grubfs_info_t *dummy ) ! 374: { ! 375: fword("register-fs-package"); ! 376: } ! 377: ! 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 }, ! 386: ! 387: /* special */ ! 388: { "get-path", grubfs_files_get_path }, ! 389: { "get-fstype", grubfs_files_get_fstype }, ! 390: ! 391: { NULL, grubfs_initializer }, ! 392: }; ! 393: ! 394: void ! 395: grubfs_init( void ) ! 396: { ! 397: REGISTER_NODE( grubfs ); ! 398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.