2 * Copyright (c) 2002 Networks Associates Technology, Inc.
5 * This software was developed for the FreeBSD Project by Marshall
6 * Kirk McKusick and Network Associates Laboratories, the Security
7 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
8 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
11 * Copyright (c) 1998 Robert Nordier
12 * All rights reserved.
14 * Redistribution and use in source and binary forms are freely
15 * permitted provided that the above copyright notice and this
16 * paragraph and the following disclaimer are duplicated in all
19 * This software is provided "AS IS" and without any express or
20 * implied warranties, including, without limitation, the implied
21 * warranties of merchantability and fitness for a particular
24 * $FreeBSD: src/sys/boot/common/ufsread.c,v 1.12 2003/08/25 23:30:41 obrien Exp $
25 * $DragonFly: src/sys/boot/common/ufsread.c,v 1.4 2007/01/22 15:31:37 y0netan1 Exp $
28 #include <vfs/ufs/dir.h>
32 /* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase
33 (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can
34 support both UFS1 and UFS2 again. */
36 #define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c)))
40 * We use 4k `virtual' blocks for filesystem data, whatever the actual
41 * filesystem block size. FFS blocks are always a multiple of 4k.
44 #define VBLKSIZE (1 << VBLKSHIFT)
45 #define VBLKMASK (VBLKSIZE - 1)
46 #define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
47 #define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT))
48 #define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT))
49 #define INO_TO_VBA(fs, ipervblk, x) \
50 (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \
51 (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))
52 #define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)
53 #define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
54 ((off) / VBLKSIZE) * DBPERVBLK)
55 #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
57 /* Buffers that must not span a 64k boundary. */
59 char blkbuf
[VBLKSIZE
]; /* filesystem blocks */
60 char indbuf
[VBLKSIZE
]; /* indir blocks */
61 char sbbuf
[SBLOCKSIZE
]; /* superblock */
62 char secbuf
[DEV_BSIZE
]; /* for MBR/disklabel */
64 static struct dmadat
*dmadat
;
66 static ino_t
lookup(const char *);
67 static ssize_t
fsread(ino_t
, void *, size_t);
69 static int ls
, dsk_meta
;
70 static uint32_t fs_off
;
73 fsfind(const char *name
, ino_t
* ino
)
81 while ((n
= fsread(*ino
, buf
, DEV_BSIZE
)) > 0)
82 for (s
= buf
; s
< buf
+ DEV_BSIZE
;) {
85 printf("%s ", d
->d_name
);
86 else if (!strcmp(name
, d
->d_name
)) {
98 lookup(const char *path
)
100 char name
[MAXNAMLEN
+ 1];
115 for (s
= path
; *s
&& *s
!= '/'; s
++);
116 if ((n
= s
- path
) > MAXNAMLEN
)
118 ls
= *path
== '?' && n
== 1 && !*s
;
119 memcpy(name
, path
, n
);
122 printf("%s: not a directory.\n", name
);
125 if ((dt
= fsfind(name
, &ino
)) <= 0)
129 return dt
== DT_REG
? ino
: 0;
133 * Possible superblock locations ordered from most to least likely.
135 static int sblock_try
[] = SBLOCKSEARCH
;
137 #if defined(UFS2_ONLY)
138 #define DIP(field) dp2.field
139 #elif defined(UFS1_ONLY)
140 #define DIP(field) dp1.field
142 #define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
146 fsread(ino_t inode
, void *buf
, size_t nbyte
)
149 static struct ufs1_dinode dp1
;
152 static struct ufs2_dinode dp2
;
159 size_t n
, nb
, size
, off
, vboff
;
161 ufs2_daddr_t addr
, vbaddr
;
162 static ufs2_daddr_t blkmap
, indmap
;
166 blkbuf
= dmadat
->blkbuf
;
167 indbuf
= dmadat
->indbuf
;
168 fs
= (struct fs
*)dmadat
->sbbuf
;
171 for (n
= 0; sblock_try
[n
] != -1; n
++) {
172 if (dskread(fs
, sblock_try
[n
] / DEV_BSIZE
,
173 SBLOCKSIZE
/ DEV_BSIZE
))
176 #if defined(UFS1_ONLY)
177 fs
->fs_magic
== FS_UFS1_MAGIC
178 #elif defined(UFS2_ONLY)
179 (fs
->fs_magic
== FS_UFS2_MAGIC
&&
180 fs
->fs_sblockloc
== sblock_try
[n
])
182 fs
->fs_magic
== FS_UFS1_MAGIC
||
183 (fs
->fs_magic
== FS_UFS2_MAGIC
&&
184 fs
->fs_sblockloc
== sblock_try
[n
])
187 fs
->fs_bsize
<= MAXBSIZE
&&
188 fs
->fs_bsize
>= sizeof(struct fs
))
191 if (sblock_try
[n
] == -1) {
199 if (inomap
!= inode
) {
201 if (dskread(blkbuf
, INO_TO_VBA(fs
, n
, inode
), DBPERVBLK
))
203 n
= INO_TO_VBO(n
, inode
);
204 #if defined(UFS1_ONLY)
205 dp1
= ((struct ufs1_dinode
*)blkbuf
)[n
];
206 #elif defined(UFS2_ONLY)
207 dp2
= ((struct ufs2_dinode
*)blkbuf
)[n
];
209 if (fs
->fs_magic
== FS_UFS1_MAGIC
)
210 dp1
= ((struct ufs1_dinode
*)blkbuf
)[n
];
212 dp2
= ((struct ufs2_dinode
*)blkbuf
)[n
];
225 lbn
= lblkno(fs
, fs_off
);
226 off
= blkoff(fs
, fs_off
);
228 addr
= DIP(di_db
[lbn
]);
229 } else if (lbn
< NDADDR
+ NINDIR(fs
)) {
230 n
= INDIRPERVBLK(fs
);
231 addr
= DIP(di_ib
[0]);
232 u
= (u_int
)(lbn
- NDADDR
) / n
* DBPERVBLK
;
233 vbaddr
= fsbtodb(fs
, addr
) + u
;
234 if (indmap
!= vbaddr
) {
235 if (dskread(indbuf
, vbaddr
, DBPERVBLK
))
239 n
= (lbn
- NDADDR
) & (n
- 1);
240 #if defined(UFS1_ONLY)
241 addr
= ((ufs1_daddr_t
*)indbuf
)[n
];
242 #elif defined(UFS2_ONLY)
243 addr
= ((ufs2_daddr_t
*)indbuf
)[n
];
245 if (fs
->fs_magic
== FS_UFS1_MAGIC
)
246 addr
= ((ufs1_daddr_t
*)indbuf
)[n
];
248 addr
= ((ufs2_daddr_t
*)indbuf
)[n
];
253 vbaddr
= fsbtodb(fs
, addr
) + (off
>> VBLKSHIFT
) * DBPERVBLK
;
254 vboff
= off
& VBLKMASK
;
255 n
= sblksize(fs
, size
, lbn
) - (off
& ~VBLKMASK
);
258 if (blkmap
!= vbaddr
) {
259 if (dskread(blkbuf
, vbaddr
, n
>> DEV_BSHIFT
))
266 memcpy(s
, blkbuf
+ vboff
, n
);