Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / grubfs / fsys_vstafs.c
1 /*
2  *  GRUB  --  GRand Unified Bootloader
3  *  Copyright (C) 2001   Free Software Foundation, Inc.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18  *  MA 02110-1301, USA.
19  */
20
21 #ifdef FSYS_VSTAFS
22
23 #include "shared.h"
24 #include "filesys.h"
25 #include "vstafs.h"
26
27
28 static void get_file_info (int sector);
29 static struct dir_entry *vstafs_readdir (long sector);
30 static struct dir_entry *vstafs_nextdir (void);
31
32
33 #define FIRST_SECTOR    ((struct first_sector *) FSYS_BUF)
34 #define FILE_INFO       ((struct fs_file *) (long) FIRST_SECTOR + 8192)
35 #define DIRECTORY_BUF   ((struct dir_entry *) (long) FILE_INFO + 512)
36
37 #define ROOT_SECTOR     1
38
39 /*
40  * In f_sector we store the sector number in which the information about
41  * the found file is.
42  */
43 static int f_sector;
44
45 int
46 vstafs_mount (void)
47 {
48   int retval = 1;
49
50   if( (((current_drive & 0x80) || (current_slice != 0))
51        && current_slice != PC_SLICE_TYPE_VSTAFS)
52       ||  ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF)
53       ||  FIRST_SECTOR->fs_magic != 0xDEADFACE)
54     retval = 0;
55
56   return retval;
57 }
58
59 static void
60 get_file_info (int sector)
61 {
62   devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO);
63 }
64
65 static int curr_ext, current_direntry, current_blockpos;
66 static struct alloc *a1;
67
68 static struct dir_entry *
69 vstafs_readdir (long sector)
70 {
71   /*
72    * Get some information from the current directory
73    */
74   get_file_info (sector);
75   if (FILE_INFO->type != 2)
76     {
77       errnum = ERR_FILE_NOT_FOUND;
78       return NULL;
79     }
80
81   a1 = FILE_INFO->blocks;
82   curr_ext = 0;
83   devread (a1[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF);
84   current_direntry = 11;
85   current_blockpos = 0;
86
87   return &DIRECTORY_BUF[10];
88 }
89
90 static struct dir_entry *
91 vstafs_nextdir (void)
92 {
93   if (current_direntry > 15)
94     {
95       current_direntry = 0;
96       if (++current_blockpos > (a1[curr_ext].a_len - 1))
97         {
98           current_blockpos = 0;
99           curr_ext++;
100         }
101
102       if (curr_ext < FILE_INFO->extents)
103         {
104             devread (a1[curr_ext].a_start + current_blockpos, 0,
105                      512, (char *) DIRECTORY_BUF);
106         }
107       else
108         {
109             /* errnum =ERR_FILE_NOT_FOUND; */
110             return NULL;
111         }
112     }
113
114   return &DIRECTORY_BUF[current_direntry++];
115 }
116
117 int
118 vstafs_dir (char *dirname)
119 {
120   char *fn, ch;
121   struct dir_entry *d;
122   /* int l, i, s; */
123
124   /*
125    * Read in the entries of the current directory.
126    */
127   f_sector = ROOT_SECTOR;
128   do
129     {
130       if (! (d = vstafs_readdir (f_sector)))
131         {
132           return 0;
133         }
134
135       /*
136        * Find the file in the path
137        */
138       while (*dirname == '/') dirname++;
139       fn = dirname;
140       while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++;
141       *fn = 0;
142
143       do
144         {
145           if (d->name[0] == 0 || d->name[0] & 0x80)
146             continue;
147
148 #ifndef STAGE1_5
149           if (print_possibilities && ch != '/'
150               && (! *dirname || strcmp (dirname, d->name) <= 0))
151             {
152               if (print_possibilities > 0)
153                 print_possibilities = -print_possibilities;
154
155               printf ("  %s", d->name);
156             }
157 #endif
158           if (! grub_strcmp (dirname, d->name))
159             {
160               f_sector = d->start;
161               get_file_info (f_sector);
162               filemax = FILE_INFO->len;
163               break;
164             }
165         }
166       while ((d =vstafs_nextdir ()));
167
168       *(dirname = fn) = ch;
169       if (! d)
170         {
171           if (print_possibilities < 0)
172             {
173 #ifndef STAGE1_5
174               putchar ('\n');
175 #endif
176               return 1;
177             }
178
179           errnum = ERR_FILE_NOT_FOUND;
180           return 0;
181         }
182     }
183   while (*dirname && ! isspace (ch));
184
185   return 1;
186 }
187
188 int
189 vstafs_read (char *addr, int len)
190 {
191   struct alloc *a2;
192   int size, ret = 0, offset, curr_len = 0;
193   int curr_ext2;
194   char extent;
195   int ext_size;
196   char *curr_pos;
197
198   get_file_info (f_sector);
199   size = FILE_INFO->len-VSTAFS_START_DATA;
200   a2 = FILE_INFO->blocks;
201
202   if (filepos > 0)
203     {
204       if (filepos < a2[0].a_len * 512 - VSTAFS_START_DATA)
205         {
206           offset = filepos + VSTAFS_START_DATA;
207           extent = 0;
208           curr_len = a2[0].a_len * 512 - offset - filepos;
209         }
210       else
211         {
212           ext_size = a2[0].a_len * 512 - VSTAFS_START_DATA;
213           offset = filepos - ext_size;
214           extent = 1;
215           do
216             {
217               curr_len -= ext_size;
218               offset -= ext_size;
219               ext_size = a2[extent+1].a_len * 512;
220             }
221           while (extent < FILE_INFO->extents && offset>ext_size);
222         }
223     }
224   else
225     {
226       offset = VSTAFS_START_DATA;
227       extent = 0;
228       curr_len = a2[0].a_len * 512 - offset;
229     }
230
231   curr_pos = addr;
232   if (curr_len > len)
233     curr_len = len;
234
235   for (curr_ext2=extent;
236        curr_ext2 < FILE_INFO->extents;
237        curr_len = a2[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext2++)
238     {
239       ret += curr_len;
240       size -= curr_len;
241       if (size < 0)
242         {
243           ret += size;
244           curr_len += size;
245         }
246
247       devread (a2[curr_ext2].a_start,offset, curr_len, curr_pos);
248       offset = 0;
249     }
250
251   return ret;
252 }
253
254 #endif /* FSYS_VSTAFS */