tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: patch: MFSv3 support (libsa) for boot2 (i386)
Hi,
Here're updated patches. Tested on sparc (build only). Gnats ID is lib/45796.
On Thu, Dec 29, 2011 at 11:20 PM, David Laight <david%l8s.co.uk@localhost>
wrote:
> On Thu, Dec 29, 2011 at 07:55:18PM +0100, Antoine LECA wrote:
>>
>> David Laight wrote:
>> > The actual 'pc' boot sequence is:
>> > Stages 1-3 (and maybe 4) are common to all OS.
>> <...>
>> > 3) The pbr code has to determine where it was loaded from, it could:
>> > a) reread sector zero and look for a partition of the relevant type
>> > b) have the sector number previously written into the sector data.
>>
>> c)
>> > The netbsd bootselect mbr passes the sector number in a register
>> > (non-standard) and the pbr code scans the partitions looking for
>> > one that starts in the correct place.
> ...
>> I am not sure whether NetBSD currently uses a or c (or a combination of
>> both); ...
>
> Last time I rewrote it, it reread the mbr and located the partition
> (following the extended/logical partition chain) looking for the
> one that starts in the sector passed in (IIRC) %esi. If not found
> it rescans looking for thr first netbsd partition.
>
> I used %esi because it reduced the number of instructions in the mbr!
> The mbr is a work of art!
>
> David
>
> --
> David Laight: david%l8s.co.uk@localhost
--
Evgeniy
From 7d7f2b29751ceccfc1addce299cb5131e9f7b1e8 Mon Sep 17 00:00:00 2001
From: Evgeniy Ivanov <lolkaantimat%gmail.com@localhost>
Date: Mon, 5 Dec 2011 19:44:33 +0400
Subject: [PATCH 1/4] MINIX 3 subpartitions support.
- Read MFS subpartitions, when neccessarly.
- Add MFS to the supported FSes list.
diff --git a/common/lib/libutil/getfstypename.c
b/common/lib/libutil/getfstypename.c
index 79ea154..26fe3a3 100644
--- a/common/lib/libutil/getfstypename.c
+++ b/common/lib/libutil/getfstypename.c
@@ -121,6 +121,8 @@ getfstypename(int fstype)
return DKW_PTYPE_CGD;
case FSMAXTYPES:
return DKW_PTYPE_UNKNOWN;
+ case FS_MINIXFS3:
+ return DKW_PTYPE_MINIXFS3;
}
/* Stupid gcc, should know it is impossible to get here */
return DKW_PTYPE_UNKNOWN;
diff --git a/sys/arch/i386/stand/lib/biosdisk.c
b/sys/arch/i386/stand/lib/biosdisk.c
index dddfdf9..13701c7 100644
--- a/sys/arch/i386/stand/lib/biosdisk.c
+++ b/sys/arch/i386/stand/lib/biosdisk.c
@@ -404,6 +404,40 @@ check_label(struct biosdisk *d, daddr_t sector)
}
static int
+read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl,
+ int this_ext, daddr_t sector)
+{
+ struct mbr_partition mbr[MBR_PART_COUNT];
+ int i;
+ int typ;
+ struct partition *p;
+
+ if (readsects(&d->ll, sector, 1, d->buf, 0)) {
+#ifdef DISK_DEBUG
+ printf("Error reading MFS sector %d\n", sector);
+#endif
+ return EIO;
+ }
+ if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) {
+ return -1;
+ }
+ memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts, sizeof(mbr));
+ for (i = 0; i < MBR_PART_COUNT; i++) {
+ typ = mbr[i].mbrp_type;
+ if (typ == 0)
+ continue;
+ sector = this_ext + mbr[i].mbrp_start;
+ if (dflt_lbl->d_npartitions >= MAXPARTITIONS)
+ continue;
+ p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++];
+ p->p_offset = sector;
+ p->p_size = mbr[i].mbrp_size;
+ p->p_fstype = xlat_mbr_fstype(typ);
+ }
+ return 0;
+}
+
+static int
read_label(struct biosdisk *d)
{
struct disklabel dflt_lbl;
@@ -452,6 +486,13 @@ read_label(struct biosdisk *d)
#ifdef DISK_DEBUG
printf("ptn type %d in sector %d\n", typ, sector);
#endif
+ if (typ == MBR_PTYPE_MINIX_14B) {
+ if (!read_minix_subp(d, &dflt_lbl,
+ this_ext, sector)) {
+ /* Don't add "container" partition */
+ continue;
+ }
+ }
if (typ == MBR_PTYPE_NETBSD) {
error = check_label(d, sector);
if (error >= 0)
diff --git a/sys/lib/libkern/xlat_mbr_fstype.c
b/sys/lib/libkern/xlat_mbr_fstype.c
index 618c55a..4151770 100644
--- a/sys/lib/libkern/xlat_mbr_fstype.c
+++ b/sys/lib/libkern/xlat_mbr_fstype.c
@@ -55,6 +55,7 @@ xlat_mbr_fstype(int mbr_type)
{ MBR_PTYPE_LNXSWAP, FS_SWAP },
{ MBR_PTYPE_NETBSD, FS_BSDFFS },
{ MBR_PTYPE_NTFS, FS_NTFS },
+ { MBR_PTYPE_MINIX_14B, FS_MINIXFS3 },
{ 0, FS_OTHER }
};
const struct ptn_types *pt;
diff --git a/sys/sys/disk.h b/sys/sys/disk.h
index 985f8e7..2c5546a 100644
--- a/sys/sys/disk.h
+++ b/sys/sys/disk.h
@@ -245,6 +245,7 @@ __link_set_add_data(dkwedge_methods, name ## _ddm)
#define DKW_PTYPE_EFS "efs"
#define DKW_PTYPE_NILFS "nilfs"
#define DKW_PTYPE_CGD "cgd"
+#define DKW_PTYPE_MINIXFS3 "minixfs3"
/*
* Disk geometry dictionary.
diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h
index ff424ea..69f79c3 100644
--- a/sys/sys/disklabel.h
+++ b/sys/sys/disklabel.h
@@ -357,7 +357,8 @@ x(UDF, 24, "UDF", NULL, "udf") /* UDF */ \
x(SYSVBFS, 25, "SysVBFS", NULL, "sysvbfs")/* System V boot file system */ \
x(EFS, 26, "EFS", NULL, "efs") /* SGI's Extent Filesystem */ \
x(NILFS, 27, "NiLFS", NULL, "nilfs") /* NTT's NiLFS(2) */ \
-x(CGD, 28, "cgd", NULL, NULL) /* Cryptographic disk */
+x(CGD, 28, "cgd", NULL, NULL) /* Cryptographic disk */ \
+x(MINIXFS3,29, "MINIX FSv3", NULL, NULL) /* MINIX file system v3 */
#ifndef _LOCORE
--
1.7.3.4
From 8c1b67f226d95e29a6adac778b4f49a05b286762 Mon Sep 17 00:00:00 2001
From: Evgeniy Ivanov <lolkaantimat%gmail.com@localhost>
Date: Sun, 18 Dec 2011 15:04:16 +0400
Subject: [PATCH 2/4] MINIX File System v3 support for libsa.
diff --git a/sys/lib/libsa/Makefile b/sys/lib/libsa/Makefile
index 4d0d951..0eb99a7 100644
--- a/sys/lib/libsa/Makefile
+++ b/sys/lib/libsa/Makefile
@@ -75,6 +75,7 @@ SRCS+= cd9660.c
SRCS+= ustarfs.c
SRCS+= dosfs.c
SRCS+= ext2fs.c
+SRCS+= minixfs3.c
# for historic compatibility ufs == ffsv1
SRCS+= ufs.c
diff --git a/sys/lib/libsa/minixfs3.c b/sys/lib/libsa/minixfs3.c
new file mode 100644
index 0000000..a722173
--- /dev/null
+++ b/sys/lib/libsa/minixfs3.c
@@ -0,0 +1,991 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2012
+ * Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved.
+ *
+ * Author: Evgeniy Ivanov (based on libsa/ext2fs.c).
+ *
+ * This code is derived from src/sys/lib/libsa/ext2fs.c contributed to
+ * The NetBSD Foundation, see copyrights below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * Copyright (c) 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: David Golub
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or
Software.Distribution%CS.CMU.EDU@localhost
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Stand-alone file reading package for MFS file system.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "minixfs3.h"
+
+#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
+#define LIBSA_NO_FS_SYMLINK
+#endif
+
+#if defined(LIBSA_NO_TWIDDLE)
+#define twiddle()
+#endif
+
+typedef uint32_t ino32_t;
+#ifndef FSBTODB
+#define FSBTODB(fs, indp) fsbtodb(fs, indp)
+#endif
+
+/*
+ * To avoid having a lot of filesystem-block sized buffers lurking (which
+ * could be 32k) we only keep a few entries of the indirect block map.
+ * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
+ * ~13 times pulling in a 6M kernel.
+ * The cache size must be smaller than the smallest filesystem block,
+ * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
+ */
+#define LN2_IND_CACHE_SZ 6
+#define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ)
+#define IND_CACHE_MASK (IND_CACHE_SZ - 1)
+
+/*
+ * In-core open file.
+ */
+struct file {
+ off_t f_seekp; /* seek pointer */
+ struct mfs_sblock *f_fs; /* pointer to super-block */
+ struct mfs_dinode f_di; /* copy of on-disk inode */
+ uint f_nishift; /* for blocks in indirect block */
+ block_t f_ind_cache_block;
+ block_t f_ind_cache[IND_CACHE_SZ];
+
+ char *f_buf; /* buffer for data block */
+ size_t f_buf_size; /* size of data block */
+ daddr_t f_buf_blkno; /* block number of data block */
+};
+
+#if defined(LIBSA_ENABLE_LS_OP)
+
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+ entry_t *e_next;
+ ino32_t e_ino;
+ char e_name[1];
+};
+
+static int
+fn_match(const char *fname, const char *pattern)
+{
+ char fc, pc;
+
+ do {
+ fc = *fname++;
+ pc = *pattern++;
+ if (!fc && !pc)
+ return 1;
+ if (pc == '?' && fc)
+ pc = fc;
+ } while (fc == pc);
+
+ if (pc != '*')
+ return 0;
+ /*
+ * Too hard (and unnecessary really) too check for "*?name" etc....
+ * "**" will look for a '*' and "*?" a '?'
+ */
+ pc = *pattern++;
+ if (!pc)
+ return 1;
+ while ((fname = strchr(fname, pc)))
+ if (fn_match(++fname, pattern))
+ return 1;
+ return 0;
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
+
+static int read_inode(ino32_t, struct open_file *);
+static int block_map(struct open_file *, block_t, block_t *);
+static int buf_read_file(struct open_file *, char **, size_t *);
+static int search_directory(const char *, int, struct open_file *, ino32_t *);
+static int read_sblock(struct open_file *, struct mfs_sblock *);
+
+/*
+ * Read a new inode into a file structure.
+ */
+static int
+read_inode(ino32_t inumber, struct open_file *f)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct mfs_sblock *fs = fp->f_fs;
+ char *buf;
+ size_t rsize;
+ int rc;
+ daddr_t inode_sector;
+ struct mfs_dinode *dip;
+
+ inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
+
+ /*
+ * Read inode and save it.
+ */
+ buf = fp->f_buf;
+ twiddle();
+ rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+ inode_sector, fs->mfs_block_size, buf, &rsize);
+ if (rc)
+ return rc;
+ if (rsize != fs->mfs_block_size)
+ return EIO;
+
+ dip = (struct mfs_dinode *)(buf +
+ INODE_SIZE * ino_to_fsbo(fs, inumber));
+ mfs_iload(dip, &fp->f_di);
+
+ /*
+ * Clear out the old buffers
+ */
+ fp->f_ind_cache_block = ~0;
+ fp->f_buf_blkno = -1;
+ return rc;
+}
+
+/*
+ * Given an offset in a file, find the disk block number (not zone!)
+ * that contains that block.
+ */
+static int
+block_map(struct open_file *f, block_t file_block, block_t *disk_block_p)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct mfs_sblock *fs = fp->f_fs;
+ uint level;
+ block_t ind_cache;
+ block_t ind_block_num;
+ zone_t zone;
+ size_t rsize;
+ int rc;
+ int boff;
+ int scale = fs->mfs_log_zone_size; /* for block-zone conversion */
+ block_t *buf = (void *)fp->f_buf;
+
+ /*
+ * Index structure of an inode:
+ *
+ * mdi_blocks[0..NR_DZONES-1]
+ * hold zone numbers for zones
+ * 0..NR_DZONES-1
+ *
+ * mdi_blocks[NR_DZONES+0]
+ * block NDADDR+0 is the single indirect block
+ * holds zone numbers for zones
+ * NR_DZONES .. NR_DZONES + NINDIR(fs)-1
+ *
+ * mdi_blocks[NR_DZONES+1]
+ * block NDADDR+1 is the double indirect block
+ * holds zone numbers for INDEX blocks for zones
+ * NR_DZONES + NINDIR(fs) ..
+ * NR_TZONES + NINDIR(fs) + NINDIR(fs)**2 - 1
+ */
+
+ zone = file_block >> scale;
+ boff = (int) (file_block - (zone << scale) ); /* relative blk in zone */
+
+ if (zone < NR_DZONES) {
+ /* Direct zone */
+ zone_t z = fs2h32(fp->f_di.mdi_zone[zone]);
+ if (z == NO_ZONE) {
+ *disk_block_p = NO_BLOCK;
+ return 0;
+ }
+ *disk_block_p = (block_t) ((z << scale) + boff);
+ return 0;
+ }
+
+ zone -= NR_DZONES;
+
+ ind_cache = zone >> LN2_IND_CACHE_SZ;
+ if (ind_cache == fp->f_ind_cache_block) {
+ *disk_block_p =
+ fs2h32(fp->f_ind_cache[zone & IND_CACHE_MASK]);
+ return 0;
+ }
+
+ for (level = 0;;) {
+ level += fp->f_nishift;
+
+ if (zone < (block_t)1 << level)
+ break;
+ if (level > NIADDR * fp->f_nishift)
+ /* Zone number too high */
+ return EFBIG;
+ zone -= (block_t)1 << level;
+ }
+
+ ind_block_num =
+ fs2h32(fp->f_di.mdi_zone[NR_DZONES + (level / fp->f_nishift - 1)]);
+
+ for (;;) {
+ level -= fp->f_nishift;
+ if (ind_block_num == 0) {
+ *disk_block_p = NO_BLOCK; /* missing */
+ return 0;
+ }
+
+ twiddle();
+ /*
+ * If we were feeling brave, we could work out the number
+ * of the disk sector and read a single disk sector instead
+ * of a filesystem block.
+ * However we don't do this very often anyway...
+ */
+ rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+ FSBTODB(fs, ind_block_num), fs->mfs_block_size,
+ buf, &rsize);
+ if (rc)
+ return rc;
+ if (rsize != fs->mfs_block_size)
+ return EIO;
+
+ ind_block_num = fs2h32(buf[zone >> level]);
+ if (level == 0)
+ break;
+ zone &= (1 << level) - 1;
+ }
+
+ /* Save the part of the block that contains this sector */
+ memcpy(fp->f_ind_cache, &buf[zone & ~IND_CACHE_MASK],
+ IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
+ fp->f_ind_cache_block = ind_cache;
+
+ zone = (zone_t)ind_block_num;
+ *disk_block_p = (block_t)((zone << scale) + boff);
+ return 0;
+}
+
+/*
+ * Read a portion of a file into an internal buffer.
+ * Return the location in the buffer and the amount in the buffer.
+ */
+static int
+buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct mfs_sblock *fs = fp->f_fs;
+ long off;
+ block_t file_block;
+ block_t disk_block;
+ size_t block_size;
+ int rc;
+
+ off = blkoff(fs, fp->f_seekp);
+ file_block = lblkno(fs, fp->f_seekp);
+ block_size = fs->mfs_block_size;
+
+ if (file_block != fp->f_buf_blkno) {
+ rc = block_map(f, file_block, &disk_block);
+ if (rc)
+ return rc;
+
+ if (disk_block == 0) {
+ memset(fp->f_buf, 0, block_size);
+ fp->f_buf_size = block_size;
+ } else {
+ twiddle();
+ rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+ FSBTODB(fs, disk_block),
+ block_size, fp->f_buf, &fp->f_buf_size);
+ if (rc)
+ return rc;
+ }
+
+ fp->f_buf_blkno = file_block;
+ }
+
+ /*
+ * Return address of byte in buffer corresponding to
+ * offset, and size of remainder of buffer after that
+ * byte.
+ */
+ *buf_p = fp->f_buf + off;
+ *size_p = block_size - off;
+
+ /*
+ * But truncate buffer at end of file.
+ */
+ if (*size_p > fp->f_di.mdi_size - fp->f_seekp)
+ *size_p = fp->f_di.mdi_size - fp->f_seekp;
+
+ return 0;
+}
+
+/*
+ * Search a directory for a name and return its
+ * inode number.
+ */
+static int
+search_directory(const char *name, int length, struct open_file *f,
+ ino32_t *inumber_p)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct mfs_sblock *fs = fp->f_fs;
+ struct mfs_direct *dp;
+ struct mfs_direct *dbuf;
+ size_t buf_size;
+ int namlen;
+ int rc;
+
+ fp->f_seekp = 0;
+
+ while (fp->f_seekp < (off_t)fp->f_di.mdi_size) {
+ rc = buf_read_file(f, (char**)&dbuf, &buf_size);
+ if (rc)
+ return rc;
+ if (buf_size == 0)
+ return EIO;
+
+ /* XXX we assume, that buf_read_file reads an fs block and
+ * doesn't truncate buffer. Currently i_size in MFS doesn't
+ * the same as size of allocated blocks, it makes buf_read_file
+ * to truncate buf_size.
+ */
+ if (buf_size < fs->mfs_block_size)
+ buf_size = fs->mfs_block_size;
+
+ for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) {
+ char *cp;
+ if (fs2h32(dp->mfsd_ino) == (ino32_t) 0)
+ continue;
+ /* Compute the length of the name */
+ cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name));
+ if (cp == NULL)
+ namlen = sizeof(dp->mfsd_name);
+ else
+ namlen = cp - (dp->mfsd_name);
+
+ if (namlen == length &&
+ !memcmp(name, dp->mfsd_name, length)) {
+ /* found entry */
+ *inumber_p = fs2h32(dp->mfsd_ino);
+ return 0;
+ }
+ }
+ fp->f_seekp += buf_size;
+ }
+ return ENOENT;
+}
+
+int
+read_sblock(struct open_file *f, struct mfs_sblock *fs)
+{
+ static uint8_t sbbuf[MINBSIZE];
+ size_t buf_size;
+ int rc;
+
+ /* We must read amount multiple of sector size, hence we can't
+ * read SBSIZE and read MINBSIZE.
+ */
+ if (SBSIZE > MINBSIZE)
+ return EINVAL;
+
+ rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+ SUPER_BLOCK_OFF / DEV_BSIZE, MINBSIZE, sbbuf, &buf_size);
+ if (rc)
+ return rc;
+
+ if (buf_size != MINBSIZE)
+ return EIO;
+
+ mfs_sbload((void *)sbbuf, fs);
+
+ if (fs->mfs_magic != SUPER_MAGIC)
+ return EINVAL;
+ if (fs->mfs_block_size < MINBSIZE)
+ return EINVAL;
+ if ((fs->mfs_block_size % 512) != 0)
+ return EINVAL;
+ if (SBSIZE > fs->mfs_block_size)
+ return EINVAL;
+ if ((fs->mfs_block_size % INODE_SIZE) != 0)
+ return EINVAL;
+
+ /* For even larger disks, a similar problem occurs with s_firstdatazone.
+ * If the on-disk field contains zero, we assume that the value was too
+ * large to fit, and compute it on the fly.
+ */
+ if (fs->mfs_firstdatazone_old == 0) {
+ block_t offset;
+ offset = START_BLOCK + fs->mfs_imap_blocks +
fs->mfs_zmap_blocks;
+ offset += (fs->mfs_ninodes + fs->mfs_inodes_per_block - 1) /
+ fs->mfs_inodes_per_block;
+
+ fs->mfs_firstdatazone =
+ (offset + (1 << fs->mfs_log_zone_size) - 1) >>
+ fs->mfs_log_zone_size;
+ } else {
+ fs->mfs_firstdatazone = (zone_t) fs->mfs_firstdatazone_old;
+ }
+
+ if (fs->mfs_imap_blocks < 1 || fs->mfs_zmap_blocks < 1
+ || fs->mfs_ninodes < 1 || fs->mfs_zones < 1
+ || fs->mfs_firstdatazone <= 4
+ || fs->mfs_firstdatazone >= fs->mfs_zones
+ || (unsigned) fs->mfs_log_zone_size > 4)
+ return EINVAL;
+
+ /* compute in-memory mfs_sblock values */
+ fs->mfs_inodes_per_block = fs->mfs_block_size / INODE_SIZE;
+
+
+ {
+ int32_t mult = fs->mfs_block_size >> LOG_MINBSIZE;
+ int ln2 = LOG_MINBSIZE;
+
+ for (; mult != 1; ln2++)
+ mult >>= 1;
+
+ fs->mfs_bshift = ln2;
+ /* XXX assume hw bsize = 512 */
+ fs->mfs_fsbtodb = ln2 - LOG_MINBSIZE + 1;
+ }
+
+ fs->mfs_qbmask = fs->mfs_block_size - 1;
+ fs->mfs_bmask = ~fs->mfs_qbmask;
+
+ return 0;
+}
+
+/*
+ * Open a file.
+ */
+__compactcall int
+minixfs3_open(const char *path, struct open_file *f)
+{
+#ifndef LIBSA_FS_SINGLECOMPONENT
+ const char *cp, *ncp;
+ int c;
+#endif
+ ino32_t inumber;
+ struct file *fp;
+ struct mfs_sblock *fs;
+ int rc;
+#ifndef LIBSA_NO_FS_SYMLINK
+ ino32_t parent_inumber;
+ int nlinks = 0;
+ char namebuf[MAXPATHLEN+1];
+ char *buf;
+#endif
+
+ /* allocate file system specific data structure */
+ fp = alloc(sizeof(struct file));
+ memset(fp, 0, sizeof(struct file));
+ f->f_fsdata = (void *)fp;
+
+ /* allocate space and read super block */
+ fs = alloc(sizeof(*fs));
+ memset(fs, 0, sizeof(*fs));
+ fp->f_fs = fs;
+ twiddle();
+
+ rc = read_sblock(f, fs);
+ if (rc)
+ goto out;
+
+ /* alloc a block sized buffer used for all fs transfers */
+ fp->f_buf = alloc(fs->mfs_block_size);
+
+ /*
+ * Calculate indirect block levels.
+ */
+ {
+ int32_t mult;
+ int ln2;
+
+ /*
+ * We note that the number of indirect blocks is always
+ * a power of 2. This lets us use shifts and masks instead
+ * of divide and remainder and avoinds pulling in the
+ * 64bit division routine into the boot code.
+ */
+ mult = NINDIR(fs);
+#ifdef DEBUG
+ if (!powerof2(mult)) {
+ /* Hummm was't a power of 2 */
+ rc = EINVAL;
+ goto out;
+ }
+#endif
+ for (ln2 = 0; mult != 1; ln2++)
+ mult >>= 1;
+
+ fp->f_nishift = ln2;
+ }
+
+ inumber = ROOT_INODE;
+ if ((rc = read_inode(inumber, f)) != 0)
+ goto out;
+
+#ifndef LIBSA_FS_SINGLECOMPONENT
+ cp = path;
+ while (*cp) {
+
+ /*
+ * Remove extra separators
+ */
+ while (*cp == '/')
+ cp++;
+ if (*cp == '\0')
+ break;
+
+ /*
+ * Check that current node is a directory.
+ */
+ if ((fp->f_di.mdi_mode & I_TYPE) != I_DIRECTORY) {
+ rc = ENOTDIR;
+ goto out;
+ }
+
+ /*
+ * Get next component of path name.
+ */
+ ncp = cp;
+ while ((c = *cp) != '\0' && c != '/')
+ cp++;
+
+ /*
+ * Look up component in current directory.
+ * Save directory inumber in case we find a
+ * symbolic link.
+ */
+#ifndef LIBSA_NO_FS_SYMLINK
+ parent_inumber = inumber;
+#endif
+ rc = search_directory(ncp, cp - ncp, f, &inumber);
+ if (rc)
+ goto out;
+
+ /*
+ * Open next component.
+ */
+ if ((rc = read_inode(inumber, f)) != 0)
+ goto out;
+
+#ifndef LIBSA_NO_FS_SYMLINK
+ /*
+ * Check for symbolic link.
+ */
+ if ((fp->f_di.mdi_mode & I_TYPE) == I_SYMBOLIC_LINK) {
+ int link_len = fp->f_di.mdi_size;
+ int len;
+ size_t buf_size;
+ block_t disk_block;
+
+ len = strlen(cp);
+
+ if (link_len + len > MAXPATHLEN ||
+ ++nlinks > MAXSYMLINKS) {
+ rc = ENOENT;
+ goto out;
+ }
+
+ memmove(&namebuf[link_len], cp, len + 1);
+
+ /*
+ * Read file for symbolic link
+ */
+ buf = fp->f_buf;
+ rc = block_map(f, (block_t)0, &disk_block);
+ if (rc)
+ goto out;
+
+ twiddle();
+ rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
+ F_READ, FSBTODB(fs, disk_block),
+ fs->mfs_block_size, buf, &buf_size);
+ if (rc)
+ goto out;
+
+ memcpy(namebuf, buf, link_len);
+
+ /*
+ * If relative pathname, restart at parent directory.
+ * If absolute pathname, restart at root.
+ */
+ cp = namebuf;
+ if (*cp != '/')
+ inumber = parent_inumber;
+ else
+ inumber = (ino32_t) ROOT_INODE;
+
+ if ((rc = read_inode(inumber, f)) != 0)
+ goto out;
+ }
+#endif /* !LIBSA_NO_FS_SYMLINK */
+ }
+
+ /*
+ * Found terminal component.
+ */
+ rc = 0;
+
+#else /* !LIBSA_FS_SINGLECOMPONENT */
+
+ /* look up component in the current (root) directory */
+ rc = search_directory(path, strlen(path), f, &inumber);
+ if (rc)
+ goto out;
+
+ /* open it */
+ rc = read_inode(inumber, f);
+
+#endif /* !LIBSA_FS_SINGLECOMPONENT */
+
+ fp->f_seekp = 0; /* reset seek pointer */
+
+out:
+ if (rc)
+ minixfs3_close(f);
+
+ return rc;
+}
+
+__compactcall int
+minixfs3_close(struct open_file *f)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ f->f_fsdata = NULL;
+ if (fp == NULL)
+ return 0;
+
+ if (fp->f_buf)
+ dealloc(fp->f_buf, fp->f_fs->mfs_block_size);
+ dealloc(fp->f_fs, sizeof(*fp->f_fs));
+ dealloc(fp, sizeof(struct file));
+ return 0;
+}
+
+/*
+ * Copy a portion of a file into kernel memory.
+ * Cross block boundaries when necessary.
+ */
+__compactcall int
+minixfs3_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ size_t csize;
+ char *buf;
+ size_t buf_size;
+ int rc = 0;
+ char *addr = start;
+
+ while (size != 0) {
+ if (fp->f_seekp >= (off_t)fp->f_di.mdi_size)
+ break;
+
+ rc = buf_read_file(f, &buf, &buf_size);
+ if (rc)
+ break;
+
+ csize = size;
+ if (csize > buf_size)
+ csize = buf_size;
+
+ memcpy(addr, buf, csize);
+
+ fp->f_seekp += csize;
+ addr += csize;
+ size -= csize;
+ }
+
+ if (resid)
+ *resid = size;
+ return rc;
+}
+
+/*
+ * Not implemented.
+ */
+#ifndef LIBSA_NO_FS_WRITE
+__compactcall int
+minixfs3_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+ return EROFS;
+}
+#endif /* !LIBSA_NO_FS_WRITE */
+
+#ifndef LIBSA_NO_FS_SEEK
+__compactcall off_t
+minixfs3_seek(struct open_file *f, off_t offset, int where)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ switch (where) {
+ case SEEK_SET:
+ fp->f_seekp = offset;
+ break;
+ case SEEK_CUR:
+ fp->f_seekp += offset;
+ break;
+ case SEEK_END:
+ fp->f_seekp = fp->f_di.mdi_size - offset;
+ break;
+ default:
+ return -1;
+ }
+ return fp->f_seekp;
+}
+#endif /* !LIBSA_NO_FS_SEEK */
+
+__compactcall int
+minixfs3_stat(struct open_file *f, struct stat *sb)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ /* only important stuff */
+ memset(sb, 0, sizeof *sb);
+ sb->st_mode = fp->f_di.mdi_mode;
+ sb->st_uid = fp->f_di.mdi_uid;
+ sb->st_gid = fp->f_di.mdi_gid;
+ sb->st_size = fp->f_di.mdi_size;
+ return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+minixfs3_ls(struct open_file *f, const char *pattern)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct mfs_sblock *fs = fp->f_fs;
+ struct mfs_direct *dp;
+ struct mfs_direct *dbuf;
+ size_t buf_size;
+ entry_t *names = 0, *n, **np;
+
+ fp->f_seekp = 0;
+ while (fp->f_seekp < (off_t)fp->f_di.mdi_size) {
+ int rc = buf_read_file(f, (char**)&dbuf, &buf_size);
+ if (rc)
+ goto out;
+
+ /* XXX we assume, that buf_read_file reads an fs block and
+ * doesn't truncate buffer. Currently i_size in MFS doesn't
+ * the same as size of allocated blocks, it makes buf_read_file
+ * to truncate buf_size.
+ */
+ if (buf_size < fs->mfs_block_size)
+ buf_size = fs->mfs_block_size;
+
+ for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) {
+ char *cp;
+ int namlen;
+
+ if (fs2h32(dp->mfsd_ino) == 0)
+ continue;
+
+ if (pattern && !fn_match(dp->mfsd_name, pattern))
+ continue;
+
+ /* Compute the length of the name,
+ * We don't use strlen and strcpy, because original MFS
+ * code doesn't.
+ */
+ cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name));
+ if (cp == NULL)
+ namlen = sizeof(dp->mfsd_name);
+ else
+ namlen = cp - (dp->mfsd_name);
+
+ n = alloc(sizeof *n + namlen);
+ if (!n) {
+ printf("%d: %s\n",
+ fs2h32(dp->mfsd_ino), dp->mfsd_name);
+ continue;
+ }
+ n->e_ino = fs2h32(dp->mfsd_ino);
+ strncpy(n->e_name, dp->mfsd_name, namlen);
+ n->e_name[namlen] = '\0';
+ for (np = &names; *np; np = &(*np)->e_next) {
+ if (strcmp(n->e_name, (*np)->e_name) < 0)
+ break;
+ }
+ n->e_next = *np;
+ *np = n;
+ }
+ fp->f_seekp += buf_size;
+ }
+
+ if (names) {
+ entry_t *p_names = names;
+ do {
+ n = p_names;
+ printf("%d: %s\n",
+ n->e_ino, n->e_name);
+ p_names = n->e_next;
+ } while (p_names);
+ } else {
+ printf("not found\n");
+ }
+out:
+ if (names) {
+ do {
+ n = names;
+ names = n->e_next;
+ dealloc(n, 0);
+ } while (names);
+ }
+ return;
+}
+#endif
+
+/*
+ * byte swap functions for big endian machines
+ * (mfs is always little endian)
+ */
+
+/* These functions are only needed if native byte order is not big endian */
+#if BYTE_ORDER == BIG_ENDIAN
+void
+minixfs3_sb_bswap(struct mfs_sblock *old, struct mfs_sblock *new)
+{
+ new->mfs_ninodes = bswap32(old->mfs_ninodes);
+ new->mfs_nzones = bswap16(old->mfs_nzones);
+ new->mfs_imap_blocks = bswap16(old->mfs_imap_blocks);
+ new->mfs_zmap_blocks = bswap16(old->mfs_zmap_blocks);
+ new->mfs_firstdatazone_old = bswap16(old->mfs_firstdatazone_old);
+ new->mfs_log_zone_size = bswap16(old->mfs_log_zone_size);
+ new->mfs_max_size = bswap32(old->mfs_max_size);
+ new->mfs_zones = bswap32(old->mfs_zones);
+ new->mfs_magic = bswap16(old->mfs_magic);
+ new->mfs_block_size = bswap16(old->mfs_block_size);
+ new->mfs_disk_version = old->mfs_disk_version;
+}
+
+void minixfs3_i_bswap(struct mfs_dinode *old, struct mfs_dinode *new)
+{
+ int i;
+
+ new->mdi_mode = bswap16(old->mdi_mode);
+ new->mdi_nlinks = bswap16(old->mdi_nlinks);
+ new->mdi_uid = bswap16(old->mdi_uid);
+ new->mdi_gid = bswap16(old->mdi_gid);
+ new->mdi_size = bswap32(old->mdi_size);
+ new->mdi_atime = bswap32(old->mdi_atime);
+ new->mdi_mtime = bswap32(old->mdi_mtime);
+ new->mdi_ctime = bswap32(old->mdi_ctime);
+
+ /* We don't swap here, because indirects must be swapped later
+ * anyway, hence everything is done by block_map().
+ */
+ for (i = 0; i < NR_TZONES; i++)
+ new->mdi_zone[i] = old->mdi_zone[i];
+}
+#endif
diff --git a/sys/lib/libsa/minixfs3.h b/sys/lib/libsa/minixfs3.h
new file mode 100644
index 0000000..aef8a54
--- /dev/null
+++ b/sys/lib/libsa/minixfs3.h
@@ -0,0 +1,176 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2012
+ * Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved.
+ *
+ * Author: Evgeniy Ivanov
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MINIX_FS_3_H
+#define MINIX_FS_3_H
+
+FS_DEF(minixfs3);
+
+typedef uint32_t zone_t;
+typedef uint16_t zone1_t;
+typedef uint32_t block_t;
+
+#define NR_DZONES 7 /* # direct zone numbers in an inode */
+#define NR_TZONES 10 /* total # zone numbers in an inode */
+#define NIADDR 2 /* Indirect addresses in inode */
+
+struct mfs_dinode {
+ uint16_t mdi_mode; /* file type, protection, etc. */
+ uint16_t mdi_nlinks; /* how many links to this file */
+ int16_t mdi_uid; /* user id of the file's owner */
+ uint16_t mdi_gid; /* group number */
+ uint32_t mdi_size; /* current file size in bytes */
+ uint32_t mdi_atime; /* time of last access */
+ uint32_t mdi_mtime; /* when was file data last changed */
+ uint32_t mdi_ctime; /* when was inode itself changed */
+ zone_t mdi_zone[NR_TZONES]; /* zone numbers for direct, ind, and
+ dbl ind */
+};
+
+/* Maximum Minix MFS on-disk directory filename.
+ * MFS uses 'struct direct' to write and parse
+ * directory entries, so this can't be changed
+ * without breaking filesystems.
+ */
+#define MFS_DIRSIZ 60
+
+struct mfs_direct {
+ uint32_t mfsd_ino;
+ char mfsd_name[MFS_DIRSIZ];
+} __packed;
+
+struct mfs_sblock {
+ uint32_t mfs_ninodes; /* # usable inodes on the minor device
*/
+ zone1_t mfs_nzones; /* total device size, including bit
maps etc */
+ int16_t mfs_imap_blocks; /* # of blocks used by inode bit map */
+ int16_t mfs_zmap_blocks; /* # of blocks used by zone bit map */
+ zone1_t mfs_firstdatazone_old;/* number of first data zone (small) */
+ int16_t mfs_log_zone_size; /* log2 of blocks/zone */
+ int16_t mfs_pad; /* try to avoid compiler-dependent
padding */
+ int32_t mfs_max_size; /* maximum file size on this device */
+ zone_t mfs_zones; /* number of zones (replaces s_nzones
in V2) */
+ int16_t mfs_magic; /* magic number to recognize
super-blocks */
+ int16_t mfs_pad2; /* try to avoid compiler-dependent
padding */
+ uint16_t mfs_block_size; /* block size in bytes. */
+ char mfs_disk_version; /* filesystem format sub-version */
+
+ /* The following items are only used when the super_block is in memory,
+ * mfs_inodes_per_block must be the firs one (see SBSIZE)
+ */
+ unsigned mfs_inodes_per_block; /* precalculated from magic number */
+ zone_t mfs_firstdatazone; /* number of first data zone (big) */
+ int32_t mfs_bshift; /* ``lblkno'' calc of logical blkno */
+ int32_t mfs_bmask; /* ``blkoff'' calc of blk offsets */
+ int64_t mfs_qbmask; /* ~fs_bmask - for use with quad size */
+ int32_t mfs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+};
+
+#define LOG_MINBSIZE 10
+#define MINBSIZE (1 << LOG_MINBSIZE)
+
+#define SUPER_MAGIC 0x4d5a /* magic # for MFSv3 file systems */
+
+#define ROOT_INODE ((uint32_t) 1) /* inode number for root directory */
+#define SUPER_BLOCK_OFF (1024) /* bytes offset */
+#define START_BLOCK ((block_t) 2) /* first fs block (not counting SB) */
+
+/* # bytes/dir entry */
+#define DIR_ENTRY_SIZE sizeof(struct mfs_direct)
+/* # dir entries/blk */
+#define NR_DIR_ENTRIES(fs) ((fs)->mfs_block_size/DIR_ENTRY_SIZE)
+/* mfs_sblock on-disk part size */
+#define SBSIZE offsetof(struct mfs_sblock,
mfs_inodes_per_block)
+
+#define ZONE_NUM_SIZE sizeof(zone_t) /* # bytes in zone */
+#define INODE_SIZE sizeof(struct mfs_dinode) /* bytes in dsk ino */
+/* # zones/indir block */
+#define NINDIR(fs) ((fs)->mfs_block_size/ZONE_NUM_SIZE)
+
+#define NO_ZONE ((zone_t) 0) /* absence of a zone
number */
+#define NO_BLOCK ((block_t) 0) /* absence of a block number */
+
+/* Turn file system block numbers into disk block addresses */
+#define fsbtodb(fs, b) ((b) << (fs)->mfs_fsbtodb)
+
+#define ino_to_fsba(fs, x)
\
+ (((x) - 1) / (fs)->mfs_inodes_per_block + \
+ START_BLOCK + (fs)->mfs_imap_blocks + (fs)->mfs_zmap_blocks)
+#define ino_to_fsbo(fs, x) (((x) - 1) % (fs)->mfs_inodes_per_block)
+
+/*
+ * MFS metadatas are stored in little-endian byte order. These macros
+ * helps reading theses metadatas.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define fs2h16(x) (x)
+# define fs2h32(x) (x)
+# define mfs_sbload(old, new) \
+ memcpy((new), (old), SBSIZE);
+# define mfs_iload(old, new) \
+ memcpy((new),(old),sizeof(struct mfs_dinode))
+#else
+void minixfs3_sb_bswap(struct mfs_sblock *, struct mfs_sblock *);
+void minixfs3_i_bswap(struct mfs_dinode *, struct mfs_dinode *);
+# define fs2h16(x) bswap16(x)
+# define fs2h32(x) bswap32(x)
+# define mfs_sbload(old, new) minixfs3_sb_bswap((old), (new))
+# define mfs_iload(old, new) minixfs3_i_bswap((old), (new))
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * The following macros optimize certain frequently calculated
+ * quantities by using shifts and masks in place of divisions
+ * modulos and multiplications.
+ */
+#define blkoff(fs, loc) /* calculates (loc % fs->mfs_bsize) */ \
+ ((loc) & (fs)->mfs_qbmask)
+#define lblkno(fs, loc) /* calculates (loc / fs->mfs_bsize) */ \
+ ((loc) >> (fs)->mfs_bshift)
+
+/* Flag bits for i_mode in the inode. */
+#define I_TYPE 0170000 /* this field gives inode type */
+#define I_UNIX_SOCKET 0140000 /* unix domain socket */
+#define I_SYMBOLIC_LINK 0120000 /* file is a symbolic link */
+#define I_REGULAR 0100000 /* regular file, not dir or special */
+#define I_BLOCK_SPECIAL 0060000 /* block special file */
+#define I_DIRECTORY 0040000 /* file is a directory */
+#define I_CHAR_SPECIAL 0020000 /* character special file */
+#define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */
+#define I_SET_UID_BIT 0004000 /* set effective uid_t on exec */
+#define I_SET_GID_BIT 0002000 /* set effective gid_t on exec */
+#define I_SET_STCKY_BIT 0001000 /* sticky bit */
+#define ALL_MODES 0007777 /* all bits for user, group and others */
+#define RWX_MODES 0000777 /* mode bits for RWX only */
+#define R_BIT 0000004 /* Rwx protection bit */
+#define W_BIT 0000002 /* rWx protection bit */
+#define X_BIT 0000001 /* rwX protection bit */
+#define I_NOT_ALLOC 0000000 /* this inode is free */
+
+#endif /* MINIX_FS_3_H */
--
1.7.3.4
From 9db57a035b7c3c6437467bdaee67b795eaf68a51 Mon Sep 17 00:00:00 2001
From: Evgeniy Ivanov <lolkaantimat%gmail.com@localhost>
Date: Sun, 18 Dec 2011 15:54:03 +0400
Subject: [PATCH 3/4] i386 boot2 MINIX FS support.
By default MINIX FS support is disabled.
diff --git a/sys/arch/i386/stand/boot/Makefile.boot
b/sys/arch/i386/stand/boot/Makefile.boot
index 78b9974..18b3eb8 100644
--- a/sys/arch/i386/stand/boot/Makefile.boot
+++ b/sys/arch/i386/stand/boot/Makefile.boot
@@ -70,6 +70,7 @@ CPPFLAGS+= -DSUPPORT_CD9660
CPPFLAGS+= -DSUPPORT_USTARFS
CPPFLAGS+= -DSUPPORT_DOSFS
CPPFLAGS+= -DSUPPORT_EXT2FS
+#CPPFLAGS+= -DSUPPORT_MINIXFS3
CPPFLAGS+= -DPASS_BIOSGEOM
CPPFLAGS+= -DPASS_MEMMAP
#CPPFLAGS+= -DBOOTPASSWD
diff --git a/sys/arch/i386/stand/boot/conf.c b/sys/arch/i386/stand/boot/conf.c
index db92a08..fa45ac2 100644
--- a/sys/arch/i386/stand/boot/conf.c
+++ b/sys/arch/i386/stand/boot/conf.c
@@ -36,6 +36,9 @@
#ifdef SUPPORT_EXT2FS
#include <lib/libsa/ext2fs.h>
#endif
+#ifdef SUPPORT_MINIXFS3
+#include <lib/libsa/minixfs3.h>
+#endif
#ifdef SUPPORT_USTARFS
#include <lib/libsa/ustarfs.h>
#endif
@@ -66,6 +69,9 @@ struct fs_ops file_system[] = {
#ifdef SUPPORT_EXT2FS
FS_OPS(ext2fs),
#endif
+#ifdef SUPPORT_MINIXFS3
+ FS_OPS(minixfs3),
+#endif
#ifdef SUPPORT_DOSFS
FS_OPS(dosfs),
#endif
--
1.7.3.4
Home |
Main Index |
Thread Index |
Old Index