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