diff options
Diffstat (limited to 'qemu/roms/openbios/fs/grubfs/fsys_xfs.c')
-rw-r--r-- | qemu/roms/openbios/fs/grubfs/fsys_xfs.c | 639 |
1 files changed, 0 insertions, 639 deletions
diff --git a/qemu/roms/openbios/fs/grubfs/fsys_xfs.c b/qemu/roms/openbios/fs/grubfs/fsys_xfs.c deleted file mode 100644 index b082621c7..000000000 --- a/qemu/roms/openbios/fs/grubfs/fsys_xfs.c +++ /dev/null @@ -1,639 +0,0 @@ -/* fsys_xfs.c - an implementation for the SGI XFS file system */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#ifdef FSYS_XFS - -#include "shared.h" -#include "filesys.h" -#include "xfs.h" - -#define MAX_LINK_COUNT 8 - -typedef struct xad { - xfs_fileoff_t offset; - xfs_fsblock_t start; - xfs_filblks_t len; -} xad_t; - -struct xfs_info { - int bsize; - int dirbsize; - int isize; - unsigned int agblocks; - int bdlog; - int blklog; - int inopblog; - int agblklog; - int agnolog; - unsigned int nextents; - xfs_daddr_t next; - xfs_daddr_t daddr; - xfs_dablk_t forw; - xfs_dablk_t dablk; - xfs_bmbt_rec_32_t *xt; - xfs_bmbt_ptr_t ptr0; - int btnode_ptr0_off; - int i8param; - int dirpos; - int dirmax; - int blkoff; - int fpos; - xfs_ino_t rootino; -}; - -static struct xfs_info xfs; - -#define dirbuf ((char *)FSYS_BUF) -#define filebuf ((char *)FSYS_BUF + 4096) -#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192)) -#define icore (inode->di_core) - -#define mask32lo(n) (((__uint32_t)1 << (n)) - 1) - -#define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1)) -#define XFS_INO_OFFSET_BITS xfs.inopblog -#define XFS_INO_AGBNO_BITS xfs.agblklog -#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog) -#define XFS_INO_AGNO_BITS xfs.agnolog - -static inline xfs_agblock_t -agino2agbno (xfs_agino_t agino) -{ - return agino >> XFS_INO_OFFSET_BITS; -} - -static inline xfs_agnumber_t -ino2agno (xfs_ino_t ino) -{ - return ino >> XFS_INO_AGINO_BITS; -} - -static inline xfs_agino_t -ino2agino (xfs_ino_t ino) -{ - return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS); -} - -static inline int -ino2offset (xfs_ino_t ino) -{ - return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS); -} - -static inline __uint16_t -le16 (__uint16_t x) -{ -#ifdef __i386__ - __asm__("xchgb %b0,%h0" \ - : "=q" (x) \ - : "0" (x)); \ - return x; -#else - return __be16_to_cpu(x); -#endif -} - -static inline __uint32_t -le32 (__uint32_t x) -{ -#ifdef __i386__ -#if 1 - /* 386 doesn't have bswap. So what. */ - __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - /* This is slower but this works on all x86 architectures. */ - __asm__("xchgb %b0, %h0" \ - "\n\troll $16, %0" \ - "\n\txchgb %b0, %h0" \ - : "=q" (x) : "0" (x)); -#endif - return x; -#else - return __be32_to_cpu(x); -#endif -} - -static inline __uint64_t -le64 (__uint64_t x) -{ - __uint32_t h = x >> 32; - __uint32_t l = x & ((1ULL<<32)-1); - return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h))); -} - - -static xfs_fsblock_t -xt_start (xfs_bmbt_rec_32_t *r) -{ - return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) | - (((xfs_fsblock_t)le32 (r->l2)) << 11) | - (((xfs_fsblock_t)le32 (r->l3)) >> 21); -} - -static xfs_fileoff_t -xt_offset (xfs_bmbt_rec_32_t *r) -{ - return (((xfs_fileoff_t)le32 (r->l0) & - mask32lo(31)) << 23) | - (((xfs_fileoff_t)le32 (r->l1)) >> 9); -} - -static xfs_filblks_t -xt_len (xfs_bmbt_rec_32_t *r) -{ - return le32(r->l3) & mask32lo(21); -} - -static inline int -xfs_highbit32(__uint32_t v) -{ - int i; - - if (--v) { - for (i = 0; i < 31; i++, v >>= 1) { - if (v == 0) - return i; - } - } - return 0; -} - -static int -isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len) -{ - return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; -} - -static xfs_daddr_t -agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno) -{ - return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog; -} - -static xfs_daddr_t -fsb2daddr (xfs_fsblock_t fsbno) -{ - return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog), - (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog))); -} - -#undef offsetof -#define offsetof(t,m) ((long)&(((t *)0)->m)) - -static inline int -btroot_maxrecs (void) -{ - int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize; - - return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) / - (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)); -} - -static int -di_read (xfs_ino_t ino) -{ - xfs_agino_t agino; - xfs_agnumber_t agno; - xfs_agblock_t agbno; - xfs_daddr_t daddr; - int offset; - - agno = ino2agno (ino); - agino = ino2agino (ino); - agbno = agino2agbno (agino); - offset = ino2offset (ino); - daddr = agb2daddr (agno, agbno); - - devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode); - - xfs.ptr0 = *(xfs_bmbt_ptr_t *) - (inode->di_u.di_c + sizeof(xfs_bmdr_block_t) - + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t)); - - return 1; -} - -static void -init_extents (void) -{ - xfs_bmbt_ptr_t ptr0; - xfs_btree_lblock_t h; - - switch (icore.di_format) { - case XFS_DINODE_FMT_EXTENTS: - xfs.xt = inode->di_u.di_bmx; - xfs.nextents = le32 (icore.di_nextents); - break; - case XFS_DINODE_FMT_BTREE: - ptr0 = xfs.ptr0; - for (;;) { - xfs.daddr = fsb2daddr (le64(ptr0)); - devread (xfs.daddr, 0, - sizeof(xfs_btree_lblock_t), (char *)&h); - if (!h.bb_level) { - xfs.nextents = le16(h.bb_numrecs); - xfs.next = fsb2daddr (le64(h.bb_rightsib)); - xfs.fpos = sizeof(xfs_btree_block_t); - return; - } - devread (xfs.daddr, xfs.btnode_ptr0_off, - sizeof(xfs_bmbt_ptr_t), (char *)&ptr0); - } - } -} - -static xad_t * -next_extent (void) -{ - static xad_t xad; - - switch (icore.di_format) { - case XFS_DINODE_FMT_EXTENTS: - if (xfs.nextents == 0) - return NULL; - break; - case XFS_DINODE_FMT_BTREE: - if (xfs.nextents == 0) { - xfs_btree_lblock_t h; - if (xfs.next == 0) - return NULL; - xfs.daddr = xfs.next; - devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h); - xfs.nextents = le16(h.bb_numrecs); - xfs.next = fsb2daddr (le64(h.bb_rightsib)); - xfs.fpos = sizeof(xfs_btree_block_t); - } - /* Yeah, I know that's slow, but I really don't care */ - devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf); - xfs.xt = (xfs_bmbt_rec_32_t *)filebuf; - xfs.fpos += sizeof(xfs_bmbt_rec_32_t); - } - xad.offset = xt_offset (xfs.xt); - xad.start = xt_start (xfs.xt); - xad.len = xt_len (xfs.xt); - ++xfs.xt; - --xfs.nextents; - - return &xad; -} - -/* - * Name lies - the function reads only first 100 bytes - */ -static void -xfs_dabread (void) -{ - xad_t *xad; - xfs_fileoff_t offset;; - - init_extents (); - while ((xad = next_extent ())) { - offset = xad->offset; - if (isinxt (xfs.dablk, offset, xad->len)) { - devread (fsb2daddr (xad->start + xfs.dablk - offset), - 0, 100, dirbuf); - break; - } - } -} - -static inline xfs_ino_t -sf_ino (char *sfe, int namelen) -{ - void *p = sfe + namelen + 3; - - return (xfs.i8param == 0) - ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p); -} - -static inline xfs_ino_t -sf_parent_ino (void) -{ - return (xfs.i8param == 0) - ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent)) - : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent)); -} - -static inline int -roundup8 (int n) -{ - return ((n+7)&~7); -} - -static char * -next_dentry (xfs_ino_t *ino) -{ - int namelen = 1; - int toread; - static char *usual[2]; - static xfs_dir2_sf_entry_t *sfe; - char *name; - - if (!usual[0]) { - usual[0] = strdup("."); - usual[1] = strdup(".."); - } - name = usual[0]; - - if (xfs.dirpos >= xfs.dirmax) { - if (xfs.forw == 0) - return NULL; - xfs.dablk = xfs.forw; - xfs_dabread (); -#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) - xfs.dirmax = le16 (h->count) - le16 (h->stale); - xfs.forw = le32 (h->info.forw); -#undef h - xfs.dirpos = 0; - } - - switch (icore.di_format) { - case XFS_DINODE_FMT_LOCAL: - switch (xfs.dirpos) { - case -2: - *ino = 0; - break; - case -1: - *ino = sf_parent_ino (); - ++name; - ++namelen; - sfe = (xfs_dir2_sf_entry_t *) - (inode->di_u.di_c - + sizeof(xfs_dir2_sf_hdr_t) - - xfs.i8param); - break; - default: - namelen = sfe->namelen; - *ino = sf_ino ((char *)sfe, namelen); - name = (char *)sfe->name; - sfe = (xfs_dir2_sf_entry_t *) - ((char *)sfe + namelen + 11 - xfs.i8param); - } - break; - case XFS_DINODE_FMT_BTREE: - case XFS_DINODE_FMT_EXTENTS: -#define dau ((xfs_dir2_data_union_t *)dirbuf) - for (;;) { - if (xfs.blkoff >= xfs.dirbsize) { - xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); - filepos &= ~(xfs.dirbsize - 1); - filepos |= xfs.blkoff; - } - xfs_read (dirbuf, 4); - xfs.blkoff += 4; - if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) { - toread = roundup8 (le16(dau->unused.length)) - 4; - xfs.blkoff += toread; - filepos += toread; - continue; - } - break; - } - xfs_read ((char *)dirbuf + 4, 5); - *ino = le64 (dau->entry.inumber); - namelen = dau->entry.namelen; -#undef dau - toread = roundup8 (namelen + 11) - 9; - xfs_read (dirbuf, toread); - name = (char *)dirbuf; - xfs.blkoff += toread + 5; - } - ++xfs.dirpos; - name[namelen] = 0; - - return name; -} - -static char * -first_dentry (xfs_ino_t *ino) -{ - xfs.forw = 0; - switch (icore.di_format) { - case XFS_DINODE_FMT_LOCAL: - xfs.dirmax = inode->di_u.di_dir2sf.hdr.count; - xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4; - xfs.dirpos = -2; - break; - case XFS_DINODE_FMT_EXTENTS: - case XFS_DINODE_FMT_BTREE: - filepos = 0; - xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t)); - if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) { -#define tail ((xfs_dir2_block_tail_t *)dirbuf) - filepos = xfs.dirbsize - sizeof(*tail); - xfs_read (dirbuf, sizeof(*tail)); - xfs.dirmax = le32 (tail->count) - le32 (tail->stale); -#undef tail - } else { - xfs.dablk = (1ULL << 35) >> xfs.blklog; -#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) -#define n ((xfs_da_intnode_t *)dirbuf) - for (;;) { - xfs_dabread (); - if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC)) - || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) { - xfs.dirmax = le16 (h->count) - le16 (h->stale); - xfs.forw = le32 (h->info.forw); - break; - } - xfs.dablk = le32 (n->btree[0].before); - } -#undef n -#undef h - } - xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); - filepos = xfs.blkoff; - xfs.dirpos = 0; - } - return next_dentry (ino); -} - -int -xfs_mount (void) -{ - xfs_sb_t super; - - if (!devread (0, 0, sizeof(super), (char *)&super) - || (le32(super.sb_magicnum) != XFS_SB_MAGIC) - || ((le16(super.sb_versionnum) - & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) { - return 0; - } - - xfs.bsize = le32 (super.sb_blocksize); - xfs.blklog = super.sb_blocklog; - xfs.bdlog = xfs.blklog - SECTOR_BITS; - xfs.rootino = le64 (super.sb_rootino); - xfs.isize = le16 (super.sb_inodesize); - xfs.agblocks = le32 (super.sb_agblocks); - xfs.dirbsize = xfs.bsize << super.sb_dirblklog; - - xfs.inopblog = super.sb_inopblog; - xfs.agblklog = super.sb_agblklog; - xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount)); - - xfs.btnode_ptr0_off = - ((xfs.bsize - sizeof(xfs_btree_block_t)) / - (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t))) - * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t); - - return 1; -} - -int -xfs_read (char *buf, int len) -{ - xad_t *xad; - xfs_fileoff_t endofprev, endofcur, offset; - xfs_filblks_t xadlen; - int toread, startpos, endpos; - - if (icore.di_format == XFS_DINODE_FMT_LOCAL) { - grub_memmove (buf, inode->di_u.di_c + filepos, len); - filepos += len; - return len; - } - - startpos = filepos; - endpos = filepos + len; - endofprev = (xfs_fileoff_t)-1; - init_extents (); - while (len > 0 && (xad = next_extent ())) { - offset = xad->offset; - xadlen = xad->len; - if (isinxt (filepos >> xfs.blklog, offset, xadlen)) { - endofcur = (offset + xadlen) << xfs.blklog; - toread = (endofcur >= endpos) - ? len : (endofcur - filepos); - - disk_read_func = disk_read_hook; - devread (fsb2daddr (xad->start), - filepos - (offset << xfs.blklog), toread, buf); - disk_read_func = NULL; - - buf += toread; - len -= toread; - filepos += toread; - } else if (offset > endofprev) { - toread = ((offset << xfs.blklog) >= endpos) - ? len : ((offset - endofprev) << xfs.blklog); - len -= toread; - filepos += toread; - for (; toread; toread--) { - *buf++ = 0; - } - continue; - } - endofprev = offset + xadlen; - } - - return filepos - startpos; -} - -int -xfs_dir (char *dirname) -{ - xfs_ino_t ino, parent_ino, new_ino; - xfs_fsize_t di_size; - int di_mode; - int cmp, n, link_count; - char linkbuf[xfs.bsize]; - char *rest, *name, ch; - - parent_ino = ino = xfs.rootino; - link_count = 0; - for (;;) { - di_read (ino); - di_size = le64 (icore.di_size); - di_mode = le16 (icore.di_mode); - - if ((di_mode & IFMT) == IFLNK) { - if (++link_count > MAX_LINK_COUNT) { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - if (di_size < xfs.bsize - 1) { - filepos = 0; - filemax = di_size; - n = xfs_read (linkbuf, filemax); - } else { - errnum = ERR_FILELENGTH; - return 0; - } - - ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino; - while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++)); - linkbuf[n] = 0; - dirname = linkbuf; - continue; - } - - if (!*dirname || isspace (*dirname)) { - if ((di_mode & IFMT) != IFREG) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - filepos = 0; - filemax = di_size; - return 1; - } - - if ((di_mode & IFMT) != IFDIR) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - for (; *dirname == '/'; dirname++); - - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - *rest = 0; - - name = first_dentry (&new_ino); - for (;;) { - cmp = (!*dirname) ? -1 : substring (dirname, name); -#ifndef STAGE1_5 - if (print_possibilities && ch != '/' && cmp <= 0) { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (name); - } else -#endif - if (cmp == 0) { - parent_ino = ino; - if (new_ino) - ino = new_ino; - *(dirname = rest) = ch; - break; - } - name = next_dentry (&new_ino); - if (name == NULL) { - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - } - } -} - -#endif /* FSYS_XFS */ |