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