17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  *  GRUB  --  GRand Unified Bootloader
37c478bd9Sstevel@tonic-gate  *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  *  This program is free software; you can redistribute it and/or modify
67c478bd9Sstevel@tonic-gate  *  it under the terms of the GNU General Public License as published by
77c478bd9Sstevel@tonic-gate  *  the Free Software Foundation; either version 2 of the License, or
87c478bd9Sstevel@tonic-gate  *  (at your option) any later version.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  *  This program is distributed in the hope that it will be useful,
117c478bd9Sstevel@tonic-gate  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
127c478bd9Sstevel@tonic-gate  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
137c478bd9Sstevel@tonic-gate  *  GNU General Public License for more details.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  *  You should have received a copy of the GNU General Public License
167c478bd9Sstevel@tonic-gate  *  along with this program; if not, write to the Free Software
177c478bd9Sstevel@tonic-gate  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
187c478bd9Sstevel@tonic-gate  */
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate /*
217c478bd9Sstevel@tonic-gate  * Elements of this file were originally from the FreeBSD "biosboot"
227c478bd9Sstevel@tonic-gate  * bootloader file "disk.c" dated 4/12/95.
237c478bd9Sstevel@tonic-gate  *
247c478bd9Sstevel@tonic-gate  * The license and header comments from that file are included here.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * Mach Operating System
297c478bd9Sstevel@tonic-gate  * Copyright (c) 1992, 1991 Carnegie Mellon University
307c478bd9Sstevel@tonic-gate  * All Rights Reserved.
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify and distribute this software and its
337c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that both the copyright
347c478bd9Sstevel@tonic-gate  * notice and this permission notice appear in all copies of the
357c478bd9Sstevel@tonic-gate  * software, derivative works or modified versions, and any portions
367c478bd9Sstevel@tonic-gate  * thereof, and that both notices appear in supporting documentation.
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
397c478bd9Sstevel@tonic-gate  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
407c478bd9Sstevel@tonic-gate  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * Carnegie Mellon requests users of this software to return to
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
457c478bd9Sstevel@tonic-gate  *  School of Computer Science
467c478bd9Sstevel@tonic-gate  *  Carnegie Mellon University
477c478bd9Sstevel@tonic-gate  *  Pittsburgh PA 15213-3890
487c478bd9Sstevel@tonic-gate  *
497c478bd9Sstevel@tonic-gate  * any improvements or extensions that they make and grant Carnegie Mellon
507c478bd9Sstevel@tonic-gate  * the rights to redistribute these changes.
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  *	from: Mach, Revision 2.2  92/04/04  11:35:49  rpd
537c478bd9Sstevel@tonic-gate  *	$Id: fsys_ffs.c,v 1.1.1.1 2003/11/20 02:04:59 fengshuo Exp $
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #ifdef FSYS_FFS
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #include "shared.h"
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #include "filesys.h"
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include "defs.h"
637c478bd9Sstevel@tonic-gate #include "disk_inode.h"
647c478bd9Sstevel@tonic-gate #include "disk_inode_ffs.h"
657c478bd9Sstevel@tonic-gate #include "dir.h"
667c478bd9Sstevel@tonic-gate #include "fs.h"
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /* used for filesystem map blocks */
697c478bd9Sstevel@tonic-gate static int mapblock;
707c478bd9Sstevel@tonic-gate static int mapblock_offset;
717c478bd9Sstevel@tonic-gate static int mapblock_bsize;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /* pointer to superblock */
747c478bd9Sstevel@tonic-gate #define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 ))
757c478bd9Sstevel@tonic-gate #define INODE ((struct icommon *) ( FSYS_BUF + 16384 ))
767c478bd9Sstevel@tonic-gate #define MAPBUF ( FSYS_BUF + 24576 )
777c478bd9Sstevel@tonic-gate #define MAPBUF_LEN 8192
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate int
ffs_mount(void)817c478bd9Sstevel@tonic-gate ffs_mount (void)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate   int retval = 1;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate   if ((((current_drive & 0x80) || (current_slice != 0))
867c478bd9Sstevel@tonic-gate        && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))
877c478bd9Sstevel@tonic-gate       || part_length < (SBLOCK + (SBSIZE / DEV_BSIZE))
887c478bd9Sstevel@tonic-gate       || !devread (SBLOCK, 0, SBSIZE, (char *) SUPERBLOCK)
897c478bd9Sstevel@tonic-gate       || SUPERBLOCK->fs_magic != FS_MAGIC)
907c478bd9Sstevel@tonic-gate     retval = 0;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate   mapblock = -1;
937c478bd9Sstevel@tonic-gate   mapblock_offset = -1;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate   return retval;
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static int
block_map(int file_block)997c478bd9Sstevel@tonic-gate block_map (int file_block)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate   int bnum, offset, bsize;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate   if (file_block < NDADDR)
1047c478bd9Sstevel@tonic-gate     return (INODE->i_db[file_block]);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate   /* If the blockmap loaded does not include FILE_BLOCK,
1077c478bd9Sstevel@tonic-gate      load a new blockmap.  */
1087c478bd9Sstevel@tonic-gate   if ((bnum = fsbtodb (SUPERBLOCK, INODE->i_ib[0])) != mapblock
1097c478bd9Sstevel@tonic-gate       || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize))
1107c478bd9Sstevel@tonic-gate     {
1117c478bd9Sstevel@tonic-gate       if (MAPBUF_LEN < SUPERBLOCK->fs_bsize)
1127c478bd9Sstevel@tonic-gate 	{
1137c478bd9Sstevel@tonic-gate 	  offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK));
1147c478bd9Sstevel@tonic-gate 	  bsize = MAPBUF_LEN;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	  if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize)
1177c478bd9Sstevel@tonic-gate 	    offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int);
1187c478bd9Sstevel@tonic-gate 	}
1197c478bd9Sstevel@tonic-gate       else
1207c478bd9Sstevel@tonic-gate 	{
1217c478bd9Sstevel@tonic-gate 	  bsize = SUPERBLOCK->fs_bsize;
1227c478bd9Sstevel@tonic-gate 	  offset = 0;
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate       if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF))
1267c478bd9Sstevel@tonic-gate 	{
1277c478bd9Sstevel@tonic-gate 	  mapblock = -1;
1287c478bd9Sstevel@tonic-gate 	  mapblock_bsize = -1;
1297c478bd9Sstevel@tonic-gate 	  mapblock_offset = -1;
1307c478bd9Sstevel@tonic-gate 	  errnum = ERR_FSYS_CORRUPT;
1317c478bd9Sstevel@tonic-gate 	  return -1;
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate       mapblock = bnum;
1357c478bd9Sstevel@tonic-gate       mapblock_bsize = bsize;
1367c478bd9Sstevel@tonic-gate       mapblock_offset = offset;
1377c478bd9Sstevel@tonic-gate     }
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate   return (((int *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK))
1407c478bd9Sstevel@tonic-gate 			  - mapblock_offset]);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate int
ffs_read(char * buf,int len)1457c478bd9Sstevel@tonic-gate ffs_read (char *buf, int len)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate   int logno, off, size, map, ret = 0;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate   while (len && !errnum)
1507c478bd9Sstevel@tonic-gate     {
1517c478bd9Sstevel@tonic-gate       off = blkoff (SUPERBLOCK, filepos);
1527c478bd9Sstevel@tonic-gate       logno = lblkno (SUPERBLOCK, filepos);
1537c478bd9Sstevel@tonic-gate       size = blksize (SUPERBLOCK, INODE, logno);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate       if ((map = block_map (logno)) < 0)
1567c478bd9Sstevel@tonic-gate 	break;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate       size -= off;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate       if (size > len)
1617c478bd9Sstevel@tonic-gate 	size = len;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate       disk_read_func = disk_read_hook;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate       devread (fsbtodb (SUPERBLOCK, map), off, size, buf);
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate       disk_read_func = NULL;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate       buf += size;
1707c478bd9Sstevel@tonic-gate       len -= size;
1717c478bd9Sstevel@tonic-gate       filepos += size;
1727c478bd9Sstevel@tonic-gate       ret += size;
1737c478bd9Sstevel@tonic-gate     }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate   if (errnum)
1767c478bd9Sstevel@tonic-gate     ret = 0;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate   return ret;
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate int
ffs_dir(char * dirname)1837c478bd9Sstevel@tonic-gate ffs_dir (char *dirname)
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate   char *rest, ch;
1867c478bd9Sstevel@tonic-gate   int block, off, loc, map, ino = ROOTINO;
1877c478bd9Sstevel@tonic-gate   struct direct *dp;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate /* main loop to find destination inode */
1907c478bd9Sstevel@tonic-gate loop:
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate   /* load current inode (defaults to the root inode) */
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (!devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)),
1957c478bd9Sstevel@tonic-gate 								ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode),
1967c478bd9Sstevel@tonic-gate 								sizeof (struct dinode), (char *) INODE))
1977c478bd9Sstevel@tonic-gate 			return 0;			/* XXX what return value? */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate   /* if we have a real file (and we're not just printing possibilities),
2007c478bd9Sstevel@tonic-gate      then this is where we want to exit */
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate   if (!*dirname || isspace (*dirname))
2037c478bd9Sstevel@tonic-gate     {
2047c478bd9Sstevel@tonic-gate       if ((INODE->i_mode & IFMT) != IFREG)
2057c478bd9Sstevel@tonic-gate 	{
2067c478bd9Sstevel@tonic-gate 	  errnum = ERR_BAD_FILETYPE;
2077c478bd9Sstevel@tonic-gate 	  return 0;
2087c478bd9Sstevel@tonic-gate 	}
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate       filemax = INODE->i_size;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate       /* incomplete implementation requires this! */
2137c478bd9Sstevel@tonic-gate       fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize;
2147c478bd9Sstevel@tonic-gate       return 1;
2157c478bd9Sstevel@tonic-gate     }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate   /* continue with file/directory name interpretation */
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate   while (*dirname == '/')
2207c478bd9Sstevel@tonic-gate     dirname++;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate   if (!(INODE->i_size) || ((INODE->i_mode & IFMT) != IFDIR))
2237c478bd9Sstevel@tonic-gate     {
2247c478bd9Sstevel@tonic-gate       errnum = ERR_BAD_FILETYPE;
2257c478bd9Sstevel@tonic-gate       return 0;
2267c478bd9Sstevel@tonic-gate     }
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate   for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate   *rest = 0;
2317c478bd9Sstevel@tonic-gate   loc = 0;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate   /* loop for reading a the entries in a directory */
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate   do
2367c478bd9Sstevel@tonic-gate     {
2377c478bd9Sstevel@tonic-gate       if (loc >= INODE->i_size)
2387c478bd9Sstevel@tonic-gate 	{
2397c478bd9Sstevel@tonic-gate #if 0
2407c478bd9Sstevel@tonic-gate 	  putchar ('\n');
2417c478bd9Sstevel@tonic-gate #endif
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	  if (print_possibilities < 0)
2447c478bd9Sstevel@tonic-gate 	    return 1;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	  errnum = ERR_FILE_NOT_FOUND;
2477c478bd9Sstevel@tonic-gate 	  *rest = ch;
2487c478bd9Sstevel@tonic-gate 	  return 0;
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate       if (!(off = blkoff (SUPERBLOCK, loc)))
2527c478bd9Sstevel@tonic-gate 	{
2537c478bd9Sstevel@tonic-gate 	  block = lblkno (SUPERBLOCK, loc);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	  if ((map = block_map (block)) < 0
2567c478bd9Sstevel@tonic-gate 	      || !devread (fsbtodb (SUPERBLOCK, map), 0,
2577c478bd9Sstevel@tonic-gate 			   blksize (SUPERBLOCK, INODE, block),
2587c478bd9Sstevel@tonic-gate 			   (char *) FSYS_BUF))
2597c478bd9Sstevel@tonic-gate 	    {
2607c478bd9Sstevel@tonic-gate 	      errnum = ERR_FSYS_CORRUPT;
2617c478bd9Sstevel@tonic-gate 	      *rest = ch;
2627c478bd9Sstevel@tonic-gate 	      return 0;
2637c478bd9Sstevel@tonic-gate 	    }
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate       dp = (struct direct *) (FSYS_BUF + off);
2677c478bd9Sstevel@tonic-gate       loc += dp->d_reclen;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate #ifndef STAGE1_5
2707c478bd9Sstevel@tonic-gate       if (dp->d_ino && print_possibilities && ch != '/'
2717c478bd9Sstevel@tonic-gate 	  && (!*dirname || substring (dirname, dp->d_name) <= 0))
2727c478bd9Sstevel@tonic-gate 	{
2737c478bd9Sstevel@tonic-gate 	  if (print_possibilities > 0)
2747c478bd9Sstevel@tonic-gate 	    print_possibilities = -print_possibilities;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	  print_a_completion (dp->d_name);
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate #endif /* STAGE1_5 */
2797c478bd9Sstevel@tonic-gate     }
2807c478bd9Sstevel@tonic-gate   while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
2817c478bd9Sstevel@tonic-gate 			|| (print_possibilities && ch != '/')));
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate   /* only get here if we have a matching directory entry */
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate   ino = dp->d_ino;
2867c478bd9Sstevel@tonic-gate   *(dirname = rest) = ch;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate   /* go back to main loop at top of function */
2897c478bd9Sstevel@tonic-gate   goto loop;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate int
ffs_embed(unsigned long long * start_sector,int needed_sectors)293*2e1aefd1SJoshua M. Clulow ffs_embed (unsigned long long *start_sector, int needed_sectors)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate   /* XXX: I don't know if this is really correct. Someone who is
2967c478bd9Sstevel@tonic-gate      familiar with BSD should check for this.  */
2977c478bd9Sstevel@tonic-gate   if (needed_sectors > 14)
2987c478bd9Sstevel@tonic-gate     return 0;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate   *start_sector = 1;
3017c478bd9Sstevel@tonic-gate #if 1
3027c478bd9Sstevel@tonic-gate   /* FIXME: Disable the embedding in FFS until someone checks if
3037c478bd9Sstevel@tonic-gate      the code above is correct.  */
3047c478bd9Sstevel@tonic-gate   return 0;
3057c478bd9Sstevel@tonic-gate #else
3067c478bd9Sstevel@tonic-gate   return 1;
3077c478bd9Sstevel@tonic-gate #endif
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate #endif /* FSYS_FFS */
311