Annotation of qemu/roms/openbios/fs/grubfs/fsys_ufs.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.