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