summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/fs/grubfs/fsys_vstafs.c')
-rw-r--r--qemu/roms/openbios/fs/grubfs/fsys_vstafs.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c b/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c
new file mode 100644
index 000000000..e06d3e73e
--- /dev/null
+++ b/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c
@@ -0,0 +1,254 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_VSTAFS
+
+#include "shared.h"
+#include "filesys.h"
+#include "vstafs.h"
+
+
+static void get_file_info (int sector);
+static struct dir_entry *vstafs_readdir (long sector);
+static struct dir_entry *vstafs_nextdir (void);
+
+
+#define FIRST_SECTOR ((struct first_sector *) FSYS_BUF)
+#define FILE_INFO ((struct fs_file *) (long) FIRST_SECTOR + 8192)
+#define DIRECTORY_BUF ((struct dir_entry *) (long) FILE_INFO + 512)
+
+#define ROOT_SECTOR 1
+
+/*
+ * In f_sector we store the sector number in which the information about
+ * the found file is.
+ */
+static int f_sector;
+
+int
+vstafs_mount (void)
+{
+ int retval = 1;
+
+ if( (((current_drive & 0x80) || (current_slice != 0))
+ && current_slice != PC_SLICE_TYPE_VSTAFS)
+ || ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF)
+ || FIRST_SECTOR->fs_magic != 0xDEADFACE)
+ retval = 0;
+
+ return retval;
+}
+
+static void
+get_file_info (int sector)
+{
+ devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO);
+}
+
+static int curr_ext, current_direntry, current_blockpos;
+static struct alloc *a1;
+
+static struct dir_entry *
+vstafs_readdir (long sector)
+{
+ /*
+ * Get some information from the current directory
+ */
+ get_file_info (sector);
+ if (FILE_INFO->type != 2)
+ {
+ errnum = ERR_FILE_NOT_FOUND;
+ return NULL;
+ }
+
+ a1 = FILE_INFO->blocks;
+ curr_ext = 0;
+ devread (a1[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF);
+ current_direntry = 11;
+ current_blockpos = 0;
+
+ return &DIRECTORY_BUF[10];
+}
+
+static struct dir_entry *
+vstafs_nextdir (void)
+{
+ if (current_direntry > 15)
+ {
+ current_direntry = 0;
+ if (++current_blockpos > (a1[curr_ext].a_len - 1))
+ {
+ current_blockpos = 0;
+ curr_ext++;
+ }
+
+ if (curr_ext < FILE_INFO->extents)
+ {
+ devread (a1[curr_ext].a_start + current_blockpos, 0,
+ 512, (char *) DIRECTORY_BUF);
+ }
+ else
+ {
+ /* errnum =ERR_FILE_NOT_FOUND; */
+ return NULL;
+ }
+ }
+
+ return &DIRECTORY_BUF[current_direntry++];
+}
+
+int
+vstafs_dir (char *dirname)
+{
+ char *fn, ch;
+ struct dir_entry *d;
+ /* int l, i, s; */
+
+ /*
+ * Read in the entries of the current directory.
+ */
+ f_sector = ROOT_SECTOR;
+ do
+ {
+ if (! (d = vstafs_readdir (f_sector)))
+ {
+ return 0;
+ }
+
+ /*
+ * Find the file in the path
+ */
+ while (*dirname == '/') dirname++;
+ fn = dirname;
+ while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++;
+ *fn = 0;
+
+ do
+ {
+ if (d->name[0] == 0 || d->name[0] & 0x80)
+ continue;
+
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/'
+ && (! *dirname || strcmp (dirname, d->name) <= 0))
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+
+ printf (" %s", d->name);
+ }
+#endif
+ if (! grub_strcmp (dirname, d->name))
+ {
+ f_sector = d->start;
+ get_file_info (f_sector);
+ filemax = FILE_INFO->len;
+ break;
+ }
+ }
+ while ((d =vstafs_nextdir ()));
+
+ *(dirname = fn) = ch;
+ if (! d)
+ {
+ if (print_possibilities < 0)
+ {
+#ifndef STAGE1_5
+ putchar ('\n');
+#endif
+ return 1;
+ }
+
+ errnum = ERR_FILE_NOT_FOUND;
+ return 0;
+ }
+ }
+ while (*dirname && ! isspace (ch));
+
+ return 1;
+}
+
+int
+vstafs_read (char *addr, int len)
+{
+ struct alloc *a2;
+ int size, ret = 0, offset, curr_len = 0;
+ int curr_ext2;
+ char extent;
+ int ext_size;
+ char *curr_pos;
+
+ get_file_info (f_sector);
+ size = FILE_INFO->len-VSTAFS_START_DATA;
+ a2 = FILE_INFO->blocks;
+
+ if (filepos > 0)
+ {
+ if (filepos < a2[0].a_len * 512 - VSTAFS_START_DATA)
+ {
+ offset = filepos + VSTAFS_START_DATA;
+ extent = 0;
+ curr_len = a2[0].a_len * 512 - offset - filepos;
+ }
+ else
+ {
+ ext_size = a2[0].a_len * 512 - VSTAFS_START_DATA;
+ offset = filepos - ext_size;
+ extent = 1;
+ do
+ {
+ curr_len -= ext_size;
+ offset -= ext_size;
+ ext_size = a2[extent+1].a_len * 512;
+ }
+ while (extent < FILE_INFO->extents && offset>ext_size);
+ }
+ }
+ else
+ {
+ offset = VSTAFS_START_DATA;
+ extent = 0;
+ curr_len = a2[0].a_len * 512 - offset;
+ }
+
+ curr_pos = addr;
+ if (curr_len > len)
+ curr_len = len;
+
+ for (curr_ext2=extent;
+ curr_ext2 < FILE_INFO->extents;
+ curr_len = a2[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext2++)
+ {
+ ret += curr_len;
+ size -= curr_len;
+ if (size < 0)
+ {
+ ret += size;
+ curr_len += size;
+ }
+
+ devread (a2[curr_ext2].a_start,offset, curr_len, curr_pos);
+ offset = 0;
+ }
+
+ return ret;
+}
+
+#endif /* FSYS_VSTAFS */