Annotation of qemu/roms/openbios/fs/grubfs/fsys_ufs.c, revision 1.1.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.