xref: /illumos-gate/usr/src/grub/grub-0.97/stage2/fsys_ffs.c (revision 1b8adde7ba7d5e04395c141c5400dc2cffd7d809)
1*1b8adde7SWilliam Kucharski /*
2*1b8adde7SWilliam Kucharski  *  GRUB  --  GRand Unified Bootloader
3*1b8adde7SWilliam Kucharski  *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
4*1b8adde7SWilliam Kucharski  *
5*1b8adde7SWilliam Kucharski  *  This program is free software; you can redistribute it and/or modify
6*1b8adde7SWilliam Kucharski  *  it under the terms of the GNU General Public License as published by
7*1b8adde7SWilliam Kucharski  *  the Free Software Foundation; either version 2 of the License, or
8*1b8adde7SWilliam Kucharski  *  (at your option) any later version.
9*1b8adde7SWilliam Kucharski  *
10*1b8adde7SWilliam Kucharski  *  This program is distributed in the hope that it will be useful,
11*1b8adde7SWilliam Kucharski  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*1b8adde7SWilliam Kucharski  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*1b8adde7SWilliam Kucharski  *  GNU General Public License for more details.
14*1b8adde7SWilliam Kucharski  *
15*1b8adde7SWilliam Kucharski  *  You should have received a copy of the GNU General Public License
16*1b8adde7SWilliam Kucharski  *  along with this program; if not, write to the Free Software
17*1b8adde7SWilliam Kucharski  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*1b8adde7SWilliam Kucharski  */
19*1b8adde7SWilliam Kucharski 
20*1b8adde7SWilliam Kucharski /*
21*1b8adde7SWilliam Kucharski  * Elements of this file were originally from the FreeBSD "biosboot"
22*1b8adde7SWilliam Kucharski  * bootloader file "disk.c" dated 4/12/95.
23*1b8adde7SWilliam Kucharski  *
24*1b8adde7SWilliam Kucharski  * The license and header comments from that file are included here.
25*1b8adde7SWilliam Kucharski  */
26*1b8adde7SWilliam Kucharski 
27*1b8adde7SWilliam Kucharski /*
28*1b8adde7SWilliam Kucharski  * Mach Operating System
29*1b8adde7SWilliam Kucharski  * Copyright (c) 1992, 1991 Carnegie Mellon University
30*1b8adde7SWilliam Kucharski  * All Rights Reserved.
31*1b8adde7SWilliam Kucharski  *
32*1b8adde7SWilliam Kucharski  * Permission to use, copy, modify and distribute this software and its
33*1b8adde7SWilliam Kucharski  * documentation is hereby granted, provided that both the copyright
34*1b8adde7SWilliam Kucharski  * notice and this permission notice appear in all copies of the
35*1b8adde7SWilliam Kucharski  * software, derivative works or modified versions, and any portions
36*1b8adde7SWilliam Kucharski  * thereof, and that both notices appear in supporting documentation.
37*1b8adde7SWilliam Kucharski  *
38*1b8adde7SWilliam Kucharski  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
39*1b8adde7SWilliam Kucharski  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
40*1b8adde7SWilliam Kucharski  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41*1b8adde7SWilliam Kucharski  *
42*1b8adde7SWilliam Kucharski  * Carnegie Mellon requests users of this software to return to
43*1b8adde7SWilliam Kucharski  *
44*1b8adde7SWilliam Kucharski  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
45*1b8adde7SWilliam Kucharski  *  School of Computer Science
46*1b8adde7SWilliam Kucharski  *  Carnegie Mellon University
47*1b8adde7SWilliam Kucharski  *  Pittsburgh PA 15213-3890
48*1b8adde7SWilliam Kucharski  *
49*1b8adde7SWilliam Kucharski  * any improvements or extensions that they make and grant Carnegie Mellon
50*1b8adde7SWilliam Kucharski  * the rights to redistribute these changes.
51*1b8adde7SWilliam Kucharski  *
52*1b8adde7SWilliam Kucharski  *	from: Mach, Revision 2.2  92/04/04  11:35:49  rpd
53*1b8adde7SWilliam Kucharski  *	$Id: fsys_ffs.c,v 1.1.1.1 2003/11/20 02:04:59 fengshuo Exp $
54*1b8adde7SWilliam Kucharski  */
55*1b8adde7SWilliam Kucharski 
56*1b8adde7SWilliam Kucharski #ifdef FSYS_FFS
57*1b8adde7SWilliam Kucharski 
58*1b8adde7SWilliam Kucharski #include "shared.h"
59*1b8adde7SWilliam Kucharski 
60*1b8adde7SWilliam Kucharski #include "filesys.h"
61*1b8adde7SWilliam Kucharski 
62*1b8adde7SWilliam Kucharski #include "defs.h"
63*1b8adde7SWilliam Kucharski #include "disk_inode.h"
64*1b8adde7SWilliam Kucharski #include "disk_inode_ffs.h"
65*1b8adde7SWilliam Kucharski #include "dir.h"
66*1b8adde7SWilliam Kucharski #include "fs.h"
67*1b8adde7SWilliam Kucharski 
68*1b8adde7SWilliam Kucharski /* used for filesystem map blocks */
69*1b8adde7SWilliam Kucharski static int mapblock;
70*1b8adde7SWilliam Kucharski static int mapblock_offset;
71*1b8adde7SWilliam Kucharski static int mapblock_bsize;
72*1b8adde7SWilliam Kucharski 
73*1b8adde7SWilliam Kucharski /* pointer to superblock */
74*1b8adde7SWilliam Kucharski #define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 ))
75*1b8adde7SWilliam Kucharski #define INODE ((struct icommon *) ( FSYS_BUF + 16384 ))
76*1b8adde7SWilliam Kucharski #define MAPBUF ( FSYS_BUF + 24576 )
77*1b8adde7SWilliam Kucharski #define MAPBUF_LEN 8192
78*1b8adde7SWilliam Kucharski 
79*1b8adde7SWilliam Kucharski 
80*1b8adde7SWilliam Kucharski int
81*1b8adde7SWilliam Kucharski ffs_mount (void)
82*1b8adde7SWilliam Kucharski {
83*1b8adde7SWilliam Kucharski   int retval = 1;
84*1b8adde7SWilliam Kucharski 
85*1b8adde7SWilliam Kucharski   if ((((current_drive & 0x80) || (current_slice != 0))
86*1b8adde7SWilliam Kucharski        && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))
87*1b8adde7SWilliam Kucharski       || part_length < (SBLOCK + (SBSIZE / DEV_BSIZE))
88*1b8adde7SWilliam Kucharski       || !devread (SBLOCK, 0, SBSIZE, (char *) SUPERBLOCK)
89*1b8adde7SWilliam Kucharski       || SUPERBLOCK->fs_magic != FS_MAGIC)
90*1b8adde7SWilliam Kucharski     retval = 0;
91*1b8adde7SWilliam Kucharski 
92*1b8adde7SWilliam Kucharski   mapblock = -1;
93*1b8adde7SWilliam Kucharski   mapblock_offset = -1;
94*1b8adde7SWilliam Kucharski 
95*1b8adde7SWilliam Kucharski   return retval;
96*1b8adde7SWilliam Kucharski }
97*1b8adde7SWilliam Kucharski 
98*1b8adde7SWilliam Kucharski static int
99*1b8adde7SWilliam Kucharski block_map (int file_block)
100*1b8adde7SWilliam Kucharski {
101*1b8adde7SWilliam Kucharski   int bnum, offset, bsize;
102*1b8adde7SWilliam Kucharski 
103*1b8adde7SWilliam Kucharski   if (file_block < NDADDR)
104*1b8adde7SWilliam Kucharski     return (INODE->i_db[file_block]);
105*1b8adde7SWilliam Kucharski 
106*1b8adde7SWilliam Kucharski   /* If the blockmap loaded does not include FILE_BLOCK,
107*1b8adde7SWilliam Kucharski      load a new blockmap.  */
108*1b8adde7SWilliam Kucharski   if ((bnum = fsbtodb (SUPERBLOCK, INODE->i_ib[0])) != mapblock
109*1b8adde7SWilliam Kucharski       || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize))
110*1b8adde7SWilliam Kucharski     {
111*1b8adde7SWilliam Kucharski       if (MAPBUF_LEN < SUPERBLOCK->fs_bsize)
112*1b8adde7SWilliam Kucharski 	{
113*1b8adde7SWilliam Kucharski 	  offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK));
114*1b8adde7SWilliam Kucharski 	  bsize = MAPBUF_LEN;
115*1b8adde7SWilliam Kucharski 
116*1b8adde7SWilliam Kucharski 	  if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize)
117*1b8adde7SWilliam Kucharski 	    offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int);
118*1b8adde7SWilliam Kucharski 	}
119*1b8adde7SWilliam Kucharski       else
120*1b8adde7SWilliam Kucharski 	{
121*1b8adde7SWilliam Kucharski 	  bsize = SUPERBLOCK->fs_bsize;
122*1b8adde7SWilliam Kucharski 	  offset = 0;
123*1b8adde7SWilliam Kucharski 	}
124*1b8adde7SWilliam Kucharski 
125*1b8adde7SWilliam Kucharski       if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF))
126*1b8adde7SWilliam Kucharski 	{
127*1b8adde7SWilliam Kucharski 	  mapblock = -1;
128*1b8adde7SWilliam Kucharski 	  mapblock_bsize = -1;
129*1b8adde7SWilliam Kucharski 	  mapblock_offset = -1;
130*1b8adde7SWilliam Kucharski 	  errnum = ERR_FSYS_CORRUPT;
131*1b8adde7SWilliam Kucharski 	  return -1;
132*1b8adde7SWilliam Kucharski 	}
133*1b8adde7SWilliam Kucharski 
134*1b8adde7SWilliam Kucharski       mapblock = bnum;
135*1b8adde7SWilliam Kucharski       mapblock_bsize = bsize;
136*1b8adde7SWilliam Kucharski       mapblock_offset = offset;
137*1b8adde7SWilliam Kucharski     }
138*1b8adde7SWilliam Kucharski 
139*1b8adde7SWilliam Kucharski   return (((int *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK))
140*1b8adde7SWilliam Kucharski 			  - mapblock_offset]);
141*1b8adde7SWilliam Kucharski }
142*1b8adde7SWilliam Kucharski 
143*1b8adde7SWilliam Kucharski 
144*1b8adde7SWilliam Kucharski int
145*1b8adde7SWilliam Kucharski ffs_read (char *buf, int len)
146*1b8adde7SWilliam Kucharski {
147*1b8adde7SWilliam Kucharski   int logno, off, size, map, ret = 0;
148*1b8adde7SWilliam Kucharski 
149*1b8adde7SWilliam Kucharski   while (len && !errnum)
150*1b8adde7SWilliam Kucharski     {
151*1b8adde7SWilliam Kucharski       off = blkoff (SUPERBLOCK, filepos);
152*1b8adde7SWilliam Kucharski       logno = lblkno (SUPERBLOCK, filepos);
153*1b8adde7SWilliam Kucharski       size = blksize (SUPERBLOCK, INODE, logno);
154*1b8adde7SWilliam Kucharski 
155*1b8adde7SWilliam Kucharski       if ((map = block_map (logno)) < 0)
156*1b8adde7SWilliam Kucharski 	break;
157*1b8adde7SWilliam Kucharski 
158*1b8adde7SWilliam Kucharski       size -= off;
159*1b8adde7SWilliam Kucharski 
160*1b8adde7SWilliam Kucharski       if (size > len)
161*1b8adde7SWilliam Kucharski 	size = len;
162*1b8adde7SWilliam Kucharski 
163*1b8adde7SWilliam Kucharski       disk_read_func = disk_read_hook;
164*1b8adde7SWilliam Kucharski 
165*1b8adde7SWilliam Kucharski       devread (fsbtodb (SUPERBLOCK, map), off, size, buf);
166*1b8adde7SWilliam Kucharski 
167*1b8adde7SWilliam Kucharski       disk_read_func = NULL;
168*1b8adde7SWilliam Kucharski 
169*1b8adde7SWilliam Kucharski       buf += size;
170*1b8adde7SWilliam Kucharski       len -= size;
171*1b8adde7SWilliam Kucharski       filepos += size;
172*1b8adde7SWilliam Kucharski       ret += size;
173*1b8adde7SWilliam Kucharski     }
174*1b8adde7SWilliam Kucharski 
175*1b8adde7SWilliam Kucharski   if (errnum)
176*1b8adde7SWilliam Kucharski     ret = 0;
177*1b8adde7SWilliam Kucharski 
178*1b8adde7SWilliam Kucharski   return ret;
179*1b8adde7SWilliam Kucharski }
180*1b8adde7SWilliam Kucharski 
181*1b8adde7SWilliam Kucharski 
182*1b8adde7SWilliam Kucharski int
183*1b8adde7SWilliam Kucharski ffs_dir (char *dirname)
184*1b8adde7SWilliam Kucharski {
185*1b8adde7SWilliam Kucharski   char *rest, ch;
186*1b8adde7SWilliam Kucharski   int block, off, loc, map, ino = ROOTINO;
187*1b8adde7SWilliam Kucharski   struct direct *dp;
188*1b8adde7SWilliam Kucharski 
189*1b8adde7SWilliam Kucharski /* main loop to find destination inode */
190*1b8adde7SWilliam Kucharski loop:
191*1b8adde7SWilliam Kucharski 
192*1b8adde7SWilliam Kucharski   /* load current inode (defaults to the root inode) */
193*1b8adde7SWilliam Kucharski 
194*1b8adde7SWilliam Kucharski 	if (!devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)),
195*1b8adde7SWilliam Kucharski 								ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode),
196*1b8adde7SWilliam Kucharski 								sizeof (struct dinode), (char *) INODE))
197*1b8adde7SWilliam Kucharski 			return 0;			/* XXX what return value? */
198*1b8adde7SWilliam Kucharski 
199*1b8adde7SWilliam Kucharski   /* if we have a real file (and we're not just printing possibilities),
200*1b8adde7SWilliam Kucharski      then this is where we want to exit */
201*1b8adde7SWilliam Kucharski 
202*1b8adde7SWilliam Kucharski   if (!*dirname || isspace (*dirname))
203*1b8adde7SWilliam Kucharski     {
204*1b8adde7SWilliam Kucharski       if ((INODE->i_mode & IFMT) != IFREG)
205*1b8adde7SWilliam Kucharski 	{
206*1b8adde7SWilliam Kucharski 	  errnum = ERR_BAD_FILETYPE;
207*1b8adde7SWilliam Kucharski 	  return 0;
208*1b8adde7SWilliam Kucharski 	}
209*1b8adde7SWilliam Kucharski 
210*1b8adde7SWilliam Kucharski       filemax = INODE->i_size;
211*1b8adde7SWilliam Kucharski 
212*1b8adde7SWilliam Kucharski       /* incomplete implementation requires this! */
213*1b8adde7SWilliam Kucharski       fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize;
214*1b8adde7SWilliam Kucharski       return 1;
215*1b8adde7SWilliam Kucharski     }
216*1b8adde7SWilliam Kucharski 
217*1b8adde7SWilliam Kucharski   /* continue with file/directory name interpretation */
218*1b8adde7SWilliam Kucharski 
219*1b8adde7SWilliam Kucharski   while (*dirname == '/')
220*1b8adde7SWilliam Kucharski     dirname++;
221*1b8adde7SWilliam Kucharski 
222*1b8adde7SWilliam Kucharski   if (!(INODE->i_size) || ((INODE->i_mode & IFMT) != IFDIR))
223*1b8adde7SWilliam Kucharski     {
224*1b8adde7SWilliam Kucharski       errnum = ERR_BAD_FILETYPE;
225*1b8adde7SWilliam Kucharski       return 0;
226*1b8adde7SWilliam Kucharski     }
227*1b8adde7SWilliam Kucharski 
228*1b8adde7SWilliam Kucharski   for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
229*1b8adde7SWilliam Kucharski 
230*1b8adde7SWilliam Kucharski   *rest = 0;
231*1b8adde7SWilliam Kucharski   loc = 0;
232*1b8adde7SWilliam Kucharski 
233*1b8adde7SWilliam Kucharski   /* loop for reading a the entries in a directory */
234*1b8adde7SWilliam Kucharski 
235*1b8adde7SWilliam Kucharski   do
236*1b8adde7SWilliam Kucharski     {
237*1b8adde7SWilliam Kucharski       if (loc >= INODE->i_size)
238*1b8adde7SWilliam Kucharski 	{
239*1b8adde7SWilliam Kucharski #if 0
240*1b8adde7SWilliam Kucharski 	  putchar ('\n');
241*1b8adde7SWilliam Kucharski #endif
242*1b8adde7SWilliam Kucharski 
243*1b8adde7SWilliam Kucharski 	  if (print_possibilities < 0)
244*1b8adde7SWilliam Kucharski 	    return 1;
245*1b8adde7SWilliam Kucharski 
246*1b8adde7SWilliam Kucharski 	  errnum = ERR_FILE_NOT_FOUND;
247*1b8adde7SWilliam Kucharski 	  *rest = ch;
248*1b8adde7SWilliam Kucharski 	  return 0;
249*1b8adde7SWilliam Kucharski 	}
250*1b8adde7SWilliam Kucharski 
251*1b8adde7SWilliam Kucharski       if (!(off = blkoff (SUPERBLOCK, loc)))
252*1b8adde7SWilliam Kucharski 	{
253*1b8adde7SWilliam Kucharski 	  block = lblkno (SUPERBLOCK, loc);
254*1b8adde7SWilliam Kucharski 
255*1b8adde7SWilliam Kucharski 	  if ((map = block_map (block)) < 0
256*1b8adde7SWilliam Kucharski 	      || !devread (fsbtodb (SUPERBLOCK, map), 0,
257*1b8adde7SWilliam Kucharski 			   blksize (SUPERBLOCK, INODE, block),
258*1b8adde7SWilliam Kucharski 			   (char *) FSYS_BUF))
259*1b8adde7SWilliam Kucharski 	    {
260*1b8adde7SWilliam Kucharski 	      errnum = ERR_FSYS_CORRUPT;
261*1b8adde7SWilliam Kucharski 	      *rest = ch;
262*1b8adde7SWilliam Kucharski 	      return 0;
263*1b8adde7SWilliam Kucharski 	    }
264*1b8adde7SWilliam Kucharski 	}
265*1b8adde7SWilliam Kucharski 
266*1b8adde7SWilliam Kucharski       dp = (struct direct *) (FSYS_BUF + off);
267*1b8adde7SWilliam Kucharski       loc += dp->d_reclen;
268*1b8adde7SWilliam Kucharski 
269*1b8adde7SWilliam Kucharski #ifndef STAGE1_5
270*1b8adde7SWilliam Kucharski       if (dp->d_ino && print_possibilities && ch != '/'
271*1b8adde7SWilliam Kucharski 	  && (!*dirname || substring (dirname, dp->d_name) <= 0))
272*1b8adde7SWilliam Kucharski 	{
273*1b8adde7SWilliam Kucharski 	  if (print_possibilities > 0)
274*1b8adde7SWilliam Kucharski 	    print_possibilities = -print_possibilities;
275*1b8adde7SWilliam Kucharski 
276*1b8adde7SWilliam Kucharski 	  print_a_completion (dp->d_name);
277*1b8adde7SWilliam Kucharski 	}
278*1b8adde7SWilliam Kucharski #endif /* STAGE1_5 */
279*1b8adde7SWilliam Kucharski     }
280*1b8adde7SWilliam Kucharski   while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
281*1b8adde7SWilliam Kucharski 			|| (print_possibilities && ch != '/')));
282*1b8adde7SWilliam Kucharski 
283*1b8adde7SWilliam Kucharski   /* only get here if we have a matching directory entry */
284*1b8adde7SWilliam Kucharski 
285*1b8adde7SWilliam Kucharski   ino = dp->d_ino;
286*1b8adde7SWilliam Kucharski   *(dirname = rest) = ch;
287*1b8adde7SWilliam Kucharski 
288*1b8adde7SWilliam Kucharski   /* go back to main loop at top of function */
289*1b8adde7SWilliam Kucharski   goto loop;
290*1b8adde7SWilliam Kucharski }
291*1b8adde7SWilliam Kucharski 
292*1b8adde7SWilliam Kucharski int
293*1b8adde7SWilliam Kucharski ffs_embed (int *start_sector, int needed_sectors)
294*1b8adde7SWilliam Kucharski {
295*1b8adde7SWilliam Kucharski   /* XXX: I don't know if this is really correct. Someone who is
296*1b8adde7SWilliam Kucharski      familiar with BSD should check for this.  */
297*1b8adde7SWilliam Kucharski   if (needed_sectors > 14)
298*1b8adde7SWilliam Kucharski     return 0;
299*1b8adde7SWilliam Kucharski 
300*1b8adde7SWilliam Kucharski   *start_sector = 1;
301*1b8adde7SWilliam Kucharski #if 1
302*1b8adde7SWilliam Kucharski   /* FIXME: Disable the embedding in FFS until someone checks if
303*1b8adde7SWilliam Kucharski      the code above is correct.  */
304*1b8adde7SWilliam Kucharski   return 0;
305*1b8adde7SWilliam Kucharski #else
306*1b8adde7SWilliam Kucharski   return 1;
307*1b8adde7SWilliam Kucharski #endif
308*1b8adde7SWilliam Kucharski }
309*1b8adde7SWilliam Kucharski 
310*1b8adde7SWilliam Kucharski #endif /* FSYS_FFS */
311