|
|
1.1 ! root 1: /* ! 2: * GRUB -- GRand Unified Bootloader ! 3: * Copyright (c) 2000, 2001 Free Software Foundation, Inc. ! 4: * Copyright (c) 2005 Rink Springer ! 5: * ! 6: * This file is based on FreeBSD 5.4-RELEASE's /sys/boot/common/ufsread.c, ! 7: * and has some minor patches so it'll work with Cromwell/GRUB. ! 8: * ! 9: */ ! 10: /*- ! 11: * Copyright (c) 2002 McAfee, Inc. ! 12: * All rights reserved. ! 13: * ! 14: * This software was developed for the FreeBSD Project by Marshall ! 15: * Kirk McKusick and McAfee Research,, the Security Research Division of ! 16: * McAfee, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as ! 17: * part of the DARPA CHATS research program ! 18: * ! 19: * Redistribution and use in source and binary forms, with or without ! 20: * modification, are permitted provided that the following conditions ! 21: * are met: ! 22: * 1. Redistributions of source code must retain the above copyright ! 23: * notice, this list of conditions and the following disclaimer. ! 24: * 2. Redistributions in binary form must reproduce the above copyright ! 25: * notice, this list of conditions and the following disclaimer in the ! 26: * documentation and/or other materials provided with the distribution. ! 27: * ! 28: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ! 29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 31: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ! 32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 38: * SUCH DAMAGE. ! 39: */ ! 40: /*- ! 41: * Copyright (c) 1998 Robert Nordier ! 42: * All rights reserved. ! 43: * ! 44: * Redistribution and use in source and binary forms are freely ! 45: * permitted provided that the above copyright notice and this ! 46: * paragraph and the following disclaimer are duplicated in all ! 47: * such forms. ! 48: * ! 49: * This software is provided "AS IS" and without any express or ! 50: * implied warranties, including, without limitation, the implied ! 51: * warranties of merchantability and fitness for a particular ! 52: * purpose. ! 53: */ ! 54: #ifdef FSYS_UFS ! 55: ! 56: #include "asm/types.h" ! 57: ! 58: #include "shared.h" ! 59: #include "filesys.h" ! 60: ! 61: #include "ufs_dinode.h" ! 62: #include "ufs_fs.h" ! 63: ! 64: #ifdef __i386__ ! 65: /* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase ! 66: (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can ! 67: support both UFS1 and UFS2 again. */ ! 68: #undef cgbase ! 69: #define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c))) ! 70: #endif ! 71: ! 72: /* ! 73: * We use 4k `virtual' blocks for filesystem data, whatever the actual ! 74: * filesystem block size. FFS blocks are always a multiple of 4k. ! 75: */ ! 76: #define VBLKSHIFT 12 ! 77: #define VBLKSIZE (1 << VBLKSHIFT) ! 78: #define VBLKMASK (VBLKSIZE - 1) ! 79: #define DBPERVBLK (VBLKSIZE / DEV_BSIZE) ! 80: #define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT)) ! 81: #define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT)) ! 82: #define INO_TO_VBA(fs, ipervblk, x) \ ! 83: (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \ ! 84: (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK)) ! 85: #define INO_TO_VBO(ipervblk, x) ((x) % ipervblk) ! 86: #define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \ ! 87: ((off) / VBLKSIZE) * DBPERVBLK) ! 88: #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK) ! 89: ! 90: /* Buffers that must not span a 64k boundary. */ ! 91: struct dmadat { ! 92: char blkbuf[VBLKSIZE]; /* filesystem blocks */ ! 93: char indbuf[VBLKSIZE]; /* indir blocks */ ! 94: char sbbuf[SBLOCKSIZE]; /* superblock */ ! 95: char secbuf[DEV_BSIZE]; /* for MBR/disklabel */ ! 96: }; ! 97: static struct dmadat *dmadat = (struct dmadat*)FSYS_BUF; ! 98: ! 99: #define SUPERBLOCK ((struct fs*)dmadat->sbbuf) ! 100: ! 101: ino_t lookup(const char *); ! 102: ssize_t fsread(ino_t, void *, size_t); ! 103: ! 104: static int dsk_meta; ! 105: static uint32_t fs_off; ! 106: static ino_t cur_ino = 0; ! 107: ! 108: static inline int ! 109: dskread (void* buf, unsigned lba, unsigned nblk) ! 110: { ! 111: return !devread (lba, 0, nblk * DEV_BSIZE, buf) ? -1 : 0; ! 112: } ! 113: ! 114: #if defined(UFS2_ONLY) ! 115: #define DIP(field) dp2.field ! 116: #elif defined(UFS1_ONLY) ! 117: #define DIP(field) dp1.field ! 118: #else ! 119: #define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field ! 120: #endif ! 121: ! 122: static __inline int ! 123: fsfind(const char *name, ino_t * ino) ! 124: { ! 125: char buf[DEV_BSIZE]; ! 126: struct ufs_dirent *d; ! 127: char *s; ! 128: ssize_t n; ! 129: #ifndef UFS2_ONLY ! 130: static struct ufs1_dinode dp1; ! 131: #endif ! 132: #ifndef UFS1_ONLY ! 133: static struct ufs2_dinode dp2; ! 134: #endif ! 135: char* blkbuf = dmadat->blkbuf; ! 136: struct fs* fs = (struct fs *)dmadat->sbbuf; ! 137: ! 138: fs_off = 0; ! 139: while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) ! 140: for (s = buf; s < buf + DEV_BSIZE;) { ! 141: d = (void *)s; ! 142: if (!strcmp(name, d->d_name)) { ! 143: *ino = d->d_fileno; ! 144: ! 145: /* below is for grub, which wants the file size ! 146: */ ! 147: n = IPERVBLK(fs); ! 148: if (dskread(blkbuf, INO_TO_VBA(fs, n, (*ino)), DBPERVBLK)) ! 149: return -1; ! 150: n = INO_TO_VBO(n, (*ino)); ! 151: #if defined(UFS1_ONLY) ! 152: dp1 = ((struct ufs1_dinode *)blkbuf)[n]; ! 153: #elif defined(UFS2_ONLY) ! 154: dp2 = ((struct ufs2_dinode *)blkbuf)[n]; ! 155: #else ! 156: if (fs->fs_magic == FS_UFS1_MAGIC) ! 157: dp1 = ((struct ufs1_dinode *)blkbuf)[n]; ! 158: else ! 159: dp2 = ((struct ufs2_dinode *)blkbuf)[n]; ! 160: #endif ! 161: ! 162: filemax = DIP(di_size); ! 163: return d->d_type; ! 164: } ! 165: s += d->d_reclen; ! 166: } ! 167: return 0; ! 168: } ! 169: ! 170: ino_t ! 171: lookup(const char *path) ! 172: { ! 173: char name[MAXNAMLEN + 1]; ! 174: const char *s; ! 175: ino_t ino; ! 176: ssize_t n; ! 177: int dt; ! 178: ! 179: ino = ROOTINO; ! 180: dt = DT_DIR; ! 181: name[0] = '/'; ! 182: name[1] = '\0'; ! 183: for (;;) { ! 184: if (*path == '/') ! 185: path++; ! 186: if (!*path) ! 187: break; ! 188: for (s = path; *s && *s != '/'; s++); ! 189: if ((n = s - path) > MAXNAMLEN) ! 190: return 0; ! 191: memcpy(name, path, n); ! 192: name[n] = 0; ! 193: if (dt != DT_DIR) { ! 194: printk("%s: not a directory.\n", name); ! 195: return (0); ! 196: } ! 197: if ((dt = fsfind(name, &ino)) <= 0) ! 198: break; ! 199: path = s; ! 200: } ! 201: return dt == DT_REG ? ino : 0; ! 202: } ! 203: ! 204: /* ! 205: * Possible superblock locations ordered from most to least likely. ! 206: */ ! 207: static const int sblock_try[] = SBLOCKSEARCH; ! 208: ! 209: ssize_t ! 210: fsread(ino_t inode, void *buf, size_t nbyte) ! 211: { ! 212: #ifndef UFS2_ONLY ! 213: static struct ufs1_dinode dp1; ! 214: #endif ! 215: #ifndef UFS1_ONLY ! 216: static struct ufs2_dinode dp2; ! 217: #endif ! 218: static ino_t inomap; ! 219: char *blkbuf; ! 220: void *indbuf; ! 221: struct fs *fs; ! 222: char *s; ! 223: size_t n, nb, size, off, vboff; ! 224: ufs_lbn_t lbn; ! 225: ufs2_daddr_t addr, vbaddr; ! 226: static ufs2_daddr_t blkmap, indmap; ! 227: unsigned int u; ! 228: ! 229: ! 230: blkbuf = dmadat->blkbuf; ! 231: indbuf = dmadat->indbuf; ! 232: fs = (struct fs *)dmadat->sbbuf; ! 233: if (!dsk_meta) { ! 234: inomap = 0; ! 235: for (n = 0; sblock_try[n] != -1; n++) { ! 236: if (dskread(fs, sblock_try[n] / DEV_BSIZE, ! 237: SBLOCKSIZE / DEV_BSIZE)) ! 238: return -1; ! 239: if (( ! 240: #if defined(UFS1_ONLY) ! 241: fs->fs_magic == FS_UFS1_MAGIC ! 242: #elif defined(UFS2_ONLY) ! 243: (fs->fs_magic == FS_UFS2_MAGIC && ! 244: fs->fs_sblockloc == sblock_try[n]) ! 245: #else ! 246: fs->fs_magic == FS_UFS1_MAGIC || ! 247: (fs->fs_magic == FS_UFS2_MAGIC && ! 248: fs->fs_sblockloc == sblock_try[n]) ! 249: #endif ! 250: ) && ! 251: fs->fs_bsize <= MAXBSIZE && ! 252: fs->fs_bsize >= sizeof(struct fs)) ! 253: break; ! 254: } ! 255: if (sblock_try[n] == -1) { ! 256: printk("Not ufs\n"); ! 257: return -1; ! 258: } ! 259: dsk_meta++; ! 260: } ! 261: if (!inode) ! 262: return 0; ! 263: if (inomap != inode) { ! 264: n = IPERVBLK(fs); ! 265: if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK)) ! 266: return -1; ! 267: n = INO_TO_VBO(n, inode); ! 268: #if defined(UFS1_ONLY) ! 269: dp1 = ((struct ufs1_dinode *)blkbuf)[n]; ! 270: #elif defined(UFS2_ONLY) ! 271: dp2 = ((struct ufs2_dinode *)blkbuf)[n]; ! 272: #else ! 273: if (fs->fs_magic == FS_UFS1_MAGIC) ! 274: dp1 = ((struct ufs1_dinode *)blkbuf)[n]; ! 275: else ! 276: dp2 = ((struct ufs2_dinode *)blkbuf)[n]; ! 277: #endif ! 278: inomap = inode; ! 279: fs_off = 0; ! 280: blkmap = indmap = 0; ! 281: } ! 282: s = buf; ! 283: size = DIP(di_size); ! 284: n = size - fs_off; ! 285: if (nbyte > n) ! 286: nbyte = n; ! 287: nb = nbyte; ! 288: while (nb) { ! 289: lbn = lblkno(fs, fs_off); ! 290: off = blkoff(fs, fs_off); ! 291: if (lbn < NDADDR) { ! 292: addr = DIP(di_db[lbn]); ! 293: } else if (lbn < NDADDR + NINDIR(fs)) { ! 294: n = INDIRPERVBLK(fs); ! 295: addr = DIP(di_ib[0]); ! 296: u = (unsigned int)(lbn - NDADDR) / (n * DBPERVBLK); ! 297: vbaddr = fsbtodb(fs, addr) + u; ! 298: if (indmap != vbaddr) { ! 299: if (dskread(indbuf, vbaddr, DBPERVBLK)) ! 300: return -1; ! 301: indmap = vbaddr; ! 302: } ! 303: n = (lbn - NDADDR) & (n - 1); ! 304: #if defined(UFS1_ONLY) ! 305: addr = ((ufs1_daddr_t *)indbuf)[n]; ! 306: #elif defined(UFS2_ONLY) ! 307: addr = ((ufs2_daddr_t *)indbuf)[n]; ! 308: #else ! 309: if (fs->fs_magic == FS_UFS1_MAGIC) ! 310: addr = ((ufs1_daddr_t *)indbuf)[n]; ! 311: else ! 312: addr = ((ufs2_daddr_t *)indbuf)[n]; ! 313: #endif ! 314: } else { ! 315: return -1; ! 316: } ! 317: vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK; ! 318: vboff = off & VBLKMASK; ! 319: n = sblksize(fs, size, lbn) - (off & ~VBLKMASK); ! 320: if (n > VBLKSIZE) ! 321: n = VBLKSIZE; ! 322: if (blkmap != vbaddr) { ! 323: if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT)) ! 324: return -1; ! 325: blkmap = vbaddr; ! 326: } ! 327: n -= vboff; ! 328: if (n > nb) ! 329: n = nb; ! 330: memcpy(s, blkbuf + vboff, n); ! 331: s += n; ! 332: fs_off += n; ! 333: nb -= n; ! 334: } ! 335: return nbyte; ! 336: } ! 337: ! 338: int ! 339: ufs_mount (void) ! 340: { ! 341: int i, retval = 0; ! 342: ! 343: /* ! 344: * We don't care about stuff being in disklabels or not. If the magic ! 345: * matches, we're good to go. ! 346: */ ! 347: for (i = 0; sblock_try[i] != -1; ++i) ! 348: { ! 349: if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE)) ! 350: || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK))) ! 351: { ! 352: if ( ! 353: #if defined(UFS1_ONLY) ! 354: SUPERBLOCK->fs_magic == FS_UFS1_MAGIC ! 355: #elif defined(UFS2_ONLY) ! 356: (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC && ! 357: SUPERBLOCK->fs_sblockloc == sblock_try[i]) ! 358: #else ! 359: SUPERBLOCK->fs_magic == FS_UFS1_MAGIC || ! 360: (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC && ! 361: SUPERBLOCK->fs_sblockloc == sblock_try[i]) ! 362: #endif ! 363: ) { ! 364: retval = 1; break; ! 365: } ! 366: } ! 367: } ! 368: return retval; ! 369: } ! 370: ! 371: int ! 372: ufs_read (char *buf, int len) ! 373: { ! 374: return fsread(cur_ino, buf, len); ! 375: } ! 376: ! 377: int ! 378: ufs_dir (char *dirname) ! 379: { ! 380: cur_ino = lookup(dirname); ! 381: return cur_ino & 0xffffffff; ! 382: } ! 383: ! 384: int ! 385: ufs_embed (int* start_sector, int needed_sectors) ! 386: { ! 387: /* TODO; unused by Cromwell */ ! 388: return 0; ! 389: } ! 390: ! 391: #endif /* FSYS_UFS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.