Home | History | Annotate | Line # | Download | only in boot_ufs
readufs_ffs.c revision 1.9.86.1
      1 /*	$NetBSD: readufs_ffs.c,v 1.9.86.1 2009/04/28 07:34:54 skrll Exp $	*/
      2 /*	from Id: readufs_ffs.c,v 1.6 2003/04/08 09:19:32 itohy Exp 	*/
      3 
      4 /*
      5  * FS specific support for 4.2BSD Fast Filesystem
      6  *
      7  * Written in 1999, 2002, 2003 by ITOH Yasufumi (itohy (at) NetBSD.org).
      8  * Public domain.
      9  *
     10  * Intended to be used for boot programs (first stage).
     11  * DON'T ADD ANY FANCY FEATURE.  THIS SHALL BE COMPACT.
     12  */
     13 
     14 #include "readufs.h"
     15 
     16 #include <ufs/ffs/fs.h>
     17 
     18 static int get_ffs_inode(ino32_t ino, union ufs_dinode *dibuf);
     19 
     20 #define fsi	(*ufsinfo)
     21 #define fsi_ffs	fsi.fs_u.u_ffs
     22 
     23 /*
     24  * Read and check superblock.
     25  * If it is an FFS, save information from the superblock.
     26  */
     27 int
     28 try_ffs(void)
     29 {
     30 	union {
     31 		struct fs	sblk;
     32 		unsigned char	pad[SBLOCKSIZE];
     33 	} buf;
     34 	struct ufs_info *ufsinfo = &ufs_info;
     35 	static const int sblocs[] = SBLOCKSEARCH;
     36 	const int *sbl;
     37 	int magic;
     38 
     39 #ifdef DEBUG_WITH_STDIO
     40 	printf("trying FFS\n");
     41 #endif
     42 	/* read FFS superblock */
     43 	for (sbl = sblocs; ; sbl++) {
     44 		if (*sbl == -1)
     45 			return 1;
     46 
     47 		RAW_READ(&buf, (daddr_t) btodb(*sbl), SBLOCKSIZE);
     48 
     49 		magic = buf.sblk.fs_magic;
     50 #ifdef DEBUG_WITH_STDIO
     51 		printf("FFS: sblk: pos %d magic 0x%x\n", btodb(*sbl), magic);
     52 #endif
     53 #ifdef USE_UFS1
     54 		if (magic == FS_UFS1_MAGIC
     55 		    && !(buf.sblk.fs_old_flags & FS_FLAGS_UPDATED)) {
     56 			if (*sbl == SBLOCK_UFS2)
     57 				/* might be an alternate suberblock */
     58 				continue;
     59 			break;
     60 		}
     61 #endif
     62 		if (*sbl != buf.sblk.fs_sblockloc)
     63 			/* must be an alternate suberblock */
     64 			continue;
     65 
     66 #ifdef USE_UFS1
     67 		if (magic == FS_UFS1_MAGIC) {
     68 			break;
     69 		}
     70 #endif
     71 #ifdef USE_UFS2
     72 		if (magic == FS_UFS2_MAGIC) {
     73 #ifdef USE_UFS1
     74 			fsi.ufstype = UFSTYPE_UFS2;
     75 #endif
     76 			break;
     77 		}
     78 #endif
     79 	}
     80 
     81 	/*
     82 	 * XXX <ufs/ffs/fs.h> always uses fs_magic
     83 	 * (UFS1 only or UFS2 only is impossible)
     84 	 */
     85 	fsi_ffs.magic = magic;
     86 #ifdef DEBUG_WITH_STDIO
     87 	printf("FFS: detected UFS%d format\n", (magic == FS_UFS2_MAGIC) + 1);
     88 #endif
     89 
     90 	/* This partition looks like an FFS. */
     91 	fsi.fstype = UFSTYPE_FFS;
     92 	fsi.get_inode = get_ffs_inode;
     93 
     94 	/* Get information from the superblock. */
     95 	fsi.bsize = buf.sblk.fs_bsize;
     96 	fsi.fsbtodb = buf.sblk.fs_fsbtodb;
     97 	fsi.nindir = buf.sblk.fs_nindir;
     98 
     99 	fsi_ffs.iblkno = buf.sblk.fs_iblkno;
    100 	fsi_ffs.old_cgoffset = buf.sblk.fs_old_cgoffset;
    101 	fsi_ffs.old_cgmask = buf.sblk.fs_old_cgmask;
    102 	fsi_ffs.fragshift = buf.sblk.fs_fragshift;
    103 	fsi_ffs.inopb = buf.sblk.fs_inopb;
    104 	fsi_ffs.ipg = buf.sblk.fs_ipg;
    105 	fsi_ffs.fpg = buf.sblk.fs_fpg;
    106 
    107 	return 0;
    108 }
    109 
    110 /* for inode macros */
    111 #define fs_ipg		fs_u.u_ffs.ipg
    112 #define fs_iblkno	fs_u.u_ffs.iblkno
    113 #define fs_old_cgoffset	fs_u.u_ffs.old_cgoffset
    114 #define fs_old_cgmask	fs_u.u_ffs.old_cgmask
    115 #define fs_fpg		fs_u.u_ffs.fpg
    116 #define fs_magic	fs_u.u_ffs.magic
    117 #define fs_inopb	fs_u.u_ffs.inopb
    118 #define fs_fragshift	fs_u.u_ffs.fragshift
    119 #define fs_fsbtodb	fsbtodb
    120 
    121 /*
    122  * Get inode from disk.
    123  */
    124 static int
    125 get_ffs_inode(ino32_t ino, union ufs_dinode *dibuf)
    126 {
    127 	struct ufs_info *ufsinfo = &ufs_info;
    128 	union ufs_dinode *buf = alloca((size_t) fsi.bsize);
    129 	union ufs_dinode *di;
    130 	unsigned ioff;
    131 
    132 	RAW_READ(buf, fsbtodb(&fsi, ino_to_fsba(&fsi, ino)),
    133 			(size_t) fsi.bsize);
    134 
    135 	ioff = ino_to_fsbo(&fsi, ino);
    136 
    137 #if defined(USE_UFS1) && defined(USE_UFS2)
    138 	if (ufsinfo->ufstype == UFSTYPE_UFS1)
    139 		di = (void *) &(&buf->di1)[ioff];
    140 	else {
    141 		di = (void *) &(&buf->di2)[ioff];
    142 
    143 		/* XXX for DI_SIZE() macro */
    144 		di->di1.di_size = di->di2.di_size;
    145 	}
    146 #else
    147 	di = &buf[ioff];
    148 #endif
    149 
    150 #ifdef DEBUG_WITH_STDIO
    151 	printf("FFS: dinode(%d): mode 0%o, nlink %d, size %u\n",
    152 		ino, di->di_common.di_mode, di->di_common.di_nlink,
    153 		(unsigned) DI_SIZE(di));
    154 #endif
    155 
    156 	if (di->di_common.di_mode == 0)
    157 		return 1;	/* unused inode (file is not found) */
    158 
    159 	*dibuf = *di;
    160 
    161 	return 0;
    162 }
    163