11.15Schs/*	$NetBSD: readufs_ffs.c,v 1.15 2022/11/17 06:40:39 chs Exp $	*/
21.3Sitohy/*	from Id: readufs_ffs.c,v 1.6 2003/04/08 09:19:32 itohy Exp 	*/
31.1Sminoura
41.1Sminoura/*
51.1Sminoura * FS specific support for 4.2BSD Fast Filesystem
61.1Sminoura *
71.13Sitohy * Written in 1999, 2002, 2003 by ITOH Yasufumi.
81.1Sminoura * Public domain.
91.1Sminoura *
101.1Sminoura * Intended to be used for boot programs (first stage).
111.1Sminoura * DON'T ADD ANY FANCY FEATURE.  THIS SHALL BE COMPACT.
121.1Sminoura */
131.1Sminoura
141.3Sitohy#include "readufs.h"
151.3Sitohy
161.1Sminoura#include <ufs/ffs/fs.h>
171.1Sminoura
181.10Sdslstatic int get_ffs_inode(ino32_t ino, union ufs_dinode *dibuf);
191.1Sminoura
201.1Sminoura#define fsi	(*ufsinfo)
211.1Sminoura#define fsi_ffs	fsi.fs_u.u_ffs
221.1Sminoura
231.1Sminoura/*
241.1Sminoura * Read and check superblock.
251.1Sminoura * If it is an FFS, save information from the superblock.
261.1Sminoura */
271.1Sminouraint
281.12Sceggertry_ffs(void)
291.1Sminoura{
301.1Sminoura	union {
311.1Sminoura		struct fs	sblk;
321.3Sitohy		unsigned char	pad[SBLOCKSIZE];
331.1Sminoura	} buf;
341.1Sminoura	struct ufs_info *ufsinfo = &ufs_info;
351.3Sitohy	static const int sblocs[] = SBLOCKSEARCH;
361.3Sitohy	const int *sbl;
371.3Sitohy	int magic;
381.1Sminoura
391.1Sminoura#ifdef DEBUG_WITH_STDIO
401.1Sminoura	printf("trying FFS\n");
411.1Sminoura#endif
421.1Sminoura	/* read FFS superblock */
431.3Sitohy	for (sbl = sblocs; ; sbl++) {
441.3Sitohy		if (*sbl == -1)
451.3Sitohy			return 1;
461.1Sminoura
471.3Sitohy		RAW_READ(&buf, (daddr_t) btodb(*sbl), SBLOCKSIZE);
481.3Sitohy
491.3Sitohy		magic = buf.sblk.fs_magic;
501.1Sminoura#ifdef DEBUG_WITH_STDIO
511.3Sitohy		printf("FFS: sblk: pos %d magic 0x%x\n", btodb(*sbl), magic);
521.1Sminoura#endif
531.7Sdsl#ifdef USE_UFS1
541.7Sdsl		if (magic == FS_UFS1_MAGIC
551.7Sdsl		    && !(buf.sblk.fs_old_flags & FS_FLAGS_UPDATED)) {
561.6Sdsl			if (*sbl == SBLOCK_UFS2)
571.6Sdsl				/* might be an alternate suberblock */
581.6Sdsl				continue;
591.7Sdsl			break;
601.6Sdsl		}
611.7Sdsl#endif
621.7Sdsl		if (*sbl != buf.sblk.fs_sblockloc)
631.7Sdsl			/* must be an alternate suberblock */
641.7Sdsl			continue;
651.1Sminoura
661.3Sitohy#ifdef USE_UFS1
671.7Sdsl		if (magic == FS_UFS1_MAGIC) {
681.3Sitohy			break;
691.7Sdsl		}
701.3Sitohy#endif
711.3Sitohy#ifdef USE_UFS2
721.15Schs		if (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) {
731.3Sitohy#ifdef USE_UFS1
741.3Sitohy			fsi.ufstype = UFSTYPE_UFS2;
751.3Sitohy#endif
761.3Sitohy			break;
771.3Sitohy		}
781.3Sitohy#endif
791.3Sitohy	}
801.3Sitohy
811.3Sitohy	/*
821.3Sitohy	 * XXX <ufs/ffs/fs.h> always uses fs_magic
831.3Sitohy	 * (UFS1 only or UFS2 only is impossible)
841.3Sitohy	 */
851.3Sitohy	fsi_ffs.magic = magic;
861.3Sitohy#ifdef DEBUG_WITH_STDIO
871.15Schs	printf("FFS: detected UFS%d format\n",
881.15Schs	       (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) + 1);
891.3Sitohy#endif
901.1Sminoura
911.1Sminoura	/* This partition looks like an FFS. */
921.1Sminoura	fsi.fstype = UFSTYPE_FFS;
931.1Sminoura	fsi.get_inode = get_ffs_inode;
941.1Sminoura
951.1Sminoura	/* Get information from the superblock. */
961.1Sminoura	fsi.bsize = buf.sblk.fs_bsize;
971.1Sminoura	fsi.fsbtodb = buf.sblk.fs_fsbtodb;
981.1Sminoura	fsi.nindir = buf.sblk.fs_nindir;
991.1Sminoura
1001.1Sminoura	fsi_ffs.iblkno = buf.sblk.fs_iblkno;
1011.3Sitohy	fsi_ffs.old_cgoffset = buf.sblk.fs_old_cgoffset;
1021.3Sitohy	fsi_ffs.old_cgmask = buf.sblk.fs_old_cgmask;
1031.1Sminoura	fsi_ffs.fragshift = buf.sblk.fs_fragshift;
1041.1Sminoura	fsi_ffs.inopb = buf.sblk.fs_inopb;
1051.1Sminoura	fsi_ffs.ipg = buf.sblk.fs_ipg;
1061.1Sminoura	fsi_ffs.fpg = buf.sblk.fs_fpg;
1071.1Sminoura
1081.1Sminoura	return 0;
1091.1Sminoura}
1101.1Sminoura
1111.1Sminoura/* for inode macros */
1121.1Sminoura#define fs_ipg		fs_u.u_ffs.ipg
1131.1Sminoura#define fs_iblkno	fs_u.u_ffs.iblkno
1141.3Sitohy#define fs_old_cgoffset	fs_u.u_ffs.old_cgoffset
1151.3Sitohy#define fs_old_cgmask	fs_u.u_ffs.old_cgmask
1161.1Sminoura#define fs_fpg		fs_u.u_ffs.fpg
1171.3Sitohy#define fs_magic	fs_u.u_ffs.magic
1181.1Sminoura#define fs_inopb	fs_u.u_ffs.inopb
1191.1Sminoura#define fs_fragshift	fs_u.u_ffs.fragshift
1201.1Sminoura#define fs_fsbtodb	fsbtodb
1211.1Sminoura
1221.1Sminoura/*
1231.1Sminoura * Get inode from disk.
1241.1Sminoura */
1251.1Sminourastatic int
1261.11Sdslget_ffs_inode(ino32_t ino, union ufs_dinode *dibuf)
1271.1Sminoura{
1281.1Sminoura	struct ufs_info *ufsinfo = &ufs_info;
1291.3Sitohy	union ufs_dinode *buf = alloca((size_t) fsi.bsize);
1301.3Sitohy	union ufs_dinode *di;
1311.3Sitohy	unsigned ioff;
1321.1Sminoura
1331.14Sdholland	RAW_READ(buf, FFS_FSBTODB(&fsi, ino_to_fsba(&fsi, ino)),
1341.1Sminoura			(size_t) fsi.bsize);
1351.1Sminoura
1361.3Sitohy	ioff = ino_to_fsbo(&fsi, ino);
1371.3Sitohy
1381.3Sitohy#if defined(USE_UFS1) && defined(USE_UFS2)
1391.3Sitohy	if (ufsinfo->ufstype == UFSTYPE_UFS1)
1401.3Sitohy		di = (void *) &(&buf->di1)[ioff];
1411.3Sitohy	else {
1421.3Sitohy		di = (void *) &(&buf->di2)[ioff];
1431.3Sitohy
1441.3Sitohy		/* XXX for DI_SIZE() macro */
1451.3Sitohy		di->di1.di_size = di->di2.di_size;
1461.3Sitohy	}
1471.3Sitohy#else
1481.3Sitohy	di = &buf[ioff];
1491.3Sitohy#endif
1501.3Sitohy
1511.1Sminoura#ifdef DEBUG_WITH_STDIO
1521.3Sitohy	printf("FFS: dinode(%d): mode 0%o, nlink %d, size %u\n",
1531.3Sitohy		ino, di->di_common.di_mode, di->di_common.di_nlink,
1541.3Sitohy		(unsigned) DI_SIZE(di));
1551.1Sminoura#endif
1561.1Sminoura
1571.3Sitohy	if (di->di_common.di_mode == 0)
1581.1Sminoura		return 1;	/* unused inode (file is not found) */
1591.1Sminoura
1601.1Sminoura	*dibuf = *di;
1611.1Sminoura
1621.1Sminoura	return 0;
1631.1Sminoura}
164